class SubscribeApi(object): def __init__(self, ws_url, new_loop): self.new_loop = new_loop self.client = BaseWebSocketClient(url=ws_url, loop=self.new_loop) self.common = Common() # 登录请求 async def LoginReq(self, token, start_time_stamp=None): data_send = LoginReq(auto_token=token, start_time_stamp=start_time_stamp) quote_msg = QuoteMsgCarrier(type=QuoteMsgType.LOGIN_REQ, data=data_send.SerializeToString()) quote_msg = quote_msg.SerializeToString() all_req = await self.client.send_and_recv(quote_msg) json_login_list = [] for req in all_req: recv_data = QuoteMsgCarrier() recv_data.ParseFromString(req) if recv_data.type == QuoteMsgType.LOGIN_RSP: login_data = LoginRsp() login_data.ParseFromString(recv_data.data) json_login_data = json_format.MessageToJson(login_data) json_login_data = json.loads(json_login_data) json_login_list.append(json_login_data) # print(json_login_list) return json_login_list # 登出请求 async def LogoutReq(self, start_time_stamp=None, recv_num=1): data_send = LoginReq(start_time_stamp=start_time_stamp) quote_msg = QuoteMsgCarrier(type=QuoteMsgType.LOGOUT_REQ, data=data_send.SerializeToString()) quote_msg = quote_msg.SerializeToString() all_req = await self.client.send_and_recv(quote_msg, recv_num=recv_num) json_logout_list = [] for req in all_req: recv_data = QuoteMsgCarrier() recv_data.ParseFromString(req) if recv_data.type == QuoteMsgType.LOGOUT_RSP: login_data = LogoutRsp() login_data.ParseFromString(recv_data.data) json_logout_data = json_format.MessageToJson(login_data) json_logout_data = json.loads(json_logout_data) json_logout_list.append(json_logout_data) print('LogoutReq json_logout_list:{}'.format(json_logout_list)) return json_logout_list # 心跳 async def HearbeatReqApi(self, connid, isKeep=False): data_send = HeartReqMsg(conn_id=connid) quote_msg = QuoteMsgCarrier(type=QuoteMsgType.HEARTBEAT_REQ, data=data_send.SerializeToString()) quote_msg = quote_msg.SerializeToString() if isKeep == False: all_req = await self.client.send_and_recv(quote_msg) json_rsp_list = [] for base_req in all_req: if base_req == None: continue rev_data = QuoteMsgCarrier() rev_data.ParseFromString(base_req) if rev_data.type == QuoteMsgType.HEARTBEAT_RSP: single_data = HeartRspMsg() single_data.ParseFromString(rev_data.data) json_single_data = json_format.MessageToJson(single_data) json_single_data = json.loads(json_single_data) json_rsp_list.append(json_single_data) # print('HearbeatReqApi json_rsp_list:{}'.format(json_rsp_list)) return json_rsp_list else: await self.client.send(quote_msg) # 保持心跳 async def hearbeat_job(self, gap_time=1): i = 1 asyncio.set_event_loop(self.new_loop) while True: if self.client.is_disconnect(): break await self.HearbeatReqApi(connid=i, isKeep=True) # print('The {} time to keep heartbeat! SendTimeStamp:{}'.format(i, str(time.time()))) await asyncio.sleep(gap_time) i = i + 1 # 测速 async def VelocityReqApi(self, start_time=None): data_send = VelocityReqMsg(start_time=start_time) quote_msg = QuoteMsgCarrier(type=QuoteMsgType.VELOCITY_REQ, data=data_send.SerializeToString()) quote_msg = quote_msg.SerializeToString() all_req = await self.client.send_and_recv(quote_msg) json_rsp_list = [] for base_req in all_req: rev_data = QuoteMsgCarrier() rev_data.ParseFromString(base_req) if rev_data.type == QuoteMsgType.VELOCITY_RSP: single_data = VelocityRspMsg() single_data.ParseFromString(rev_data.data) json_single_data = json_format.MessageToJson(single_data) json_single_data = json.loads(json_single_data) json_rsp_list.append(json_single_data) # print('VelocityReqApi json_rsp_list:{}'.format(json_rsp_list)) return json_rsp_list # 订阅 async def SubsQutoMsgReqApi(self, sub_type=None, child_type=None, base_info=None, recv_num=1, start_time_stamp=None, sub_quote_type=SubQuoteMsgType.REAL_QUOTE_MSG): # Return: # { # 'first_rsp_list': [{}, {}, {}], # 表示订阅应答响应 SUBSCRIBE_RSP # 'snapshot_json_list': [{}, {}, {}, {}, {}], # 表示返回的当前时间之前的合约快照数据 # 'basic_json_list': [{}, {}, {}, {}, {}] # 表示返回的当前时间之前的合约静态数据 # } # print('''sub_type:{}, child_type:{}, base_info:{}'''.format(sub_type, child_type, base_info)) send_data = SubscribeQuoteMsgReq(sub_type=sub_type, child_type=child_type, base_info=base_info, start_time_stamp=start_time_stamp, sub_quote_type=sub_quote_type) quote_msg = QuoteMsgCarrier(type=QuoteMsgType.SUBSCRIBE_REQ, data=send_data.SerializeToString()) quote_msg = quote_msg.SerializeToString() await self.HearbeatReqApi(connid=10086, isKeep=True) # 避免循环接消息时心跳断掉 all_req = await self.client.send_and_recv(quote_msg, recv_num=recv_num) first_rsp_list = [] for base_req in all_req: rev_data = QuoteMsgCarrier() rev_data.ParseFromString(base_req) if rev_data.type == QuoteMsgType.SUBSCRIBE_RSP: single_data = SubscribeQuoteMsgRsp() single_data.ParseFromString(rev_data.data) json_single_data = json_format.MessageToJson(single_data) json_single_data = json.loads(json_single_data) first_rsp_list.append(json_single_data) elif rev_data.type == QuoteMsgType.HEARTBEAT_RSP: # 如果接到心跳数据应忽略,继续接受一次 all_req = await self.client.recv(recv_num=1) for base_req in all_req: rev_data = QuoteMsgCarrier() rev_data.ParseFromString(base_req) if rev_data.type == QuoteMsgType.SUBSCRIBE_RSP: single_data = SubscribeQuoteMsgRsp() single_data.ParseFromString(rev_data.data) json_single_data = json_format.MessageToJson( single_data) json_single_data = json.loads(json_single_data) first_rsp_list.append(json_single_data) finally_rsp = {} finally_rsp['first_rsp_list'] = first_rsp_list before_snapshot_json_list = [] before_basic_json_list = [] # 接收该合约前一刻的最新一笔静态、快照,直到更新时间超出请求时间则跳出 # while True: # before_time_reqs = await self.client.recv(recv_num=1) # if before_time_reqs != []: # base_req = before_time_reqs[0] # rev_data = QuoteMsgCarrier() # rev_data.ParseFromString(base_req) # if rev_data.type == QuoteMsgType.PUSH_SNAPSHOT: # single_data = QuoteSnapshot() # single_data.ParseFromString(rev_data.data) # json_snapshot_data = json_format.MessageToJson(single_data) # json_snapshot_data = json.loads(json_snapshot_data) # # print('before_json_snapshot_data:{}'.format(json_snapshot_data)) # req_source_time = self.common.searchDicKV(json_snapshot_data, 'sourceUpdateTime') # instr_code = self.common.searchDicKV(json_snapshot_data, 'instrCode') # # 毫秒级别对比 # if int(int(req_source_time) / (pow(10, 6))) < start_time_stamp: # before_snapshot_json_list.append(json_snapshot_data) # # self.sq.subscribe_new_record(rev_data.type, instr_code, req_source_time, json_snapshot_data) # else: # break # elif rev_data.type == QuoteMsgType.PUSH_BASIC: # single_data = QuoteBasicInfo() # single_data.ParseFromString(rev_data.data) # basic_single_data = json_format.MessageToJson(single_data) # basic_single_data = json.loads(basic_single_data) # # print('before_basic_single_data:{}'.format(basic_single_data)) # req_source_time = self.common.searchDicKV(basic_single_data, 'updateTimestamp') # instr_code = self.common.searchDicKV(basic_single_data, 'instrCode') # # 毫秒级别对比 # if int(int(req_source_time) / (pow(10, 6))) < start_time_stamp: # before_basic_json_list.append(basic_single_data) # # self.sq.subscribe_new_record(rev_data.type, instr_code, req_source_time, basic_single_data) # else: # break # elif rev_data.type not in [QuoteMsgType.PUSH_SNAPSHOT, QuoteMsgType.PUSH_BASIC, QuoteMsgType.HEARTBEAT_RSP, QuoteMsgType.SUBSCRIBE_RSP]: # break # else: # break finally_rsp['before_snapshot_json_list'] = before_snapshot_json_list finally_rsp['before_basic_json_list'] = before_basic_json_list return finally_rsp # 取消行情订阅 async def UnSubsQutoMsgReqApi(self, unsub_type, unchild_type=None, unbase_info=None, recv_num=20, start_time_stamp=None): # print('''sub_type:{}, child_type:{}, base_info:{}'''.format(unsub_type, unchild_type, unbase_info)) send_data = UnsubscribeQuoteMsgReq(sub_type=unsub_type, child_type=unchild_type, base_info=unbase_info, stat_time_stamp=start_time_stamp) quote_msg = QuoteMsgCarrier(type=QuoteMsgType.UNSUBSCRIBE_REQ, data=send_data.SerializeToString()) quote_msg = quote_msg.SerializeToString() all_req = await self.client.send_and_recv(quote_msg, recv_num=recv_num) json_rsp_list = [] for base_req in all_req: rev_data = QuoteMsgCarrier() rev_data.ParseFromString(base_req) if rev_data.type == QuoteMsgType.UNSUBSCRIBE_RSP: single_data = UnsubscribeQuoteMsgRsp() single_data.ParseFromString(rev_data.data) json_single_data = json_format.MessageToJson(single_data) json_single_data = json.loads(json_single_data) json_rsp_list.append(json_single_data) # print('UnSubsQutoMsgReqApi json_rsp_list:{}'.format(json_rsp_list)) return json_rsp_list # 订阅盘口数据(依赖订阅接口) async def QuoteOrderBookDataApi(self, recv_num=10, is_filter=True): await self.HearbeatReqApi(connid=10086, isKeep=True) # 避免循环接消息时心跳断掉 all_req = await self.client.recv(recv_num) json_rsp_list = [] for base_req in all_req: rev_data = QuoteMsgCarrier() rev_data.ParseFromString(base_req) if is_filter: if rev_data.type == QuoteMsgType.PUSH_ORDER_BOOK: single_data = QuoteOrderBookData() single_data.ParseFromString(rev_data.data) json_single_data = json_format.MessageToJson(single_data) json_single_data = json.loads(json_single_data) json_rsp_list.append(json_single_data) req_source_time = self.common.searchDicKV( json_single_data, 'sourceUpdateTime') instr_code = self.common.searchDicKV( json_single_data, 'instrCode') # self.sq.subscribe_new_record(rev_data.type, instr_code, req_source_time, json_single_data) else: single_data = QuoteOrderBookData() single_data.ParseFromString(rev_data.data) json_single_data = json_format.MessageToJson(single_data) json_single_data = json.loads(json_single_data) json_rsp_list.append(json_single_data) req_source_time = self.common.searchDicKV( json_single_data, 'sourceUpdateTime') instr_code = self.common.searchDicKV(json_single_data, 'instrCode') # self.sq.subscribe_new_record(rev_data.type, instr_code, req_source_time, json_single_data) # print('QuoteOrderBookDataApi json_rsp_list:{}'.format(json_rsp_list)) return json_rsp_list # 订阅逐笔成交数据(依赖订阅接口) async def QuoteTradeDataApi(self, recv_num=10, is_filter=True): all_req = await self.client.recv(recv_num) json_rsp_list = [] for base_req in all_req: rev_data = QuoteMsgCarrier() rev_data.ParseFromString(base_req) if is_filter: if rev_data.type == QuoteMsgType.PUSH_TRADE_DATA: single_data = QuoteTradeData() single_data.ParseFromString(rev_data.data) json_single_data = json_format.MessageToJson(single_data) json_single_data = json.loads(json_single_data) json_rsp_list.append(json_single_data) req_source_time = self.common.searchDicKV( json_single_data, 'sourceUpdateTime') instr_code = self.common.searchDicKV( json_single_data, 'instrCode') # self.sq.subscribe_new_record(rev_data.type, instr_code, req_source_time, json_single_data) else: single_data = QuoteTradeData() single_data.ParseFromString(rev_data.data) json_single_data = json_format.MessageToJson(single_data) json_single_data = json.loads(json_single_data) json_rsp_list.append(json_single_data) req_source_time = self.common.searchDicKV( json_single_data, 'sourceUpdateTime') instr_code = self.common.searchDicKV(json_single_data, 'instrCode') # self.sq.subscribe_new_record(rev_data.type, instr_code, req_source_time, json_single_data) # print('QuoteTradeDataApi json_rsp_list:{}'.format(json_rsp_list)) return json_rsp_list # 订阅静态数据(依赖订阅接口) async def QuoteBasicInfoApi(self, recv_num=10, is_filter=True): all_req = await self.client.recv(recv_num) json_basic_list = [] for base_req in all_req: rev_data = QuoteMsgCarrier() rev_data.ParseFromString(base_req) if is_filter: if rev_data.type == QuoteMsgType.PUSH_BASIC: basic_data = QuoteBasicInfo() basic_data.ParseFromString(rev_data.data) json_basic_data = json_format.MessageToJson(basic_data) json_basic_data = json.loads(json_basic_data) json_basic_list.append(json_basic_data) req_source_time = self.common.searchDicKV( json_basic_data, 'sourceUpdateTime') instr_code = self.common.searchDicKV( json_basic_data, 'instrCode') # self.sq.subscribe_new_record(rev_data.type, instr_code, req_source_time, json_basic_data) else: basic_data = QuoteTradeData() basic_data.ParseFromString(rev_data.data) json_basic_data = json_format.MessageToJson(basic_data) json_basic_data = json.loads(json_basic_data) json_basic_list.append(json_basic_data) req_source_time = self.common.searchDicKV( json_basic_data, 'sourceUpdateTime') instr_code = self.common.searchDicKV(json_basic_data, 'instrCode') # self.sq.subscribe_new_record(rev_data.type, instr_code, req_source_time, json_basic_data) # print('QuoteBasicInfoApi json_rsp_list:{}'.format(json_basic_list)) return json_basic_list # 订阅快照数据(依赖订阅接口) async def QuoteSnapshotApi(self, recv_num=10, is_filter=True): if self.client.is_disconnect(): return [] await self.HearbeatReqApi(connid=10086, isKeep=True) # 避免循环接消息时心跳断掉 all_req = await self.client.recv(recv_num) json_rsp_list = [] for base_req in all_req: rev_data = QuoteMsgCarrier() rev_data.ParseFromString(base_req) if is_filter: if rev_data.type == QuoteMsgType.PUSH_SNAPSHOT: basic_data = QuoteSnapshot() basic_data.ParseFromString(rev_data.data) json_basic_data = json_format.MessageToJson(basic_data) json_basic_data = json.loads(json_basic_data) json_rsp_list.append(json_basic_data) req_source_time = self.common.searchDicKV( json_basic_data, 'sourceUpdateTime') instr_code = self.common.searchDicKV( json_basic_data, 'instrCode') # self.sq.subscribe_new_record(rev_data.type, instr_code, req_source_time, json_basic_data) else: basic_data = QuoteSnapshot() basic_data.ParseFromString(rev_data.data) json_basic_data = json_format.MessageToJson(basic_data) json_basic_data = json.loads(json_basic_data) json_rsp_list.append(json_basic_data) req_source_time = self.common.searchDicKV( json_basic_data, 'sourceUpdateTime') instr_code = self.common.searchDicKV(json_basic_data, 'instrCode') # self.sq.subscribe_new_record(rev_data.type, instr_code, req_source_time, json_basic_data) # print('QuoteSnapshotApi json_rsp_list:{}'.format(json_rsp_list)) return json_rsp_list # 手机Api---开始请求分时页面数据 async def StartChartDataReqApi(self, exchange, code, frequency, start_time, start_time_stamp): data_send = StartChartDataReq(exchange=exchange, code=code, frequency=frequency, start_time=start_time, start_time_stamp=start_time_stamp) quote_msg = QuoteMsgCarrier(type=QuoteMsgType.START_CHART_DATA_REQ, data=data_send.SerializeToString()) quote_msg = quote_msg.SerializeToString() all_req = await self.client.send_and_recv(quote_msg) first_app_rsp_list = [] for base_req in all_req: rev_data = QuoteMsgCarrier() rev_data.ParseFromString(base_req) if rev_data.type == QuoteMsgType.START_CHART_DATA_RSP: single_data = StartChartDataRsp() single_data.ParseFromString(rev_data.data) json_single_data = json_format.MessageToJson(single_data) json_single_data = json.loads(json_single_data) first_app_rsp_list.append(json_single_data) # print('StartChartDataReqApi first_rsp_list:{}'.format(first_app_rsp_list)) finally_rsp = {} finally_rsp['first_app_rsp_list'] = first_app_rsp_list before_appsnapshot_json_list = [] before_appbasic_json_list = [] # 接收该app订阅前一刻的最新一笔静态、快照,直到更新时间超出请求时间则跳出 while True: before_time_reqs = await self.client.recv(recv_num=1) if before_time_reqs != []: for base_req in before_time_reqs: rev_data = QuoteMsgCarrier() rev_data.ParseFromString(base_req) if rev_data.type == QuoteMsgType.PUSH_SNAPSHOT: single_data = QuoteSnapshot() single_data.ParseFromString(rev_data.data) json_snapshot_data = json_format.MessageToJson( single_data) json_snapshot_data = json.loads(json_snapshot_data) req_source_time = self.common.searchDicKV( json_snapshot_data, 'sourceUpdateTime') instr_code = self.common.searchDicKV( json_snapshot_data, 'instrCode') # 毫秒级别对比 if int(req_source_time / (pow(10, 6))) < start_time_stamp: before_appsnapshot_json_list.append( json_snapshot_data) # self.sq.subscribe_new_record(rev_data.type, instr_code, req_source_time, json_snapshot_data) else: break elif rev_data.type == QuoteMsgType.PUSH_BASIC: single_data = QuoteBasicInfo() single_data.ParseFromString(rev_data.data) basic_single_data = json_format.MessageToJson( single_data) basic_single_data = json.loads(basic_single_data) req_source_time = self.common.searchDicKV( basic_single_data, 'sourceUpdateTime') instr_code = self.common.searchDicKV( basic_single_data, 'instrCode') # 毫秒级别对比 if int(req_source_time / (pow(10, 6))) < start_time_stamp: before_appbasic_json_list.append(basic_single_data) # self.sq.subscribe_new_record(rev_data.type, instr_code, req_source_time, basic_single_data) else: break else: break else: break finally_rsp[ 'before_appsnapshot_json_list'] = before_appsnapshot_json_list finally_rsp['before_appbasic_json_list'] = before_appbasic_json_list # print('StartChartDataReqApi finally_rsp:{}'.format(finally_rsp)) return finally_rsp # 手机Api---结束请求分时页面数据 async def StopChartDataReqApi(self, exchange, code, start_time_stamp): data_send = StopChartDataReq(exchange=exchange, code=code, start_time_stamp=start_time_stamp) quote_msg = QuoteMsgCarrier(type=QuoteMsgType.STOP_CHART_DATA_REQ, data=data_send.SerializeToString()) quote_msg = quote_msg.SerializeToString() all_req = await self.client.send_and_recv(quote_msg) json_rsp_list = [] for base_req in all_req: rev_data = QuoteMsgCarrier() rev_data.ParseFromString(base_req) if rev_data.type == QuoteMsgType.STOP_CHART_DATA_RSP: single_data = StopChartDataRsp() single_data.ParseFromString(rev_data.data) json_single_data = json_format.MessageToJson(single_data) json_single_data = json.loads(json_single_data) json_rsp_list.append(json_single_data) # print('StopChartDataReqApi json_rsp_list:{}'.format(json_rsp_list)) return json_rsp_list # 手机Api---推送分时数据 async def PushKLineMinDataApi(self, recv_num=10, is_filter=True): all_req = await self.client.recv(recv_num) json_basic_list = [] for base_req in all_req: rev_data = QuoteMsgCarrier() rev_data.ParseFromString(base_req) if is_filter: if rev_data.type == QuoteMsgType.PUSH_KLINE_MIN: basic_data = PushKLineMinData() basic_data.ParseFromString(rev_data.data) json_basic_data = json_format.MessageToJson(basic_data) json_basic_data = json.loads(json_basic_data) json_basic_list.append(json_basic_data) req_source_time = self.common.searchDicKV( json_basic_data, 'sourceUpdateTime') instr_code = self.common.searchDicKV( json_basic_data, 'code') # self.sq.subscribe_new_record(rev_data.type, instr_code, req_source_time, json_basic_data) else: basic_data = PushKLineMinData() basic_data.ParseFromString(rev_data.data) json_basic_data = json_format.MessageToJson(basic_data) json_basic_data = json.loads(json_basic_data) json_basic_list.append(json_basic_data) req_source_time = self.common.searchDicKV( json_basic_data, 'sourceUpdateTime') instr_code = self.common.searchDicKV(json_basic_data, 'code') # self.sq.subscribe_new_record(rev_data.type, instr_code, req_source_time, json_basic_data) # print('PushKLineMinDataApi json_rsp_list:{}'.format(json_basic_list)) return json_basic_list # 手机Api---请求分时页面数据,会主推静态、快照、盘口、逐笔、分时数据,此方法用于接收 async def AppQuoteAllApi(self, recv_num=20): all_req = await self.client.recv(recv_num) json_rsp_list = [] for base_req in all_req: rev_data = QuoteMsgCarrier() rev_data.ParseFromString(base_req) if rev_data.type == QuoteMsgType.PUSH_BASIC: single_data = QuoteBasicInfo() single_data.ParseFromString(rev_data.data) json_single_data = json_format.MessageToJson(single_data) json_single_data = json.loads(json_single_data) json_rsp_list.append(json_single_data) req_source_time = self.common.searchDicKV( json_single_data, 'sourceUpdateTime') instr_code = self.common.searchDicKV(json_single_data, 'instrCode') # self.sq.subscribe_new_record(rev_data.type, instr_code, req_source_time, json_single_data) elif rev_data.type == QuoteMsgType.PUSH_SNAPSHOT: single_data = QuoteSnapshot() single_data.ParseFromString(rev_data.data) json_single_data = json_format.MessageToJson(single_data) json_single_data = json.loads(json_single_data) json_rsp_list.append(json_single_data) req_source_time = self.common.searchDicKV( json_single_data, 'sourceUpdateTime') instr_code = self.common.searchDicKV(json_single_data, 'instrCode') # self.sq.subscribe_new_record(rev_data.type, instr_code, req_source_time, json_single_data) elif rev_data.type == QuoteMsgType.PUSH_ORDER_BOOK: single_data = QuoteOrderBookData() single_data.ParseFromString(rev_data.data) json_single_data = json_format.MessageToJson(single_data) json_single_data = json.loads(json_single_data) json_rsp_list.append(json_single_data) req_source_time = self.common.searchDicKV( json_single_data, 'sourceUpdateTime') instr_code = self.common.searchDicKV(json_single_data, 'instrCode') # self.sq.subscribe_new_record(rev_data.type, instr_code, req_source_time, json_single_data) elif rev_data.type == QuoteMsgType.PUSH_TRADE_DATA: single_data = QuoteTradeData() single_data.ParseFromString(rev_data.data) json_single_data = json_format.MessageToJson(single_data) json_single_data = json.loads(json_single_data) json_rsp_list.append(json_single_data) req_source_time = self.common.searchDicKV( json_single_data, 'sourceUpdateTime') instr_code = self.common.searchDicKV(json_single_data, 'instrCode') # self.sq.subscribe_new_record(rev_data.type, instr_code, req_source_time, json_single_data) elif rev_data.type == QuoteMsgType.PUSH_KLINE_MIN: single_data = PushKLineMinData() single_data.ParseFromString(rev_data.data) json_single_data = json_format.MessageToJson(single_data) json_single_data = json.loads(json_single_data) json_rsp_list.append(json_single_data) req_source_time = self.common.searchDicKV( json_single_data, 'sourceUpdateTime') instr_code = self.common.searchDicKV(json_single_data, 'code') # self.sq.subscribe_new_record(rev_data.type, instr_code, req_source_time, json_single_data) # print('AppQuoteAllApi json_rsp_list:{}'.format(json_rsp_list)) return json_rsp_list # 手机Api---查询K线数据 async def QueryKLineMsgReqApi(self, exchange, code, peroid_type, type, direct, start, end): now_timestamp = int(time.time() * 1000) # 毫秒时间戳 data_send = QueryKLineMsgReq(exchange=exchange, code=code, peroid_type=peroid_type, type=type, direct=direct, start=start, end=end, start_time_stamp=now_timestamp) quote_msg = QuoteMsgCarrier(type=QuoteMsgType.QUERY_KLINE_REQ, data=data_send.SerializeToString()) quote_msg = quote_msg.SerializeToString() all_req = await self.client.send_and_recv(quote_msg) json_rsp_list = [] for base_req in all_req: rev_data = QuoteMsgCarrier() rev_data.ParseFromString(base_req) if rev_data.type == QuoteMsgType.QUERY_KLINE_RSP: single_data = QueryKLineMsgRsp() single_data.ParseFromString(rev_data.data) json_single_data = json_format.MessageToJson(single_data) json_single_data = json.loads(json_single_data) json_rsp_list.append(json_single_data) # print('QueryKLineMsgReqApi json_rsp_list:{}'.format(json_rsp_list)) return json_rsp_list # app查询分时数据 async def QueryKLineMinMsgReqApi( self, isSubKLineMin, exchange, code, query_type=None, direct=None, start=None, end=None, vol=None, start_time_stamp=None, recv_num=1, sub_quote_type=SubQuoteMsgType.REAL_QUOTE_MSG): # app订阅服务中,该api只会自动返回当天的分时数据,与入参无关 ''' message QueryKLineMinMsgReq { bool isSubKLineMin = 1; // 是否订阅KLineMin common.ExchangeType exchange = 2; // 交易所 string code = 3; // 合约代码 QueryKLineMsgType type = 4; // 获取K线的方式 QueryKLineDirectType direct = 5; // 查询K线的方向 uint64 start = 6; // 开始时间 uint64 end = 7; // 结束时间 uint64 vol = 8; // 按量查询时此字段表示多少根 uint64 start_time_stamp = 9; // 发起请求的时间戳 UTC时间戳 } ''' await self.HearbeatReqApi(connid=10086, isKeep=True) # 避免循环接消息时心跳断掉 data_send = QueryKLineMinMsgReq(isSubKLineMin=isSubKLineMin, exchange=exchange, code=code, type=query_type, direct=direct, start=start, end=end, vol=vol, start_time_stamp=start_time_stamp, sub_quote_type=sub_quote_type) quote_msg = QuoteMsgCarrier(type=QuoteMsgType.QUERY_KLINE_MIN_REQ, data=data_send.SerializeToString()) quote_msg = quote_msg.SerializeToString() all_req = await self.client.send_and_recv(quote_msg, recv_num=recv_num) final_rsp = {} query_kline_min_rsp_list = [] sub_kline_min_rsp_list = [] for base_req in all_req: rev_data = QuoteMsgCarrier() rev_data.ParseFromString(base_req) if rev_data.type == QuoteMsgType.QUERY_KLINE_MIN_RSP: single_data = QueryKLineMinMsgRsp() single_data.ParseFromString(rev_data.data) json_single_data = json_format.MessageToJson(single_data) json_single_data = json.loads(json_single_data) query_kline_min_rsp_list.append(json_single_data) elif rev_data.type == QuoteMsgType.SUBSCRIBE_KLINE_MIN_RSP: single_data = SubscribeKlineMinRsp() single_data.ParseFromString(rev_data.data) json_single_data = json_format.MessageToJson(single_data) json_single_data = json.loads(json_single_data) sub_kline_min_rsp_list.append(json_single_data) final_rsp['query_kline_min_rsp_list'] = query_kline_min_rsp_list final_rsp['sub_kline_min_rsp_list'] = sub_kline_min_rsp_list # print(final_rsp) return final_rsp
class TimerTask(object): """docstring for TimerTask""" def __init__(self): super(TimerTask, self).__init__() self.logger = get_log("timerTask") self.max_instances = 20 # 最大并发数 # self.scheduler = BlockingScheduler() self.scheduler = AsyncIOScheduler() self.common = Common() # 清盘-实时行情校验 async def CleanData(self, exchange, code, loop, sub_quote_type=sub_quote_type): """ 测试清盘 """ self.logger.debug("执行的参数为: exchange: {}, code: {}, sub_quote_type: {}".format(exchange, code, sub_quote_type)) exchange = exchange code = code frequence = None isSubKLineMin = True query_type = 0 direct = 0 start = 0 end = 0 vol = 0 start_time_stamp = int(time.time() * 1000) isSubTrade = True type = "BY_VOL" start_time = start_time_stamp end_time = None vol = 100 count = 50 # http = MarketHttpClient() # market_token = http.get_market_token( # http.get_login_token(phone=login_phone, pwd=login_pwd, device_id=login_device_id)) market_token = None asyncio.set_event_loop(loop) try: api = SubscribeApi(union_ws_url, loop, logger=self.logger) await api.client.ws_connect() await api.LoginReq(token=market_token, start_time_stamp=start_time_stamp, frequence=frequence) asyncio.run_coroutine_threadsafe(api.hearbeat_job(), loop) self.logger.debug("订阅手机图表行情, 不会返回前快照数据和前盘口数据, {}, {}".format(sub_quote_type, code)) app_rsp_list = await api.StartChartDataReqApi(exchange, code, start_time_stamp, recv_num=1, sub_quote_type=sub_quote_type) app_rsp = app_rsp_list[0] basic_json_list = app_rsp.get("basicData") # 静态数据 assert self.common.searchDicKV(app_rsp.get("snapshot"), "high") is None assert self.common.searchDicKV(app_rsp.get("snapshot"), "open") is None assert self.common.searchDicKV(app_rsp.get("snapshot"), "low") is None assert self.common.searchDicKV(app_rsp.get("snapshot"), "close") is None assert self.common.searchDicKV(app_rsp.get("snapshot"), "last") is None if exchange not in ["ASE", "NYSE", "NASDAQ"]: # 美股盘前 assert app_rsp.get("orderbook") is None self.logger.debug("查询并订阅分时, 查询为空, 订阅成功, 不会返回前数据, {}, {}".format(sub_quote_type, code)) final_rsp = await api.QueryKLineMinMsgReqApi(isSubKLineMin, exchange, code, query_type, direct, start, end, vol, start_time_stamp, sub_quote_type=sub_quote_type) if sub_quote_type == "REAL_QUOTE_MSG": assert self.common.searchDicKV(final_rsp["query_kline_min_rsp_list"][0], 'retCode') == 'INITQUOTE_TIME' elif sub_quote_type == "DELAY_QUOTE_MSG": assert self.common.searchDicKV(final_rsp["query_kline_min_rsp_list"][0], 'data') is None assert self.common.searchDicKV(final_rsp["sub_kline_min_rsp_list"][0], 'retCode') == 'SUCCESS' assert final_rsp.get("before_kline_min_list") is None self.logger.debug("查询五日分时") fiveday_rsp = await api.QueryFiveDaysKLineMinReqApi(isSubKLineMin, exchange, code, start, start_time_stamp) query_5day_klinemin_rsp_list = fiveday_rsp['query_5day_klinemin_rsp_list'] sub_kline_min_rsp_list = fiveday_rsp['sub_kline_min_rsp_list'] assert self.common.searchDicKV(query_5day_klinemin_rsp_list[0], 'retCode') == 'SUCCESS' assert self.common.searchDicKV(sub_kline_min_rsp_list[0], 'retCode') == 'SUCCESS' # self.logger.debug(u'校验五日分时清盘时的数据, {}, {}'.format(sub_quote_type, code)) day_data_list = self.common.searchDicKV(query_5day_klinemin_rsp_list[0], 'dayData') assert day_data_list.__len__() == 5 # 获取五个交易日 fiveDateList = self.common.get_fiveDays(exchange) self.logger.debug("合约 {} , 五个交易日时间 : {}".format(code, fiveDateList)) for i in range(len(day_data_list)): # 校验五日date依次递增, 遇到节假日无法校验 assert day_data_list[i].get("date") == fiveDateList[i] info_list = self.common.searchDicKV(day_data_list[i], 'data') if info_list.__len__() > 0: if exchange == "HKFE": assert day_data_list[i].get("date") == info_list[-1].get("updateDateTime")[:8] else: assert day_data_list[i].get("date") == info_list[0].get("updateDateTime")[:8] self.logger.debug("查询并订阅逐笔, 查询为空, 订阅成功, 不会返回前数据, {}, {}".format(sub_quote_type, code)) final_rsp = await api.QueryTradeTickMsgReqApi(isSubTrade, exchange, code, type, direct, start_time, end_time, vol, start_time_stamp, sub_quote_type=sub_quote_type) try: assert final_rsp["query_trade_tick_rsp_list"] == [] except AssertionError: assert self.common.searchDicKV(final_rsp["query_trade_tick_rsp_list"], "data") is None assert self.common.searchDicKV(final_rsp["sub_trade_tick_rsp_list"][0], 'retCode') == 'SUCCESS' assert final_rsp.get("before_tickdata_list") is None # 港股才有经济席位 if exchange == "SEHK": # 只有港股有经济席位 self.logger.debug("订阅经济席位快照, 不会返回前数据, {}, {}".format(sub_quote_type, code)) final_rsp = await api.SubscribeBrokerSnapshotReqApi(exchange, code, start_time_stamp, sub_quote_type=sub_quote_type) assert self.common.searchDicKV(final_rsp["first_rsp_list"][0], 'retCode') == 'SUCCESS' assert final_rsp["before_broker_snapshot_json_list"] == [] # 查询指数成分股 self.logger.debug("查询港股指数成分股, {}, {}".format(sub_quote_type, code)) IndexShare = await api.QueryIndexShareMsgReqApi(isSubTrade=isSubTrade, exchange=exchange, sort_direct="DESCENDING_ORDER", indexCode="0000100", count=count, start_time_stamp=int(time.time() * 1000)) for indexData in self.common.searchDicKV(IndexShare, "snapshotData"): assert indexData.get("last") is None assert indexData.get("riseFall") is None # 按版块 self.logger.debug("查询港股版块信息, {}, {}".format(sub_quote_type, code)) for plate_type in ["MAIN", "LISTED_NEW_SHARES", "RED_SHIPS", "ETF", "GME"]: PlateSort = await api.QueryPlateSortMsgReqApi(isSubTrade=isSubTrade, zone="HK", plate_type=plate_type, sort_direct="DESCENDING_ORDER", count=count, start_time_stamp=int(time.time() * 1000)) if self.common.searchDicKV(PlateSort, "snapshotData"): for quoteData in self.common.searchDicKV(PlateSort, "snapshotData"): assert quoteData.get("last") is None assert quoteData.get("riseFall") is None if exchange in [ASE_exchange, NYSE_exchange, NASDAQ_exchange]: self.logger.debug("查询美股中概版和明星版, {}, {}".format(sub_quote_type, code)) for plate_type in ["START_STOCK", "CHINA_CONCEPT_STOCK"]: PlateSort = await api.QueryPlateSortMsgReqApi(isSubTrade=isSubTrade, zone="US", plate_type=plate_type, sort_direct="DESCENDING_ORDER", count=count, start_time_stamp=int(time.time() * 1000)) if self.common.searchDicKV(PlateSort, "snapshotData"): for quoteData in self.common.searchDicKV(PlateSort, "snapshotData"): assert quoteData.get("last") is None assert quoteData.get("riseFall") is None self.logger.debug("查询美股交易所排序--按涨跌排序, {}, {}".format(sub_quote_type, code)) ExchangeSort = await api.QueryExchangeSortMsgReqApi(isSubTrade=isSubTrade, exchange=exchange, sortFiled="R_F_RATIO", count=count, start_time_stamp=int(time.time() * 1000)) for ex_sort in self.common.searchDicKV(ExchangeSort, "snapshotData"): assert ex_sort.get("last") is None assert ex_sort.get("riseFall") is None finally: api.client.disconnect() # 验证状态改变后的推送通知 async def push_TradeStasut(self, exchange, code, loop): exchange = exchange product_list = [code] frequence = None start_time_stamp = int(time.time() * 1000) market_token = None asyncio.set_event_loop(loop) try: api = SubscribeApi(union_ws_url, loop, logger=self.logger) await api.client.ws_connect() await api.LoginReq(token=market_token, start_time_stamp=start_time_stamp, frequence=frequence) asyncio.run_coroutine_threadsafe(api.hearbeat_job(), loop) self.logger.debug(u'查询代码:{} 的交易状态, curtime : {}'.format(code, str(datetime.datetime.now()))) first_rsp_list = await api.QueryTradeStatusMsgReqApi(exchange=exchange, productList=product_list, recv_num=2) cur_status = self.common.searchDicKV(first_rsp_list, "status") self.logger.info("cur_status : {}".format(cur_status)) _start = time.time() PUSH_TRADE_STATUS = False while time.time() - _start < 120: # 循环120秒 rsp = await api.client.recv(recv_timeout_sec=5) if rsp: rev_data = QuoteMsgCarrier() rev_data.ParseFromString(rsp[0]) # self.logger.debug(rev_data) if rev_data.type == QuoteMsgType.PUSH_TRADE_STATUS: PUSH_TRADE_STATUS = True tradeStatus = TradeStatusData() tradeStatus.ParseFromString(rev_data.data) self.logger.info(tradeStatus) assert tradeStatus.status != cur_status # 确认校验状态只变化的一次 assert PUSH_TRADE_STATUS self.logger.debug("代码 : {} 有推送交易状态".format(code)) finally: api.client.disconnect() async def Liquidation(self, exchange, code): # loop = asyncio.new_event_loop() # loop.run_until_complete(future=self.CleanData(exchange, code, loop, "REAL_QUOTE_MSG")) loop = asyncio.get_event_loop() await self.CleanData(exchange, code, loop, "REAL_QUOTE_MSG") # 清盘-延时行情校验 async def Liquidation_DELAY(self, exchange, code): """ 延迟清盘 """ # loop = asyncio.new_event_loop() # loop.run_until_complete(future=self.CleanData(exchange, code, loop, "DELAY_QUOTE_MSG")) loop = asyncio.get_event_loop() await self.CleanData(exchange, code, loop, "DELAY_QUOTE_MSG") async def check_TradeStatus(self, exchange, code): loop = asyncio.get_event_loop() await self.push_TradeStasut(exchange, code, loop) # 定时任务回调 def Listener(self, event): # 监听器, 输出对应的错误信息 if event.exception: self.logger.error("{} 异常, 错误信息为 : \n{}".format(event.job_id, event.traceback)) # 创建清盘定时任务 def run_CleanData(self): self.logger.debug("runner 定时任务验证清盘") HK_stock = [ [SEHK_exchange, SEHK_code1], [SEHK_exchange, SEHK_indexCode1], [SEHK_exchange, SEHK_TrstCode1], [SEHK_exchange, SEHK_WarrantCode1], [SEHK_exchange, SEHK_CbbcCode1], [SEHK_exchange, SEHK_InnerCode1], ] US_stock = [ [ASE_exchange, ASE_code1], [NYSE_exchange, NYSE_code1], [NASDAQ_exchange, NASDAQ_code1], [BATS_exchange, BATS_code1], ] # 实时订阅清盘定时任务 [self.scheduler.add_job(self.Liquidation, 'cron', day_of_week='mon-fri', hour="08", minute="55-59", args=product, id='CleanData>>{}'.format('-'.join(product)), max_instances=self.max_instances) for product in HK_stock] [self.scheduler.add_job(self.Liquidation, 'cron', day_of_week='mon-fri', hour="22", minute="25-29", args=product, id='CleanData>>{}'.format('-'.join(product)), max_instances=self.max_instances) for product in US_stock] [self.scheduler.add_job(self.Liquidation_DELAY, 'cron', day_of_week='mon-fri', hour="08", minute="55-59", args=product, id='DELAY_CleanData>>{}'.format('-'.join(product)), max_instances=self.max_instances) for product in HK_stock] [self.scheduler.add_job(self.Liquidation_DELAY, 'cron', day_of_week='mon-fri', hour="22", minute="25-29", args=product, id='DELAYCleanData>>{}'.format('-'.join(product)), max_instances=self.max_instances) for product in US_stock] # 从exchangeTradeTime遍历, 添加定时任务 curDate = datetime.datetime.strftime(datetime.datetime.now(), "%Y-%m-%d") for key, value in exchangeTradeTime.items(): if key in ["HK_Stock", "US_Stock", "Grey"]: continue arg = key.split('_') arg[1] = arg[1] + "main" # print(arg) _time = datetime.datetime.strptime(curDate + value[0], '%Y-%m-%d%H:%M') # 开盘时间 if arg[0] not in ["HKFE", "SGX", "SEHK", "Grey"] and not isSummerTime: # 冬令时加一个小时 _time = datetime.datetime.strptime(curDate + value[0], '%Y-%m-%d%H:%M') + datetime.timedelta(hours=1) start_date = _time # copy一个变量 delay_endTime = _time start_date = start_date - datetime.timedelta(minutes=10) delay_endTime = delay_endTime + datetime.timedelta(minutes=15) # s_time = datetime.datetime.strftime(start_date, "%H%M") job_id = "CleanData_{}>>>start_date:{}, end_date:{}".format(arg, start_date, _time) # print(job_id) # self.scheduler.add_job(self.Liquidation, 'interval', minutes=1, start_date=start_date, end_date=_time, args=arg, id=job_id) self.scheduler.add_job(self.Liquidation, 'cron', day_of_week='mon-fri', hour=s_time[:-2], minute=s_time[-2:], args=arg, max_instances=self.max_instances, id=job_id) # 延时行情 delay_job_id = "DELAY_CleanData_{}>>>start_date:{}, end_date:{}".format(arg, start_date, delay_endTime) # print(delay_job_id) # self.scheduler.add_job(self.Liquidation_DELAY, 'interval', minutes=1, start_date=start_date, end_date=delay_endTime, args=arg, id=delay_job_id) self.scheduler.add_job(self.Liquidation_DELAY, 'cron', day_of_week='mon-fri', hour=s_time[:-2], minute=s_time[-2:], args=arg, max_instances=self.max_instances, id=delay_job_id) # 创建交易状态推送定时任务 def run_TradeStatus(self): self.logger.debug("交易交易状态推送通知") # 从exchangeTradeTime遍历, 添加定时任务 curDate = datetime.datetime.strftime(datetime.datetime.now(), "%Y-%m-%d") for key, value in exchangeTradeTime.items(): if key in ["HK_Stock", "US_Stock", "Grey"]: continue arg = key.split('_') # 每个时间段, 交易状态都会发生变化 for val in value: _time = datetime.datetime.strptime(curDate + val, '%Y-%m-%d%H:%M') if arg[0] not in ["HKFE", "SGX", "SEHK", "Grey"] and not isSummerTime: # 冬令时加一个小时 _time = datetime.datetime.strptime(curDate + val, '%Y-%m-%d%H:%M') + datetime.timedelta(hours=1) _time = _time - datetime.timedelta(seconds=30) s_time = datetime.datetime.strftime(_time, "%H%M") job_id = "push_status_{}>>>BeginTime:{}".format('-'.join(arg), s_time) # print(job_id) self.scheduler.add_job(self.check_TradeStatus, 'cron', hour=s_time[:-2], minute=s_time[-2:], second="00", args=arg, max_instances=self.max_instances, id=job_id) # 港股 self.scheduler.add_job(self.check_TradeStatus, 'cron', day_of_week='mon-fri', hour="09", minute="29", second="00", args=["SEHK", "00700"], max_instances=self.max_instances, id="SEHK_pushStatus_open") self.scheduler.add_job(self.check_TradeStatus, 'cron', day_of_week='mon-fri', hour="11-12,15", minute="59", second="00", args=["SEHK", "00700"], max_instances=self.max_instances, id="SEHK_pushStatus") # 美股 self.scheduler.add_job(self.check_TradeStatus, 'cron', day_of_week='mon-fri', hour="22", minute="29", second="00", args=[NASDAQ_exchange, NASDAQ_code1], max_instances=self.max_instances, id="NASDAQ_pushStatus_open") self.scheduler.add_job(self.check_TradeStatus, 'cron', day_of_week='mon-fri', hour="04", minute="59", second="00", args=[NASDAQ_exchange, NASDAQ_code1], max_instances=self.max_instances, id="NASDAQ_pushStatus") self.scheduler.add_job(self.check_TradeStatus, 'cron', day_of_week='sat', hour="04", minute="59", second="00", args=[ NASDAQ_exchange, NASDAQ_code1], max_instances=self.max_instances, id="NASDAQ_pushStatus_sat") # 定时任务运行入口 def run_Scheduler(self): self.run_CleanData() self.run_TradeStatus() # 更新合约 self.scheduler.add_job(start, 'cron', hour="08", minute="10", args=['SYNC_INSTR_REQ', codegenerate_dealer_address], id="dealer_instr") self.scheduler.add_listener(self.Listener, EVENT_JOB_EXECUTED | EVENT_JOB_ERROR) self.scheduler.start() try: asyncio.get_event_loop().run_forever() except (KeyboardInterrupt, SystemExit): pass