binance: port `stream_messages()` to use `match:` and a new `L1` struct
parent
f6cd08c6fa
commit
af068c5c51
|
@ -176,6 +176,18 @@ class OHLC(Struct):
|
||||||
bar_wap: float = 0.0
|
bar_wap: float = 0.0
|
||||||
|
|
||||||
|
|
||||||
|
class L1(Struct):
|
||||||
|
# https://binance-docs.github.io/apidocs/spot/en/#individual-symbol-book-ticker-streams
|
||||||
|
|
||||||
|
update_id: int
|
||||||
|
sym: str
|
||||||
|
|
||||||
|
bid: float
|
||||||
|
bsize: float
|
||||||
|
ask: float
|
||||||
|
asize: float
|
||||||
|
|
||||||
|
|
||||||
# convert datetime obj timestamp to unixtime in milliseconds
|
# convert datetime obj timestamp to unixtime in milliseconds
|
||||||
def binance_timestamp(
|
def binance_timestamp(
|
||||||
when: datetime
|
when: datetime
|
||||||
|
@ -363,45 +375,85 @@ async def stream_messages(
|
||||||
) -> AsyncGenerator[NoBsWs, dict]:
|
) -> AsyncGenerator[NoBsWs, dict]:
|
||||||
|
|
||||||
# TODO: match syntax here!
|
# TODO: match syntax here!
|
||||||
|
msg: dict[str, Any]
|
||||||
async for msg in ws:
|
async for msg in ws:
|
||||||
|
match msg:
|
||||||
# for l1 streams binance doesn't add an event type field so
|
# for l1 streams binance doesn't add an event type field so
|
||||||
# identify those messages by matching keys
|
# identify those messages by matching keys
|
||||||
# https://binance-docs.github.io/apidocs/spot/en/#individual-symbol-book-ticker-streams
|
# https://binance-docs.github.io/apidocs/spot/en/#individual-symbol-book-ticker-streams
|
||||||
if msg.get('u'):
|
case {
|
||||||
sym = msg['s']
|
# NOTE: this is never an old value it seems, so
|
||||||
bid = float(msg['b'])
|
# they are always sending real L1 spread updates.
|
||||||
bsize = float(msg['B'])
|
'u': upid, # update id
|
||||||
ask = float(msg['a'])
|
's': sym,
|
||||||
asize = float(msg['A'])
|
'b': bid,
|
||||||
|
'B': bsize,
|
||||||
|
'a': ask,
|
||||||
|
'A': asize,
|
||||||
|
}:
|
||||||
|
# TODO: it would be super nice to have a `L1` piker type
|
||||||
|
# which "renders" incremental tick updates from a packed
|
||||||
|
# msg-struct:
|
||||||
|
# - backend msgs after packed into the type such that we
|
||||||
|
# can reduce IPC usage but without each backend having
|
||||||
|
# to do that incremental update logic manually B)
|
||||||
|
# - would it maybe be more efficient to use this instead?
|
||||||
|
# https://binance-docs.github.io/apidocs/spot/en/#diff-depth-stream
|
||||||
|
l1 = L1(
|
||||||
|
update_id=upid,
|
||||||
|
sym=sym,
|
||||||
|
bid=bid,
|
||||||
|
bsize=bsize,
|
||||||
|
ask=ask,
|
||||||
|
asize=asize,
|
||||||
|
)
|
||||||
|
l1.typecast()
|
||||||
|
|
||||||
|
# repack into piker's tick-quote format
|
||||||
yield 'l1', {
|
yield 'l1', {
|
||||||
'symbol': sym,
|
'symbol': l1.sym,
|
||||||
'ticks': [
|
'ticks': [
|
||||||
{'type': 'bid', 'price': bid, 'size': bsize},
|
{
|
||||||
{'type': 'bsize', 'price': bid, 'size': bsize},
|
'type': 'bid',
|
||||||
{'type': 'ask', 'price': ask, 'size': asize},
|
'price': l1.bid,
|
||||||
{'type': 'asize', 'price': ask, 'size': asize}
|
'size': l1.bsize,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'bsize',
|
||||||
|
'price': l1.bid,
|
||||||
|
'size': l1.bsize,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'ask',
|
||||||
|
'price': l1.ask,
|
||||||
|
'size': l1.asize,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'asize',
|
||||||
|
'price': l1.ask,
|
||||||
|
'size': l1.asize,
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
elif msg.get('e') == 'aggTrade':
|
# https://binance-docs.github.io/apidocs/spot/en/#aggregate-trade-streams
|
||||||
|
case {
|
||||||
# NOTE: this is purely for a definition, ``msgspec.Struct``
|
'e': 'aggTrade',
|
||||||
# does not runtime-validate until you decode/encode.
|
}:
|
||||||
# see: https://jcristharif.com/msgspec/structs.html#type-validation
|
# NOTE: this is purely for a definition,
|
||||||
|
# ``msgspec.Struct`` does not runtime-validate until you
|
||||||
|
# decode/encode, see:
|
||||||
|
# https://jcristharif.com/msgspec/structs.html#type-validation
|
||||||
msg = AggTrade(**msg)
|
msg = AggTrade(**msg)
|
||||||
|
msg.typecast()
|
||||||
# TODO: type out and require this quote format
|
|
||||||
# from all backends!
|
|
||||||
yield 'trade', {
|
yield 'trade', {
|
||||||
'symbol': msg.s,
|
'symbol': msg.s,
|
||||||
'last': msg.p,
|
'last': msg.p,
|
||||||
'brokerd_ts': time.time(),
|
'brokerd_ts': time.time(),
|
||||||
'ticks': [{
|
'ticks': [{
|
||||||
'type': 'trade',
|
'type': 'trade',
|
||||||
'price': float(msg.p),
|
'price': msg.p,
|
||||||
'size': float(msg.q),
|
'size': msg.q,
|
||||||
'broker_ts': msg.T,
|
'broker_ts': msg.T,
|
||||||
}],
|
}],
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue