@363045841yyt/klinechart-core 0.7.8 → 0.7.10

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 (251) hide show
  1. package/dist/controllers/index.d.ts +1 -1
  2. package/dist/controllers/index.d.ts.map +1 -1
  3. package/dist/controllers/index.js.map +1 -1
  4. package/dist/engine/chart.d.ts.map +1 -1
  5. package/dist/engine/chart.js +41 -229
  6. package/dist/engine/chart.js.map +1 -1
  7. package/dist/engine/indicators/indicatorDefinitionRegistry.d.ts +10 -3
  8. package/dist/engine/indicators/indicatorDefinitionRegistry.d.ts.map +1 -1
  9. package/dist/engine/indicators/indicatorDefinitionRegistry.js +29 -2
  10. package/dist/engine/indicators/indicatorDefinitionRegistry.js.map +1 -1
  11. package/dist/engine/indicators/indicatorMetadata.d.ts +79 -2
  12. package/dist/engine/indicators/indicatorMetadata.d.ts.map +1 -1
  13. package/dist/engine/indicators/indicatorMetadata.js.map +1 -1
  14. package/dist/engine/indicators/indicatorRegistry.d.ts +5 -0
  15. package/dist/engine/indicators/indicatorRegistry.d.ts.map +1 -1
  16. package/dist/engine/indicators/indicatorRegistry.js +49 -5
  17. package/dist/engine/indicators/indicatorRegistry.js.map +1 -1
  18. package/dist/engine/indicators/registerBuiltins.d.ts +42 -0
  19. package/dist/engine/indicators/registerBuiltins.d.ts.map +1 -0
  20. package/dist/engine/indicators/registerBuiltins.js +46 -0
  21. package/dist/engine/indicators/registerBuiltins.js.map +1 -0
  22. package/dist/engine/indicators/scheduler.d.ts +2 -2
  23. package/dist/engine/indicators/scheduler.d.ts.map +1 -1
  24. package/dist/engine/indicators/scheduler.js +41 -11
  25. package/dist/engine/indicators/scheduler.js.map +1 -1
  26. package/dist/engine/indicators/stateComposer.d.ts +6 -4
  27. package/dist/engine/indicators/stateComposer.d.ts.map +1 -1
  28. package/dist/engine/indicators/stateComposer.js +80 -984
  29. package/dist/engine/indicators/stateComposer.js.map +1 -1
  30. package/dist/engine/indicators/visibleStateComposers.d.ts +145 -0
  31. package/dist/engine/indicators/visibleStateComposers.d.ts.map +1 -0
  32. package/dist/engine/indicators/visibleStateComposers.js +469 -0
  33. package/dist/engine/indicators/visibleStateComposers.js.map +1 -0
  34. package/dist/engine/renderers/Indicator/atr.d.ts.map +1 -1
  35. package/dist/engine/renderers/Indicator/atr.js +8 -0
  36. package/dist/engine/renderers/Indicator/atr.js.map +1 -1
  37. package/dist/engine/renderers/Indicator/boll.d.ts.map +1 -1
  38. package/dist/engine/renderers/Indicator/boll.js +47 -0
  39. package/dist/engine/renderers/Indicator/boll.js.map +1 -1
  40. package/dist/engine/renderers/Indicator/cci.d.ts.map +1 -1
  41. package/dist/engine/renderers/Indicator/cci.js +8 -1
  42. package/dist/engine/renderers/Indicator/cci.js.map +1 -1
  43. package/dist/engine/renderers/Indicator/chaikinVol.d.ts.map +1 -1
  44. package/dist/engine/renderers/Indicator/chaikinVol.js +7 -1
  45. package/dist/engine/renderers/Indicator/chaikinVol.js.map +1 -1
  46. package/dist/engine/renderers/Indicator/cmf.d.ts.map +1 -1
  47. package/dist/engine/renderers/Indicator/cmf.js +7 -1
  48. package/dist/engine/renderers/Indicator/cmf.js.map +1 -1
  49. package/dist/engine/renderers/Indicator/dema.d.ts.map +1 -1
  50. package/dist/engine/renderers/Indicator/dema.js +8 -1
  51. package/dist/engine/renderers/Indicator/dema.js.map +1 -1
  52. package/dist/engine/renderers/Indicator/donchian.d.ts.map +1 -1
  53. package/dist/engine/renderers/Indicator/donchian.js +8 -1
  54. package/dist/engine/renderers/Indicator/donchian.js.map +1 -1
  55. package/dist/engine/renderers/Indicator/ene.d.ts.map +1 -1
  56. package/dist/engine/renderers/Indicator/ene.js +45 -0
  57. package/dist/engine/renderers/Indicator/ene.js.map +1 -1
  58. package/dist/engine/renderers/Indicator/expma.d.ts.map +1 -1
  59. package/dist/engine/renderers/Indicator/expma.js +45 -0
  60. package/dist/engine/renderers/Indicator/expma.js.map +1 -1
  61. package/dist/engine/renderers/Indicator/fastk.d.ts.map +1 -1
  62. package/dist/engine/renderers/Indicator/fastk.js +8 -1
  63. package/dist/engine/renderers/Indicator/fastk.js.map +1 -1
  64. package/dist/engine/renderers/Indicator/fib.d.ts.map +1 -1
  65. package/dist/engine/renderers/Indicator/fib.js +8 -1
  66. package/dist/engine/renderers/Indicator/fib.js.map +1 -1
  67. package/dist/engine/renderers/Indicator/hma.d.ts.map +1 -1
  68. package/dist/engine/renderers/Indicator/hma.js +8 -1
  69. package/dist/engine/renderers/Indicator/hma.js.map +1 -1
  70. package/dist/engine/renderers/Indicator/hv.d.ts.map +1 -1
  71. package/dist/engine/renderers/Indicator/hv.js +7 -0
  72. package/dist/engine/renderers/Indicator/hv.js.map +1 -1
  73. package/dist/engine/renderers/Indicator/ichimoku.d.ts.map +1 -1
  74. package/dist/engine/renderers/Indicator/ichimoku.js +8 -1
  75. package/dist/engine/renderers/Indicator/ichimoku.js.map +1 -1
  76. package/dist/engine/renderers/Indicator/index.d.ts +7 -2
  77. package/dist/engine/renderers/Indicator/index.d.ts.map +1 -1
  78. package/dist/engine/renderers/Indicator/index.js +2 -114
  79. package/dist/engine/renderers/Indicator/index.js.map +1 -1
  80. package/dist/engine/renderers/Indicator/kama.d.ts.map +1 -1
  81. package/dist/engine/renderers/Indicator/kama.js +8 -1
  82. package/dist/engine/renderers/Indicator/kama.js.map +1 -1
  83. package/dist/engine/renderers/Indicator/keltner.d.ts.map +1 -1
  84. package/dist/engine/renderers/Indicator/keltner.js +8 -1
  85. package/dist/engine/renderers/Indicator/keltner.js.map +1 -1
  86. package/dist/engine/renderers/Indicator/kst.d.ts.map +1 -1
  87. package/dist/engine/renderers/Indicator/kst.js +8 -0
  88. package/dist/engine/renderers/Indicator/kst.js.map +1 -1
  89. package/dist/engine/renderers/Indicator/ma.d.ts.map +1 -1
  90. package/dist/engine/renderers/Indicator/ma.js +63 -0
  91. package/dist/engine/renderers/Indicator/ma.js.map +1 -1
  92. package/dist/engine/renderers/Indicator/macd.d.ts.map +1 -1
  93. package/dist/engine/renderers/Indicator/macd.js +8 -1
  94. package/dist/engine/renderers/Indicator/macd.js.map +1 -1
  95. package/dist/engine/renderers/Indicator/mfi.d.ts.map +1 -1
  96. package/dist/engine/renderers/Indicator/mfi.js +7 -1
  97. package/dist/engine/renderers/Indicator/mfi.js.map +1 -1
  98. package/dist/engine/renderers/Indicator/mom.d.ts.map +1 -1
  99. package/dist/engine/renderers/Indicator/mom.js +8 -0
  100. package/dist/engine/renderers/Indicator/mom.js.map +1 -1
  101. package/dist/engine/renderers/Indicator/obv.d.ts.map +1 -1
  102. package/dist/engine/renderers/Indicator/obv.js +7 -1
  103. package/dist/engine/renderers/Indicator/obv.js.map +1 -1
  104. package/dist/engine/renderers/Indicator/parkinson.d.ts.map +1 -1
  105. package/dist/engine/renderers/Indicator/parkinson.js +7 -0
  106. package/dist/engine/renderers/Indicator/parkinson.js.map +1 -1
  107. package/dist/engine/renderers/Indicator/pivot.d.ts.map +1 -1
  108. package/dist/engine/renderers/Indicator/pivot.js +8 -1
  109. package/dist/engine/renderers/Indicator/pivot.js.map +1 -1
  110. package/dist/engine/renderers/Indicator/pvt.d.ts.map +1 -1
  111. package/dist/engine/renderers/Indicator/pvt.js +7 -1
  112. package/dist/engine/renderers/Indicator/pvt.js.map +1 -1
  113. package/dist/engine/renderers/Indicator/roc.d.ts.map +1 -1
  114. package/dist/engine/renderers/Indicator/roc.js +7 -1
  115. package/dist/engine/renderers/Indicator/roc.js.map +1 -1
  116. package/dist/engine/renderers/Indicator/rsi.d.ts.map +1 -1
  117. package/dist/engine/renderers/Indicator/rsi.js +8 -1
  118. package/dist/engine/renderers/Indicator/rsi.js.map +1 -1
  119. package/dist/engine/renderers/Indicator/sar.d.ts.map +1 -1
  120. package/dist/engine/renderers/Indicator/sar.js +8 -1
  121. package/dist/engine/renderers/Indicator/sar.js.map +1 -1
  122. package/dist/engine/renderers/Indicator/stoch.d.ts.map +1 -1
  123. package/dist/engine/renderers/Indicator/stoch.js +8 -1
  124. package/dist/engine/renderers/Indicator/stoch.js.map +1 -1
  125. package/dist/engine/renderers/Indicator/structure.d.ts.map +1 -1
  126. package/dist/engine/renderers/Indicator/structure.js +8 -1
  127. package/dist/engine/renderers/Indicator/structure.js.map +1 -1
  128. package/dist/engine/renderers/Indicator/subPaneConfig.d.ts +1 -1
  129. package/dist/engine/renderers/Indicator/subPaneConfig.d.ts.map +1 -1
  130. package/dist/engine/renderers/Indicator/subPaneConfig.js.map +1 -1
  131. package/dist/engine/renderers/Indicator/supertrend.d.ts.map +1 -1
  132. package/dist/engine/renderers/Indicator/supertrend.js +8 -1
  133. package/dist/engine/renderers/Indicator/supertrend.js.map +1 -1
  134. package/dist/engine/renderers/Indicator/tema.d.ts.map +1 -1
  135. package/dist/engine/renderers/Indicator/tema.js +8 -1
  136. package/dist/engine/renderers/Indicator/tema.js.map +1 -1
  137. package/dist/engine/renderers/Indicator/trix.d.ts.map +1 -1
  138. package/dist/engine/renderers/Indicator/trix.js +7 -0
  139. package/dist/engine/renderers/Indicator/trix.js.map +1 -1
  140. package/dist/engine/renderers/Indicator/vma.d.ts.map +1 -1
  141. package/dist/engine/renderers/Indicator/vma.js +7 -0
  142. package/dist/engine/renderers/Indicator/vma.js.map +1 -1
  143. package/dist/engine/renderers/Indicator/volumeProfile.d.ts.map +1 -1
  144. package/dist/engine/renderers/Indicator/volumeProfile.js +7 -1
  145. package/dist/engine/renderers/Indicator/volumeProfile.js.map +1 -1
  146. package/dist/engine/renderers/Indicator/vwap.d.ts.map +1 -1
  147. package/dist/engine/renderers/Indicator/vwap.js +7 -1
  148. package/dist/engine/renderers/Indicator/vwap.js.map +1 -1
  149. package/dist/engine/renderers/Indicator/wma.d.ts.map +1 -1
  150. package/dist/engine/renderers/Indicator/wma.js +8 -1
  151. package/dist/engine/renderers/Indicator/wma.js.map +1 -1
  152. package/dist/engine/renderers/Indicator/wmsr.d.ts.map +1 -1
  153. package/dist/engine/renderers/Indicator/wmsr.js +8 -1
  154. package/dist/engine/renderers/Indicator/wmsr.js.map +1 -1
  155. package/dist/engine/renderers/Indicator/zones.d.ts.map +1 -1
  156. package/dist/engine/renderers/Indicator/zones.js +8 -1
  157. package/dist/engine/renderers/Indicator/zones.js.map +1 -1
  158. package/dist/engine/renderers/extremaMarkers.d.ts.map +1 -1
  159. package/dist/engine/renderers/extremaMarkers.js +0 -22
  160. package/dist/engine/renderers/extremaMarkers.js.map +1 -1
  161. package/dist/engine/renderers/subVolume.d.ts.map +1 -1
  162. package/dist/engine/renderers/subVolume.js +3 -0
  163. package/dist/engine/renderers/subVolume.js.map +1 -1
  164. package/dist/engine/subPaneManager.d.ts +1 -0
  165. package/dist/engine/subPaneManager.d.ts.map +1 -1
  166. package/dist/engine/subPaneManager.js +30 -237
  167. package/dist/engine/subPaneManager.js.map +1 -1
  168. package/dist/semantic/controller.d.ts +9 -4
  169. package/dist/semantic/controller.d.ts.map +1 -1
  170. package/dist/semantic/controller.js +57 -53
  171. package/dist/semantic/controller.js.map +1 -1
  172. package/dist/tokens/theme-dark.js +1 -1
  173. package/dist/version.d.ts +1 -1
  174. package/dist/version.d.ts.map +1 -1
  175. package/dist/version.js +1 -1
  176. package/dist/version.js.map +1 -1
  177. package/package.json +1 -1
  178. package/src/controllers/index.ts +7 -0
  179. package/src/engine/__tests__/chart.dpr.test.ts +2 -1
  180. package/src/engine/__tests__/paneRenderer.resize.test.ts +1 -0
  181. package/src/engine/chart.ts +51 -229
  182. package/src/engine/controller/__tests__/interaction.dpr.test.ts +1 -0
  183. package/src/engine/indicators/__tests__/indicatorDefinitionRegistry.test.ts +59 -0
  184. package/src/engine/indicators/__tests__/indicatorRegistry.test.ts +62 -0
  185. package/src/engine/indicators/__tests__/registerBuiltins.test.ts +380 -0
  186. package/src/engine/indicators/__tests__/scheduler.test.ts +92 -8
  187. package/src/engine/indicators/__tests__/stateComposer.test.ts +444 -0
  188. package/src/engine/indicators/indicatorDefinitionRegistry.ts +49 -4
  189. package/src/engine/indicators/indicatorMetadata.ts +107 -2
  190. package/src/engine/indicators/indicatorRegistry.ts +54 -5
  191. package/src/engine/indicators/registerBuiltins.ts +47 -0
  192. package/src/engine/indicators/scheduler.ts +61 -13
  193. package/src/engine/indicators/stateComposer.ts +110 -1040
  194. package/src/engine/indicators/visibleStateComposers.ts +734 -0
  195. package/src/engine/renderers/Indicator/__tests__/createSubIndicatorRenderer.test.ts +61 -0
  196. package/src/engine/renderers/Indicator/atr.ts +9 -1
  197. package/src/engine/renderers/Indicator/boll.ts +53 -1
  198. package/src/engine/renderers/Indicator/cci.ts +9 -2
  199. package/src/engine/renderers/Indicator/chaikinVol.ts +8 -2
  200. package/src/engine/renderers/Indicator/cmf.ts +8 -2
  201. package/src/engine/renderers/Indicator/dema.ts +9 -2
  202. package/src/engine/renderers/Indicator/donchian.ts +9 -2
  203. package/src/engine/renderers/Indicator/ene.ts +51 -1
  204. package/src/engine/renderers/Indicator/expma.ts +51 -1
  205. package/src/engine/renderers/Indicator/fastk.ts +9 -2
  206. package/src/engine/renderers/Indicator/fib.ts +9 -2
  207. package/src/engine/renderers/Indicator/hma.ts +9 -2
  208. package/src/engine/renderers/Indicator/hv.ts +8 -1
  209. package/src/engine/renderers/Indicator/ichimoku.ts +9 -2
  210. package/src/engine/renderers/Indicator/index.ts +9 -121
  211. package/src/engine/renderers/Indicator/kama.ts +9 -2
  212. package/src/engine/renderers/Indicator/keltner.ts +9 -2
  213. package/src/engine/renderers/Indicator/kst.ts +9 -1
  214. package/src/engine/renderers/Indicator/ma.ts +69 -0
  215. package/src/engine/renderers/Indicator/macd.ts +9 -2
  216. package/src/engine/renderers/Indicator/mfi.ts +8 -2
  217. package/src/engine/renderers/Indicator/mom.ts +9 -1
  218. package/src/engine/renderers/Indicator/obv.ts +8 -2
  219. package/src/engine/renderers/Indicator/parkinson.ts +8 -1
  220. package/src/engine/renderers/Indicator/pivot.ts +9 -2
  221. package/src/engine/renderers/Indicator/pvt.ts +8 -2
  222. package/src/engine/renderers/Indicator/roc.ts +8 -2
  223. package/src/engine/renderers/Indicator/rsi.ts +9 -2
  224. package/src/engine/renderers/Indicator/sar.ts +9 -2
  225. package/src/engine/renderers/Indicator/stoch.ts +9 -2
  226. package/src/engine/renderers/Indicator/structure.ts +9 -2
  227. package/src/engine/renderers/Indicator/subPaneConfig.ts +1 -1
  228. package/src/engine/renderers/Indicator/supertrend.ts +9 -2
  229. package/src/engine/renderers/Indicator/tema.ts +9 -2
  230. package/src/engine/renderers/Indicator/trix.ts +8 -1
  231. package/src/engine/renderers/Indicator/vma.ts +8 -1
  232. package/src/engine/renderers/Indicator/volumeProfile.ts +8 -2
  233. package/src/engine/renderers/Indicator/vwap.ts +8 -2
  234. package/src/engine/renderers/Indicator/wma.ts +9 -2
  235. package/src/engine/renderers/Indicator/wmsr.ts +9 -2
  236. package/src/engine/renderers/Indicator/zones.ts +9 -2
  237. package/src/engine/renderers/__tests__/boll.renderer.test.ts +9 -1
  238. package/src/engine/renderers/__tests__/ene.renderer.test.ts +2 -1
  239. package/src/engine/renderers/__tests__/expma.renderer.test.ts +0 -1
  240. package/src/engine/renderers/__tests__/ma.renderer.test.ts +0 -1
  241. package/src/engine/renderers/__tests__/mainIndicatorLegend.renderer.test.ts +0 -1
  242. package/src/engine/renderers/__tests__/yAxis.renderer.test.ts +3 -0
  243. package/src/engine/renderers/extremaMarkers.ts +0 -24
  244. package/src/engine/renderers/subVolume.ts +3 -0
  245. package/src/engine/subPaneManager.ts +34 -274
  246. package/src/semantic/__tests__/controller.test.ts +84 -0
  247. package/src/semantic/controller.ts +69 -65
  248. package/src/tokens/__tests__/__snapshots__/baseline.test.ts.snap +4 -2
  249. package/src/tokens/__tests__/tokens.test.ts +1 -0
  250. package/src/tokens/theme-dark.ts +1 -1
  251. package/src/version.ts +1 -1
