Compare commits
1 Commits
577da2e8e3
...
81693cc2f7
| Author | SHA1 | Date |
|---|---|---|
|
|
81693cc2f7 |
|
|
@ -42,6 +42,7 @@ from ._mktinfo import (
|
||||||
dec_digits,
|
dec_digits,
|
||||||
digits_to_dec,
|
digits_to_dec,
|
||||||
MktPair,
|
MktPair,
|
||||||
|
Symbol,
|
||||||
unpack_fqme,
|
unpack_fqme,
|
||||||
_derivs as DerivTypes,
|
_derivs as DerivTypes,
|
||||||
)
|
)
|
||||||
|
|
@ -59,6 +60,7 @@ __all__ = [
|
||||||
'Asset',
|
'Asset',
|
||||||
'MktPair',
|
'MktPair',
|
||||||
'Position',
|
'Position',
|
||||||
|
'Symbol',
|
||||||
'Transaction',
|
'Transaction',
|
||||||
'TransactionLedger',
|
'TransactionLedger',
|
||||||
'dec_digits',
|
'dec_digits',
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ import tomli_w # for fast ledger writing
|
||||||
|
|
||||||
from piker.types import Struct
|
from piker.types import Struct
|
||||||
from piker import config
|
from piker import config
|
||||||
from piker.log import get_logger
|
from ..log import get_logger
|
||||||
from .calc import (
|
from .calc import (
|
||||||
iter_by_dt,
|
iter_by_dt,
|
||||||
)
|
)
|
||||||
|
|
@ -239,9 +239,7 @@ class TransactionLedger(UserDict):
|
||||||
|
|
||||||
symcache: SymbologyCache = self._symcache
|
symcache: SymbologyCache = self._symcache
|
||||||
towrite: dict[str, Any] = {}
|
towrite: dict[str, Any] = {}
|
||||||
for tid, txdict in self.tx_sort(
|
for tid, txdict in self.tx_sort(self.data.copy()):
|
||||||
self.data.copy()
|
|
||||||
):
|
|
||||||
# write blank-str expiry for non-expiring assets
|
# write blank-str expiry for non-expiring assets
|
||||||
if (
|
if (
|
||||||
'expiry' in txdict
|
'expiry' in txdict
|
||||||
|
|
@ -379,7 +377,7 @@ def open_trade_ledger(
|
||||||
account,
|
account,
|
||||||
dirpath=_fp,
|
dirpath=_fp,
|
||||||
)
|
)
|
||||||
cpy: dict = ledger_dict.copy()
|
cpy = ledger_dict.copy()
|
||||||
|
|
||||||
# XXX NOTE: if not provided presume we are being called from
|
# XXX NOTE: if not provided presume we are being called from
|
||||||
# sync code and need to maybe run `trio` to generate..
|
# sync code and need to maybe run `trio` to generate..
|
||||||
|
|
@ -408,13 +406,7 @@ def open_trade_ledger(
|
||||||
account=account,
|
account=account,
|
||||||
mod=mod,
|
mod=mod,
|
||||||
symcache=symcache,
|
symcache=symcache,
|
||||||
|
tx_sort=getattr(mod, 'tx_sort', tx_sort),
|
||||||
# NOTE: allow backends to provide custom ledger sorting
|
|
||||||
tx_sort=getattr(
|
|
||||||
mod,
|
|
||||||
'tx_sort',
|
|
||||||
tx_sort,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
yield ledger
|
yield ledger
|
||||||
|
|
|
||||||
|
|
@ -305,8 +305,8 @@ class MktPair(Struct, frozen=True):
|
||||||
# config right?
|
# config right?
|
||||||
# src_type: AssetTypeName
|
# src_type: AssetTypeName
|
||||||
|
|
||||||
# for derivs, info describing contract, egs. strike price, call
|
# for derivs, info describing contract, egs.
|
||||||
# or put, swap type, exercise model, etc.
|
# strike price, call or put, swap type, exercise model, etc.
|
||||||
contract_info: list[str] | None = None
|
contract_info: list[str] | None = None
|
||||||
|
|
||||||
# TODO: rename to sectype since all of these can
|
# TODO: rename to sectype since all of these can
|
||||||
|
|
@ -390,8 +390,8 @@ class MktPair(Struct, frozen=True):
|
||||||
cls,
|
cls,
|
||||||
fqme: str,
|
fqme: str,
|
||||||
|
|
||||||
price_tick: float|str,
|
price_tick: float | str,
|
||||||
size_tick: float|str,
|
size_tick: float | str,
|
||||||
bs_mktid: str,
|
bs_mktid: str,
|
||||||
|
|
||||||
broker: str | None = None,
|
broker: str | None = None,
|
||||||
|
|
@ -677,3 +677,90 @@ def unpack_fqme(
|
||||||
# '.'.join([mkt_ep, venue]),
|
# '.'.join([mkt_ep, venue]),
|
||||||
suffix,
|
suffix,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Symbol(Struct):
|
||||||
|
'''
|
||||||
|
I guess this is some kinda container thing for dealing with
|
||||||
|
all the different meta-data formats from brokers?
|
||||||
|
|
||||||
|
'''
|
||||||
|
key: str
|
||||||
|
|
||||||
|
broker: str = ''
|
||||||
|
venue: str = ''
|
||||||
|
|
||||||
|
# precision descriptors for price and vlm
|
||||||
|
tick_size: Decimal = Decimal('0.01')
|
||||||
|
lot_tick_size: Decimal = Decimal('0.0')
|
||||||
|
|
||||||
|
suffix: str = ''
|
||||||
|
broker_info: dict[str, dict[str, Any]] = {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_fqme(
|
||||||
|
cls,
|
||||||
|
fqsn: str,
|
||||||
|
info: dict[str, Any],
|
||||||
|
|
||||||
|
) -> Symbol:
|
||||||
|
broker, mktep, venue, suffix = unpack_fqme(fqsn)
|
||||||
|
tick_size = info.get('price_tick_size', 0.01)
|
||||||
|
lot_size = info.get('lot_tick_size', 0.0)
|
||||||
|
|
||||||
|
return Symbol(
|
||||||
|
broker=broker,
|
||||||
|
key=mktep,
|
||||||
|
tick_size=tick_size,
|
||||||
|
lot_tick_size=lot_size,
|
||||||
|
venue=venue,
|
||||||
|
suffix=suffix,
|
||||||
|
broker_info={broker: info},
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def type_key(self) -> str:
|
||||||
|
return list(self.broker_info.values())[0]['asset_type']
|
||||||
|
|
||||||
|
@property
|
||||||
|
def tick_size_digits(self) -> int:
|
||||||
|
return float_digits(self.tick_size)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def lot_size_digits(self) -> int:
|
||||||
|
return float_digits(self.lot_tick_size)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def price_tick(self) -> Decimal:
|
||||||
|
return Decimal(str(self.tick_size))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def size_tick(self) -> Decimal:
|
||||||
|
return Decimal(str(self.lot_tick_size))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def broker(self) -> str:
|
||||||
|
return list(self.broker_info.keys())[0]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def fqme(self) -> str:
|
||||||
|
return maybe_cons_tokens([
|
||||||
|
self.key, # final "pair name" (eg. qqq[/usd], btcusdt)
|
||||||
|
self.venue,
|
||||||
|
self.suffix, # includes expiry and other con info
|
||||||
|
self.broker,
|
||||||
|
])
|
||||||
|
|
||||||
|
def quantize(
|
||||||
|
self,
|
||||||
|
size: float,
|
||||||
|
) -> Decimal:
|
||||||
|
digits = float_digits(self.lot_tick_size)
|
||||||
|
return Decimal(size).quantize(
|
||||||
|
Decimal(f'1.{"0".ljust(digits, "0")}'),
|
||||||
|
rounding=ROUND_HALF_EVEN
|
||||||
|
)
|
||||||
|
|
||||||
|
# NOTE: when cast to `str` return fqme
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return self.fqme
|
||||||
|
|
|
||||||
|
|
@ -251,16 +251,10 @@ def iter_by_dt(
|
||||||
for k in parsers:
|
for k in parsers:
|
||||||
if (
|
if (
|
||||||
isdict and k in tx
|
isdict and k in tx
|
||||||
or
|
or getattr(tx, k, None)
|
||||||
getattr(tx, k, None)
|
|
||||||
):
|
):
|
||||||
v = (
|
v = tx[k] if isdict else tx.dt
|
||||||
tx[k] if isdict
|
assert v is not None, f'No valid value for `{k}`!?'
|
||||||
else tx.dt
|
|
||||||
)
|
|
||||||
assert v is not None, (
|
|
||||||
f'No valid value for `{k}`!?'
|
|
||||||
)
|
|
||||||
|
|
||||||
# only call parser on the value if not None from
|
# only call parser on the value if not None from
|
||||||
# the `parsers` table above (when NOT using
|
# the `parsers` table above (when NOT using
|
||||||
|
|
@ -275,21 +269,8 @@ def iter_by_dt(
|
||||||
return v
|
return v
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# TODO: move to top?
|
# XXX: should never get here..
|
||||||
from piker.log import get_logger
|
breakpoint()
|
||||||
log = get_logger(__name__)
|
|
||||||
|
|
||||||
# XXX: we should really never get here..
|
|
||||||
# only if a ledger record has no expected sort(able)
|
|
||||||
# field will we likely hit this.. like with ze IB.
|
|
||||||
# if no sortable field just deliver epoch?
|
|
||||||
log.warning(
|
|
||||||
'No (time) sortable field for TXN:\n'
|
|
||||||
f'{tx}\n'
|
|
||||||
)
|
|
||||||
return from_timestamp(0)
|
|
||||||
# breakpoint()
|
|
||||||
|
|
||||||
|
|
||||||
entry: tuple[str, dict] | Transaction
|
entry: tuple[str, dict] | Transaction
|
||||||
for entry in sorted(
|
for entry in sorted(
|
||||||
|
|
|
||||||
|
|
@ -300,8 +300,7 @@ def disect(
|
||||||
assert not df.is_empty()
|
assert not df.is_empty()
|
||||||
|
|
||||||
# muck around in pdbp REPL
|
# muck around in pdbp REPL
|
||||||
# tractor.devx.mk_pdb().set_trace()
|
breakpoint()
|
||||||
# breakpoint()
|
|
||||||
|
|
||||||
# TODO: we REALLY need a better console REPL for this
|
# TODO: we REALLY need a better console REPL for this
|
||||||
# kinda thing..
|
# kinda thing..
|
||||||
|
|
|
||||||
|
|
@ -786,7 +786,6 @@ async def install_brokerd_search(
|
||||||
|
|
||||||
@acm
|
@acm
|
||||||
async def maybe_open_feed(
|
async def maybe_open_feed(
|
||||||
|
|
||||||
fqmes: list[str],
|
fqmes: list[str],
|
||||||
loglevel: str | None = None,
|
loglevel: str | None = None,
|
||||||
|
|
||||||
|
|
@ -840,13 +839,12 @@ async def maybe_open_feed(
|
||||||
|
|
||||||
@acm
|
@acm
|
||||||
async def open_feed(
|
async def open_feed(
|
||||||
|
|
||||||
fqmes: list[str],
|
fqmes: list[str],
|
||||||
|
|
||||||
loglevel: str | None = None,
|
loglevel: str|None = None,
|
||||||
allow_overruns: bool = True,
|
allow_overruns: bool = True,
|
||||||
start_stream: bool = True,
|
start_stream: bool = True,
|
||||||
tick_throttle: float | None = None, # Hz
|
tick_throttle: float|None = None, # Hz
|
||||||
|
|
||||||
allow_remote_ctl_ui: bool = False,
|
allow_remote_ctl_ui: bool = False,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,10 +36,10 @@ from ._sharedmem import (
|
||||||
ShmArray,
|
ShmArray,
|
||||||
_Token,
|
_Token,
|
||||||
)
|
)
|
||||||
|
from piker.accounting import MktPair
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ..accounting import MktPair
|
from piker.data.feed import Feed
|
||||||
from .feed import Feed
|
|
||||||
|
|
||||||
|
|
||||||
class Flume(Struct):
|
class Flume(Struct):
|
||||||
|
|
@ -82,7 +82,7 @@ class Flume(Struct):
|
||||||
|
|
||||||
# TODO: do we need this really if we can pull the `Portal` from
|
# TODO: do we need this really if we can pull the `Portal` from
|
||||||
# ``tractor``'s internals?
|
# ``tractor``'s internals?
|
||||||
feed: Feed | None = None
|
feed: Feed|None = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def rt_shm(self) -> ShmArray:
|
def rt_shm(self) -> ShmArray:
|
||||||
|
|
|
||||||
|
|
@ -113,9 +113,9 @@ def validate_backend(
|
||||||
)
|
)
|
||||||
if ep is None:
|
if ep is None:
|
||||||
log.warning(
|
log.warning(
|
||||||
f'Provider backend {mod.name} is missing '
|
f'Provider backend {mod.name!r} is missing '
|
||||||
f'{daemon_name} support :(\n'
|
f'{daemon_name!r} support?\n'
|
||||||
f'The following endpoint is missing: {name}'
|
f'|_module endpoint-func missing: {name!r}\n'
|
||||||
)
|
)
|
||||||
|
|
||||||
inits: list[
|
inits: list[
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue