@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,213 @@
1
+ /**
2
+ * Volume Profile controller — framework-agnostic, signal-based.
3
+ *
4
+ * Mirrors the dispose-guard pattern from `createIndicatorSelectorController`
5
+ * so React/Vue/Angular adapters bridge identically. The controller is pure
6
+ * data — no DOM, no rendering, no canvas. It plays the same role as
7
+ * `src/core/indicators/volumeProfileState.ts` (the maintainer's legacy state
8
+ * module) but with the new reactive contract; the legacy state file and the
9
+ * legacy renderer at `src/core/renderers/Indicator/volumeProfile.ts` are
10
+ * intentionally NOT touched (per branch policy).
11
+ *
12
+ * Flow on `ingest`:
13
+ * 1. Walk the bars once to learn `[minLow, maxHigh]`.
14
+ * 2. Derive `binMin`/`binSize` from that range + config.binCount.
15
+ * 3. Allocate a fresh `Float64Array(binCount)` (or reuse if size unchanged).
16
+ * 4. For each bar, call `binBarToBuckets` (typical-price or proportional).
17
+ * 5. `findPOCIndex` → `computeValueArea` → assemble `VolumeProfileState`.
18
+ *
19
+ * Non-goals:
20
+ * - Incremental ingest. `ingest` always recomputes from scratch. The
21
+ * incremental path comes with the WebGPU compute shader (see
22
+ * `computeShader.wgsl.md`).
23
+ * - Auto-binning by tick size. The current heuristic (range / binCount) is
24
+ * adequate for visual profiles; tick-snapped binning is a future option.
25
+ */
26
+
27
+ import { createSignal, type Signal } from '../../reactivity'
28
+ import { binBarToBuckets } from './binning'
29
+ import { findPOCIndex } from './poc'
30
+ import { computeValueArea } from './valueArea'
31
+ import type {
32
+ VolumeProfileBar,
33
+ VolumeProfileConfig,
34
+ VolumeProfileController,
35
+ VolumeProfileState,
36
+ } from './types'
37
+
38
+ const DEFAULT_CONFIG: VolumeProfileConfig = {
39
+ binCount: 100,
40
+ binningMode: 'typical-price',
41
+ valueAreaPercent: 0.7,
42
+ }
43
+
44
+ // Smallest binSize we will use. Prevents a degenerate "all bars same price"
45
+ // input from producing a division-by-zero. The value is arbitrary but small
46
+ // enough that real markets never hit it.
47
+ const MIN_BIN_SIZE = 1e-12
48
+
49
+ export interface VolumeProfileControllerInit {
50
+ config?: Partial<VolumeProfileConfig>
51
+ }
52
+
53
+ export function createVolumeProfileController(
54
+ init?: VolumeProfileControllerInit,
55
+ ): VolumeProfileController {
56
+ // -------------------------------------------------------------------
57
+ // Signals
58
+ // -------------------------------------------------------------------
59
+ const initialConfig: VolumeProfileConfig = {
60
+ ...DEFAULT_CONFIG,
61
+ ...(init?.config ?? {}),
62
+ }
63
+ // Defensive clamp: percent in [0, 1], binCount >= 1.
64
+ if (initialConfig.valueAreaPercent < 0) initialConfig.valueAreaPercent = 0
65
+ if (initialConfig.valueAreaPercent > 1) initialConfig.valueAreaPercent = 1
66
+ if (initialConfig.binCount < 1) initialConfig.binCount = 1
67
+
68
+ const config: Signal<VolumeProfileConfig> = createSignal(initialConfig)
69
+ const state: Signal<VolumeProfileState | null> =
70
+ createSignal<VolumeProfileState | null>(null)
71
+
72
+ // -------------------------------------------------------------------
73
+ // ingest — full recompute
74
+ // -------------------------------------------------------------------
75
+ function ingest(bars: ReadonlyArray<VolumeProfileBar>): void {
76
+ const cfg = config.peek()
77
+
78
+ if (bars.length === 0) {
79
+ state.set(null)
80
+ return
81
+ }
82
+
83
+ // First pass: range of the data.
84
+ let minLow = Infinity
85
+ let maxHigh = -Infinity
86
+ for (let i = 0; i < bars.length; i++) {
87
+ const b = bars[i]
88
+ if (b === undefined) continue
89
+ if (b.low < minLow) minLow = b.low
90
+ if (b.high > maxHigh) maxHigh = b.high
91
+ }
92
+
93
+ if (!Number.isFinite(minLow) || !Number.isFinite(maxHigh)) {
94
+ state.set(null)
95
+ return
96
+ }
97
+
98
+ const range = maxHigh - minLow
99
+ // Degenerate range: every bar at the same price. We still want a
100
+ // non-zero binSize so the math works; centre a tiny window on the
101
+ // price so the single bucket captures everything.
102
+ const binSize =
103
+ range > MIN_BIN_SIZE ? range / cfg.binCount : MIN_BIN_SIZE
104
+ const binMin = minLow
105
+
106
+ // Allocate or reuse the buckets. Reuse only if the size matches —
107
+ // changing `binCount` via `setConfig` requires a fresh array.
108
+ const prev = state.peek()
109
+ const buckets =
110
+ prev !== null && prev.buckets.length === cfg.binCount
111
+ ? prev.buckets
112
+ : new Float64Array(cfg.binCount)
113
+ // Zero it (whether reused or freshly allocated) — `fill(0)` is cheap
114
+ // on typed arrays.
115
+ buckets.fill(0)
116
+
117
+ // Second pass: drop volume into buckets.
118
+ for (let i = 0; i < bars.length; i++) {
119
+ const b = bars[i]
120
+ if (b === undefined) continue
121
+ binBarToBuckets(
122
+ b,
123
+ buckets,
124
+ binMin,
125
+ binSize,
126
+ cfg.binCount,
127
+ cfg.binningMode,
128
+ )
129
+ }
130
+
131
+ // POC + VA.
132
+ const pocIdx = findPOCIndex(buckets)
133
+ // findPOCIndex returns -1 only on empty arrays — guarded above.
134
+ const va = computeValueArea(
135
+ buckets,
136
+ pocIdx < 0 ? 0 : pocIdx,
137
+ cfg.valueAreaPercent,
138
+ )
139
+
140
+ // Prices: each bucket spans `[binMin + i*binSize, binMin + (i+1)*binSize)`.
141
+ // We report POC as the bucket *center*, VAH as the upper bucket's high
142
+ // edge, VAL as the lower bucket's low edge — this matches how a
143
+ // renderer wants to draw them: POC as a centerline, VAH/VAL as
144
+ // envelope edges.
145
+ const pocPrice = binMin + (va.pocIndex + 0.5) * binSize
146
+ const vahPrice = binMin + (va.vahIndex + 1) * binSize
147
+ const valPrice = binMin + va.valIndex * binSize
148
+
149
+ const next: VolumeProfileState = {
150
+ buckets,
151
+ binMin,
152
+ binSize,
153
+ poc: pocPrice,
154
+ vah: vahPrice,
155
+ val: valPrice,
156
+ totalVolume: va.totalVolume,
157
+ vaVolume: va.vaVolume,
158
+ }
159
+ state.set(next)
160
+ }
161
+
162
+ // -------------------------------------------------------------------
163
+ // setConfig — patch + invalidate
164
+ // -------------------------------------------------------------------
165
+ function setConfig(next: Partial<VolumeProfileConfig>): void {
166
+ const cur = config.peek()
167
+ const merged: VolumeProfileConfig = { ...cur, ...next }
168
+ // Re-apply the defensive clamps.
169
+ if (merged.valueAreaPercent < 0) merged.valueAreaPercent = 0
170
+ if (merged.valueAreaPercent > 1) merged.valueAreaPercent = 1
171
+ if (merged.binCount < 1) merged.binCount = 1
172
+
173
+ // If binCount changed, the existing buckets are stale (different
174
+ // resolution) — clear state so callers know to re-ingest. Other
175
+ // field changes leave the data untouched until next ingest.
176
+ if (merged.binCount !== cur.binCount) {
177
+ state.set(null)
178
+ }
179
+ config.set(merged)
180
+ }
181
+
182
+ // -------------------------------------------------------------------
183
+ // reset — clear state, keep config
184
+ // -------------------------------------------------------------------
185
+ function reset(): void {
186
+ state.set(null)
187
+ }
188
+
189
+ // -------------------------------------------------------------------
190
+ // dispose — silence mutators (same pattern as IndicatorSelectorController)
191
+ // -------------------------------------------------------------------
192
+ let disposed = false
193
+ function dispose(): void {
194
+ if (disposed) return
195
+ disposed = true
196
+ }
197
+
198
+ function guard<T extends (...args: never[]) => unknown>(fn: T): T {
199
+ return ((...args: Parameters<T>): ReturnType<T> => {
200
+ if (disposed) return undefined as ReturnType<T>
201
+ return fn(...args) as ReturnType<T>
202
+ }) as T
203
+ }
204
+
205
+ return {
206
+ config,
207
+ state,
208
+ ingest: guard(ingest),
209
+ setConfig: guard(setConfig),
210
+ reset: guard(reset),
211
+ dispose,
212
+ }
213
+ }
@@ -0,0 +1,12 @@
1
+ export type {
2
+ BinningMode,
3
+ VolumeProfileConfig,
4
+ VolumeProfileState,
5
+ VolumeProfileBar,
6
+ VolumeProfileController,
7
+ ValueAreaResult,
8
+ } from './types'
9
+ export { binBarToBuckets } from './binning'
10
+ export { findPOCIndex } from './poc'
11
+ export { computeValueArea } from './valueArea'
12
+ export { createVolumeProfileController } from './createVolumeProfileController'
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Point of Control — argmax over the bucket histogram.
3
+ *
4
+ * The POC is the single bucket with the largest total volume. It is the seed
5
+ * for the Value Area expansion (`valueArea.ts`) and the most-referenced level
6
+ * on a volume profile chart.
7
+ *
8
+ * Tie-breaker policy (important — make sure it stays stable):
9
+ * When two or more buckets share the maximum, the **lowest index wins**.
10
+ *
11
+ * Rationale: argmax under ties is otherwise undefined, which leads to
12
+ * non-deterministic state across runs and breaks snapshot tests. Returning
13
+ * the lowest index is also the convention KLineCharts and the maintainer's
14
+ * legacy renderer follow, so the visual placement of the POC line is
15
+ * consistent across our data model and the existing renderer.
16
+ *
17
+ * Edge case: an empty array returns `-1`. Callers (the controller) treat
18
+ * that as "no profile" and emit `state = null`. We pick -1 (not 0) so the
19
+ * empty case is impossible to confuse with "argmax happens to be bucket 0".
20
+ */
21
+
22
+ /**
23
+ * Returns the index of the largest bucket. Ties resolve to the lowest index.
24
+ * Returns -1 if `buckets.length === 0`.
25
+ *
26
+ * Single pass, branch-light, O(n).
27
+ *
28
+ * @internal — building block used by the corresponding controller
29
+ * factory. Reachable today via the top-level `@klinechart-quant/core`
30
+ * barrel but **NOT part of the supported public API**. typedoc / api-
31
+ * extractor hide it from generated docs. Prefer the controller
32
+ * factory (e.g. `createVolumeProfileController`) for stable user code.
33
+ * Closes API audit BLOCKER-002 (export * leakage taxonomy).
34
+ */
35
+ export function findPOCIndex(buckets: Float64Array): number {
36
+ const n = buckets.length
37
+ if (n === 0) return -1
38
+
39
+ let bestIdx = 0
40
+ let bestVol = buckets[0] ?? 0
41
+
42
+ // Walk buckets[1..]; strictly-greater wins, equal does NOT (keeps the
43
+ // earliest index — the documented tie-breaker).
44
+ for (let i = 1; i < n; i++) {
45
+ const v = buckets[i] ?? 0
46
+ if (v > bestVol) {
47
+ bestVol = v
48
+ bestIdx = i
49
+ }
50
+ }
51
+
52
+ return bestIdx
53
+ }
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Volume Profile — public type contract.
3
+ *
4
+ * Volume Profile aggregates traded volume by **price** (not time), producing a
5
+ * horizontal histogram pinned to the price axis. Traders read it for
6
+ * accumulation zones (POC), the 70% Value Area (VAH/VAL — CME convention),
7
+ * and developing support/resistance.
8
+ *
9
+ * This module owns the **data model + math only**. Rendering belongs to the
10
+ * `@klinechart-quant/core` Renderer/Scene layer (or the maintainer's legacy
11
+ * renderer at `src/core/renderers/Indicator/volumeProfile.ts`, which is kept
12
+ * untouched per branch policy).
13
+ *
14
+ * See `docs/ROADMAP.md` §3.1 for the algorithm rationale and §0 for the
15
+ * controller layering this fits into. See `computeShader.wgsl.md` for the
16
+ * planned WebGPU compute path of the heavy `binBarToBuckets` work.
17
+ */
18
+
19
+ import type { Signal } from '../../reactivity'
20
+
21
+ /**
22
+ * How a bar's volume is distributed across price buckets.
23
+ *
24
+ * - `typical-price` — the fast default. The entire bar volume is dropped into
25
+ * the single bucket containing (high+low+close)/3. O(1) per bar.
26
+ * - `proportional` — accurate. The bar volume is split across every bucket
27
+ * that overlaps `[low, high]`, proportional to that bucket's price-range
28
+ * overlap with the bar. O(buckets-spanned) per bar.
29
+ *
30
+ * The trade-off is laid out in `docs/ROADMAP.md` §3.1: typical-price is what
31
+ * you want for live profile rendering at frame rate; proportional is what you
32
+ * want for "true" historical profiles and TPO-style work.
33
+ */
34
+ export type BinningMode = 'typical-price' | 'proportional'
35
+
36
+ /**
37
+ * Inputs to the controller. All fields are deliberately required at the
38
+ * controller surface — `createVolumeProfileController` fills missing fields
39
+ * from sensible defaults so callers can pass `{}`.
40
+ */
41
+ export interface VolumeProfileConfig {
42
+ /** Number of price buckets (histogram resolution). Typical 50–200. */
43
+ binCount: number
44
+ /** Per-bar binning strategy. See `BinningMode`. */
45
+ binningMode: BinningMode
46
+ /**
47
+ * Fraction of total volume that must be inside the Value Area, in [0, 1].
48
+ * CME convention is 0.70. Set 1.0 to use the full range, set to e.g. 0.95
49
+ * for institution-style "value extended" envelopes.
50
+ */
51
+ valueAreaPercent: number
52
+ }
53
+
54
+ /**
55
+ * The reactive output. `null` while no bars have been ingested.
56
+ *
57
+ * Prices are absolute (real, not normalised) so renderers can place them on
58
+ * the same Y axis as candles. `buckets` is a `Float64Array` rather than
59
+ * `number[]` for two reasons: (1) contiguous memory layout for cache-friendly
60
+ * argmax / VA scans, and (2) it is the same format we'll upload to a GPU
61
+ * storage buffer once the WebGPU compute path lands (see `computeShader.wgsl.md`).
62
+ */
63
+ export interface VolumeProfileState {
64
+ /** Histogram. `buckets[i]` is the total volume in bucket i. */
65
+ buckets: Float64Array
66
+ /** Low-edge price of bucket 0. */
67
+ binMin: number
68
+ /** Price width of one bucket. `buckets.length * binSize = total price span`. */
69
+ binSize: number
70
+ /** Point of Control — center price of the highest-volume bucket. */
71
+ poc: number
72
+ /** Value Area High — upper edge price of the VAH bucket. */
73
+ vah: number
74
+ /** Value Area Low — lower edge price of the VAL bucket. */
75
+ val: number
76
+ /** Sum of every bucket. */
77
+ totalVolume: number
78
+ /** Volume inside the closed Value Area `[valIndex, vahIndex]`. */
79
+ vaVolume: number
80
+ }
81
+
82
+ /**
83
+ * Minimum bar shape consumed by `ingest`. Matches the cross-renderer KLineData
84
+ * subset used elsewhere in core. We intentionally do NOT require `open` or
85
+ * `timestamp` so callers can stream from any source.
86
+ */
87
+ export interface VolumeProfileBar {
88
+ high: number
89
+ low: number
90
+ close: number
91
+ volume: number
92
+ }
93
+
94
+ /**
95
+ * Framework-agnostic controller — mirrors `IndicatorSelectorController`'s
96
+ * shape (signals for state, plain functions for mutations, idempotent
97
+ * `dispose`).
98
+ */
99
+ export interface VolumeProfileController {
100
+ /** Current config; re-emits when `setConfig` is called. */
101
+ readonly config: Signal<VolumeProfileConfig>
102
+ /** Current state; `null` until the first ingest. */
103
+ readonly state: Signal<VolumeProfileState | null>
104
+
105
+ /**
106
+ * Recompute the profile from a fresh bar slice. Idempotent: calling this
107
+ * twice with the same bars yields the same state (it is NOT cumulative —
108
+ * the prior buckets are discarded). Incremental ingestion will land with
109
+ * the GPU compute path; see `computeShader.wgsl.md`.
110
+ */
111
+ ingest(bars: ReadonlyArray<VolumeProfileBar>): void
112
+
113
+ /**
114
+ * Patch the config. If `binCount` changes the buckets are re-sized on the
115
+ * next `ingest` (state is cleared immediately because the old buckets are
116
+ * now meaningless under the new resolution).
117
+ */
118
+ setConfig(next: Partial<VolumeProfileConfig>): void
119
+
120
+ /** Clear state to null (does not change config). */
121
+ reset(): void
122
+
123
+ /**
124
+ * Stop emitting. Subsequent calls to ingest/setConfig/reset are silent
125
+ * no-ops; previously-attached subscribers receive no further
126
+ * notifications. Idempotent.
127
+ */
128
+ dispose(): void
129
+ }
130
+
131
+ /**
132
+ * Result of the Value Area greedy expansion. Indices are inclusive bucket
133
+ * indices; prices are derived by the controller using `binMin + binSize * i`.
134
+ */
135
+ export interface ValueAreaResult {
136
+ /** Upper bucket index (inclusive). */
137
+ vahIndex: number
138
+ /** Lower bucket index (inclusive). */
139
+ valIndex: number
140
+ /** Argmax bucket index used as the seed. */
141
+ pocIndex: number
142
+ /** Total of all buckets. */
143
+ totalVolume: number
144
+ /** Sum of `buckets[i]` for `i in [valIndex, vahIndex]`. */
145
+ vaVolume: number
146
+ /** `vaVolume / totalVolume`. 0 when `totalVolume` is 0. */
147
+ vaPercent: number
148
+ }
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Value Area greedy expansion — VAH / VAL computation around the POC.
3
+ *
4
+ * Algorithm (CME-traditional, see `docs/ROADMAP.md` §3.1):
5
+ * 1. Seed the Value Area with the POC bucket.
6
+ * 2. Compute the target volume `target = totalVolume * percent`.
7
+ * 3. Repeatedly grow the VA by **one** of its boundary's neighbours:
8
+ * compare the volume of `buckets[vahIdx + 1]` (upper neighbour) and
9
+ * `buckets[valIdx - 1]` (lower neighbour); annex the side with the
10
+ * larger volume.
11
+ * 4. If one side has no neighbour left (boundary of the histogram), only
12
+ * the other side is available.
13
+ * 5. Stop when `vaVolume >= target` or both sides are exhausted.
14
+ *
15
+ * Tie-breakers (critical — get these wrong and the test plan fails):
16
+ *
17
+ * (A) When `upper.vol == lower.vol`, expand toward the POC. "Toward the
18
+ * POC" means: pick the side whose current boundary is **closer** to
19
+ * `pocIndex`. The intuition is that a symmetric tie should grow the
20
+ * VA evenly around the POC instead of drifting whichever way the
21
+ * comparison happens to land first. This matches the spirit of the
22
+ * CME spec, which expects the VA to be "balanced around POC" when
23
+ * data is symmetric, and it's the choice the maintainer's legacy
24
+ * renderer makes by default.
25
+ *
26
+ * (B) When `upper.vol == lower.vol` AND both boundaries are equidistant
27
+ * from POC, prefer the **upper** side. This is documented because it
28
+ * is otherwise underspecified; the rationale is that an upper-side
29
+ * preference matches the default direction of price discovery on
30
+ * most assets (markets tend to break up out of balance).
31
+ *
32
+ * (C) The CME-style "two-bucket lookahead" tie-breaker is intentionally
33
+ * NOT implemented in this pass — it adds complexity for a tiny
34
+ * difference in result and is not required by the test plan. It can
35
+ * be added behind a `tieBreaker: 'lookahead'` option later without
36
+ * breaking the API.
37
+ *
38
+ * Edge cases:
39
+ * - Empty / all-zero buckets ⇒ `vah = val = poc`, `vaVolume = 0`,
40
+ * `vaPercent = 0`. No expansion happens.
41
+ * - Single non-zero bucket ⇒ `vah = val = poc` already covers it.
42
+ * - POC at index 0 ⇒ only the upper neighbour exists.
43
+ * - POC at index N-1 ⇒ only the lower neighbour exists.
44
+ * - `targetPercent >= 1.0` ⇒ the loop expands until the full range is
45
+ * swept, yielding `valIdx = 0`, `vahIdx = N-1`.
46
+ * - `targetPercent <= 0` ⇒ the loop never runs; only the POC bucket is in
47
+ * the VA.
48
+ */
49
+
50
+ import type { ValueAreaResult } from './types'
51
+
52
+ /**
53
+ * @internal — building block used by `createVolumeProfileController`. Reachable today
54
+ * via the top-level `@klinechart-quant/core` barrel but **NOT
55
+ * part of the supported public API**. typedoc / api-extractor
56
+ * hide it from generated docs. Prefer the controller factory
57
+ * for stable user code. Closes API audit BLOCKER-002.
58
+ */
59
+ export function computeValueArea(
60
+ buckets: Float64Array,
61
+ pocIndex: number,
62
+ targetPercent: number,
63
+ ): ValueAreaResult {
64
+ const n = buckets.length
65
+
66
+ // -------------------------------------------------------------------
67
+ // Empty histogram → degenerate result.
68
+ // -------------------------------------------------------------------
69
+ if (n === 0) {
70
+ return {
71
+ vahIndex: 0,
72
+ valIndex: 0,
73
+ pocIndex: 0,
74
+ totalVolume: 0,
75
+ vaVolume: 0,
76
+ vaPercent: 0,
77
+ }
78
+ }
79
+
80
+ // Clamp pocIndex defensively. The controller always passes a valid
81
+ // value, but valueArea.ts is also exported for direct use.
82
+ const poc = pocIndex < 0 ? 0 : pocIndex >= n ? n - 1 : pocIndex
83
+
84
+ // -------------------------------------------------------------------
85
+ // Total volume — single pass.
86
+ // -------------------------------------------------------------------
87
+ let totalVolume = 0
88
+ for (let i = 0; i < n; i++) {
89
+ totalVolume += buckets[i] ?? 0
90
+ }
91
+
92
+ // Zero-volume case → degenerate result, VA collapses to POC.
93
+ if (totalVolume === 0) {
94
+ return {
95
+ vahIndex: poc,
96
+ valIndex: poc,
97
+ pocIndex: poc,
98
+ totalVolume: 0,
99
+ vaVolume: 0,
100
+ vaPercent: 0,
101
+ }
102
+ }
103
+
104
+ // -------------------------------------------------------------------
105
+ // Seed the Value Area with the POC bucket.
106
+ // -------------------------------------------------------------------
107
+ let valIdx = poc
108
+ let vahIdx = poc
109
+ let vaVolume = buckets[poc] ?? 0
110
+
111
+ const pct = targetPercent < 0 ? 0 : targetPercent > 1 ? 1 : targetPercent
112
+ const target = totalVolume * pct
113
+
114
+ // Already covered (rare — happens when POC bucket alone is > target%).
115
+ // Still proceeds via the loop guard.
116
+
117
+ // -------------------------------------------------------------------
118
+ // Greedy expansion.
119
+ // -------------------------------------------------------------------
120
+ while (vaVolume < target) {
121
+ const canUp = vahIdx < n - 1
122
+ const canDown = valIdx > 0
123
+
124
+ if (!canUp && !canDown) break // exhausted entire histogram
125
+
126
+ // Single-side: only one direction has a neighbour.
127
+ if (canUp && !canDown) {
128
+ vahIdx += 1
129
+ vaVolume += buckets[vahIdx] ?? 0
130
+ continue
131
+ }
132
+ if (!canUp && canDown) {
133
+ valIdx -= 1
134
+ vaVolume += buckets[valIdx] ?? 0
135
+ continue
136
+ }
137
+
138
+ const upVol = buckets[vahIdx + 1] ?? 0
139
+ const downVol = buckets[valIdx - 1] ?? 0
140
+
141
+ let goUp: boolean
142
+
143
+ if (upVol > downVol) {
144
+ goUp = true
145
+ } else if (downVol > upVol) {
146
+ goUp = false
147
+ } else {
148
+ // ----- Tie: expand toward POC (see (A)/(B) in header). -----
149
+ // Distance from each *current* boundary to the POC. The
150
+ // boundary that's farther from POC is on the "long" side; we
151
+ // pull the VA back toward POC by extending the *closer*
152
+ // boundary (i.e. the side that has further to travel before
153
+ // it leaves POC's neighbourhood).
154
+ //
155
+ // Equivalently: pick the boundary whose distance to POC is
156
+ // smaller — that side still has room to grow "around" POC,
157
+ // the other side has already drifted.
158
+ const distUp = vahIdx - poc // >= 0
159
+ const distDown = poc - valIdx // >= 0
160
+ if (distUp < distDown) {
161
+ goUp = true
162
+ } else if (distDown < distUp) {
163
+ goUp = false
164
+ } else {
165
+ // Equidistant — documented upper-side preference (B).
166
+ goUp = true
167
+ }
168
+ }
169
+
170
+ if (goUp) {
171
+ vahIdx += 1
172
+ vaVolume += buckets[vahIdx] ?? 0
173
+ } else {
174
+ valIdx -= 1
175
+ vaVolume += buckets[valIdx] ?? 0
176
+ }
177
+ }
178
+
179
+ return {
180
+ vahIndex: vahIdx,
181
+ valIndex: valIdx,
182
+ pocIndex: poc,
183
+ totalVolume,
184
+ vaVolume,
185
+ vaPercent: totalVolume === 0 ? 0 : vaVolume / totalVolume,
186
+ }
187
+ }