Add volume plot as default
Toss in support for a "step mode" curve (unfinished atm) and use it to plot from the `volume` field of the ohlcv shm array (if available). changes to make it happen, - dynamically generate the fsp sidepane form from an input config `dict` |_ dynamically generate the underlying `pydantic` model |_ - add a "volume checker" helper func that inspects the shm array - toss in sidepane resize calls to avoid race where the ohlcv array is plotted too slowly compared to the volume and the chart somehow doesn't show.. - drop duplicate rsi2 cruft (previously used to test plots of the shm data)windows_testing_volume
							parent
							
								
									699e670363
								
							
						
					
					
						commit
						168c1eb2a9
					
				| 
						 | 
					@ -326,8 +326,8 @@ class LinkedSplits(QWidget):
 | 
				
			||||||
        #     self.xaxis.hide()
 | 
					        #     self.xaxis.hide()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.splitter = QtWidgets.QSplitter(QtCore.Qt.Vertical)
 | 
					        self.splitter = QtWidgets.QSplitter(QtCore.Qt.Vertical)
 | 
				
			||||||
        self.splitter.setMidLineWidth(1)
 | 
					        self.splitter.setMidLineWidth(0)
 | 
				
			||||||
        self.splitter.setHandleWidth(0)
 | 
					        self.splitter.setHandleWidth(2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.layout = QtWidgets.QVBoxLayout(self)
 | 
					        self.layout = QtWidgets.QVBoxLayout(self)
 | 
				
			||||||
        self.layout.setContentsMargins(0, 0, 0, 0)
 | 
					        self.layout.setContentsMargins(0, 0, 0, 0)
 | 
				
			||||||
| 
						 | 
					@ -341,8 +341,7 @@ class LinkedSplits(QWidget):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set_split_sizes(
 | 
					    def set_split_sizes(
 | 
				
			||||||
        self,
 | 
					        self,
 | 
				
			||||||
        # prop: float = 0.375,  # proportion allocated to consumer subcharts
 | 
					        prop: float = 0.375,  # proportion allocated to consumer subcharts
 | 
				
			||||||
        prop: float = 5/8,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ) -> None:
 | 
					    ) -> None:
 | 
				
			||||||
        '''Set the proportion of space allocated for linked subcharts.
 | 
					        '''Set the proportion of space allocated for linked subcharts.
 | 
				
			||||||
| 
						 | 
					@ -495,8 +494,9 @@ class LinkedSplits(QWidget):
 | 
				
			||||||
        cpw.plotItem.vb.linkedsplits = self
 | 
					        cpw.plotItem.vb.linkedsplits = self
 | 
				
			||||||
        cpw.setFrameStyle(
 | 
					        cpw.setFrameStyle(
 | 
				
			||||||
            QtWidgets.QFrame.StyledPanel
 | 
					            QtWidgets.QFrame.StyledPanel
 | 
				
			||||||
            # | QtWidgets.QFrame.Plain)
 | 
					            # | QtWidgets.QFrame.Plain
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        cpw.hideButtons()
 | 
					        cpw.hideButtons()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # XXX: gives us outline on backside of y-axis
 | 
					        # XXX: gives us outline on backside of y-axis
 | 
				
			||||||
| 
						 | 
					@ -515,7 +515,20 @@ class LinkedSplits(QWidget):
 | 
				
			||||||
            cpw.draw_ohlc(name, array, array_key=array_key)
 | 
					            cpw.draw_ohlc(name, array, array_key=array_key)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        elif style == 'line':
 | 
					        elif style == 'line':
 | 
				
			||||||
            cpw.draw_curve(name, array, array_key=array_key)
 | 
					            cpw.draw_curve(
 | 
				
			||||||
 | 
					                name,
 | 
				
			||||||
 | 
					                array,
 | 
				
			||||||
 | 
					                array_key=array_key,
 | 
				
			||||||
 | 
					                color='default_lightest',
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        elif style == 'step':
 | 
				
			||||||
 | 
					            cpw.draw_curve(
 | 
				
			||||||
 | 
					                name,
 | 
				
			||||||
 | 
					                array,
 | 
				
			||||||
 | 
					                array_key=array_key,
 | 
				
			||||||
 | 
					                step_mode=True,
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            raise ValueError(f"Chart style {style} is currently unsupported")
 | 
					            raise ValueError(f"Chart style {style} is currently unsupported")
 | 
				
			||||||
| 
						 | 
					@ -523,14 +536,7 @@ class LinkedSplits(QWidget):
 | 
				
			||||||
        if not _is_main:
 | 
					        if not _is_main:
 | 
				
			||||||
            # track by name
 | 
					            # track by name
 | 
				
			||||||
            self.subplots[name] = cpw
 | 
					            self.subplots[name] = cpw
 | 
				
			||||||
 | 
					 | 
				
			||||||
            # if sidepane:
 | 
					 | 
				
			||||||
            #     # TODO: use a "panes" collection to manage this?
 | 
					 | 
				
			||||||
            #     qframe.setMaximumWidth(self.chart.sidepane.width())
 | 
					 | 
				
			||||||
            #     qframe.setMinimumWidth(self.chart.sidepane.width())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            self.splitter.addWidget(qframe)
 | 
					            self.splitter.addWidget(qframe)
 | 
				
			||||||
 | 
					 | 
				
			||||||
            # scale split regions
 | 
					            # scale split regions
 | 
				
			||||||
            self.set_split_sizes()
 | 
					            self.set_split_sizes()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -600,7 +606,7 @@ class ChartPlotWidget(pg.PlotWidget):
 | 
				
			||||||
            # parent=None,
 | 
					            # parent=None,
 | 
				
			||||||
            # plotItem=None,
 | 
					            # plotItem=None,
 | 
				
			||||||
            # antialias=True,
 | 
					            # antialias=True,
 | 
				
			||||||
            useOpenGL=True,
 | 
					            # useOpenGL=True,
 | 
				
			||||||
            **kwargs
 | 
					            **kwargs
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        self.name = name
 | 
					        self.name = name
 | 
				
			||||||
| 
						 | 
					@ -784,7 +790,7 @@ class ChartPlotWidget(pg.PlotWidget):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        array_key: Optional[str] = None,
 | 
					        array_key: Optional[str] = None,
 | 
				
			||||||
        overlay: bool = False,
 | 
					        overlay: bool = False,
 | 
				
			||||||
        color: str = 'default_light',
 | 
					        color: Optional[str] = None,
 | 
				
			||||||
        add_label: bool = True,
 | 
					        add_label: bool = True,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        **pdi_kwargs,
 | 
					        **pdi_kwargs,
 | 
				
			||||||
| 
						 | 
					@ -794,6 +800,8 @@ class ChartPlotWidget(pg.PlotWidget):
 | 
				
			||||||
        the input array ``data``.
 | 
					        the input array ``data``.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 | 
					        color = color or self.pen_color or 'default_light'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        _pdi_defaults = {
 | 
					        _pdi_defaults = {
 | 
				
			||||||
            'pen': pg.mkPen(hcolor(color)),
 | 
					            'pen': pg.mkPen(hcolor(color)),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -944,13 +952,13 @@ class ChartPlotWidget(pg.PlotWidget):
 | 
				
			||||||
        yrange: Optional[tuple[float, float]] = None,
 | 
					        yrange: Optional[tuple[float, float]] = None,
 | 
				
			||||||
        range_margin: float = 0.06,
 | 
					        range_margin: float = 0.06,
 | 
				
			||||||
    ) -> None:
 | 
					    ) -> None:
 | 
				
			||||||
        """Set the viewable y-range based on embedded data.
 | 
					        '''Set the viewable y-range based on embedded data.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        This adds auto-scaling like zoom on the scroll wheel such
 | 
					        This adds auto-scaling like zoom on the scroll wheel such
 | 
				
			||||||
        that data always fits nicely inside the current view of the
 | 
					        that data always fits nicely inside the current view of the
 | 
				
			||||||
        data set.
 | 
					        data set.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        """
 | 
					        '''
 | 
				
			||||||
        set_range = True
 | 
					        set_range = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self._static_yrange == 'axis':
 | 
					        if self._static_yrange == 'axis':
 | 
				
			||||||
| 
						 | 
					@ -1003,15 +1011,17 @@ class ChartPlotWidget(pg.PlotWidget):
 | 
				
			||||||
            a = self._arrays['ohlc']
 | 
					            a = self._arrays['ohlc']
 | 
				
			||||||
            ifirst = a[0]['index']
 | 
					            ifirst = a[0]['index']
 | 
				
			||||||
            bars = a[lbar - ifirst:rbar - ifirst + 1]
 | 
					            bars = a[lbar - ifirst:rbar - ifirst + 1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if not len(bars):
 | 
					            if not len(bars):
 | 
				
			||||||
                # likely no data loaded yet or extreme scrolling?
 | 
					                # likely no data loaded yet or extreme scrolling?
 | 
				
			||||||
                log.error(f"WTF bars_range = {lbar}:{rbar}")
 | 
					                log.error(f"WTF bars_range = {lbar}:{rbar}")
 | 
				
			||||||
                return
 | 
					                return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if self.data_key != self.linked.symbol.key:
 | 
					            if self.data_key != self.linked.symbol.key:
 | 
				
			||||||
                bars = a[self.data_key]
 | 
					                bars = bars[self.data_key]
 | 
				
			||||||
                ylow = np.nanmin(bars)
 | 
					                ylow = np.nanmin(bars)
 | 
				
			||||||
                yhigh = np.nanmax((bars))
 | 
					                yhigh = np.nanmax(bars)
 | 
				
			||||||
 | 
					                # print(f'{(ylow, yhigh)}')
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                # just the std ohlc bars
 | 
					                # just the std ohlc bars
 | 
				
			||||||
                ylow = np.nanmin(bars['low'])
 | 
					                ylow = np.nanmin(bars['low'])
 | 
				
			||||||
| 
						 | 
					@ -1072,7 +1082,6 @@ class ChartPlotWidget(pg.PlotWidget):
 | 
				
			||||||
        # TODO: this should go onto some sort of
 | 
					        # TODO: this should go onto some sort of
 | 
				
			||||||
        # data-view strimg thinger..right?
 | 
					        # data-view strimg thinger..right?
 | 
				
			||||||
        ohlc = self._shm.array
 | 
					        ohlc = self._shm.array
 | 
				
			||||||
        # ohlc = chart._shm.array
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # XXX: not sure why the time is so off here
 | 
					        # XXX: not sure why the time is so off here
 | 
				
			||||||
        # looks like we're gonna have to do some fixing..
 | 
					        # looks like we're gonna have to do some fixing..
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,11 +20,10 @@ Real-time display tasks for charting / graphics.
 | 
				
			||||||
'''
 | 
					'''
 | 
				
			||||||
from contextlib import asynccontextmanager
 | 
					from contextlib import asynccontextmanager
 | 
				
			||||||
import time
 | 
					import time
 | 
				
			||||||
from typing import Any
 | 
					 | 
				
			||||||
from types import ModuleType
 | 
					from types import ModuleType
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import numpy as np
 | 
					import numpy as np
 | 
				
			||||||
from pydantic import BaseModel
 | 
					from pydantic import create_model
 | 
				
			||||||
import tractor
 | 
					import tractor
 | 
				
			||||||
import trio
 | 
					import trio
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -345,45 +344,51 @@ async def fan_out_spawn_fsp_daemons(
 | 
				
			||||||
    # blocks here until all fsp actors complete
 | 
					    # blocks here until all fsp actors complete
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class FspConfig(BaseModel):
 | 
					 | 
				
			||||||
    class Config:
 | 
					 | 
				
			||||||
        validate_assignment = True
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    name: str
 | 
					 | 
				
			||||||
    period: int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@asynccontextmanager
 | 
					@asynccontextmanager
 | 
				
			||||||
async def open_sidepane(
 | 
					async def open_sidepane(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    linked: LinkedSplits,
 | 
					    linked: LinkedSplits,
 | 
				
			||||||
    display_name: str,
 | 
					    conf: dict[str, dict[str, str]],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
) -> FspConfig:
 | 
					) -> FieldsForm:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    schema = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert len(conf) == 1  # for now
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # add (single) selection widget
 | 
				
			||||||
 | 
					    for display_name, config in conf.items():
 | 
				
			||||||
 | 
					        schema[display_name] = {
 | 
				
			||||||
 | 
					                'label': '**fsp**:',
 | 
				
			||||||
 | 
					                'type': 'select',
 | 
				
			||||||
 | 
					                'default_value': [display_name],
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # add parameters for selection "options"
 | 
				
			||||||
 | 
					        defaults = config.get('params', {})
 | 
				
			||||||
 | 
					        for name, default in defaults.items():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # add to ORM schema
 | 
				
			||||||
 | 
					            schema.update({
 | 
				
			||||||
 | 
					                name: {
 | 
				
			||||||
 | 
					                    'label': f'**{name}**:',
 | 
				
			||||||
 | 
					                    'type': 'edit',
 | 
				
			||||||
 | 
					                    'default_value': default,
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sidepane: FieldsForm = mk_form(
 | 
					    sidepane: FieldsForm = mk_form(
 | 
				
			||||||
        parent=linked.godwidget,
 | 
					        parent=linked.godwidget,
 | 
				
			||||||
        fields_schema={
 | 
					        fields_schema=schema,
 | 
				
			||||||
            'name': {
 | 
					    )
 | 
				
			||||||
                'label': '**fsp**:',
 | 
					 | 
				
			||||||
                'type': 'select',
 | 
					 | 
				
			||||||
                'default_value': [
 | 
					 | 
				
			||||||
                    f'{display_name}'
 | 
					 | 
				
			||||||
                ],
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # TODO: generate this from input map
 | 
					    # https://pydantic-docs.helpmanual.io/usage/models/#dynamic-model-creation
 | 
				
			||||||
            'period': {
 | 
					    FspConfig = create_model(
 | 
				
			||||||
                'label': '**period**:',
 | 
					        'FspConfig',
 | 
				
			||||||
                'type': 'edit',
 | 
					 | 
				
			||||||
                'default_value': 14,
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    sidepane.model = FspConfig(
 | 
					 | 
				
			||||||
        name=display_name,
 | 
					        name=display_name,
 | 
				
			||||||
        period=14,
 | 
					        **defaults,
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					    sidepane.model = FspConfig()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # just a logger for now until we get fsp configs up and running.
 | 
					    # just a logger for now until we get fsp configs up and running.
 | 
				
			||||||
    async def settings_change(key: str, value: str) -> bool:
 | 
					    async def settings_change(key: str, value: str) -> bool:
 | 
				
			||||||
| 
						 | 
					@ -410,7 +415,7 @@ async def run_fsp(
 | 
				
			||||||
    src_shm: ShmArray,
 | 
					    src_shm: ShmArray,
 | 
				
			||||||
    fsp_func_name: str,
 | 
					    fsp_func_name: str,
 | 
				
			||||||
    display_name: str,
 | 
					    display_name: str,
 | 
				
			||||||
    conf: dict[str, Any],
 | 
					    conf: dict[str, dict],
 | 
				
			||||||
    group_status_key: str,
 | 
					    group_status_key: str,
 | 
				
			||||||
    loglevel: str,
 | 
					    loglevel: str,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -444,7 +449,7 @@ async def run_fsp(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        open_sidepane(
 | 
					        open_sidepane(
 | 
				
			||||||
            linkedsplits,
 | 
					            linkedsplits,
 | 
				
			||||||
            display_name,
 | 
					            {display_name: conf},
 | 
				
			||||||
        ) as sidepane,
 | 
					        ) as sidepane,
 | 
				
			||||||
    ):
 | 
					    ):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -457,9 +462,10 @@ async def run_fsp(
 | 
				
			||||||
        if conf.get('overlay'):
 | 
					        if conf.get('overlay'):
 | 
				
			||||||
            chart = linkedsplits.chart
 | 
					            chart = linkedsplits.chart
 | 
				
			||||||
            chart.draw_curve(
 | 
					            chart.draw_curve(
 | 
				
			||||||
                name='vwap',
 | 
					                name=display_name,
 | 
				
			||||||
                data=shm.array,
 | 
					                data=shm.array,
 | 
				
			||||||
                overlay=True,
 | 
					                overlay=True,
 | 
				
			||||||
 | 
					                color='default_light',
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            last_val_sticky = None
 | 
					            last_val_sticky = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -662,22 +668,23 @@ async def maybe_open_vlm_display(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
) -> ChartPlotWidget:
 | 
					) -> ChartPlotWidget:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # make sure that the instrument supports volume history
 | 
					 | 
				
			||||||
    # (sometimes this is not the case for some commodities and
 | 
					 | 
				
			||||||
    # derivatives)
 | 
					 | 
				
			||||||
    # volm = ohlcv.array['volume']
 | 
					 | 
				
			||||||
    # if (
 | 
					 | 
				
			||||||
    #     np.all(np.isin(volm, -1)) or
 | 
					 | 
				
			||||||
    #     np.all(np.isnan(volm))
 | 
					 | 
				
			||||||
    # ):
 | 
					 | 
				
			||||||
    if not has_vlm(ohlcv):
 | 
					    if not has_vlm(ohlcv):
 | 
				
			||||||
        log.warning(f"{linked.symbol.key} does not seem to have volume info")
 | 
					        log.warning(f"{linked.symbol.key} does not seem to have volume info")
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        async with open_sidepane(linked, 'volume') as sidepane:
 | 
					        async with open_sidepane(
 | 
				
			||||||
 | 
					            linked, {
 | 
				
			||||||
 | 
					                'volume': {
 | 
				
			||||||
 | 
					                    'params': {
 | 
				
			||||||
 | 
					                        'price_func': 'ohl3'
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        ) as sidepane:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # built-in $vlm
 | 
					            # built-in $vlm
 | 
				
			||||||
            shm = ohlcv
 | 
					            shm = ohlcv
 | 
				
			||||||
            chart = linked.add_plot(
 | 
					            chart = linked.add_plot(
 | 
				
			||||||
                name='vlm',
 | 
					                name='volume',
 | 
				
			||||||
                array=shm.array,
 | 
					                array=shm.array,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                array_key='volume',
 | 
					                array_key='volume',
 | 
				
			||||||
| 
						 | 
					@ -685,10 +692,10 @@ async def maybe_open_vlm_display(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                # curve by default
 | 
					                # curve by default
 | 
				
			||||||
                ohlc=False,
 | 
					                ohlc=False,
 | 
				
			||||||
 | 
					                style='step',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                # vertical bars
 | 
					                # vertical bars, we do this internally ourselves
 | 
				
			||||||
                # stepMode=True,
 | 
					                # stepMode=True,
 | 
				
			||||||
                # static_yrange=(0, 100),
 | 
					 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # XXX: ONLY for sub-chart fsps, overlays have their
 | 
					            # XXX: ONLY for sub-chart fsps, overlays have their
 | 
				
			||||||
| 
						 | 
					@ -707,9 +714,23 @@ async def maybe_open_vlm_display(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            last_val_sticky.update_from_data(-1, value)
 | 
					            last_val_sticky.update_from_data(-1, value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            chart.update_curve_from_array(
 | 
				
			||||||
 | 
					                'volume',
 | 
				
			||||||
 | 
					                shm.array,
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # size view to data once at outset
 | 
					            # size view to data once at outset
 | 
				
			||||||
            chart._set_yrange()
 | 
					            chart._set_yrange()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # size pain to parent chart
 | 
				
			||||||
 | 
					            # TODO: this appears to nearly fix a bug where the vlm sidepane
 | 
				
			||||||
 | 
					            # could be sized correctly nearly immediately (since the
 | 
				
			||||||
 | 
					            # order pane is already sized), right now it doesn't seem to
 | 
				
			||||||
 | 
					            # fully align until the VWAP fsp-actor comes up...
 | 
				
			||||||
 | 
					            await trio.sleep(0)
 | 
				
			||||||
 | 
					            chart.linked.resize_sidepanes()
 | 
				
			||||||
 | 
					            await trio.sleep(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            yield chart
 | 
					            yield chart
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -809,20 +830,11 @@ async def display_symbol_data(
 | 
				
			||||||
        fsp_conf = {
 | 
					        fsp_conf = {
 | 
				
			||||||
            'rsi': {
 | 
					            'rsi': {
 | 
				
			||||||
                'fsp_func_name': 'rsi',
 | 
					                'fsp_func_name': 'rsi',
 | 
				
			||||||
                'period': 14,
 | 
					                'params': {'period': 14},
 | 
				
			||||||
                'chart_kwargs': {
 | 
					                'chart_kwargs': {
 | 
				
			||||||
                    'static_yrange': (0, 100),
 | 
					                    'static_yrange': (0, 100),
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            # # test for duplicate fsps on same chart
 | 
					 | 
				
			||||||
            # 'rsi2': {
 | 
					 | 
				
			||||||
            #     'fsp_func_name': 'rsi',
 | 
					 | 
				
			||||||
            #     'period': 14,
 | 
					 | 
				
			||||||
            #     'chart_kwargs': {
 | 
					 | 
				
			||||||
            #         'static_yrange': (0, 100),
 | 
					 | 
				
			||||||
            #     },
 | 
					 | 
				
			||||||
            # },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if has_vlm(ohlcv):
 | 
					        if has_vlm(ohlcv):
 | 
				
			||||||
| 
						 | 
					@ -835,8 +847,14 @@ async def display_symbol_data(
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        async with (
 | 
					        # NOTE: we must immediately tell Qt to show the OHLC chart
 | 
				
			||||||
 | 
					        # to avoid a race where the subplots get added/shown to
 | 
				
			||||||
 | 
					        # the linked set *before* the main price chart!
 | 
				
			||||||
 | 
					        linkedsplits.show()
 | 
				
			||||||
 | 
					        linkedsplits.focus()
 | 
				
			||||||
 | 
					        await trio.sleep(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        async with (
 | 
				
			||||||
            trio.open_nursery() as ln,
 | 
					            trio.open_nursery() as ln,
 | 
				
			||||||
        ):
 | 
					        ):
 | 
				
			||||||
            # load initial fsp chain (otherwise known as "indicators")
 | 
					            # load initial fsp chain (otherwise known as "indicators")
 | 
				
			||||||
| 
						 | 
					@ -868,10 +886,7 @@ async def display_symbol_data(
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            async with (
 | 
					            async with (
 | 
				
			||||||
                # XXX: this slipped in during a commits refacotr,
 | 
					                maybe_open_vlm_display(linkedsplits, ohlcv),
 | 
				
			||||||
                # it's actually landing proper in #231
 | 
					 | 
				
			||||||
                # maybe_open_vlm_display(linkedsplits, ohlcv),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                open_order_mode(
 | 
					                open_order_mode(
 | 
				
			||||||
                    feed,
 | 
					                    feed,
 | 
				
			||||||
                    chart,
 | 
					                    chart,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue