Port to order pane apis
parent
bc2f4186fd
commit
206af0d575
|
@ -44,6 +44,7 @@ import pydantic
|
|||
|
||||
from ._event import open_handlers
|
||||
from ._style import hcolor, _font, _font_small, DpiAwareFont
|
||||
from .. import brokers
|
||||
|
||||
|
||||
class FontAndChartAwareLineEdit(QLineEdit):
|
||||
|
@ -366,11 +367,15 @@ async def handle_field_input(
|
|||
|
||||
# process field input
|
||||
if key in (Qt.Key_Enter, Qt.Key_Return):
|
||||
|
||||
value = widget.text()
|
||||
key = widget._key
|
||||
|
||||
old = getattr(model, key)
|
||||
|
||||
try:
|
||||
setattr(model, key, value)
|
||||
|
||||
except pydantic.error_wrappers.ValidationError:
|
||||
setattr(model, key, old)
|
||||
widget.setText(str(old))
|
||||
|
@ -380,16 +385,14 @@ async def handle_field_input(
|
|||
|
||||
def mk_form(
|
||||
|
||||
model: pydantic.BaseModel,
|
||||
parent: QWidget,
|
||||
fields_schema: dict,
|
||||
|
||||
) -> FieldsForm:
|
||||
|
||||
form = FieldsForm(parent=parent)
|
||||
# TODO: generate components from model
|
||||
# instead of schema dict (aka use an ORM)
|
||||
form.model = model
|
||||
form = FieldsForm(parent=parent)
|
||||
|
||||
# generate sub-components from schema dict
|
||||
for key, config in fields_schema.items():
|
||||
|
@ -413,18 +416,6 @@ def mk_form(
|
|||
values
|
||||
)
|
||||
|
||||
def write_model(text: str, key: str):
|
||||
print(f'{text}')
|
||||
setattr(form.model, key, text)
|
||||
print(form.model)
|
||||
|
||||
w.currentTextChanged.connect(
|
||||
partial(
|
||||
write_model,
|
||||
key=key,
|
||||
)
|
||||
)
|
||||
|
||||
w._key = key
|
||||
|
||||
return form
|
||||
|
@ -438,7 +429,7 @@ async def open_form_input_handling(
|
|||
|
||||
) -> FieldsForm:
|
||||
|
||||
assert form.model, f'{form} must define a `.model`'
|
||||
# assert form.model, f'{form} must define a `.model`'
|
||||
|
||||
async with open_handlers(
|
||||
|
||||
|
@ -630,31 +621,27 @@ def mk_fill_status_bar(
|
|||
slots = 4
|
||||
bar.set_slots(slots, value=0)
|
||||
|
||||
return hbox, bar
|
||||
return hbox, bar, left_label, top_label, bottom_label
|
||||
|
||||
|
||||
def mk_order_pane_layout(
|
||||
|
||||
parent: QWidget,
|
||||
# accounts: dict[str, Optional[str]],
|
||||
font_size: int = _font_small.px_size - 2
|
||||
|
||||
) -> FieldsForm:
|
||||
|
||||
from ._position import mk_alloc
|
||||
# TODO: some kinda pydantic sub-type
|
||||
# that enforces a composite widget attr er sumthin..
|
||||
# as part of our ORM thingers.
|
||||
alloc = mk_alloc()
|
||||
accounts = brokers.config.load_accounts()
|
||||
|
||||
# TODO: maybe just allocate the whole fields form here
|
||||
# and expect an async ctx entry?
|
||||
form = mk_form(
|
||||
parent=parent,
|
||||
model=alloc,
|
||||
fields_schema={
|
||||
'account': {
|
||||
'type': 'select',
|
||||
'default_value': alloc._accounts.keys()
|
||||
'default_value': accounts.keys(),
|
||||
},
|
||||
'size_unit': {
|
||||
'label': '**allocate**:',
|
||||
|
@ -670,8 +657,8 @@ def mk_order_pane_layout(
|
|||
'type': 'select',
|
||||
'default_value': ['uniform'],
|
||||
},
|
||||
'size': {
|
||||
'label': '**size**:',
|
||||
'limit': {
|
||||
'label': '**limit**:',
|
||||
'type': 'edit',
|
||||
'default_value': 5000,
|
||||
},
|
||||
|
@ -683,7 +670,6 @@ def mk_order_pane_layout(
|
|||
},
|
||||
)
|
||||
form._font_size = font_size
|
||||
alloc._widget = form
|
||||
|
||||
# top level pane layout
|
||||
# XXX: see ``FieldsForm.__init__()`` for why we can't do basic
|
||||
|
@ -693,8 +679,15 @@ def mk_order_pane_layout(
|
|||
# _, h = form.width(), form.height()
|
||||
# print(f'w, h: {w, h}')
|
||||
|
||||
hbox, fill_bar = mk_fill_status_bar(form, pane_vbox=vbox)
|
||||
hbox, fill_bar, left_label, bottom_label, top_label = mk_fill_status_bar(
|
||||
form, pane_vbox=vbox
|
||||
)
|
||||
# TODO: would be nice to have some better way of reffing these over
|
||||
# monkey patching...
|
||||
form.fill_bar = fill_bar
|
||||
form.left_label = left_label
|
||||
form.bottom_label = bottom_label
|
||||
form.top_label = top_label
|
||||
|
||||
# add pp fill bar + spacing
|
||||
vbox.addLayout(hbox, stretch=1/3)
|
||||
|
@ -702,9 +695,9 @@ def mk_order_pane_layout(
|
|||
feed_label = form.add_field_label(
|
||||
dedent("""
|
||||
brokerd.ib\n
|
||||
|_@localhost:8509\n
|
||||
|_consumers: 4\n
|
||||
|_streams: 9\n
|
||||
|_@{host}:{port}\n
|
||||
|_consumers: {cons}\n
|
||||
|_streams: {streams}\n
|
||||
"""),
|
||||
font_size=_font.px_size - 5,
|
||||
)
|
||||
|
@ -722,5 +715,4 @@ def mk_order_pane_layout(
|
|||
vbox.setSpacing(36)
|
||||
|
||||
form.show()
|
||||
|
||||
return form
|
||||
|
|
|
@ -261,14 +261,16 @@ async def handle_viewmode_kb_inputs(
|
|||
):
|
||||
# hot key to set order slots size
|
||||
num = int(text)
|
||||
pp = order_mode.pp
|
||||
pp_pane = pp.pane
|
||||
pp_pane.model.slots = num
|
||||
edit = pp_pane.fields['slots']
|
||||
pp_pane = order_mode.pane
|
||||
pp_pane.alloc.slots = num
|
||||
|
||||
edit = pp_pane.form.fields['slots']
|
||||
edit.setText(text)
|
||||
edit.selectAll()
|
||||
|
||||
on_next_release = edit.deselect
|
||||
pp.init_status_ui()
|
||||
|
||||
pp_pane.init_status_ui()
|
||||
|
||||
else: # none active
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ Chart trading, the only way to scalp.
|
|||
|
||||
"""
|
||||
from dataclasses import dataclass, field
|
||||
from functools import partial
|
||||
from pprint import pformat
|
||||
import time
|
||||
from typing import Optional, Dict, Callable, Any
|
||||
|
@ -28,15 +29,16 @@ from pydantic import BaseModel
|
|||
import tractor
|
||||
import trio
|
||||
|
||||
from .. import brokers
|
||||
from ..clearing._client import open_ems, OrderBook
|
||||
from ..data._source import Symbol
|
||||
from ..log import get_logger
|
||||
from ._editors import LineEditor, ArrowEditor
|
||||
from ._lines import order_line, LevelLine
|
||||
from ._position import PositionTracker
|
||||
from ._position import PositionTracker, OrderModePane, mk_alloc
|
||||
from ._window import MultiStatus
|
||||
from ..clearing._messages import Order
|
||||
# from ._forms import FieldsForm
|
||||
from ._forms import open_form_input_handling
|
||||
|
||||
|
||||
log = get_logger(__name__)
|
||||
|
@ -88,6 +90,8 @@ class OrderMode:
|
|||
multistatus: MultiStatus
|
||||
pp: PositionTracker
|
||||
allocator: 'Allocator' # noqa
|
||||
pane: OrderModePane
|
||||
|
||||
active: bool = False
|
||||
|
||||
name: str = 'order'
|
||||
|
@ -127,31 +131,16 @@ class OrderMode:
|
|||
) else False,
|
||||
|
||||
**line_kwargs,
|
||||
|
||||
)
|
||||
|
||||
# define a callback applied for each level change to the line
|
||||
# which will recompute the order size based on allocator
|
||||
# settings:
|
||||
def update_from_size_calc(y: float) -> None:
|
||||
|
||||
order_info = self.allocator.get_order_info(
|
||||
symbol=symbol,
|
||||
price=y,
|
||||
action=order.action,
|
||||
# set level update callback to order pane method and update once
|
||||
# immediately
|
||||
line._on_level_change = partial(
|
||||
self.pane.on_level_change_update_next_order_info,
|
||||
line=line,
|
||||
order=order,
|
||||
)
|
||||
line.update_labels(order_info)
|
||||
order.price = y
|
||||
order.size = order_info['size']
|
||||
|
||||
# return is used to update labels implicitly
|
||||
return order_info
|
||||
|
||||
update_from_size_calc(order.price)
|
||||
|
||||
# set level update cb
|
||||
# line._on_level_change = partial(update_from_size_calc, order=order)
|
||||
line._on_level_change = update_from_size_calc
|
||||
line._on_level_change(order.price)
|
||||
|
||||
return line
|
||||
|
||||
|
@ -493,16 +482,52 @@ async def run_order_mode(
|
|||
),
|
||||
|
||||
):
|
||||
log.info(f'Opening order mode for {brokername}.{symbol.key}')
|
||||
|
||||
view = chart.view
|
||||
|
||||
# annotations editors
|
||||
lines = LineEditor(chart=chart)
|
||||
arrows = ArrowEditor(chart, {})
|
||||
|
||||
log.info("Opening order mode")
|
||||
# allocator
|
||||
alloc = mk_alloc(
|
||||
symbol=symbol,
|
||||
accounts=brokers.config.load_accounts()
|
||||
)
|
||||
|
||||
# form = chart.linked.godwidget.pp_pane.model
|
||||
form = chart.sidepane
|
||||
form.model = alloc
|
||||
|
||||
alloc = chart.linked.godwidget.pp_pane.model
|
||||
pp_tracker = PositionTracker(chart, alloc=alloc)
|
||||
pp_tracker.hide()
|
||||
alloc._position = pp_tracker
|
||||
|
||||
# order pane widgets and allocation model
|
||||
order_pane = OrderModePane(
|
||||
tracker=pp_tracker,
|
||||
form=form,
|
||||
alloc=alloc,
|
||||
fill_bar=form.fill_bar,
|
||||
pnl_label=form.left_label,
|
||||
step_label=form.bottom_label,
|
||||
limit_label=form.top_label,
|
||||
)
|
||||
|
||||
for key in ('account', 'size_unit', 'disti_weight'):
|
||||
w = form.fields[key]
|
||||
|
||||
def write_model(text: str, key: str):
|
||||
print(f'{text}')
|
||||
setattr(alloc, key, text)
|
||||
print(alloc)
|
||||
|
||||
w.currentTextChanged.connect(
|
||||
partial(
|
||||
write_model,
|
||||
key=key,
|
||||
)
|
||||
)
|
||||
|
||||
mode = OrderMode(
|
||||
chart,
|
||||
|
@ -512,6 +537,7 @@ async def run_order_mode(
|
|||
multistatus,
|
||||
pp_tracker,
|
||||
allocator=alloc,
|
||||
pane=order_pane,
|
||||
)
|
||||
|
||||
# TODO: create a mode "manager" of sorts?
|
||||
|
@ -529,7 +555,6 @@ async def run_order_mode(
|
|||
pp_tracker.update(msg, position=pp_tracker.startup_pp)
|
||||
pp_tracker.update(msg)
|
||||
|
||||
|
||||
# default entry sizing
|
||||
if asset_type in ('stock', 'crypto', 'forex'):
|
||||
alloc.size_unit = '$ size'
|
||||
|
@ -544,11 +569,11 @@ async def run_order_mode(
|
|||
pp_tracker.pane.fields['slots'].setText(str(alloc.slots))
|
||||
|
||||
# make entry step 1.0
|
||||
alloc.size = slots
|
||||
pp_tracker.pane.fields['size'].setText(str(alloc.size))
|
||||
alloc.units_size = slots
|
||||
pp_tracker.pane.fields['size'].setText(str(alloc.units_size))
|
||||
|
||||
# make fill bar and positioning snapshot
|
||||
pp_tracker.init_status_ui()
|
||||
order_pane.init_status_ui()
|
||||
|
||||
# TODO: this should go onto some sort of
|
||||
# data-view strimg thinger..right?
|
||||
|
@ -572,7 +597,11 @@ async def run_order_mode(
|
|||
async with (
|
||||
chart.view.open_async_input_handler(),
|
||||
|
||||
# TODO: config form handler nursery
|
||||
# pp pane kb inputs
|
||||
open_form_input_handling(
|
||||
form,
|
||||
focus_next=chart.linked.godwidget,
|
||||
),
|
||||
|
||||
):
|
||||
|
||||
|
|
Loading…
Reference in New Issue