Switch `Client.mkt_mode` to 'usd_futes' if 'perp' in fqme

The beginning of supporting multi-markets through a common API client.
Change to futes market mode in the client if `.perp.` is matched in the
fqme. Currently the exchange info and live feed ws impl will swap out
for their usd-margin futures market equivalent (endpoints).
basic_buy_bot
Tyler Goodlet 2023-06-12 21:58:46 -04:00
parent dc23f1c9bd
commit e68c55e9bd
3 changed files with 45 additions and 30 deletions

View File

@ -30,7 +30,6 @@ from datetime import datetime
from typing import ( from typing import (
Any, Any,
Callable, Callable,
Literal,
) )
import hmac import hmac
import hashlib import hashlib
@ -53,8 +52,9 @@ from piker.brokers._util import (
get_logger, get_logger,
) )
from .schemas import ( from .schemas import (
SpotPair, PAIRTYPES,
FutesPair, Pair,
MarketType,
) )
log = get_logger('piker.brokers.binance') log = get_logger('piker.brokers.binance')
@ -150,14 +150,6 @@ def binance_timestamp(
return int((when.timestamp() * 1000) + (when.microsecond / 1000)) return int((when.timestamp() * 1000) + (when.microsecond / 1000))
MarketType: Literal[
'spot',
'margin',
'usd_futes',
'coin_futes',
]
class Client: class Client:
''' '''
Async ReST API client using ``trio`` + ``asks`` B) Async ReST API client using ``trio`` + ``asks`` B)
@ -319,7 +311,7 @@ class Client:
self, self,
sym: str | None = None, sym: str | None = None,
mkt_type: MarketType = 'spot', mkt_type: MarketType | None = None,
) -> dict[str, Pair] | Pair: ) -> dict[str, Pair] | Pair:
''' '''
@ -334,7 +326,10 @@ class Client:
https://binance-docs.github.io/apidocs/delivery/en/#exchange-information https://binance-docs.github.io/apidocs/delivery/en/#exchange-information
''' '''
cached_pair = self._pairs.get(sym) mkt_type: MarketType = mkt_type or self.mkt_mode
cached_pair = self._pairs.get(
(sym, mkt_type)
)
if cached_pair: if cached_pair:
return cached_pair return cached_pair
@ -344,16 +339,15 @@ class Client:
sym = sym.lower() sym = sym.lower()
params = {'symbol': sym} params = {'symbol': sym}
resp = await self.mkt_req[self.mkt_mode]('exchangeInfo', params=params) resp = await self.mkt_req[mkt_type]('exchangeInfo', params=params)
entries = resp['symbols'] entries = resp['symbols']
if not entries: if not entries:
raise SymbolNotFound(f'{sym} not found:\n{resp}') raise SymbolNotFound(f'{sym} not found:\n{resp}')
# import tractor # import tractor
# await tractor.breakpoint() # await tractor.breakpoint()
pairs = {} pairs: dict[str, Pair] = {}
for item in entries: for item in entries:
symbol = item['symbol']
# for spot mkts, pre-process .filters field into # for spot mkts, pre-process .filters field into
# a table.. # a table..
@ -364,17 +358,14 @@ class Client:
ftype = entry['filterType'] ftype = entry['filterType']
filters[ftype] = entry filters[ftype] = entry
# TODO: lookup pair schema by mkt type item['filters'] = filters
# pair_type = mkt_type
# pairs[symbol] = SpotPair( symbol = item['symbol']
# filters=filters, pair_type: Pair = PAIRTYPES[mkt_type or self.mkt_mode]
# ) pairs[(symbol, mkt_type)] = pair_type(
pairs[symbol] = FutesPair(**item) **item,
)
# pairs = {
# item['symbol']: Pair(**item) for item in entries
# }
self._pairs.update(pairs) self._pairs.update(pairs)
if sym is not None: if sym is not None:
@ -633,8 +624,12 @@ class Client:
@acm @acm
async def get_client() -> Client: async def get_client(
client = Client(mkt_mode='usd_futes') mkt_mode: str = 'spot',
log.info('Caching exchange infos..') ) -> Client:
client = Client(mkt_mode=mkt_mode)
log.info(f'{client} in {mkt_mode} mode: caching exchange infos..')
await client.exch_info() await client.exch_info()
yield client yield client

View File

@ -104,6 +104,7 @@ async def trades_dialogue(
) -> AsyncIterator[dict[str, Any]]: ) -> AsyncIterator[dict[str, Any]]:
async with open_cached_client('binance') as client: async with open_cached_client('binance') as client:
await tractor.breakpoint()
if not client.api_key: if not client.api_key:
await ctx.started('paper') await ctx.started('paper')
return return

View File

@ -50,6 +50,7 @@ from piker._cacheables import (
from piker.accounting._mktinfo import ( from piker.accounting._mktinfo import (
Asset, Asset,
MktPair, MktPair,
unpack_fqme,
digits_to_dec, digits_to_dec,
) )
from piker.data.types import Struct from piker.data.types import Struct
@ -263,9 +264,27 @@ async def get_mkt_info(
) -> tuple[MktPair, Pair]: ) -> tuple[MktPair, Pair]:
async with open_cached_client('binance') as client: # uppercase since kraken bs_mktid is always upper
if 'binance' not in fqme:
fqme += '.binance'
pair: Pair = await client.exch_info(fqme.upper()) bs_fqme, _, broker = fqme.rpartition('.')
broker, mkt_ep, venue, suffix = unpack_fqme(fqme)
# bs_fqme, _, broker = fqme.partition('.')
mkt_mode: str = 'spot'
if 'perp' in bs_fqme:
mkt_mode = 'usd_futes'
async with open_cached_client(
'binance',
mkt_mode=mkt_mode,
) as client:
pair_str: str = mkt_ep.upper()
pair: Pair = await client.exch_info(pair_str)
await tractor.breakpoint()
mkt = MktPair( mkt = MktPair(
dst=Asset( dst=Asset(
name=pair.baseAsset, name=pair.baseAsset,