async def process_kline_update(self, data): """ Deal with 1min kline data, and publish kline message to EventCenter via KlineEvent. Args: data: Newest kline data. """ for item in data: timestamp = item[0] * 1000 _open = "%.8f" % float(item[1]) close = "%.8f" % float(item[2]) high = "%.8f" % float(item[3]) low = "%.8f" % float(item[4]) volume = "%.8f" % float(item[6]) symbol = item[-1].replace("_", "/") # Publish EventKline kline = { "platform": self._platform, "symbol": symbol, "open": _open, "high": high, "low": low, "close": close, "volume": volume, "timestamp": timestamp, "kline_type": const.MARKET_TYPE_KLINE } EventKline(**kline).publish() logger.info("symbol:", symbol, "kline:", kline, caller=self)
def __init__(self, platform, symbol, range_type=KLINE_1MIN): """ 初始化 @param platform 交易平台 @param symbol 交易对 @param range_type K线类型 1min 5min 15min,默认为 1min """ self._platform = platform # 交易平台 self._symbol = symbol # 交易对 self._open = None # 开盘价 self._high = None # 最高价 self._low = None # 最低价 self._close = None # 收盘价 self._volume = None # 交易量 self._timestamp = None # 更新时间戳(秒) self._range_type = range_type self._callback_handlers = [] # 外盘K线数据有更新的时候,执行的回调函数 # 订阅事件回调 if range_type == KLINE_1MIN: EventKline(self.platform, self.symbol).subscribe(self.on_event_kline) elif range_type == KLINE_5MIN: EventKline5Min(self.platform, self.symbol).subscribe(self.on_event_kline) elif range_type == KLINE_15MIN: EventKline15Min(self.platform, self.symbol).subscribe(self.on_event_kline)
async def process(self, msg): """ 处理websocket上接收到的消息 """ # logger.debug("msg:", msg, caller=self) if not isinstance(msg, dict): return channel = msg.get("stream") if channel not in self._c_to_s: logger.warn("unkown channel, msg:", msg, caller=self) return symbol = self._c_to_s[channel] data = msg.get("data") e = data.get("e") # 事件名称 # 保存数据到数据库 if e == "kline": # K线 kline = { "platform": self._platform, "symbol": symbol, "open": data.get("k").get("o"), # 开盘价 "high": data.get("k").get("h"), # 最高价 "low": data.get("k").get("l"), # 最低价 "close": data.get("k").get("c"), # 收盘价 "volume": data.get("k").get("q"), # 交易量 "timestamp": data.get("k").get("t"), # 时间戳 "kline_type": const.MARKET_TYPE_KLINE } EventKline(**kline).publish() logger.info("symbol:", symbol, "kline:", kline, caller=self) elif channel.endswith("depth20"): # 订单薄 bids = [] asks = [] for bid in data.get("bids"): bids.append(bid[:2]) for ask in data.get("asks"): asks.append(ask[:2]) orderbook = { "platform": self._platform, "symbol": symbol, "asks": asks, "bids": bids, "timestamp": tools.get_cur_timestamp_ms() } EventOrderbook(**orderbook).publish() logger.info("symbol:", symbol, "orderbook:", orderbook, caller=self) elif e == "trade": # 实时成交信息 trade = { "platform": self._platform, "symbol": symbol, "action": ORDER_ACTION_SELL if data["m"] else ORDER_ACTION_BUY, "price": data.get("p"), "quantity": data.get("q"), "timestamp": data.get("T") } EventTrade(**trade).publish() logger.info("symbol:", symbol, "trade:", trade, caller=self) else: logger.error("event error! msg:", msg, caller=self)
async def process_kline(self, data): """ Deal with 1min kline data, and publish kline message to EventCenter via KlineEvent. Args: data: Newest kline data. """ symbol = data["instrument_id"] if symbol not in self._symbols: return timestamp = tools.utctime_str_to_mts(data["candle"][0]) _open = "%.5f" % float(data["candle"][1]) high = "%.5f" % float(data["candle"][2]) low = "%.5f" % float(data["candle"][3]) close = "%.5f" % float(data["candle"][4]) volume = str(data["candle"][5]) # Publish EventKline kline = { "platform": self._platform, "symbol": symbol, "open": _open, "high": high, "low": low, "close": close, "volume": volume, "timestamp": timestamp, "kline_type": const.MARKET_TYPE_KLINE } EventKline(**kline).publish() logger.debug("symbol:", symbol, "kline:", kline, caller=self)
async def deal_kline_update(self, data): """ 处理K线数据 1分钟 """ symbol = data["instrument_id"].replace("-", "/") if symbol not in self._symbols: return timestamp = tools.utctime_str_to_mts(data["candle"][0]) _open = "%.8f" % float(data["candle"][1]) high = "%.8f" % float(data["candle"][2]) low = "%.8f" % float(data["candle"][3]) close = "%.8f" % float(data["candle"][4]) volume = "%.8f" % float(data["candle"][5]) # 推送trade数据 kline = { "platform": self._platform, "symbol": symbol, "open": _open, "high": high, "low": low, "close": close, "volume": volume, "timestamp": timestamp, "kline_type": const.MARKET_TYPE_KLINE } EventKline(**kline).publish() logger.info("symbol:", symbol, "kline:", kline, caller=self)
async def _publish_kline(self, symbol, new_kline): #发布自合成K线到消息队列 kwargs = { "platform": self.platform, "symbol": symbol, "timestamp": new_kline["begin_dt"], "kline_type": const.MARKET_TYPE_KLINE } kwargs.update(new_kline) #填充剩余字段 EventKline(**kwargs).publish()
async def process(self, msg): """ 处理websocket上接收到的消息 """ logger.debug("msg:", msg, caller=self) if not isinstance(msg, dict): return table = msg.get("table") if table == "orderBook10": # 订单薄数据 for item in msg["data"]: symbol = item.get("symbol") orderbook = { "platform": self._platform, "symbol": symbol, "asks": item.get("asks"), "bids": item.get("bids"), "timestamp": tools.utctime_str_to_mts(item["timestamp"]) } EventOrderbook(**orderbook).publish() logger.info("symbol:", symbol, "orderbook:", orderbook, caller=self) elif table == "trade": # 成交数据 for item in msg["data"]: symbol = item["symbol"] trade = { "platform": self._platform, "symbol": symbol, "action": ORDER_ACTION_BUY if item["side"] else ORDER_ACTION_SELL, "price": "%.1f" % item["price"], "quantity": str(item["size"]), "timestamp": tools.utctime_str_to_mts(item["timestamp"]) } EventTrade(**trade).publish() logger.info("symbol:", symbol, "trade:", trade, caller=self) elif table == "tradeBin1m": # 1分钟K线数据 for item in msg["data"]: symbol = item["symbol"] kline = { "platform": self._platform, "symbol": symbol, "open": "%.1f" % item["open"], # 开盘价 "high": "%.1f" % item["high"], # 最高价 "low": "%.1f" % item["low"], # 最低价 "close": "%.1f" % item["close"], # 收盘价 "volume": str(item["volume"]), # 交易量 "timestamp": tools.utctime_str_to_mts(item["timestamp"]), # 时间戳 "kline_type": MARKET_TYPE_KLINE } EventKline(**kline).publish() logger.info("symbol:", symbol, "kline:", kline, caller=self)
async def process_kline(self, symbol, data): """Process kline data and publish KlineEvent.""" kline = { "platform": self._platform, "symbol": symbol, "open": data.get("k").get("o"), "high": data.get("k").get("h"), "low": data.get("k").get("l"), "close": data.get("k").get("c"), "volume": data.get("k").get("q"), "timestamp": data.get("k").get("t"), "kline_type": const.MARKET_TYPE_KLINE } EventKline(**kline).publish() logger.info("symbol:", symbol, "kline:", kline, caller=self)
def __init__(self, market_type, platform, symbol, callback): """ 初始化 @param market_type 行情类型 @param platform 交易平台 @param symbol 交易对 @param callback 行情更新回调函数,必须是async异步函数,回调参数为行情对象,比如k线回调函数: async def on_event_kline_update(kline: Kline): pass """ if market_type == const.MARKET_TYPE_ORDERBOOK: from quant.event import EventOrderbook EventOrderbook(platform, symbol).subscribe(callback) elif market_type == const.MARKET_TYPE_TRADE: from quant.event import EventTrade EventTrade(platform, symbol).subscribe(callback) elif market_type == const.MARKET_TYPE_KLINE: from quant.event import EventKline EventKline(platform, symbol, kline_type=const.MARKET_TYPE_KLINE).subscribe(callback) elif market_type == const.MARKET_TYPE_KLINE_5M: from quant.event import EventKline EventKline(platform, symbol, kline_type=const.MARKET_TYPE_KLINE).subscribe(callback) elif market_type == const.MARKET_TYPE_KLINE_15M: from quant.event import EventKline EventKline(platform, symbol, kline_type=const.MARKET_TYPE_KLINE_15M).subscribe(callback) else: logger.error("market_type error:", market_type, caller=self)
async def on_kline_update_callback(self, kline: Kline): """ 市场K线更新 """ logger.info("kline:", kline, caller=self) kwargs = { "platform": kline.platform, "symbol": kline.symbol, "open": "%.8f" % kline.open, "high": "%.8f" % kline.high, "low": "%.8f" % kline.low, "close": "%.8f" % kline.close, "volume": kline.volume, "timestamp": kline.timestamp, "kline_type": kline.kline_type } EventKline(**kwargs).publish()
def __init__(self, market_type, platform, symbol, callback): """ 初始化 @param market_type 行情类型 @param platform 交易平台 @param symbol 交易对 @param callback 更新回调函数 """ if market_type == const.MARKET_TYPE_ORDERBOOK: from quant.event import EventOrderbook EventOrderbook(platform, symbol).subscribe(callback) elif market_type == const.MARKET_TYPE_TRADE: from quant.event import EventTrade EventTrade(platform, symbol).subscribe(callback) elif market_type == const.MARKET_TYPE_KLINE: from quant.event import EventKline EventKline(platform, symbol).subscribe(callback)
async def on_event_kline(self, event): """ 事件回调 K线信息 """ event = EventKline().duplicate(event) if event.platform != self._platform: return if event.symbol != self._symbol: return self._open = event.open self._high = event.high self._low = event.low self._close = event.close self._volume = event.volume self._timestamp = event.timestamp for func in self._callback_handlers: asyncio.get_event_loop().create_task( func(event.platform, event.data))
def __init__(self, market_type, platform, symbol, callback): """ Initialize. """ if platform == "#" or symbol == "#": multi = True else: multi = False if market_type == const.MARKET_TYPE_ORDERBOOK: from quant.event import EventOrderbook EventOrderbook(platform, symbol).subscribe(callback, multi) elif market_type == const.MARKET_TYPE_TRADE: from quant.event import EventTrade EventTrade(platform, symbol).subscribe(callback, multi) elif market_type in [const.MARKET_TYPE_KLINE, const.MARKET_TYPE_KLINE_5M, const.MARKET_TYPE_KLINE_15M]: from quant.event import EventKline EventKline(platform, symbol, kline_type=market_type).subscribe(callback, multi) else: logger.error("market_type error:", market_type, caller=self)
async def process_kline(self, data): """Process kline data and publish KlineEvent.""" for item in data: symbol = item["symbol"] kline = { "platform": self._platform, "symbol": symbol, "open": "%.1f" % item["open"], "high": "%.1f" % item["high"], "low": "%.1f" % item["low"], "close": "%.1f" % item["close"], "volume": str(item["volume"]), "timestamp": tools.utctime_str_to_mts(item["timestamp"]), "kline_type": MARKET_TYPE_KLINE } EventKline(**kline).publish() logger.info("symbol:", symbol, "kline:", kline, caller=self)
async def do_kline_update(self, symbol, kline_type): if kline_type == const.MARKET_TYPE_KLINE_5M: range_type = "5min" elif kline_type == const.MARKET_TYPE_KLINE_15M: range_type = "15min" elif kline_type == const.MARKET_TYPE_KLINE_1H: range_type = "60min" elif kline_type == const.MARKET_TYPE_KLINE_1H: range_type = "4hour" elif kline_type == const.MARKET_TYPE_KLINE_1H: range_type = "1day" else: return result, error = await self._rest_api.get_kline(symbol, size=130, period=range_type) if error: return open, hig, low, close = [], [], [], [] if len(result): for item in result["data"]: open.append(item["open"]) hig.append(item["high"]) low.append(item["low"]) close.append(item["close"]) kline = { "platform": self._platform, "symbol": symbol, "open": open, #最近的数据在最后面 "high": hig, "low": low, "close": close, "kline_type": kline_type } EventKline(**kline).publish() logger.info("symbol:", symbol, "kline_%s:" % range_type, kline, caller=self)
async def do_kline_update(self, symbol, kline_type): if kline_type == const.MARKET_TYPE_KLINE_5M: range_type = 5 * 60 elif kline_type == const.MARKET_TYPE_KLINE_15M: range_type = 15 * 60 elif kline_type == const.MARKET_TYPE_KLINE_1H: range_type = 60 * 60 else: return start = get_timestamp(datetime.datetime.now() - datetime.timedelta(days=5)) end = get_timestamp() result, error = await self._rest_api.get_kline(symbol, start, end, range_type) if error: return open, hig, low, close = [], [], [], [] if len(result): for item in result: open.append(item[1]) hig.append(item[2]) low.append(item[3]) close.append(item[4]) kline = { "platform": self._platform, "symbol": symbol, "open": open[::-1], #最近的数据在最后面 "high": hig[::-1], "low": low[::-1], "close": close[::-1], "kline_type": kline_type } print(kline) EventKline(**kline).publish() logger.info("symbol:", symbol, "kline:", kline, caller=self)
async def do_kline_update(self, symbol, kline_type): if kline_type == const.MARKET_TYPE_KLINE_5M: range_type = "5min" elif kline_type == const.MARKET_TYPE_KLINE_15M: range_type = "15min" else: return result, error = await self._rest_api.get_kline(symbol, 1, range_type) if error: return kline = { "platform": self._platform, "symbol": symbol, "open": "%.8f" % float(result[0]["open"]), "high": "%.8f" % float(result[0]["high"]), "low": "%.8f" % float(result[0]["low"]), "close": "%.8f" % float(result[0]["close"]), "volume": "%.8f" % float(result[0]["volume"]), "timestamp": result[0]["timestamp"], "kline_type": kline_type } EventKline(**kline).publish() logger.info("symbol:", symbol, "kline:", kline, caller=self)
async def on_kline_update_callback(self, kline: Kline): """ 市场K线更新 """ logger.info("kline:", kline, caller=self) #行情保存进数据库 kwargs = { "open": kline.open, "high": kline.high, "low": kline.low, "close": kline.close, "volume": kline.volume, "begin_dt": kline.timestamp, "end_dt": kline.timestamp + 60 * 1000 - 1 } async def save(kwargs): t_kline = self.t_kline_map[kline.symbol] if t_kline: s, e = await t_kline.insert(kwargs) if e: logger.error("insert kline:", e, caller=self) SingleTask.run(save, kwargs) #发布行情到消息队列 kwargs = { "platform": kline.platform, "symbol": kline.symbol, "open": kline.open, "high": kline.high, "low": kline.low, "close": kline.close, "volume": kline.volume, "timestamp": kline.timestamp, "kline_type": kline.kline_type } EventKline(**kwargs).publish()
async def process_binary(self, msg): """ 处理websocket上接收到的消息 """ data = json.loads(gzip.decompress(msg).decode()) # logger.debug("data:", json.dumps(data), caller=self) channel = data.get("ch") if not channel: if data.get("ping"): self.heartbeat_msg = data return symbol = self._c_to_s[channel] if channel.find("kline") != -1: # K线 d = data.get("tick") kline = { "platform": self._platform, "symbol": symbol, "open": "%.8f" % d["open"], # 开盘价 "high": "%.8f" % d["high"], # 最高价 "low": "%.8f" % d["low"], # 最低价 "close": "%.8f" % d["close"], # 收盘价 "volume": "%.8f" % d["amount"], # 成交量 "timestamp": int(data.get("ts")), # 时间戳 "kline_type": MARKET_TYPE_KLINE } EventKline(**kline).publish() logger.info("symbol:", symbol, "kline:", kline, caller=self) elif channel.find("depth") != -1: # 订单薄 d = data.get("tick") asks, bids = [], [] for item in d.get("asks")[:10]: price = "%.8f" % item[0] quantity = "%.8f" % item[1] asks.append([price, quantity]) for item in d.get("bids")[:10]: price = "%.8f" % item[0] quantity = "%.8f" % item[1] bids.append([price, quantity]) orderbook = { "platform": self._platform, "symbol": symbol, "asks": asks, "bids": bids, "timestamp": d.get("ts") } EventOrderbook(**orderbook).publish() logger.info("symbol:", symbol, "orderbook:", orderbook, caller=self) elif channel.find("trade") != -1: # 实时交易数据 tick = data.get("tick") direction = tick["data"][0].get("direction") price = tick["data"][0].get("price") quantity = tick["data"][0].get("amount") trade = { "platform": self._platform, "symbol": symbol, "action": ORDER_ACTION_BUY if direction == "buy" else ORDER_ACTION_SELL, "price": "%.8f" % price, "quantity": "%.8f" % quantity, "timestamp": tick.get("ts") } EventTrade(**trade).publish() logger.info("symbol:", symbol, "trade:", trade, caller=self) else: logger.error("event error! msg:", msg, caller=self)
async def process_binary(self, msg): """ Process binary message that received from Websocket connection. Args: msg: Binary message. """ data = json.loads(gzip.decompress(msg).decode()) # logger.debug("data:", json.dumps(data), caller=self) channel = data.get("ch") if not channel: if data.get("ping"): hb_msg = {"pong": data.get("ping")} await self._ws.send(hb_msg) return symbol = self._c_to_s[channel] if channel.find("kline") != -1: d = data.get("tick") kline = { "platform": self._platform, "symbol": symbol, "open": d["open"], "high": d["high"], "low": d["low"], "close": d["close"], "volume": d["amount"], "timestamp": data.get("ts"), "kline_type": MARKET_TYPE_KLINE } EventKline(**kline).publish() logger.debug("symbol:", symbol, "kline:", kline, caller=self) elif channel.find("depth") != -1: tick = data.get("tick") asks = tick.get("asks")[:self._orderbook_length] bids = tick.get("bids")[:self._orderbook_length] timestamp = tick.get("ts") orderbook = { "platform": self._platform, "symbol": symbol, "asks": asks, "bids": bids, "timestamp": timestamp } EventOrderbook(**orderbook).publish() logger.debug("symbol:", symbol, "orderbook:", orderbook, caller=self) elif channel.find("trade") != -1: tick = data.get("tick") direction = tick["data"][0].get("direction") price = tick["data"][0].get("price") quantity = tick["data"][0].get("amount") trade = { "platform": self._platform, "symbol": symbol, "action": ORDER_ACTION_BUY if direction == "buy" else ORDER_ACTION_SELL, "price": price, "quantity": quantity, "timestamp": tick.get("ts") } EventTrade(**trade).publish() logger.debug("symbol:", symbol, "trade:", trade, caller=self) else: logger.error("event error! msg:", msg, caller=self)