@363045841yyt/klinechart-core 0.7.12-alpha.1 → 0.7.13

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 (277) hide show
  1. package/dist/controllers/createIndicatorSelectorController.d.ts.map +1 -1
  2. package/dist/controllers/createIndicatorSelectorController.js +4 -6
  3. package/dist/controllers/createIndicatorSelectorController.js.map +1 -1
  4. package/dist/controllers/index.d.ts +0 -1
  5. package/dist/controllers/index.d.ts.map +1 -1
  6. package/dist/controllers/index.js +0 -1
  7. package/dist/controllers/index.js.map +1 -1
  8. package/dist/engine/chart.d.ts +6 -2
  9. package/dist/engine/chart.d.ts.map +1 -1
  10. package/dist/engine/chart.js +26 -23
  11. package/dist/engine/chart.js.map +1 -1
  12. package/dist/engine/indicators/indicator.worker.js +32 -4
  13. package/dist/engine/indicators/indicator.worker.js.map +1 -1
  14. package/dist/engine/indicators/indicatorDefinitionRegistry.d.ts +5 -3
  15. package/dist/engine/indicators/indicatorDefinitionRegistry.d.ts.map +1 -1
  16. package/dist/engine/indicators/indicatorDefinitionRegistry.js +26 -1
  17. package/dist/engine/indicators/indicatorDefinitionRegistry.js.map +1 -1
  18. package/dist/engine/indicators/indicatorMetadata.d.ts +54 -1
  19. package/dist/engine/indicators/indicatorMetadata.d.ts.map +1 -1
  20. package/dist/engine/indicators/indicatorMetadata.js.map +1 -1
  21. package/dist/engine/indicators/indicatorRuntime.d.ts +12 -117
  22. package/dist/engine/indicators/indicatorRuntime.d.ts.map +1 -1
  23. package/dist/engine/indicators/indicatorRuntime.js +124 -1308
  24. package/dist/engine/indicators/indicatorRuntime.js.map +1 -1
  25. package/dist/engine/indicators/scheduler.d.ts +19 -143
  26. package/dist/engine/indicators/scheduler.d.ts.map +1 -1
  27. package/dist/engine/indicators/scheduler.js +81 -434
  28. package/dist/engine/indicators/scheduler.js.map +1 -1
  29. package/dist/engine/indicators/stateComposer.d.ts.map +1 -1
  30. package/dist/engine/indicators/stateComposer.js +15 -47
  31. package/dist/engine/indicators/stateComposer.js.map +1 -1
  32. package/dist/engine/indicators/workerProtocol.d.ts +12 -36
  33. package/dist/engine/indicators/workerProtocol.d.ts.map +1 -1
  34. package/dist/engine/indicators/workerProtocol.js.map +1 -1
  35. package/dist/engine/renderers/Indicator/atr.d.ts +2 -1
  36. package/dist/engine/renderers/Indicator/atr.d.ts.map +1 -1
  37. package/dist/engine/renderers/Indicator/atr.js +11 -9
  38. package/dist/engine/renderers/Indicator/atr.js.map +1 -1
  39. package/dist/engine/renderers/Indicator/boll.d.ts +4 -1
  40. package/dist/engine/renderers/Indicator/boll.d.ts.map +1 -1
  41. package/dist/engine/renderers/Indicator/boll.js +24 -10
  42. package/dist/engine/renderers/Indicator/boll.js.map +1 -1
  43. package/dist/engine/renderers/Indicator/cci.d.ts +2 -1
  44. package/dist/engine/renderers/Indicator/cci.d.ts.map +1 -1
  45. package/dist/engine/renderers/Indicator/cci.js +12 -10
  46. package/dist/engine/renderers/Indicator/cci.js.map +1 -1
  47. package/dist/engine/renderers/Indicator/chaikinVol.d.ts +4 -1
  48. package/dist/engine/renderers/Indicator/chaikinVol.d.ts.map +1 -1
  49. package/dist/engine/renderers/Indicator/chaikinVol.js +21 -7
  50. package/dist/engine/renderers/Indicator/chaikinVol.js.map +1 -1
  51. package/dist/engine/renderers/Indicator/cmf.d.ts +4 -1
  52. package/dist/engine/renderers/Indicator/cmf.d.ts.map +1 -1
  53. package/dist/engine/renderers/Indicator/cmf.js +20 -7
  54. package/dist/engine/renderers/Indicator/cmf.js.map +1 -1
  55. package/dist/engine/renderers/Indicator/dema.d.ts +2 -0
  56. package/dist/engine/renderers/Indicator/dema.d.ts.map +1 -1
  57. package/dist/engine/renderers/Indicator/dema.js +19 -8
  58. package/dist/engine/renderers/Indicator/dema.js.map +1 -1
  59. package/dist/engine/renderers/Indicator/donchian.d.ts +4 -1
  60. package/dist/engine/renderers/Indicator/donchian.d.ts.map +1 -1
  61. package/dist/engine/renderers/Indicator/donchian.js +20 -8
  62. package/dist/engine/renderers/Indicator/donchian.js.map +1 -1
  63. package/dist/engine/renderers/Indicator/ene.d.ts +12 -1
  64. package/dist/engine/renderers/Indicator/ene.d.ts.map +1 -1
  65. package/dist/engine/renderers/Indicator/ene.js +25 -11
  66. package/dist/engine/renderers/Indicator/ene.js.map +1 -1
  67. package/dist/engine/renderers/Indicator/expma.d.ts +4 -1
  68. package/dist/engine/renderers/Indicator/expma.d.ts.map +1 -1
  69. package/dist/engine/renderers/Indicator/expma.js +22 -9
  70. package/dist/engine/renderers/Indicator/expma.js.map +1 -1
  71. package/dist/engine/renderers/Indicator/fastk.d.ts +2 -1
  72. package/dist/engine/renderers/Indicator/fastk.d.ts.map +1 -1
  73. package/dist/engine/renderers/Indicator/fastk.js +12 -10
  74. package/dist/engine/renderers/Indicator/fastk.js.map +1 -1
  75. package/dist/engine/renderers/Indicator/fib.d.ts +2 -0
  76. package/dist/engine/renderers/Indicator/fib.d.ts.map +1 -1
  77. package/dist/engine/renderers/Indicator/fib.js +26 -8
  78. package/dist/engine/renderers/Indicator/fib.js.map +1 -1
  79. package/dist/engine/renderers/Indicator/hma.d.ts +2 -0
  80. package/dist/engine/renderers/Indicator/hma.d.ts.map +1 -1
  81. package/dist/engine/renderers/Indicator/hma.js +19 -8
  82. package/dist/engine/renderers/Indicator/hma.js.map +1 -1
  83. package/dist/engine/renderers/Indicator/hv.d.ts +4 -1
  84. package/dist/engine/renderers/Indicator/hv.d.ts.map +1 -1
  85. package/dist/engine/renderers/Indicator/hv.js +18 -8
  86. package/dist/engine/renderers/Indicator/hv.js.map +1 -1
  87. package/dist/engine/renderers/Indicator/ichimoku.d.ts +4 -1
  88. package/dist/engine/renderers/Indicator/ichimoku.d.ts.map +1 -1
  89. package/dist/engine/renderers/Indicator/ichimoku.js +27 -8
  90. package/dist/engine/renderers/Indicator/ichimoku.js.map +1 -1
  91. package/dist/engine/renderers/Indicator/index.d.ts +27 -28
  92. package/dist/engine/renderers/Indicator/index.d.ts.map +1 -1
  93. package/dist/engine/renderers/Indicator/index.js +27 -28
  94. package/dist/engine/renderers/Indicator/index.js.map +1 -1
  95. package/dist/engine/renderers/Indicator/kama.d.ts +2 -0
  96. package/dist/engine/renderers/Indicator/kama.d.ts.map +1 -1
  97. package/dist/engine/renderers/Indicator/kama.js +19 -8
  98. package/dist/engine/renderers/Indicator/kama.js.map +1 -1
  99. package/dist/engine/renderers/Indicator/keltner.d.ts +4 -1
  100. package/dist/engine/renderers/Indicator/keltner.d.ts.map +1 -1
  101. package/dist/engine/renderers/Indicator/keltner.js +20 -8
  102. package/dist/engine/renderers/Indicator/keltner.js.map +1 -1
  103. package/dist/engine/renderers/Indicator/kst.d.ts +2 -1
  104. package/dist/engine/renderers/Indicator/kst.d.ts.map +1 -1
  105. package/dist/engine/renderers/Indicator/kst.js +13 -11
  106. package/dist/engine/renderers/Indicator/kst.js.map +1 -1
  107. package/dist/engine/renderers/Indicator/ma.d.ts +4 -1
  108. package/dist/engine/renderers/Indicator/ma.d.ts.map +1 -1
  109. package/dist/engine/renderers/Indicator/ma.js +36 -8
  110. package/dist/engine/renderers/Indicator/ma.js.map +1 -1
  111. package/dist/engine/renderers/Indicator/macd.d.ts +1 -1
  112. package/dist/engine/renderers/Indicator/macd.d.ts.map +1 -1
  113. package/dist/engine/renderers/Indicator/macd.js +9 -10
  114. package/dist/engine/renderers/Indicator/macd.js.map +1 -1
  115. package/dist/engine/renderers/Indicator/mainIndicatorLegend.d.ts.map +1 -1
  116. package/dist/engine/renderers/Indicator/mainIndicatorLegend.js +38 -136
  117. package/dist/engine/renderers/Indicator/mainIndicatorLegend.js.map +1 -1
  118. package/dist/engine/renderers/Indicator/mfi.d.ts +4 -1
  119. package/dist/engine/renderers/Indicator/mfi.d.ts.map +1 -1
  120. package/dist/engine/renderers/Indicator/mfi.js +20 -7
  121. package/dist/engine/renderers/Indicator/mfi.js.map +1 -1
  122. package/dist/engine/renderers/Indicator/mom.d.ts +2 -1
  123. package/dist/engine/renderers/Indicator/mom.d.ts.map +1 -1
  124. package/dist/engine/renderers/Indicator/mom.js +12 -10
  125. package/dist/engine/renderers/Indicator/mom.js.map +1 -1
  126. package/dist/engine/renderers/Indicator/obv.d.ts +4 -1
  127. package/dist/engine/renderers/Indicator/obv.d.ts.map +1 -1
  128. package/dist/engine/renderers/Indicator/obv.js +19 -7
  129. package/dist/engine/renderers/Indicator/obv.js.map +1 -1
  130. package/dist/engine/renderers/Indicator/parkinson.d.ts +4 -1
  131. package/dist/engine/renderers/Indicator/parkinson.d.ts.map +1 -1
  132. package/dist/engine/renderers/Indicator/parkinson.js +18 -8
  133. package/dist/engine/renderers/Indicator/parkinson.js.map +1 -1
  134. package/dist/engine/renderers/Indicator/pivot.d.ts +2 -0
  135. package/dist/engine/renderers/Indicator/pivot.d.ts.map +1 -1
  136. package/dist/engine/renderers/Indicator/pivot.js +43 -8
  137. package/dist/engine/renderers/Indicator/pivot.js.map +1 -1
  138. package/dist/engine/renderers/Indicator/pvt.d.ts +4 -1
  139. package/dist/engine/renderers/Indicator/pvt.d.ts.map +1 -1
  140. package/dist/engine/renderers/Indicator/pvt.js +19 -7
  141. package/dist/engine/renderers/Indicator/pvt.js.map +1 -1
  142. package/dist/engine/renderers/Indicator/roc.d.ts +4 -1
  143. package/dist/engine/renderers/Indicator/roc.d.ts.map +1 -1
  144. package/dist/engine/renderers/Indicator/roc.js +20 -7
  145. package/dist/engine/renderers/Indicator/roc.js.map +1 -1
  146. package/dist/engine/renderers/Indicator/rsi.d.ts +2 -1
  147. package/dist/engine/renderers/Indicator/rsi.d.ts.map +1 -1
  148. package/dist/engine/renderers/Indicator/rsi.js +14 -11
  149. package/dist/engine/renderers/Indicator/rsi.js.map +1 -1
  150. package/dist/engine/renderers/Indicator/sar.d.ts +4 -1
  151. package/dist/engine/renderers/Indicator/sar.d.ts.map +1 -1
  152. package/dist/engine/renderers/Indicator/sar.js +18 -8
  153. package/dist/engine/renderers/Indicator/sar.js.map +1 -1
  154. package/dist/engine/renderers/Indicator/stoch.d.ts +2 -1
  155. package/dist/engine/renderers/Indicator/stoch.d.ts.map +1 -1
  156. package/dist/engine/renderers/Indicator/stoch.js +10 -11
  157. package/dist/engine/renderers/Indicator/stoch.js.map +1 -1
  158. package/dist/engine/renderers/Indicator/structure.d.ts +4 -1
  159. package/dist/engine/renderers/Indicator/structure.d.ts.map +1 -1
  160. package/dist/engine/renderers/Indicator/structure.js +21 -8
  161. package/dist/engine/renderers/Indicator/structure.js.map +1 -1
  162. package/dist/engine/renderers/Indicator/supertrend.d.ts +4 -1
  163. package/dist/engine/renderers/Indicator/supertrend.d.ts.map +1 -1
  164. package/dist/engine/renderers/Indicator/supertrend.js +18 -8
  165. package/dist/engine/renderers/Indicator/supertrend.js.map +1 -1
  166. package/dist/engine/renderers/Indicator/tema.d.ts +2 -0
  167. package/dist/engine/renderers/Indicator/tema.d.ts.map +1 -1
  168. package/dist/engine/renderers/Indicator/tema.js +19 -8
  169. package/dist/engine/renderers/Indicator/tema.js.map +1 -1
  170. package/dist/engine/renderers/Indicator/trix.d.ts +4 -1
  171. package/dist/engine/renderers/Indicator/trix.d.ts.map +1 -1
  172. package/dist/engine/renderers/Indicator/trix.js +30 -8
  173. package/dist/engine/renderers/Indicator/trix.js.map +1 -1
  174. package/dist/engine/renderers/Indicator/vma.d.ts +4 -1
  175. package/dist/engine/renderers/Indicator/vma.d.ts.map +1 -1
  176. package/dist/engine/renderers/Indicator/vma.js +20 -7
  177. package/dist/engine/renderers/Indicator/vma.js.map +1 -1
  178. package/dist/engine/renderers/Indicator/volumeProfile.d.ts +4 -1
  179. package/dist/engine/renderers/Indicator/volumeProfile.d.ts.map +1 -1
  180. package/dist/engine/renderers/Indicator/volumeProfile.js +28 -8
  181. package/dist/engine/renderers/Indicator/volumeProfile.js.map +1 -1
  182. package/dist/engine/renderers/Indicator/vwap.d.ts +4 -1
  183. package/dist/engine/renderers/Indicator/vwap.d.ts.map +1 -1
  184. package/dist/engine/renderers/Indicator/vwap.js +19 -7
  185. package/dist/engine/renderers/Indicator/vwap.js.map +1 -1
  186. package/dist/engine/renderers/Indicator/wma.d.ts +2 -0
  187. package/dist/engine/renderers/Indicator/wma.d.ts.map +1 -1
  188. package/dist/engine/renderers/Indicator/wma.js +19 -8
  189. package/dist/engine/renderers/Indicator/wma.js.map +1 -1
  190. package/dist/engine/renderers/Indicator/wmsr.d.ts +2 -1
  191. package/dist/engine/renderers/Indicator/wmsr.d.ts.map +1 -1
  192. package/dist/engine/renderers/Indicator/wmsr.js +12 -10
  193. package/dist/engine/renderers/Indicator/wmsr.js.map +1 -1
  194. package/dist/engine/renderers/Indicator/zones.d.ts +2 -0
  195. package/dist/engine/renderers/Indicator/zones.d.ts.map +1 -1
  196. package/dist/engine/renderers/Indicator/zones.js +24 -8
  197. package/dist/engine/renderers/Indicator/zones.js.map +1 -1
  198. package/dist/engine/renderers/paneTitle.d.ts +4 -10
  199. package/dist/engine/renderers/paneTitle.d.ts.map +1 -1
  200. package/dist/engine/renderers/paneTitle.js +28 -6
  201. package/dist/engine/renderers/paneTitle.js.map +1 -1
  202. package/dist/engine/renderers/subVolume.js +0 -3
  203. package/dist/engine/renderers/subVolume.js.map +1 -1
  204. package/dist/version.d.ts +1 -1
  205. package/dist/version.d.ts.map +1 -1
  206. package/dist/version.js +1 -1
  207. package/dist/version.js.map +1 -1
  208. package/package.json +4 -4
  209. package/src/controllers/__tests__/indicatorSelector.test.ts +4 -3
  210. package/src/controllers/createIndicatorSelectorController.ts +4 -6
  211. package/src/controllers/index.ts +0 -4
  212. package/src/engine/chart.ts +30 -22
  213. package/src/engine/indicators/__tests__/registerBuiltins.test.ts +14 -23
  214. package/src/engine/indicators/__tests__/scheduler.test.ts +14 -14
  215. package/src/engine/indicators/__tests__/stateComposer.test.ts +7 -4
  216. package/src/engine/indicators/indicator.worker.ts +36 -4
  217. package/src/engine/indicators/indicatorDefinitionRegistry.ts +38 -3
  218. package/src/engine/indicators/indicatorMetadata.ts +66 -1
  219. package/src/engine/indicators/indicatorRuntime.ts +121 -1447
  220. package/src/engine/indicators/scheduler.ts +85 -489
  221. package/src/engine/indicators/stateComposer.ts +16 -60
  222. package/src/engine/indicators/workerProtocol.ts +14 -36
  223. package/src/engine/renderers/Indicator/atr.ts +14 -11
  224. package/src/engine/renderers/Indicator/boll.ts +33 -10
  225. package/src/engine/renderers/Indicator/cci.ts +15 -14
  226. package/src/engine/renderers/Indicator/chaikinVol.ts +29 -7
  227. package/src/engine/renderers/Indicator/cmf.ts +28 -7
  228. package/src/engine/renderers/Indicator/dema.ts +28 -9
  229. package/src/engine/renderers/Indicator/donchian.ts +28 -9
  230. package/src/engine/renderers/Indicator/ene.ts +34 -11
  231. package/src/engine/renderers/Indicator/expma.ts +31 -9
  232. package/src/engine/renderers/Indicator/fastk.ts +15 -14
  233. package/src/engine/renderers/Indicator/fib.ts +29 -9
  234. package/src/engine/renderers/Indicator/hma.ts +28 -9
  235. package/src/engine/renderers/Indicator/hv.ts +27 -8
  236. package/src/engine/renderers/Indicator/ichimoku.ts +31 -9
  237. package/src/engine/renderers/Indicator/index.ts +27 -28
  238. package/src/engine/renderers/Indicator/kama.ts +28 -9
  239. package/src/engine/renderers/Indicator/keltner.ts +28 -9
  240. package/src/engine/renderers/Indicator/kst.ts +16 -19
  241. package/src/engine/renderers/Indicator/ma.ts +44 -9
  242. package/src/engine/renderers/Indicator/macd.ts +31 -36
  243. package/src/engine/renderers/Indicator/mainIndicatorLegend.ts +43 -162
  244. package/src/engine/renderers/Indicator/mfi.ts +28 -7
  245. package/src/engine/renderers/Indicator/mom.ts +15 -14
  246. package/src/engine/renderers/Indicator/obv.ts +27 -7
  247. package/src/engine/renderers/Indicator/parkinson.ts +27 -8
  248. package/src/engine/renderers/Indicator/pivot.ts +47 -9
  249. package/src/engine/renderers/Indicator/pvt.ts +27 -7
  250. package/src/engine/renderers/Indicator/roc.ts +29 -7
  251. package/src/engine/renderers/Indicator/rsi.ts +14 -17
  252. package/src/engine/renderers/Indicator/sar.ts +26 -9
  253. package/src/engine/renderers/Indicator/stoch.ts +13 -16
  254. package/src/engine/renderers/Indicator/structure.ts +31 -8
  255. package/src/engine/renderers/Indicator/supertrend.ts +26 -9
  256. package/src/engine/renderers/Indicator/tema.ts +28 -9
  257. package/src/engine/renderers/Indicator/trix.ts +39 -8
  258. package/src/engine/renderers/Indicator/vma.ts +28 -7
  259. package/src/engine/renderers/Indicator/volumeProfile.ts +40 -8
  260. package/src/engine/renderers/Indicator/vwap.ts +27 -7
  261. package/src/engine/renderers/Indicator/wma.ts +28 -9
  262. package/src/engine/renderers/Indicator/wmsr.ts +15 -14
  263. package/src/engine/renderers/Indicator/zones.ts +29 -9
  264. package/src/engine/renderers/__tests__/mainIndicatorLegend.renderer.test.ts +142 -79
  265. package/src/engine/renderers/paneTitle.ts +43 -18
  266. package/src/engine/renderers/subVolume.ts +0 -2
  267. package/src/version.ts +1 -1
  268. package/dist/engine/renderers/Indicator/macdLegend.d.ts +0 -13
  269. package/dist/engine/renderers/Indicator/macdLegend.d.ts.map +0 -1
  270. package/dist/engine/renderers/Indicator/macdLegend.js +0 -116
  271. package/dist/engine/renderers/Indicator/macdLegend.js.map +0 -1
  272. package/dist/engine/renderers/Indicator/subPaneConfig.d.ts +0 -16
  273. package/dist/engine/renderers/Indicator/subPaneConfig.d.ts.map +0 -1
  274. package/dist/engine/renderers/Indicator/subPaneConfig.js +0 -194
  275. package/dist/engine/renderers/Indicator/subPaneConfig.js.map +0 -1
  276. package/src/engine/renderers/Indicator/macdLegend.ts +0 -141
  277. package/src/engine/renderers/Indicator/subPaneConfig.ts +0 -265
