@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.
Files changed (578) hide show
  1. package/dist/alerts/createAlertController.d.ts +30 -0
  2. package/dist/alerts/createAlertController.d.ts.map +1 -0
  3. package/dist/alerts/createAlertController.js +261 -0
  4. package/dist/alerts/createAlertController.js.map +1 -0
  5. package/dist/alerts/index.d.ts +5 -0
  6. package/dist/alerts/index.d.ts.map +1 -0
  7. package/dist/alerts/index.js +4 -0
  8. package/dist/alerts/index.js.map +1 -0
  9. package/dist/alerts/predicates.d.ts +28 -0
  10. package/dist/alerts/predicates.d.ts.map +1 -0
  11. package/dist/alerts/predicates.js +211 -0
  12. package/dist/alerts/predicates.js.map +1 -0
  13. package/dist/alerts/rollingVolume.d.ts +15 -0
  14. package/dist/alerts/rollingVolume.d.ts.map +1 -0
  15. package/dist/alerts/rollingVolume.js +42 -0
  16. package/dist/alerts/rollingVolume.js.map +1 -0
  17. package/dist/alerts/ruleSchema.d.ts +42 -0
  18. package/dist/alerts/ruleSchema.d.ts.map +1 -0
  19. package/dist/alerts/ruleSchema.js +240 -0
  20. package/dist/alerts/ruleSchema.js.map +1 -0
  21. package/dist/alerts/types.d.ts +169 -0
  22. package/dist/alerts/types.d.ts.map +1 -0
  23. package/dist/alerts/types.js +24 -0
  24. package/dist/alerts/types.js.map +1 -0
  25. package/dist/chartTypes/heikinAshi.d.ts +49 -0
  26. package/dist/chartTypes/heikinAshi.d.ts.map +1 -0
  27. package/dist/chartTypes/heikinAshi.js +94 -0
  28. package/dist/chartTypes/heikinAshi.js.map +1 -0
  29. package/dist/chartTypes/index.d.ts +6 -0
  30. package/dist/chartTypes/index.d.ts.map +1 -0
  31. package/dist/chartTypes/index.js +5 -0
  32. package/dist/chartTypes/index.js.map +1 -0
  33. package/dist/chartTypes/pointAndFigure.d.ts +83 -0
  34. package/dist/chartTypes/pointAndFigure.d.ts.map +1 -0
  35. package/dist/chartTypes/pointAndFigure.js +159 -0
  36. package/dist/chartTypes/pointAndFigure.js.map +1 -0
  37. package/dist/chartTypes/rangeBars.d.ts +61 -0
  38. package/dist/chartTypes/rangeBars.d.ts.map +1 -0
  39. package/dist/chartTypes/rangeBars.js +181 -0
  40. package/dist/chartTypes/rangeBars.js.map +1 -0
  41. package/dist/chartTypes/renko.d.ts +94 -0
  42. package/dist/chartTypes/renko.d.ts.map +1 -0
  43. package/dist/chartTypes/renko.js +207 -0
  44. package/dist/chartTypes/renko.js.map +1 -0
  45. package/dist/chartTypes/types.d.ts +97 -0
  46. package/dist/chartTypes/types.d.ts.map +1 -0
  47. package/dist/chartTypes/types.js +39 -0
  48. package/dist/chartTypes/types.js.map +1 -0
  49. package/dist/components/anchoredVwap/computeAnchoredVwap.d.ts +76 -0
  50. package/dist/components/anchoredVwap/computeAnchoredVwap.d.ts.map +1 -0
  51. package/dist/components/anchoredVwap/computeAnchoredVwap.js +155 -0
  52. package/dist/components/anchoredVwap/computeAnchoredVwap.js.map +1 -0
  53. package/dist/components/anchoredVwap/createAnchoredVwapController.d.ts +28 -0
  54. package/dist/components/anchoredVwap/createAnchoredVwapController.d.ts.map +1 -0
  55. package/dist/components/anchoredVwap/createAnchoredVwapController.js +282 -0
  56. package/dist/components/anchoredVwap/createAnchoredVwapController.js.map +1 -0
  57. package/dist/components/anchoredVwap/index.d.ts +11 -0
  58. package/dist/components/anchoredVwap/index.d.ts.map +1 -0
  59. package/dist/components/anchoredVwap/index.js +10 -0
  60. package/dist/components/anchoredVwap/index.js.map +1 -0
  61. package/dist/components/anchoredVwap/types.d.ts +171 -0
  62. package/dist/components/anchoredVwap/types.d.ts.map +1 -0
  63. package/dist/components/anchoredVwap/types.js +25 -0
  64. package/dist/components/anchoredVwap/types.js.map +1 -0
  65. package/dist/components/crosshairSync/createCrosshairSync.d.ts +94 -0
  66. package/dist/components/crosshairSync/createCrosshairSync.d.ts.map +1 -0
  67. package/dist/components/crosshairSync/createCrosshairSync.js +118 -0
  68. package/dist/components/crosshairSync/createCrosshairSync.js.map +1 -0
  69. package/dist/components/crosshairSync/index.d.ts +2 -0
  70. package/dist/components/crosshairSync/index.d.ts.map +1 -0
  71. package/dist/components/crosshairSync/index.js +2 -0
  72. package/dist/components/crosshairSync/index.js.map +1 -0
  73. package/dist/components/footprint/aggressor.d.ts +89 -0
  74. package/dist/components/footprint/aggressor.d.ts.map +1 -0
  75. package/dist/components/footprint/aggressor.js +106 -0
  76. package/dist/components/footprint/aggressor.js.map +1 -0
  77. package/dist/components/footprint/createFootprintController.d.ts +29 -0
  78. package/dist/components/footprint/createFootprintController.d.ts.map +1 -0
  79. package/dist/components/footprint/createFootprintController.js +264 -0
  80. package/dist/components/footprint/createFootprintController.js.map +1 -0
  81. package/dist/components/footprint/index.d.ts +7 -0
  82. package/dist/components/footprint/index.d.ts.map +1 -0
  83. package/dist/components/footprint/index.js +4 -0
  84. package/dist/components/footprint/index.js.map +1 -0
  85. package/dist/components/footprint/perBarStats.d.ts +63 -0
  86. package/dist/components/footprint/perBarStats.d.ts.map +1 -0
  87. package/dist/components/footprint/perBarStats.js +123 -0
  88. package/dist/components/footprint/perBarStats.js.map +1 -0
  89. package/dist/components/footprint/types.d.ts +197 -0
  90. package/dist/components/footprint/types.d.ts.map +1 -0
  91. package/dist/components/footprint/types.js +23 -0
  92. package/dist/components/footprint/types.js.map +1 -0
  93. package/dist/components/mtfOverlay/alignToBaseIndex.d.ts +45 -0
  94. package/dist/components/mtfOverlay/alignToBaseIndex.d.ts.map +1 -0
  95. package/dist/components/mtfOverlay/alignToBaseIndex.js +92 -0
  96. package/dist/components/mtfOverlay/alignToBaseIndex.js.map +1 -0
  97. package/dist/components/mtfOverlay/createMtfController.d.ts +7 -0
  98. package/dist/components/mtfOverlay/createMtfController.d.ts.map +1 -0
  99. package/dist/components/mtfOverlay/createMtfController.js +134 -0
  100. package/dist/components/mtfOverlay/createMtfController.js.map +1 -0
  101. package/dist/components/mtfOverlay/index.d.ts +19 -0
  102. package/dist/components/mtfOverlay/index.d.ts.map +1 -0
  103. package/dist/components/mtfOverlay/index.js +18 -0
  104. package/dist/components/mtfOverlay/index.js.map +1 -0
  105. package/dist/components/mtfOverlay/resampleBars.d.ts +37 -0
  106. package/dist/components/mtfOverlay/resampleBars.d.ts.map +1 -0
  107. package/dist/components/mtfOverlay/resampleBars.js +93 -0
  108. package/dist/components/mtfOverlay/resampleBars.js.map +1 -0
  109. package/dist/components/mtfOverlay/types.d.ts +132 -0
  110. package/dist/components/mtfOverlay/types.d.ts.map +1 -0
  111. package/dist/components/mtfOverlay/types.js +22 -0
  112. package/dist/components/mtfOverlay/types.js.map +1 -0
  113. package/dist/components/orderBookHeatmap/createHeatmapController.d.ts +21 -0
  114. package/dist/components/orderBookHeatmap/createHeatmapController.d.ts.map +1 -0
  115. package/dist/components/orderBookHeatmap/createHeatmapController.js +234 -0
  116. package/dist/components/orderBookHeatmap/createHeatmapController.js.map +1 -0
  117. package/dist/components/orderBookHeatmap/createOrderBookState.d.ts +18 -0
  118. package/dist/components/orderBookHeatmap/createOrderBookState.d.ts.map +1 -0
  119. package/dist/components/orderBookHeatmap/createOrderBookState.js +102 -0
  120. package/dist/components/orderBookHeatmap/createOrderBookState.js.map +1 -0
  121. package/dist/components/orderBookHeatmap/deltaArchive.d.ts +25 -0
  122. package/dist/components/orderBookHeatmap/deltaArchive.d.ts.map +1 -0
  123. package/dist/components/orderBookHeatmap/deltaArchive.js +106 -0
  124. package/dist/components/orderBookHeatmap/deltaArchive.js.map +1 -0
  125. package/dist/components/orderBookHeatmap/index.d.ts +13 -0
  126. package/dist/components/orderBookHeatmap/index.d.ts.map +1 -0
  127. package/dist/components/orderBookHeatmap/index.js +12 -0
  128. package/dist/components/orderBookHeatmap/index.js.map +1 -0
  129. package/dist/components/orderBookHeatmap/logColorScale.d.ts +20 -0
  130. package/dist/components/orderBookHeatmap/logColorScale.d.ts.map +1 -0
  131. package/dist/components/orderBookHeatmap/logColorScale.js +71 -0
  132. package/dist/components/orderBookHeatmap/logColorScale.js.map +1 -0
  133. package/dist/components/orderBookHeatmap/snapshotRing.d.ts +16 -0
  134. package/dist/components/orderBookHeatmap/snapshotRing.d.ts.map +1 -0
  135. package/dist/components/orderBookHeatmap/snapshotRing.js +61 -0
  136. package/dist/components/orderBookHeatmap/snapshotRing.js.map +1 -0
  137. package/dist/components/orderBookHeatmap/types.d.ts +128 -0
  138. package/dist/components/orderBookHeatmap/types.d.ts.map +1 -0
  139. package/dist/components/orderBookHeatmap/types.js +16 -0
  140. package/dist/components/orderBookHeatmap/types.js.map +1 -0
  141. package/dist/components/volumeProfile/binning.d.ts +54 -0
  142. package/dist/components/volumeProfile/binning.d.ts.map +1 -0
  143. package/dist/components/volumeProfile/binning.js +123 -0
  144. package/dist/components/volumeProfile/binning.js.map +1 -0
  145. package/dist/components/volumeProfile/createVolumeProfileController.d.ts +31 -0
  146. package/dist/components/volumeProfile/createVolumeProfileController.d.ts.map +1 -0
  147. package/dist/components/volumeProfile/createVolumeProfileController.js +179 -0
  148. package/dist/components/volumeProfile/createVolumeProfileController.js.map +1 -0
  149. package/dist/components/volumeProfile/index.d.ts +6 -0
  150. package/dist/components/volumeProfile/index.d.ts.map +1 -0
  151. package/dist/components/volumeProfile/index.js +5 -0
  152. package/dist/components/volumeProfile/index.js.map +1 -0
  153. package/dist/components/volumeProfile/poc.d.ts +35 -0
  154. package/dist/components/volumeProfile/poc.d.ts.map +1 -0
  155. package/dist/components/volumeProfile/poc.js +51 -0
  156. package/dist/components/volumeProfile/poc.js.map +1 -0
  157. package/dist/components/volumeProfile/types.d.ts +138 -0
  158. package/dist/components/volumeProfile/types.d.ts.map +1 -0
  159. package/dist/components/volumeProfile/types.js +19 -0
  160. package/dist/components/volumeProfile/types.js.map +1 -0
  161. package/dist/components/volumeProfile/valueArea.d.ts +58 -0
  162. package/dist/components/volumeProfile/valueArea.d.ts.map +1 -0
  163. package/dist/components/volumeProfile/valueArea.js +172 -0
  164. package/dist/components/volumeProfile/valueArea.js.map +1 -0
  165. package/dist/controllers/createChartController.d.ts.map +1 -1
  166. package/dist/controllers/createChartController.js +22 -11
  167. package/dist/controllers/createChartController.js.map +1 -1
  168. package/dist/controllers/types.d.ts +3 -1
  169. package/dist/controllers/types.d.ts.map +1 -1
  170. package/dist/data-fetchers/baostock.d.ts.map +1 -1
  171. package/dist/data-fetchers/baostock.js +2 -1
  172. package/dist/data-fetchers/baostock.js.map +1 -1
  173. package/dist/data-fetchers/dataBuffer.effects.d.ts.map +1 -1
  174. package/dist/data-fetchers/dataBuffer.effects.js +2 -1
  175. package/dist/data-fetchers/dataBuffer.effects.js.map +1 -1
  176. package/dist/data-fetchers/fetcherDefinitionRegistry.d.ts.map +1 -1
  177. package/dist/data-fetchers/fetcherDefinitionRegistry.js +2 -1
  178. package/dist/data-fetchers/fetcherDefinitionRegistry.js.map +1 -1
  179. package/dist/data-fetchers/gotdx.js +4 -3
  180. package/dist/data-fetchers/gotdx.js.map +1 -1
  181. package/dist/data-fetchers/router.d.ts.map +1 -1
  182. package/dist/data-fetchers/router.js +4 -3
  183. package/dist/data-fetchers/router.js.map +1 -1
  184. package/dist/data-fetchers/tradingview.js +3 -2
  185. package/dist/data-fetchers/tradingview.js.map +1 -1
  186. package/dist/engine/chart.d.ts +13 -0
  187. package/dist/engine/chart.d.ts.map +1 -1
  188. package/dist/engine/chart.js +109 -0
  189. package/dist/engine/chart.js.map +1 -1
  190. package/dist/engine/data/chartDataManager.d.ts +1 -0
  191. package/dist/engine/data/chartDataManager.d.ts.map +1 -1
  192. package/dist/engine/data/chartDataManager.js +27 -4
  193. package/dist/engine/data/chartDataManager.js.map +1 -1
  194. package/dist/engine/drawing/toolConfig.d.ts.map +1 -1
  195. package/dist/engine/drawing/toolConfig.js +2 -1
  196. package/dist/engine/drawing/toolConfig.js.map +1 -1
  197. package/dist/engine/indicators/chartIndicatorManager.d.ts.map +1 -1
  198. package/dist/engine/indicators/chartIndicatorManager.js +2 -1
  199. package/dist/engine/indicators/chartIndicatorManager.js.map +1 -1
  200. package/dist/engine/indicators/indicatorDefinitionRegistry.d.ts.map +1 -1
  201. package/dist/engine/indicators/indicatorDefinitionRegistry.js +2 -1
  202. package/dist/engine/indicators/indicatorDefinitionRegistry.js.map +1 -1
  203. package/dist/engine/indicators/indicatorMetadata.d.ts.map +1 -1
  204. package/dist/engine/indicators/indicatorMetadata.js +2 -1
  205. package/dist/engine/indicators/indicatorMetadata.js.map +1 -1
  206. package/dist/engine/indicators/indicatorRegistry.d.ts.map +1 -1
  207. package/dist/engine/indicators/indicatorRegistry.js +6 -5
  208. package/dist/engine/indicators/indicatorRegistry.js.map +1 -1
  209. package/dist/engine/indicators/registerBuiltins.d.ts.map +1 -1
  210. package/dist/engine/indicators/registerBuiltins.js +2 -1
  211. package/dist/engine/indicators/registerBuiltins.js.map +1 -1
  212. package/dist/engine/indicators/scheduler.d.ts +6 -0
  213. package/dist/engine/indicators/scheduler.d.ts.map +1 -1
  214. package/dist/engine/indicators/scheduler.js +12 -0
  215. package/dist/engine/indicators/scheduler.js.map +1 -1
  216. package/dist/engine/indicators/soa.d.ts.map +1 -1
  217. package/dist/engine/indicators/soa.js +2 -1
  218. package/dist/engine/indicators/soa.js.map +1 -1
  219. package/dist/engine/indicators/stateComposer.d.ts.map +1 -1
  220. package/dist/engine/indicators/stateComposer.js +2 -1
  221. package/dist/engine/indicators/stateComposer.js.map +1 -1
  222. package/dist/engine/subPaneManager.d.ts.map +1 -1
  223. package/dist/engine/subPaneManager.js +2 -1
  224. package/dist/engine/subPaneManager.js.map +1 -1
  225. package/dist/engine/utils/chartZoomController.d.ts +2 -0
  226. package/dist/engine/utils/chartZoomController.d.ts.map +1 -1
  227. package/dist/engine/utils/chartZoomController.js +5 -1
  228. package/dist/engine/utils/chartZoomController.js.map +1 -1
  229. package/dist/errors-help.d.ts +72 -0
  230. package/dist/errors-help.d.ts.map +1 -0
  231. package/dist/errors-help.js +149 -0
  232. package/dist/errors-help.js.map +1 -0
  233. package/dist/errors.d.ts +64 -0
  234. package/dist/errors.d.ts.map +1 -0
  235. package/dist/errors.js +61 -0
  236. package/dist/errors.js.map +1 -0
  237. package/dist/index.d.ts +18 -0
  238. package/dist/index.d.ts.map +1 -1
  239. package/dist/index.js +22 -0
  240. package/dist/index.js.map +1 -1
  241. package/dist/indicators/alma.d.ts +27 -0
  242. package/dist/indicators/alma.d.ts.map +1 -0
  243. package/dist/indicators/alma.js +36 -0
  244. package/dist/indicators/alma.js.map +1 -0
  245. package/dist/indicators/awesomeOscillator.d.ts +19 -0
  246. package/dist/indicators/awesomeOscillator.d.ts.map +1 -0
  247. package/dist/indicators/awesomeOscillator.js +36 -0
  248. package/dist/indicators/awesomeOscillator.js.map +1 -0
  249. package/dist/indicators/dpo.d.ts +17 -0
  250. package/dist/indicators/dpo.d.ts.map +1 -0
  251. package/dist/indicators/dpo.js +24 -0
  252. package/dist/indicators/dpo.js.map +1 -0
  253. package/dist/indicators/fisherTransform.d.ts +26 -0
  254. package/dist/indicators/fisherTransform.d.ts.map +1 -0
  255. package/dist/indicators/fisherTransform.js +44 -0
  256. package/dist/indicators/fisherTransform.js.map +1 -0
  257. package/dist/indicators/frama.d.ts +25 -0
  258. package/dist/indicators/frama.d.ts.map +1 -0
  259. package/dist/indicators/frama.js +61 -0
  260. package/dist/indicators/frama.js.map +1 -0
  261. package/dist/indicators/index.d.ts +24 -0
  262. package/dist/indicators/index.d.ts.map +1 -0
  263. package/dist/indicators/index.js +26 -0
  264. package/dist/indicators/index.js.map +1 -0
  265. package/dist/indicators/lsma.d.ts +21 -0
  266. package/dist/indicators/lsma.d.ts.map +1 -0
  267. package/dist/indicators/lsma.js +37 -0
  268. package/dist/indicators/lsma.js.map +1 -0
  269. package/dist/indicators/schaffTrendCycle.d.ts +24 -0
  270. package/dist/indicators/schaffTrendCycle.d.ts.map +1 -0
  271. package/dist/indicators/schaffTrendCycle.js +70 -0
  272. package/dist/indicators/schaffTrendCycle.js.map +1 -0
  273. package/dist/indicators/stochRSI.d.ts +24 -0
  274. package/dist/indicators/stochRSI.d.ts.map +1 -0
  275. package/dist/indicators/stochRSI.js +86 -0
  276. package/dist/indicators/stochRSI.js.map +1 -0
  277. package/dist/indicators/t3.d.ts +31 -0
  278. package/dist/indicators/t3.d.ts.map +1 -0
  279. package/dist/indicators/t3.js +63 -0
  280. package/dist/indicators/t3.js.map +1 -0
  281. package/dist/indicators/ultimateOscillator.d.ts +26 -0
  282. package/dist/indicators/ultimateOscillator.d.ts.map +1 -0
  283. package/dist/indicators/ultimateOscillator.js +59 -0
  284. package/dist/indicators/ultimateOscillator.js.map +1 -0
  285. package/dist/indicators/vidya.d.ts +24 -0
  286. package/dist/indicators/vidya.d.ts.map +1 -0
  287. package/dist/indicators/vidya.js +54 -0
  288. package/dist/indicators/vidya.js.map +1 -0
  289. package/dist/indicators/zlema.d.ts +16 -0
  290. package/dist/indicators/zlema.d.ts.map +1 -0
  291. package/dist/indicators/zlema.js +26 -0
  292. package/dist/indicators/zlema.js.map +1 -0
  293. package/dist/input/gesture.d.ts +125 -0
  294. package/dist/input/gesture.d.ts.map +1 -0
  295. package/dist/input/gesture.js +249 -0
  296. package/dist/input/gesture.js.map +1 -0
  297. package/dist/input/index.d.ts +9 -0
  298. package/dist/input/index.d.ts.map +1 -0
  299. package/dist/input/index.js +9 -0
  300. package/dist/input/index.js.map +1 -0
  301. package/dist/input/keyboard.d.ts +140 -0
  302. package/dist/input/keyboard.d.ts.map +1 -0
  303. package/dist/input/keyboard.js +260 -0
  304. package/dist/input/keyboard.js.map +1 -0
  305. package/dist/mcp/chartBridge.d.ts +2 -2
  306. package/dist/mcp/chartBridge.d.ts.map +1 -1
  307. package/dist/mcp/chartBridge.js +27 -21
  308. package/dist/mcp/chartBridge.js.map +1 -1
  309. package/dist/plugin/PluginHost.d.ts +0 -3
  310. package/dist/plugin/PluginHost.d.ts.map +1 -1
  311. package/dist/plugin/PluginHost.js +7 -3
  312. package/dist/plugin/PluginHost.js.map +1 -1
  313. package/dist/plugin/PluginRegistry.d.ts +0 -3
  314. package/dist/plugin/PluginRegistry.d.ts.map +1 -1
  315. package/dist/plugin/PluginRegistry.js +5 -1
  316. package/dist/plugin/PluginRegistry.js.map +1 -1
  317. package/dist/render/Renderer.d.ts +116 -0
  318. package/dist/render/Renderer.d.ts.map +1 -0
  319. package/dist/render/Renderer.js +31 -0
  320. package/dist/render/Renderer.js.map +1 -0
  321. package/dist/render/SurfaceBackend.d.ts +83 -0
  322. package/dist/render/SurfaceBackend.d.ts.map +1 -0
  323. package/dist/render/SurfaceBackend.js +27 -0
  324. package/dist/render/SurfaceBackend.js.map +1 -0
  325. package/dist/render/index.d.ts +12 -0
  326. package/dist/render/index.d.ts.map +1 -0
  327. package/dist/render/index.js +11 -0
  328. package/dist/render/index.js.map +1 -0
  329. package/dist/renderer-tier/detectRendererTier.d.ts +57 -0
  330. package/dist/renderer-tier/detectRendererTier.d.ts.map +1 -0
  331. package/dist/renderer-tier/detectRendererTier.js +143 -0
  332. package/dist/renderer-tier/detectRendererTier.js.map +1 -0
  333. package/dist/renderer-tier/index.d.ts +12 -0
  334. package/dist/renderer-tier/index.d.ts.map +1 -0
  335. package/dist/renderer-tier/index.js +12 -0
  336. package/dist/renderer-tier/index.js.map +1 -0
  337. package/dist/renderer-tier/selectBackend.d.ts +106 -0
  338. package/dist/renderer-tier/selectBackend.d.ts.map +1 -0
  339. package/dist/renderer-tier/selectBackend.js +113 -0
  340. package/dist/renderer-tier/selectBackend.js.map +1 -0
  341. package/dist/renderer-tier/types.d.ts +50 -0
  342. package/dist/renderer-tier/types.d.ts.map +1 -0
  343. package/dist/renderer-tier/types.js +24 -0
  344. package/dist/renderer-tier/types.js.map +1 -0
  345. package/dist/replay/createReplayController.d.ts +3 -0
  346. package/dist/replay/createReplayController.d.ts.map +1 -0
  347. package/dist/replay/createReplayController.js +251 -0
  348. package/dist/replay/createReplayController.js.map +1 -0
  349. package/dist/replay/index.d.ts +5 -0
  350. package/dist/replay/index.d.ts.map +1 -0
  351. package/dist/replay/index.js +3 -0
  352. package/dist/replay/index.js.map +1 -0
  353. package/dist/replay/timeline.d.ts +50 -0
  354. package/dist/replay/timeline.d.ts.map +1 -0
  355. package/dist/replay/timeline.js +104 -0
  356. package/dist/replay/timeline.js.map +1 -0
  357. package/dist/replay/types.d.ts +94 -0
  358. package/dist/replay/types.d.ts.map +1 -0
  359. package/dist/replay/types.js +21 -0
  360. package/dist/replay/types.js.map +1 -0
  361. package/dist/scale/anchoredZoom.d.ts +64 -0
  362. package/dist/scale/anchoredZoom.d.ts.map +1 -0
  363. package/dist/scale/anchoredZoom.js +67 -0
  364. package/dist/scale/anchoredZoom.js.map +1 -0
  365. package/dist/scale/createPriceScale.d.ts +49 -0
  366. package/dist/scale/createPriceScale.d.ts.map +1 -0
  367. package/dist/scale/createPriceScale.js +175 -0
  368. package/dist/scale/createPriceScale.js.map +1 -0
  369. package/dist/scale/createTimeScale.d.ts +27 -0
  370. package/dist/scale/createTimeScale.d.ts.map +1 -0
  371. package/dist/scale/createTimeScale.js +139 -0
  372. package/dist/scale/createTimeScale.js.map +1 -0
  373. package/dist/scale/index.d.ts +6 -0
  374. package/dist/scale/index.d.ts.map +1 -0
  375. package/dist/scale/index.js +5 -0
  376. package/dist/scale/index.js.map +1 -0
  377. package/dist/scale/originShift.d.ts +69 -0
  378. package/dist/scale/originShift.d.ts.map +1 -0
  379. package/dist/scale/originShift.js +41 -0
  380. package/dist/scale/originShift.js.map +1 -0
  381. package/dist/scale/types.d.ts +90 -0
  382. package/dist/scale/types.d.ts.map +1 -0
  383. package/dist/scale/types.js +17 -0
  384. package/dist/scale/types.js.map +1 -0
  385. package/dist/scene/createScene.d.ts +22 -0
  386. package/dist/scene/createScene.d.ts.map +1 -0
  387. package/dist/scene/createScene.js +114 -0
  388. package/dist/scene/createScene.js.map +1 -0
  389. package/dist/scene/index.d.ts +13 -0
  390. package/dist/scene/index.d.ts.map +1 -0
  391. package/dist/scene/index.js +11 -0
  392. package/dist/scene/index.js.map +1 -0
  393. package/dist/scene/layerRegistry.d.ts +83 -0
  394. package/dist/scene/layerRegistry.d.ts.map +1 -0
  395. package/dist/scene/layerRegistry.js +43 -0
  396. package/dist/scene/layerRegistry.js.map +1 -0
  397. package/dist/scene/types.d.ts +128 -0
  398. package/dist/scene/types.d.ts.map +1 -0
  399. package/dist/scene/types.js +21 -0
  400. package/dist/scene/types.js.map +1 -0
  401. package/dist/scheduler/createFrameBudget.d.ts +91 -0
  402. package/dist/scheduler/createFrameBudget.d.ts.map +1 -0
  403. package/dist/scheduler/createFrameBudget.js +232 -0
  404. package/dist/scheduler/createFrameBudget.js.map +1 -0
  405. package/dist/scheduler/index.d.ts +2 -0
  406. package/dist/scheduler/index.d.ts.map +1 -0
  407. package/dist/scheduler/index.js +2 -0
  408. package/dist/scheduler/index.js.map +1 -0
  409. package/dist/tokens/themeToCssVars.d.ts.map +1 -1
  410. package/dist/tokens/themeToCssVars.js +2 -28
  411. package/dist/tokens/themeToCssVars.js.map +1 -1
  412. package/dist/version.d.ts +1 -1
  413. package/dist/version.d.ts.map +1 -1
  414. package/dist/version.js +1 -1
  415. package/dist/version.js.map +1 -1
  416. package/package.json +1 -1
  417. package/src/__bench__/indicators.bench.ts +215 -0
  418. package/src/__bench__/orderBookHeatmap.bench.ts +68 -0
  419. package/src/__bench__/scale.bench.ts +80 -0
  420. package/src/__bench__/signal.bench.ts +41 -0
  421. package/src/__bench__/volumeProfile.bench.ts +66 -0
  422. package/src/__tests__/errors-help.test.ts +184 -0
  423. package/src/__tests__/errors.test.ts +187 -0
  424. package/src/alerts/__tests__/controller.test.ts +231 -0
  425. package/src/alerts/__tests__/predicates.test.ts +374 -0
  426. package/src/alerts/__tests__/ruleSchema.test.ts +180 -0
  427. package/src/alerts/createAlertController.ts +312 -0
  428. package/src/alerts/index.ts +18 -0
  429. package/src/alerts/predicates.ts +231 -0
  430. package/src/alerts/rollingVolume.ts +51 -0
  431. package/src/alerts/ruleSchema.ts +278 -0
  432. package/src/alerts/types.ts +177 -0
  433. package/src/chartTypes/__tests__/heikinAshi.test.ts +122 -0
  434. package/src/chartTypes/__tests__/pointAndFigure.test.ts +167 -0
  435. package/src/chartTypes/__tests__/rangeBars.test.ts +146 -0
  436. package/src/chartTypes/__tests__/renko.test.ts +160 -0
  437. package/src/chartTypes/heikinAshi.ts +116 -0
  438. package/src/chartTypes/index.ts +5 -0
  439. package/src/chartTypes/pointAndFigure.ts +278 -0
  440. package/src/chartTypes/rangeBars.ts +303 -0
  441. package/src/chartTypes/renko.ts +311 -0
  442. package/src/chartTypes/types.ts +99 -0
  443. package/src/components/anchoredVwap/__tests__/computeAnchoredVwap.test.ts +331 -0
  444. package/src/components/anchoredVwap/__tests__/controller.test.ts +430 -0
  445. package/src/components/anchoredVwap/computeAnchoredVwap.ts +174 -0
  446. package/src/components/anchoredVwap/createAnchoredVwapController.ts +358 -0
  447. package/src/components/anchoredVwap/index.ts +17 -0
  448. package/src/components/anchoredVwap/types.ts +187 -0
  449. package/src/components/crosshairSync/__tests__/crosshairSync.test.ts +261 -0
  450. package/src/components/crosshairSync/createCrosshairSync.ts +187 -0
  451. package/src/components/crosshairSync/index.ts +5 -0
  452. package/src/components/footprint/__tests__/aggressor.test.ts +127 -0
  453. package/src/components/footprint/__tests__/controller.test.ts +130 -0
  454. package/src/components/footprint/__tests__/perBarStats.test.ts +114 -0
  455. package/src/components/footprint/aggressor.ts +165 -0
  456. package/src/components/footprint/createFootprintController.ts +338 -0
  457. package/src/components/footprint/index.ts +21 -0
  458. package/src/components/footprint/perBarStats.ts +137 -0
  459. package/src/components/footprint/types.ts +232 -0
  460. package/src/components/mtfOverlay/__tests__/alignToBaseIndex.test.ts +103 -0
  461. package/src/components/mtfOverlay/__tests__/controller.test.ts +172 -0
  462. package/src/components/mtfOverlay/__tests__/resampleBars.test.ts +106 -0
  463. package/src/components/mtfOverlay/alignToBaseIndex.ts +108 -0
  464. package/src/components/mtfOverlay/createMtfController.ts +180 -0
  465. package/src/components/mtfOverlay/index.ts +26 -0
  466. package/src/components/mtfOverlay/resampleBars.ts +134 -0
  467. package/src/components/mtfOverlay/types.ts +148 -0
  468. package/src/components/orderBookHeatmap/__tests__/controller.test.ts +237 -0
  469. package/src/components/orderBookHeatmap/__tests__/deltaArchive.test.ts +88 -0
  470. package/src/components/orderBookHeatmap/__tests__/logColorScale.test.ts +69 -0
  471. package/src/components/orderBookHeatmap/__tests__/orderBookState.test.ts +113 -0
  472. package/src/components/orderBookHeatmap/__tests__/snapshotRing.test.ts +53 -0
  473. package/src/components/orderBookHeatmap/computeShader.wgsl.md +130 -0
  474. package/src/components/orderBookHeatmap/createHeatmapController.ts +273 -0
  475. package/src/components/orderBookHeatmap/createOrderBookState.ts +116 -0
  476. package/src/components/orderBookHeatmap/deltaArchive.ts +113 -0
  477. package/src/components/orderBookHeatmap/index.ts +25 -0
  478. package/src/components/orderBookHeatmap/logColorScale.ts +77 -0
  479. package/src/components/orderBookHeatmap/snapshotRing.ts +65 -0
  480. package/src/components/orderBookHeatmap/types.ts +168 -0
  481. package/src/components/volumeProfile/__tests__/binning.test.ts +133 -0
  482. package/src/components/volumeProfile/__tests__/poc.test.ts +44 -0
  483. package/src/components/volumeProfile/__tests__/valueArea.test.ts +177 -0
  484. package/src/components/volumeProfile/binning.ts +133 -0
  485. package/src/components/volumeProfile/createVolumeProfileController.ts +213 -0
  486. package/src/components/volumeProfile/index.ts +12 -0
  487. package/src/components/volumeProfile/poc.ts +53 -0
  488. package/src/components/volumeProfile/types.ts +148 -0
  489. package/src/components/volumeProfile/valueArea.ts +187 -0
  490. package/src/controllers/createChartController.ts +23 -10
  491. package/src/controllers/types.ts +5 -1
  492. package/src/data-fetchers/baostock.ts +2 -1
  493. package/src/data-fetchers/dataBuffer.effects.ts +3 -1
  494. package/src/data-fetchers/fetcherDefinitionRegistry.ts +2 -1
  495. package/src/data-fetchers/gotdx.ts +4 -3
  496. package/src/data-fetchers/router.ts +6 -3
  497. package/src/data-fetchers/tradingview.ts +3 -2
  498. package/src/engine/chart.ts +126 -3
  499. package/src/engine/data/chartDataManager.ts +26 -4
  500. package/src/engine/drawing/toolConfig.ts +2 -1
  501. package/src/engine/indicators/chartIndicatorManager.ts +2 -1
  502. package/src/engine/indicators/indicatorDefinitionRegistry.ts +2 -1
  503. package/src/engine/indicators/indicatorMetadata.ts +2 -1
  504. package/src/engine/indicators/indicatorRegistry.ts +6 -5
  505. package/src/engine/indicators/registerBuiltins.ts +2 -1
  506. package/src/engine/indicators/scheduler.ts +15 -0
  507. package/src/engine/indicators/soa.ts +2 -1
  508. package/src/engine/indicators/stateComposer.ts +2 -1
  509. package/src/engine/subPaneManager.ts +2 -1
  510. package/src/engine/utils/chartZoomController.ts +7 -1
  511. package/src/errors-help.ts +218 -0
  512. package/src/errors.ts +128 -0
  513. package/src/index.ts +37 -0
  514. package/src/indicators/__tests__/maFamily.test.ts +159 -0
  515. package/src/indicators/__tests__/oscillators.test.ts +150 -0
  516. package/src/indicators/alma.ts +61 -0
  517. package/src/indicators/awesomeOscillator.ts +54 -0
  518. package/src/indicators/dpo.ts +37 -0
  519. package/src/indicators/fisherTransform.ts +63 -0
  520. package/src/indicators/frama.ts +87 -0
  521. package/src/indicators/index.ts +39 -0
  522. package/src/indicators/lsma.ts +58 -0
  523. package/src/indicators/schaffTrendCycle.ts +92 -0
  524. package/src/indicators/stochRSI.ts +108 -0
  525. package/src/indicators/t3.ts +96 -0
  526. package/src/indicators/ultimateOscillator.ts +83 -0
  527. package/src/indicators/vidya.ts +80 -0
  528. package/src/indicators/zlema.ts +41 -0
  529. package/src/input/__tests__/gesture.test.ts +271 -0
  530. package/src/input/__tests__/keyboard.test.ts +317 -0
  531. package/src/input/gesture.ts +357 -0
  532. package/src/input/index.ts +26 -0
  533. package/src/input/keyboard.ts +373 -0
  534. package/src/mcp/chartBridge.ts +98 -72
  535. package/src/plugin/PluginHost.ts +4 -3
  536. package/src/plugin/PluginRegistry.ts +2 -1
  537. package/src/render/Renderer.ts +127 -0
  538. package/src/render/SurfaceBackend.ts +94 -0
  539. package/src/render/__tests__/contract.test.ts +176 -0
  540. package/src/render/index.ts +27 -0
  541. package/src/renderer-tier/__tests__/detectRendererTier.test.ts +180 -0
  542. package/src/renderer-tier/__tests__/selectBackend.test.ts +253 -0
  543. package/src/renderer-tier/detectRendererTier.ts +168 -0
  544. package/src/renderer-tier/index.ts +30 -0
  545. package/src/renderer-tier/selectBackend.ts +201 -0
  546. package/src/renderer-tier/types.ts +59 -0
  547. package/src/replay/__tests__/controller.test.ts +309 -0
  548. package/src/replay/__tests__/timeline.test.ts +99 -0
  549. package/src/replay/createReplayController.ts +302 -0
  550. package/src/replay/index.ts +15 -0
  551. package/src/replay/timeline.ts +106 -0
  552. package/src/replay/types.ts +107 -0
  553. package/src/scale/__tests__/anchoredZoom.test.ts +125 -0
  554. package/src/scale/__tests__/originShift.test.ts +97 -0
  555. package/src/scale/__tests__/priceScale.test.ts +219 -0
  556. package/src/scale/__tests__/timeScale.test.ts +119 -0
  557. package/src/scale/anchoredZoom.ts +104 -0
  558. package/src/scale/createPriceScale.ts +226 -0
  559. package/src/scale/createTimeScale.ts +150 -0
  560. package/src/scale/index.ts +9 -0
  561. package/src/scale/originShift.ts +111 -0
  562. package/src/scale/types.ts +100 -0
  563. package/src/scene/__tests__/layerRegistry.test.ts +207 -0
  564. package/src/scene/__tests__/scene.test.ts +411 -0
  565. package/src/scene/createScene.ts +117 -0
  566. package/src/scene/index.ts +29 -0
  567. package/src/scene/layerRegistry.ts +117 -0
  568. package/src/scene/types.ts +143 -0
  569. package/src/scheduler/__tests__/createFrameBudget.test.ts +315 -0
  570. package/src/scheduler/createFrameBudget.ts +316 -0
  571. package/src/scheduler/index.ts +7 -0
  572. package/src/tokens/themeToCssVars.ts +3 -1
  573. package/src/version.ts +1 -1
  574. package/dist/data-fetchers/gotdx/gotdx.d.ts +0 -7
  575. package/dist/data-fetchers/gotdx/gotdx.d.ts.map +0 -1
  576. package/dist/data-fetchers/gotdx/gotdx.js +0 -7
  577. package/dist/data-fetchers/gotdx/gotdx.js.map +0 -1
  578. package/src/data-fetchers/gotdx/gotdx.ts +0 -6
