async def _md_recv(self, pack): """ 处理下行数据包 0 将行情数据和交易数据合并至 self._data 1 生成增量业务截面, 该截面包含期权补充的字段 """ for d in pack.get("data", {}): self._datetime_state.update_state(d) _simple_merge_diff(self._data_quotes, d.get('quotes', {})) _merge_diff(self._data, {"trade": d.get('trade', {})}, prototype=self._prototype, persist=False, reduce_diff=False) self._diffs.append(d) # 添加至 self._diff 等待被发送 for obj in self._new_objs_list: # 新添加的 Position / Order / Trade 节点 if hasattr(obj, '_path') and obj['_path'][2] in ['positions', 'trades', 'orders']: symbol = f"{obj.get('exchange_id', '')}.{obj.get('instrument_id', '')}" if symbol not in self._all_trade_symbols: self._all_trade_symbols.add(symbol) self._need_wait_symbol_info.add(symbol) # 需要发送合约信息请求 for s in self._need_wait_symbol_info.copy(): if self._data_quotes.get(s, {}).get("price_tick", 0) > 0: self._need_wait_symbol_info.remove(s) # 需要发送合约信息请求 + 不知道合约信息的合约 # 不知道合约信息 并且未发送请求查询合约信息 unknown_symbols = self._need_wait_symbol_info - self._query_symbols if len(unknown_symbols) > 0: self._query_symbols = self._query_symbols.union(unknown_symbols) # 所有发送过ins_query的合约 query_pack = _query_for_quote(list(unknown_symbols)) await self._md_send_chan.send(query_pack)
async def _ensure_symbols(self): if all([q.price_tick > 0 for q in self]): return query_symbols = [q._path[-1] for q in self if not q.price_tick > 0] query_pack = _query_for_quote(query_symbols) self._api._send_pack(query_pack) async with self._api.register_update_notify(self) as update_chan: async for _ in update_chan: if all([q.price_tick > 0 for q in self]): return
async def _ensure_quote_info(self, symbol, quote_chan): """quote收到合约信息后返回""" quote = _get_obj(self._data, ["quotes", symbol], Quote(self._api)) if quote.get("price_tick") == quote.get("price_tick"): return quote.copy() if quote.get("price_tick") != quote.get("price_tick"): await self._md_send_chan.send(_query_for_quote(symbol)) async for _ in quote_chan: quote_chan.task_done() if quote.get("price_tick") == quote.get("price_tick"): return quote.copy()
async def _ensure_quote(self, ins): # 在接新版合约服务器后,合约信息程序运行过程中查询得到的,这里不再能保证合约一定存在,需要添加 quote 默认值 quote = _get_obj(self._data, ["quotes", ins], BtQuote(self._api)) if math.isnan(quote.get("price_tick")): query_pack = _query_for_quote(ins) await self._md_send_chan.send(query_pack) async with TqChan(self._api, last_only=True) as update_chan: quote["_listener"].add(update_chan) while math.isnan(quote.get("price_tick")): await update_chan.recv() if ins not in self._quotes or self._quotes[ins]["min_duration"] > 60000000000: await self._ensure_serial(ins, 60000000000)
async def _ensure_quote(self, symbol, quote_chan): """quote收到行情以及合约信息后返回""" quote = _get_obj(self._data, ["quotes", symbol], Quote(self._api)) _register_update_chan(quote, quote_chan) if quote.get("datetime", "") and quote.get("price_tick") == quote.get("price_tick"): return quote.copy() if quote.get("price_tick") != quote.get("price_tick"): # 对于没有合约信息的 quote,发送查询合约信息的请求 await self._md_send_chan.send(_query_for_quote(symbol)) async for _ in quote_chan: quote_chan.task_done() if quote.get("datetime", "") and quote.get("price_tick") == quote.get("price_tick"): return quote.copy()
print( "* margin commission 部分合约不一致, 组合没有 volume_multiple, 指数、主连符合预期,SPOT 没有 expired product_short_name," ) print( "* 新版合约服务中已经删去的字段", ["ins_id", "ins_name", "sort_key", "delivery_year", "delivery_month"]) print("* 旧版合约服务里行情相关的数据不需要关心", ["settlement_price", "open_interest", "last_price", "pre_volume"]) symbols_diff = {} i = 0 for symbol, old_quote in old_symbols.items(): # i += 1 # if i > 100: # break query_pack = _query_for_quote(symbol) query_result = api.query_graphql(query=query_pack["query"], variables=query_pack["variables"]) quotes = query_result.get("result", {}).get("symbol_info", []) assert len(quotes) == 1 new_quote = quotes[0] assert new_quote["instrument_id"] == symbol diff = symbols_diff.setdefault(symbol, []) different(old_quote, new_quote, diff) for symbol, diffs in symbols_diff.items(): if diffs: logger.info( f"{'-'*10} {symbol} {old_symbols[symbol]['class']} {'-'*20}") for d in diffs: logger.info(d)