@363045841yyt/klinechart-core 0.7.3 → 0.7.5

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 (247) hide show
  1. package/README.md +201 -201
  2. package/README.zh-CN.md +201 -201
  3. package/dist/controllers/index.d.ts +1 -0
  4. package/dist/controllers/index.d.ts.map +1 -1
  5. package/dist/controllers/index.js +1 -0
  6. package/dist/controllers/index.js.map +1 -1
  7. package/dist/engine/chart.d.ts +11 -19
  8. package/dist/engine/chart.d.ts.map +1 -1
  9. package/dist/engine/chart.js +92 -109
  10. package/dist/engine/chart.js.map +1 -1
  11. package/dist/engine/renderers/Indicator/indicatorData.d.ts +1 -0
  12. package/dist/engine/renderers/Indicator/indicatorData.d.ts.map +1 -1
  13. package/dist/engine/renderers/Indicator/indicatorData.js +1 -1
  14. package/dist/engine/renderers/Indicator/indicatorData.js.map +1 -1
  15. package/dist/engine/renderers/webgl/candleSurface.js +47 -47
  16. package/dist/engine/subPaneManager.d.ts +4 -0
  17. package/dist/engine/subPaneManager.d.ts.map +1 -1
  18. package/dist/engine/subPaneManager.js +13 -0
  19. package/dist/engine/subPaneManager.js.map +1 -1
  20. package/dist/version.d.ts +1 -1
  21. package/dist/version.d.ts.map +1 -1
  22. package/dist/version.js +1 -2
  23. package/dist/version.js.map +1 -1
  24. package/package.json +129 -122
  25. package/src/__tests__/signal.test.ts +124 -124
  26. package/src/config/chartSettings.ts +66 -66
  27. package/src/controllers/__tests__/drawing.test.ts +214 -214
  28. package/src/controllers/__tests__/indicatorSelector.test.ts +481 -481
  29. package/src/controllers/__tests__/toolbar.test.ts +225 -225
  30. package/src/controllers/createChartController.ts +665 -665
  31. package/src/controllers/createDrawingController.ts +96 -96
  32. package/src/controllers/createIndicatorSelectorController.ts +307 -307
  33. package/src/controllers/createToolbarController.ts +146 -146
  34. package/src/controllers/index.ts +20 -19
  35. package/src/controllers/types.ts +284 -284
  36. package/src/engine/__tests__/chart.dpr.test.ts +401 -401
  37. package/src/engine/__tests__/paneRenderer.resize.test.ts +92 -92
  38. package/src/engine/chart-store.ts +121 -121
  39. package/src/engine/chart.d.ts +617 -617
  40. package/src/engine/chart.ts +2803 -2815
  41. package/src/engine/controller/__tests__/interaction.dpr.test.ts +259 -259
  42. package/src/engine/controller/interaction.ts +722 -722
  43. package/src/engine/controller/markerInteraction.ts +130 -130
  44. package/src/engine/controller/pinchTracker.ts +82 -82
  45. package/src/engine/controller/tooltipPosition.ts +48 -48
  46. package/src/engine/draw/__tests__/pixelAlign.spec.ts +176 -176
  47. package/src/engine/draw/pixelAlign.ts +259 -259
  48. package/src/engine/drawing/index.ts +655 -655
  49. package/src/engine/drawing/interaction.ts +842 -842
  50. package/src/engine/drawing/plugin.ts +343 -343
  51. package/src/engine/indicators/__tests__/__fixtures__/golden/atr.json +38 -38
  52. package/src/engine/indicators/__tests__/__fixtures__/golden/dema.json +14 -14
  53. package/src/engine/indicators/__tests__/__fixtures__/golden/hma.json +14 -14
  54. package/src/engine/indicators/__tests__/__fixtures__/golden/index.ts +55 -55
  55. package/src/engine/indicators/__tests__/__fixtures__/golden/kama.json +14 -14
  56. package/src/engine/indicators/__tests__/__fixtures__/golden/tema.json +14 -14
  57. package/src/engine/indicators/__tests__/__fixtures__/golden/wma.json +40 -40
  58. package/src/engine/indicators/__tests__/__fixtures__/synthetic.ts +65 -65
  59. package/src/engine/indicators/__tests__/_propertyAssertions.ts +76 -76
  60. package/src/engine/indicators/__tests__/atr.test.ts +153 -153
  61. package/src/engine/indicators/__tests__/calculators.test.ts +614 -614
  62. package/src/engine/indicators/__tests__/cmf-mfi.test.ts +100 -100
  63. package/src/engine/indicators/__tests__/dema.test.ts +73 -73
  64. package/src/engine/indicators/__tests__/donchian.test.ts +70 -70
  65. package/src/engine/indicators/__tests__/hma.test.ts +73 -73
  66. package/src/engine/indicators/__tests__/ichimoku.test.ts +105 -105
  67. package/src/engine/indicators/__tests__/kama.test.ts +80 -80
  68. package/src/engine/indicators/__tests__/keltner.test.ts +65 -65
  69. package/src/engine/indicators/__tests__/pivot-fib.test.ts +110 -110
  70. package/src/engine/indicators/__tests__/roc.test.ts +68 -68
  71. package/src/engine/indicators/__tests__/sar.test.ts +86 -86
  72. package/src/engine/indicators/__tests__/scheduler.test.ts +831 -831
  73. package/src/engine/indicators/__tests__/soa.test.ts +533 -533
  74. package/src/engine/indicators/__tests__/structure.test.ts +110 -110
  75. package/src/engine/indicators/__tests__/supertrend.test.ts +65 -65
  76. package/src/engine/indicators/__tests__/tema.test.ts +68 -68
  77. package/src/engine/indicators/__tests__/trix.test.ts +70 -70
  78. package/src/engine/indicators/__tests__/volatility.test.ts +117 -117
  79. package/src/engine/indicators/__tests__/volume.test.ts +115 -115
  80. package/src/engine/indicators/__tests__/volumeProfile.test.ts +74 -74
  81. package/src/engine/indicators/__tests__/vwap.test.ts +69 -69
  82. package/src/engine/indicators/__tests__/wma.test.ts +112 -112
  83. package/src/engine/indicators/__tests__/zones.test.ts +95 -95
  84. package/src/engine/indicators/atrState.ts +27 -27
  85. package/src/engine/indicators/bollState.ts +51 -51
  86. package/src/engine/indicators/calculators.ts +2593 -2593
  87. package/src/engine/indicators/cciState.ts +25 -25
  88. package/src/engine/indicators/chaikinVolState.ts +32 -32
  89. package/src/engine/indicators/cmfState.ts +27 -27
  90. package/src/engine/indicators/demaState.ts +27 -27
  91. package/src/engine/indicators/donchianState.ts +43 -43
  92. package/src/engine/indicators/eneState.ts +43 -43
  93. package/src/engine/indicators/expmaState.ts +43 -43
  94. package/src/engine/indicators/fastkState.ts +25 -25
  95. package/src/engine/indicators/fibState.ts +41 -41
  96. package/src/engine/indicators/hmaState.ts +27 -27
  97. package/src/engine/indicators/hvState.ts +28 -28
  98. package/src/engine/indicators/ichimokuState.ts +70 -70
  99. package/src/engine/indicators/indicator.worker.ts +169 -169
  100. package/src/engine/indicators/indicatorDefinitionRegistry.ts +62 -62
  101. package/src/engine/indicators/indicatorMetadata.ts +110 -110
  102. package/src/engine/indicators/indicatorRegistry.ts +106 -106
  103. package/src/engine/indicators/indicatorRuntime.ts +1548 -1548
  104. package/src/engine/indicators/kamaState.ts +34 -34
  105. package/src/engine/indicators/keltnerState.ts +49 -49
  106. package/src/engine/indicators/kstState.ts +42 -42
  107. package/src/engine/indicators/maState.ts +36 -36
  108. package/src/engine/indicators/macdState.ts +76 -76
  109. package/src/engine/indicators/mfiState.ts +27 -27
  110. package/src/engine/indicators/momState.ts +25 -25
  111. package/src/engine/indicators/obvState.ts +25 -25
  112. package/src/engine/indicators/parkinsonState.ts +28 -28
  113. package/src/engine/indicators/pivotState.ts +51 -51
  114. package/src/engine/indicators/pvtState.ts +25 -25
  115. package/src/engine/indicators/rocState.ts +27 -27
  116. package/src/engine/indicators/rsiState.ts +65 -65
  117. package/src/engine/indicators/sarState.ts +41 -41
  118. package/src/engine/indicators/scheduler.ts +1205 -1205
  119. package/src/engine/indicators/soa.ts +352 -352
  120. package/src/engine/indicators/stateComposer.ts +1262 -1262
  121. package/src/engine/indicators/stochState.ts +26 -26
  122. package/src/engine/indicators/structureState.ts +69 -69
  123. package/src/engine/indicators/supertrendState.ts +37 -37
  124. package/src/engine/indicators/temaState.ts +27 -27
  125. package/src/engine/indicators/trixState.ts +35 -35
  126. package/src/engine/indicators/vmaState.ts +27 -27
  127. package/src/engine/indicators/volumeProfileState.ts +63 -63
  128. package/src/engine/indicators/vwapState.ts +29 -29
  129. package/src/engine/indicators/wmaState.ts +27 -27
  130. package/src/engine/indicators/wmsrState.ts +25 -25
  131. package/src/engine/indicators/workerProtocol.ts +613 -613
  132. package/src/engine/indicators/zonesState.ts +47 -47
  133. package/src/engine/layout/pane.ts +161 -161
  134. package/src/engine/marker/registry.ts +265 -265
  135. package/src/engine/paneRenderer.ts +169 -169
  136. package/src/engine/renderers/Indicator/atr.ts +237 -237
  137. package/src/engine/renderers/Indicator/boll.ts +317 -317
  138. package/src/engine/renderers/Indicator/cci.ts +275 -275
  139. package/src/engine/renderers/Indicator/chaikinVol.ts +138 -138
  140. package/src/engine/renderers/Indicator/cmf.ts +137 -137
  141. package/src/engine/renderers/Indicator/dema.ts +136 -136
  142. package/src/engine/renderers/Indicator/donchian.ts +137 -137
  143. package/src/engine/renderers/Indicator/ene.ts +271 -271
  144. package/src/engine/renderers/Indicator/expma.ts +197 -197
  145. package/src/engine/renderers/Indicator/fastk.ts +316 -316
  146. package/src/engine/renderers/Indicator/fib.ts +141 -141
  147. package/src/engine/renderers/Indicator/hma.ts +136 -136
  148. package/src/engine/renderers/Indicator/hv.ts +124 -124
  149. package/src/engine/renderers/Indicator/ichimoku.ts +181 -181
  150. package/src/engine/renderers/Indicator/index.ts +241 -241
  151. package/src/engine/renderers/Indicator/indicatorData.ts +650 -650
  152. package/src/engine/renderers/Indicator/kama.ts +136 -136
  153. package/src/engine/renderers/Indicator/keltner.ts +137 -137
  154. package/src/engine/renderers/Indicator/kst.ts +302 -302
  155. package/src/engine/renderers/Indicator/ma.ts +200 -200
  156. package/src/engine/renderers/Indicator/macd.ts +477 -477
  157. package/src/engine/renderers/Indicator/macdLegend.ts +141 -141
  158. package/src/engine/renderers/Indicator/mainIndicatorLegend.ts +272 -272
  159. package/src/engine/renderers/Indicator/mfi.ts +142 -142
  160. package/src/engine/renderers/Indicator/mom.ts +311 -311
  161. package/src/engine/renderers/Indicator/obv.ts +123 -123
  162. package/src/engine/renderers/Indicator/parkinson.ts +124 -124
  163. package/src/engine/renderers/Indicator/pivot.ts +131 -131
  164. package/src/engine/renderers/Indicator/pvt.ts +123 -123
  165. package/src/engine/renderers/Indicator/roc.ts +143 -143
  166. package/src/engine/renderers/Indicator/rsi.ts +390 -390
  167. package/src/engine/renderers/Indicator/sar.ts +113 -113
  168. package/src/engine/renderers/Indicator/scale/atr_scale.ts +19 -19
  169. package/src/engine/renderers/Indicator/scale/cci_scale.ts +19 -19
  170. package/src/engine/renderers/Indicator/scale/fastk_scale.ts +19 -19
  171. package/src/engine/renderers/Indicator/scale/indicator_scale.ts +204 -204
  172. package/src/engine/renderers/Indicator/scale/kst_scale.ts +19 -19
  173. package/src/engine/renderers/Indicator/scale/macd_scale.ts +22 -22
  174. package/src/engine/renderers/Indicator/scale/mom_scale.ts +19 -19
  175. package/src/engine/renderers/Indicator/scale/rsi_scale.ts +19 -19
  176. package/src/engine/renderers/Indicator/scale/stoch_scale.ts +19 -19
  177. package/src/engine/renderers/Indicator/scale/volume_scale.ts +26 -26
  178. package/src/engine/renderers/Indicator/scale/wmsr_scale.ts +19 -19
  179. package/src/engine/renderers/Indicator/stoch.ts +359 -359
  180. package/src/engine/renderers/Indicator/structure.ts +126 -126
  181. package/src/engine/renderers/Indicator/subPaneConfig.ts +265 -265
  182. package/src/engine/renderers/Indicator/supertrend.ts +115 -115
  183. package/src/engine/renderers/Indicator/tema.ts +136 -136
  184. package/src/engine/renderers/Indicator/trix.ts +158 -158
  185. package/src/engine/renderers/Indicator/vma.ts +124 -124
  186. package/src/engine/renderers/Indicator/volumeProfile.ts +125 -125
  187. package/src/engine/renderers/Indicator/vwap.ts +123 -123
  188. package/src/engine/renderers/Indicator/wma.ts +136 -136
  189. package/src/engine/renderers/Indicator/wmsr.ts +328 -328
  190. package/src/engine/renderers/Indicator/zones.ts +104 -104
  191. package/src/engine/renderers/__tests__/boll.renderer.test.ts +314 -314
  192. package/src/engine/renderers/__tests__/ene.renderer.test.ts +305 -305
  193. package/src/engine/renderers/__tests__/expma.renderer.test.ts +279 -279
  194. package/src/engine/renderers/__tests__/ma.renderer.test.ts +426 -426
  195. package/src/engine/renderers/__tests__/mainIndicatorLegend.renderer.test.ts +502 -502
  196. package/src/engine/renderers/__tests__/yAxis.renderer.test.ts +173 -173
  197. package/src/engine/renderers/candle.ts +459 -459
  198. package/src/engine/renderers/crosshair.ts +69 -69
  199. package/src/engine/renderers/customMarkers.ts +162 -162
  200. package/src/engine/renderers/extremaMarkers.ts +246 -246
  201. package/src/engine/renderers/gridLines.ts +90 -90
  202. package/src/engine/renderers/lastPrice.ts +97 -97
  203. package/src/engine/renderers/paneTitle.ts +136 -136
  204. package/src/engine/renderers/subVolume.ts +236 -236
  205. package/src/engine/renderers/timeAxis.ts +121 -121
  206. package/src/engine/renderers/webgl/candleSurface.ts +955 -955
  207. package/src/engine/renderers/webgl/sharedWebGLSurface.ts +146 -146
  208. package/src/engine/renderers/yAxis.ts +105 -105
  209. package/src/engine/scale/__tests__/logFormula.spec.ts +148 -148
  210. package/src/engine/scale/logFormula.ts +130 -130
  211. package/src/engine/scale/price.ts +39 -39
  212. package/src/engine/scale/priceScale.ts +264 -264
  213. package/src/engine/subPaneManager.ts +442 -427
  214. package/src/engine/theme/colors.ts +642 -642
  215. package/src/engine/theme/fonts.ts +20 -20
  216. package/src/engine/utils/klineConfig.ts +49 -49
  217. package/src/engine/utils/tickCount.ts +11 -11
  218. package/src/engine/utils/tickPosition.ts +214 -214
  219. package/src/engine/utils/zoom.ts +83 -83
  220. package/src/engine/viewport/viewport.ts +67 -67
  221. package/src/index.ts +3 -3
  222. package/src/plugin/ConfigManager.ts +93 -93
  223. package/src/plugin/EventBus.ts +77 -77
  224. package/src/plugin/HookSystem.ts +106 -106
  225. package/src/plugin/PluginHost.ts +243 -243
  226. package/src/plugin/PluginRegistry.ts +92 -92
  227. package/src/plugin/StateStore.ts +73 -73
  228. package/src/plugin/index.ts +19 -19
  229. package/src/plugin/rendererPluginManager.ts +368 -368
  230. package/src/plugin/stateKeys.ts +8 -8
  231. package/src/plugin/types.ts +526 -526
  232. package/src/reactivity/index.ts +2 -2
  233. package/src/reactivity/signal.ts +119 -119
  234. package/src/semantic/controller.ts +251 -251
  235. package/src/semantic/drawShape.ts +260 -260
  236. package/src/semantic/index.ts +28 -28
  237. package/src/semantic/schema.json +256 -256
  238. package/src/semantic/types.ts +251 -251
  239. package/src/semantic/validator.ts +349 -349
  240. package/src/types/kLine.ts +13 -13
  241. package/src/types/price.ts +56 -56
  242. package/src/types/volumePrice.ts +33 -33
  243. package/src/utils/dateFormat.ts +208 -208
  244. package/src/utils/kLineDraw/axis.ts +562 -562
  245. package/src/utils/priceToY.ts +34 -34
  246. package/src/utils/volumePrice.ts +202 -202
  247. package/src/version.ts +1 -1
