.kraken: start new `.symbols` submod and move symcache and search stuff there
parent
82fd785646
commit
912f1bc635
|
@ -19,23 +19,26 @@ Kraken backend.
|
||||||
|
|
||||||
Sub-modules within break into the core functionalities:
|
Sub-modules within break into the core functionalities:
|
||||||
|
|
||||||
- ``broker.py`` part for orders / trading endpoints
|
- .api: for the core API machinery which generally
|
||||||
- ``feed.py`` for real-time data feed endpoints
|
a ``asks``/``trio-websocket`` implemented ``Client``.
|
||||||
- ``api.py`` for the core API machinery which is ``trio``-ized
|
- .broker: part for orders / trading endpoints.
|
||||||
wrapping around ``ib_insync``.
|
- .feed: for real-time and historical data query endpoints.
|
||||||
|
- .ledger: for transaction processing as it pertains to accounting.
|
||||||
|
- .symbols: for market (name) search and symbology meta-defs.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
from .symbols import Pair # for symcache
|
from .symbols import (
|
||||||
|
Pair, # for symcache
|
||||||
|
open_symbol_search,
|
||||||
|
# required by `.accounting`, `.data`
|
||||||
|
get_mkt_info,
|
||||||
|
)
|
||||||
# required by `.brokers`
|
# required by `.brokers`
|
||||||
from .api import (
|
from .api import (
|
||||||
get_client,
|
get_client,
|
||||||
)
|
)
|
||||||
from .feed import (
|
from .feed import (
|
||||||
# required by `.accounting`, `.data`
|
|
||||||
get_mkt_info,
|
|
||||||
|
|
||||||
# required by `.data`
|
# required by `.data`
|
||||||
open_symbol_search,
|
|
||||||
stream_quotes,
|
stream_quotes,
|
||||||
open_history_client,
|
open_history_client,
|
||||||
)
|
)
|
||||||
|
@ -66,6 +69,7 @@ __all__ = [
|
||||||
# tractor RPC enable arg
|
# tractor RPC enable arg
|
||||||
__enable_modules__: list[str] = [
|
__enable_modules__: list[str] = [
|
||||||
'api',
|
'api',
|
||||||
'feed',
|
|
||||||
'broker',
|
'broker',
|
||||||
|
'feed',
|
||||||
|
'symbols',
|
||||||
]
|
]
|
||||||
|
|
|
@ -30,24 +30,16 @@ from typing import (
|
||||||
)
|
)
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from fuzzywuzzy import process as fuzzy
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import pendulum
|
import pendulum
|
||||||
from trio_typing import TaskStatus
|
from trio_typing import TaskStatus
|
||||||
import tractor
|
|
||||||
import trio
|
import trio
|
||||||
|
|
||||||
from piker.accounting._mktinfo import (
|
from piker.accounting._mktinfo import (
|
||||||
Asset,
|
|
||||||
MktPair,
|
MktPair,
|
||||||
unpack_fqme,
|
|
||||||
)
|
)
|
||||||
from piker.brokers import (
|
from piker.brokers import (
|
||||||
open_cached_client,
|
open_cached_client,
|
||||||
SymbolNotFound,
|
|
||||||
)
|
|
||||||
from piker._cacheables import (
|
|
||||||
async_lifo_cache,
|
|
||||||
)
|
)
|
||||||
from piker.brokers._util import (
|
from piker.brokers._util import (
|
||||||
BrokerError,
|
BrokerError,
|
||||||
|
@ -59,9 +51,8 @@ from piker.data.validate import FeedInit
|
||||||
from piker.data._web_bs import open_autorecon_ws, NoBsWs
|
from piker.data._web_bs import open_autorecon_ws, NoBsWs
|
||||||
from .api import (
|
from .api import (
|
||||||
log,
|
log,
|
||||||
Client,
|
|
||||||
Pair,
|
|
||||||
)
|
)
|
||||||
|
from .symbols import get_mkt_info
|
||||||
|
|
||||||
|
|
||||||
class OHLC(Struct, frozen=True):
|
class OHLC(Struct, frozen=True):
|
||||||
|
@ -267,70 +258,6 @@ async def open_history_client(
|
||||||
yield get_ohlc, {'erlangs': 1, 'rate': 1}
|
yield get_ohlc, {'erlangs': 1, 'rate': 1}
|
||||||
|
|
||||||
|
|
||||||
@async_lifo_cache()
|
|
||||||
async def get_mkt_info(
|
|
||||||
fqme: str,
|
|
||||||
|
|
||||||
) -> tuple[MktPair, Pair]:
|
|
||||||
'''
|
|
||||||
Query for and return a `MktPair` and backend-native `Pair` (or
|
|
||||||
wtv else) info.
|
|
||||||
|
|
||||||
If more then one fqme is provided return a ``dict`` of native
|
|
||||||
key-strs to `MktPair`s.
|
|
||||||
|
|
||||||
'''
|
|
||||||
venue: str = 'spot'
|
|
||||||
expiry: str = ''
|
|
||||||
if '.kraken' not in fqme:
|
|
||||||
fqme += '.kraken'
|
|
||||||
|
|
||||||
broker, pair, venue, expiry = unpack_fqme(fqme)
|
|
||||||
venue: str = venue or 'spot'
|
|
||||||
|
|
||||||
if venue.lower() != 'spot':
|
|
||||||
raise SymbolNotFound(
|
|
||||||
'kraken only supports spot markets right now!\n'
|
|
||||||
f'{fqme}\n'
|
|
||||||
)
|
|
||||||
|
|
||||||
async with open_cached_client('kraken') as client:
|
|
||||||
|
|
||||||
# uppercase since kraken bs_mktid is always upper
|
|
||||||
# bs_fqme, _, broker = fqme.partition('.')
|
|
||||||
# pair_str: str = bs_fqme.upper()
|
|
||||||
pair_str: str = f'{pair}.{venue}'
|
|
||||||
|
|
||||||
pair: Pair | None = client._pairs.get(pair_str.upper())
|
|
||||||
if not pair:
|
|
||||||
bs_fqme: str = Client.to_bs_fqme(pair_str)
|
|
||||||
pair: Pair = client._pairs[bs_fqme]
|
|
||||||
|
|
||||||
if not (assets := client._assets):
|
|
||||||
assets: dict[str, Asset] = await client.get_assets()
|
|
||||||
|
|
||||||
dst_asset: Asset = assets[pair.bs_dst_asset]
|
|
||||||
src_asset: Asset = assets[pair.bs_src_asset]
|
|
||||||
|
|
||||||
mkt = MktPair(
|
|
||||||
dst=dst_asset,
|
|
||||||
src=src_asset,
|
|
||||||
|
|
||||||
price_tick=pair.price_tick,
|
|
||||||
size_tick=pair.size_tick,
|
|
||||||
bs_mktid=pair.bs_mktid,
|
|
||||||
|
|
||||||
expiry=expiry,
|
|
||||||
venue=venue or 'spot',
|
|
||||||
|
|
||||||
# TODO: futes
|
|
||||||
# _atype=_atype,
|
|
||||||
|
|
||||||
broker='kraken',
|
|
||||||
)
|
|
||||||
return mkt, pair
|
|
||||||
|
|
||||||
|
|
||||||
async def stream_quotes(
|
async def stream_quotes(
|
||||||
|
|
||||||
send_chan: trio.abc.SendChannel,
|
send_chan: trio.abc.SendChannel,
|
||||||
|
@ -486,30 +413,3 @@ async def stream_quotes(
|
||||||
log.warning(f'Unknown WSS message: {typ}, {quote}')
|
log.warning(f'Unknown WSS message: {typ}, {quote}')
|
||||||
|
|
||||||
await send_chan.send({topic: quote})
|
await send_chan.send({topic: quote})
|
||||||
|
|
||||||
|
|
||||||
@tractor.context
|
|
||||||
async def open_symbol_search(
|
|
||||||
ctx: tractor.Context,
|
|
||||||
|
|
||||||
) -> Client:
|
|
||||||
async with open_cached_client('kraken') as client:
|
|
||||||
|
|
||||||
# load all symbols locally for fast search
|
|
||||||
cache = await client.get_mkt_pairs()
|
|
||||||
await ctx.started(cache)
|
|
||||||
|
|
||||||
async with ctx.open_stream() as stream:
|
|
||||||
|
|
||||||
async for pattern in stream:
|
|
||||||
|
|
||||||
matches = fuzzy.extractBests(
|
|
||||||
pattern,
|
|
||||||
client._pairs,
|
|
||||||
score_cutoff=50,
|
|
||||||
)
|
|
||||||
# repack in dict form
|
|
||||||
await stream.send({
|
|
||||||
pair[0].altname: pair[0]
|
|
||||||
for pair in matches
|
|
||||||
})
|
|
||||||
|
|
|
@ -15,15 +15,30 @@
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Symbology defs and deats!
|
Symbology defs and search.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
|
import tractor
|
||||||
|
from fuzzywuzzy import process as fuzzy
|
||||||
|
|
||||||
|
from piker._cacheables import (
|
||||||
|
async_lifo_cache,
|
||||||
|
)
|
||||||
from piker.accounting._mktinfo import (
|
from piker.accounting._mktinfo import (
|
||||||
digits_to_dec,
|
digits_to_dec,
|
||||||
)
|
)
|
||||||
|
from piker.brokers import (
|
||||||
|
open_cached_client,
|
||||||
|
SymbolNotFound,
|
||||||
|
)
|
||||||
from piker.data.types import Struct
|
from piker.data.types import Struct
|
||||||
|
from piker.accounting._mktinfo import (
|
||||||
|
Asset,
|
||||||
|
MktPair,
|
||||||
|
unpack_fqme,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# https://www.kraken.com/features/api#get-tradable-pairs
|
# https://www.kraken.com/features/api#get-tradable-pairs
|
||||||
|
@ -112,3 +127,89 @@ class Pair(Struct):
|
||||||
return f'{dst}{src}.SPOT'
|
return f'{dst}{src}.SPOT'
|
||||||
|
|
||||||
|
|
||||||
|
@tractor.context
|
||||||
|
async def open_symbol_search(ctx: tractor.Context) -> None:
|
||||||
|
async with open_cached_client('kraken') as client:
|
||||||
|
|
||||||
|
# load all symbols locally for fast search
|
||||||
|
cache = await client.get_mkt_pairs()
|
||||||
|
await ctx.started(cache)
|
||||||
|
|
||||||
|
async with ctx.open_stream() as stream:
|
||||||
|
|
||||||
|
async for pattern in stream:
|
||||||
|
|
||||||
|
matches = fuzzy.extractBests(
|
||||||
|
pattern,
|
||||||
|
client._pairs,
|
||||||
|
score_cutoff=50,
|
||||||
|
)
|
||||||
|
# repack in dict form
|
||||||
|
await stream.send({
|
||||||
|
pair[0].altname: pair[0]
|
||||||
|
for pair in matches
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@async_lifo_cache()
|
||||||
|
async def get_mkt_info(
|
||||||
|
fqme: str,
|
||||||
|
|
||||||
|
) -> tuple[MktPair, Pair]:
|
||||||
|
'''
|
||||||
|
Query for and return a `MktPair` and backend-native `Pair` (or
|
||||||
|
wtv else) info.
|
||||||
|
|
||||||
|
If more then one fqme is provided return a ``dict`` of native
|
||||||
|
key-strs to `MktPair`s.
|
||||||
|
|
||||||
|
'''
|
||||||
|
venue: str = 'spot'
|
||||||
|
expiry: str = ''
|
||||||
|
if '.kraken' not in fqme:
|
||||||
|
fqme += '.kraken'
|
||||||
|
|
||||||
|
broker, pair, venue, expiry = unpack_fqme(fqme)
|
||||||
|
venue: str = venue or 'spot'
|
||||||
|
|
||||||
|
if venue.lower() != 'spot':
|
||||||
|
raise SymbolNotFound(
|
||||||
|
'kraken only supports spot markets right now!\n'
|
||||||
|
f'{fqme}\n'
|
||||||
|
)
|
||||||
|
|
||||||
|
async with open_cached_client('kraken') as client:
|
||||||
|
|
||||||
|
# uppercase since kraken bs_mktid is always upper
|
||||||
|
# bs_fqme, _, broker = fqme.partition('.')
|
||||||
|
# pair_str: str = bs_fqme.upper()
|
||||||
|
pair_str: str = f'{pair}.{venue}'
|
||||||
|
|
||||||
|
pair: Pair | None = client._pairs.get(pair_str.upper())
|
||||||
|
if not pair:
|
||||||
|
bs_fqme: str = client.to_bs_fqme(pair_str)
|
||||||
|
pair: Pair = client._pairs[bs_fqme]
|
||||||
|
|
||||||
|
if not (assets := client._assets):
|
||||||
|
assets: dict[str, Asset] = await client.get_assets()
|
||||||
|
|
||||||
|
dst_asset: Asset = assets[pair.bs_dst_asset]
|
||||||
|
src_asset: Asset = assets[pair.bs_src_asset]
|
||||||
|
|
||||||
|
mkt = MktPair(
|
||||||
|
dst=dst_asset,
|
||||||
|
src=src_asset,
|
||||||
|
|
||||||
|
price_tick=pair.price_tick,
|
||||||
|
size_tick=pair.size_tick,
|
||||||
|
bs_mktid=pair.bs_mktid,
|
||||||
|
|
||||||
|
expiry=expiry,
|
||||||
|
venue=venue or 'spot',
|
||||||
|
|
||||||
|
# TODO: futes
|
||||||
|
# _atype=_atype,
|
||||||
|
|
||||||
|
broker='kraken',
|
||||||
|
)
|
||||||
|
return mkt, pair
|
||||||
|
|
Loading…
Reference in New Issue