@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,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PriceScale factory — price ↔ screen Y (ROADMAP §1.2) + origin-shift policy
|
|
3
|
+
* (ROADMAP §2.5).
|
|
4
|
+
*
|
|
5
|
+
* Linear mapping (top-origin, Y grows downward):
|
|
6
|
+
*
|
|
7
|
+
* t = (p - visibleMin) / (visibleMax - visibleMin)
|
|
8
|
+
* y = height - t * height
|
|
9
|
+
* inverse: p = visibleMin + (1 - y / height) * (visibleMax - visibleMin)
|
|
10
|
+
*
|
|
11
|
+
* Log mapping (only valid for strictly positive ranges):
|
|
12
|
+
*
|
|
13
|
+
* t = (ln(p) - ln(visibleMin)) / (ln(visibleMax) - ln(visibleMin))
|
|
14
|
+
* y = height - t * height
|
|
15
|
+
* inverse: p = exp(ln(visibleMin) + (1 - y / height) * (ln(visibleMax) - ln(visibleMin)))
|
|
16
|
+
*
|
|
17
|
+
* Origin-shift policy: lives inside this scale and is consulted on every
|
|
18
|
+
* `setVisibleRange`. It is intentionally in **linear-price space**, applied
|
|
19
|
+
* *before* the log transform — that matches the existing engine and keeps the
|
|
20
|
+
* "shift is just a translation" mental model clean. (Log-space shift is also
|
|
21
|
+
* mathematically valid; it would compose better with sub-cent log-axis zoom on
|
|
22
|
+
* astronomically high prices, but we have no such use case and this keeps
|
|
23
|
+
* parity with the legacy renderer.)
|
|
24
|
+
*
|
|
25
|
+
* Degenerate range handling: when `visibleMin === visibleMax`, `priceToY` and
|
|
26
|
+
* `yToPrice` would divide by zero. We pin the output to `height / 2` (the
|
|
27
|
+
* geometric center) and document that the caller should treat this as
|
|
28
|
+
* "everything at the same price"; this is preferred over throwing because
|
|
29
|
+
* mid-frame `setVisibleRange(p, p)` is reachable from external data feeds and
|
|
30
|
+
* we don't want one bad row to crash the chart.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
import { createSignal } from '../reactivity/signal'
|
|
34
|
+
import { KLineChartError } from '../errors'
|
|
35
|
+
import type { Signal } from '../reactivity/signal'
|
|
36
|
+
import { createOriginShiftPolicy, type OriginShiftPolicy } from './originShift'
|
|
37
|
+
import type { PriceScale, ScaleMode } from './types'
|
|
38
|
+
|
|
39
|
+
export interface PriceScaleConfig {
|
|
40
|
+
/** Initial mode. Default `'linear'`. */
|
|
41
|
+
initialMode?: ScaleMode
|
|
42
|
+
/** Initial visibleMin. Default 0. (Must be > 0 if initialMode === 'log'.) */
|
|
43
|
+
initialVisibleMin?: number
|
|
44
|
+
/** Initial visibleMax. Default 100. */
|
|
45
|
+
initialVisibleMax?: number
|
|
46
|
+
/** Initial canvas height in logical px. Default 480. */
|
|
47
|
+
initialHeight?: number
|
|
48
|
+
/**
|
|
49
|
+
* Threshold for the origin-shift rebaseline policy. Default 0.01 (1% of
|
|
50
|
+
* visible range). See `originShift.ts` for the rationale.
|
|
51
|
+
*/
|
|
52
|
+
originShiftThreshold?: number
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function createPriceScale(config: PriceScaleConfig = {}): PriceScale {
|
|
56
|
+
const initialMode: ScaleMode = config.initialMode ?? 'linear'
|
|
57
|
+
const initialVisibleMin = config.initialVisibleMin ?? 0
|
|
58
|
+
const initialVisibleMax = config.initialVisibleMax ?? 100
|
|
59
|
+
const initialHeight = config.initialHeight ?? 480
|
|
60
|
+
|
|
61
|
+
if (!(initialVisibleMax >= initialVisibleMin)) {
|
|
62
|
+
throw new KLineChartError(
|
|
63
|
+
'SCALE_RANGE_INVALID',
|
|
64
|
+
`createPriceScale: initialVisibleMax (${initialVisibleMax}) must be >= initialVisibleMin (${initialVisibleMin})`,
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
if (initialMode === 'log' && !(initialVisibleMin > 0)) {
|
|
68
|
+
throw new KLineChartError(
|
|
69
|
+
'SCALE_LOG_REQUIRES_POSITIVE',
|
|
70
|
+
`createPriceScale: log mode requires visibleMin > 0, got ${initialVisibleMin}`,
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
if (!(initialHeight > 0)) {
|
|
74
|
+
throw new KLineChartError('SCALE_HEIGHT_INVALID', `createPriceScale: initialHeight must be > 0, got ${initialHeight}`)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const mode = createSignal<ScaleMode>(initialMode)
|
|
78
|
+
const visibleMin = createSignal(initialVisibleMin)
|
|
79
|
+
const visibleMax = createSignal(initialVisibleMax)
|
|
80
|
+
const height = createSignal(initialHeight)
|
|
81
|
+
|
|
82
|
+
const initialRef = (initialVisibleMin + initialVisibleMax) / 2
|
|
83
|
+
const policy: OriginShiftPolicy = createOriginShiftPolicy(
|
|
84
|
+
initialRef,
|
|
85
|
+
config.originShiftThreshold,
|
|
86
|
+
)
|
|
87
|
+
const originShiftRef = createSignal(policy.ref)
|
|
88
|
+
|
|
89
|
+
let disposed = false
|
|
90
|
+
/**
|
|
91
|
+
* Post-dispose: mutator calls become silent no-ops. See createTimeScale.ts
|
|
92
|
+
* for the rationale + API audit BLOCKER-004 reference. Returns `true` when
|
|
93
|
+
* the operation should proceed.
|
|
94
|
+
*/
|
|
95
|
+
const guard = (): boolean => !disposed
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Run `policy.maybeRebaseline` with the latest visible range and, if it
|
|
99
|
+
* rebased, mirror the new value into the reactive `originShiftRef` signal
|
|
100
|
+
* so subscribers (uniform updaters, GPU buffer uploaders) can pick it up.
|
|
101
|
+
*/
|
|
102
|
+
const syncOriginShift = (): void => {
|
|
103
|
+
const min = visibleMin.peek()
|
|
104
|
+
const max = visibleMax.peek()
|
|
105
|
+
const range = max - min
|
|
106
|
+
const mid = (min + max) / 2
|
|
107
|
+
if (policy.maybeRebaseline(mid, range)) {
|
|
108
|
+
originShiftRef.set(policy.ref)
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const priceToYLinear = (p: number): number => {
|
|
113
|
+
const min = visibleMin.peek()
|
|
114
|
+
const max = visibleMax.peek()
|
|
115
|
+
const h = height.peek()
|
|
116
|
+
const span = max - min
|
|
117
|
+
if (span <= 0) return h / 2
|
|
118
|
+
const t = (p - min) / span
|
|
119
|
+
return h - t * h
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const priceToYLog = (p: number): number => {
|
|
123
|
+
const min = visibleMin.peek()
|
|
124
|
+
const max = visibleMax.peek()
|
|
125
|
+
const h = height.peek()
|
|
126
|
+
// Defensive — setMode('log') already rejects bad ranges, but we keep
|
|
127
|
+
// priceToY total so a stray p<=0 doesn't NaN out the whole chart.
|
|
128
|
+
if (p <= 0 || min <= 0 || max <= 0 || max <= min) return h / 2
|
|
129
|
+
const t = (Math.log(p) - Math.log(min)) / (Math.log(max) - Math.log(min))
|
|
130
|
+
return h - t * h
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const yToPriceLinear = (y: number): number => {
|
|
134
|
+
const min = visibleMin.peek()
|
|
135
|
+
const max = visibleMax.peek()
|
|
136
|
+
const h = height.peek()
|
|
137
|
+
const span = max - min
|
|
138
|
+
if (span <= 0) return min
|
|
139
|
+
return min + (1 - y / h) * span
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const yToPriceLog = (y: number): number => {
|
|
143
|
+
const min = visibleMin.peek()
|
|
144
|
+
const max = visibleMax.peek()
|
|
145
|
+
const h = height.peek()
|
|
146
|
+
if (min <= 0 || max <= 0 || max <= min) return min
|
|
147
|
+
const lmin = Math.log(min)
|
|
148
|
+
const lmax = Math.log(max)
|
|
149
|
+
const ly = lmin + (1 - y / h) * (lmax - lmin)
|
|
150
|
+
return Math.exp(ly)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const scale: PriceScale = {
|
|
154
|
+
mode,
|
|
155
|
+
visibleMin,
|
|
156
|
+
visibleMax,
|
|
157
|
+
height,
|
|
158
|
+
originShiftRef: originShiftRef as Signal<number>,
|
|
159
|
+
|
|
160
|
+
priceToY(p: number): number {
|
|
161
|
+
return mode.peek() === 'log' ? priceToYLog(p) : priceToYLinear(p)
|
|
162
|
+
},
|
|
163
|
+
|
|
164
|
+
yToPrice(y: number): number {
|
|
165
|
+
return mode.peek() === 'log' ? yToPriceLog(y) : yToPriceLinear(y)
|
|
166
|
+
},
|
|
167
|
+
|
|
168
|
+
setMode(next: ScaleMode): void {
|
|
169
|
+
if (!guard()) return
|
|
170
|
+
if (next === 'log') {
|
|
171
|
+
const min = visibleMin.peek()
|
|
172
|
+
const max = visibleMax.peek()
|
|
173
|
+
if (!(min > 0) || !(max > 0)) {
|
|
174
|
+
throw new KLineChartError(
|
|
175
|
+
'SCALE_LOG_REQUIRES_POSITIVE',
|
|
176
|
+
`PriceScale.setMode('log'): requires visibleMin > 0 and visibleMax > 0, got min=${min}, max=${max}`,
|
|
177
|
+
)
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
mode.set(next)
|
|
181
|
+
},
|
|
182
|
+
|
|
183
|
+
setVisibleRange(min: number, max: number): void {
|
|
184
|
+
if (!guard()) return
|
|
185
|
+
if (!Number.isFinite(min) || !Number.isFinite(max)) {
|
|
186
|
+
throw new KLineChartError(
|
|
187
|
+
'SCALE_RANGE_INVALID',
|
|
188
|
+
`PriceScale.setVisibleRange: both bounds must be finite, got min=${min}, max=${max}`,
|
|
189
|
+
)
|
|
190
|
+
}
|
|
191
|
+
if (max < min) {
|
|
192
|
+
throw new KLineChartError(
|
|
193
|
+
'SCALE_RANGE_INVALID',
|
|
194
|
+
`PriceScale.setVisibleRange: max (${max}) must be >= min (${min})`,
|
|
195
|
+
)
|
|
196
|
+
}
|
|
197
|
+
if (mode.peek() === 'log' && !(min > 0)) {
|
|
198
|
+
throw new KLineChartError(
|
|
199
|
+
'SCALE_LOG_REQUIRES_POSITIVE',
|
|
200
|
+
`PriceScale.setVisibleRange: log mode requires min > 0, got ${min}`,
|
|
201
|
+
)
|
|
202
|
+
}
|
|
203
|
+
visibleMin.set(min)
|
|
204
|
+
visibleMax.set(max)
|
|
205
|
+
syncOriginShift()
|
|
206
|
+
},
|
|
207
|
+
|
|
208
|
+
setHeight(h: number): void {
|
|
209
|
+
if (!guard()) return
|
|
210
|
+
if (!(h > 0)) {
|
|
211
|
+
throw new KLineChartError('SCALE_HEIGHT_INVALID', `PriceScale.setHeight: height must be > 0, got ${h}`)
|
|
212
|
+
}
|
|
213
|
+
height.set(h)
|
|
214
|
+
},
|
|
215
|
+
|
|
216
|
+
toShiftedFp32(p: number): number {
|
|
217
|
+
return policy.shift(p)
|
|
218
|
+
},
|
|
219
|
+
|
|
220
|
+
dispose(): void {
|
|
221
|
+
disposed = true
|
|
222
|
+
},
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return scale
|
|
226
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TimeScale factory — discrete bar-index ↔ screen X mapping (ROADMAP §1.1).
|
|
3
|
+
*
|
|
4
|
+
* The math is one-line in each direction; the value of this factory is the
|
|
5
|
+
* reactive plumbing (signals so adapters can subscribe) and the optional
|
|
6
|
+
* wall-clock calendar that maps bar indices ↔ timestamps.
|
|
7
|
+
*
|
|
8
|
+
* forward: x(i) = (i - firstVisibleIndex) * barWidth + leftPadding
|
|
9
|
+
* inverse: i(x) = (x - leftPadding) / barWidth + firstVisibleIndex
|
|
10
|
+
*
|
|
11
|
+
* Calendar semantics: when the user attaches a `barTimestamps` array, we treat
|
|
12
|
+
* bar index `i` as the array index. Integer indices map directly; fractional
|
|
13
|
+
* indices linearly interpolate between neighboring timestamps. Anything
|
|
14
|
+
* outside `[0, N-1]` returns `null` — the caller decides whether to clamp,
|
|
15
|
+
* extrapolate, or display a "—" label.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { createSignal } from '../reactivity/signal'
|
|
19
|
+
import { KLineChartError } from '../errors'
|
|
20
|
+
import type { TimeScale } from './types'
|
|
21
|
+
|
|
22
|
+
export interface TimeScaleConfig {
|
|
23
|
+
/** Default firstVisibleIndex. Fractional/negative allowed. Default 0. */
|
|
24
|
+
initialFirstVisibleIndex?: number
|
|
25
|
+
/** Default barWidth in logical px. Must be > 0. Default 8. */
|
|
26
|
+
initialBarWidth?: number
|
|
27
|
+
/** Default leftPadding in logical px. Default 0. */
|
|
28
|
+
initialLeftPadding?: number
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function createTimeScale(config: TimeScaleConfig = {}): TimeScale {
|
|
32
|
+
const initialFirstVisibleIndex = config.initialFirstVisibleIndex ?? 0
|
|
33
|
+
const initialBarWidth = config.initialBarWidth ?? 8
|
|
34
|
+
const initialLeftPadding = config.initialLeftPadding ?? 0
|
|
35
|
+
|
|
36
|
+
if (!(initialBarWidth > 0)) {
|
|
37
|
+
throw new KLineChartError('SCALE_BAR_WIDTH_INVALID', `createTimeScale: initialBarWidth must be > 0, got ${initialBarWidth}`)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const firstVisibleIndex = createSignal(initialFirstVisibleIndex)
|
|
41
|
+
const barWidth = createSignal(initialBarWidth)
|
|
42
|
+
const leftPadding = createSignal(initialLeftPadding)
|
|
43
|
+
|
|
44
|
+
let calendar: { barTimestamps: ReadonlyArray<number> } | null = null
|
|
45
|
+
let disposed = false
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Post-dispose: mutator calls become silent no-ops. This matches the
|
|
49
|
+
* convention used by every other controller in @klinechart-quant/core
|
|
50
|
+
* (IndicatorSelector, Toolbar, Drawing, Alerts, Replay, VolumeProfile,
|
|
51
|
+
* Footprint, OrderBookHeatmap, AnchoredVwap, MtfOverlay). Throwing on
|
|
52
|
+
* stale references — as the original implementation did — was the API
|
|
53
|
+
* audit BLOCKER-004 (docs/audit/API_REVIEW.md) divergence; harmonized
|
|
54
|
+
* to silent-no-op here.
|
|
55
|
+
*
|
|
56
|
+
* Returns `true` when the operation should proceed (controller live),
|
|
57
|
+
* `false` when it should be skipped (post-dispose).
|
|
58
|
+
*/
|
|
59
|
+
const guard = (): boolean => !disposed
|
|
60
|
+
|
|
61
|
+
const scale: TimeScale = {
|
|
62
|
+
firstVisibleIndex,
|
|
63
|
+
barWidth,
|
|
64
|
+
leftPadding,
|
|
65
|
+
|
|
66
|
+
xToBarIndex(x: number): number {
|
|
67
|
+
// We deliberately read with `.peek()` here — these methods are pure
|
|
68
|
+
// queries, they must not register the caller as a reactive subscriber.
|
|
69
|
+
const lp = leftPadding.peek()
|
|
70
|
+
const bw = barWidth.peek()
|
|
71
|
+
const fvi = firstVisibleIndex.peek()
|
|
72
|
+
return (x - lp) / bw + fvi
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
barIndexToX(i: number): number {
|
|
76
|
+
const lp = leftPadding.peek()
|
|
77
|
+
const bw = barWidth.peek()
|
|
78
|
+
const fvi = firstVisibleIndex.peek()
|
|
79
|
+
return (i - fvi) * bw + lp
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
setFirstVisibleIndex(i: number): void {
|
|
83
|
+
if (!guard()) return
|
|
84
|
+
firstVisibleIndex.set(i)
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
setBarWidth(w: number): void {
|
|
88
|
+
if (!guard()) return
|
|
89
|
+
if (!(w > 0)) {
|
|
90
|
+
throw new KLineChartError('SCALE_BAR_WIDTH_INVALID', `TimeScale.setBarWidth: barWidth must be > 0, got ${w}`)
|
|
91
|
+
}
|
|
92
|
+
barWidth.set(w)
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
setLeftPadding(p: number): void {
|
|
96
|
+
if (!guard()) return
|
|
97
|
+
leftPadding.set(p)
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
setCalendar(c) {
|
|
101
|
+
if (!guard()) return
|
|
102
|
+
calendar = c
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
timeToBarIndex(timestamp: number): number | null {
|
|
106
|
+
if (calendar === null) return null
|
|
107
|
+
const ts = calendar.barTimestamps
|
|
108
|
+
const n = ts.length
|
|
109
|
+
if (n === 0) return null
|
|
110
|
+
// Binary search for the upper bound of `timestamp` in `ts`.
|
|
111
|
+
// Returns the fractional index that interpolates linearly between
|
|
112
|
+
// bracketing bars. Outside the calendar → null.
|
|
113
|
+
if (timestamp < ts[0] || timestamp > ts[n - 1]) return null
|
|
114
|
+
if (timestamp === ts[n - 1]) return n - 1
|
|
115
|
+
let lo = 0
|
|
116
|
+
let hi = n - 1
|
|
117
|
+
while (hi - lo > 1) {
|
|
118
|
+
const mid = (lo + hi) >>> 1
|
|
119
|
+
if (ts[mid] <= timestamp) lo = mid
|
|
120
|
+
else hi = mid
|
|
121
|
+
}
|
|
122
|
+
const span = ts[hi] - ts[lo]
|
|
123
|
+
if (span <= 0) return lo
|
|
124
|
+
return lo + (timestamp - ts[lo]) / span
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
barIndexToTime(i: number): number | null {
|
|
128
|
+
if (calendar === null) return null
|
|
129
|
+
const ts = calendar.barTimestamps
|
|
130
|
+
const n = ts.length
|
|
131
|
+
if (n === 0) return null
|
|
132
|
+
if (i < 0 || i > n - 1) return null
|
|
133
|
+
const lo = Math.floor(i)
|
|
134
|
+
const hi = Math.min(lo + 1, n - 1)
|
|
135
|
+
if (lo === hi) return ts[lo]
|
|
136
|
+
const frac = i - lo
|
|
137
|
+
return ts[lo] + (ts[hi] - ts[lo]) * frac
|
|
138
|
+
},
|
|
139
|
+
|
|
140
|
+
dispose(): void {
|
|
141
|
+
// Signals don't allocate listeners we own; we just mark the
|
|
142
|
+
// instance as dead so writes throw and tests can assert dispose
|
|
143
|
+
// semantics. Reads remain functional as pure math.
|
|
144
|
+
disposed = true
|
|
145
|
+
calendar = null
|
|
146
|
+
},
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return scale
|
|
150
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type { ScaleMode, TimeScale, PriceScale } from './types'
|
|
2
|
+
export { createTimeScale, type TimeScaleConfig } from './createTimeScale'
|
|
3
|
+
export { createPriceScale, type PriceScaleConfig } from './createPriceScale'
|
|
4
|
+
export {
|
|
5
|
+
computeAnchoredZoom,
|
|
6
|
+
type AnchoredZoomOptions,
|
|
7
|
+
type AnchoredZoomResult,
|
|
8
|
+
} from './anchoredZoom'
|
|
9
|
+
export { createOriginShiftPolicy, type OriginShiftPolicy } from './originShift'
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { KLineChartError } from '../errors'
|
|
2
|
+
/**
|
|
3
|
+
* Origin-shift policy — ROADMAP §2.5, refined per the upstream PR feedback
|
|
4
|
+
* about *rebaseline drift*.
|
|
5
|
+
*
|
|
6
|
+
* Background. GPUs run fp32 (~7 decimal digits of precision). At BTC-tier
|
|
7
|
+
* prices (~67,000) and tick sizes (~0.01) the absolute price burns most of
|
|
8
|
+
* the mantissa, and a subtraction like `(p - pMin)` inside a zoomed-in
|
|
9
|
+
* sub-dollar range produces catastrophic cancellation. The cheap fix is to
|
|
10
|
+
* subtract a "reference value" `ref` on the CPU (which is fp64 and can spare
|
|
11
|
+
* it) before uploading, so the GPU only ever sees relative deltas in the
|
|
12
|
+
* 0.1-or-so range.
|
|
13
|
+
*
|
|
14
|
+
* Why this is its own policy object, and why **threshold-based**:
|
|
15
|
+
*
|
|
16
|
+
* The naive implementation — "every frame, set `ref = midpoint of current
|
|
17
|
+
* visible range`" — looks right but is actively harmful on pan. Every time
|
|
18
|
+
* the user drags one logical pixel, `ref` changes by one logical-pixel-of-
|
|
19
|
+
* price, and *all* prices get re-quantized to a slightly different fp32
|
|
20
|
+
* rounding. The result is a continuous, sub-pixel **shimmer** of the entire
|
|
21
|
+
* chart that the eye perceives as soft jitter even when no actual data has
|
|
22
|
+
* changed. (This is the bug I flagged on the upstream PR.)
|
|
23
|
+
*
|
|
24
|
+
* The fix is to keep `ref` *stable* until the visible-range center has
|
|
25
|
+
* drifted far enough that the fp32 budget is at risk of being exhausted —
|
|
26
|
+
* then rebaseline once, deliberately. The visible artifact becomes a single
|
|
27
|
+
* imperceptible discrete snap, instead of a continuous wobble.
|
|
28
|
+
*
|
|
29
|
+
* In practice 1% of the visible range works well: at a 100-dollar range you
|
|
30
|
+
* tolerate `ref` being 1 dollar off-center before re-snapping, which is
|
|
31
|
+
* nowhere near the fp32 cliff but cuts rebaselines from "every frame" to
|
|
32
|
+
* a handful per pan gesture.
|
|
33
|
+
*
|
|
34
|
+
* Edge cases worth documenting:
|
|
35
|
+
*
|
|
36
|
+
* - `threshold === 0` forces a rebaseline on *every* call where the midpoint
|
|
37
|
+
* differs from `ref` at all — this is the legacy "naive" behaviour, kept
|
|
38
|
+
* for parity tests against the bug we're avoiding.
|
|
39
|
+
*
|
|
40
|
+
* - `threshold >= 1` effectively disables rebaselining, useful when an
|
|
41
|
+
* adapter wants to manage `ref` externally.
|
|
42
|
+
*
|
|
43
|
+
* - A `currentRange` of zero (degenerate, visibleMin === visibleMax) is
|
|
44
|
+
* treated as "no signal" — we don't rebaseline because we cannot compute a
|
|
45
|
+
* meaningful normalized drift. The caller is responsible for handling the
|
|
46
|
+
* degenerate range elsewhere.
|
|
47
|
+
*/
|
|
48
|
+
|
|
49
|
+
export interface OriginShiftPolicy {
|
|
50
|
+
/** Current reference value. Subtract this from any price before upload. */
|
|
51
|
+
readonly ref: number
|
|
52
|
+
/** Subtract `ref` from `value`. The fp32-safe number to upload. */
|
|
53
|
+
shift(value: number): number
|
|
54
|
+
/**
|
|
55
|
+
* Maybe rebaseline. Returns `true` iff `ref` was updated.
|
|
56
|
+
*
|
|
57
|
+
* Policy: rebaseline only when
|
|
58
|
+
* `|currentMid - ref| / currentRange > threshold`.
|
|
59
|
+
* On rebaseline, `ref` becomes `currentMid`.
|
|
60
|
+
*/
|
|
61
|
+
maybeRebaseline(currentMid: number, currentRange: number): boolean
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const DEFAULT_THRESHOLD = 0.01
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @internal — building block used by `createPriceScale`. Reachable today
|
|
68
|
+
* via the top-level `@klinechart-quant/core` barrel but **NOT
|
|
69
|
+
* part of the supported public API**. typedoc / api-extractor
|
|
70
|
+
* hide it from generated docs. Prefer the controller factory
|
|
71
|
+
* for stable user code. Closes API audit BLOCKER-002.
|
|
72
|
+
*/
|
|
73
|
+
export function createOriginShiftPolicy(
|
|
74
|
+
initialRef: number,
|
|
75
|
+
threshold: number = DEFAULT_THRESHOLD,
|
|
76
|
+
): OriginShiftPolicy {
|
|
77
|
+
if (!Number.isFinite(initialRef)) {
|
|
78
|
+
throw new KLineChartError('INVALID_PARAM', `createOriginShiftPolicy: initialRef must be finite, got ${initialRef}`)
|
|
79
|
+
}
|
|
80
|
+
if (!Number.isFinite(threshold) || threshold < 0) {
|
|
81
|
+
throw new KLineChartError('INVALID_PARAM', `createOriginShiftPolicy: threshold must be >= 0, got ${threshold}`)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
let ref = initialRef
|
|
85
|
+
|
|
86
|
+
const policy: OriginShiftPolicy = {
|
|
87
|
+
get ref() {
|
|
88
|
+
return ref
|
|
89
|
+
},
|
|
90
|
+
shift(value: number): number {
|
|
91
|
+
return value - ref
|
|
92
|
+
},
|
|
93
|
+
maybeRebaseline(currentMid: number, currentRange: number): boolean {
|
|
94
|
+
// Degenerate range — refuse to rebaseline. Caller handles this elsewhere.
|
|
95
|
+
if (!Number.isFinite(currentMid) || !Number.isFinite(currentRange) || currentRange <= 0) {
|
|
96
|
+
return false
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const drift = Math.abs(currentMid - ref)
|
|
100
|
+
const normalized = drift / currentRange
|
|
101
|
+
|
|
102
|
+
if (normalized > threshold) {
|
|
103
|
+
ref = currentMid
|
|
104
|
+
return true
|
|
105
|
+
}
|
|
106
|
+
return false
|
|
107
|
+
},
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return policy
|
|
111
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coordinate-system interfaces for the headless core.
|
|
3
|
+
*
|
|
4
|
+
* The `TimeScale` maps **bar index** (a discrete-but-fractional sequence number)
|
|
5
|
+
* to a screen X position, per ROADMAP §1.1. Wall-clock time is a secondary
|
|
6
|
+
* label, available only when a calendar is attached.
|
|
7
|
+
*
|
|
8
|
+
* The `PriceScale` maps a (possibly very narrow) price range to screen Y per
|
|
9
|
+
* ROADMAP §1.2 — and additionally exposes an origin-shift policy so adapters
|
|
10
|
+
* can keep GPU uploads in safe fp32 territory (ROADMAP §2.5).
|
|
11
|
+
*
|
|
12
|
+
* Both scales are **reactive**: their core state is exposed as signals so the
|
|
13
|
+
* React/Vue/Angular adapter layer can subscribe without re-implementing the
|
|
14
|
+
* change-detection plumbing.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import type { Signal } from '../reactivity/signal'
|
|
18
|
+
|
|
19
|
+
/** Linear (arithmetic) or logarithmic Y mapping. */
|
|
20
|
+
export type ScaleMode = 'linear' | 'log'
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Discrete bar-index ↔ screen X mapping (ROADMAP §1.1).
|
|
24
|
+
*
|
|
25
|
+
* Forward equation (the only equation a renderer needs to know):
|
|
26
|
+
*
|
|
27
|
+
* x(i) = (i - firstVisibleIndex) * barWidth + leftPadding
|
|
28
|
+
*
|
|
29
|
+
* Inverse, used by anchored zoom and hit-testing:
|
|
30
|
+
*
|
|
31
|
+
* i(x) = (x - leftPadding) / barWidth + firstVisibleIndex
|
|
32
|
+
*
|
|
33
|
+
* `firstVisibleIndex` is allowed to be **fractional, negative, or > N**;
|
|
34
|
+
* this is what lets the user pan to "half a bar" or scroll into the future.
|
|
35
|
+
*/
|
|
36
|
+
export interface TimeScale {
|
|
37
|
+
/** Inverse: screen X (logical px) → fractional bar index. */
|
|
38
|
+
xToBarIndex(x: number): number
|
|
39
|
+
/** Forward: fractional bar index → screen X (logical px). */
|
|
40
|
+
barIndexToX(i: number): number
|
|
41
|
+
|
|
42
|
+
/** Fractional, may be negative or > N. */
|
|
43
|
+
readonly firstVisibleIndex: Signal<number>
|
|
44
|
+
/** Logical pixels per bar. Clamped by the caller (e.g. zoom) not the scale. */
|
|
45
|
+
readonly barWidth: Signal<number>
|
|
46
|
+
/** Logical pixels added on the left edge before bar 0. */
|
|
47
|
+
readonly leftPadding: Signal<number>
|
|
48
|
+
|
|
49
|
+
setFirstVisibleIndex(i: number): void
|
|
50
|
+
setBarWidth(w: number): void
|
|
51
|
+
setLeftPadding(p: number): void
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Attach (or detach with `null`) a wall-clock calendar so the scale can
|
|
55
|
+
* answer `timeToBarIndex` / `barIndexToTime`. Bar indices not covered by
|
|
56
|
+
* the calendar return `null` — *time is a label, not a coordinate*.
|
|
57
|
+
*/
|
|
58
|
+
setCalendar(c: { barTimestamps: ReadonlyArray<number> } | null): void
|
|
59
|
+
|
|
60
|
+
/** wall-clock ms → fractional bar index; `null` if no calendar / out of range. */
|
|
61
|
+
timeToBarIndex(timestamp: number): number | null
|
|
62
|
+
/** fractional bar index → wall-clock ms; `null` if no calendar / out of range. */
|
|
63
|
+
barIndexToTime(i: number): number | null
|
|
64
|
+
|
|
65
|
+
/** Detach signal subscribers and release any internal listeners. */
|
|
66
|
+
dispose(): void
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Price → screen Y mapping (ROADMAP §1.2) plus an origin-shift policy
|
|
71
|
+
* (ROADMAP §2.5) so adapters can upload fp32-safe values to the GPU.
|
|
72
|
+
*
|
|
73
|
+
* Coordinate convention: top-origin, Y increases downward (DOM standard).
|
|
74
|
+
* A price ≥ `visibleMax` maps to y = 0, a price ≤ `visibleMin` maps to
|
|
75
|
+
* y = `height`.
|
|
76
|
+
*/
|
|
77
|
+
export interface PriceScale {
|
|
78
|
+
/** Forward: price → screen Y (top-origin, increases downward). */
|
|
79
|
+
priceToY(p: number): number
|
|
80
|
+
/** Inverse: screen Y → price. */
|
|
81
|
+
yToPrice(y: number): number
|
|
82
|
+
|
|
83
|
+
readonly mode: Signal<ScaleMode>
|
|
84
|
+
readonly visibleMin: Signal<number>
|
|
85
|
+
readonly visibleMax: Signal<number>
|
|
86
|
+
readonly height: Signal<number>
|
|
87
|
+
|
|
88
|
+
/** Set `'linear'` or `'log'`; throws on `'log'` if `visibleMin <= 0`. */
|
|
89
|
+
setMode(mode: ScaleMode): void
|
|
90
|
+
/** Update visible range. Triggers the origin-shift rebaseline check. */
|
|
91
|
+
setVisibleRange(min: number, max: number): void
|
|
92
|
+
setHeight(h: number): void
|
|
93
|
+
|
|
94
|
+
/** Origin-shift reference; managed automatically but exposed for tests. */
|
|
95
|
+
readonly originShiftRef: Signal<number>
|
|
96
|
+
/** Returns `p - originShiftRef.peek()` — what to upload to the GPU as fp32. */
|
|
97
|
+
toShiftedFp32(p: number): number
|
|
98
|
+
|
|
99
|
+
dispose(): void
|
|
100
|
+
}
|