def main(): logging.basicConfig(level=logging.INFO) feed = 'iex' # <- replace to SIP if you have PRO subscription stream = Stream(data_feed=feed, raw_data=True) stream.subscribe_trade_updates(print_trade_update) stream.subscribe_trades(print_trade, 'AAPL') stream.subscribe_quotes(print_quote, 'IBM') stream.subscribe_crypto_trades(print_crypto_trade, 'BTCUSD') @stream.on_bar('MSFT') async def _(bar): print('bar', bar) @stream.on_updated_bar('MSFT') async def _(bar): print('updated bar', bar) @stream.on_status("*") async def _(status): print('status', status) @stream.on_luld('AAPL', 'MSFT') async def _(luld): print('LULD', luld) stream.run()
class Streamer: conn = None def __init__(self, q, api_key='', api_secret='', instrument='', method: StreamingMethod = StreamingMethod.AccountUpdate, base_url='', data_url='', data_feed='iex', *args, **kwargs): try: # make sure we have an event loop, if not create a new one asyncio.get_event_loop() except RuntimeError: asyncio.set_event_loop(asyncio.new_event_loop()) self.conn = Stream(api_key, api_secret, base_url, data_stream_url=data_url, data_feed=data_feed) self.instrument = instrument self.method = method self.q = q def run(self): if self.method == StreamingMethod.AccountUpdate: self.conn.subscribe_trade_updates(self.on_trade) elif self.method == StreamingMethod.MinuteAgg: self.conn.subscribe_bars(self.on_agg_min, self.instrument) elif self.method == StreamingMethod.Quote: self.conn.subscribe_quotes(self.on_quotes, self.instrument) # this code runs in a new thread. we need to set the loop for it loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) self.conn.run() async def on_listen(self, conn, stream, msg): pass async def on_quotes(self, msg): msg._raw['time'] = msg.timestamp self.q.put(msg._raw) async def on_agg_min(self, msg): msg._raw['time'] = msg.timestamp self.q.put(msg._raw) async def on_account(self, msg): self.q.put(msg) async def on_trade(self, msg): self.q.put(msg)
def consumer_thread(): global conn conn = Stream(ALPACA_API_KEY, ALPACA_SECRET_KEY, base_url=URL('https://paper-api.alpaca.markets'), data_feed='iex') conn.subscribe_quotes(print_quote, 'AAPL') conn.run()
class AlpacaStream(StreamingAPI): def __init__(self, queues: QueueMapper): self.alpaca_ws_client = Stream( key_id=config.alpaca_api_key, secret_key=config.alpaca_api_secret ) if not self.alpaca_ws_client: raise AssertionError( "Failed to authenticate Alpaca web_socket client" ) self.alpaca_ws_client.subscribe_trade_updates( AlpacaStream.trade_update_handler ) self.alpaca_ws_client.run() super().__init__(queues) @classmethod async def trade_update_handler(cls, msg): print(f"trade_update_handler:{msg}") @classmethod async def bar_handler(cls, msg): print(f"bar_handler:{msg}") @classmethod async def trades_handler(cls, msg): print(f"trades_handler:{msg}") @classmethod async def quotes_handler(cls, msg): print(f"quotes_handler:{msg}") async def subscribe( self, symbols: List[str], events: List[WSEventType] ) -> bool: for event in events: if event == WSEventType.SEC_AGG: raise NotImplementedError( f"event {event} not implemente in Alpaca" ) elif event == WSEventType.MIN_AGG: self.alpaca_ws_client.subscribe_bars( AlpacaStream.bar_handler, symbols ) elif event == WSEventType.TRADE: self.alpaca_ws_client.subscribe_trades( AlpacaStream.trades_handler, symbols ) elif event == WSEventType.QUOTE: self.alpaca_ws_client.subscribe_quotes( AlpacaStream.quotes_handler, symbols ) return True
def main(): logging.basicConfig(level=logging.INFO) feed = 'iex' # <- replace to SIP if you have PRO subscription stream = Stream(data_feed=feed, raw_data=True) stream.subscribe_trade_updates(print_trade_update) stream.subscribe_trades(print_trade, 'AAPL') stream.subscribe_quotes(print_quote, 'IBM') @stream.on_bar('MSFT') async def _(bar): print('bar', bar) stream.run()
def consumer_thread(): try: # make sure we have an event loop, if not create a new one loop = asyncio.get_event_loop() loop.set_debug(True) except RuntimeError: asyncio.set_event_loop(asyncio.new_event_loop()) global conn conn = Stream(ALPACA_API_KEY, ALPACA_SECRET_KEY, base_url=URL('https://paper-api.alpaca.markets'), data_feed='iex') conn.subscribe_quotes(print_quote, 'AAPL') conn.run()
def run_connection(conn): try: conn.run() except KeyboardInterrupt: print("Interrupted execution by user") loop.run_until_complete(conn.stop_ws()) exit(0) except Exception as e: print(f'Exception from websocket connection: {e}') finally: print("Trying to re-establish connection") time.sleep(3) run_connection(conn) async def print_quote(q): print('quote', q) if __name__ == '__main__': conn = Stream(ALPACA_API_KEY, ALPACA_SECRET_KEY, base_url=URL('https://paper-api.alpaca.markets'), data_feed='iex') conn.subscribe_quotes(print_quote, 'AAPL') run_connection(conn)
class AlpacaStream(StreamingAPI): def __init__(self, queues: QueueMapper): self.alpaca_ws_client = Stream( base_url=URL(config.alpaca_base_url), key_id=config.alpaca_api_key, secret_key=config.alpaca_api_secret, data_feed="sip", # config.alpaca_data_feed, ) if not self.alpaca_ws_client: raise AssertionError( "Failed to authenticate Alpaca web_socket client") self.running = False super().__init__(queues) async def run(self): if not self.running: if not self.queues: raise AssertionError( "can't call `AlpacaStream.run()` without queues") asyncio.create_task(self.alpaca_ws_client._run_forever()) self.running = True @classmethod async def bar_handler(cls, msg): try: event = { "symbol": msg.symbol, "open": msg.open, "close": msg.close, "high": msg.high, "low": msg.low, "start": int(msg.timestamp // 1000000), "volume": msg.volume, "count": 0.0, "vwap": 0.0, "average": 0.0, "totalvolume": None, "EV": "AM", } cls.get_instance().queues[msg.symbol].put(event, timeout=1) except queue.Full as f: tlog( f"[EXCEPTION] process_message(): queue for {event['sym']} is FULL:{f}, sleeping for 2 seconds and re-trying." ) raise except Exception as e: tlog( f"[EXCEPTION] process_message(): exception of type {type(e).__name__} with args {e.args}" ) traceback.print_exc() @classmethod async def trades_handler(cls, msg): try: event = { "symbol": msg.symbol, "price": msg.price, "timestamp": pd.to_datetime(msg.timestamp), "volume": msg.size, "exchange": msg.exchange, "conditions": msg.conditions, "tape": msg.tape, "EV": "T", } cls.get_instance().queues[msg.symbol].put(event, timeout=1) except queue.Full as f: tlog( f"[EXCEPTION] process_message(): queue for {event['sym']} is FULL:{f}, sleeping for 2 seconds and re-trying." ) raise except Exception as e: tlog( f"[EXCEPTION] process_message(): exception of type {type(e).__name__} with args {e.args}" ) traceback.print_exc() @classmethod async def quotes_handler(cls, msg): print(f"quotes_handler:{msg}") async def subscribe(self, symbols: List[str], events: List[WSEventType]) -> bool: for event in events: if event == WSEventType.SEC_AGG: tlog(f"event {event} not implemented in Alpaca") elif event == WSEventType.MIN_AGG: self.alpaca_ws_client._data_ws._running = False self.alpaca_ws_client.subscribe_bars(AlpacaStream.bar_handler, *symbols) elif event == WSEventType.TRADE: self.alpaca_ws_client.subscribe_trades( AlpacaStream.trades_handler, *symbols) elif event == WSEventType.QUOTE: self.alpaca_ws_client.subscribe_quotes( AlpacaStream.quotes_handler, *symbols) return True