Add global `i_step` per overlay to `DisplayState`
Using a global "last index step" (via module var) obviously has problems when working with multiple feed sets in a single global app instance: any separate feed-set will be incremented according to an app-global index-step and thus won't correctly calc per-feed-set-step update info. Impl deatz: - drop `DisplayState.incr_info()` (since previously moved to `Viz`) and call that method on each appropriate `Viz` instance where necessary; further ensure the appropriate `DisplayState` instance is passed in to each call and make sure to pass a `state: DisplayState`. - add `DisplayState.hist_vars: dict` for history chart (sets) to determine the per-feed (not set) current slow chart (time) step. - add `DisplayState.globalz: dict` to house a common per-feed-set state and use it inside the new `Viz.incr_info()` such that a `should_increment: bool` can be returned and used by the display loop to determine whether to x-shift the current chart.epoch_index_backup
							parent
							
								
									2a4fafcf21
								
							
						
					
					
						commit
						1059520212
					
				| 
						 | 
				
			
			@ -126,10 +126,6 @@ def chart_maxmin(
 | 
			
		|||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
_i_last: int = 0
 | 
			
		||||
_i_last_append: int = 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DisplayState(Struct):
 | 
			
		||||
    '''
 | 
			
		||||
    Chart-local real-time graphics state container.
 | 
			
		||||
| 
						 | 
				
			
			@ -160,105 +156,21 @@ class DisplayState(Struct):
 | 
			
		|||
        'last_mx': 0,
 | 
			
		||||
        'last_mn': 0,
 | 
			
		||||
    }
 | 
			
		||||
    hist_vars: dict[str, Any] = {
 | 
			
		||||
        'tick_margin': 0,
 | 
			
		||||
        'i_last': 0,
 | 
			
		||||
        'i_last_append': 0,
 | 
			
		||||
        'last_mx_vlm': 0,
 | 
			
		||||
        'last_mx': 0,
 | 
			
		||||
        'last_mn': 0,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    globalz: None | dict[str, Any] = None
 | 
			
		||||
 | 
			
		||||
    vlm_chart: Optional[ChartPlotWidget] = None
 | 
			
		||||
    vlm_sticky: Optional[YAxisLabel] = None
 | 
			
		||||
    wap_in_history: bool = False
 | 
			
		||||
 | 
			
		||||
    def incr_info(
 | 
			
		||||
        self,
 | 
			
		||||
        chart: Optional[ChartPlotWidget] = None,
 | 
			
		||||
        shm: Optional[ShmArray] = None,
 | 
			
		||||
        state: Optional[dict] = None,  # pass in a copy if you don't
 | 
			
		||||
 | 
			
		||||
        update_state: bool = True,
 | 
			
		||||
        update_uppx: float = 16,
 | 
			
		||||
        is_1m: bool = False,
 | 
			
		||||
 | 
			
		||||
    ) -> tuple:
 | 
			
		||||
 | 
			
		||||
        shm = shm or self.ohlcv
 | 
			
		||||
        chart = chart or self.chart
 | 
			
		||||
        # state = state or self.vars
 | 
			
		||||
 | 
			
		||||
        if (
 | 
			
		||||
            not update_state
 | 
			
		||||
            and state
 | 
			
		||||
        ):
 | 
			
		||||
            state = state.copy()
 | 
			
		||||
 | 
			
		||||
        # compute the first available graphic's x-units-per-pixel
 | 
			
		||||
        uppx = chart.view.x_uppx()
 | 
			
		||||
 | 
			
		||||
        # NOTE: this used to be implemented in a dedicated
 | 
			
		||||
        # "increment task": ``check_for_new_bars()`` but it doesn't
 | 
			
		||||
        # make sense to do a whole task switch when we can just do
 | 
			
		||||
        # this simple index-diff and all the fsp sub-curve graphics
 | 
			
		||||
        # are diffed on each draw cycle anyway; so updates to the
 | 
			
		||||
        # "curve" length is already automatic.
 | 
			
		||||
 | 
			
		||||
        # increment the view position by the sample offset.
 | 
			
		||||
        # i_step = shm.index
 | 
			
		||||
        i_step = shm.array[-1]['time']
 | 
			
		||||
        # i_diff = i_step - state['i_last']
 | 
			
		||||
        # state['i_last'] = i_step
 | 
			
		||||
        global _i_last, _i_last_append
 | 
			
		||||
        i_diff = i_step - _i_last
 | 
			
		||||
        # update global state
 | 
			
		||||
        if (
 | 
			
		||||
            # state is None
 | 
			
		||||
            not is_1m
 | 
			
		||||
            and i_diff > 0
 | 
			
		||||
        ):
 | 
			
		||||
            _i_last = i_step
 | 
			
		||||
 | 
			
		||||
        # append_diff = i_step - state['i_last_append']
 | 
			
		||||
        append_diff = i_step - _i_last_append
 | 
			
		||||
 | 
			
		||||
        # real-time update necessary?
 | 
			
		||||
        main_viz = chart.get_viz(chart.name)
 | 
			
		||||
        _, _, _, r = main_viz.bars_range()
 | 
			
		||||
        liv = r >= shm.index
 | 
			
		||||
 | 
			
		||||
        # update the "last datum" (aka extending the vizs graphic with
 | 
			
		||||
        # new data) only if the number of unit steps is >= the number of
 | 
			
		||||
        # such unit steps per pixel (aka uppx). Iow, if the zoom level
 | 
			
		||||
        # is such that a datum(s) update to graphics wouldn't span
 | 
			
		||||
        # to a new pixel, we don't update yet.
 | 
			
		||||
        do_append = (
 | 
			
		||||
            append_diff >= uppx
 | 
			
		||||
            and i_diff
 | 
			
		||||
        )
 | 
			
		||||
        if (
 | 
			
		||||
            do_append
 | 
			
		||||
            and not is_1m
 | 
			
		||||
        ):
 | 
			
		||||
            _i_last_append = i_step
 | 
			
		||||
            # fqsn = self.flume.symbol.fqsn
 | 
			
		||||
            # print(
 | 
			
		||||
            #     f'DOING APPEND => {fqsn}\n'
 | 
			
		||||
            #     f'i_step:{i_step}\n'
 | 
			
		||||
            #     f'i_diff:{i_diff}\n'
 | 
			
		||||
            #     f'last:{_i_last}\n'
 | 
			
		||||
            #     f'last_append:{_i_last_append}\n'
 | 
			
		||||
            #     f'append_diff:{append_diff}\n'
 | 
			
		||||
            #     f'r: {r}\n'
 | 
			
		||||
            #     f'liv: {liv}\n'
 | 
			
		||||
            #     f'uppx: {uppx}\n'
 | 
			
		||||
            # )
 | 
			
		||||
 | 
			
		||||
        do_rt_update = uppx < update_uppx
 | 
			
		||||
 | 
			
		||||
        # TODO: pack this into a struct
 | 
			
		||||
        return (
 | 
			
		||||
            uppx,
 | 
			
		||||
            liv,
 | 
			
		||||
            do_append,
 | 
			
		||||
            i_diff,
 | 
			
		||||
            append_diff,
 | 
			
		||||
            do_rt_update,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async def graphics_update_loop(
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -293,7 +205,15 @@ async def graphics_update_loop(
 | 
			
		|||
    hist_chart = godwidget.hist_linked.chart
 | 
			
		||||
    assert hist_chart
 | 
			
		||||
 | 
			
		||||
    # per-viz-set global last index tracking for global chart
 | 
			
		||||
    # view UX incrementing.
 | 
			
		||||
    globalz = {
 | 
			
		||||
        'i_last':  0,
 | 
			
		||||
        'i_last_append': 0,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    dss: dict[str, DisplayState] = {}
 | 
			
		||||
 | 
			
		||||
    for fqsn, flume in feed.flumes.items():
 | 
			
		||||
        ohlcv = flume.rt_shm
 | 
			
		||||
        hist_ohlcv = flume.hist_shm
 | 
			
		||||
| 
						 | 
				
			
			@ -313,7 +233,8 @@ async def graphics_update_loop(
 | 
			
		|||
        )
 | 
			
		||||
        last_price_sticky.show()
 | 
			
		||||
 | 
			
		||||
        slow_pi = hist_chart._vizs[fqsn].plot
 | 
			
		||||
        hist_viz = hist_chart._vizs[fqsn]
 | 
			
		||||
        slow_pi = hist_viz.plot
 | 
			
		||||
        hist_last_price_sticky = slow_pi.getAxis('right')._stickies[fqsn]
 | 
			
		||||
        hist_last_price_sticky.update_from_data(
 | 
			
		||||
            *hist_ohlcv.array[-1][[
 | 
			
		||||
| 
						 | 
				
			
			@ -387,7 +308,8 @@ async def graphics_update_loop(
 | 
			
		|||
                'last_mx_vlm': last_mx_vlm,
 | 
			
		||||
                'last_mx': last_mx,
 | 
			
		||||
                'last_mn': last_mn,
 | 
			
		||||
            }
 | 
			
		||||
            },
 | 
			
		||||
            'globalz': globalz,
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        if vlm_chart:
 | 
			
		||||
| 
						 | 
				
			
			@ -398,15 +320,15 @@ async def graphics_update_loop(
 | 
			
		|||
 | 
			
		||||
        fast_chart.default_view()
 | 
			
		||||
 | 
			
		||||
        ds.hist_vars.update({
 | 
			
		||||
            'i_last_append': i_last,
 | 
			
		||||
            'i_last': i_last,
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        # TODO: probably factor this into some kinda `DisplayState`
 | 
			
		||||
        # API that can be reused at least in terms of pulling view
 | 
			
		||||
        # params (eg ``.bars_range()``).
 | 
			
		||||
        async def increment_history_view():
 | 
			
		||||
            i_last = hist_ohlcv.index
 | 
			
		||||
            state = ds.vars.copy() | {
 | 
			
		||||
                'i_last_append': i_last,
 | 
			
		||||
                'i_last': i_last,
 | 
			
		||||
            }
 | 
			
		||||
            _, hist_step_size_s, _ = flume.get_ds_info()
 | 
			
		||||
 | 
			
		||||
            async with flume.index_stream(
 | 
			
		||||
| 
						 | 
				
			
			@ -431,12 +353,11 @@ async def graphics_update_loop(
 | 
			
		|||
                        i_diff,
 | 
			
		||||
                        append_diff,
 | 
			
		||||
                        do_rt_update,
 | 
			
		||||
                    ) = ds.incr_info(
 | 
			
		||||
                        chart=hist_chart,
 | 
			
		||||
                        shm=ds.hist_ohlcv,
 | 
			
		||||
                        state=state,
 | 
			
		||||
                        should_incr,
 | 
			
		||||
 | 
			
		||||
                    ) = hist_viz.incr_info(
 | 
			
		||||
                        state=ds,
 | 
			
		||||
                        is_1m=True,
 | 
			
		||||
                        # update_state=False,
 | 
			
		||||
                    )
 | 
			
		||||
                    # print(
 | 
			
		||||
                    #     f'liv: {liv}\n'
 | 
			
		||||
| 
						 | 
				
			
			@ -557,40 +478,8 @@ def graphics_update_cycle(
 | 
			
		|||
        i_diff,
 | 
			
		||||
        append_diff,
 | 
			
		||||
        do_rt_update,
 | 
			
		||||
    ) = ds.incr_info()
 | 
			
		||||
 | 
			
		||||
    # don't real-time "shift" the curve to the
 | 
			
		||||
    # left unless we get one of the following:
 | 
			
		||||
    if (
 | 
			
		||||
        (
 | 
			
		||||
            do_append
 | 
			
		||||
            and liv
 | 
			
		||||
        )
 | 
			
		||||
        or trigger_all
 | 
			
		||||
    ):
 | 
			
		||||
        # print(f'INCREMENTING {fqsn}')
 | 
			
		||||
        chart.increment_view(steps=i_diff)
 | 
			
		||||
        main_viz.plot.vb._set_yrange(
 | 
			
		||||
            # yrange=(mn, mx),
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        # NOTE: since vlm and ohlc charts are axis linked now we don't
 | 
			
		||||
        # need the double increment request?
 | 
			
		||||
        # if vlm_chart:
 | 
			
		||||
        #     vlm_chart.increment_view(steps=i_diff)
 | 
			
		||||
 | 
			
		||||
        profiler('view incremented')
 | 
			
		||||
 | 
			
		||||
    # frames_by_type: dict[str, dict] = {}
 | 
			
		||||
    # lasts = {}
 | 
			
		||||
 | 
			
		||||
    # build tick-type "frames" of tick sequences since
 | 
			
		||||
    # likely the tick arrival rate is higher then our
 | 
			
		||||
    # (throttled) quote stream rate.
 | 
			
		||||
 | 
			
		||||
    # iterate in FIFO order per tick-frame
 | 
			
		||||
    # if sym != fqsn:
 | 
			
		||||
    #     continue
 | 
			
		||||
        should_incr,
 | 
			
		||||
    ) = main_viz.incr_info(state=ds)
 | 
			
		||||
 | 
			
		||||
    # TODO: we should only run mxmn when we know
 | 
			
		||||
    # an update is due via ``do_append`` above.
 | 
			
		||||
| 
						 | 
				
			
			@ -621,11 +510,6 @@ def graphics_update_cycle(
 | 
			
		|||
    # graphic.
 | 
			
		||||
    clear_types = _tick_groups['clears']
 | 
			
		||||
 | 
			
		||||
    # XXX: if we wanted to iterate in "latest" (i.e. most
 | 
			
		||||
    # current) tick first order as an optimization where we only
 | 
			
		||||
    # update from the last tick from each type class.
 | 
			
		||||
    # last_clear_updated: bool = False
 | 
			
		||||
 | 
			
		||||
    # update ohlc sampled price bars
 | 
			
		||||
    if (
 | 
			
		||||
        do_rt_update
 | 
			
		||||
| 
						 | 
				
			
			@ -645,6 +529,29 @@ def graphics_update_cycle(
 | 
			
		|||
            # do_append=do_append,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    # don't real-time "shift" the curve to the
 | 
			
		||||
    # left unless we get one of the following:
 | 
			
		||||
    if (
 | 
			
		||||
        (
 | 
			
		||||
            should_incr
 | 
			
		||||
            and do_append
 | 
			
		||||
            and liv
 | 
			
		||||
        )
 | 
			
		||||
        or trigger_all
 | 
			
		||||
    ):
 | 
			
		||||
        # print(f'INCREMENTING {fqsn}')
 | 
			
		||||
        chart.increment_view(steps=i_diff)
 | 
			
		||||
        main_viz.plot.vb._set_yrange(
 | 
			
		||||
            # yrange=(mn, mx),
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        # NOTE: since vlm and ohlc charts are axis linked now we don't
 | 
			
		||||
        # need the double increment request?
 | 
			
		||||
        # if vlm_chart:
 | 
			
		||||
        #     vlm_chart.increment_view(steps=i_diff)
 | 
			
		||||
 | 
			
		||||
        profiler('view incremented')
 | 
			
		||||
 | 
			
		||||
    # from pprint import pformat
 | 
			
		||||
    # frame_counts = {
 | 
			
		||||
    #     typ: len(frame) for typ, frame in frames_by_type.items()
 | 
			
		||||
| 
						 | 
				
			
			@ -765,6 +672,8 @@ def graphics_update_cycle(
 | 
			
		|||
                )
 | 
			
		||||
 | 
			
		||||
        # check if slow chart needs a resize
 | 
			
		||||
 | 
			
		||||
        hist_viz = hist_chart._vizs[fqsn]
 | 
			
		||||
        (
 | 
			
		||||
            _,
 | 
			
		||||
            hist_liv,
 | 
			
		||||
| 
						 | 
				
			
			@ -772,15 +681,13 @@ def graphics_update_cycle(
 | 
			
		|||
            _,
 | 
			
		||||
            _,
 | 
			
		||||
            _,
 | 
			
		||||
        ) = ds.incr_info(
 | 
			
		||||
            chart=hist_chart,
 | 
			
		||||
            shm=ds.hist_ohlcv,
 | 
			
		||||
            update_state=False,
 | 
			
		||||
            _,
 | 
			
		||||
        ) = hist_viz.incr_info(
 | 
			
		||||
            state=ds,
 | 
			
		||||
            is_1m=True,
 | 
			
		||||
        )
 | 
			
		||||
        if hist_liv:
 | 
			
		||||
            viz = hist_chart._vizs[fqsn]
 | 
			
		||||
            viz.plot.vb._set_yrange(
 | 
			
		||||
            hist_viz.plot.vb._set_yrange(
 | 
			
		||||
                # yrange=hist_chart.maxmin(name=fqsn),
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -814,7 +721,7 @@ def graphics_update_cycle(
 | 
			
		|||
        ):
 | 
			
		||||
            viz.draw_last(
 | 
			
		||||
                array_key=curve_name,
 | 
			
		||||
                only_last_uppx=True,
 | 
			
		||||
                # only_last_uppx=True,
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
    # volume chart logic..
 | 
			
		||||
| 
						 | 
				
			
			@ -1207,7 +1114,7 @@ async def display_symbol_data(
 | 
			
		|||
        # for zoom-interaction purposes.
 | 
			
		||||
        hist_chart.get_viz(fqsn).draw_last(
 | 
			
		||||
            array_key=fqsn,
 | 
			
		||||
            only_last_uppx=True,
 | 
			
		||||
            # only_last_uppx=True,
 | 
			
		||||
        )
 | 
			
		||||
        pis.setdefault(fqsn, [None, None])[1] = hist_chart.plotItem
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1306,7 +1213,7 @@ async def display_symbol_data(
 | 
			
		|||
                # for zoom-interaction purposes.
 | 
			
		||||
                viz.draw_last(
 | 
			
		||||
                    array_key=fqsn,
 | 
			
		||||
                    only_last_uppx=True,
 | 
			
		||||
                    # only_last_uppx=True,
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
                hist_pi.vb.maxmin = partial(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue