Compare commits

..

10 Commits

Author SHA1 Message Date
wattygetlood 75faf83004 Set isn't serializable on std msgpack 2021-11-07 13:14:38 -05:00
wattygetlood a270b2e033 Only load 4 ib requests worth of bars on windows... 2021-11-07 13:14:38 -05:00
wattygetlood 09fd8ef742 Hack search view on windows to 1/2 window height; needs a better solution 2021-11-07 13:14:38 -05:00
wattygetlood 422f203fc3 Size the window to aproximately 1/3 the screen space 2021-11-07 13:14:38 -05:00
wattygetlood 8fbd0cd067 No support for notifications (yet) on windows 2021-11-07 13:14:38 -05:00
wattygetlood 68ed1164a1 Fix divide-by-zero when quote read is too fast in throttle task 2021-11-07 13:14:38 -05:00
wattygetlood 2f73f809f1 Fix default `brokers.toml` copying since module move 2021-11-07 13:14:38 -05:00
wattygetlood ba7b01b704 Configure window size based on screen dims on windows 2021-11-07 13:14:38 -05:00
Tyler Goodlet 83299c3a8b Start nts 2021-11-05 15:56:43 -04:00
Tyler Goodlet 0d17f4ff4c Drop print around unshown fsp updates 2021-11-05 15:48:03 -04:00
10 changed files with 117 additions and 58 deletions

28
notes_to_self.rst 100644
View File

@ -0,0 +1,28 @@
Notes to self
=============
chicken scratch we shan't forget, consider this staging
for actual feature issues on wtv git wrapper-provider we're
using (no we shan't stick with GH long term likely).
cool chart features
-------------------
- allow right-click to spawn shell with current in view
data passed to the new process via ``msgpack-numpy``.
- expand OHLC datum to lower time frame.
- auto-highlight current time range on tick feed
features from IB charting
-------------------------
- vlm diffing from ticks and compare when bar arrives from historical
- should help isolate dark vlm / trades
chart ux ideas
--------------
- hotkey to zoom to order intersection (horizontal line) with previous
price levels (+ some margin obvs).
- L1 "lines" (queue size repr) should normalize to some fixed x width
such that when levels with more vlm appear other smaller levels are
scaled down giving an immediate indication of the liquidity diff.

View File

@ -1157,6 +1157,11 @@ async def backfill_bars(
https://github.com/pikers/piker/issues/128
"""
if platform.system() == 'Windows':
log.warning(
'Decreasing history query count to 4 since, windows...')
count = 4
out, fails = await get_bars(sym)
if out is None:
raise RuntimeError("Could not pull currrent history?!")

View File

@ -1046,7 +1046,7 @@ async def _emsd_main(
# signal to client that we're started and deliver
# all known pps and accounts for this ``brokerd``.
await ems_ctx.started((pp_msgs, relay.accounts))
await ems_ctx.started((pp_msgs, list(relay.accounts)))
# establish 2-way stream with requesting order-client and
# begin handling inbound order requests and updates

View File

@ -60,7 +60,7 @@ def repodir():
"""
dirpath = os.path.abspath(
# we're 3 levels down in **this** module file
dirname(dirname(dirname(os.path.realpath(__file__))))
dirname(dirname(os.path.realpath(__file__)))
)
return dirpath
@ -73,7 +73,7 @@ def load(
path = path or get_broker_conf_path()
if not os.path.isfile(path):
shutil.copyfile(
os.path.join(repodir(), 'data/brokers.toml'),
os.path.join(repodir(), 'config', 'brokers.toml'),
path,
)

View File

@ -172,6 +172,7 @@ async def sample_and_broadcast(
# iterate stream delivered by broker
async for quotes in quote_stream:
# TODO: ``numba`` this!
for sym, quote in quotes.items():
@ -184,12 +185,8 @@ async def sample_and_broadcast(
# start writing the shm buffer with appropriate
# trade data
for tick in quote['ticks']:
# TODO: we should probably not write every single
# value to an OHLC sample stream XD
# for a tick stream sure.. but this is excessive..
ticks = quote['ticks']
for tick in ticks:
ticktype = tick['type']
# write trade events to shm last OHLC sample
@ -261,8 +258,7 @@ async def sample_and_broadcast(
except (
trio.BrokenResourceError,
trio.ClosedResourceError,
trio.EndOfChannel,
trio.ClosedResourceError
):
# XXX: do we need to deregister here
# if it's done in the fee bus code?
@ -272,10 +268,6 @@ async def sample_and_broadcast(
f'{stream._ctx.chan.uid} dropped '
'`brokerd`-quotes-feed connection'
)
if tick_throttle:
assert stream.closed()
# await stream.aclose()
subs.remove((stream, tick_throttle))
@ -291,8 +283,12 @@ async def uniform_rate_send(
) -> None:
sleep_period = 1/rate - 0.0001 # 100us
sleep_period = 1/rate - 0.000616
last_send = time.time()
aname = stream._ctx.chan.uid[0]
fsp = False
if 'fsp' in aname:
fsp = True
while True:
@ -312,33 +308,21 @@ async def uniform_rate_send(
sym, next_quote = quote_stream.receive_nowait()
ticks = next_quote.get('ticks')
# XXX: idea for frame type data structure we could use on the
# wire instead of a simple list?
# frames = {
# 'index': ['type_a', 'type_c', 'type_n', 'type_n'],
# 'type_a': [tick0, tick1, tick2, .., tickn],
# 'type_b': [tick0, tick1, tick2, .., tickn],
# 'type_c': [tick0, tick1, tick2, .., tickn],
# ...
# 'type_n': [tick0, tick1, tick2, .., tickn],
# }
if ticks:
first_quote['ticks'].extend(ticks)
except trio.WouldBlock:
now = time.time()
rate = 1 / (now - last_send)
diff = now - last_send
rate = 1 / diff if diff else float('inf')
last_send = now
log.debug(
f'`{sym}` throttled send hz: {round(rate, ndigits=1)}'
)
# log.info(f'{rate} Hz sending quotes') # \n{first_quote}')
# TODO: now if only we could sync this to the display
# rate timing exactly lul
try:
await stream.send({sym: first_quote})
last_send = now
break
except trio.ClosedResourceError:
# if the feed consumer goes down then drop

View File

@ -800,14 +800,11 @@ async def update_chart_from_fsp(
profiler.finish()
# update chart graphics
i = 0
last = time.time()
async for value in stream:
# chart isn't actively shown so just skip render cycle
if chart.linked.isHidden():
print(f'{i} unseen fsp cyclce')
i += 1
continue
else:

View File

@ -61,7 +61,9 @@ _do_overrides()
# XXX: pretty sure none of this shit works on linux as per:
# https://bugreports.qt.io/browse/QTBUG-53022
# it seems to work on windows.. no idea wtf is up.
is_windows = False
if platform.system() == "Windows":
is_windows = True
# Proper high DPI scaling is available in Qt >= 5.6.0. This attibute
# must be set before creating the application
@ -182,6 +184,8 @@ def run_qtractor(
window.main_widget = main_widget
window.setCentralWidget(instance)
if is_windows:
window.configure_to_desktop()
# actually render to screen
window.show()

View File

@ -49,7 +49,7 @@ from PyQt5 import QtCore
from PyQt5 import QtWidgets
from PyQt5.QtCore import (
Qt,
# QSize,
QSize,
QModelIndex,
QItemSelectionModel,
)
@ -112,6 +112,7 @@ class CompleterView(QTreeView):
model = QStandardItemModel(self)
self.labels = labels
self._last_window_h: Optional[int] = None
# a std "tabular" config
self.setItemDelegate(FontScaledDelegate(self))
@ -126,6 +127,10 @@ class CompleterView(QTreeView):
# self.setSizeAdjustPolicy(QAbstractScrollArea.AdjustIgnored)
# ux settings
self.setSizePolicy(
QtWidgets.QSizePolicy.Expanding,
QtWidgets.QSizePolicy.Expanding,
)
self.setItemsExpandable(True)
self.setExpandsOnDoubleClick(False)
self.setAnimated(False)
@ -152,24 +157,41 @@ class CompleterView(QTreeView):
self._font_size = size
self.setStyleSheet(f"font: {size}px")
#def resizeEvent(self, event: 'QEvent') -> None:
# self.resize_to_results()
# super().resizeEvent(event)
def resize(self):
def resize_to_results(self):
model = self.model()
cols = model.columnCount()
for i in range(cols):
self.resizeColumnToContents(i)
# inclusive of search bar and header "rows" in pixel terms
rows = 100
# max_rows = 8 # 6 + search and headers
row_px = self.rowHeight(self.currentIndex())
# print(f'font_h: {font_h}\n px_height: {px_height}')
# TODO: probably make this more general / less hacky
self.setMinimumSize(self.width(), rows * row_px)
self.setMaximumSize(self.width() + 10, rows * row_px)
# we should figure out the exact number of rows to allow
# inclusive of search bar and header "rows", in pixel terms.
window_h = self.window().height()
rows = round(window_h * 0.5 / row_px) - 4
# TODO: the problem here is that this view widget is **not** resizing/scaling
# when the parent layout is adjusted, not sure what exactly is up...
# only "scale up" the results view when the window size has increased/
if not self._last_window_h or self._last_window_h < window_h:
self.setMaximumSize(self.width(), rows * row_px)
self.setMinimumSize(self.width(), rows * row_px)
#elif not self._last_window_h or self._last_window_h > window_h:
# self.setMinimumSize(self.width(), rows * row_px)
# self.setMaximumSize(self.width(), rows * row_px)
self.resize(self.width(), rows * row_px)
self._last_window_h = window_h
self.setFixedWidth(333)
self.update()
def is_selecting_d1(self) -> bool:
cidx = self.selectionModel().currentIndex()
@ -334,7 +356,7 @@ class CompleterView(QTreeView):
else:
model.setItem(idx.row(), 1, QStandardItem())
self.resize()
self.resize_to_results()
return idx
else:
@ -404,7 +426,7 @@ class CompleterView(QTreeView):
def show_matches(self) -> None:
self.show()
self.resize()
self.resize_to_results()
class SearchBar(Edit):
@ -457,7 +479,7 @@ class SearchWidget(QtWidgets.QWidget):
# size it as we specify
self.setSizePolicy(
QtWidgets.QSizePolicy.Fixed,
QtWidgets.QSizePolicy.Fixed,
QtWidgets.QSizePolicy.Expanding,
)
self.godwidget = godwidget

View File

@ -151,8 +151,8 @@ class MainWindow(QtGui.QMainWindow):
# XXX: for tiling wms this should scale
# with the alloted window size.
# TODO: detect for tiling and if untrue set some size?
# size = (300, 500)
size = (0, 0)
size = (300, 500)
#size = (0, 0)
title = 'piker chart (ur symbol is loading bby)'
@ -163,7 +163,8 @@ class MainWindow(QtGui.QMainWindow):
self._status_bar: QStatusBar = None
self._status_label: QLabel = None
self._size: Optional[tuple[int, int]] = None
@property
def mode_label(self) -> QtGui.QLabel:
@ -267,6 +268,22 @@ class MainWindow(QtGui.QMainWindow):
assert screen, "Wow Qt is dumb as shit and has no screen..."
return screen
def configure_to_desktop(
self,
size: Optional[tuple[int, int]] = None,
) -> None:
# https://stackoverflow.com/a/18975846
if not size and not self._size:
app = QtGui.QApplication.instance()
geo = self.current_screen().geometry()
h, w = geo.height(), geo.width()
self.setMaximumSize(w, h)
# use approx 1/3 of the area of the screen by default
self._size = round(w * .666), round(h * .666)
self.resize(*size or self._size)
# singleton app per actor
_qt_win: QtGui.QMainWindow = None

View File

@ -22,6 +22,7 @@ from contextlib import asynccontextmanager
from dataclasses import dataclass, field
from functools import partial
from pprint import pformat
import platform
import time
from typing import Optional, Dict, Callable, Any
import uuid
@ -429,16 +430,17 @@ class OrderMode:
# TODO: make this not trash.
# XXX: linux only for now
result = await trio.run_process(
[
'notify-send',
'-u', 'normal',
'-t', '10000',
'piker',
f'alert: {msg}',
],
)
log.runtime(result)
if platform.system() != "Windows":
result = await trio.run_process(
[
'notify-send',
'-u', 'normal',
'-t', '10000',
'piker',
f'alert: {msg}',
],
)
log.runtime(result)
def on_cancel(
self,