@@ -0,0 +1,61 @@
1
+ import { describe, expect, it, vi } from 'vitest'
2
+ import type { RendererPluginWithHost } from '../../../../plugin'
3
+ import { IndicatorRegistry } from '../../../indicators/indicatorRegistry'
4
+ import { getBuiltinIndicatorDefinitions } from '../../../indicators/registerBuiltins'
5
+ import type { IndicatorMetadata } from '../../../indicators/indicatorMetadata'
6
+ import { createSubIndicatorRenderer } from '../index'
7
+
8
+ function createRenderer(name: string): RendererPluginWithHost {
9
+ return {
10
+ name,
11
+ version: '1.0.0',
12
+ description: 'test renderer',
13
+ paneId: 'test',
14
+ draw: vi.fn(),
15
+ }
16
+ }
17
+
18
+ describe('createSubIndicatorRenderer', () => {
19
+ it('creates renderers through registered indicator metadata', () => {
20
+ const rendererFactory = vi.fn(() => createRenderer('custom_renderer'))
21
+ const definition: IndicatorMetadata = {
22
+ name: 'customIndicator',
23
+ displayName: 'CUSTOM',
24
+ category: 'sub',
25
+ stateKey: (paneId: string) => `indicator:custom:${paneId}`,
26
+ defaultPaneId: 'sub_CUSTOM',
27
+ rendererFactory,
28
+ }
29
+
30
+ const renderer = createSubIndicatorRenderer({
31
+ indicatorId: 'CUSTOM',
32
+ paneId: 'sub_CUSTOM',
33
+ definition,
34
+ params: { period: 12 },
35
+ })
36
+
37
+ expect(renderer.name).toBe('custom_renderer')
38
+ expect(rendererFactory).toHaveBeenCalledWith({
39
+ indicatorId: 'CUSTOM',
40
+ paneId: 'sub_CUSTOM',
41
+ params: { period: 12 },
42
+ })
43
+ })
44
+
45
+ it('supports legacy uppercase ids through registry normalization', () => {
46
+ const registry = new IndicatorRegistry()
47
+ for (const definition of getBuiltinIndicatorDefinitions()) {
48
+ registry.register(definition)
49
+ }
50
+
51
+ const definition = registry.getRequired('VOLUME_PROFILE')
52
+ const renderer = createSubIndicatorRenderer({
53
+ indicatorId: 'VOLUME_PROFILE',
54
+ paneId: 'VOLUME_PROFILE_0',
55
+ definition,
56
+ })
57
+
58
+ expect(definition.name).toBe('volumeProfile')
59
+ expect(renderer.name).toBe('volumeProfile_VOLUME_PROFILE_0')
60
+ })
61
+ })
@@ -3,9 +3,12 @@ import { RENDERER_PRIORITY } from '../../../plugin'
3
3
  import { resolveThemeColors } from '../../../tokens'
