def subscribe(self, instrument_id_list=None): """订阅合约""" super().subscribe(instrument_id_list) if instrument_id_list is None: instrument_id_list = self.instrument_id_list # channel_head = Config.REDIS_CHANNEL[self.md_period] # channel_list = [channel_head + instrument_id for instrument_id in instrument_id_list] channel_list = [get_channel(config.MARKET_NAME, self.md_period, instrument_id) for instrument_id in instrument_id_list] self.pub_sub.psubscribe(*channel_list)
def unsubscribe(self, instrument_id_list): """退订合约""" if instrument_id_list is None: instrument_id_list = self.instrument_id_list super().unsubscribe(instrument_id_list) # channel_head = config.REDIS_CHANNEL[self.md_period] # channel_list = [channel_head + instrument_id for instrument_id in instrument_id_list] channel_list = [get_channel(config.MARKET_NAME, self.md_period, instrument_id) for instrument_id in instrument_id_list] if self.pub_sub is not None: # 在回测模式下有可能不进行 connect 调用以及 subscribe 订阅,因此,没有 pub_sub 实例 self.pub_sub.punsubscribe(*channel_list)
def check_redis(): """ 检测redis是否可以正常工作 """ global _signal instrument_id = 'rb1805' channel = get_channel(market=config.MARKET_NAME, period=PeriodType.Year1, symbol=instrument_id) logger.info('测试 Channel:%s', channel) _signal['redis'] = False timer_t = threading.Thread(target=_timer, args=(channel, )) timer_t.start() def _receiver(_channel): # 接收订阅的行情,成功接收后退出 global _signal redis_client = get_redis(config.REDIS_INFO_DIC['REDIS_HOST'], config.REDIS_INFO_DIC['REDIS_PORT']) try: pub_sub = redis_client.pubsub() pub_sub.psubscribe(_channel) for item in pub_sub.listen(): logger.debug("接收成功 %s", item) if item['type'] == 'pmessage': md_dic_str = bytes_2_str(item['data']) md_dic = json.loads(md_dic_str) if "message" in md_dic and "count" in md_dic: _signal['redis'] = True logger.debug("接收到消息") break except: logger.exception('Redis 检测时发现异常,可能是由于redis没有启动') pass receiver_t = threading.Thread(target=_receiver, args=(channel, )) receiver_t.start() for n in range(20): if _signal['redis']: logging.debug("检测redis %d %s", n, _signal['redis']) timer_t.join(1) break time.sleep(1) else: logger.error("redis 检测未通过") return _signal['redis']
def check_redis(): global _signal # channel_header = Config.REDIS_CHANNEL[PeriodType.Tick] instrument_id = 'rb1805' # channel = channel_header + 'test.' + instrument_id channel = get_channel(ExchangeName.BitMex.name, PeriodType.Year1, instrument_id) _signal['redis'] = False timer_t = threading.Thread(target=_timer, args=(channel, )) timer_t.start() def _receiver(channel): # 接收订阅的行情,成功接收后退出 global _signal redis_client = get_redis() pub_sub = redis_client.pubsub() pub_sub.psubscribe(channel) for item in pub_sub.listen(): logger.debug("接收成功 %s", item) if item['type'] == 'pmessage': md_dic_str = bytes_2_str(item['data']) md_dic = json.loads(md_dic_str) if "message" in md_dic and "count" in md_dic: _signal['redis'] = True logger.debug("接收到消息") break receiver_t = threading.Thread(target=_receiver, args=(channel, )) receiver_t.start() for n in range(20): if _signal['redis']: logging.debug("检测redis %d %s", n, _signal['redis']) timer_t.join(1) break time.sleep(1) else: logger.error("redis 检测未通过") return _signal['redis']
def handle(self, msg): """ 收到数据后,tick数据直接发送, channel:md.market.tick.pair channel:md.market.min1.pair 每个分钟时点切换时,发送一次分钟线数据 例如: md.huobi.tick.ethusdt md.huobi.1min.ethusdt 通过 redis-cli 可以 PUBSUB CHANNELS 查阅活跃的频道 PSUBSCRIBE pattern [pattern ...] 查看频道内容 SUBSCRIBE channel [channel ...] 查看频道内容 :param msg: :return: """ # TODO: 设定一个定期检查机制,只发送订阅的品种,降低网络负载 if 'ch' in msg: topic = msg.get('ch') _, symbol, _, period_str = topic.split('.') data = msg.get('tick') # 调整相关属性 ts_start = datetime.fromtimestamp(data.pop('id')) data['ts_start'] = datetime_2_str(ts_start, format=STR_FORMAT_DATETIME2) data['market'] = config.MARKET_NAME # 'huobi' data['ts_curr'] = datetime_2_str(datetime.fromtimestamp(msg['ts'] / 1000), format=STR_FORMAT_DATETIME2) data['symbol'] = symbol # Json md_str = json.dumps(data) # 先发送Tick数据 if period_str == '1min': # channel = f'md.{self.market}.tick.{symbol}' channel = get_channel(self.market, PeriodType.Tick, symbol) self.r.publish(channel, md_str) # period_str 1min, 5min, 15min, 30min, 60min, 1day, 1mon, 1week, 1year if period_str == '1min': period = PeriodType.Min1 elif period_str == '5min': period = PeriodType.Min5 elif period_str == '15min': period = PeriodType.Min15 elif period_str == '30min': period = PeriodType.Min30 elif period_str == '60min': period = PeriodType.Hour1 elif period_str == '1day': period = PeriodType.Day1 elif period_str == '1mon': period = PeriodType.Mon1 elif period_str == '1week': period = PeriodType.Week1 elif period_str == '1year': period = PeriodType.Year1 else: raise ValueError('period_str=%s 为无效参数' % period_str) # 分钟线切换时发送分钟线数据 ts_start_last = self.last_ts_start_pair_tick.setdefault((period_str, symbol), None) if ts_start_last is not None and ts_start_last != ts_start: md_str_last = self.last_tick_pair_tick[(period_str, symbol)] # channel_min1 = f'md.{self.market}.{period}.{pair}' channel_min1 = get_channel(self.market, period, symbol) self.r.publish(channel_min1, md_str_last) self.last_ts_start_pair_tick[(period_str, symbol)] = ts_start self.last_tick_pair_tick[(period_str, symbol)] = md_str elif 'rep' in msg: # topic = msg.get('rep') # data = msg.get('data') self.logger.info(msg) else: self.logger.warning(msg)