Support real-time account switch and status update
Make a pp tracker per account and load on order mode boot. Only show details on the pp tracker for the selected account. Make the settings pane assign a `.current_pp` state on the order mode instance (for the charted symbol) on account selection switches and no longer keep a ref to a single pp tracker and allocator in the pane. `SettingsPane.update_status_ui()` now expects an explicit tracker reference as input. Still need to figure out the pnl update task logic despite the intermittent account changes.fsp_feeds
parent
d25aec53e3
commit
f16591612e
|
@ -198,7 +198,7 @@ async def handle_viewmode_kb_inputs(
|
||||||
Qt.Key_P,
|
Qt.Key_P,
|
||||||
}
|
}
|
||||||
):
|
):
|
||||||
pp_pane = order_mode.pp.pane
|
pp_pane = order_mode.current_pp.pane
|
||||||
if pp_pane.isHidden():
|
if pp_pane.isHidden():
|
||||||
pp_pane.show()
|
pp_pane.show()
|
||||||
else:
|
else:
|
||||||
|
@ -213,7 +213,7 @@ async def handle_viewmode_kb_inputs(
|
||||||
if order_keys_pressed:
|
if order_keys_pressed:
|
||||||
|
|
||||||
# show the pp size label
|
# show the pp size label
|
||||||
order_mode.pp.show()
|
order_mode.current_pp.show()
|
||||||
|
|
||||||
# TODO: show pp config mini-params in status bar widget
|
# TODO: show pp config mini-params in status bar widget
|
||||||
# mode.pp_config.show()
|
# mode.pp_config.show()
|
||||||
|
@ -259,20 +259,23 @@ async def handle_viewmode_kb_inputs(
|
||||||
) and
|
) and
|
||||||
key in NUMBER_LINE
|
key in NUMBER_LINE
|
||||||
):
|
):
|
||||||
# hot key to set order slots size
|
# hot key to set order slots size.
|
||||||
|
# change edit field to current number line value,
|
||||||
|
# update the pp allocator bar, unhighlight the
|
||||||
|
# field when ctrl is released.
|
||||||
num = int(text)
|
num = int(text)
|
||||||
pp_pane = order_mode.pane
|
pp_pane = order_mode.pane
|
||||||
pp_pane.on_ui_settings_change('slots', num)
|
pp_pane.on_ui_settings_change('slots', num)
|
||||||
edit = pp_pane.form.fields['slots']
|
edit = pp_pane.form.fields['slots']
|
||||||
edit.selectAll()
|
edit.selectAll()
|
||||||
|
# un-highlight on ctrl release
|
||||||
on_next_release = edit.deselect
|
on_next_release = edit.deselect
|
||||||
|
|
||||||
pp_pane.update_status_ui()
|
pp_pane.update_status_ui()
|
||||||
|
|
||||||
else: # none active
|
else: # none active
|
||||||
|
|
||||||
# hide pp label
|
# hide pp label
|
||||||
order_mode.pp.hide_info()
|
order_mode.current_pp.hide_info()
|
||||||
|
|
||||||
# if none are pressed, remove "staged" level
|
# if none are pressed, remove "staged" level
|
||||||
# line under cursor position
|
# line under cursor position
|
||||||
|
|
|
@ -50,10 +50,6 @@ class SettingsPane:
|
||||||
order entry sizes and position limits per tradable instrument.
|
order entry sizes and position limits per tradable instrument.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
# config for and underlying validation model
|
|
||||||
tracker: PositionTracker
|
|
||||||
alloc: Allocator
|
|
||||||
|
|
||||||
# input fields
|
# input fields
|
||||||
form: FieldsForm
|
form: FieldsForm
|
||||||
|
|
||||||
|
@ -64,9 +60,8 @@ class SettingsPane:
|
||||||
pnl_label: QLabel
|
pnl_label: QLabel
|
||||||
limit_label: QLabel
|
limit_label: QLabel
|
||||||
|
|
||||||
def transform_to(self, size_unit: str) -> None:
|
# encompasing high level namespace
|
||||||
if self.alloc.size_unit == size_unit:
|
order_mode: Optional['OrderMode'] = None # typing: ignore # noqa
|
||||||
return
|
|
||||||
|
|
||||||
def on_selection_change(
|
def on_selection_change(
|
||||||
self,
|
self,
|
||||||
|
@ -79,7 +74,6 @@ class SettingsPane:
|
||||||
|
|
||||||
'''
|
'''
|
||||||
log.info(f'selection input: {text}')
|
log.info(f'selection input: {text}')
|
||||||
setattr(self.alloc, key, text)
|
|
||||||
self.on_ui_settings_change(key, text)
|
self.on_ui_settings_change(key, text)
|
||||||
|
|
||||||
def on_ui_settings_change(
|
def on_ui_settings_change(
|
||||||
|
@ -92,10 +86,34 @@ class SettingsPane:
|
||||||
'''Called on any order pane edit field value change.
|
'''Called on any order pane edit field value change.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
alloc = self.alloc
|
mode = self.order_mode
|
||||||
|
|
||||||
|
if key == 'account':
|
||||||
|
# an account switch request
|
||||||
|
|
||||||
|
# hide detail on the old pp
|
||||||
|
old_tracker = mode.current_pp
|
||||||
|
old_tracker.hide_info()
|
||||||
|
|
||||||
|
# re-assign the order mode tracker
|
||||||
|
account_name = value
|
||||||
|
tracker = mode.trackers[account_name]
|
||||||
|
self.order_mode.current_pp = tracker
|
||||||
|
assert tracker.alloc.account_name() == account_name
|
||||||
|
self.form.fields['account'].setCurrentText(account_name)
|
||||||
|
tracker.show()
|
||||||
|
tracker.hide_info()
|
||||||
|
|
||||||
|
# load the new account's allocator
|
||||||
|
alloc = tracker.alloc
|
||||||
|
|
||||||
|
else:
|
||||||
|
tracker = mode.current_pp
|
||||||
|
alloc = tracker.alloc
|
||||||
|
|
||||||
size_unit = alloc.size_unit
|
size_unit = alloc.size_unit
|
||||||
|
|
||||||
# write any passed settings to allocator
|
# WRITE any settings to current pp's allocator
|
||||||
if key == 'limit':
|
if key == 'limit':
|
||||||
if size_unit == 'currency':
|
if size_unit == 'currency':
|
||||||
alloc.currency_limit = float(value)
|
alloc.currency_limit = float(value)
|
||||||
|
@ -110,14 +128,10 @@ class SettingsPane:
|
||||||
# the current settings in the new units
|
# the current settings in the new units
|
||||||
pass
|
pass
|
||||||
|
|
||||||
elif key == 'account':
|
elif key != 'account':
|
||||||
account_name = value or 'paper'
|
|
||||||
alloc.account = account_name
|
|
||||||
|
|
||||||
else:
|
|
||||||
raise ValueError(f'Unknown setting {key}')
|
raise ValueError(f'Unknown setting {key}')
|
||||||
|
|
||||||
# read out settings and update UI
|
# READ out settings and update UI
|
||||||
log.info(f'settings change: {key}: {value}')
|
log.info(f'settings change: {key}: {value}')
|
||||||
|
|
||||||
suffix = {'currency': ' $', 'units': ' u'}[size_unit]
|
suffix = {'currency': ' $', 'units': ' u'}[size_unit]
|
||||||
|
@ -125,7 +139,7 @@ class SettingsPane:
|
||||||
|
|
||||||
# TODO: a reverse look up from the position to the equivalent
|
# TODO: a reverse look up from the position to the equivalent
|
||||||
# account(s), if none then look to user config for default?
|
# account(s), if none then look to user config for default?
|
||||||
self.update_status_ui()
|
self.update_status_ui(pp=tracker)
|
||||||
|
|
||||||
step_size, currency_per_slot = alloc.step_sizes()
|
step_size, currency_per_slot = alloc.step_sizes()
|
||||||
|
|
||||||
|
@ -143,7 +157,6 @@ class SettingsPane:
|
||||||
self.form.fields['size_unit'].setCurrentText(
|
self.form.fields['size_unit'].setCurrentText(
|
||||||
alloc._size_units[alloc.size_unit]
|
alloc._size_units[alloc.size_unit]
|
||||||
)
|
)
|
||||||
self.form.fields['account'].setCurrentText(alloc.account_name())
|
|
||||||
self.form.fields['slots'].setText(str(alloc.slots))
|
self.form.fields['slots'].setText(str(alloc.slots))
|
||||||
self.form.fields['limit'].setText(str(limit))
|
self.form.fields['limit'].setText(str(limit))
|
||||||
|
|
||||||
|
@ -154,13 +167,14 @@ class SettingsPane:
|
||||||
|
|
||||||
def update_status_ui(
|
def update_status_ui(
|
||||||
self,
|
self,
|
||||||
size: float = None,
|
|
||||||
|
pp: PositionTracker,
|
||||||
|
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
||||||
alloc = self.alloc
|
alloc = pp.alloc
|
||||||
slots = alloc.slots
|
slots = alloc.slots
|
||||||
used = alloc.slots_used(self.tracker.live_pp)
|
used = alloc.slots_used(pp.live_pp)
|
||||||
|
|
||||||
# calculate proportion of position size limit
|
# calculate proportion of position size limit
|
||||||
# that exists and display in fill bar
|
# that exists and display in fill bar
|
||||||
|
@ -173,12 +187,17 @@ class SettingsPane:
|
||||||
min(used, slots)
|
min(used, slots)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# TODO: move to order mode module! doesn't need to be a method since
|
||||||
|
# we partial in all the state
|
||||||
def on_level_change_update_next_order_info(
|
def on_level_change_update_next_order_info(
|
||||||
self,
|
self,
|
||||||
|
|
||||||
level: float,
|
level: float,
|
||||||
|
|
||||||
|
# these are all ``partial``-ed in at callback assignment time.
|
||||||
line: LevelLine,
|
line: LevelLine,
|
||||||
order: Order,
|
order: Order,
|
||||||
|
tracker: PositionTracker,
|
||||||
|
|
||||||
) -> None:
|
) -> None:
|
||||||
'''A callback applied for each level change to the line
|
'''A callback applied for each level change to the line
|
||||||
|
@ -187,9 +206,9 @@ class SettingsPane:
|
||||||
``OrderMode.line_from_order()``
|
``OrderMode.line_from_order()``
|
||||||
|
|
||||||
'''
|
'''
|
||||||
order_info = self.alloc.next_order_info(
|
order_info = tracker.alloc.next_order_info(
|
||||||
startup_pp=self.tracker.startup_pp,
|
startup_pp=tracker.startup_pp,
|
||||||
live_pp=self.tracker.live_pp,
|
live_pp=tracker.live_pp,
|
||||||
price=level,
|
price=level,
|
||||||
action=order.action,
|
action=order.action,
|
||||||
)
|
)
|
||||||
|
@ -267,8 +286,8 @@ def position_line(
|
||||||
|
|
||||||
|
|
||||||
class PositionTracker:
|
class PositionTracker:
|
||||||
'''Track and display a real-time position for a single symbol
|
'''Track and display real-time positions for a single symbol
|
||||||
on a chart.
|
over multiple accounts on a single chart.
|
||||||
|
|
||||||
Graphically composed of a level line and marker as well as labels
|
Graphically composed of a level line and marker as well as labels
|
||||||
for indcating current position information. Updates are made to the
|
for indcating current position information. Updates are made to the
|
||||||
|
@ -277,11 +296,12 @@ class PositionTracker:
|
||||||
'''
|
'''
|
||||||
# inputs
|
# inputs
|
||||||
chart: 'ChartPlotWidget' # noqa
|
chart: 'ChartPlotWidget' # noqa
|
||||||
|
|
||||||
alloc: Allocator
|
alloc: Allocator
|
||||||
startup_pp: Position
|
startup_pp: Position
|
||||||
|
live_pp: Position
|
||||||
|
|
||||||
# allocated
|
# allocated
|
||||||
live_pp: Position
|
|
||||||
pp_label: Label
|
pp_label: Label
|
||||||
size_label: Label
|
size_label: Label
|
||||||
line: Optional[LevelLine] = None
|
line: Optional[LevelLine] = None
|
||||||
|
@ -297,6 +317,7 @@ class PositionTracker:
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
||||||
self.chart = chart
|
self.chart = chart
|
||||||
|
|
||||||
self.alloc = alloc
|
self.alloc = alloc
|
||||||
self.startup_pp = startup_pp
|
self.startup_pp = startup_pp
|
||||||
self.live_pp = startup_pp.copy()
|
self.live_pp = startup_pp.copy()
|
||||||
|
@ -375,7 +396,6 @@ class PositionTracker:
|
||||||
'''
|
'''
|
||||||
# live pp updates
|
# live pp updates
|
||||||
pp = position or self.live_pp
|
pp = position or self.live_pp
|
||||||
# pp.update_from_msg(msg)
|
|
||||||
|
|
||||||
self.update_line(
|
self.update_line(
|
||||||
pp.avg_price,
|
pp.avg_price,
|
||||||
|
@ -413,7 +433,6 @@ class PositionTracker:
|
||||||
|
|
||||||
def show(self) -> None:
|
def show(self) -> None:
|
||||||
if self.live_pp.size:
|
if self.live_pp.size:
|
||||||
|
|
||||||
self.line.show()
|
self.line.show()
|
||||||
self.line.show_labels()
|
self.line.show_labels()
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,6 @@ import time
|
||||||
from typing import Optional, Dict, Callable, Any
|
from typing import Optional, Dict, Callable, Any
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from bidict import bidict
|
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
import tractor
|
import tractor
|
||||||
import trio
|
import trio
|
||||||
|
@ -36,7 +35,6 @@ from .. import config
|
||||||
from ..calc import pnl
|
from ..calc import pnl
|
||||||
from ..clearing._client import open_ems, OrderBook
|
from ..clearing._client import open_ems, OrderBook
|
||||||
from ..clearing._allocate import (
|
from ..clearing._allocate import (
|
||||||
Allocator,
|
|
||||||
mk_allocator,
|
mk_allocator,
|
||||||
Position,
|
Position,
|
||||||
)
|
)
|
||||||
|
@ -102,12 +100,12 @@ class OrderMode:
|
||||||
lines: LineEditor
|
lines: LineEditor
|
||||||
arrows: ArrowEditor
|
arrows: ArrowEditor
|
||||||
multistatus: MultiStatus
|
multistatus: MultiStatus
|
||||||
pp: PositionTracker
|
|
||||||
alloc: 'Allocator' # noqa
|
|
||||||
pane: SettingsPane
|
pane: SettingsPane
|
||||||
|
trackers: dict[str, PositionTracker]
|
||||||
|
|
||||||
|
# switched state, the current position
|
||||||
|
current_pp: Optional[PositionTracker] = None
|
||||||
active: bool = False
|
active: bool = False
|
||||||
|
|
||||||
name: str = 'order'
|
name: str = 'order'
|
||||||
dialogs: dict[str, OrderDialog] = field(default_factory=dict)
|
dialogs: dict[str, OrderDialog] = field(default_factory=dict)
|
||||||
|
|
||||||
|
@ -155,6 +153,7 @@ class OrderMode:
|
||||||
self.pane.on_level_change_update_next_order_info,
|
self.pane.on_level_change_update_next_order_info,
|
||||||
line=line,
|
line=line,
|
||||||
order=order,
|
order=order,
|
||||||
|
tracker=self.current_pp,
|
||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -193,7 +192,7 @@ class OrderMode:
|
||||||
order = self._staged_order = Order(
|
order = self._staged_order = Order(
|
||||||
action=action,
|
action=action,
|
||||||
price=price,
|
price=price,
|
||||||
account=self.alloc.account_name(),
|
account=self.current_pp.alloc.account_name(),
|
||||||
size=0,
|
size=0,
|
||||||
symbol=symbol,
|
symbol=symbol,
|
||||||
brokers=symbol.brokers,
|
brokers=symbol.brokers,
|
||||||
|
@ -499,7 +498,7 @@ async def open_order_mode(
|
||||||
|
|
||||||
book: OrderBook
|
book: OrderBook
|
||||||
trades_stream: tractor.MsgStream
|
trades_stream: tractor.MsgStream
|
||||||
positions: dict
|
position_msgs: dict
|
||||||
|
|
||||||
# spawn EMS actor-service
|
# spawn EMS actor-service
|
||||||
async with (
|
async with (
|
||||||
|
@ -507,7 +506,7 @@ async def open_order_mode(
|
||||||
open_ems(brokername, symbol) as (
|
open_ems(brokername, symbol) as (
|
||||||
book,
|
book,
|
||||||
trades_stream,
|
trades_stream,
|
||||||
positions
|
position_msgs
|
||||||
),
|
),
|
||||||
trio.open_nursery() as tn,
|
trio.open_nursery() as tn,
|
||||||
|
|
||||||
|
@ -520,64 +519,91 @@ async def open_order_mode(
|
||||||
lines = LineEditor(chart=chart)
|
lines = LineEditor(chart=chart)
|
||||||
arrows = ArrowEditor(chart, {})
|
arrows = ArrowEditor(chart, {})
|
||||||
|
|
||||||
|
# allocation and account settings side pane
|
||||||
form = chart.sidepane
|
form = chart.sidepane
|
||||||
|
|
||||||
# update any from exising positions received from ``brokerd``
|
# symbol id
|
||||||
symbol = chart.linked.symbol
|
symbol = chart.linked.symbol
|
||||||
symkey = chart.linked._symbol.key
|
symkey = symbol.key
|
||||||
|
|
||||||
# NOTE: requires that the backend exactly specifies
|
# map of per-provider account keys to position tracker instances
|
||||||
# the expected symbol key in it's positions msg.
|
trackers: dict[str, PositionTracker] = {}
|
||||||
pp_msg = positions.get(symkey)
|
|
||||||
|
|
||||||
# net-zero pp
|
|
||||||
startup_pp = Position(
|
|
||||||
symbol=symbol,
|
|
||||||
size=0,
|
|
||||||
avg_price=0,
|
|
||||||
)
|
|
||||||
|
|
||||||
# load account names from ``brokers.toml``
|
# load account names from ``brokers.toml``
|
||||||
accounts = bidict(config.load_accounts())
|
accounts = config.load_accounts(providers=symbol.brokers)
|
||||||
# process pps back from broker, only present
|
if accounts:
|
||||||
# account names reported back from ``brokerd``.
|
# first account listed is the one we select at startup
|
||||||
pp_account = None
|
# (aka order based selection).
|
||||||
|
pp_account = next(iter(accounts.keys()))
|
||||||
|
else:
|
||||||
|
pp_account = 'paper'
|
||||||
|
|
||||||
if pp_msg:
|
# for each account with this broker, allocate pp tracker components
|
||||||
log.info(f'Loading pp for {symkey}:\n{pformat(pp_msg)}')
|
for config_name, account in accounts.items():
|
||||||
startup_pp.update_from_msg(pp_msg)
|
# net-zero pp
|
||||||
pp_account = accounts.inverse.get(pp_msg.get('account'))
|
startup_pp = Position(
|
||||||
|
symbol=symbol,
|
||||||
|
size=0,
|
||||||
|
avg_price=0,
|
||||||
|
)
|
||||||
|
|
||||||
# lookup account for this pp or load the user default
|
# allocator
|
||||||
# for this backend
|
alloc = mk_allocator(
|
||||||
|
symbol=symbol,
|
||||||
# allocator
|
accounts=accounts,
|
||||||
alloc = mk_allocator(
|
account=config_name,
|
||||||
symbol=symbol,
|
startup_pp=startup_pp,
|
||||||
accounts=accounts,
|
)
|
||||||
account=pp_account,
|
pp_tracker = PositionTracker(
|
||||||
startup_pp=startup_pp,
|
chart,
|
||||||
)
|
alloc,
|
||||||
form.model = alloc
|
startup_pp
|
||||||
|
)
|
||||||
pp_tracker = PositionTracker(
|
|
||||||
chart,
|
|
||||||
alloc,
|
|
||||||
startup_pp
|
|
||||||
)
|
|
||||||
pp_tracker.update_from_pp(startup_pp)
|
|
||||||
|
|
||||||
if startup_pp.size == 0:
|
|
||||||
# if no position, don't show pp tracking graphics
|
|
||||||
pp_tracker.hide()
|
pp_tracker.hide()
|
||||||
|
trackers[config_name] = pp_tracker
|
||||||
|
|
||||||
|
# TODO: preparse and account-map these msgs and do it all in ONE LOOP!
|
||||||
|
|
||||||
|
# NOTE: requires the backend exactly specifies
|
||||||
|
# the expected symbol key in its positions msg.
|
||||||
|
pp_msgs = position_msgs.get(symkey, ())
|
||||||
|
|
||||||
|
# update all pp trackers with existing data relayed
|
||||||
|
# from ``brokerd``.
|
||||||
|
for msg in pp_msgs:
|
||||||
|
log.info(f'Loading pp for {symkey}:\n{pformat(msg)}')
|
||||||
|
account_name = accounts.inverse.get(msg.get('account'))
|
||||||
|
tracker = trackers[account_name]
|
||||||
|
|
||||||
|
# TODO: do we even really need the "startup pp" or can we
|
||||||
|
# just take the max and pass that into the some state / the
|
||||||
|
# alloc?
|
||||||
|
tracker.startup_pp.update_from_msg(msg)
|
||||||
|
tracker.live_pp.update_from_msg(msg)
|
||||||
|
|
||||||
|
# TODO:
|
||||||
|
# if this startup size is greater the allocator limit,
|
||||||
|
# increase the limit to the current pp size which is done
|
||||||
|
# in this alloc factory..
|
||||||
|
# tracker.alloc = mk_allocator(
|
||||||
|
# symbol=symbol,
|
||||||
|
# accounts=accounts,
|
||||||
|
# account=account_name,
|
||||||
|
# startup_pp=tracker.live_pp,
|
||||||
|
# )
|
||||||
|
|
||||||
|
# tracker.update_from_pp(tracker.startup_pp)
|
||||||
|
tracker.update_from_pp(tracker.live_pp)
|
||||||
|
|
||||||
|
if tracker.startup_pp.size != 0:
|
||||||
|
# if no position, don't show pp tracking graphics
|
||||||
|
tracker.show()
|
||||||
|
|
||||||
|
tracker.hide_info()
|
||||||
|
|
||||||
# order pane widgets and allocation model
|
# order pane widgets and allocation model
|
||||||
order_pane = SettingsPane(
|
order_pane = SettingsPane(
|
||||||
|
|
||||||
tracker=pp_tracker,
|
|
||||||
form=form,
|
form=form,
|
||||||
alloc=alloc,
|
|
||||||
|
|
||||||
# XXX: ugh, so hideous...
|
# XXX: ugh, so hideous...
|
||||||
fill_bar=form.fill_bar,
|
fill_bar=form.fill_bar,
|
||||||
pnl_label=form.left_label,
|
pnl_label=form.left_label,
|
||||||
|
@ -585,13 +611,6 @@ async def open_order_mode(
|
||||||
limit_label=form.top_label,
|
limit_label=form.top_label,
|
||||||
)
|
)
|
||||||
|
|
||||||
# set startup limit value read during alloc init
|
|
||||||
order_pane.on_ui_settings_change('limit', alloc.limit())
|
|
||||||
order_pane.on_ui_settings_change('account', pp_account)
|
|
||||||
|
|
||||||
# make fill bar and positioning snapshot
|
|
||||||
order_pane.update_status_ui(size=startup_pp.size)
|
|
||||||
|
|
||||||
# top level abstraction which wraps all this crazyness into
|
# top level abstraction which wraps all this crazyness into
|
||||||
# a namespace..
|
# a namespace..
|
||||||
mode = OrderMode(
|
mode = OrderMode(
|
||||||
|
@ -600,10 +619,18 @@ async def open_order_mode(
|
||||||
lines,
|
lines,
|
||||||
arrows,
|
arrows,
|
||||||
multistatus,
|
multistatus,
|
||||||
pp_tracker,
|
|
||||||
alloc=alloc,
|
|
||||||
pane=order_pane,
|
pane=order_pane,
|
||||||
|
trackers=trackers,
|
||||||
|
|
||||||
)
|
)
|
||||||
|
# XXX: MUST be set
|
||||||
|
order_pane.order_mode = mode
|
||||||
|
|
||||||
|
# select a pp to track
|
||||||
|
tracker = trackers[pp_account]
|
||||||
|
mode.current_pp = tracker
|
||||||
|
tracker.show()
|
||||||
|
tracker.hide_info()
|
||||||
|
|
||||||
# XXX: would love to not have to do this separate from edit
|
# XXX: would love to not have to do this separate from edit
|
||||||
# fields (which are done in an async loop - see below)
|
# fields (which are done in an async loop - see below)
|
||||||
|
@ -619,13 +646,19 @@ async def open_order_mode(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# make fill bar and positioning snapshot
|
||||||
|
order_pane.on_ui_settings_change('limit', tracker.alloc.limit())
|
||||||
|
order_pane.on_ui_settings_change('account', pp_account)
|
||||||
|
# order_pane.update_status_ui(pp=tracker.startup_pp)
|
||||||
|
order_pane.update_status_ui(pp=tracker)
|
||||||
|
|
||||||
# TODO: create a mode "manager" of sorts?
|
# TODO: create a mode "manager" of sorts?
|
||||||
# -> probably just call it "UxModes" err sumthin?
|
# -> probably just call it "UxModes" err sumthin?
|
||||||
# so that view handlers can access it
|
# so that view handlers can access it
|
||||||
view.order_mode = mode
|
view.order_mode = mode
|
||||||
|
|
||||||
# real-time pnl display task allocation
|
# real-time pnl display task allocation
|
||||||
live_pp = mode.pp.live_pp
|
live_pp = mode.current_pp.live_pp
|
||||||
size = live_pp.size
|
size = live_pp.size
|
||||||
if size:
|
if size:
|
||||||
global _pnl_tasks
|
global _pnl_tasks
|
||||||
|
@ -697,7 +730,7 @@ async def display_pnl(
|
||||||
'''
|
'''
|
||||||
global _pnl_tasks
|
global _pnl_tasks
|
||||||
|
|
||||||
pp = order_mode.pp
|
pp = order_mode.current_pp
|
||||||
live = pp.live_pp
|
live = pp.live_pp
|
||||||
|
|
||||||
sym = live.symbol.key
|
sym = live.symbol.key
|
||||||
|
@ -727,7 +760,7 @@ async def display_pnl(
|
||||||
for tick in iterticks(quote, types):
|
for tick in iterticks(quote, types):
|
||||||
# print(f'{1/period} Hz')
|
# print(f'{1/period} Hz')
|
||||||
|
|
||||||
size = live.size
|
size = order_mode.current_pp.live_pp.size
|
||||||
if size == 0:
|
if size == 0:
|
||||||
# terminate this update task since we're
|
# terminate this update task since we're
|
||||||
# no longer in a pp
|
# no longer in a pp
|
||||||
|
@ -738,7 +771,8 @@ async def display_pnl(
|
||||||
# compute and display pnl status
|
# compute and display pnl status
|
||||||
order_mode.pane.pnl_label.format(
|
order_mode.pane.pnl_label.format(
|
||||||
pnl=copysign(1, size) * pnl(
|
pnl=copysign(1, size) * pnl(
|
||||||
live.avg_price,
|
# live.avg_price,
|
||||||
|
order_mode.current_pp.live_pp.avg_price,
|
||||||
tick['price'],
|
tick['price'],
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -760,7 +794,6 @@ async def process_trades_and_update_ui(
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
||||||
get_index = mode.chart.get_index
|
get_index = mode.chart.get_index
|
||||||
tracker = mode.pp
|
|
||||||
global _pnl_tasks
|
global _pnl_tasks
|
||||||
|
|
||||||
# this is where we receive **back** messages
|
# this is where we receive **back** messages
|
||||||
|
@ -774,16 +807,15 @@ async def process_trades_and_update_ui(
|
||||||
if name in (
|
if name in (
|
||||||
'position',
|
'position',
|
||||||
):
|
):
|
||||||
# show line label once order is live
|
|
||||||
|
|
||||||
sym = mode.chart.linked.symbol
|
sym = mode.chart.linked.symbol
|
||||||
if msg['symbol'].lower() in sym.key:
|
if msg['symbol'].lower() in sym.key:
|
||||||
|
|
||||||
|
tracker = mode.trackers[msg['account']]
|
||||||
tracker.live_pp.update_from_msg(msg)
|
tracker.live_pp.update_from_msg(msg)
|
||||||
tracker.update_from_pp()
|
tracker.update_from_pp()
|
||||||
|
|
||||||
# update order pane widgets
|
# update order pane widgets
|
||||||
mode.pane.update_status_ui()
|
mode.pane.update_status_ui(tracker.live_pp)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
tracker.live_pp.size and
|
tracker.live_pp.size and
|
||||||
|
@ -795,7 +827,7 @@ async def process_trades_and_update_ui(
|
||||||
mode,
|
mode,
|
||||||
)
|
)
|
||||||
# short circuit to next msg to avoid
|
# short circuit to next msg to avoid
|
||||||
# uncessary msg content lookups
|
# unnecessary msg content lookups
|
||||||
continue
|
continue
|
||||||
|
|
||||||
resp = msg['resp']
|
resp = msg['resp']
|
||||||
|
|
Loading…
Reference in New Issue