@363045841yyt/klinechart-core 0.8.11-alpha.0 → 0.8.12
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/alerts/createAlertController.d.ts +30 -0
- package/dist/alerts/createAlertController.d.ts.map +1 -0
- package/dist/alerts/createAlertController.js +261 -0
- package/dist/alerts/createAlertController.js.map +1 -0
- package/dist/alerts/index.d.ts +5 -0
- package/dist/alerts/index.d.ts.map +1 -0
- package/dist/alerts/index.js +4 -0
- package/dist/alerts/index.js.map +1 -0
- package/dist/alerts/predicates.d.ts +28 -0
- package/dist/alerts/predicates.d.ts.map +1 -0
- package/dist/alerts/predicates.js +211 -0
- package/dist/alerts/predicates.js.map +1 -0
- package/dist/alerts/rollingVolume.d.ts +15 -0
- package/dist/alerts/rollingVolume.d.ts.map +1 -0
- package/dist/alerts/rollingVolume.js +42 -0
- package/dist/alerts/rollingVolume.js.map +1 -0
- package/dist/alerts/ruleSchema.d.ts +42 -0
- package/dist/alerts/ruleSchema.d.ts.map +1 -0
- package/dist/alerts/ruleSchema.js +240 -0
- package/dist/alerts/ruleSchema.js.map +1 -0
- package/dist/alerts/types.d.ts +169 -0
- package/dist/alerts/types.d.ts.map +1 -0
- package/dist/alerts/types.js +24 -0
- package/dist/alerts/types.js.map +1 -0
- package/dist/chartTypes/heikinAshi.d.ts +49 -0
- package/dist/chartTypes/heikinAshi.d.ts.map +1 -0
- package/dist/chartTypes/heikinAshi.js +94 -0
- package/dist/chartTypes/heikinAshi.js.map +1 -0
- package/dist/chartTypes/index.d.ts +6 -0
- package/dist/chartTypes/index.d.ts.map +1 -0
- package/dist/chartTypes/index.js +5 -0
- package/dist/chartTypes/index.js.map +1 -0
- package/dist/chartTypes/pointAndFigure.d.ts +83 -0
- package/dist/chartTypes/pointAndFigure.d.ts.map +1 -0
- package/dist/chartTypes/pointAndFigure.js +159 -0
- package/dist/chartTypes/pointAndFigure.js.map +1 -0
- package/dist/chartTypes/rangeBars.d.ts +61 -0
- package/dist/chartTypes/rangeBars.d.ts.map +1 -0
- package/dist/chartTypes/rangeBars.js +181 -0
- package/dist/chartTypes/rangeBars.js.map +1 -0
- package/dist/chartTypes/renko.d.ts +94 -0
- package/dist/chartTypes/renko.d.ts.map +1 -0
- package/dist/chartTypes/renko.js +207 -0
- package/dist/chartTypes/renko.js.map +1 -0
- package/dist/chartTypes/types.d.ts +97 -0
- package/dist/chartTypes/types.d.ts.map +1 -0
- package/dist/chartTypes/types.js +39 -0
- package/dist/chartTypes/types.js.map +1 -0
- package/dist/components/anchoredVwap/computeAnchoredVwap.d.ts +76 -0
- package/dist/components/anchoredVwap/computeAnchoredVwap.d.ts.map +1 -0
- package/dist/components/anchoredVwap/computeAnchoredVwap.js +155 -0
- package/dist/components/anchoredVwap/computeAnchoredVwap.js.map +1 -0
- package/dist/components/anchoredVwap/createAnchoredVwapController.d.ts +28 -0
- package/dist/components/anchoredVwap/createAnchoredVwapController.d.ts.map +1 -0
- package/dist/components/anchoredVwap/createAnchoredVwapController.js +282 -0
- package/dist/components/anchoredVwap/createAnchoredVwapController.js.map +1 -0
- package/dist/components/anchoredVwap/index.d.ts +11 -0
- package/dist/components/anchoredVwap/index.d.ts.map +1 -0
- package/dist/components/anchoredVwap/index.js +10 -0
- package/dist/components/anchoredVwap/index.js.map +1 -0
- package/dist/components/anchoredVwap/types.d.ts +171 -0
- package/dist/components/anchoredVwap/types.d.ts.map +1 -0
- package/dist/components/anchoredVwap/types.js +25 -0
- package/dist/components/anchoredVwap/types.js.map +1 -0
- package/dist/components/crosshairSync/createCrosshairSync.d.ts +94 -0
- package/dist/components/crosshairSync/createCrosshairSync.d.ts.map +1 -0
- package/dist/components/crosshairSync/createCrosshairSync.js +118 -0
- package/dist/components/crosshairSync/createCrosshairSync.js.map +1 -0
- package/dist/components/crosshairSync/index.d.ts +2 -0
- package/dist/components/crosshairSync/index.d.ts.map +1 -0
- package/dist/components/crosshairSync/index.js +2 -0
- package/dist/components/crosshairSync/index.js.map +1 -0
- package/dist/components/footprint/aggressor.d.ts +89 -0
- package/dist/components/footprint/aggressor.d.ts.map +1 -0
- package/dist/components/footprint/aggressor.js +106 -0
- package/dist/components/footprint/aggressor.js.map +1 -0
- package/dist/components/footprint/createFootprintController.d.ts +29 -0
- package/dist/components/footprint/createFootprintController.d.ts.map +1 -0
- package/dist/components/footprint/createFootprintController.js +264 -0
- package/dist/components/footprint/createFootprintController.js.map +1 -0
- package/dist/components/footprint/index.d.ts +7 -0
- package/dist/components/footprint/index.d.ts.map +1 -0
- package/dist/components/footprint/index.js +4 -0
- package/dist/components/footprint/index.js.map +1 -0
- package/dist/components/footprint/perBarStats.d.ts +63 -0
- package/dist/components/footprint/perBarStats.d.ts.map +1 -0
- package/dist/components/footprint/perBarStats.js +123 -0
- package/dist/components/footprint/perBarStats.js.map +1 -0
- package/dist/components/footprint/types.d.ts +197 -0
- package/dist/components/footprint/types.d.ts.map +1 -0
- package/dist/components/footprint/types.js +23 -0
- package/dist/components/footprint/types.js.map +1 -0
- package/dist/components/mtfOverlay/alignToBaseIndex.d.ts +45 -0
- package/dist/components/mtfOverlay/alignToBaseIndex.d.ts.map +1 -0
- package/dist/components/mtfOverlay/alignToBaseIndex.js +92 -0
- package/dist/components/mtfOverlay/alignToBaseIndex.js.map +1 -0
- package/dist/components/mtfOverlay/createMtfController.d.ts +7 -0
- package/dist/components/mtfOverlay/createMtfController.d.ts.map +1 -0
- package/dist/components/mtfOverlay/createMtfController.js +134 -0
- package/dist/components/mtfOverlay/createMtfController.js.map +1 -0
- package/dist/components/mtfOverlay/index.d.ts +19 -0
- package/dist/components/mtfOverlay/index.d.ts.map +1 -0
- package/dist/components/mtfOverlay/index.js +18 -0
- package/dist/components/mtfOverlay/index.js.map +1 -0
- package/dist/components/mtfOverlay/resampleBars.d.ts +37 -0
- package/dist/components/mtfOverlay/resampleBars.d.ts.map +1 -0
- package/dist/components/mtfOverlay/resampleBars.js +93 -0
- package/dist/components/mtfOverlay/resampleBars.js.map +1 -0
- package/dist/components/mtfOverlay/types.d.ts +132 -0
- package/dist/components/mtfOverlay/types.d.ts.map +1 -0
- package/dist/components/mtfOverlay/types.js +22 -0
- package/dist/components/mtfOverlay/types.js.map +1 -0
- package/dist/components/orderBookHeatmap/createHeatmapController.d.ts +21 -0
- package/dist/components/orderBookHeatmap/createHeatmapController.d.ts.map +1 -0
- package/dist/components/orderBookHeatmap/createHeatmapController.js +234 -0
- package/dist/components/orderBookHeatmap/createHeatmapController.js.map +1 -0
- package/dist/components/orderBookHeatmap/createOrderBookState.d.ts +18 -0
- package/dist/components/orderBookHeatmap/createOrderBookState.d.ts.map +1 -0
- package/dist/components/orderBookHeatmap/createOrderBookState.js +102 -0
- package/dist/components/orderBookHeatmap/createOrderBookState.js.map +1 -0
- package/dist/components/orderBookHeatmap/deltaArchive.d.ts +25 -0
- package/dist/components/orderBookHeatmap/deltaArchive.d.ts.map +1 -0
- package/dist/components/orderBookHeatmap/deltaArchive.js +106 -0
- package/dist/components/orderBookHeatmap/deltaArchive.js.map +1 -0
- package/dist/components/orderBookHeatmap/index.d.ts +13 -0
- package/dist/components/orderBookHeatmap/index.d.ts.map +1 -0
- package/dist/components/orderBookHeatmap/index.js +12 -0
- package/dist/components/orderBookHeatmap/index.js.map +1 -0
- package/dist/components/orderBookHeatmap/logColorScale.d.ts +20 -0
- package/dist/components/orderBookHeatmap/logColorScale.d.ts.map +1 -0
- package/dist/components/orderBookHeatmap/logColorScale.js +71 -0
- package/dist/components/orderBookHeatmap/logColorScale.js.map +1 -0
- package/dist/components/orderBookHeatmap/snapshotRing.d.ts +16 -0
- package/dist/components/orderBookHeatmap/snapshotRing.d.ts.map +1 -0
- package/dist/components/orderBookHeatmap/snapshotRing.js +61 -0
- package/dist/components/orderBookHeatmap/snapshotRing.js.map +1 -0
- package/dist/components/orderBookHeatmap/types.d.ts +128 -0
- package/dist/components/orderBookHeatmap/types.d.ts.map +1 -0
- package/dist/components/orderBookHeatmap/types.js +16 -0
- package/dist/components/orderBookHeatmap/types.js.map +1 -0
- package/dist/components/volumeProfile/binning.d.ts +54 -0
- package/dist/components/volumeProfile/binning.d.ts.map +1 -0
- package/dist/components/volumeProfile/binning.js +123 -0
- package/dist/components/volumeProfile/binning.js.map +1 -0
- package/dist/components/volumeProfile/createVolumeProfileController.d.ts +31 -0
- package/dist/components/volumeProfile/createVolumeProfileController.d.ts.map +1 -0
- package/dist/components/volumeProfile/createVolumeProfileController.js +179 -0
- package/dist/components/volumeProfile/createVolumeProfileController.js.map +1 -0
- package/dist/components/volumeProfile/index.d.ts +6 -0
- package/dist/components/volumeProfile/index.d.ts.map +1 -0
- package/dist/components/volumeProfile/index.js +5 -0
- package/dist/components/volumeProfile/index.js.map +1 -0
- package/dist/components/volumeProfile/poc.d.ts +35 -0
- package/dist/components/volumeProfile/poc.d.ts.map +1 -0
- package/dist/components/volumeProfile/poc.js +51 -0
- package/dist/components/volumeProfile/poc.js.map +1 -0
- package/dist/components/volumeProfile/types.d.ts +138 -0
- package/dist/components/volumeProfile/types.d.ts.map +1 -0
- package/dist/components/volumeProfile/types.js +19 -0
- package/dist/components/volumeProfile/types.js.map +1 -0
- package/dist/components/volumeProfile/valueArea.d.ts +58 -0
- package/dist/components/volumeProfile/valueArea.d.ts.map +1 -0
- package/dist/components/volumeProfile/valueArea.js +172 -0
- package/dist/components/volumeProfile/valueArea.js.map +1 -0
- package/dist/controllers/createChartController.d.ts.map +1 -1
- package/dist/controllers/createChartController.js +22 -11
- package/dist/controllers/createChartController.js.map +1 -1
- package/dist/controllers/types.d.ts +3 -1
- package/dist/controllers/types.d.ts.map +1 -1
- package/dist/data-fetchers/baostock.d.ts.map +1 -1
- package/dist/data-fetchers/baostock.js +2 -1
- package/dist/data-fetchers/baostock.js.map +1 -1
- package/dist/data-fetchers/dataBuffer.effects.d.ts.map +1 -1
- package/dist/data-fetchers/dataBuffer.effects.js +2 -1
- package/dist/data-fetchers/dataBuffer.effects.js.map +1 -1
- package/dist/data-fetchers/fetcherDefinitionRegistry.d.ts.map +1 -1
- package/dist/data-fetchers/fetcherDefinitionRegistry.js +2 -1
- package/dist/data-fetchers/fetcherDefinitionRegistry.js.map +1 -1
- package/dist/data-fetchers/gotdx.js +4 -3
- package/dist/data-fetchers/gotdx.js.map +1 -1
- package/dist/data-fetchers/router.d.ts.map +1 -1
- package/dist/data-fetchers/router.js +4 -3
- package/dist/data-fetchers/router.js.map +1 -1
- package/dist/data-fetchers/tradingview.js +3 -2
- package/dist/data-fetchers/tradingview.js.map +1 -1
- package/dist/engine/chart.d.ts +13 -0
- package/dist/engine/chart.d.ts.map +1 -1
- package/dist/engine/chart.js +109 -0
- package/dist/engine/chart.js.map +1 -1
- package/dist/engine/data/chartDataManager.d.ts +1 -0
- package/dist/engine/data/chartDataManager.d.ts.map +1 -1
- package/dist/engine/data/chartDataManager.js +27 -4
- package/dist/engine/data/chartDataManager.js.map +1 -1
- package/dist/engine/drawing/toolConfig.d.ts.map +1 -1
- package/dist/engine/drawing/toolConfig.js +2 -1
- package/dist/engine/drawing/toolConfig.js.map +1 -1
- package/dist/engine/indicators/chartIndicatorManager.d.ts.map +1 -1
- package/dist/engine/indicators/chartIndicatorManager.js +2 -1
- package/dist/engine/indicators/chartIndicatorManager.js.map +1 -1
- package/dist/engine/indicators/indicatorDefinitionRegistry.d.ts.map +1 -1
- package/dist/engine/indicators/indicatorDefinitionRegistry.js +2 -1
- package/dist/engine/indicators/indicatorDefinitionRegistry.js.map +1 -1
- package/dist/engine/indicators/indicatorMetadata.d.ts.map +1 -1
- package/dist/engine/indicators/indicatorMetadata.js +2 -1
- package/dist/engine/indicators/indicatorMetadata.js.map +1 -1
- package/dist/engine/indicators/indicatorRegistry.d.ts.map +1 -1
- package/dist/engine/indicators/indicatorRegistry.js +6 -5
- package/dist/engine/indicators/indicatorRegistry.js.map +1 -1
- package/dist/engine/indicators/registerBuiltins.d.ts.map +1 -1
- package/dist/engine/indicators/registerBuiltins.js +2 -1
- package/dist/engine/indicators/registerBuiltins.js.map +1 -1
- package/dist/engine/indicators/scheduler.d.ts +6 -0
- package/dist/engine/indicators/scheduler.d.ts.map +1 -1
- package/dist/engine/indicators/scheduler.js +12 -0
- package/dist/engine/indicators/scheduler.js.map +1 -1
- package/dist/engine/indicators/soa.d.ts.map +1 -1
- package/dist/engine/indicators/soa.js +2 -1
- package/dist/engine/indicators/soa.js.map +1 -1
- package/dist/engine/indicators/stateComposer.d.ts.map +1 -1
- package/dist/engine/indicators/stateComposer.js +2 -1
- package/dist/engine/indicators/stateComposer.js.map +1 -1
- package/dist/engine/subPaneManager.d.ts.map +1 -1
- package/dist/engine/subPaneManager.js +2 -1
- package/dist/engine/subPaneManager.js.map +1 -1
- package/dist/engine/utils/chartZoomController.d.ts +2 -0
- package/dist/engine/utils/chartZoomController.d.ts.map +1 -1
- package/dist/engine/utils/chartZoomController.js +5 -1
- package/dist/engine/utils/chartZoomController.js.map +1 -1
- package/dist/errors-help.d.ts +72 -0
- package/dist/errors-help.d.ts.map +1 -0
- package/dist/errors-help.js +149 -0
- package/dist/errors-help.js.map +1 -0
- package/dist/errors.d.ts +64 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +61 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -1
- package/dist/indicators/alma.d.ts +27 -0
- package/dist/indicators/alma.d.ts.map +1 -0
- package/dist/indicators/alma.js +36 -0
- package/dist/indicators/alma.js.map +1 -0
- package/dist/indicators/awesomeOscillator.d.ts +19 -0
- package/dist/indicators/awesomeOscillator.d.ts.map +1 -0
- package/dist/indicators/awesomeOscillator.js +36 -0
- package/dist/indicators/awesomeOscillator.js.map +1 -0
- package/dist/indicators/dpo.d.ts +17 -0
- package/dist/indicators/dpo.d.ts.map +1 -0
- package/dist/indicators/dpo.js +24 -0
- package/dist/indicators/dpo.js.map +1 -0
- package/dist/indicators/fisherTransform.d.ts +26 -0
- package/dist/indicators/fisherTransform.d.ts.map +1 -0
- package/dist/indicators/fisherTransform.js +44 -0
- package/dist/indicators/fisherTransform.js.map +1 -0
- package/dist/indicators/frama.d.ts +25 -0
- package/dist/indicators/frama.d.ts.map +1 -0
- package/dist/indicators/frama.js +61 -0
- package/dist/indicators/frama.js.map +1 -0
- package/dist/indicators/index.d.ts +24 -0
- package/dist/indicators/index.d.ts.map +1 -0
- package/dist/indicators/index.js +26 -0
- package/dist/indicators/index.js.map +1 -0
- package/dist/indicators/lsma.d.ts +21 -0
- package/dist/indicators/lsma.d.ts.map +1 -0
- package/dist/indicators/lsma.js +37 -0
- package/dist/indicators/lsma.js.map +1 -0
- package/dist/indicators/schaffTrendCycle.d.ts +24 -0
- package/dist/indicators/schaffTrendCycle.d.ts.map +1 -0
- package/dist/indicators/schaffTrendCycle.js +70 -0
- package/dist/indicators/schaffTrendCycle.js.map +1 -0
- package/dist/indicators/stochRSI.d.ts +24 -0
- package/dist/indicators/stochRSI.d.ts.map +1 -0
- package/dist/indicators/stochRSI.js +86 -0
- package/dist/indicators/stochRSI.js.map +1 -0
- package/dist/indicators/t3.d.ts +31 -0
- package/dist/indicators/t3.d.ts.map +1 -0
- package/dist/indicators/t3.js +63 -0
- package/dist/indicators/t3.js.map +1 -0
- package/dist/indicators/ultimateOscillator.d.ts +26 -0
- package/dist/indicators/ultimateOscillator.d.ts.map +1 -0
- package/dist/indicators/ultimateOscillator.js +59 -0
- package/dist/indicators/ultimateOscillator.js.map +1 -0
- package/dist/indicators/vidya.d.ts +24 -0
- package/dist/indicators/vidya.d.ts.map +1 -0
- package/dist/indicators/vidya.js +54 -0
- package/dist/indicators/vidya.js.map +1 -0
- package/dist/indicators/zlema.d.ts +16 -0
- package/dist/indicators/zlema.d.ts.map +1 -0
- package/dist/indicators/zlema.js +26 -0
- package/dist/indicators/zlema.js.map +1 -0
- package/dist/input/gesture.d.ts +125 -0
- package/dist/input/gesture.d.ts.map +1 -0
- package/dist/input/gesture.js +249 -0
- package/dist/input/gesture.js.map +1 -0
- package/dist/input/index.d.ts +9 -0
- package/dist/input/index.d.ts.map +1 -0
- package/dist/input/index.js +9 -0
- package/dist/input/index.js.map +1 -0
- package/dist/input/keyboard.d.ts +140 -0
- package/dist/input/keyboard.d.ts.map +1 -0
- package/dist/input/keyboard.js +260 -0
- package/dist/input/keyboard.js.map +1 -0
- package/dist/mcp/chartBridge.d.ts +2 -2
- package/dist/mcp/chartBridge.d.ts.map +1 -1
- package/dist/mcp/chartBridge.js +27 -21
- package/dist/mcp/chartBridge.js.map +1 -1
- package/dist/plugin/PluginHost.d.ts +0 -3
- package/dist/plugin/PluginHost.d.ts.map +1 -1
- package/dist/plugin/PluginHost.js +7 -3
- package/dist/plugin/PluginHost.js.map +1 -1
- package/dist/plugin/PluginRegistry.d.ts +0 -3
- package/dist/plugin/PluginRegistry.d.ts.map +1 -1
- package/dist/plugin/PluginRegistry.js +5 -1
- package/dist/plugin/PluginRegistry.js.map +1 -1
- package/dist/render/Renderer.d.ts +116 -0
- package/dist/render/Renderer.d.ts.map +1 -0
- package/dist/render/Renderer.js +31 -0
- package/dist/render/Renderer.js.map +1 -0
- package/dist/render/SurfaceBackend.d.ts +83 -0
- package/dist/render/SurfaceBackend.d.ts.map +1 -0
- package/dist/render/SurfaceBackend.js +27 -0
- package/dist/render/SurfaceBackend.js.map +1 -0
- package/dist/render/index.d.ts +12 -0
- package/dist/render/index.d.ts.map +1 -0
- package/dist/render/index.js +11 -0
- package/dist/render/index.js.map +1 -0
- package/dist/renderer-tier/detectRendererTier.d.ts +57 -0
- package/dist/renderer-tier/detectRendererTier.d.ts.map +1 -0
- package/dist/renderer-tier/detectRendererTier.js +143 -0
- package/dist/renderer-tier/detectRendererTier.js.map +1 -0
- package/dist/renderer-tier/index.d.ts +12 -0
- package/dist/renderer-tier/index.d.ts.map +1 -0
- package/dist/renderer-tier/index.js +12 -0
- package/dist/renderer-tier/index.js.map +1 -0
- package/dist/renderer-tier/selectBackend.d.ts +106 -0
- package/dist/renderer-tier/selectBackend.d.ts.map +1 -0
- package/dist/renderer-tier/selectBackend.js +113 -0
- package/dist/renderer-tier/selectBackend.js.map +1 -0
- package/dist/renderer-tier/types.d.ts +50 -0
- package/dist/renderer-tier/types.d.ts.map +1 -0
- package/dist/renderer-tier/types.js +24 -0
- package/dist/renderer-tier/types.js.map +1 -0
- package/dist/replay/createReplayController.d.ts +3 -0
- package/dist/replay/createReplayController.d.ts.map +1 -0
- package/dist/replay/createReplayController.js +251 -0
- package/dist/replay/createReplayController.js.map +1 -0
- package/dist/replay/index.d.ts +5 -0
- package/dist/replay/index.d.ts.map +1 -0
- package/dist/replay/index.js +3 -0
- package/dist/replay/index.js.map +1 -0
- package/dist/replay/timeline.d.ts +50 -0
- package/dist/replay/timeline.d.ts.map +1 -0
- package/dist/replay/timeline.js +104 -0
- package/dist/replay/timeline.js.map +1 -0
- package/dist/replay/types.d.ts +94 -0
- package/dist/replay/types.d.ts.map +1 -0
- package/dist/replay/types.js +21 -0
- package/dist/replay/types.js.map +1 -0
- package/dist/scale/anchoredZoom.d.ts +64 -0
- package/dist/scale/anchoredZoom.d.ts.map +1 -0
- package/dist/scale/anchoredZoom.js +67 -0
- package/dist/scale/anchoredZoom.js.map +1 -0
- package/dist/scale/createPriceScale.d.ts +49 -0
- package/dist/scale/createPriceScale.d.ts.map +1 -0
- package/dist/scale/createPriceScale.js +175 -0
- package/dist/scale/createPriceScale.js.map +1 -0
- package/dist/scale/createTimeScale.d.ts +27 -0
- package/dist/scale/createTimeScale.d.ts.map +1 -0
- package/dist/scale/createTimeScale.js +139 -0
- package/dist/scale/createTimeScale.js.map +1 -0
- package/dist/scale/index.d.ts +6 -0
- package/dist/scale/index.d.ts.map +1 -0
- package/dist/scale/index.js +5 -0
- package/dist/scale/index.js.map +1 -0
- package/dist/scale/originShift.d.ts +69 -0
- package/dist/scale/originShift.d.ts.map +1 -0
- package/dist/scale/originShift.js +41 -0
- package/dist/scale/originShift.js.map +1 -0
- package/dist/scale/types.d.ts +90 -0
- package/dist/scale/types.d.ts.map +1 -0
- package/dist/scale/types.js +17 -0
- package/dist/scale/types.js.map +1 -0
- package/dist/scene/createScene.d.ts +22 -0
- package/dist/scene/createScene.d.ts.map +1 -0
- package/dist/scene/createScene.js +114 -0
- package/dist/scene/createScene.js.map +1 -0
- package/dist/scene/index.d.ts +13 -0
- package/dist/scene/index.d.ts.map +1 -0
- package/dist/scene/index.js +11 -0
- package/dist/scene/index.js.map +1 -0
- package/dist/scene/layerRegistry.d.ts +83 -0
- package/dist/scene/layerRegistry.d.ts.map +1 -0
- package/dist/scene/layerRegistry.js +43 -0
- package/dist/scene/layerRegistry.js.map +1 -0
- package/dist/scene/types.d.ts +128 -0
- package/dist/scene/types.d.ts.map +1 -0
- package/dist/scene/types.js +21 -0
- package/dist/scene/types.js.map +1 -0
- package/dist/scheduler/createFrameBudget.d.ts +91 -0
- package/dist/scheduler/createFrameBudget.d.ts.map +1 -0
- package/dist/scheduler/createFrameBudget.js +232 -0
- package/dist/scheduler/createFrameBudget.js.map +1 -0
- package/dist/scheduler/index.d.ts +2 -0
- package/dist/scheduler/index.d.ts.map +1 -0
- package/dist/scheduler/index.js +2 -0
- package/dist/scheduler/index.js.map +1 -0
- package/dist/tokens/themeToCssVars.d.ts.map +1 -1
- package/dist/tokens/themeToCssVars.js +2 -28
- package/dist/tokens/themeToCssVars.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +1 -1
- package/src/__bench__/indicators.bench.ts +215 -0
- package/src/__bench__/orderBookHeatmap.bench.ts +68 -0
- package/src/__bench__/scale.bench.ts +80 -0
- package/src/__bench__/signal.bench.ts +41 -0
- package/src/__bench__/volumeProfile.bench.ts +66 -0
- package/src/__tests__/errors-help.test.ts +184 -0
- package/src/__tests__/errors.test.ts +187 -0
- package/src/alerts/__tests__/controller.test.ts +231 -0
- package/src/alerts/__tests__/predicates.test.ts +374 -0
- package/src/alerts/__tests__/ruleSchema.test.ts +180 -0
- package/src/alerts/createAlertController.ts +312 -0
- package/src/alerts/index.ts +18 -0
- package/src/alerts/predicates.ts +231 -0
- package/src/alerts/rollingVolume.ts +51 -0
- package/src/alerts/ruleSchema.ts +278 -0
- package/src/alerts/types.ts +177 -0
- package/src/chartTypes/__tests__/heikinAshi.test.ts +122 -0
- package/src/chartTypes/__tests__/pointAndFigure.test.ts +167 -0
- package/src/chartTypes/__tests__/rangeBars.test.ts +146 -0
- package/src/chartTypes/__tests__/renko.test.ts +160 -0
- package/src/chartTypes/heikinAshi.ts +116 -0
- package/src/chartTypes/index.ts +5 -0
- package/src/chartTypes/pointAndFigure.ts +278 -0
- package/src/chartTypes/rangeBars.ts +303 -0
- package/src/chartTypes/renko.ts +311 -0
- package/src/chartTypes/types.ts +99 -0
- package/src/components/anchoredVwap/__tests__/computeAnchoredVwap.test.ts +331 -0
- package/src/components/anchoredVwap/__tests__/controller.test.ts +430 -0
- package/src/components/anchoredVwap/computeAnchoredVwap.ts +174 -0
- package/src/components/anchoredVwap/createAnchoredVwapController.ts +358 -0
- package/src/components/anchoredVwap/index.ts +17 -0
- package/src/components/anchoredVwap/types.ts +187 -0
- package/src/components/crosshairSync/__tests__/crosshairSync.test.ts +261 -0
- package/src/components/crosshairSync/createCrosshairSync.ts +187 -0
- package/src/components/crosshairSync/index.ts +5 -0
- package/src/components/footprint/__tests__/aggressor.test.ts +127 -0
- package/src/components/footprint/__tests__/controller.test.ts +130 -0
- package/src/components/footprint/__tests__/perBarStats.test.ts +114 -0
- package/src/components/footprint/aggressor.ts +165 -0
- package/src/components/footprint/createFootprintController.ts +338 -0
- package/src/components/footprint/index.ts +21 -0
- package/src/components/footprint/perBarStats.ts +137 -0
- package/src/components/footprint/types.ts +232 -0
- package/src/components/mtfOverlay/__tests__/alignToBaseIndex.test.ts +103 -0
- package/src/components/mtfOverlay/__tests__/controller.test.ts +172 -0
- package/src/components/mtfOverlay/__tests__/resampleBars.test.ts +106 -0
- package/src/components/mtfOverlay/alignToBaseIndex.ts +108 -0
- package/src/components/mtfOverlay/createMtfController.ts +180 -0
- package/src/components/mtfOverlay/index.ts +26 -0
- package/src/components/mtfOverlay/resampleBars.ts +134 -0
- package/src/components/mtfOverlay/types.ts +148 -0
- package/src/components/orderBookHeatmap/__tests__/controller.test.ts +237 -0
- package/src/components/orderBookHeatmap/__tests__/deltaArchive.test.ts +88 -0
- package/src/components/orderBookHeatmap/__tests__/logColorScale.test.ts +69 -0
- package/src/components/orderBookHeatmap/__tests__/orderBookState.test.ts +113 -0
- package/src/components/orderBookHeatmap/__tests__/snapshotRing.test.ts +53 -0
- package/src/components/orderBookHeatmap/computeShader.wgsl.md +130 -0
- package/src/components/orderBookHeatmap/createHeatmapController.ts +273 -0
- package/src/components/orderBookHeatmap/createOrderBookState.ts +116 -0
- package/src/components/orderBookHeatmap/deltaArchive.ts +113 -0
- package/src/components/orderBookHeatmap/index.ts +25 -0
- package/src/components/orderBookHeatmap/logColorScale.ts +77 -0
- package/src/components/orderBookHeatmap/snapshotRing.ts +65 -0
- package/src/components/orderBookHeatmap/types.ts +168 -0
- package/src/components/volumeProfile/__tests__/binning.test.ts +133 -0
- package/src/components/volumeProfile/__tests__/poc.test.ts +44 -0
- package/src/components/volumeProfile/__tests__/valueArea.test.ts +177 -0
- package/src/components/volumeProfile/binning.ts +133 -0
- package/src/components/volumeProfile/createVolumeProfileController.ts +213 -0
- package/src/components/volumeProfile/index.ts +12 -0
- package/src/components/volumeProfile/poc.ts +53 -0
- package/src/components/volumeProfile/types.ts +148 -0
- package/src/components/volumeProfile/valueArea.ts +187 -0
- package/src/controllers/createChartController.ts +23 -10
- package/src/controllers/types.ts +5 -1
- package/src/data-fetchers/baostock.ts +2 -1
- package/src/data-fetchers/dataBuffer.effects.ts +3 -1
- package/src/data-fetchers/fetcherDefinitionRegistry.ts +2 -1
- package/src/data-fetchers/gotdx.ts +4 -3
- package/src/data-fetchers/router.ts +6 -3
- package/src/data-fetchers/tradingview.ts +3 -2
- package/src/engine/chart.ts +126 -3
- package/src/engine/data/chartDataManager.ts +26 -4
- package/src/engine/drawing/toolConfig.ts +2 -1
- package/src/engine/indicators/chartIndicatorManager.ts +2 -1
- package/src/engine/indicators/indicatorDefinitionRegistry.ts +2 -1
- package/src/engine/indicators/indicatorMetadata.ts +2 -1
- package/src/engine/indicators/indicatorRegistry.ts +6 -5
- package/src/engine/indicators/registerBuiltins.ts +2 -1
- package/src/engine/indicators/scheduler.ts +15 -0
- package/src/engine/indicators/soa.ts +2 -1
- package/src/engine/indicators/stateComposer.ts +2 -1
- package/src/engine/subPaneManager.ts +2 -1
- package/src/engine/utils/chartZoomController.ts +7 -1
- package/src/errors-help.ts +218 -0
- package/src/errors.ts +128 -0
- package/src/index.ts +37 -0
- package/src/indicators/__tests__/maFamily.test.ts +159 -0
- package/src/indicators/__tests__/oscillators.test.ts +150 -0
- package/src/indicators/alma.ts +61 -0
- package/src/indicators/awesomeOscillator.ts +54 -0
- package/src/indicators/dpo.ts +37 -0
- package/src/indicators/fisherTransform.ts +63 -0
- package/src/indicators/frama.ts +87 -0
- package/src/indicators/index.ts +39 -0
- package/src/indicators/lsma.ts +58 -0
- package/src/indicators/schaffTrendCycle.ts +92 -0
- package/src/indicators/stochRSI.ts +108 -0
- package/src/indicators/t3.ts +96 -0
- package/src/indicators/ultimateOscillator.ts +83 -0
- package/src/indicators/vidya.ts +80 -0
- package/src/indicators/zlema.ts +41 -0
- package/src/input/__tests__/gesture.test.ts +271 -0
- package/src/input/__tests__/keyboard.test.ts +317 -0
- package/src/input/gesture.ts +357 -0
- package/src/input/index.ts +26 -0
- package/src/input/keyboard.ts +373 -0
- package/src/mcp/chartBridge.ts +98 -72
- package/src/plugin/PluginHost.ts +4 -3
- package/src/plugin/PluginRegistry.ts +2 -1
- package/src/render/Renderer.ts +127 -0
- package/src/render/SurfaceBackend.ts +94 -0
- package/src/render/__tests__/contract.test.ts +176 -0
- package/src/render/index.ts +27 -0
- package/src/renderer-tier/__tests__/detectRendererTier.test.ts +180 -0
- package/src/renderer-tier/__tests__/selectBackend.test.ts +253 -0
- package/src/renderer-tier/detectRendererTier.ts +168 -0
- package/src/renderer-tier/index.ts +30 -0
- package/src/renderer-tier/selectBackend.ts +201 -0
- package/src/renderer-tier/types.ts +59 -0
- package/src/replay/__tests__/controller.test.ts +309 -0
- package/src/replay/__tests__/timeline.test.ts +99 -0
- package/src/replay/createReplayController.ts +302 -0
- package/src/replay/index.ts +15 -0
- package/src/replay/timeline.ts +106 -0
- package/src/replay/types.ts +107 -0
- package/src/scale/__tests__/anchoredZoom.test.ts +125 -0
- package/src/scale/__tests__/originShift.test.ts +97 -0
- package/src/scale/__tests__/priceScale.test.ts +219 -0
- package/src/scale/__tests__/timeScale.test.ts +119 -0
- package/src/scale/anchoredZoom.ts +104 -0
- package/src/scale/createPriceScale.ts +226 -0
- package/src/scale/createTimeScale.ts +150 -0
- package/src/scale/index.ts +9 -0
- package/src/scale/originShift.ts +111 -0
- package/src/scale/types.ts +100 -0
- package/src/scene/__tests__/layerRegistry.test.ts +207 -0
- package/src/scene/__tests__/scene.test.ts +411 -0
- package/src/scene/createScene.ts +117 -0
- package/src/scene/index.ts +29 -0
- package/src/scene/layerRegistry.ts +117 -0
- package/src/scene/types.ts +143 -0
- package/src/scheduler/__tests__/createFrameBudget.test.ts +315 -0
- package/src/scheduler/createFrameBudget.ts +316 -0
- package/src/scheduler/index.ts +7 -0
- package/src/tokens/themeToCssVars.ts +3 -1
- package/src/version.ts +1 -1
- package/dist/data-fetchers/gotdx/gotdx.d.ts +0 -7
- package/dist/data-fetchers/gotdx/gotdx.d.ts.map +0 -1
- package/dist/data-fetchers/gotdx/gotdx.js +0 -7
- package/dist/data-fetchers/gotdx/gotdx.js.map +0 -1
- package/src/data-fetchers/gotdx/gotdx.ts +0 -6
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renderer tier types.
|
|
3
|
+
*
|
|
4
|
+
* `RendererTier` is a totally-ordered enum (`'webgpu' > 'webgl2' >
|
|
5
|
+
* 'canvas2d' > 'none'`). Consumers pick the highest tier the host
|
|
6
|
+
* environment supports and configure the {@link Renderer} accordingly.
|
|
7
|
+
*
|
|
8
|
+
* Why a string union (not a numeric enum):
|
|
9
|
+
* - Logs and analytics stay human-readable.
|
|
10
|
+
* - Tree-shakable; no runtime enum object.
|
|
11
|
+
* - Cross-package safe — string equality survives serialization
|
|
12
|
+
* and avoids the "two enum copies don't compare" footgun.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export type RendererTier = 'webgpu' | 'webgl2' | 'canvas2d' | 'none'
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Numeric rank used for `compareRendererTier`. Higher = better.
|
|
19
|
+
* Exposed so consumers can write their own "at least X" guards.
|
|
20
|
+
*/
|
|
21
|
+
export const RENDERER_TIER_RANK: Readonly<Record<RendererTier, number>> = {
|
|
22
|
+
webgpu: 3,
|
|
23
|
+
webgl2: 2,
|
|
24
|
+
canvas2d: 1,
|
|
25
|
+
none: 0,
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Detection result. `tier` is the picked tier; `reason` is a one-line
|
|
30
|
+
* human-readable explanation (intended for diagnostics, not for
|
|
31
|
+
* branching — branch on `tier`).
|
|
32
|
+
*
|
|
33
|
+
* `tried` enumerates the tiers probed in order — useful when reporting
|
|
34
|
+
* "we wanted WebGPU but it threw" telemetry.
|
|
35
|
+
*/
|
|
36
|
+
export interface RendererTierResult {
|
|
37
|
+
readonly tier: RendererTier
|
|
38
|
+
readonly reason: string
|
|
39
|
+
readonly tried: ReadonlyArray<RendererTier>
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Probe injection — the unit tests use this to simulate every tier
|
|
44
|
+
* combination without poking globals. Production code passes nothing
|
|
45
|
+
* and the real `globalThis` probes run.
|
|
46
|
+
*
|
|
47
|
+
* Each probe returns `true` when the tier is detected, `false` when
|
|
48
|
+
* it is conclusively unavailable. Throwing is treated as "unavailable"
|
|
49
|
+
* with the message folded into `reason`.
|
|
50
|
+
*/
|
|
51
|
+
export interface RendererTierProbes {
|
|
52
|
+
readonly webgpu?: () => boolean
|
|
53
|
+
readonly webgl2?: () => boolean
|
|
54
|
+
readonly canvas2d?: () => boolean
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface DetectRendererTierOptions {
|
|
58
|
+
readonly probes?: RendererTierProbes
|
|
59
|
+
}
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest'
|
|
2
|
+
import { createReplayController } from '../createReplayController'
|
|
3
|
+
import type { ReplayState } from '../types'
|
|
4
|
+
|
|
5
|
+
// A 1-minute bar interval so wall-clock math is easy to reason about:
|
|
6
|
+
// 1000ms of wall-clock at speed=1 advances 1000/60000 = 0.01666... bars.
|
|
7
|
+
// At speed=60, 1000ms advances 1 full bar.
|
|
8
|
+
const ONE_MINUTE_MS = 60_000
|
|
9
|
+
|
|
10
|
+
function build(initOverride: Partial<Parameters<typeof createReplayController>[0]> = {}) {
|
|
11
|
+
return createReplayController({
|
|
12
|
+
start: 0,
|
|
13
|
+
end: 99,
|
|
14
|
+
pacing: 'bar',
|
|
15
|
+
speed: 1,
|
|
16
|
+
barIntervalMs: ONE_MINUTE_MS,
|
|
17
|
+
...initOverride,
|
|
18
|
+
})
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
describe('createReplayController', () => {
|
|
22
|
+
it('initialises position at start with mode=paused', () => {
|
|
23
|
+
const ctrl = build()
|
|
24
|
+
const s = ctrl.state.peek()
|
|
25
|
+
expect(s.position).toBe(0)
|
|
26
|
+
expect(s.start).toBe(0)
|
|
27
|
+
expect(s.end).toBe(99)
|
|
28
|
+
expect(s.mode).toBe('paused')
|
|
29
|
+
expect(s.pacing).toBe('bar')
|
|
30
|
+
expect(s.speed).toBe(1)
|
|
31
|
+
ctrl.dispose()
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it('throws on construction when end < start', () => {
|
|
35
|
+
expect(() => build({ start: 10, end: 5 })).toThrow(/end.*start/i)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('throws on construction when speed <= 0', () => {
|
|
39
|
+
expect(() => build({ speed: 0 })).toThrow(/speed/i)
|
|
40
|
+
expect(() => build({ speed: -1 })).toThrow(/speed/i)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
it('seekTo within range updates state and notifies subscribers', () => {
|
|
44
|
+
const ctrl = build()
|
|
45
|
+
const fn = vi.fn()
|
|
46
|
+
const unsub = ctrl.state.subscribe(fn)
|
|
47
|
+
ctrl.seekTo(42)
|
|
48
|
+
expect(ctrl.state.peek().position).toBe(42)
|
|
49
|
+
expect(fn).toHaveBeenCalledTimes(1)
|
|
50
|
+
unsub()
|
|
51
|
+
ctrl.dispose()
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it('seekTo above end clamps to end', () => {
|
|
55
|
+
const ctrl = build()
|
|
56
|
+
ctrl.seekTo(1_000_000)
|
|
57
|
+
expect(ctrl.state.peek().position).toBe(99)
|
|
58
|
+
ctrl.dispose()
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
it('seekTo below start clamps to start', () => {
|
|
62
|
+
const ctrl = build()
|
|
63
|
+
ctrl.seekTo(-50)
|
|
64
|
+
expect(ctrl.state.peek().position).toBe(0)
|
|
65
|
+
ctrl.dispose()
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it('stepForward + stepBackward returns to the same position', () => {
|
|
69
|
+
const ctrl = build()
|
|
70
|
+
ctrl.seekTo(20)
|
|
71
|
+
ctrl.stepForward()
|
|
72
|
+
expect(ctrl.state.peek().position).toBe(21)
|
|
73
|
+
ctrl.stepBackward()
|
|
74
|
+
expect(ctrl.state.peek().position).toBe(20)
|
|
75
|
+
ctrl.dispose()
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
it('consecutive stepForward past end clamps to end and auto-pauses if playing', () => {
|
|
79
|
+
const ctrl = build({ end: 3 })
|
|
80
|
+
ctrl.seekTo(2)
|
|
81
|
+
ctrl.play()
|
|
82
|
+
expect(ctrl.state.peek().mode).toBe('playing')
|
|
83
|
+
ctrl.stepForward() // -> 3, hits end while playing => auto-paused
|
|
84
|
+
const s = ctrl.state.peek()
|
|
85
|
+
expect(s.position).toBe(3)
|
|
86
|
+
expect(s.mode).toBe('paused')
|
|
87
|
+
// Further forwards stay clamped.
|
|
88
|
+
ctrl.stepForward()
|
|
89
|
+
expect(ctrl.state.peek().position).toBe(3)
|
|
90
|
+
ctrl.dispose()
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
it('play() then pause() toggles mode and emits both transitions', () => {
|
|
94
|
+
const ctrl = build()
|
|
95
|
+
ctrl.seekTo(10)
|
|
96
|
+
const fn = vi.fn()
|
|
97
|
+
const unsub = ctrl.state.subscribe(fn)
|
|
98
|
+
ctrl.play()
|
|
99
|
+
expect(ctrl.state.peek().mode).toBe('playing')
|
|
100
|
+
ctrl.pause()
|
|
101
|
+
expect(ctrl.state.peek().mode).toBe('paused')
|
|
102
|
+
expect(fn).toHaveBeenCalledTimes(2)
|
|
103
|
+
unsub()
|
|
104
|
+
ctrl.dispose()
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
it('toggle() flips between paused and playing', () => {
|
|
108
|
+
const ctrl = build()
|
|
109
|
+
ctrl.seekTo(10)
|
|
110
|
+
expect(ctrl.state.peek().mode).toBe('paused')
|
|
111
|
+
ctrl.toggle()
|
|
112
|
+
expect(ctrl.state.peek().mode).toBe('playing')
|
|
113
|
+
ctrl.toggle()
|
|
114
|
+
expect(ctrl.state.peek().mode).toBe('paused')
|
|
115
|
+
ctrl.dispose()
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
it('play() at end stays paused (no observable mode flip)', () => {
|
|
119
|
+
const ctrl = build({ end: 5 })
|
|
120
|
+
ctrl.seekTo(5)
|
|
121
|
+
const fn = vi.fn()
|
|
122
|
+
const unsub = ctrl.state.subscribe(fn)
|
|
123
|
+
ctrl.play()
|
|
124
|
+
expect(ctrl.state.peek().mode).toBe('paused')
|
|
125
|
+
expect(fn).not.toHaveBeenCalled()
|
|
126
|
+
unsub()
|
|
127
|
+
ctrl.dispose()
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
it('tick() in bar mode is a no-op when playing', () => {
|
|
131
|
+
const ctrl = build({ pacing: 'bar' })
|
|
132
|
+
ctrl.play()
|
|
133
|
+
const before = ctrl.state.peek().position
|
|
134
|
+
const changed = ctrl.tick(1000)
|
|
135
|
+
expect(changed).toBe(false)
|
|
136
|
+
expect(ctrl.state.peek().position).toBe(before)
|
|
137
|
+
ctrl.dispose()
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
it('tick() in wallclock mode advances proportional to deltaMs * speed', () => {
|
|
141
|
+
const ctrl = build({ pacing: 'wallclock', speed: 1 })
|
|
142
|
+
ctrl.play()
|
|
143
|
+
// 1000ms at speed=1 with 60_000ms/bar → 1/60 of a bar.
|
|
144
|
+
const changed = ctrl.tick(1000)
|
|
145
|
+
expect(changed).toBe(true)
|
|
146
|
+
expect(ctrl.state.peek().position).toBeCloseTo(1 / 60, 10)
|
|
147
|
+
|
|
148
|
+
// Bump speed to 60 → 1000ms advances exactly 1 bar.
|
|
149
|
+
ctrl.setSpeed(60)
|
|
150
|
+
const before = ctrl.state.peek().position
|
|
151
|
+
ctrl.tick(1000)
|
|
152
|
+
expect(ctrl.state.peek().position).toBeCloseTo(before + 1, 10)
|
|
153
|
+
ctrl.dispose()
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
it('tick() in tick mode advances faster than wallclock at the same speed', () => {
|
|
157
|
+
const wallCtrl = build({ pacing: 'wallclock', speed: 1 })
|
|
158
|
+
const tickCtrl = build({ pacing: 'tick', speed: 1 })
|
|
159
|
+
wallCtrl.play()
|
|
160
|
+
tickCtrl.play()
|
|
161
|
+
wallCtrl.tick(1000)
|
|
162
|
+
tickCtrl.tick(1000)
|
|
163
|
+
const wallAdvance = wallCtrl.state.peek().position
|
|
164
|
+
const tickAdvance = tickCtrl.state.peek().position
|
|
165
|
+
expect(tickAdvance).toBeGreaterThan(wallAdvance)
|
|
166
|
+
// 1000ms / 100ms-per-bar * speed=1 = 10 bars
|
|
167
|
+
expect(tickAdvance).toBeCloseTo(10, 10)
|
|
168
|
+
wallCtrl.dispose()
|
|
169
|
+
tickCtrl.dispose()
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
it('reaching end via tick() auto-pauses and clamps to end', () => {
|
|
173
|
+
const ctrl = build({ pacing: 'wallclock', speed: 60, end: 5 })
|
|
174
|
+
ctrl.play()
|
|
175
|
+
// 10 bars worth of advance — far past the end (5).
|
|
176
|
+
ctrl.tick(10_000)
|
|
177
|
+
const s = ctrl.state.peek()
|
|
178
|
+
expect(s.position).toBe(5)
|
|
179
|
+
expect(s.mode).toBe('paused')
|
|
180
|
+
ctrl.dispose()
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
it('setPacing mid-play keeps mode=playing and switches tick math', () => {
|
|
184
|
+
const ctrl = build({ pacing: 'wallclock', speed: 1 })
|
|
185
|
+
ctrl.play()
|
|
186
|
+
ctrl.tick(1000)
|
|
187
|
+
const afterWall = ctrl.state.peek().position
|
|
188
|
+
expect(ctrl.state.peek().mode).toBe('playing')
|
|
189
|
+
|
|
190
|
+
ctrl.setPacing('bar')
|
|
191
|
+
// Still playing, but bar pacing means tick() no longer advances.
|
|
192
|
+
expect(ctrl.state.peek().mode).toBe('playing')
|
|
193
|
+
const changed = ctrl.tick(1000)
|
|
194
|
+
expect(changed).toBe(false)
|
|
195
|
+
expect(ctrl.state.peek().position).toBe(afterWall)
|
|
196
|
+
ctrl.dispose()
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
it('setSpeed(<=0) throws and does not mutate state', () => {
|
|
200
|
+
const ctrl = build()
|
|
201
|
+
const before = ctrl.state.peek()
|
|
202
|
+
expect(() => ctrl.setSpeed(0)).toThrow(/speed/i)
|
|
203
|
+
expect(() => ctrl.setSpeed(-2)).toThrow(/speed/i)
|
|
204
|
+
expect(ctrl.state.peek()).toBe(before) // same object reference
|
|
205
|
+
ctrl.dispose()
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
it('setRange clamps current position into the new range', () => {
|
|
209
|
+
const ctrl = build({ end: 100 })
|
|
210
|
+
ctrl.seekTo(80)
|
|
211
|
+
ctrl.setRange(0, 50)
|
|
212
|
+
const s = ctrl.state.peek()
|
|
213
|
+
expect(s.start).toBe(0)
|
|
214
|
+
expect(s.end).toBe(50)
|
|
215
|
+
expect(s.position).toBe(50)
|
|
216
|
+
ctrl.dispose()
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
it('setRange throws when end < start and leaves state untouched', () => {
|
|
220
|
+
const ctrl = build()
|
|
221
|
+
const before = ctrl.state.peek()
|
|
222
|
+
expect(() => ctrl.setRange(20, 10)).toThrow(/end.*start/i)
|
|
223
|
+
expect(ctrl.state.peek()).toBe(before)
|
|
224
|
+
ctrl.dispose()
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
it('tick() returns true only when position changed', () => {
|
|
228
|
+
const ctrl = build({ pacing: 'wallclock', speed: 60, end: 10 })
|
|
229
|
+
ctrl.play()
|
|
230
|
+
expect(ctrl.tick(1000)).toBe(true) // advanced ~1 bar
|
|
231
|
+
// Seek to the end manually so playback is at the right edge.
|
|
232
|
+
ctrl.seekTo(10)
|
|
233
|
+
// After clamping at end, the controller has auto-paused already, so
|
|
234
|
+
// tick() should refuse to advance (mode != 'playing').
|
|
235
|
+
expect(ctrl.tick(1000)).toBe(false)
|
|
236
|
+
|
|
237
|
+
// Negative or zero delta is ignored regardless of mode.
|
|
238
|
+
const fresh = build({ pacing: 'wallclock' })
|
|
239
|
+
fresh.play()
|
|
240
|
+
expect(fresh.tick(0)).toBe(false)
|
|
241
|
+
expect(fresh.tick(-100)).toBe(false)
|
|
242
|
+
ctrl.dispose()
|
|
243
|
+
fresh.dispose()
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
it('dispose silences subsequent mutators (no further emissions)', () => {
|
|
247
|
+
const ctrl = build()
|
|
248
|
+
ctrl.seekTo(10)
|
|
249
|
+
const fn = vi.fn()
|
|
250
|
+
const unsub = ctrl.state.subscribe(fn)
|
|
251
|
+
ctrl.dispose()
|
|
252
|
+
ctrl.seekTo(20)
|
|
253
|
+
ctrl.play()
|
|
254
|
+
ctrl.stepForward()
|
|
255
|
+
ctrl.setPacing('wallclock')
|
|
256
|
+
// Tick after dispose returns false and emits nothing.
|
|
257
|
+
expect(ctrl.tick(1000)).toBe(false)
|
|
258
|
+
expect(fn).not.toHaveBeenCalled()
|
|
259
|
+
// State observably unchanged from pre-dispose.
|
|
260
|
+
expect(ctrl.state.peek().position).toBe(10)
|
|
261
|
+
unsub()
|
|
262
|
+
})
|
|
263
|
+
|
|
264
|
+
it('seekBy clamps and notifies on net change', () => {
|
|
265
|
+
const ctrl = build()
|
|
266
|
+
ctrl.seekTo(50)
|
|
267
|
+
const fn = vi.fn()
|
|
268
|
+
const unsub = ctrl.state.subscribe(fn)
|
|
269
|
+
ctrl.seekBy(10)
|
|
270
|
+
expect(ctrl.state.peek().position).toBe(60)
|
|
271
|
+
ctrl.seekBy(1_000_000)
|
|
272
|
+
expect(ctrl.state.peek().position).toBe(99)
|
|
273
|
+
ctrl.seekBy(-1_000_000)
|
|
274
|
+
expect(ctrl.state.peek().position).toBe(0)
|
|
275
|
+
expect(fn).toHaveBeenCalledTimes(3)
|
|
276
|
+
unsub()
|
|
277
|
+
ctrl.dispose()
|
|
278
|
+
})
|
|
279
|
+
|
|
280
|
+
it('state is a single transactional snapshot — one notification per mutation', () => {
|
|
281
|
+
// Verifies the "single signal" design: setRange changes multiple
|
|
282
|
+
// fields but subscribers see one emission.
|
|
283
|
+
const ctrl = build()
|
|
284
|
+
ctrl.seekTo(80)
|
|
285
|
+
const captured: ReplayState[] = []
|
|
286
|
+
const unsub = ctrl.state.subscribe(() => {
|
|
287
|
+
captured.push(ctrl.state.peek())
|
|
288
|
+
})
|
|
289
|
+
ctrl.setRange(10, 50)
|
|
290
|
+
expect(captured).toHaveLength(1)
|
|
291
|
+
const snap = captured[0] as ReplayState
|
|
292
|
+
expect(snap.start).toBe(10)
|
|
293
|
+
expect(snap.end).toBe(50)
|
|
294
|
+
expect(snap.position).toBe(50) // clamped from 80
|
|
295
|
+
unsub()
|
|
296
|
+
ctrl.dispose()
|
|
297
|
+
})
|
|
298
|
+
|
|
299
|
+
it('no-op seekTo to current position does not notify', () => {
|
|
300
|
+
const ctrl = build()
|
|
301
|
+
ctrl.seekTo(25)
|
|
302
|
+
const fn = vi.fn()
|
|
303
|
+
const unsub = ctrl.state.subscribe(fn)
|
|
304
|
+
ctrl.seekTo(25)
|
|
305
|
+
expect(fn).not.toHaveBeenCalled()
|
|
306
|
+
unsub()
|
|
307
|
+
ctrl.dispose()
|
|
308
|
+
})
|
|
309
|
+
})
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import {
|
|
3
|
+
barIndexToTimestamp,
|
|
4
|
+
timestampToBarIndex,
|
|
5
|
+
inferBarIntervalMs,
|
|
6
|
+
type BarCalendar,
|
|
7
|
+
} from '../timeline'
|
|
8
|
+
|
|
9
|
+
// 1-minute bars covering 10 bars starting at an arbitrary epoch.
|
|
10
|
+
const MINUTE_MS = 60_000
|
|
11
|
+
const T0 = 1_700_000_000_000
|
|
12
|
+
function uniformCalendar(n: number, intervalMs = MINUTE_MS): BarCalendar {
|
|
13
|
+
const out: number[] = []
|
|
14
|
+
for (let i = 0; i < n; i++) out.push(T0 + i * intervalMs)
|
|
15
|
+
return out
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
describe('timeline', () => {
|
|
19
|
+
describe('barIndexToTimestamp + timestampToBarIndex', () => {
|
|
20
|
+
it('round-trips on a uniform calendar', () => {
|
|
21
|
+
const cal = uniformCalendar(10)
|
|
22
|
+
for (let i = 0; i < cal.length; i++) {
|
|
23
|
+
const ts = barIndexToTimestamp(cal, i)
|
|
24
|
+
expect(ts).not.toBeNull()
|
|
25
|
+
const back = timestampToBarIndex(cal, ts as number)
|
|
26
|
+
expect(back).toBe(i)
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('returns null for out-of-range bar indices', () => {
|
|
31
|
+
const cal = uniformCalendar(5)
|
|
32
|
+
expect(barIndexToTimestamp(cal, -1)).toBeNull()
|
|
33
|
+
expect(barIndexToTimestamp(cal, 5)).toBeNull()
|
|
34
|
+
expect(barIndexToTimestamp(cal, 999)).toBeNull()
|
|
35
|
+
expect(barIndexToTimestamp(cal, Number.NaN)).toBeNull()
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('returns null for empty calendars on both directions', () => {
|
|
39
|
+
const empty: BarCalendar = []
|
|
40
|
+
expect(barIndexToTimestamp(empty, 0)).toBeNull()
|
|
41
|
+
expect(timestampToBarIndex(empty, T0)).toBeNull()
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
it('honors non-uniform gaps (e.g. weekend close)', () => {
|
|
45
|
+
// Friday 16:00 close, then Monday 09:30 open — a ~65h gap.
|
|
46
|
+
// bars 0..3 are 1-minute Friday afternoon; bar 4 is Monday open.
|
|
47
|
+
const friday = T0
|
|
48
|
+
const cal: BarCalendar = [
|
|
49
|
+
friday + 0 * MINUTE_MS,
|
|
50
|
+
friday + 1 * MINUTE_MS,
|
|
51
|
+
friday + 2 * MINUTE_MS,
|
|
52
|
+
friday + 3 * MINUTE_MS,
|
|
53
|
+
friday + (65 * 60 + 30) * MINUTE_MS, // ~65.5h later
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
// Sanity: bar 4 timestamp matches what we put in.
|
|
57
|
+
expect(barIndexToTimestamp(cal, 4)).toBe(cal[4])
|
|
58
|
+
// A timestamp inside the weekend gap resolves to the last
|
|
59
|
+
// pre-gap bar (Friday's close), not the Monday open.
|
|
60
|
+
const insideGap = (cal[3] as number) + 12 * 60 * MINUTE_MS // Saturday noon
|
|
61
|
+
expect(timestampToBarIndex(cal, insideGap)).toBe(3)
|
|
62
|
+
// A timestamp at or after the Monday open resolves to bar 4.
|
|
63
|
+
expect(timestampToBarIndex(cal, cal[4] as number)).toBe(4)
|
|
64
|
+
expect(timestampToBarIndex(cal, (cal[4] as number) + MINUTE_MS)).toBe(4)
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
it('clamps timestamps below the first bar to null and above the last bar to the final index', () => {
|
|
68
|
+
const cal = uniformCalendar(5)
|
|
69
|
+
expect(timestampToBarIndex(cal, (cal[0] as number) - 1)).toBeNull()
|
|
70
|
+
expect(timestampToBarIndex(cal, (cal[4] as number) + 999_999)).toBe(4)
|
|
71
|
+
})
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
describe('inferBarIntervalMs', () => {
|
|
75
|
+
it('returns the dominant interval on a uniform calendar', () => {
|
|
76
|
+
expect(inferBarIntervalMs(uniformCalendar(10))).toBe(MINUTE_MS)
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
it('uses the median so outlier gaps do not skew the estimate', () => {
|
|
80
|
+
// Mostly 1-minute, with one massive weekend gap.
|
|
81
|
+
const cal: BarCalendar = [
|
|
82
|
+
0,
|
|
83
|
+
MINUTE_MS,
|
|
84
|
+
2 * MINUTE_MS,
|
|
85
|
+
3 * MINUTE_MS,
|
|
86
|
+
// 3-day gap
|
|
87
|
+
3 * MINUTE_MS + 3 * 24 * 60 * MINUTE_MS,
|
|
88
|
+
3 * MINUTE_MS + 3 * 24 * 60 * MINUTE_MS + MINUTE_MS,
|
|
89
|
+
3 * MINUTE_MS + 3 * 24 * 60 * MINUTE_MS + 2 * MINUTE_MS,
|
|
90
|
+
]
|
|
91
|
+
expect(inferBarIntervalMs(cal)).toBe(MINUTE_MS)
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
it('returns null when the calendar has fewer than two bars', () => {
|
|
95
|
+
expect(inferBarIntervalMs([])).toBeNull()
|
|
96
|
+
expect(inferBarIntervalMs([T0])).toBeNull()
|
|
97
|
+
})
|
|
98
|
+
})
|
|
99
|
+
})
|