Add order cancellation and submission statuses
Generalize the methods for cancelling groups of orders (all or those under cursor) and add new group status support such that statuses for each cancel or order submission is displayed in the status bar. In the "cancel-all-orders" case, use the new group status stuff.backup_asyncify_input_modes
parent
0c1c18bb94
commit
7d1f9c5102
|
@ -125,7 +125,9 @@ def get_orders(
|
|||
if _orders is None:
|
||||
# setup local ui event streaming channels for request/resp
|
||||
# streamging with EMS daemon
|
||||
_orders = OrderBook(*trio.open_memory_channel(1))
|
||||
_orders = OrderBook(
|
||||
*trio.open_memory_channel(100),
|
||||
)
|
||||
|
||||
return _orders
|
||||
|
||||
|
|
|
@ -28,10 +28,10 @@ import uuid
|
|||
import pyqtgraph as pg
|
||||
from pydantic import BaseModel
|
||||
import trio
|
||||
# from trio_typing import TaskStatus
|
||||
|
||||
from ._graphics._lines import LevelLine, position_line
|
||||
from ._editors import LineEditor, ArrowEditor, _order_lines
|
||||
from ._window import MultiStatus, main_window
|
||||
from ..clearing._client import open_ems, OrderBook
|
||||
from ..data._source import Symbol
|
||||
from ..log import get_logger
|
||||
|
@ -49,18 +49,28 @@ class Position(BaseModel):
|
|||
|
||||
@dataclass
|
||||
class OrderMode:
|
||||
"""Major mode for placing orders on a chart view.
|
||||
'''Major mode for placing orders on a chart view.
|
||||
|
||||
This is the default mode that pairs with "follow mode"
|
||||
(when wathing the rt price update at the current time step)
|
||||
and allows entering orders using the ``a, d, f`` keys and
|
||||
cancelling moused-over orders with the ``c`` key.
|
||||
and allows entering orders using mouse and keyboard.
|
||||
|
||||
"""
|
||||
Current manual:
|
||||
a -> alert
|
||||
s/ctrl -> submission type modifier {on: live, off: dark}
|
||||
f (fill) -> buy limit order
|
||||
d (dump) -> sell limit order
|
||||
c (cancel) -> cancel order under cursor
|
||||
cc -> cancel all submitted orders on chart
|
||||
mouse click and drag -> modify current order under cursor
|
||||
|
||||
'''
|
||||
chart: 'ChartPlotWidget' # type: ignore # noqa
|
||||
book: OrderBook
|
||||
lines: LineEditor
|
||||
arrows: ArrowEditor
|
||||
status_bar: MultiStatus
|
||||
|
||||
_colors = {
|
||||
'alert': 'alert_yellow',
|
||||
'buy': 'buy_green',
|
||||
|
@ -72,7 +82,8 @@ class OrderMode:
|
|||
_position: Dict[str, Any] = field(default_factory=dict)
|
||||
_position_line: dict = None
|
||||
|
||||
key_map: Dict[str, Callable] = field(default_factory=dict)
|
||||
_pending_submissions: dict[str, (LevelLine, Callable)] = field(
|
||||
default_factory=dict)
|
||||
|
||||
def on_position_update(
|
||||
self,
|
||||
|
@ -134,6 +145,13 @@ class OrderMode:
|
|||
|
||||
"""
|
||||
line = self.lines.commit_line(uuid)
|
||||
|
||||
pending = self._pending_submissions.get(uuid)
|
||||
if pending:
|
||||
order_line, func = pending
|
||||
assert order_line is line
|
||||
func()
|
||||
|
||||
return line
|
||||
|
||||
def on_fill(
|
||||
|
@ -191,6 +209,10 @@ class OrderMode:
|
|||
self.lines.remove_line(uuid=uuid)
|
||||
self.chart._cursor.show_xhair()
|
||||
|
||||
pending = self._pending_submissions.pop(uuid, None)
|
||||
if pending:
|
||||
order_line, func = pending
|
||||
func()
|
||||
else:
|
||||
log.warning(
|
||||
f'Received cancel for unsubmitted order {pformat(msg)}'
|
||||
|
@ -245,17 +267,67 @@ class OrderMode:
|
|||
)
|
||||
line.oid = uid
|
||||
|
||||
# enter submission which will be popped once a response
|
||||
# from the EMS is received to move the order to a different# status
|
||||
self._pending_submissions[uid] = (
|
||||
line,
|
||||
self.status_bar.open_status(
|
||||
f'submitting {self._exec_mode}-{action}',
|
||||
final_msg=f'submitted {self._exec_mode}-{action}',
|
||||
clear_on_next=True,
|
||||
)
|
||||
)
|
||||
|
||||
# hook up mouse drag handlers
|
||||
line._on_drag_start = self.order_line_modify_start
|
||||
line._on_drag_end = self.order_line_modify_complete
|
||||
|
||||
return line
|
||||
|
||||
def cancel_order_under_cursor(self) -> None:
|
||||
for line in self.lines.lines_under_cursor():
|
||||
self.book.cancel(uuid=line.oid)
|
||||
def cancel_orders_under_cursor(self) -> list[str]:
|
||||
return self.cancel_orders_from_lines(
|
||||
self.lines.lines_under_cursor()
|
||||
)
|
||||
|
||||
def cancel_all_orders(self) -> list[str]:
|
||||
return self.cancel_orders_from_lines(
|
||||
self.lines.all_lines()
|
||||
)
|
||||
|
||||
def cancel_orders_from_lines(
|
||||
self,
|
||||
lines: list[LevelLine],
|
||||
|
||||
) -> list[str]:
|
||||
|
||||
ids: list = []
|
||||
if lines:
|
||||
key = self.status_bar.open_status(
|
||||
f'cancelling {len(lines)} orders',
|
||||
final_msg=f'cancelled {len(lines)} orders',
|
||||
group_key=True
|
||||
)
|
||||
|
||||
# cancel all active orders and triggers
|
||||
for line in lines:
|
||||
oid = getattr(line, 'oid', None)
|
||||
|
||||
if oid:
|
||||
self._pending_submissions[oid] = (
|
||||
line,
|
||||
self.status_bar.open_status(
|
||||
f'cancelling order {oid[:6]}',
|
||||
group_key=key,
|
||||
),
|
||||
)
|
||||
|
||||
ids.append(oid)
|
||||
self.book.cancel(uuid=oid)
|
||||
|
||||
return ids
|
||||
|
||||
# order-line modify handlers
|
||||
|
||||
def order_line_modify_start(
|
||||
self,
|
||||
line: LevelLine,
|
||||
|
@ -281,13 +353,14 @@ async def open_order_mode(
|
|||
chart: pg.PlotWidget,
|
||||
book: OrderBook,
|
||||
):
|
||||
status_bar: MultiStatus = main_window().status_bar
|
||||
view = chart._vb
|
||||
lines = LineEditor(chart=chart, _order_lines=_order_lines)
|
||||
arrows = ArrowEditor(chart, {})
|
||||
|
||||
log.info("Opening order mode")
|
||||
|
||||
mode = OrderMode(chart, book, lines, arrows)
|
||||
mode = OrderMode(chart, book, lines, arrows, status_bar)
|
||||
view.mode = mode
|
||||
|
||||
asset_type = symbol.type_key
|
||||
|
@ -318,7 +391,6 @@ async def start_order_mode(
|
|||
symbol: Symbol,
|
||||
brokername: str,
|
||||
|
||||
# task_status: TaskStatus[trio.Event] = trio.TASK_STATUS_IGNORED,
|
||||
started: trio.Event,
|
||||
|
||||
) -> None:
|
||||
|
|
Loading…
Reference in New Issue