4
4
  import type { ATRRenderState } from '../../indicators/atrState'
5
5
  import { createATRStateKey } from '../../indicators/atrState'
6
+ import { EMPTY_ATR_STATE } from '../../indicators/atrState'
7
+ import { createNonNegativeSparseVisibleStateComposer } from '../../indicators/visibleStateComposers'
6
8
  import { Indicator } from '../../indicators/indicatorDefinitionRegistry'
7
9
  import { resolveStateKey } from '../../indicators/indicatorMetadata'
8
- import type { IndicatorScheduler } from '../../indicators/scheduler'
10
+ import type { IndicatorScheduler, ATRSchedulerConfig } from '../../indicators/scheduler'
11
+ import { createAtrScaleRendererPlugin } from './scale/atr_scale'
9
12
 
10
13
  type LinePoint = { x: number; y: number }
11
14
 
@@ -232,6 +235,11 @@ export function getATRTitleInfo(
232
235
  stateKey: createATRStateKey,
233
236
  defaultPaneId: 'sub_ATR',
234
237
  paneIdField: 'atrPaneId',
238
+ scaleRendererFactory: createAtrScaleRendererPlugin,
239
+ updateConfig: (scheduler, params, paneId) => {
240
+ (scheduler as IndicatorScheduler).updateATRConfig(params as Partial<ATRSchedulerConfig>, paneId)
241
+ },
242
+ visibleState: { compose: createNonNegativeSparseVisibleStateComposer('atr', EMPTY_ATR_STATE) },
235
243
  applyResult: (host, state, paneId) => {
236
244
  host.setSharedState(createATRStateKey(paneId), state as any, 'indicator_scheduler')
237
245
  },
@@ -6,7 +6,8 @@ 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 { IndicatorScheduler } from '../../indicators/scheduler'
9
+ import type { IndicatorPriceRangeComputer, IndicatorRenderStateComposer } from '../../indicators/indicatorMetadata'
10
+ import type { BOLLSchedulerConfig, IndicatorScheduler } from '../../indicators/scheduler'
10
11
 
11
12
  type LinePoint = { x: number; y: number }
12
13
 
@@ -122,12 +123,63 @@ function getBOLLStateKey(host: PluginHost | null): string | null {
122
123
  return resolveStateKey(meta.stateKey)
123
124
  }
124
125
 
126
+ const computeBOLLPriceRange: IndicatorPriceRangeComputer = (bundle, range) => {
127
+ const series = bundle.boll.series
128
+ if (series.length === 0 || range.start >= series.length) {
129
+ return null
130
+ }
131
+
132
+ let min = Infinity
133
+ let max = -Infinity
134
+ const end = Math.min(range.end, series.length)
135
+ for (let i = range.start; i < end; i++) {
136
+ const p = series[i]
137
+ if (p) {
138
+ min = Math.min(min, p.upper, p.middle, p.lower)
139
+ max = Math.max(max, p.upper, p.middle, p.lower)
140
+ }
141
+ }
142
+
143
+ return Number.isFinite(min) && Number.isFinite(max) ? { min, max } : null
144
+ }
145
+
146
+ const composeBOLLRenderState: IndicatorRenderStateComposer = (bundle, range, timestamp): BOLLRenderState => {
147
+ const priceRange = computeBOLLPriceRange(bundle, range) ?? { min: Infinity, max: -Infinity }
148
+ return {
149
+ timestamp,
150
+ series: bundle.boll.series,
151
+ params: bundle.boll.params,
152
+ visibleMin: priceRange.min,
153
+ visibleMax: priceRange.max,
154
+ }
155
+ }
156
+
125
157
  @Indicator({
126
158
  name: 'boll',
127
159
  displayName: 'BOLL',
128
160
  category: 'main',
129
161
  stateKey: BOLL_STATE_KEY,
130
162
  defaultPaneId: 'main',
163
+ mainPane: {
164
+ rendererName: 'boll',
165
+ toActiveConfig: (params, active) => active
166
+ ? params
167
+ : { ...params, showUpper: false, showMiddle: false, showLower: false, showBand: false },
168
+ computePriceRange: computeBOLLPriceRange,
169
+ composeRenderState: composeBOLLRenderState,
170
+ },
171
+ updateConfig: (scheduler, params) => {
172
+ (scheduler as IndicatorScheduler).updateBOLLConfig(params as Partial<BOLLSchedulerConfig>)
173
+ },
174
+ semantic: {
175
+ apply: (chart, indicator) => {
176
+ const params = (indicator as { params?: { period?: number; multiplier?: number } }).params
177
+ chart.updateRendererConfig('boll', {
178
+ period: params?.period || 20,
179
+ multiplier: params?.multiplier || 2,
180
+ })
181
+ },
182
+ },
131
183
  applyResult: (host, state, _paneId) => {
132
184
  host.setSharedState(BOLL_STATE_KEY, state as any, 'indicator_scheduler')
133
185
  },
@@ -2,10 +2,12 @@ import type { RendererPluginWithHost, RenderContext, PluginHost } from '../../..
2
2
  import { RENDERER_PRIORITY } from '../../../plugin'
3
3
  import { resolveThemeColors } from '../../../tokens'
4
4
  import type { CCIRenderState } from '../../indicators/cciState'
5
- import { createCCIStateKey } from '../../indicators/cciState'
5
+ import { createCCIStateKey, EMPTY_CCI_STATE } from '../../indicators/cciState'
6
+ import { createCCIVisibleStateComposer } from '../../indicators/visibleStateComposers'
6
7
  import { Indicator } from '../../indicators/indicatorDefinitionRegistry'
7
8
  import { resolveStateKey } from '../../indicators/indicatorMetadata'
8
- import type { IndicatorScheduler } from '../../indicators/scheduler'
9
+ import type { IndicatorScheduler, CCISchedulerConfig } from '../../indicators/scheduler'
10
+ import { createCciScaleRendererPlugin } from './scale/cci_scale'
9
11
 
10
12
  type LinePoint = { x: number; y: number }
11
13
 
@@ -267,6 +269,11 @@ export function getCCITitleInfo(
267
269
  stateKey: createCCIStateKey,
268
270
  defaultPaneId: 'sub_CCI',
269
271
  paneIdField: 'cciPaneId',
272
+ scaleRendererFactory: createCciScaleRendererPlugin,
273
+ visibleState: { compose: createCCIVisibleStateComposer('cci', EMPTY_CCI_STATE) },
274
+ updateConfig: (scheduler, params, paneId) => {
275
+ (scheduler as IndicatorScheduler).updateCCIConfig(params as Partial<CCISchedulerConfig>, paneId)
276
+ },
270
277
  applyResult: (host, state, paneId) => {
271
278
  host.setSharedState(createCCIStateKey(paneId), state as any, 'indicator_scheduler')
272
279
  },
@@ -1,10 +1,11 @@
1
1
  import type { RendererPluginWithHost, RenderContext, PluginHost } from '../../../plugin'
2
2
  import { RENDERER_PRIORITY } from '../../../plugin'
3
3
  import type { ChaikinVolRenderState } from '../../indicators/chaikinVolState'
4
- import { createChaikinVolStateKey } from '../../indicators/chaikinVolState'
4
+ import { createChaikinVolStateKey, EMPTY_CHAIKIN_VOL_STATE } from '../../indicators/chaikinVolState'
5
5
  import { Indicator } from '../../indicators/indicatorDefinitionRegistry'
6
6
  import { resolveStateKey } from '../../indicators/indicatorMetadata'
7
- import type { IndicatorScheduler } from '../../indicators/scheduler'
7
+ import { createSparseVisibleStateComposer } from '../../indicators/visibleStateComposers'
8
+ import type { IndicatorScheduler, ChaikinVolSchedulerConfig } from '../../indicators/scheduler'
8
9
 
9
10
  const CHAIKIN_VOL_COLOR = '#f59e0b'
10
11
 
@@ -129,6 +130,11 @@ export function createChaikinVolRendererPlugin(options: { paneId?: string } = {}
129
130
  stateKey: createChaikinVolStateKey,
130
131
  defaultPaneId: 'sub_ChaikinVol',
131
132
  paneIdField: 'chaikinVolPaneId',
133
+ visibleState: { compose: createSparseVisibleStateComposer('chaikinVol', EMPTY_CHAIKIN_VOL_STATE) },
134
+ scale: { indicatorKey: 'chaikinVol', label: 'ChaikinVol', decimals: 2 },
135
+ updateConfig: (scheduler, params, paneId) => {
136
+ (scheduler as IndicatorScheduler).updateChaikinVolConfig(params as Partial<ChaikinVolSchedulerConfig>, paneId)
137
+ },
132
138
  applyResult: (host, state, paneId) => {
133
139
  host.setSharedState(createChaikinVolStateKey(paneId), state as any, 'indicator_scheduler')
134
140
  },
@@ -1,10 +1,11 @@
1
1
  import type { RendererPluginWithHost, RenderContext, PluginHost } from '../../../plugin'
2
2
  import { RENDERER_PRIORITY } from '../../../plugin'
3
3
  import type { CMFRenderState } from '../../indicators/cmfState'
4
- import { createCMFStateKey } from '../../indicators/cmfState'
4
+ import { createCMFStateKey, EMPTY_CMF_STATE } from '../../indicators/cmfState'
5
5
  import { Indicator } from '../../indicators/indicatorDefinitionRegistry'
6
+ import { createFixedRangeSparseVisibleStateComposer } from '../../indicators/visibleStateComposers'
6
7
  import { resolveStateKey } from '../../indicators/indicatorMetadata'
7
- import type { IndicatorScheduler } from '../../indicators/scheduler'
8
+ import type { IndicatorScheduler, CMFSchedulerConfig } from '../../indicators/scheduler'
8
9
 
9
10
  const CMF_COLOR = '#06b6d4'
10
11
 
@@ -128,6 +129,11 @@ export function createCMFRendererPlugin(options: { paneId?: string } = {}): Rend
128
129
  stateKey: createCMFStateKey,
129
130
  defaultPaneId: 'sub_CMF',
130
131
  paneIdField: 'cmfPaneId',
132
+ visibleState: { compose: createFixedRangeSparseVisibleStateComposer('cmf', EMPTY_CMF_STATE) },
133
+ scale: { indicatorKey: 'cmf', label: 'CMF', decimals: 4 },
134
+ updateConfig: (scheduler, params, paneId) => {
135
+ (scheduler as IndicatorScheduler).updateCMFConfig(params as Partial<CMFSchedulerConfig>, paneId)
136
+ },
131
137
  applyResult: (host, state, paneId) => {
132
138
  host.setSharedState(createCMFStateKey(paneId), state as any, 'indicator_scheduler')
133
139
  },
@@ -1,10 +1,11 @@
1
1
  import type { RendererPluginWithHost, RenderContext, PluginHost } from '../../../plugin'
2
2
  import { RENDERER_PRIORITY } from '../../../plugin'
3
3
  import type { DEMARenderState } from '../../indicators/demaState'
4
- import { createDEMAStateKey } from '../../indicators/demaState'
4
+ import { createDEMAStateKey, EMPTY_DEMA_STATE } from '../../indicators/demaState'
5
5
  import { Indicator } from '../../indicators/indicatorDefinitionRegistry'
6
6
  import { resolveStateKey } from '../../indicators/indicatorMetadata'
7
- import type { IndicatorScheduler } from '../../indicators/scheduler'
7
+ import { createSparseVisibleStateComposer } from '../../indicators/visibleStateComposers'
8
+ import type { IndicatorScheduler, DEMASchedulerConfig } from '../../indicators/scheduler'
8
9
 
9
10
  const DEMA_COLOR = '#6366f1'
10
11
 
@@ -127,6 +128,12 @@ export function createDEMARendererPlugin(options: DEMARendererOptions = {}): Ren
127
128
  defaultPaneId: 'main',
128
129
  paneIdField: 'demaPaneId',
129
130
  allowMainPane: true,
131
+ mainPane: { rendererName: 'dema_main', toActiveConfig: (params, active) => ({ ...params, showDEMA: active }) },
132
+ visibleState: { compose: createSparseVisibleStateComposer('dema', EMPTY_DEMA_STATE) },
133
+ scale: { indicatorKey: 'dema', label: 'DEMA', decimals: 2 },
134
+ updateConfig: (scheduler, params, paneId) => {
135
+ (scheduler as IndicatorScheduler).updateDEMAConfig(params as Partial<DEMASchedulerConfig>, paneId)
136
+ },
130
137
  applyResult: (host, state, paneId) => {
131
138
  host.setSharedState(createDEMAStateKey(paneId), state as any, 'indicator_scheduler')
132
139
  },
@@ -1,10 +1,11 @@
1
1
  import type { RendererPluginWithHost, RenderContext, PluginHost } from '../../../plugin'
2
2
  import { RENDERER_PRIORITY } from '../../../plugin'
3
3
  import type { DonchianRenderState } from '../../indicators/donchianState'
4
- import { createDonchianStateKey } from '../../indicators/donchianState'
4
+ import { createDonchianStateKey, EMPTY_DONCHIAN_STATE } from '../../indicators/donchianState'
5
5
  import { Indicator } from '../../indicators/indicatorDefinitionRegistry'
6
6
  import { resolveStateKey } from '../../indicators/indicatorMetadata'
7
- import type { IndicatorScheduler } from '../../indicators/scheduler'
7
+ import type { IndicatorScheduler, DonchianSchedulerConfig } from '../../indicators/scheduler'
8
+ import { createBandVisibleStateComposer } from '../../indicators/visibleStateComposers'
8
9
 
9
10
  const DONCHIAN_UPPER_COLOR = '#0891b2'
10
11
  const DONCHIAN_MIDDLE_COLOR = '#94a3b8'
@@ -129,6 +130,12 @@ function drawLine(ctx: CanvasRenderingContext2D, pts: Point[], color: string): v
129
130
  defaultPaneId: 'main',
130
131
  paneIdField: 'donchianPaneId',
131
132
  allowMainPane: true,
133
+ mainPane: { rendererName: 'donchian_main', toActiveConfig: (params, active) => ({ ...params, showUpper: active, showMiddle: active, showLower: active }) },
134
+ scale: { indicatorKey: 'donchian', label: 'Donchian', decimals: 2 },
135
+ 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
+ },
132
139
  applyResult: (host, state, paneId) => {
133
140
  host.setSharedState(createDonchianStateKey(paneId), state as any, 'indicator_scheduler')
134
141
  },
@@ -6,7 +6,8 @@ import { resolveThemeColors } from '../../../tokens'
6
6
  import { ENE_STATE_KEY, type ENERenderState } from '../../indicators/eneState'
7
7
  import { Indicator } from '../../indicators/indicatorDefinitionRegistry'
8
8
  import { resolveStateKey } from '../../indicators/indicatorMetadata'
9
- import type { IndicatorScheduler } from '../../indicators/scheduler'
9
+ import type { IndicatorPriceRangeComputer, IndicatorRenderStateComposer } from '../../indicators/indicatorMetadata'
10
+ import type { ENESchedulerConfig, IndicatorScheduler } from '../../indicators/scheduler'
10
11
 
11
12
  type LinePoint = { x: number; y: number }
12
13
 
@@ -106,6 +107,37 @@ function getENEStateKey(host: PluginHost | null): string | null {
106
107
  return resolveStateKey(meta.stateKey)
107
108
  }
108
109
 
110
+ const computeENEPriceRange: IndicatorPriceRangeComputer = (bundle, range) => {
111
+ const series = bundle.ene.series
112
+ if (series.length === 0 || range.start >= series.length) {
113
+ return null
114
+ }
115
+
116
+ let min = Infinity
117
+ let max = -Infinity
118
+ const end = Math.min(range.end, series.length)
119
+ for (let i = range.start; i < end; i++) {
120
+ const p = series[i]
121
+ if (p) {
122
+ min = Math.min(min, p.upper, p.middle, p.lower)
123
+ max = Math.max(max, p.upper, p.middle, p.lower)
124
+ }
125
+ }
126
+
127
+ return Number.isFinite(min) && Number.isFinite(max) ? { min, max } : null
128
+ }
129
+
130
+ const composeENERenderState: IndicatorRenderStateComposer = (bundle, range, timestamp): ENERenderState => {
131
+ const priceRange = computeENEPriceRange(bundle, range) ?? { min: Infinity, max: -Infinity }
132
+ return {
133
+ timestamp,
134
+ series: bundle.ene.series,
135
+ params: bundle.ene.params,
136
+ visibleMin: priceRange.min,
137
+ visibleMax: priceRange.max,
138
+ }
139
+ }
140
+
109
141
  export function createENERendererPlugin(): RendererPluginWithHost {
110
142
  let pluginHost: PluginHost | null = null
111
143
 
@@ -262,6 +294,24 @@ export function createENERendererPlugin(): RendererPluginWithHost {
262
294
  category: 'main',
263
295
  stateKey: ENE_STATE_KEY,
264
296
  defaultPaneId: 'main',
297
+ mainPane: {
298
+ rendererName: 'ene',
299
+ toActiveConfig: (params, active) => active ? params : null,
300
+ computePriceRange: computeENEPriceRange,
301
+ composeRenderState: composeENERenderState,
302
+ },
303
+ updateConfig: (scheduler, params) => {
304
+ (scheduler as IndicatorScheduler).updateENEConfig(params as Partial<ENESchedulerConfig>)
305
+ },
306
+ semantic: {
307
+ apply: (chart, indicator) => {
308
+ const params = (indicator as { params?: { period?: number; deviation?: number } }).params
309
+ chart.updateRendererConfig('ene', {
310
+ period: params?.period || 10,
311
+ deviation: params?.deviation || 11,
312
+ })
313
+ },
314
+ },
265
315
  applyResult: (host, state, _paneId) => {
266
316
  host.setSharedState(ENE_STATE_KEY, state as any, 'indicator_scheduler')
267
317
  },
@@ -6,7 +6,8 @@ import { resolveThemeColors } from '../../../tokens'
6
6
  import { EXPMA_STATE_KEY, type EXPMARenderState } from '../../indicators/expmaState'
7
7
  import { Indicator } from '../../indicators/indicatorDefinitionRegistry'
8
8
  import { resolveStateKey } from '../../indicators/indicatorMetadata'
9
- import type { IndicatorScheduler } from '../../indicators/scheduler'
9
+ import type { IndicatorPriceRangeComputer, IndicatorRenderStateComposer } from '../../indicators/indicatorMetadata'
10
+ import type { EXPMASchedulerConfig, IndicatorScheduler } from '../../indicators/scheduler'
10
11
 
11
12
  type LinePoint = { x: number; y: number }
12
13
 
@@ -46,6 +47,37 @@ function getEXPMAStateKey(host: PluginHost | null): string | null {
46
47
  return resolveStateKey(meta.stateKey)
47
48
  }
48
49
 
50
+ const computeEXPMAPriceRange: IndicatorPriceRangeComputer = (bundle, range) => {
51
+ const series = bundle.expma.series
52
+ if (series.length === 0 || range.start >= series.length) {
53
+ return null
54
+ }
55
+
56
+ let min = Infinity
57
+ let max = -Infinity
58
+ const end = Math.min(range.end, series.length)
59
+ for (let i = range.start; i < end; i++) {
60
+ const p = series[i]
61
+ if (p) {
62
+ min = Math.min(min, p.fast, p.slow)
63
+ max = Math.max(max, p.fast, p.slow)
64
+ }
65
+ }
66
+
67
+ return Number.isFinite(min) && Number.isFinite(max) ? { min, max } : null
68
+ }
69
+
70
+ const composeEXPMARenderState: IndicatorRenderStateComposer = (bundle, range, timestamp): EXPMARenderState => {
71
+ const priceRange = computeEXPMAPriceRange(bundle, range) ?? { min: Infinity, max: -Infinity }
72
+ return {
73
+ timestamp,
74
+ series: bundle.expma.series,
75
+ params: bundle.expma.params,
76
+ visibleMin: priceRange.min,
77
+ visibleMax: priceRange.max,
78
+ }
79
+ }
80
+
49
81
  export function createEXPMARendererPlugin(): RendererPluginWithHost {
50
82
  let pluginHost: PluginHost | null = null
51
83
  let cachedKey = ''
@@ -188,6 +220,24 @@ export function createEXPMARendererPlugin(): RendererPluginWithHost {
188
220
  category: 'main',
189
221
  stateKey: EXPMA_STATE_KEY,
190
222
  defaultPaneId: 'main',
223
+ mainPane: {
224
+ rendererName: 'expma',
225
+ toActiveConfig: (params, active) => active ? params : null,
226
+ computePriceRange: computeEXPMAPriceRange,
227
+ composeRenderState: composeEXPMARenderState,
228
+ },
229
+ updateConfig: (scheduler, params) => {
230
+ (scheduler as IndicatorScheduler).updateEXPMAConfig(params as Partial<EXPMASchedulerConfig>)
231
+ },
232
+ semantic: {
233
+ apply: (chart, indicator) => {
234
+ const params = (indicator as { params?: { fastPeriod?: number; slowPeriod?: number } }).params
235
+ chart.updateRendererConfig('expma', {
236
+ fastPeriod: params?.fastPeriod || 12,
237
+ slowPeriod: params?.slowPeriod || 50,
238
+ })
239
+ },
240
+ },
191
241
  applyResult: (host, state, _paneId) => {
192
242
  host.setSharedState(EXPMA_STATE_KEY, state as any, 'indicator_scheduler')
193
243
  },
@@ -3,10 +3,12 @@ import { RENDERER_PRIORITY } from '../../../plugin'
3
3
  import { resolveThemeColors } from '../../../tokens'
4
4
  import { alignToPhysicalPixelCenter } from '../../draw/pixelAlign'
5
5
  import type { FASTKRenderState } from '../../indicators/fastkState'
6
- import { createFASTKStateKey } from '../../indicators/fastkState'
6
+ import { createFASTKStateKey, EMPTY_FASTK_STATE } from '../../indicators/fastkState'
7
7
  import { Indicator } from '../../indicators/indicatorDefinitionRegistry'
8
+ import { createFixedRangeSparseVisibleStateComposer } from '../../indicators/visibleStateComposers'
8
9
  import { resolveStateKey } from '../../indicators/indicatorMetadata'
9
- import type { IndicatorScheduler } from '../../indicators/scheduler'
10
+ import type { IndicatorScheduler, FASTKSchedulerConfig } from '../../indicators/scheduler'
11
+ import { createFastkScaleRendererPlugin } from './scale/fastk_scale'
10
12
 
11
13
  type LinePoint = { x: number; y: number }
12
14
 
@@ -308,6 +310,11 @@ export function getFASTKTitleInfo(
308
310
  stateKey: createFASTKStateKey,
309
311
  defaultPaneId: 'sub_FASTK',
310
312
  paneIdField: 'fastkPaneId',
313
+ visibleState: { compose: createFixedRangeSparseVisibleStateComposer('fastk', EMPTY_FASTK_STATE) },
314
+ scaleRendererFactory: createFastkScaleRendererPlugin,
315
+ updateConfig: (scheduler, params, paneId) => {
316
+ (scheduler as IndicatorScheduler).updateFASTKConfig(params as Partial<FASTKSchedulerConfig>, paneId)
317
+ },
311
318
  applyResult: (host, state, paneId) => {
312
319
  host.setSharedState(createFASTKStateKey(paneId), state as any, 'indicator_scheduler')
313
320
  },
@@ -1,10 +1,11 @@
1
1
  import type { RendererPluginWithHost, RenderContext, PluginHost } from '../../../plugin'
2
2
  import { RENDERER_PRIORITY } from '../../../plugin'
3
3
  import type { FibRenderState } from '../../indicators/fibState'
4
- import { createFibStateKey } from '../../indicators/fibState'
4
+ import { createFibStateKey, EMPTY_FIB_STATE } from '../../indicators/fibState'
5
5
  import { Indicator } from '../../indicators/indicatorDefinitionRegistry'
6
6
  import { resolveStateKey } from '../../indicators/indicatorMetadata'
7
- import type { IndicatorScheduler } from '../../indicators/scheduler'
7
+ import type { IndicatorScheduler, FibSchedulerConfig } from '../../indicators/scheduler'
8
+ import { createExactRangePointVisibleStateComposer } from '../../indicators/visibleStateComposers'
8
9
 
9
10
  const FIB_COLORS = {
10
11
  high: '#94a3b8',
@@ -132,6 +133,12 @@ function drawLine(ctx: CanvasRenderingContext2D, pts: Point[], color: string): v
132
133
  defaultPaneId: 'main',
133
134
  paneIdField: 'fibPaneId',
134
135
  allowMainPane: true,
136
+ mainPane: { rendererName: 'fib_main', toActiveConfig: (params, active) => ({ ...params, showLevels: active }) },
137
+ scale: { indicatorKey: 'fib', label: 'Fib', decimals: 4 },
138
+ visibleState: { compose: createExactRangePointVisibleStateComposer('fib', EMPTY_FIB_STATE, ['low', 'high']) },
139
+ updateConfig: (scheduler, params, paneId) => {
140
+ (scheduler as IndicatorScheduler).updateFibConfig(params as Partial<FibSchedulerConfig>, paneId)
141
+ },
135
142
  applyResult: (host, state, paneId) => {
136
143
  host.setSharedState(createFibStateKey(paneId), state as any, 'indicator_scheduler')
137
144
  },
@@ -1,10 +1,11 @@
1
1
  import type { RendererPluginWithHost, RenderContext, PluginHost } from '../../../plugin'
2
2
  import { RENDERER_PRIORITY } from '../../../plugin'
3
3
  import type { HMARenderState } from '../../indicators/hmaState'
4
- import { createHMAStateKey } from '../../indicators/hmaState'
4
+ import { createHMAStateKey, EMPTY_HMA_STATE } from '../../indicators/hmaState'
5
5
  import { Indicator } from '../../indicators/indicatorDefinitionRegistry'
6
6
  import { resolveStateKey } from '../../indicators/indicatorMetadata'
7
- import type { IndicatorScheduler } from '../../indicators/scheduler'
7
+ import { createSparseVisibleStateComposer } from '../../indicators/visibleStateComposers'
8
+ import type { IndicatorScheduler, HMASchedulerConfig } from '../../indicators/scheduler'
8
9
 
9
10
  const HMA_COLOR = '#f43f5e'
10
11
 
@@ -127,6 +128,12 @@ export function createHMARendererPlugin(options: HMARendererOptions = {}): Rende
127
128
  defaultPaneId: 'main',
128
129
  paneIdField: 'hmaPaneId',
129
130
  allowMainPane: true,
131
+ mainPane: { rendererName: 'hma_main', toActiveConfig: (params, active) => ({ ...params, showHMA: active }) },
132
+ visibleState: { compose: createSparseVisibleStateComposer('hma', EMPTY_HMA_STATE) },
133
+ scale: { indicatorKey: 'hma', label: 'HMA', decimals: 2 },
134
+ updateConfig: (scheduler, params, paneId) => {
135
+ (scheduler as IndicatorScheduler).updateHMAConfig(params as Partial<HMASchedulerConfig>, paneId)
136
+ },
130
137
  applyResult: (host, state, paneId) => {
131
138
  host.setSharedState(createHMAStateKey(paneId), state as any, 'indicator_scheduler')
132
139
  },
@@ -2,9 +2,11 @@ import type { RendererPluginWithHost, RenderContext, PluginHost } from '../../..
2
2
  import { RENDERER_PRIORITY } from '../../../plugin'
3
3
  import type { HVRenderState } from '../../indicators/hvState'
4
4
  import { createHVStateKey } from '../../indicators/hvState'
5
+ import { EMPTY_HV_STATE } from '../../indicators/hvState'
6
+ import { createNonNegativeSparseVisibleStateComposer } from '../../indicators/visibleStateComposers'
5
7
  import { Indicator } from '../../indicators/indicatorDefinitionRegistry'
6
8
  import { resolveStateKey } from '../../indicators/indicatorMetadata'
7
- import type { IndicatorScheduler } from '../../indicators/scheduler'
9
+ import type { IndicatorScheduler, HVSchedulerConfig } from '../../indicators/scheduler'
8
10
 
9
11
  const HV_COLOR = '#7c3aed'
10
12
 
@@ -115,6 +117,11 @@ export function createHVRendererPlugin(options: { paneId?: string } = {}): Rende
115
117
  stateKey: createHVStateKey,
116
118
  defaultPaneId: 'sub_HV',
117
119
  paneIdField: 'hvPaneId',
120
+ scale: { indicatorKey: 'hv', label: 'HV', decimals: 2 },
121
+ updateConfig: (scheduler, params, paneId) => {
122
+ (scheduler as IndicatorScheduler).updateHVConfig(params as Partial<HVSchedulerConfig>, paneId)
123
+ },
124
+ visibleState: { compose: createNonNegativeSparseVisibleStateComposer('hv', EMPTY_HV_STATE) },
118
125
  applyResult: (host, state, paneId) => {
119
126
  host.setSharedState(createHVStateKey(paneId), state as any, 'indicator_scheduler')
120
127
  },
@@ -1,10 +1,11 @@
1
1
  import type { RendererPluginWithHost, RenderContext, PluginHost } from '../../../plugin'
2
2
  import { RENDERER_PRIORITY } from '../../../plugin'
3
3
  import type { IchimokuRenderState } from '../../indicators/ichimokuState'
4
- import { createIchimokuStateKey } from '../../indicators/ichimokuState'
4
+ import { createIchimokuStateKey, EMPTY_ICHIMOKU_STATE } from '../../indicators/ichimokuState'
5
5
  import { Indicator } from '../../indicators/indicatorDefinitionRegistry'
6
6
  import { resolveStateKey } from '../../indicators/indicatorMetadata'
7
- import type { IndicatorScheduler } from '../../indicators/scheduler'
7
+ import type { IndicatorScheduler, IchimokuSchedulerConfig } from '../../indicators/scheduler'
8
+ import { createValuePointVisibleStateComposer } from '../../indicators/visibleStateComposers'
8
9
 
9
10
  const TENKAN_COLOR = '#dc2626'
10
11
  const KIJUN_COLOR = '#2563eb'
@@ -173,6 +174,12 @@ function fillCloud(
173
174
  defaultPaneId: 'main',
174
175
  paneIdField: 'ichimokuPaneId',
175
176
  allowMainPane: true,
177
+ mainPane: { rendererName: 'ichimoku_main', toActiveConfig: (params, active) => ({ ...params, showTenkan: active, showKijun: active, showSpanA: active, showSpanB: active, showChikou: active, showCloud: active }) },
178
+ scale: { indicatorKey: 'ichimoku', label: 'Ichimoku', decimals: 2 },
179
+ visibleState: { compose: createValuePointVisibleStateComposer('ichimoku', EMPTY_ICHIMOKU_STATE, ['tenkan', 'kijun', 'spanA', 'spanB', 'chikou']) },
180
+ updateConfig: (scheduler, params, paneId) => {
181
+ (scheduler as IndicatorScheduler).updateIchimokuConfig(params as Partial<IchimokuSchedulerConfig>, paneId)
182
+ },
176
183
  applyResult: (host, state, paneId) => {
177
184
  host.setSharedState(createIchimokuStateKey(paneId), state as any, 'indicator_scheduler')
178
185
  },