def process_cross(self, id, fulfilling_order_id, price, volume, timestamp, liquidity_flag = b'?'): log.debug('Orders (%s, %s) crossed at price %s, volume %s', id, fulfilling_order_id, price, volume) order_message = self.order_store.orders[id].first_message fulfilling_order_message = self.order_store.orders[fulfilling_order_id].first_message log.debug('%s,%s',order_message,fulfilling_order_message) match_number = self.next_match_number self.next_match_number += 1 r1 = OuchServerMessages.Executed( timestamp = timestamp, order_token = id, executed_shares = volume, execution_price = price, liquidity_flag = liquidity_flag, match_number = match_number ) r1.meta = order_message.meta self.order_store.add_to_order(r1['order_token'], r1) r2 = OuchServerMessages.Executed( timestamp = timestamp, order_token = fulfilling_order_id, executed_shares = volume, execution_price = price, liquidity_flag = liquidity_flag, match_number = match_number ) r2.meta = fulfilling_order_message.meta self.order_store.add_to_order(r2['order_token'], r2) return [r1, r2]
def order_cancelled_from_cancel(self, cancel_order_message, timestamp, amount_canceled, reason=b'U'): m = OuchServerMessages.Canceled(timestamp = timestamp, order_token = cancel_order_message['order_token'], decrement_shares = amount_canceled, reason = reason) m.meta = cancel_order_message.meta return m
def system_start_atomic(self, system_event_message, timestamp): log.debug('received reset signal at %s.' % timestamp) self.order_store.clear_order_store() self.order_book.reset_book() m = OuchServerMessages.SystemEvent(event_code=b'S', timestamp=timestamp) m.meta = system_event_message.meta self.outgoing_messages.append(m)
def accepted_from_enter(self, enter_order_message, timestamp, order_reference_number, order_state=b'L', bbo_weight_indicator=b' '): m = OuchServerMessages.Accepted( timestamp=timestamp, order_reference_number=order_reference_number, order_state=order_state, bbo_weight_indicator=bbo_weight_indicator, order_token=enter_order_message['order_token'], buy_sell_indicator=enter_order_message['buy_sell_indicator'], shares=enter_order_message['shares'], stock=enter_order_message['stock'], price=enter_order_message['price'], time_in_force=enter_order_message['time_in_force'], firm=enter_order_message['firm'], display=enter_order_message['display'], capacity=enter_order_message['capacity'], intermarket_sweep_eligibility=enter_order_message[ 'intermarket_sweep_eligibility'], minimum_quantity=enter_order_message['minimum_quantity'], cross_type=enter_order_message['cross_type']) m.meta = enter_order_message.meta return m
def best_quote_update(self, order_message, new_bbo, timestamp): m = OuchServerMessages.BestBidAndOffer(timestamp=timestamp, stock=b'AMAZGOOG', best_bid=new_bbo.best_bid, volume_at_best_bid=new_bbo.volume_at_best_bid, best_ask=new_bbo.best_ask, volume_at_best_ask=new_bbo.volume_at_best_ask ) m.meta = order_message.meta return m
async def run_batch_repeating(self): while True: log.debug('Starting batch at %s', self.loop.time()) timestamp = nanoseconds_since_midnight() await self.message_broadcast( OuchServerMessages.SystemEvent(event_code=b'B', timestamp=timestamp)) self.run_batch_atomic() await self.message_broadcast( OuchServerMessages.SystemEvent( event_code=b'P', timestamp=nanoseconds_since_midnight())) await self.send_outgoing_messages() self.order_book_logger.log_book(self.order_book, timestamp, self.order_store) log.debug('Ended batch at %s', self.loop.time()) await asyncio.sleep(self.interval - (self.loop.time() % self.interval))
def system_start_atomic(self, system_event_message, timestamp): log.info("System start message sent : " + str(system_event_message['timestamp'])) log.info("System start message received : " + str(timestamp)) self.order_store.clear_order_store() self.order_book.reset_book() m = OuchServerMessages.SystemEvent(event_code=b'S', timestamp=timestamp) m.meta = system_event_message.meta # await self.message_broadcast( # OuchServerMessages.SystemEvent( # event_code=b'S', # timestamp=timestamp)) self.outgoing_messages.append(m)
async def recv(): try: header = (await reader.readexactly(1)) except asyncio.IncompleteReadError: log.error('connection terminated without response') return None message_type = OuchServerMessages.lookup_by_header_bytes(header) try: payload = (await reader.readexactly(message_type.payload_size)) except asyncio.IncompleteReadError as err: log.error('Connection terminated mid-packet!') return None response_msg = message_type.from_bytes(payload, header=False) return response_msg
async def recv(self): try: header = (await self.reader.readexactly(1)) except asyncio.IncompleteReadError: log.error('connection terminated without response') return None log.debug('Received Ouch header as binary: %r', header) log.debug('bytes: %r', list(header)) message_type = OuchServerMessages.lookup_by_header_bytes(header) try: payload = (await self.reader.readexactly(message_type.payload_size)) except asyncio.IncompleteReadError as err: log.error('Connection terminated mid-packet!') return None log.debug('Received Ouch payload as binary: %r', payload) log.debug('bytes: %r', list(payload)) response_msg = message_type.from_bytes(payload, header=False) return response_msg
def replace_order_atomic(self, replace_order_message, timestamp): if replace_order_message['existing_order_token'] not in self.order_store.orders: log.debug('Existing token %s unknown, siliently ignoring', replace_order_message['existing_order_token']) return [] elif replace_order_message['replacement_order_token'] in self.order_store.orders: log.debug('Replacement token %s unknown, siliently ignoring', replace_order_message['existing_order_token']) return [] else: store_entry = self.order_store.orders[replace_order_message['existing_order_token']] log.debug('store_entry: %s', store_entry) cancelled_orders, new_bbo_post_cancel = self.order_book.cancel_order( id = replace_order_message['existing_order_token'], price = store_entry.first_message['price'], volume = 0, buy_sell_indicator = store_entry.original_enter_message['buy_sell_indicator']) # Fully cancel if len(cancelled_orders)==0: log.debug('No orders cancelled, siliently ignoring') return [] else: (id_cancelled, amount_cancelled) = cancelled_orders[0] original_enter_message = store_entry.original_enter_message first_message = store_entry.first_message shares_diff = replace_order_message['shares'] - first_message['shares'] liable_shares = max(0, amount_cancelled + shares_diff ) if liable_shares == 0: log.debug('No remaining liable shares on the book to replace') #send cancel else: self.order_store.store_order( id = replace_order_message['replacement_order_token'], message = replace_order_message, original_enter_message = original_enter_message) time_in_force = replace_order_message['time_in_force'] enter_into_book = True if time_in_force > 0 else False if time_in_force > 0 and time_in_force < 99998: #schedule a cancellation at some point in the future cancel_order_message = cancel_order_from_replace_order( replace_order_message ) self.loop.call_later(time_in_force, partial(self.cancel_order_atomic, cancel_order_message, timestamp)) enter_order_func = self.order_book.enter_buy if original_enter_message['buy_sell_indicator'] == b'B' else self.order_book.enter_sell crossed_orders, entered_order, new_bbo_post_enter = enter_order_func( replace_order_message['replacement_order_token'], replace_order_message['price'], liable_shares, enter_into_book) log.debug("Resulting book: %s", self.order_book) r = OuchServerMessages.Replaced( timestamp=timestamp, replacement_order_token = replace_order_message['replacement_order_token'], buy_sell_indicator=original_enter_message['buy_sell_indicator'], shares=liable_shares, stock=original_enter_message['stock'], price=replace_order_message['price'], time_in_force=replace_order_message['time_in_force'], firm=original_enter_message['firm'], display=replace_order_message['display'], order_reference_number=next(self.order_ref_numbers), capacity=b'*', intermarket_sweep_eligibility = replace_order_message['intermarket_sweep_eligibility'], minimum_quantity = replace_order_message['minimum_quantity'], cross_type=b'*', order_state=b'L' if entered_order is not None else b'D', previous_order_token=replace_order_message['existing_order_token'], bbo_weight_indicator=b'*' ) r.meta = replace_order_message.meta self.outgoing_messages.append(r) self.order_store.add_to_order(r['replacement_order_token'], r) cross_messages = [m for ((id, fulfilling_order_id), price, volume) in crossed_orders for m in self.process_cross(id, fulfilling_order_id, price, volume, timestamp=timestamp)] self.outgoing_messages.extend(cross_messages) bbo_message = None if new_bbo_post_enter: bbo_message = self.best_quote_update(replace_order_message, new_bbo_post_enter, timestamp) elif new_bbo_post_cancel: bbo_message = self.best_quote_update(replace_order_message, new_bbo_post_cancel, timestamp) if bbo_message: self.outgoing_broadcast_messages.append(bbo_message)
def decodeServerOUCH(data): header = chr(data[0]).encode('ascii') msg_type = OuchServerMessages.lookup_by_header_bytes(header) msg = msg_type.from_bytes(data[1:], header=False) return header, msg