@@ -1,9 +1,3 @@
1
- /**
2
- * Indicator 纯计算运行时
3
- * 不依赖 PluginHost/StateStore,只负责计算和缓存
4
- * 可被主线程(inline fallback)或 Worker 使用
5
- */
6
-
7
1
  import type { KLineData } from '../../types/price'
8
2
  import {
9
3
  calcMAData,
@@ -46,401 +40,107 @@ import {
46
40
  calcZonesData,
47
41
  calcVolumeProfileData,
48
42
  DEFAULT_MA_PERIODS,
49
- DEFAULT_ATR_PERIOD,
50
- DEFAULT_VMA_PERIOD,
51
- DEFAULT_STRUCTURE_LEFT,
52
- DEFAULT_STRUCTURE_RIGHT,
53
- DEFAULT_ZONES_OB_LOOKBACK,
54
- DEFAULT_VP_BINS,
55
- DEFAULT_VP_LOOKBACK,
56
- DEFAULT_VP_VALUE_AREA,
57
- DEFAULT_VWAP_SESSION_GAP_MS,
58
- DEFAULT_CMF_PERIOD,
59
- DEFAULT_MFI_PERIOD,
60
- DEFAULT_FIB_PERIOD,
61
- DEFAULT_WMA_PERIOD,
62
- DEFAULT_DEMA_PERIOD,
63
- DEFAULT_TEMA_PERIOD,
64
- DEFAULT_HMA_PERIOD,
65
- DEFAULT_KAMA_PERIOD,
66
- DEFAULT_KAMA_FAST_PERIOD,
67
- DEFAULT_KAMA_SLOW_PERIOD,
68
- DEFAULT_SAR_STEP,
69
- DEFAULT_SAR_MAX_STEP,
70
- DEFAULT_SUPERTREND_ATR_PERIOD,
71
- DEFAULT_SUPERTREND_MULTIPLIER,
72
- DEFAULT_KELTNER_EMA_PERIOD,
73
- DEFAULT_KELTNER_ATR_PERIOD,
74
- DEFAULT_KELTNER_MULTIPLIER,
75
- DEFAULT_DONCHIAN_PERIOD,
76
- DEFAULT_ICHIMOKU_TENKAN,
77
- DEFAULT_ICHIMOKU_KIJUN,
78
- DEFAULT_ICHIMOKU_SPAN_B,
79
- DEFAULT_ICHIMOKU_DISPLACEMENT,
80
- DEFAULT_ROC_PERIOD,
81
- DEFAULT_TRIX_PERIOD,
82
- DEFAULT_TRIX_SIGNAL_PERIOD,
83
- DEFAULT_HV_PERIOD,
84
- DEFAULT_HV_ANNUALIZATION,
85
- DEFAULT_PARKINSON_PERIOD,
86
- DEFAULT_PARKINSON_ANNUALIZATION,
87
- DEFAULT_CHAIKIN_VOL_EMA_PERIOD,
88
- DEFAULT_CHAIKIN_VOL_ROC_PERIOD,
89
- type MAFlags,
90
- type BOLLPoint,
91
- type EXPMAPoint,
92
- type ENEPoint,
93
- type STOCHPoint,
94
- type KSTPoint,
95
- type MACDPoint,
96
- type SARPoint,
97
- type SuperTrendPoint,
98
- type KeltnerPoint,
99
- type DonchianPoint,
100
- type IchimokuPoint,
101
- type PivotPoint,
102
- type FibPoint,
103
- type StructureSnapshot,
104
- type Zone,
105
- type VolumeProfileResult,
106
43
  } from './calculators'
107
- import type {
108
- BOLLSchedulerConfig,
109
- EXPMASchedulerConfig,
110
- ENESchedulerConfig,
111
- RSISchedulerConfig,
112
- CCISchedulerConfig,
113
- STOCHSchedulerConfig,
114
- MOMSchedulerConfig,
115
- WMSRSchedulerConfig,
116
- KSTSchedulerConfig,
117
- FASTKSchedulerConfig,
118
- MACDSchedulerConfig,
119
- ATRSchedulerConfig,
120
- WMASchedulerConfig,
121
- DEMASchedulerConfig,
122
- TEMASchedulerConfig,
123
- HMASchedulerConfig,
124
- KAMASchedulerConfig,
125
- SARSchedulerConfig,
126
- SuperTrendSchedulerConfig,
127
- KeltnerSchedulerConfig,
128
- DonchianSchedulerConfig,
129
- IchimokuSchedulerConfig,
130
- ROCSchedulerConfig,
131
- TRIXSchedulerConfig,
132
- HVSchedulerConfig,
133
- ParkinsonSchedulerConfig,
134
- ChaikinVolSchedulerConfig,
135
- VMASchedulerConfig,
136
- OBVSchedulerConfig,
137
- PVTSchedulerConfig,
138
- VWAPSchedulerConfig,
139
- CMFSchedulerConfig,
140
- MFISchedulerConfig,
141
- PivotSchedulerConfig,
142
- FibSchedulerConfig,
143
- StructureSchedulerConfig,
144
- ZonesSchedulerConfig,
145
- VolumeProfileSchedulerConfig,
146
- IndicatorConfigSnapshot,
147
- IndicatorSeriesBundle,
148
- } from './workerProtocol'
44
+ import type { IndicatorRuntimeDescriptor } from './indicatorMetadata'
45
+ import type { IndicatorConfigSnapshot, IndicatorSeriesBundle } from './workerProtocol'
46
+
47
+ export const CALCULATOR_MAP: Record<string, (data: KLineData[], config: any) => unknown> = {
48
+ calcCCIData: (data, c) => calcCCIData(data, c.period),
49
+ calcMACDData: (data, c) => calcMACDData(data, c.fastPeriod, c.slowPeriod, c.signalPeriod),
50
+ calcMAData: (data, c) => {
51
+ const r: Record<number, (number | undefined)[]> = {}
52
+ for (const p of DEFAULT_MA_PERIODS) {
53
+ if ((c as any)['ma' + p]) r[p] = calcMAData(data, p)
54
+ }
55
+ return { series: r, enabledPeriods: Object.keys(r).map(Number) }
56
+ },
57
+ calcRSIData: (data, c) => {
58
+ const p = [c.period1, c.period2, c.period3]
59
+ const s = [c.showRSI1, c.showRSI2, c.showRSI3]
60
+ const r: Record<number, (number | undefined)[]> = {}
61
+ for (let i = 0; i < 3; i++) {
62
+ if (s[i]) r[p[i]] = calcRSIData(data, p[i])
63
+ }
64
+ return { series: r, enabledPeriods: Object.keys(r).map(Number) }
65
+ },
66
+ calcTRIXData: (data, c) => calcTRIXData(data, c.period, c.signalPeriod),
67
+ calcBOLLData: (data, c) => calcBOLLData(data, c.period, c.multiplier),
68
+ calcEXPMAData: (data, c) => calcEXPMAData(data, c.fastPeriod, c.slowPeriod),
69
+ calcENEData: (data, c) => calcENEData(data, c.period, c.deviation),
70
+ calcSTOCHData: (data, c) => calcSTOCHData(data, c.n, c.m),
71
+ calcMOMData: (data, c) => calcMOMData(data, c.period),
72
+ calcWMSRData: (data, c) => calcWMSRData(data, c.period),
73
+ calcKSTData: (data, c) => calcKSTData(data, c.roc1, c.roc2, c.roc3, c.roc4, c.signalPeriod),
74
+ calcFASTKData: (data, c) => calcFASTKData(data, c.period),
75
+ calcATRData: (data, c) => calcATRData(data, c.period),
76
+ calcWMAData: (data, c) => calcWMAData(data, c.period),
77
+ calcDEMAData: (data, c) => calcDEMAData(data, c.period),
78
+ calcTEMAData: (data, c) => calcTEMAData(data, c.period),
79
+ calcHMAData: (data, c) => calcHMAData(data, c.period),
80
+ calcKAMAData: (data, c) => calcKAMAData(data, c.period, c.fastPeriod, c.slowPeriod),
81
+ calcSARData: (data, c) => calcSARData(data, c.step, c.maxStep),
82
+ calcSuperTrendData: (data, c) => calcSuperTrendData(data, c.atrPeriod, c.multiplier),
83
+ calcKeltnerData: (data, c) => calcKeltnerData(data, c.emaPeriod, c.atrPeriod, c.multiplier),
84
+ calcDonchianData: (data, c) => calcDonchianData(data, c.period),
85
+ calcIchimokuData: (data, c) => calcIchimokuData(data, c.tenkanPeriod, c.kijunPeriod, c.spanBPeriod, c.displacement),
86
+ calcROCData: (data, c) => calcROCData(data, c.period),
87
+ calcHVData: (data, c) => calcHVData(data, c.period, c.annualizationFactor),
88
+ calcParkinsonData: (data, c) => calcParkinsonData(data, c.period, c.annualizationFactor),
89
+ calcChaikinVolData: (data, c) => calcChaikinVolData(data, c.emaPeriod, c.rocPeriod),
90
+ calcVMAData: (data, c) => calcVMAData(data, c.period),
91
+ calcOBVData: (data, c) => calcOBVData(data),
92
+ calcPVTData: (data, c) => calcPVTData(data),
93
+ calcVWAPData: (data, c) => calcVWAPData(data, c.sessionResetGapMs),
94
+ calcCMFData: (data, c) => calcCMFData(data, c.period),
95
+ calcMFIData: (data, c) => calcMFIData(data, c.period),
96
+ calcPivotData: (data, c) => calcPivotData(data),
97
+ calcFibData: (data, c) => calcFibData(data, c.period),
98
+ calcStructureData: (data, c) => calcStructureData(data, c.leftWindow, c.rightWindow, c.breakoutSource),
99
+ calcZonesData: (data, c) => calcZonesData(data, c.obLookback, 5, 2, 'close'),
100
+ calcVolumeProfileData: (data, c) => calcVolumeProfileData(data, c.bins, c.lookback, c.valueAreaPercent),
101
+ }
149
102
 
150
- /**
151
- * 可见范围
152
- */
153
- interface VisibleRange {
154
- start: number
155
- end: number
103
+ export function createWorkerCompute(descriptor: { computeKey: string }): (data: KLineData[], config: any) => unknown {
104
+ return CALCULATOR_MAP[descriptor.computeKey] ?? ((_data: KLineData[], _config: any) => {
105
+ console.warn(`[IndicatorRuntime] Unknown computeKey: ${descriptor.computeKey}`)
106
+ return []
107
+ })
156
108
  }
157
109
 
158
- /**
159
- * 计算运行时
160
- * 管理数据、配置、缓存和脏标记
161
- */
162
110
  export class IndicatorRuntime {
163
- // 数据
164
111
  private currentData: KLineData[] = []
165
112
  private dataVersion = 0
166
-
167
- // 配置
168
- private config: IndicatorConfigSnapshot = this.getDefaultConfig()
169
113
  private configVersion = 0
114
+ private dataDirty = true
115
+ private configMap = new Map<string, any>()
116
+ private seriesMap = new Map<string, unknown>()
117
+ private dirtyFlags = new Map<string, boolean>()
118
+ private descriptorMap = new Map<string, IndicatorRuntimeDescriptor>()
170
119
 
171
- // 缓存的 series
172
- private cachedSeries: Record<number, (number | undefined)[]> = {}
173
- private cachedBollSeries: BOLLPoint[] = []
174
- private cachedExpmaSeries: EXPMAPoint[] = []
175
- private cachedEneSeries: ENEPoint[] = []
176
- private cachedRsiSeries: Record<number, (number | undefined)[]> = {}
177
- private cachedCciSeries: (number | undefined)[] = []
178
- private cachedStochSeries: STOCHPoint[] = []
179
- private cachedMomSeries: (number | undefined)[] = []
180
- private cachedWmsrSeries: (number | undefined)[] = []
181
- private cachedKstSeries: KSTPoint[] = []
182
- private cachedFastkSeries: (number | undefined)[] = []
183
- private cachedMacdSeries: MACDPoint[] = []
184
- private cachedAtrSeries: (number | undefined)[] = []
185
- private cachedWmaSeries: (number | undefined)[] = []
186
- private cachedDemaSeries: (number | undefined)[] = []
187
- private cachedTemaSeries: (number | undefined)[] = []
188
- private cachedHmaSeries: (number | undefined)[] = []
189
- private cachedKamaSeries: (number | undefined)[] = []
190
- private cachedSarSeries: (SARPoint | undefined)[] = []
191
- private cachedSupertrendSeries: (SuperTrendPoint | undefined)[] = []
192
- private cachedKeltnerSeries: (KeltnerPoint | undefined)[] = []
193
- private cachedDonchianSeries: (DonchianPoint | undefined)[] = []
194
- private cachedIchimokuSeries: (IchimokuPoint | undefined)[] = []
195
- private cachedRocSeries: (number | undefined)[] = []
196
- private cachedTrixSeries: (number | undefined)[] = []
197
- private cachedTrixSignalSeries: (number | undefined)[] = []
198
- private cachedHvSeries: (number | undefined)[] = []
199
- private cachedParkinsonSeries: (number | undefined)[] = []
200
- private cachedChaikinVolSeries: (number | undefined)[] = []
201
- private cachedVmaSeries: (number | undefined)[] = []
202
- private cachedObvSeries: (number | undefined)[] = []
203
- private cachedPvtSeries: (number | undefined)[] = []
204
- private cachedVwapSeries: (number | undefined)[] = []
205
- private cachedCmfSeries: (number | undefined)[] = []
206
- private cachedMfiSeries: (number | undefined)[] = []
207
- private cachedPivotSeries: (PivotPoint | undefined)[] = []
208
- private cachedFibSeries: (FibPoint | undefined)[] = []
209
- private cachedStructureSeries: StructureSnapshot = { swings: [], events: [], trend: 'range' }
210
- private cachedZonesSeries: Zone[] = []
211
- private cachedVolumeProfileSeries: VolumeProfileResult = { bins: [], poc: 0, vah: 0, val: 0, totalVolume: 0 }
212
-
213
- // 脏标记
214
- private dirtyData = true
215
- private dirtyMAConfig = true
216
- private dirtyBollConfig = true
217
- private dirtyExpmaConfig = true
218
- private dirtyEneConfig = true
219
- private dirtyRsiConfig = true
220
- private dirtyCciConfig = true
221
- private dirtyStochConfig = true
222
- private dirtyMomConfig = true
223
- private dirtyWmsrConfig = true
224
- private dirtyKstConfig = true
225
- private dirtyFastkConfig = true
226
- private dirtyMacdConfig = true
227
- private dirtyAtrConfig = true
228
- private dirtyWmaConfig = true
229
- private dirtyDemaConfig = true
230
- private dirtyTemaConfig = true
231
- private dirtyHmaConfig = true
232
- private dirtyKamaConfig = true
233
- private dirtySarConfig = true
234
- private dirtySupertrendConfig = true
235
- private dirtyKeltnerConfig = true
236
- private dirtyDonchianConfig = true
237
- private dirtyIchimokuConfig = true
238
- private dirtyRocConfig = true
239
- private dirtyTrixConfig = true
240
- private dirtyHvConfig = true
241
- private dirtyParkinsonConfig = true
242
- private dirtyChaikinVolConfig = true
243
- private dirtyVmaConfig = true
244
- private dirtyObvConfig = true
245
- private dirtyPvtConfig = true
246
- private dirtyVwapConfig = true
247
- private dirtyCmfConfig = true
248
- private dirtyMfiConfig = true
249
- private dirtyPivotConfig = true
250
- private dirtyFibConfig = true
251
- private dirtyStructureConfig = true
252
- private dirtyZonesConfig = true
253
- private dirtyVolumeProfileConfig = true
254
-
255
- private getDefaultConfig(): IndicatorConfigSnapshot {
256
- return {
257
- ma: { ma5: true, ma10: true, ma20: true, ma30: true, ma60: true },
258
- boll: {
259
- period: 20,
260
- multiplier: 2,
261
- showUpper: true,
262
- showMiddle: true,
263
- showLower: true,
264
- showBand: true,
265
- },
266
- expma: { fastPeriod: 12, slowPeriod: 50 },
267
- ene: { period: 10, deviation: 11 },
268
- rsi: {
269
- period1: 6,
270
- period2: 12,
271
- period3: 24,
272
- showRSI1: true,
273
- showRSI2: true,
274
- showRSI3: true,
275
- },
276
- cci: { period: 14, showCCI: true },
277
- stoch: { n: 9, m: 3, showK: true, showD: true },
278
- mom: { period: 10, showMOM: true },
279
- wmsr: { period: 14, showWMSR: true },
280
- kst: {
281
- roc1: 10,
282
- roc2: 15,
283
- roc3: 20,
284
- roc4: 30,
285
- signalPeriod: 9,
286
- showKST: true,
287
- showSignal: true,
288
- },
289
- fastk: { period: 9, showFASTK: true },
290
- macd: {
291
- fastPeriod: 12,
292
- slowPeriod: 26,
293
- signalPeriod: 9,
294
- showDIF: true,
295
- showDEA: true,
296
- showBAR: true,
297
- },
298
- atr: { period: DEFAULT_ATR_PERIOD, showATR: true },
299
- wma: { period: DEFAULT_WMA_PERIOD, showWMA: true },
300
- dema: { period: DEFAULT_DEMA_PERIOD, showDEMA: true },
301
- tema: { period: DEFAULT_TEMA_PERIOD, showTEMA: true },
302
- hma: { period: DEFAULT_HMA_PERIOD, showHMA: true },
303
- kama: {
304
- period: DEFAULT_KAMA_PERIOD,
305
- fastPeriod: DEFAULT_KAMA_FAST_PERIOD,
306
- slowPeriod: DEFAULT_KAMA_SLOW_PERIOD,
307
- showKAMA: true,
308
- },
309
- sar: { step: DEFAULT_SAR_STEP, maxStep: DEFAULT_SAR_MAX_STEP, showSAR: true },
310
- supertrend: {
311
- atrPeriod: DEFAULT_SUPERTREND_ATR_PERIOD,
312
- multiplier: DEFAULT_SUPERTREND_MULTIPLIER,
313
- showSuperTrend: true,
314
- },
315
- keltner: {
316
- emaPeriod: DEFAULT_KELTNER_EMA_PERIOD,
317
- atrPeriod: DEFAULT_KELTNER_ATR_PERIOD,
318
- multiplier: DEFAULT_KELTNER_MULTIPLIER,
319
- showUpper: true,
320
- showMiddle: true,
321
- showLower: true,
322
- },
323
- donchian: {
324
- period: DEFAULT_DONCHIAN_PERIOD,
325
- showUpper: true,
326
- showMiddle: true,
327
- showLower: true,
328
- },
329
- ichimoku: {
330
- tenkanPeriod: DEFAULT_ICHIMOKU_TENKAN,
331
- kijunPeriod: DEFAULT_ICHIMOKU_KIJUN,
332
- spanBPeriod: DEFAULT_ICHIMOKU_SPAN_B,
333
- displacement: DEFAULT_ICHIMOKU_DISPLACEMENT,
334
- showTenkan: true,
335
- showKijun: true,
336
- showSpanA: true,
337
- showSpanB: true,
338
- showCloud: true,
339
- showChikou: true,
340
- },
341
- roc: { period: DEFAULT_ROC_PERIOD, showROC: true },
342
- trix: {
343
- period: DEFAULT_TRIX_PERIOD,
344
- signalPeriod: DEFAULT_TRIX_SIGNAL_PERIOD,
345
- showTRIX: true,
346
- showSignal: true,
347
- },
348
- hv: {
349
- period: DEFAULT_HV_PERIOD,
350
- annualizationFactor: DEFAULT_HV_ANNUALIZATION,
351
- showHV: true,
352
- },
353
- parkinson: {
354
- period: DEFAULT_PARKINSON_PERIOD,
355
- annualizationFactor: DEFAULT_PARKINSON_ANNUALIZATION,
356
- showParkinson: true,
357
- },
358
- chaikinVol: {
359
- emaPeriod: DEFAULT_CHAIKIN_VOL_EMA_PERIOD,
360
- rocPeriod: DEFAULT_CHAIKIN_VOL_ROC_PERIOD,
361
- showChaikinVol: true,
362
- },
363
- vma: { period: DEFAULT_VMA_PERIOD, showVMA: true },
364
- obv: { showOBV: true },
365
- pvt: { showPVT: true },
366
- vwap: { sessionResetGapMs: DEFAULT_VWAP_SESSION_GAP_MS, showVWAP: true },
367
- cmf: { period: DEFAULT_CMF_PERIOD, showCMF: true },
368
- mfi: { period: DEFAULT_MFI_PERIOD, showMFI: true },
369
- pivot: { showPP: true, showR1: true, showR2: true, showR3: false, showS1: true, showS2: true, showS3: false },
370
- fib: { period: DEFAULT_FIB_PERIOD, showLevels: true },
371
- structure: {
372
- leftWindow: DEFAULT_STRUCTURE_LEFT,
373
- rightWindow: DEFAULT_STRUCTURE_RIGHT,
374
- breakoutSource: 'close',
375
- showSwingLabels: true,
376
- showBOS: true,
377
- showCHOCH: true,
378
- showProvisional: false,
379
- },
380
- zones: {
381
- showFVG: true,
382
- showOB: true,
383
- showFilledZones: false,
384
- obLookback: DEFAULT_ZONES_OB_LOOKBACK,
385
- },
386
- volumeProfile: {
387
- bins: DEFAULT_VP_BINS,
388
- lookback: DEFAULT_VP_LOOKBACK,
389
- valueAreaPercent: DEFAULT_VP_VALUE_AREA,
390
- showPOC: true,
391
- showValueArea: true,
392
- },
393
- rsiPaneId: 'sub_RSI',
394
- cciPaneId: 'sub_CCI',
395
- stochPaneId: 'sub_STOCH',
396
- momPaneId: 'sub_MOM',
397
- wmsrPaneId: 'sub_WMSR',
398
- kstPaneId: 'sub_KST',
399
- fastkPaneId: 'sub_FASTK',
400
- macdPaneId: 'sub_MACD',
401
- atrPaneId: 'sub_ATR',
402
- wmaPaneId: 'sub_WMA',
403
- demaPaneId: 'sub_DEMA',
404
- temaPaneId: 'sub_TEMA',
405
- hmaPaneId: 'sub_HMA',
406
- kamaPaneId: 'sub_KAMA',
407
- sarPaneId: 'sub_SAR',
408
- supertrendPaneId: 'sub_SuperTrend',
409
- keltnerPaneId: 'sub_Keltner',
410
- donchianPaneId: 'sub_Donchian',
411
- ichimokuPaneId: 'sub_Ichimoku',
412
- rocPaneId: 'sub_ROC',
413
- trixPaneId: 'sub_TRIX',
414
- hvPaneId: 'sub_HV',
415
- parkinsonPaneId: 'sub_Parkinson',
416
- chaikinVolPaneId: 'sub_ChaikinVol',
417
- vmaPaneId: 'sub_VMA',
418
- obvPaneId: 'sub_OBV',
419
- pvtPaneId: 'sub_PVT',
420
- vwapPaneId: 'sub_VWAP',
421
- cmfPaneId: 'sub_CMF',
422
- mfiPaneId: 'sub_MFI',
423
- pivotPaneId: 'sub_Pivot',
424
- fibPaneId: 'sub_Fib',
425
- structurePaneId: 'sub_Structure',
426
- zonesPaneId: 'sub_Zones',
427
- volumeProfilePaneId: 'sub_VolumeProfile',
120
+ constructor(descriptors: IndicatorRuntimeDescriptor[] = []) {
121
+ for (const d of descriptors) {
122
+ this.addDescriptor(d)
428
123
  }
429
124
  }
430
125
 
431
- /**
432
- * 更新数据
433
- */
126
+ addDescriptor(d: IndicatorRuntimeDescriptor): void {
127
+ const configKey = d.configKey ?? 'unknown'
128
+ if (this.descriptorMap.has(configKey)) return
129
+ this.descriptorMap.set(configKey, d)
130
+ const def = typeof d.defaultConfig === 'function'
131
+ ? (d.defaultConfig as () => any)()
132
+ : d.defaultConfig
133
+ this.configMap.set(configKey, { ...def })
134
+ this.dirtyFlags.set(configKey, true)
135
+ }
136
+
434
137
  setData(data: KLineData[], version: number): void {
435
- if (this.dataVersion === version && !this.dirtyData) return
138
+ if (this.dataVersion === version && !this.dataDirty) return
436
139
  this.currentData = data
437
140
  this.dataVersion = version
438
- this.dirtyData = true
141
+ this.dataDirty = true
439
142
  }
440
143
 
441
- /**
442
- * 更新配置
443
- */
444
144
  private shallowEqual(a: Record<string, unknown>, b: Record<string, unknown>): boolean {
445
145
  const keysA = Object.keys(a)
446
146
  const keysB = Object.keys(b)
@@ -451,1098 +151,72 @@ export class IndicatorRuntime {
451
151
  return true
452
152
  }
453
153
 
454
- /**
455
- * 更新配置(仅值变更时才设置脏标记)
456
- */
457
154
  setConfig(config: Partial<IndicatorConfigSnapshot>, version: number): void {
458
- // 合并配置(仅值变更时才标记脏)
459
- if (config.ma !== undefined && !this.shallowEqual(config.ma as unknown as Record<string, unknown>, this.config.ma as unknown as Record<string, unknown>)) {
460
- this.config.ma = { ...this.config.ma, ...config.ma }
461
- this.dirtyMAConfig = true
462
- }
463
- if (config.boll !== undefined && !this.shallowEqual(config.boll as unknown as Record<string, unknown>, this.config.boll as unknown as Record<string, unknown>)) {
464
- this.config.boll = { ...this.config.boll, ...config.boll }
465
- this.dirtyBollConfig = true
466
- }
467
- if (config.expma !== undefined && !this.shallowEqual(config.expma as unknown as Record<string, unknown>, this.config.expma as unknown as Record<string, unknown>)) {
468
- this.config.expma = { ...this.config.expma, ...config.expma }
469
- this.dirtyExpmaConfig = true
470
- }
471
- if (config.ene !== undefined && !this.shallowEqual(config.ene as unknown as Record<string, unknown>, this.config.ene as unknown as Record<string, unknown>)) {
472
- this.config.ene = { ...this.config.ene, ...config.ene }
473
- this.dirtyEneConfig = true
474
- }
475
- if (config.rsi !== undefined && !this.shallowEqual(config.rsi as unknown as Record<string, unknown>, this.config.rsi as unknown as Record<string, unknown>)) {
476
- this.config.rsi = { ...this.config.rsi, ...config.rsi }
477
- this.dirtyRsiConfig = true
478
- }
479
- if (config.cci !== undefined && !this.shallowEqual(config.cci as unknown as Record<string, unknown>, this.config.cci as unknown as Record<string, unknown>)) {
480
- this.config.cci = { ...this.config.cci, ...config.cci }
481
- this.dirtyCciConfig = true
482
- }
483
- if (config.stoch !== undefined && !this.shallowEqual(config.stoch as unknown as Record<string, unknown>, this.config.stoch as unknown as Record<string, unknown>)) {
484
- this.config.stoch = { ...this.config.stoch, ...config.stoch }
485
- this.dirtyStochConfig = true
486
- }
487
- if (config.mom !== undefined && !this.shallowEqual(config.mom as unknown as Record<string, unknown>, this.config.mom as unknown as Record<string, unknown>)) {
488
- this.config.mom = { ...this.config.mom, ...config.mom }
489
- this.dirtyMomConfig = true
490
- }
491
- if (config.wmsr !== undefined && !this.shallowEqual(config.wmsr as unknown as Record<string, unknown>, this.config.wmsr as unknown as Record<string, unknown>)) {
492
- this.config.wmsr = { ...this.config.wmsr, ...config.wmsr }
493
- this.dirtyWmsrConfig = true
494
- }
495
- if (config.kst !== undefined && !this.shallowEqual(config.kst as unknown as Record<string, unknown>, this.config.kst as unknown as Record<string, unknown>)) {
496
- this.config.kst = { ...this.config.kst, ...config.kst }
497
- this.dirtyKstConfig = true
498
- }
499
- if (config.fastk !== undefined && !this.shallowEqual(config.fastk as unknown as Record<string, unknown>, this.config.fastk as unknown as Record<string, unknown>)) {
500
- this.config.fastk = { ...this.config.fastk, ...config.fastk }
501
- this.dirtyFastkConfig = true
502
- }
503
- if (config.macd !== undefined && !this.shallowEqual(config.macd as unknown as Record<string, unknown>, this.config.macd as unknown as Record<string, unknown>)) {
504
- this.config.macd = { ...this.config.macd, ...config.macd }
505
- this.dirtyMacdConfig = true
506
- }
507
- if (config.atr !== undefined && !this.shallowEqual(config.atr as unknown as Record<string, unknown>, this.config.atr as unknown as Record<string, unknown>)) {
508
- this.config.atr = { ...this.config.atr, ...config.atr }
509
- this.dirtyAtrConfig = true
510
- }
511
- if (config.wma !== undefined && !this.shallowEqual(config.wma as unknown as Record<string, unknown>, this.config.wma as unknown as Record<string, unknown>)) {
512
- this.config.wma = { ...this.config.wma, ...config.wma }
513
- this.dirtyWmaConfig = true
514
- }
515
- if (config.dema !== undefined && !this.shallowEqual(config.dema as unknown as Record<string, unknown>, this.config.dema as unknown as Record<string, unknown>)) {
516
- this.config.dema = { ...this.config.dema, ...config.dema }
517
- this.dirtyDemaConfig = true
518
- }
519
- if (config.tema !== undefined && !this.shallowEqual(config.tema as unknown as Record<string, unknown>, this.config.tema as unknown as Record<string, unknown>)) {
520
- this.config.tema = { ...this.config.tema, ...config.tema }
521
- this.dirtyTemaConfig = true
522
- }
523
- if (config.hma !== undefined && !this.shallowEqual(config.hma as unknown as Record<string, unknown>, this.config.hma as unknown as Record<string, unknown>)) {
524
- this.config.hma = { ...this.config.hma, ...config.hma }
525
- this.dirtyHmaConfig = true
526
- }
527
- if (config.kama !== undefined && !this.shallowEqual(config.kama as unknown as Record<string, unknown>, this.config.kama as unknown as Record<string, unknown>)) {
528
- this.config.kama = { ...this.config.kama, ...config.kama }
529
- this.dirtyKamaConfig = true
530
- }
531
- if (config.sar !== undefined && !this.shallowEqual(config.sar as unknown as Record<string, unknown>, this.config.sar as unknown as Record<string, unknown>)) {
532
- this.config.sar = { ...this.config.sar, ...config.sar }
533
- this.dirtySarConfig = true
534
- }
535
- if (config.supertrend !== undefined && !this.shallowEqual(config.supertrend as unknown as Record<string, unknown>, this.config.supertrend as unknown as Record<string, unknown>)) {
536
- this.config.supertrend = { ...this.config.supertrend, ...config.supertrend }
537
- this.dirtySupertrendConfig = true
538
- }
539
- if (config.keltner !== undefined && !this.shallowEqual(config.keltner as unknown as Record<string, unknown>, this.config.keltner as unknown as Record<string, unknown>)) {
540
- this.config.keltner = { ...this.config.keltner, ...config.keltner }
541
- this.dirtyKeltnerConfig = true
542
- }
543
- if (config.donchian !== undefined && !this.shallowEqual(config.donchian as unknown as Record<string, unknown>, this.config.donchian as unknown as Record<string, unknown>)) {
544
- this.config.donchian = { ...this.config.donchian, ...config.donchian }
545
- this.dirtyDonchianConfig = true
546
- }
547
- if (config.ichimoku !== undefined && !this.shallowEqual(config.ichimoku as unknown as Record<string, unknown>, this.config.ichimoku as unknown as Record<string, unknown>)) {
548
- this.config.ichimoku = { ...this.config.ichimoku, ...config.ichimoku }
549
- this.dirtyIchimokuConfig = true
550
- }
551
- if (config.roc !== undefined && !this.shallowEqual(config.roc as unknown as Record<string, unknown>, this.config.roc as unknown as Record<string, unknown>)) {
552
- this.config.roc = { ...this.config.roc, ...config.roc }
553
- this.dirtyRocConfig = true
554
- }
555
- if (config.trix !== undefined && !this.shallowEqual(config.trix as unknown as Record<string, unknown>, this.config.trix as unknown as Record<string, unknown>)) {
556
- this.config.trix = { ...this.config.trix, ...config.trix }
557
- this.dirtyTrixConfig = true
558
- }
559
- if (config.hv !== undefined && !this.shallowEqual(config.hv as unknown as Record<string, unknown>, this.config.hv as unknown as Record<string, unknown>)) {
560
- this.config.hv = { ...this.config.hv, ...config.hv }
561
- this.dirtyHvConfig = true
562
- }
563
- if (config.parkinson !== undefined && !this.shallowEqual(config.parkinson as unknown as Record<string, unknown>, this.config.parkinson as unknown as Record<string, unknown>)) {
564
- this.config.parkinson = { ...this.config.parkinson, ...config.parkinson }
565
- this.dirtyParkinsonConfig = true
566
- }
567
- if (config.chaikinVol !== undefined && !this.shallowEqual(config.chaikinVol as unknown as Record<string, unknown>, this.config.chaikinVol as unknown as Record<string, unknown>)) {
568
- this.config.chaikinVol = { ...this.config.chaikinVol, ...config.chaikinVol }
569
- this.dirtyChaikinVolConfig = true
570
- }
571
- if (config.vma !== undefined && !this.shallowEqual(config.vma as unknown as Record<string, unknown>, this.config.vma as unknown as Record<string, unknown>)) {
572
- this.config.vma = { ...this.config.vma, ...config.vma }
573
- this.dirtyVmaConfig = true
574
- }
575
- if (config.obv !== undefined && !this.shallowEqual(config.obv as unknown as Record<string, unknown>, this.config.obv as unknown as Record<string, unknown>)) {
576
- this.config.obv = { ...this.config.obv, ...config.obv }
577
- this.dirtyObvConfig = true
578
- }
579
- if (config.pvt !== undefined && !this.shallowEqual(config.pvt as unknown as Record<string, unknown>, this.config.pvt as unknown as Record<string, unknown>)) {
580
- this.config.pvt = { ...this.config.pvt, ...config.pvt }
581
- this.dirtyPvtConfig = true
582
- }
583
- if (config.vwap !== undefined && !this.shallowEqual(config.vwap as unknown as Record<string, unknown>, this.config.vwap as unknown as Record<string, unknown>)) {
584
- this.config.vwap = { ...this.config.vwap, ...config.vwap }
585
- this.dirtyVwapConfig = true
586
- }
587
- if (config.cmf !== undefined && !this.shallowEqual(config.cmf as unknown as Record<string, unknown>, this.config.cmf as unknown as Record<string, unknown>)) {
588
- this.config.cmf = { ...this.config.cmf, ...config.cmf }
589
- this.dirtyCmfConfig = true
590
- }
591
- if (config.mfi !== undefined && !this.shallowEqual(config.mfi as unknown as Record<string, unknown>, this.config.mfi as unknown as Record<string, unknown>)) {
592
- this.config.mfi = { ...this.config.mfi, ...config.mfi }
593
- this.dirtyMfiConfig = true
594
- }
595
- if (config.pivot !== undefined && !this.shallowEqual(config.pivot as unknown as Record<string, unknown>, this.config.pivot as unknown as Record<string, unknown>)) {
596
- this.config.pivot = { ...this.config.pivot, ...config.pivot }
597
- this.dirtyPivotConfig = true
598
- }
599
- if (config.fib !== undefined && !this.shallowEqual(config.fib as unknown as Record<string, unknown>, this.config.fib as unknown as Record<string, unknown>)) {
600
- this.config.fib = { ...this.config.fib, ...config.fib }
601
- this.dirtyFibConfig = true
602
- }
603
- if (config.structure !== undefined && !this.shallowEqual(config.structure as unknown as Record<string, unknown>, this.config.structure as unknown as Record<string, unknown>)) {
604
- this.config.structure = { ...this.config.structure, ...config.structure }
605
- this.dirtyStructureConfig = true
606
- }
607
- if (config.zones !== undefined && !this.shallowEqual(config.zones as unknown as Record<string, unknown>, this.config.zones as unknown as Record<string, unknown>)) {
608
- this.config.zones = { ...this.config.zones, ...config.zones }
609
- this.dirtyZonesConfig = true
610
- }
611
- if (config.volumeProfile !== undefined && !this.shallowEqual(config.volumeProfile as unknown as Record<string, unknown>, this.config.volumeProfile as unknown as Record<string, unknown>)) {
612
- this.config.volumeProfile = { ...this.config.volumeProfile, ...config.volumeProfile }
613
- this.dirtyVolumeProfileConfig = true
155
+ for (const [key, value] of Object.entries(config)) {
156
+ if (value === undefined) continue
157
+ const desc = this.descriptorMap.get(key)
158
+ if (desc) {
159
+ const current = this.configMap.get(key)
160
+ if (!current || !this.shallowEqual(value as Record<string, unknown>, current as Record<string, unknown>)) {
161
+ this.configMap.set(key, { ...(current ?? {}), ...(value as any) })
162
+ this.dirtyFlags.set(key, true)
163
+ }
164
+ continue
165
+ }
614
166
  }
615
- // pane IDs
616
- if (config.rsiPaneId !== undefined) this.config.rsiPaneId = config.rsiPaneId
617
- if (config.cciPaneId !== undefined) this.config.cciPaneId = config.cciPaneId
618
- if (config.stochPaneId !== undefined) this.config.stochPaneId = config.stochPaneId
619
- if (config.momPaneId !== undefined) this.config.momPaneId = config.momPaneId
620
- if (config.wmsrPaneId !== undefined) this.config.wmsrPaneId = config.wmsrPaneId
621
- if (config.kstPaneId !== undefined) this.config.kstPaneId = config.kstPaneId
622
- if (config.fastkPaneId !== undefined) this.config.fastkPaneId = config.fastkPaneId
623
- if (config.macdPaneId !== undefined) this.config.macdPaneId = config.macdPaneId
624
- if (config.atrPaneId !== undefined) this.config.atrPaneId = config.atrPaneId
625
- if (config.wmaPaneId !== undefined) this.config.wmaPaneId = config.wmaPaneId
626
- if (config.demaPaneId !== undefined) this.config.demaPaneId = config.demaPaneId
627
- if (config.temaPaneId !== undefined) this.config.temaPaneId = config.temaPaneId
628
- if (config.hmaPaneId !== undefined) this.config.hmaPaneId = config.hmaPaneId
629
- if (config.kamaPaneId !== undefined) this.config.kamaPaneId = config.kamaPaneId
630
- if (config.sarPaneId !== undefined) this.config.sarPaneId = config.sarPaneId
631
- if (config.supertrendPaneId !== undefined) this.config.supertrendPaneId = config.supertrendPaneId
632
- if (config.keltnerPaneId !== undefined) this.config.keltnerPaneId = config.keltnerPaneId
633
- if (config.donchianPaneId !== undefined) this.config.donchianPaneId = config.donchianPaneId
634
- if (config.ichimokuPaneId !== undefined) this.config.ichimokuPaneId = config.ichimokuPaneId
635
- if (config.rocPaneId !== undefined) this.config.rocPaneId = config.rocPaneId
636
- if (config.trixPaneId !== undefined) this.config.trixPaneId = config.trixPaneId
637
- if (config.hvPaneId !== undefined) this.config.hvPaneId = config.hvPaneId
638
- if (config.parkinsonPaneId !== undefined) this.config.parkinsonPaneId = config.parkinsonPaneId
639
- if (config.chaikinVolPaneId !== undefined) this.config.chaikinVolPaneId = config.chaikinVolPaneId
640
- if (config.vmaPaneId !== undefined) this.config.vmaPaneId = config.vmaPaneId
641
- if (config.obvPaneId !== undefined) this.config.obvPaneId = config.obvPaneId
642
- if (config.pvtPaneId !== undefined) this.config.pvtPaneId = config.pvtPaneId
643
- if (config.vwapPaneId !== undefined) this.config.vwapPaneId = config.vwapPaneId
644
- if (config.cmfPaneId !== undefined) this.config.cmfPaneId = config.cmfPaneId
645
- if (config.mfiPaneId !== undefined) this.config.mfiPaneId = config.mfiPaneId
646
- if (config.pivotPaneId !== undefined) this.config.pivotPaneId = config.pivotPaneId
647
- if (config.fibPaneId !== undefined) this.config.fibPaneId = config.fibPaneId
648
- if (config.structurePaneId !== undefined) this.config.structurePaneId = config.structurePaneId
649
- if (config.zonesPaneId !== undefined) this.config.zonesPaneId = config.zonesPaneId
650
- if (config.volumeProfilePaneId !== undefined) this.config.volumeProfilePaneId = config.volumeProfilePaneId
651
-
652
167
  this.configVersion = version
653
168
  }
654
169
 
655
- /**
656
- * 强制所有指标标记为脏(用于 recompute)
657
- */
658
170
  forceDirty(): void {
659
- this.dirtyData = true
660
- this.dirtyMAConfig = true
661
- this.dirtyBollConfig = true
662
- this.dirtyExpmaConfig = true
663
- this.dirtyEneConfig = true
664
- this.dirtyRsiConfig = true
665
- this.dirtyCciConfig = true
666
- this.dirtyStochConfig = true
667
- this.dirtyMomConfig = true
668
- this.dirtyWmsrConfig = true
669
- this.dirtyKstConfig = true
670
- this.dirtyFastkConfig = true
671
- this.dirtyMacdConfig = true
672
- this.dirtyAtrConfig = true
673
- this.dirtyWmaConfig = true
674
- this.dirtyDemaConfig = true
675
- this.dirtyTemaConfig = true
676
- this.dirtyHmaConfig = true
677
- this.dirtyKamaConfig = true
678
- this.dirtySarConfig = true
679
- this.dirtySupertrendConfig = true
680
- this.dirtyKeltnerConfig = true
681
- this.dirtyDonchianConfig = true
682
- this.dirtyIchimokuConfig = true
683
- this.dirtyRocConfig = true
684
- this.dirtyTrixConfig = true
685
- this.dirtyHvConfig = true
686
- this.dirtyParkinsonConfig = true
687
- this.dirtyChaikinVolConfig = true
688
- this.dirtyVmaConfig = true
689
- this.dirtyObvConfig = true
690
- this.dirtyPvtConfig = true
691
- this.dirtyVwapConfig = true
692
- this.dirtyCmfConfig = true
693
- this.dirtyMfiConfig = true
694
- this.dirtyPivotConfig = true
695
- this.dirtyFibConfig = true
696
- this.dirtyStructureConfig = true
697
- this.dirtyZonesConfig = true
698
- this.dirtyVolumeProfileConfig = true
171
+ this.dataDirty = true
172
+ for (const key of this.dirtyFlags.keys()) {
173
+ this.dirtyFlags.set(key, true)
174
+ }
699
175
  }
700
176
 
701
- /**
702
- * 获取当前数据版本
703
- */
704
177
  getDataVersion(): number {
705
178
  return this.dataVersion
706
179
  }
707
180
 
708
- /**
709
- * 获取当前配置版本
710
- */
711
181
  getConfigVersion(): number {
712
182
  return this.configVersion
713
183
  }
714
184
 
715
- /**
716
- * 计算所有指标的 series(如果脏了)
717
- * 返回结果包,供主线程组装成 render states
718
- */
719
185
  computeSeries(): IndicatorSeriesBundle {
720
186
  const data = this.currentData
721
187
  const changed: string[] = []
722
188
 
723
- // MA
724
- if (this.dirtyData || this.dirtyMAConfig) {
725
- this.cachedSeries = {}
726
- for (const period of DEFAULT_MA_PERIODS) {
727
- const flagKey = `ma${period}` as keyof MAFlags
728
- if (this.config.ma[flagKey]) {
729
- this.cachedSeries[period] = calcMAData(data, period)
730
- }
189
+ for (const [configKey, desc] of this.descriptorMap) {
190
+ if (this.dataDirty || this.dirtyFlags.get(configKey)) {
191
+ const config = this.configMap.get(configKey)
192
+ this.seriesMap.set(configKey, desc.compute(data, config))
193
+ changed.push(configKey)
731
194
  }
732
- changed.push('ma')
733
- }
734
-
735
- // BOLL
736
- if (this.dirtyData || this.dirtyBollConfig) {
737
- this.cachedBollSeries = calcBOLLData(
738
- data,
739
- this.config.boll.period,
740
- this.config.boll.multiplier
741
- )
742
- changed.push('boll')
743
195
  }
744
196
 
745
- // EXPMA
746
- if (this.dirtyData || this.dirtyExpmaConfig) {
747
- this.cachedExpmaSeries = calcEXPMAData(
748
- data,
749
- this.config.expma.fastPeriod,
750
- this.config.expma.slowPeriod
751
- )
752
- changed.push('expma')
197
+ this.dataDirty = false
198
+ for (const key of this.dirtyFlags.keys()) {
199
+ this.dirtyFlags.set(key, false)
753
200
  }
754
201
 
755
- // ENE
756
- if (this.dirtyData || this.dirtyEneConfig) {
757
- this.cachedEneSeries = calcENEData(
758
- data,
759
- this.config.ene.period,
760
- this.config.ene.deviation
761
- )
762
- changed.push('ene')
763
- }
202
+ const bundle: Record<string, unknown> = { _changed: changed }
203
+ for (const [configKey] of this.descriptorMap) {
204
+ const raw = this.seriesMap.get(configKey)
205
+ const params = { ...(this.configMap.get(configKey) ?? {}) }
206
+ const entry: Record<string, unknown> = {}
764
207
 
765
- // RSI
766
- if (this.dirtyData || this.dirtyRsiConfig) {
767
- this.cachedRsiSeries = {}
768
- const periods = [this.config.rsi.period1, this.config.rsi.period2, this.config.rsi.period3]
769
- const shows = [this.config.rsi.showRSI1, this.config.rsi.showRSI2, this.config.rsi.showRSI3]
770
- for (let i = 0; i < periods.length; i++) {
771
- if (shows[i]) {
772
- this.cachedRsiSeries[periods[i]] = calcRSIData(data, periods[i])
773
- }
774
- }
775
- changed.push('rsi')
776
- }
777
-
778
- // CCI
779
- if (this.dirtyData || this.dirtyCciConfig) {
780
- if (this.config.cci.showCCI) {
781
- this.cachedCciSeries = calcCCIData(data, this.config.cci.period)
782
- } else {
783
- this.cachedCciSeries = []
784
- }
785
- changed.push('cci')
786
- }
787
-
788
- // STOCH
789
- if (this.dirtyData || this.dirtyStochConfig) {
790
- if (this.config.stoch.showK || this.config.stoch.showD) {
791
- this.cachedStochSeries = calcSTOCHData(data, this.config.stoch.n, this.config.stoch.m)
208
+ if (raw && typeof raw === 'object' && 'series' in (raw as Record<string, unknown>)) {
209
+ Object.assign(entry, raw as Record<string, unknown>)
792
210
  } else {
793
- this.cachedStochSeries = []
794
- }
795
- changed.push('stoch')
796
- }
797
-
798
- // MOM
799
- if (this.dirtyData || this.dirtyMomConfig) {
800
- if (this.config.mom.showMOM) {
801
- this.cachedMomSeries = calcMOMData(data, this.config.mom.period)
802
- } else {
803
- this.cachedMomSeries = []
804
- }
805
- changed.push('mom')
806
- }
807
-
808
- // WMSR
809
- if (this.dirtyData || this.dirtyWmsrConfig) {
810
- if (this.config.wmsr.showWMSR) {
811
- this.cachedWmsrSeries = calcWMSRData(data, this.config.wmsr.period)
812
- } else {
813
- this.cachedWmsrSeries = []
814
- }
815
- changed.push('wmsr')
816
- }
817
-
818
- // KST
819
- if (this.dirtyData || this.dirtyKstConfig) {
820
- if (this.config.kst.showKST || this.config.kst.showSignal) {
821
- this.cachedKstSeries = calcKSTData(
822
- data,
823
- this.config.kst.roc1,
824
- this.config.kst.roc2,
825
- this.config.kst.roc3,
826
- this.config.kst.roc4,
827
- this.config.kst.signalPeriod
828
- )
829
- } else {
830
- this.cachedKstSeries = []
831
- }
832
- changed.push('kst')
833
- }
834
-
835
- // FASTK
836
- if (this.dirtyData || this.dirtyFastkConfig) {
837
- if (this.config.fastk.showFASTK) {
838
- this.cachedFastkSeries = calcFASTKData(data, this.config.fastk.period)
839
- } else {
840
- this.cachedFastkSeries = []
841
- }
842
- changed.push('fastk')
843
- }
844
-
845
- // MACD
846
- if (this.dirtyData || this.dirtyMacdConfig) {
847
- if (this.config.macd.showDIF || this.config.macd.showDEA || this.config.macd.showBAR) {
848
- this.cachedMacdSeries = calcMACDData(
849
- data,
850
- this.config.macd.fastPeriod,
851
- this.config.macd.slowPeriod,
852
- this.config.macd.signalPeriod
853
- )
854
- } else {
855
- this.cachedMacdSeries = []
856
- }
857
- changed.push('macd')
858
- }
859
-
860
- // ATR
861
- if (this.dirtyData || this.dirtyAtrConfig) {
862
- if (this.config.atr.showATR) {
863
- this.cachedAtrSeries = calcATRData(data, this.config.atr.period)
864
- } else {
865
- this.cachedAtrSeries = []
866
- }
867
- changed.push('atr')
868
- }
869
-
870
- // WMA
871
- if (this.dirtyData || this.dirtyWmaConfig) {
872
- if (this.config.wma.showWMA) {
873
- this.cachedWmaSeries = calcWMAData(data, this.config.wma.period)
874
- } else {
875
- this.cachedWmaSeries = []
876
- }
877
- changed.push('wma')
878
- }
879
-
880
- // DEMA
881
- if (this.dirtyData || this.dirtyDemaConfig) {
882
- if (this.config.dema.showDEMA) {
883
- this.cachedDemaSeries = calcDEMAData(data, this.config.dema.period)
884
- } else {
885
- this.cachedDemaSeries = []
886
- }
887
- changed.push('dema')
888
- }
889
-
890
- // TEMA
891
- if (this.dirtyData || this.dirtyTemaConfig) {
892
- if (this.config.tema.showTEMA) {
893
- this.cachedTemaSeries = calcTEMAData(data, this.config.tema.period)
894
- } else {
895
- this.cachedTemaSeries = []
896
- }
897
- changed.push('tema')
898
- }
899
-
900
- // HMA
901
- if (this.dirtyData || this.dirtyHmaConfig) {
902
- if (this.config.hma.showHMA) {
903
- this.cachedHmaSeries = calcHMAData(data, this.config.hma.period)
904
- } else {
905
- this.cachedHmaSeries = []
906
- }
907
- changed.push('hma')
908
- }
909
-
910
- // KAMA
911
- if (this.dirtyData || this.dirtyKamaConfig) {
912
- if (this.config.kama.showKAMA) {
913
- this.cachedKamaSeries = calcKAMAData(
914
- data,
915
- this.config.kama.period,
916
- this.config.kama.fastPeriod,
917
- this.config.kama.slowPeriod,
918
- )
919
- } else {
920
- this.cachedKamaSeries = []
921
- }
922
- changed.push('kama')
923
- }
924
-
925
- // SAR
926
- if (this.dirtyData || this.dirtySarConfig) {
927
- if (this.config.sar.showSAR) {
928
- this.cachedSarSeries = calcSARData(
929
- data,
930
- this.config.sar.step,
931
- this.config.sar.maxStep,
932
- )
933
- } else {
934
- this.cachedSarSeries = []
935
- }
936
- changed.push('sar')
937
- }
938
-
939
- // SuperTrend
940
- if (this.dirtyData || this.dirtySupertrendConfig) {
941
- if (this.config.supertrend.showSuperTrend) {
942
- this.cachedSupertrendSeries = calcSuperTrendData(
943
- data,
944
- this.config.supertrend.atrPeriod,
945
- this.config.supertrend.multiplier,
946
- )
947
- } else {
948
- this.cachedSupertrendSeries = []
949
- }
950
- changed.push('supertrend')
951
- }
952
-
953
- // Keltner
954
- if (this.dirtyData || this.dirtyKeltnerConfig) {
955
- if (this.config.keltner.showUpper || this.config.keltner.showMiddle || this.config.keltner.showLower) {
956
- this.cachedKeltnerSeries = calcKeltnerData(
957
- data,
958
- this.config.keltner.emaPeriod,
959
- this.config.keltner.atrPeriod,
960
- this.config.keltner.multiplier,
961
- )
962
- } else {
963
- this.cachedKeltnerSeries = []
964
- }
965
- changed.push('keltner')
966
- }
967
-
968
- // Donchian
969
- if (this.dirtyData || this.dirtyDonchianConfig) {
970
- if (this.config.donchian.showUpper || this.config.donchian.showMiddle || this.config.donchian.showLower) {
971
- this.cachedDonchianSeries = calcDonchianData(data, this.config.donchian.period)
972
- } else {
973
- this.cachedDonchianSeries = []
974
- }
975
- changed.push('donchian')
976
- }
977
-
978
- // Ichimoku
979
- if (this.dirtyData || this.dirtyIchimokuConfig) {
980
- const ic = this.config.ichimoku
981
- if (ic.showTenkan || ic.showKijun || ic.showSpanA || ic.showSpanB || ic.showCloud || ic.showChikou) {
982
- this.cachedIchimokuSeries = calcIchimokuData(
983
- data,
984
- ic.tenkanPeriod,
985
- ic.kijunPeriod,
986
- ic.spanBPeriod,
987
- ic.displacement,
988
- )
989
- } else {
990
- this.cachedIchimokuSeries = []
991
- }
992
- changed.push('ichimoku')
993
- }
994
-
995
- // ROC
996
- if (this.dirtyData || this.dirtyRocConfig) {
997
- if (this.config.roc.showROC) {
998
- this.cachedRocSeries = calcROCData(data, this.config.roc.period)
999
- } else {
1000
- this.cachedRocSeries = []
1001
- }
1002
- changed.push('roc')
1003
- }
1004
-
1005
- // TRIX
1006
- if (this.dirtyData || this.dirtyTrixConfig) {
1007
- if (this.config.trix.showTRIX || this.config.trix.showSignal) {
1008
- const result = calcTRIXData(data, this.config.trix.period, this.config.trix.signalPeriod)
1009
- this.cachedTrixSeries = result.series
1010
- this.cachedTrixSignalSeries = result.signalSeries
1011
- } else {
1012
- this.cachedTrixSeries = []
1013
- this.cachedTrixSignalSeries = []
1014
- }
1015
- changed.push('trix')
1016
- }
1017
-
1018
- // HV
1019
- if (this.dirtyData || this.dirtyHvConfig) {
1020
- if (this.config.hv.showHV) {
1021
- this.cachedHvSeries = calcHVData(data, this.config.hv.period, this.config.hv.annualizationFactor)
1022
- } else {
1023
- this.cachedHvSeries = []
1024
- }
1025
- changed.push('hv')
1026
- }
1027
-
1028
- // Parkinson
1029
- if (this.dirtyData || this.dirtyParkinsonConfig) {
1030
- if (this.config.parkinson.showParkinson) {
1031
- this.cachedParkinsonSeries = calcParkinsonData(
1032
- data,
1033
- this.config.parkinson.period,
1034
- this.config.parkinson.annualizationFactor,
1035
- )
1036
- } else {
1037
- this.cachedParkinsonSeries = []
1038
- }
1039
- changed.push('parkinson')
1040
- }
1041
-
1042
- // Chaikin Volatility
1043
- if (this.dirtyData || this.dirtyChaikinVolConfig) {
1044
- if (this.config.chaikinVol.showChaikinVol) {
1045
- this.cachedChaikinVolSeries = calcChaikinVolData(
1046
- data,
1047
- this.config.chaikinVol.emaPeriod,
1048
- this.config.chaikinVol.rocPeriod,
1049
- )
1050
- } else {
1051
- this.cachedChaikinVolSeries = []
1052
- }
1053
- changed.push('chaikinVol')
1054
- }
1055
-
1056
- // VMA
1057
- if (this.dirtyData || this.dirtyVmaConfig) {
1058
- if (this.config.vma.showVMA) {
1059
- this.cachedVmaSeries = calcVMAData(data, this.config.vma.period)
1060
- } else {
1061
- this.cachedVmaSeries = []
1062
- }
1063
- changed.push('vma')
1064
- }
1065
-
1066
- // OBV
1067
- if (this.dirtyData || this.dirtyObvConfig) {
1068
- if (this.config.obv.showOBV) {
1069
- this.cachedObvSeries = calcOBVData(data)
1070
- } else {
1071
- this.cachedObvSeries = []
1072
- }
1073
- changed.push('obv')
1074
- }
1075
-
1076
- // PVT
1077
- if (this.dirtyData || this.dirtyPvtConfig) {
1078
- if (this.config.pvt.showPVT) {
1079
- this.cachedPvtSeries = calcPVTData(data)
1080
- } else {
1081
- this.cachedPvtSeries = []
1082
- }
1083
- changed.push('pvt')
1084
- }
1085
-
1086
- // VWAP
1087
- if (this.dirtyData || this.dirtyVwapConfig) {
1088
- if (this.config.vwap.showVWAP) {
1089
- this.cachedVwapSeries = calcVWAPData(data, this.config.vwap.sessionResetGapMs)
1090
- } else {
1091
- this.cachedVwapSeries = []
1092
- }
1093
- changed.push('vwap')
1094
- }
1095
-
1096
- // CMF
1097
- if (this.dirtyData || this.dirtyCmfConfig) {
1098
- if (this.config.cmf.showCMF) {
1099
- this.cachedCmfSeries = calcCMFData(data, this.config.cmf.period)
1100
- } else {
1101
- this.cachedCmfSeries = []
1102
- }
1103
- changed.push('cmf')
1104
- }
1105
-
1106
- // MFI
1107
- if (this.dirtyData || this.dirtyMfiConfig) {
1108
- if (this.config.mfi.showMFI) {
1109
- this.cachedMfiSeries = calcMFIData(data, this.config.mfi.period)
1110
- } else {
1111
- this.cachedMfiSeries = []
1112
- }
1113
- changed.push('mfi')
1114
- }
1115
-
1116
- // Pivot
1117
- if (this.dirtyData || this.dirtyPivotConfig) {
1118
- const p = this.config.pivot
1119
- if (p.showPP || p.showR1 || p.showR2 || p.showR3 || p.showS1 || p.showS2 || p.showS3) {
1120
- this.cachedPivotSeries = calcPivotData(data)
1121
- } else {
1122
- this.cachedPivotSeries = []
1123
- }
1124
- changed.push('pivot')
1125
- }
1126
-
1127
- // Fibonacci
1128
- if (this.dirtyData || this.dirtyFibConfig) {
1129
- if (this.config.fib.showLevels) {
1130
- this.cachedFibSeries = calcFibData(data, this.config.fib.period)
1131
- } else {
1132
- this.cachedFibSeries = []
1133
- }
1134
- changed.push('fib')
1135
- }
1136
-
1137
- // SMC Structure
1138
- if (this.dirtyData || this.dirtyStructureConfig) {
1139
- const s = this.config.structure
1140
- if (s.showSwingLabels || s.showBOS || s.showCHOCH) {
1141
- this.cachedStructureSeries = calcStructureData(data, s.leftWindow, s.rightWindow, s.breakoutSource)
1142
- } else {
1143
- this.cachedStructureSeries = { swings: [], events: [], trend: 'range' }
1144
- }
1145
- changed.push('structure')
1146
- }
1147
-
1148
- // SMC Zones
1149
- if (this.dirtyData || this.dirtyZonesConfig) {
1150
- const z = this.config.zones
1151
- if (z.showFVG || z.showOB) {
1152
- this.cachedZonesSeries = calcZonesData(
1153
- data,
1154
- z.obLookback,
1155
- this.config.structure.leftWindow,
1156
- this.config.structure.rightWindow,
1157
- this.config.structure.breakoutSource,
1158
- )
1159
- } else {
1160
- this.cachedZonesSeries = []
1161
- }
1162
- changed.push('zones')
1163
- }
1164
-
1165
- // Volume Profile
1166
- if (this.dirtyData || this.dirtyVolumeProfileConfig) {
1167
- const vp = this.config.volumeProfile
1168
- if (vp.showPOC || vp.showValueArea) {
1169
- this.cachedVolumeProfileSeries = calcVolumeProfileData(data, vp.bins, vp.lookback, vp.valueAreaPercent)
1170
- } else {
1171
- this.cachedVolumeProfileSeries = { bins: [], poc: 0, vah: 0, val: 0, totalVolume: 0 }
211
+ entry.series = raw
212
+ if (raw && typeof raw === 'object' && !Array.isArray(raw)) {
213
+ entry.enabledPeriods = Object.keys(raw).map(Number)
214
+ }
1172
215
  }
1173
- changed.push('volumeProfile')
1174
- }
1175
-
1176
- // 重置脏标记
1177
- this.dirtyData = false
1178
- this.dirtyMAConfig = false
1179
- this.dirtyBollConfig = false
1180
- this.dirtyExpmaConfig = false
1181
- this.dirtyEneConfig = false
1182
- this.dirtyRsiConfig = false
1183
- this.dirtyCciConfig = false
1184
- this.dirtyStochConfig = false
1185
- this.dirtyMomConfig = false
1186
- this.dirtyWmsrConfig = false
1187
- this.dirtyKstConfig = false
1188
- this.dirtyFastkConfig = false
1189
- this.dirtyMacdConfig = false
1190
- this.dirtyAtrConfig = false
1191
- this.dirtyWmaConfig = false
1192
- this.dirtyDemaConfig = false
1193
- this.dirtyTemaConfig = false
1194
- this.dirtyHmaConfig = false
1195
- this.dirtyKamaConfig = false
1196
- this.dirtySarConfig = false
1197
- this.dirtySupertrendConfig = false
1198
- this.dirtyKeltnerConfig = false
1199
- this.dirtyDonchianConfig = false
1200
- this.dirtyIchimokuConfig = false
1201
- this.dirtyRocConfig = false
1202
- this.dirtyTrixConfig = false
1203
- this.dirtyHvConfig = false
1204
- this.dirtyParkinsonConfig = false
1205
- this.dirtyChaikinVolConfig = false
1206
- this.dirtyVmaConfig = false
1207
- this.dirtyObvConfig = false
1208
- this.dirtyPvtConfig = false
1209
- this.dirtyVwapConfig = false
1210
- this.dirtyCmfConfig = false
1211
- this.dirtyMfiConfig = false
1212
- this.dirtyPivotConfig = false
1213
- this.dirtyFibConfig = false
1214
- this.dirtyStructureConfig = false
1215
- this.dirtyZonesConfig = false
1216
- this.dirtyVolumeProfileConfig = false
1217
-
1218
- // 组装结果
1219
- return {
1220
- ma: {
1221
- series: this.cachedSeries,
1222
- enabledPeriods: Object.keys(this.cachedSeries).map(Number),
1223
- },
1224
- boll: {
1225
- series: this.cachedBollSeries,
1226
- params: { ...this.config.boll },
1227
- },
1228
- expma: {
1229
- series: this.cachedExpmaSeries,
1230
- params: { ...this.config.expma },
1231
- },
1232
- ene: {
1233
- series: this.cachedEneSeries,
1234
- params: { ...this.config.ene },
1235
- },
1236
- rsi: {
1237
- series: this.cachedRsiSeries,
1238
- enabledPeriods: Object.keys(this.cachedRsiSeries).map(Number),
1239
- params: { ...this.config.rsi },
1240
- },
1241
- cci: {
1242
- series: this.cachedCciSeries,
1243
- params: { ...this.config.cci },
1244
- },
1245
- stoch: {
1246
- series: this.cachedStochSeries,
1247
- params: { ...this.config.stoch },
1248
- },
1249
- mom: {
1250
- series: this.cachedMomSeries,
1251
- params: { ...this.config.mom },
1252
- },
1253
- wmsr: {
1254
- series: this.cachedWmsrSeries,
1255
- params: { ...this.config.wmsr },
1256
- },
1257
- kst: {
1258
- series: this.cachedKstSeries,
1259
- params: { ...this.config.kst },
1260
- },
1261
- fastk: {
1262
- series: this.cachedFastkSeries,
1263
- params: { ...this.config.fastk },
1264
- },
1265
- macd: {
1266
- series: this.cachedMacdSeries,
1267
- params: { ...this.config.macd },
1268
- },
1269
- atr: {
1270
- series: this.cachedAtrSeries,
1271
- params: { ...this.config.atr },
1272
- },
1273
- wma: {
1274
- series: this.cachedWmaSeries,
1275
- params: { ...this.config.wma },
1276
- },
1277
- dema: {
1278
- series: this.cachedDemaSeries,
1279
- params: { ...this.config.dema },
1280
- },
1281
- tema: {
1282
- series: this.cachedTemaSeries,
1283
- params: { ...this.config.tema },
1284
- },
1285
- hma: {
1286
- series: this.cachedHmaSeries,
1287
- params: { ...this.config.hma },
1288
- },
1289
- kama: {
1290
- series: this.cachedKamaSeries,
1291
- params: { ...this.config.kama },
1292
- },
1293
- sar: {
1294
- series: this.cachedSarSeries,
1295
- params: { ...this.config.sar },
1296
- },
1297
- supertrend: {
1298
- series: this.cachedSupertrendSeries,
1299
- params: { ...this.config.supertrend },
1300
- },
1301
- keltner: {
1302
- series: this.cachedKeltnerSeries,
1303
- params: { ...this.config.keltner },
1304
- },
1305
- donchian: {
1306
- series: this.cachedDonchianSeries,
1307
- params: { ...this.config.donchian },
1308
- },
1309
- ichimoku: {
1310
- series: this.cachedIchimokuSeries,
1311
- params: { ...this.config.ichimoku },
1312
- },
1313
- roc: {
1314
- series: this.cachedRocSeries,
1315
- params: { ...this.config.roc },
1316
- },
1317
- trix: {
1318
- series: this.cachedTrixSeries,
1319
- signalSeries: this.cachedTrixSignalSeries,
1320
- params: { ...this.config.trix },
1321
- },
1322
- hv: {
1323
- series: this.cachedHvSeries,
1324
- params: { ...this.config.hv },
1325
- },
1326
- parkinson: {
1327
- series: this.cachedParkinsonSeries,
1328
- params: { ...this.config.parkinson },
1329
- },
1330
- chaikinVol: {
1331
- series: this.cachedChaikinVolSeries,
1332
- params: { ...this.config.chaikinVol },
1333
- },
1334
- vma: {
1335
- series: this.cachedVmaSeries,
1336
- params: { ...this.config.vma },
1337
- },
1338
- obv: {
1339
- series: this.cachedObvSeries,
1340
- params: { ...this.config.obv },
1341
- },
1342
- pvt: {
1343
- series: this.cachedPvtSeries,
1344
- params: { ...this.config.pvt },
1345
- },
1346
- vwap: {
1347
- series: this.cachedVwapSeries,
1348
- params: { ...this.config.vwap },
1349
- },
1350
- cmf: {
1351
- series: this.cachedCmfSeries,
1352
- params: { ...this.config.cmf },
1353
- },
1354
- mfi: {
1355
- series: this.cachedMfiSeries,
1356
- params: { ...this.config.mfi },
1357
- },
1358
- pivot: {
1359
- series: this.cachedPivotSeries,
1360
- params: { ...this.config.pivot },
1361
- },
1362
- fib: {
1363
- series: this.cachedFibSeries,
1364
- params: { ...this.config.fib },
1365
- },
1366
- structure: {
1367
- series: this.cachedStructureSeries,
1368
- params: { ...this.config.structure },
1369
- },
1370
- zones: {
1371
- series: this.cachedZonesSeries,
1372
- params: { ...this.config.zones },
1373
- },
1374
- volumeProfile: {
1375
- series: this.cachedVolumeProfileSeries,
1376
- params: { ...this.config.volumeProfile },
1377
- },
1378
- _changed: changed,
216
+ entry.params = params
217
+ bundle[configKey] = entry
1379
218
  }
1380
- }
1381
219
 
1382
- /**
1383
- * 获取缓存的 series(用于 visibleRange 变更时扫描极值)
1384
- */
1385
- getCachedSeries(): IndicatorSeriesBundle {
1386
- return {
1387
- _changed: [],
1388
- ma: {
1389
- series: this.cachedSeries,
1390
- enabledPeriods: Object.keys(this.cachedSeries).map(Number),
1391
- },
1392
- boll: {
1393
- series: this.cachedBollSeries,
1394
- params: { ...this.config.boll },
1395
- },
1396
- expma: {
1397
- series: this.cachedExpmaSeries,
1398
- params: { ...this.config.expma },
1399
- },
1400
- ene: {
1401
- series: this.cachedEneSeries,
1402
- params: { ...this.config.ene },
1403
- },
1404
- rsi: {
1405
- series: this.cachedRsiSeries,
1406
- enabledPeriods: Object.keys(this.cachedRsiSeries).map(Number),
1407
- params: { ...this.config.rsi },
1408
- },
1409
- cci: {
1410
- series: this.cachedCciSeries,
1411
- params: { ...this.config.cci },
1412
- },
1413
- stoch: {
1414
- series: this.cachedStochSeries,
1415
- params: { ...this.config.stoch },
1416
- },
1417
- mom: {
1418
- series: this.cachedMomSeries,
1419
- params: { ...this.config.mom },
1420
- },
1421
- wmsr: {
1422
- series: this.cachedWmsrSeries,
1423
- params: { ...this.config.wmsr },
1424
- },
1425
- kst: {
1426
- series: this.cachedKstSeries,
1427
- params: { ...this.config.kst },
1428
- },
1429
- fastk: {
1430
- series: this.cachedFastkSeries,
1431
- params: { ...this.config.fastk },
1432
- },
1433
- macd: {
1434
- series: this.cachedMacdSeries,
1435
- params: { ...this.config.macd },
1436
- },
1437
- atr: {
1438
- series: this.cachedAtrSeries,
1439
- params: { ...this.config.atr },
1440
- },
1441
- wma: {
1442
- series: this.cachedWmaSeries,
1443
- params: { ...this.config.wma },
1444
- },
1445
- dema: {
1446
- series: this.cachedDemaSeries,
1447
- params: { ...this.config.dema },
1448
- },
1449
- tema: {
1450
- series: this.cachedTemaSeries,
1451
- params: { ...this.config.tema },
1452
- },
1453
- hma: {
1454
- series: this.cachedHmaSeries,
1455
- params: { ...this.config.hma },
1456
- },
1457
- kama: {
1458
- series: this.cachedKamaSeries,
1459
- params: { ...this.config.kama },
1460
- },
1461
- sar: {
1462
- series: this.cachedSarSeries,
1463
- params: { ...this.config.sar },
1464
- },
1465
- supertrend: {
1466
- series: this.cachedSupertrendSeries,
1467
- params: { ...this.config.supertrend },
1468
- },
1469
- keltner: {
1470
- series: this.cachedKeltnerSeries,
1471
- params: { ...this.config.keltner },
1472
- },
1473
- donchian: {
1474
- series: this.cachedDonchianSeries,
1475
- params: { ...this.config.donchian },
1476
- },
1477
- ichimoku: {
1478
- series: this.cachedIchimokuSeries,
1479
- params: { ...this.config.ichimoku },
1480
- },
1481
- roc: {
1482
- series: this.cachedRocSeries,
1483
- params: { ...this.config.roc },
1484
- },
1485
- trix: {
1486
- series: this.cachedTrixSeries,
1487
- signalSeries: this.cachedTrixSignalSeries,
1488
- params: { ...this.config.trix },
1489
- },
1490
- hv: {
1491
- series: this.cachedHvSeries,
1492
- params: { ...this.config.hv },
1493
- },
1494
- parkinson: {
1495
- series: this.cachedParkinsonSeries,
1496
- params: { ...this.config.parkinson },
1497
- },
1498
- chaikinVol: {
1499
- series: this.cachedChaikinVolSeries,
1500
- params: { ...this.config.chaikinVol },
1501
- },
1502
- vma: {
1503
- series: this.cachedVmaSeries,
1504
- params: { ...this.config.vma },
1505
- },
1506
- obv: {
1507
- series: this.cachedObvSeries,
1508
- params: { ...this.config.obv },
1509
- },
1510
- pvt: {
1511
- series: this.cachedPvtSeries,
1512
- params: { ...this.config.pvt },
1513
- },
1514
- vwap: {
1515
- series: this.cachedVwapSeries,
1516
- params: { ...this.config.vwap },
1517
- },
1518
- cmf: {
1519
- series: this.cachedCmfSeries,
1520
- params: { ...this.config.cmf },
1521
- },
1522
- mfi: {
1523
- series: this.cachedMfiSeries,
1524
- params: { ...this.config.mfi },
1525
- },
1526
- pivot: {
1527
- series: this.cachedPivotSeries,
1528
- params: { ...this.config.pivot },
1529
- },
1530
- fib: {
1531
- series: this.cachedFibSeries,
1532
- params: { ...this.config.fib },
1533
- },
1534
- structure: {
1535
- series: this.cachedStructureSeries,
1536
- params: { ...this.config.structure },
1537
- },
1538
- zones: {
1539
- series: this.cachedZonesSeries,
1540
- params: { ...this.config.zones },
1541
- },
1542
- volumeProfile: {
1543
- series: this.cachedVolumeProfileSeries,
1544
- params: { ...this.config.volumeProfile },
1545
- },
1546
- }
220
+ return bundle as unknown as IndicatorSeriesBundle
1547
221
  }
1548
222
  }