Compare commits

...

10 Commits

Author SHA1 Message Date
wattygetlood 98df996209 Set isn't serializable on std msgpack 2021-11-03 09:09:43 -04:00
wattygetlood 614089ae84 Only load 4 ib requests worth of bars on windows... 2021-11-03 09:09:43 -04:00
wattygetlood 3c9c772177 Hack search view on windows to 1/2 window height; needs a better solution 2021-11-03 09:09:43 -04:00
wattygetlood a5d38df689 Size the window to aproximately 1/3 the screen space 2021-11-03 09:09:43 -04:00
wattygetlood 02e9240986 No support for notifications (yet) on windows 2021-11-03 09:09:43 -04:00
wattygetlood ad623119fa Fix divide-by-zero when quote read is too fast in throttle task 2021-11-03 09:09:43 -04:00
wattygetlood 48ad97de2c Fix default `brokers.toml` copying since module move 2021-11-03 09:09:43 -04:00
wattygetlood 25eb6f0087 Configure window size based on screen dims on windows 2021-11-03 09:09:43 -04:00
Tyler Goodlet 6c86db8f2c Drop order status bar down a font px size 2021-11-03 09:09:02 -04:00
Tyler Goodlet 704cc80708 Only update curve lengths on non-negative index diffs 2021-11-03 09:09:02 -04:00
10 changed files with 95 additions and 58 deletions

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

@ -137,6 +137,9 @@ class FastAppendCurve(pg.PlotCurveItem):
# print(f"xrange: {self._xrange}")
istart, istop = self._xrange
# compute the length diffs between the first/last index entry in
# the input data and the last indexes we have on record from the
# last time we updated the curve index.
prepend_length = istart - x[0]
append_length = x[-1] - istop
@ -149,7 +152,7 @@ class FastAppendCurve(pg.PlotCurveItem):
# by default we only pull data up to the last (current) index
x_out, y_out = x[:-1], y[:-1]
if self.path is None or prepend_length:
if self.path is None or prepend_length > 0:
self.path = pg.functions.arrayToQPath(
x_out,
y_out,
@ -177,7 +180,7 @@ class FastAppendCurve(pg.PlotCurveItem):
# # self.path.moveTo(new_x[0], new_y[0])
# self.path.connectPath(old_path)
elif append_length:
elif append_length > 0:
if self._step_mode:
new_x, new_y = step_path_arrays_from_1d(
x[-append_length - 2:-1],

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

@ -732,7 +732,7 @@ def mk_order_pane_layout(
) -> FieldsForm:
font_size: int = _font.px_size - 1
font_size: int = _font.px_size - 2
# TODO: maybe just allocate the whole fields form here
# and expect an async ctx entry?

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)
@ -153,23 +158,40 @@ class CompleterView(QTreeView):
self.setStyleSheet(f"font: {size}px")
def resize(self):
#def resizeEvent(self, event: 'QEvent') -> None:
# self.resize_to_results()
# super().resizeEvent(event)
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
# 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)
self.setMaximumSize(self.width() + 10, 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,6 +163,7 @@ 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,6 +430,7 @@ class OrderMode:
# TODO: make this not trash.
# XXX: linux only for now
if platform.system() != "Windows":
result = await trio.run_process(
[
'notify-send',