ib: expose trade EP as `open_trade_dialog()`
Should be the final production backend to switch this over B) Also tidy up the `update_and_audit_msgs()` validator to log vs. raise when `validate: bool` is set; turn it off by default to avoid raises until we figure out wtf is up with ib ledger processing or wtv..basic_buy_bot
parent
b1ef549276
commit
3be1d610e0
|
@ -34,12 +34,12 @@ from .feed import (
|
||||||
stream_quotes,
|
stream_quotes,
|
||||||
)
|
)
|
||||||
from .broker import (
|
from .broker import (
|
||||||
trades_dialogue,
|
open_trade_dialog,
|
||||||
)
|
)
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'get_client',
|
'get_client',
|
||||||
'trades_dialogue',
|
'open_trade_dialog',
|
||||||
'open_history_client',
|
'open_history_client',
|
||||||
'open_symbol_search',
|
'open_symbol_search',
|
||||||
'stream_quotes',
|
'stream_quotes',
|
||||||
|
|
|
@ -29,7 +29,7 @@ import subprocess
|
||||||
|
|
||||||
import tractor
|
import tractor
|
||||||
|
|
||||||
from .._util import get_logger
|
from piker.brokers._util import get_logger
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .api import Client
|
from .api import Client
|
||||||
|
|
|
@ -85,8 +85,9 @@ import numpy as np
|
||||||
# non-relative for backends so that non-builting backends
|
# non-relative for backends so that non-builting backends
|
||||||
# can be easily modelled after this style B)
|
# can be easily modelled after this style B)
|
||||||
from piker import config
|
from piker import config
|
||||||
from piker.brokers._util import (
|
from ._util import (
|
||||||
log,
|
log,
|
||||||
|
# only for the ib_sync internal logging
|
||||||
get_logger,
|
get_logger,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,7 @@ from piker.accounting import (
|
||||||
Position,
|
Position,
|
||||||
Transaction,
|
Transaction,
|
||||||
open_trade_ledger,
|
open_trade_ledger,
|
||||||
|
TransactionLedger,
|
||||||
iter_by_dt,
|
iter_by_dt,
|
||||||
open_pps,
|
open_pps,
|
||||||
PpTable,
|
PpTable,
|
||||||
|
@ -78,10 +79,10 @@ from piker.clearing._messages import (
|
||||||
from piker.accounting import (
|
from piker.accounting import (
|
||||||
MktPair,
|
MktPair,
|
||||||
)
|
)
|
||||||
|
from ._util import log
|
||||||
from .api import (
|
from .api import (
|
||||||
_accounts2clients,
|
_accounts2clients,
|
||||||
con2fqme,
|
con2fqme,
|
||||||
log,
|
|
||||||
get_config,
|
get_config,
|
||||||
open_client_proxies,
|
open_client_proxies,
|
||||||
Client,
|
Client,
|
||||||
|
@ -90,6 +91,7 @@ from .api import (
|
||||||
from ._flex_reports import parse_flex_dt
|
from ._flex_reports import parse_flex_dt
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def pack_position(
|
def pack_position(
|
||||||
pos: IbPosition
|
pos: IbPosition
|
||||||
|
|
||||||
|
@ -339,7 +341,7 @@ async def update_and_audit_msgs(
|
||||||
acctid: str, # no `ib.` prefix is required!
|
acctid: str, # no `ib.` prefix is required!
|
||||||
pps: list[Position],
|
pps: list[Position],
|
||||||
cids2pps: dict[tuple[str, int], BrokerdPosition],
|
cids2pps: dict[tuple[str, int], BrokerdPosition],
|
||||||
validate: bool = False,
|
validate: bool = True,
|
||||||
|
|
||||||
) -> list[BrokerdPosition]:
|
) -> list[BrokerdPosition]:
|
||||||
|
|
||||||
|
@ -352,9 +354,9 @@ async def update_and_audit_msgs(
|
||||||
# for comparison/audit versus the piker equivalent
|
# for comparison/audit versus the piker equivalent
|
||||||
# breakeven pp calcs.
|
# breakeven pp calcs.
|
||||||
ibppmsg = cids2pps.get((acctid, bs_mktid))
|
ibppmsg = cids2pps.get((acctid, bs_mktid))
|
||||||
|
|
||||||
if ibppmsg:
|
if ibppmsg:
|
||||||
symbol = ibppmsg.symbol
|
|
||||||
|
symbol: str = ibppmsg.symbol
|
||||||
msg = BrokerdPosition(
|
msg = BrokerdPosition(
|
||||||
broker='ib',
|
broker='ib',
|
||||||
|
|
||||||
|
@ -375,36 +377,41 @@ async def update_and_audit_msgs(
|
||||||
ibfmtmsg = pformat(ibppmsg.to_dict())
|
ibfmtmsg = pformat(ibppmsg.to_dict())
|
||||||
pikerfmtmsg = pformat(msg.to_dict())
|
pikerfmtmsg = pformat(msg.to_dict())
|
||||||
|
|
||||||
if validate:
|
ibsize = ibppmsg.size
|
||||||
ibsize = ibppmsg.size
|
pikersize = msg.size
|
||||||
pikersize = msg.size
|
diff = pikersize - ibsize
|
||||||
diff = pikersize - ibsize
|
|
||||||
|
|
||||||
# if ib reports a lesser pp it's not as bad since we can
|
# if ib reports a lesser pp it's not as bad since we can
|
||||||
# presume we're at least not more in the shit then we
|
# presume we're at least not more in the shit then we
|
||||||
# thought.
|
# thought.
|
||||||
if diff and pikersize:
|
if diff and pikersize:
|
||||||
reverse_split_ratio = pikersize / ibsize
|
reverse_split_ratio = pikersize / ibsize
|
||||||
split_ratio = 1/reverse_split_ratio
|
split_ratio = 1/reverse_split_ratio
|
||||||
|
|
||||||
if split_ratio >= reverse_split_ratio:
|
if split_ratio >= reverse_split_ratio:
|
||||||
entry = f'split_ratio = {int(split_ratio)}'
|
entry = f'split_ratio = {int(split_ratio)}'
|
||||||
else:
|
else:
|
||||||
entry = f'split_ratio = 1/{int(reverse_split_ratio)}'
|
entry = f'split_ratio = 1/{int(reverse_split_ratio)}'
|
||||||
|
|
||||||
# raise ValueError(
|
msg.size = ibsize
|
||||||
log.error(
|
|
||||||
f'Pos mismatch in ib vs. the piker ledger!\n'
|
logmsg: str = (
|
||||||
f'IB:\n{ibfmtmsg}\n\n'
|
f'Pos mismatch in ib vs. the piker ledger!\n'
|
||||||
f'PIKER:\n{pikerfmtmsg}\n\n'
|
f'IB:\n{ibfmtmsg}\n\n'
|
||||||
'If you are expecting a (reverse) split in this '
|
f'PIKER:\n{pikerfmtmsg}\n\n'
|
||||||
'instrument you should probably put the following'
|
'If you are expecting a (reverse) split in this '
|
||||||
'in the `pps.toml` section:\n'
|
'instrument you should probably put the following'
|
||||||
f'{entry}\n'
|
'in the `pps.toml` section:\n'
|
||||||
# f'reverse_split_ratio: {reverse_split_ratio}\n'
|
f'{entry}\n'
|
||||||
# f'split_ratio: {split_ratio}\n\n'
|
# f'reverse_split_ratio: {reverse_split_ratio}\n'
|
||||||
)
|
# f'split_ratio: {split_ratio}\n\n'
|
||||||
msg.size = ibsize
|
)
|
||||||
|
|
||||||
|
if validate:
|
||||||
|
raise ValueError(logmsg)
|
||||||
|
else:
|
||||||
|
# await tractor.pause()
|
||||||
|
log.error(logmsg)
|
||||||
|
|
||||||
if ibppmsg.avg_price != msg.avg_price:
|
if ibppmsg.avg_price != msg.avg_price:
|
||||||
# TODO: make this a "propaganda" log level?
|
# TODO: make this a "propaganda" log level?
|
||||||
|
@ -432,12 +439,16 @@ async def update_and_audit_msgs(
|
||||||
size=p.size,
|
size=p.size,
|
||||||
avg_price=p.ppu,
|
avg_price=p.ppu,
|
||||||
)
|
)
|
||||||
if validate and p.size:
|
if p.size:
|
||||||
# raise ValueError(
|
logmsg: str = (
|
||||||
log.error(
|
|
||||||
f'UNEXPECTED POSITION says IB => {msg.symbol}\n'
|
f'UNEXPECTED POSITION says IB => {msg.symbol}\n'
|
||||||
'Maybe they LIQUIDATED YOU or are missing ledger entries?\n'
|
'Maybe they LIQUIDATED YOU or are missing ledger entries?\n'
|
||||||
)
|
)
|
||||||
|
log.error(logmsg)
|
||||||
|
|
||||||
|
# if validate:
|
||||||
|
# raise ValueError(logmsg)
|
||||||
|
|
||||||
msgs.append(msg)
|
msgs.append(msg)
|
||||||
|
|
||||||
return msgs
|
return msgs
|
||||||
|
@ -520,10 +531,8 @@ async def open_trade_event_stream(
|
||||||
|
|
||||||
|
|
||||||
@tractor.context
|
@tractor.context
|
||||||
async def trades_dialogue(
|
async def open_trade_dialog(
|
||||||
|
|
||||||
ctx: tractor.Context,
|
ctx: tractor.Context,
|
||||||
# loglevel: str = None,
|
|
||||||
|
|
||||||
) -> AsyncIterator[dict[str, Any]]:
|
) -> AsyncIterator[dict[str, Any]]:
|
||||||
|
|
||||||
|
@ -575,6 +584,7 @@ async def trades_dialogue(
|
||||||
|
|
||||||
# open ledger and pptable wrapper for each
|
# open ledger and pptable wrapper for each
|
||||||
# detected account.
|
# detected account.
|
||||||
|
ledger: TransactionLedger
|
||||||
ledger = ledgers[acctid] = lstack.enter_context(
|
ledger = ledgers[acctid] = lstack.enter_context(
|
||||||
open_trade_ledger(
|
open_trade_ledger(
|
||||||
'ib',
|
'ib',
|
||||||
|
@ -643,13 +653,14 @@ async def trades_dialogue(
|
||||||
|
|
||||||
# TODO: fix this `tractor` BUG!
|
# TODO: fix this `tractor` BUG!
|
||||||
# https://github.com/goodboy/tractor/issues/354
|
# https://github.com/goodboy/tractor/issues/354
|
||||||
# await tractor.breakpoint()
|
# await tractor.pp()
|
||||||
|
|
||||||
if trade_entries:
|
if trade_entries:
|
||||||
# write ledger with all new api_trades
|
# write ledger with all new api_trades
|
||||||
# **AFTER** we've updated the `pps.toml`
|
# **AFTER** we've updated the `pps.toml`
|
||||||
# from the original ledger state! (i.e. this
|
# from the original ledger state! (i.e. this
|
||||||
# is currently done on exit)
|
# is currently done on exit)
|
||||||
|
|
||||||
for tid, entry in trade_entries.items():
|
for tid, entry in trade_entries.items():
|
||||||
ledger.setdefault(tid, {}).update(entry)
|
ledger.setdefault(tid, {}).update(entry)
|
||||||
|
|
||||||
|
@ -670,6 +681,7 @@ async def trades_dialogue(
|
||||||
# -> collect all ib-pp reported positions so that we can be
|
# -> collect all ib-pp reported positions so that we can be
|
||||||
# sure know which positions to update from the ledger if
|
# sure know which positions to update from the ledger if
|
||||||
# any are missing from the ``pps.toml``
|
# any are missing from the ``pps.toml``
|
||||||
|
# await tractor.pp()
|
||||||
|
|
||||||
pos: IbPosition # named tuple subtype
|
pos: IbPosition # named tuple subtype
|
||||||
for pos in client.positions():
|
for pos in client.positions():
|
||||||
|
@ -702,7 +714,7 @@ async def trades_dialogue(
|
||||||
acctid,
|
acctid,
|
||||||
pps.values(),
|
pps.values(),
|
||||||
cids2pps,
|
cids2pps,
|
||||||
validate=True,
|
validate=False,
|
||||||
)
|
)
|
||||||
all_positions.extend(msg for msg in msgs)
|
all_positions.extend(msg for msg in msgs)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue