-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mxmn from m4 #342
Mxmn from m4 #342
Changes from all commits
d92ff9c
4ad7b07
191b94b
7a33ba6
e977597
920a394
783914c
a425c29
c620517
49c720a
dd2a9f7
03a7940
147ceca
ed2c962
1c56120
be7afda
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -223,14 +223,20 @@ def ds_m4( | |
assert frames >= (xrange / uppx) | ||
|
||
# call into ``numba`` | ||
nb, i_win, y_out = _m4( | ||
( | ||
nb, | ||
x_out, | ||
y_out, | ||
ymn, | ||
ymx, | ||
) = _m4( | ||
x, | ||
y, | ||
|
||
frames, | ||
|
||
# TODO: see func below.. | ||
# i_win, | ||
# x_out, | ||
# y_out, | ||
|
||
# first index in x data to start at | ||
|
@@ -243,10 +249,11 @@ def ds_m4( | |
# filter out any overshoot in the input allocation arrays by | ||
# removing zero-ed tail entries which should start at a certain | ||
# index. | ||
i_win = i_win[i_win != 0] | ||
y_out = y_out[:i_win.size] | ||
x_out = x_out[x_out != 0] | ||
y_out = y_out[:x_out.size] | ||
|
||
return nb, i_win, y_out | ||
# print(f'M4 output ymn, ymx: {ymn},{ymx}') | ||
return nb, x_out, y_out, ymn, ymx | ||
|
||
|
||
@jit( | ||
|
@@ -260,8 +267,8 @@ def _m4( | |
|
||
frames: int, | ||
|
||
# TODO: using this approach by having the ``.zeros()`` alloc lines | ||
# below, in put python was causing segs faults and alloc crashes.. | ||
# TODO: using this approach, having the ``.zeros()`` alloc lines | ||
# below in pure python, there were segs faults and alloc crashes.. | ||
# we might need to see how it behaves with shm arrays and consider | ||
# allocating them once at startup? | ||
|
||
|
@@ -274,14 +281,22 @@ def _m4( | |
x_start: int, | ||
step: float, | ||
|
||
) -> int: | ||
# nbins = len(i_win) | ||
# count = len(xs) | ||
) -> tuple[ | ||
int, | ||
np.ndarray, | ||
np.ndarray, | ||
float, | ||
float, | ||
]: | ||
''' | ||
Implementation of the m4 algorithm in ``numba``: | ||
http://www.vldb.org/pvldb/vol7/p797-jugel.pdf | ||
|
||
''' | ||
# these are pre-allocated and mutated by ``numba`` | ||
# code in-place. | ||
y_out = np.zeros((frames, 4), ys.dtype) | ||
i_win = np.zeros(frames, xs.dtype) | ||
x_out = np.zeros(frames, xs.dtype) | ||
|
||
bincount = 0 | ||
x_left = x_start | ||
|
@@ -295,24 +310,34 @@ def _m4( | |
|
||
# set all bins in the left-most entry to the starting left-most x value | ||
# (aka a row broadcast). | ||
i_win[bincount] = x_left | ||
x_out[bincount] = x_left | ||
# set all y-values to the first value passed in. | ||
y_out[bincount] = ys[0] | ||
|
||
# full input y-data mx and mn | ||
mx: float = -np.inf | ||
mn: float = np.inf | ||
|
||
# compute OHLC style max / min values per window sized x-frame. | ||
for i in range(len(xs)): | ||
|
||
x = xs[i] | ||
y = ys[i] | ||
|
||
if x < x_left + step: # the current window "step" is [bin, bin+1) | ||
y_out[bincount, 1] = min(y, y_out[bincount, 1]) | ||
y_out[bincount, 2] = max(y, y_out[bincount, 2]) | ||
ymn = y_out[bincount, 1] = min(y, y_out[bincount, 1]) | ||
ymx = y_out[bincount, 2] = max(y, y_out[bincount, 2]) | ||
y_out[bincount, 3] = y | ||
mx = max(mx, ymx) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah so just to point to the crux of it all, there's really no point in not capturing these summary max/min values during each downsample cycle and this is now what we take an use in place of "manual" y-range sorting on the source data when possible. |
||
mn = min(mn, ymn) | ||
|
||
else: | ||
# Find the next bin | ||
while x >= x_left + step: | ||
x_left += step | ||
|
||
bincount += 1 | ||
i_win[bincount] = x_left | ||
x_out[bincount] = x_left | ||
y_out[bincount] = y | ||
|
||
return bincount, i_win, y_out | ||
return bincount, x_out, y_out, mn, mx |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -105,6 +105,10 @@ def chart_maxmin( | |
mn, mx = out | ||
|
||
mx_vlm_in_view = 0 | ||
|
||
# TODO: we need to NOT call this to avoid a manual | ||
# np.max/min trigger and especially on the vlm_chart | ||
# flows which aren't shown.. like vlm? | ||
if vlm_chart: | ||
out = vlm_chart.maxmin() | ||
if out: | ||
|
@@ -222,33 +226,9 @@ async def graphics_update_loop( | |
tick_margin = 3 * tick_size | ||
|
||
chart.show() | ||
# view = chart.view | ||
last_quote = time.time() | ||
i_last = ohlcv.index | ||
|
||
# async def iter_drain_quotes(): | ||
# # NOTE: all code below this loop is expected to be synchronous | ||
# # and thus draw instructions are not picked up jntil the next | ||
# # wait / iteration. | ||
# async for quotes in stream: | ||
# while True: | ||
# try: | ||
# moar = stream.receive_nowait() | ||
# except trio.WouldBlock: | ||
# yield quotes | ||
# break | ||
# else: | ||
# for sym, quote in moar.items(): | ||
# ticks_frame = quote.get('ticks') | ||
# if ticks_frame: | ||
# quotes[sym].setdefault( | ||
# 'ticks', []).extend(ticks_frame) | ||
# print('pulled extra') | ||
|
||
# yield quotes | ||
|
||
# async for quotes in iter_drain_quotes(): | ||
|
||
ds = linked.display_state = DisplayState(**{ | ||
'quotes': {}, | ||
'linked': linked, | ||
|
@@ -293,6 +273,7 @@ async def graphics_update_loop( | |
|
||
# chart isn't active/shown so skip render cycle and pause feed(s) | ||
if chart.linked.isHidden(): | ||
print('skipping update') | ||
chart.pause_all_feeds() | ||
continue | ||
|
||
|
@@ -416,10 +397,8 @@ def graphics_update_cycle( | |
) | ||
or trigger_all | ||
): | ||
# TODO: we should track and compute whether the last | ||
# pixel in a curve should show new data based on uppx | ||
# and then iff update curves and shift? | ||
chart.increment_view(steps=i_diff) | ||
# chart.increment_view(steps=i_diff + round(append_diff - uppx)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. left this is in because to me the logic makes sense but for whatever reason it doesn't seem to actually be correct based on testing. Ideally we can get to where there's never an error margin on shifts when optimizing for uppx scaling. |
||
|
||
if vlm_chart: | ||
vlm_chart.increment_view(steps=i_diff) | ||
|
@@ -477,7 +456,6 @@ def graphics_update_cycle( | |
): | ||
chart.update_graphics_from_flow( | ||
chart.name, | ||
# do_append=uppx < update_uppx, | ||
do_append=do_append, | ||
) | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a hitch to avoid blank views on first datums load..
probably should do something more elegant for this eventually?