def __init__(self, symbol="ALL", application=None): self.symbol = str(symbol) self.buy_side = [] self.sell_side = [] self.volume_dict = {} self.inst_status = InstrumentStatusHelper(symbol) self.md_pub_socket = None self.md_pub_socket_stream = None self.is_ready = False self.process_later = [] self.application = application self.db_session = application.db_session
def __init__(self, symbol = "ALL", application = None): self.symbol = str(symbol) self.buy_side = [] self.sell_side = [] self.volume_dict = {} self.inst_status = InstrumentStatusHelper(symbol) self.md_pub_socket = None self.md_pub_socket_stream = None self.is_ready = False self.process_later = [] self.application = application self.db_session = application.db_session
class MarketDataSubscriber(object): """" MarketDataSubscriber. """ @classmethod def instance(cls): if not hasattr(cls, "_instance"): cls._instance = cls() return cls._instance def __init__(self, symbol = "ALL", application = None): self.symbol = str(symbol) self.buy_side = [] self.sell_side = [] self.volume_dict = {} self.inst_status = InstrumentStatusHelper(symbol) self.md_pub_socket = None self.md_pub_socket_stream = None self.is_ready = False self.process_later = [] self.application = application self.db_session = application.db_session def subscribe(self,zmq_context,trade_pub_connection_string,trade_client): """" subscribe. """ self.md_pub_socket = zmq_context.socket(zmq.SUB) self.md_pub_socket.connect(trade_pub_connection_string) self.md_pub_socket.setsockopt(zmq.SUBSCRIBE,"MD_FULL_REFRESH_" +self.symbol) self.md_pub_socket.setsockopt(zmq.SUBSCRIBE, "MD_TRADE_" + self.symbol) self.md_pub_socket.setsockopt(zmq.SUBSCRIBE,"MD_INCREMENTAL_" +self.symbol +".0") self.md_pub_socket.setsockopt(zmq.SUBSCRIBE,"MD_INCREMENTAL_" +self.symbol +".1") self.md_pub_socket_stream = ZMQStream(self.md_pub_socket) self.md_pub_socket_stream.on_recv(self.on_md_publish) md_subscription_msg = { 'MsgType': 'V', 'MDReqID': '0', # not important. 'SubscriptionRequestType': '0', 'MarketDepth': 0, 'TradeDate': time.strftime("%Y%m%d", time.localtime()), 'MDUpdateType': '0', 'MDEntryTypes': ['0', '1', '2'], 'Instruments': [self.symbol] } return trade_client.sendJSON(md_subscription_msg) def ready(self): self.is_ready = True for trade in self.process_later: self.on_trade(trade) self.process_later = [] @staticmethod def get(symbol, application=None): """" get. """ global MDSUBSCRIBEDICT if symbol not in MDSUBSCRIBEDICT: MDSUBSCRIBEDICT[symbol] = MarketDataSubscriber(symbol, application) return MDSUBSCRIBEDICT[symbol] def get_last_trades(self): """" get_last_trades. """ return Trade.get_last_trades(self.db_session) def get_trades(self, symbol, since): """" get_trades. """ return Trade.get_trades(self.db_session, symbol, since) def on_md_publish(self, publish_msg): """" on_md_publish. """ topic = publish_msg[0] raw_message = publish_msg[1] self.application.log('IN', 'TRADE_PUB', raw_message ) msg = JsonMessage(raw_message) if msg.type == 'W': # Full Refresh self.on_md_full_refresh(msg) elif msg.type == 'X': # Incremental self.on_md_incremental(msg) def on_md_full_refresh(self, msg): """" on_md_full_refresh. """ # TODO: Check if our current order book is sync with the full refresh if msg.get('MarketDepth') != 1: # Has Market Depth self.on_book_clear() self.on_trade_clear() group = msg.get('MDFullGrp') for entry in group: entry_type = entry.get('MDEntryType') if entry_type == '0' or entry_type == '1': self.on_book_new_order(entry) elif entry_type == '2': self.on_trade(entry) def on_md_incremental(self, msg): """" on_md_incremental. """ if msg.get('MDBkTyp') == '3': # Order Depth group = msg.get('MDIncGrp') for entry in group: entry_type = entry.get('MDEntryType') signal_order_depth_entry( self.symbol + '.3.' + entry_type, entry) if entry_type == '0' or entry_type == '1': update_action = entry.get('MDUpdateAction') if update_action == '0': self.on_book_new_order(entry) elif update_action == '1': self.on_book_update_order(entry) elif update_action == '2': self.on_book_delete_order(entry) elif update_action == '3': self.on_book_delete_orders_thru(entry) elif entry_type == '2': self.on_trade(entry) signal_publish_md_order_depth_incremental( self.symbol + '.3', {"MsgType": "X"}) def on_book_clear(self): """" on_book_clear. """ self.buy_side = [] self.sell_side = [] def on_trade_clear(self): """" on_trade_clear. """ self.volume_dict = {} def on_book_delete_orders_thru(self, msg): """" on_book_delete_orders_thru. """ index = msg.get('MDEntryPositionNo') side = msg.get('MDEntryType') if side == '0': self.buy_side = self.buy_side[index:] if self.buy_side: self.inst_status.set_best_bid(self.buy_side[0]['price']) else: self.inst_status.set_best_bid(None) elif side == '1': self.sell_side = self.sell_side[index:] if self.sell_side: self.inst_status.set_best_ask(self.sell_side[0]['price']) else: self.inst_status.set_best_ask(None) def on_book_delete_order(self, msg): """" on_book_delete_order. """ index = msg.get('MDEntryPositionNo') - 1 side = msg.get('MDEntryType') if side == '0': del self.buy_side[index] if index == 0: if self.buy_side: self.inst_status.set_best_bid(self.buy_side[0]['price']) else: self.inst_status.set_best_bid(None) elif side == '1': del self.sell_side[index] if index == 0: if self.sell_side: self.inst_status.set_best_ask(self.sell_side[0]['price']) else: self.inst_status.set_best_ask(None) def on_book_new_order(self, msg): """" on_book_new_order. """ index = msg.get('MDEntryPositionNo') - 1 order = { 'price': msg.get('MDEntryPx'), 'qty': msg.get('MDEntrySize'), 'username': msg.get('Username'), 'user_id': msg.get('UserID'), 'broker': msg.get('Broker'), 'order_id': msg.get('OrderID'), 'side': msg.get('MDEntryType'), 'order_time': msg.get('MDEntryTime'), 'order_date': msg.get('MDEntryDate') } if msg.get('MDEntryType') == '0': # buy self.buy_side.insert(index, order) if index == 0: self.inst_status.set_best_bid(msg.get('MDEntryPx')) elif msg.get('MDEntryType') == '1': # sell self.sell_side.insert(index, order) if index == 0: self.inst_status.set_best_ask(msg.get('MDEntryPx')) def on_book_update_order(self, msg): """" on_book_new_order. """ index = msg.get('MDEntryPositionNo') - 1 order = { 'price': msg.get('MDEntryPx'), 'qty': msg.get('MDEntrySize'), 'username': msg.get('Username'), 'user_id': msg.get('UserID'), 'broker': msg.get('Broker'), 'order_id': msg.get('OrderID'), 'side': msg.get('MDEntryType'), 'order_time': msg.get('MDEntryTime'), 'order_date': msg.get('MDEntryDate') } if msg.get('MDEntryType') == '0': # sell self.buy_side[index] = order if index == 0: self.inst_status.set_best_bid(msg.get('MDEntryPx')) elif msg.get('MDEntryType') == '1': # sell self.sell_side[index] = order if index == 0: self.inst_status.set_best_ask(msg.get('MDEntryPx')) def on_trade(self, msg): if not self.is_ready: self.process_later.append(msg) return trade = { "price": msg.get('MDEntryPx'), "symbol": msg.get('Symbol'), "size": msg.get('MDEntrySize'), "trade_date": msg.get('MDEntryDate'), "trade_time": msg.get('MDEntryTime'), "order_id": msg.get('OrderID'), "side": msg.get('Side'), "counter_order_id": msg.get('SecondaryOrderID'), "id": msg.get('TradeID'), "buyer_id": msg.get('MDEntryBuyerID'), "seller_id": msg.get('MDEntrySellerID'), "buyer_username": msg.get('MDEntryBuyer'), "seller_username": msg.get('MDEntrySeller'), } Trade.create(self.db_session, trade) # BTC BRL price_currency = self.symbol[3:] size_currency = self.symbol[:3] if price_currency not in self.volume_dict: self.volume_dict[price_currency] = 0 if size_currency not in self.volume_dict: self.volume_dict[size_currency] = 0 volume_price = int( msg.get('MDEntryPx') * msg.get('MDEntrySize') / 1.e8) volume_size = msg.get('MDEntrySize') self.volume_dict[price_currency] += volume_price self.volume_dict[size_currency] += volume_size self.volume_dict['MDEntryType'] = '4' signal_publish_md_status('MD_STATUS', self.volume_dict) self.inst_status.push_trade(trade)
class MarketDataSubscriber(object): """" MarketDataSubscriber. """ @classmethod def instance(cls): if not hasattr(cls, "_instance"): cls._instance = cls() return cls._instance def __init__(self, symbol="ALL", application=None): self.symbol = str(symbol) self.buy_side = [] self.sell_side = [] self.volume_dict = {} self.inst_status = InstrumentStatusHelper(symbol) self.md_pub_socket = None self.md_pub_socket_stream = None self.is_ready = False self.process_later = [] self.application = application self.db_session = application.db_session def subscribe(self, zmq_context, trade_pub_connection_string, trade_client): """" subscribe. """ self.md_pub_socket = zmq_context.socket(zmq.SUB) self.md_pub_socket.connect(trade_pub_connection_string) self.md_pub_socket.setsockopt(zmq.SUBSCRIBE, "MD_FULL_REFRESH_" + self.symbol) self.md_pub_socket.setsockopt(zmq.SUBSCRIBE, "MD_TRADE_" + self.symbol) self.md_pub_socket.setsockopt(zmq.SUBSCRIBE, "MD_INCREMENTAL_" + self.symbol + ".0") self.md_pub_socket.setsockopt(zmq.SUBSCRIBE, "MD_INCREMENTAL_" + self.symbol + ".1") self.md_pub_socket_stream = ZMQStream(self.md_pub_socket) self.md_pub_socket_stream.on_recv(self.on_md_publish) md_subscription_msg = { 'MsgType': 'V', 'MDReqID': '0', # not important. 'SubscriptionRequestType': '0', 'MarketDepth': 0, 'TradeDate': time.strftime("%Y%m%d", time.localtime()), 'MDUpdateType': '0', 'MDEntryTypes': ['0', '1', '2'], 'Instruments': [self.symbol] } return trade_client.sendJSON(md_subscription_msg) def ready(self): self.is_ready = True for trade in self.process_later: self.on_trade(trade) self.process_later = [] @staticmethod def get(symbol, application=None): """" get. """ global MDSUBSCRIBEDICT if symbol not in MDSUBSCRIBEDICT: MDSUBSCRIBEDICT[symbol] = MarketDataSubscriber(symbol, application) return MDSUBSCRIBEDICT[symbol] def get_last_trades(self): """" get_last_trades. """ return Trade.get_last_trades() def get_trades(self, symbol, since): """" get_trades. """ return Trade.get_trades(self.db_session, symbol, since) def on_md_publish(self, publish_msg): """" on_md_publish. """ topic = publish_msg[0] raw_message = publish_msg[1] self.application.log('IN', 'TRADE_PUB', raw_message) msg = JsonMessage(raw_message) if msg.type == 'W': # Full Refresh self.on_md_full_refresh(msg) elif msg.type == 'X': # Incremental self.on_md_incremental(msg) def on_md_full_refresh(self, msg): """" on_md_full_refresh. """ # TODO: Check if our current order book is sync with the full refresh if msg.get('MarketDepth') != 1: # Has Market Depth self.on_book_clear() self.on_trade_clear() group = msg.get('MDFullGrp') for entry in group: entry_type = entry.get('MDEntryType') if entry_type == '0' or entry_type == '1': self.on_book_new_order(entry) elif entry_type == '2': self.on_trade(entry) def on_md_incremental(self, msg): """" on_md_incremental. """ if msg.get('MDBkTyp') == '3': # Order Depth group = msg.get('MDIncGrp') for entry in group: entry_type = entry.get('MDEntryType') signal_order_depth_entry(self.symbol + '.3.' + entry_type, entry) if entry_type == '0' or entry_type == '1': update_action = entry.get('MDUpdateAction') if update_action == '0': self.on_book_new_order(entry) elif update_action == '1': self.on_book_update_order(entry) elif update_action == '2': self.on_book_delete_order(entry) elif update_action == '3': self.on_book_delete_orders_thru(entry) elif entry_type == '2': self.on_trade(entry) signal_publish_md_order_depth_incremental(self.symbol + '.3', {"MsgType": "X"}) def on_book_clear(self): """" on_book_clear. """ self.buy_side = [] self.sell_side = [] def on_trade_clear(self): """" on_trade_clear. """ self.volume_dict = {} def on_book_delete_orders_thru(self, msg): """" on_book_delete_orders_thru. """ index = msg.get('MDEntryPositionNo') side = msg.get('MDEntryType') if side == '0': self.buy_side = self.buy_side[index:] if self.buy_side: self.inst_status.set_best_bid(self.buy_side[0]['price']) else: self.inst_status.set_best_bid(None) elif side == '1': self.sell_side = self.sell_side[index:] if self.sell_side: self.inst_status.set_best_ask(self.sell_side[0]['price']) else: self.inst_status.set_best_ask(None) def on_book_delete_order(self, msg): """" on_book_delete_order. """ index = msg.get('MDEntryPositionNo') - 1 side = msg.get('MDEntryType') if side == '0': del self.buy_side[index] if index == 0: if self.buy_side: self.inst_status.set_best_bid(self.buy_side[0]['price']) else: self.inst_status.set_best_bid(None) elif side == '1': del self.sell_side[index] if index == 0: if self.sell_side: self.inst_status.set_best_ask(self.sell_side[0]['price']) else: self.inst_status.set_best_ask(None) def on_book_new_order(self, msg): """" on_book_new_order. """ index = msg.get('MDEntryPositionNo') - 1 order = { 'price': msg.get('MDEntryPx'), 'qty': msg.get('MDEntrySize'), 'username': msg.get('Username'), 'broker': msg.get('Broker'), 'order_id': msg.get('OrderID'), 'side': msg.get('MDEntryType'), 'order_time': msg.get('MDEntryTime'), 'order_date': msg.get('MDEntryDate') } if msg.get('MDEntryType') == '0': # buy self.buy_side.insert(index, order) if index == 0: self.inst_status.set_best_bid(msg.get('MDEntryPx')) elif msg.get('MDEntryType') == '1': # sell self.sell_side.insert(index, order) if index == 0: self.inst_status.set_best_ask(msg.get('MDEntryPx')) def on_book_update_order(self, msg): """" on_book_new_order. """ index = msg.get('MDEntryPositionNo') - 1 order = { 'price': msg.get('MDEntryPx'), 'qty': msg.get('MDEntrySize'), 'username': msg.get('Username'), 'broker': msg.get('Broker'), 'order_id': msg.get('OrderID'), 'side': msg.get('MDEntryType'), 'order_time': msg.get('MDEntryTime'), 'order_date': msg.get('MDEntryDate') } if msg.get('MDEntryType') == '0': # sell self.buy_side[index] = order if index == 0: self.inst_status.set_best_bid(msg.get('MDEntryPx')) elif msg.get('MDEntryType') == '1': # sell self.sell_side[index] = order if index == 0: self.inst_status.set_best_ask(msg.get('MDEntryPx')) def on_trade(self, msg): if not self.is_ready: self.process_later.append(msg) return trade = { "price": msg.get('MDEntryPx'), "symbol": msg.get('Symbol'), "size": msg.get('MDEntrySize'), "trade_date": msg.get('MDEntryDate'), "trade_time": msg.get('MDEntryTime'), "order_id": msg.get('OrderID'), "side": msg.get('Side'), "counter_order_id": msg.get('SecondaryOrderID'), "id": msg.get('TradeID'), "buyer_username": msg.get('MDEntryBuyer'), "seller_username": msg.get('MDEntrySeller'), } Trade.create(self.db_session, trade) # BTC BRL price_currency = self.symbol[3:] size_currency = self.symbol[:3] if price_currency not in self.volume_dict: self.volume_dict[price_currency] = 0 if size_currency not in self.volume_dict: self.volume_dict[size_currency] = 0 volume_price = int( msg.get('MDEntryPx') * msg.get('MDEntrySize') / 1.e8) volume_size = msg.get('MDEntrySize') self.volume_dict[price_currency] += volume_price self.volume_dict[size_currency] += volume_size self.volume_dict['MDEntryType'] = '4' signal_publish_md_status('MD_STATUS', self.volume_dict) self.inst_status.push_trade(trade)