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()
logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO) ALPACA_API_KEY = "<YOUR-API-KEY>" ALPACA_SECRET_KEY = "<YOUR-SECRET-KEY>" def run_connection(conn): try: conn.run() 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') conn.run() run_connection(conn)
def start_trading(self): conn = Stream( self.key_id, self.secret_key, base_url=self.base_url, data_feed='iex') # <- replace to SIP if you have PRO subscription # Listen for second aggregates and perform trading logic async def handle_bar(bar): self.tick_index = (self.tick_index + 1) % self.tick_size if self.tick_index == 0: # It's time to update # Update price info tick_open = self.last_price tick_close = bar.close self.last_price = tick_close self.process_current_tick(tick_open, tick_close) conn.subscribe_bars(handle_bar, self.symbol) # Listen for quote data and perform trading logic async def handle_trades(trade): now = datetime.datetime.utcnow() if now - self.last_trade_time < datetime.timedelta(seconds=1): # don't react every tick unless at least 1 second past return self.last_trade_time = now self.tick_index = (self.tick_index + 1) % self.tick_size if self.tick_index == 0: # It's time to update # Update price info tick_open = self.last_price tick_close = trade.price self.last_price = tick_close self.process_current_tick(tick_open, tick_close) conn.subscribe_trades(handle_trades, self.symbol) # Listen for updates to our orders async def handle_trade_updates(data): symbol = data.order['symbol'] if symbol != self.symbol: # The order was for a position unrelated to this script return event_type = data.event qty = int(data.order['filled_qty']) side = data.order['side'] oid = data.order['id'] if event_type == 'fill' or event_type == 'partial_fill': # Our position size has changed self.position = int(data.position_qty) print(f'New position size due to order fill: {self.position}') if (event_type == 'fill' and self.current_order and self.current_order.id == oid): self.current_order = None elif event_type == 'rejected' or event_type == 'canceled': if self.current_order and self.current_order.id == oid: # Our last order should be removed self.current_order = None elif event_type != 'new': print(f'Unexpected order event type {event_type} received') conn.subscribe_trade_updates(handle_trade_updates) conn.run()