@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,108 @@
|
|
|
1
|
+
import { KLineChartError } from '../errors'
|
|
2
|
+
/**
|
|
3
|
+
* Stochastic RSI (Chande & Kroll, 1994).
|
|
4
|
+
*
|
|
5
|
+
* Two-step composition:
|
|
6
|
+
* 1. RSI(period) over close-only.
|
|
7
|
+
* 2. Stochastic over the RSI series:
|
|
8
|
+
* k[i] = 100 * (RSI[i] - min(RSI, stochPeriod))
|
|
9
|
+
* / (max(RSI, stochPeriod) - min(RSI, stochPeriod))
|
|
10
|
+
* 3. Smooth k by SMA(smoothK) → %K; smooth %K by SMA(smoothD) → %D.
|
|
11
|
+
*
|
|
12
|
+
* Output: parallel `Float64Array` pair { k, d }, both length === input.
|
|
13
|
+
* NaN leading. Returns 0..100.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export interface StochRsiOptions {
|
|
17
|
+
rsiPeriod: number
|
|
18
|
+
stochPeriod: number
|
|
19
|
+
smoothK?: number
|
|
20
|
+
smoothD?: number
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function computeStochRSI(
|
|
24
|
+
prices: ReadonlyArray<number>,
|
|
25
|
+
opts: StochRsiOptions,
|
|
26
|
+
): { k: Float64Array; d: Float64Array } {
|
|
27
|
+
const { rsiPeriod, stochPeriod } = opts
|
|
28
|
+
const smoothK = opts.smoothK ?? 3
|
|
29
|
+
const smoothD = opts.smoothD ?? 3
|
|
30
|
+
if (rsiPeriod < 2 || stochPeriod < 2 || smoothK < 1 || smoothD < 1) {
|
|
31
|
+
throw new KLineChartError('INDICATOR_INVALID_PARAM', 'computeStochRSI: invalid period args')
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const n = prices.length
|
|
35
|
+
const rsi = computeRsiSeries(prices, rsiPeriod)
|
|
36
|
+
|
|
37
|
+
const rawK = new Float64Array(n)
|
|
38
|
+
rawK.fill(Number.NaN)
|
|
39
|
+
for (let i = rsiPeriod + stochPeriod - 1; i < n; i++) {
|
|
40
|
+
let lo = Infinity
|
|
41
|
+
let hi = -Infinity
|
|
42
|
+
for (let j = i - stochPeriod + 1; j <= i; j++) {
|
|
43
|
+
const v = rsi[j] as number
|
|
44
|
+
if (Number.isNaN(v)) continue
|
|
45
|
+
if (v < lo) lo = v
|
|
46
|
+
if (v > hi) hi = v
|
|
47
|
+
}
|
|
48
|
+
const denom = hi - lo
|
|
49
|
+
rawK[i] = denom === 0 ? 50 : (100 * ((rsi[i] as number) - lo)) / denom
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const k = smaSeries(rawK, smoothK)
|
|
53
|
+
const d = smaSeries(k, smoothD)
|
|
54
|
+
return { k, d }
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function computeRsiSeries(prices: ReadonlyArray<number>, period: number): Float64Array {
|
|
58
|
+
const n = prices.length
|
|
59
|
+
const out = new Float64Array(n)
|
|
60
|
+
out.fill(Number.NaN)
|
|
61
|
+
if (n < period + 1) return out
|
|
62
|
+
|
|
63
|
+
let gainSum = 0
|
|
64
|
+
let lossSum = 0
|
|
65
|
+
for (let i = 1; i <= period; i++) {
|
|
66
|
+
const diff = (prices[i] as number) - (prices[i - 1] as number)
|
|
67
|
+
if (diff > 0) gainSum += diff
|
|
68
|
+
else lossSum += -diff
|
|
69
|
+
}
|
|
70
|
+
let avgGain = gainSum / period
|
|
71
|
+
let avgLoss = lossSum / period
|
|
72
|
+
out[period] = avgLoss === 0 ? 100 : 100 - 100 / (1 + avgGain / avgLoss)
|
|
73
|
+
|
|
74
|
+
for (let i = period + 1; i < n; i++) {
|
|
75
|
+
const diff = (prices[i] as number) - (prices[i - 1] as number)
|
|
76
|
+
const g = diff > 0 ? diff : 0
|
|
77
|
+
const l = diff < 0 ? -diff : 0
|
|
78
|
+
avgGain = (avgGain * (period - 1) + g) / period
|
|
79
|
+
avgLoss = (avgLoss * (period - 1) + l) / period
|
|
80
|
+
out[i] = avgLoss === 0 ? 100 : 100 - 100 / (1 + avgGain / avgLoss)
|
|
81
|
+
}
|
|
82
|
+
return out
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function smaSeries(input: Float64Array, period: number): Float64Array {
|
|
86
|
+
const n = input.length
|
|
87
|
+
const out = new Float64Array(n)
|
|
88
|
+
out.fill(Number.NaN)
|
|
89
|
+
let acc = 0
|
|
90
|
+
let count = 0
|
|
91
|
+
let start = 0
|
|
92
|
+
for (let i = 0; i < n; i++) {
|
|
93
|
+
const v = input[i] as number
|
|
94
|
+
if (!Number.isNaN(v)) {
|
|
95
|
+
acc += v
|
|
96
|
+
count++
|
|
97
|
+
}
|
|
98
|
+
if (count >= period) {
|
|
99
|
+
out[i] = acc / period
|
|
100
|
+
// Slide window: subtract the value leaving the window (period back).
|
|
101
|
+
const left = input[start + count - period] as number
|
|
102
|
+
if (!Number.isNaN(left)) acc -= left
|
|
103
|
+
else count-- // adjust if a NaN was at the left edge
|
|
104
|
+
start = i - period + 2
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return out
|
|
108
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { KLineChartError } from '../errors'
|
|
2
|
+
/**
|
|
3
|
+
* T3 — Tim Tillson's smoothed-EMA cascade (1998).
|
|
4
|
+
*
|
|
5
|
+
* Public reference: T. Tillson, "Better Moving Averages",
|
|
6
|
+
* Technical Analysis of Stocks & Commodities, January 1998.
|
|
7
|
+
*
|
|
8
|
+
* Algorithm:
|
|
9
|
+
* 1. EMA1 = EMA(price, period)
|
|
10
|
+
* 2. EMA2 = EMA(EMA1, period)
|
|
11
|
+
* 3. EMA3 = EMA(EMA2, period)
|
|
12
|
+
* 4. EMA4 = EMA(EMA3, period)
|
|
13
|
+
* 5. EMA5 = EMA(EMA4, period)
|
|
14
|
+
* 6. EMA6 = EMA(EMA5, period)
|
|
15
|
+
* T3 = c1*EMA6 + c2*EMA5 + c3*EMA4 + c4*EMA3
|
|
16
|
+
* where
|
|
17
|
+
* a = volume factor in [0, 1], default 0.7
|
|
18
|
+
* c1 = -a^3
|
|
19
|
+
* c2 = 3*a^2 + 3*a^3
|
|
20
|
+
* c3 = -6*a^2 - 3*a - 3*a^3
|
|
21
|
+
* c4 = 1 + 3*a + a^3 + 3*a^2
|
|
22
|
+
*
|
|
23
|
+
* Output length === input length. The first non-NaN value emerges once the
|
|
24
|
+
* EMA cascade has primed (we seed each EMA on its first input).
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
export interface T3Options {
|
|
28
|
+
period: number
|
|
29
|
+
/** Volume factor in [0, 1]. Default 0.7. Lower = smoother. */
|
|
30
|
+
volumeFactor?: number
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function emaSeries(input: Float64Array, period: number): Float64Array {
|
|
34
|
+
const out = new Float64Array(input.length)
|
|
35
|
+
const k = 2 / (period + 1)
|
|
36
|
+
let prev = Number.NaN
|
|
37
|
+
for (let i = 0; i < input.length; i++) {
|
|
38
|
+
const v = input[i] as number
|
|
39
|
+
if (Number.isNaN(v)) {
|
|
40
|
+
out[i] = Number.NaN
|
|
41
|
+
continue
|
|
42
|
+
}
|
|
43
|
+
if (Number.isNaN(prev)) {
|
|
44
|
+
prev = v
|
|
45
|
+
} else {
|
|
46
|
+
prev = k * v + (1 - k) * prev
|
|
47
|
+
}
|
|
48
|
+
out[i] = prev
|
|
49
|
+
}
|
|
50
|
+
return out
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function computeT3(prices: ReadonlyArray<number>, opts: T3Options): Float64Array {
|
|
54
|
+
const { period } = opts
|
|
55
|
+
const a = opts.volumeFactor ?? 0.7
|
|
56
|
+
if (period < 2 || !Number.isFinite(period)) throw new KLineChartError('INDICATOR_INVALID_PARAM', 'computeT3: period must be >= 2')
|
|
57
|
+
if (a < 0 || a > 1 || !Number.isFinite(a)) {
|
|
58
|
+
throw new KLineChartError('INDICATOR_INVALID_PARAM', 'computeT3: volumeFactor must be in [0, 1]')
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const src = new Float64Array(prices.length)
|
|
62
|
+
for (let i = 0; i < prices.length; i++) src[i] = prices[i] as number
|
|
63
|
+
|
|
64
|
+
const e1 = emaSeries(src, period)
|
|
65
|
+
const e2 = emaSeries(e1, period)
|
|
66
|
+
const e3 = emaSeries(e2, period)
|
|
67
|
+
const e4 = emaSeries(e3, period)
|
|
68
|
+
const e5 = emaSeries(e4, period)
|
|
69
|
+
const e6 = emaSeries(e5, period)
|
|
70
|
+
|
|
71
|
+
const a2 = a * a
|
|
72
|
+
const a3 = a2 * a
|
|
73
|
+
const c1 = -a3
|
|
74
|
+
const c2 = 3 * a2 + 3 * a3
|
|
75
|
+
const c3 = -6 * a2 - 3 * a - 3 * a3
|
|
76
|
+
const c4 = 1 + 3 * a + a3 + 3 * a2
|
|
77
|
+
|
|
78
|
+
const out = new Float64Array(prices.length)
|
|
79
|
+
for (let i = 0; i < prices.length; i++) {
|
|
80
|
+
const v6 = e6[i] as number
|
|
81
|
+
const v5 = e5[i] as number
|
|
82
|
+
const v4 = e4[i] as number
|
|
83
|
+
const v3 = e3[i] as number
|
|
84
|
+
if (
|
|
85
|
+
Number.isNaN(v6) ||
|
|
86
|
+
Number.isNaN(v5) ||
|
|
87
|
+
Number.isNaN(v4) ||
|
|
88
|
+
Number.isNaN(v3)
|
|
89
|
+
) {
|
|
90
|
+
out[i] = Number.NaN
|
|
91
|
+
} else {
|
|
92
|
+
out[i] = c1 * v6 + c2 * v5 + c3 * v4 + c4 * v3
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return out
|
|
96
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { KLineChartError } from '../errors'
|
|
2
|
+
/**
|
|
3
|
+
* Ultimate Oscillator — Larry Williams (1976).
|
|
4
|
+
*
|
|
5
|
+
* Weighted multi-period buying-pressure / true-range oscillator.
|
|
6
|
+
*
|
|
7
|
+
* prevClose[i] = close[i-1]
|
|
8
|
+
* BP[i] = close[i] - min(low[i], prevClose[i])
|
|
9
|
+
* TR[i] = max(high[i], prevClose[i]) - min(low[i], prevClose[i])
|
|
10
|
+
* avg(N) = sum(BP, N) / sum(TR, N)
|
|
11
|
+
* UO[i] = 100 * (4*avg(p1) + 2*avg(p2) + avg(p3)) / 7
|
|
12
|
+
*
|
|
13
|
+
* Defaults: p1=7, p2=14, p3=28.
|
|
14
|
+
*
|
|
15
|
+
* Output: `Float64Array` length === input. NaN until index >= max(p1,p2,p3).
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
export interface UltimateOscillatorOptions {
|
|
19
|
+
p1?: number
|
|
20
|
+
p2?: number
|
|
21
|
+
p3?: number
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function computeUltimateOscillator(
|
|
25
|
+
bars: ReadonlyArray<{ high: number; low: number; close: number }>,
|
|
26
|
+
opts: UltimateOscillatorOptions = {},
|
|
27
|
+
): Float64Array {
|
|
28
|
+
const p1 = opts.p1 ?? 7
|
|
29
|
+
const p2 = opts.p2 ?? 14
|
|
30
|
+
const p3 = opts.p3 ?? 28
|
|
31
|
+
if (p1 < 1 || p2 < 1 || p3 < 1) {
|
|
32
|
+
throw new KLineChartError('INDICATOR_INVALID_PARAM', 'computeUltimateOscillator: all periods must be >= 1')
|
|
33
|
+
}
|
|
34
|
+
const n = bars.length
|
|
35
|
+
const bp = new Float64Array(n)
|
|
36
|
+
const tr = new Float64Array(n)
|
|
37
|
+
for (let i = 0; i < n; i++) {
|
|
38
|
+
const b = bars[i] as { high: number; low: number; close: number }
|
|
39
|
+
if (i === 0) {
|
|
40
|
+
bp[i] = 0
|
|
41
|
+
tr[i] = b.high - b.low
|
|
42
|
+
continue
|
|
43
|
+
}
|
|
44
|
+
const pc = (bars[i - 1] as { close: number }).close
|
|
45
|
+
const minLow = Math.min(b.low, pc)
|
|
46
|
+
bp[i] = b.close - minLow
|
|
47
|
+
tr[i] = Math.max(b.high, pc) - minLow
|
|
48
|
+
}
|
|
49
|
+
const r1 = rollingRatio(bp, tr, p1)
|
|
50
|
+
const r2 = rollingRatio(bp, tr, p2)
|
|
51
|
+
const r3 = rollingRatio(bp, tr, p3)
|
|
52
|
+
const out = new Float64Array(n)
|
|
53
|
+
const maxP = Math.max(p1, p2, p3)
|
|
54
|
+
for (let i = 0; i < n; i++) {
|
|
55
|
+
if (i < maxP) {
|
|
56
|
+
out[i] = Number.NaN
|
|
57
|
+
continue
|
|
58
|
+
}
|
|
59
|
+
out[i] = (100 * (4 * (r1[i] as number) + 2 * (r2[i] as number) + (r3[i] as number))) / 7
|
|
60
|
+
}
|
|
61
|
+
return out
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function rollingRatio(num: Float64Array, den: Float64Array, period: number): Float64Array {
|
|
65
|
+
const n = num.length
|
|
66
|
+
const out = new Float64Array(n)
|
|
67
|
+
let sNum = 0
|
|
68
|
+
let sDen = 0
|
|
69
|
+
for (let i = 0; i < n; i++) {
|
|
70
|
+
sNum += num[i] as number
|
|
71
|
+
sDen += den[i] as number
|
|
72
|
+
if (i >= period) {
|
|
73
|
+
sNum -= num[i - period] as number
|
|
74
|
+
sDen -= den[i - period] as number
|
|
75
|
+
}
|
|
76
|
+
if (i < period - 1 || sDen === 0) {
|
|
77
|
+
out[i] = Number.NaN
|
|
78
|
+
} else {
|
|
79
|
+
out[i] = sNum / sDen
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return out
|
|
83
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { KLineChartError } from '../errors'
|
|
2
|
+
/**
|
|
3
|
+
* VIDYA — Variable Index Dynamic Average (Tushar Chande).
|
|
4
|
+
*
|
|
5
|
+
* CMO-adapted EMA: the smoothing constant is scaled by the absolute value
|
|
6
|
+
* of the Chande Momentum Oscillator, so VIDYA accelerates in trending
|
|
7
|
+
* markets and slows in chop.
|
|
8
|
+
*
|
|
9
|
+
* gain[i] = max(price[i] - price[i-1], 0)
|
|
10
|
+
* loss[i] = max(price[i-1] - price[i], 0)
|
|
11
|
+
* CMO(t) = 100 * (sum(gain, t-cmoPeriod+1..t) - sum(loss, ...))
|
|
12
|
+
* / (sum(gain) + sum(loss)) (NaN-guarded)
|
|
13
|
+
* alpha = (2 / (period + 1)) * |CMO(t) / 100|
|
|
14
|
+
* VIDYA[i] = alpha * price[i] + (1 - alpha) * VIDYA[i-1]
|
|
15
|
+
*
|
|
16
|
+
* Output length === input length. Indices < cmoPeriod are NaN. VIDYA seeds
|
|
17
|
+
* on the first valid CMO sample.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
export interface VidyaOptions {
|
|
21
|
+
period: number
|
|
22
|
+
/** Window for the CMO numerator/denominator. Default 9. */
|
|
23
|
+
cmoPeriod?: number
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function computeVIDYA(prices: ReadonlyArray<number>, opts: VidyaOptions): Float64Array {
|
|
27
|
+
const { period } = opts
|
|
28
|
+
const cmoPeriod = opts.cmoPeriod ?? 9
|
|
29
|
+
if (period < 2 || !Number.isFinite(period)) throw new KLineChartError('INDICATOR_INVALID_PARAM', 'computeVIDYA: period must be >= 2')
|
|
30
|
+
if (cmoPeriod < 1 || !Number.isFinite(cmoPeriod)) {
|
|
31
|
+
throw new KLineChartError('INDICATOR_INVALID_PARAM', 'computeVIDYA: cmoPeriod must be >= 1')
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const n = prices.length
|
|
35
|
+
const out = new Float64Array(n)
|
|
36
|
+
const baseAlpha = 2 / (period + 1)
|
|
37
|
+
|
|
38
|
+
// Rolling sums of gain / loss across the cmoPeriod window of diffs.
|
|
39
|
+
let gainSum = 0
|
|
40
|
+
let lossSum = 0
|
|
41
|
+
let prev = Number.NaN
|
|
42
|
+
|
|
43
|
+
for (let i = 0; i < n; i++) {
|
|
44
|
+
if (i === 0) {
|
|
45
|
+
out[i] = Number.NaN
|
|
46
|
+
continue
|
|
47
|
+
}
|
|
48
|
+
const cur = prices[i] as number
|
|
49
|
+
const previous = prices[i - 1] as number
|
|
50
|
+
const diff = cur - previous
|
|
51
|
+
const gain = diff > 0 ? diff : 0
|
|
52
|
+
const loss = diff < 0 ? -diff : 0
|
|
53
|
+
gainSum += gain
|
|
54
|
+
lossSum += loss
|
|
55
|
+
|
|
56
|
+
// Drop the diff that just slid out of the window.
|
|
57
|
+
if (i > cmoPeriod) {
|
|
58
|
+
const drop = (prices[i - cmoPeriod] as number) - (prices[i - cmoPeriod - 1] as number)
|
|
59
|
+
if (drop > 0) gainSum -= drop
|
|
60
|
+
else if (drop < 0) lossSum += drop // (-drop is the abs)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (i < cmoPeriod) {
|
|
64
|
+
out[i] = Number.NaN
|
|
65
|
+
continue
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const denom = gainSum + lossSum
|
|
69
|
+
const cmoAbs = denom === 0 ? 0 : Math.abs((gainSum - lossSum) / denom)
|
|
70
|
+
const alpha = baseAlpha * cmoAbs
|
|
71
|
+
|
|
72
|
+
if (Number.isNaN(prev)) {
|
|
73
|
+
prev = cur
|
|
74
|
+
} else {
|
|
75
|
+
prev = alpha * cur + (1 - alpha) * prev
|
|
76
|
+
}
|
|
77
|
+
out[i] = prev
|
|
78
|
+
}
|
|
79
|
+
return out
|
|
80
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { KLineChartError } from '../errors'
|
|
2
|
+
/**
|
|
3
|
+
* ZLEMA — Zero-Lag Exponential Moving Average (Ehlers).
|
|
4
|
+
*
|
|
5
|
+
* Removes EMA lag by feeding the EMA a "momentum-adjusted" series:
|
|
6
|
+
* lag = floor((period - 1) / 2)
|
|
7
|
+
* adj[i] = price[i] + (price[i] - price[i - lag])
|
|
8
|
+
* zlema = EMA(adj, period)
|
|
9
|
+
*
|
|
10
|
+
* Output length === input length. Indices < lag are NaN (no adjustment
|
|
11
|
+
* available); the EMA seeds on the first valid sample.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
export interface ZlemaOptions {
|
|
15
|
+
period: number
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function computeZLEMA(prices: ReadonlyArray<number>, opts: ZlemaOptions): Float64Array {
|
|
19
|
+
const { period } = opts
|
|
20
|
+
if (period < 2 || !Number.isFinite(period)) throw new KLineChartError('INDICATOR_INVALID_PARAM', 'computeZLEMA: period must be >= 2')
|
|
21
|
+
|
|
22
|
+
const out = new Float64Array(prices.length)
|
|
23
|
+
const lag = Math.floor((period - 1) / 2)
|
|
24
|
+
const k = 2 / (period + 1)
|
|
25
|
+
|
|
26
|
+
let ema = Number.NaN
|
|
27
|
+
for (let i = 0; i < prices.length; i++) {
|
|
28
|
+
if (i < lag) {
|
|
29
|
+
out[i] = Number.NaN
|
|
30
|
+
continue
|
|
31
|
+
}
|
|
32
|
+
const adj = 2 * (prices[i] as number) - (prices[i - lag] as number)
|
|
33
|
+
if (Number.isNaN(ema)) {
|
|
34
|
+
ema = adj
|
|
35
|
+
} else {
|
|
36
|
+
ema = k * adj + (1 - k) * ema
|
|
37
|
+
}
|
|
38
|
+
out[i] = ema
|
|
39
|
+
}
|
|
40
|
+
return out
|
|
41
|
+
}
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for `createGestureRecognizer`.
|
|
3
|
+
*
|
|
4
|
+
* Coverage:
|
|
5
|
+
* 1. State machine — idle / tracking / pan / pinch transitions.
|
|
6
|
+
* 2. Tap — single pointer down/up within deadzone.
|
|
7
|
+
* 3. Pan — primary pointer escapes deadzone, emits panStart + pan + panEnd.
|
|
8
|
+
* 4. Swipe — pan with fast release crosses velocity threshold → swipe.
|
|
9
|
+
* 5. Pinch — two pointers down, scale computed against initial distance.
|
|
10
|
+
* 6. Pinch → tracking demotion when one of the two pointers releases.
|
|
11
|
+
* 7. cancel() resets without emit.
|
|
12
|
+
* 8. Config validation — negative deadzone / velocity rejected.
|
|
13
|
+
* 9. dispose() makes everything a no-op.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { describe, it, expect } from 'vitest'
|
|
17
|
+
|
|
18
|
+
import { createGestureRecognizer, type PointerEventLike, type GestureEvent } from '..'
|
|
19
|
+
import { isKLineChartError } from '../../errors'
|
|
20
|
+
|
|
21
|
+
function pt(id: number, x: number, y: number, ts: number): PointerEventLike {
|
|
22
|
+
return { pointerId: id, x, y, timestamp: ts }
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Drive the recognizer and collect every emitted event in order.
|
|
27
|
+
*/
|
|
28
|
+
function drive(
|
|
29
|
+
g: ReturnType<typeof createGestureRecognizer>,
|
|
30
|
+
steps: Array<['down' | 'move' | 'up', PointerEventLike]>,
|
|
31
|
+
): GestureEvent[] {
|
|
32
|
+
const out: GestureEvent[] = []
|
|
33
|
+
g.events.subscribe(() => {
|
|
34
|
+
const e = g.events.peek()
|
|
35
|
+
if (e !== null) out.push(e)
|
|
36
|
+
})
|
|
37
|
+
for (const [op, e] of steps) {
|
|
38
|
+
if (op === 'down') g.onPointerDown(e)
|
|
39
|
+
else if (op === 'move') g.onPointerMove(e)
|
|
40
|
+
else g.onPointerUp(e)
|
|
41
|
+
}
|
|
42
|
+
return out
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
// Tap
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
|
|
49
|
+
describe('tap', () => {
|
|
50
|
+
it('down + up within deadzone emits a tap', () => {
|
|
51
|
+
const g = createGestureRecognizer({ panDeadzone: 6 })
|
|
52
|
+
const events = drive(g, [
|
|
53
|
+
['down', pt(1, 100, 100, 0)],
|
|
54
|
+
['up', pt(1, 102, 101, 50)],
|
|
55
|
+
])
|
|
56
|
+
expect(events.map((e) => e.type)).toEqual(['tap'])
|
|
57
|
+
expect(g.state.peek()).toBe('idle')
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('down + up at exact same point emits a tap (no movement at all)', () => {
|
|
61
|
+
const g = createGestureRecognizer()
|
|
62
|
+
const events = drive(g, [
|
|
63
|
+
['down', pt(1, 50, 50, 0)],
|
|
64
|
+
['up', pt(1, 50, 50, 100)],
|
|
65
|
+
])
|
|
66
|
+
expect(events.map((e) => e.type)).toEqual(['tap'])
|
|
67
|
+
})
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
// Pan
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
|
|
74
|
+
describe('pan', () => {
|
|
75
|
+
it('promotes to pan when movement escapes deadzone', () => {
|
|
76
|
+
const g = createGestureRecognizer({ panDeadzone: 6, swipeMinVelocity: 999 })
|
|
77
|
+
const events = drive(g, [
|
|
78
|
+
['down', pt(1, 100, 100, 0)],
|
|
79
|
+
['move', pt(1, 102, 102, 10)],
|
|
80
|
+
['move', pt(1, 120, 100, 20)], // 20px from start → past deadzone
|
|
81
|
+
['move', pt(1, 140, 100, 30)],
|
|
82
|
+
['up', pt(1, 140, 100, 1000)], // slow release → panEnd, not swipe
|
|
83
|
+
])
|
|
84
|
+
const types = events.map((e) => e.type)
|
|
85
|
+
expect(types).toContain('panStart')
|
|
86
|
+
expect(types.filter((t) => t === 'pan').length).toBeGreaterThanOrEqual(1)
|
|
87
|
+
expect(types[types.length - 1]).toBe('panEnd')
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
it('panStart fires exactly once per gesture', () => {
|
|
91
|
+
const g = createGestureRecognizer({ panDeadzone: 6, swipeMinVelocity: 999 })
|
|
92
|
+
const events = drive(g, [
|
|
93
|
+
['down', pt(1, 0, 0, 0)],
|
|
94
|
+
['move', pt(1, 20, 0, 10)],
|
|
95
|
+
['move', pt(1, 40, 0, 20)],
|
|
96
|
+
['move', pt(1, 60, 0, 30)],
|
|
97
|
+
['up', pt(1, 60, 0, 1000)],
|
|
98
|
+
])
|
|
99
|
+
expect(events.filter((e) => e.type === 'panStart').length).toBe(1)
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
it('pan events carry running dx/dy', () => {
|
|
103
|
+
const g = createGestureRecognizer({ panDeadzone: 0, swipeMinVelocity: 999 })
|
|
104
|
+
const events = drive(g, [
|
|
105
|
+
['down', pt(1, 0, 0, 0)],
|
|
106
|
+
['move', pt(1, 10, 5, 10)],
|
|
107
|
+
['move', pt(1, 30, 12, 20)],
|
|
108
|
+
['up', pt(1, 30, 12, 1000)],
|
|
109
|
+
])
|
|
110
|
+
const pans = events.filter((e): e is Extract<GestureEvent, { type: 'pan' }> => e.type === 'pan')
|
|
111
|
+
// First pan: dx = 10 - 0 = 10, dy = 5 - 0 = 5
|
|
112
|
+
expect(pans[0]?.dx).toBe(10)
|
|
113
|
+
expect(pans[0]?.dy).toBe(5)
|
|
114
|
+
// Second pan: dx = 30 - 10 = 20, dy = 12 - 5 = 7
|
|
115
|
+
expect(pans[1]?.dx).toBe(20)
|
|
116
|
+
expect(pans[1]?.dy).toBe(7)
|
|
117
|
+
})
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
121
|
+
// Swipe
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
|
|
124
|
+
describe('swipe', () => {
|
|
125
|
+
it('fast release after pan emits swipe instead of panEnd', () => {
|
|
126
|
+
const g = createGestureRecognizer({
|
|
127
|
+
panDeadzone: 6,
|
|
128
|
+
swipeMinVelocity: 0.5,
|
|
129
|
+
swipeVelocityWindowMs: 100,
|
|
130
|
+
})
|
|
131
|
+
// 100px in 50ms → 2 px/ms, comfortably above 0.5
|
|
132
|
+
const events = drive(g, [
|
|
133
|
+
['down', pt(1, 0, 0, 0)],
|
|
134
|
+
['move', pt(1, 20, 0, 10)],
|
|
135
|
+
['move', pt(1, 60, 0, 30)],
|
|
136
|
+
['move', pt(1, 100, 0, 50)],
|
|
137
|
+
['up', pt(1, 100, 0, 50)],
|
|
138
|
+
])
|
|
139
|
+
const last = events[events.length - 1]
|
|
140
|
+
expect(last?.type).toBe('swipe')
|
|
141
|
+
const swipe = last as Extract<GestureEvent, { type: 'swipe' }>
|
|
142
|
+
expect(swipe.vx).toBeGreaterThan(0.5)
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
it('slow release after pan emits panEnd, not swipe', () => {
|
|
146
|
+
const g = createGestureRecognizer({
|
|
147
|
+
panDeadzone: 6,
|
|
148
|
+
swipeMinVelocity: 0.5,
|
|
149
|
+
swipeVelocityWindowMs: 100,
|
|
150
|
+
})
|
|
151
|
+
// 20px in 200ms → 0.1 px/ms, below threshold
|
|
152
|
+
const events = drive(g, [
|
|
153
|
+
['down', pt(1, 0, 0, 0)],
|
|
154
|
+
['move', pt(1, 10, 0, 100)],
|
|
155
|
+
['move', pt(1, 20, 0, 200)],
|
|
156
|
+
['up', pt(1, 20, 0, 200)],
|
|
157
|
+
])
|
|
158
|
+
expect(events[events.length - 1]?.type).toBe('panEnd')
|
|
159
|
+
})
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
// ---------------------------------------------------------------------------
|
|
163
|
+
// Pinch
|
|
164
|
+
// ---------------------------------------------------------------------------
|
|
165
|
+
|
|
166
|
+
describe('pinch', () => {
|
|
167
|
+
it('second pointer down → pinchStart', () => {
|
|
168
|
+
const g = createGestureRecognizer()
|
|
169
|
+
const events = drive(g, [
|
|
170
|
+
['down', pt(1, 0, 0, 0)],
|
|
171
|
+
['down', pt(2, 100, 0, 10)],
|
|
172
|
+
])
|
|
173
|
+
const start = events.find((e) => e.type === 'pinchStart') as
|
|
174
|
+
| Extract<GestureEvent, { type: 'pinchStart' }>
|
|
175
|
+
| undefined
|
|
176
|
+
expect(start).toBeDefined()
|
|
177
|
+
expect(start?.cx).toBe(50)
|
|
178
|
+
expect(start?.distance).toBe(100)
|
|
179
|
+
expect(g.state.peek()).toBe('pinch')
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
it('scale doubles when distance doubles', () => {
|
|
183
|
+
const g = createGestureRecognizer()
|
|
184
|
+
const events = drive(g, [
|
|
185
|
+
['down', pt(1, 0, 0, 0)],
|
|
186
|
+
['down', pt(2, 100, 0, 10)],
|
|
187
|
+
['move', pt(2, 200, 0, 20)], // distance 200, started at 100 → scale 2
|
|
188
|
+
])
|
|
189
|
+
const pinches = events.filter(
|
|
190
|
+
(e): e is Extract<GestureEvent, { type: 'pinch' }> => e.type === 'pinch',
|
|
191
|
+
)
|
|
192
|
+
expect(pinches[pinches.length - 1]?.scale).toBeCloseTo(2, 10)
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
it('lifting one finger emits pinchEnd and demotes to tracking', () => {
|
|
196
|
+
const g = createGestureRecognizer()
|
|
197
|
+
const events = drive(g, [
|
|
198
|
+
['down', pt(1, 0, 0, 0)],
|
|
199
|
+
['down', pt(2, 100, 0, 10)],
|
|
200
|
+
['up', pt(2, 100, 0, 20)],
|
|
201
|
+
])
|
|
202
|
+
expect(events.find((e) => e.type === 'pinchEnd')).toBeDefined()
|
|
203
|
+
expect(g.state.peek()).toBe('tracking')
|
|
204
|
+
})
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
// ---------------------------------------------------------------------------
|
|
208
|
+
// Cancel
|
|
209
|
+
// ---------------------------------------------------------------------------
|
|
210
|
+
|
|
211
|
+
describe('cancel', () => {
|
|
212
|
+
it('resets to idle without emitting', () => {
|
|
213
|
+
const g = createGestureRecognizer()
|
|
214
|
+
const seen: GestureEvent[] = []
|
|
215
|
+
g.events.subscribe(() => {
|
|
216
|
+
const e = g.events.peek()
|
|
217
|
+
if (e !== null) seen.push(e)
|
|
218
|
+
})
|
|
219
|
+
g.onPointerDown(pt(1, 0, 0, 0))
|
|
220
|
+
g.onPointerMove(pt(1, 100, 0, 10))
|
|
221
|
+
const before = seen.length
|
|
222
|
+
g.cancel()
|
|
223
|
+
expect(g.state.peek()).toBe('idle')
|
|
224
|
+
expect(seen.length).toBe(before) // no emit on cancel
|
|
225
|
+
})
|
|
226
|
+
})
|
|
227
|
+
|
|
228
|
+
// ---------------------------------------------------------------------------
|
|
229
|
+
// Config validation
|
|
230
|
+
// ---------------------------------------------------------------------------
|
|
231
|
+
|
|
232
|
+
describe('options validation', () => {
|
|
233
|
+
it('rejects negative panDeadzone', () => {
|
|
234
|
+
try {
|
|
235
|
+
createGestureRecognizer({ panDeadzone: -1 })
|
|
236
|
+
expect.fail('expected throw')
|
|
237
|
+
} catch (e) {
|
|
238
|
+
expect(isKLineChartError(e, 'INVALID_PARAM')).toBe(true)
|
|
239
|
+
}
|
|
240
|
+
})
|
|
241
|
+
|
|
242
|
+
it('rejects negative swipeMinVelocity', () => {
|
|
243
|
+
try {
|
|
244
|
+
createGestureRecognizer({ swipeMinVelocity: -0.1 })
|
|
245
|
+
expect.fail('expected throw')
|
|
246
|
+
} catch (e) {
|
|
247
|
+
expect(isKLineChartError(e, 'INVALID_PARAM')).toBe(true)
|
|
248
|
+
}
|
|
249
|
+
})
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
// ---------------------------------------------------------------------------
|
|
253
|
+
// Dispose
|
|
254
|
+
// ---------------------------------------------------------------------------
|
|
255
|
+
|
|
256
|
+
describe('dispose', () => {
|
|
257
|
+
it('makes pointer handlers and cancel into no-ops', () => {
|
|
258
|
+
const g = createGestureRecognizer()
|
|
259
|
+
g.dispose()
|
|
260
|
+
const seen: GestureEvent[] = []
|
|
261
|
+
g.events.subscribe(() => {
|
|
262
|
+
const e = g.events.peek()
|
|
263
|
+
if (e !== null) seen.push(e)
|
|
264
|
+
})
|
|
265
|
+
g.onPointerDown(pt(1, 0, 0, 0))
|
|
266
|
+
g.onPointerMove(pt(1, 100, 0, 10))
|
|
267
|
+
g.onPointerUp(pt(1, 100, 0, 20))
|
|
268
|
+
expect(seen).toEqual([])
|
|
269
|
+
expect(g.state.peek()).toBe('idle')
|
|
270
|
+
})
|
|
271
|
+
})
|