async def _subscribe_trades_and_quotes(self): network = self.scheduler.get_network() for instrument in self.get_instruments(): symbol = instrument.get_exchange_instrument_code() self.instrument_trades[symbol] = MutableSignal() self.instrument_quotes[symbol] = MutableSignal() # magic: inject the bare Signal into the graph so we can # fire events on it without any downstream connections # yet made network.attach(self.instrument_trades[symbol]) network.attach(self.instrument_quotes[symbol]) subscribe_msg = { 'id': 1, 'method': 'trade.subscribe', 'params': [symbol] } messages = MutableSignal() json_messages = Map(network, messages, lambda x: json.loads(x)) incr_messages = Filter(network, json_messages, lambda x: x.get('type', None) == 'incremental') trade_lists = Map(network, incr_messages, lambda x: self.__extract_trades(x)) trades = FlatMap(self.scheduler, trade_lists) class TradeScheduler(Event): # noinspection PyShadowingNames def __init__(self, fh: PhemexFeedHandler, trades: Signal): self.fh = fh self.trades = trades def on_activate(self) -> bool: if self.trades.is_valid(): trade = self.trades.get_value() trade_symbol = trade.get_instrument().get_exchange_instrument_code() trade_signal = self.fh.instrument_trades[trade_symbol] self.fh.scheduler.schedule_update(trade_signal, trade) return True else: return False network.connect(trades, TradeScheduler(self, trades)) # noinspection PyShadowingNames async def do_subscribe(instrument, subscribe_msg, messages): async with websockets.connect(self.ws_uri) as sock: subscribe_msg_txt = json.dumps(subscribe_msg) self.logger.info(f'sending subscription request for {instrument.get_exchange_instrument_code()}') await sock.send(subscribe_msg_txt) while True: self.scheduler.schedule_update(messages, await sock.recv()) asyncio.ensure_future(do_subscribe(instrument, subscribe_msg, messages)) # we are now live self.scheduler.schedule_update(self.state, FeedHandlerState.LIVE)
async def _subscribe_trades_and_quotes(self): network = self.scheduler.get_network() symbols = [] for instrument in self.get_instruments(): symbol = instrument.get_exchange_instrument_code() symbols.append(f'{symbol}') self.instrument_trades[symbol] = MutableSignal() self.instrument_quotes[symbol] = MutableSignal() self.instrument_order_books[symbol] = MutableSignal() # magic: inject the bare Signal into the graph so we can # fire events on it without any downstream connections # yet made network.attach(self.instrument_trades[symbol]) network.attach(self.instrument_quotes[symbol]) network.attach(self.instrument_order_books[symbol]) subscribe_msg = { 'type': 'subscribe', 'product_ids': symbols, 'channels': ['matches', 'heartbeat'] } messages = MutableSignal() json_messages = Map(network, messages, lambda x: json.loads(x)) match_messages = Filter(network, json_messages, lambda x: x.get('type', None) == 'match') trades = Map(network, match_messages, lambda x: self.__extract_trade(x)) class TradeScheduler(Event): def __init__(self, fh: CoinbaseProFeedHandler): self.fh = fh def on_activate(self) -> bool: if trades.is_valid(): trade = trades.get_value() trade_symbol = trade.get_instrument( ).get_exchange_instrument_code() trade_signal = self.fh.instrument_trades[trade_symbol] self.fh.scheduler.schedule_update(trade_signal, trade) return True else: return False network.connect(trades, TradeScheduler(self)) async with websockets.connect(self.ws_uri) as sock: self.logger.info('Sending subscription request for all products') await sock.send(json.dumps(subscribe_msg)) self.scheduler.schedule_update(self.state, FeedHandlerState.LIVE) while True: self.scheduler.schedule_update(messages, await sock.recv())
def get_order_books(self, instrument: ExchangeInstrument) -> Signal: symbol = instrument.get_exchange_instrument_code() exchange_code_upper = instrument.get_exchange().get_exchange_code().upper() order_books = self.book_signal_by_symbol.get(symbol, None) if order_books is None: self._maybe_notify_subscription(instrument) order_books = MutableSignal() self.scheduler.network.attach(order_books) self.book_signal_by_symbol[symbol] = order_books class OrderBookGenerator(SignalGenerator): def __init__(self, mds): self.mds = mds def generate(self, scheduler: NetworkScheduler): tickstore = AzureBlobTickstore(self.mds.credential, f'{exchange_code_upper}_BOOKS', timestamp_column='time') books_df = tickstore.select(symbol, self.mds.start_time, self.mds.end_time) for row in books_df.itertuples(): at_time = row[0].asm8.astype('int64') / 10**6 best_bid = BookLevel(row[2], row[1]) best_ask = BookLevel(row[4], row[3]) book = OrderBook(bids=[best_bid], asks=[best_ask]) scheduler.schedule_update_at(order_books, book, at_time) tickstore.close() self.scheduler.add_generator(OrderBookGenerator(self)) # workaround: force scheduling of all historic trade events self.get_trades(instrument) return order_books
def __init__(self, scheduler: NetworkScheduler, registry: FeedHandlerRegistry, instance_id: str = 'prod'): self.scheduler = scheduler self.registry = registry self.instance_id = instance_id self.subscribed_instruments = MutableSignal() self.notified_instruments = set() scheduler.get_network().attach(self.subscribed_instruments)
def get_position(self, account: str, instrument: ExchangeInstrument) -> MutableSignal: position = self.positions.get((account, instrument), None) if position is None: position = MutableSignal(Position(account, instrument)) self.positions[(account, instrument)] = position self.scheduler.get_network().attach(position) return position
def __init__(self, scheduler: NetworkScheduler, mds: MarketdataService): super().__init__(OrderFactory()) self.scheduler = scheduler self.mds = mds self.order_events = MutableSignal() self.scheduler.get_network().attach(self.order_events) self.orders = {}
def start(self): network = self.scheduler.get_network() messages = MutableSignal() json_messages = Map(network, messages, lambda x: json.loads(x)) json_messages = Filter( network, json_messages, lambda x: x.get('type', None) in ['incremental', 'snapshot']) class OrderEventScheduler(Event): # noinspection PyShadowingNames def __init__(self, sub: AccountOrderPositionSubscriber, json_messages: Signal): self.sub = sub self.json_messages = json_messages def on_activate(self) -> bool: if self.json_messages.is_valid(): msg = self.json_messages.get_value() accounts = msg['accounts'] for account in accounts: orders = account['orders'] for order in orders: order_event = OrderEvent() self.sub.scheduler.schedule_update( self.sub.order_events, order_event) return True else: return False network.connect(json_messages, OrderEventScheduler(self, json_messages)) # noinspection PyShadowingNames async def do_subscribe(): async with websockets.connect(self.ws_uri) as sock: self.logger.info( f'sending Account-Order-Position subscription request') auth_msg = self.auth.get_user_auth_message() await sock.send(auth_msg) error_msg = await sock.recv() error_struct = json.loads(error_msg) if error_struct['error'] is not None: raise ConnectionError( f'Unable to authenticate: {error_msg}') aop_sub_msg = { 'id': 2, 'method': 'aop.subscribe', 'params': [] } await sock.send(json.dumps(aop_sub_msg)) while True: self.scheduler.schedule_update(messages, await sock.recv()) asyncio.ensure_future(do_subscribe())
def get_marks(self, instrument: ExchangeInstrument) -> Signal: economics = instrument.get_instrument().get_economics() if isinstance(economics, FutureContract): economics = economics.get_underlier().get_economics() if isinstance(economics, CurrencyPair): ccy_code = economics.get_base_currency().get_currency_code() symbol = f'.M{ccy_code}' cash_instrument = self.instrument_cache.get_or_create_cash_instrument( ccy_code) else: raise ValueError( 'Unable to get marks: expected CurrencyPair or FutureContract on CurrencyPair' ) network = self.scheduler.get_network() marks = self.instrument_marks.get(symbol) if marks is None: marks = MutableSignal() network.attach(marks) self.instrument_marks[symbol] = marks subscribe_msg = { 'id': 1, 'method': 'tick.subscribe', 'params': [symbol] } messages = MutableSignal() json_messages = Map(network, messages, lambda x: json.loads(x)) tick_messages = Filter(network, json_messages, lambda x: 'tick' in x) ticks = Map( network, tick_messages, lambda x: self.__extract_tick( x, cash_instrument.get_instrument())) Pipe(self.scheduler, ticks, marks) asyncio.ensure_future( websocket_subscribe_with_retry(self.ws_uri, self.timeout, self.logger, subscribe_msg, self.scheduler, messages, symbol, 'ticks')) return marks
def __init__(self, scheduler: HistoricNetworkScheduler, azure_connect_str: str): self.scheduler = scheduler self.azure_connect_str = azure_connect_str self.subscribed_instruments = MutableSignal() self.scheduler.get_network().attach(self.subscribed_instruments) self.start_time = scheduler.get_clock().get_start_time() self.end_time = scheduler.get_clock().get_end_time() self.all_subscribed = set() self.book_signal_by_symbol = {} self.trade_signal_by_symbol = {}
def __init__(self, scheduler: NetworkScheduler, instrument_cache: InstrumentCache, instance_id: str): self.scheduler = scheduler self.instrument_cache = instrument_cache self.type_code_cache = instrument_cache.get_type_code_cache() self.instance_id = instance_id self.instruments = [] self.known_instrument_ids = {} self.price_scaling = {} self._load_instruments() self.state = MutableSignal(FeedHandlerState.INITIALIZING) self.scheduler.get_network().attach(self.state)
def test_buffer_with_time_historic(): scheduler = HistoricNetworkScheduler(0, 30 * 1000) network = scheduler.get_network() values = MutableSignal() scheduler.schedule_update_at(values, 1.0, 1000) scheduler.schedule_update_at(values, -3.2, 2000) scheduler.schedule_update_at(values, 2.1, 10000) scheduler.schedule_update_at(values, -2.9, 15000) scheduler.schedule_update_at(values, 8.3, 25000) scheduler.schedule_update_at(values, -5.7, 30000) buffer = BufferWithTime(scheduler, values, timedelta(seconds=5)) Do(network, buffer, lambda: print(f'{buffer.get_value()}')) scheduler.run()
def __init__(self, scheduler: HistoricNetworkScheduler): self.scheduler = scheduler self.subscribed_instruments = MutableSignal() self.scheduler.get_network().attach(self.subscribed_instruments) self.start_time = scheduler.get_clock().get_start_time() self.end_time = scheduler.get_clock().get_end_time() self.all_subscribed = set() self.book_signal_by_symbol = {} self.trade_signal_by_symbol = {} self.credential = DeviceCodeCredential(client_id=get_global_defaults()['azure']['client_id'], tenant_id=get_global_defaults()['azure']['tenant_id'])
def __init__(self, scheduler: NetworkScheduler, booker: TradeBookingService = NullTradeBookingService()): self.scheduler = scheduler self.order_state_by_cl_ord_id = {} self.order_by_cl_ord_id = {} self.order_events = MutableSignal() self.orders = MutableSignal() self.scheduler.get_network().attach(self.orders) self.scheduler.get_network().attach(self.order_events) class OnBookingEvent(Event): def __init__(self, oms: OrderManagerService): self.oms = oms def on_activate(self) -> bool: if self.oms.order_events.is_valid(): order_event = self.oms.order_events.get_value() if isinstance(order_event, ExecutionReport): cl_ord_id = order_event.get_cl_ord_id() order = self.oms.get_order_by_cl_ord_id(cl_ord_id) booker.book(order, order_event) return False self.scheduler.get_network().connect(self.order_events, OnBookingEvent(self))
def __init__(self, credentials: AuthCredentials, scheduler: NetworkScheduler, oms: OrderManagerService, instance_id: str = 'prod'): self.auth = PhemexWebsocketAuthenticator(credentials) self.scheduler = scheduler self.oms = oms # timeout in seconds self.timeout = 60 self.order_events = MutableSignal() self.scheduler.network.attach(self.order_events) (self.phemex, self.ws_uri) = get_phemex_connection(credentials, instance_id)
def get_trades(self, instrument: ExchangeInstrument) -> Signal: trade_symbol = instrument.get_exchange_instrument_code() exchange_code_upper = instrument.get_exchange().get_exchange_code( ).upper() self._maybe_notify_subscription(instrument) trades = self.trade_signal_by_symbol.get(trade_symbol, None) if trades is None: trades = MutableSignal() self.scheduler.network.attach(trades) self.trade_signal_by_symbol[trade_symbol] = trades class TradeGenerator(SignalGenerator): def __init__(self, mds): self.mds = mds def generate(self, scheduler: NetworkScheduler): tickstore = AzureBlobTickstore( self.mds.azure_connect_str, f'{exchange_code_upper}_TRADES', timestamp_column='time') trades_df = tickstore.select(trade_symbol, self.mds.start_time, self.mds.end_time) for row in trades_df.itertuples(): at_time = row[0].asm8.astype('int64') / 10**6 sequence = row[1] trade_id = row[2] side = Side.SELL if row[4] == 'sell' else Side.BUY qty = row[5] price = row[6] trade = Trade(instrument, sequence, trade_id, side, qty, price) scheduler.schedule_update_at(trades, trade, at_time) tickstore.close() self.scheduler.add_generator(TradeGenerator(self)) # workaround: force scheduling of all historic order book events self.get_order_books(instrument) return trades
def __init__(self, auth: WebsocketAuthenticator, scheduler: NetworkScheduler, instance_id: str = 'prod'): self.auth = auth self.scheduler = scheduler self.order_events = MutableSignal() self.scheduler.network.attach(self.order_events) if instance_id == 'prod': self.ws_uri = 'wss://phemex.com/ws' self.phemex = PhemexConnection() elif instance_id == 'test': self.ws_uri = 'wss://testnet.phemex.com/ws' self.phemex = PhemexConnection( api_url='https://testnet-api.phemex.com') else: raise ValueError(f'Unknown instance_id: {instance_id}')
def __init__(self, credentials: AuthCredentials, scheduler: NetworkScheduler, instrument_cache: InstrumentCache, account: str, instance_id: str = 'prod'): super().__init__(scheduler) self.auth = PhemexWebsocketAuthenticator(credentials) self.scheduler = scheduler self.instrument_cache = instrument_cache self.account = account # timeout in seconds self.timeout = 60 self.order_events = MutableSignal() self.scheduler.network.attach(self.order_events) (self.phemex, self.ws_uri) = get_phemex_connection(credentials, instance_id)
def __init__(self, scheduler: NetworkScheduler): self.scheduler = scheduler self.exchange_positions = MutableSignal() self.scheduler.get_network().attach(self.exchange_positions)
async def _subscribe_trades_and_quotes(self): network = self.scheduler.get_network() symbols = [] for instrument in self.get_instruments(): symbol = instrument.get_exchange_instrument_code() symbols.append(f'{symbol.lower()}@aggTrade') self.instrument_trades[symbol] = MutableSignal() self.instrument_quotes[symbol] = MutableSignal() # magic: inject the bare Signal into the graph so we can # fire events on it without any downstream connections # yet made network.attach(self.instrument_trades[symbol]) network.attach(self.instrument_quotes[symbol]) messages = MutableSignal() json_messages = Map(network, messages, lambda x: json.loads(x)) trade_messages = Filter(network, json_messages, lambda x: 'data' in x) trades = Map(network, trade_messages, lambda x: self.__extract_trade(x)) class TradeScheduler(Event): def __init__(self, fh: BinanceFeedHandler): self.fh = fh def on_activate(self) -> bool: if trades.is_valid(): trade = trades.get_value() trade_symbol = trade.get_instrument( ).get_exchange_instrument_code() trade_signal = self.fh.instrument_trades[trade_symbol] self.fh.scheduler.schedule_update(trade_signal, trade) return True else: return False network.connect(trades, TradeScheduler(self)) async with websockets.connect(self.ws_uri) as sock: ndx = 1 n = 250 symbols_chunked = [ symbols[i:i + n] for i in range(0, len(symbols), n) ] for symbols in symbols_chunked: self.logger.info( f'Sending subscription request for {len(symbols)} symbols: {symbols}' ) subscribe_msg = { "method": "SUBSCRIBE", "params": symbols, "id": ndx } await sock.send(json.dumps(subscribe_msg)) ndx = ndx + 1 self.scheduler.schedule_update(self.state, FeedHandlerState.LIVE) while True: self.scheduler.schedule_update(messages, await sock.recv())
async def _subscribe_trades_and_quotes(self): network = self.scheduler.get_network() for instrument in self.get_instruments(): symbol = instrument.get_exchange_instrument_code() if symbol == self.include_symbol or self.include_symbol == '*': self.instrument_trades[symbol] = MutableSignal() self.instrument_order_book_events[symbol] = MutableSignal() self.instrument_order_books[symbol] = OrderBookBuilder( network, self.instrument_order_book_events[symbol]) # magic: inject the bare Signal into the graph so we can # fire events on it without any downstream connections network.attach(self.instrument_trades[symbol]) network.attach(self.instrument_order_book_events[symbol]) network.attach(self.instrument_order_books[symbol]) trade_subscribe_msg = { 'id': 1, 'method': 'trade.subscribe', 'params': [symbol] } trade_messages = MutableSignal() trade_json_messages = Map(network, trade_messages, lambda x: json.loads(x)) trade_incr_messages = Filter( network, trade_json_messages, lambda x: x.get('type', None) == 'incremental') trade_lists = Map(network, trade_incr_messages, lambda x: self.__extract_trades(x)) trades = FlatMap(self.scheduler, trade_lists) class TradeScheduler(Event): # noinspection PyShadowingNames def __init__(self, fh: PhemexFeedHandler, trades: Signal): self.fh = fh self.trades = trades def on_activate(self) -> bool: if self.trades.is_valid(): trade = self.trades.get_value() trade_symbol = trade.get_instrument( ).get_exchange_instrument_code() trade_signal = self.fh.instrument_trades[ trade_symbol] self.fh.scheduler.schedule_update( trade_signal, trade) return True else: return False network.connect(trades, TradeScheduler(self, trades)) orderbook_subscribe_msg = { 'id': 2, 'method': 'orderbook.subscribe', 'params': [symbol] } obe_messages = MutableSignal() obe_json_messages = Map(network, obe_messages, lambda x: json.loads(x)) obe_json_messages = Filter( network, obe_json_messages, lambda x: x.get('type', None) in ['incremental', 'snapshot']) order_book_events = Map( network, obe_json_messages, lambda x: self.__extract_order_book_event(x)) class OrderBookEventScheduler(Event): # noinspection PyShadowingNames def __init__(self, fh: PhemexFeedHandler, order_book_events: Signal): self.fh = fh self.order_book_events = order_book_events def on_activate(self) -> bool: if self.order_book_events.is_valid(): obe = self.order_book_events.get_value() obe_symbol = obe.get_instrument( ).get_exchange_instrument_code() obe_signal = self.fh.instrument_order_book_events[ obe_symbol] self.fh.scheduler.schedule_update(obe_signal, obe) return True else: return False network.connect( order_book_events, OrderBookEventScheduler(self, order_book_events)) asyncio.ensure_future( websocket_subscribe_with_retry(self.ws_uri, self.timeout, self.logger, trade_subscribe_msg, self.scheduler, trade_messages, symbol, 'trade')) asyncio.ensure_future( websocket_subscribe_with_retry(self.ws_uri, self.timeout, self.logger, orderbook_subscribe_msg, self.scheduler, obe_messages, symbol, 'order book')) # we are now live self.scheduler.schedule_update(self.state, FeedHandlerState.LIVE)
def subscribe(self): network = self.scheduler.get_network() messages = MutableSignal() json_messages = Map(network, messages, lambda x: json.loads(x)) class PositionUpdateScheduler(Event): # noinspection PyShadowingNames def __init__(self, sub: PhemexExchangePositionService, json_messages: Signal): self.sub = sub self.json_messages = json_messages def on_activate(self) -> bool: if self.json_messages.is_valid(): msg = self.json_messages.get_value() if 'positions' in msg: for position in msg['positions']: if position['accountID'] == self.sub.account: qty = (position['crossSharedBalanceEv'] / 100_000_000) ccy_symbol = position['currency'] ccy = self.sub.instrument_cache.get_or_create_currency( ccy_symbol) xp = ExchangePosition(self.sub.account, ccy, qty) self.sub.scheduler.schedule_update( self.sub.exchange_positions, xp) return True else: return False network.connect(json_messages, PositionUpdateScheduler(self, json_messages)) # noinspection PyShadowingNames,PyBroadException async def do_subscribe(): while True: try: async with websockets.connect(self.ws_uri) as sock: self.logger.info( 'sending Account-Order-Position subscription request for positions' ) auth_msg = self.auth.get_user_auth_message(2) await sock.send(auth_msg) error_msg = await sock.recv() error_struct = json.loads(error_msg) if error_struct['error'] is not None: raise ConnectionError( f'Unable to authenticate: {error_msg}') aop_sub_msg = { 'id': 3, 'method': 'aop.subscribe', 'params': [] } await sock.send(json.dumps(aop_sub_msg)) while True: try: self.scheduler.schedule_update( messages, await sock.recv()) except BaseException as error: self.logger.error( f'disconnected; attempting to reconnect after {self.timeout} ' f'seconds: {error}') await asyncio.sleep(self.timeout) # exit inner loop break except socket.gaierror as error: self.logger.error( f'failed with socket error; attempting to reconnect after {self.timeout} ' f'seconds: {error}') await asyncio.sleep(self.timeout) continue except ConnectionRefusedError as error: self.logger.error( f'connection refused; attempting to reconnect after {self.timeout} ' f'seconds: {error}') await asyncio.sleep(self.timeout) continue except BaseException as error: self.logger.error( f'unknown connection error; attempting to reconnect after {self.timeout} ' f'seconds: {error}') await asyncio.sleep(self.timeout) continue asyncio.ensure_future(do_subscribe())
async def _subscribe_trades_and_quotes(self): network = self.scheduler.get_network() symbols = [] for instrument in self.get_instruments(): symbol = instrument.get_exchange_instrument_code() if symbol == self.include_symbol or self.include_symbol == '*': symbols.append(f'{symbol}') self.instrument_trades[symbol] = MutableSignal() self.instrument_order_book_events[symbol] = MutableSignal() self.instrument_order_books[symbol] = OrderBookBuilder( network, self.instrument_order_book_events[symbol]) # magic: inject the bare Signal into the graph so we can # fire events on it without any downstream connections # yet made network.attach(self.instrument_trades[symbol]) network.attach(self.instrument_order_book_events[symbol]) network.attach(self.instrument_order_books[symbol]) subscribe_msg = { 'type': 'subscribe', 'product_ids': symbols, 'channels': ['matches', 'level2', 'heartbeat'] } messages = MutableSignal() json_messages = Map(network, messages, lambda x: json.loads(x)) match_messages = Filter(network, json_messages, lambda x: x.get('type', None) == 'match') book_messages = Filter( network, json_messages, lambda x: x.get('type', None) in {'snapshot', 'l2update'}) trades = Map(network, match_messages, lambda x: self.__extract_trade(x)) books = Map(network, book_messages, lambda x: self.__extract_order_book_event(x)) class TradeScheduler(Event): def __init__(self, fh: CoinbaseProFeedHandler): self.fh = fh def on_activate(self) -> bool: if trades.is_valid(): trade = trades.get_value() trade_symbol = trade.get_instrument( ).get_exchange_instrument_code() trade_signal = self.fh.instrument_trades[trade_symbol] self.fh.scheduler.schedule_update(trade_signal, trade) return True else: return False network.connect(trades, TradeScheduler(self)) class OrderBookScheduler(Event): def __init__(self, fh: CoinbaseProFeedHandler): self.fh = fh def on_activate(self) -> bool: if books.is_valid(): obe = books.get_value() obe_symbol = obe.get_instrument( ).get_exchange_instrument_code() obe_signal = self.fh.instrument_order_book_events[ obe_symbol] self.fh.scheduler.schedule_update(obe_signal, obe) return True else: return False network.connect(books, OrderBookScheduler(self)) asyncio.ensure_future( websocket_subscribe_with_retry(self.ws_uri, self.timeout, self.logger, subscribe_msg, self.scheduler, messages, 'all products', 'global')) # we are now live self.scheduler.schedule_update(self.state, FeedHandlerState.LIVE)
def start(self): network = self.scheduler.get_network() messages = MutableSignal() json_messages = Map(network, messages, lambda x: json.loads(x)) json_messages = Filter(network, json_messages, lambda x: x.get('type', None) == 'incremental') class OrderEventScheduler(Event): # noinspection PyShadowingNames def __init__(self, sub: OrderEventSubscriber, json_messages: Signal): self.sub = sub self.json_messages = json_messages def on_activate(self) -> bool: if self.json_messages.is_valid(): msg = self.json_messages.get_value() orders = msg['orders'] for order_msg in orders: order_id = order_msg['orderID'] cl_ord_id = order_msg['clOrdID'] exec_id = order_msg['execID'] last_px = order_msg['execPriceEp'] / 10000 last_qty = order_msg['execQty'] order = self.sub.oms.get_order_by_cl_ord_id(cl_ord_id) if order is None: if cl_ord_id is None or cl_ord_id == '': self.sub.logger.warning( f'Received message from exchange with missing clOrdID, ' f'orderID={order_id}') else: self.sub.logger.warning( f'Received message from exchange for unknown ' f'clOrdID={cl_ord_id}, orderID={order_id}') return False elif order.get_order_id() is None: self.sub.logger.info( f'OMS order missing orderID; patching from clOrdID={cl_ord_id}' ) order.set_order_id(order_id) if order_msg['ordStatus'] == 'New': self.sub.oms.new(order, exec_id) elif order_msg['ordStatus'] == 'Canceled': self.sub.oms.apply_cancel(order, exec_id) elif order_msg[ 'ordStatus'] == 'PartiallyFilled' or order_msg[ 'ordStatus'] == 'Filled': self.sub.oms.apply_fill(order, last_qty, last_px, exec_id) return True else: return False network.connect(json_messages, OrderEventScheduler(self, json_messages)) # noinspection PyShadowingNames,PyBroadException async def do_subscribe(): while True: try: async with websockets.connect(self.ws_uri) as sock: self.logger.info( 'sending Account-Order-Position subscription request for orders' ) auth_msg = self.auth.get_user_auth_message(1) await sock.send(auth_msg) error_msg = await sock.recv() error_struct = json.loads(error_msg) if error_struct['error'] is not None: raise ConnectionError( f'Unable to authenticate: {error_msg}') aop_sub_msg = { 'id': 2, 'method': 'aop.subscribe', 'params': [] } await sock.send(json.dumps(aop_sub_msg)) while True: try: self.scheduler.schedule_update( messages, await sock.recv()) except BaseException as error: self.logger.error( f'disconnected; attempting to reconnect after {self.timeout} ' f'seconds: {error}') await asyncio.sleep(self.timeout) # exit inner loop break except socket.gaierror as error: self.logger.error( f'failed with socket error; attempting to reconnect after {self.timeout} ' f'seconds: {error}') await asyncio.sleep(self.timeout) continue except ConnectionRefusedError as error: self.logger.error( f'connection refused; attempting to reconnect after {self.timeout} ' f'seconds: {error}') await asyncio.sleep(self.timeout) continue except BaseException as error: self.logger.error( f'unknown connection error; attempting to reconnect after {self.timeout} ' f'seconds: {error}') await asyncio.sleep(self.timeout) continue asyncio.ensure_future(do_subscribe())