@@ -0,0 +1,430 @@
1
+ /**
2
+ * Tests for `createAnchoredVwapController` — multi-anchor reactive surface.
3
+ *
4
+ * The controller is held to three behavioural contracts:
5
+ * 1. Signals fire on every structural change (add, remove, update,
6
+ * setBars, appendBar).
7
+ * 2. The incremental `appendBar` is bit-for-bit equivalent (to
8
+ * floating-point precision) to a fresh `computeAnchoredVwap` over
9
+ * the same bars. The MAX_INCREMENTAL_DELTA assertion below is the
10
+ * reported delta in the summary.
11
+ * 3. `dispose` makes every mutator a silent no-op.
12
+ */
13
+
14
+ import { describe, it, expect } from 'vitest'
15
+
16
+ import { createAnchoredVwapController } from '../createAnchoredVwapController'
17
+ import { computeAnchoredVwap } from '../computeAnchoredVwap'
18
+ import type { AnchorDefinition, AVWAPBar } from '../types'
19
+
20
+ // ---------------------------------------------------------------------------
21
+ // Fixture helpers
22
+ // ---------------------------------------------------------------------------
23
+
24
+ function bar(
25
+ high: number,
26
+ low: number,
27
+ close: number,
28
+ volume: number,
29
+ ): AVWAPBar {
30
+ return { high, low, close, volume }
31
+ }
32
+
33
+ /** Realistic-ish trending series with mixed volume for the equivalence test. */
34
+ function makeSeries(n: number, seed = 1): AVWAPBar[] {
35
+ const out: AVWAPBar[] = []
36
+ let price = 100
37
+ // Tiny deterministic PRNG — keeps the fixture reproducible without
38
+ // a dependency.
39
+ let s = seed
40
+ const rand = (): number => {
41
+ s = (s * 9301 + 49297) % 233280
42
+ return s / 233280
43
+ }
44
+ for (let i = 0; i < n; i++) {
45
+ const drift = (rand() - 0.5) * 2
46
+ price = Math.max(1, price + drift)
47
+ const high = price + rand() * 1.5
48
+ const low = price - rand() * 1.5
49
+ const close = low + rand() * (high - low)
50
+ const volume = 100 + Math.floor(rand() * 10_000)
51
+ out.push(bar(high, low, close, volume))
52
+ }
53
+ return out
54
+ }
55
+
56
+ function defaultAnchor(
57
+ id: string,
58
+ barIndex: number,
59
+ includeBands = true,
60
+ ): AnchorDefinition {
61
+ return { id, label: id, barIndex, includeBands }
62
+ }
63
+
64
+ // ---------------------------------------------------------------------------
65
+ // addAnchor / signal contract
66
+ // ---------------------------------------------------------------------------
67
+
68
+ describe('createAnchoredVwapController — addAnchor + signal', () => {
69
+ it('addAnchor returns the supplied id and fires the anchors signal', () => {
70
+ const bars = makeSeries(10)
71
+ const c = createAnchoredVwapController({ initialBars: bars })
72
+
73
+ // Subscribe BEFORE calling addAnchor — we want to confirm the
74
+ // notification happens as a result of the mutation.
75
+ let notifications = 0
76
+ const unsub = c.anchors.subscribe(() => {
77
+ notifications += 1
78
+ })
79
+
80
+ const returnedId = c.addAnchor(defaultAnchor('a1', 2))
81
+ expect(returnedId).toBe('a1')
82
+
83
+ const state = c.anchors.peek()
84
+ expect(state).toHaveLength(1)
85
+ expect(state[0]!.definition.id).toBe('a1')
86
+ // The series should span bars 2..9 inclusive.
87
+ expect(state[0]!.series).toHaveLength(8)
88
+ expect(state[0]!.series[0]!.barIndex).toBe(2)
89
+ expect(state[0]!.series[7]!.barIndex).toBe(9)
90
+
91
+ expect(notifications).toBeGreaterThanOrEqual(1)
92
+
93
+ unsub()
94
+ c.dispose()
95
+ })
96
+
97
+ it('addAnchor with a duplicate id REPLACES the existing anchor', () => {
98
+ // We document this choice in the test name. The brief allows
99
+ // either reject-or-replace; we picked replace because UIs that
100
+ // drag an anchor onto an existing one expect in-place update.
101
+ const bars = makeSeries(10)
102
+ const c = createAnchoredVwapController({ initialBars: bars })
103
+
104
+ c.addAnchor(defaultAnchor('a1', 2))
105
+ const firstSeriesLen = c.anchors.peek()[0]!.series.length
106
+
107
+ // Same id, different bar index → must replace, not insert a
108
+ // second entry.
109
+ c.addAnchor(defaultAnchor('a1', 5))
110
+ const after = c.anchors.peek()
111
+ expect(after).toHaveLength(1)
112
+ expect(after[0]!.definition.barIndex).toBe(5)
113
+ // The new series is shorter because it starts later.
114
+ expect(after[0]!.series.length).toBeLessThan(firstSeriesLen)
115
+ expect(after[0]!.series[0]!.barIndex).toBe(5)
116
+
117
+ c.dispose()
118
+ })
119
+ })
120
+
121
+ // ---------------------------------------------------------------------------
122
+ // removeAnchor
123
+ // ---------------------------------------------------------------------------
124
+
125
+ describe('createAnchoredVwapController — removeAnchor', () => {
126
+ it('removeAnchor returns false for an unknown id and does not emit', () => {
127
+ const bars = makeSeries(10)
128
+ const c = createAnchoredVwapController({ initialBars: bars })
129
+ c.addAnchor(defaultAnchor('a1', 2))
130
+
131
+ let notifications = 0
132
+ const unsub = c.anchors.subscribe(() => {
133
+ notifications += 1
134
+ })
135
+
136
+ expect(c.removeAnchor('nope')).toBe(false)
137
+ // No mutation happened → no notification.
138
+ expect(notifications).toBe(0)
139
+ // Existing anchor untouched.
140
+ expect(c.anchors.peek()).toHaveLength(1)
141
+
142
+ unsub()
143
+ c.dispose()
144
+ })
145
+
146
+ it('removeAnchor returns true for a known id and drops it from the signal', () => {
147
+ const bars = makeSeries(10)
148
+ const c = createAnchoredVwapController({ initialBars: bars })
149
+ c.addAnchor(defaultAnchor('a1', 2))
150
+ c.addAnchor(defaultAnchor('a2', 5))
151
+ expect(c.anchors.peek()).toHaveLength(2)
152
+
153
+ expect(c.removeAnchor('a1')).toBe(true)
154
+ const after = c.anchors.peek()
155
+ expect(after).toHaveLength(1)
156
+ expect(after[0]!.definition.id).toBe('a2')
157
+
158
+ c.dispose()
159
+ })
160
+ })
161
+
162
+ // ---------------------------------------------------------------------------
163
+ // updateAnchor
164
+ // ---------------------------------------------------------------------------
165
+
166
+ describe('createAnchoredVwapController — updateAnchor', () => {
167
+ it('moving an anchor barIndex recomputes the series', () => {
168
+ const bars = makeSeries(20)
169
+ const c = createAnchoredVwapController({ initialBars: bars })
170
+ c.addAnchor(defaultAnchor('a1', 3))
171
+
172
+ const before = c.anchors.peek()[0]!.series
173
+ const beforeLen = before.length
174
+ const beforeFirstVwap = before[0]!.vwap
175
+
176
+ expect(c.updateAnchor('a1', { barIndex: 10 })).toBe(true)
177
+ const after = c.anchors.peek()[0]!
178
+ // Series shrunk because the anchor moved forward.
179
+ expect(after.series).toHaveLength(beforeLen - 7)
180
+ expect(after.series[0]!.barIndex).toBe(10)
181
+ // The first vwap differs because it now reflects a different
182
+ // typical price.
183
+ expect(after.series[0]!.vwap).not.toBe(beforeFirstVwap)
184
+ expect(after.definition.barIndex).toBe(10)
185
+
186
+ c.dispose()
187
+ })
188
+
189
+ it('updateAnchor on an unknown id returns false', () => {
190
+ const c = createAnchoredVwapController({ initialBars: makeSeries(5) })
191
+ expect(c.updateAnchor('ghost', { label: 'hi' })).toBe(false)
192
+ c.dispose()
193
+ })
194
+
195
+ it('updateAnchor label-only does not change the math', () => {
196
+ const c = createAnchoredVwapController({ initialBars: makeSeries(10) })
197
+ c.addAnchor(defaultAnchor('a1', 2))
198
+ const before = c.anchors.peek()[0]!.series
199
+ c.updateAnchor('a1', { label: 'new label' })
200
+ const after = c.anchors.peek()[0]!
201
+ expect(after.definition.label).toBe('new label')
202
+ // Series is structurally identical (same length, same vwap values).
203
+ expect(after.series).toHaveLength(before.length)
204
+ for (let i = 0; i < before.length; i++) {
205
+ expect(after.series[i]!.vwap).toBe(before[i]!.vwap)
206
+ }
207
+ c.dispose()
208
+ })
209
+ })
210
+
211
+ // ---------------------------------------------------------------------------
212
+ // setBars
213
+ // ---------------------------------------------------------------------------
214
+
215
+ describe('createAnchoredVwapController — setBars', () => {
216
+ it('setBars rebuilds every anchor series', () => {
217
+ const c = createAnchoredVwapController({ initialBars: makeSeries(10) })
218
+ c.addAnchor(defaultAnchor('a1', 2))
219
+ c.addAnchor(defaultAnchor('a2', 5))
220
+ const before = c.anchors.peek().map((a) => a.series.length)
221
+
222
+ // Larger bar set → both series should grow.
223
+ c.setBars(makeSeries(30, 99))
224
+ const after = c.anchors.peek().map((a) => a.series.length)
225
+ // a1 was anchored at 2 → previously 8 points, now 28.
226
+ expect(after[0]).toBe(28)
227
+ // a2 was anchored at 5 → previously 5 points, now 25.
228
+ expect(after[1]).toBe(25)
229
+ // Both grew.
230
+ expect(after[0]).toBeGreaterThan(before[0]!)
231
+ expect(after[1]).toBeGreaterThan(before[1]!)
232
+ c.dispose()
233
+ })
234
+ })
235
+
236
+ // ---------------------------------------------------------------------------
237
+ // appendBar — the perf optimisation
238
+ // ---------------------------------------------------------------------------
239
+
240
+ describe('createAnchoredVwapController — appendBar', () => {
241
+ it('extends every active anchor series by exactly one point', () => {
242
+ const c = createAnchoredVwapController({ initialBars: makeSeries(5) })
243
+ c.addAnchor(defaultAnchor('a1', 1))
244
+ c.addAnchor(defaultAnchor('a2', 3))
245
+ const before = c.anchors.peek().map((a) => a.series.length)
246
+
247
+ c.appendBar(bar(110, 108, 109, 500))
248
+
249
+ const after = c.anchors.peek()
250
+ for (let i = 0; i < after.length; i++) {
251
+ expect(after[i]!.series.length).toBe(before[i]! + 1)
252
+ const last = after[i]!.series[after[i]!.series.length - 1]!
253
+ // New point references the just-appended bar.
254
+ expect(last.barIndex).toBe(5)
255
+ }
256
+ c.dispose()
257
+ })
258
+
259
+ it('appendBar incrementally matches a full computeAnchoredVwap recompute', () => {
260
+ // The headline performance contract: walking via N appendBar
261
+ // calls must produce the same series as a single
262
+ // computeAnchoredVwap over the final bars. We pin the max delta
263
+ // here at 1e-9 (we measure 0 in practice — the operands are
264
+ // added in the same order) so a regression to a different
265
+ // accumulation order would fail loudly.
266
+ const initial = makeSeries(20)
267
+ const tail = makeSeries(30, 42)
268
+ const all = [...initial, ...tail]
269
+
270
+ const c = createAnchoredVwapController({ initialBars: initial })
271
+ c.addAnchor(defaultAnchor('a-bands', 5, true))
272
+ c.addAnchor(defaultAnchor('a-no-bands', 12, false))
273
+
274
+ for (const b of tail) c.appendBar(b)
275
+
276
+ const incrementalAnchors = c.anchors.peek()
277
+ const referenceBands = computeAnchoredVwap(all, 5, true)
278
+ const referenceNoBands = computeAnchoredVwap(all, 12, false)
279
+
280
+ const compare = (
281
+ label: string,
282
+ inc: ReadonlyArray<{
283
+ vwap: number
284
+ upper1: number
285
+ lower1: number
286
+ upper2: number
287
+ lower2: number
288
+ cumulativeVolume: number
289
+ barIndex: number
290
+ }>,
291
+ ref: ReadonlyArray<{
292
+ vwap: number
293
+ upper1: number
294
+ lower1: number
295
+ upper2: number
296
+ lower2: number
297
+ cumulativeVolume: number
298
+ barIndex: number
299
+ }>,
300
+ ): number => {
301
+ expect(inc.length, `${label} length`).toBe(ref.length)
302
+ let maxDelta = 0
303
+ for (let i = 0; i < inc.length; i++) {
304
+ const a = inc[i]!
305
+ const b = ref[i]!
306
+ expect(a.barIndex).toBe(b.barIndex)
307
+ const fields: Array<keyof typeof a> = [
308
+ 'vwap',
309
+ 'upper1',
310
+ 'lower1',
311
+ 'upper2',
312
+ 'lower2',
313
+ 'cumulativeVolume',
314
+ ]
315
+ for (const f of fields) {
316
+ const av = a[f]
317
+ const bv = b[f]
318
+ if (Number.isNaN(av) && Number.isNaN(bv)) continue
319
+ const d = Math.abs((av as number) - (bv as number))
320
+ if (d > maxDelta) maxDelta = d
321
+ }
322
+ }
323
+ return maxDelta
324
+ }
325
+
326
+ const deltaBands = compare(
327
+ 'bands',
328
+ incrementalAnchors[0]!.series,
329
+ referenceBands,
330
+ )
331
+ const deltaNoBands = compare(
332
+ 'no-bands',
333
+ incrementalAnchors[1]!.series,
334
+ referenceNoBands,
335
+ )
336
+ const maxDelta = Math.max(deltaBands, deltaNoBands)
337
+
338
+ // Hard limit: 1e-9. Empirically we see exact 0 because the
339
+ // arithmetic is identical between the two paths — same operands
340
+ // added in the same order. The 1e-9 limit gives a tolerance to
341
+ // a future refactor that reorders summation, while still
342
+ // catching a meaningful divergence.
343
+ expect(maxDelta).toBeLessThan(1e-9)
344
+ // A stricter, observation-pinning assertion: today we see EXACT
345
+ // bit-for-bit equality. Keeping this assertion as documentation
346
+ // of the current invariant; a future refactor that reorders
347
+ // summation should consciously decide to relax it.
348
+ expect(maxDelta).toBe(0)
349
+
350
+ c.dispose()
351
+ })
352
+
353
+ it('appendBar emits a notification per call', () => {
354
+ const c = createAnchoredVwapController({ initialBars: makeSeries(5) })
355
+ c.addAnchor(defaultAnchor('a1', 0))
356
+ let notifications = 0
357
+ const unsub = c.anchors.subscribe(() => {
358
+ notifications += 1
359
+ })
360
+ c.appendBar(bar(110, 108, 109, 500))
361
+ c.appendBar(bar(111, 109, 110, 500))
362
+ c.appendBar(bar(112, 110, 111, 500))
363
+ expect(notifications).toBe(3)
364
+ unsub()
365
+ c.dispose()
366
+ })
367
+ })
368
+
369
+ // ---------------------------------------------------------------------------
370
+ // Independence of multiple anchors
371
+ // ---------------------------------------------------------------------------
372
+
373
+ describe('createAnchoredVwapController — multiple anchors', () => {
374
+ it('two anchors at different positions produce independent series', () => {
375
+ const bars = makeSeries(15)
376
+ const c = createAnchoredVwapController({ initialBars: bars })
377
+ c.addAnchor(defaultAnchor('early', 2))
378
+ c.addAnchor(defaultAnchor('late', 10))
379
+
380
+ const list = c.anchors.peek()
381
+ expect(list).toHaveLength(2)
382
+ // Early anchor covers more bars.
383
+ expect(list[0]!.series.length).toBeGreaterThan(
384
+ list[1]!.series.length,
385
+ )
386
+ // First bar index of each series matches its anchor.
387
+ expect(list[0]!.series[0]!.barIndex).toBe(2)
388
+ expect(list[1]!.series[0]!.barIndex).toBe(10)
389
+ // Removing one does not affect the other.
390
+ c.removeAnchor('early')
391
+ const after = c.anchors.peek()
392
+ expect(after).toHaveLength(1)
393
+ expect(after[0]!.definition.id).toBe('late')
394
+ c.dispose()
395
+ })
396
+ })
397
+
398
+ // ---------------------------------------------------------------------------
399
+ // Dispose
400
+ // ---------------------------------------------------------------------------
401
+
402
+ describe('createAnchoredVwapController — dispose', () => {
403
+ it('dispose silences subsequent mutators', () => {
404
+ const c = createAnchoredVwapController({ initialBars: makeSeries(5) })
405
+ c.addAnchor(defaultAnchor('a1', 0))
406
+
407
+ let notifications = 0
408
+ const unsub = c.anchors.subscribe(() => {
409
+ notifications += 1
410
+ })
411
+
412
+ c.dispose()
413
+ // dispose is idempotent.
414
+ c.dispose()
415
+
416
+ // Every mutator becomes a no-op with the documented fallback.
417
+ expect(c.addAnchor(defaultAnchor('a2', 1))).toBeNull()
418
+ expect(c.removeAnchor('a1')).toBe(false)
419
+ expect(c.updateAnchor('a1', { label: 'no' })).toBe(false)
420
+ c.appendBar(bar(110, 108, 109, 500))
421
+ c.setBars(makeSeries(8))
422
+
423
+ expect(notifications).toBe(0)
424
+ // Underlying state was not modified by any of those calls.
425
+ expect(c.anchors.peek()).toHaveLength(1)
426
+ expect(c.anchors.peek()[0]!.definition.id).toBe('a1')
427
+
428
+ unsub()
429
+ })
430
+ })
@@ -0,0 +1,174 @@
1
+ /**
2
+ * Pure math: anchored VWAP + volume-weighted standard-deviation bands.
3
+ *
4
+ * Used by `createAnchoredVwapController` for the from-scratch path
5
+ * (`setBars`, `addAnchor`, `updateAnchor` when `barIndex` changes). The
6
+ * controller's incremental `appendBar` reuses the same formulas via
7
+ * running sums; the controller's tests pin equivalence between the two
8
+ * paths.
9
+ *
10
+ * Math summary (formal derivation in `docs/ROADMAP.md` §3):
11
+ *
12
+ * typicalPrice(j) = (H[j] + L[j] + C[j]) / 3
13
+ * vwp(j) = typicalPrice(j) * V[j]
14
+ * sumVwp(i) = Σ_{j=a..i} vwp(j)
15
+ * sumVol(i) = Σ_{j=a..i} V[j]
16
+ * AVWAP(i) = sumVwp(i) / sumVol(i) (when sumVol > 0)
17
+ *
18
+ * ─── important subtlety ─────────────────────────────────────────────────
19
+ * The standard-deviation bands MUST use the **prevailing** AVWAP(j) at
20
+ * each bar j ∈ [a..i], NOT the final AVWAP(i). Naive implementations that
21
+ * reuse the final mean understate the deviation early in the anchor and
22
+ * overstate it late — the bands wind up visibly off-centre on long
23
+ * anchors. The dedicated test
24
+ * `computeAnchoredVwap.test.ts → "bands use prevailing AVWAP at j"` pins
25
+ * this and would catch a regression to the wrong formula.
26
+ *
27
+ * sqDev(j) = (typicalPrice(j) - AVWAP(j))^2 * V[j]
28
+ * sumSqDev(i) = Σ_{j=a..i} sqDev(j)
29
+ * variance(i) = sumSqDev(i) / sumVol(i)
30
+ * stdDev(i) = sqrt(variance(i))
31
+ * upper1(i) = AVWAP(i) + stdDev(i)
32
+ * lower1(i) = AVWAP(i) - stdDev(i)
33
+ * upper2(i) = AVWAP(i) + 2 * stdDev(i)
34
+ * lower2(i) = AVWAP(i) - 2 * stdDev(i)
35
+ *
36
+ * Zero-volume handling:
37
+ * - A bar with `volume === 0` contributes 0 to numerator, 0 to
38
+ * denominator, and 0 to the squared-deviation sum. The cumulative
39
+ * volume is unchanged.
40
+ * - If the cumulative volume is still > 0 at this bar (i.e. there was a
41
+ * prior non-zero bar) the AVWAP and bands **carry forward** the prior
42
+ * values — they are still mathematically well-defined.
43
+ * - If the cumulative volume is 0 (i.e. the anchor bar itself has
44
+ * volume 0 and every subsequent bar so far has volume 0 too), the
45
+ * point's `vwap` and band fields are `NaN`. The series still has an
46
+ * entry for the bar — `barIndex` and `cumulativeVolume` are filled in.
47
+ */
48
+
49
+ import type { AVWAPBar, AVWAPPoint } from './types'
50
+ import { KLineChartError } from '../../errors'
51
+
52
+ /**
53
+ * Compute the Anchored VWAP series for `bars`, anchored at
54
+ * `anchorIndex` (inclusive). Returns one `AVWAPPoint` per bar from
55
+ * `bars[anchorIndex]` through `bars[bars.length - 1]`.
56
+ *
57
+ * @param bars the bar series; the anchor must lie inside it
58
+ * @param anchorIndex 0-based index of the anchor bar (must satisfy
59
+ * `0 <= anchorIndex < bars.length`)
60
+ * @param includeBands when `false`, the four band fields equal `vwap` and
61
+ * the (cheaper) one-pass cumulative-volume math is
62
+ * used. The second pass that drives the bands is
63
+ * skipped entirely.
64
+ *
65
+ * @throws RangeError when `anchorIndex` is out of range and `bars` is
66
+ * non-empty. An empty `bars` array returns `[]` even
67
+ * if `anchorIndex` would otherwise be invalid — this
68
+ * mirrors the "no data, no work" convention used by
69
+ * the volume-profile controller.
70
+ *
71
+ * @internal — building block used by the corresponding controller
72
+ * factory. Reachable today via the top-level `@klinechart-quant/core`
73
+ * barrel but **NOT part of the supported public API**. typedoc / api-
74
+ * extractor hide it from generated docs. Prefer the controller
75
+ * factory (e.g. `createVolumeProfileController`) for stable user code.
76
+ * Closes API audit BLOCKER-002 (export * leakage taxonomy).
77
+ */
78
+ export function computeAnchoredVwap(
79
+ bars: ReadonlyArray<AVWAPBar>,
80
+ anchorIndex: number,
81
+ includeBands: boolean,
82
+ ): ReadonlyArray<AVWAPPoint> {
83
+ if (bars.length === 0) return []
84
+
85
+ if (anchorIndex < 0 || anchorIndex >= bars.length) {
86
+ throw new KLineChartError(
87
+ 'AVWAP_ANCHOR_OUT_OF_RANGE',
88
+ `anchoredVwap: anchorIndex ${anchorIndex} is out of range ` +
89
+ `for bars of length ${bars.length}`,
90
+ )
91
+ }
92
+
93
+ const out: AVWAPPoint[] = []
94
+
95
+ // Running sums, advanced bar-by-bar.
96
+ let sumVwp = 0
97
+ let sumVol = 0
98
+ let sumSqDev = 0
99
+
100
+ // `prevVwap` carries forward when a bar has zero volume but the
101
+ // cumulative volume so far is > 0. Initial value `NaN` flags the
102
+ // "anchor bar volume 0" case (see the docstring).
103
+ let prevVwap = Number.NaN
104
+
105
+ for (let i = anchorIndex; i < bars.length; i++) {
106
+ const bar = bars[i]
107
+ // Guard against sparse arrays / undefined entries. `Float64Array`
108
+ // would never have this hole, but plain arrays might.
109
+ if (bar === undefined) continue
110
+
111
+ const tp = (bar.high + bar.low + bar.close) / 3
112
+ const v = bar.volume
113
+
114
+ // First update cumulative volume + vwp. A v === 0 bar is a no-op
115
+ // here and the running totals stay where they were.
116
+ if (v > 0) {
117
+ sumVwp += tp * v
118
+ sumVol += v
119
+ }
120
+
121
+ let vwap: number
122
+ if (sumVol > 0) {
123
+ vwap = sumVwp / sumVol
124
+ prevVwap = vwap
125
+ } else {
126
+ // No volume ever ingested — emit NaN. This only happens when
127
+ // the anchor bar and every bar since it has v === 0.
128
+ vwap = Number.NaN
129
+ }
130
+
131
+ // Bands: the *prevailing* AVWAP at bar j is the mean used to weigh
132
+ // sqDev. That's exactly the `vwap` we just computed. Important:
133
+ // if v === 0 the squared-deviation contribution is also 0, so we
134
+ // can skip the term entirely (which also avoids touching `tp`
135
+ // when `vwap` is NaN).
136
+ if (includeBands && v > 0 && Number.isFinite(vwap)) {
137
+ const diff = tp - vwap
138
+ sumSqDev += diff * diff * v
139
+ }
140
+
141
+ let upper1 = vwap
142
+ let lower1 = vwap
143
+ let upper2 = vwap
144
+ let lower2 = vwap
145
+ if (includeBands && sumVol > 0 && Number.isFinite(vwap)) {
146
+ const variance = sumSqDev / sumVol
147
+ // Numerical safety: variance can be a tiny negative on
148
+ // catastrophic cancellation. Treat as 0.
149
+ const stdDev = Math.sqrt(variance > 0 ? variance : 0)
150
+ upper1 = vwap + stdDev
151
+ lower1 = vwap - stdDev
152
+ upper2 = vwap + 2 * stdDev
153
+ lower2 = vwap - 2 * stdDev
154
+ }
155
+
156
+ out.push({
157
+ barIndex: i,
158
+ vwap,
159
+ upper1,
160
+ lower1,
161
+ upper2,
162
+ lower2,
163
+ cumulativeVolume: sumVol,
164
+ })
165
+
166
+ // `prevVwap` is kept up to date for documentation/clarity even
167
+ // though we don't currently read it (the `sumVol > 0` branch above
168
+ // assigns directly). Left in place to make the carry-forward
169
+ // semantics explicit to future readers.
170
+ void prevVwap
171
+ }
172
+
173
+ return out
174
+ }