| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527 |
- import APP from '@/services';
- import { getGoodsByCode } from '@/services/bus/goods';
- import { geLoginID_number, isLogin } from '@/services/bus/login';
- import { getToken } from '@/services/bus/token';
- import { funCode } from '@/services/funcode/index';
- import { QueryQuoteDayRsp } from '@/services/go/quote/interface';
- import { Package40 } from '@/utils/websocket/package';
- import Long from 'long';
- import moment from 'moment';
- import { SubscribeInfoType } from '../interface';
- import { byteArrayToUInt, subscribeInfosToByteArrary } from './byteUtils';
- /**
- * 构建行情订阅请求包
- */
- export function buildSubscribePeq(subscribeInfos: SubscribeInfoType[]): Package40 {
- // 如果是登录状态,就走正常行情链路. 否则走游客
- const loginId = isLogin() ? Long.fromNumber(geLoginID_number()) : Long.fromNumber(2);
- const token = isLogin() ? getToken() : '2_TOKEN_NEKOT_';
- const content = subscribeInfosToByteArrary(subscribeInfos, token, loginId);
- const reqPackage = new Package40([funCode.MainClassNumber_Quota_SubscriptReq, content], undefined);
- return reqPackage;
- }
- /**
- * 解析行情订阅请求包
- * @param rspPackage
- */
- export function parseSubscribeRsp(rspPackage: any): Promise<string | SubscribeInfoType[]> {
- return new Promise((resolve, reject) => {
- const content = rspPackage.content;
- if (content.length === 0) {
- // 有可能空订阅,也有可能订阅返回数据为空,但其实已经订阅了商品
- // 暂做正常返回 空字符串 处理,如遇到问题继续优化即可
- console.warn('行情订阅请求包返回为空');
- resolve('');
- }
- const count = byteArrayToUInt(content.subarray(0, 4), false);
- if (count > 1000) {
- // 游客模式 刷新成长问题,为了不让页面卡死,暂时处理
- return null;
- }
- switch (count) {
- case -1:
- reject('订阅失败');
- break;
- case -2:
- reject('Token校验失败');
- break;
- case -3:
- reject('无对应商品信息');
- break;
- default:
- break;
- }
- // 判断返回的Count是否有问题
- if (!count || count > (content.length - 4) / 66) {
- reject('行情订阅返回数据不正确');
- }
- const result: SubscribeInfoType[] = [];
- let position = 4;
- for (let i = 0; i < count; i++) {
- const dataArray = content.subarray(position, position + 66);
- const subState = dataArray[0];
- // FIXME: 目前行情接入服务不能正确返回交易所代码
- const exchangeCode = dataArray[2];
- const goodsCode = String.fromCharCode(...dataArray.subarray(2, dataArray.length)).trim();
- result.push({ subState, goodsCode, exchangeCode });
- position += 66;
- }
- resolve(result);
- });
- }
- /**
- * 解析行情推送报文
- * @param {Array} quotationData 行情信息
- * @param {Boolean} isPushQuote 实时行情推送为true;盘面为false
- *
- */
- export function parseReceivePush(quotationData: any) {
- // 目前发现可能会传入空数组
- if (!quotationData.length) {
- return;
- }
- // 分解行正则
- const regRow = /10\s.*?11/g;
- // 分解单行 key 正则
- const regKey = /01\s.*?02/g;
- // 分解单行 value 正则
- const regValue = /02\s.*?01|02\s.*?11/g;
- // 记录已经更新盘面的商品信息数组
- // 0x10 ... 0x01 key 0x02 value 0x01 key 0x02 value ... 0x11
- const hexString = Array.prototype.map.call(quotationData, (x) => ('00' + x.toString(16)).slice(-2)).join(' ');
- // let hexString = 'FF 10 01 55 02 45 46 47 48 01 66 02 48 47 46 45 11 10 01 77 02 AA BB CC DD 11 00';
- // 获取单行行情
- const rows = hexString.match(regRow);
- if (rows === null) {
- return;
- }
- for (const low of rows) {
- // 获取 key value 表列
- const keys: any = low.match(regKey);
- const values: any = low.match(regValue);
- const goodsQuoteTik: any = {};
- for (let i = 0; i < keys.length; i++) {
- const key = parseInt(keys[i].substring(3, 5), 16);
- const tmpValue = values[i];
- const value = new Uint8Array(
- tmpValue
- .substring(3, tmpValue.length - 3)
- .split(' ')
- .map((byte: any) => parseInt(byte, 16))
- );
- // 缓存值
- setQuoteTikFieldByByte(goodsQuoteTik, key, value);
- }
- const quoteDayInfo = APP.getRef('quoteDayInfo');
- const itemQuote = quoteDayInfo.value.find((el: QueryQuoteDayRsp) => {
- const goodcode = el.refgoodscode || el.goodscode
- // console.log(el.goodscode, el.refgoodscode, goodsQuoteTik.goodscode)
- return goodcode === goodsQuoteTik.goodscode
- });
- if (itemQuote) {
- const goods = getGoodsByCode(itemQuote.goodscode);
- if (goods) {
- console.log('goodsQuoteTik', goodsQuoteTik)
- // 处理报价小数为
- const decimalplace = goods.decimalplace
- const num = Math.pow(10, decimalplace)
- const fn = (value: number) => +(value / num).toFixed(decimalplace)
- //
- // 处理 报价小数位
- const handleDeimalplace = (key: string) => {
- return Reflect.has(goodsQuoteTik, key) ? fn(goodsQuoteTik[key]) : itemQuote[key]
- }
- // 处理 如果有值则更新值,没有的话,则取上次的值
- // 注意: 0 也是有效数字
- const handleNoneValue = (key: string) => {
- return Reflect.has(goodsQuoteTik, key) ? goodsQuoteTik[key] : itemQuote[key]
- }
- const changeValue = () => {
- // 实时行情由于行情源的问题可能不会下发现量,这时用盘面的总量来计算
- if (!goodsQuoteTik.lastvolume) {
- if (itemQuote.totalvolume) {
- itemQuote.lastvolume = goodsQuoteTik.totalvolume - itemQuote.totalvolume;
- }
- }
- // 处理 最高最低价
- if (Reflect.has(goodsQuoteTik, 'last')) {
- const last = itemQuote.last = handleDeimalplace('last')
- if (last < itemQuote.lowest) {
- itemQuote.lowest = handleDeimalplace('last')
- } else if (last > itemQuote.highest) {
- itemQuote.highest = handleDeimalplace('last')
- }
- }
- // 处理价格
- itemQuote.decimalplace = decimalplace
- itemQuote.ask = handleDeimalplace('ask')
- itemQuote.ask2 = handleDeimalplace('ask2')
- itemQuote.ask3 = handleDeimalplace('ask3')
- itemQuote.ask4 = handleDeimalplace('ask4')
- itemQuote.ask5 = handleDeimalplace('ask5')
- itemQuote.ask6 = handleDeimalplace('ask6')
- itemQuote.ask7 = handleDeimalplace('ask7')
- itemQuote.ask8 = handleDeimalplace('ask8')
- itemQuote.ask9 = handleDeimalplace('ask9')
- itemQuote.ask10 = handleDeimalplace('ask10')
- itemQuote.bid = handleDeimalplace('bid')
- itemQuote.bid2 = handleDeimalplace('bid2')
- itemQuote.bid3 = handleDeimalplace('bid3')
- itemQuote.bid4 = handleDeimalplace('bid4')
- itemQuote.bid5 = handleDeimalplace('bid5')
- itemQuote.bid6 = handleDeimalplace('bid6')
- itemQuote.bid7 = handleDeimalplace('bid7')
- itemQuote.bid8 = handleDeimalplace('bid8')
- itemQuote.bid9 = handleDeimalplace('bid9')
- itemQuote.averageprice = handleDeimalplace('averageprice')
- itemQuote.grepmarketprice = handleDeimalplace('grepmarketprice')
- itemQuote.iep = handleDeimalplace('iep')
- itemQuote.limitdown = handleDeimalplace('limitdown')
- itemQuote.limitup = handleDeimalplace('limitup')
- itemQuote.opened = handleDeimalplace('opened')
- itemQuote.lastturnover = handleDeimalplace('lastturnover')
- itemQuote.nontotalturnover = handleDeimalplace('nontotalturnover')
- itemQuote.lastturnover = handleDeimalplace('lastturnover')
- itemQuote.preclose = handleDeimalplace('preclose')
- itemQuote.settle = handleDeimalplace('settle')
- itemQuote.totalturnover = handleDeimalplace('totalturnover')
- itemQuote.askorderid = handleNoneValue('askorderid')
- itemQuote.askorderid2 = handleNoneValue('askorderid2')
- itemQuote.askorderid3 = handleNoneValue('askorderid3')
- itemQuote.askorderid4 = handleNoneValue('askorderid4')
- itemQuote.askorderid5 = handleNoneValue('askorderid5')
- itemQuote.askordervolume = handleNoneValue('askordervolume')
- itemQuote.askordervolume2 = handleNoneValue('askordervolume2')
- itemQuote.askordervolume3 = handleNoneValue('askordervolume3')
- itemQuote.askordervolume4 = handleNoneValue('askordervolume4')
- itemQuote.askordervolume5 = handleNoneValue('askordervolume5')
- itemQuote.askordervolume6 = handleNoneValue('askordervolume6')
- itemQuote.askordervolume7 = handleNoneValue('askordervolume7')
- itemQuote.askordervolume8 = handleNoneValue('askordervolume8')
- itemQuote.askordervolume9 = handleNoneValue('askordervolume9')
- itemQuote.askqueueinfo = handleNoneValue('askqueueinfo')
- itemQuote.askvolume = handleNoneValue('askvolume')
- itemQuote.askvolume2 = handleNoneValue('askvolume2')
- itemQuote.askvolume3 = handleNoneValue('askvolume3')
- itemQuote.askvolume4 = handleNoneValue('askvolume4')
- itemQuote.askvolume5 = handleNoneValue('askvolume5')
- itemQuote.askvolume6 = handleNoneValue('askvolume6')
- itemQuote.askvolume7 = handleNoneValue('askvolume7')
- itemQuote.askvolume8 = handleNoneValue('askvolume8')
- itemQuote.askvolume9 = handleNoneValue('askvolume9')
- itemQuote.bidorderid = handleNoneValue('bidorderid')
- itemQuote.bidorderid2 = handleNoneValue('bidorderid2')
- itemQuote.bidorderid3 = handleNoneValue('bidorderid3')
- itemQuote.bidorderid4 = handleNoneValue('bidorderid4')
- itemQuote.bidorderid5 = handleNoneValue('bidorderid5')
- itemQuote.bidordervolume = handleNoneValue('bidordervolume')
- itemQuote.bidordervolume2 = handleNoneValue('bidordervolume2')
- itemQuote.bidordervolume3 = handleNoneValue('bidordervolume3')
- itemQuote.bidordervolume4 = handleNoneValue('bidordervolume4')
- itemQuote.bidordervolume5 = handleNoneValue('bidordervolume5')
- itemQuote.bidordervolume6 = handleNoneValue('bidordervolume6')
- itemQuote.bidordervolume7 = handleNoneValue('bidordervolume7')
- itemQuote.bidordervolume8 = handleNoneValue('bidordervolume8')
- itemQuote.bidordervolume9 = handleNoneValue('bidordervolume9')
- itemQuote.bidqueueinfo = handleNoneValue('bidqueueinfo')
- itemQuote.bidvolume = handleNoneValue('bidvolume')
- itemQuote.bidvolume2 = handleNoneValue('bidvolume2')
- itemQuote.bidvolume3 = handleNoneValue('bidvolume3')
- itemQuote.bidvolume4 = handleNoneValue('bidvolume4')
- itemQuote.bidvolume5 = handleNoneValue('bidvolume5')
- itemQuote.bidvolume6 = handleNoneValue('bidvolume6')
- itemQuote.bidvolume7 = handleNoneValue('bidvolume7')
- itemQuote.bidvolume8 = handleNoneValue('bidvolume8')
- itemQuote.bidvolume9 = handleNoneValue('bidvolume9')
- itemQuote.calloptionpremiums = handleNoneValue('calloptionpremiums')
- itemQuote.calloptionpremiums2 = handleNoneValue('calloptionpremiums2')
- itemQuote.calloptionpremiums3 = handleNoneValue('calloptionpremiums3')
- itemQuote.calloptionpremiums4 = handleNoneValue('calloptionpremiums4')
- itemQuote.calloptionpremiums5 = handleNoneValue('calloptionpremiums5')
- itemQuote.holdincrement = handleNoneValue('holdincrement')
- itemQuote.holdvolume = handleNoneValue('holdvolume')
- itemQuote.inventory = handleNoneValue('inventory')
- itemQuote.lastlot = handleNoneValue('lastlot')
- itemQuote.nontotalholdervolume = handleNoneValue('nontotalholdervolume')
- itemQuote.nontotallot = handleNoneValue('nontotallot')
- itemQuote.nontotalvolume = handleNoneValue('nontotalvolume')
- itemQuote.totallot = handleNoneValue('totallot')
- itemQuote.totalvolume = handleNoneValue('totalvolume')
- }
- // 判断是一下行情时间是否比现在的要早
- if (goodsQuoteTik.lasttime) {
- const quoteTime = moment(goodsQuoteTik.lasttime, 'YYYY-MM-DD HH:mm:ss')
- const localTime = moment(itemQuote.lasttime, 'YYYY-MM-DD HH:mm:ss')
- if (quoteTime >= localTime) {
- changeValue()
- itemQuote.lasttime = handleNoneValue('lasttime')
- }
- } else {
- // 委托单 没有 行情变更时间
- changeValue()
- }
- // goodsQuoteTik.averageprice = goodsQuoteTik.averageprice ? (fn(goodsQuoteTik.averageprice)) : '--'
- // goodsQuoteTik.grepmarketprice = goodsQuoteTik.grepmarketprice ? (fn(goodsQuoteTik.grepmarketprice)) : '--'
- // goodsQuoteTik.highest = goodsQuoteTik.highest ? (fn(goodsQuoteTik.highest)) : '--'
- // goodsQuoteTik.iep = goodsQuoteTik.iep ? (fn(goodsQuoteTik.iep)) : '--'
- // goodsQuoteTik.limitdown = goodsQuoteTik.limitdown ? (fn(goodsQuoteTik.limitdown)) : '--'
- // goodsQuoteTik.limitup = goodsQuoteTik.limitup ? (fn(goodsQuoteTik.limitup)) : '--'
- // goodsQuoteTik.lowest = goodsQuoteTik.lowest ? (fn(goodsQuoteTik.lowest)) : '--'
- // goodsQuoteTik.opened = goodsQuoteTik.opened ? (fn(goodsQuoteTik.opened)) : '--'
- // goodsQuoteTik.preclose = goodsQuoteTik.preclose ? (fn(goodsQuoteTik.preclose)) : '--'
- // goodsQuoteTik.settle = goodsQuoteTik.settle ? (fn(goodsQuoteTik.settle)) : '--'
- // goodsQuoteTik.strikeprice = goodsQuoteTik.strikeprice ? (fn(goodsQuoteTik.strikeprice)) : '--'
- // goodsQuoteTik.lasttime = moment(goodsQuoteTik.date + goodsQuoteTik.time, 'YYYYMMDDHHmmss').format('YYYY-MM-DD HH:mm:ss')
- // // 实时行情由于行情源的问题可能不会下发现量,这时用盘面的总量来计算
- // if (!goodsQuoteTik.lastvolume) {
- // if (itemQuote.totalvolume) {
- // goodsQuoteTik.lastvolume = goodsQuoteTik.totalvolume - itemQuote.totalvolume;
- // } else {
- // goodsQuoteTik.lastvolume = "--";
- // }
- // }
- // !goodsQuoteTik.holdvolume && (goodsQuoteTik.holdvolume = '--')
- // !goodsQuoteTik.holdincrement && (goodsQuoteTik.holdincrement = '--')
- // !goodsQuoteTik.totalturnover && (goodsQuoteTik.totalturnover = '--')
- // console.log('goodsQuoteTik', goodsQuoteTik)
- // mergeObj(itemQuote, goodsQuoteTik);
- } else {
- console.warn(`行情推送的商品goods:${itemQuote.goodscode}在商品列表里不存在`)
- }
- // 注意:此处已 go 服务查询出来的盘面数据为基准,查询盘面 先修改成go 服务,第一次进入项目时候回查询一次所有盘面
- // 之前是 通过 websocket 查询的,故 可能存在字段发生变化问题,如遇到,则进行优化处理
- // 判断是一下行情时间是否比现在的要早
- // const quoteTime = moment(goodsQuoteTik.lasttime, 'YYYY-MM-DD HH:mm:ss')
- // const localTime = moment(itemQuote.lasttime, 'YYYY-MM-DD HH:mm:ss')
- // if (quoteTime >= localTime) {
- // mergeObj(itemQuote, goodsQuoteTik);
- // }
- } else {
- // 此处 待优化(存在字段变化问题)
- // console.log('itemQuote', itemQuote)
- // quoteDayInfo.value.push(itemQuote);
- }
- }
- }
- /**
- * 分解缓存行情字段的方法
- * goodsQuoteTik
- * keyItem
- * valueItem
- */
- function setQuoteTikFieldByByte(goodsQuoteTik: any, keyItem: any, valueItem: any) {
- const strValue = String.fromCharCode(...valueItem);
- switch (keyItem) {
- case 0x56:
- goodsQuoteTik.exchangecode = strValue;
- break;
- case 0x21:
- goodsQuoteTik.goodscode = strValue;
- break;
- case 0x24:
- goodsQuoteTik.last = Number(strValue);
- break;
- case 0x5b:
- goodsQuoteTik.holdvolume = Number(strValue);
- break;
- case 0x25:
- goodsQuoteTik.lastvolume = Number(strValue);
- break;
- case 0x3c:
- goodsQuoteTik.preholdvolume = Number(strValue);
- break;
- case 0x32:
- goodsQuoteTik.presettle = Number(strValue);
- break;
- case 0x33:
- goodsQuoteTik.settle = Number(strValue);
- break;
- case 0x29:
- goodsQuoteTik.totalturnover = Number(strValue);
- break;
- case 0x28:
- goodsQuoteTik.totalvolume = Number(strValue);
- break;
- case 0x35:
- goodsQuoteTik.limithigh = Number(strValue);
- break;
- case 0x36:
- goodsQuoteTik.limitlow = Number(strValue);
- break;
- case 'L'.charCodeAt(0):
- goodsQuoteTik.ask = Number(strValue);
- break;
- case 'M'.charCodeAt(0):
- goodsQuoteTik.ask2 = Number(strValue);
- break;
- case 'N'.charCodeAt(0):
- goodsQuoteTik.ask3 = Number(strValue);
- break;
- case 'O'.charCodeAt(0):
- goodsQuoteTik.ask4 = Number(strValue);
- break;
- case 'P'.charCodeAt(0):
- goodsQuoteTik.ask5 = Number(strValue);
- break;
- case 'Q'.charCodeAt(0):
- goodsQuoteTik.askvolume = Number(strValue);
- break;
- case 'R'.charCodeAt(0):
- goodsQuoteTik.askvolume2 = Number(strValue);
- break;
- case 'S'.charCodeAt(0):
- goodsQuoteTik.askvolume3 = Number(strValue);
- break;
- case 'T'.charCodeAt(0):
- goodsQuoteTik.askvolume4 = Number(strValue);
- break;
- case 'U'.charCodeAt(0):
- goodsQuoteTik.askvolume5 = Number(strValue);
- break;
- case 'B'.charCodeAt(0):
- goodsQuoteTik.bid = Number(strValue);
- break;
- case 'C'.charCodeAt(0):
- goodsQuoteTik.bid2 = Number(strValue);
- break;
- case 'D'.charCodeAt(0):
- goodsQuoteTik.bid3 = Number(strValue);
- break;
- case 'E'.charCodeAt(0):
- goodsQuoteTik.bid4 = Number(strValue);
- break;
- case 'F'.charCodeAt(0):
- goodsQuoteTik.bid5 = Number(strValue);
- break;
- case 'G'.charCodeAt(0):
- goodsQuoteTik.bidvolume = Number(strValue);
- break;
- case 'H'.charCodeAt(0):
- goodsQuoteTik.bidvolume2 = Number(strValue);
- break;
- case 'I'.charCodeAt(0):
- goodsQuoteTik.bidvolume3 = Number(strValue);
- break;
- case 'J'.charCodeAt(0):
- goodsQuoteTik.bidvolume4 = Number(strValue);
- break;
- case 'K'.charCodeAt(0):
- goodsQuoteTik.bidvolume5 = Number(strValue);
- break;
- case ','.charCodeAt(0):
- goodsQuoteTik.highest = Number(strValue);
- break;
- case '-'.charCodeAt(0):
- goodsQuoteTik.lowest = Number(strValue);
- break;
- case '@'.charCodeAt(0):
- goodsQuoteTik.date = strValue;
- break;
- case 'A'.charCodeAt(0):
- goodsQuoteTik.time = strValue;
- break;
- case '+'.charCodeAt(0):
- goodsQuoteTik.preclose = Number(strValue);
- break;
- case '.'.charCodeAt(0):
- goodsQuoteTik.opened = Number(strValue);
- break;
- case 0x5c:
- goodsQuoteTik.exerciseprice = Number(strValue);
- break;
- case 0x7a:
- goodsQuoteTik.inventory = Number(strValue);
- break;
- case 0x7c:
- goodsQuoteTik.exchangedate = Number(strValue);
- break;
- case 0x70:
- goodsQuoteTik.strbidorder = strValue;
- break;
- case 0x71:
- goodsQuoteTik.strbidorder2 = strValue;
- break;
- case 0x72:
- goodsQuoteTik.strbidorder3 = strValue;
- break;
- case 0x73:
- goodsQuoteTik.strbidorder4 = strValue;
- break;
- case 0x74:
- goodsQuoteTik.strbidorder5 = strValue;
- break;
- case 0x75:
- goodsQuoteTik.straskorder = strValue;
- break;
- case 0x76:
- goodsQuoteTik.straskorder2 = strValue;
- break;
- case 0x77:
- goodsQuoteTik.straskorder3 = strValue;
- break;
- case 0x78:
- goodsQuoteTik.straskorder4 = strValue;
- break;
- case 0x79:
- goodsQuoteTik.straskorder5 = strValue;
- break;
- case 0x7d:
- goodsQuoteTik.putoptionpremiums = strValue;
- break;
- case 0x7e:
- goodsQuoteTik.putoptionpremiums2 = strValue;
- break;
- case 0x80:
- goodsQuoteTik.putoptionpremiums3 = strValue;
- break;
- case 0x81:
- goodsQuoteTik.putoptionpremiums4 = strValue;
- break;
- case 0x82:
- goodsQuoteTik.putoptionpremiums5 = strValue;
- break;
- case 0x83:
- goodsQuoteTik.calloptionpremiums = strValue;
- break;
- case 0x84:
- goodsQuoteTik.calloptionpremiums2 = strValue;
- break;
- case 0x85:
- goodsQuoteTik.calloptionpremiums3 = strValue;
- break;
- case 0x86:
- goodsQuoteTik.calloptionpremiums4 = strValue;
- break;
- case 0x87:
- goodsQuoteTik.calloptionpremiums5 = strValue;
- break;
- default:
- break;
- }
- }
|