Deliver symbol info from kraken; start using pydantic
parent
a8c4829cb6
commit
69df73afc3
|
@ -18,7 +18,7 @@
|
||||||
Kraken backend.
|
Kraken backend.
|
||||||
"""
|
"""
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
from dataclasses import dataclass, asdict, field
|
from dataclasses import asdict, field
|
||||||
from typing import List, Dict, Any, Tuple, Optional
|
from typing import List, Dict, Any, Tuple, Optional
|
||||||
import json
|
import json
|
||||||
import time
|
import time
|
||||||
|
@ -30,6 +30,8 @@ import asks
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import trio
|
import trio
|
||||||
import tractor
|
import tractor
|
||||||
|
from pydantic.dataclasses import dataclass
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
from ._util import resproc, SymbolNotFound, BrokerError
|
from ._util import resproc, SymbolNotFound, BrokerError
|
||||||
from ..log import get_logger, get_console_log
|
from ..log import get_logger, get_console_log
|
||||||
|
@ -68,6 +70,68 @@ ohlc_dtype = np.dtype(_ohlc_dtype)
|
||||||
_show_wap_in_history = True
|
_show_wap_in_history = True
|
||||||
|
|
||||||
|
|
||||||
|
_symbol_info_translation: Dict[str, str] = {
|
||||||
|
'tick_decimals': 'pair_decimals',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# https://www.kraken.com/features/api#get-tradable-pairs
|
||||||
|
class Pair(BaseModel):
|
||||||
|
altname: str # alternate pair name
|
||||||
|
wsname: str # WebSocket pair name (if available)
|
||||||
|
aclass_base: str # asset class of base component
|
||||||
|
base: str # asset id of base component
|
||||||
|
aclass_quote: str # asset class of quote component
|
||||||
|
quote: str # asset id of quote component
|
||||||
|
lot: str # volume lot size
|
||||||
|
|
||||||
|
pair_decimals: int # scaling decimal places for pair
|
||||||
|
lot_decimals: int # scaling decimal places for volume
|
||||||
|
|
||||||
|
# amount to multiply lot volume by to get currency volume
|
||||||
|
lot_multiplier: float
|
||||||
|
|
||||||
|
# array of leverage amounts available when buying
|
||||||
|
leverage_buy: List[int]
|
||||||
|
# array of leverage amounts available when selling
|
||||||
|
leverage_sell: List[int]
|
||||||
|
|
||||||
|
# fee schedule array in [volume, percent fee] tuples
|
||||||
|
fees: List[Tuple[int, float]]
|
||||||
|
|
||||||
|
# maker fee schedule array in [volume, percent fee] tuples (if on
|
||||||
|
# maker/taker)
|
||||||
|
fees_maker: List[Tuple[int, float]]
|
||||||
|
|
||||||
|
fee_volume_currency: str # volume discount currency
|
||||||
|
margin_call: str # margin call level
|
||||||
|
margin_stop: str # stop-out/liquidation margin level
|
||||||
|
ordermin: float # minimum order volume for pair
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class OHLC:
|
||||||
|
"""Description of the flattened OHLC quote format.
|
||||||
|
|
||||||
|
For schema details see:
|
||||||
|
https://docs.kraken.com/websockets/#message-ohlc
|
||||||
|
"""
|
||||||
|
chan_id: int # internal kraken id
|
||||||
|
chan_name: str # eg. ohlc-1 (name-interval)
|
||||||
|
pair: str # fx pair
|
||||||
|
time: float # Begin time of interval, in seconds since epoch
|
||||||
|
etime: float # End time of interval, in seconds since epoch
|
||||||
|
open: float # Open price of interval
|
||||||
|
high: float # High price within interval
|
||||||
|
low: float # Low price within interval
|
||||||
|
close: float # Close price of interval
|
||||||
|
vwap: float # Volume weighted average price within interval
|
||||||
|
volume: float # Accumulated volume **within interval**
|
||||||
|
count: int # Number of trades within interval
|
||||||
|
# (sampled) generated tick data
|
||||||
|
ticks: List[Any] = field(default_factory=list)
|
||||||
|
|
||||||
|
|
||||||
class Client:
|
class Client:
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
|
@ -165,36 +229,6 @@ async def get_client() -> Client:
|
||||||
yield Client()
|
yield Client()
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class OHLC:
|
|
||||||
"""Description of the flattened OHLC quote format.
|
|
||||||
|
|
||||||
For schema details see:
|
|
||||||
https://docs.kraken.com/websockets/#message-ohlc
|
|
||||||
"""
|
|
||||||
chan_id: int # internal kraken id
|
|
||||||
chan_name: str # eg. ohlc-1 (name-interval)
|
|
||||||
pair: str # fx pair
|
|
||||||
time: float # Begin time of interval, in seconds since epoch
|
|
||||||
etime: float # End time of interval, in seconds since epoch
|
|
||||||
open: float # Open price of interval
|
|
||||||
high: float # High price within interval
|
|
||||||
low: float # Low price within interval
|
|
||||||
close: float # Close price of interval
|
|
||||||
vwap: float # Volume weighted average price within interval
|
|
||||||
volume: float # Accumulated volume **within interval**
|
|
||||||
count: int # Number of trades within interval
|
|
||||||
# (sampled) generated tick data
|
|
||||||
ticks: List[Any] = field(default_factory=list)
|
|
||||||
|
|
||||||
# XXX: ugh, super hideous.. needs built-in converters.
|
|
||||||
def __post_init__(self):
|
|
||||||
for f, val in self.__dataclass_fields__.items():
|
|
||||||
if f == 'ticks':
|
|
||||||
continue
|
|
||||||
setattr(self, f, val.type(getattr(self, f)))
|
|
||||||
|
|
||||||
|
|
||||||
async def recv_msg(recv):
|
async def recv_msg(recv):
|
||||||
too_slow_count = last_hb = 0
|
too_slow_count = last_hb = 0
|
||||||
|
|
||||||
|
@ -317,8 +351,12 @@ async def stream_quotes(
|
||||||
|
|
||||||
# keep client cached for real-time section
|
# keep client cached for real-time section
|
||||||
for sym in symbols:
|
for sym in symbols:
|
||||||
si = sym_infos[sym] = await client.symbol_info(sym)
|
si = Pair(**await client.symbol_info(sym)) # validation
|
||||||
ws_pairs[sym] = si['wsname']
|
syminfo = si.dict()
|
||||||
|
syminfo['price_tick_size'] = 1/10**si.pair_decimals
|
||||||
|
syminfo['lot_tick_size'] = 1/10**si.lot_decimals
|
||||||
|
sym_infos[sym] = syminfo
|
||||||
|
ws_pairs[sym] = si.wsname
|
||||||
|
|
||||||
# maybe load historical ohlcv in to shared mem
|
# maybe load historical ohlcv in to shared mem
|
||||||
# check if shm has already been created by previous
|
# check if shm has already been created by previous
|
||||||
|
@ -349,9 +387,9 @@ async def stream_quotes(
|
||||||
symbol: {
|
symbol: {
|
||||||
'is_shm_writer': not writer_exists,
|
'is_shm_writer': not writer_exists,
|
||||||
'shm_token': shm_token,
|
'shm_token': shm_token,
|
||||||
'symbol_info': sym_infos[symbol],
|
'symbol_info': sym_infos[sym],
|
||||||
}
|
}
|
||||||
for sym in symbols
|
# for sym in symbols
|
||||||
}
|
}
|
||||||
yield init_msgs
|
yield init_msgs
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue