Drop `Symbol` / `.symbol` support from `.accounting`
Only stuff left was the allocator stuff. Drop the top level subpkg exports and finally kill off the awkwardly named `Symbol.lot_size_digits` properties XD Expose a bunch more util funcs at subpkg top level, do some typing in allocator method internals.master
parent
738d0ca38b
commit
35f0520cb0
|
@ -38,23 +38,33 @@ from ._mktinfo import (
|
||||||
dec_digits,
|
dec_digits,
|
||||||
digits_to_dec,
|
digits_to_dec,
|
||||||
MktPair,
|
MktPair,
|
||||||
|
Symbol,
|
||||||
unpack_fqme,
|
unpack_fqme,
|
||||||
)
|
)
|
||||||
|
from ._allocate import (
|
||||||
|
mk_allocator,
|
||||||
|
Allocator,
|
||||||
|
)
|
||||||
|
|
||||||
log = get_logger(__name__)
|
log = get_logger(__name__)
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
'Allocator',
|
||||||
'Asset',
|
'Asset',
|
||||||
'dec_digits',
|
|
||||||
'digits_to_dec',
|
|
||||||
'MktPair',
|
'MktPair',
|
||||||
'Position',
|
'Position',
|
||||||
'PpTable',
|
'PpTable',
|
||||||
|
'Symbol',
|
||||||
'Transaction',
|
'Transaction',
|
||||||
'TransactionLedger',
|
'TransactionLedger',
|
||||||
|
'dec_digits',
|
||||||
|
'digits_to_dec',
|
||||||
|
'iter_by_dt',
|
||||||
'load_pps_from_ledger',
|
'load_pps_from_ledger',
|
||||||
|
'mk_allocator',
|
||||||
'open_pps',
|
'open_pps',
|
||||||
'open_trade_ledger',
|
'open_trade_ledger',
|
||||||
|
'unpack_fqme',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ from typing import Optional
|
||||||
from bidict import bidict
|
from bidict import bidict
|
||||||
|
|
||||||
from ._pos import Position
|
from ._pos import Position
|
||||||
from ._mktinfo import Symbol
|
from . import MktPair
|
||||||
from ..data.types import Struct
|
from ..data.types import Struct
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ SizeUnit = Enum(
|
||||||
|
|
||||||
class Allocator(Struct):
|
class Allocator(Struct):
|
||||||
|
|
||||||
symbol: Symbol
|
mkt: MktPair
|
||||||
|
|
||||||
# TODO: if we ever want ot support non-uniform entry-slot-proportion
|
# TODO: if we ever want ot support non-uniform entry-slot-proportion
|
||||||
# "sizes"
|
# "sizes"
|
||||||
|
@ -114,8 +114,8 @@ class Allocator(Struct):
|
||||||
depending on position / order entry config.
|
depending on position / order entry config.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
sym = self.symbol
|
mkt: MktPair = self.mkt
|
||||||
ld = sym.lot_size_digits
|
ld: int = mkt.size_tick_digits
|
||||||
|
|
||||||
size_unit = self.size_unit
|
size_unit = self.size_unit
|
||||||
live_size = live_pp.size
|
live_size = live_pp.size
|
||||||
|
@ -125,13 +125,13 @@ class Allocator(Struct):
|
||||||
u_per_slot, currency_per_slot = self.step_sizes()
|
u_per_slot, currency_per_slot = self.step_sizes()
|
||||||
|
|
||||||
if size_unit == 'units':
|
if size_unit == 'units':
|
||||||
slot_size = u_per_slot
|
slot_size: float = u_per_slot
|
||||||
l_sub_pp = self.units_limit - abs_live_size
|
l_sub_pp: float = self.units_limit - abs_live_size
|
||||||
|
|
||||||
elif size_unit == 'currency':
|
elif size_unit == 'currency':
|
||||||
live_cost_basis = abs_live_size * live_pp.ppu
|
live_cost_basis: float = abs_live_size * live_pp.ppu
|
||||||
slot_size = currency_per_slot / price
|
slot_size: float = currency_per_slot / price
|
||||||
l_sub_pp = (self.currency_limit - live_cost_basis) / price
|
l_sub_pp: float = (self.currency_limit - live_cost_basis) / price
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
|
@ -141,8 +141,14 @@ class Allocator(Struct):
|
||||||
# an entry (adding-to or starting a pp)
|
# an entry (adding-to or starting a pp)
|
||||||
if (
|
if (
|
||||||
live_size == 0
|
live_size == 0
|
||||||
or (action == 'buy' and live_size > 0)
|
or (
|
||||||
or action == 'sell' and live_size < 0
|
action == 'buy'
|
||||||
|
and live_size > 0
|
||||||
|
)
|
||||||
|
or (
|
||||||
|
action == 'sell'
|
||||||
|
and live_size < 0
|
||||||
|
)
|
||||||
):
|
):
|
||||||
order_size = min(
|
order_size = min(
|
||||||
slot_size,
|
slot_size,
|
||||||
|
@ -178,7 +184,7 @@ class Allocator(Struct):
|
||||||
order_size = max(slotted_pp, slot_size)
|
order_size = max(slotted_pp, slot_size)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
abs_live_size < slot_size or
|
abs_live_size < slot_size
|
||||||
|
|
||||||
# NOTE: front/back "loading" heurstic:
|
# NOTE: front/back "loading" heurstic:
|
||||||
# if the remaining pp is in between 0-1.5x a slot's
|
# if the remaining pp is in between 0-1.5x a slot's
|
||||||
|
@ -187,14 +193,17 @@ class Allocator(Struct):
|
||||||
# **without** going past a net-zero pp. if the pp is
|
# **without** going past a net-zero pp. if the pp is
|
||||||
# > 1.5x a slot size, then front load: exit a slot's and
|
# > 1.5x a slot size, then front load: exit a slot's and
|
||||||
# expect net-zero to be acquired on the final exit.
|
# expect net-zero to be acquired on the final exit.
|
||||||
slot_size < pp_size < round((1.5*slot_size), ndigits=ld) or
|
or slot_size < pp_size < round((1.5*slot_size), ndigits=ld)
|
||||||
|
or (
|
||||||
|
|
||||||
# underlying requires discrete (int) units (eg. stocks)
|
# underlying requires discrete (int) units (eg. stocks)
|
||||||
# and thus our slot size (based on our limit) would
|
# and thus our slot size (based on our limit) would
|
||||||
# exit a fractional unit's worth so, presuming we aren't
|
# exit a fractional unit's worth so, presuming we aren't
|
||||||
# supporting a fractional-units-style broker, we need
|
# supporting a fractional-units-style broker, we need
|
||||||
# exit the final unit.
|
# exit the final unit.
|
||||||
ld == 0 and abs_live_size == 1
|
ld == 0
|
||||||
|
and abs_live_size == 1
|
||||||
|
)
|
||||||
):
|
):
|
||||||
order_size = abs_live_size
|
order_size = abs_live_size
|
||||||
|
|
||||||
|
@ -203,13 +212,14 @@ class Allocator(Struct):
|
||||||
# compute a fractional slots size to display
|
# compute a fractional slots size to display
|
||||||
slots_used = self.slots_used(
|
slots_used = self.slots_used(
|
||||||
Position(
|
Position(
|
||||||
mkt=sym,
|
mkt=mkt,
|
||||||
size=order_size,
|
size=order_size,
|
||||||
ppu=price,
|
ppu=price,
|
||||||
bs_mktid=sym,
|
bs_mktid=mkt.bs_mktid,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# TODO: render an actual ``Executable`` type here?
|
||||||
return {
|
return {
|
||||||
'size': abs(round(order_size, ndigits=ld)),
|
'size': abs(round(order_size, ndigits=ld)),
|
||||||
'size_digits': ld,
|
'size_digits': ld,
|
||||||
|
@ -249,7 +259,7 @@ class Allocator(Struct):
|
||||||
|
|
||||||
def mk_allocator(
|
def mk_allocator(
|
||||||
|
|
||||||
symbol: Symbol,
|
mkt: MktPair,
|
||||||
startup_pp: Position,
|
startup_pp: Position,
|
||||||
|
|
||||||
# default allocation settings
|
# default allocation settings
|
||||||
|
@ -276,6 +286,6 @@ def mk_allocator(
|
||||||
defaults.update(user_def)
|
defaults.update(user_def)
|
||||||
|
|
||||||
return Allocator(
|
return Allocator(
|
||||||
symbol=symbol,
|
mkt=mkt,
|
||||||
**defaults,
|
**defaults,
|
||||||
)
|
)
|
||||||
|
|
|
@ -22,9 +22,9 @@ from __future__ import annotations
|
||||||
from collections import UserDict
|
from collections import UserDict
|
||||||
from contextlib import contextmanager as cm
|
from contextlib import contextmanager as cm
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import time
|
|
||||||
from typing import (
|
from typing import (
|
||||||
Any,
|
Any,
|
||||||
|
Callable,
|
||||||
Iterator,
|
Iterator,
|
||||||
Union,
|
Union,
|
||||||
Generator
|
Generator
|
||||||
|
@ -158,7 +158,7 @@ class TransactionLedger(UserDict):
|
||||||
for tid, txdict in self.data.items():
|
for tid, txdict in self.data.items():
|
||||||
# special field handling for datetimes
|
# special field handling for datetimes
|
||||||
# to ensure pendulum is used!
|
# to ensure pendulum is used!
|
||||||
fqme = txdict.get('fqme', txdict['fqsn'])
|
fqme = txdict.get('fqme') or txdict['fqsn']
|
||||||
dt = parse(txdict['dt'])
|
dt = parse(txdict['dt'])
|
||||||
expiry = txdict.get('expiry')
|
expiry = txdict.get('expiry')
|
||||||
|
|
||||||
|
@ -242,8 +242,6 @@ def iter_by_dt(
|
||||||
datetime presumably set at the ``'dt'`` field in each entry.
|
datetime presumably set at the ``'dt'`` field in each entry.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
txs = records.items()
|
|
||||||
|
|
||||||
def dyn_parse_to_dt(
|
def dyn_parse_to_dt(
|
||||||
pair: tuple[str, dict],
|
pair: tuple[str, dict],
|
||||||
) -> DateTime:
|
) -> DateTime:
|
||||||
|
|
|
@ -519,11 +519,11 @@ class MktPair(Struct, frozen=True):
|
||||||
return self._atype
|
return self._atype
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def tick_size_digits(self) -> int:
|
def price_tick_digits(self) -> int:
|
||||||
return float_digits(self.price_tick)
|
return float_digits(self.price_tick)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def lot_size_digits(self) -> int:
|
def size_tick_digits(self) -> int:
|
||||||
return float_digits(self.size_tick)
|
return float_digits(self.size_tick)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,6 @@ from ._ledger import (
|
||||||
open_trade_ledger,
|
open_trade_ledger,
|
||||||
)
|
)
|
||||||
from ._mktinfo import (
|
from ._mktinfo import (
|
||||||
Symbol,
|
|
||||||
MktPair,
|
MktPair,
|
||||||
Asset,
|
Asset,
|
||||||
unpack_fqme,
|
unpack_fqme,
|
||||||
|
@ -247,11 +246,8 @@ class Position(Struct):
|
||||||
|
|
||||||
# XXX: better place to do this?
|
# XXX: better place to do this?
|
||||||
mkt = self.mkt
|
mkt = self.mkt
|
||||||
|
size_tick_digits = mkt.size_tick_digits
|
||||||
# TODO: switch to new fields..?
|
price_tick_digits = mkt.price_tick_digits
|
||||||
# .size_tick_digits, .price_tick_digits
|
|
||||||
size_tick_digits = mkt.lot_size_digits
|
|
||||||
price_tick_digits = mkt.tick_size_digits
|
|
||||||
|
|
||||||
self.ppu = round(
|
self.ppu = round(
|
||||||
# TODO: change this to ppu?
|
# TODO: change this to ppu?
|
||||||
|
|
Loading…
Reference in New Issue