Skip to content

Commit a12a2ca

Browse files
committed
add spread_typefilter for UDS. added global message hanlder on_message`
1 parent ed2f3f4 commit a12a2ca

File tree

5 files changed

+68
-33
lines changed

5 files changed

+68
-33
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ of_client.on_error = lambda x: print("Error:", x)
2525
of_client.on_connected = lambda x: print("Connected")
2626
of_client.on_disconnected = lambda x: print("Disconnected")
2727

28+
# attach a global message handler
29+
of_client.on_message = lambda x: print("Global Message:", x)
30+
2831
# sub to markets by symbol
2932
def on_message(msg):
3033
print("Market Data: ", msg)

example.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
args = parser.parse_args()
1010

1111
# new client with credentials
12-
of_client = openfeed.OpenfeedClient(args.u, args.p)
12+
of_client = openfeed.OpenfeedClient(
13+
args.u, args.p, debug=False, server="demo.openfeed.barchart.com")
1314

1415
# app state handlers
1516
of_client.on_error = lambda x: print("OnError:", x)
@@ -18,13 +19,18 @@
1819
of_client.on_login = lambda x: print("OnLogin:", x)
1920
of_client.on_logout = lambda x: print("OnLogout:", x)
2021

21-
# sub to markets by symbol
22+
# add a global message handler for all incoming OF messages
23+
# of_client.on_message = lambda msg: print("Global Message:", msg)
24+
25+
# sub message handler
2226
def on_message(msg):
2327
print("Market Data Message: ", msg)
2428

25-
#of_client.add_symbol_subscription("ADF.WS", callback=on_message, subscription_type=["OHLC"])
29+
# subscribe to UDS an filter by type (optional)
30+
of_client.add_symbol_subscription(
31+
"T8^UDS", callback=on_message, subscription_type=["QUOTE"], spread_type_filter=["RR", "JR"])
2632

27-
of_client.request_instruments_for_exchange("AMEX", callback=on_message)
33+
# of_client.request_instruments_for_exchange("AMEX", callback=on_message)
2834

2935
# list exchanges
3036

openfeed/openfeed_client.py

Lines changed: 53 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ def __init__(self, username, password, server="openfeed.aws.barchart.com", debug
4444
self.on_error = None
4545
self.on_login = None
4646
self.on_logout = None
47+
self.on_message = None
4748

4849
websocket.enableTrace(self.debug)
4950

@@ -75,7 +76,7 @@ def add_heartbeat_subscription(self, callback):
7576

7677
return self
7778

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=[]):
7980
"""Subscribe to [Market Data] by Barchart Symbols
8081
8182
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
9091
Default is ['QUOTE']. Can contain any of: 'ALL', 'QUOTE', 'QUOTE_PARTICIPANT', 'DEPTH_PRICE', 'DEPTH_ORDER', 'TRADES', 'OHLC'
9192
9293
[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/
9496
[Service]: https://docs.barchart.com/openfeed/#/proto?id=service
9597
"""
9698
symbols = []
@@ -105,11 +107,11 @@ def add_symbol_subscription(self, symbol: Union[str, list], callback, service="R
105107
self.symbol_handlers[sym] = []
106108

107109
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))
109111

110112
if self.token is not None:
111113
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))
113115

114116
return self
115117

@@ -136,10 +138,13 @@ def add_exchange_subscription(self, exchange: Union[str, list], callback, servic
136138
List of [BulkSubscriptionFilter]
137139
138140
[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/
140143
[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/
143148
"""
144149
exchanges = []
145150

@@ -156,15 +161,16 @@ def add_exchange_subscription(self, exchange: Union[str, list], callback, servic
156161
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))
157162

158163
if self.token is not None:
159-
self._send_message(
164+
self._send_message(
160165
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))
161166

162167
return self
163168

164169
def request_available_exchanges(self, callback):
165170
"""Request a list of available [Exchanges] for subscription.
166171
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/
168174
"""
169175
rid = random.getrandbits(32)
170176
req = self.__create_exchange_request(rid)
@@ -179,7 +185,8 @@ def request_available_exchanges(self, callback):
179185
def request_instruments_for_exchange(self, exchange, callback):
180186
"""Request a list of [Instrument Definitions] actively trading trading on an exchange.
181187
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/
183190
"""
184191

185192
rid = random.getrandbits(32)
@@ -193,12 +200,14 @@ def request_instruments_for_exchange(self, exchange, callback):
193200
return self
194201

195202
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`
197204
198205
See [Instrument Request]
199206
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/
202211
"""
203212

204213
rid = random.getrandbits(32)
@@ -215,22 +224,26 @@ def request_instruments(self, callback, symbol=None, market_id=None, exchange=No
215224
def get_instrument_definitions(self):
216225
"""Returns a dict of Openfeed [Instrument Definitions] keyed by MarketID
217226
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/
219229
"""
220230
return self.instrument_definitions
221231

222-
def get_instrument_definition(self, id):
232+
def get_instrument_definition(self, _id):
223233
"""Returns an [Instrument Definition] for a Market ID
224234
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/
226237
"""
227-
return self.instrument_definitions[id].instrumentDefinition
238+
return self.instrument_definitions[_id].instrumentDefinition
228239

229240
def get_instrument_definition_by_symbol(self, symbol):
230241
"""Returns an [Instrument Definition] for a [Symbol] string
231242
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/
234247
"""
235248
return self.instruments_by_symbol[symbol].instrumentDefinition
236249

@@ -390,15 +403,19 @@ def on_message(ws: websocket.WebSocketApp, message):
390403
msg = openfeed_api_pb2.OpenfeedGatewayMessage()
391404
msg.ParseFromString(byte_buffer.read(msg_len))
392405

406+
msg_type = msg.WhichOneof("data")
407+
393408
if self.debug:
394409
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)
398412

399413
handler = handlers.get(
400414
msg_type, lambda x: print("Unhandled Message:", x))
401415

416+
# global on_message callback
417+
self.__callback(self.on_message, msg)
418+
402419
try:
403420
handler(msg)
404421
except Exception as e:
@@ -443,6 +460,9 @@ def __notify_symbol_listeners(self, instrument, msg):
443460
if instrument.marketId in self.subscription_symbol_by_marketid:
444461
symbol_key = self.subscription_symbol_by_marketid[instrument.marketId]
445462

463+
if symbol_key == "":
464+
symbol_key = instrument.subscriptionSymbol
465+
446466
for s in instrument.symbols:
447467
if s.symbol not in self.symbol_handlers or s.vendor != "Barchart":
448468
continue
@@ -456,6 +476,9 @@ def __notify_symbol_listeners(self, instrument, msg):
456476
if self.debug:
457477
print("Failed to notify `symbol` callback:", symbol_key, e)
458478
self.__callback(self.on_error, e)
479+
else:
480+
if self.debug:
481+
print("Failed to find symbol key:", instrument)
459482

460483
def __notify_exchange_listeners(self, exchange, msg):
461484
if exchange not in self.exchange_handlers:
@@ -492,7 +515,7 @@ def __send_existing_interest(self):
492515
listeners_by_service = interest[l.service]
493516
if l.key() not in listeners_by_service:
494517
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)
496519
else:
497520
existing = listeners_by_service[l.key()]
498521
existing.subscription_type = list(set(
@@ -508,13 +531,14 @@ def __send_existing_interest(self):
508531
subscription_type=i.subscription_type,
509532
instrument_type=i.get_instrument_types(),
510533
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))
512536

513537
# send other rpc requests
514538
for req in self.request_id_handlers.values():
515539
req.send(self)
516540

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=[]):
518542
requests = []
519543

520544
if len(exchanges) > 0:
@@ -536,7 +560,8 @@ def __create_subscription_request(self, exchanges=[], symbols=[], service="REAL_
536560
symbol=sym,
537561
subscriptionType=[openfeed_api_pb2.SubscriptionType.Value(
538562
t) for t in subscription_type],
539-
snapshotIntervalSeconds=snapshot_interval_seconds
563+
snapshotIntervalSeconds=snapshot_interval_seconds,
564+
spreadTypeFilter=spread_types
540565
))
541566

542567
of_req = openfeed_api_pb2.OpenfeedGatewayRequest(
@@ -611,7 +636,7 @@ def __callback(self, callback, *args):
611636

612637

613638
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=[]):
615640
self.symbol = symbol
616641
self.exchange = exchange
617642
self.callback = callback
@@ -620,6 +645,7 @@ def __init__(self, symbol="", exchange="", callback=None, service="REAL_TIME", s
620645
self.instrument_type = instrument_type
621646
self.snapshot_interval_seconds = snapshot_interval_seconds
622647
self.bulk_subscription_filters = bulk_subscription_filters
648+
self.spread_types = spread_types
623649

624650
def key(self):
625651
if len(self.exchange) > 0:

openfeed/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
VERSION = '1.3.0'
1+
VERSION = '1.4.0'

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
name='openfeed',
2020
version='1.4.0',
2121
author='Barchart',
22-
author_email='mike@barchart.com',
22+
author_email='openfeed@barchart.com',
2323
license='MIT',
2424
url='https://github.com/openfeed-org/sdk-python',
2525
include_package_data=True,

0 commit comments

Comments
 (0)