Drop the open ctx mng; add wip pp label
parent
69091a894f
commit
d21112dcd7
|
@ -65,7 +65,7 @@ from .. import data
|
|||
from ..log import get_logger
|
||||
from ._exec import run_qtractor
|
||||
from ._interaction import ChartView
|
||||
from .order_mode import start_order_mode
|
||||
from .order_mode import run_order_mode
|
||||
from .. import fsp
|
||||
from ..data import feed
|
||||
|
||||
|
@ -1574,7 +1574,7 @@ async def display_symbol_data(
|
|||
linkedsplits
|
||||
)
|
||||
|
||||
await start_order_mode(chart, symbol, provider, order_mode_started)
|
||||
await run_order_mode(chart, symbol, provider, order_mode_started)
|
||||
|
||||
|
||||
async def load_provider_search(
|
||||
|
|
|
@ -18,23 +18,24 @@
|
|||
Chart trading, the only way to scalp.
|
||||
|
||||
"""
|
||||
from contextlib import asynccontextmanager
|
||||
from dataclasses import dataclass, field
|
||||
from pprint import pformat
|
||||
import time
|
||||
from typing import Optional, Dict, Callable, Any
|
||||
import uuid
|
||||
|
||||
import pyqtgraph as pg
|
||||
from pydantic import BaseModel
|
||||
import tractor
|
||||
import trio
|
||||
|
||||
from ._lines import LevelLine, position_line
|
||||
from ._editors import LineEditor, ArrowEditor
|
||||
from ._window import MultiStatus, main_window
|
||||
from ._anchors import marker_right_points
|
||||
from ..clearing._client import open_ems, OrderBook
|
||||
from ..data._source import Symbol
|
||||
from ..log import get_logger
|
||||
from ._editors import LineEditor, ArrowEditor
|
||||
from ._label import Label
|
||||
from ._lines import LevelLine, position_line
|
||||
from ._window import MultiStatus, main_window
|
||||
|
||||
|
||||
log = get_logger(__name__)
|
||||
|
@ -91,6 +92,10 @@ class OrderMode:
|
|||
lines: LineEditor
|
||||
arrows: ArrowEditor
|
||||
status_bar: MultiStatus
|
||||
|
||||
# pp status info
|
||||
label: Label
|
||||
|
||||
name: str = 'order'
|
||||
|
||||
_colors = {
|
||||
|
@ -381,50 +386,11 @@ class OrderMode:
|
|||
)
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def open_order_mode(
|
||||
symbol: Symbol,
|
||||
chart: pg.PlotWidget,
|
||||
book: OrderBook,
|
||||
):
|
||||
status_bar: MultiStatus = main_window().status_bar
|
||||
view = chart._vb
|
||||
lines = LineEditor(chart=chart)
|
||||
arrows = ArrowEditor(chart, {})
|
||||
|
||||
log.info("Opening order mode")
|
||||
|
||||
mode = OrderMode(chart, book, lines, arrows, status_bar)
|
||||
view.mode = mode
|
||||
|
||||
asset_type = symbol.type_key
|
||||
|
||||
if asset_type == 'stock':
|
||||
mode._size = 100.0
|
||||
|
||||
elif asset_type in ('future', 'option', 'futures_option'):
|
||||
mode._size = 1.0
|
||||
|
||||
else: # to be safe
|
||||
mode._size = 1.0
|
||||
|
||||
try:
|
||||
yield mode
|
||||
|
||||
finally:
|
||||
# XXX special teardown handling like for ex.
|
||||
# - cancelling orders if needed?
|
||||
# - closing positions if desired?
|
||||
# - switching special condition orders to safer/more reliable variants
|
||||
log.info("Closing order mode")
|
||||
|
||||
|
||||
async def start_order_mode(
|
||||
async def run_order_mode(
|
||||
|
||||
chart: 'ChartPlotWidget', # noqa
|
||||
symbol: Symbol,
|
||||
brokername: str,
|
||||
|
||||
started: trio.Event,
|
||||
|
||||
) -> None:
|
||||
|
@ -436,19 +402,90 @@ async def start_order_mode(
|
|||
'''
|
||||
done = chart.window().status_bar.open_status('starting order mode..')
|
||||
|
||||
book: OrderBook
|
||||
trades_stream: tractor.MsgStream
|
||||
positions: dict
|
||||
|
||||
# spawn EMS actor-service
|
||||
async with (
|
||||
open_ems(brokername, symbol) as (book, trades_stream, positions),
|
||||
open_order_mode(symbol, chart, book) as order_mode,
|
||||
|
||||
open_ems(brokername, symbol) as (
|
||||
book,
|
||||
trades_stream,
|
||||
positions
|
||||
),
|
||||
|
||||
# # start async input handling for chart's view
|
||||
# # await godwidget._task_stack.enter_async_context(
|
||||
# chart._vb.open_async_input_handler(),
|
||||
):
|
||||
status_bar: MultiStatus = main_window().status_bar
|
||||
view = chart._vb
|
||||
lines = LineEditor(chart=chart)
|
||||
arrows = ArrowEditor(chart, {})
|
||||
|
||||
log.info("Opening order mode")
|
||||
|
||||
pp_label = Label(
|
||||
view=view,
|
||||
color='default_light',
|
||||
|
||||
# this is "static" label
|
||||
# update_on_range_change=False,
|
||||
|
||||
fmt_str='\n'.join((
|
||||
'size: {entry_count}',
|
||||
'% port: {percent_of_port}',
|
||||
# '$val: {base_unit_value}',
|
||||
)),
|
||||
fields={
|
||||
'entry_count': 0,
|
||||
'percent_of_port': 0,
|
||||
'base_unit_value': 0,
|
||||
},
|
||||
)
|
||||
pp_label.render()
|
||||
|
||||
from PyQt5.QtCore import QPointF
|
||||
|
||||
# order line endpoint anchor
|
||||
def bottom_marker_right() -> QPointF:
|
||||
|
||||
return QPointF(
|
||||
marker_right_points(chart)[0] - pp_label.w,
|
||||
view.height() - pp_label.h,
|
||||
)
|
||||
|
||||
# TODO: position on botto if l1/book is on top side
|
||||
pp_label.scene_anchor = bottom_marker_right
|
||||
pp_label.hide()
|
||||
|
||||
mode = OrderMode(
|
||||
chart,
|
||||
book,
|
||||
lines,
|
||||
arrows,
|
||||
status_bar,
|
||||
label=pp_label,
|
||||
)
|
||||
|
||||
view.mode = mode
|
||||
|
||||
asset_type = symbol.type_key
|
||||
|
||||
# default entry sizing
|
||||
if asset_type == 'stock':
|
||||
mode._size = 100.0
|
||||
|
||||
elif asset_type in ('future', 'option', 'futures_option'):
|
||||
mode._size = 1.0
|
||||
|
||||
else: # to be safe
|
||||
mode._size = 1.0
|
||||
|
||||
# update any exising positions
|
||||
for sym, msg in positions.items():
|
||||
order_mode.on_position_update(msg)
|
||||
mode.on_position_update(msg)
|
||||
|
||||
def get_index(time: float):
|
||||
|
||||
|
@ -485,13 +522,13 @@ async def start_order_mode(
|
|||
'position',
|
||||
):
|
||||
# show line label once order is live
|
||||
order_mode.on_position_update(msg)
|
||||
mode.on_position_update(msg)
|
||||
continue
|
||||
|
||||
resp = msg['resp']
|
||||
oid = msg['oid']
|
||||
|
||||
dialog = order_mode.dialogs[oid]
|
||||
dialog = mode.dialogs[oid]
|
||||
# record message to dialog tracking
|
||||
dialog.msgs[oid] = msg
|
||||
|
||||
|
@ -502,7 +539,7 @@ async def start_order_mode(
|
|||
):
|
||||
|
||||
# show line label once order is live
|
||||
order_mode.on_submit(oid)
|
||||
mode.on_submit(oid)
|
||||
|
||||
# resp to 'cancel' request or error condition
|
||||
# for action request
|
||||
|
@ -512,7 +549,7 @@ async def start_order_mode(
|
|||
'dark_cancelled'
|
||||
):
|
||||
# delete level line from view
|
||||
order_mode.on_cancel(oid)
|
||||
mode.on_cancel(oid)
|
||||
|
||||
elif resp in (
|
||||
'dark_triggered'
|
||||
|
@ -524,23 +561,23 @@ async def start_order_mode(
|
|||
):
|
||||
# should only be one "fill" for an alert
|
||||
# add a triangle and remove the level line
|
||||
order_mode.on_fill(
|
||||
mode.on_fill(
|
||||
oid,
|
||||
price=msg['trigger_price'],
|
||||
arrow_index=get_index(time.time()),
|
||||
)
|
||||
order_mode.lines.remove_line(uuid=oid)
|
||||
await order_mode.on_exec(oid, msg)
|
||||
mode.lines.remove_line(uuid=oid)
|
||||
await mode.on_exec(oid, msg)
|
||||
|
||||
# response to completed 'action' request for buy/sell
|
||||
elif resp in (
|
||||
'broker_executed',
|
||||
):
|
||||
# right now this is just triggering a system alert
|
||||
await order_mode.on_exec(oid, msg)
|
||||
await mode.on_exec(oid, msg)
|
||||
|
||||
if msg['brokerd_msg']['remaining'] == 0:
|
||||
order_mode.lines.remove_line(uuid=oid)
|
||||
mode.lines.remove_line(uuid=oid)
|
||||
|
||||
# each clearing tick is responded individually
|
||||
elif resp in ('broker_filled',):
|
||||
|
@ -554,7 +591,7 @@ async def start_order_mode(
|
|||
details = msg['brokerd_msg']
|
||||
|
||||
# TODO: some kinda progress system
|
||||
order_mode.on_fill(
|
||||
mode.on_fill(
|
||||
oid,
|
||||
price=details['price'],
|
||||
pointing='up' if action == 'buy' else 'down',
|
||||
|
|
Loading…
Reference in New Issue