@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
|
@@ -141,6 +141,9 @@ export class IndicatorScheduler {
|
|
|
141
141
|
// 重绘回调
|
|
142
142
|
private invalidateCallback: (() => void) | null = null
|
|
143
143
|
|
|
144
|
+
// Worker 异步结果应用完毕回调(用于串联其他管线,如 Alert)
|
|
145
|
+
private onResultsAppliedCallback: (() => void) | null = null
|
|
146
|
+
|
|
144
147
|
/** 从 Chart 获取活跃副图 paneId 列表的回调 */
|
|
145
148
|
private getActiveSubPaneIds: (() => string[]) | null = null
|
|
146
149
|
|
|
@@ -229,6 +232,14 @@ export class IndicatorScheduler {
|
|
|
229
232
|
this.invalidateCallback = callback
|
|
230
233
|
}
|
|
231
234
|
|
|
235
|
+
/**
|
|
236
|
+
* 设置 Worker 异步结果应用完毕回调
|
|
237
|
+
* 当 Worker 返回计算结果并写入 StateStore 后触发,用于串联 Alert 等管线
|
|
238
|
+
*/
|
|
239
|
+
setOnResultsApplied(callback: () => void): void {
|
|
240
|
+
this.onResultsAppliedCallback = callback
|
|
241
|
+
}
|
|
242
|
+
|
|
232
243
|
/**
|
|
233
244
|
* 副图增删后通知 scheduler 刷新 active mask
|
|
234
245
|
*/
|
|
@@ -251,6 +262,7 @@ export class IndicatorScheduler {
|
|
|
251
262
|
this.inlineRuntime = null
|
|
252
263
|
this.latestResult = null
|
|
253
264
|
this.invalidateCallback = null
|
|
265
|
+
this.onResultsAppliedCallback = null
|
|
254
266
|
}
|
|
255
267
|
|
|
256
268
|
// ============================================================================
|
|
@@ -402,6 +414,9 @@ export class IndicatorScheduler {
|
|
|
402
414
|
|
|
403
415
|
// 触发重绘
|
|
404
416
|
this.invalidateCallback?.()
|
|
417
|
+
|
|
418
|
+
// 通知外部(Alert 等管线)指标结果已就绪
|
|
419
|
+
this.onResultsAppliedCallback?.()
|
|
405
420
|
}
|
|
406
421
|
|
|
407
422
|
// ============================================================================
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { KLineChartError } from '../../errors'
|
|
1
2
|
import type { KLineData } from '../../types/price'
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -249,7 +250,7 @@ export class SharedKLineBuffer {
|
|
|
249
250
|
if (start < 0) start = 0
|
|
250
251
|
if (end > layout.length) end = layout.length
|
|
251
252
|
if (start >= end) {
|
|
252
|
-
throw new
|
|
253
|
+
throw new KLineChartError('INDICATOR_INVALID_PARAM', `Invalid subview range: [${start}, ${end})`)
|
|
253
254
|
}
|
|
254
255
|
|
|
255
256
|
const length = end - start
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* 把 Worker/Runtime 返回的 series bundle 组装成与现有兼容的 render states
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import { KLineChartError } from '../../errors'
|
|
6
7
|
import type {
|
|
7
8
|
MARenderState,
|
|
8
9
|
} from './state/maState'
|
|
@@ -229,7 +230,7 @@ function composeRequiredMetadataVisibleState(
|
|
|
229
230
|
|
|
230
231
|
const compose = meta.visibleState?.compose
|
|
231
232
|
if (!compose) {
|
|
232
|
-
throw new
|
|
233
|
+
throw new KLineChartError('NOT_REGISTERED', `[StateComposer] Missing visibleState.compose for ${indicatorId}`)
|
|
233
234
|
}
|
|
234
235
|
|
|
235
236
|
return compose({
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { KLineChartError } from '../errors'
|
|
1
2
|
import type { SubIndicatorType } from './renderers/Indicator'
|
|
2
3
|
import { createSignal, type Signal } from '../reactivity/signal'
|
|
3
4
|
import { createSubIndicatorRenderer } from './renderers/Indicator'
|
|
@@ -157,7 +158,7 @@ export class SubPaneManager {
|
|
|
157
158
|
): RendererPlugin {
|
|
158
159
|
const definition = ctx.getIndicatorScheduler().getIndicatorMetadata(indicatorId)
|
|
159
160
|
if (!definition) {
|
|
160
|
-
throw new
|
|
161
|
+
throw new KLineChartError('NOT_REGISTERED', `[SubPaneManager] Unknown indicator: ${indicatorId}`)
|
|
161
162
|
}
|
|
162
163
|
return createSubIndicatorRenderer({ indicatorId, paneId, definition, params })
|
|
163
164
|
}
|
|
@@ -10,6 +10,8 @@ export interface ZoomDependencies {
|
|
|
10
10
|
getLogicalScrollLeft: () => number
|
|
11
11
|
getCurrentDpr: () => number
|
|
12
12
|
getLeftLoadBufferWidth: () => number
|
|
13
|
+
getContentWidth: () => number
|
|
14
|
+
getClientWidth: () => number
|
|
13
15
|
setScrollLeft: (v: number) => void
|
|
14
16
|
onZoomCommitted: (result: ZoomCommittedResult) => void
|
|
15
17
|
getKWidth: () => number
|
|
@@ -93,8 +95,12 @@ export class ChartZoomController {
|
|
|
93
95
|
if (!result) return
|
|
94
96
|
|
|
95
97
|
const domScrollLeft = result.newScrollLeft + this.deps.getLeftLoadBufferWidth()
|
|
98
|
+
const contentWidth = this.deps.getContentWidth()
|
|
99
|
+
const clientWidth = this.deps.getClientWidth()
|
|
100
|
+
const maxScroll = Math.max(0, contentWidth - clientWidth)
|
|
101
|
+
const clampedScrollLeft = Math.round(Math.max(0, Math.min(domScrollLeft, maxScroll)) * dpr) / dpr
|
|
96
102
|
this._currentZoomLevel = result.targetLevel
|
|
97
|
-
this.deps.setScrollLeft(
|
|
103
|
+
this.deps.setScrollLeft(clampedScrollLeft)
|
|
98
104
|
this.deps.onZoomCommitted({
|
|
99
105
|
kWidth: result.newKWidth,
|
|
100
106
|
kGap: result.newKGap,
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error recovery hints + diagnostic formatter.
|
|
3
|
+
*
|
|
4
|
+
* The companion to `errors.ts`: that file defines the contract
|
|
5
|
+
* ({@link KLineChartError} + {@link KLineChartErrorCode}); this file
|
|
6
|
+
* makes each thrown error *useful at the point of catch*.
|
|
7
|
+
*
|
|
8
|
+
* What hosts get:
|
|
9
|
+
*
|
|
10
|
+
* - `getRecoveryHint(code)` — a 1–2 sentence "what to do next"
|
|
11
|
+
* keyed by error code. Suitable for displaying inline in a dev
|
|
12
|
+
* overlay, terminal log, or React error boundary.
|
|
13
|
+
* - `formatKLineChartError(err)` — multi-line diagnostic that
|
|
14
|
+
* combines the code, the original message, the recovery hint,
|
|
15
|
+
* and the cause chain (ES2022 `Error.cause`). The output is
|
|
16
|
+
* plain text — no ANSI, no Markdown — so it composes with
|
|
17
|
+
* whatever rendering layer the host chooses.
|
|
18
|
+
*
|
|
19
|
+
* Why this isn't in `errors.ts`: the recovery hints are user-facing
|
|
20
|
+
* copy. Keeping them separate means the message taxonomy stays
|
|
21
|
+
* focused (it's the contract), while the help text can evolve
|
|
22
|
+
* without churning the contract file.
|
|
23
|
+
*
|
|
24
|
+
* Why hints are bundled (not lazy-loaded from a CDN, à la React):
|
|
25
|
+
* @klinechart-quant ships to environments without network
|
|
26
|
+
* (kiosk dashboards, isolated trading workstations, Electron apps).
|
|
27
|
+
* The hint text adds ~2 KB; that's the cheapest possible "useful
|
|
28
|
+
* error" we can ship.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
import type { KLineChartError, KLineChartErrorCode } from './errors'
|
|
32
|
+
import { isKLineChartError } from './errors'
|
|
33
|
+
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
// Recovery hints — keyed by KLineChartErrorCode
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Note for maintainers: every code in `KLineChartErrorCode` MUST have an
|
|
40
|
+
* entry here. The "every code has a hint" test enforces this — adding a
|
|
41
|
+
* code without a hint fails CI.
|
|
42
|
+
*/
|
|
43
|
+
const HINTS: Readonly<Record<KLineChartErrorCode, string>> = {
|
|
44
|
+
// Generic
|
|
45
|
+
INVALID_PARAM:
|
|
46
|
+
'Check the argument values against the documented contract. If a finite number is expected, NaN / Infinity are rejected; if a positive value is expected, zero and negatives are rejected.',
|
|
47
|
+
INVALID_STATE:
|
|
48
|
+
'The operation is incompatible with the current controller state. Read the relevant state signal (e.g. `position`, `mode`) before retrying.',
|
|
49
|
+
DISPOSED:
|
|
50
|
+
'This controller was disposed and silently no-ops on further mutations. Create a new instance — disposal is one-way.',
|
|
51
|
+
NOT_REGISTERED:
|
|
52
|
+
'The id was not registered with this controller. Call register() / setBaseBars() / equivalent before the operation that needs it.',
|
|
53
|
+
|
|
54
|
+
// Scale (TimeScale + PriceScale)
|
|
55
|
+
SCALE_RANGE_INVALID:
|
|
56
|
+
'visibleMax must be >= visibleMin and both must be finite. Verify any computed range (e.g. autoFit) is well-formed before passing it in.',
|
|
57
|
+
SCALE_HEIGHT_INVALID:
|
|
58
|
+
'height must be > 0. After a host resize, re-check the container has a non-zero rect before updating the scale.',
|
|
59
|
+
SCALE_LOG_REQUIRES_POSITIVE:
|
|
60
|
+
"Log-mode price scales require strictly positive bounds. Either clamp the range to (0, +∞) or switch the scale's mode to 'linear' before assigning a range that includes <= 0.",
|
|
61
|
+
SCALE_BAR_WIDTH_INVALID:
|
|
62
|
+
'barWidth must be > 0. Zoom helpers should clamp the result above a floor (e.g. 0.5 px) before calling setBarWidth.',
|
|
63
|
+
|
|
64
|
+
// Footprint controller
|
|
65
|
+
FOOTPRINT_TICKSIZE_INVALID:
|
|
66
|
+
'FootprintController tickSize must be > 0 (the quantization unit for the price ladder).',
|
|
67
|
+
FOOTPRINT_BAR_INTERVAL_INVALID:
|
|
68
|
+
'FootprintController barIntervalMs must be a positive finite number — the ms-per-bar bucket width.',
|
|
69
|
+
FOOTPRINT_RATIO_INVALID:
|
|
70
|
+
'FootprintController imbalanceRatio must be > 0 — the ask:bid ratio threshold for the diagonal imbalance flag.',
|
|
71
|
+
|
|
72
|
+
// Anchored VWAP
|
|
73
|
+
AVWAP_ANCHOR_OUT_OF_RANGE:
|
|
74
|
+
'anchorIndex must satisfy 0 <= idx < bars.length. Pass an empty bars[] to short-circuit if you have no data yet.',
|
|
75
|
+
|
|
76
|
+
// Indicators (shared)
|
|
77
|
+
INDICATOR_INVALID_PARAM:
|
|
78
|
+
'Indicator input validation failed. Common causes: period < 2, sigma <= 0, offset outside [0, 1]. See the indicator function header for its exact ranges.',
|
|
79
|
+
|
|
80
|
+
// Order Book Heatmap (shared across subsystems)
|
|
81
|
+
HEATMAP_CONFIG_INVALID:
|
|
82
|
+
'Order book heatmap config check failed. Most likely culprit: tickSize, snapshotIntervalMs, snapshotRingCapacity, or logColorRange bounds out of range. The error message names the failing field.',
|
|
83
|
+
|
|
84
|
+
// MTF Overlay
|
|
85
|
+
MTF_CONFIG_INVALID:
|
|
86
|
+
'Multi-timeframe overlay config check failed. Likely targetIntervalMs <= 0, base/target interval mismatch, or a duplicate series id. The error message names the failing field.',
|
|
87
|
+
|
|
88
|
+
// Alternative chart types
|
|
89
|
+
CHART_TYPE_CONFIG_INVALID:
|
|
90
|
+
'Alternative chart-type config check failed. Renko needs brickSize > 0 (or useATR.period >= 1); Range Bars needs range > 0; Point & Figure needs boxSize > 0 and reversal >= 1.',
|
|
91
|
+
|
|
92
|
+
// Replay
|
|
93
|
+
REPLAY_CONFIG_INVALID:
|
|
94
|
+
'Replay config check failed. Range needs finite start/end with end >= start; speed must be a positive finite number (reverse playback is rejected in v1).',
|
|
95
|
+
|
|
96
|
+
// Controller wiring
|
|
97
|
+
CONTROLLER_CONFIG_INVALID:
|
|
98
|
+
'Chart controller wiring is incomplete. Most often: container is null/undefined, opts is missing, or no ChartControllerFactory was registered via __setChartFactory before mount.',
|
|
99
|
+
|
|
100
|
+
// Data-fetcher
|
|
101
|
+
FETCH_FAILED:
|
|
102
|
+
'A remote data-fetch failed. Check network connectivity, API endpoint, and authentication tokens. If using baostock/tradingview provider, verify the symbol and period are valid.',
|
|
103
|
+
|
|
104
|
+
// Serialization
|
|
105
|
+
SCHEMA_VERSION_MISMATCH:
|
|
106
|
+
'The serialized state was produced by a different schema version. Migrate it via the schema-version converter, or re-export from the source session.',
|
|
107
|
+
INVALID_JSON:
|
|
108
|
+
'The state string was not valid JSON. If it came from a textarea, check for accidental BOM, smart quotes, or trailing commas.',
|
|
109
|
+
NOT_OBJECT:
|
|
110
|
+
'A SerializedChartState root must be a JSON object. Arrays and primitives are rejected.',
|
|
111
|
+
INVALID_TIMESTAMP:
|
|
112
|
+
'snapshotTakenAt must be an ISO 8601 string parseable by Date.parse. Format it via new Date().toISOString() on the producing side.',
|
|
113
|
+
MISSING_CONTROLLERS:
|
|
114
|
+
'A SerializedChartState requires a controllers object. If you intentionally have no controllers, pass an empty object {}.',
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Returns the recovery hint for an error code. Always non-empty; if a new
|
|
119
|
+
* code lands without an entry, the bundled test fails at CI.
|
|
120
|
+
*/
|
|
121
|
+
export function getRecoveryHint(code: KLineChartErrorCode): string {
|
|
122
|
+
return HINTS[code]
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
// formatKLineChartError — dev-overlay-ready diagnostic
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
|
|
129
|
+
export interface FormatErrorOptions {
|
|
130
|
+
/**
|
|
131
|
+
* Include the recovery hint line. Default true. Set false when the
|
|
132
|
+
* host renders the hint separately (e.g. a foldable section).
|
|
133
|
+
*/
|
|
134
|
+
readonly includeHint?: boolean
|
|
135
|
+
/**
|
|
136
|
+
* Include the `.cause` chain (ES2022). Default true. When false the
|
|
137
|
+
* output is single-error.
|
|
138
|
+
*/
|
|
139
|
+
readonly includeCause?: boolean
|
|
140
|
+
/**
|
|
141
|
+
* Include the stack trace. Default false — stacks are noisy and most
|
|
142
|
+
* dev overlays render them separately. Set true for log output.
|
|
143
|
+
*/
|
|
144
|
+
readonly includeStack?: boolean
|
|
145
|
+
/**
|
|
146
|
+
* Indent prefix for cause-chain lines. Default `' '` (two spaces).
|
|
147
|
+
*/
|
|
148
|
+
readonly indent?: string
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const DEFAULTS: Required<FormatErrorOptions> = {
|
|
152
|
+
includeHint: true,
|
|
153
|
+
includeCause: true,
|
|
154
|
+
includeStack: false,
|
|
155
|
+
indent: ' ',
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Format a KLineChartError (or any value caught in a try / catch) into
|
|
160
|
+
* a plain-text multi-line diagnostic ready for a dev overlay, console,
|
|
161
|
+
* or test failure message.
|
|
162
|
+
*
|
|
163
|
+
* Example output:
|
|
164
|
+
*
|
|
165
|
+
* KLineChartError [SCALE_BAR_WIDTH_INVALID]
|
|
166
|
+
* createTimeScale: initialBarWidth must be > 0, got 0
|
|
167
|
+
* Hint: barWidth must be > 0. Zoom helpers should clamp the result above a floor (e.g. 0.5 px) before calling setBarWidth.
|
|
168
|
+
*
|
|
169
|
+
* For non-KLineChartError input the output is one line — the value's
|
|
170
|
+
* own `toString()` or `String(value)`.
|
|
171
|
+
*/
|
|
172
|
+
export function formatKLineChartError(
|
|
173
|
+
err: unknown,
|
|
174
|
+
opts?: FormatErrorOptions,
|
|
175
|
+
): string {
|
|
176
|
+
const cfg = { ...DEFAULTS, ...(opts ?? {}) }
|
|
177
|
+
if (!isKLineChartError(err)) {
|
|
178
|
+
// Pass-through for unknown errors so callers can use this
|
|
179
|
+
// unconditionally and still get readable output.
|
|
180
|
+
if (err instanceof Error) {
|
|
181
|
+
const head = `${err.name}: ${err.message}`
|
|
182
|
+
if (!cfg.includeStack || typeof err.stack !== 'string') return head
|
|
183
|
+
return `${head}\n${err.stack}`
|
|
184
|
+
}
|
|
185
|
+
return String(err)
|
|
186
|
+
}
|
|
187
|
+
const lines: string[] = []
|
|
188
|
+
lines.push(`KLineChartError [${err.code}]`)
|
|
189
|
+
lines.push(`${cfg.indent}${err.message}`)
|
|
190
|
+
if (cfg.includeHint) {
|
|
191
|
+
lines.push(`${cfg.indent}Hint: ${getRecoveryHint(err.code)}`)
|
|
192
|
+
}
|
|
193
|
+
if (cfg.includeCause && hasCause(err)) {
|
|
194
|
+
const cause = (err as KLineChartError & { cause?: unknown }).cause
|
|
195
|
+
lines.push(`${cfg.indent}Caused by:`)
|
|
196
|
+
const child = formatKLineChartError(cause, {
|
|
197
|
+
...cfg,
|
|
198
|
+
indent: cfg.indent + cfg.indent,
|
|
199
|
+
})
|
|
200
|
+
// Indent every line of the child.
|
|
201
|
+
for (const ln of child.split('\n')) {
|
|
202
|
+
lines.push(`${cfg.indent}${ln}`)
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
if (cfg.includeStack && typeof err.stack === 'string') {
|
|
206
|
+
lines.push(`${cfg.indent}Stack:`)
|
|
207
|
+
for (const ln of err.stack.split('\n')) {
|
|
208
|
+
lines.push(`${cfg.indent}${cfg.indent}${ln}`)
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return lines.join('\n')
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function hasCause(err: unknown): boolean {
|
|
215
|
+
if (typeof err !== 'object' || err === null) return false
|
|
216
|
+
const cause = (err as { cause?: unknown }).cause
|
|
217
|
+
return cause !== undefined && cause !== null
|
|
218
|
+
}
|
package/src/errors.ts
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KLineChartError — shared error taxonomy for `@klinechart-quant/*`.
|
|
3
|
+
*
|
|
4
|
+
* API audit BLOCKER-005 reported 53/54 throws were plain `Error`, 1
|
|
5
|
+
* `RangeError`, and 2 one-off custom classes with no shared base. This
|
|
6
|
+
* file is the harmonisation point: every recoverable failure across all
|
|
7
|
+
* five publishable packages should be a `KLineChartError` carrying a
|
|
8
|
+
* stable `code` from {@link KLineChartErrorCode}.
|
|
9
|
+
*
|
|
10
|
+
* Design:
|
|
11
|
+
* - Extends `Error` directly (no abstract layer) so it Just Works under
|
|
12
|
+
* V8 stack traces, async/await, and `Error.captureStackTrace`.
|
|
13
|
+
* - `code` is a string enum (not a literal union) so end-user code can
|
|
14
|
+
* branch on it without importing the enum object.
|
|
15
|
+
* - `cause` mirrors the ES2022 `Error.cause` field so wrapping a lower-
|
|
16
|
+
* level failure preserves the chain.
|
|
17
|
+
* - `instanceof KLineChartError` works across the package boundary
|
|
18
|
+
* because every publishable package imports this same module.
|
|
19
|
+
*
|
|
20
|
+
* Migration policy: each existing `throw new Error('msg')` becomes
|
|
21
|
+
* `throw new KLineChartError('CODE', 'msg', { cause? })`. We do NOT rename
|
|
22
|
+
* `RangeError` throws or browser/Node built-in errors raised by lower
|
|
23
|
+
* layers — those keep their native type but downstream catch blocks
|
|
24
|
+
* `instanceof KLineChartError` distinguish "expected/recoverable" from
|
|
25
|
+
* "platform/unexpected".
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Stable error code surface. New codes append-only — never remove or
|
|
30
|
+
* renumber. Downstream code branches on these strings.
|
|
31
|
+
*
|
|
32
|
+
* Naming convention: SCREAMING_SNAKE_CASE, domain-prefixed where useful
|
|
33
|
+
* (`SCALE_`, `FOOTPRINT_`, etc.) to disambiguate similar shapes across
|
|
34
|
+
* controllers.
|
|
35
|
+
*/
|
|
36
|
+
export type KLineChartErrorCode =
|
|
37
|
+
// generic
|
|
38
|
+
| 'INVALID_PARAM'
|
|
39
|
+
| 'INVALID_STATE'
|
|
40
|
+
| 'DISPOSED'
|
|
41
|
+
| 'NOT_REGISTERED'
|
|
42
|
+
// scale (TimeScale / PriceScale construction + setters)
|
|
43
|
+
| 'SCALE_RANGE_INVALID'
|
|
44
|
+
| 'SCALE_HEIGHT_INVALID'
|
|
45
|
+
| 'SCALE_LOG_REQUIRES_POSITIVE'
|
|
46
|
+
| 'SCALE_BAR_WIDTH_INVALID'
|
|
47
|
+
// footprint
|
|
48
|
+
| 'FOOTPRINT_TICKSIZE_INVALID'
|
|
49
|
+
| 'FOOTPRINT_BAR_INTERVAL_INVALID'
|
|
50
|
+
| 'FOOTPRINT_RATIO_INVALID'
|
|
51
|
+
// anchoredVwap
|
|
52
|
+
| 'AVWAP_ANCHOR_OUT_OF_RANGE'
|
|
53
|
+
// indicators (shared — every indicator validates inputs the same way)
|
|
54
|
+
| 'INDICATOR_INVALID_PARAM'
|
|
55
|
+
// orderBookHeatmap (controller + logColorScale + state + snapshotRing)
|
|
56
|
+
| 'HEATMAP_CONFIG_INVALID'
|
|
57
|
+
// mtfOverlay (alignToBaseIndex + resampleBars + createMtfController)
|
|
58
|
+
| 'MTF_CONFIG_INVALID'
|
|
59
|
+
// alternative chart types (renko / rangeBars / pointAndFigure)
|
|
60
|
+
| 'CHART_TYPE_CONFIG_INVALID'
|
|
61
|
+
// replay controller
|
|
62
|
+
| 'REPLAY_CONFIG_INVALID'
|
|
63
|
+
// scene / chart-controller / framework adapter wiring
|
|
64
|
+
| 'CONTROLLER_CONFIG_INVALID'
|
|
65
|
+
// data-fetcher (gotdx / baostock / tradingview)
|
|
66
|
+
| 'FETCH_FAILED'
|
|
67
|
+
// serialization
|
|
68
|
+
| 'SCHEMA_VERSION_MISMATCH'
|
|
69
|
+
| 'INVALID_JSON'
|
|
70
|
+
| 'NOT_OBJECT'
|
|
71
|
+
| 'INVALID_TIMESTAMP'
|
|
72
|
+
| 'MISSING_CONTROLLERS'
|
|
73
|
+
|
|
74
|
+
export interface KLineChartErrorOptions {
|
|
75
|
+
/** Lower-level error this wraps (preserved as the standard `.cause`). */
|
|
76
|
+
cause?: unknown
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Base error for everything thrown by `@klinechart-quant/*` that's
|
|
81
|
+
* expected as part of the API contract.
|
|
82
|
+
*
|
|
83
|
+
* Always pass a `code` from {@link KLineChartErrorCode}; the message is
|
|
84
|
+
* the human-readable explanation.
|
|
85
|
+
*/
|
|
86
|
+
export class KLineChartError extends Error {
|
|
87
|
+
readonly code: KLineChartErrorCode
|
|
88
|
+
|
|
89
|
+
constructor(code: KLineChartErrorCode, message: string, opts?: KLineChartErrorOptions) {
|
|
90
|
+
// Forward `cause` via the ES2022 Error options bag when available.
|
|
91
|
+
if (opts?.cause !== undefined) {
|
|
92
|
+
super(message, { cause: opts.cause })
|
|
93
|
+
} else {
|
|
94
|
+
super(message)
|
|
95
|
+
}
|
|
96
|
+
this.code = code
|
|
97
|
+
// `name` defaults to the constructor name in V8; pinning it makes
|
|
98
|
+
// serialized errors (e.g. via JSON.stringify) carry the type tag.
|
|
99
|
+
this.name = 'KLineChartError'
|
|
100
|
+
// Capture stack at the throw site, not inside the constructor.
|
|
101
|
+
// V8-specific but harmless elsewhere.
|
|
102
|
+
if (typeof (Error as unknown as { captureStackTrace?: unknown }).captureStackTrace === 'function') {
|
|
103
|
+
; (Error as unknown as { captureStackTrace: (e: Error, c: unknown) => void }).captureStackTrace(
|
|
104
|
+
this,
|
|
105
|
+
KLineChartError,
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Convenience type-guard that doubles as a `code`-narrower:
|
|
113
|
+
*
|
|
114
|
+
* try { ... } catch (e) {
|
|
115
|
+
* if (isKLineChartError(e, 'DISPOSED')) {
|
|
116
|
+
* // e.code is narrowed to 'DISPOSED'
|
|
117
|
+
* }
|
|
118
|
+
* }
|
|
119
|
+
*/
|
|
120
|
+
export function isKLineChartError(value: unknown): value is KLineChartError
|
|
121
|
+
export function isKLineChartError<C extends KLineChartErrorCode>(
|
|
122
|
+
value: unknown,
|
|
123
|
+
code: C,
|
|
124
|
+
): value is KLineChartError & { code: C }
|
|
125
|
+
export function isKLineChartError(value: unknown, code?: KLineChartErrorCode): boolean {
|
|
126
|
+
if (!(value instanceof KLineChartError)) return false
|
|
127
|
+
return code === undefined || value.code === code
|
|
128
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -5,3 +5,40 @@ export { VERSION } from './version'
|
|
|
5
5
|
export * from './tokens'
|
|
6
6
|
export { formatTimestamp } from './utils/dateFormat'
|
|
7
7
|
export { generateUUID } from './utils/uuid'
|
|
8
|
+
|
|
9
|
+
// ── Batch 1: Error taxonomy ───────────────────────────────────────────────
|
|
10
|
+
export {
|
|
11
|
+
KLineChartError,
|
|
12
|
+
isKLineChartError,
|
|
13
|
+
type KLineChartErrorCode,
|
|
14
|
+
type KLineChartErrorOptions,
|
|
15
|
+
} from './errors'
|
|
16
|
+
export {
|
|
17
|
+
getRecoveryHint,
|
|
18
|
+
formatKLineChartError,
|
|
19
|
+
type FormatErrorOptions,
|
|
20
|
+
} from './errors-help'
|
|
21
|
+
|
|
22
|
+
// ── Batch 2: Framework-agnostic foundation ────────────────────────────────
|
|
23
|
+
export * from './input'
|
|
24
|
+
export * from './scale'
|
|
25
|
+
export * from './scheduler'
|
|
26
|
+
export type * from './render'
|
|
27
|
+
export * from './renderer-tier'
|
|
28
|
+
|
|
29
|
+
// ── Batch 3: Scene abstraction (depends on render) ────────────────────────
|
|
30
|
+
export * from './scene'
|
|
31
|
+
|
|
32
|
+
// ── Batch 4: Independent business features ────────────────────────────────
|
|
33
|
+
export * from './alerts'
|
|
34
|
+
export * from './replay'
|
|
35
|
+
export * from './chartTypes'
|
|
36
|
+
export * from './indicators'
|
|
37
|
+
|
|
38
|
+
// ── Batch 5: Component data models ────────────────────────────────────────
|
|
39
|
+
export * from './components/volumeProfile'
|
|
40
|
+
export * from './components/orderBookHeatmap'
|
|
41
|
+
export * from './components/footprint'
|
|
42
|
+
export * from './components/anchoredVwap'
|
|
43
|
+
export * from './components/mtfOverlay'
|
|
44
|
+
export * from './components/crosshairSync'
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MA family completion pack tests (B-9).
|
|
3
|
+
*
|
|
4
|
+
* Each indicator gets at least:
|
|
5
|
+
* - length parity assertion (output length === input length)
|
|
6
|
+
* - NaN-priming-window assertion (correct number of leading NaN)
|
|
7
|
+
* - convergence-or-fixture assertion (constant input → constant output;
|
|
8
|
+
* known-trending input → monotonic output where applicable)
|
|
9
|
+
* - parameter-validation throw paths
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { describe, it, expect } from 'vitest'
|
|
13
|
+
import { computeALMA } from '../alma'
|
|
14
|
+
import { computeT3 } from '../t3'
|
|
15
|
+
import { computeZLEMA } from '../zlema'
|
|
16
|
+
import { computeLSMA } from '../lsma'
|
|
17
|
+
import { computeVIDYA } from '../vidya'
|
|
18
|
+
import { computeFRAMA } from '../frama'
|
|
19
|
+
|
|
20
|
+
function constant(n: number, v: number): number[] {
|
|
21
|
+
return Array.from({ length: n }, () => v)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function ramp(n: number, start = 1, step = 1): number[] {
|
|
25
|
+
return Array.from({ length: n }, (_, i) => start + step * i)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function countLeadingNaN(out: Float64Array): number {
|
|
29
|
+
let c = 0
|
|
30
|
+
for (let i = 0; i < out.length; i++) {
|
|
31
|
+
if (Number.isNaN(out[i])) c++
|
|
32
|
+
else break
|
|
33
|
+
}
|
|
34
|
+
return c
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
describe('computeALMA', () => {
|
|
38
|
+
it('output length === input length', () => {
|
|
39
|
+
const r = computeALMA(ramp(50), { period: 10 })
|
|
40
|
+
expect(r.length).toBe(50)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
it('first period - 1 entries are NaN', () => {
|
|
44
|
+
const r = computeALMA(ramp(20), { period: 5 })
|
|
45
|
+
expect(countLeadingNaN(r)).toBe(4)
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it('constant input → constant output (after priming)', () => {
|
|
49
|
+
const r = computeALMA(constant(20, 100), { period: 5 })
|
|
50
|
+
for (let i = 4; i < 20; i++) expect(r[i]!).toBeCloseTo(100, 9)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('throws on invalid params', () => {
|
|
54
|
+
expect(() => computeALMA([1, 2], { period: 0 })).toThrow(/period/)
|
|
55
|
+
expect(() => computeALMA([1, 2], { period: 5, offset: -0.1 })).toThrow(/offset/)
|
|
56
|
+
expect(() => computeALMA([1, 2], { period: 5, sigma: 0 })).toThrow(/sigma/)
|
|
57
|
+
})
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
describe('computeT3', () => {
|
|
61
|
+
it('output length === input length', () => {
|
|
62
|
+
const r = computeT3(ramp(50), { period: 5 })
|
|
63
|
+
expect(r.length).toBe(50)
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
it('seeds on first sample and produces no NaN once primed', () => {
|
|
67
|
+
const r = computeT3(constant(30, 50), { period: 5 })
|
|
68
|
+
// T3 with constant input is a 6-deep EMA cascade of 50 → asymptotes to 50.
|
|
69
|
+
const last = r[r.length - 1]!
|
|
70
|
+
expect(last).toBeCloseTo(50, 6)
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
it('respects volumeFactor bounds', () => {
|
|
74
|
+
expect(() => computeT3(ramp(20), { period: 5, volumeFactor: -0.1 })).toThrow(/volumeFactor/)
|
|
75
|
+
expect(() => computeT3(ramp(20), { period: 5, volumeFactor: 1.1 })).toThrow(/volumeFactor/)
|
|
76
|
+
})
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
describe('computeZLEMA', () => {
|
|
80
|
+
it('output length === input length', () => {
|
|
81
|
+
const r = computeZLEMA(ramp(30), { period: 8 })
|
|
82
|
+
expect(r.length).toBe(30)
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
it('lag = floor((period-1)/2) leading NaN', () => {
|
|
86
|
+
// period 8 → lag = 3 → 3 leading NaN
|
|
87
|
+
const r = computeZLEMA(ramp(30), { period: 8 })
|
|
88
|
+
expect(countLeadingNaN(r)).toBe(3)
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
it('on a linear ramp, leads or matches the ramp value (zero-lag promise)', () => {
|
|
92
|
+
// For prices = i, the zero-lag-adjusted series is also linear and a
|
|
93
|
+
// unit-slope EMA over it tracks the line within numerical tolerance
|
|
94
|
+
// once primed. We check that the indicator value at i is within a
|
|
95
|
+
// small constant of i (no large lag).
|
|
96
|
+
const r = computeZLEMA(ramp(40, 0, 1), { period: 10 })
|
|
97
|
+
for (let i = 15; i < 40; i++) {
|
|
98
|
+
expect(Math.abs(r[i]! - i)).toBeLessThan(2)
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
describe('computeLSMA', () => {
|
|
104
|
+
it('output length === input length and period-1 leading NaN', () => {
|
|
105
|
+
const r = computeLSMA(ramp(30), { period: 7 })
|
|
106
|
+
expect(r.length).toBe(30)
|
|
107
|
+
expect(countLeadingNaN(r)).toBe(6)
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
it('on a perfect linear ramp, LSMA value equals the ramp value (LR endpoint = current bar)', () => {
|
|
111
|
+
const r = computeLSMA(ramp(40, 10, 0.5), { period: 5 })
|
|
112
|
+
// ramp(i) = 10 + 0.5 * i; LSMA fits over [i-4..i] and returns line at right endpoint = ramp(i)
|
|
113
|
+
for (let i = 4; i < 40; i++) {
|
|
114
|
+
expect(r[i]!).toBeCloseTo(10 + 0.5 * i, 9)
|
|
115
|
+
}
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
it('constant input → LSMA equals the constant', () => {
|
|
119
|
+
const r = computeLSMA(constant(20, 7), { period: 5 })
|
|
120
|
+
for (let i = 4; i < 20; i++) expect(r[i]!).toBeCloseTo(7, 9)
|
|
121
|
+
})
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
describe('computeVIDYA', () => {
|
|
125
|
+
it('output length === input length', () => {
|
|
126
|
+
const r = computeVIDYA(ramp(30), { period: 9 })
|
|
127
|
+
expect(r.length).toBe(30)
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
it('first cmoPeriod entries are NaN', () => {
|
|
131
|
+
const r = computeVIDYA(ramp(30), { period: 9, cmoPeriod: 5 })
|
|
132
|
+
expect(countLeadingNaN(r)).toBe(5)
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
it('constant input → CMO degenerate → alpha == 0 → stays at seed', () => {
|
|
136
|
+
// With constant input the CMO has no signal (sum gain = sum loss = 0),
|
|
137
|
+
// we treat it as 0 → alpha = 0 → VIDYA equals the first valid price.
|
|
138
|
+
const r = computeVIDYA(constant(20, 42), { period: 5, cmoPeriod: 3 })
|
|
139
|
+
for (let i = 3; i < 20; i++) expect(r[i]!).toBeCloseTo(42, 9)
|
|
140
|
+
})
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
describe('computeFRAMA', () => {
|
|
144
|
+
it('output length === input length and period-1 leading NaN', () => {
|
|
145
|
+
const r = computeFRAMA(ramp(40), { period: 16 })
|
|
146
|
+
expect(r.length).toBe(40)
|
|
147
|
+
expect(countLeadingNaN(r)).toBe(15)
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
it('rejects odd or too-small periods', () => {
|
|
151
|
+
expect(() => computeFRAMA(ramp(20), { period: 3 })).toThrow(/period/)
|
|
152
|
+
expect(() => computeFRAMA(ramp(20), { period: 5 })).toThrow(/period/)
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
it('constant input → flat output once primed', () => {
|
|
156
|
+
const r = computeFRAMA(constant(40, 9), { period: 8 })
|
|
157
|
+
for (let i = 7; i < 40; i++) expect(r[i]!).toBeCloseTo(9, 6)
|
|
158
|
+
})
|
|
159
|
+
})
|