@@ -44,6 +44,7 @@ def __init__(self, username, password, server="openfeed.aws.barchart.com", debug
44
44
self .on_error = None
45
45
self .on_login = None
46
46
self .on_logout = None
47
+ self .on_message = None
47
48
48
49
websocket .enableTrace (self .debug )
49
50
@@ -75,7 +76,7 @@ def add_heartbeat_subscription(self, callback):
75
76
76
77
return self
77
78
78
- def add_symbol_subscription (self , symbol : Union [str , list ], callback , service = "REAL_TIME" , subscription_type = ["QUOTE" ], snapshot_interval_seconds = 60 ):
79
+ def add_symbol_subscription (self , symbol : Union [str , list ], callback , service = "REAL_TIME" , subscription_type = ["QUOTE" ], snapshot_interval_seconds = 60 , spread_type_filter = [] ):
79
80
"""Subscribe to [Market Data] by Barchart Symbols
80
81
81
82
Complete list of [SubscriptionTypes]. List of [Service] types. List of [InstrumentTypes].
@@ -90,7 +91,8 @@ def add_symbol_subscription(self, symbol: Union[str, list], callback, service="R
90
91
Default is ['QUOTE']. Can contain any of: 'ALL', 'QUOTE', 'QUOTE_PARTICIPANT', 'DEPTH_PRICE', 'DEPTH_ORDER', 'TRADES', 'OHLC'
91
92
92
93
[Market Data]: https://docs.barchart.com/openfeed/#/proto?id=marketupdate
93
- [SubscriptionTypes]: https://docs.barchart.com/openfeed/#/proto?id=subscriptiontype
94
+ #/proto?id=subscriptiontype
95
+ [SubscriptionTypes]: https://docs.barchart.com/openfeed/
94
96
[Service]: https://docs.barchart.com/openfeed/#/proto?id=service
95
97
"""
96
98
symbols = []
@@ -105,11 +107,11 @@ def add_symbol_subscription(self, symbol: Union[str, list], callback, service="R
105
107
self .symbol_handlers [sym ] = []
106
108
107
109
self .symbol_handlers [sym ].append (
108
- Listener (symbol = sym , callback = callback , service = service , subscription_type = subscription_type , snapshot_interval_seconds = snapshot_interval_seconds ))
110
+ Listener (symbol = sym , callback = callback , service = service , subscription_type = subscription_type , snapshot_interval_seconds = snapshot_interval_seconds , spread_types = spread_type_filter ))
109
111
110
112
if self .token is not None :
111
113
self ._send_message (
112
- self .__create_subscription_request (symbols = symbols , service = service , subscription_type = subscription_type , snapshot_interval_seconds = snapshot_interval_seconds ))
114
+ self .__create_subscription_request (symbols = symbols , service = service , subscription_type = subscription_type , snapshot_interval_seconds = snapshot_interval_seconds , spread_types = spread_type_filter ))
113
115
114
116
return self
115
117
@@ -136,10 +138,13 @@ def add_exchange_subscription(self, exchange: Union[str, list], callback, servic
136
138
List of [BulkSubscriptionFilter]
137
139
138
140
[Market Data]: https://docs.barchart.com/openfeed/#/proto?id=marketupdate
139
- [SubscriptionTypes]: https://docs.barchart.com/openfeed/#/proto?id=subscriptiontype
141
+ #/proto?id=subscriptiontype
142
+ [SubscriptionTypes]: https://docs.barchart.com/openfeed/
140
143
[ServiceType]: https://docs.barchart.com/openfeed/#/proto?id=service
141
- [InstrumentTypes]: https://docs.barchart.com/openfeed/#/proto?id=instrumentdefinitioninstrumenttype
142
- [BulkSubscriptionFilter]: https://docs.barchart.com/openfeed/#/proto?id=bulksubscriptionfilter
144
+ #/proto?id=instrumentdefinitioninstrumenttype
145
+ [InstrumentTypes]: https://docs.barchart.com/openfeed/
146
+ #/proto?id=bulksubscriptionfilter
147
+ [BulkSubscriptionFilter]: https://docs.barchart.com/openfeed/
143
148
"""
144
149
exchanges = []
145
150
@@ -156,15 +161,16 @@ def add_exchange_subscription(self, exchange: Union[str, list], callback, servic
156
161
exchange = exch , callback = callback , service = service , subscription_type = subscription_type , instrument_type = instrument_type , snapshot_interval_seconds = snapshot_interval_seconds , bulk_subscription_filters = bulk_subscription_filters ))
157
162
158
163
if self .token is not None :
159
- self ._send_message (
164
+ self ._send_message (
160
165
self .__create_subscription_request (exchanges = exchanges , service = service , subscription_type = subscription_type , instrument_type = instrument_type , snapshot_interval_seconds = snapshot_interval_seconds , bulk_subscription_filters = bulk_subscription_filters ))
161
166
162
167
return self
163
168
164
169
def request_available_exchanges (self , callback ):
165
170
"""Request a list of available [Exchanges] for subscription.
166
171
167
- [Exchanges]: https://docs.barchart.com/openfeed/#/openfeed_streaming?id=requesting-exchanges
172
+ #/openfeed_streaming?id=requesting-exchanges
173
+ [Exchanges]: https://docs.barchart.com/openfeed/
168
174
"""
169
175
rid = random .getrandbits (32 )
170
176
req = self .__create_exchange_request (rid )
@@ -179,7 +185,8 @@ def request_available_exchanges(self, callback):
179
185
def request_instruments_for_exchange (self , exchange , callback ):
180
186
"""Request a list of [Instrument Definitions] actively trading trading on an exchange.
181
187
182
- [Instrument Definitions]: https://docs.barchart.com/openfeed/#/proto?id=openfeed_instrumentproto
188
+ #/proto?id=openfeed_instrumentproto
189
+ [Instrument Definitions]: https://docs.barchart.com/openfeed/
183
190
"""
184
191
185
192
rid = random .getrandbits (32 )
@@ -193,12 +200,14 @@ def request_instruments_for_exchange(self, exchange, callback):
193
200
return self
194
201
195
202
def request_instruments (self , callback , symbol = None , market_id = None , exchange = None ):
196
- """Request [Instrument Definitions] by `symbol`, `market_id`, or `exchange`
203
+ """Request [Instrument Definitions] by `symbol`, `market_id`, or `exchange`
197
204
198
205
See [Instrument Request]
199
206
200
- [Instrument Definitions]: https://docs.barchart.com/openfeed/#/proto?id=openfeed_instrumentproto
201
- [Instrument Request]: https://docs.barchart.com/openfeed/#/proto?id=instrumentrequest
207
+ #/proto?id=openfeed_instrumentproto
208
+ [Instrument Definitions]: https://docs.barchart.com/openfeed/
209
+ #/proto?id=instrumentrequest
210
+ [Instrument Request]: https://docs.barchart.com/openfeed/
202
211
"""
203
212
204
213
rid = random .getrandbits (32 )
@@ -215,22 +224,26 @@ def request_instruments(self, callback, symbol=None, market_id=None, exchange=No
215
224
def get_instrument_definitions (self ):
216
225
"""Returns a dict of Openfeed [Instrument Definitions] keyed by MarketID
217
226
218
- [Instrument Definitions]: https://docs.barchart.com/openfeed/#/proto?id=openfeed_instrumentproto
227
+ #/proto?id=openfeed_instrumentproto
228
+ [Instrument Definitions]: https://docs.barchart.com/openfeed/
219
229
"""
220
230
return self .instrument_definitions
221
231
222
- def get_instrument_definition (self , id ):
232
+ def get_instrument_definition (self , _id ):
223
233
"""Returns an [Instrument Definition] for a Market ID
224
234
225
- [Instrument Definition]: https://docs.barchart.com/openfeed/#/proto?id=openfeed_instrumentproto
235
+ #/proto?id=openfeed_instrumentproto
236
+ [Instrument Definition]: https://docs.barchart.com/openfeed/
226
237
"""
227
- return self .instrument_definitions [id ].instrumentDefinition
238
+ return self .instrument_definitions [_id ].instrumentDefinition
228
239
229
240
def get_instrument_definition_by_symbol (self , symbol ):
230
241
"""Returns an [Instrument Definition] for a [Symbol] string
231
242
232
- [Instrument Definition]: https://docs.barchart.com/openfeed/#/proto?id=openfeed_instrumentproto
233
- [Symbol]: https://docs.barchart.com/openfeed/#/proto?id=instrumentdefinitionsymbol
243
+ #/proto?id=openfeed_instrumentproto
244
+ [Instrument Definition]: https://docs.barchart.com/openfeed/
245
+ #/proto?id=instrumentdefinitionsymbol
246
+ [Symbol]: https://docs.barchart.com/openfeed/
234
247
"""
235
248
return self .instruments_by_symbol [symbol ].instrumentDefinition
236
249
@@ -390,15 +403,19 @@ def on_message(ws: websocket.WebSocketApp, message):
390
403
msg = openfeed_api_pb2 .OpenfeedGatewayMessage ()
391
404
msg .ParseFromString (byte_buffer .read (msg_len ))
392
405
406
+ msg_type = msg .WhichOneof ("data" )
407
+
393
408
if self .debug :
394
409
msg_count = msg_count + 1
395
- print ("msg len:" , msg_len , "number of messages:" , msg_count )
396
-
397
- msg_type = msg .WhichOneof ("data" )
410
+ print ("msg len:" , msg_len , "type:" ,
411
+ msg_type , "total messages:" , msg_count )
398
412
399
413
handler = handlers .get (
400
414
msg_type , lambda x : print ("Unhandled Message:" , x ))
401
415
416
+ # global on_message callback
417
+ self .__callback (self .on_message , msg )
418
+
402
419
try :
403
420
handler (msg )
404
421
except Exception as e :
@@ -443,6 +460,9 @@ def __notify_symbol_listeners(self, instrument, msg):
443
460
if instrument .marketId in self .subscription_symbol_by_marketid :
444
461
symbol_key = self .subscription_symbol_by_marketid [instrument .marketId ]
445
462
463
+ if symbol_key == "" :
464
+ symbol_key = instrument .subscriptionSymbol
465
+
446
466
for s in instrument .symbols :
447
467
if s .symbol not in self .symbol_handlers or s .vendor != "Barchart" :
448
468
continue
@@ -456,6 +476,9 @@ def __notify_symbol_listeners(self, instrument, msg):
456
476
if self .debug :
457
477
print ("Failed to notify `symbol` callback:" , symbol_key , e )
458
478
self .__callback (self .on_error , e )
479
+ else :
480
+ if self .debug :
481
+ print ("Failed to find symbol key:" , instrument )
459
482
460
483
def __notify_exchange_listeners (self , exchange , msg ):
461
484
if exchange not in self .exchange_handlers :
@@ -492,7 +515,7 @@ def __send_existing_interest(self):
492
515
listeners_by_service = interest [l .service ]
493
516
if l .key () not in listeners_by_service :
494
517
listeners_by_service [l .key ()] = Listener (
495
- symbol = l .symbol , exchange = l .exchange , service = l .service , subscription_type = l .subscription_type , instrument_type = l .instrument_type , snapshot_interval_seconds = l .snapshot_interval_seconds , bulk_subscription_filters = l .bulk_subscription_filters )
518
+ symbol = l .symbol , exchange = l .exchange , service = l .service , subscription_type = l .subscription_type , instrument_type = l .instrument_type , snapshot_interval_seconds = l .snapshot_interval_seconds , bulk_subscription_filters = l .bulk_subscription_filters , spread_types = l . spread_types )
496
519
else :
497
520
existing = listeners_by_service [l .key ()]
498
521
existing .subscription_type = list (set (
@@ -508,13 +531,14 @@ def __send_existing_interest(self):
508
531
subscription_type = i .subscription_type ,
509
532
instrument_type = i .get_instrument_types (),
510
533
snapshot_interval_seconds = i .snapshot_interval_seconds ,
511
- bulk_subscription_filters = i .bulk_subscription_filters ))
534
+ bulk_subscription_filters = i .bulk_subscription_filters ,
535
+ spread_types = i .spread_types ))
512
536
513
537
# send other rpc requests
514
538
for req in self .request_id_handlers .values ():
515
539
req .send (self )
516
540
517
- def __create_subscription_request (self , exchanges = [], symbols = [], service = "REAL_TIME" , subscription_type = ["QUOTE" ], instrument_type = [], snapshot_interval_seconds = 60 , bulk_subscription_filters = []):
541
+ def __create_subscription_request (self , exchanges = [], symbols = [], service = "REAL_TIME" , subscription_type = ["QUOTE" ], instrument_type = [], snapshot_interval_seconds = 60 , bulk_subscription_filters = [], spread_types = [] ):
518
542
requests = []
519
543
520
544
if len (exchanges ) > 0 :
@@ -536,7 +560,8 @@ def __create_subscription_request(self, exchanges=[], symbols=[], service="REAL_
536
560
symbol = sym ,
537
561
subscriptionType = [openfeed_api_pb2 .SubscriptionType .Value (
538
562
t ) for t in subscription_type ],
539
- snapshotIntervalSeconds = snapshot_interval_seconds
563
+ snapshotIntervalSeconds = snapshot_interval_seconds ,
564
+ spreadTypeFilter = spread_types
540
565
))
541
566
542
567
of_req = openfeed_api_pb2 .OpenfeedGatewayRequest (
@@ -611,7 +636,7 @@ def __callback(self, callback, *args):
611
636
612
637
613
638
class Listener (object ):
614
- def __init__ (self , symbol = "" , exchange = "" , callback = None , service = "REAL_TIME" , subscription_type = ["QUOTE" ], instrument_type = [], snapshot_interval_seconds = 60 , bulk_subscription_filters = []):
639
+ def __init__ (self , symbol = "" , exchange = "" , callback = None , service = "REAL_TIME" , subscription_type = ["QUOTE" ], instrument_type = [], snapshot_interval_seconds = 60 , bulk_subscription_filters = [], spread_types = [] ):
615
640
self .symbol = symbol
616
641
self .exchange = exchange
617
642
self .callback = callback
@@ -620,6 +645,7 @@ def __init__(self, symbol="", exchange="", callback=None, service="REAL_TIME", s
620
645
self .instrument_type = instrument_type
621
646
self .snapshot_interval_seconds = snapshot_interval_seconds
622
647
self .bulk_subscription_filters = bulk_subscription_filters
648
+ self .spread_types = spread_types
623
649
624
650
def key (self ):
625
651
if len (self .exchange ) > 0 :
0 commit comments