@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
@@ -70,6 +70,7 @@ import type { ZonesRenderState } from './zonesState'
70
70
  import type { VolumeProfileRenderState } from './volumeProfileState'
71
71
  import type { IndicatorSeriesBundle } from './workerProtocol'
72
72
  import type { IndicatorMetadata } from './indicatorMetadata'
73
+ import { getRegisteredIndicatorDefinitions } from './indicatorDefinitionRegistry'
73
74
 
74
75
  /**
75
76
  * 可见范围
@@ -166,56 +167,13 @@ type MainRenderStateIndicatorId = keyof MainRenderStates
166
167
 
167
168
  type ComposedRenderStates = VisibleSubIndicatorStates & MainRenderStates
168
169
 
169
- const MAIN_RENDER_STATE_INDICATOR_IDS: readonly MainRenderStateIndicatorId[] = ['ma', 'boll', 'expma', 'ene']
170
- const METADATA_VISIBLE_STATE_INDICATOR_IDS = [
171
- 'cci',
172
- 'wma',
173
- 'dema',
174
- 'tema',
175
- 'hma',
176
- 'kama',
177
- 'roc',
178
- 'chaikinVol',
179
- 'obv',
180
- 'pvt',
181
- 'vwap',
182
- 'rsi',
183
- 'stoch',
184
- 'fastk',
185
- 'mfi',
186
- 'wmsr',
187
- 'cmf',
188
- 'atr',
189
- 'hv',
190
- 'kst',
191
- 'mom',
192
- 'parkinson',
193
- 'trix',
194
- 'vma',
195
- 'macd',
196
- 'sar',
197
- 'supertrend',
198
- 'keltner',
199
- 'donchian',
200
- 'ichimoku',
201
- 'pivot',
202
- 'fib',
203
- 'structure',
204
- 'zones',
205
- 'volumeProfile',
206
- ] as const satisfies readonly (keyof VisibleSubIndicatorStates)[]
207
-
208
- type _MissingVisibleStateId = Exclude<
209
- keyof VisibleSubIndicatorStates,
210
- typeof METADATA_VISIBLE_STATE_INDICATOR_IDS[number]
211
- >
212
- type _ExtraVisibleStateId = Exclude<
213
- typeof METADATA_VISIBLE_STATE_INDICATOR_IDS[number],
214
- keyof VisibleSubIndicatorStates
215
- >
216
- type AssertNever<T extends never> = T
217
- type _AssertNoMissingId = AssertNever<_MissingVisibleStateId>
218
- type _AssertNoExtraId = AssertNever<_ExtraVisibleStateId>
170
+ function getVisibleStateIndicatorIds(): (keyof VisibleSubIndicatorStates)[] {
171
+ return getRegisteredIndicatorDefinitions()
172
+ .filter((d): d is IndicatorMetadata & { visibleState: NonNullable<IndicatorMetadata['visibleState']> } =>
173
+ !!d.visibleState?.compose
174
+ )
175
+ .map(d => d.name as keyof VisibleSubIndicatorStates)
176
+ }
219
177
 
220
178
  /**
221
179
  * 仅计算副图指标的 visible-only states
@@ -230,7 +188,7 @@ export function composeVisibleSubIndicatorStates(
230
188
  ): VisibleSubIndicatorStates {
231
189
  const states: Partial<VisibleSubIndicatorStates> = {}
232
190
 
233
- for (const indicatorId of METADATA_VISIBLE_STATE_INDICATOR_IDS) {
191
+ for (const indicatorId of getVisibleStateIndicatorIds()) {
234
192
  states[indicatorId] = composeRequiredMetadataVisibleState(
235
193
  indicatorId, bundle, visibleRange, timestamp, activeMask, getIndicatorMetadata,
236
194
  ) as never
@@ -290,15 +248,13 @@ function composeMainRenderStates(
290
248
  ): MainRenderStates {
291
249
  const states: Partial<Record<MainRenderStateIndicatorId, unknown>> = {}
292
250
 
293
- for (const indicatorId of MAIN_RENDER_STATE_INDICATOR_IDS) {
294
- const definition = getIndicatorMetadata(indicatorId)
295
- if (!definition) continue
296
-
297
- const composeRenderState = definition.mainPane?.composeRenderState
298
- if (!composeRenderState) {
299
- throw new Error(`[StateComposer] Missing mainPane.composeRenderState for ${indicatorId}`)
300
- }
301
- states[indicatorId] = composeRenderState(bundle, visibleRange, timestamp)
251
+ for (const def of getRegisteredIndicatorDefinitions()) {
252
+ if (!def.mainPane?.composeRenderState) continue
253
+ const indicatorId = def.name as MainRenderStateIndicatorId
254
+ const meta = getIndicatorMetadata(indicatorId)
255
+ const compose = meta?.mainPane?.composeRenderState ?? def.mainPane.composeRenderState
256
+ if (!compose) continue
257
+ states[indicatorId] = compose(bundle, visibleRange, timestamp)
302
258
  }
303
259
 
304
260
  return states as MainRenderStates
@@ -277,9 +277,22 @@ export interface VolumeProfileSchedulerConfig {
277
277
  // Worker 请求类型
278
278
  // ============================================================================
279
279
 
280
+ export interface SerializedRuntimeDescriptor {
281
+ configKey: string
282
+ paneIdKey?: string
283
+ defaultConfig: unknown
284
+ computeKey: string
285
+ }
286
+
280
287
  export interface InitRequest {
281
288
  type: 'init'
282
289
  protocolVersion: number
290
+ descriptors?: SerializedRuntimeDescriptor[]
291
+ }
292
+
293
+ export interface AddDescriptorRequest {
294
+ type: 'addDescriptor'
295
+ descriptor: SerializedRuntimeDescriptor
283
296
  }
284
297
 
285
298
  export interface SetDataRequest {
@@ -308,6 +321,7 @@ export interface DisposeRequest {
308
321
 
309
322
  export type IndicatorWorkerRequest =
310
323
  | InitRequest
324
+ | AddDescriptorRequest
311
325
  | SetDataRequest
312
326
  | SetConfigRequest
313
327
  | ComputeSeriesRequest
@@ -390,42 +404,6 @@ export interface IndicatorConfigSnapshot {
390
404
  structure: StructureSchedulerConfig
391
405
  zones: ZonesSchedulerConfig
392
406
  volumeProfile: VolumeProfileSchedulerConfig
393
- // pane IDs for sub-indicators
394
- rsiPaneId: string
395
- cciPaneId: string
396
- stochPaneId: string
397
- momPaneId: string
398
- wmsrPaneId: string
399
- kstPaneId: string
400
- fastkPaneId: string
401
- macdPaneId: string
402
- atrPaneId: string
403
- wmaPaneId: string
404
- demaPaneId: string
405
- temaPaneId: string
406
- hmaPaneId: string
407
- kamaPaneId: string
408
- sarPaneId: string
409
- supertrendPaneId: string
410
- keltnerPaneId: string
411
- donchianPaneId: string
412
- ichimokuPaneId: string
413
- rocPaneId: string
414
- trixPaneId: string
415
- hvPaneId: string
416
- parkinsonPaneId: string
417
- chaikinVolPaneId: string
418
- vmaPaneId: string
419
- obvPaneId: string
420
- pvtPaneId: string
421
- vwapPaneId: string
422
- cmfPaneId: string
423
- mfiPaneId: string
424
- pivotPaneId: string
425
- fibPaneId: string
426
- structurePaneId: string
427
- zonesPaneId: string
428
- volumeProfilePaneId: string
429
407
  }
430
408
 
431
409
  // ============================================================================
@@ -9,6 +9,8 @@ import { Indicator } from '../../indicators/indicatorDefinitionRegistry'
9
9
  import { resolveStateKey } from '../../indicators/indicatorMetadata'
10
10
  import type { IndicatorScheduler, ATRSchedulerConfig } from '../../indicators/scheduler'
11
11
  import { createAtrScaleRendererPlugin } from './scale/atr_scale'
12
+ import { calcATRData } from '../../indicators/calculators'
13
+ import type { KLineData } from '../../../types/price'
12
14
 
13
15
  type LinePoint = { x: number; y: number }
14
16
 
@@ -176,7 +178,7 @@ export function createATRRendererPlugin(options: ATRRendererOptions = {}): Rende
176
178
  },
177
179
 
178
180
  setConfig() {
179
- // no-op: 配置通过 scheduler.updateATRConfig() 更新
181
+ // no-op: 配置通过 scheduler.updateIndicatorConfig() 更新
180
182
  },
181
183
  }
182
184
  }
@@ -208,11 +210,14 @@ function drawWithCanvas2D(
208
210
  * 获取 ATR 标题信息(供 paneTitle 使用)
209
211
  */
210
212
  export function getATRTitleInfo(
211
- index: number,
212
- period: number,
213
+ _data: KLineData[],
214
+ index: number | null,
215
+ params: Record<string, number | boolean | string>,
213
216
  pluginHost: PluginHost,
214
- paneId: string = 'sub_ATR',
217
+ paneId: string,
215
218
  ): { name: string; params: number[]; values: Array<{ label: string; value: number; color: string }> } | null {
219
+ if (index === null) return null
220
+ const period = (params.period as number) ?? 14
216
221
  const state = pluginHost.getSharedState<ATRRenderState>(createATRStateKey(paneId))
217
222
  if (!state) return null
218
223
 
@@ -232,16 +237,14 @@ export function getATRTitleInfo(
232
237
  name: 'atr',
233
238
  displayName: 'ATR',
234
239
  category: 'oscillator',
235
- stateKey: createATRStateKey,
236
240
  defaultPaneId: 'sub_ATR',
237
- paneIdField: 'atrPaneId',
238
241
  scaleRendererFactory: createAtrScaleRendererPlugin,
239
- updateConfig: (scheduler, params, paneId) => {
240
- (scheduler as IndicatorScheduler).updateATRConfig(params as Partial<ATRSchedulerConfig>, paneId)
241
- },
242
242
  visibleState: { compose: createNonNegativeSparseVisibleStateComposer('atr', EMPTY_ATR_STATE) },
243
- applyResult: (host, state, paneId) => {
244
- host.setSharedState(createATRStateKey(paneId), state as any, 'indicator_scheduler')
243
+ getTitleInfo: getATRTitleInfo,
244
+ runtime: {
245
+ defaultConfig: { period: 14, showATR: true },
246
+ computeKey: 'calcATRData',
247
+ compute: (data, c) => calcATRData(data, c.period),
245
248
  },
246
249
  })
247
250
  class ATRIndicatorDefinition {
@@ -6,8 +6,9 @@ import { resolveThemeColors } from '../../../tokens'
6
6
  import { BOLL_STATE_KEY, type BOLLRenderState } from '../../indicators/bollState'
7
7
  import { Indicator } from '../../indicators/indicatorDefinitionRegistry'
8
8
  import { resolveStateKey } from '../../indicators/indicatorMetadata'
9
- import type { IndicatorPriceRangeComputer, IndicatorRenderStateComposer } from '../../indicators/indicatorMetadata'
9
+ import type { IndicatorPriceRangeComputer, IndicatorRenderStateComposer, GetTitleInfoFn, TitleInfo, TitleValueItem } from '../../indicators/indicatorMetadata'
10
10
  import type { BOLLSchedulerConfig, IndicatorScheduler } from '../../indicators/scheduler'
11
+ import { calcBOLLData } from '../../indicators/calculators'
11
12
 
12
13
  type LinePoint = { x: number; y: number }
13
14
 
@@ -109,7 +110,7 @@ function buildPriceCacheKey(
109
110
  return `${range.start}|${range.end}|${dataLength}|${lastTimestamp}|${period}`
110
111
  }
111
112
 
112
- function getBOLLStateKey(host: PluginHost | null): string | null {
113
+ export function getBOLLStateKey(host: PluginHost | null): string | null {
113
114
  const scheduler = host?.getService<IndicatorScheduler>('indicatorScheduler')
114
115
  if (!scheduler) {
115
116
  console.warn('[BOLLRenderer] Scheduler not available via service locator')
@@ -154,11 +155,37 @@ const composeBOLLRenderState: IndicatorRenderStateComposer = (bundle, range, tim
154
155
  }
155
156
  }
156
157
 
158
+ export const getBOLLTitleInfo: GetTitleInfoFn = (
159
+ _data: KLineData[],
160
+ index: number | null,
161
+ _params: Record<string, number | boolean | string>,
162
+ pluginHost: PluginHost,
163
+ _paneId: string,
164
+ ): TitleInfo | null => {
165
+ if (index === null) return null
166
+
167
+ const stateKey = getBOLLStateKey(pluginHost)
168
+ if (!stateKey) return null
169
+
170
+ const state = pluginHost?.getSharedState<BOLLRenderState>(stateKey)
171
+ if (!state || state.visibleMin > state.visibleMax) return null
172
+
173
+ const bollPoint = state.series[index]
174
+ if (!bollPoint) return null
175
+
176
+ const values: TitleValueItem[] = [
177
+ { label: 'UP', value: bollPoint.upper, color: '#C83C3C' },
178
+ { label: 'MID', value: bollPoint.middle, color: '#5A8CFF' },
179
+ { label: 'DN', value: bollPoint.lower, color: '#32AA3C' },
180
+ ]
181
+
182
+ return { name: 'BOLL', params: [state.params.period, state.params.multiplier], values }
183
+ }
184
+
157
185
  @Indicator({
158
186
  name: 'boll',
159
187
  displayName: 'BOLL',
160
188
  category: 'main',
161
- stateKey: BOLL_STATE_KEY,
162
189
  defaultPaneId: 'main',
163
190
  mainPane: {
164
191
  rendererName: 'boll',
@@ -168,9 +195,6 @@ const composeBOLLRenderState: IndicatorRenderStateComposer = (bundle, range, tim
168
195
  computePriceRange: computeBOLLPriceRange,
169
196
  composeRenderState: composeBOLLRenderState,
170
197
  },
171
- updateConfig: (scheduler, params) => {
172
- (scheduler as IndicatorScheduler).updateBOLLConfig(params as Partial<BOLLSchedulerConfig>)
173
- },
174
198
  semantic: {
175
199
  apply: (chart, indicator) => {
176
200
  const params = (indicator as { params?: { period?: number; multiplier?: number } }).params
@@ -180,9 +204,8 @@ const composeBOLLRenderState: IndicatorRenderStateComposer = (bundle, range, tim
180
204
  })
181
205
  },
182
206
  },
183
- applyResult: (host, state, _paneId) => {
184
- host.setSharedState(BOLL_STATE_KEY, state as any, 'indicator_scheduler')
185
- },
207
+ runtime: { defaultConfig:{period:20,multiplier:2,showUpper:true,showMiddle:true,showLower:true,showBand:true}, computeKey:'calcBOLLData', compute:(data,c)=>calcBOLLData(data,c.period,c.multiplier) },
208
+ getTitleInfo: getBOLLTitleInfo,
186
209
  })
187
210
  class BOLLDefinition {
188
211
  static rendererFactory = createBOLLRendererPlugin
@@ -363,7 +386,7 @@ export function createBOLLRendererPlugin(): RendererPluginWithHost {
363
386
  },
364
387
 
365
388
  setConfig(_newConfig: Record<string, unknown>) {
366
- // 外部控制器应调用 chart.getIndicatorScheduler().updateBOLLConfig()
389
+ // 外部控制器应调用 chart.getIndicatorScheduler().updateIndicatorConfig()
367
390
  },
368
391
  }
369
392
  }
@@ -8,6 +8,8 @@ import { Indicator } from '../../indicators/indicatorDefinitionRegistry'
8
8
  import { resolveStateKey } from '../../indicators/indicatorMetadata'
9
9
  import type { IndicatorScheduler, CCISchedulerConfig } from '../../indicators/scheduler'
10
10
  import { createCciScaleRendererPlugin } from './scale/cci_scale'
11
+ import { calcCCIData } from '../../indicators/calculators'
12
+ import type { KLineData } from '../../../types/price'
11
13
 
12
14
  type LinePoint = { x: number; y: number }
13
15
 
@@ -202,7 +204,7 @@ const { ctx, pane, range, scrollLeft, dpr, kLineCenters, lineWebGLSurface } = co
202
204
  },
203
205
 
204
206
  setConfig() {
205
- // no-op: 配置通过 scheduler.updateCCIConfig() 更新
207
+ // no-op: 配置通过 scheduler.updateIndicatorConfig() 更新
206
208
  },
207
209
  }
208
210
  }
