@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,167 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { createPointAndFigure } from '../pointAndFigure'
|
|
3
|
+
import type { OHLCV } from '../types'
|
|
4
|
+
|
|
5
|
+
const bar = (i: number, o: number, h: number, l: number, c: number, v = 100): OHLCV => ({
|
|
6
|
+
timestamp: 1_700_000_000_000 + i * 60_000,
|
|
7
|
+
open: o,
|
|
8
|
+
high: h,
|
|
9
|
+
low: l,
|
|
10
|
+
close: c,
|
|
11
|
+
volume: v,
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
describe('pointAndFigure', () => {
|
|
15
|
+
it('simple uptrend produces a single X column (batch includes in-progress)', () => {
|
|
16
|
+
const pf = createPointAndFigure()
|
|
17
|
+
const out = pf.transform(
|
|
18
|
+
[
|
|
19
|
+
bar(0, 100, 100, 100, 100),
|
|
20
|
+
bar(1, 100, 110, 100, 110),
|
|
21
|
+
bar(2, 110, 120, 110, 120),
|
|
22
|
+
bar(3, 120, 130, 120, 130),
|
|
23
|
+
],
|
|
24
|
+
{ boxSize: 10, reversal: 3 },
|
|
25
|
+
)
|
|
26
|
+
expect(out).toHaveLength(1)
|
|
27
|
+
expect(out[0]!.meta?.direction).toBe('up')
|
|
28
|
+
expect(out[0]!.high).toBeGreaterThan(out[0]!.low)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('a 3-box reversal closes the X column and opens an O column', () => {
|
|
32
|
+
const pf = createPointAndFigure()
|
|
33
|
+
const out = pf.transform(
|
|
34
|
+
[
|
|
35
|
+
bar(0, 100, 100, 100, 100),
|
|
36
|
+
bar(1, 100, 130, 100, 130), // big X column up to 130
|
|
37
|
+
bar(2, 130, 130, 90, 90), // drops 40 (4 boxes), reversal of 3 met
|
|
38
|
+
],
|
|
39
|
+
{ boxSize: 10, reversal: 3 },
|
|
40
|
+
)
|
|
41
|
+
const directions = out.map((b) => b.meta?.direction)
|
|
42
|
+
expect(directions).toContain('up')
|
|
43
|
+
expect(directions).toContain('down')
|
|
44
|
+
// First (closed) column is the X.
|
|
45
|
+
expect(out[0]!.meta?.direction).toBe('up')
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it('a 2-box reversal stays in the same X column (no flip)', () => {
|
|
49
|
+
const pf = createPointAndFigure()
|
|
50
|
+
const out = pf.transform(
|
|
51
|
+
[
|
|
52
|
+
bar(0, 100, 100, 100, 100),
|
|
53
|
+
bar(1, 100, 130, 100, 130),
|
|
54
|
+
bar(2, 130, 130, 115, 115), // only 1.5 boxes down — below threshold
|
|
55
|
+
],
|
|
56
|
+
{ boxSize: 10, reversal: 3 },
|
|
57
|
+
)
|
|
58
|
+
// Only the in-progress X column should be present.
|
|
59
|
+
expect(out).toHaveLength(1)
|
|
60
|
+
expect(out[0]!.meta?.direction).toBe('up')
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
it('alternating chop emits multiple columns at the reversal threshold', () => {
|
|
64
|
+
const pf = createPointAndFigure()
|
|
65
|
+
const out = pf.transform(
|
|
66
|
+
[
|
|
67
|
+
bar(0, 100, 100, 100, 100),
|
|
68
|
+
bar(1, 100, 130, 100, 130), // X up to 130
|
|
69
|
+
bar(2, 130, 130, 90, 90), // O down (reverse, 4 boxes)
|
|
70
|
+
bar(3, 90, 130, 90, 130), // X back up (reverse from O, 4 boxes)
|
|
71
|
+
bar(4, 130, 130, 90, 90), // O down again
|
|
72
|
+
],
|
|
73
|
+
{ boxSize: 10, reversal: 3 },
|
|
74
|
+
)
|
|
75
|
+
const closed = out.filter((b) => b.sourceBarIndexEnd < 4)
|
|
76
|
+
// Expect at least 3 alternating-direction closed columns.
|
|
77
|
+
expect(closed.length).toBeGreaterThanOrEqual(3)
|
|
78
|
+
const dirs = closed.map((b) => b.meta?.direction)
|
|
79
|
+
// No two consecutive closed columns have the same direction.
|
|
80
|
+
for (let i = 1; i < dirs.length; i++) {
|
|
81
|
+
expect(dirs[i]).not.toBe(dirs[i - 1])
|
|
82
|
+
}
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
it('first bar seeds an X column with low/high snapped to box boundaries', () => {
|
|
86
|
+
const pf = createPointAndFigure()
|
|
87
|
+
const out = pf.transform([bar(0, 103, 117, 102, 115)], { boxSize: 5, reversal: 3 })
|
|
88
|
+
expect(out).toHaveLength(1)
|
|
89
|
+
// low 102 -> 100 (floor of 5), high 117 -> 115 (floor of 5).
|
|
90
|
+
expect(out[0]!.low).toBeCloseTo(100, 10)
|
|
91
|
+
expect(out[0]!.high).toBeCloseTo(115, 10)
|
|
92
|
+
expect(out[0]!.meta?.direction).toBe('up')
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
it('column open and close match the column endpoints', () => {
|
|
96
|
+
const pf = createPointAndFigure()
|
|
97
|
+
const out = pf.transform(
|
|
98
|
+
[bar(0, 100, 100, 100, 100), bar(1, 100, 130, 100, 130)],
|
|
99
|
+
{ boxSize: 10, reversal: 3 },
|
|
100
|
+
)
|
|
101
|
+
const col = out[0]!
|
|
102
|
+
// X column: open = start price, close = end price = high.
|
|
103
|
+
expect(col.open).toBeLessThanOrEqual(col.close)
|
|
104
|
+
expect(col.close).toBe(col.high)
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
it('reversal exactly at threshold triggers a flip (>=, not >)', () => {
|
|
108
|
+
const pf = createPointAndFigure()
|
|
109
|
+
const out = pf.transform(
|
|
110
|
+
[
|
|
111
|
+
bar(0, 100, 100, 100, 100),
|
|
112
|
+
bar(1, 100, 130, 100, 130),
|
|
113
|
+
bar(2, 130, 130, 100, 100), // exactly 3 boxes (30) down — at threshold
|
|
114
|
+
],
|
|
115
|
+
{ boxSize: 10, reversal: 3 },
|
|
116
|
+
)
|
|
117
|
+
const dirs = out.map((b) => b.meta?.direction)
|
|
118
|
+
expect(dirs).toContain('up')
|
|
119
|
+
expect(dirs).toContain('down')
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
it('empty input yields empty output', () => {
|
|
123
|
+
const pf = createPointAndFigure()
|
|
124
|
+
const out = pf.transform([], { boxSize: 10, reversal: 3 })
|
|
125
|
+
expect(out).toEqual([])
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
it('throws on invalid config', () => {
|
|
129
|
+
expect(() => createPointAndFigure().transform([], { boxSize: 0, reversal: 3 })).toThrow()
|
|
130
|
+
expect(() => createPointAndFigure().transform([], { boxSize: 10, reversal: 0 })).toThrow()
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
it('incremental closed columns match batch closed columns', () => {
|
|
134
|
+
const series: OHLCV[] = [
|
|
135
|
+
bar(0, 100, 100, 100, 100),
|
|
136
|
+
bar(1, 100, 130, 100, 130),
|
|
137
|
+
bar(2, 130, 130, 90, 90),
|
|
138
|
+
bar(3, 90, 130, 90, 130),
|
|
139
|
+
bar(4, 130, 130, 100, 100),
|
|
140
|
+
bar(5, 100, 140, 100, 140),
|
|
141
|
+
]
|
|
142
|
+
const batch = createPointAndFigure().transform(series, { boxSize: 10, reversal: 3 })
|
|
143
|
+
const inc = createPointAndFigure()
|
|
144
|
+
inc.transform([], { boxSize: 10, reversal: 3 })
|
|
145
|
+
const incremental: ReturnType<typeof inc.transform> = []
|
|
146
|
+
for (const b of series) {
|
|
147
|
+
for (const out of inc.appendBar!(b)) incremental.push(out)
|
|
148
|
+
}
|
|
149
|
+
// Batch may include a final in-progress column. Compare CLOSED prefix.
|
|
150
|
+
const batchClosed = batch.slice(0, incremental.length)
|
|
151
|
+
expect(incremental.length).toBe(batchClosed.length)
|
|
152
|
+
for (let i = 0; i < batchClosed.length; i++) {
|
|
153
|
+
expect(batchClosed[i]!.open).toBeCloseTo(incremental[i]!.open, 10)
|
|
154
|
+
expect(batchClosed[i]!.close).toBeCloseTo(incremental[i]!.close, 10)
|
|
155
|
+
expect(batchClosed[i]!.meta?.direction).toBe(incremental[i]!.meta?.direction)
|
|
156
|
+
}
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
it('reset() returns to a seed state', () => {
|
|
160
|
+
const pf = createPointAndFigure()
|
|
161
|
+
pf.transform([bar(0, 100, 130, 100, 130)], { boxSize: 10, reversal: 3 })
|
|
162
|
+
pf.reset!()
|
|
163
|
+
const out = pf.appendBar!(bar(1, 200, 215, 200, 215))
|
|
164
|
+
// No closed columns yet; in-progress is now an X anchored at 200/215.
|
|
165
|
+
expect(out).toEqual([])
|
|
166
|
+
})
|
|
167
|
+
})
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { createRangeBars } from '../rangeBars'
|
|
3
|
+
import type { OHLCV } from '../types'
|
|
4
|
+
|
|
5
|
+
const bar = (i: number, o: number, h: number, l: number, c: number, v = 100): OHLCV => ({
|
|
6
|
+
timestamp: 1_700_000_000_000 + i * 60_000,
|
|
7
|
+
open: o,
|
|
8
|
+
high: h,
|
|
9
|
+
low: l,
|
|
10
|
+
close: c,
|
|
11
|
+
volume: v,
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
describe('rangeBars', () => {
|
|
15
|
+
it('simple trending input produces range bars whose span = range', () => {
|
|
16
|
+
const r = createRangeBars()
|
|
17
|
+
const out = r.transform(
|
|
18
|
+
[
|
|
19
|
+
bar(0, 100, 102, 99, 101),
|
|
20
|
+
bar(1, 101, 105, 100, 104),
|
|
21
|
+
bar(2, 104, 110, 103, 109),
|
|
22
|
+
bar(3, 109, 115, 108, 114),
|
|
23
|
+
],
|
|
24
|
+
{ range: 5 },
|
|
25
|
+
)
|
|
26
|
+
// The closed bars must each have span === 5 (within fp tolerance).
|
|
27
|
+
const closedBars = out.slice(0, -1)
|
|
28
|
+
for (const b of closedBars) {
|
|
29
|
+
expect(b.high - b.low).toBeCloseTo(5, 8)
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('sideways input within range emits no closed bars', () => {
|
|
34
|
+
const r = createRangeBars()
|
|
35
|
+
const out = r.transform(
|
|
36
|
+
[bar(0, 100, 101, 99, 100), bar(1, 100, 102, 99, 101), bar(2, 101, 102, 99, 100)],
|
|
37
|
+
{ range: 10 },
|
|
38
|
+
)
|
|
39
|
+
// Only the in-progress bar should be present.
|
|
40
|
+
expect(out).toHaveLength(1)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
it('first bar establishes the first range', () => {
|
|
44
|
+
const r = createRangeBars()
|
|
45
|
+
const out = r.transform([bar(0, 100, 101, 99, 100)], { range: 10 })
|
|
46
|
+
expect(out).toHaveLength(1)
|
|
47
|
+
expect(out[0]!.open).toBe(100)
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
it('input bar exceeding range splits into multiple output bars', () => {
|
|
51
|
+
const r = createRangeBars()
|
|
52
|
+
// A wide input bar spanning 50 units with range 10 should split into ~5 bars.
|
|
53
|
+
const out = r.transform([bar(0, 100, 150, 100, 150)], { range: 10 })
|
|
54
|
+
const closed = out.filter((b) => Math.abs(b.high - b.low - 10) < 1e-6)
|
|
55
|
+
expect(closed.length).toBeGreaterThanOrEqual(4)
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
it('exact-range boundary triggers immediate close', () => {
|
|
59
|
+
const r = createRangeBars()
|
|
60
|
+
// Single bar with H - L == 10 exactly.
|
|
61
|
+
const out = r.transform([bar(0, 100, 110, 100, 110)], { range: 10 })
|
|
62
|
+
// At least one bar must have closed.
|
|
63
|
+
const closed = out.filter((_, i, arr) => i < arr.length - 1)
|
|
64
|
+
expect(closed.length).toBeGreaterThanOrEqual(1)
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
it('volume is aggregated across input bars within one range bar', () => {
|
|
68
|
+
const r = createRangeBars()
|
|
69
|
+
// Three sideways bars accumulate into one open range bar.
|
|
70
|
+
const out = r.transform(
|
|
71
|
+
[bar(0, 100, 101, 99, 100, 50), bar(1, 100, 102, 99, 101, 60), bar(2, 101, 102, 99, 100, 70)],
|
|
72
|
+
{ range: 10 },
|
|
73
|
+
)
|
|
74
|
+
// The only present bar (the open one) should hold the summed volume.
|
|
75
|
+
expect(out).toHaveLength(1)
|
|
76
|
+
expect(out[0]!.volume).toBe(50 + 60 + 70)
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
it('split input bar distributes volume proportionally (no spike on first)', () => {
|
|
80
|
+
const r = createRangeBars()
|
|
81
|
+
const out = r.transform([bar(0, 100, 150, 100, 150, 500)], { range: 10 })
|
|
82
|
+
const closed = out.slice(0, -1)
|
|
83
|
+
expect(closed.length).toBeGreaterThan(1)
|
|
84
|
+
// No single closed bar should hold all the volume.
|
|
85
|
+
for (const b of closed) {
|
|
86
|
+
expect(b.volume).toBeLessThan(500)
|
|
87
|
+
}
|
|
88
|
+
// The sum across closed + open should not exceed the input volume.
|
|
89
|
+
const total = out.reduce((s, b) => s + b.volume, 0)
|
|
90
|
+
expect(total).toBeLessThanOrEqual(500 + 1e-6)
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
it('empty input yields empty output', () => {
|
|
94
|
+
const r = createRangeBars()
|
|
95
|
+
const out = r.transform([], { range: 5 })
|
|
96
|
+
expect(out).toEqual([])
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
it('throws on invalid range', () => {
|
|
100
|
+
expect(() => createRangeBars().transform([], { range: 0 })).toThrow()
|
|
101
|
+
expect(() => createRangeBars().transform([], { range: -1 })).toThrow()
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
it('incremental closed bars match batch closed bars on a random series', () => {
|
|
105
|
+
let seed = 7
|
|
106
|
+
const rand = () => {
|
|
107
|
+
seed = (seed * 1103515245 + 12345) & 0x7fffffff
|
|
108
|
+
return seed / 0x7fffffff
|
|
109
|
+
}
|
|
110
|
+
const series: OHLCV[] = []
|
|
111
|
+
let price = 100
|
|
112
|
+
for (let i = 0; i < 30; i++) {
|
|
113
|
+
const drift = (rand() - 0.5) * 4
|
|
114
|
+
const close = price + drift
|
|
115
|
+
const high = Math.max(price, close) + rand() * 1.5
|
|
116
|
+
const low = Math.min(price, close) - rand() * 1.5
|
|
117
|
+
series.push(bar(i, price, high, low, close, Math.floor(rand() * 100)))
|
|
118
|
+
price = close
|
|
119
|
+
}
|
|
120
|
+
const batch = createRangeBars().transform(series, { range: 3 })
|
|
121
|
+
const inc = createRangeBars()
|
|
122
|
+
inc.transform([], { range: 3 })
|
|
123
|
+
const incremental: ReturnType<typeof inc.transform> = []
|
|
124
|
+
for (const b of series) {
|
|
125
|
+
for (const out of inc.appendBar!(b)) incremental.push(out)
|
|
126
|
+
}
|
|
127
|
+
// Batch includes the final in-progress bar. Compare closed prefix.
|
|
128
|
+
const batchClosed = batch.slice(0, incremental.length)
|
|
129
|
+
expect(incremental.length).toBe(batchClosed.length)
|
|
130
|
+
for (let i = 0; i < batchClosed.length; i++) {
|
|
131
|
+
expect(batchClosed[i]!.open).toBeCloseTo(incremental[i]!.open, 8)
|
|
132
|
+
expect(batchClosed[i]!.close).toBeCloseTo(incremental[i]!.close, 8)
|
|
133
|
+
// Span equals range within fp tolerance for every closed bar.
|
|
134
|
+
expect(Math.abs(incremental[i]!.high - incremental[i]!.low - 3)).toBeLessThan(1e-6)
|
|
135
|
+
}
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
it('reset() drops state so the next series starts clean', () => {
|
|
139
|
+
const r = createRangeBars()
|
|
140
|
+
r.transform([bar(0, 100, 110, 100, 110)], { range: 10 })
|
|
141
|
+
r.reset!()
|
|
142
|
+
const out = r.appendBar!(bar(1, 200, 201, 199, 200))
|
|
143
|
+
// First post-reset bar should not have closed anything (range not met).
|
|
144
|
+
expect(out).toEqual([])
|
|
145
|
+
})
|
|
146
|
+
})
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { createRenko } from '../renko'
|
|
3
|
+
import type { OHLCV } from '../types'
|
|
4
|
+
|
|
5
|
+
const bar = (i: number, o: number, h: number, l: number, c: number, v = 100): OHLCV => ({
|
|
6
|
+
timestamp: 1_700_000_000_000 + i * 60_000,
|
|
7
|
+
open: o,
|
|
8
|
+
high: h,
|
|
9
|
+
low: l,
|
|
10
|
+
close: c,
|
|
11
|
+
volume: v,
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
describe('renko', () => {
|
|
15
|
+
it('rising prices emit up-bricks', () => {
|
|
16
|
+
const r = createRenko()
|
|
17
|
+
// Anchor at close 100, then push close up 30 (3 bricks of 10).
|
|
18
|
+
const out = r.transform([bar(0, 100, 100, 100, 100), bar(1, 100, 130, 100, 130)], { brickSize: 10 })
|
|
19
|
+
expect(out).toHaveLength(3)
|
|
20
|
+
for (const b of out) {
|
|
21
|
+
expect(b.meta?.direction).toBe('up')
|
|
22
|
+
expect(b.close).toBeGreaterThan(b.open)
|
|
23
|
+
}
|
|
24
|
+
// Brick closes form a 10-unit ladder.
|
|
25
|
+
expect(out[0]!.close - out[0]!.open).toBeCloseTo(10, 10)
|
|
26
|
+
expect(out[2]!.close).toBeCloseTo(130, 10)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it('falling prices emit down-bricks', () => {
|
|
30
|
+
const r = createRenko()
|
|
31
|
+
const out = r.transform([bar(0, 100, 100, 100, 100), bar(1, 100, 100, 70, 70)], { brickSize: 10 })
|
|
32
|
+
expect(out).toHaveLength(3)
|
|
33
|
+
for (const b of out) {
|
|
34
|
+
expect(b.meta?.direction).toBe('down')
|
|
35
|
+
expect(b.close).toBeLessThan(b.open)
|
|
36
|
+
}
|
|
37
|
+
expect(out[2]!.close).toBeCloseTo(70, 10)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('sideways prices within brickSize emit no bricks', () => {
|
|
41
|
+
const r = createRenko()
|
|
42
|
+
const out = r.transform(
|
|
43
|
+
[
|
|
44
|
+
bar(0, 100, 100, 100, 100),
|
|
45
|
+
bar(1, 100, 105, 95, 103),
|
|
46
|
+
bar(2, 103, 106, 98, 102),
|
|
47
|
+
bar(3, 102, 109, 100, 108),
|
|
48
|
+
],
|
|
49
|
+
{ brickSize: 10 },
|
|
50
|
+
)
|
|
51
|
+
expect(out).toHaveLength(0)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it('reversal requires 2x brickSize after an up-brick', () => {
|
|
55
|
+
const r = createRenko()
|
|
56
|
+
// Anchor at 100, push up to 110 (one up-brick from 100->110).
|
|
57
|
+
// Then a 1x brickSize move down (to 100) should NOT reverse.
|
|
58
|
+
const out1 = r.transform(
|
|
59
|
+
[bar(0, 100, 100, 100, 100), bar(1, 100, 110, 100, 110), bar(2, 110, 110, 100, 100)],
|
|
60
|
+
{ brickSize: 10 },
|
|
61
|
+
)
|
|
62
|
+
// Only the original up-brick should be emitted.
|
|
63
|
+
expect(out1).toHaveLength(1)
|
|
64
|
+
expect(out1[0]!.meta?.direction).toBe('up')
|
|
65
|
+
|
|
66
|
+
// 2x brickSize move down DOES reverse (down to 90 = 110 - 20).
|
|
67
|
+
const r2 = createRenko()
|
|
68
|
+
const out2 = r2.transform(
|
|
69
|
+
[bar(0, 100, 100, 100, 100), bar(1, 100, 110, 100, 110), bar(2, 110, 110, 90, 90)],
|
|
70
|
+
{ brickSize: 10 },
|
|
71
|
+
)
|
|
72
|
+
expect(out2.length).toBeGreaterThanOrEqual(2)
|
|
73
|
+
expect(out2[0]!.meta?.direction).toBe('up')
|
|
74
|
+
expect(out2[1]!.meta?.direction).toBe('down')
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
it('ATR mode produces brick size from rolling ATR (no bricks until window fills)', () => {
|
|
78
|
+
const r = createRenko()
|
|
79
|
+
// ATR period 3 — no bricks until the third bar's TR fills the window.
|
|
80
|
+
const series: OHLCV[] = [
|
|
81
|
+
bar(0, 100, 102, 99, 101),
|
|
82
|
+
bar(1, 101, 103, 100, 102),
|
|
83
|
+
bar(2, 102, 104, 101, 103),
|
|
84
|
+
bar(3, 103, 120, 102, 119),
|
|
85
|
+
]
|
|
86
|
+
const out = r.transform(series, { useATR: { period: 3 } })
|
|
87
|
+
// After bar 3 the window has 4 TR values; brickSize is the rolling mean
|
|
88
|
+
// of the last 3. Should emit at least one up-brick from the +16 move.
|
|
89
|
+
expect(out.length).toBeGreaterThan(0)
|
|
90
|
+
for (const b of out) {
|
|
91
|
+
expect(b.meta?.direction).toBe('up')
|
|
92
|
+
expect(b.meta?.brickSize).toBeGreaterThan(0)
|
|
93
|
+
}
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
it('incremental mode matches batch mode on a random series', () => {
|
|
97
|
+
let seed = 99
|
|
98
|
+
const rand = () => {
|
|
99
|
+
seed = (seed * 1103515245 + 12345) & 0x7fffffff
|
|
100
|
+
return seed / 0x7fffffff
|
|
101
|
+
}
|
|
102
|
+
const series: OHLCV[] = []
|
|
103
|
+
let price = 100
|
|
104
|
+
for (let i = 0; i < 30; i++) {
|
|
105
|
+
const drift = (rand() - 0.5) * 6
|
|
106
|
+
const close = price + drift
|
|
107
|
+
const high = Math.max(price, close) + rand() * 2
|
|
108
|
+
const low = Math.min(price, close) - rand() * 2
|
|
109
|
+
series.push(bar(i, price, high, low, close, Math.floor(rand() * 100)))
|
|
110
|
+
price = close
|
|
111
|
+
}
|
|
112
|
+
const batch = createRenko().transform(series, { brickSize: 3 })
|
|
113
|
+
const inc = createRenko()
|
|
114
|
+
const incremental: ReturnType<typeof inc.transform> = []
|
|
115
|
+
// Prime config via transform on empty array (sets activeConfig)…
|
|
116
|
+
inc.transform([], { brickSize: 3 })
|
|
117
|
+
for (const b of series) {
|
|
118
|
+
for (const out of inc.appendBar!(b)) incremental.push(out)
|
|
119
|
+
}
|
|
120
|
+
expect(incremental.length).toBe(batch.length)
|
|
121
|
+
for (let i = 0; i < batch.length; i++) {
|
|
122
|
+
expect(batch[i]!.open).toBeCloseTo(incremental[i]!.open, 10)
|
|
123
|
+
expect(batch[i]!.close).toBeCloseTo(incremental[i]!.close, 10)
|
|
124
|
+
expect(batch[i]!.meta?.direction).toBe(incremental[i]!.meta?.direction)
|
|
125
|
+
}
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
it('large gap close emits multiple bricks from one input bar', () => {
|
|
129
|
+
const r = createRenko()
|
|
130
|
+
const out = r.transform([bar(0, 100, 100, 100, 100), bar(1, 100, 200, 100, 200)], { brickSize: 10 })
|
|
131
|
+
// 100 -> 200 across one bar should emit 10 up-bricks.
|
|
132
|
+
expect(out).toHaveLength(10)
|
|
133
|
+
// Only the first brick from that source bar carries its volume; the
|
|
134
|
+
// rest are zero (see file header comment).
|
|
135
|
+
expect(out[0]!.volume).toBe(100)
|
|
136
|
+
expect(out[1]!.volume).toBe(0)
|
|
137
|
+
expect(out[9]!.close).toBeCloseTo(200, 10)
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
it('empty input yields empty output', () => {
|
|
141
|
+
const r = createRenko()
|
|
142
|
+
const out = r.transform([], { brickSize: 5 })
|
|
143
|
+
expect(out).toEqual([])
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
it('throws on invalid config', () => {
|
|
147
|
+
expect(() => createRenko().transform([], { brickSize: 0 })).toThrow()
|
|
148
|
+
expect(() => createRenko().transform([], {})).toThrow()
|
|
149
|
+
expect(() => createRenko().transform([], { useATR: { period: 0 } })).toThrow()
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
it('reset() drops state so the next series starts fresh', () => {
|
|
153
|
+
const r = createRenko()
|
|
154
|
+
r.transform([bar(0, 100, 100, 100, 100), bar(1, 100, 150, 100, 150)], { brickSize: 10 })
|
|
155
|
+
r.reset!()
|
|
156
|
+
// After reset the next bar anchors the new series — no bricks yet.
|
|
157
|
+
const out = r.appendBar!(bar(2, 200, 200, 200, 200))
|
|
158
|
+
expect(out).toHaveLength(0)
|
|
159
|
+
})
|
|
160
|
+
})
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Heikin Ashi — "average bar" smoothing of an OHLCV series.
|
|
3
|
+
*
|
|
4
|
+
* Heikin Ashi (平均足) was popularised by Munehisa Homma; the modern formula
|
|
5
|
+
* is the one taught by Dan Valcu. It produces a one-to-one transform — each
|
|
6
|
+
* input bar yields exactly one output bar — but the values are smoothed so
|
|
7
|
+
* trends visually persist through noise.
|
|
8
|
+
*
|
|
9
|
+
* ## Formula
|
|
10
|
+
*
|
|
11
|
+
* HA_close[i] = (O[i] + H[i] + L[i] + C[i]) / 4
|
|
12
|
+
* HA_open[i] = (HA_open[i-1] + HA_close[i-1]) / 2 for i >= 1
|
|
13
|
+
* HA_open[0] = (O[0] + C[0]) / 2 (seed)
|
|
14
|
+
* HA_high[i] = max(H[i], HA_open[i], HA_close[i])
|
|
15
|
+
* HA_low[i] = min(L[i], HA_open[i], HA_close[i])
|
|
16
|
+
* HA_volume[i] = V[i] (unchanged)
|
|
17
|
+
*
|
|
18
|
+
* The seed for `HA_open[0]` is the standard convention used by all major
|
|
19
|
+
* charting platforms (TradingView, MetaTrader). An alternative seed of
|
|
20
|
+
* `O[0]` exists in some older books but produces a slightly different shape
|
|
21
|
+
* for the first bar; we follow the modern convention.
|
|
22
|
+
*
|
|
23
|
+
* ## Trade-offs
|
|
24
|
+
*
|
|
25
|
+
* - Volume is **not** smoothed. Smoothing volume distorts indicators that
|
|
26
|
+
* consume the derived series (OBV, VWAP, CMF), so we keep it raw. This
|
|
27
|
+
* matches TradingView's behaviour.
|
|
28
|
+
* - Output `timestamp` equals input `timestamp` — Heikin Ashi does not
|
|
29
|
+
* re-bucket time.
|
|
30
|
+
*
|
|
31
|
+
* ## Statefulness
|
|
32
|
+
*
|
|
33
|
+
* The transform carries `HA_open[i-1]` and `HA_close[i-1]` between calls so
|
|
34
|
+
* `appendBar` produces the same result as a batch `transform` over the same
|
|
35
|
+
* series. The `reset()` method clears that carry.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
import type { ChartTypeTransform, OHLCV, TransformedBar } from './types'
|
|
39
|
+
|
|
40
|
+
/** Heikin Ashi has no configuration. The empty type makes the contract explicit. */
|
|
41
|
+
export type HeikinAshiConfig = Record<string, never>
|
|
42
|
+
|
|
43
|
+
interface HAState {
|
|
44
|
+
/** Previous HA_open. */
|
|
45
|
+
prevOpen: number
|
|
46
|
+
/** Previous HA_close. */
|
|
47
|
+
prevClose: number
|
|
48
|
+
/** Index of the next input bar (i.e. count of bars consumed so far). */
|
|
49
|
+
nextIndex: number
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Build a Heikin Ashi transform. The returned object is stateful — `transform`
|
|
54
|
+
* resets state before running, `appendBar` mutates state, `reset` clears it.
|
|
55
|
+
*
|
|
56
|
+
* The factory pattern (rather than a singleton) matches the controller style
|
|
57
|
+
* elsewhere in this package — multiple panes can each hold their own
|
|
58
|
+
* independent transform without crossed state.
|
|
59
|
+
*/
|
|
60
|
+
export function createHeikinAshi(): ChartTypeTransform<HeikinAshiConfig> {
|
|
61
|
+
let state: HAState | null = null
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Compute one HA bar. `prev` is `null` for the very first bar in a series,
|
|
65
|
+
* which triggers the seed `HA_open = (O + C) / 2`.
|
|
66
|
+
*/
|
|
67
|
+
const computeBar = (
|
|
68
|
+
bar: OHLCV,
|
|
69
|
+
prev: { prevOpen: number; prevClose: number } | null,
|
|
70
|
+
sourceIndex: number,
|
|
71
|
+
): TransformedBar => {
|
|
72
|
+
const haClose = (bar.open + bar.high + bar.low + bar.close) / 4
|
|
73
|
+
const haOpen = prev === null ? (bar.open + bar.close) / 2 : (prev.prevOpen + prev.prevClose) / 2
|
|
74
|
+
const haHigh = Math.max(bar.high, haOpen, haClose)
|
|
75
|
+
const haLow = Math.min(bar.low, haOpen, haClose)
|
|
76
|
+
return {
|
|
77
|
+
timestamp: bar.timestamp,
|
|
78
|
+
open: haOpen,
|
|
79
|
+
high: haHigh,
|
|
80
|
+
low: haLow,
|
|
81
|
+
close: haClose,
|
|
82
|
+
volume: bar.volume,
|
|
83
|
+
sourceBarIndexStart: sourceIndex,
|
|
84
|
+
sourceBarIndexEnd: sourceIndex,
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
typeId: 'heikin-ashi',
|
|
90
|
+
|
|
91
|
+
transform(input: ReadonlyArray<OHLCV>): ReadonlyArray<TransformedBar> {
|
|
92
|
+
state = null
|
|
93
|
+
const out: TransformedBar[] = []
|
|
94
|
+
for (let i = 0; i < input.length; i++) {
|
|
95
|
+
const bar = input[i]
|
|
96
|
+
if (!bar) continue
|
|
97
|
+
const ha = computeBar(bar, state === null ? null : { prevOpen: state.prevOpen, prevClose: state.prevClose }, i)
|
|
98
|
+
out.push(ha)
|
|
99
|
+
state = { prevOpen: ha.open, prevClose: ha.close, nextIndex: i + 1 }
|
|
100
|
+
}
|
|
101
|
+
return out
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
appendBar(bar: OHLCV): ReadonlyArray<TransformedBar> {
|
|
105
|
+
const prev = state === null ? null : { prevOpen: state.prevOpen, prevClose: state.prevClose }
|
|
106
|
+
const nextIndex = state === null ? 0 : state.nextIndex
|
|
107
|
+
const ha = computeBar(bar, prev, nextIndex)
|
|
108
|
+
state = { prevOpen: ha.open, prevClose: ha.close, nextIndex: nextIndex + 1 }
|
|
109
|
+
return [ha]
|
|
110
|
+
},
|
|
111
|
+
|
|
112
|
+
reset(): void {
|
|
113
|
+
state = null
|
|
114
|
+
},
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type { OHLCV, TransformedBar, ChartTypeTransform } from './types'
|
|
2
|
+
export { createHeikinAshi } from './heikinAshi'
|
|
3
|
+
export { createRenko, type RenkoConfig } from './renko'
|
|
4
|
+
export { createPointAndFigure, type PointAndFigureConfig } from './pointAndFigure'
|
|
5
|
+
export { createRangeBars, type RangeBarsConfig } from './rangeBars'
|