@@ -1,4 +1,4 @@
1
- import { createSignal } from '../reactivity/signal';
1
+ import { createSignal, computed } from '../reactivity/signal';
2
2
  import { getVisibleRange } from './viewport/viewport';
3
3
  import { Pane, UpdateLevel } from './layout/pane';
4
4
  import { InteractionController } from './controller/interaction';
@@ -97,11 +97,11 @@ export class Chart {
97
97
  /** Overlay 帧复用的最近主渲染结果 */
98
98
  cachedDrawFrame = null;
99
99
  /** 副图管理器 */
100
- subPaneManager;
101
- /** 当前激活的主图指标列表(如 ['boll', 'ma']) */
102
- activeMainIndicators = new Set();
103
- /** 主图指标参数配置 */
104
- mainIndicatorParams = {
100
+ subPaneManager = new SubPaneManager();
101
+ /** 主图指标激活状态与参数(存在即激活,默认参数在 enable 时初始化) */
102
+ _mainIndicatorsSignal = createSignal(new Map());
103
+ /** 主图指标默认参数 */
104
+ static DEFAULT_MAIN_PARAMS = {
105
105
  MA: { ma5: true, ma10: true, ma20: true, ma30: true, ma60: true },
106
106
  BOLL: { period: 20, multiplier: 2, showUpper: true, showMiddle: true, showLower: true, showBand: true },
107
107
  EXPMA: { fastPeriod: 12, slowPeriod: 50 },
@@ -133,26 +133,29 @@ export class Chart {
133
133
  console.warn(`[Chart] 未知的主图指标: ${indicatorId}`);
134
134
  return false;
135
135
  }
136
- if (this.activeMainIndicators.has(id)) {
136
+ const map = this._mainIndicatorsSignal.peek();
137
+ const existing = map.get(id);
138
+ if (existing) {
137
139
  // 已启用,更新参数
138
140
  if (params) {
139
- this.mainIndicatorParams[id] = { ...this.mainIndicatorParams[id], ...params };
141
+ const next = new Map(map);
142
+ next.set(id, { params: { ...existing.params, ...params } });
143
+ this._mainIndicatorsSignal.set(next);
140
144
  this.updateIndicatorSchedulerConfig(id);
141
- this.syncIndicatorsSignal();
142
145
  }
143
146
  return true;
144
147
  }
145
- this.activeMainIndicators.add(id);
146
148
  // 合并默认参数和传入参数
147
- if (params) {
148
- this.mainIndicatorParams[id] = { ...this.mainIndicatorParams[id], ...params };
149
- }
149
+ const defaults = Chart.DEFAULT_MAIN_PARAMS[id] ?? {};
150
+ const merged = params ? { ...defaults, ...params } : defaults;
151
+ const next = new Map(map);
152
+ next.set(id, { params: merged });
153
+ this._mainIndicatorsSignal.set(next);
150
154
  // 启用对应的渲染器
151
155
  this.enableMainIndicatorRenderer(id);
152
156
  // 更新调度器配置
153
157
  this.updateIndicatorSchedulerConfig(id);
154
158
  this.scheduleDraw();
155
- this.syncIndicatorsSignal();
156
159
  return true;
157
160
  }
158
161
  /**
@@ -162,15 +165,17 @@ export class Chart {
162
165
  */
163
166
  disableMainIndicator(indicatorId) {
164
167
  const id = indicatorId.toUpperCase();
165
- if (!this.activeMainIndicators.has(id))
168
+ const map = this._mainIndicatorsSignal.peek();
169
+ if (!map.has(id))
166
170
  return false;
167
- this.activeMainIndicators.delete(id);
171
+ const next = new Map(map);
172
+ next.delete(id);
173
+ this._mainIndicatorsSignal.set(next);
168
174
  // 禁用对应的渲染器
169
175
  this.disableMainIndicatorRenderer(id);
170
176
  // 更新调度器配置
171
177
  this.updateIndicatorSchedulerConfig(id);
172
178
  this.scheduleDraw();
173
- this.syncIndicatorsSignal();
174
179
  return true;
175
180
  }
176
181
  /**
@@ -191,14 +196,14 @@ export class Chart {
191
196
  * @returns 激活的指标ID数组
192
197
  */
193
198
  getActiveMainIndicators() {
194
- return Array.from(this.activeMainIndicators);
199
+ return [...this._mainIndicatorsSignal.peek().keys()];
195
200
  }
196
201
  /**
197
202
  * 检查主图指标是否激活
198
203
  * @param indicatorId 指标ID
199
204
  */
200
205
  isMainIndicatorActive(indicatorId) {
201
- return this.activeMainIndicators.has(indicatorId.toUpperCase());
206
+ return this._mainIndicatorsSignal.peek().has(indicatorId.toUpperCase());
202
207
  }
203
208
  /**
204
209
  * 更新主图指标参数
@@ -207,38 +212,41 @@ export class Chart {
207
212
  */
208
213
  updateMainIndicatorParams(indicatorId, params) {
209
214
  const id = indicatorId.toUpperCase();
210
- if (!this.mainIndicatorParams[id]) {
211
- this.mainIndicatorParams[id] = {};
212
- }
213
- this.mainIndicatorParams[id] = { ...this.mainIndicatorParams[id], ...params };
215
+ const map = this._mainIndicatorsSignal.peek();
216
+ const entry = map.get(id);
217
+ if (!entry)
218
+ return;
219
+ const merged = { ...entry.params, ...params };
220
+ const next = new Map(map);
221
+ next.set(id, { params: merged });
222
+ this._mainIndicatorsSignal.set(next);
214
223
  // 同步更新渲染器配置
215
224
  const rendererName = id.toLowerCase();
216
225
  const renderer = this.getRenderer(rendererName);
217
226
  if (renderer && renderer.setConfig) {
218
- renderer.setConfig(this.mainIndicatorParams[id]);
227
+ renderer.setConfig(merged);
219
228
  }
220
229
  // 更新调度器
221
230
  this.updateIndicatorSchedulerConfig(id);
222
231
  this.scheduleDraw();
223
- this.syncIndicatorsSignal();
224
232
  }
225
233
  /**
226
234
  * 获取主图指标参数
227
235
  * @param indicatorId 指标ID
228
236
  */
229
237
  getMainIndicatorParams(indicatorId) {
230
- return this.mainIndicatorParams[indicatorId.toUpperCase()] ?? null;
238
+ return this._mainIndicatorsSignal.peek().get(indicatorId.toUpperCase())?.params ?? null;
231
239
  }
232
240
  /**
233
241
  * 清除所有主图指标
234
242
  */
235
243
  clearMainIndicators() {
236
- for (const id of this.activeMainIndicators) {
244
+ const map = this._mainIndicatorsSignal.peek();
245
+ for (const id of map.keys()) {
237
246
  this.disableMainIndicatorRenderer(id);
238
247
  }
239
- this.activeMainIndicators.clear();
248
+ this._mainIndicatorsSignal.set(new Map());
240
249
  this.scheduleDraw();
241
- this.syncIndicatorsSignal();
242
250
  }
243
251
  /**
244
252
  * 启用主图指标渲染器(内部方法)
@@ -395,8 +403,9 @@ export class Chart {
395
403
  * 更新调度器配置(内部方法)
396
404
  */
397
405
  updateIndicatorSchedulerConfig(indicatorId) {
398
- const isActive = this.activeMainIndicators.has(indicatorId);
399
- const params = this.mainIndicatorParams[indicatorId] || {};
406
+ const entry = this._mainIndicatorsSignal.peek().get(indicatorId);
407
+ const isActive = entry !== undefined;
408
+ const params = entry?.params ?? {};
400
409
  switch (indicatorId) {
401
410
  case 'MA':
402
411
  this.indicatorScheduler.updateMAConfig({
@@ -475,7 +484,7 @@ export class Chart {
475
484
  setActiveMainIndicators(indicators) {
476
485
  // 计算需要启用和禁用的指标
477
486
  const newSet = new Set(indicators.map(i => i.toUpperCase()));
478
- const currentSet = new Set(this.activeMainIndicators);
487
+ const currentSet = new Set(this._mainIndicatorsSignal.peek().keys());
479
488
  // 禁用不再激活的
480
489
  for (const id of currentSet) {
481
490
  if (!newSet.has(id)) {
@@ -523,11 +532,20 @@ export class Chart {
523
532
  this.indicatorScheduler.registerIndicator(definition);
524
533
  }
525
534
  this.indicatorScheduler.setInvalidateCallback(() => this.scheduleDraw());
526
- // 初始化副图管理器
527
- this.subPaneManager = new SubPaneManager();
528
535
  // 注册副图活跃列表提供者,调度器据此只计算启用的副图
529
536
  this.indicatorScheduler.setActiveSubPaneProvider(() => this.subPaneManager.getPaneIds());
530
537
  this.initPanes();
538
+ // dev: 主副图状态变更日志
539
+ if (import.meta.env?.MODE !== 'production') {
540
+ this._indicatorsComputed.subscribe(() => {
541
+ const instances = this._indicatorsComputed.peek();
542
+ console.log('[Chart] indicators signal changed:', instances);
543
+ });
544
+ this._subPanesComputed.subscribe(() => {
545
+ const subPanes = this._subPanesComputed.peek();
546
+ console.log('[Chart] subPanes signal changed:', subPanes);
547
+ });
548
+ }
531
549
  // 注册绘图主插件(负责绘制 shape,layer: 'main')
532
550
  this.useRenderer(createDrawingRendererPlugin({ store: this.drawingStore }));
533
551
  // 注册绘图标签插件(负责推送选中绘图的轴标签,layer: 'overlay')
@@ -707,7 +725,7 @@ export class Chart {
707
725
  // 3. 更新交互控制器坐标映射
708
726
  this.interaction.setKLinePositions(kLinePositions, range, kWidthPx);
709
727
  // 4. 通知调度器当前活跃主图指标 + 获取价格范围
710
- this.indicatorScheduler.setActiveMainIndicators(Array.from(this.activeMainIndicators));
728
+ this.indicatorScheduler.setActiveMainIndicators([...this._mainIndicatorsSignal.peek().keys()]);
711
729
  const mainIndicatorRange = useCachedFrame ? null : this.indicatorScheduler.getMainIndicatorPriceRange();
712
730
  const hasCrosshair = this.interaction.getCrosshairIndex() !== null;
713
731
  // 5. 遍历所有 Pane 渲染主层 / overlay / Y 轴
@@ -1101,7 +1119,6 @@ export class Chart {
1101
1119
  ratios[id] = ratio;
1102
1120
  });
1103
1121
  this._paneRatiosSignal.set(ratios);
1104
- this.syncSubPanesSignal();
1105
1122
  this.onPaneLayoutChange?.(this.getPaneLayoutSpecs());
1106
1123
  }
1107
1124
  applyPaneLayoutSpecs(panes) {
@@ -1257,8 +1274,6 @@ export class Chart {
1257
1274
  }
1258
1275
  this.upsertPane({ id: paneId, ratio: this._internalPaneRatios.get(paneId) ?? 1, visible: true, role: 'indicator' });
1259
1276
  const success = this.subPaneManager.create(this, paneId, indicatorId, params ?? this.getDefaultSubPaneParams(indicatorId));
1260
- this.syncIndicatorsSignal();
1261
- this.syncSubPanesSignal();
1262
1277
  return success;
1263
1278
  }
1264
1279
  /**
@@ -1267,9 +1282,6 @@ export class Chart {
1267
1282
  */
1268
1283
  removeSubPane(paneId) {
1269
1284
  this.subPaneManager.remove(this, paneId);
1270
- this._internalPaneRatios.delete(paneId);
1271
- this.syncIndicatorsSignal();
1272
- this.syncSubPanesSignal();
1273
1285
  }
1274
1286
  /**
1275
1287
  * 替换副图的指标类型
@@ -1279,8 +1291,6 @@ export class Chart {
1279
1291
  */
1280
1292
  replaceSubPaneIndicator(paneId, newIndicatorId, params) {
1281
1293
  this.subPaneManager.replaceIndicator(this, paneId, newIndicatorId, params ?? this.getDefaultSubPaneParams(newIndicatorId));
1282
- this.syncIndicatorsSignal();
1283
- this.syncSubPanesSignal();
1284
1294
  }
1285
1295
  /**
1286
1296
  * 更新副图指标参数
@@ -1289,7 +1299,6 @@ export class Chart {
1289
1299
  */
1290
1300
  updateSubPaneParams(paneId, params) {
1291
1301
  this.subPaneManager.updateParams(this, paneId, params);
1292
- this.syncIndicatorsSignal();
1293
1302
  }
1294
1303
  /**
1295
1304
  * 清除所有副图面板
@@ -1307,8 +1316,6 @@ export class Chart {
1307
1316
  }
1308
1317
  // 更新布局,移除所有副图 pane
1309
1318
  this.applyPaneLayoutSpecs(this.opt.panes.filter((spec) => !subPaneIds.includes(spec.id)));
1310
- this.syncIndicatorsSignal();
1311
- this.syncSubPanesSignal();
1312
1319
  }
1313
1320
  /**
1314
1321
  * 获取当前所有副图指标类型
@@ -1848,8 +1855,6 @@ export class Chart {
1848
1855
  });
1849
1856
  _dataSignal = createSignal([]);
1850
1857
  _themeSignal = createSignal('light');
1851
- _indicatorsSignal = createSignal([]);
1852
- _subPanesSignal = createSignal([]);
1853
1858
  _drawingToolSignal = createSignal(null);
1854
1859
  _drawingsSignal = createSignal([]);
1855
1860
  _paneRatiosSignal = createSignal({});
@@ -1869,6 +1874,35 @@ export class Chart {
1869
1874
  hoveredPaneBoundaryId: null,
1870
1875
  isHoveringRightAxis: false,
1871
1876
  });
1877
+ _indicatorsComputed = computed(() => {
1878
+ const mainIndicators = [...this._mainIndicatorsSignal().entries()].map(([id, entry]) => ({
1879
+ id,
1880
+ definitionId: id,
1881
+ label: id,
1882
+ name: id,
1883
+ role: 'main',
1884
+ params: { ...entry.params },
1885
+ }));
1886
+ const subIndicators = this.subPaneManager.entriesSignal().map(entry => ({
1887
+ id: entry.paneId,
1888
+ definitionId: entry.indicatorId,
1889
+ label: entry.indicatorId,
1890
+ name: entry.indicatorId,
1891
+ role: 'sub',
1892
+ paneId: entry.paneId,
1893
+ params: { ...entry.params },
1894
+ }));
1895
+ return [...mainIndicators, ...subIndicators];
1896
+ });
1897
+ _subPanesComputed = computed(() => {
1898
+ const ratios = this._paneRatiosSignal();
1899
+ return this.subPaneManager.entriesSignal().map(entry => ({
1900
+ paneId: entry.paneId,
1901
+ indicatorId: entry.indicatorId,
1902
+ params: { ...entry.params },
1903
+ ratio: ratios[entry.paneId] ?? 1,
1904
+ }));
1905
+ });
1872
1906
  /** 视口状态信号 */
1873
1907
  get viewport() {
1874
1908
  return this._viewportSignal;
@@ -1881,13 +1915,13 @@ export class Chart {
1881
1915
  get theme() {
1882
1916
  return this._themeSignal;
1883
1917
  }
1884
- /** 指标实例列表信号 */
1918
+ /** 指标实例列表信号(派生信号,自动随主/副图状态更新) */
1885
1919
  get indicators() {
1886
- return this._indicatorsSignal;
1920
+ return this._indicatorsComputed;
1887
1921
  }
1888
- /** 子图信息信号 */
1922
+ /** 子图信息信号(派生信号,自动随副图条目/比例更新) */
1889
1923
  get subPanes() {
1890
- return this._subPanesSignal;
1924
+ return this._subPanesComputed;
1891
1925
  }
1892
1926
  /** 当前绘图工具信号 */
1893
1927
  get drawingTool() {
@@ -2120,8 +2154,6 @@ export class Chart {
2120
2154
  const success = this.enableMainIndicator(definitionId, params);
2121
2155
  if (!success)
2122
2156
  return null;
2123
- // 更新 indicators signal
2124
- this.syncIndicatorsSignal();
2125
2157
  return definitionId.toUpperCase();
2126
2158
  }
2127
2159
  else {
@@ -2130,9 +2162,6 @@ export class Chart {
2130
2162
  const success = this.createSubPane(paneId, definitionId, params);
2131
2163
  if (!success)
2132
2164
  return null;
2133
- // 更新 signals
2134
- this.syncIndicatorsSignal();
2135
- this.syncSubPanesSignal();
2136
2165
  return paneId;
2137
2166
  }
2138
2167
  }
@@ -2143,23 +2172,16 @@ export class Chart {
2143
2172
  */
2144
2173
  removeIndicator(instanceId) {
2145
2174
  const id = instanceId.toUpperCase();
2146
- // 先尝试作为主图指标移除(直接检查内部状态,不依赖 signal)
2147
- if (this.activeMainIndicators.has(id)) {
2148
- const success = this.disableMainIndicator(instanceId);
2149
- if (success) {
2150
- this.syncIndicatorsSignal();
2151
- }
2152
- return success;
2175
+ // 先尝试作为主图指标移除
2176
+ if (this._mainIndicatorsSignal.peek().has(id)) {
2177
+ return this.disableMainIndicator(instanceId);
2153
2178
  }
2154
- // 再尝试作为副图指标移除(检查 sub pane 是否存在)
2179
+ // 再尝试作为副图指标移除
2155
2180
  const subPaneEntry = this.getSubPaneEntry(instanceId);
2156
2181
  if (subPaneEntry) {
2157
2182
  this.removeSubPane(instanceId);
2158
- this.syncIndicatorsSignal();
2159
- this.syncSubPanesSignal();
2160
2183
  return true;
2161
2184
  }
2162
- // 都没找到,返回 false
2163
2185
  return false;
2164
2186
  }
2165
2187
  /**
@@ -2170,20 +2192,17 @@ export class Chart {
2170
2192
  */
2171
2193
  updateIndicatorParams(instanceId, params) {
2172
2194
  const id = instanceId.toUpperCase();
2173
- // 先尝试作为主图指标更新(直接检查内部状态)
2174
- if (this.activeMainIndicators.has(id)) {
2195
+ // 先尝试作为主图指标更新
2196
+ if (this._mainIndicatorsSignal.peek().has(id)) {
2175
2197
  this.updateMainIndicatorParams(instanceId, params);
2176
- this.syncIndicatorsSignal();
2177
2198
  return true;
2178
2199
  }
2179
2200
  // 再尝试作为副图指标更新
2180
2201
  const subPaneEntry = this.getSubPaneEntry(instanceId);
2181
2202
  if (subPaneEntry) {
2182
2203
  this.updateSubPaneParams(instanceId, params);
2183
- this.syncIndicatorsSignal();
2184
2204
  return true;
2185
2205
  }
2186
- // 都没找到
2187
2206
  return false;
2188
2207
  }
2189
2208
  /**
@@ -2197,42 +2216,6 @@ export class Chart {
2197
2216
  console.warn('[Chart] reorderIndicators not fully implemented yet');
2198
2217
  return false;
2199
2218
  }
2200
- /**
2201
- * 同步 indicators signal
2202
- */
2203
- syncIndicatorsSignal() {
2204
- const mainIndicators = this.getActiveMainIndicators().map(id => ({
2205
- id,
2206
- definitionId: id,
2207
- label: id,
2208
- name: id,
2209
- role: 'main',
2210
- params: this.getMainIndicatorParams(id) ?? {},
2211
- }));
2212
- const subIndicators = this.getSubPaneEntries().map(entry => ({
2213
- id: entry.paneId,
2214
- definitionId: entry.indicatorId,
2215
- label: entry.indicatorId,
2216
- name: entry.indicatorId,
2217
- role: 'sub',
2218
- paneId: entry.paneId,
2219
- params: entry.params,
2220
- }));
2221
- this._indicatorsSignal.set([...mainIndicators, ...subIndicators]);
2222
- }
2223
- /**
2224
- * 同步 sub panes signal
2225
- */
2226
- syncSubPanesSignal() {
2227
- const entries = this.getSubPaneEntries();
2228
- const subPanes = entries.map(entry => ({
2229
- paneId: entry.paneId,
2230
- indicatorId: entry.indicatorId,
2231
- params: entry.params,
2232
- ratio: this._internalPaneRatios.get(entry.paneId) ?? 1,
2233
- }));
2234
- this._subPanesSignal.set(subPanes);
2235
- }
2236
2219
  // ---------- Sub Panes ----------
2237
2220
  /**
2238
2221
  * 调整子图大小(高层 API)