2022-11-07 20:40:52 +00:00
|
|
|
'''
|
|
|
|
Data feed layer APIs, performance, msg throttling.
|
|
|
|
|
|
|
|
'''
|
2022-11-09 23:57:15 +00:00
|
|
|
from collections import Counter
|
2022-11-07 20:40:52 +00:00
|
|
|
from pprint import pprint
|
2023-01-09 23:16:55 +00:00
|
|
|
from typing import AsyncContextManager
|
2022-11-07 20:40:52 +00:00
|
|
|
|
|
|
|
import pytest
|
2022-11-11 22:27:02 +00:00
|
|
|
# import tractor
|
2022-11-07 20:40:52 +00:00
|
|
|
import trio
|
2023-01-09 23:16:55 +00:00
|
|
|
from piker.data import (
|
|
|
|
ShmArray,
|
2022-11-07 20:40:52 +00:00
|
|
|
open_feed,
|
|
|
|
)
|
2023-04-12 03:59:50 +00:00
|
|
|
from piker.data.flows import Flume
|
2023-05-17 20:43:31 +00:00
|
|
|
from piker.accounting import (
|
2023-04-18 23:12:14 +00:00
|
|
|
unpack_fqme,
|
2022-11-10 15:38:45 +00:00
|
|
|
)
|
2022-11-07 20:40:52 +00:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
2023-04-12 03:59:50 +00:00
|
|
|
'fqmes',
|
2022-11-07 20:40:52 +00:00
|
|
|
[
|
2022-11-11 22:27:02 +00:00
|
|
|
# binance
|
2023-01-09 23:16:55 +00:00
|
|
|
(100, {'btcusdt.binance', 'ethusdt.binance'}, False),
|
2022-11-11 22:27:02 +00:00
|
|
|
|
|
|
|
# kraken
|
2023-01-09 23:16:55 +00:00
|
|
|
(20, {'ethusdt.kraken', 'xbtusd.kraken'}, True),
|
2022-11-11 22:27:02 +00:00
|
|
|
|
|
|
|
# binance + kraken
|
2023-01-09 23:16:55 +00:00
|
|
|
(100, {'btcusdt.binance', 'xbtusd.kraken'}, False),
|
2022-11-07 20:40:52 +00:00
|
|
|
],
|
2023-04-12 03:59:50 +00:00
|
|
|
ids=lambda param: f'quotes={param[0]}@fqmes={param[1]}',
|
2022-11-07 20:40:52 +00:00
|
|
|
)
|
2022-11-11 22:27:02 +00:00
|
|
|
def test_multi_fqsn_feed(
|
2023-01-09 23:16:55 +00:00
|
|
|
open_test_pikerd: AsyncContextManager,
|
2023-04-12 03:59:50 +00:00
|
|
|
fqmes: set[str],
|
2023-02-21 15:21:03 +00:00
|
|
|
loglevel: str,
|
2023-01-09 23:16:55 +00:00
|
|
|
ci_env: bool
|
2022-11-07 20:40:52 +00:00
|
|
|
):
|
|
|
|
'''
|
2023-04-12 03:59:50 +00:00
|
|
|
Start a real-time data feed for provided fqme and pull
|
2022-11-07 20:40:52 +00:00
|
|
|
a few quotes then simply shut down.
|
|
|
|
|
|
|
|
'''
|
2023-04-12 03:59:50 +00:00
|
|
|
max_quotes, fqmes, run_in_ci = fqmes
|
2023-01-09 23:16:55 +00:00
|
|
|
|
|
|
|
if (
|
|
|
|
ci_env
|
|
|
|
and not run_in_ci
|
|
|
|
):
|
|
|
|
pytest.skip('Skipping CI disabled test due to feed restrictions')
|
2022-11-10 15:38:45 +00:00
|
|
|
|
|
|
|
brokers = set()
|
2023-04-12 03:59:50 +00:00
|
|
|
for fqme in fqmes:
|
2023-04-18 23:12:14 +00:00
|
|
|
brokername, *_ = unpack_fqme(fqme)
|
2022-11-10 15:38:45 +00:00
|
|
|
brokers.add(brokername)
|
|
|
|
|
2022-11-07 20:40:52 +00:00
|
|
|
async def main():
|
|
|
|
async with (
|
2023-01-09 23:16:55 +00:00
|
|
|
open_test_pikerd(),
|
2022-11-07 20:40:52 +00:00
|
|
|
open_feed(
|
2023-04-12 03:59:50 +00:00
|
|
|
fqmes,
|
2023-02-21 15:21:03 +00:00
|
|
|
loglevel=loglevel,
|
2022-11-07 20:40:52 +00:00
|
|
|
|
|
|
|
# TODO: ensure throttle rate is applied
|
|
|
|
# limit to at least display's FPS
|
|
|
|
# avoiding needless Qt-in-guest-mode context switches
|
|
|
|
# tick_throttle=_quote_throttle_rate,
|
|
|
|
|
|
|
|
) as feed
|
|
|
|
):
|
2022-11-08 21:09:18 +00:00
|
|
|
# verify shm buffers exist
|
2023-04-12 03:59:50 +00:00
|
|
|
for fqin in fqmes:
|
2022-11-08 21:09:18 +00:00
|
|
|
flume = feed.flumes[fqin]
|
|
|
|
ohlcv: ShmArray = flume.rt_shm
|
|
|
|
hist_ohlcv: ShmArray = flume.hist_shm
|
2022-11-07 20:40:52 +00:00
|
|
|
|
2022-11-11 22:27:02 +00:00
|
|
|
async with feed.open_multi_stream(brokers) as stream:
|
|
|
|
|
2023-04-12 03:59:50 +00:00
|
|
|
# pull the first startup quotes, one for each fqme, and
|
2022-11-11 22:27:02 +00:00
|
|
|
# ensure they match each flume's startup quote value.
|
2023-04-12 03:59:50 +00:00
|
|
|
fqsns_copy = fqmes.copy()
|
2022-11-11 22:27:02 +00:00
|
|
|
with trio.fail_after(0.5):
|
|
|
|
for _ in range(1):
|
|
|
|
first_quotes = await stream.receive()
|
2023-04-12 03:59:50 +00:00
|
|
|
for fqme, quote in first_quotes.items():
|
2022-11-11 22:27:02 +00:00
|
|
|
|
|
|
|
# XXX: TODO: WTF apparently this error will get
|
|
|
|
# supressed and only show up in the teardown
|
|
|
|
# excgroup if we don't have the fix from
|
|
|
|
# <tractorbugurl>
|
|
|
|
# assert 0
|
|
|
|
|
2023-04-12 03:59:50 +00:00
|
|
|
fqsns_copy.remove(fqme)
|
|
|
|
flume: Flume = feed.flumes[fqme]
|
2022-11-11 22:27:02 +00:00
|
|
|
assert quote['last'] == flume.first_quote['last']
|
|
|
|
|
|
|
|
cntr = Counter()
|
2022-12-10 20:32:09 +00:00
|
|
|
with trio.fail_after(6):
|
2022-11-11 22:27:02 +00:00
|
|
|
async for quotes in stream:
|
2023-04-12 03:59:50 +00:00
|
|
|
for fqme, quote in quotes.items():
|
|
|
|
cntr[fqme] += 1
|
2022-11-11 22:27:02 +00:00
|
|
|
|
|
|
|
# await tractor.breakpoint()
|
2023-04-12 03:59:50 +00:00
|
|
|
flume = feed.flumes[fqme]
|
2022-11-11 22:27:02 +00:00
|
|
|
ohlcv: ShmArray = flume.rt_shm
|
|
|
|
hist_ohlcv: ShmArray = flume.hist_shm
|
|
|
|
|
|
|
|
# print quote msg, rt and history
|
|
|
|
# buffer values on console.
|
|
|
|
rt_row = ohlcv.array[-1]
|
|
|
|
hist_row = hist_ohlcv.array[-1]
|
|
|
|
# last = quote['last']
|
|
|
|
|
|
|
|
# assert last == rt_row['close']
|
|
|
|
# assert last == hist_row['close']
|
|
|
|
pprint(
|
2023-04-12 03:59:50 +00:00
|
|
|
f'{fqme}: {quote}\n'
|
2022-11-11 22:27:02 +00:00
|
|
|
f'rt_ohlc: {rt_row}\n'
|
|
|
|
f'hist_ohlc: {hist_row}\n'
|
|
|
|
)
|
|
|
|
|
|
|
|
if cntr.total() >= max_quotes:
|
|
|
|
break
|
|
|
|
|
2023-04-12 03:59:50 +00:00
|
|
|
assert set(cntr.keys()) == fqmes
|
2022-11-09 23:57:15 +00:00
|
|
|
|
2022-11-07 20:40:52 +00:00
|
|
|
trio.run(main)
|