Better doc strings and detailed comments
parent
ce1eb11b59
commit
de77c7d209
|
@ -312,9 +312,14 @@ async def trades_dialogue(
|
|||
accounts.add(account)
|
||||
|
||||
pp_msgs = {}
|
||||
|
||||
# process pp value reported from ib's system. we only use these
|
||||
# to cross-check sizing since average pricing on their end uses
|
||||
# the so called (bs) "FIFO" style which more or less results in
|
||||
# a price that's not useful for traders who want to not lose
|
||||
# money.. xb
|
||||
for client in aioclients.values():
|
||||
for pos in client.positions():
|
||||
|
||||
msg = pack_position(pos)
|
||||
msg.account = accounts_def.inverse[msg.account]
|
||||
pp_msgs[msg.symbol] = msg
|
||||
|
@ -322,8 +327,14 @@ async def trades_dialogue(
|
|||
assert msg.account in accounts, (
|
||||
f'Position for unknown account: {msg.account}')
|
||||
|
||||
# built-out piker pps from trade ledger, underneath using
|
||||
# LIFO style breakeven pricing calcs.
|
||||
trades_by_account: dict = {}
|
||||
conf = get_config()
|
||||
|
||||
# retreive new trade executions from the last session
|
||||
# and/or day's worth of trading and convert into trade
|
||||
# records suitable for a local ledger file.
|
||||
for proxy in proxies.values():
|
||||
trade_entries = await proxy.trades()
|
||||
records = trades_to_records(
|
||||
|
@ -332,18 +343,27 @@ async def trades_dialogue(
|
|||
)
|
||||
trades_by_account.update(records)
|
||||
|
||||
# write recent session's trades to the user's (local) ledger
|
||||
# file.
|
||||
for acctid, trades_by_id in trades_by_account.items():
|
||||
with config.open_trade_ledger('ib', acctid) as ledger:
|
||||
ledger.update(trades_by_id)
|
||||
|
||||
# (incrementally) update the user's pps in mem and
|
||||
# in the `pps.toml`.
|
||||
records = norm_trade_records(trades_by_id)
|
||||
active = update_pps_conf('ib', acctid, records)
|
||||
|
||||
# relay re-formatted pps as msgs to the ems.
|
||||
for fqsn, pp in active.items():
|
||||
|
||||
ibppmsg = pp_msgs[fqsn.rstrip('.ib')]
|
||||
msg = BrokerdPosition(
|
||||
broker='ib',
|
||||
# account=acctid + '.ib',
|
||||
# XXX: ok so this is annoying, we're relaying
|
||||
# an account name with the backend suffix prefixed
|
||||
# but when reading accounts from ledgers
|
||||
account=ibppmsg.account,
|
||||
# XXX: the `.ib` is stripped..?
|
||||
symbol=ibppmsg.symbol,
|
||||
|
@ -614,6 +634,7 @@ def norm_trade_records(
|
|||
|
||||
|
||||
def trades_to_records(
|
||||
|
||||
accounts: bidict,
|
||||
trade_entries: list[object],
|
||||
source_type: str = 'api',
|
||||
|
|
40
piker/pp.py
40
piker/pp.py
|
@ -21,7 +21,6 @@ that doesn't try to cuk most humans who prefer to not lose their moneys..
|
|||
|
||||
'''
|
||||
from typing import (
|
||||
Any,
|
||||
Optional,
|
||||
Union,
|
||||
)
|
||||
|
@ -153,14 +152,15 @@ def update_pps(
|
|||
Compile a set of positions from a trades ledger.
|
||||
|
||||
'''
|
||||
|
||||
pps: dict[str, Position] = pps or {}
|
||||
|
||||
# lifo update all pps from records
|
||||
for r in records:
|
||||
key = r.fqsn or r.symkey
|
||||
|
||||
pp = pps.setdefault(
|
||||
key,
|
||||
r.fqsn or r.symkey,
|
||||
|
||||
# if no existing pp, allocate fresh one.
|
||||
Position(
|
||||
Symbol.from_fqsn(
|
||||
r.fqsn,
|
||||
|
@ -173,6 +173,11 @@ def update_pps(
|
|||
# don't do updates for ledger records we already have
|
||||
# included in the current pps state.
|
||||
if r.tid in pp.fills:
|
||||
# NOTE: likely you'll see repeats of the same
|
||||
# ``TradeRecord`` passed in here if/when you are restarting
|
||||
# a ``brokerd.ib`` where the API will re-report trades from
|
||||
# the current session, so we need to make sure we don't
|
||||
# "double count" these in pp calculations.
|
||||
continue
|
||||
|
||||
# lifo style average price calc
|
||||
|
@ -187,7 +192,16 @@ def _split_active(
|
|||
pps: dict[str, Position],
|
||||
|
||||
) -> tuple[dict, dict]:
|
||||
'''
|
||||
Split pps into those that are "active" (non-zero size) and "closed"
|
||||
(zero size) and return in 2 dicts.
|
||||
|
||||
Returning the "closed" set is important for updating the pps state
|
||||
in any ``pps.toml`` such that we remove entries which are no longer
|
||||
part of any "VaR" set (well presumably, except of course your liquidity
|
||||
asset could be full of "risk" XD ).
|
||||
|
||||
'''
|
||||
active = {}
|
||||
closed = {}
|
||||
|
||||
|
@ -207,8 +221,14 @@ def load_pps_from_ledger(
|
|||
brokername: str,
|
||||
acctname: str,
|
||||
|
||||
) -> dict[str, Any]:
|
||||
) -> tuple[dict, dict]:
|
||||
'''
|
||||
Open a ledger file by broker name and account and read in and
|
||||
process any trade records into our normalized ``TradeRecord``
|
||||
form and then pass these into the position processing routine
|
||||
and deliver the two dict-sets of the active and closed pps.
|
||||
|
||||
'''
|
||||
with config.open_trade_ledger(
|
||||
brokername,
|
||||
acctname,
|
||||
|
@ -217,10 +237,8 @@ def load_pps_from_ledger(
|
|||
|
||||
brokermod = get_brokermod(brokername)
|
||||
records = brokermod.norm_trade_records(ledger)
|
||||
pps = update_pps(
|
||||
brokername,
|
||||
records,
|
||||
)
|
||||
pps = update_pps(brokername, records)
|
||||
|
||||
return _split_active(pps)
|
||||
|
||||
|
||||
|
@ -282,14 +300,12 @@ def update_pps_conf(
|
|||
config.write(
|
||||
conf,
|
||||
'pps',
|
||||
# TODO: make nested tables and/or inline tables work?
|
||||
# encoder=config.toml.Encoder(preserve=True),
|
||||
)
|
||||
|
||||
return active
|
||||
|
||||
# from pprint import pprint
|
||||
# pprint(conf)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
update_pps_conf('ib', 'algopaper')
|
||||
|
|
Loading…
Reference in New Issue