@363045841yyt/klinechart-core 0.8.5 → 0.8.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/chartSettings.d.ts +21 -2
- package/dist/config/chartSettings.d.ts.map +1 -1
- package/dist/config/chartSettings.js +9 -1
- package/dist/config/chartSettings.js.map +1 -1
- package/dist/controllers/createChartController.d.ts.map +1 -1
- package/dist/controllers/createChartController.js +50 -3
- package/dist/controllers/createChartController.js.map +1 -1
- package/dist/controllers/types.d.ts +34 -23
- package/dist/controllers/types.d.ts.map +1 -1
- package/dist/data-fetchers/baostock.d.ts +0 -3
- package/dist/data-fetchers/baostock.d.ts.map +1 -1
- package/dist/data-fetchers/baostock.js +0 -1
- package/dist/data-fetchers/baostock.js.map +1 -1
- package/dist/data-fetchers/dataBuffer.d.ts +13 -2
- package/dist/data-fetchers/dataBuffer.d.ts.map +1 -1
- package/dist/data-fetchers/dataBuffer.js +41 -7
- package/dist/data-fetchers/dataBuffer.js.map +1 -1
- package/dist/data-fetchers/dataBufferTypes.d.ts +11 -0
- package/dist/data-fetchers/dataBufferTypes.d.ts.map +1 -0
- package/dist/data-fetchers/dataBufferTypes.js +2 -0
- package/dist/data-fetchers/dataBufferTypes.js.map +1 -0
- package/dist/data-fetchers/fetcherDefinitionRegistry.d.ts +4 -3
- package/dist/data-fetchers/fetcherDefinitionRegistry.d.ts.map +1 -1
- package/dist/data-fetchers/fetcherDefinitionRegistry.js +9 -2
- package/dist/data-fetchers/fetcherDefinitionRegistry.js.map +1 -1
- package/dist/data-fetchers/gotdx/gotdx.d.ts +7 -0
- package/dist/data-fetchers/gotdx/gotdx.d.ts.map +1 -0
- package/dist/data-fetchers/gotdx/gotdx.js +7 -0
- package/dist/data-fetchers/gotdx/gotdx.js.map +1 -0
- package/dist/data-fetchers/gotdx.d.ts +0 -8
- package/dist/data-fetchers/gotdx.d.ts.map +1 -1
- package/dist/data-fetchers/gotdx.js +40 -3
- package/dist/data-fetchers/gotdx.js.map +1 -1
- package/dist/data-fetchers/hundred-mock.d.ts +0 -3
- package/dist/data-fetchers/hundred-mock.d.ts.map +1 -1
- package/dist/data-fetchers/hundred-mock.js +0 -1
- package/dist/data-fetchers/hundred-mock.js.map +1 -1
- package/dist/data-fetchers/index.d.ts +10 -8
- package/dist/data-fetchers/index.d.ts.map +1 -1
- package/dist/data-fetchers/index.js +8 -7
- package/dist/data-fetchers/index.js.map +1 -1
- package/dist/data-fetchers/router.d.ts +2 -0
- package/dist/data-fetchers/router.d.ts.map +1 -1
- package/dist/data-fetchers/router.js +8 -1
- package/dist/data-fetchers/router.js.map +1 -1
- package/dist/data-fetchers/thousand-mock.d.ts +0 -3
- package/dist/data-fetchers/thousand-mock.d.ts.map +1 -1
- package/dist/data-fetchers/thousand-mock.js +0 -1
- package/dist/data-fetchers/thousand-mock.js.map +1 -1
- package/dist/data-fetchers/timeShareBuffer.d.ts +27 -0
- package/dist/data-fetchers/timeShareBuffer.d.ts.map +1 -0
- package/dist/data-fetchers/timeShareBuffer.js +79 -0
- package/dist/data-fetchers/timeShareBuffer.js.map +1 -0
- package/dist/data-fetchers/tradingview.d.ts +0 -8
- package/dist/data-fetchers/tradingview.d.ts.map +1 -1
- package/dist/data-fetchers/tradingview.js +1 -2
- package/dist/data-fetchers/tradingview.js.map +1 -1
- package/dist/data-fetchers/types.d.ts +9 -1
- package/dist/data-fetchers/types.d.ts.map +1 -1
- package/dist/engine/chart.d.ts +29 -1
- package/dist/engine/chart.d.ts.map +1 -1
- package/dist/engine/chart.js +140 -5
- package/dist/engine/chart.js.map +1 -1
- package/dist/engine/chartTypes.d.ts +3 -0
- package/dist/engine/chartTypes.d.ts.map +1 -1
- package/dist/engine/controller/interaction.d.ts +12 -1
- package/dist/engine/controller/interaction.d.ts.map +1 -1
- package/dist/engine/controller/interaction.js +105 -14
- package/dist/engine/controller/interaction.js.map +1 -1
- package/dist/engine/data/chartDataManager.d.ts +38 -11
- package/dist/engine/data/chartDataManager.d.ts.map +1 -1
- package/dist/engine/data/chartDataManager.js +491 -188
- package/dist/engine/data/chartDataManager.js.map +1 -1
- package/dist/engine/draw/pixelAlign.d.ts +0 -27
- package/dist/engine/draw/pixelAlign.d.ts.map +1 -1
- package/dist/engine/draw/pixelAlign.js +1 -1
- package/dist/engine/draw/pixelAlign.js.map +1 -1
- package/dist/engine/indicators/calculators.d.ts +0 -104
- package/dist/engine/indicators/calculators.d.ts.map +1 -1
- package/dist/engine/indicators/calculators.js +77 -171
- package/dist/engine/indicators/calculators.js.map +1 -1
- package/dist/engine/indicators/chartIndicatorManager.d.ts.map +1 -1
- package/dist/engine/indicators/chartIndicatorManager.js +3 -2
- package/dist/engine/indicators/chartIndicatorManager.js.map +1 -1
- package/dist/engine/indicators/ichimokuState.d.ts +2 -0
- package/dist/engine/indicators/ichimokuState.d.ts.map +1 -1
- package/dist/engine/indicators/ichimokuState.js.map +1 -1
- package/dist/engine/indicators/macdState.d.ts +0 -5
- package/dist/engine/indicators/macdState.d.ts.map +1 -1
- package/dist/engine/indicators/macdState.js +1 -1
- package/dist/engine/indicators/macdState.js.map +1 -1
- package/dist/engine/indicators/registerBuiltins.d.ts.map +1 -1
- package/dist/engine/indicators/registerBuiltins.js +1 -0
- package/dist/engine/indicators/registerBuiltins.js.map +1 -1
- package/dist/engine/indicators/rsiState.d.ts +0 -4
- package/dist/engine/indicators/rsiState.d.ts.map +1 -1
- package/dist/engine/indicators/rsiState.js +1 -1
- package/dist/engine/indicators/rsiState.js.map +1 -1
- package/dist/engine/indicators/scheduler.d.ts.map +1 -1
- package/dist/engine/indicators/scheduler.js +1 -7
- package/dist/engine/indicators/scheduler.js.map +1 -1
- package/dist/engine/indicators/visibleStateComposers.d.ts +14 -0
- package/dist/engine/indicators/visibleStateComposers.d.ts.map +1 -1
- package/dist/engine/indicators/visibleStateComposers.js +34 -0
- package/dist/engine/indicators/visibleStateComposers.js.map +1 -1
- package/dist/engine/layout/chartPaneLayout.d.ts +2 -0
- package/dist/engine/layout/chartPaneLayout.d.ts.map +1 -1
- package/dist/engine/layout/chartPaneLayout.js +24 -6
- package/dist/engine/layout/chartPaneLayout.js.map +1 -1
- package/dist/engine/modes/kLineMode.d.ts +37 -0
- package/dist/engine/modes/kLineMode.d.ts.map +1 -0
- package/dist/engine/modes/kLineMode.js +22 -0
- package/dist/engine/modes/kLineMode.js.map +1 -0
- package/dist/engine/modes/timeShareMode.d.ts +37 -0
- package/dist/engine/modes/timeShareMode.d.ts.map +1 -0
- package/dist/engine/modes/timeShareMode.js +59 -0
- package/dist/engine/modes/timeShareMode.js.map +1 -0
- package/dist/engine/modes/types.d.ts +47 -0
- package/dist/engine/modes/types.d.ts.map +1 -0
- package/dist/engine/modes/types.js +2 -0
- package/dist/engine/modes/types.js.map +1 -0
- package/dist/engine/paneRenderer.d.ts +4 -0
- package/dist/engine/paneRenderer.d.ts.map +1 -1
- package/dist/engine/paneRenderer.js +27 -40
- package/dist/engine/paneRenderer.js.map +1 -1
- package/dist/engine/render/chartRenderer.d.ts +4 -23
- package/dist/engine/render/chartRenderer.d.ts.map +1 -1
- package/dist/engine/render/chartRenderer.js +87 -17
- package/dist/engine/render/chartRenderer.js.map +1 -1
- package/dist/engine/renderers/Indicator/atr.d.ts +1 -18
- package/dist/engine/renderers/Indicator/atr.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/atr.js +3 -22
- package/dist/engine/renderers/Indicator/atr.js.map +1 -1
- package/dist/engine/renderers/Indicator/boll.d.ts +1 -4
- package/dist/engine/renderers/Indicator/boll.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/boll.js +3 -18
- package/dist/engine/renderers/Indicator/boll.js.map +1 -1
- package/dist/engine/renderers/Indicator/cci.d.ts +1 -22
- package/dist/engine/renderers/Indicator/cci.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/cci.js +8 -20
- package/dist/engine/renderers/Indicator/cci.js.map +1 -1
- package/dist/engine/renderers/Indicator/chaikinVol.d.ts +1 -7
- package/dist/engine/renderers/Indicator/chaikinVol.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/chaikinVol.js +3 -16
- package/dist/engine/renderers/Indicator/chaikinVol.js.map +1 -1
- package/dist/engine/renderers/Indicator/cmf.d.ts +1 -7
- package/dist/engine/renderers/Indicator/cmf.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/cmf.js +3 -15
- package/dist/engine/renderers/Indicator/cmf.js.map +1 -1
- package/dist/engine/renderers/Indicator/dema.d.ts +1 -7
- package/dist/engine/renderers/Indicator/dema.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/dema.js +3 -17
- package/dist/engine/renderers/Indicator/dema.js.map +1 -1
- package/dist/engine/renderers/Indicator/donchian.d.ts +1 -8
- package/dist/engine/renderers/Indicator/donchian.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/donchian.js +2 -2
- package/dist/engine/renderers/Indicator/donchian.js.map +1 -1
- package/dist/engine/renderers/Indicator/ene.d.ts +1 -12
- package/dist/engine/renderers/Indicator/ene.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/ene.js +3 -18
- package/dist/engine/renderers/Indicator/ene.js.map +1 -1
- package/dist/engine/renderers/Indicator/expma.d.ts +1 -4
- package/dist/engine/renderers/Indicator/expma.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/expma.js +2 -2
- package/dist/engine/renderers/Indicator/expma.js.map +1 -1
- package/dist/engine/renderers/Indicator/fastk.d.ts +1 -22
- package/dist/engine/renderers/Indicator/fastk.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/fastk.js +11 -64
- package/dist/engine/renderers/Indicator/fastk.js.map +1 -1
- package/dist/engine/renderers/Indicator/fib.d.ts +1 -6
- package/dist/engine/renderers/Indicator/fib.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/fib.js +2 -2
- package/dist/engine/renderers/Indicator/fib.js.map +1 -1
- package/dist/engine/renderers/Indicator/hma.d.ts +1 -7
- package/dist/engine/renderers/Indicator/hma.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/hma.js +3 -17
- package/dist/engine/renderers/Indicator/hma.js.map +1 -1
- package/dist/engine/renderers/Indicator/hv.d.ts +1 -7
- package/dist/engine/renderers/Indicator/hv.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/hv.js +3 -16
- package/dist/engine/renderers/Indicator/hv.js.map +1 -1
- package/dist/engine/renderers/Indicator/ichimoku.d.ts +1 -8
- package/dist/engine/renderers/Indicator/ichimoku.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/ichimoku.js +27 -5
- package/dist/engine/renderers/Indicator/ichimoku.js.map +1 -1
- package/dist/engine/renderers/Indicator/kama.d.ts +1 -7
- package/dist/engine/renderers/Indicator/kama.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/kama.js +3 -17
- package/dist/engine/renderers/Indicator/kama.js.map +1 -1
- package/dist/engine/renderers/Indicator/keltner.d.ts +1 -8
- package/dist/engine/renderers/Indicator/keltner.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/keltner.js +2 -2
- package/dist/engine/renderers/Indicator/keltner.js.map +1 -1
- package/dist/engine/renderers/Indicator/kst.d.ts +1 -22
- package/dist/engine/renderers/Indicator/kst.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/kst.js +2 -2
- package/dist/engine/renderers/Indicator/kst.js.map +1 -1
- package/dist/engine/renderers/Indicator/ma.d.ts +1 -4
- package/dist/engine/renderers/Indicator/ma.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/ma.js +1 -1
- package/dist/engine/renderers/Indicator/ma.js.map +1 -1
- package/dist/engine/renderers/Indicator/macd.d.ts +1 -49
- package/dist/engine/renderers/Indicator/macd.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/macd.js +2 -12
- package/dist/engine/renderers/Indicator/macd.js.map +1 -1
- package/dist/engine/renderers/Indicator/mainIndicatorLegend.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/mainIndicatorLegend.js +205 -0
- package/dist/engine/renderers/Indicator/mainIndicatorLegend.js.map +1 -1
- package/dist/engine/renderers/Indicator/mfi.d.ts +1 -7
- package/dist/engine/renderers/Indicator/mfi.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/mfi.js +3 -15
- package/dist/engine/renderers/Indicator/mfi.js.map +1 -1
- package/dist/engine/renderers/Indicator/mom.d.ts +1 -22
- package/dist/engine/renderers/Indicator/mom.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/mom.js +8 -23
- package/dist/engine/renderers/Indicator/mom.js.map +1 -1
- package/dist/engine/renderers/Indicator/obv.d.ts +1 -7
- package/dist/engine/renderers/Indicator/obv.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/obv.js +3 -14
- package/dist/engine/renderers/Indicator/obv.js.map +1 -1
- package/dist/engine/renderers/Indicator/parkinson.d.ts +1 -7
- package/dist/engine/renderers/Indicator/parkinson.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/parkinson.js +3 -16
- package/dist/engine/renderers/Indicator/parkinson.js.map +1 -1
- package/dist/engine/renderers/Indicator/pivot.d.ts +1 -6
- package/dist/engine/renderers/Indicator/pivot.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/pivot.js +2 -2
- package/dist/engine/renderers/Indicator/pivot.js.map +1 -1
- package/dist/engine/renderers/Indicator/pvt.d.ts +1 -7
- package/dist/engine/renderers/Indicator/pvt.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/pvt.js +3 -14
- package/dist/engine/renderers/Indicator/pvt.js.map +1 -1
- package/dist/engine/renderers/Indicator/roc.d.ts +1 -8
- package/dist/engine/renderers/Indicator/roc.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/roc.js +3 -15
- package/dist/engine/renderers/Indicator/roc.js.map +1 -1
- package/dist/engine/renderers/Indicator/rsi.d.ts +0 -32
- package/dist/engine/renderers/Indicator/rsi.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/rsi.js +3 -3
- package/dist/engine/renderers/Indicator/rsi.js.map +1 -1
- package/dist/engine/renderers/Indicator/sar.d.ts +1 -8
- package/dist/engine/renderers/Indicator/sar.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/sar.js +2 -2
- package/dist/engine/renderers/Indicator/sar.js.map +1 -1
- package/dist/engine/renderers/Indicator/scale/indicator_scale.d.ts +2 -0
- package/dist/engine/renderers/Indicator/scale/indicator_scale.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/scale/indicator_scale.js +10 -6
- package/dist/engine/renderers/Indicator/scale/indicator_scale.js.map +1 -1
- package/dist/engine/renderers/Indicator/shared/dashedLines.d.ts +4 -0
- package/dist/engine/renderers/Indicator/shared/dashedLines.d.ts.map +1 -0
- package/dist/engine/renderers/Indicator/shared/dashedLines.js +50 -0
- package/dist/engine/renderers/Indicator/shared/dashedLines.js.map +1 -0
- package/dist/engine/renderers/Indicator/shared/titleInfo.d.ts +14 -0
- package/dist/engine/renderers/Indicator/shared/titleInfo.d.ts.map +1 -0
- package/dist/engine/renderers/Indicator/shared/titleInfo.js +25 -0
- package/dist/engine/renderers/Indicator/shared/titleInfo.js.map +1 -0
- package/dist/engine/renderers/Indicator/shared/webglBand.d.ts +5 -0
- package/dist/engine/renderers/Indicator/shared/webglBand.d.ts.map +1 -0
- package/dist/engine/renderers/Indicator/shared/webglBand.js +17 -0
- package/dist/engine/renderers/Indicator/shared/webglBand.js.map +1 -0
- package/dist/engine/renderers/Indicator/stoch.d.ts +1 -22
- package/dist/engine/renderers/Indicator/stoch.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/stoch.js +5 -46
- package/dist/engine/renderers/Indicator/stoch.js.map +1 -1
- package/dist/engine/renderers/Indicator/structure.d.ts +1 -7
- package/dist/engine/renderers/Indicator/structure.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/structure.js +2 -2
- package/dist/engine/renderers/Indicator/structure.js.map +1 -1
- package/dist/engine/renderers/Indicator/supertrend.d.ts +1 -8
- package/dist/engine/renderers/Indicator/supertrend.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/supertrend.js +2 -2
- package/dist/engine/renderers/Indicator/supertrend.js.map +1 -1
- package/dist/engine/renderers/Indicator/tema.d.ts +1 -7
- package/dist/engine/renderers/Indicator/tema.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/tema.js +3 -17
- package/dist/engine/renderers/Indicator/tema.js.map +1 -1
- package/dist/engine/renderers/Indicator/trix.d.ts +1 -8
- package/dist/engine/renderers/Indicator/trix.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/trix.js +2 -2
- package/dist/engine/renderers/Indicator/trix.js.map +1 -1
- package/dist/engine/renderers/Indicator/vma.d.ts +1 -7
- package/dist/engine/renderers/Indicator/vma.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/vma.js +3 -15
- package/dist/engine/renderers/Indicator/vma.js.map +1 -1
- package/dist/engine/renderers/Indicator/volumeProfile.d.ts +1 -7
- package/dist/engine/renderers/Indicator/volumeProfile.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/volumeProfile.js +2 -2
- package/dist/engine/renderers/Indicator/volumeProfile.js.map +1 -1
- package/dist/engine/renderers/Indicator/vwap.d.ts +1 -7
- package/dist/engine/renderers/Indicator/vwap.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/vwap.js +3 -14
- package/dist/engine/renderers/Indicator/vwap.js.map +1 -1
- package/dist/engine/renderers/Indicator/wma.d.ts +1 -7
- package/dist/engine/renderers/Indicator/wma.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/wma.js +3 -17
- package/dist/engine/renderers/Indicator/wma.js.map +1 -1
- package/dist/engine/renderers/Indicator/wmsr.d.ts +1 -22
- package/dist/engine/renderers/Indicator/wmsr.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/wmsr.js +8 -23
- package/dist/engine/renderers/Indicator/wmsr.js.map +1 -1
- package/dist/engine/renderers/Indicator/zones.d.ts +1 -6
- package/dist/engine/renderers/Indicator/zones.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/zones.js +2 -2
- package/dist/engine/renderers/Indicator/zones.js.map +1 -1
- package/dist/engine/renderers/candle.d.ts +0 -16
- package/dist/engine/renderers/candle.d.ts.map +1 -1
- package/dist/engine/renderers/candle.js +1 -1
- package/dist/engine/renderers/candle.js.map +1 -1
- package/dist/engine/renderers/comparisonLine.d.ts.map +1 -1
- package/dist/engine/renderers/comparisonLine.js +2 -0
- package/dist/engine/renderers/comparisonLine.js.map +1 -1
- package/dist/engine/renderers/crosshair.js +1 -1
- package/dist/engine/renderers/crosshair.js.map +1 -1
- package/dist/engine/renderers/extremaMarkers.d.ts.map +1 -1
- package/dist/engine/renderers/extremaMarkers.js +2 -0
- package/dist/engine/renderers/extremaMarkers.js.map +1 -1
- package/dist/engine/renderers/lastPrice.d.ts.map +1 -1
- package/dist/engine/renderers/lastPrice.js +7 -2
- package/dist/engine/renderers/lastPrice.js.map +1 -1
- package/dist/engine/renderers/leftYAxis.d.ts +11 -0
- package/dist/engine/renderers/leftYAxis.d.ts.map +1 -0
- package/dist/engine/renderers/leftYAxis.js +67 -0
- package/dist/engine/renderers/leftYAxis.js.map +1 -0
- package/dist/engine/renderers/subVolume.d.ts +1 -13
- package/dist/engine/renderers/subVolume.d.ts.map +1 -1
- package/dist/engine/renderers/subVolume.js +1 -1
- package/dist/engine/renderers/subVolume.js.map +1 -1
- package/dist/engine/renderers/timeAxis.d.ts +0 -2
- package/dist/engine/renderers/timeAxis.d.ts.map +1 -1
- package/dist/engine/renderers/timeAxis.js +4 -1
- package/dist/engine/renderers/timeAxis.js.map +1 -1
- package/dist/engine/renderers/timeShare.d.ts +3 -0
- package/dist/engine/renderers/timeShare.d.ts.map +1 -0
- package/dist/engine/renderers/timeShare.js +260 -0
- package/dist/engine/renderers/timeShare.js.map +1 -0
- package/dist/engine/renderers/yAxis.d.ts.map +1 -1
- package/dist/engine/renderers/yAxis.js +9 -1
- package/dist/engine/renderers/yAxis.js.map +1 -1
- package/dist/engine/scale/price.d.ts +0 -7
- package/dist/engine/scale/price.d.ts.map +1 -1
- package/dist/engine/scale/price.js +3 -2
- package/dist/engine/scale/price.js.map +1 -1
- package/dist/engine/theme/fonts.d.ts +0 -2
- package/dist/engine/theme/fonts.d.ts.map +1 -1
- package/dist/engine/theme/fonts.js +1 -1
- package/dist/engine/theme/fonts.js.map +1 -1
- package/dist/engine/utils/klineConfig.d.ts.map +1 -1
- package/dist/engine/utils/klineConfig.js +1 -5
- package/dist/engine/utils/klineConfig.js.map +1 -1
- package/dist/engine/viewport/chartViewportManager.d.ts.map +1 -1
- package/dist/engine/viewport/chartViewportManager.js +6 -5
- package/dist/engine/viewport/chartViewportManager.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/chartBridge.d.ts.map +1 -1
- package/dist/mcp/chartBridge.js +2 -1
- package/dist/mcp/chartBridge.js.map +1 -1
- package/dist/plugin/types.d.ts +1 -0
- package/dist/plugin/types.d.ts.map +1 -1
- package/dist/plugin/types.js.map +1 -1
- package/dist/semantic/types.d.ts +1 -1
- package/dist/semantic/types.d.ts.map +1 -1
- package/dist/tokens/theme-base.d.ts +5 -0
- package/dist/tokens/theme-base.d.ts.map +1 -0
- package/dist/tokens/theme-base.js +31 -0
- package/dist/tokens/theme-base.js.map +1 -0
- package/dist/tokens/theme-china.d.ts.map +1 -1
- package/dist/tokens/theme-china.js +3 -0
- package/dist/tokens/theme-china.js.map +1 -1
- package/dist/tokens/theme-dark.d.ts.map +1 -1
- package/dist/tokens/theme-dark.js +12 -31
- package/dist/tokens/theme-dark.js.map +1 -1
- package/dist/tokens/theme-light.d.ts.map +1 -1
- package/dist/tokens/theme-light.js +11 -30
- package/dist/tokens/theme-light.js.map +1 -1
- package/dist/tokens/types.d.ts +7 -0
- package/dist/tokens/types.d.ts.map +1 -1
- package/dist/types/price.d.ts +8 -0
- package/dist/types/price.d.ts.map +1 -1
- package/dist/types/price.js +4 -0
- package/dist/types/price.js.map +1 -1
- package/dist/utils/dateFormat.d.ts +5 -42
- package/dist/utils/dateFormat.d.ts.map +1 -1
- package/dist/utils/dateFormat.js +24 -4
- package/dist/utils/dateFormat.js.map +1 -1
- package/dist/utils/kLineDraw/axis.d.ts +9 -28
- package/dist/utils/kLineDraw/axis.d.ts.map +1 -1
- package/dist/utils/kLineDraw/axis.js +33 -58
- package/dist/utils/kLineDraw/axis.js.map +1 -1
- package/dist/utils/uuid.d.ts +2 -0
- package/dist/utils/uuid.d.ts.map +1 -0
- package/dist/utils/uuid.js +10 -0
- package/dist/utils/uuid.js.map +1 -0
- package/dist/utils/volumePrice.d.ts +0 -40
- package/dist/utils/volumePrice.d.ts.map +1 -1
- package/dist/utils/volumePrice.js +2 -2
- package/dist/utils/volumePrice.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/src/config/chartSettings.ts +9 -1
- package/src/controllers/createChartController.ts +53 -3
- package/src/controllers/types.ts +36 -17
- package/src/data-fetchers/__tests__/dataBuffer.test.ts +39 -5
- package/src/data-fetchers/baostock.ts +1 -1
- package/src/data-fetchers/dataBuffer.ts +48 -11
- package/src/data-fetchers/dataBufferTypes.ts +11 -0
- package/src/data-fetchers/fetcherDefinitionRegistry.ts +14 -4
- package/src/data-fetchers/gotdx/gotdx.ts +6 -0
- package/src/data-fetchers/gotdx.ts +45 -7
- package/src/data-fetchers/hundred-mock.ts +1 -1
- package/src/data-fetchers/index.ts +10 -20
- package/src/data-fetchers/router.ts +12 -1
- package/src/data-fetchers/thousand-mock.ts +1 -1
- package/src/data-fetchers/timeShareBuffer.ts +92 -0
- package/src/data-fetchers/tradingview.ts +2 -2
- package/src/data-fetchers/types.ts +15 -2
- package/src/engine/__tests__/chart.dpr.test.ts +1 -0
- package/src/engine/chart.ts +157 -7
- package/src/engine/chartTypes.ts +3 -0
- package/src/engine/controller/__tests__/interaction.dpr.test.ts +2 -0
- package/src/engine/controller/interaction.ts +115 -16
- package/src/engine/data/chartDataManager.ts +557 -214
- package/src/engine/draw/pixelAlign.ts +1 -1
- package/src/engine/indicators/__tests__/_propertyAssertions.ts +2 -2
- package/src/engine/indicators/__tests__/ichimoku.test.ts +3 -3
- package/src/engine/indicators/__tests__/registerBuiltins.test.ts +1 -1
- package/src/engine/indicators/calculators.ts +105 -236
- package/src/engine/indicators/chartIndicatorManager.ts +3 -2
- package/src/engine/indicators/ichimokuState.ts +2 -0
- package/src/engine/indicators/macdState.ts +1 -1
- package/src/engine/indicators/registerBuiltins.ts +1 -0
- package/src/engine/indicators/rsiState.ts +1 -1
- package/src/engine/indicators/scheduler.ts +1 -7
- package/src/engine/indicators/visibleStateComposers.ts +51 -0
- package/src/engine/layout/chartPaneLayout.ts +26 -6
- package/src/engine/modes/kLineMode.ts +57 -0
- package/src/engine/modes/timeShareMode.ts +95 -0
- package/src/engine/modes/types.ts +63 -0
- package/src/engine/paneRenderer.ts +37 -46
- package/src/engine/render/chartRenderer.ts +93 -20
- package/src/engine/renderers/Indicator/atr.ts +4 -29
- package/src/engine/renderers/Indicator/boll.ts +3 -24
- package/src/engine/renderers/Indicator/cci.ts +9 -27
- package/src/engine/renderers/Indicator/chaikinVol.ts +3 -23
- package/src/engine/renderers/Indicator/cmf.ts +3 -22
- package/src/engine/renderers/Indicator/dema.ts +5 -26
- package/src/engine/renderers/Indicator/donchian.ts +3 -3
- package/src/engine/renderers/Indicator/ene.ts +3 -24
- package/src/engine/renderers/Indicator/expma.ts +2 -2
- package/src/engine/renderers/Indicator/fastk.ts +12 -95
- package/src/engine/renderers/Indicator/fib.ts +2 -2
- package/src/engine/renderers/Indicator/hma.ts +5 -26
- package/src/engine/renderers/Indicator/hv.ts +3 -23
- package/src/engine/renderers/Indicator/ichimoku.ts +26 -6
- package/src/engine/renderers/Indicator/kama.ts +5 -26
- package/src/engine/renderers/Indicator/keltner.ts +3 -3
- package/src/engine/renderers/Indicator/kst.ts +3 -3
- package/src/engine/renderers/Indicator/ma.ts +1 -1
- package/src/engine/renderers/Indicator/macd.ts +4 -21
- package/src/engine/renderers/Indicator/mainIndicatorLegend.ts +228 -1
- package/src/engine/renderers/Indicator/mfi.ts +3 -22
- package/src/engine/renderers/Indicator/mom.ts +9 -30
- package/src/engine/renderers/Indicator/obv.ts +3 -21
- package/src/engine/renderers/Indicator/parkinson.ts +3 -23
- package/src/engine/renderers/Indicator/pivot.ts +2 -2
- package/src/engine/renderers/Indicator/pvt.ts +3 -21
- package/src/engine/renderers/Indicator/roc.ts +4 -23
- package/src/engine/renderers/Indicator/rsi.ts +4 -4
- package/src/engine/renderers/Indicator/sar.ts +3 -3
- package/src/engine/renderers/Indicator/scale/indicator_scale.ts +11 -4
- package/src/engine/renderers/Indicator/shared/dashedLines.ts +81 -0
- package/src/engine/renderers/Indicator/shared/titleInfo.ts +52 -0
- package/src/engine/renderers/Indicator/shared/webglBand.ts +23 -0
- package/src/engine/renderers/Indicator/stoch.ts +6 -71
- package/src/engine/renderers/Indicator/structure.ts +2 -2
- package/src/engine/renderers/Indicator/supertrend.ts +3 -3
- package/src/engine/renderers/Indicator/tema.ts +5 -26
- package/src/engine/renderers/Indicator/trix.ts +3 -3
- package/src/engine/renderers/Indicator/vma.ts +3 -22
- package/src/engine/renderers/Indicator/volumeProfile.ts +2 -2
- package/src/engine/renderers/Indicator/vwap.ts +3 -21
- package/src/engine/renderers/Indicator/wma.ts +5 -26
- package/src/engine/renderers/Indicator/wmsr.ts +9 -30
- package/src/engine/renderers/Indicator/zones.ts +2 -2
- package/src/engine/renderers/candle.ts +1 -1
- package/src/engine/renderers/comparisonLine.ts +1 -0
- package/src/engine/renderers/crosshair.ts +1 -1
- package/src/engine/renderers/extremaMarkers.ts +1 -0
- package/src/engine/renderers/lastPrice.ts +5 -2
- package/src/engine/renderers/leftYAxis.ts +77 -0
- package/src/engine/renderers/subVolume.ts +3 -3
- package/src/engine/renderers/timeAxis.ts +16 -13
- package/src/engine/renderers/timeShare.ts +271 -0
- package/src/engine/renderers/yAxis.ts +9 -1
- package/src/engine/scale/price.ts +2 -2
- package/src/engine/theme/fonts.ts +1 -1
- package/src/engine/utils/klineConfig.ts +1 -5
- package/src/engine/viewport/chartViewportManager.ts +6 -5
- package/src/index.ts +1 -0
- package/src/mcp/chartBridge.ts +2 -1
- package/src/plugin/types.ts +1 -0
- package/src/semantic/types.ts +1 -1
- package/src/tokens/__tests__/__snapshots__/baseline.test.ts.snap +15 -1
- package/src/tokens/theme-base.ts +36 -0
- package/src/tokens/theme-china.ts +4 -0
- package/src/tokens/theme-dark.ts +13 -33
- package/src/tokens/theme-light.ts +13 -33
- package/src/tokens/types.ts +9 -0
- package/src/types/price.ts +13 -0
- package/src/utils/dateFormat.ts +27 -4
- package/src/utils/kLineDraw/axis.ts +40 -107
- package/src/utils/uuid.ts +8 -0
- package/src/utils/volumePrice.ts +2 -2
- package/src/version.ts +1 -1
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import type { KLineData } from '../../types/price'
|
|
2
|
-
import type { SymbolSpec, DataFetcher } from '../../controllers/types'
|
|
1
|
+
import type { KLineData, TimeShareData } from '../../types/price'
|
|
2
|
+
import type { SymbolSpec, DataFetcher, CustomDataSource } from '../../controllers/types'
|
|
3
3
|
import { createSignal, type Signal } from '../../reactivity/signal'
|
|
4
4
|
import { DataBuffer } from '../../data-fetchers/dataBuffer'
|
|
5
|
+
import { TimeShareBuffer } from '../../data-fetchers/timeShareBuffer'
|
|
6
|
+
import type { DataBufferLike } from '../../data-fetchers/dataBufferTypes'
|
|
7
|
+
import type { TimeShareFetcherFn } from '../../data-fetchers/types'
|
|
5
8
|
import type { ChartDom, Viewport } from '../chartTypes'
|
|
6
9
|
import type { VisibleRange, UpdateLevel } from '../layout/pane'
|
|
7
10
|
import { getVisibleRange } from '../viewport/viewport'
|
|
@@ -27,24 +30,40 @@ export interface DataDependencies {
|
|
|
27
30
|
}
|
|
28
31
|
setPendingIndicatorDataUpdate: (v: boolean) => void
|
|
29
32
|
isPointerDown: () => boolean
|
|
33
|
+
onTimeShareDataReady: (dataLength: number) => void
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const BUF_PRIMARY = 'main'
|
|
37
|
+
const BUF_COMPARISON = 'cmp'
|
|
38
|
+
const BUF_TIMESHARE = 'ts'
|
|
39
|
+
|
|
40
|
+
function bufKey(type: string, symbol: string, period?: string): string {
|
|
41
|
+
if (type === BUF_TIMESHARE) return `ts:${symbol}`
|
|
42
|
+
return `${type}:${symbol}:${period ?? 'daily'}`
|
|
30
43
|
}
|
|
31
44
|
|
|
32
45
|
export class ChartDataManager {
|
|
33
|
-
private _internalData: KLineData[] = []
|
|
34
46
|
private _dataFetcher: DataFetcher | null = null
|
|
35
|
-
private
|
|
36
|
-
|
|
47
|
+
private _timeShareFetcher: TimeShareFetcherFn | null = null
|
|
48
|
+
|
|
49
|
+
private _buffers = new Map<string, any>()
|
|
50
|
+
private _activeBufferKey: string | null = null
|
|
51
|
+
private _activeBufferUnsub: (() => void) | null = null
|
|
52
|
+
|
|
53
|
+
private _dataSignal = createSignal<ReadonlyArray<unknown>>([])
|
|
54
|
+
private _loadingSignal = createSignal<boolean>(false)
|
|
55
|
+
private _symbolsSignal = createSignal<ReadonlyArray<SymbolSpec>>([])
|
|
56
|
+
|
|
57
|
+
private _currentSpec: SymbolSpec | null = null
|
|
58
|
+
|
|
59
|
+
// Comparison-specific state (still needed for rendering pass-through)
|
|
37
60
|
private _comparisonSpecs: SymbolSpec[] = []
|
|
38
61
|
private _comparisonData: Map<string, KLineData[]> = new Map()
|
|
39
|
-
private _comparisonBuffers: Map<string, DataBuffer> = new Map()
|
|
40
|
-
private _comparisonBufferUnsubs: Map<string, () => void> = new Map()
|
|
41
62
|
private _comparisonColors: Map<string, string> = new Map()
|
|
42
63
|
private _comparisonColorsSignal = createSignal<ReadonlyMap<string, string>>(new Map())
|
|
43
|
-
private _comparisonLoadingUnsubs: Map<string, () => void> = new Map()
|
|
44
64
|
private _comparisonLoadingSignal = createSignal<boolean>(false)
|
|
45
|
-
|
|
46
|
-
private
|
|
47
|
-
private _symbolsSignal = createSignal<ReadonlyArray<SymbolSpec>>([])
|
|
65
|
+
// Track loading per-comparison buffer (keyed by buffer key)
|
|
66
|
+
private _cmpLoadingUnsubs = new Map<string, () => void>()
|
|
48
67
|
|
|
49
68
|
private _pendingFetches: Array<{
|
|
50
69
|
source: string
|
|
@@ -71,20 +90,184 @@ export class ChartDataManager {
|
|
|
71
90
|
this.deps = deps
|
|
72
91
|
}
|
|
73
92
|
|
|
93
|
+
// ── Buffer helpers ──
|
|
94
|
+
|
|
95
|
+
private activateBuffer(key: string): void {
|
|
96
|
+
if (this._activeBufferKey === key) return
|
|
97
|
+
this._activeBufferUnsub?.()
|
|
98
|
+
this._activeBufferKey = key
|
|
99
|
+
const buf = this._buffers.get(key) as DataBufferLike | undefined
|
|
100
|
+
if (buf) {
|
|
101
|
+
this._dataSignal.set([...buf.data.peek() as unknown[]])
|
|
102
|
+
this._loadingSignal.set(buf.loading.peek())
|
|
103
|
+
const unsubData = buf.data.subscribe(() => {
|
|
104
|
+
this._dataSignal.set([...buf.data.peek() as unknown[]])
|
|
105
|
+
this.onBufferDataChanged(key)
|
|
106
|
+
})
|
|
107
|
+
const unsubLoading = buf.loading.subscribe(() => {
|
|
108
|
+
this._loadingSignal.set(buf.loading.peek())
|
|
109
|
+
})
|
|
110
|
+
this._activeBufferUnsub = () => {
|
|
111
|
+
unsubData()
|
|
112
|
+
unsubLoading()
|
|
113
|
+
}
|
|
114
|
+
} else {
|
|
115
|
+
this._dataSignal.set([])
|
|
116
|
+
this._loadingSignal.set(false)
|
|
117
|
+
this._activeBufferUnsub = null
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
private disposeBuffer(key: string): void {
|
|
122
|
+
const buf = this._buffers.get(key)
|
|
123
|
+
if (!buf) return
|
|
124
|
+
const unsub = this._cmpLoadingUnsubs.get(key)
|
|
125
|
+
unsub?.()
|
|
126
|
+
const loadingUnsub = this._cmpLoadingUnsubs.get(`loading:${key}`)
|
|
127
|
+
loadingUnsub?.()
|
|
128
|
+
this._cmpLoadingUnsubs.delete(key)
|
|
129
|
+
this._cmpLoadingUnsubs.delete(`loading:${key}`)
|
|
130
|
+
buf.dispose()
|
|
131
|
+
this._buffers.delete(key)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
private getActiveDataBuffer(): DataBuffer | null {
|
|
135
|
+
const buf = this._activeBufferKey ? this._buffers.get(this._activeBufferKey) : null
|
|
136
|
+
return buf instanceof DataBuffer ? buf : null
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private getActiveTimeShareBuffer(): TimeShareBuffer | null {
|
|
140
|
+
const buf = this._activeBufferKey ? this._buffers.get(this._activeBufferKey) : null
|
|
141
|
+
return buf instanceof TimeShareBuffer ? buf : null
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
private getPrimaryDataBuffer(symbol: string, period: string): DataBuffer {
|
|
145
|
+
const key = bufKey(BUF_PRIMARY, symbol, period)
|
|
146
|
+
let buf = this._buffers.get(key) as DataBuffer | undefined
|
|
147
|
+
if (!buf) {
|
|
148
|
+
buf = new DataBuffer()
|
|
149
|
+
buf.setFetcher(this._dataFetcher)
|
|
150
|
+
if (this._dataFetcher) {
|
|
151
|
+
buf.setRequestFetch(this._createBatchHandler(this._dataFetcher))
|
|
152
|
+
}
|
|
153
|
+
this._buffers.set(key, buf)
|
|
154
|
+
} else {
|
|
155
|
+
buf.setFetcher(this._dataFetcher)
|
|
156
|
+
if (this._dataFetcher) {
|
|
157
|
+
buf.setRequestFetch(this._createBatchHandler(this._dataFetcher))
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return buf
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// ── Buffer data change handler ──
|
|
164
|
+
|
|
165
|
+
private onBufferDataChanged(key: string): void {
|
|
166
|
+
const buf = this._buffers.get(key)
|
|
167
|
+
if (!buf) return
|
|
168
|
+
|
|
169
|
+
if (buf instanceof DataBuffer) {
|
|
170
|
+
this.onKLineBufferChanged(key, buf)
|
|
171
|
+
} else if (buf instanceof TimeShareBuffer) {
|
|
172
|
+
this.onTimeShareBufferChanged(key, buf)
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
private onKLineBufferChanged(key: string, buf: DataBuffer): void {
|
|
177
|
+
if (!key.startsWith('main:')) return
|
|
178
|
+
|
|
179
|
+
const prevLength = this.getActiveKLineLength()
|
|
180
|
+
const bufferData = buf.getRawData() as KLineData[]
|
|
181
|
+
const prependedCount = this.pendingPrependedCount
|
|
182
|
+
this.pendingPrependedCount = 0
|
|
183
|
+
|
|
184
|
+
if (this.deps.getCachedScrollLeft() < this.getLeftLoadBufferWidth()) {
|
|
185
|
+
const desiredScrollLeft = this.getLeftLoadBufferWidth()
|
|
186
|
+
this.deps.setCachedScrollLeft(desiredScrollLeft)
|
|
187
|
+
this.deps.setPendingScrollLeft(desiredScrollLeft)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (prevLength === 0 && bufferData.length > 0) {
|
|
191
|
+
const dpr = this.deps.getEffectiveDpr()
|
|
192
|
+
const opt = this.deps.getOption()
|
|
193
|
+
const { unitPx, startXPx } = getPhysicalKLineConfig(opt.kWidth, opt.kGap, dpr)
|
|
194
|
+
const lastKLineEndPx = (startXPx + bufferData.length * unitPx) / dpr
|
|
195
|
+
const container = this.deps.getDom().container
|
|
196
|
+
if (container) {
|
|
197
|
+
const target = this.getLeftLoadBufferWidth() + Math.max(0, lastKLineEndPx - container.clientWidth)
|
|
198
|
+
const contentWidth = this.getContentWidth()
|
|
199
|
+
const maxScroll = Math.max(0, contentWidth - container.clientWidth)
|
|
200
|
+
const scrollLeft = Math.round(Math.min(target, maxScroll) * dpr) / dpr
|
|
201
|
+
this.deps.setCachedScrollLeft(scrollLeft)
|
|
202
|
+
this.deps.setPendingScrollLeft(scrollLeft)
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
this.deps.resetInteraction()
|
|
207
|
+
|
|
208
|
+
if (this.lastVisibleRange.start === 0 && this.lastVisibleRange.end === 0 && bufferData.length > 0) {
|
|
209
|
+
const plotWidth = this.deps.getObservedSize().width > 0
|
|
210
|
+
? this.deps.getObservedSize().width
|
|
211
|
+
: Math.max(1, Math.round(this.deps.getDom().container?.clientWidth ?? 800))
|
|
212
|
+
const dpr = this.deps.getEffectiveDpr()
|
|
213
|
+
const opt = this.deps.getOption()
|
|
214
|
+
const { start, end } = getVisibleRange(
|
|
215
|
+
this.deps.getLogicalScrollLeft(),
|
|
216
|
+
plotWidth,
|
|
217
|
+
opt.kWidth,
|
|
218
|
+
opt.kGap,
|
|
219
|
+
bufferData.length,
|
|
220
|
+
dpr,
|
|
221
|
+
)
|
|
222
|
+
this.lastRawVisibleRange = { start, end }
|
|
223
|
+
this.lastVisibleRange = { start: Math.max(0, start), end }
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const scheduler = this.deps.getIndicatorScheduler()
|
|
227
|
+
const indicatorsReady = scheduler.update(bufferData, this.lastVisibleRange)
|
|
228
|
+
if (indicatorsReady) {
|
|
229
|
+
this.pendingIndicatorDataUpdate = false
|
|
230
|
+
this.deps.scheduleDraw()
|
|
231
|
+
} else {
|
|
232
|
+
this.pendingIndicatorDataUpdate = true
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
this.showIncrementalLoadHint(prependedCount)
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
private onTimeShareBufferChanged(_key: string, _buf: TimeShareBuffer): void {
|
|
239
|
+
const data = this._dataSignal.peek() as TimeShareData[]
|
|
240
|
+
this.lastVisibleRange = { start: 0, end: data.length }
|
|
241
|
+
this.lastRawVisibleRange = { start: 0, end: data.length }
|
|
242
|
+
this.deps.resetInteraction()
|
|
243
|
+
this.deps.onTimeShareDataReady(data.length)
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// ── Internal helpers ──
|
|
247
|
+
|
|
74
248
|
private getScrollContentHost(): HTMLDivElement | null {
|
|
75
249
|
return this.deps.getDom().scrollContent ?? this.deps.getDom().container ?? null
|
|
76
250
|
}
|
|
77
251
|
|
|
78
252
|
getLeftLoadBufferWidth(): number {
|
|
79
|
-
|
|
253
|
+
const buf = this.getActiveDataBuffer()
|
|
254
|
+
const dataLength = buf ? buf.getRawData().length : 0
|
|
255
|
+
if (dataLength === 0) return 0
|
|
80
256
|
const plotWidth = this.deps.getViewport()?.plotWidth
|
|
81
257
|
?? (this.deps.getObservedSize().width > 0 ? this.deps.getObservedSize().width : undefined)
|
|
82
258
|
?? Math.round(this.deps.getDom().container?.clientWidth ?? 0)
|
|
83
259
|
return Math.max(0, plotWidth)
|
|
84
260
|
}
|
|
85
261
|
|
|
262
|
+
private getActiveKLineLength(): number {
|
|
263
|
+
const buf = this.getActiveDataBuffer()
|
|
264
|
+
return buf ? buf.getRawData().length : 0
|
|
265
|
+
}
|
|
266
|
+
|
|
86
267
|
private computeRawVisibleRange(): VisibleRange | null {
|
|
87
|
-
|
|
268
|
+
const buf = this.getActiveDataBuffer()
|
|
269
|
+
const dataLength = buf ? buf.getRawData().length : 0
|
|
270
|
+
if (dataLength === 0) return null
|
|
88
271
|
const vp = this.deps.getViewport()
|
|
89
272
|
if (!vp) return null
|
|
90
273
|
const opt = this.deps.getOption()
|
|
@@ -93,7 +276,7 @@ export class ChartDataManager {
|
|
|
93
276
|
vp.plotWidth,
|
|
94
277
|
opt.kWidth,
|
|
95
278
|
opt.kGap,
|
|
96
|
-
|
|
279
|
+
dataLength,
|
|
97
280
|
vp.dpr,
|
|
98
281
|
)
|
|
99
282
|
}
|
|
@@ -102,7 +285,6 @@ export class ChartDataManager {
|
|
|
102
285
|
return 24
|
|
103
286
|
}
|
|
104
287
|
|
|
105
|
-
private static readonly LEADING_SLOTS = 60
|
|
106
288
|
private static readonly TRAILING_DRAWING_SLOTS = 24
|
|
107
289
|
|
|
108
290
|
private clearIncrementalLoadHintTimer(): void {
|
|
@@ -169,8 +351,16 @@ export class ChartDataManager {
|
|
|
169
351
|
}, 900)
|
|
170
352
|
}
|
|
171
353
|
|
|
354
|
+
// ── Public accessors ──
|
|
355
|
+
|
|
356
|
+
/** Unified data signal — always reflects the active buffer's data */
|
|
172
357
|
get data(): Signal<ReadonlyArray<KLineData>> {
|
|
173
|
-
return this._dataSignal
|
|
358
|
+
return this._dataSignal as Signal<ReadonlyArray<KLineData>>
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/** Loading signal — mirrors the active buffer's loading state */
|
|
362
|
+
get loading(): Signal<boolean> {
|
|
363
|
+
return this._loadingSignal
|
|
174
364
|
}
|
|
175
365
|
|
|
176
366
|
get symbols(): Signal<ReadonlyArray<SymbolSpec>> {
|
|
@@ -178,11 +368,36 @@ export class ChartDataManager {
|
|
|
178
368
|
}
|
|
179
369
|
|
|
180
370
|
get currentPeriod(): string {
|
|
181
|
-
return this.
|
|
371
|
+
return this._currentSpec?.period ?? 'daily'
|
|
182
372
|
}
|
|
183
373
|
|
|
374
|
+
/** Internal KLine data for indicator scheduler (empty in timeshare mode) */
|
|
184
375
|
getInternalData(): KLineData[] {
|
|
185
|
-
|
|
376
|
+
const buf = this.getActiveDataBuffer()
|
|
377
|
+
return buf ? buf.getRawData() : []
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
getRenderData(): unknown[] {
|
|
381
|
+
return [...this._dataSignal.peek()]
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
getTimeShareData(): TimeShareData[] {
|
|
385
|
+
const buf = this.getActiveTimeShareBuffer()
|
|
386
|
+
return buf ? buf.getRawData() : []
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
getTimeShareSignal(): Signal<ReadonlyArray<TimeShareData>> {
|
|
390
|
+
const buf = this.getActiveTimeShareBuffer()
|
|
391
|
+
return (buf?.data ?? createSignal<ReadonlyArray<TimeShareData>>([])) as Signal<ReadonlyArray<TimeShareData>>
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
getTimeShareLoadingSignal(): Signal<boolean> {
|
|
395
|
+
const buf = this.getActiveTimeShareBuffer()
|
|
396
|
+
return (buf?.loading ?? createSignal<boolean>(false)) as Signal<boolean>
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
setTimeShareFetcher(fetcher: TimeShareFetcherFn | null): void {
|
|
400
|
+
this._timeShareFetcher = fetcher
|
|
186
401
|
}
|
|
187
402
|
|
|
188
403
|
getComparisonData(): Map<string, KLineData[]> {
|
|
@@ -194,7 +409,16 @@ export class ChartDataManager {
|
|
|
194
409
|
}
|
|
195
410
|
|
|
196
411
|
get dataBuffer(): DataBuffer {
|
|
197
|
-
|
|
412
|
+
const buf = this.getActiveDataBuffer()
|
|
413
|
+
if (buf) return buf
|
|
414
|
+
// Fallback: create a primary buffer if none exists yet
|
|
415
|
+
const key = bufKey(BUF_PRIMARY, '', 'daily')
|
|
416
|
+
let fallback = this._buffers.get(key) as DataBuffer | undefined
|
|
417
|
+
if (!fallback) {
|
|
418
|
+
fallback = new DataBuffer()
|
|
419
|
+
this._buffers.set(key, fallback)
|
|
420
|
+
}
|
|
421
|
+
return fallback
|
|
198
422
|
}
|
|
199
423
|
|
|
200
424
|
get comparisonColors(): Signal<ReadonlyMap<string, string>> {
|
|
@@ -210,85 +434,65 @@ export class ChartDataManager {
|
|
|
210
434
|
}
|
|
211
435
|
|
|
212
436
|
private recomputeComparisonLoading(): void {
|
|
213
|
-
const anyLoading = Array.from(this.
|
|
437
|
+
const anyLoading = Array.from(this._buffers.entries()).some(
|
|
438
|
+
([k, b]) => k.startsWith(BUF_COMPARISON) && b instanceof DataBuffer && b.loading.peek(),
|
|
439
|
+
)
|
|
214
440
|
this._comparisonLoadingSignal.set(anyLoading)
|
|
215
441
|
}
|
|
216
442
|
|
|
217
|
-
|
|
218
|
-
this._internalData = data ?? []
|
|
219
|
-
this._dataSignal.set([...this._internalData])
|
|
220
|
-
|
|
221
|
-
const container = this.deps.getDom().container
|
|
222
|
-
if (container) {
|
|
223
|
-
const minScrollLeft = this.getLeftLoadBufferWidth()
|
|
224
|
-
if (this.deps.getCachedScrollLeft() < minScrollLeft) {
|
|
225
|
-
this.deps.setCachedScrollLeft(minScrollLeft)
|
|
226
|
-
this.deps.setPendingScrollLeft(minScrollLeft)
|
|
227
|
-
}
|
|
228
|
-
const contentWidth = this.getContentWidth()
|
|
229
|
-
const maxScrollLeft = Math.max(0, contentWidth - container.clientWidth)
|
|
230
|
-
if (this.deps.getCachedScrollLeft() > maxScrollLeft) {
|
|
231
|
-
this.deps.setCachedScrollLeft(maxScrollLeft)
|
|
232
|
-
this.deps.setPendingScrollLeft(maxScrollLeft)
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
this.deps.resetInteraction()
|
|
237
|
-
|
|
238
|
-
if (this.lastVisibleRange.start === 0 && this.lastVisibleRange.end === 0 && this._internalData.length > 0) {
|
|
239
|
-
const plotWidth = this.deps.getObservedSize().width > 0
|
|
240
|
-
? this.deps.getObservedSize().width
|
|
241
|
-
: Math.max(1, Math.round(this.deps.getDom().container?.clientWidth ?? 800))
|
|
242
|
-
const dpr = this.deps.getEffectiveDpr()
|
|
243
|
-
const opt = this.deps.getOption()
|
|
244
|
-
const { start, end } = getVisibleRange(
|
|
245
|
-
this.deps.getLogicalScrollLeft(),
|
|
246
|
-
plotWidth,
|
|
247
|
-
opt.kWidth,
|
|
248
|
-
opt.kGap,
|
|
249
|
-
this._internalData.length,
|
|
250
|
-
dpr,
|
|
251
|
-
)
|
|
252
|
-
this.lastRawVisibleRange = { start, end }
|
|
253
|
-
this.lastVisibleRange = { start: Math.max(0, start), end }
|
|
254
|
-
}
|
|
443
|
+
// ── Data updates (KLine) ──
|
|
255
444
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
} else {
|
|
262
|
-
this.pendingIndicatorDataUpdate = true
|
|
445
|
+
updateData(data: KLineData[]): void {
|
|
446
|
+
if (this.currentPeriod === 'timeshare') return
|
|
447
|
+
const buf = this.getActiveDataBuffer()
|
|
448
|
+
if (buf) {
|
|
449
|
+
buf.setInlineData(data)
|
|
263
450
|
}
|
|
264
451
|
}
|
|
265
452
|
|
|
266
453
|
setData(data: KLineData[]): void {
|
|
267
|
-
this.
|
|
454
|
+
const buf = this.getActiveDataBuffer()
|
|
455
|
+
if (buf) {
|
|
456
|
+
buf.setInlineData(data)
|
|
457
|
+
} else {
|
|
458
|
+
this._dataSignal.set([...data])
|
|
459
|
+
}
|
|
268
460
|
}
|
|
269
461
|
|
|
270
462
|
appendData(newData: KLineData[]): void {
|
|
271
|
-
const
|
|
272
|
-
|
|
463
|
+
const buf = this.getActiveDataBuffer()
|
|
464
|
+
if (buf) {
|
|
465
|
+
const merged = [...buf.getRawData(), ...newData]
|
|
466
|
+
buf.setInlineData(merged)
|
|
467
|
+
} else {
|
|
468
|
+
this._dataSignal.set([...this._dataSignal.peek(), ...newData])
|
|
469
|
+
}
|
|
273
470
|
}
|
|
274
471
|
|
|
275
472
|
getData(): KLineData[] {
|
|
276
|
-
|
|
473
|
+
const buf = this.getActiveDataBuffer()
|
|
474
|
+
return buf ? buf.getRawData() : []
|
|
277
475
|
}
|
|
278
476
|
|
|
477
|
+
// ── Fetcher ──
|
|
478
|
+
|
|
279
479
|
setDataFetcher(fetcher: DataFetcher | null): void {
|
|
280
480
|
this._dataFetcher = fetcher
|
|
281
481
|
if (!fetcher) {
|
|
282
|
-
this.
|
|
283
|
-
|
|
284
|
-
|
|
482
|
+
for (const [key, buf] of this._buffers) {
|
|
483
|
+
if (buf instanceof DataBuffer) {
|
|
484
|
+
const dataBuf = buf as DataBuffer
|
|
485
|
+
dataBuf.setRequestFetch(null)
|
|
486
|
+
}
|
|
285
487
|
}
|
|
286
488
|
return
|
|
287
489
|
}
|
|
288
490
|
const handler = this._createBatchHandler(fetcher)
|
|
289
|
-
this.
|
|
290
|
-
|
|
291
|
-
|
|
491
|
+
for (const [key, buf] of this._buffers) {
|
|
492
|
+
if (buf instanceof DataBuffer) {
|
|
493
|
+
const dataBuf = buf as DataBuffer
|
|
494
|
+
dataBuf.setRequestFetch(handler)
|
|
495
|
+
}
|
|
292
496
|
}
|
|
293
497
|
}
|
|
294
498
|
|
|
@@ -339,8 +543,11 @@ export class ChartDataManager {
|
|
|
339
543
|
}
|
|
340
544
|
|
|
341
545
|
checkVisibleRangeGap(): void {
|
|
342
|
-
|
|
343
|
-
|
|
546
|
+
const buf = this.getActiveDataBuffer()
|
|
547
|
+
if (!buf) return
|
|
548
|
+
const data = buf.getRawData()
|
|
549
|
+
if (data.length === 0) return
|
|
550
|
+
const window = buf.loadedWindow
|
|
344
551
|
if (!window) return
|
|
345
552
|
const range = this.computeRawVisibleRange() ?? this.lastRawVisibleRange
|
|
346
553
|
|
|
@@ -349,73 +556,83 @@ export class ChartDataManager {
|
|
|
349
556
|
|
|
350
557
|
if (range.start < 0 && this._dataFetcher) {
|
|
351
558
|
const earlierThanEarliest = window.earliestTs - 365 * MS_PER_DAY
|
|
352
|
-
|
|
353
|
-
firstVisibleTs =
|
|
354
|
-
} else if (range.start <
|
|
355
|
-
firstVisibleTs =
|
|
559
|
+
buf.ensureRange(earlierThanEarliest, window.earliestTs)
|
|
560
|
+
firstVisibleTs = data[0]?.timestamp
|
|
561
|
+
} else if (range.start < data.length) {
|
|
562
|
+
firstVisibleTs = data[Math.max(0, range.start)]?.timestamp
|
|
356
563
|
if (firstVisibleTs !== undefined && firstVisibleTs < window.earliestTs) {
|
|
357
|
-
|
|
564
|
+
buf.ensureRange(firstVisibleTs, window.earliestTs)
|
|
358
565
|
}
|
|
359
566
|
}
|
|
360
567
|
|
|
361
568
|
if (firstVisibleTs === undefined) return
|
|
362
569
|
|
|
363
|
-
for (const
|
|
364
|
-
|
|
570
|
+
for (const [key, b] of this._buffers) {
|
|
571
|
+
if (key.startsWith(BUF_COMPARISON) && b instanceof DataBuffer) {
|
|
572
|
+
b.ensureRange(firstVisibleTs, window.earliestTs)
|
|
573
|
+
}
|
|
365
574
|
}
|
|
366
575
|
}
|
|
367
576
|
|
|
577
|
+
// ── Comparison management ──
|
|
578
|
+
|
|
368
579
|
private syncComparisonBuffers(specs: ReadonlyArray<SymbolSpec>): void {
|
|
369
580
|
this._comparisonSpecs = [...specs]
|
|
370
581
|
const nextKeys = new Set(specs.map((spec) => spec.symbol))
|
|
371
582
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
this.
|
|
378
|
-
this._comparisonData.delete(
|
|
583
|
+
// Remove buffers for removed comparisons
|
|
584
|
+
for (const [key, buf] of this._buffers) {
|
|
585
|
+
if (!key.startsWith(BUF_COMPARISON)) continue
|
|
586
|
+
const symbol = key.split(':')[1]!
|
|
587
|
+
if (nextKeys.has(symbol)) continue
|
|
588
|
+
this.disposeBuffer(key)
|
|
589
|
+
this._comparisonData.delete(symbol)
|
|
379
590
|
}
|
|
380
591
|
|
|
381
592
|
if (!this._dataFetcher) return
|
|
382
593
|
|
|
594
|
+
const primaryBuf = this.getActiveDataBuffer()
|
|
595
|
+
|
|
383
596
|
for (const spec of specs) {
|
|
384
|
-
const key = spec.symbol
|
|
385
|
-
|
|
386
|
-
|
|
597
|
+
const key = bufKey(BUF_COMPARISON, spec.symbol, spec.period)
|
|
598
|
+
const symbol = spec.symbol
|
|
599
|
+
let buf = this._buffers.get(key) as DataBuffer | undefined
|
|
600
|
+
if (!buf) {
|
|
387
601
|
const newBuffer = new DataBuffer()
|
|
388
602
|
newBuffer.setFetcher(this._dataFetcher)
|
|
389
603
|
if (this._dataFetcher) {
|
|
390
604
|
newBuffer.setRequestFetch(this._createBatchHandler(this._dataFetcher))
|
|
391
605
|
}
|
|
392
|
-
this.
|
|
606
|
+
this._buffers.set(key, newBuffer)
|
|
607
|
+
|
|
393
608
|
const unsubscribe = newBuffer.data.subscribe(() => {
|
|
394
|
-
this._comparisonData.set(
|
|
609
|
+
this._comparisonData.set(symbol, [...newBuffer.getRawData()])
|
|
395
610
|
this.deps.scheduleDraw()
|
|
396
611
|
})
|
|
397
|
-
this.
|
|
612
|
+
this._cmpLoadingUnsubs.set(key, unsubscribe)
|
|
613
|
+
|
|
398
614
|
const unsubLoading = newBuffer.loading.subscribe(() => this.recomputeComparisonLoading())
|
|
399
|
-
|
|
400
|
-
|
|
615
|
+
// Store loading unsubscribe with a special key
|
|
616
|
+
this._cmpLoadingUnsubs.set(`loading:${key}`, unsubLoading)
|
|
617
|
+
|
|
618
|
+
buf = newBuffer
|
|
401
619
|
} else {
|
|
402
|
-
|
|
620
|
+
buf.setFetcher(this._dataFetcher)
|
|
403
621
|
if (this._dataFetcher) {
|
|
404
|
-
|
|
622
|
+
buf.setRequestFetch(this._createBatchHandler(this._dataFetcher))
|
|
405
623
|
}
|
|
406
624
|
}
|
|
407
|
-
const mainEarliest =
|
|
408
|
-
|
|
625
|
+
const mainEarliest = primaryBuf?.loadedWindow?.earliestTs
|
|
626
|
+
buf.setSymbol(spec, mainEarliest)
|
|
409
627
|
}
|
|
410
628
|
}
|
|
411
629
|
|
|
412
630
|
private clearComparisonBuffers(): void {
|
|
413
|
-
for (const
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
this._comparisonBuffers.clear()
|
|
631
|
+
for (const [key, buf] of this._buffers) {
|
|
632
|
+
if (key.startsWith(BUF_COMPARISON)) {
|
|
633
|
+
this.disposeBuffer(key)
|
|
634
|
+
}
|
|
635
|
+
}
|
|
419
636
|
this._comparisonData.clear()
|
|
420
637
|
this._comparisonColors.clear()
|
|
421
638
|
this._comparisonColorsSignal.set(new Map())
|
|
@@ -424,12 +641,18 @@ export class ChartDataManager {
|
|
|
424
641
|
}
|
|
425
642
|
|
|
426
643
|
addComparisonSymbol(spec: SymbolSpec): void {
|
|
427
|
-
const
|
|
428
|
-
|
|
644
|
+
const symbol = spec.symbol
|
|
645
|
+
const key = bufKey(BUF_COMPARISON, symbol, spec.period)
|
|
646
|
+
|
|
647
|
+
// Check if already exists
|
|
648
|
+
for (const k of this._buffers.keys()) {
|
|
649
|
+
if (k.startsWith(BUF_COMPARISON) && k.split(':')[1] === symbol) return
|
|
650
|
+
}
|
|
651
|
+
|
|
429
652
|
this._comparisonSpecs.push(spec)
|
|
430
653
|
|
|
431
654
|
const color = COMPARISON_PALETTE[this._comparisonColors.size % COMPARISON_PALETTE.length] ?? DEFAULT_COMPARISON_COLOR
|
|
432
|
-
this._comparisonColors.set(
|
|
655
|
+
this._comparisonColors.set(symbol, color)
|
|
433
656
|
this._comparisonColorsSignal.set(new Map(this._comparisonColors))
|
|
434
657
|
|
|
435
658
|
if (!this._dataFetcher) return
|
|
@@ -439,50 +662,206 @@ export class ChartDataManager {
|
|
|
439
662
|
if (this._dataFetcher) {
|
|
440
663
|
newBuffer.setRequestFetch(this._createBatchHandler(this._dataFetcher))
|
|
441
664
|
}
|
|
442
|
-
this.
|
|
665
|
+
this._buffers.set(key, newBuffer)
|
|
443
666
|
const unsubscribe = newBuffer.data.subscribe(() => {
|
|
444
|
-
this._comparisonData.set(
|
|
667
|
+
this._comparisonData.set(symbol, [...newBuffer.getRawData()])
|
|
445
668
|
this.deps.scheduleDraw()
|
|
446
669
|
})
|
|
447
|
-
this.
|
|
670
|
+
this._cmpLoadingUnsubs.set(key, unsubscribe)
|
|
448
671
|
const unsubLoading = newBuffer.loading.subscribe(() => this.recomputeComparisonLoading())
|
|
449
|
-
this.
|
|
450
|
-
const
|
|
672
|
+
this._cmpLoadingUnsubs.set(`loading:${key}`, unsubLoading)
|
|
673
|
+
const primaryBuf = this.getActiveDataBuffer()
|
|
674
|
+
const mainEarliest = primaryBuf?.loadedWindow?.earliestTs
|
|
451
675
|
newBuffer.setSymbol(spec, mainEarliest)
|
|
452
676
|
this._symbolsSignal.set([this._symbolsSignal.peek()[0]!, ...this._comparisonSpecs])
|
|
453
677
|
}
|
|
454
678
|
|
|
679
|
+
setComparisonData(symbol: string, data: KLineData[]): void {
|
|
680
|
+
const period = this.currentPeriod
|
|
681
|
+
const key = bufKey(BUF_COMPARISON, symbol, period)
|
|
682
|
+
|
|
683
|
+
const existing = this._buffers.get(key) as DataBuffer | undefined
|
|
684
|
+
if (!existing) {
|
|
685
|
+
const buffer = new DataBuffer()
|
|
686
|
+
this._buffers.set(key, buffer)
|
|
687
|
+
|
|
688
|
+
const unsub = buffer.data.subscribe(() => {
|
|
689
|
+
this._comparisonData.set(symbol, [...buffer.getRawData()])
|
|
690
|
+
this.deps.scheduleDraw()
|
|
691
|
+
})
|
|
692
|
+
this._cmpLoadingUnsubs.set(key, unsub)
|
|
693
|
+
|
|
694
|
+
const unsubLoading = buffer.loading.subscribe(() => this.recomputeComparisonLoading())
|
|
695
|
+
this._cmpLoadingUnsubs.set(`loading:${key}`, unsubLoading)
|
|
696
|
+
|
|
697
|
+
const color =
|
|
698
|
+
COMPARISON_PALETTE[this._comparisonColors.size % COMPARISON_PALETTE.length] ??
|
|
699
|
+
DEFAULT_COMPARISON_COLOR
|
|
700
|
+
this._comparisonColors.set(symbol, color)
|
|
701
|
+
this._comparisonColorsSignal.set(new Map(this._comparisonColors))
|
|
702
|
+
|
|
703
|
+
const spec: SymbolSpec = { symbol, period }
|
|
704
|
+
this._comparisonSpecs.push(spec)
|
|
705
|
+
const mainSpec = this._symbolsSignal.peek()[0]
|
|
706
|
+
this._symbolsSignal.set(mainSpec ? [mainSpec, ...this._comparisonSpecs] : [...this._comparisonSpecs])
|
|
707
|
+
|
|
708
|
+
buffer.setInlineData(data)
|
|
709
|
+
return
|
|
710
|
+
}
|
|
711
|
+
existing.setInlineData(data)
|
|
712
|
+
}
|
|
713
|
+
|
|
455
714
|
removeComparisonSymbol(symbol: string): void {
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
this.
|
|
715
|
+
let found = false
|
|
716
|
+
for (const [key, buf] of this._buffers) {
|
|
717
|
+
if (key.startsWith(BUF_COMPARISON) && key.split(':')[1] === symbol) {
|
|
718
|
+
this.disposeBuffer(key)
|
|
719
|
+
found = true
|
|
720
|
+
break
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
if (!found) return
|
|
724
|
+
|
|
725
|
+
this._comparisonData.delete(symbol)
|
|
726
|
+
this._comparisonColors.delete(symbol)
|
|
467
727
|
this._comparisonColorsSignal.set(new Map(this._comparisonColors))
|
|
468
728
|
this._comparisonSpecs = this._comparisonSpecs.filter((s) => s.symbol !== symbol)
|
|
469
729
|
this._symbolsSignal.set([this._symbolsSignal.peek()[0]!, ...this._comparisonSpecs])
|
|
470
730
|
this.recomputeComparisonLoading()
|
|
731
|
+
this.deps.scheduleDraw()
|
|
471
732
|
}
|
|
472
733
|
|
|
734
|
+
// ── Symbol / Period ──
|
|
735
|
+
|
|
736
|
+
setCurrentSymbol(symbol: string): void {
|
|
737
|
+
const current = this._currentSpec ?? { symbol }
|
|
738
|
+
this._currentSpec = { ...current, symbol }
|
|
739
|
+
const specs = this._symbolsSignal.peek()
|
|
740
|
+
if (specs.length > 0) {
|
|
741
|
+
const updated = [{ ...specs[0], symbol }, ...specs.slice(1)] as SymbolSpec[]
|
|
742
|
+
this._symbolsSignal.set(updated)
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
setTimeShareQueryDate(date: number): void {
|
|
747
|
+
const buf = this.getActiveTimeShareBuffer()
|
|
748
|
+
if (buf) {
|
|
749
|
+
buf.setQueryDate(date)
|
|
750
|
+
} else {
|
|
751
|
+
// Store for later when buffer is created
|
|
752
|
+
const tsBuf = new TimeShareBuffer()
|
|
753
|
+
tsBuf.setFetcher(this._timeShareFetcher)
|
|
754
|
+
tsBuf.setQueryDate(date)
|
|
755
|
+
const spec = this._currentSpec
|
|
756
|
+
if (spec) {
|
|
757
|
+
const key = bufKey(BUF_TIMESHARE, spec.symbol)
|
|
758
|
+
this._buffers.set(key, tsBuf)
|
|
759
|
+
this.activateBuffer(key)
|
|
760
|
+
tsBuf.load(spec)
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
setCurrentPeriod(period: string): void {
|
|
766
|
+
const current = this._currentSpec
|
|
767
|
+
if (!current) {
|
|
768
|
+
this._currentSpec = { symbol: '', period }
|
|
769
|
+
return
|
|
770
|
+
}
|
|
771
|
+
const next = { ...current, period }
|
|
772
|
+
this.setSymbols([next, ...this._comparisonSpecs])
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
applyCustomData(source: CustomDataSource): void {
|
|
776
|
+
if (source.symbol) this.setCurrentSymbol(source.symbol)
|
|
777
|
+
if (source.period) this.setCurrentPeriod(source.period)
|
|
778
|
+
|
|
779
|
+
const specs = this._symbolsSignal.peek()
|
|
780
|
+
if (specs.length === 0 && source.symbol) {
|
|
781
|
+
const mainSpec: SymbolSpec = {
|
|
782
|
+
symbol: source.symbol,
|
|
783
|
+
period: source.period ?? 'daily',
|
|
784
|
+
}
|
|
785
|
+
this._symbolsSignal.set([mainSpec])
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
const plainData = source.data.map((d) => ({ ...d }))
|
|
789
|
+
this.setData(plainData)
|
|
790
|
+
if (source.comparisons) {
|
|
791
|
+
for (const key of this._comparisonData.keys()) {
|
|
792
|
+
if (!source.comparisons[key]) this.removeComparisonSymbol(key)
|
|
793
|
+
}
|
|
794
|
+
for (const [symbol, data] of Object.entries(source.comparisons)) {
|
|
795
|
+
this.setComparisonData(symbol, data.map((d) => ({ ...d })))
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
// ── Main symbol switching ──
|
|
801
|
+
|
|
473
802
|
setSymbols(specs: ReadonlyArray<SymbolSpec>): void {
|
|
474
803
|
this._symbolsSignal.set(specs)
|
|
804
|
+
|
|
475
805
|
if (specs.length === 0) {
|
|
806
|
+
this._currentSpec = null
|
|
807
|
+
this.disposeAllBuffers()
|
|
808
|
+
this._dataSignal.set([])
|
|
809
|
+
this.lastVisibleRange = { start: 0, end: 0 }
|
|
810
|
+
this.lastRawVisibleRange = { start: 0, end: 0 }
|
|
811
|
+
return
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
const primary = specs[0]!
|
|
815
|
+
this._currentSpec = primary
|
|
816
|
+
|
|
817
|
+
if (primary.period === 'timeshare') {
|
|
818
|
+
// Switch to timeshare mode
|
|
476
819
|
this.clearComparisonBuffers()
|
|
820
|
+
// Dispose primary KLine buffer
|
|
821
|
+
for (const [key, buf] of this._buffers) {
|
|
822
|
+
if (key.startsWith(BUF_PRIMARY)) {
|
|
823
|
+
this.disposeBuffer(key)
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
this._dataSignal.set([])
|
|
827
|
+
this.lastVisibleRange = { start: 0, end: 0 }
|
|
828
|
+
this.lastRawVisibleRange = { start: 0, end: 0 }
|
|
829
|
+
|
|
830
|
+
// Get or create timeshare buffer
|
|
831
|
+
const tsKey = bufKey(BUF_TIMESHARE, primary.symbol)
|
|
832
|
+
let tsBuf = this._buffers.get(tsKey) as TimeShareBuffer | undefined
|
|
833
|
+
if (!tsBuf) {
|
|
834
|
+
tsBuf = new TimeShareBuffer()
|
|
835
|
+
tsBuf.setFetcher(this._timeShareFetcher)
|
|
836
|
+
this._buffers.set(tsKey, tsBuf)
|
|
837
|
+
}
|
|
838
|
+
this.activateBuffer(tsKey)
|
|
839
|
+
tsBuf.load(primary)
|
|
477
840
|
return
|
|
478
841
|
}
|
|
842
|
+
|
|
843
|
+
// KLine mode
|
|
844
|
+
// Dispose timeshare buffer
|
|
845
|
+
for (const [key, buf] of this._buffers) {
|
|
846
|
+
if (key.startsWith(BUF_TIMESHARE)) {
|
|
847
|
+
this.disposeBuffer(key)
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
this.loadKLineSymbols(specs)
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
// ── KLine loading ──
|
|
855
|
+
|
|
856
|
+
private loadKLineSymbols(specs: ReadonlyArray<SymbolSpec>): void {
|
|
479
857
|
const spec = specs[0]!
|
|
480
858
|
this.syncComparisonBuffers(specs.slice(1))
|
|
481
859
|
if (!this._dataFetcher) return
|
|
482
860
|
|
|
483
|
-
this.
|
|
861
|
+
const buf = this.getPrimaryDataBuffer(spec.symbol, spec.period!)
|
|
862
|
+
this.activateBuffer(bufKey(BUF_PRIMARY, spec.symbol, spec.period!))
|
|
484
863
|
|
|
485
|
-
|
|
864
|
+
buf.onPrepend = (count: number) => {
|
|
486
865
|
this.pendingPrependedCount = count
|
|
487
866
|
const dpr = this.deps.getEffectiveDpr()
|
|
488
867
|
const opt = this.deps.getOption()
|
|
@@ -495,101 +874,52 @@ export class ChartDataManager {
|
|
|
495
874
|
}
|
|
496
875
|
}
|
|
497
876
|
|
|
498
|
-
|
|
499
|
-
this._dataBufferUnsub = this._dataBuffer.data.subscribe(() => {
|
|
500
|
-
const prevLength = this._internalData.length
|
|
501
|
-
const bufferData = this._dataBuffer.data.peek()
|
|
502
|
-
this._internalData = [...bufferData]
|
|
503
|
-
this._dataSignal.set([...this._internalData])
|
|
504
|
-
const prependedCount = this.pendingPrependedCount
|
|
505
|
-
this.pendingPrependedCount = 0
|
|
506
|
-
|
|
507
|
-
if (this.deps.getCachedScrollLeft() < this.getLeftLoadBufferWidth()) {
|
|
508
|
-
const desiredScrollLeft = this.getLeftLoadBufferWidth()
|
|
509
|
-
this.deps.setCachedScrollLeft(desiredScrollLeft)
|
|
510
|
-
this.deps.setPendingScrollLeft(desiredScrollLeft)
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
if (prevLength === 0 && this._internalData.length > 0) {
|
|
514
|
-
const dpr = this.deps.getEffectiveDpr()
|
|
515
|
-
const opt = this.deps.getOption()
|
|
516
|
-
const { unitPx, startXPx } = getPhysicalKLineConfig(opt.kWidth, opt.kGap, dpr)
|
|
517
|
-
const lastKLineEndPx = (startXPx + this._internalData.length * unitPx) / dpr
|
|
518
|
-
const container = this.deps.getDom().container
|
|
519
|
-
if (container) {
|
|
520
|
-
const target = this.getLeftLoadBufferWidth() + Math.max(0, lastKLineEndPx - container.clientWidth)
|
|
521
|
-
const contentWidth = this.getContentWidth()
|
|
522
|
-
const maxScroll = Math.max(0, contentWidth - container.clientWidth)
|
|
523
|
-
const scrollLeft = Math.round(Math.min(target, maxScroll) * dpr) / dpr
|
|
524
|
-
this.deps.setCachedScrollLeft(scrollLeft)
|
|
525
|
-
this.deps.setPendingScrollLeft(scrollLeft)
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
this.deps.resetInteraction()
|
|
530
|
-
|
|
531
|
-
if (this.lastVisibleRange.start === 0 && this.lastVisibleRange.end === 0 && this._internalData.length > 0) {
|
|
532
|
-
const plotWidth = this.deps.getObservedSize().width > 0
|
|
533
|
-
? this.deps.getObservedSize().width
|
|
534
|
-
: Math.max(1, Math.round(this.deps.getDom().container?.clientWidth ?? 800))
|
|
535
|
-
const dpr = this.deps.getEffectiveDpr()
|
|
536
|
-
const opt = this.deps.getOption()
|
|
537
|
-
const { start, end } = getVisibleRange(
|
|
538
|
-
this.deps.getLogicalScrollLeft(),
|
|
539
|
-
plotWidth,
|
|
540
|
-
opt.kWidth,
|
|
541
|
-
opt.kGap,
|
|
542
|
-
this._internalData.length,
|
|
543
|
-
dpr,
|
|
544
|
-
)
|
|
545
|
-
this.lastRawVisibleRange = { start, end }
|
|
546
|
-
this.lastVisibleRange = { start: Math.max(0, start), end }
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
const scheduler = this.deps.getIndicatorScheduler()
|
|
550
|
-
const indicatorsReady = scheduler.update(this._internalData, this.lastVisibleRange)
|
|
551
|
-
if (indicatorsReady) {
|
|
552
|
-
this.pendingIndicatorDataUpdate = false
|
|
553
|
-
this.deps.scheduleDraw()
|
|
554
|
-
} else {
|
|
555
|
-
this.pendingIndicatorDataUpdate = true
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
this.showIncrementalLoadHint(prependedCount)
|
|
559
|
-
})
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
this._dataBuffer.setSymbol(spec)
|
|
877
|
+
buf.setSymbol(spec)
|
|
563
878
|
}
|
|
564
879
|
|
|
880
|
+
// ── Content width ──
|
|
881
|
+
|
|
565
882
|
getContentWidth(): number {
|
|
566
|
-
|
|
883
|
+
if (this.currentPeriod === 'timeshare') {
|
|
884
|
+
const tsData = this.getTimeShareData()
|
|
885
|
+
if (tsData.length === 0) return 0
|
|
886
|
+
const viewWidth = this.deps.getViewport()?.plotWidth ?? 0
|
|
887
|
+
return this.getLeftLoadBufferWidth() + Math.max(viewWidth, 1)
|
|
888
|
+
}
|
|
889
|
+
const buf = this.getActiveDataBuffer()
|
|
890
|
+
const dataLength = buf ? buf.getRawData().length : 0
|
|
567
891
|
if (dataLength === 0) return 0
|
|
568
892
|
const opt = this.deps.getOption()
|
|
569
893
|
const viewWidth = this.deps.getViewport()?.plotWidth ?? 0
|
|
570
894
|
const dpr = this.deps.getEffectiveDpr()
|
|
571
895
|
const { startXPx, unitPx } = getPhysicalKLineConfig(opt.kWidth, opt.kGap, dpr)
|
|
572
|
-
const dataPlotWidth = (startXPx + (
|
|
896
|
+
const dataPlotWidth = (startXPx + (dataLength + ChartDataManager.TRAILING_DRAWING_SLOTS) * unitPx) / dpr
|
|
573
897
|
return this.getLeftLoadBufferWidth() + Math.max(dataPlotWidth, viewWidth)
|
|
574
898
|
}
|
|
575
899
|
|
|
576
900
|
scrollToRight(): void {
|
|
901
|
+
const buf = this.getActiveDataBuffer()
|
|
902
|
+
const dataLength = buf ? buf.getRawData().length : 0
|
|
577
903
|
const container = this.deps.getDom().container
|
|
578
|
-
if (!container ||
|
|
904
|
+
if (!container || dataLength === 0) return
|
|
579
905
|
const dpr = this.deps.getEffectiveDpr()
|
|
580
906
|
const opt = this.deps.getOption()
|
|
581
907
|
const { unitPx, startXPx } = getPhysicalKLineConfig(opt.kWidth, opt.kGap, dpr)
|
|
582
|
-
const lastKLineEndPx = (startXPx +
|
|
908
|
+
const lastKLineEndPx = (startXPx + dataLength * unitPx) / dpr
|
|
583
909
|
const target = this.getLeftLoadBufferWidth() + Math.max(0, lastKLineEndPx - container.clientWidth)
|
|
584
910
|
const maxScroll = Math.max(0, container.scrollWidth - container.clientWidth)
|
|
585
911
|
container.scrollLeft = Math.round(Math.min(target, maxScroll) * dpr) / dpr
|
|
586
912
|
this.deps.setCachedScrollLeft(container.scrollLeft)
|
|
587
913
|
}
|
|
588
914
|
|
|
915
|
+
// ── Comparison price range ──
|
|
916
|
+
|
|
589
917
|
getComparisonEquivalentPriceRange(range: VisibleRange): { min: number; max: number } | null {
|
|
590
918
|
if (this._comparisonSpecs.length === 0 || this._comparisonData.size === 0) return null
|
|
919
|
+
const buf = this.getActiveDataBuffer()
|
|
920
|
+
const internalData = buf ? buf.getRawData() : []
|
|
591
921
|
const baseIndex = Math.max(0, range.start)
|
|
592
|
-
const baseItem =
|
|
922
|
+
const baseItem = internalData[baseIndex]
|
|
593
923
|
if (!baseItem || !Number.isFinite(baseItem.close) || baseItem.close <= 0) return null
|
|
594
924
|
const mainBase = baseItem.close
|
|
595
925
|
const baseDate = baseItem.date ?? ''
|
|
@@ -612,8 +942,8 @@ export class ChartDataManager {
|
|
|
612
942
|
else byDate.set(String(item.timestamp), item)
|
|
613
943
|
}
|
|
614
944
|
|
|
615
|
-
for (let i = Math.max(0, range.start); i < range.end && i <
|
|
616
|
-
const mainItem =
|
|
945
|
+
for (let i = Math.max(0, range.start); i < range.end && i < internalData.length; i++) {
|
|
946
|
+
const mainItem = internalData[i]
|
|
617
947
|
if (!mainItem) continue
|
|
618
948
|
const key = mainItem.date ?? String(mainItem.timestamp)
|
|
619
949
|
const item = byDate.get(key)
|
|
@@ -631,18 +961,27 @@ export class ChartDataManager {
|
|
|
631
961
|
return { min, max }
|
|
632
962
|
}
|
|
633
963
|
|
|
964
|
+
// ── Index helpers ──
|
|
965
|
+
|
|
634
966
|
getLogicalSlotCount(): number {
|
|
635
|
-
|
|
967
|
+
const buf = this.getActiveDataBuffer()
|
|
968
|
+
const dataLength = buf ? buf.getRawData().length : 0
|
|
969
|
+
return dataLength + this.getTrailingSlotCount()
|
|
636
970
|
}
|
|
637
971
|
|
|
638
972
|
getTimestampAtLogicalIndex(index: number): number | null {
|
|
639
|
-
|
|
640
|
-
|
|
973
|
+
const buf = this.getActiveDataBuffer()
|
|
974
|
+
const data = buf ? buf.getRawData() : []
|
|
975
|
+
if (!Number.isInteger(index) || index < 0 || index >= data.length) return null
|
|
976
|
+
return data[index]?.timestamp ?? null
|
|
641
977
|
}
|
|
642
978
|
|
|
643
979
|
getLogicalIndexAtX(mouseX: number): number | null {
|
|
644
980
|
const vp = this.deps.getViewport()
|
|
645
|
-
if (!vp
|
|
981
|
+
if (!vp) return null
|
|
982
|
+
const buf = this.getActiveDataBuffer()
|
|
983
|
+
const data = buf ? buf.getRawData() : []
|
|
984
|
+
if (data.length === 0) return null
|
|
646
985
|
const dpr = this.deps.getEffectiveDpr()
|
|
647
986
|
const opt = this.deps.getOption()
|
|
648
987
|
const { startXPx, unitPx } = getPhysicalKLineConfig(opt.kWidth, opt.kGap, dpr)
|
|
@@ -654,21 +993,25 @@ export class ChartDataManager {
|
|
|
654
993
|
|
|
655
994
|
getDataIndexAtX(mouseX: number): number | null {
|
|
656
995
|
const index = this.getLogicalIndexAtX(mouseX)
|
|
657
|
-
|
|
996
|
+
const buf = this.getActiveDataBuffer()
|
|
997
|
+
const dataLength = buf ? buf.getRawData().length : 0
|
|
998
|
+
if (index === null || index >= dataLength) return null
|
|
658
999
|
return index
|
|
659
1000
|
}
|
|
660
1001
|
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
this.
|
|
664
|
-
this._dataBufferUnsub = null
|
|
1002
|
+
private disposeAllBuffers(): void {
|
|
1003
|
+
for (const key of this._buffers.keys()) {
|
|
1004
|
+
this.disposeBuffer(key)
|
|
665
1005
|
}
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
destroy(): void {
|
|
1009
|
+
this._activeBufferUnsub?.()
|
|
1010
|
+
this.disposeAllBuffers()
|
|
666
1011
|
this.clearIncrementalLoadHintTimer()
|
|
667
1012
|
this.incrementalLoadHintEl?.remove()
|
|
668
1013
|
this.incrementalLoadHintEl = null
|
|
669
1014
|
this.pendingPrependedCount = 0
|
|
670
|
-
this._dataBuffer.dispose()
|
|
671
|
-
this.clearComparisonBuffers()
|
|
672
1015
|
}
|
|
673
1016
|
}
|
|
674
1017
|
|
|
@@ -692,4 +1035,4 @@ function batchFormatDate(ts: number): string {
|
|
|
692
1035
|
const m = String(d.getMonth() + 1).padStart(2, '0')
|
|
693
1036
|
const day = String(d.getDate()).padStart(2, '0')
|
|
694
1037
|
return `${y}-${m}-${day}`
|
|
695
|
-
}
|
|
1038
|
+
}
|