@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,104 @@
1
+ /**
2
+ * Timeline — bar-index ↔ timestamp navigation.
3
+ *
4
+ * A `BarCalendar` is the authoritative list of bar open-times in
5
+ * milliseconds. Real markets aren't uniformly spaced: there are weekend
6
+ * gaps, half-day holiday closes, exchange maintenance windows, etc. The
7
+ * timeline functions must honor those gaps exactly — bar N and bar N+1 can
8
+ * be 60 seconds apart on a Tuesday and three days apart Friday→Monday.
9
+ *
10
+ * Both functions are pure and total: out-of-range inputs return `null`
11
+ * instead of throwing. Callers (e.g. the replay controller, the crosshair
12
+ * tooltip) should treat `null` as "no data at that position".
13
+ */
14
+ /**
15
+ * Look up the timestamp for an integer bar index.
16
+ *
17
+ * Fractional `barIndex` is floored — the timestamp returned is the
18
+ * open-time of the containing bar. (Callers that want intra-bar
19
+ * interpolation should do it themselves.)
20
+ *
21
+ * Returns `null` if the calendar is empty or the index is out of range.
22
+ */
23
+ export function barIndexToTimestamp(calendar, barIndex) {
24
+ if (calendar.length === 0)
25
+ return null;
26
+ if (!Number.isFinite(barIndex))
27
+ return null;
28
+ const idx = Math.floor(barIndex);
29
+ if (idx < 0 || idx >= calendar.length)
30
+ return null;
31
+ // We've bounds-checked the index, so this access is safe.
32
+ return calendar[idx];
33
+ }
34
+ /**
35
+ * Look up the bar index that contains a given timestamp.
36
+ *
37
+ * Uses binary search; cost is O(log n). The returned index is the bar
38
+ * whose open-time is the largest value `<= ts`. This means a timestamp
39
+ * that falls inside a non-trading gap (e.g. Saturday) resolves to the
40
+ * last bar before the gap (Friday's close), which is the intuitive
41
+ * behavior for "scrub to this wall-clock time".
42
+ *
43
+ * Returns `null` if the calendar is empty or `ts` precedes the first bar.
44
+ */
45
+ export function timestampToBarIndex(calendar, ts) {
46
+ if (calendar.length === 0)
47
+ return null;
48
+ if (!Number.isFinite(ts))
49
+ return null;
50
+ const first = calendar[0];
51
+ if (ts < first)
52
+ return null;
53
+ const last = calendar[calendar.length - 1];
54
+ if (ts >= last)
55
+ return calendar.length - 1;
56
+ // Binary search for the largest index `i` such that calendar[i] <= ts.
57
+ let lo = 0;
58
+ let hi = calendar.length - 1;
59
+ while (lo < hi) {
60
+ // Bias the midpoint up so `lo` converges to the upper bound.
61
+ const mid = (lo + hi + 1) >>> 1;
62
+ const v = calendar[mid];
63
+ if (v <= ts) {
64
+ lo = mid;
65
+ }
66
+ else {
67
+ hi = mid - 1;
68
+ }
69
+ }
70
+ return lo;
71
+ }
72
+ /**
73
+ * Compute the dominant bar interval (in ms) from a calendar.
74
+ *
75
+ * Uses the median delta between successive bars, which is robust to
76
+ * weekend and holiday gaps that would skew a simple mean. Returns
77
+ * `null` if the calendar has fewer than two bars.
78
+ *
79
+ * The replay controller uses this when `barIntervalMs` is not configured
80
+ * but a calendar is available, so wall-clock pacing self-calibrates.
81
+ */
82
+ export function inferBarIntervalMs(calendar) {
83
+ if (calendar.length < 2)
84
+ return null;
85
+ const deltas = [];
86
+ for (let i = 1; i < calendar.length; i++) {
87
+ const a = calendar[i - 1];
88
+ const b = calendar[i];
89
+ const d = b - a;
90
+ if (d > 0)
91
+ deltas.push(d);
92
+ }
93
+ if (deltas.length === 0)
94
+ return null;
95
+ deltas.sort((a, b) => a - b);
96
+ const mid = deltas.length >>> 1;
97
+ if (deltas.length % 2 === 1) {
98
+ return deltas[mid];
99
+ }
100
+ const lo = deltas[mid - 1];
101
+ const hi = deltas[mid];
102
+ return (lo + hi) / 2;
103
+ }
104
+ //# sourceMappingURL=timeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline.js","sourceRoot":"","sources":["../../src/replay/timeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAC/B,QAAqB,EACrB,QAAgB;IAEhB,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACtC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAA;IAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;IAChC,IAAI,GAAG,GAAG,CAAC,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM;QAAE,OAAO,IAAI,CAAA;IAClD,0DAA0D;IAC1D,OAAO,QAAQ,CAAC,GAAG,CAAW,CAAA;AAClC,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CAC/B,QAAqB,EACrB,EAAU;IAEV,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACtC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QAAE,OAAO,IAAI,CAAA;IACrC,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAW,CAAA;IACnC,IAAI,EAAE,GAAG,KAAK;QAAE,OAAO,IAAI,CAAA;IAC3B,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAW,CAAA;IACpD,IAAI,EAAE,IAAI,IAAI;QAAE,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAA;IAE1C,uEAAuE;IACvE,IAAI,EAAE,GAAG,CAAC,CAAA;IACV,IAAI,EAAE,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAA;IAC5B,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC;QACb,6DAA6D;QAC7D,MAAM,GAAG,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAA;QAC/B,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAW,CAAA;QACjC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;YACV,EAAE,GAAG,GAAG,CAAA;QACZ,CAAC;aAAM,CAAC;YACJ,EAAE,GAAG,GAAG,GAAG,CAAC,CAAA;QAChB,CAAC;IACL,CAAC;IACD,OAAO,EAAE,CAAA;AACb,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAqB;IACpD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAA;IACpC,MAAM,MAAM,GAAa,EAAE,CAAA;IAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAW,CAAA;QACnC,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAW,CAAA;QAC/B,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QACf,IAAI,CAAC,GAAG,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAC7B,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACpC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IAC5B,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,KAAK,CAAC,CAAA;IAC/B,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,MAAM,CAAC,GAAG,CAAW,CAAA;IAChC,CAAC;IACD,MAAM,EAAE,GAAG,MAAM,CAAC,GAAG,GAAG,CAAC,CAAW,CAAA;IACpC,MAAM,EAAE,GAAG,MAAM,CAAC,GAAG,CAAW,CAAA;IAChC,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAA;AACxB,CAAC"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Bar Replay — public types.
3
+ *
4
+ * The replay subsystem models a playhead that scrubs through a finite bar
5
+ * series. Three pacing strategies are supported:
6
+ *
7
+ * - `bar` step-by-bar; `tick()` is a no-op, callers drive position
8
+ * via `stepForward` / `stepBackward` (keyboard-driven).
9
+ * - `wallclock` real-time playback; `tick(deltaMs)` advances by
10
+ * `(deltaMs / msPerBar) * speed` bars. `speed` is a
11
+ * multiplier (1 = realtime, 10 = 10x).
12
+ * - `tick` synthetic tick replay; `tick(deltaMs)` advances by
13
+ * `(deltaMs / 100) * speed` bars (100ms per nominal step).
14
+ *
15
+ * Why this matters: TradingView's Bar Replay is wall-clock only and hides its
16
+ * state. Ours is observable via the `state` signal — any backtest engine,
17
+ * recording session, or sibling controller can subscribe and react to
18
+ * playhead changes deterministically.
19
+ */
20
+ import type { Signal } from '../reactivity/signal';
21
+ export type ReplayMode = 'paused' | 'playing';
22
+ export type ReplayPacing = 'bar' | 'wallclock' | 'tick';
23
+ export interface ReplayState {
24
+ /** Position in the full data series; fractional values are allowed and
25
+ * represent sub-bar progress for wall-clock / tick pacing. Callers that
26
+ * need an integer bar index should `Math.floor(position)`. */
27
+ position: number;
28
+ /** Inclusive lower bound of the playhead (clamp floor). */
29
+ start: number;
30
+ /** Inclusive upper bound of the playhead (clamp ceiling). Typically
31
+ * `totalBars - 1`. */
32
+ end: number;
33
+ mode: ReplayMode;
34
+ pacing: ReplayPacing;
35
+ /** Pacing-dependent rate:
36
+ * - `wallclock`: multiplier (1.0 = realtime).
37
+ * - `bar`: reserved; ignored by `tick()`.
38
+ * - `tick`: multiplier (1.0 = 1 bar per 100ms). */
39
+ speed: number;
40
+ }
41
+ export interface ReplayControllerInit {
42
+ start?: number;
43
+ end?: number;
44
+ pacing?: ReplayPacing;
45
+ speed?: number;
46
+ /** Bar interval in milliseconds. Used by wall-clock pacing to compute
47
+ * how many bars one wall-second represents. Defaults to 60_000 (1m). */
48
+ barIntervalMs?: number;
49
+ }
50
+ export interface ReplayController {
51
+ /** Reactive view of the entire replay state. Subscribers fire after any
52
+ * mutation that changes the state object (Object.is equality). */
53
+ readonly state: Signal<ReplayState>;
54
+ /** Set the inclusive `[start, end]` range. The current position is
55
+ * re-clamped into the new range. Throws if `end < start`. */
56
+ setRange(start: number, end: number): void;
57
+ /** Seek the playhead to an absolute position; clamped to `[start, end]`. */
58
+ seekTo(position: number): void;
59
+ /** Seek by a relative delta; clamped to `[start, end]`. */
60
+ seekBy(delta: number): void;
61
+ /** Advance exactly one bar (`position += 1`), clamped to `end`. If the
62
+ * step lands on `end`, mode transitions to `paused`. */
63
+ stepForward(): void;
64
+ /** Retreat exactly one bar (`position -= 1`), clamped to `start`. */
65
+ stepBackward(): void;
66
+ /** Begin playback from the current position using the configured
67
+ * pacing/speed. If already at `end`, this is a no-op. */
68
+ play(): void;
69
+ pause(): void;
70
+ /** Toggle between `playing` and `paused`. */
71
+ toggle(): void;
72
+ setPacing(p: ReplayPacing): void;
73
+ /** Set the speed multiplier. Throws on `speed <= 0` (reverse play not
74
+ * supported in v1 — see Open Question in the controller header). */
75
+ setSpeed(s: number): void;
76
+ /** Frame-loop hook. The chart's render loop calls this with the elapsed
77
+ * wall-clock time since the last frame; the controller decides whether
78
+ * to advance `position` based on `mode`, `pacing`, and `speed`.
79
+ *
80
+ * Returns `true` if `position` (and therefore `state`) changed, so the
81
+ * caller can request a re-render. Returns `false` for no-op frames
82
+ * (paused, bar-pacing, or sub-bar accumulation that didn't cross a
83
+ * whole-bar boundary — though in this v1 we keep `tick()` stateless and
84
+ * always commit the fractional advance, so any non-zero advance returns
85
+ * `true`). */
86
+ tick(deltaMs: number): boolean;
87
+ /** Tear down. After `dispose()`, all mutators become silent no-ops and
88
+ * the `state` signal stops emitting. */
89
+ dispose(): void;
90
+ }
91
+ /** Factory shape — matches the exported function. Re-stated here so callers
92
+ * importing only the types file can type-check controller construction. */
93
+ export type CreateReplayController = (init?: ReplayControllerInit) => ReplayController;
94
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/replay/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAElD,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAA;AAC7C,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,WAAW,GAAG,MAAM,CAAA;AAEvD,MAAM,WAAW,WAAW;IACxB;;mEAE+D;IAC/D,QAAQ,EAAE,MAAM,CAAA;IAChB,2DAA2D;IAC3D,KAAK,EAAE,MAAM,CAAA;IACb;2BACuB;IACvB,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,UAAU,CAAA;IAChB,MAAM,EAAE,YAAY,CAAA;IACpB;;;6DAGyD;IACzD,KAAK,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,oBAAoB;IACjC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,YAAY,CAAA;IACrB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;6EACyE;IACzE,aAAa,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC7B;uEACmE;IACnE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,WAAW,CAAC,CAAA;IAEnC;kEAC8D;IAC9D,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAE1C,4EAA4E;IAC5E,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,2DAA2D;IAC3D,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B;6DACyD;IACzD,WAAW,IAAI,IAAI,CAAA;IACnB,qEAAqE;IACrE,YAAY,IAAI,IAAI,CAAA;IAEpB;8DAC0D;IAC1D,IAAI,IAAI,IAAI,CAAA;IACZ,KAAK,IAAI,IAAI,CAAA;IACb,6CAA6C;IAC7C,MAAM,IAAI,IAAI,CAAA;IAEd,SAAS,CAAC,CAAC,EAAE,YAAY,GAAG,IAAI,CAAA;IAChC;yEACqE;IACrE,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAEzB;;;;;;;;;mBASe;IACf,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAA;IAE9B;6CACyC;IACzC,OAAO,IAAI,IAAI,CAAA;CAClB;AAED;4EAC4E;AAC5E,MAAM,MAAM,sBAAsB,GAAG,CACjC,IAAI,CAAC,EAAE,oBAAoB,KAC1B,gBAAgB,CAAA"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Bar Replay — public types.
3
+ *
4
+ * The replay subsystem models a playhead that scrubs through a finite bar
5
+ * series. Three pacing strategies are supported:
6
+ *
7
+ * - `bar` step-by-bar; `tick()` is a no-op, callers drive position
8
+ * via `stepForward` / `stepBackward` (keyboard-driven).
9
+ * - `wallclock` real-time playback; `tick(deltaMs)` advances by
10
+ * `(deltaMs / msPerBar) * speed` bars. `speed` is a
11
+ * multiplier (1 = realtime, 10 = 10x).
12
+ * - `tick` synthetic tick replay; `tick(deltaMs)` advances by
13
+ * `(deltaMs / 100) * speed` bars (100ms per nominal step).
14
+ *
15
+ * Why this matters: TradingView's Bar Replay is wall-clock only and hides its
16
+ * state. Ours is observable via the `state` signal — any backtest engine,
17
+ * recording session, or sibling controller can subscribe and react to
18
+ * playhead changes deterministically.
19
+ */
20
+ export {};
21
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/replay/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Anchored zoom — ROADMAP §1.3.
3
+ *
4
+ * Why this exists in its own file: the "data point under the mouse stays under
5
+ * the mouse" guarantee is the single most-felt detail of chart UX. Getting it
6
+ * mathematically right (so the screen-pixel offset survives sequential zooms
7
+ * within sub-pixel error) is the only path to a feel that matches TradingView.
8
+ *
9
+ * Forward equation, before zoom:
10
+ *
11
+ * mouseX = (i_anchor - firstVisibleIndex) * barWidth + leftPadding
12
+ *
13
+ * Solve for `i_anchor` first (this is the bar index the user is pointing at):
14
+ *
15
+ * i_anchor = (mouseX - leftPadding) / barWidth + firstVisibleIndex
16
+ *
17
+ * Then pick the new bar width and solve the same equation for the new first
18
+ * visible index so that `mouseX` still maps to `i_anchor`:
19
+ *
20
+ * barWidth' = clamp(barWidth * zoomFactor, minBarWidth, maxBarWidth)
21
+ * firstVisibleIndex' = i_anchor - (mouseX - leftPadding) / barWidth'
22
+ *
23
+ * Two non-obvious cases worth flagging:
24
+ *
25
+ * 1. **zoomFactor === 1** is a true no-op; we short-circuit so floating-point
26
+ * round-trips don't sneak a sub-ULP drift into the state on every mouse-move.
27
+ *
28
+ * 2. **barWidth' got clamped** (user keeps wheeling at the min/max). Once the
29
+ * clamp engages we re-derive `firstVisibleIndex` from the clamped width.
30
+ * The anchor is preserved at the clamped width, which means the visible
31
+ * anchor point will *drift in screen X by the same amount the wheel tried
32
+ * to push the bar width past the clamp*. This is the expected behavior —
33
+ * it's how the user feels "the chart can't zoom any further" rather than
34
+ * watching the wheel become a silent dead-zone.
35
+ */
36
+ export interface AnchoredZoomOptions {
37
+ /** Screen X (logical px) where the wheel event fired. */
38
+ mouseX: number;
39
+ /** Logical px on the left edge before bar 0. */
40
+ leftPadding: number;
41
+ /** Current `firstVisibleIndex` (fractional). */
42
+ firstVisibleIndex: number;
43
+ /** Current `barWidth` in logical px. */
44
+ barWidth: number;
45
+ /** > 1 zoom in (wheel up), < 1 zoom out, === 1 no-op. */
46
+ zoomFactor: number;
47
+ /** Lower clamp for the resulting bar width. Default 0.5 logical px. */
48
+ minBarWidth?: number;
49
+ /** Upper clamp for the resulting bar width. Default 200 logical px. */
50
+ maxBarWidth?: number;
51
+ }
52
+ export interface AnchoredZoomResult {
53
+ firstVisibleIndex: number;
54
+ barWidth: number;
55
+ }
56
+ /**
57
+ * @internal — building block used by `createTimeScale / interaction handlers`. Reachable today
58
+ * via the top-level `@klinechart-quant/core` barrel but **NOT
59
+ * part of the supported public API**. typedoc / api-extractor
60
+ * hide it from generated docs. Prefer the controller factory
61
+ * for stable user code. Closes API audit BLOCKER-002.
62
+ */
63
+ export declare function computeAnchoredZoom(opts: AnchoredZoomOptions): AnchoredZoomResult;
64
+ //# sourceMappingURL=anchoredZoom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anchoredZoom.d.ts","sourceRoot":"","sources":["../../src/scale/anchoredZoom.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,MAAM,WAAW,mBAAmB;IAChC,yDAAyD;IACzD,MAAM,EAAE,MAAM,CAAA;IACd,gDAAgD;IAChD,WAAW,EAAE,MAAM,CAAA;IACnB,gDAAgD;IAChD,iBAAiB,EAAE,MAAM,CAAA;IACzB,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAA;IAChB,yDAAyD;IACzD,UAAU,EAAE,MAAM,CAAA;IAClB,uEAAuE;IACvE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,uEAAuE;IACvE,WAAW,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,kBAAkB;IAC/B,iBAAiB,EAAE,MAAM,CAAA;IACzB,QAAQ,EAAE,MAAM,CAAA;CACnB;AAKD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,mBAAmB,GAAG,kBAAkB,CAmCjF"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Anchored zoom — ROADMAP §1.3.
3
+ *
4
+ * Why this exists in its own file: the "data point under the mouse stays under
5
+ * the mouse" guarantee is the single most-felt detail of chart UX. Getting it
6
+ * mathematically right (so the screen-pixel offset survives sequential zooms
7
+ * within sub-pixel error) is the only path to a feel that matches TradingView.
8
+ *
9
+ * Forward equation, before zoom:
10
+ *
11
+ * mouseX = (i_anchor - firstVisibleIndex) * barWidth + leftPadding
12
+ *
13
+ * Solve for `i_anchor` first (this is the bar index the user is pointing at):
14
+ *
15
+ * i_anchor = (mouseX - leftPadding) / barWidth + firstVisibleIndex
16
+ *
17
+ * Then pick the new bar width and solve the same equation for the new first
18
+ * visible index so that `mouseX` still maps to `i_anchor`:
19
+ *
20
+ * barWidth' = clamp(barWidth * zoomFactor, minBarWidth, maxBarWidth)
21
+ * firstVisibleIndex' = i_anchor - (mouseX - leftPadding) / barWidth'
22
+ *
23
+ * Two non-obvious cases worth flagging:
24
+ *
25
+ * 1. **zoomFactor === 1** is a true no-op; we short-circuit so floating-point
26
+ * round-trips don't sneak a sub-ULP drift into the state on every mouse-move.
27
+ *
28
+ * 2. **barWidth' got clamped** (user keeps wheeling at the min/max). Once the
29
+ * clamp engages we re-derive `firstVisibleIndex` from the clamped width.
30
+ * The anchor is preserved at the clamped width, which means the visible
31
+ * anchor point will *drift in screen X by the same amount the wheel tried
32
+ * to push the bar width past the clamp*. This is the expected behavior —
33
+ * it's how the user feels "the chart can't zoom any further" rather than
34
+ * watching the wheel become a silent dead-zone.
35
+ */
36
+ const DEFAULT_MIN_BAR_WIDTH = 0.5;
37
+ const DEFAULT_MAX_BAR_WIDTH = 200;
38
+ /**
39
+ * @internal — building block used by `createTimeScale / interaction handlers`. Reachable today
40
+ * via the top-level `@klinechart-quant/core` barrel but **NOT
41
+ * part of the supported public API**. typedoc / api-extractor
42
+ * hide it from generated docs. Prefer the controller factory
43
+ * for stable user code. Closes API audit BLOCKER-002.
44
+ */
45
+ export function computeAnchoredZoom(opts) {
46
+ const { mouseX, leftPadding, firstVisibleIndex, barWidth, zoomFactor, minBarWidth = DEFAULT_MIN_BAR_WIDTH, maxBarWidth = DEFAULT_MAX_BAR_WIDTH, } = opts;
47
+ // No-op short-circuit — avoid round-trip rounding when not zooming.
48
+ if (zoomFactor === 1) {
49
+ return { firstVisibleIndex, barWidth };
50
+ }
51
+ // Defensive: a non-positive or non-finite current barWidth would blow up the
52
+ // inverse formula. The TimeScale itself never lets barWidth reach 0, but we
53
+ // belt-and-brace it here so the function is total.
54
+ if (!Number.isFinite(barWidth) || barWidth <= 0) {
55
+ return { firstVisibleIndex, barWidth };
56
+ }
57
+ const dx = mouseX - leftPadding;
58
+ const iAnchor = dx / barWidth + firstVisibleIndex;
59
+ const rawNewBarWidth = barWidth * zoomFactor;
60
+ const newBarWidth = Math.min(Math.max(rawNewBarWidth, minBarWidth), maxBarWidth);
61
+ const newFirstVisibleIndex = iAnchor - dx / newBarWidth;
62
+ return {
63
+ firstVisibleIndex: newFirstVisibleIndex,
64
+ barWidth: newBarWidth,
65
+ };
66
+ }
67
+ //# sourceMappingURL=anchoredZoom.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anchoredZoom.js","sourceRoot":"","sources":["../../src/scale/anchoredZoom.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAwBH,MAAM,qBAAqB,GAAG,GAAG,CAAA;AACjC,MAAM,qBAAqB,GAAG,GAAG,CAAA;AAEjC;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAyB;IACzD,MAAM,EACF,MAAM,EACN,WAAW,EACX,iBAAiB,EACjB,QAAQ,EACR,UAAU,EACV,WAAW,GAAG,qBAAqB,EACnC,WAAW,GAAG,qBAAqB,GACtC,GAAG,IAAI,CAAA;IAER,oEAAoE;IACpE,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;QACnB,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,CAAA;IAC1C,CAAC;IAED,6EAA6E;IAC7E,4EAA4E;IAC5E,mDAAmD;IACnD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,IAAI,CAAC,EAAE,CAAC;QAC9C,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,CAAA;IAC1C,CAAC;IAED,MAAM,EAAE,GAAG,MAAM,GAAG,WAAW,CAAA;IAC/B,MAAM,OAAO,GAAG,EAAE,GAAG,QAAQ,GAAG,iBAAiB,CAAA;IAEjD,MAAM,cAAc,GAAG,QAAQ,GAAG,UAAU,CAAA;IAC5C,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,WAAW,CAAC,EAAE,WAAW,CAAC,CAAA;IAEhF,MAAM,oBAAoB,GAAG,OAAO,GAAG,EAAE,GAAG,WAAW,CAAA;IAEvD,OAAO;QACH,iBAAiB,EAAE,oBAAoB;QACvC,QAAQ,EAAE,WAAW;KACxB,CAAA;AACL,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * PriceScale factory — price ↔ screen Y (ROADMAP §1.2) + origin-shift policy
3
+ * (ROADMAP §2.5).
4
+ *
5
+ * Linear mapping (top-origin, Y grows downward):
6
+ *
7
+ * t = (p - visibleMin) / (visibleMax - visibleMin)
8
+ * y = height - t * height
9
+ * inverse: p = visibleMin + (1 - y / height) * (visibleMax - visibleMin)
10
+ *
11
+ * Log mapping (only valid for strictly positive ranges):
12
+ *
13
+ * t = (ln(p) - ln(visibleMin)) / (ln(visibleMax) - ln(visibleMin))
14
+ * y = height - t * height
15
+ * inverse: p = exp(ln(visibleMin) + (1 - y / height) * (ln(visibleMax) - ln(visibleMin)))
16
+ *
17
+ * Origin-shift policy: lives inside this scale and is consulted on every
18
+ * `setVisibleRange`. It is intentionally in **linear-price space**, applied
19
+ * *before* the log transform — that matches the existing engine and keeps the
20
+ * "shift is just a translation" mental model clean. (Log-space shift is also
21
+ * mathematically valid; it would compose better with sub-cent log-axis zoom on
22
+ * astronomically high prices, but we have no such use case and this keeps
23
+ * parity with the legacy renderer.)
24
+ *
25
+ * Degenerate range handling: when `visibleMin === visibleMax`, `priceToY` and
26
+ * `yToPrice` would divide by zero. We pin the output to `height / 2` (the
27
+ * geometric center) and document that the caller should treat this as
28
+ * "everything at the same price"; this is preferred over throwing because
29
+ * mid-frame `setVisibleRange(p, p)` is reachable from external data feeds and
30
+ * we don't want one bad row to crash the chart.
31
+ */
32
+ import type { PriceScale, ScaleMode } from './types';
33
+ export interface PriceScaleConfig {
34
+ /** Initial mode. Default `'linear'`. */
35
+ initialMode?: ScaleMode;
36
+ /** Initial visibleMin. Default 0. (Must be > 0 if initialMode === 'log'.) */
37
+ initialVisibleMin?: number;
38
+ /** Initial visibleMax. Default 100. */
39
+ initialVisibleMax?: number;
40
+ /** Initial canvas height in logical px. Default 480. */
41
+ initialHeight?: number;
42
+ /**
43
+ * Threshold for the origin-shift rebaseline policy. Default 0.01 (1% of
44
+ * visible range). See `originShift.ts` for the rationale.
45
+ */
46
+ originShiftThreshold?: number;
47
+ }
48
+ export declare function createPriceScale(config?: PriceScaleConfig): PriceScale;
49
+ //# sourceMappingURL=createPriceScale.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createPriceScale.d.ts","sourceRoot":"","sources":["../../src/scale/createPriceScale.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAEpD,MAAM,WAAW,gBAAgB;IAC7B,wCAAwC;IACxC,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB,6EAA6E;IAC7E,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,uCAAuC;IACvC,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,wDAAwD;IACxD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAA;CAChC;AAED,wBAAgB,gBAAgB,CAAC,MAAM,GAAE,gBAAqB,GAAG,UAAU,CA2K1E"}
@@ -0,0 +1,175 @@
1
+ /**
2
+ * PriceScale factory — price ↔ screen Y (ROADMAP §1.2) + origin-shift policy
3
+ * (ROADMAP §2.5).
4
+ *
5
+ * Linear mapping (top-origin, Y grows downward):
6
+ *
7
+ * t = (p - visibleMin) / (visibleMax - visibleMin)
8
+ * y = height - t * height
9
+ * inverse: p = visibleMin + (1 - y / height) * (visibleMax - visibleMin)
10
+ *
11
+ * Log mapping (only valid for strictly positive ranges):
12
+ *
13
+ * t = (ln(p) - ln(visibleMin)) / (ln(visibleMax) - ln(visibleMin))
14
+ * y = height - t * height
15
+ * inverse: p = exp(ln(visibleMin) + (1 - y / height) * (ln(visibleMax) - ln(visibleMin)))
16
+ *
17
+ * Origin-shift policy: lives inside this scale and is consulted on every
18
+ * `setVisibleRange`. It is intentionally in **linear-price space**, applied
19
+ * *before* the log transform — that matches the existing engine and keeps the
20
+ * "shift is just a translation" mental model clean. (Log-space shift is also
21
+ * mathematically valid; it would compose better with sub-cent log-axis zoom on
22
+ * astronomically high prices, but we have no such use case and this keeps
23
+ * parity with the legacy renderer.)
24
+ *
25
+ * Degenerate range handling: when `visibleMin === visibleMax`, `priceToY` and
26
+ * `yToPrice` would divide by zero. We pin the output to `height / 2` (the
27
+ * geometric center) and document that the caller should treat this as
28
+ * "everything at the same price"; this is preferred over throwing because
29
+ * mid-frame `setVisibleRange(p, p)` is reachable from external data feeds and
30
+ * we don't want one bad row to crash the chart.
31
+ */
32
+ import { createSignal } from '../reactivity/signal';
33
+ import { KLineChartError } from '../errors';
34
+ import { createOriginShiftPolicy } from './originShift';
35
+ export function createPriceScale(config = {}) {
36
+ const initialMode = config.initialMode ?? 'linear';
37
+ const initialVisibleMin = config.initialVisibleMin ?? 0;
38
+ const initialVisibleMax = config.initialVisibleMax ?? 100;
39
+ const initialHeight = config.initialHeight ?? 480;
40
+ if (!(initialVisibleMax >= initialVisibleMin)) {
41
+ throw new KLineChartError('SCALE_RANGE_INVALID', `createPriceScale: initialVisibleMax (${initialVisibleMax}) must be >= initialVisibleMin (${initialVisibleMin})`);
42
+ }
43
+ if (initialMode === 'log' && !(initialVisibleMin > 0)) {
44
+ throw new KLineChartError('SCALE_LOG_REQUIRES_POSITIVE', `createPriceScale: log mode requires visibleMin > 0, got ${initialVisibleMin}`);
45
+ }
46
+ if (!(initialHeight > 0)) {
47
+ throw new KLineChartError('SCALE_HEIGHT_INVALID', `createPriceScale: initialHeight must be > 0, got ${initialHeight}`);
48
+ }
49
+ const mode = createSignal(initialMode);
50
+ const visibleMin = createSignal(initialVisibleMin);
51
+ const visibleMax = createSignal(initialVisibleMax);
52
+ const height = createSignal(initialHeight);
53
+ const initialRef = (initialVisibleMin + initialVisibleMax) / 2;
54
+ const policy = createOriginShiftPolicy(initialRef, config.originShiftThreshold);
55
+ const originShiftRef = createSignal(policy.ref);
56
+ let disposed = false;
57
+ /**
58
+ * Post-dispose: mutator calls become silent no-ops. See createTimeScale.ts
59
+ * for the rationale + API audit BLOCKER-004 reference. Returns `true` when
60
+ * the operation should proceed.
61
+ */
62
+ const guard = () => !disposed;
63
+ /**
64
+ * Run `policy.maybeRebaseline` with the latest visible range and, if it
65
+ * rebased, mirror the new value into the reactive `originShiftRef` signal
66
+ * so subscribers (uniform updaters, GPU buffer uploaders) can pick it up.
67
+ */
68
+ const syncOriginShift = () => {
69
+ const min = visibleMin.peek();
70
+ const max = visibleMax.peek();
71
+ const range = max - min;
72
+ const mid = (min + max) / 2;
73
+ if (policy.maybeRebaseline(mid, range)) {
74
+ originShiftRef.set(policy.ref);
75
+ }
76
+ };
77
+ const priceToYLinear = (p) => {
78
+ const min = visibleMin.peek();
79
+ const max = visibleMax.peek();
80
+ const h = height.peek();
81
+ const span = max - min;
82
+ if (span <= 0)
83
+ return h / 2;
84
+ const t = (p - min) / span;
85
+ return h - t * h;
86
+ };
87
+ const priceToYLog = (p) => {
88
+ const min = visibleMin.peek();
89
+ const max = visibleMax.peek();
90
+ const h = height.peek();
91
+ // Defensive — setMode('log') already rejects bad ranges, but we keep
92
+ // priceToY total so a stray p<=0 doesn't NaN out the whole chart.
93
+ if (p <= 0 || min <= 0 || max <= 0 || max <= min)
94
+ return h / 2;
95
+ const t = (Math.log(p) - Math.log(min)) / (Math.log(max) - Math.log(min));
96
+ return h - t * h;
97
+ };
98
+ const yToPriceLinear = (y) => {
99
+ const min = visibleMin.peek();
100
+ const max = visibleMax.peek();
101
+ const h = height.peek();
102
+ const span = max - min;
103
+ if (span <= 0)
104
+ return min;
105
+ return min + (1 - y / h) * span;
106
+ };
107
+ const yToPriceLog = (y) => {
108
+ const min = visibleMin.peek();
109
+ const max = visibleMax.peek();
110
+ const h = height.peek();
111
+ if (min <= 0 || max <= 0 || max <= min)
112
+ return min;
113
+ const lmin = Math.log(min);
114
+ const lmax = Math.log(max);
115
+ const ly = lmin + (1 - y / h) * (lmax - lmin);
116
+ return Math.exp(ly);
117
+ };
118
+ const scale = {
119
+ mode,
120
+ visibleMin,
121
+ visibleMax,
122
+ height,
123
+ originShiftRef: originShiftRef,
124
+ priceToY(p) {
125
+ return mode.peek() === 'log' ? priceToYLog(p) : priceToYLinear(p);
126
+ },
127
+ yToPrice(y) {
128
+ return mode.peek() === 'log' ? yToPriceLog(y) : yToPriceLinear(y);
129
+ },
130
+ setMode(next) {
131
+ if (!guard())
132
+ return;
133
+ if (next === 'log') {
134
+ const min = visibleMin.peek();
135
+ const max = visibleMax.peek();
136
+ if (!(min > 0) || !(max > 0)) {
137
+ throw new KLineChartError('SCALE_LOG_REQUIRES_POSITIVE', `PriceScale.setMode('log'): requires visibleMin > 0 and visibleMax > 0, got min=${min}, max=${max}`);
138
+ }
139
+ }
140
+ mode.set(next);
141
+ },
142
+ setVisibleRange(min, max) {
143
+ if (!guard())
144
+ return;
145
+ if (!Number.isFinite(min) || !Number.isFinite(max)) {
146
+ throw new KLineChartError('SCALE_RANGE_INVALID', `PriceScale.setVisibleRange: both bounds must be finite, got min=${min}, max=${max}`);
147
+ }
148
+ if (max < min) {
149
+ throw new KLineChartError('SCALE_RANGE_INVALID', `PriceScale.setVisibleRange: max (${max}) must be >= min (${min})`);
150
+ }
151
+ if (mode.peek() === 'log' && !(min > 0)) {
152
+ throw new KLineChartError('SCALE_LOG_REQUIRES_POSITIVE', `PriceScale.setVisibleRange: log mode requires min > 0, got ${min}`);
153
+ }
154
+ visibleMin.set(min);
155
+ visibleMax.set(max);
156
+ syncOriginShift();
157
+ },
158
+ setHeight(h) {
159
+ if (!guard())
160
+ return;
161
+ if (!(h > 0)) {
162
+ throw new KLineChartError('SCALE_HEIGHT_INVALID', `PriceScale.setHeight: height must be > 0, got ${h}`);
163
+ }
164
+ height.set(h);
165
+ },
166
+ toShiftedFp32(p) {
167
+ return policy.shift(p);
168
+ },
169
+ dispose() {
170
+ disposed = true;
171
+ },
172
+ };
173
+ return scale;
174
+ }
175
+ //# sourceMappingURL=createPriceScale.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createPriceScale.js","sourceRoot":"","sources":["../../src/scale/createPriceScale.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * TimeScale factory — discrete bar-index ↔ screen X mapping (ROADMAP §1.1).
3
+ *
4
+ * The math is one-line in each direction; the value of this factory is the
5
+ * reactive plumbing (signals so adapters can subscribe) and the optional
6
+ * wall-clock calendar that maps bar indices ↔ timestamps.
7
+ *
8
+ * forward: x(i) = (i - firstVisibleIndex) * barWidth + leftPadding
9
+ * inverse: i(x) = (x - leftPadding) / barWidth + firstVisibleIndex
10
+ *
11
+ * Calendar semantics: when the user attaches a `barTimestamps` array, we treat
12
+ * bar index `i` as the array index. Integer indices map directly; fractional
13
+ * indices linearly interpolate between neighboring timestamps. Anything
14
+ * outside `[0, N-1]` returns `null` — the caller decides whether to clamp,
15
+ * extrapolate, or display a "—" label.
16
+ */
17
+ import type { TimeScale } from './types';
18
+ export interface TimeScaleConfig {
19
+ /** Default firstVisibleIndex. Fractional/negative allowed. Default 0. */
20
+ initialFirstVisibleIndex?: number;
21
+ /** Default barWidth in logical px. Must be > 0. Default 8. */
22
+ initialBarWidth?: number;
23
+ /** Default leftPadding in logical px. Default 0. */
24
+ initialLeftPadding?: number;
25
+ }
26
+ export declare function createTimeScale(config?: TimeScaleConfig): TimeScale;
27
+ //# sourceMappingURL=createTimeScale.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createTimeScale.d.ts","sourceRoot":"","sources":["../../src/scale/createTimeScale.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAExC,MAAM,WAAW,eAAe;IAC5B,yEAAyE;IACzE,wBAAwB,CAAC,EAAE,MAAM,CAAA;IACjC,8DAA8D;IAC9D,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,oDAAoD;IACpD,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC9B;AAED,wBAAgB,eAAe,CAAC,MAAM,GAAE,eAAoB,GAAG,SAAS,CAuHvE"}