def on_default_handler(self, header: ResponseHeader, body: Buffer): """ 如果没有匹配处理器则由此处理 :param header: :param body: :return: """ if header.event_id == 0x0B: print("注册模拟设备成功的信息: %s." % str(binascii.b2a_hex(body.bytes()))) elif header.event_id == 0x0FDB: notice = struct.unpack("<116s", body.bytes()[0xb2:0x126]) print("收到代理服务器的公告信息:%s ..." % notice[0].decode('gbk')) callback_proc = self.get_handler(EVENT_READY) if callback_proc is not None: callback_proc() elif header.event_id == 0x000D: self.market = ResponseMarketInfo.parse(body) print("市场最新交易信息: 券商名称:%s, 最后交易时间:%d" % (self.market.server_name, self.market.date_sz)) elif header.event_id == 0x044E: count = body.read_format("<H")[0] if header.cmd_id == 0x6B: print("收到sz市场股票数量为: %d." % count) self.stock_sz_count = count elif header.cmd_id == 0x6C: print("收到sh市场股票数量为: %d." % count) self.stock_sh_count = count else: # 收到未知封包 print("收到未知封包, event_id = %d, content: %s." % (header.event_id, str(binascii.b2a_hex(body.bytes()))))
def handle_read(self): super(TdxReportClient, self).handle_read() while True: try: if self.in_buffer.length() <= 0: break header_size = ResponseHeader.length() header = self.in_buffer.peek_bytes(header_size) if len(header) < header_size: self.get_handler(0)(header=Buffer(header)) break """ L: 封包标识 B: 是否压缩的标识 H: 索引(股票索引) B: 判断封包类型(此字段与发送的字段相同,靠这个字段可以确定封包的功能) H: 未知标识 H: 事件标识,靠此字段可以确定封包的类别 2H: 分别是封包长度, 解压所需要的空间大小 """ obj_header = ResponseHeader.parse(Buffer(header)) if self.in_buffer.length( ) < obj_header.body_length + header_size: # 如果封包不足则等待下一次接收后继续再判断,直至封包完整再继续解析 break self.in_buffer.read_bytes(header_size) compress_data = self.in_buffer.read_bytes( obj_header.body_length) if obj_header.is_compress: decompiler = zlib.decompressobj() content = decompiler.decompress(compress_data) else: content = compress_data # print("收到 content: %s." % str(binascii.b2a_hex(content))) handle_proc = self.get_handler(obj_header.event_id) if handle_proc is None: self.get_handler(0)(header=obj_header, body=Buffer(content)) else: handle_proc(header=obj_header, body=Buffer(content)) except StopIteration: sys.exit() except Exception as ex: print("发生未知错误: %s" % str(ex))
def on_download(self, header: ResponseHeader, body: Buffer): length = body.read_format("<I")[0] # 移除body大小字段, 只保留文件内容 content = body.bytes() if self.current_report_offset is 0: fp = open(self.current_save_report, 'wb+') else: fp = open(self.current_save_report, 'ab+') self.current_report_offset += length with fp as outfile: outfile.write(content) fp.close() self.send(next(self.data_gen))
def parse(cls, data: Buffer, _fund: bool = False): """ 解析 :param data: :param bool _fund: 是否是基金 :return: """ data_stock = data.read_format(cls.__identity) stock_day = ResponseStockDays() stock_day.date = "%d%02d%02d" % (data_stock[0] / 10000, data_stock[0] % 10000 / 100, data_stock[0] % 100) precision = 100.00 if _fund: precision = 1000.00 stock_day.open = data_stock[1] / precision stock_day.high = data_stock[2] / precision stock_day.low = data_stock[3] / precision stock_day.close = data_stock[4] / precision stock_day.amount = data_stock[5] stock_day.volume = data_stock[6] return stock_day
def on_stock_bonus(self, header: ResponseHeader, body: Buffer): """处理权息封包""" idx = 0 current_df_list = [] stocks_count = body.read_format("<H")[0] self.bonus_idx += stocks_count while idx < stocks_count: idx += 1 bonus_idx = 0 body.read_bytes(7) # 跳过股票代码和市场的字节 bonus_count = body.read_format("<H")[0] while bonus_idx < bonus_count: stock_bonus = ResponseStockBonus.parse(body) bonus_item = [ stock_bonus.code, stock_bonus.date, stock_bonus.market, stock_bonus.type, stock_bonus.money, stock_bonus.price, stock_bonus.count, stock_bonus.rate ] current_df_list.append(bonus_item) bonus_idx += 1 data_bonus = pd.DataFrame(current_df_list, columns=[ "code", "date", "market", "type", "money", "price", "count", "rate" ]) self.data_bonus = pd.concat([self.data_bonus, data_bonus], ignore_index=True) print("收到 %d 只股票的高送转信息." % stocks_count) if header.idx == 0x1100: print("保存权息数据") self.data_bonus.to_csv(config.get("files").get("bonus"), index=False, mode="w", encoding='utf8', float_format="%.6f") # 数据更新完毕, 解除事件绑定 self.bonus_idx = 0 self.proxy.del_handler(header.event_id) print("权息数据更新完毕") self.proxy.close() else: self.update_bonus()
def on_default_handler(header: ResponseHeader, body: Buffer): """ 如果没有匹配处理器则由此处理 :param header: :param body: :return: """ print("收到未知封包, event_id = %d, content: %s." % (header.event_id, str(binascii.b2a_hex(body.bytes()))))
def on_base(self, header: ResponseHeader, body: Buffer): """更新市场股票基础信息列表""" idx = 0 current_df_list = [] market_type = 0 if header.cmd_id == 0x6D else 1 # 0表示深市,1表示沪市 stocks_count = body.read_format("<H")[0] while idx < stocks_count: obj_stock_base = ResponseStockBase.parse(body) stock_item = [ obj_stock_base.code, obj_stock_base.name, market_type, obj_stock_base.unknown1, obj_stock_base.unknown2, obj_stock_base.unknown3, obj_stock_base.price, obj_stock_base.bonus1, obj_stock_base.bonus2 ] current_df_list.append(stock_item) idx += 1 data_stocks = pd.DataFrame(current_df_list, columns=[ 'code', 'name', 'market', 'unknown1', 'unknown2', 'unknown3', 'price', 'bonus1', 'bonus2' ]) self.data_stocks = pd.concat([self.data_stocks, data_stocks], ignore_index=True) if len(self.data_stocks) >= (self.proxy.stock_sz_count + self.proxy.stock_sh_count): # 保存数据信息 print("保存基础数据...") self.data_stocks.to_csv(config.get("files").get("stock_list"), index=False, mode="w", encoding='utf8', float_format="%.3f") # 解绑事件处理器 self.proxy.del_handler(header.event_id) # 开始更新股票权息数据 self.update_bonus() return self.proxy.send(next(self.data_gen))
def on_history(self, header: ResponseHeader, body: Buffer): """处理日线封包""" current_df_list = [] is_st = 0 stock_code = self.data_stocks.ix[header.idx]['code'] stock_name = self.data_stocks.ix[header.idx]['name'] market = int(self.data_stocks.ix[header.idx]['market']) if header.cmd_id != 0x87: # 只处理日线数据 return if stock_name.startswith("ST") or stock_name.startswith("SST") or \ stock_name.startswith("*ST") or stock_name.startswith("S*ST"): is_st = 1 # 日线数据 item_count = body.read_format("<HL")[1] / ResponseStockDays.length() idx = 0 while idx < item_count: if stocks.type_with_code(stock_code) == 2: item = ResponseStockDays.parse(body, _fund=True) else: item = ResponseStockDays.parse(body) current_df_list.append([ item.date, int(market), stock_code, stock_name, item.open, item.low, item.high, item.close, item.volume, item.amount, is_st ]) idx += 1 print("获取 %d-%s 的日线数据" % (market, stock_code)) hs_df = pd.DataFrame(current_df_list, columns=[ 'date', 'market', 'code', 'name', 'open', 'low', 'high', 'close', 'volume', 'amount', 'st' ]) self.__db_client.insert_json(hs_df) self.proxy.send(next(self.data_gen))
def parse(cls, data: Buffer): """ 解析 :param data: :return: """ market_info = ResponseMarketInfo() server_info = data.read_format(cls.__identity) market_info.date_sz = server_info[11] market_info.last_flag_sz = server_info[12] market_info.data_sh = server_info[13] market_info.last_flag_sh = server_info[14] market_info.server_name = str(server_info[18].decode('gbk')) market_info.domain_url = str(server_info[19].decode('ascii')) return market_info
def parse(cls, data: Buffer): """ 解析应答封包 :param data: :return: """ header = ResponseHeader() data_header = data.read_format(cls.__identity) header.pkg_flag = data_header[0] header.is_compress = data_header[1] & 0x10 != 0 header.idx = data_header[2] header.cmd_id = data_header[3] header.unknown = data_header[4] header.event_id = data_header[5] header.body_length = data_header[6] header.body_max_length = data_header[7] return header
def parse(cls, data: Buffer): """ 解析 :param data: :return: """ data_stock = data.read_format(cls.__identity) stock_base = ResponseStockBase() stock_base.code = "%s" % data_stock[0].decode('gbk') stock_base.unknown1 = data_stock[1] stock_base.name = "%s" % data_stock[2].decode('gbk').replace("\00", "") stock_base.unknown2 = data_stock[3] stock_base.unknown3 = data_stock[4] stock_base.price = data_stock[5] stock_base.bonus1 = data_stock[6] stock_base.bonus2 = data_stock[7] return stock_base
def parse(cls, data: Buffer): """ 解析 :param data: :return: """ data_stock = data.read_format(cls.__identity) stock_bonus = ResponseStockBonus() stock_bonus.market = data_stock[0] stock_bonus.code = "%s" % data_stock[1].decode('ascii') stock_bonus.date = "%d%02d%02d" % (data_stock[3] / 10000, data_stock[3] % 10000 / 100, data_stock[3] % 100) stock_bonus.type = data_stock[4] stock_bonus.money = data_stock[5] stock_bonus.price = data_stock[6] stock_bonus.count = data_stock[7] stock_bonus.rate = data_stock[8] return stock_bonus
def on_report_list(self, header: ResponseHeader, body: Buffer): body.read_format("<I") content = body.bytes().decode("utf-8") self.cw_list = content.split('\n') self.__callback_proc()