Compare commits
7 Commits
310_plus
...
pause_feed
Author | SHA1 | Date |
---|---|---|
Tyler Goodlet | 73f1a58038 | |
Tyler Goodlet | 5698ac9a78 | |
Tyler Goodlet | 5dc2f93a7e | |
Tyler Goodlet | 1d1b13bce0 | |
Tyler Goodlet | 24c3f84496 | |
Tyler Goodlet | 829820060f | |
Tyler Goodlet | 9fc46fd40d |
|
@ -140,7 +140,7 @@ async def maybe_open_ctx(
|
||||||
yield True, value
|
yield True, value
|
||||||
|
|
||||||
except KeyError:
|
except KeyError:
|
||||||
log.info(f'Allocating new feed for {key}')
|
log.info(f'Allocating new resource for {key}')
|
||||||
|
|
||||||
# **critical section** that should prevent other tasks from
|
# **critical section** that should prevent other tasks from
|
||||||
# checking the cache until complete otherwise the scheduler
|
# checking the cache until complete otherwise the scheduler
|
||||||
|
|
|
@ -576,7 +576,8 @@ async def translate_and_relay_brokerd_events(
|
||||||
# cancelled by the ems controlling client before we
|
# cancelled by the ems controlling client before we
|
||||||
# received this ack, in which case we relay that cancel
|
# received this ack, in which case we relay that cancel
|
||||||
# signal **asap** to the backend broker
|
# signal **asap** to the backend broker
|
||||||
if entry.action == 'cancel':
|
action = getattr(entry, 'action', None)
|
||||||
|
if action and action == 'cancel':
|
||||||
# assign newly providerd broker backend request id
|
# assign newly providerd broker backend request id
|
||||||
entry.reqid = reqid
|
entry.reqid = reqid
|
||||||
|
|
||||||
|
@ -966,10 +967,10 @@ async def _emsd_main(
|
||||||
):
|
):
|
||||||
|
|
||||||
# XXX: this should be initial price quote from target provider
|
# XXX: this should be initial price quote from target provider
|
||||||
first_quote = feed.first_quote
|
first_quote = feed.first_quotes[symbol]
|
||||||
|
|
||||||
book = _router.get_dark_book(broker)
|
book = _router.get_dark_book(broker)
|
||||||
book.lasts[(broker, symbol)] = first_quote[symbol]['last']
|
book.lasts[(broker, symbol)] = first_quote['last']
|
||||||
|
|
||||||
# open a stream with the brokerd backend for order
|
# open a stream with the brokerd backend for order
|
||||||
# flow dialogue
|
# flow dialogue
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# piker: trading gear for hackers
|
# piker: trading gear for hackers
|
||||||
# Copyright (C) 2018-present Tyler Goodlet (in stewardship of piker0)
|
# Copyright (C) 2018-present Tyler Goodlet (in stewardship for piker0)
|
||||||
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU Affero General Public License as published by
|
# it under the terms of the GNU Affero General Public License as published by
|
||||||
|
|
|
@ -192,7 +192,7 @@ async def allocate_persistent_feed(
|
||||||
|
|
||||||
# establish broker backend quote stream
|
# establish broker backend quote stream
|
||||||
# ``stream_quotes()`` is a required backend func
|
# ``stream_quotes()`` is a required backend func
|
||||||
init_msg, first_quote = await bus.nursery.start(
|
init_msg, first_quotes = await bus.nursery.start(
|
||||||
partial(
|
partial(
|
||||||
mod.stream_quotes,
|
mod.stream_quotes,
|
||||||
send_chan=send,
|
send_chan=send,
|
||||||
|
@ -212,7 +212,7 @@ async def allocate_persistent_feed(
|
||||||
|
|
||||||
# XXX: the ``symbol`` here is put into our native piker format (i.e.
|
# XXX: the ``symbol`` here is put into our native piker format (i.e.
|
||||||
# lower case).
|
# lower case).
|
||||||
bus.feeds[symbol.lower()] = (cs, init_msg, first_quote)
|
bus.feeds[symbol.lower()] = (cs, init_msg, first_quotes)
|
||||||
|
|
||||||
if opened:
|
if opened:
|
||||||
# start history backfill task ``backfill_bars()`` is
|
# start history backfill task ``backfill_bars()`` is
|
||||||
|
@ -227,7 +227,7 @@ async def allocate_persistent_feed(
|
||||||
init_msg[symbol]['sample_rate'] = int(delay_s)
|
init_msg[symbol]['sample_rate'] = int(delay_s)
|
||||||
|
|
||||||
# yield back control to starting nursery
|
# yield back control to starting nursery
|
||||||
task_status.started((init_msg, first_quote))
|
task_status.started((init_msg, first_quotes))
|
||||||
|
|
||||||
await feed_is_live.wait()
|
await feed_is_live.wait()
|
||||||
|
|
||||||
|
@ -277,7 +277,7 @@ async def attach_feed_bus(
|
||||||
# service nursery
|
# service nursery
|
||||||
async with bus.task_lock:
|
async with bus.task_lock:
|
||||||
if entry is None:
|
if entry is None:
|
||||||
init_msg, first_quote = await bus.nursery.start(
|
init_msg, first_quotes = await bus.nursery.start(
|
||||||
partial(
|
partial(
|
||||||
allocate_persistent_feed,
|
allocate_persistent_feed,
|
||||||
|
|
||||||
|
@ -294,13 +294,13 @@ async def attach_feed_bus(
|
||||||
)
|
)
|
||||||
assert isinstance(bus.feeds[symbol], tuple)
|
assert isinstance(bus.feeds[symbol], tuple)
|
||||||
|
|
||||||
# XXX: ``first_quote`` may be outdated here if this is secondary
|
# XXX: ``first_quotes`` may be outdated here if this is secondary
|
||||||
# subscriber
|
# subscriber
|
||||||
cs, init_msg, first_quote = bus.feeds[symbol]
|
cs, init_msg, first_quotes = bus.feeds[symbol]
|
||||||
|
|
||||||
# send this even to subscribers to existing feed?
|
# send this even to subscribers to existing feed?
|
||||||
# deliver initial info message a first quote asap
|
# deliver initial info message a first quote asap
|
||||||
await ctx.started((init_msg, first_quote))
|
await ctx.started((init_msg, first_quotes))
|
||||||
|
|
||||||
async with (
|
async with (
|
||||||
ctx.open_stream() as stream,
|
ctx.open_stream() as stream,
|
||||||
|
@ -392,7 +392,7 @@ class Feed:
|
||||||
name: str
|
name: str
|
||||||
shm: ShmArray
|
shm: ShmArray
|
||||||
mod: ModuleType
|
mod: ModuleType
|
||||||
first_quote: dict
|
first_quotes: dict # symbol names to first quote dicts
|
||||||
stream: trio.abc.ReceiveChannel[dict[str, Any]]
|
stream: trio.abc.ReceiveChannel[dict[str, Any]]
|
||||||
|
|
||||||
_brokerd_portal: tractor._portal.Portal
|
_brokerd_portal: tractor._portal.Portal
|
||||||
|
@ -509,7 +509,7 @@ async def open_feed(
|
||||||
|
|
||||||
tick_throttle=tick_throttle,
|
tick_throttle=tick_throttle,
|
||||||
|
|
||||||
) as (ctx, (init_msg, first_quote)),
|
) as (ctx, (init_msg, first_quotes)),
|
||||||
|
|
||||||
ctx.open_stream() as stream,
|
ctx.open_stream() as stream,
|
||||||
|
|
||||||
|
@ -524,7 +524,7 @@ async def open_feed(
|
||||||
name=brokername,
|
name=brokername,
|
||||||
shm=shm,
|
shm=shm,
|
||||||
mod=mod,
|
mod=mod,
|
||||||
first_quote=first_quote,
|
first_quotes=first_quotes,
|
||||||
stream=stream,
|
stream=stream,
|
||||||
_brokerd_portal=portal,
|
_brokerd_portal=portal,
|
||||||
)
|
)
|
||||||
|
|
|
@ -280,14 +280,13 @@ class LinkedSplits(QtWidgets.QWidget):
|
||||||
# self.xaxis.hide()
|
# self.xaxis.hide()
|
||||||
|
|
||||||
self.splitter = QtWidgets.QSplitter(QtCore.Qt.Vertical)
|
self.splitter = QtWidgets.QSplitter(QtCore.Qt.Vertical)
|
||||||
self.splitter.setMidLineWidth(2)
|
self.splitter.setMidLineWidth(1)
|
||||||
self.splitter.setHandleWidth(0)
|
self.splitter.setHandleWidth(0)
|
||||||
|
|
||||||
self.layout = QtWidgets.QVBoxLayout(self)
|
self.layout = QtWidgets.QVBoxLayout(self)
|
||||||
self.layout.setContentsMargins(0, 0, 0, 0)
|
self.layout.setContentsMargins(0, 0, 0, 0)
|
||||||
self.layout.addWidget(self.splitter)
|
self.layout.addWidget(self.splitter)
|
||||||
|
|
||||||
# state tracker?
|
|
||||||
self._symbol: Symbol = None
|
self._symbol: Symbol = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -491,7 +490,6 @@ class ChartPlotWidget(pg.PlotWidget):
|
||||||
**kwargs
|
**kwargs
|
||||||
)
|
)
|
||||||
self.name = name
|
self.name = name
|
||||||
self._lc = linkedsplits
|
|
||||||
self.linked = linkedsplits
|
self.linked = linkedsplits
|
||||||
|
|
||||||
# scene-local placeholder for book graphics
|
# scene-local placeholder for book graphics
|
||||||
|
@ -733,7 +731,7 @@ class ChartPlotWidget(pg.PlotWidget):
|
||||||
|
|
||||||
# if the sticky is for our symbol
|
# if the sticky is for our symbol
|
||||||
# use the tick size precision for display
|
# use the tick size precision for display
|
||||||
sym = self._lc.symbol
|
sym = self.linked.symbol
|
||||||
if name == sym.key:
|
if name == sym.key:
|
||||||
digits = sym.digits()
|
digits = sym.digits()
|
||||||
else:
|
else:
|
||||||
|
@ -983,7 +981,7 @@ async def chart_from_quotes(
|
||||||
|
|
||||||
last, volume = ohlcv.array[-1][['close', 'volume']]
|
last, volume = ohlcv.array[-1][['close', 'volume']]
|
||||||
|
|
||||||
symbol = chart._lc.symbol
|
symbol = chart.linked.symbol
|
||||||
|
|
||||||
l1 = L1Labels(
|
l1 = L1Labels(
|
||||||
chart,
|
chart,
|
||||||
|
@ -1001,7 +999,7 @@ async def chart_from_quotes(
|
||||||
# levels this might be dark volume we need to
|
# levels this might be dark volume we need to
|
||||||
# present differently?
|
# present differently?
|
||||||
|
|
||||||
tick_size = chart._lc.symbol.tick_size
|
tick_size = chart.linked.symbol.tick_size
|
||||||
tick_margin = 2 * tick_size
|
tick_margin = 2 * tick_size
|
||||||
|
|
||||||
last_ask = last_bid = last_clear = time.time()
|
last_ask = last_bid = last_clear = time.time()
|
||||||
|
@ -1010,7 +1008,7 @@ async def chart_from_quotes(
|
||||||
async for quotes in stream:
|
async for quotes in stream:
|
||||||
|
|
||||||
# chart isn't actively shown so just skip render cycle
|
# chart isn't actively shown so just skip render cycle
|
||||||
if chart._lc.isHidden():
|
if chart.linked.isHidden():
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for sym, quote in quotes.items():
|
for sym, quote in quotes.items():
|
||||||
|
@ -1154,6 +1152,8 @@ async def spawn_fsps(
|
||||||
|
|
||||||
linkedsplits.focus()
|
linkedsplits.focus()
|
||||||
|
|
||||||
|
uid = tractor.current_actor().uid
|
||||||
|
|
||||||
# spawns sub-processes which execute cpu bound FSP code
|
# spawns sub-processes which execute cpu bound FSP code
|
||||||
async with tractor.open_nursery(loglevel=loglevel) as n:
|
async with tractor.open_nursery(loglevel=loglevel) as n:
|
||||||
|
|
||||||
|
@ -1174,7 +1174,7 @@ async def spawn_fsps(
|
||||||
# TODO: should `index` be a required internal field?
|
# TODO: should `index` be a required internal field?
|
||||||
fsp_dtype = np.dtype([('index', int), (fsp_func_name, float)])
|
fsp_dtype = np.dtype([('index', int), (fsp_func_name, float)])
|
||||||
|
|
||||||
key = f'{sym}.' + display_name
|
key = f'{sym}.fsp.{display_name}.{".".join(uid)}'
|
||||||
|
|
||||||
# this is all sync currently
|
# this is all sync currently
|
||||||
shm, opened = maybe_open_shm_array(
|
shm, opened = maybe_open_shm_array(
|
||||||
|
@ -1184,9 +1184,10 @@ async def spawn_fsps(
|
||||||
readonly=True,
|
readonly=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
# XXX: fsp may have been opened by a duplicate chart. Error for
|
# XXX: fsp may have been opened by a duplicate chart.
|
||||||
# now until we figure out how to wrap fsps as "feeds".
|
# Error for now until we figure out how to wrap fsps as
|
||||||
# assert opened, f"A chart for {key} likely already exists?"
|
# "feeds". assert opened, f"A chart for {key} likely
|
||||||
|
# already exists?"
|
||||||
|
|
||||||
conf['shm'] = shm
|
conf['shm'] = shm
|
||||||
|
|
||||||
|
@ -1300,7 +1301,7 @@ async def run_fsp(
|
||||||
value = array[fsp_func_name][-1]
|
value = array[fsp_func_name][-1]
|
||||||
last_val_sticky.update_from_data(-1, value)
|
last_val_sticky.update_from_data(-1, value)
|
||||||
|
|
||||||
chart._lc.focus()
|
chart.linked.focus()
|
||||||
|
|
||||||
# works also for overlays in which case data is looked up from
|
# works also for overlays in which case data is looked up from
|
||||||
# internal chart array set....
|
# internal chart array set....
|
||||||
|
@ -1335,7 +1336,7 @@ async def run_fsp(
|
||||||
async for value in stream:
|
async for value in stream:
|
||||||
|
|
||||||
# chart isn't actively shown so just skip render cycle
|
# chart isn't actively shown so just skip render cycle
|
||||||
if chart._lc.isHidden():
|
if chart.linked.isHidden():
|
||||||
continue
|
continue
|
||||||
|
|
||||||
now = time.time()
|
now = time.time()
|
||||||
|
|
|
@ -118,7 +118,7 @@ class LineEditor:
|
||||||
chart = cursor.active_plot
|
chart = cursor.active_plot
|
||||||
y = cursor._datum_xy[1]
|
y = cursor._datum_xy[1]
|
||||||
|
|
||||||
symbol = chart._lc.symbol
|
symbol = chart.linked.symbol
|
||||||
|
|
||||||
# add a "staged" cursor-tracking line to view
|
# add a "staged" cursor-tracking line to view
|
||||||
# and cash it in a a var
|
# and cash it in a a var
|
||||||
|
@ -194,7 +194,7 @@ class LineEditor:
|
||||||
if not line:
|
if not line:
|
||||||
raise RuntimeError("No line is currently staged!?")
|
raise RuntimeError("No line is currently staged!?")
|
||||||
|
|
||||||
sym = chart._lc.symbol
|
sym = chart.linked.symbol
|
||||||
|
|
||||||
line = order_line(
|
line = order_line(
|
||||||
chart,
|
chart,
|
||||||
|
|
|
@ -115,7 +115,7 @@ async def handle_viewmode_inputs(
|
||||||
Qt.Key_Space,
|
Qt.Key_Space,
|
||||||
}
|
}
|
||||||
):
|
):
|
||||||
view._chart._lc.godwidget.search.focus()
|
view._chart.linked.godwidget.search.focus()
|
||||||
|
|
||||||
# esc and ctrl-c
|
# esc and ctrl-c
|
||||||
if key == Qt.Key_Escape or (ctrl and key == Qt.Key_C):
|
if key == Qt.Key_Escape or (ctrl and key == Qt.Key_C):
|
||||||
|
|
|
@ -210,9 +210,6 @@ class Label:
|
||||||
|
|
||||||
assert s_xy == self.txt.pos()
|
assert s_xy == self.txt.pos()
|
||||||
|
|
||||||
def orient_on(self, h: str, v: str) -> None:
|
|
||||||
pass
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def fmt_str(self) -> str:
|
def fmt_str(self) -> str:
|
||||||
return self._fmt_str
|
return self._fmt_str
|
||||||
|
|
|
@ -114,9 +114,7 @@ class LevelLine(pg.InfiniteLine):
|
||||||
self._on_drag_start = lambda l: None
|
self._on_drag_start = lambda l: None
|
||||||
self._on_drag_end = lambda l: None
|
self._on_drag_end = lambda l: None
|
||||||
|
|
||||||
self._y_incr_mult = 1 / chart._lc._symbol.tick_size
|
self._y_incr_mult = 1 / chart.linked.symbol.tick_size
|
||||||
self._last_scene_y: float = 0
|
|
||||||
|
|
||||||
self._right_end_sc: float = 0
|
self._right_end_sc: float = 0
|
||||||
|
|
||||||
def txt_offsets(self) -> Tuple[int, int]:
|
def txt_offsets(self) -> Tuple[int, int]:
|
||||||
|
|
|
@ -121,7 +121,7 @@ class DpiAwareFont:
|
||||||
self._font_inches = inches
|
self._font_inches = inches
|
||||||
|
|
||||||
font_size = math.floor(inches * dpi)
|
font_size = math.floor(inches * dpi)
|
||||||
log.info(
|
log.debug(
|
||||||
f"\nscreen:{screen.name()} with pDPI: {pdpi}, lDPI: {ldpi}"
|
f"\nscreen:{screen.name()} with pDPI: {pdpi}, lDPI: {ldpi}"
|
||||||
f"\nOur best guess font size is {font_size}\n"
|
f"\nOur best guess font size is {font_size}\n"
|
||||||
)
|
)
|
||||||
|
|
|
@ -230,7 +230,7 @@ class MainWindow(QtGui.QMainWindow):
|
||||||
|
|
||||||
for _ in range(3):
|
for _ in range(3):
|
||||||
screen = app.screenAt(self.pos())
|
screen = app.screenAt(self.pos())
|
||||||
print('trying to access QScreen...')
|
log.debug('trying to access QScreen...')
|
||||||
if screen is None:
|
if screen is None:
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -112,7 +112,7 @@ class OrderMode:
|
||||||
) -> None:
|
) -> None:
|
||||||
print(f'Position update {msg}')
|
print(f'Position update {msg}')
|
||||||
|
|
||||||
sym = self.chart._lc._symbol
|
sym = self.chart.linked.symbol
|
||||||
if msg['symbol'].lower() not in sym.key:
|
if msg['symbol'].lower() not in sym.key:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue