Move order mode handling into charting code

basic_orders
Tyler Goodlet 2021-01-18 20:28:37 -05:00
parent f3ae8db04b
commit e6724b6559
2 changed files with 99 additions and 38 deletions

View File

@ -18,8 +18,10 @@
High level Qt chart widgets.
"""
from pprint import pformat
from typing import Tuple, Dict, Any, Optional, Callable
from functools import partial
import time
from PyQt5 import QtCore, QtGui
import numpy as np
@ -950,23 +952,83 @@ async def _async_main(
linked_charts
)
async with open_order_mode(
chart,
) as order_mode:
# spawn EMS actor-service
async with open_ems(
brokername,
symbol,
) as (book, trades_stream):
# TODO: this should probably be implicitly spawned
# inside the above mngr?
async with open_order_mode(
chart,
book,
) as order_mode:
# spawn EMS actor-service
await n.start(
open_ems,
order_mode,
brokername,
symbol,
)
def get_index(time: float):
# XXX: not sure why the time is so off here
# looks like we're gonna have to do some fixing..
ohlc = chart._shm.array
indexes = ohlc['time'] >= time
# probably where we'll eventually start the user input loop
await trio.sleep_forever()
if any(indexes):
return ohlc['index'][indexes[-1]]
else:
return ohlc['index'][-1]
# Begin order-response streaming
# this is where we receive **back** messages
# about executions **from** the EMS actor
async for msg in trades_stream:
fmsg = pformat(msg)
log.info(f'Received order msg: {fmsg}')
# delete the line from view
oid = msg['oid']
resp = msg['resp']
# response to 'action' request (buy/sell)
if resp in ('dark_submitted', 'broker_submitted'):
# show line label once order is live
order_mode.on_submit(oid)
# resp to 'cancel' request or error condition
# for action request
elif resp in ('broker_cancelled', 'dark_cancelled'):
# delete level line from view
order_mode.on_cancel(oid)
elif resp in ('dark_executed'):
log.info(f'Dark order filled for {fmsg}')
# for alerts add a triangle and remove the
# level line
if msg['cmd']['action'] == 'alert':
# should only be one "fill" for an alert
order_mode.on_fill(
oid,
price=msg['trigger_price'],
arrow_index=get_index(time.time())
)
await order_mode.on_exec(oid, msg)
# response to completed 'action' request for buy/sell
elif resp in ('broker_executed',):
await order_mode.on_exec(oid, msg)
# each clearing tick is responded individually
elif resp in ('broker_filled',):
action = msg['action']
# TODO: some kinda progress system
order_mode.on_fill(
oid,
price=msg['price'],
arrow_index=get_index(msg['broker_time']),
pointing='up' if action == 'buy' else 'down',
)
async def chart_from_quotes(

View File

@ -33,7 +33,7 @@ import numpy as np
from ..log import get_logger
from ._style import _min_points_to_show, hcolor, _font
from ._graphics._lines import level_line, LevelLine
from .._ems import get_orders, OrderBook
from .._ems import OrderBook
log = get_logger(__name__)
@ -370,12 +370,16 @@ class ArrowEditor:
x: float,
y: float,
color='default',
pointing: str = 'up',
pointing: Optional[str] = None,
) -> pg.ArrowItem:
"""Add an arrow graphic to view at given (x, y).
"""
angle = 90 if pointing == 'up' else -90
angle = {
'up': 90,
'down': -90,
None: 0,
}[pointing]
yb = pg.mkBrush(hcolor(color))
arrow = pg.ArrowItem(
@ -431,34 +435,33 @@ class OrderMode:
self.lines.stage_line(color=self._colors[name])
def on_submit(self, uuid: str) -> dict:
"""On order submitted event, commit the order line
and registered order uuid, store ack time stamp.
TODO: annotate order line with submission type ('live' vs.
'dark').
"""
self.lines.commit_line(uuid)
req_msg = self.book._sent_orders.get(uuid)
req_msg['ack_time_ns'] = time.time_ns()
# self.book._confirmed_orders[uuid] = req_msg
return req_msg
def on_fill(
self,
uuid: str,
msg: Dict[str, Any],
price: float,
arrow_index: float,
pointing: Optional[str] = None
) -> None:
log.info(f'New fill\n{pformat(msg)}')
line = self.lines._order_lines[uuid]
# XXX: not sure why the time is so off here
# looks like we're gonna have to do some fixing..
ohlc = self.chart._shm.array
indexes = ohlc['time'] >= msg['broker_time']
if any(indexes):
arrow_index = ohlc['index'][indexes[-1]]
else:
arrow_index = ohlc['index'][-1]
self.arrows.add(
uuid,
arrow_index,
msg['price'],
pointing='up' if msg['action'] == 'buy' else 'down',
price,
pointing=pointing,
color=line.color
)
@ -526,11 +529,12 @@ class OrderMode:
@asynccontextmanager
async def open_order_mode(
chart,
book: OrderBook,
):
# global _order_lines
view = chart._vb
book = get_orders()
# book = get_orders()
lines = LineEditor(view=view, _order_lines=_order_lines, chart=chart)
arrows = ArrowEditor(chart, {})
@ -539,11 +543,6 @@ async def open_order_mode(
mode = OrderMode(chart, book, lines, arrows)
view.mode = mode
# # setup local ui event streaming channels for request/resp
# # streamging with EMS daemon
# global _to_ems, _from_order_book
# _to_ems, _from_order_book = trio.open_memory_channel(100)
try:
yield mode