@@ -239,14 +241,15 @@ function drawCCILineWithCanvas2D(
239
241
  * 获取 CCI 标题信息(供 paneTitle 使用)
240
242
  */
241
243
  export function getCCITitleInfo(
242
- index: number,
243
- period: number,
244
+ _data: KLineData[],
245
+ index: number | null,
246
+ params: Record<string, number | boolean | string>,
244
247
  pluginHost: PluginHost,
245
- paneId: string = 'sub_CCI',
246
- theme: 'light' | 'dark' = 'light',
247
- isAsiaMarket?: boolean
248
+ paneId: string,
248
249
  ): { name: string; params: number[]; values: Array<{ label: string; value: number; color: string }> } | null {
249
- const colors = resolveThemeColors(theme, isAsiaMarket)
250
+ if (index === null) return null
251
+ const period = (params.period as number) ?? 14
252
+ const colors = resolveThemeColors('light')
250
253
  const state = pluginHost.getSharedState<CCIRenderState>(createCCIStateKey(paneId))
251
254
  if (!state) return null
252
255
 
@@ -266,16 +269,14 @@ export function getCCITitleInfo(
266
269
  name: 'cci',
267
270
  displayName: 'CCI',
268
271
  category: 'oscillator',
269
- stateKey: createCCIStateKey,
270
272
  defaultPaneId: 'sub_CCI',
271
- paneIdField: 'cciPaneId',
272
273
  scaleRendererFactory: createCciScaleRendererPlugin,
273
274
  visibleState: { compose: createCCIVisibleStateComposer('cci', EMPTY_CCI_STATE) },
274
- updateConfig: (scheduler, params, paneId) => {
275
- (scheduler as IndicatorScheduler).updateCCIConfig(params as Partial<CCISchedulerConfig>, paneId)
276
- },
277
- applyResult: (host, state, paneId) => {
278
- host.setSharedState(createCCIStateKey(paneId), state as any, 'indicator_scheduler')
275
+ getTitleInfo: getCCITitleInfo,
276
+ runtime: {
277
+ defaultConfig: { period: 14, showCCI: true },
278
+ computeKey: 'calcCCIData',
279
+ compute: (data, c) => calcCCIData(data, c.period),
279
280
  },
280
281
  })
281
282
  class CCIIndicatorDefinition {
@@ -2,10 +2,13 @@ import type { RendererPluginWithHost, RenderContext, PluginHost } from '../../..
2
2
  import { RENDERER_PRIORITY } from '../../../plugin'
3
3
  import type { ChaikinVolRenderState } from '../../indicators/chaikinVolState'
4
4
  import { createChaikinVolStateKey, EMPTY_CHAIKIN_VOL_STATE } from '../../indicators/chaikinVolState'
5
+ import type { TitleInfo } from '../../indicators/indicatorMetadata'
6
+ import type { KLineData } from '../../../types/price'
5
7
  import { Indicator } from '../../indicators/indicatorDefinitionRegistry'
6
8
  import { resolveStateKey } from '../../indicators/indicatorMetadata'
7
9
  import { createSparseVisibleStateComposer } from '../../indicators/visibleStateComposers'
8
10
  import type { IndicatorScheduler, ChaikinVolSchedulerConfig } from '../../indicators/scheduler'
11
+ import { calcChaikinVolData } from '../../indicators/calculators'
9
12
 
10
13
  const CHAIKIN_VOL_COLOR = '#f59e0b'
11
14
 
@@ -123,20 +126,39 @@ export function createChaikinVolRendererPlugin(options: { paneId?: string } = {}
123
126
  }
124
127
  }
125
128
 
129
+ export function getChaikinVolTitleInfo(
130
+ _data: KLineData[],
131
+ index: number | null,
132
+ params: Record<string, number | boolean | string>,
133
+ host: PluginHost,
134
+ paneId: string,
135
+ ): TitleInfo | null {
136
+ if (index === null) return null
137
+ const emaPeriod = (params.emaPeriod as number) ?? 10
138
+ const rocPeriod = (params.rocPeriod as number) ?? 10
139
+ const state = host.getSharedState<ChaikinVolRenderState>(createChaikinVolStateKey(paneId))
140
+ const value = state?.series[index]
141
+ if (value === undefined) return null
142
+
143
+ return {
144
+ name: 'ChaikinVol',
145
+ params: [emaPeriod, rocPeriod],
146
+ values: [{ label: 'ChaikinVol', value, color: CHAIKIN_VOL_COLOR }],
147
+ }
148
+ }
149
+
126
150
  @Indicator({
127
151
  name: 'chaikinVol',
128
152
  displayName: 'ChaikinVol',
129
153
  category: 'oscillator',
130
- stateKey: createChaikinVolStateKey,
131
154
  defaultPaneId: 'sub_ChaikinVol',
132
- paneIdField: 'chaikinVolPaneId',
133
155
  visibleState: { compose: createSparseVisibleStateComposer('chaikinVol', EMPTY_CHAIKIN_VOL_STATE) },
134
156
  scale: { indicatorKey: 'chaikinVol', label: 'ChaikinVol', decimals: 2 },
135
- updateConfig: (scheduler, params, paneId) => {
136
- (scheduler as IndicatorScheduler).updateChaikinVolConfig(params as Partial<ChaikinVolSchedulerConfig>, paneId)
137
- },
138
- applyResult: (host, state, paneId) => {
139
- host.setSharedState(createChaikinVolStateKey(paneId), state as any, 'indicator_scheduler')
157
+ getTitleInfo: getChaikinVolTitleInfo,
158
+ runtime: {
159
+ defaultConfig: { emaPeriod: 10, rocPeriod: 10, showChaikinVol: true },
160
+ computeKey: 'calcChaikinVolData',
161
+ compute: (data, c) => calcChaikinVolData(data, c.emaPeriod, c.rocPeriod),
140
162
  },
141
163
  })
142
164
  class ChaikinVolIndicatorDefinition {
@@ -2,10 +2,13 @@ import type { RendererPluginWithHost, RenderContext, PluginHost } from '../../..
2
2
  import { RENDERER_PRIORITY } from '../../../plugin'
3
3
  import type { CMFRenderState } from '../../indicators/cmfState'
4
4
  import { createCMFStateKey, EMPTY_CMF_STATE } from '../../indicators/cmfState'
5
+ import type { TitleInfo } from '../../indicators/indicatorMetadata'
6
+ import type { KLineData } from '../../../types/price'
5
7
  import { Indicator } from '../../indicators/indicatorDefinitionRegistry'
6
8
  import { createFixedRangeSparseVisibleStateComposer } from '../../indicators/visibleStateComposers'
7
9
  import { resolveStateKey } from '../../indicators/indicatorMetadata'
8
10
  import type { IndicatorScheduler, CMFSchedulerConfig } from '../../indicators/scheduler'
11
+ import { calcCMFData } from '../../indicators/calculators'
9
12
 
10
13
  const CMF_COLOR = '#06b6d4'
11
14
 
@@ -122,20 +125,38 @@ export function createCMFRendererPlugin(options: { paneId?: string } = {}): Rend
122
125
  }
123
126
  }
124
127
 
128
+ export function getCMFTitleInfo(
129
+ _data: KLineData[],
130
+ index: number | null,
131
+ params: Record<string, number | boolean | string>,
132
+ host: PluginHost,
133
+ paneId: string,
134
+ ): TitleInfo | null {
135
+ if (index === null) return null
136
+ const period = (params.period as number) ?? 20
137
+ const state = host.getSharedState<CMFRenderState>(createCMFStateKey(paneId))
138
+ const value = state?.series[index]
139
+ if (value === undefined) return null
140
+
141
+ return {
142
+ name: 'CMF',
143
+ params: [period],
144
+ values: [{ label: 'CMF', value, color: CMF_COLOR }],
145
+ }
146
+ }
147
+
125
148
  @Indicator({
126
149
  name: 'cmf',
127
150
  displayName: 'CMF',
128
151
  category: 'volume',
129
- stateKey: createCMFStateKey,
130
152
  defaultPaneId: 'sub_CMF',
131
- paneIdField: 'cmfPaneId',
132
153
  visibleState: { compose: createFixedRangeSparseVisibleStateComposer('cmf', EMPTY_CMF_STATE) },
133
154
  scale: { indicatorKey: 'cmf', label: 'CMF', decimals: 4 },
134
- updateConfig: (scheduler, params, paneId) => {
135
- (scheduler as IndicatorScheduler).updateCMFConfig(params as Partial<CMFSchedulerConfig>, paneId)
136
- },
137
- applyResult: (host, state, paneId) => {
138
- host.setSharedState(createCMFStateKey(paneId), state as any, 'indicator_scheduler')
155
+ getTitleInfo: getCMFTitleInfo,
156
+ runtime: {
157
+ defaultConfig: { period: 20, showCMF: true },
158
+ computeKey: 'calcCMFData',
159
+ compute: (data, c) => calcCMFData(data, c.period),
139
160
  },
140
161
  })
141
162
  class CMFIndicatorDefinition {
@@ -1,11 +1,13 @@
1
1
  import type { RendererPluginWithHost, RenderContext, PluginHost } from '../../../plugin'
2
+ import type { KLineData } from '../../../types/price'
2
3
  import { RENDERER_PRIORITY } from '../../../plugin'
3
4
  import type { DEMARenderState } from '../../indicators/demaState'
4
5
  import { createDEMAStateKey, EMPTY_DEMA_STATE } from '../../indicators/demaState'
5
6
  import { Indicator } from '../../indicators/indicatorDefinitionRegistry'
6
- import { resolveStateKey } from '../../indicators/indicatorMetadata'
7
+ import { resolveStateKey, type TitleInfo, type TitleValueItem, type GetTitleInfoFn } from '../../indicators/indicatorMetadata'
7
8
  import { createSparseVisibleStateComposer } from '../../indicators/visibleStateComposers'
8
9
  import type { IndicatorScheduler, DEMASchedulerConfig } from '../../indicators/scheduler'
10
+ import { calcDEMAData } from '../../indicators/calculators'
9
11
 
10
12
  const DEMA_COLOR = '#6366f1'
11
13
 
@@ -120,23 +122,40 @@ export function createDEMARendererPlugin(options: DEMARendererOptions = {}): Ren
120
122
  }
121
123
  }
122
124
 
125
+ export const getDEMATitleInfo: GetTitleInfoFn = (
126
+ _data: KLineData[],
127
+ index: number | null,
128
+ _params: Record<string, number | boolean | string>,
129
+ pluginHost: PluginHost,
130
+ paneId: string,
131
+ ): TitleInfo | null => {
132
+ if (index === null) return null
133
+
134
+ const stateKey = createDEMAStateKey(paneId)
135
+ const state = pluginHost?.getSharedState<DEMARenderState>(stateKey)
136
+ if (!state || state.visibleMin > state.visibleMax) return null
137
+
138
+ const value = state.series[index]
139
+ if (value === undefined) return null
140
+
141
+ return {
142
+ name: 'DEMA',
143
+ params: [state.params.period],
144
+ values: [{ label: 'DEMA', value, color: '#6366f1' }],
145
+ }
146
+ }
147
+
123
148
  @Indicator({
124
149
  name: 'dema',
125
150
  displayName: 'DEMA',
151
+ getTitleInfo: getDEMATitleInfo,
126
152
  category: 'main',
127
- stateKey: createDEMAStateKey,
128
153
  defaultPaneId: 'main',
129
- paneIdField: 'demaPaneId',
130
154
  allowMainPane: true,
131
155
  mainPane: { rendererName: 'dema_main', toActiveConfig: (params, active) => ({ ...params, showDEMA: active }) },
132
156
  visibleState: { compose: createSparseVisibleStateComposer('dema', EMPTY_DEMA_STATE) },
133
157
  scale: { indicatorKey: 'dema', label: 'DEMA', decimals: 2 },
134
- updateConfig: (scheduler, params, paneId) => {
135
- (scheduler as IndicatorScheduler).updateDEMAConfig(params as Partial<DEMASchedulerConfig>, paneId)
136
- },
137
- applyResult: (host, state, paneId) => {
138
- host.setSharedState(createDEMAStateKey(paneId), state as any, 'indicator_scheduler')
139
- },
158
+ runtime: { defaultConfig:{period:14,showDEMA:true}, computeKey:'calcDEMAData', compute:(data,c)=>calcDEMAData(data,c.period) },
140
159
  })
141
160
  class DEMADefinition {
142
161
  static rendererFactory = createDEMARendererPlugin
@@ -1,10 +1,12 @@
1
1
  import type { RendererPluginWithHost, RenderContext, PluginHost } from '../../../plugin'
2
2
  import { RENDERER_PRIORITY } from '../../../plugin'
3
+ import type { KLineData } from '../../../types/price'
3
4
  import type { DonchianRenderState } from '../../indicators/donchianState'
4
5
  import { createDonchianStateKey, EMPTY_DONCHIAN_STATE } from '../../indicators/donchianState'
5
6
  import { Indicator } from '../../indicators/indicatorDefinitionRegistry'
6
- import { resolveStateKey } from '../../indicators/indicatorMetadata'
7
+ import { resolveStateKey, type TitleInfo, type GetTitleInfoFn } from '../../indicators/indicatorMetadata'
7
8
  import type { IndicatorScheduler, DonchianSchedulerConfig } from '../../indicators/scheduler'
9
+ import { calcDonchianData } from '../../indicators/calculators'
8
10
  import { createBandVisibleStateComposer } from '../../indicators/visibleStateComposers'
9
11
 
10
12
  const DONCHIAN_UPPER_COLOR = '#0891b2'
@@ -122,23 +124,40 @@ function drawLine(ctx: CanvasRenderingContext2D, pts: Point[], color: string): v
122
124
  ctx.stroke()
123
125
  }
124
126
 
127
+ export function getDonchianTitleInfo(
128
+ _data: KLineData[],
129
+ index: number | null,
130
+ params: Record<string, number | boolean | string>,
131
+ host: PluginHost,
132
+ paneId: string,
133
+ ): TitleInfo | null {
134
+ if (index === null) return null
135
+ const state = host.getSharedState<DonchianRenderState>(createDonchianStateKey(paneId))
136
+ const p = state?.series[index]
137
+ if (!p) return null
138
+
139
+ return {
140
+ name: 'Donchian',
141
+ params: [(params.period as number) ?? 20],
142
+ values: [
143
+ { label: 'Upper', value: p.upper, color: '#0891b2' },
144
+ { label: 'Mid', value: p.middle, color: '#94a3b8' },
145
+ { label: 'Lower', value: p.lower, color: '#0891b2' },
146
+ ],
147
+ }
148
+ }
149
+
125
150
  @Indicator({
126
151
  name: 'donchian',
127
152
  displayName: 'Donchian',
153
+ getTitleInfo: getDonchianTitleInfo,
128
154
  category: 'main',
129
- stateKey: createDonchianStateKey,
130
155
  defaultPaneId: 'main',
131
- paneIdField: 'donchianPaneId',
132
156
  allowMainPane: true,
133
157
  mainPane: { rendererName: 'donchian_main', toActiveConfig: (params, active) => ({ ...params, showUpper: active, showMiddle: active, showLower: active }) },
134
158
  scale: { indicatorKey: 'donchian', label: 'Donchian', decimals: 2 },
135
159
  visibleState: { compose: createBandVisibleStateComposer('donchian', EMPTY_DONCHIAN_STATE, 'lower', 'upper') },
136
- updateConfig: (scheduler, params, paneId) => {
137
- (scheduler as IndicatorScheduler).updateDonchianConfig(params as Partial<DonchianSchedulerConfig>, paneId)
138
- },
139
- applyResult: (host, state, paneId) => {
140
- host.setSharedState(createDonchianStateKey(paneId), state as any, 'indicator_scheduler')
141
- },
160
+ runtime: { defaultConfig:{period:20,showUpper:true,showMiddle:true,showLower:true}, computeKey:'calcDonchianData', compute:(data,c)=>calcDonchianData(data,c.period) },
142
161
  })
143
162
  class DonchianDefinition {
144
163
  static rendererFactory = createDonchianRendererPlugin