Drop the open ctx mng; add wip pp label

fsp_feeds
Tyler Goodlet 2021-07-16 18:32:56 -04:00
parent 69091a894f
commit d21112dcd7
2 changed files with 97 additions and 60 deletions

View File

@ -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(

View File

@ -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',