@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,130 @@
1
+ /**
2
+ * Footprint controller integration tests — trade ingestion, bar bucketing,
3
+ * classifier composition, cumulativeDelta wiring, dispose semantics.
4
+ */
5
+
6
+ import { describe, it, expect, vi } from 'vitest'
7
+ import { createFootprintController } from '../createFootprintController'
8
+ import type { FootprintController, FootprintConfig } from '../types'
9
+
10
+ const baseConfig: FootprintConfig = {
11
+ tickSize: 0.01,
12
+ barIntervalMs: 60_000, // 1m bars
13
+ imbalanceRatio: 3,
14
+ fallbackClassifier: 'tick-rule',
15
+ }
16
+
17
+ function makeController(patch: Partial<FootprintConfig> = {}): FootprintController {
18
+ return createFootprintController({ ...baseConfig, ...patch })
19
+ }
20
+
21
+ describe('createFootprintController — single trade ingestion', () => {
22
+ it('single explicit-flag trade → 1 bar, 1 cell with correct direction', () => {
23
+ const c = makeController()
24
+ c.ingestTrade({ timestamp: 1_000_000, price: 100.05, size: 10, isBuyerMaker: false })
25
+ // buy aggressor → askVol increments at the quantized price
26
+ const bars = c.bars()
27
+ expect(bars).toHaveLength(1)
28
+ expect(bars[0]?.cells).toHaveLength(1)
29
+ const cell = bars[0]!.cells[0]!
30
+ expect(cell.price).toBeCloseTo(100.05, 6)
31
+ expect(cell.askVol).toBe(10)
32
+ expect(cell.bidVol).toBe(0)
33
+ })
34
+
35
+ it('same-bar trades at same price → cells aggregate', () => {
36
+ const c = makeController()
37
+ c.ingestTrade({ timestamp: 1_000_000, price: 100.05, size: 10, isBuyerMaker: false })
38
+ c.ingestTrade({ timestamp: 1_000_500, price: 100.05, size: 5, isBuyerMaker: true })
39
+ const bars = c.bars()
40
+ expect(bars).toHaveLength(1)
41
+ const cell = bars[0]!.cells[0]!
42
+ expect(cell.askVol).toBe(10) // first trade buy
43
+ expect(cell.bidVol).toBe(5) // second trade sell
44
+ })
45
+
46
+ it('crossing the bar interval boundary → new bar', () => {
47
+ const c = makeController({ barIntervalMs: 1000 })
48
+ c.ingestTrade({ timestamp: 1_000_000, price: 100, size: 10, isBuyerMaker: false })
49
+ c.ingestTrade({ timestamp: 1_001_000, price: 100, size: 10, isBuyerMaker: false })
50
+ const bars = c.bars()
51
+ expect(bars).toHaveLength(2)
52
+ })
53
+ })
54
+
55
+ describe('createFootprintController — classifier fallback chain', () => {
56
+ it('uses explicit flag when present, ignoring fallbackClassifier', () => {
57
+ const c = makeController({ fallbackClassifier: 'tick-rule' })
58
+ c.ingestTrade({ timestamp: 1_000_000, price: 100, size: 5, isBuyerMaker: true })
59
+ // explicit says sell aggressor → bidVol += 5
60
+ const cell = c.bars()[0]!.cells[0]!
61
+ expect(cell.bidVol).toBe(5)
62
+ expect(cell.askVol).toBe(0)
63
+ })
64
+
65
+ it('falls back to tick rule when flag is absent', () => {
66
+ const c = makeController({ fallbackClassifier: 'tick-rule' })
67
+ // first trade → tick rule returns unknown; controller drops it from aggregate
68
+ c.ingestTrade({ timestamp: 1_000_000, price: 100, size: 5 })
69
+ c.ingestTrade({ timestamp: 1_000_100, price: 101, size: 5 }) // uptick → buy
70
+ // The first trade was unknown (dropped). The second is buy at price 101.
71
+ const cells = c.bars()[0]!.cells
72
+ const cellAt101 = cells.find((x) => Math.abs(x.price - 101) < 1e-6)
73
+ expect(cellAt101?.askVol).toBe(5)
74
+ })
75
+
76
+ it('Lee-Ready fallback uses bid/ask when provided', () => {
77
+ const c = makeController({ fallbackClassifier: 'lee-ready' })
78
+ c.ingestTrade({ timestamp: 1_000_000, price: 100.6, size: 5 }, 100, 101)
79
+ // mid = 100.5, price > mid → buy
80
+ const cell = c.bars()[0]!.cells[0]!
81
+ expect(cell.askVol).toBe(5)
82
+ })
83
+ })
84
+
85
+ describe('createFootprintController — derived stats', () => {
86
+ it('bar.delta updates as trades accumulate', () => {
87
+ const c = makeController()
88
+ c.ingestTrade({ timestamp: 1_000_000, price: 100, size: 10, isBuyerMaker: false })
89
+ c.ingestTrade({ timestamp: 1_000_100, price: 100, size: 4, isBuyerMaker: true })
90
+ const bar = c.bars()[0]!
91
+ expect(bar.delta).toBe(6) // 10 ask - 4 bid
92
+ expect(bar.totalVolume).toBe(14)
93
+ })
94
+
95
+ it('cumulativeDelta signal emits running sum across bars', () => {
96
+ const c = makeController({ barIntervalMs: 1000 })
97
+ c.ingestTrade({ timestamp: 1_000_000, price: 100, size: 10, isBuyerMaker: false }) // +10
98
+ c.ingestTrade({ timestamp: 1_001_000, price: 100, size: 4, isBuyerMaker: true }) // -4
99
+ c.ingestTrade({ timestamp: 1_002_000, price: 100, size: 8, isBuyerMaker: false }) // +8
100
+ expect(c.cumulativeDelta()).toEqual([10, 6, 14])
101
+ })
102
+ })
103
+
104
+ describe('createFootprintController — config + lifecycle', () => {
105
+ it('setConfig with new barIntervalMs invalidates existing bars', () => {
106
+ const c = makeController({ barIntervalMs: 60_000 })
107
+ c.ingestTrade({ timestamp: 1_000_000, price: 100, size: 5, isBuyerMaker: false })
108
+ expect(c.bars()).toHaveLength(1)
109
+ c.setConfig({ barIntervalMs: 1000 })
110
+ expect(c.bars()).toHaveLength(0)
111
+ })
112
+
113
+ it('reset clears all bars and cumulativeDelta', () => {
114
+ const c = makeController()
115
+ c.ingestTrade({ timestamp: 1_000_000, price: 100, size: 5, isBuyerMaker: false })
116
+ c.reset()
117
+ expect(c.bars()).toEqual([])
118
+ expect(c.cumulativeDelta()).toEqual([])
119
+ })
120
+
121
+ it('dispose silences subsequent mutators and signal emissions', () => {
122
+ const c = makeController()
123
+ const listener = vi.fn()
124
+ c.bars.subscribe(listener)
125
+ c.dispose()
126
+ c.ingestTrade({ timestamp: 1_000_000, price: 100, size: 5, isBuyerMaker: false })
127
+ expect(listener).not.toHaveBeenCalled()
128
+ expect(c.bars()).toEqual([])
129
+ })
130
+ })
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Per-bar statistics tests — delta / cumulativeDelta / diagonal imbalance.
3
+ */
4
+
5
+ import { describe, it, expect } from 'vitest'
6
+ import {
7
+ computeDelta,
8
+ computeCumulativeDelta,
9
+ computeDiagonalImbalances,
10
+ type FootprintBarCell,
11
+ } from '../perBarStats'
12
+
13
+ const cell = (price: number, askVol: number, bidVol: number): FootprintBarCell => ({
14
+ price,
15
+ askVol,
16
+ bidVol,
17
+ })
18
+
19
+ describe('computeDelta', () => {
20
+ it('pure buy bar → positive delta equals total ask volume', () => {
21
+ const cells = [cell(100, 50, 0), cell(101, 30, 0)]
22
+ expect(computeDelta(cells)).toBe(80)
23
+ })
24
+
25
+ it('pure sell bar → negative delta', () => {
26
+ const cells = [cell(100, 0, 50), cell(101, 0, 30)]
27
+ expect(computeDelta(cells)).toBe(-80)
28
+ })
29
+
30
+ it('balanced bar → 0', () => {
31
+ const cells = [cell(100, 25, 25), cell(101, 25, 25)]
32
+ expect(computeDelta(cells)).toBe(0)
33
+ })
34
+
35
+ it('empty cells → 0', () => {
36
+ expect(computeDelta([])).toBe(0)
37
+ })
38
+ })
39
+
40
+ describe('computeCumulativeDelta', () => {
41
+ it('all positive deltas → strictly monotonic increasing', () => {
42
+ expect(computeCumulativeDelta([10, 20, 30])).toEqual([10, 30, 60])
43
+ })
44
+
45
+ it('mixed signs → correct running sum', () => {
46
+ expect(computeCumulativeDelta([10, -5, 8, -3])).toEqual([10, 5, 13, 10])
47
+ })
48
+
49
+ it('empty input → []', () => {
50
+ expect(computeCumulativeDelta([])).toEqual([])
51
+ })
52
+
53
+ it('single delta → [delta]', () => {
54
+ expect(computeCumulativeDelta([42])).toEqual([42])
55
+ })
56
+ })
57
+
58
+ describe('computeDiagonalImbalances', () => {
59
+ it('buy imbalance detected when ask[i] >= 3 * bid[i-1] and bid[i-1] > 0', () => {
60
+ // cells sorted ascending: i=0 at price 100, i=1 at price 101
61
+ // ask[1]=30, bid[0]=10 → ratio 3, triggers
62
+ const cells = [cell(100, 5, 10), cell(101, 30, 5)]
63
+ const imb = computeDiagonalImbalances(cells, 3)
64
+ const buy = imb.find((x) => x.direction === 'buy-imbalance')
65
+ expect(buy).toBeDefined()
66
+ expect(buy?.priceIndex).toBe(1)
67
+ expect(buy?.ratio).toBeCloseTo(3, 6)
68
+ })
69
+
70
+ it('NOT triggered at ratio 2.9x', () => {
71
+ const cells = [cell(100, 5, 10), cell(101, 29, 5)]
72
+ const imb = computeDiagonalImbalances(cells, 3)
73
+ expect(imb.find((x) => x.direction === 'buy-imbalance')).toBeUndefined()
74
+ })
75
+
76
+ it('sell imbalance detected when bid[i] >= 3 * ask[i+1] and ask[i+1] > 0', () => {
77
+ const cells = [cell(100, 5, 30), cell(101, 10, 5)]
78
+ // bid[0]=30, ask[1]=10 → ratio 3, sell imbalance at i=0
79
+ const imb = computeDiagonalImbalances(cells, 3)
80
+ const sell = imb.find((x) => x.direction === 'sell-imbalance')
81
+ expect(sell).toBeDefined()
82
+ expect(sell?.priceIndex).toBe(0)
83
+ expect(sell?.ratio).toBeCloseTo(3, 6)
84
+ })
85
+
86
+ it('handles boundary cells without crashing (no neighbour above for last, below for first)', () => {
87
+ const cells = [cell(100, 10, 10)]
88
+ expect(() => computeDiagonalImbalances(cells, 3)).not.toThrow()
89
+ expect(computeDiagonalImbalances(cells, 3)).toEqual([])
90
+ })
91
+
92
+ it('cell with zero bid/ask does not trigger imbalance (divide-by-zero guard)', () => {
93
+ const cells = [cell(100, 0, 0), cell(101, 100, 0)]
94
+ // bid[0]=0 means we can't compute ask[1]/bid[0] → no buy imbalance
95
+ const imb = computeDiagonalImbalances(cells, 3)
96
+ expect(imb.find((x) => x.direction === 'buy-imbalance')).toBeUndefined()
97
+ })
98
+
99
+ it('multiple imbalances in one bar are all reported', () => {
100
+ const cells = [
101
+ cell(100, 5, 10),
102
+ cell(101, 100, 5), // buy imb at 1 (100 / 10 = 10x)
103
+ cell(102, 5, 100), // sell imb at 2 (next ask=10? need cell 3); test:
104
+ cell(103, 10, 5), // sell imb at 2: bid[2]=100, ask[3]=10 → 10x
105
+ ]
106
+ const imb = computeDiagonalImbalances(cells, 3)
107
+ expect(imb.some((x) => x.direction === 'buy-imbalance' && x.priceIndex === 1)).toBe(true)
108
+ expect(imb.some((x) => x.direction === 'sell-imbalance' && x.priceIndex === 2)).toBe(true)
109
+ })
110
+
111
+ it('empty cells → empty imbalances', () => {
112
+ expect(computeDiagonalImbalances([], 3)).toEqual([])
113
+ })
114
+ })
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Aggressor classification — three heuristics for tagging a print as
3
+ * buyer-initiated ("buy", aggressor lifted the ASK) or seller-initiated
4
+ * ("sell", aggressor hit the BID).
5
+ *
6
+ * Future hook: Bulk Volume Classification (BVC) by Easley/Lopez de Prado/O'Hara
7
+ * 2012 is more robust in HFT-fragmented markets where the tick rule's serial
8
+ * correlation assumptions break. BVC is planned as a v2 classifier under the
9
+ * same `AggressorResult` interface.
10
+ *
11
+ * Each classifier exports the same `AggressorResult` shape so the controller
12
+ * can compose them in a fallback chain (explicit → heuristic) without
13
+ * branching on classifier identity.
14
+ *
15
+ * See `docs/ROADMAP.md` §3.3 for the rationale — order of preference is
16
+ * always explicit > Lee-Ready > tick rule.
17
+ */
18
+
19
+ import type { AggressorSide, Trade, TradeWithFlag } from './types'
20
+
21
+ /**
22
+ * Output of every classifier.
23
+ *
24
+ * `side` is `'unknown'` only when there is genuinely no information to act
25
+ * on (e.g. the first trade in a tick-rule sequence). The controller should
26
+ * treat `'unknown'` as "drop this trade from the aggregate", NOT as a
27
+ * silent default to 'buy' or 'sell'.
28
+ *
29
+ * `inferred=false` means the side came from an exchange flag (zero error).
30
+ * `inferred=true` means it was estimated; downstream UI should mark such
31
+ * bars as approximate.
32
+ */
33
+ export type { AggressorSide, Trade, TradeWithFlag }
34
+ export interface AggressorResult {
35
+ side: AggressorSide | 'unknown'
36
+ inferred: boolean
37
+ }
38
+
39
+ // ---------------------------------------------------------------------------
40
+ // 1. Explicit (exchange-provided flag)
41
+ // ---------------------------------------------------------------------------
42
+
43
+ /**
44
+ * Read Binance-style `isBuyerMaker`. When the buyer is the maker (passive),
45
+ * the seller was the aggressor — so we report `'sell'`. When the buyer is
46
+ * NOT the maker, the buyer was the aggressor — `'buy'`.
47
+ *
48
+ * Returns `null` (not an `AggressorResult`) when the flag is missing so the
49
+ * caller can distinguish "no data" from "we classified it as unknown". This
50
+ * lets the controller fall back to the configured heuristic only when truly
51
+ * needed.
52
+ */
53
+ export function classifyExplicit(
54
+ trade: TradeWithFlag,
55
+ ): AggressorResult | null {
56
+ if (trade.isBuyerMaker === undefined) return null
57
+ return {
58
+ side: trade.isBuyerMaker ? 'sell' : 'buy',
59
+ inferred: false,
60
+ }
61
+ }
62
+
63
+ // ---------------------------------------------------------------------------
64
+ // 2. Tick rule
65
+ // ---------------------------------------------------------------------------
66
+
67
+ /**
68
+ * State carried across consecutive trades for the tick rule. The classifier
69
+ * MUTATES this in place — callers should keep one instance per stream
70
+ * (per-symbol if multiplexing).
71
+ */
72
+ export interface TickRuleState {
73
+ prevPrice: number | null
74
+ prevSide: AggressorSide | null
75
+ }
76
+
77
+ /**
78
+ * Classic tick test (Lee & Ready 1991 §2):
79
+ *
80
+ * price > prevPrice → 'buy' (uptick)
81
+ * price < prevPrice → 'sell' (downtick)
82
+ * price == prevPrice → repeats prevSide (zero-tick)
83
+ * first trade (prevPrice null) → 'unknown'
84
+ *
85
+ * The state is MUTATED so subsequent calls inherit the running context.
86
+ */
87
+ export function classifyTickRule(
88
+ state: TickRuleState,
89
+ trade: Trade,
90
+ ): AggressorResult {
91
+ const prev = state.prevPrice
92
+ let side: AggressorSide | 'unknown'
93
+
94
+ if (prev === null) {
95
+ side = 'unknown'
96
+ } else if (trade.price > prev) {
97
+ side = 'buy'
98
+ } else if (trade.price < prev) {
99
+ side = 'sell'
100
+ } else {
101
+ // zero-tick: inherit previous decision; 'unknown' if no prior side.
102
+ side = state.prevSide ?? 'unknown'
103
+ }
104
+
105
+ // Update running state. We commit a known side; we deliberately do NOT
106
+ // overwrite `prevSide` with 'unknown', otherwise a single missing-price
107
+ // trade would poison the carry-over for the rest of the stream.
108
+ state.prevPrice = trade.price
109
+ if (side === 'buy' || side === 'sell') state.prevSide = side
110
+
111
+ return { side, inferred: true }
112
+ }
113
+
114
+ // ---------------------------------------------------------------------------
115
+ // 3. Lee-Ready (quote-rule with tick-rule tiebreak)
116
+ // ---------------------------------------------------------------------------
117
+
118
+ /**
119
+ * Lee-Ready uses the same carry-over fields as the tick rule — the two
120
+ * heuristics can share a single state record because Lee-Ready falls back
121
+ * to the tick rule on a quote-mid hit.
122
+ */
123
+ export interface LeeReadyState extends TickRuleState {}
124
+
125
+ /**
126
+ * Lee-Ready (1991) quote test:
127
+ *
128
+ * If bid and ask are both finite:
129
+ * mid = (bid + ask) / 2
130
+ * price > mid → 'buy'
131
+ * price < mid → 'sell'
132
+ * price == mid → tick-rule fallback (zero spread or mid-cross)
133
+ * Else (bid/ask missing or non-finite) → tick-rule fallback.
134
+ *
135
+ * The state MUTATES exactly like `classifyTickRule` — when the quote test
136
+ * resolves, we still update `prevPrice`/`prevSide` so a subsequent
137
+ * tick-rule fallback has the latest context.
138
+ */
139
+ export function classifyLeeReady(
140
+ state: LeeReadyState,
141
+ trade: Trade,
142
+ bid: number,
143
+ ask: number,
144
+ ): AggressorResult {
145
+ const quotesUsable = Number.isFinite(bid) && Number.isFinite(ask)
146
+
147
+ if (!quotesUsable) {
148
+ return classifyTickRule(state, trade)
149
+ }
150
+
151
+ const mid = (bid + ask) / 2
152
+
153
+ if (trade.price > mid) {
154
+ state.prevPrice = trade.price
155
+ state.prevSide = 'buy'
156
+ return { side: 'buy', inferred: true }
157
+ }
158
+ if (trade.price < mid) {
159
+ state.prevPrice = trade.price
160
+ state.prevSide = 'sell'
161
+ return { side: 'sell', inferred: true }
162
+ }
163
+ // price == mid → fall back to tick rule (which updates state).
164
+ return classifyTickRule(state, trade)
165
+ }