@backtest-kit/ui 6.16.0 → 7.0.0
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.
- package/README.md +3 -1
- package/build/index.cjs +0 -2
- package/build/index.mjs +0 -2
- package/build/modules/frontend/build/3rdparty/qfchart_0.8.7/echarts.min.js +45 -45
- package/build/modules/frontend/build/3rdparty/qfchart_0.8.7/pinets.js +122 -21534
- package/build/modules/frontend/build/3rdparty/qfchart_0.8.7/qfchart.js +37 -3976
- package/build/modules/frontend/build/assets/{Article-DYhWfFAi.js → Article-CUKUVtNn.js} +1 -1
- package/build/modules/frontend/build/assets/{Background-COpkJTP-.js → Background-Cm7NWjYf.js} +1 -1
- package/build/modules/frontend/build/assets/{IconPhoto-DUgsqsYP.js → IconPhoto-VQJtz-we.js} +1 -1
- package/build/modules/frontend/build/assets/{KeyboardArrowLeft-BlwcBPHn.js → KeyboardArrowLeft-Bx3w5JlP.js} +1 -1
- package/build/modules/frontend/build/assets/{Refresh-aWduZclR.js → Refresh-BkaYn01m.js} +1 -1
- package/build/modules/frontend/build/assets/emitters-DFr8bMD1.js +1 -0
- package/build/modules/frontend/build/assets/{hasRouteMatch-CImjW4Jf.js → hasRouteMatch-F5OIUGjU.js} +1 -1
- package/build/modules/frontend/build/assets/{html2canvas-Do8zi4tS.js → html2canvas-D9EezEc_.js} +1 -1
- package/build/modules/frontend/build/assets/index-ApVR6Ifc.js +1 -0
- package/build/modules/frontend/build/assets/{index-Cb4CVVwH.js → index-BTuorlT_.js} +1 -1
- package/build/modules/frontend/build/assets/{index-WhalaOXd.js → index-BdOvXECv.js} +1 -1
- package/build/modules/frontend/build/assets/{index-7wQuV9F_.js → index-Bo9eE7UW.js} +1 -1
- package/build/modules/frontend/build/assets/{index-CjymMd2D.js → index-C6MJd2e7.js} +1 -1
- package/build/modules/frontend/build/assets/{index-BfiWEbdc.js → index-CROpLyTo.js} +1 -1
- package/build/modules/frontend/build/assets/{index-lZGMPvrT.js → index-ChbT-tDv.js} +1 -1
- package/build/modules/frontend/build/assets/{index-CETLG42q.js → index-Cx2iXzXi.js} +1 -1
- package/build/modules/frontend/build/assets/{index-D6YeBcAB.js → index-D4lcxG8i.js} +1 -1
- package/build/modules/frontend/build/assets/{index-kQ_oUmTQ.js → index-D5q-xBp8.js} +1 -1
- package/build/modules/frontend/build/assets/{index-Ce2sQITf.js → index-Mr3SEWze.js} +6 -6
- package/build/modules/frontend/build/assets/index-XWTSQlQH.js +1 -0
- package/build/modules/frontend/build/assets/{index.es-Cel98f_u.js → index.es-Dy9r9ja5.js} +1 -1
- package/build/modules/frontend/build/assets/{markdownit-22RgFULT.js → markdownit-CaCiS1m5.js} +1 -1
- package/build/modules/frontend/build/index.html +1 -1
- package/package.json +4 -4
- package/build/modules/frontend/build/assets/emitters-CSLNlyHG.js +0 -1
- package/build/modules/frontend/build/assets/index-B_46G-d8.js +0 -1
- package/build/modules/frontend/build/assets/index-Bmqo1dsM.js +0 -1
|
@@ -14,3984 +14,45 @@
|
|
|
14
14
|
* See the License for the specific language governing permissions and
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
|
-
(function (global, factory) {
|
|
18
|
-
|
|
19
|
-
typeof define === 'function' && define.amd ? define(['exports', 'echarts'], factory) :
|
|
20
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.QFChart = {}, global.echarts));
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
var n = Object.create(null);
|
|
25
|
-
if (e) {
|
|
26
|
-
Object.keys(e).forEach(function (k) {
|
|
27
|
-
if (k !== 'default') {
|
|
28
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
29
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
30
|
-
enumerable: true,
|
|
31
|
-
get: function () { return e[k]; }
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
n.default = e;
|
|
37
|
-
return Object.freeze(n);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
var echarts__namespace = /*#__PURE__*/_interopNamespaceDefault(echarts);
|
|
41
|
-
|
|
42
|
-
var __defProp$a = Object.defineProperty;
|
|
43
|
-
var __defNormalProp$a = (obj, key, value) => key in obj ? __defProp$a(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
44
|
-
var __publicField$a = (obj, key, value) => {
|
|
45
|
-
__defNormalProp$a(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
46
|
-
return value;
|
|
47
|
-
};
|
|
48
|
-
class Indicator {
|
|
49
|
-
constructor(id, plots, paneIndex, options = {}) {
|
|
50
|
-
__publicField$a(this, "id");
|
|
51
|
-
__publicField$a(this, "plots");
|
|
52
|
-
__publicField$a(this, "paneIndex");
|
|
53
|
-
__publicField$a(this, "height");
|
|
54
|
-
__publicField$a(this, "collapsed");
|
|
55
|
-
__publicField$a(this, "titleColor");
|
|
56
|
-
__publicField$a(this, "controls");
|
|
57
|
-
this.id = id;
|
|
58
|
-
this.plots = plots;
|
|
59
|
-
this.paneIndex = paneIndex;
|
|
60
|
-
this.height = options.height;
|
|
61
|
-
this.collapsed = options.collapsed || false;
|
|
62
|
-
this.titleColor = options.titleColor;
|
|
63
|
-
this.controls = options.controls;
|
|
64
|
-
}
|
|
65
|
-
toggleCollapse() {
|
|
66
|
-
this.collapsed = !this.collapsed;
|
|
67
|
-
}
|
|
68
|
-
isVisible() {
|
|
69
|
-
return !this.collapsed;
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Update indicator data incrementally by merging new points
|
|
73
|
-
*
|
|
74
|
-
* @param plots - New plots data to merge (same structure as constructor)
|
|
75
|
-
*
|
|
76
|
-
* @remarks
|
|
77
|
-
* This method merges new indicator data with existing data by timestamp.
|
|
78
|
-
* - New timestamps are added
|
|
79
|
-
* - Existing timestamps are updated with new values
|
|
80
|
-
* - All data is automatically sorted by time after merge
|
|
81
|
-
*
|
|
82
|
-
* **Important**: This method only updates the indicator's internal data structure.
|
|
83
|
-
* To see the changes reflected in the chart, you MUST call `chart.updateData()`
|
|
84
|
-
* after updating indicator data.
|
|
85
|
-
*
|
|
86
|
-
* **Usage Pattern**:
|
|
87
|
-
* ```typescript
|
|
88
|
-
* // 1. Update indicator data first
|
|
89
|
-
* indicator.updateData({
|
|
90
|
-
* macd: { data: [{ time: 1234567890, value: 150 }], options: { style: 'line', color: '#2962FF' } }
|
|
91
|
-
* });
|
|
92
|
-
*
|
|
93
|
-
* // 2. Then update chart data to trigger re-render
|
|
94
|
-
* chart.updateData([
|
|
95
|
-
* { time: 1234567890, open: 100, high: 105, low: 99, close: 103, volume: 1000 }
|
|
96
|
-
* ]);
|
|
97
|
-
* ```
|
|
98
|
-
*
|
|
99
|
-
* **Note**: If you update indicator data without corresponding market data changes,
|
|
100
|
-
* this typically indicates a recalculation scenario. In normal workflows, indicator
|
|
101
|
-
* values are derived from market data, so indicator updates should correspond to
|
|
102
|
-
* new or modified market bars.
|
|
103
|
-
*/
|
|
104
|
-
updateData(plots) {
|
|
105
|
-
Object.keys(plots).forEach((plotName) => {
|
|
106
|
-
if (!this.plots[plotName]) {
|
|
107
|
-
this.plots[plotName] = plots[plotName];
|
|
108
|
-
} else {
|
|
109
|
-
const existingPlot = this.plots[plotName];
|
|
110
|
-
const newPlot = plots[plotName];
|
|
111
|
-
if (!existingPlot.data)
|
|
112
|
-
return;
|
|
113
|
-
if (newPlot.options) {
|
|
114
|
-
existingPlot.options = { ...existingPlot.options, ...newPlot.options };
|
|
115
|
-
}
|
|
116
|
-
const existingTimeMap = /* @__PURE__ */ new Map();
|
|
117
|
-
existingPlot.data?.forEach((point) => {
|
|
118
|
-
existingTimeMap.set(point.time, point);
|
|
119
|
-
});
|
|
120
|
-
newPlot.data?.forEach((point) => {
|
|
121
|
-
existingTimeMap.set(point.time, point);
|
|
122
|
-
});
|
|
123
|
-
existingPlot.data = Array.from(existingTimeMap.values()).sort((a, b) => a.time - b.time);
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
class AxisUtils {
|
|
130
|
-
// Create min/max functions that apply padding
|
|
131
|
-
static createMinFunction(paddingPercent) {
|
|
132
|
-
return (value) => {
|
|
133
|
-
const range = value.max - value.min;
|
|
134
|
-
const padding = range * (paddingPercent / 100);
|
|
135
|
-
return value.min - padding;
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
static createMaxFunction(paddingPercent) {
|
|
139
|
-
return (value) => {
|
|
140
|
-
const range = value.max - value.min;
|
|
141
|
-
const padding = range * (paddingPercent / 100);
|
|
142
|
-
return value.max + padding;
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
class LayoutManager {
|
|
148
|
-
static calculate(containerHeight, indicators, options, isMainCollapsed = false, maximizedPaneId = null, marketData) {
|
|
149
|
-
let pixelToPercent = 0;
|
|
150
|
-
if (containerHeight > 0) {
|
|
151
|
-
pixelToPercent = 1 / containerHeight * 100;
|
|
152
|
-
}
|
|
153
|
-
const yAxisPaddingPercent = options.yAxisPadding !== void 0 ? options.yAxisPadding : 5;
|
|
154
|
-
const separatePaneIndices = Array.from(indicators.values()).map((ind) => ind.paneIndex).filter((idx) => idx > 0).sort((a, b) => a - b).filter((value, index, self) => self.indexOf(value) === index);
|
|
155
|
-
const hasSeparatePane = separatePaneIndices.length > 0;
|
|
156
|
-
const dzVisible = options.dataZoom?.visible ?? true;
|
|
157
|
-
const dzPosition = options.dataZoom?.position ?? "top";
|
|
158
|
-
const dzHeight = options.dataZoom?.height ?? 6;
|
|
159
|
-
const dzStart = options.dataZoom?.start ?? 0;
|
|
160
|
-
const dzEnd = options.dataZoom?.end ?? 100;
|
|
161
|
-
let mainPaneTop = 8;
|
|
162
|
-
let chartAreaBottom = 92;
|
|
163
|
-
let maximizeTargetIndex = -1;
|
|
164
|
-
if (maximizedPaneId) {
|
|
165
|
-
if (maximizedPaneId === "main") {
|
|
166
|
-
maximizeTargetIndex = 0;
|
|
167
|
-
} else {
|
|
168
|
-
const ind = indicators.get(maximizedPaneId);
|
|
169
|
-
if (ind) {
|
|
170
|
-
maximizeTargetIndex = ind.paneIndex;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
if (maximizeTargetIndex !== -1) {
|
|
175
|
-
const grid2 = [];
|
|
176
|
-
const xAxis2 = [];
|
|
177
|
-
const yAxis2 = [];
|
|
178
|
-
const dataZoom2 = [];
|
|
179
|
-
const dzStart2 = options.dataZoom?.start ?? 50;
|
|
180
|
-
const dzEnd2 = options.dataZoom?.end ?? 100;
|
|
181
|
-
const zoomOnTouch = options.dataZoom?.zoomOnTouch ?? true;
|
|
182
|
-
if (zoomOnTouch) {
|
|
183
|
-
dataZoom2.push({ type: "inside", xAxisIndex: "all", start: dzStart2, end: dzEnd2 });
|
|
184
|
-
}
|
|
185
|
-
const maxPaneIndex = hasSeparatePane ? Math.max(...separatePaneIndices) : 0;
|
|
186
|
-
const paneConfigs2 = [];
|
|
187
|
-
for (let i = 0; i <= maxPaneIndex; i++) {
|
|
188
|
-
const isTarget = i === maximizeTargetIndex;
|
|
189
|
-
grid2.push({
|
|
190
|
-
left: "10%",
|
|
191
|
-
right: "10%",
|
|
192
|
-
top: isTarget ? "5%" : "0%",
|
|
193
|
-
height: isTarget ? "90%" : "0%",
|
|
194
|
-
show: isTarget,
|
|
195
|
-
containLabel: false
|
|
196
|
-
});
|
|
197
|
-
xAxis2.push({
|
|
198
|
-
type: "category",
|
|
199
|
-
gridIndex: i,
|
|
200
|
-
data: [],
|
|
201
|
-
show: isTarget,
|
|
202
|
-
axisLabel: {
|
|
203
|
-
show: isTarget,
|
|
204
|
-
color: "#94a3b8",
|
|
205
|
-
fontFamily: options.fontFamily
|
|
206
|
-
},
|
|
207
|
-
axisLine: { show: isTarget, lineStyle: { color: "#334155" } },
|
|
208
|
-
splitLine: {
|
|
209
|
-
show: isTarget,
|
|
210
|
-
lineStyle: { color: "#334155", opacity: 0.5 }
|
|
211
|
-
}
|
|
212
|
-
});
|
|
213
|
-
let yMin;
|
|
214
|
-
let yMax;
|
|
215
|
-
if (i === 0 && maximizeTargetIndex === 0) {
|
|
216
|
-
yMin = options.yAxisMin !== void 0 && options.yAxisMin !== "auto" ? options.yAxisMin : AxisUtils.createMinFunction(yAxisPaddingPercent);
|
|
217
|
-
yMax = options.yAxisMax !== void 0 && options.yAxisMax !== "auto" ? options.yAxisMax : AxisUtils.createMaxFunction(yAxisPaddingPercent);
|
|
218
|
-
} else {
|
|
219
|
-
yMin = AxisUtils.createMinFunction(yAxisPaddingPercent);
|
|
220
|
-
yMax = AxisUtils.createMaxFunction(yAxisPaddingPercent);
|
|
221
|
-
}
|
|
222
|
-
yAxis2.push({
|
|
223
|
-
position: "right",
|
|
224
|
-
gridIndex: i,
|
|
225
|
-
show: isTarget,
|
|
226
|
-
scale: true,
|
|
227
|
-
min: yMin,
|
|
228
|
-
max: yMax,
|
|
229
|
-
axisLabel: {
|
|
230
|
-
show: isTarget,
|
|
231
|
-
color: "#94a3b8",
|
|
232
|
-
fontFamily: options.fontFamily,
|
|
233
|
-
formatter: (value) => {
|
|
234
|
-
if (options.yAxisLabelFormatter) {
|
|
235
|
-
return options.yAxisLabelFormatter(value);
|
|
236
|
-
}
|
|
237
|
-
const decimals = options.yAxisDecimalPlaces !== void 0 ? options.yAxisDecimalPlaces : 2;
|
|
238
|
-
if (typeof value === "number") {
|
|
239
|
-
return value.toFixed(decimals);
|
|
240
|
-
}
|
|
241
|
-
return String(value);
|
|
242
|
-
}
|
|
243
|
-
},
|
|
244
|
-
splitLine: {
|
|
245
|
-
show: isTarget,
|
|
246
|
-
lineStyle: { color: "#334155", opacity: 0.5 }
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
if (i > 0) {
|
|
250
|
-
const ind = Array.from(indicators.values()).find((ind2) => ind2.paneIndex === i);
|
|
251
|
-
if (ind) {
|
|
252
|
-
paneConfigs2.push({
|
|
253
|
-
index: i,
|
|
254
|
-
height: isTarget ? 90 : 0,
|
|
255
|
-
top: isTarget ? 5 : 0,
|
|
256
|
-
isCollapsed: false,
|
|
257
|
-
indicatorId: ind.id,
|
|
258
|
-
titleColor: ind.titleColor,
|
|
259
|
-
controls: ind.controls
|
|
260
|
-
});
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
return {
|
|
265
|
-
grid: grid2,
|
|
266
|
-
xAxis: xAxis2,
|
|
267
|
-
yAxis: yAxis2,
|
|
268
|
-
dataZoom: dataZoom2,
|
|
269
|
-
paneLayout: paneConfigs2,
|
|
270
|
-
mainPaneHeight: maximizeTargetIndex === 0 ? 90 : 0,
|
|
271
|
-
mainPaneTop: maximizeTargetIndex === 0 ? 5 : 0,
|
|
272
|
-
pixelToPercent,
|
|
273
|
-
overlayYAxisMap: /* @__PURE__ */ new Map(),
|
|
274
|
-
// No overlays in maximized view
|
|
275
|
-
separatePaneYAxisOffset: 1
|
|
276
|
-
// In maximized view, no overlays, so separate panes start at 1
|
|
277
|
-
};
|
|
278
|
-
}
|
|
279
|
-
if (dzVisible) {
|
|
280
|
-
if (dzPosition === "top") {
|
|
281
|
-
mainPaneTop = dzHeight + 4;
|
|
282
|
-
chartAreaBottom = 95;
|
|
283
|
-
} else {
|
|
284
|
-
chartAreaBottom = 100 - dzHeight - 2;
|
|
285
|
-
mainPaneTop = 8;
|
|
286
|
-
}
|
|
287
|
-
} else {
|
|
288
|
-
mainPaneTop = 5;
|
|
289
|
-
chartAreaBottom = 95;
|
|
290
|
-
}
|
|
291
|
-
let gapPercent = 5;
|
|
292
|
-
if (containerHeight > 0) {
|
|
293
|
-
gapPercent = 20 / containerHeight * 100;
|
|
294
|
-
}
|
|
295
|
-
let mainHeightVal = 75;
|
|
296
|
-
let paneConfigs = [];
|
|
297
|
-
if (hasSeparatePane) {
|
|
298
|
-
const panes = separatePaneIndices.map((idx) => {
|
|
299
|
-
const ind = Array.from(indicators.values()).find((i) => i.paneIndex === idx);
|
|
300
|
-
return {
|
|
301
|
-
index: idx,
|
|
302
|
-
requestedHeight: ind?.height,
|
|
303
|
-
isCollapsed: ind?.collapsed ?? false,
|
|
304
|
-
indicatorId: ind?.id,
|
|
305
|
-
titleColor: ind?.titleColor,
|
|
306
|
-
controls: ind?.controls
|
|
307
|
-
};
|
|
308
|
-
});
|
|
309
|
-
const resolvedPanes = panes.map((p) => ({
|
|
310
|
-
...p,
|
|
311
|
-
height: p.isCollapsed ? 3 : p.requestedHeight !== void 0 ? p.requestedHeight : 15
|
|
312
|
-
}));
|
|
313
|
-
const totalIndicatorHeight = resolvedPanes.reduce((sum, p) => sum + p.height, 0);
|
|
314
|
-
const totalGaps = resolvedPanes.length * gapPercent;
|
|
315
|
-
const totalBottomSpace = totalIndicatorHeight + totalGaps;
|
|
316
|
-
const totalAvailable = chartAreaBottom - mainPaneTop;
|
|
317
|
-
mainHeightVal = totalAvailable - totalBottomSpace;
|
|
318
|
-
if (isMainCollapsed) {
|
|
319
|
-
mainHeightVal = 3;
|
|
320
|
-
} else {
|
|
321
|
-
if (mainHeightVal < 20) {
|
|
322
|
-
mainHeightVal = Math.max(mainHeightVal, 10);
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
let currentTop = mainPaneTop + mainHeightVal + gapPercent;
|
|
326
|
-
paneConfigs = resolvedPanes.map((p) => {
|
|
327
|
-
const config = {
|
|
328
|
-
index: p.index,
|
|
329
|
-
height: p.height,
|
|
330
|
-
top: currentTop,
|
|
331
|
-
isCollapsed: p.isCollapsed,
|
|
332
|
-
indicatorId: p.indicatorId,
|
|
333
|
-
titleColor: p.titleColor,
|
|
334
|
-
controls: p.controls
|
|
335
|
-
};
|
|
336
|
-
currentTop += p.height + gapPercent;
|
|
337
|
-
return config;
|
|
338
|
-
});
|
|
339
|
-
} else {
|
|
340
|
-
mainHeightVal = chartAreaBottom - mainPaneTop;
|
|
341
|
-
if (isMainCollapsed) {
|
|
342
|
-
mainHeightVal = 3;
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
const grid = [];
|
|
346
|
-
grid.push({
|
|
347
|
-
left: "10%",
|
|
348
|
-
right: "10%",
|
|
349
|
-
top: mainPaneTop + "%",
|
|
350
|
-
height: mainHeightVal + "%",
|
|
351
|
-
containLabel: false
|
|
352
|
-
// We handle margins explicitly
|
|
353
|
-
});
|
|
354
|
-
paneConfigs.forEach((pane) => {
|
|
355
|
-
grid.push({
|
|
356
|
-
left: "10%",
|
|
357
|
-
right: "10%",
|
|
358
|
-
top: pane.top + "%",
|
|
359
|
-
height: pane.height + "%",
|
|
360
|
-
containLabel: false
|
|
361
|
-
});
|
|
362
|
-
});
|
|
363
|
-
const allXAxisIndices = [0, ...paneConfigs.map((_, i) => i + 1)];
|
|
364
|
-
const xAxis = [];
|
|
365
|
-
const isMainBottom = paneConfigs.length === 0;
|
|
366
|
-
xAxis.push({
|
|
367
|
-
type: "category",
|
|
368
|
-
data: [],
|
|
369
|
-
// Will be filled by SeriesBuilder or QFChart
|
|
370
|
-
gridIndex: 0,
|
|
371
|
-
scale: true,
|
|
372
|
-
// boundaryGap will be set in QFChart.ts based on padding option
|
|
373
|
-
axisLine: {
|
|
374
|
-
onZero: false,
|
|
375
|
-
show: !isMainCollapsed,
|
|
376
|
-
lineStyle: { color: "#334155" }
|
|
377
|
-
},
|
|
378
|
-
splitLine: {
|
|
379
|
-
show: !isMainCollapsed,
|
|
380
|
-
lineStyle: { color: "#334155", opacity: 0.5 }
|
|
381
|
-
},
|
|
382
|
-
axisLabel: {
|
|
383
|
-
show: !isMainCollapsed,
|
|
384
|
-
color: "#94a3b8",
|
|
385
|
-
fontFamily: options.fontFamily || "sans-serif",
|
|
386
|
-
formatter: (value) => {
|
|
387
|
-
if (options.yAxisLabelFormatter) {
|
|
388
|
-
return options.yAxisLabelFormatter(value);
|
|
389
|
-
}
|
|
390
|
-
const decimals = options.yAxisDecimalPlaces !== void 0 ? options.yAxisDecimalPlaces : 2;
|
|
391
|
-
if (typeof value === "number") {
|
|
392
|
-
return value.toFixed(decimals);
|
|
393
|
-
}
|
|
394
|
-
return String(value);
|
|
395
|
-
}
|
|
396
|
-
},
|
|
397
|
-
axisTick: { show: !isMainCollapsed },
|
|
398
|
-
axisPointer: {
|
|
399
|
-
label: {
|
|
400
|
-
show: isMainBottom,
|
|
401
|
-
fontSize: 11,
|
|
402
|
-
backgroundColor: "#475569"
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
});
|
|
406
|
-
paneConfigs.forEach((pane, i) => {
|
|
407
|
-
const isBottom = i === paneConfigs.length - 1;
|
|
408
|
-
xAxis.push({
|
|
409
|
-
type: "category",
|
|
410
|
-
gridIndex: i + 1,
|
|
411
|
-
// 0 is main
|
|
412
|
-
data: [],
|
|
413
|
-
// Shared data
|
|
414
|
-
axisLabel: { show: false },
|
|
415
|
-
// Hide labels on indicator panes
|
|
416
|
-
axisLine: { show: !pane.isCollapsed, lineStyle: { color: "#334155" } },
|
|
417
|
-
axisTick: { show: false },
|
|
418
|
-
splitLine: { show: false },
|
|
419
|
-
axisPointer: {
|
|
420
|
-
label: {
|
|
421
|
-
show: isBottom,
|
|
422
|
-
fontSize: 11,
|
|
423
|
-
backgroundColor: "#475569"
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
});
|
|
427
|
-
});
|
|
428
|
-
const yAxis = [];
|
|
429
|
-
let mainYAxisMin;
|
|
430
|
-
let mainYAxisMax;
|
|
431
|
-
if (options.yAxisMin !== void 0 && options.yAxisMin !== "auto") {
|
|
432
|
-
mainYAxisMin = options.yAxisMin;
|
|
433
|
-
} else {
|
|
434
|
-
mainYAxisMin = AxisUtils.createMinFunction(yAxisPaddingPercent);
|
|
435
|
-
}
|
|
436
|
-
if (options.yAxisMax !== void 0 && options.yAxisMax !== "auto") {
|
|
437
|
-
mainYAxisMax = options.yAxisMax;
|
|
438
|
-
} else {
|
|
439
|
-
mainYAxisMax = AxisUtils.createMaxFunction(yAxisPaddingPercent);
|
|
440
|
-
}
|
|
441
|
-
yAxis.push({
|
|
442
|
-
position: "right",
|
|
443
|
-
scale: true,
|
|
444
|
-
min: mainYAxisMin,
|
|
445
|
-
max: mainYAxisMax,
|
|
446
|
-
gridIndex: 0,
|
|
447
|
-
splitLine: {
|
|
448
|
-
show: !isMainCollapsed,
|
|
449
|
-
lineStyle: { color: "#334155", opacity: 0.5 }
|
|
450
|
-
},
|
|
451
|
-
axisLine: { show: !isMainCollapsed, lineStyle: { color: "#334155" } },
|
|
452
|
-
axisLabel: {
|
|
453
|
-
show: !isMainCollapsed,
|
|
454
|
-
color: "#94a3b8",
|
|
455
|
-
fontFamily: options.fontFamily || "sans-serif",
|
|
456
|
-
formatter: (value) => {
|
|
457
|
-
if (options.yAxisLabelFormatter) {
|
|
458
|
-
return options.yAxisLabelFormatter(value);
|
|
459
|
-
}
|
|
460
|
-
const decimals = options.yAxisDecimalPlaces !== void 0 ? options.yAxisDecimalPlaces : 2;
|
|
461
|
-
if (typeof value === "number") {
|
|
462
|
-
return value.toFixed(decimals);
|
|
463
|
-
}
|
|
464
|
-
return String(value);
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
});
|
|
468
|
-
let nextYAxisIndex = 1;
|
|
469
|
-
let priceMin = -Infinity;
|
|
470
|
-
let priceMax = Infinity;
|
|
471
|
-
if (marketData && marketData.length > 0) {
|
|
472
|
-
priceMin = Math.min(...marketData.map((d) => d.low));
|
|
473
|
-
priceMax = Math.max(...marketData.map((d) => d.high));
|
|
474
|
-
}
|
|
475
|
-
const overlayYAxisMap = /* @__PURE__ */ new Map();
|
|
476
|
-
indicators.forEach((indicator, id) => {
|
|
477
|
-
if (indicator.paneIndex === 0 && !indicator.collapsed) {
|
|
478
|
-
if (marketData && marketData.length > 0) {
|
|
479
|
-
Object.entries(indicator.plots).forEach(([plotName, plot]) => {
|
|
480
|
-
const plotKey = `${id}::${plotName}`;
|
|
481
|
-
const visualOnlyStyles = ["background", "barcolor", "char"];
|
|
482
|
-
const isShapeWithPriceLocation = plot.options.style === "shape" && (plot.options.location === "abovebar" || plot.options.location === "belowbar");
|
|
483
|
-
if (visualOnlyStyles.includes(plot.options.style)) {
|
|
484
|
-
if (!overlayYAxisMap.has(plotKey)) {
|
|
485
|
-
overlayYAxisMap.set(plotKey, nextYAxisIndex);
|
|
486
|
-
nextYAxisIndex++;
|
|
487
|
-
}
|
|
488
|
-
return;
|
|
489
|
-
}
|
|
490
|
-
if (plot.options.style === "shape" && !isShapeWithPriceLocation) {
|
|
491
|
-
if (!overlayYAxisMap.has(plotKey)) {
|
|
492
|
-
overlayYAxisMap.set(plotKey, nextYAxisIndex);
|
|
493
|
-
nextYAxisIndex++;
|
|
494
|
-
}
|
|
495
|
-
return;
|
|
496
|
-
}
|
|
497
|
-
const values = [];
|
|
498
|
-
if (plot.data) {
|
|
499
|
-
Object.values(plot.data).forEach((value) => {
|
|
500
|
-
if (typeof value === "number" && !isNaN(value) && isFinite(value)) {
|
|
501
|
-
values.push(value);
|
|
502
|
-
}
|
|
503
|
-
});
|
|
504
|
-
}
|
|
505
|
-
if (values.length > 0) {
|
|
506
|
-
const plotMin = Math.min(...values);
|
|
507
|
-
const plotMax = Math.max(...values);
|
|
508
|
-
const plotRange = plotMax - plotMin;
|
|
509
|
-
const priceRange = priceMax - priceMin;
|
|
510
|
-
const isWithinBounds = plotMin >= priceMin * 0.5 && plotMax <= priceMax * 1.5;
|
|
511
|
-
const hasSimilarMagnitude = plotRange > priceRange * 0.01;
|
|
512
|
-
const isCompatible = isWithinBounds && hasSimilarMagnitude;
|
|
513
|
-
if (!isCompatible) {
|
|
514
|
-
if (!overlayYAxisMap.has(plotKey)) {
|
|
515
|
-
overlayYAxisMap.set(plotKey, nextYAxisIndex);
|
|
516
|
-
nextYAxisIndex++;
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
});
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
});
|
|
524
|
-
const numOverlayAxes = overlayYAxisMap.size > 0 ? nextYAxisIndex - 1 : 0;
|
|
525
|
-
for (let i = 0; i < numOverlayAxes; i++) {
|
|
526
|
-
yAxis.push({
|
|
527
|
-
position: "left",
|
|
528
|
-
scale: true,
|
|
529
|
-
min: AxisUtils.createMinFunction(yAxisPaddingPercent),
|
|
530
|
-
max: AxisUtils.createMaxFunction(yAxisPaddingPercent),
|
|
531
|
-
gridIndex: 0,
|
|
532
|
-
show: false,
|
|
533
|
-
// Hide the axis visual elements
|
|
534
|
-
splitLine: { show: false },
|
|
535
|
-
axisLine: { show: false },
|
|
536
|
-
axisLabel: { show: false }
|
|
537
|
-
});
|
|
538
|
-
}
|
|
539
|
-
const separatePaneYAxisOffset = nextYAxisIndex;
|
|
540
|
-
paneConfigs.forEach((pane, i) => {
|
|
541
|
-
yAxis.push({
|
|
542
|
-
position: "right",
|
|
543
|
-
scale: true,
|
|
544
|
-
min: AxisUtils.createMinFunction(yAxisPaddingPercent),
|
|
545
|
-
max: AxisUtils.createMaxFunction(yAxisPaddingPercent),
|
|
546
|
-
gridIndex: i + 1,
|
|
547
|
-
splitLine: {
|
|
548
|
-
show: !pane.isCollapsed,
|
|
549
|
-
lineStyle: { color: "#334155", opacity: 0.3 }
|
|
550
|
-
},
|
|
551
|
-
axisLabel: {
|
|
552
|
-
show: !pane.isCollapsed,
|
|
553
|
-
color: "#94a3b8",
|
|
554
|
-
fontFamily: options.fontFamily || "sans-serif",
|
|
555
|
-
fontSize: 10,
|
|
556
|
-
formatter: (value) => {
|
|
557
|
-
if (options.yAxisLabelFormatter) {
|
|
558
|
-
return options.yAxisLabelFormatter(value);
|
|
559
|
-
}
|
|
560
|
-
const decimals = options.yAxisDecimalPlaces !== void 0 ? options.yAxisDecimalPlaces : 2;
|
|
561
|
-
if (typeof value === "number") {
|
|
562
|
-
return value.toFixed(decimals);
|
|
563
|
-
}
|
|
564
|
-
return String(value);
|
|
565
|
-
}
|
|
566
|
-
},
|
|
567
|
-
axisLine: { show: !pane.isCollapsed, lineStyle: { color: "#334155" } }
|
|
568
|
-
});
|
|
569
|
-
});
|
|
570
|
-
const dataZoom = [];
|
|
571
|
-
if (dzVisible) {
|
|
572
|
-
const zoomOnTouch = options.dataZoom?.zoomOnTouch ?? true;
|
|
573
|
-
if (zoomOnTouch) {
|
|
574
|
-
dataZoom.push({
|
|
575
|
-
type: "inside",
|
|
576
|
-
xAxisIndex: allXAxisIndices,
|
|
577
|
-
start: dzStart,
|
|
578
|
-
end: dzEnd
|
|
579
|
-
});
|
|
580
|
-
}
|
|
581
|
-
if (dzPosition === "top") {
|
|
582
|
-
dataZoom.push({
|
|
583
|
-
type: "slider",
|
|
584
|
-
xAxisIndex: allXAxisIndices,
|
|
585
|
-
top: "1%",
|
|
586
|
-
height: dzHeight + "%",
|
|
587
|
-
start: dzStart,
|
|
588
|
-
end: dzEnd,
|
|
589
|
-
borderColor: "#334155",
|
|
590
|
-
textStyle: { color: "#cbd5e1" },
|
|
591
|
-
brushSelect: false
|
|
592
|
-
});
|
|
593
|
-
} else {
|
|
594
|
-
dataZoom.push({
|
|
595
|
-
type: "slider",
|
|
596
|
-
xAxisIndex: allXAxisIndices,
|
|
597
|
-
bottom: "1%",
|
|
598
|
-
height: dzHeight + "%",
|
|
599
|
-
start: dzStart,
|
|
600
|
-
end: dzEnd,
|
|
601
|
-
borderColor: "#334155",
|
|
602
|
-
textStyle: { color: "#cbd5e1" },
|
|
603
|
-
brushSelect: false
|
|
604
|
-
});
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
return {
|
|
608
|
-
grid,
|
|
609
|
-
xAxis,
|
|
610
|
-
yAxis,
|
|
611
|
-
dataZoom,
|
|
612
|
-
paneLayout: paneConfigs,
|
|
613
|
-
mainPaneHeight: mainHeightVal,
|
|
614
|
-
mainPaneTop,
|
|
615
|
-
pixelToPercent,
|
|
616
|
-
overlayYAxisMap,
|
|
617
|
-
separatePaneYAxisOffset
|
|
618
|
-
};
|
|
619
|
-
}
|
|
620
|
-
static calculateMaximized(containerHeight, options, targetPaneIndex) {
|
|
621
|
-
return {
|
|
622
|
-
grid: [],
|
|
623
|
-
xAxis: [],
|
|
624
|
-
yAxis: [],
|
|
625
|
-
dataZoom: [],
|
|
626
|
-
paneLayout: [],
|
|
627
|
-
mainPaneHeight: 0,
|
|
628
|
-
mainPaneTop: 0,
|
|
629
|
-
pixelToPercent: 0
|
|
630
|
-
};
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
class LineRenderer {
|
|
635
|
-
render(context) {
|
|
636
|
-
const { seriesName, xAxisIndex, yAxisIndex, dataArray, colorArray, plotOptions } = context;
|
|
637
|
-
const defaultColor = "#2962ff";
|
|
638
|
-
return {
|
|
639
|
-
name: seriesName,
|
|
640
|
-
type: "custom",
|
|
641
|
-
xAxisIndex,
|
|
642
|
-
yAxisIndex,
|
|
643
|
-
renderItem: (params, api) => {
|
|
644
|
-
const index = params.dataIndex;
|
|
645
|
-
if (index === 0)
|
|
646
|
-
return;
|
|
647
|
-
const y2 = api.value(1);
|
|
648
|
-
const y1 = api.value(2);
|
|
649
|
-
if (y2 === null || isNaN(y2) || y1 === null || isNaN(y1))
|
|
650
|
-
return;
|
|
651
|
-
const p1 = api.coord([index - 1, y1]);
|
|
652
|
-
const p2 = api.coord([index, y2]);
|
|
653
|
-
return {
|
|
654
|
-
type: "line",
|
|
655
|
-
shape: {
|
|
656
|
-
x1: p1[0],
|
|
657
|
-
y1: p1[1],
|
|
658
|
-
x2: p2[0],
|
|
659
|
-
y2: p2[1]
|
|
660
|
-
},
|
|
661
|
-
style: {
|
|
662
|
-
stroke: colorArray[index] || plotOptions.color || defaultColor,
|
|
663
|
-
lineWidth: plotOptions.linewidth || 1
|
|
664
|
-
},
|
|
665
|
-
silent: true
|
|
666
|
-
};
|
|
667
|
-
},
|
|
668
|
-
// Data format: [index, value, prevValue]
|
|
669
|
-
data: dataArray.map((val, i) => [i, val, i > 0 ? dataArray[i - 1] : null])
|
|
670
|
-
};
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
class StepRenderer {
|
|
675
|
-
render(context) {
|
|
676
|
-
const { seriesName, xAxisIndex, yAxisIndex, dataArray, colorArray, plotOptions } = context;
|
|
677
|
-
const defaultColor = "#2962ff";
|
|
678
|
-
return {
|
|
679
|
-
name: seriesName,
|
|
680
|
-
type: "custom",
|
|
681
|
-
xAxisIndex,
|
|
682
|
-
yAxisIndex,
|
|
683
|
-
renderItem: (params, api) => {
|
|
684
|
-
const x = api.value(0);
|
|
685
|
-
const y = api.value(1);
|
|
686
|
-
if (isNaN(y) || y === null)
|
|
687
|
-
return;
|
|
688
|
-
const coords = api.coord([x, y]);
|
|
689
|
-
const width = api.size([1, 0])[0];
|
|
690
|
-
return {
|
|
691
|
-
type: "line",
|
|
692
|
-
shape: {
|
|
693
|
-
x1: coords[0] - width / 2,
|
|
694
|
-
y1: coords[1],
|
|
695
|
-
x2: coords[0] + width / 2,
|
|
696
|
-
y2: coords[1]
|
|
697
|
-
},
|
|
698
|
-
style: {
|
|
699
|
-
stroke: colorArray[params.dataIndex] || plotOptions.color || defaultColor,
|
|
700
|
-
lineWidth: plotOptions.linewidth || 1
|
|
701
|
-
},
|
|
702
|
-
silent: true
|
|
703
|
-
};
|
|
704
|
-
},
|
|
705
|
-
data: dataArray.map((val, i) => [i, val])
|
|
706
|
-
};
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
class HistogramRenderer {
|
|
711
|
-
render(context) {
|
|
712
|
-
const { seriesName, xAxisIndex, yAxisIndex, dataArray, colorArray, plotOptions } = context;
|
|
713
|
-
const defaultColor = "#2962ff";
|
|
714
|
-
return {
|
|
715
|
-
name: seriesName,
|
|
716
|
-
type: "bar",
|
|
717
|
-
xAxisIndex,
|
|
718
|
-
yAxisIndex,
|
|
719
|
-
data: dataArray.map((val, i) => ({
|
|
720
|
-
value: val,
|
|
721
|
-
itemStyle: colorArray[i] ? { color: colorArray[i] } : void 0
|
|
722
|
-
})),
|
|
723
|
-
itemStyle: { color: plotOptions.color || defaultColor }
|
|
724
|
-
};
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
const imageCache = /* @__PURE__ */ new Map();
|
|
729
|
-
function textToBase64Image(text, color = "#00da3c", fontSize = "64px") {
|
|
730
|
-
if (typeof document === "undefined")
|
|
731
|
-
return "";
|
|
732
|
-
const cacheKey = `${text}-${color}-${fontSize}`;
|
|
733
|
-
if (imageCache.has(cacheKey)) {
|
|
734
|
-
return imageCache.get(cacheKey);
|
|
735
|
-
}
|
|
736
|
-
const canvas = document.createElement("canvas");
|
|
737
|
-
const ctx = canvas.getContext("2d");
|
|
738
|
-
canvas.width = 32;
|
|
739
|
-
canvas.height = 32;
|
|
740
|
-
if (ctx) {
|
|
741
|
-
ctx.font = "bold " + fontSize + " Arial";
|
|
742
|
-
ctx.fillStyle = color;
|
|
743
|
-
ctx.textAlign = "center";
|
|
744
|
-
ctx.textBaseline = "middle";
|
|
745
|
-
ctx.fillText(text, 16, 16);
|
|
746
|
-
const dataUrl = canvas.toDataURL("image/png");
|
|
747
|
-
imageCache.set(cacheKey, dataUrl);
|
|
748
|
-
return dataUrl;
|
|
749
|
-
}
|
|
750
|
-
return "";
|
|
751
|
-
}
|
|
752
|
-
|
|
753
|
-
class ScatterRenderer {
|
|
754
|
-
render(context) {
|
|
755
|
-
const { seriesName, xAxisIndex, yAxisIndex, dataArray, colorArray, plotOptions } = context;
|
|
756
|
-
const defaultColor = "#2962ff";
|
|
757
|
-
const style = plotOptions.style;
|
|
758
|
-
if (style === "char") {
|
|
759
|
-
return {
|
|
760
|
-
name: seriesName,
|
|
761
|
-
type: "scatter",
|
|
762
|
-
xAxisIndex,
|
|
763
|
-
yAxisIndex,
|
|
764
|
-
symbolSize: 0,
|
|
765
|
-
// Invisible
|
|
766
|
-
data: dataArray.map((val, i) => ({
|
|
767
|
-
value: [i, val],
|
|
768
|
-
itemStyle: { opacity: 0 }
|
|
769
|
-
})),
|
|
770
|
-
silent: true
|
|
771
|
-
// No interaction
|
|
772
|
-
};
|
|
773
|
-
}
|
|
774
|
-
const scatterData = dataArray.map((val, i) => {
|
|
775
|
-
if (val === null)
|
|
776
|
-
return null;
|
|
777
|
-
const pointColor = colorArray[i] || plotOptions.color || defaultColor;
|
|
778
|
-
const item = {
|
|
779
|
-
value: [i, val],
|
|
780
|
-
itemStyle: { color: pointColor }
|
|
781
|
-
};
|
|
782
|
-
if (style === "cross") {
|
|
783
|
-
item.symbol = `image://${textToBase64Image("+", pointColor, "24px")}`;
|
|
784
|
-
item.symbolSize = 16;
|
|
785
|
-
} else {
|
|
786
|
-
item.symbol = "circle";
|
|
787
|
-
item.symbolSize = 6;
|
|
788
|
-
}
|
|
789
|
-
return item;
|
|
790
|
-
}).filter((item) => item !== null);
|
|
791
|
-
return {
|
|
792
|
-
name: seriesName,
|
|
793
|
-
type: "scatter",
|
|
794
|
-
xAxisIndex,
|
|
795
|
-
yAxisIndex,
|
|
796
|
-
data: scatterData
|
|
797
|
-
};
|
|
798
|
-
}
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
class OHLCBarRenderer {
|
|
802
|
-
render(context) {
|
|
803
|
-
const { seriesName, xAxisIndex, yAxisIndex, dataArray, colorArray, optionsArray, plotOptions } = context;
|
|
804
|
-
const defaultColor = "#2962ff";
|
|
805
|
-
const isCandle = plotOptions.style === "candle";
|
|
806
|
-
const ohlcData = dataArray.map((val, i) => {
|
|
807
|
-
if (val === null || !Array.isArray(val) || val.length !== 4)
|
|
808
|
-
return null;
|
|
809
|
-
const [open, high, low, close] = val;
|
|
810
|
-
const pointOpts = optionsArray[i] || {};
|
|
811
|
-
const color = pointOpts.color || colorArray[i] || plotOptions.color || defaultColor;
|
|
812
|
-
const wickColor = pointOpts.wickcolor || plotOptions.wickcolor || color;
|
|
813
|
-
const borderColor = pointOpts.bordercolor || plotOptions.bordercolor || wickColor;
|
|
814
|
-
return [i, open, close, low, high, color, wickColor, borderColor];
|
|
815
|
-
}).filter((item) => item !== null);
|
|
816
|
-
return {
|
|
817
|
-
name: seriesName,
|
|
818
|
-
type: "custom",
|
|
819
|
-
xAxisIndex,
|
|
820
|
-
yAxisIndex,
|
|
821
|
-
renderItem: (params, api) => {
|
|
822
|
-
const xValue = api.value(0);
|
|
823
|
-
const openValue = api.value(1);
|
|
824
|
-
const closeValue = api.value(2);
|
|
825
|
-
const lowValue = api.value(3);
|
|
826
|
-
const highValue = api.value(4);
|
|
827
|
-
const color = api.value(5);
|
|
828
|
-
const wickColor = api.value(6);
|
|
829
|
-
const borderColor = api.value(7);
|
|
830
|
-
if (isNaN(openValue) || isNaN(closeValue) || isNaN(lowValue) || isNaN(highValue)) {
|
|
831
|
-
return null;
|
|
832
|
-
}
|
|
833
|
-
const xPos = api.coord([xValue, 0])[0];
|
|
834
|
-
const openPos = api.coord([xValue, openValue])[1];
|
|
835
|
-
const closePos = api.coord([xValue, closeValue])[1];
|
|
836
|
-
const lowPos = api.coord([xValue, lowValue])[1];
|
|
837
|
-
const highPos = api.coord([xValue, highValue])[1];
|
|
838
|
-
const barWidth = api.size([1, 0])[0] * 0.6;
|
|
839
|
-
if (isCandle) {
|
|
840
|
-
const bodyTop = Math.min(openPos, closePos);
|
|
841
|
-
const bodyBottom = Math.max(openPos, closePos);
|
|
842
|
-
const bodyHeight = Math.abs(closePos - openPos);
|
|
843
|
-
return {
|
|
844
|
-
type: "group",
|
|
845
|
-
children: [
|
|
846
|
-
// Upper wick
|
|
847
|
-
{
|
|
848
|
-
type: "line",
|
|
849
|
-
shape: {
|
|
850
|
-
x1: xPos,
|
|
851
|
-
y1: highPos,
|
|
852
|
-
x2: xPos,
|
|
853
|
-
y2: bodyTop
|
|
854
|
-
},
|
|
855
|
-
style: {
|
|
856
|
-
stroke: wickColor,
|
|
857
|
-
lineWidth: 1
|
|
858
|
-
}
|
|
859
|
-
},
|
|
860
|
-
// Lower wick
|
|
861
|
-
{
|
|
862
|
-
type: "line",
|
|
863
|
-
shape: {
|
|
864
|
-
x1: xPos,
|
|
865
|
-
y1: bodyBottom,
|
|
866
|
-
x2: xPos,
|
|
867
|
-
y2: lowPos
|
|
868
|
-
},
|
|
869
|
-
style: {
|
|
870
|
-
stroke: wickColor,
|
|
871
|
-
lineWidth: 1
|
|
872
|
-
}
|
|
873
|
-
},
|
|
874
|
-
// Body
|
|
875
|
-
{
|
|
876
|
-
type: "rect",
|
|
877
|
-
shape: {
|
|
878
|
-
x: xPos - barWidth / 2,
|
|
879
|
-
y: bodyTop,
|
|
880
|
-
width: barWidth,
|
|
881
|
-
height: bodyHeight || 1
|
|
882
|
-
// Minimum height for doji
|
|
883
|
-
},
|
|
884
|
-
style: {
|
|
885
|
-
fill: color,
|
|
886
|
-
stroke: borderColor,
|
|
887
|
-
lineWidth: 1
|
|
888
|
-
}
|
|
889
|
-
}
|
|
890
|
-
]
|
|
891
|
-
};
|
|
892
|
-
} else {
|
|
893
|
-
const tickWidth = barWidth * 0.5;
|
|
894
|
-
return {
|
|
895
|
-
type: "group",
|
|
896
|
-
children: [
|
|
897
|
-
// Vertical line (low to high)
|
|
898
|
-
{
|
|
899
|
-
type: "line",
|
|
900
|
-
shape: {
|
|
901
|
-
x1: xPos,
|
|
902
|
-
y1: lowPos,
|
|
903
|
-
x2: xPos,
|
|
904
|
-
y2: highPos
|
|
905
|
-
},
|
|
906
|
-
style: {
|
|
907
|
-
stroke: color,
|
|
908
|
-
lineWidth: 1
|
|
909
|
-
}
|
|
910
|
-
},
|
|
911
|
-
// Open tick (left)
|
|
912
|
-
{
|
|
913
|
-
type: "line",
|
|
914
|
-
shape: {
|
|
915
|
-
x1: xPos - tickWidth,
|
|
916
|
-
y1: openPos,
|
|
917
|
-
x2: xPos,
|
|
918
|
-
y2: openPos
|
|
919
|
-
},
|
|
920
|
-
style: {
|
|
921
|
-
stroke: color,
|
|
922
|
-
lineWidth: 1
|
|
923
|
-
}
|
|
924
|
-
},
|
|
925
|
-
// Close tick (right)
|
|
926
|
-
{
|
|
927
|
-
type: "line",
|
|
928
|
-
shape: {
|
|
929
|
-
x1: xPos,
|
|
930
|
-
y1: closePos,
|
|
931
|
-
x2: xPos + tickWidth,
|
|
932
|
-
y2: closePos
|
|
933
|
-
},
|
|
934
|
-
style: {
|
|
935
|
-
stroke: color,
|
|
936
|
-
lineWidth: 1
|
|
937
|
-
}
|
|
938
|
-
}
|
|
939
|
-
]
|
|
940
|
-
};
|
|
941
|
-
}
|
|
942
|
-
},
|
|
943
|
-
data: ohlcData
|
|
944
|
-
};
|
|
945
|
-
}
|
|
946
|
-
}
|
|
947
|
-
|
|
948
|
-
class ShapeUtils {
|
|
949
|
-
static getShapeSymbol(shape) {
|
|
950
|
-
switch (shape) {
|
|
951
|
-
case "arrowdown":
|
|
952
|
-
return "path://M12 24l-12-12h8v-12h8v12h8z";
|
|
953
|
-
case "arrowup":
|
|
954
|
-
return "path://M12 0l12 12h-8v12h-8v-12h-8z";
|
|
955
|
-
case "circle":
|
|
956
|
-
return "circle";
|
|
957
|
-
case "cross":
|
|
958
|
-
return "path://M11 2h2v9h9v2h-9v9h-2v-9h-9v-2h9z";
|
|
959
|
-
case "diamond":
|
|
960
|
-
return "diamond";
|
|
961
|
-
case "flag":
|
|
962
|
-
return "path://M6 2v20h2v-8h12l-2-6 2-6h-12z";
|
|
963
|
-
case "labeldown":
|
|
964
|
-
return "path://M4 2h16a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-6l-2 4l-2 -4h-6a2 2 0 0 1 -2 -2v-12a2 2 0 0 1 2 -2z";
|
|
965
|
-
case "labelup":
|
|
966
|
-
return "path://M12 2l2 4h6a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-16a2 2 0 0 1 -2 -2v-12a2 2 0 0 1 2 -2h6z";
|
|
967
|
-
case "square":
|
|
968
|
-
return "rect";
|
|
969
|
-
case "triangledown":
|
|
970
|
-
return "path://M12 21l-10-18h20z";
|
|
971
|
-
case "triangleup":
|
|
972
|
-
return "triangle";
|
|
973
|
-
case "xcross":
|
|
974
|
-
return "path://M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z";
|
|
975
|
-
default:
|
|
976
|
-
return "circle";
|
|
977
|
-
}
|
|
978
|
-
}
|
|
979
|
-
static getShapeRotation(shape) {
|
|
980
|
-
return 0;
|
|
981
|
-
}
|
|
982
|
-
static getShapeSize(size, width, height) {
|
|
983
|
-
if (width !== void 0 && height !== void 0) {
|
|
984
|
-
return [width, height];
|
|
985
|
-
}
|
|
986
|
-
let baseSize;
|
|
987
|
-
switch (size) {
|
|
988
|
-
case "tiny":
|
|
989
|
-
baseSize = 8;
|
|
990
|
-
break;
|
|
991
|
-
case "small":
|
|
992
|
-
baseSize = 12;
|
|
993
|
-
break;
|
|
994
|
-
case "normal":
|
|
995
|
-
case "auto":
|
|
996
|
-
baseSize = 16;
|
|
997
|
-
break;
|
|
998
|
-
case "large":
|
|
999
|
-
baseSize = 24;
|
|
1000
|
-
break;
|
|
1001
|
-
case "huge":
|
|
1002
|
-
baseSize = 32;
|
|
1003
|
-
break;
|
|
1004
|
-
default:
|
|
1005
|
-
baseSize = 16;
|
|
1006
|
-
}
|
|
1007
|
-
if (width !== void 0) {
|
|
1008
|
-
return [width, width];
|
|
1009
|
-
}
|
|
1010
|
-
if (height !== void 0) {
|
|
1011
|
-
return [height, height];
|
|
1012
|
-
}
|
|
1013
|
-
return baseSize;
|
|
1014
|
-
}
|
|
1015
|
-
// Helper to determine label position and distance relative to shape BASED ON LOCATION
|
|
1016
|
-
static getLabelConfig(shape, location) {
|
|
1017
|
-
switch (location) {
|
|
1018
|
-
case "abovebar":
|
|
1019
|
-
return { position: "top", distance: 5 };
|
|
1020
|
-
case "belowbar":
|
|
1021
|
-
return { position: "bottom", distance: 5 };
|
|
1022
|
-
case "top":
|
|
1023
|
-
return { position: "bottom", distance: 5 };
|
|
1024
|
-
case "bottom":
|
|
1025
|
-
return { position: "top", distance: 5 };
|
|
1026
|
-
case "absolute":
|
|
1027
|
-
default:
|
|
1028
|
-
if (shape === "labelup" || shape === "labeldown") {
|
|
1029
|
-
return { position: "inside", distance: 0 };
|
|
1030
|
-
}
|
|
1031
|
-
return { position: "top", distance: 5 };
|
|
1032
|
-
}
|
|
1033
|
-
}
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
|
-
class ShapeRenderer {
|
|
1037
|
-
render(context) {
|
|
1038
|
-
const { seriesName, xAxisIndex, yAxisIndex, dataArray, colorArray, optionsArray, plotOptions, candlestickData } = context;
|
|
1039
|
-
const defaultColor = "#2962ff";
|
|
1040
|
-
const shapeData = dataArray.map((val, i) => {
|
|
1041
|
-
const pointOpts = optionsArray[i] || {};
|
|
1042
|
-
const globalOpts = plotOptions;
|
|
1043
|
-
const location = pointOpts.location || globalOpts.location || "absolute";
|
|
1044
|
-
if (location !== "absolute" && !val) {
|
|
1045
|
-
return null;
|
|
1046
|
-
}
|
|
1047
|
-
if (val === null || val === void 0) {
|
|
1048
|
-
return null;
|
|
1049
|
-
}
|
|
1050
|
-
const color = pointOpts.color || globalOpts.color || defaultColor;
|
|
1051
|
-
const shape = pointOpts.shape || globalOpts.shape || "circle";
|
|
1052
|
-
const size = pointOpts.size || globalOpts.size || "normal";
|
|
1053
|
-
const text = pointOpts.text || globalOpts.text;
|
|
1054
|
-
const textColor = pointOpts.textcolor || globalOpts.textcolor || "white";
|
|
1055
|
-
const width = pointOpts.width || globalOpts.width;
|
|
1056
|
-
const height = pointOpts.height || globalOpts.height;
|
|
1057
|
-
let yValue = val;
|
|
1058
|
-
let symbolOffset = [0, 0];
|
|
1059
|
-
if (location === "abovebar") {
|
|
1060
|
-
if (candlestickData && candlestickData[i]) {
|
|
1061
|
-
yValue = candlestickData[i].high;
|
|
1062
|
-
}
|
|
1063
|
-
symbolOffset = [0, "-150%"];
|
|
1064
|
-
} else if (location === "belowbar") {
|
|
1065
|
-
if (candlestickData && candlestickData[i]) {
|
|
1066
|
-
yValue = candlestickData[i].low;
|
|
1067
|
-
}
|
|
1068
|
-
symbolOffset = [0, "150%"];
|
|
1069
|
-
} else if (location === "top") {
|
|
1070
|
-
yValue = val;
|
|
1071
|
-
symbolOffset = [0, 0];
|
|
1072
|
-
} else if (location === "bottom") {
|
|
1073
|
-
yValue = val;
|
|
1074
|
-
symbolOffset = [0, 0];
|
|
1075
|
-
}
|
|
1076
|
-
const symbol = ShapeUtils.getShapeSymbol(shape);
|
|
1077
|
-
const symbolSize = ShapeUtils.getShapeSize(size, width, height);
|
|
1078
|
-
const rotate = ShapeUtils.getShapeRotation(shape);
|
|
1079
|
-
let finalSize = symbolSize;
|
|
1080
|
-
if (shape.includes("label")) {
|
|
1081
|
-
if (Array.isArray(symbolSize)) {
|
|
1082
|
-
finalSize = [symbolSize[0] * 2.5, symbolSize[1] * 2.5];
|
|
1083
|
-
} else {
|
|
1084
|
-
finalSize = symbolSize * 2.5;
|
|
1085
|
-
}
|
|
1086
|
-
}
|
|
1087
|
-
const labelConfig = ShapeUtils.getLabelConfig(shape, location);
|
|
1088
|
-
const item = {
|
|
1089
|
-
value: [i, yValue],
|
|
1090
|
-
symbol,
|
|
1091
|
-
symbolSize: finalSize,
|
|
1092
|
-
symbolRotate: rotate,
|
|
1093
|
-
symbolOffset,
|
|
1094
|
-
itemStyle: {
|
|
1095
|
-
color
|
|
1096
|
-
},
|
|
1097
|
-
label: {
|
|
1098
|
-
show: !!text,
|
|
1099
|
-
position: labelConfig.position,
|
|
1100
|
-
distance: labelConfig.distance,
|
|
1101
|
-
formatter: text,
|
|
1102
|
-
color: textColor,
|
|
1103
|
-
fontSize: 10,
|
|
1104
|
-
fontWeight: "bold"
|
|
1105
|
-
}
|
|
1106
|
-
};
|
|
1107
|
-
return item;
|
|
1108
|
-
}).filter((item) => item !== null);
|
|
1109
|
-
return {
|
|
1110
|
-
name: seriesName,
|
|
1111
|
-
type: "scatter",
|
|
1112
|
-
xAxisIndex,
|
|
1113
|
-
yAxisIndex,
|
|
1114
|
-
data: shapeData
|
|
1115
|
-
};
|
|
1116
|
-
}
|
|
1117
|
-
}
|
|
1118
|
-
|
|
1119
|
-
class BackgroundRenderer {
|
|
1120
|
-
render(context) {
|
|
1121
|
-
const { seriesName, xAxisIndex, yAxisIndex, dataArray, colorArray } = context;
|
|
1122
|
-
return {
|
|
1123
|
-
name: seriesName,
|
|
1124
|
-
type: "custom",
|
|
1125
|
-
xAxisIndex,
|
|
1126
|
-
yAxisIndex,
|
|
1127
|
-
z: -10,
|
|
1128
|
-
renderItem: (params, api) => {
|
|
1129
|
-
const xVal = api.value(0);
|
|
1130
|
-
if (isNaN(xVal))
|
|
1131
|
-
return;
|
|
1132
|
-
const start = api.coord([xVal, 0]);
|
|
1133
|
-
const size = api.size([1, 0]);
|
|
1134
|
-
const width = size[0];
|
|
1135
|
-
const sys = params.coordSys;
|
|
1136
|
-
const x = start[0] - width / 2;
|
|
1137
|
-
const barColor = colorArray[params.dataIndex];
|
|
1138
|
-
const val = api.value(1);
|
|
1139
|
-
if (!barColor || val === null || val === void 0 || isNaN(val))
|
|
1140
|
-
return;
|
|
1141
|
-
return {
|
|
1142
|
-
type: "rect",
|
|
1143
|
-
shape: {
|
|
1144
|
-
x,
|
|
1145
|
-
y: sys.y,
|
|
1146
|
-
width,
|
|
1147
|
-
height: sys.height
|
|
1148
|
-
},
|
|
1149
|
-
style: {
|
|
1150
|
-
fill: barColor,
|
|
1151
|
-
opacity: 0.3
|
|
1152
|
-
},
|
|
1153
|
-
silent: true
|
|
1154
|
-
};
|
|
1155
|
-
},
|
|
1156
|
-
data: dataArray.map((val, i) => [i, val])
|
|
1157
|
-
};
|
|
1158
|
-
}
|
|
1159
|
-
}
|
|
1160
|
-
|
|
1161
|
-
class ColorUtils {
|
|
1162
|
-
/**
|
|
1163
|
-
* Parse color string and extract opacity
|
|
1164
|
-
* Supports: hex (#RRGGBB), named colors (green, red), rgba(r,g,b,a), rgb(r,g,b)
|
|
1165
|
-
*/
|
|
1166
|
-
static parseColor(colorStr) {
|
|
1167
|
-
if (!colorStr) {
|
|
1168
|
-
return { color: "#888888", opacity: 0.2 };
|
|
1169
|
-
}
|
|
1170
|
-
const rgbaMatch = colorStr.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);
|
|
1171
|
-
if (rgbaMatch) {
|
|
1172
|
-
const r = rgbaMatch[1];
|
|
1173
|
-
const g = rgbaMatch[2];
|
|
1174
|
-
const b = rgbaMatch[3];
|
|
1175
|
-
const a = rgbaMatch[4] ? parseFloat(rgbaMatch[4]) : 1;
|
|
1176
|
-
return {
|
|
1177
|
-
color: `rgb(${r},${g},${b})`,
|
|
1178
|
-
opacity: a
|
|
1179
|
-
};
|
|
1180
|
-
}
|
|
1181
|
-
return {
|
|
1182
|
-
color: colorStr,
|
|
1183
|
-
opacity: 0.3
|
|
1184
|
-
};
|
|
1185
|
-
}
|
|
1186
|
-
}
|
|
1187
|
-
|
|
1188
|
-
class FillRenderer {
|
|
1189
|
-
render(context) {
|
|
1190
|
-
const { seriesName, xAxisIndex, yAxisIndex, plotOptions, plotDataArrays, indicatorId, plotName } = context;
|
|
1191
|
-
const totalDataLength = context.dataArray.length;
|
|
1192
|
-
const plot1Key = plotOptions.plot1 ? `${indicatorId}::${plotOptions.plot1}` : null;
|
|
1193
|
-
const plot2Key = plotOptions.plot2 ? `${indicatorId}::${plotOptions.plot2}` : null;
|
|
1194
|
-
if (!plot1Key || !plot2Key) {
|
|
1195
|
-
console.warn(`Fill plot "${plotName}" missing plot1 or plot2 reference`);
|
|
1196
|
-
return null;
|
|
1197
|
-
}
|
|
1198
|
-
const plot1Data = plotDataArrays?.get(plot1Key);
|
|
1199
|
-
const plot2Data = plotDataArrays?.get(plot2Key);
|
|
1200
|
-
if (!plot1Data || !plot2Data) {
|
|
1201
|
-
console.warn(`Fill plot "${plotName}" references non-existent plots: ${plotOptions.plot1}, ${plotOptions.plot2}`);
|
|
1202
|
-
return null;
|
|
1203
|
-
}
|
|
1204
|
-
const { color: fillColor, opacity: fillOpacity } = ColorUtils.parseColor(plotOptions.color || "rgba(128, 128, 128, 0.2)");
|
|
1205
|
-
const fillDataWithPrev = [];
|
|
1206
|
-
for (let i = 0; i < totalDataLength; i++) {
|
|
1207
|
-
const y1 = plot1Data[i];
|
|
1208
|
-
const y2 = plot2Data[i];
|
|
1209
|
-
const prevY1 = i > 0 ? plot1Data[i - 1] : null;
|
|
1210
|
-
const prevY2 = i > 0 ? plot2Data[i - 1] : null;
|
|
1211
|
-
fillDataWithPrev.push([i, y1, y2, prevY1, prevY2]);
|
|
1212
|
-
}
|
|
1213
|
-
return {
|
|
1214
|
-
name: seriesName,
|
|
1215
|
-
type: "custom",
|
|
1216
|
-
xAxisIndex,
|
|
1217
|
-
yAxisIndex,
|
|
1218
|
-
z: -5,
|
|
1219
|
-
// Render behind lines but above background
|
|
1220
|
-
renderItem: (params, api) => {
|
|
1221
|
-
const index = params.dataIndex;
|
|
1222
|
-
if (index === 0)
|
|
1223
|
-
return null;
|
|
1224
|
-
const y1 = api.value(1);
|
|
1225
|
-
const y2 = api.value(2);
|
|
1226
|
-
const prevY1 = api.value(3);
|
|
1227
|
-
const prevY2 = api.value(4);
|
|
1228
|
-
if (y1 === null || y2 === null || prevY1 === null || prevY2 === null || isNaN(y1) || isNaN(y2) || isNaN(prevY1) || isNaN(prevY2)) {
|
|
1229
|
-
return null;
|
|
1230
|
-
}
|
|
1231
|
-
const p1Prev = api.coord([index - 1, prevY1]);
|
|
1232
|
-
const p1Curr = api.coord([index, y1]);
|
|
1233
|
-
const p2Curr = api.coord([index, y2]);
|
|
1234
|
-
const p2Prev = api.coord([index - 1, prevY2]);
|
|
1235
|
-
return {
|
|
1236
|
-
type: "polygon",
|
|
1237
|
-
shape: {
|
|
1238
|
-
points: [
|
|
1239
|
-
p1Prev,
|
|
1240
|
-
// Top-left
|
|
1241
|
-
p1Curr,
|
|
1242
|
-
// Top-right
|
|
1243
|
-
p2Curr,
|
|
1244
|
-
// Bottom-right
|
|
1245
|
-
p2Prev
|
|
1246
|
-
// Bottom-left
|
|
1247
|
-
]
|
|
1248
|
-
},
|
|
1249
|
-
style: {
|
|
1250
|
-
fill: fillColor,
|
|
1251
|
-
opacity: fillOpacity
|
|
1252
|
-
},
|
|
1253
|
-
silent: true
|
|
1254
|
-
};
|
|
1255
|
-
},
|
|
1256
|
-
data: fillDataWithPrev
|
|
1257
|
-
};
|
|
1258
|
-
}
|
|
1259
|
-
}
|
|
1260
|
-
|
|
1261
|
-
var __defProp$9 = Object.defineProperty;
|
|
1262
|
-
var __defNormalProp$9 = (obj, key, value) => key in obj ? __defProp$9(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1263
|
-
var __publicField$9 = (obj, key, value) => {
|
|
1264
|
-
__defNormalProp$9(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1265
|
-
return value;
|
|
1266
|
-
};
|
|
1267
|
-
const _SeriesRendererFactory = class _SeriesRendererFactory {
|
|
1268
|
-
static register(style, renderer) {
|
|
1269
|
-
this.renderers.set(style, renderer);
|
|
1270
|
-
}
|
|
1271
|
-
static get(style) {
|
|
1272
|
-
return this.renderers.get(style) || this.renderers.get("line");
|
|
1273
|
-
}
|
|
1274
|
-
};
|
|
1275
|
-
__publicField$9(_SeriesRendererFactory, "renderers", /* @__PURE__ */ new Map());
|
|
1276
|
-
_SeriesRendererFactory.register("line", new LineRenderer());
|
|
1277
|
-
_SeriesRendererFactory.register("step", new StepRenderer());
|
|
1278
|
-
_SeriesRendererFactory.register("histogram", new HistogramRenderer());
|
|
1279
|
-
_SeriesRendererFactory.register("columns", new HistogramRenderer());
|
|
1280
|
-
_SeriesRendererFactory.register("circles", new ScatterRenderer());
|
|
1281
|
-
_SeriesRendererFactory.register("cross", new ScatterRenderer());
|
|
1282
|
-
_SeriesRendererFactory.register("char", new ScatterRenderer());
|
|
1283
|
-
_SeriesRendererFactory.register("bar", new OHLCBarRenderer());
|
|
1284
|
-
_SeriesRendererFactory.register("candle", new OHLCBarRenderer());
|
|
1285
|
-
_SeriesRendererFactory.register("shape", new ShapeRenderer());
|
|
1286
|
-
_SeriesRendererFactory.register("background", new BackgroundRenderer());
|
|
1287
|
-
_SeriesRendererFactory.register("fill", new FillRenderer());
|
|
1288
|
-
let SeriesRendererFactory = _SeriesRendererFactory;
|
|
1289
|
-
|
|
1290
|
-
var __defProp$8 = Object.defineProperty;
|
|
1291
|
-
var __defNormalProp$8 = (obj, key, value) => key in obj ? __defProp$8(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1292
|
-
var __publicField$8 = (obj, key, value) => {
|
|
1293
|
-
__defNormalProp$8(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1294
|
-
return value;
|
|
1295
|
-
};
|
|
1296
|
-
const _SeriesBuilder = class _SeriesBuilder {
|
|
1297
|
-
static buildCandlestickSeries(marketData, options, totalLength) {
|
|
1298
|
-
const upColor = options.upColor || "#00da3c";
|
|
1299
|
-
const downColor = options.downColor || "#ec0000";
|
|
1300
|
-
const data = marketData.map((d) => [d.open, d.close, d.low, d.high]);
|
|
1301
|
-
if (totalLength && totalLength > data.length) {
|
|
1302
|
-
const padding = totalLength - data.length;
|
|
1303
|
-
for (let i = 0; i < padding; i++) {
|
|
1304
|
-
data.push(null);
|
|
1305
|
-
}
|
|
1306
|
-
}
|
|
1307
|
-
let markLine = void 0;
|
|
1308
|
-
if (options.lastPriceLine?.visible !== false && marketData.length > 0) {
|
|
1309
|
-
const lastBar = marketData[marketData.length - 1];
|
|
1310
|
-
const lastClose = lastBar.close;
|
|
1311
|
-
const isUp = lastBar.close >= lastBar.open;
|
|
1312
|
-
const lineColor = options.lastPriceLine?.color || (isUp ? upColor : downColor);
|
|
1313
|
-
let lineStyleType = options.lastPriceLine?.lineStyle || "dashed";
|
|
1314
|
-
if (lineStyleType.startsWith("linestyle_")) {
|
|
1315
|
-
lineStyleType = lineStyleType.replace("linestyle_", "");
|
|
1316
|
-
}
|
|
1317
|
-
markLine = {
|
|
1318
|
-
symbol: ["none", "none"],
|
|
1319
|
-
data: [
|
|
1320
|
-
{
|
|
1321
|
-
yAxis: lastClose,
|
|
1322
|
-
label: {
|
|
1323
|
-
show: true,
|
|
1324
|
-
position: "end",
|
|
1325
|
-
// Right side
|
|
1326
|
-
formatter: (params) => {
|
|
1327
|
-
if (options.yAxisLabelFormatter) {
|
|
1328
|
-
return options.yAxisLabelFormatter(params.value);
|
|
1329
|
-
}
|
|
1330
|
-
const decimals = options.yAxisDecimalPlaces !== void 0 ? options.yAxisDecimalPlaces : 2;
|
|
1331
|
-
return typeof params.value === "number" ? params.value.toFixed(decimals) : params.value;
|
|
1332
|
-
},
|
|
1333
|
-
color: "#fff",
|
|
1334
|
-
backgroundColor: lineColor,
|
|
1335
|
-
padding: [2, 4],
|
|
1336
|
-
borderRadius: 2,
|
|
1337
|
-
fontSize: 11,
|
|
1338
|
-
fontWeight: "bold"
|
|
1339
|
-
},
|
|
1340
|
-
lineStyle: {
|
|
1341
|
-
color: lineColor,
|
|
1342
|
-
type: lineStyleType,
|
|
1343
|
-
width: 1,
|
|
1344
|
-
opacity: 0.8
|
|
1345
|
-
}
|
|
1346
|
-
}
|
|
1347
|
-
],
|
|
1348
|
-
animation: false,
|
|
1349
|
-
silent: true
|
|
1350
|
-
// Disable interaction
|
|
1351
|
-
};
|
|
1352
|
-
}
|
|
1353
|
-
return {
|
|
1354
|
-
type: "candlestick",
|
|
1355
|
-
name: options.title || "Market",
|
|
1356
|
-
data,
|
|
1357
|
-
itemStyle: {
|
|
1358
|
-
color: upColor,
|
|
1359
|
-
color0: downColor,
|
|
1360
|
-
borderColor: upColor,
|
|
1361
|
-
borderColor0: downColor
|
|
1362
|
-
},
|
|
1363
|
-
markLine,
|
|
1364
|
-
xAxisIndex: 0,
|
|
1365
|
-
yAxisIndex: 0,
|
|
1366
|
-
z: 5
|
|
1367
|
-
};
|
|
1368
|
-
}
|
|
1369
|
-
static buildIndicatorSeries(indicators, timeToIndex, paneLayout, totalDataLength, dataIndexOffset = 0, candlestickData, overlayYAxisMap, separatePaneYAxisOffset = 1) {
|
|
1370
|
-
const series = [];
|
|
1371
|
-
const barColors = new Array(totalDataLength).fill(null);
|
|
1372
|
-
const plotDataArrays = /* @__PURE__ */ new Map();
|
|
1373
|
-
indicators.forEach((indicator, id) => {
|
|
1374
|
-
if (indicator.collapsed)
|
|
1375
|
-
return;
|
|
1376
|
-
const sortedPlots = Object.keys(indicator.plots).sort((a, b) => {
|
|
1377
|
-
const plotA = indicator.plots[a];
|
|
1378
|
-
const plotB = indicator.plots[b];
|
|
1379
|
-
const isFillA = plotA.options.style === "fill";
|
|
1380
|
-
const isFillB = plotB.options.style === "fill";
|
|
1381
|
-
if (isFillA && !isFillB)
|
|
1382
|
-
return 1;
|
|
1383
|
-
if (!isFillA && isFillB)
|
|
1384
|
-
return -1;
|
|
1385
|
-
return 0;
|
|
1386
|
-
});
|
|
1387
|
-
sortedPlots.forEach((plotName) => {
|
|
1388
|
-
const plot = indicator.plots[plotName];
|
|
1389
|
-
const seriesName = `${id}::${plotName}`;
|
|
1390
|
-
let xAxisIndex = 0;
|
|
1391
|
-
let yAxisIndex = 0;
|
|
1392
|
-
const plotOverlay = plot.options.overlay;
|
|
1393
|
-
const isPlotOverlay = plotOverlay !== void 0 ? plotOverlay : indicator.paneIndex === 0;
|
|
1394
|
-
if (isPlotOverlay) {
|
|
1395
|
-
xAxisIndex = 0;
|
|
1396
|
-
if (overlayYAxisMap && overlayYAxisMap.has(seriesName)) {
|
|
1397
|
-
yAxisIndex = overlayYAxisMap.get(seriesName);
|
|
1398
|
-
} else {
|
|
1399
|
-
yAxisIndex = 0;
|
|
1400
|
-
}
|
|
1401
|
-
} else {
|
|
1402
|
-
const confIndex = paneLayout.findIndex((p) => p.index === indicator.paneIndex);
|
|
1403
|
-
if (confIndex !== -1) {
|
|
1404
|
-
xAxisIndex = confIndex + 1;
|
|
1405
|
-
yAxisIndex = separatePaneYAxisOffset + confIndex;
|
|
1406
|
-
}
|
|
1407
|
-
}
|
|
1408
|
-
const dataArray = new Array(totalDataLength).fill(null);
|
|
1409
|
-
const colorArray = new Array(totalDataLength).fill(null);
|
|
1410
|
-
const optionsArray = new Array(totalDataLength).fill(null);
|
|
1411
|
-
plot.data?.forEach((point) => {
|
|
1412
|
-
const index = timeToIndex.get(point.time);
|
|
1413
|
-
if (index !== void 0) {
|
|
1414
|
-
const plotOffset = point.options?.offset ?? plot.options.offset ?? 0;
|
|
1415
|
-
const offsetIndex = index + dataIndexOffset + plotOffset;
|
|
1416
|
-
if (offsetIndex >= 0 && offsetIndex < totalDataLength) {
|
|
1417
|
-
let value = point.value;
|
|
1418
|
-
const pointColor = point.options?.color;
|
|
1419
|
-
const isNaColor = pointColor === null || pointColor === "na" || pointColor === "NaN" || typeof pointColor === "number" && isNaN(pointColor);
|
|
1420
|
-
if (isNaColor) {
|
|
1421
|
-
value = null;
|
|
1422
|
-
}
|
|
1423
|
-
dataArray[offsetIndex] = value;
|
|
1424
|
-
colorArray[offsetIndex] = pointColor || plot.options.color || _SeriesBuilder.DEFAULT_COLOR;
|
|
1425
|
-
optionsArray[offsetIndex] = point.options || {};
|
|
1426
|
-
}
|
|
1427
|
-
}
|
|
1428
|
-
});
|
|
1429
|
-
plotDataArrays.set(`${id}::${plotName}`, dataArray);
|
|
1430
|
-
if (plot.options?.style?.startsWith("style_")) {
|
|
1431
|
-
plot.options.style = plot.options.style.replace("style_", "");
|
|
1432
|
-
}
|
|
1433
|
-
if (plot.options.style === "barcolor") {
|
|
1434
|
-
plot.data?.forEach((point) => {
|
|
1435
|
-
const index = timeToIndex.get(point.time);
|
|
1436
|
-
if (index !== void 0) {
|
|
1437
|
-
const plotOffset = point.options?.offset ?? plot.options.offset ?? 0;
|
|
1438
|
-
const offsetIndex = index + dataIndexOffset + plotOffset;
|
|
1439
|
-
if (offsetIndex >= 0 && offsetIndex < totalDataLength) {
|
|
1440
|
-
const pointColor = point.options?.color || plot.options.color || _SeriesBuilder.DEFAULT_COLOR;
|
|
1441
|
-
const isNaColor = pointColor === null || pointColor === "na" || pointColor === "NaN" || typeof pointColor === "number" && isNaN(pointColor);
|
|
1442
|
-
if (!isNaColor && point.value !== null && point.value !== void 0) {
|
|
1443
|
-
barColors[offsetIndex] = pointColor;
|
|
1444
|
-
}
|
|
1445
|
-
}
|
|
1446
|
-
}
|
|
1447
|
-
});
|
|
1448
|
-
return;
|
|
1449
|
-
}
|
|
1450
|
-
const renderer = SeriesRendererFactory.get(plot.options.style);
|
|
1451
|
-
const seriesConfig = renderer.render({
|
|
1452
|
-
seriesName,
|
|
1453
|
-
xAxisIndex,
|
|
1454
|
-
yAxisIndex,
|
|
1455
|
-
dataArray,
|
|
1456
|
-
colorArray,
|
|
1457
|
-
optionsArray,
|
|
1458
|
-
plotOptions: plot.options,
|
|
1459
|
-
candlestickData,
|
|
1460
|
-
plotDataArrays,
|
|
1461
|
-
indicatorId: id,
|
|
1462
|
-
plotName
|
|
1463
|
-
});
|
|
1464
|
-
if (seriesConfig) {
|
|
1465
|
-
series.push(seriesConfig);
|
|
1466
|
-
}
|
|
1467
|
-
});
|
|
1468
|
-
});
|
|
1469
|
-
return { series, barColors };
|
|
1470
|
-
}
|
|
1471
|
-
};
|
|
1472
|
-
__publicField$8(_SeriesBuilder, "DEFAULT_COLOR", "#2962ff");
|
|
1473
|
-
let SeriesBuilder = _SeriesBuilder;
|
|
1474
|
-
|
|
1475
|
-
class GraphicBuilder {
|
|
1476
|
-
static build(layout, options, onToggle, isMainCollapsed = false, maximizedPaneId = null) {
|
|
1477
|
-
const graphic = [];
|
|
1478
|
-
const pixelToPercent = layout.pixelToPercent;
|
|
1479
|
-
const mainPaneTop = layout.mainPaneTop;
|
|
1480
|
-
const showMain = !maximizedPaneId || maximizedPaneId === "main";
|
|
1481
|
-
if (showMain) {
|
|
1482
|
-
const titleTopMargin = 10 * pixelToPercent;
|
|
1483
|
-
graphic.push({
|
|
1484
|
-
type: "text",
|
|
1485
|
-
left: "8.5%",
|
|
1486
|
-
top: mainPaneTop + titleTopMargin + "%",
|
|
1487
|
-
z: 10,
|
|
1488
|
-
style: {
|
|
1489
|
-
text: options.title || "Market",
|
|
1490
|
-
fill: options.titleColor || "#fff",
|
|
1491
|
-
font: `bold 16px ${options.fontFamily || "sans-serif"}`,
|
|
1492
|
-
textVerticalAlign: "top"
|
|
1493
|
-
}
|
|
1494
|
-
});
|
|
1495
|
-
if (options.watermark !== false) {
|
|
1496
|
-
const bottomY = layout.mainPaneTop + layout.mainPaneHeight;
|
|
1497
|
-
graphic.push({
|
|
1498
|
-
type: "text",
|
|
1499
|
-
right: "11%",
|
|
1500
|
-
top: bottomY - 3 + "%",
|
|
1501
|
-
// Position 5% from bottom of main chart
|
|
1502
|
-
z: 10,
|
|
1503
|
-
style: {
|
|
1504
|
-
text: "QFChart",
|
|
1505
|
-
fill: options.fontColor || "#cbd5e1",
|
|
1506
|
-
font: `bold 16px sans-serif`,
|
|
1507
|
-
opacity: 0.1
|
|
1508
|
-
},
|
|
1509
|
-
cursor: "pointer",
|
|
1510
|
-
onclick: () => {
|
|
1511
|
-
window.open("https://quantforge.org", "_blank");
|
|
1512
|
-
}
|
|
1513
|
-
});
|
|
1514
|
-
}
|
|
1515
|
-
const controls = [];
|
|
1516
|
-
if (options.controls?.collapse) {
|
|
1517
|
-
controls.push({
|
|
1518
|
-
type: "group",
|
|
1519
|
-
children: [
|
|
1520
|
-
{
|
|
1521
|
-
type: "rect",
|
|
1522
|
-
shape: { width: 20, height: 20, r: 2 },
|
|
1523
|
-
style: { fill: "#334155", stroke: "#475569", lineWidth: 1 },
|
|
1524
|
-
onclick: () => onToggle("main", "collapse")
|
|
1525
|
-
},
|
|
1526
|
-
{
|
|
1527
|
-
type: "text",
|
|
1528
|
-
style: {
|
|
1529
|
-
text: isMainCollapsed ? "+" : "\u2212",
|
|
1530
|
-
fill: "#cbd5e1",
|
|
1531
|
-
font: `bold 14px ${options.fontFamily}`,
|
|
1532
|
-
x: 10,
|
|
1533
|
-
y: 10,
|
|
1534
|
-
textAlign: "center",
|
|
1535
|
-
textVerticalAlign: "middle"
|
|
1536
|
-
},
|
|
1537
|
-
silent: true
|
|
1538
|
-
}
|
|
1539
|
-
]
|
|
1540
|
-
});
|
|
1541
|
-
}
|
|
1542
|
-
if (options.controls?.maximize) {
|
|
1543
|
-
const isMaximized = maximizedPaneId === "main";
|
|
1544
|
-
const xOffset = options.controls?.collapse ? 25 : 0;
|
|
1545
|
-
controls.push({
|
|
1546
|
-
type: "group",
|
|
1547
|
-
x: xOffset,
|
|
1548
|
-
children: [
|
|
1549
|
-
{
|
|
1550
|
-
type: "rect",
|
|
1551
|
-
shape: { width: 20, height: 20, r: 2 },
|
|
1552
|
-
style: { fill: "#334155", stroke: "#475569", lineWidth: 1 },
|
|
1553
|
-
onclick: () => onToggle("main", "maximize")
|
|
1554
|
-
},
|
|
1555
|
-
{
|
|
1556
|
-
type: "text",
|
|
1557
|
-
style: {
|
|
1558
|
-
text: isMaximized ? "\u2750" : "\u25A1",
|
|
1559
|
-
// Simple chars for now
|
|
1560
|
-
fill: "#cbd5e1",
|
|
1561
|
-
font: `14px ${options.fontFamily}`,
|
|
1562
|
-
x: 10,
|
|
1563
|
-
y: 10,
|
|
1564
|
-
textAlign: "center",
|
|
1565
|
-
textVerticalAlign: "middle"
|
|
1566
|
-
},
|
|
1567
|
-
silent: true
|
|
1568
|
-
}
|
|
1569
|
-
]
|
|
1570
|
-
});
|
|
1571
|
-
}
|
|
1572
|
-
if (options.controls?.fullscreen) {
|
|
1573
|
-
let xOffset = 0;
|
|
1574
|
-
if (options.controls?.collapse)
|
|
1575
|
-
xOffset += 25;
|
|
1576
|
-
if (options.controls?.maximize)
|
|
1577
|
-
xOffset += 25;
|
|
1578
|
-
controls.push({
|
|
1579
|
-
type: "group",
|
|
1580
|
-
x: xOffset,
|
|
1581
|
-
children: [
|
|
1582
|
-
{
|
|
1583
|
-
type: "rect",
|
|
1584
|
-
shape: { width: 20, height: 20, r: 2 },
|
|
1585
|
-
style: { fill: "#334155", stroke: "#475569", lineWidth: 1 },
|
|
1586
|
-
onclick: () => onToggle("main", "fullscreen")
|
|
1587
|
-
},
|
|
1588
|
-
{
|
|
1589
|
-
type: "text",
|
|
1590
|
-
style: {
|
|
1591
|
-
text: "\u26F6",
|
|
1592
|
-
fill: "#cbd5e1",
|
|
1593
|
-
font: `14px ${options.fontFamily}`,
|
|
1594
|
-
x: 10,
|
|
1595
|
-
y: 10,
|
|
1596
|
-
textAlign: "center",
|
|
1597
|
-
textVerticalAlign: "middle"
|
|
1598
|
-
},
|
|
1599
|
-
silent: true
|
|
1600
|
-
}
|
|
1601
|
-
]
|
|
1602
|
-
});
|
|
1603
|
-
}
|
|
1604
|
-
if (controls.length > 0) {
|
|
1605
|
-
graphic.push({
|
|
1606
|
-
type: "group",
|
|
1607
|
-
right: "10.5%",
|
|
1608
|
-
top: mainPaneTop + "%",
|
|
1609
|
-
children: controls
|
|
1610
|
-
});
|
|
1611
|
-
}
|
|
1612
|
-
}
|
|
1613
|
-
layout.paneLayout.forEach((pane) => {
|
|
1614
|
-
if (maximizedPaneId && pane.indicatorId !== maximizedPaneId) {
|
|
1615
|
-
return;
|
|
1616
|
-
}
|
|
1617
|
-
graphic.push({
|
|
1618
|
-
type: "text",
|
|
1619
|
-
left: "8.5%",
|
|
1620
|
-
top: pane.top + 10 * pixelToPercent + "%",
|
|
1621
|
-
z: 10,
|
|
1622
|
-
style: {
|
|
1623
|
-
text: pane.indicatorId || "",
|
|
1624
|
-
fill: pane.titleColor || "#fff",
|
|
1625
|
-
font: `bold 12px ${options.fontFamily || "sans-serif"}`,
|
|
1626
|
-
textVerticalAlign: "top"
|
|
1627
|
-
}
|
|
1628
|
-
});
|
|
1629
|
-
const controls = [];
|
|
1630
|
-
if (pane.controls?.collapse) {
|
|
1631
|
-
controls.push({
|
|
1632
|
-
type: "group",
|
|
1633
|
-
children: [
|
|
1634
|
-
{
|
|
1635
|
-
type: "rect",
|
|
1636
|
-
shape: { width: 20, height: 20, r: 2 },
|
|
1637
|
-
style: { fill: "#334155", stroke: "#475569", lineWidth: 1 },
|
|
1638
|
-
onclick: () => pane.indicatorId && onToggle(pane.indicatorId, "collapse")
|
|
1639
|
-
},
|
|
1640
|
-
{
|
|
1641
|
-
type: "text",
|
|
1642
|
-
style: {
|
|
1643
|
-
text: pane.isCollapsed ? "+" : "\u2212",
|
|
1644
|
-
fill: "#cbd5e1",
|
|
1645
|
-
font: `bold 14px ${options.fontFamily}`,
|
|
1646
|
-
x: 10,
|
|
1647
|
-
y: 10,
|
|
1648
|
-
textAlign: "center",
|
|
1649
|
-
textVerticalAlign: "middle"
|
|
1650
|
-
},
|
|
1651
|
-
silent: true
|
|
1652
|
-
}
|
|
1653
|
-
]
|
|
1654
|
-
});
|
|
1655
|
-
}
|
|
1656
|
-
if (pane.controls?.maximize) {
|
|
1657
|
-
const isMaximized = maximizedPaneId === pane.indicatorId;
|
|
1658
|
-
const xOffset = pane.controls?.collapse ? 25 : 0;
|
|
1659
|
-
controls.push({
|
|
1660
|
-
type: "group",
|
|
1661
|
-
x: xOffset,
|
|
1662
|
-
children: [
|
|
1663
|
-
{
|
|
1664
|
-
type: "rect",
|
|
1665
|
-
shape: { width: 20, height: 20, r: 2 },
|
|
1666
|
-
style: { fill: "#334155", stroke: "#475569", lineWidth: 1 },
|
|
1667
|
-
onclick: () => pane.indicatorId && onToggle(pane.indicatorId, "maximize")
|
|
1668
|
-
},
|
|
1669
|
-
{
|
|
1670
|
-
type: "text",
|
|
1671
|
-
style: {
|
|
1672
|
-
text: isMaximized ? "\u2750" : "\u25A1",
|
|
1673
|
-
fill: "#cbd5e1",
|
|
1674
|
-
font: `14px ${options.fontFamily}`,
|
|
1675
|
-
x: 10,
|
|
1676
|
-
y: 10,
|
|
1677
|
-
textAlign: "center",
|
|
1678
|
-
textVerticalAlign: "middle"
|
|
1679
|
-
},
|
|
1680
|
-
silent: true
|
|
1681
|
-
}
|
|
1682
|
-
]
|
|
1683
|
-
});
|
|
1684
|
-
}
|
|
1685
|
-
if (controls.length > 0) {
|
|
1686
|
-
graphic.push({
|
|
1687
|
-
type: "group",
|
|
1688
|
-
right: "10.5%",
|
|
1689
|
-
top: pane.top + "%",
|
|
1690
|
-
children: controls
|
|
1691
|
-
});
|
|
1692
|
-
}
|
|
1693
|
-
});
|
|
1694
|
-
return graphic;
|
|
1695
|
-
}
|
|
1696
|
-
}
|
|
1697
|
-
|
|
1698
|
-
class TooltipFormatter {
|
|
1699
|
-
static format(params, options) {
|
|
1700
|
-
if (!params || params.length === 0)
|
|
1701
|
-
return "";
|
|
1702
|
-
const marketName = options.title || "Market";
|
|
1703
|
-
const upColor = options.upColor || "#00da3c";
|
|
1704
|
-
const downColor = options.downColor || "#ec0000";
|
|
1705
|
-
const fontFamily = options.fontFamily || "sans-serif";
|
|
1706
|
-
const date = params[0].axisValue;
|
|
1707
|
-
let html = `<div style="font-weight: bold; margin-bottom: 5px; color: #cbd5e1; font-family: ${fontFamily};">${date}</div>`;
|
|
1708
|
-
const marketSeries = params.find(
|
|
1709
|
-
(p) => p.seriesType === "candlestick"
|
|
1710
|
-
);
|
|
1711
|
-
const indicatorParams = params.filter(
|
|
1712
|
-
(p) => p.seriesType !== "candlestick"
|
|
1713
|
-
);
|
|
1714
|
-
if (marketSeries) {
|
|
1715
|
-
const [_, open, close, low, high] = marketSeries.value;
|
|
1716
|
-
const color = close >= open ? upColor : downColor;
|
|
1717
|
-
html += `
|
|
1718
|
-
<div style="margin-bottom: 8px; font-family: ${fontFamily};">
|
|
1719
|
-
<div style="display:flex; justify-content:space-between; color:${color}; font-weight:bold;">
|
|
1720
|
-
<span>${marketName}</span>
|
|
17
|
+
(function(T,Lt){typeof exports=="object"&&typeof module<"u"?Lt(exports,require("echarts")):typeof define=="function"&&define.amd?define(["exports","echarts"],Lt):(T=typeof globalThis<"u"?globalThis:T||self,Lt(T.QFChart={},T.echarts))})(this,function(T,Lt){"use strict";function ni(h){var t=Object.create(null);return h&&Object.keys(h).forEach(function(e){if(e!=="default"){var i=Object.getOwnPropertyDescriptor(h,e);Object.defineProperty(t,e,i.get?i:{enumerable:!0,get:function(){return h[e]}})}}),t.default=h,Object.freeze(t)}var _=ni(Lt),si=Object.defineProperty,oi=(h,t,e)=>t in h?si(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,Pt=(h,t,e)=>(oi(h,typeof t!="symbol"?t+"":t,e),e);class ri{constructor(t,e,i,n={}){Pt(this,"id"),Pt(this,"plots"),Pt(this,"paneIndex"),Pt(this,"height"),Pt(this,"collapsed"),Pt(this,"titleColor"),Pt(this,"controls"),this.id=t,this.plots=e,this.paneIndex=i,this.height=n.height,this.collapsed=n.collapsed||!1,this.titleColor=n.titleColor,this.controls=n.controls}toggleCollapse(){this.collapsed=!this.collapsed}isVisible(){return!this.collapsed}updateData(t){Object.keys(t).forEach(e=>{if(!this.plots[e])this.plots[e]=t[e];else{const i=this.plots[e],n=t[e];if(!i.data)return;n.options&&(i.options={...i.options,...n.options});const r=new Map;i.data?.forEach(s=>{r.set(s.time,s)}),n.data?.forEach(s=>{r.set(s.time,s)}),i.data=Array.from(r.values()).sort((s,l)=>s.time-l.time)}})}}class U{static createMinFunction(t){return e=>{const i=(e.max-e.min)*(t/100);return e.min-i}}static createMaxFunction(t){return e=>{const i=(e.max-e.min)*(t/100);return e.max+i}}static autoDetectDecimals(t){if(!t||t.length===0)return 2;const e=t[t.length-1].close;if(e===0||!isFinite(e)||isNaN(e))return 2;const i=Math.abs(e);if(i>=1)return 2;const n=Math.ceil(-Math.log10(i));return Math.min(n+4,10)}static formatValue(t,e){return typeof t=="number"?t.toFixed(e):String(t)}}class Qt{static calculate(t,e,i,n=!1,r=null,s,l){let a=0;t>0&&(a=1/t*100);const o=i.yAxisPadding!==void 0?i.yAxisPadding:5,c=i.grid?.show===!0,y=i.grid?.lineColor??"#334155",d=i.grid?.lineOpacity??.5,u=i.grid?.borderColor??"#334155",p=i.grid?.borderShow===!0,f=i.layout?.left??"10%",g=i.layout?.right??"10%",m=Array.from(e.values()).map(L=>L.paneIndex).filter(L=>L>0).sort((L,B)=>L-B).filter((L,B,J)=>J.indexOf(L)===B),x=m.length>0,P=i.dataZoom?.visible??!0,w=i.dataZoom?.position??"top",D=i.dataZoom?.height??6,S=i.dataZoom?.start??0,M=i.dataZoom?.end??100;let b=8,k=92,C=-1;if(r)if(r==="main")C=0;else{const L=e.get(r);L&&(C=L.paneIndex)}if(C!==-1){const L=[],B=[],J=[],Y=[],ct=i.dataZoom?.start??50,Et=i.dataZoom?.end??100;(i.dataZoom?.zoomOnTouch??!0)&&Y.push({type:"inside",xAxisIndex:"all",start:ct,end:Et,filterMode:"weakFilter"});const V=x?Math.max(...m):0,et=[];for(let j=0;j<=V;j++){const nt=j===C;L.push({left:f,right:g,top:nt?"5%":"0%",height:nt?"90%":"0%",show:nt,containLabel:!1}),B.push({type:"category",gridIndex:j,data:[],show:nt,axisLabel:{show:nt,color:"#94a3b8",fontFamily:i.fontFamily},axisLine:{show:nt&&p,lineStyle:{color:u}},splitLine:{show:nt&&c,lineStyle:{color:y,opacity:d}}});let Bt,jt;if(j===0&&C===0?(Bt=i.yAxisMin!==void 0&&i.yAxisMin!=="auto"?i.yAxisMin:U.createMinFunction(o),jt=i.yAxisMax!==void 0&&i.yAxisMax!=="auto"?i.yAxisMax:U.createMaxFunction(o)):(Bt=U.createMinFunction(o),jt=U.createMaxFunction(o)),J.push({position:"right",gridIndex:j,show:nt,scale:!0,min:Bt,max:jt,axisLabel:{show:nt,color:"#94a3b8",fontFamily:i.fontFamily,formatter:vt=>{if(i.yAxisLabelFormatter)return i.yAxisLabelFormatter(vt);const Yt=i.yAxisDecimalPlaces!==void 0?i.yAxisDecimalPlaces:U.autoDetectDecimals(s);return U.formatValue(vt,Yt)}},splitLine:{show:nt&&c,lineStyle:{color:y,opacity:d}}}),j>0){const vt=Array.from(e.values()).find(Yt=>Yt.paneIndex===j);vt&&et.push({index:j,height:nt?90:0,top:nt?5:0,isCollapsed:!1,indicatorId:vt.id,titleColor:vt.titleColor,controls:vt.controls})}}return{grid:L,xAxis:B,yAxis:J,dataZoom:Y,paneLayout:et,mainPaneHeight:C===0?90:0,mainPaneTop:C===0?5:0,pixelToPercent:a,overlayYAxisMap:new Map,separatePaneYAxisOffset:1}}P?w==="top"?(b=D+4,k=95):(k=100-D-2,b=8):(b=5,k=95);let A=5;t>0&&(A=20/t*100);let G=75,z;if(i.layout?.mainPaneHeight!==void 0){const L=i.layout.mainPaneHeight;if(typeof L=="string"){const B=parseFloat(L);isNaN(B)||(z=B)}else typeof L=="number"&&(z=L)}let $=[];if(x){const L=m.map(V=>{const et=Array.from(e.values()).find(j=>j.paneIndex===V);return{index:V,requestedHeight:et?.height,isCollapsed:et?.collapsed??!1,indicatorId:et?.id,titleColor:et?.titleColor,controls:et?.controls}}).map(V=>({...V,rawHeight:V.isCollapsed?3:V.requestedHeight!==void 0?V.requestedHeight:15})),B=k-b,J=L.length*A;if(l!==void 0&&l>0&&!n)G=l;else if(n)G=3;else if(z!==void 0&&z>0)G=z;else{const V=L.reduce((et,j)=>et+j.rawHeight,0);G=B-V-J,G<20&&(G=Math.max(G,10))}const Y=l!==void 0&&l>0&&!n||z!==void 0&&z>0&&!n;let ct;if(Y){const V=B-G-J,et=L.filter(j=>!j.isCollapsed).reduce((j,nt)=>j+nt.rawHeight,0);ct=L.map(j=>({...j,height:j.isCollapsed?3:et>0?Math.max(5,j.rawHeight/et*V):V/L.filter(nt=>!nt.isCollapsed).length}))}else ct=L.map(V=>({...V,height:V.rawHeight}));let Et=b+G+A;$=ct.map(V=>{const et={index:V.index,height:V.height,top:Et,isCollapsed:V.isCollapsed,indicatorId:V.indicatorId,titleColor:V.titleColor,controls:V.controls};return Et+=V.height+A,et})}else G=k-b,n&&(G=3);const v=[];if($.length>0){v.push({yPercent:b+G+A/2,aboveId:"main",belowId:$[0].indicatorId||""});for(let L=0;L<$.length-1;L++)v.push({yPercent:$[L].top+$[L].height+A/2,aboveId:$[L].indicatorId||"",belowId:$[L+1].indicatorId||""})}const E=[];E.push({left:f,right:g,top:b+"%",height:G+"%",containLabel:!1}),$.forEach(L=>{E.push({left:f,right:g,top:L.top+"%",height:L.height+"%",containLabel:!1})});const I=[0,...$.map((L,B)=>B+1)],N=[],F=$.length===0,Z=!n&&F;N.push({type:"category",data:[],gridIndex:0,scale:!0,axisLine:{onZero:!1,show:!n&&p,lineStyle:{color:u}},splitLine:{show:!n&&c,lineStyle:{color:y,opacity:d}},axisLabel:{show:Z,color:"#94a3b8",fontFamily:i.fontFamily||"sans-serif",formatter:L=>{if(i.yAxisLabelFormatter)return i.yAxisLabelFormatter(L);const B=i.yAxisDecimalPlaces!==void 0?i.yAxisDecimalPlaces:U.autoDetectDecimals(s);return U.formatValue(L,B)}},axisTick:{show:Z},axisPointer:{label:{show:F,fontSize:11,backgroundColor:"#475569"}}}),$.forEach((L,B)=>{const J=B===$.length-1,Y=J&&!L.isCollapsed;N.push({type:"category",gridIndex:B+1,data:[],axisLabel:{show:Y,color:"#94a3b8",fontFamily:i.fontFamily||"sans-serif"},axisLine:{show:!L.isCollapsed&&p,lineStyle:{color:u}},axisTick:{show:Y},splitLine:{show:!1},axisPointer:{label:{show:J,fontSize:11,backgroundColor:"#475569"}}})});const R=[];let H,q;i.yAxisMin!==void 0&&i.yAxisMin!=="auto"?H=i.yAxisMin:H=U.createMinFunction(o),i.yAxisMax!==void 0&&i.yAxisMax!=="auto"?q=i.yAxisMax:q=U.createMaxFunction(o),R.push({position:"right",scale:!0,min:H,max:q,gridIndex:0,splitLine:{show:!n&&c,lineStyle:{color:y,opacity:d}},axisLine:{show:!n&&p,lineStyle:{color:u}},axisLabel:{show:!n,color:"#94a3b8",fontFamily:i.fontFamily||"sans-serif",formatter:L=>{if(i.yAxisLabelFormatter)return i.yAxisLabelFormatter(L);const B=i.yAxisDecimalPlaces!==void 0?i.yAxisDecimalPlaces:U.autoDetectDecimals(s);return U.formatValue(L,B)}}});let X=1,rt=-1/0,tt=1/0;s&&s.length>0&&(rt=Math.min(...s.map(L=>L.low)),tt=Math.max(...s.map(L=>L.high)));const O=new Map;e.forEach((L,B)=>{L.paneIndex===0&&!L.collapsed&&s&&s.length>0&&Object.entries(L.plots).forEach(([J,Y])=>{const ct=`${B}::${J}`,Et=["background","barcolor"],V=(Y.options.style==="shape"||Y.options.style==="char")&&(Y.options.location==="abovebar"||Y.options.location==="AboveBar"||Y.options.location==="ab"||Y.options.location==="belowbar"||Y.options.location==="BelowBar"||Y.options.location==="bl"||Y.options.location==="absolute"||Y.options.location==="Absolute");if(Et.includes(Y.options.style)){O.has(ct)||(O.set(ct,X),X++);return}if((Y.options.style==="shape"||Y.options.style==="char")&&!V){O.has(ct)||(O.set(ct,X),X++);return}const et=[];if(Y.data&&Object.values(Y.data).forEach(j=>{typeof j=="number"&&!isNaN(j)&&isFinite(j)&&et.push(j)}),et.length>0){const j=Math.min(...et),nt=Math.max(...et),Bt=nt-j,jt=tt-rt,vt=j>=rt*.5&&nt<=tt*1.5,Yt=Bt>jt*.01;vt&&Yt||O.has(ct)||(O.set(ct,X),X++)}})});const Q=O.size>0?X-1:0,mt=new Set;O.forEach((L,B)=>{e.forEach(J=>{Object.entries(J.plots).forEach(([Y,ct])=>{`${J.id}::${Y}`===B&&["background","barcolor","char"].includes(ct.options.style)&&mt.add(L)})})});for(let L=0;L<Q;L++){const B=L+1,J=mt.has(B);R.push({position:"left",scale:!J,min:J?0:U.createMinFunction(o),max:J?1:U.createMaxFunction(o),gridIndex:0,show:!1,splitLine:{show:!1},axisLine:{show:!1},axisLabel:{show:!1}})}const Jt=X;$.forEach((L,B)=>{R.push({position:"right",scale:!0,min:U.createMinFunction(o),max:U.createMaxFunction(o),gridIndex:B+1,splitLine:{show:!L.isCollapsed&&c,lineStyle:{color:y,opacity:d*.6}},axisLabel:{show:!L.isCollapsed,color:"#94a3b8",fontFamily:i.fontFamily||"sans-serif",fontSize:10,formatter:J=>{if(i.yAxisLabelFormatter)return i.yAxisLabelFormatter(J);const Y=i.yAxisDecimalPlaces!==void 0?i.yAxisDecimalPlaces:U.autoDetectDecimals(s);return U.formatValue(J,Y)}},axisLine:{show:!L.isCollapsed&&p,lineStyle:{color:u}}})});const It=[],uo=i.dataZoom?.zoomOnTouch??!0,go=i.dataZoom?.pannable??!0;return uo&&go&&It.push({type:"inside",xAxisIndex:I,start:S,end:M,filterMode:"weakFilter"}),P&&(w==="top"?It.push({type:"slider",xAxisIndex:I,top:"1%",height:D+"%",start:S,end:M,borderColor:"#334155",textStyle:{color:"#cbd5e1"},brushSelect:!1,filterMode:"weakFilter"}):It.push({type:"slider",xAxisIndex:I,bottom:"1%",height:D+"%",start:S,end:M,borderColor:"#334155",textStyle:{color:"#cbd5e1"},brushSelect:!1,filterMode:"weakFilter"})),{grid:E,xAxis:N,yAxis:R,dataZoom:It,paneLayout:$,mainPaneHeight:G,mainPaneTop:b,pixelToPercent:a,paneBoundaries:v,overlayYAxisMap:O,separatePaneYAxisOffset:Jt}}static calculateMaximized(t,e,i){return{grid:[],xAxis:[],yAxis:[],dataZoom:[],paneLayout:[],mainPaneHeight:0,mainPaneTop:0,pixelToPercent:0,paneBoundaries:[]}}}class ai{render(t){const{seriesName:e,xAxisIndex:i,yAxisIndex:n,dataArray:r,colorArray:s,plotOptions:l}=t,a="#2962ff";return{name:e,type:"custom",xAxisIndex:i,yAxisIndex:n,renderItem:(o,c)=>{const y=o.dataIndex;if(y===0)return;const d=c.value(1),u=c.value(2);if(d===null||isNaN(d)||u===null||isNaN(u))return;const p=c.coord([y-1,u]),f=c.coord([y,d]);return{type:"line",shape:{x1:p[0],y1:p[1],x2:f[0],y2:f[1]},style:{stroke:s[y]||l.color||a,lineWidth:l.linewidth||1},silent:!0}},data:r.map((o,c)=>[c,o,c>0?r[c-1]:null])}}}class li{render(t){const{seriesName:e,xAxisIndex:i,yAxisIndex:n,dataArray:r,colorArray:s,plotOptions:l}=t,a="#2962ff";return{name:e,type:"custom",xAxisIndex:i,yAxisIndex:n,renderItem:(o,c)=>{const y=c.value(0),d=c.value(1);if(isNaN(d)||d===null)return;const u=c.coord([y,d]),p=c.size([1,0])[0];return{type:"line",shape:{x1:u[0]-p/2,y1:u[1],x2:u[0]+p/2,y2:u[1]},style:{stroke:s[o.dataIndex]||l.color||a,lineWidth:l.linewidth||1},silent:!0}},data:r.map((o,c)=>[c,o])}}}class ce{render(t){const{seriesName:e,xAxisIndex:i,yAxisIndex:n,dataArray:r,colorArray:s,plotOptions:l}=t,a="#2962ff",o=l.histbase??0,c=l.style==="columns",y=l.linewidth??1,d=r.map((u,p)=>u==null||typeof u=="number"&&isNaN(u)?null:[p,u,s[p]||l.color||a]);return{name:e,type:"custom",xAxisIndex:i,yAxisIndex:n,renderItem:(u,p)=>{const f=p.value(0),g=p.value(1),m=p.value(2);if(g==null||isNaN(g))return null;const x=p.coord([f,o]),P=p.coord([f,g]),w=p.size([1,0])[0];let D;c?D=w*.6:D=Math.max(1,y);const S=x[0],M=x[1],b=P[1],k=Math.min(M,b),C=Math.abs(b-M);return{type:"rect",shape:{x:S-D/2,y:k,width:D,height:C||1},style:{fill:m}}},data:d.filter(u=>u!==null)}}}const te=new Map;function de(h,t="#00da3c",e="64px"){if(typeof document>"u")return"";const i=`${h}-${t}-${e}`;if(te.has(i))return te.get(i);const n=document.createElement("canvas"),r=n.getContext("2d");if(n.width=32,n.height=32,r){r.font="bold "+e+" Arial",r.fillStyle=t,r.textAlign="center",r.textBaseline="middle",r.fillText(h,16,16);const s=n.toDataURL("image/png");return te.set(i,s),s}return""}class ee{render(t){const{seriesName:e,xAxisIndex:i,yAxisIndex:n,dataArray:r,colorArray:s,plotOptions:l}=t,a="#2962ff",o=l.style;if(o==="char"){const{optionsArray:y,candlestickData:d}=t,u=l.char||"\u2022",p=l.location||"abovebar",f=r.map((g,m)=>{if(g==null||typeof g=="number"&&isNaN(g))return null;const x=y?.[m]||{},P=x.char||u,w=x.color||s[m]||l.color||a,D=x.location||p,S=x.size||l.size||"normal";let M=g,b=[0,0];D==="abovebar"||D==="AboveBar"||D==="ab"?(d&&d[m]&&(M=d[m].high),b=[0,"-150%"]):(D==="belowbar"||D==="BelowBar"||D==="bl")&&(d&&d[m]&&(M=d[m].low),b=[0,"150%"]);const k={tiny:"18px",small:"26px",normal:"34px",large:"42px",huge:"54px",auto:"28px"}[S]||"34px";return{value:[m,M],symbol:`image://${de(P,w,k)}`,symbolSize:parseInt(k)+8,symbolOffset:b}}).filter(g=>g!==null);return{name:e,type:"scatter",xAxisIndex:i,yAxisIndex:n,z:10,data:f}}const c=r.map((y,d)=>{if(y===null)return null;const u=s[d]||l.color||a,p={value:[d,y],itemStyle:{color:u}};return o==="cross"?(p.symbol=`image://${de("+",u,"24px")}`,p.symbolSize=16):(p.symbol="circle",p.symbolSize=6),p}).filter(y=>y!==null);return{name:e,type:"scatter",xAxisIndex:i,yAxisIndex:n,data:c}}}class pe{render(t){const{seriesName:e,xAxisIndex:i,yAxisIndex:n,dataArray:r,colorArray:s,optionsArray:l,plotOptions:a}=t,o="#2962ff",c=a.style==="candle",y=[],d=r.map((u,p)=>{if(u===null||!Array.isArray(u)||u.length!==4)return null;const[f,g,m,x]=u,P=l[p]||{},w=P.color||s[p]||a.color||o,D=P.wickcolor||a.wickcolor||w,S=P.bordercolor||a.bordercolor||D;return y[p]={color:w,wickColor:D,borderColor:S},[p,f,x,m,g]}).filter(u=>u!==null);return{name:e,type:"custom",xAxisIndex:i,yAxisIndex:n,renderItem:(u,p)=>{const f=p.value(0),g=p.value(1),m=p.value(2),x=p.value(3),P=p.value(4);if(isNaN(g)||isNaN(m)||isNaN(x)||isNaN(P))return null;const w=y[f]||{color:o,wickColor:o,borderColor:o},D=w.color,S=w.wickColor,M=w.borderColor,b=p.coord([f,0])[0],k=p.coord([f,g])[1],C=p.coord([f,m])[1],A=p.coord([f,x])[1],G=p.coord([f,P])[1],z=p.size([1,0])[0]*.6;if(c){const $=Math.min(k,C),v=Math.max(k,C),E=Math.abs(C-k);return{type:"group",children:[{type:"line",shape:{x1:b,y1:G,x2:b,y2:$},style:{stroke:S,lineWidth:1}},{type:"line",shape:{x1:b,y1:v,x2:b,y2:A},style:{stroke:S,lineWidth:1}},{type:"rect",shape:{x:b-z/2,y:$,width:z,height:E||1},style:{fill:D,stroke:M,lineWidth:1}}]}}else{const $=z*.5;return{type:"group",children:[{type:"line",shape:{x1:b,y1:A,x2:b,y2:G},style:{stroke:D,lineWidth:1}},{type:"line",shape:{x1:b-$,y1:k,x2:b,y2:k},style:{stroke:D,lineWidth:1}},{type:"line",shape:{x1:b,y1:C,x2:b+$,y2:C},style:{stroke:D,lineWidth:1}}]}}},data:d}}}class At{static getShapeSymbol(t){switch(t){case"arrowdown":case"shape_arrow_down":return"path://M12 24l-12-12h8v-12h8v12h8z";case"arrowup":case"shape_arrow_up":return"path://M12 0l12 12h-8v12h-8v-12h-8z";case"circle":case"shape_circle":return"circle";case"cross":case"shape_cross":return"path://M11 2h2v9h9v2h-9v9h-2v-9h-9v-2h9z";case"diamond":case"shape_diamond":return"diamond";case"flag":case"shape_flag":return"path://M6 2v20h2v-8h12l-2-6 2-6h-12z";case"labeldown":case"shape_label_down":return"path://M2 1h20a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1h-8l-2 3-2-3h-8a1 1 0 0 1-1-1v-14a1 1 0 0 1 1-1z";case"labelleft":case"shape_label_left":return"path://M0 10l3-3v-5a1 1 0 0 1 1-1h18a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1h-18a1 1 0 0 1-1-1v-5z";case"labelright":case"shape_label_right":return"path://M24 10l-3-3v-5a1 1 0 0 0-1-1h-18a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h18a1 1 0 0 0 1-1v-5z";case"labelup":case"shape_label_up":return"path://M12 1l2 3h8a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1h-20a1 1 0 0 1-1-1v-14a1 1 0 0 1 1-1h8z";case"labelcenter":case"shape_label_center":return"path://M1 1h22a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1h-22a1 1 0 0 1-1-1v-16a1 1 0 0 1 1-1z";case"square":case"shape_square":return"rect";case"triangledown":case"shape_triangle_down":return"path://M12 21l-10-18h20z";case"triangleup":case"shape_triangle_up":return"triangle";case"xcross":case"shape_xcross":return"path://M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z";default:return"circle"}}static getShapeRotation(t){return 0}static getShapeSize(t,e,i){if(e!==void 0&&i!==void 0)return[e,i];let n;switch(t){case"tiny":n=8;break;case"small":n=12;break;case"normal":case"auto":n=16;break;case"large":n=24;break;case"huge":n=32;break;default:n=16}return e!==void 0?[e,e]:i!==void 0?[i,i]:n}static getLabelConfig(t,e){switch(e){case"abovebar":case"AboveBar":return{position:"top",distance:5};case"belowbar":case"BelowBar":return{position:"bottom",distance:5};case"top":case"Top":return{position:"bottom",distance:5};case"bottom":case"Bottom":return{position:"top",distance:5};case"absolute":case"Absolute":default:return t==="labelup"||t==="labeldown"||t==="shape_label_up"||t==="shape_label_down"?{position:"inside",distance:0}:{position:"top",distance:5}}}}class hi{render(t){const{seriesName:e,xAxisIndex:i,yAxisIndex:n,dataArray:r,colorArray:s,optionsArray:l,plotOptions:a,candlestickData:o}=t,c="#2962ff",y=r.map((d,u)=>{const p=l[u]||{},f=a,g=p.location||f.location||"absolute";if(g!=="absolute"&&g!=="Absolute"&&!d||d==null)return null;const m=p.color||f.color||c,x=p.shape||f.shape||"circle",P=p.size||f.size||"normal",w=p.text||f.text,D=p.textcolor||f.textcolor||"white",S=p.width||f.width,M=p.height||f.height;let b=d,k=[0,0];const C=x.includes("label_up")||x==="labelup",A=x.includes("label_down")||x==="labeldown";g==="abovebar"||g==="AboveBar"||g==="ab"?(o&&o[u]&&(b=o[u].high),k=[0,"-150%"]):g==="belowbar"||g==="BelowBar"||g==="bl"?(o&&o[u]&&(b=o[u].low),k=[0,"150%"]):g==="top"||g==="Top"?(b=d,k=[0,0]):(g==="bottom"||g==="Bottom")&&(b=d,k=[0,0]);const G=At.getShapeSymbol(x),z=At.getShapeSize(P,S,M),$=At.getShapeRotation(x);let v=z;x.includes("label")&&(Array.isArray(z)?v=[z[0]*2.5,z[1]*2.5]:v=z*2.5),C?k=[k[0],"50%"]:A&&(k=[k[0],"-50%"]);const E=At.getLabelConfig(x,g);return{value:[u,b],symbol:G,symbolSize:v,symbolRotate:$,symbolOffset:k,itemStyle:{color:m},label:{show:!!w,position:E.position,distance:E.distance,formatter:w,color:D,fontSize:10,fontWeight:"bold"}}}).filter(d=>d!==null);return{name:e,type:"scatter",xAxisIndex:i,yAxisIndex:n,z:10,data:y}}}class lt{static parseColor(t){if(!t||typeof t!="string")return{color:"#888888",opacity:.2};const e=t.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);if(e){const n=e[1],r=e[2],s=e[3],l=e[4]?parseFloat(e[4]):1;return{color:`rgb(${n},${r},${s})`,opacity:l}}const i=t.match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);if(i){const n=parseInt(i[1],16),r=parseInt(i[2],16),s=parseInt(i[3],16),l=parseInt(i[4],16)/255;return{color:`rgb(${n},${r},${s})`,opacity:l}}return{color:t,opacity:1}}static toRgba(t,e){const i=t.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/);if(i)return`rgba(${i[1]},${i[2]},${i[3]},${e})`;const n=t.match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);if(n){const s=parseInt(n[1],16),l=parseInt(n[2],16),a=parseInt(n[3],16);return`rgba(${s},${l},${a},${e})`}const r=t.match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);if(r){const s=parseInt(r[1],16),l=parseInt(r[2],16),a=parseInt(r[3],16);return`rgba(${s},${l},${a},${e})`}return t}static toRGB(t){const e=t.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/);if(e)return{r:+e[1],g:+e[2],b:+e[3]};const i=t.match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})/);return i?{r:parseInt(i[1],16),g:parseInt(i[2],16),b:parseInt(i[3],16)}:{r:128,g:128,b:128}}static interpolateColor(t,e,i,n,r){const s=this.toRGB(t),l=this.toRGB(i),a=Math.round(s.r+(l.r-s.r)*r),o=Math.round(s.g+(l.g-s.g)*r),c=Math.round(s.b+(l.b-s.b)*r),y=e+(n-e)*r;return`rgba(${a},${o},${c},${y})`}}class ci{render(t){const{seriesName:e,xAxisIndex:i,yAxisIndex:n,dataArray:r,colorArray:s}=t,l=[];for(let a=0;a<s.length;a++)l[a]=s[a]?lt.parseColor(s[a]):{color:"",opacity:0};return{name:e,type:"custom",xAxisIndex:i,yAxisIndex:n,z:-10,renderItem:(a,o)=>{const c=o.value(0);if(isNaN(c))return;const y=o.coord([c,.5]),d=o.size([1,0])[0],u=a.coordSys,p=y[0]-d/2,f=s[a.dataIndex],g=o.value(1);if(!f||g===null||g===void 0||isNaN(g))return;const m=l[a.dataIndex];if(!(!m||m.opacity<=0))return{type:"rect",shape:{x:p,y:u.y,width:d,height:u.height},style:{fill:m.color,opacity:m.opacity},silent:!0}},data:r.map((a,o)=>[o,a!=null&&!isNaN(a)?.5:null])}}}class ue{render(t){const{seriesName:e,xAxisIndex:i,yAxisIndex:n,plotOptions:r,plotDataArrays:s,indicatorId:l,plotName:a,optionsArray:o}=t,c=t.dataArray.length,y=r.plot1?`${l}::${r.plot1}`:null,d=r.plot2?`${l}::${r.plot2}`:null;if(!y||!d)return console.warn(`Fill plot "${a}" missing plot1 or plot2 reference`),null;const u=s?.get(y),p=s?.get(d);if(!u||!p)return console.warn(`Fill plot "${a}" references non-existent plots: ${r.plot1}, ${r.plot2}`),null;if(r.gradient===!0)return this.renderGradientFill(e,i,n,u,p,c,o,r);const{color:f,opacity:g}=lt.parseColor(r.color||"rgba(128, 128, 128, 0.2)"),m=o?.some(w=>w&&w.color!==void 0);let x=null;if(m){x=[];for(let w=0;w<c;w++){const D=o?.[w];D&&D.color!==void 0?x[w]=lt.parseColor(D.color):x[w]={color:f,opacity:g}}}const P=[];for(let w=0;w<c;w++){const D=u[w],S=p[w],M=w>0?u[w-1]:null,b=w>0?p[w-1]:null;P.push([w,D,S,M,b])}return{name:e,type:"custom",xAxisIndex:i,yAxisIndex:n,z:1,clip:!0,encode:{x:0},animation:!1,renderItem:(w,D)=>{const S=w.dataIndex;if(S===0)return null;const M=D.value(1),b=D.value(2),k=D.value(3),C=D.value(4);if(M===null||b===null||k===null||C===null||isNaN(M)||isNaN(b)||isNaN(k)||isNaN(C))return null;const A=x?x[S]:null,G=A?A.opacity:g;if(G<.01)return null;const z=A?A.color:f,$=k-C,v=M-b;if($>0&&v<0||$<0&&v>0){const Z=$/($-v),R=S-1+Z,H=k+Z*(M-k),q=D.coord([R,H]),X=D.coord([S-1,k]),rt=D.coord([S,M]),tt=D.coord([S,b]),O=D.coord([S-1,C]);return{type:"group",children:[{type:"polygon",shape:{points:[X,q,O]},style:{fill:z,opacity:G},silent:!0},{type:"polygon",shape:{points:[q,rt,tt]},style:{fill:z,opacity:G},silent:!0}],silent:!0}}const E=D.coord([S-1,k]),I=D.coord([S,M]),N=D.coord([S,b]),F=D.coord([S-1,C]);return{type:"polygon",shape:{points:[E,I,N,F]},style:{fill:z,opacity:G},silent:!0}},data:P,silent:!0}}renderBatched(t,e,i,n,r){const s=Array.from({length:n},(l,a)=>[a]);return{name:t,type:"custom",xAxisIndex:e,yAxisIndex:i,z:1,clip:!0,encode:{x:0},animation:!1,renderItem:(l,a)=>{const o=l.dataIndex;if(o===0)return null;const c=[];for(let y=0;y<r.length;y++){const d=r[y],u=d.plot1Data[o],p=d.plot2Data[o],f=d.plot1Data[o-1],g=d.plot2Data[o-1];if(u==null||p==null||f==null||g==null||isNaN(u)||isNaN(p)||isNaN(f)||isNaN(g))continue;const m=d.barColors[o];if(!m||m.opacity<.01)continue;const x={fill:m.color,opacity:m.opacity},P=f-g,w=u-p;if(P>0&&w<0||P<0&&w>0){const D=P/(P-w),S=o-1+D,M=f+D*(u-f),b=a.coord([S,M]),k=a.coord([o-1,f]),C=a.coord([o,u]),A=a.coord([o,p]),G=a.coord([o-1,g]);c.push({type:"polygon",shape:{points:[k,b,G]},style:x,silent:!0}),c.push({type:"polygon",shape:{points:[b,C,A]},style:x,silent:!0})}else{const D=a.coord([o-1,f]),S=a.coord([o,u]),M=a.coord([o,p]),b=a.coord([o-1,g]);c.push({type:"polygon",shape:{points:[D,S,M,b]},style:x,silent:!0})}}return c.length>0?{type:"group",children:c,silent:!0}:null},data:s,silent:!0}}renderGradientFill(t,e,i,n,r,s,l,a){const o=[],c=d=>!!(d==null||typeof d=="number"&&isNaN(d)||d==="na"||d==="NaN"||d==="");for(let d=0;d<s;d++){const u=l?.[d];if(u&&(u.top_color!==void 0||u.bottom_color!==void 0)){const p=c(u.top_color),f=c(u.bottom_color);if(p&&f){o[d]=null;continue}const g=p?{color:"rgba(0,0,0,0)",opacity:0}:lt.parseColor(u.top_color),m=f?{color:"rgba(0,0,0,0)",opacity:0}:lt.parseColor(u.bottom_color),x=u.top_value,P=u.bottom_value,w=x==null||typeof x=="number"&&isNaN(x)?null:x,D=P==null||typeof P=="number"&&isNaN(P)?null:P;if(w==null||D==null){o[d]=null;continue}o[d]={topValue:w,bottomValue:D,topColor:g.color,topOpacity:g.opacity,bottomColor:m.color,bottomOpacity:m.opacity,topIsNa:p,btmIsNa:f}}else o[d]=null}const y=[];for(let d=0;d<s;d++){const u=n[d],p=r[d],f=d>0?n[d-1]:null,g=d>0?r[d-1]:null;y.push([d,u,p,f,g])}return{name:t,type:"custom",xAxisIndex:e,yAxisIndex:i,z:1,clip:!0,encode:{x:0},animation:!1,renderItem:(d,u)=>{const p=d.dataIndex;if(p===0)return null;const f=u.value(1),g=u.value(2),m=u.value(3),x=u.value(4);if(f==null||g==null||m==null||x==null||isNaN(f)||isNaN(g)||isNaN(m)||isNaN(x))return null;const P=o[p];if(!P)return null;const w=P.topValue-P.bottomValue,D=P.topIsNa||P.btmIsNa,S=$=>{let v;return Math.abs(w)<1e-10?v=.5:v=1-($-P.bottomValue)/w,v=Math.max(0,Math.min(1,v)),P.topIsNa?lt.toRgba(P.bottomColor,P.bottomOpacity*v):P.btmIsNa?lt.toRgba(P.topColor,P.topOpacity*(1-v)):lt.interpolateColor(P.topColor,P.topOpacity,P.bottomColor,P.bottomOpacity,v)},M=u.coord([p-1,m]),b=u.coord([p,f]),k=u.coord([p,g]),C=u.coord([p-1,x]),A=Math.max(f,g,m,x),G=Math.min(f,g,m,x),z={type:"polygon",shape:{points:[M,b,k,C]},style:{fill:{type:"linear",x:0,y:0,x2:0,y2:1,colorStops:[{offset:0,color:S(A)},{offset:1,color:S(G)}]}},silent:!0};if(D){const $=d.coordSys,v=u.coord([p-1,x])[1],E=u.coord([p,g])[1],I=(v+E)/2;let N,F;return P.btmIsNa?(N=$.y,F=I-$.y):(N=I,F=$.y+$.height-I),F<=0?null:{type:"group",children:[z],clipPath:{type:"rect",shape:{x:$.x,y:N,width:$.width,height:F}},silent:!0}}return z},data:y,silent:!0}}}function yt(h,t,e,i,n){if(!t||t==="bar_index"||t==="bi")return h+e;if(i){const r=i.get(h);if(r!==void 0)return r+e}if(n&&n.length>=2){const r=n[n.length-1].time,s=n.length-1;if(h>r){const l=n[n.length-2].time,a=r-l;if(a>0){const o=(h-r)/a;return s+o+e}}else if(h<n[0].time){const l=n[0].time,a=n[1].time-l;if(a>0)return 0-(l-h)/a+e}else{let l=0,a=n.length-1;for(;l<a;){const o=l+a>>1;n[o].time<h?l=o+1:a=o}if(l>0){const o=n[l-1].time,c=n[l].time,y=(h-o)/(c-o);return l-1+y+e}return l+e}}return NaN}class di{render(t){const{seriesName:e,xAxisIndex:i,yAxisIndex:n,dataArray:r,candlestickData:s,dataIndexOffset:l,timeToIndex:a,marketData:o}=t,c=l||0,y=[];for(let u=0;u<r.length;u++){const p=r[u];if(!p)continue;const f=Array.isArray(p)?p:[p];for(const g of f)g&&typeof g=="object"&&!g._deleted&&y.push(g)}const d=y.map(u=>{const p=R=>typeof R=="function"?R():R,f=p(u.text)||"",g=p(u.color),m=g!=null&&g!==""?g:"transparent",x=p(u.textcolor)||"#ffffff",P=p(u.yloc)||"price",w=p(u.style)||"style_label_down",D=p(u.size)||"normal",S=p(u.textalign)||"align_center",M=p(u.tooltip)||"",b=this.styleToShape(w),k=yt(u.x,u.xloc,c,a,o);if(isNaN(k))return null;let C=u.y,A=[0,0];P==="abovebar"||P==="AboveBar"||P==="ab"?(s&&s[k]&&(C=s[k].high),A=[0,"-150%"]):(P==="belowbar"||P==="BelowBar"||P==="bl")&&(s&&s[k]&&(C=s[k].low),A=[0,"150%"]);const G=At.getShapeSymbol(b),z=At.getShapeSize(D),$=this.getSizePx(D);let v;const E=b==="labeldown"||b==="shape_label_down"||b==="labelup"||b==="shape_label_up"||b==="labelleft"||b==="labelright";let I=[0,0];if(E){const R=f.split(`
|
|
18
|
+
`),H=R.reduce((Q,mt)=>Q.length>mt.length?Q:mt,"").length*$*.65,q=$*2.5,X=Math.max(q,H+$*1.6),rt=$*1.4,tt=Math.max($*2.8,R.length*rt+$*1.2),O=3/24;if(b==="labelleft"||b==="labelright"){const Q=X/(1-O);v=[Q,tt];const mt=typeof A[0]=="string"?0:A[0];b==="labelleft"?(A=[mt+Q*.42,A[1]],I=[Q*O*.5,0]):(A=[mt-Q*.42,A[1]],I=[-Q*O*.5,0])}else{const Q=tt/(1-O);v=[X,Q],b==="labeldown"?(A=[A[0],typeof A[1]=="string"?A[1]:A[1]-Q*.42],I=[0,-Q*O*.5]):(A=[A[0],typeof A[1]=="string"?A[1]:A[1]+Q*.42],I=[0,Q*O*.5])}}else if(b==="labelcenter"){const R=f.split(`
|
|
19
|
+
`),H=R.reduce((O,Q)=>O.length>Q.length?O:Q,"").length*$*.65,q=$*2.5,X=Math.max(q,H+$*1.6),rt=$*1.4,tt=Math.max($*2.8,R.length*rt+$*1.2);v=[X,tt]}else b==="none"?v=0:Array.isArray(z)?v=[z[0]*1.5,z[1]*1.5]:v=z*1.5;const N=this.getLabelPosition(w,P),F=N==="inside"||N.startsWith("inside"),Z={value:[k,C],symbol:G,symbolSize:v,symbolOffset:A,itemStyle:{color:m},label:{show:!!f,position:N,distance:F?0:5,offset:I,formatter:f,color:x,fontSize:$,fontWeight:"bold",align:F?"center":S==="align_left"||S==="left"?"left":S==="align_right"||S==="right"?"right":"center",verticalAlign:"middle",padding:[2,6]}};return M?(Z._tooltipText=M,Z.emphasis={scale:!1,itemStyle:{color:m},label:{show:Z.label.show,color:x,fontSize:$,fontWeight:"bold"}}):Z.emphasis={disabled:!0},Z}).filter(u=>u!==null);return{name:e,type:"scatter",xAxisIndex:i,yAxisIndex:n,data:d,z:20,animation:!1,clip:!1}}styleToShape(t){switch(t.startsWith("style_")?t.substring(6):t){case"label_down":return"labeldown";case"label_up":return"labelup";case"label_left":return"labelleft";case"label_right":return"labelright";case"label_lower_left":return"labeldown";case"label_lower_right":return"labeldown";case"label_upper_left":return"labelup";case"label_upper_right":return"labelup";case"label_center":return"labelcenter";case"circle":return"circle";case"square":return"square";case"diamond":return"diamond";case"flag":return"flag";case"arrowup":return"arrowup";case"arrowdown":return"arrowdown";case"cross":return"cross";case"xcross":return"xcross";case"triangleup":return"triangleup";case"triangledown":return"triangledown";case"text_outline":return"none";case"none":return"none";default:return"labeldown"}}getLabelPosition(t,e){switch(t.startsWith("style_")?t.substring(6):t){case"label_down":case"label_up":case"label_left":case"label_right":case"label_lower_left":case"label_lower_right":case"label_upper_left":case"label_upper_right":case"label_center":return"inside";case"text_outline":case"none":return e==="abovebar"||e==="AboveBar"||e==="ab"?"top":e==="belowbar"||e==="BelowBar"||e==="bl"?"bottom":"top";default:return e==="belowbar"||e==="BelowBar"||e==="bl"?"bottom":"top"}}getSizePx(t){switch(t){case"tiny":return 8;case"small":return 11;case"normal":case"auto":return 14;case"large":return 20;case"huge":return 36;default:return 14}}}class pi{render(t){const{seriesName:e,xAxisIndex:i,yAxisIndex:n,dataArray:r,dataIndexOffset:s,timeToIndex:l,marketData:a}=t,o=s||0,c="#2962ff",y=[];for(let p=0;p<r.length;p++){const f=r[p];if(!f)continue;const g=Array.isArray(f)?f:[f];for(const m of g)m&&typeof m=="object"&&!m._deleted&&y.push(m)}if(y.length===0)return{name:e,type:"custom",xAxisIndex:i,yAxisIndex:n,data:[],silent:!0};const d=(t.candlestickData?.length||0)+o,u=Math.max(0,d-1);return{name:e,type:"custom",xAxisIndex:i,yAxisIndex:n,renderItem:(p,f)=>{const g=[];for(const m of y){if(m._deleted)continue;const x=yt(m.x1,m.xloc,o,l,a),P=yt(m.x2,m.xloc,o,l,a);if(isNaN(x)||isNaN(P))continue;let w=f.coord([x,m.y1]),D=f.coord([P,m.y2]);const S=m.extend||"none";if(S!=="none"&&S!=="n"){const C=p.coordSys;[w,D]=this.extendLine(w,D,S,C.x,C.x+C.width,C.y,C.y+C.height)}const M=m.color||c,b=m.width||1;g.push({type:"line",shape:{x1:w[0],y1:w[1],x2:D[0],y2:D[1]},style:{fill:"none",stroke:M,lineWidth:b,lineDash:this.getDashPattern(m.style)}});const k=m.style||"style_solid";if(k==="style_arrow_left"||k==="style_arrow_both"){const C=this.arrowHead(D,w,b,M);C&&g.push(C)}if(k==="style_arrow_right"||k==="style_arrow_both"){const C=this.arrowHead(w,D,b,M);C&&g.push(C)}}return{type:"group",children:g}},data:[[0,u]],clip:!0,encode:{x:[0,1]},itemStyle:{color:"transparent",borderColor:"transparent"},z:15,silent:!0,emphasis:{disabled:!0}}}getDashPattern(t){switch(t){case"style_dotted":return[2,2];case"style_dashed":return[6,4];default:return}}extendLine(t,e,i,n,r,s,l){const a=e[0]-t[0],o=e[1]-t[1];if(a===0&&o===0)return[t,e];const c=(u,p)=>{let f=1/0;if(p[0]!==0){const g=p[0]>0?(r-u[0])/p[0]:(n-u[0])/p[0];f=Math.min(f,g)}if(p[1]!==0){const g=p[1]>0?(l-u[1])/p[1]:(s-u[1])/p[1];f=Math.min(f,g)}return isFinite(f)||(f=0),[u[0]+f*p[0],u[1]+f*p[1]]};let y=t,d=e;return(i==="right"||i==="r"||i==="both"||i==="b")&&(d=c(t,[a,o])),(i==="left"||i==="l"||i==="both"||i==="b")&&(y=c(e,[-a,-o])),[y,d]}arrowHead(t,e,i,n){const r=e[0]-t[0],s=e[1]-t[1],l=Math.sqrt(r*r+s*s);if(l<1)return null;const a=Math.max(8,i*4),o=r/l,c=s/l,y=e[0]-o*a,d=e[1]-c*a,u=-c*a*.4,p=o*a*.4;return{type:"polygon",shape:{points:[[e[0],e[1]],[y+u,d+p],[y-u,d-p]]},style:{fill:n}}}}class ui{render(t){const{seriesName:e,xAxisIndex:i,yAxisIndex:n,dataArray:r,dataIndexOffset:s,timeToIndex:l,marketData:a}=t,o=s||0,c=[];for(let u=0;u<r.length;u++){const p=r[u];if(!p)continue;const f=Array.isArray(p)?p:[p];for(const g of f){if(!g||typeof g!="object"||g._deleted)continue;const m=g.line1,x=g.line2;!m||!x||m._deleted||x._deleted||c.push(g)}}if(c.length===0)return{name:e,type:"custom",xAxisIndex:i,yAxisIndex:n,data:[],silent:!0};const y=(t.candlestickData?.length||0)+o,d=Math.max(0,y-1);return{name:e,type:"custom",xAxisIndex:i,yAxisIndex:n,renderItem:(u,p)=>{const f=[];for(const g of c){if(g._deleted)continue;const m=g.line1,x=g.line2;if(!m||!x||m._deleted||x._deleted)continue;const P=yt(m.x1,m.xloc,o,l,a),w=yt(m.x2,m.xloc,o,l,a),D=yt(x.x1,x.xloc,o,l,a),S=yt(x.x2,x.xloc,o,l,a);if(isNaN(P)||isNaN(w)||isNaN(D)||isNaN(S))continue;let M=p.coord([P,m.y1]),b=p.coord([w,m.y2]),k=p.coord([D,x.y1]),C=p.coord([S,x.y2]);const A=m.extend||"none",G=x.extend||"none";if(A!=="none"||G!=="none"){const v=u.coordSys,E=v.x,I=v.x+v.width,N=v.y,F=v.y+v.height;A!=="none"&&([M,b]=this.extendLine(M,b,A,E,I,N,F)),G!=="none"&&([k,C]=this.extendLine(k,C,G,E,I,N,F))}const{color:z,opacity:$}=lt.parseColor(g.color||"rgba(128, 128, 128, 0.2)");f.push({type:"polygon",shape:{points:[M,b,C,k]},style:{fill:z,opacity:$},silent:!0})}return{type:"group",children:f}},data:[[0,d]],clip:!0,encode:{x:[0,1]},z:10,silent:!0,emphasis:{disabled:!0}}}extendLine(t,e,i,n,r,s,l){const a=e[0]-t[0],o=e[1]-t[1];if(a===0&&o===0)return[t,e];const c=(u,p)=>{let f=1/0;if(p[0]!==0){const g=p[0]>0?(r-u[0])/p[0]:(n-u[0])/p[0];f=Math.min(f,g)}if(p[1]!==0){const g=p[1]>0?(l-u[1])/p[1]:(s-u[1])/p[1];f=Math.min(f,g)}return isFinite(f)||(f=0),[u[0]+f*p[0],u[1]+f*p[1]]};let y=t,d=e;return(i==="right"||i==="both")&&(d=c(t,[a,o])),(i==="left"||i==="both")&&(y=c(e,[-a,-o])),[y,d]}}class gi{render(t){const{seriesName:e,xAxisIndex:i,yAxisIndex:n,dataArray:r,dataIndexOffset:s,timeToIndex:l,marketData:a}=t,o=s||0,c=[];for(let u=0;u<r.length;u++){const p=r[u];if(!p)continue;const f=Array.isArray(p)?p:[p];for(const g of f)g&&typeof g=="object"&&!g._deleted&&g.points&&g.points.length>=2&&c.push(g)}if(c.length===0)return{name:e,type:"custom",xAxisIndex:i,yAxisIndex:n,data:[],silent:!0};const y=(t.candlestickData?.length||0)+o,d=Math.max(0,y-1);return{name:e,type:"custom",xAxisIndex:i,yAxisIndex:n,renderItem:(u,p)=>{const f=[];for(const g of c){if(g._deleted)continue;const m=g.points;if(!m||m.length<2)continue;const x=g.xloc==="bi"||g.xloc==="bar_index",P=[];let w=!1;for(const k of m){let C;if(x){const G=k.index;if(G==null||typeof G=="number"&&isNaN(G)){w=!0;break}C=G+o}else if(C=yt(k.time??0,"bt",o,l,a),isNaN(C)){w=!0;break}const A=k.price??0;P.push(p.coord([C,A]))}if(w||P.length<2)continue;const D=g.line_color,S=D==null||typeof D=="number"&&isNaN(D)||D==="na"||D==="NaN"?null:D||"#2962ff",M=g.line_width||1,b=this.getDashPattern(g.line_style);if(g.fill_color&&g.fill_color!==""&&g.fill_color!=="na"){const{color:k,opacity:C}=lt.parseColor(g.fill_color);if(g.curved){const A=this.buildCurvedPath(P,g.closed);f.push({type:"path",shape:{pathData:A+" Z"},style:{fill:k,opacity:C,stroke:"none"},silent:!0})}else f.push({type:"polygon",shape:{points:P},style:{fill:k,opacity:C,stroke:"none"},silent:!0})}if(S&&M>0)if(g.curved){const k=this.buildCurvedPath(P,g.closed);f.push({type:"path",shape:{pathData:k},style:{fill:"none",stroke:S,lineWidth:M,lineDash:b},silent:!0})}else{const k=g.closed?[...P,P[0]]:P;f.push({type:"polyline",shape:{points:k},style:{fill:"none",stroke:S,lineWidth:M,lineDash:b},silent:!0})}}return{type:"group",children:f}},data:[[0,d]],clip:!0,encode:{x:[0,1]},itemStyle:{color:"transparent",borderColor:"transparent"},z:15,silent:!0,emphasis:{disabled:!0}}}buildCurvedPath(t,e){const i=t.length;if(i<2)return"";if(i===2)return`M ${t[0][0]} ${t[0][1]} L ${t[1][0]} ${t[1][1]}`;const n=.5;let r=`M ${t[0][0]} ${t[0][1]}`;const s=a=>e?t[(a%i+i)%i]:a<0?t[0]:a>=i?t[i-1]:t[a],l=e?i:i-1;for(let a=0;a<l;a++){const o=s(a-1),c=s(a),y=s(a+1),d=s(a+2),u=c[0]+(y[0]-o[0])*n/3,p=c[1]+(y[1]-o[1])*n/3,f=y[0]-(d[0]-c[0])*n/3,g=y[1]-(d[1]-c[1])*n/3;r+=` C ${u} ${p}, ${f} ${g}, ${y[0]} ${y[1]}`}return e&&(r+=" Z"),r}getDashPattern(t){switch(t){case"style_dotted":return[2,2];case"style_dashed":return[6,4];default:return}}}function ie(h){if(!h||typeof h!="string")return h;if(h.startsWith("#")){const t=h.slice(1);if(t.length===8){const e=parseInt(t.slice(0,2),16),i=parseInt(t.slice(2,4),16),n=parseInt(t.slice(4,6),16),r=parseInt(t.slice(6,8),16)/255;return`rgba(${e},${i},${n},${r.toFixed(3)})`}}return h}function yi(h){if(!h||typeof h!="string")return null;if(h.startsWith("#")){const e=h.slice(1);if(e.length>=6){const i=parseInt(e.slice(0,2),16),n=parseInt(e.slice(2,4),16),r=parseInt(e.slice(4,6),16);if(!isNaN(i)&&!isNaN(n)&&!isNaN(r))return{r:i,g:n,b:r}}if(e.length===3){const i=parseInt(e[0]+e[0],16),n=parseInt(e[1]+e[1],16),r=parseInt(e[2]+e[2],16);if(!isNaN(i)&&!isNaN(n)&&!isNaN(r))return{r:i,g:n,b:r}}return null}const t=h.match(/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/);return t?{r:+t[1],g:+t[2],b:+t[3]}:null}function fi(h,t,e){return(.299*h+.587*t+.114*e)/255}class xi{render(t){const{seriesName:e,xAxisIndex:i,yAxisIndex:n,dataArray:r,dataIndexOffset:s,timeToIndex:l,marketData:a}=t,o=s||0,c=[];for(let u=0;u<r.length;u++){const p=r[u];if(!p)continue;const f=Array.isArray(p)?p:[p];for(const g of f)g&&typeof g=="object"&&!g._deleted&&c.push(g)}if(c.length===0)return{name:e,type:"custom",xAxisIndex:i,yAxisIndex:n,data:[],silent:!0};const y=(t.candlestickData?.length||0)+o,d=Math.max(0,y-1);return{name:e,type:"custom",xAxisIndex:i,yAxisIndex:n,renderItem:(u,p)=>{const f=[];for(const g of c){if(g._deleted)continue;const m=yt(g.left,g.xloc,o,l,a),x=yt(g.right,g.xloc,o,l,a);if(isNaN(m)||isNaN(x))continue;const P=p.coord([m,g.top]),w=p.coord([x,g.bottom]);let D=P[0],S=P[1],M=w[0]-P[0],b=w[1]-P[1];const k=g.extend||"none";if(k!=="none"&&k!=="n"){const v=u.coordSys;(k==="left"||k==="l"||k==="both"||k==="b")&&(D=v.x,M=k==="both"||k==="b"?v.width:w[0]-v.x),(k==="right"||k==="r"||k==="both"||k==="b")&&(k==="right"||k==="r")&&(M=v.x+v.width-P[0])}const C=g.bgcolor,A=C==null||typeof C=="number"&&isNaN(C)||C==="na"||C==="NaN"||C===""?null:ie(C)||"#2962ff";A&&f.push({type:"rect",shape:{x:D,y:S,width:M,height:b},style:{fill:A,stroke:"none"}});const G=g.border_color,z=G==null||typeof G=="number"&&isNaN(G)||G==="na"||G==="NaN"?null:ie(G)||"#2962ff",$=g.border_width??1;if($>0&&z&&f.push({type:"rect",shape:{x:D,y:S,width:M,height:b},style:{fill:"none",stroke:z,lineWidth:$,lineDash:this.getDashPattern(g.border_style)}}),g.text){const v=this.getTextX(D,M,g.text_halign),E=this.getTextY(S,b,g.text_valign);let I=ie(g.text_color)||"#000000";if((!g.text_color||g.text_color==="#000000"||g.text_color==="black"||g.text_color==="color.black")&&A){const Z=yi(A);Z&&fi(Z.r,Z.g,Z.b)<.5&&(I="#FFFFFF")}const N=!g.text_formatting||g.text_formatting==="format_none"||g.text_formatting==="format_bold",F=this.computeFontSize(g.text_size,g.text,Math.abs(M),Math.abs(b),N);f.push({type:"text",style:{x:v,y:E,text:g.text,fill:I,fontSize:F,fontFamily:g.text_font_family==="monospace"?"monospace":"sans-serif",fontWeight:N?"bold":"normal",fontStyle:g.text_formatting==="format_italic"?"italic":"normal",textAlign:this.mapHAlign(g.text_halign),textVerticalAlign:this.mapVAlign(g.text_valign)}})}}return{type:"group",children:f}},data:[[0,d]],clip:!0,encode:{x:[0,1]},itemStyle:{color:"transparent",borderColor:"transparent"},z:14,silent:!0,emphasis:{disabled:!0}}}getDashPattern(t){switch(t){case"style_dotted":return[2,2];case"style_dashed":return[6,4];default:return}}computeFontSize(t,e,i,n,r){if(typeof t=="number"&&t>0)return t;switch(t){case"tiny":case"size.tiny":return 8;case"small":case"size.small":return 10;case"normal":case"size.normal":return 14;case"large":case"size.large":return 20;case"huge":case"size.huge":return 36}if(!e||i<=0||n<=0)return 12;const s=6,l=i-s*2,a=n-s*2;if(l<=0||a<=0)return 6;const o=e.split(`
|
|
20
|
+
`),c=o.length;let y=1;for(const f of o)f.length>y&&(y=f.length);const d=l/(y*(r?.62:.55)),u=a/(c*1.3),p=Math.min(d,u);return Math.max(6,Math.min(p,48))}mapHAlign(t){switch(t){case"left":case"text.align_left":return"left";case"right":case"text.align_right":return"right";case"center":case"text.align_center":default:return"center"}}mapVAlign(t){switch(t){case"top":case"text.align_top":return"top";case"bottom":case"text.align_bottom":return"bottom";case"center":case"text.align_center":default:return"middle"}}getTextX(t,e,i){switch(i){case"left":case"text.align_left":return t+4;case"right":case"text.align_right":return t+e-4;case"center":case"text.align_center":default:return t+e/2}}getTextY(t,e,i){switch(i){case"top":case"text.align_top":return t+4;case"bottom":case"text.align_bottom":return t+e-4;case"center":case"text.align_center":default:return t+e/2}}}var mi=Object.defineProperty,bi=(h,t,e)=>t in h?mi(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,vi=(h,t,e)=>(bi(h,typeof t!="symbol"?t+"":t,e),e);const it=class{static register(t,e){this.renderers.set(t,e)}static get(t){return this.renderers.get(t)||this.renderers.get("line")}};vi(it,"renderers",new Map),it.register("line",new ai),it.register("step",new li),it.register("histogram",new ce),it.register("columns",new ce),it.register("circles",new ee),it.register("cross",new ee),it.register("char",new ee),it.register("bar",new pe),it.register("candle",new pe),it.register("shape",new hi),it.register("background",new ci),it.register("fill",new ue),it.register("label",new di),it.register("drawing_line",new pi),it.register("linefill",new ui),it.register("drawing_polyline",new gi),it.register("drawing_box",new xi);let wi=it;var Ci=Object.defineProperty,Pi=(h,t,e)=>t in h?Ci(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,ki=(h,t,e)=>(Pi(h,typeof t!="symbol"?t+"":t,e),e);const ge=class he{static buildCandlestickSeries(t,e,i){const n=e.upColor||"#00da3c",r=e.downColor||"#ec0000",s=t.map(a=>[a.open,a.close,a.low,a.high]);if(i&&i>s.length){const a=i-s.length;for(let o=0;o<a;o++)s.push(null)}let l;if(e.lastPriceLine?.visible!==!1&&t.length>0){const a=t[t.length-1],o=a.close,c=a.close>=a.open,y=e.lastPriceLine?.color||(c?n:r);let d=e.lastPriceLine?.lineStyle||"dashed";d.startsWith("linestyle_")&&(d=d.replace("linestyle_",""));const u=e.yAxisDecimalPlaces!==void 0?e.yAxisDecimalPlaces:U.autoDetectDecimals(t);l={symbol:["none","none"],precision:u,data:[{yAxis:o,label:{show:!0,position:"end",formatter:p=>e.yAxisLabelFormatter?e.yAxisLabelFormatter(p.value):U.formatValue(p.value,u),color:"#fff",backgroundColor:y,padding:[2,4],borderRadius:2,fontSize:11,fontWeight:"bold"},lineStyle:{color:y,type:d,width:1,opacity:.8}}],animation:!1,silent:!0}}return{type:"candlestick",id:"__candlestick__",name:e.title,data:s,itemStyle:{color:n,color0:r,borderColor:n,borderColor0:r},markLine:l,xAxisIndex:0,yAxisIndex:0,z:5}}static buildIndicatorSeries(t,e,i,n,r=0,s,l,a=1){const o=[],c=new Array(n).fill(null),y=s?.filter(u=>u!=null&&u.time!==void 0),d=new Map;return t.forEach((u,p)=>{if(u.collapsed)return;const f=Object.keys(u.plots).sort((m,x)=>{const P=u.plots[m],w=u.plots[x],D=P.options.style==="fill",S=w.options.style==="fill";return D&&!S?1:!D&&S?-1:0}),g=new Map;if(f.forEach(m=>{const x=u.plots[m],P=x.options.display==="none",w=`${p}::${m}`;let D=0,S=0,M=x.options.overlay;if(x.options.style==="fill"&&M===void 0){const z=x.options.plot1,$=x.options.plot2;if(z&&$){const v=u.plots[z],E=u.plots[$];(v?.options?.overlay===!0||E?.options?.overlay===!0)&&(M=!0)}}if(u.paneIndex===0||M===!0)D=0,l&&l.has(w)?S=l.get(w):S=0;else{const z=i.findIndex($=>$.index===u.paneIndex);z!==-1&&(D=z+1,S=a+z)}const b=new Array(n).fill(null),k=new Array(n).fill(null),C=new Array(n).fill(null),A=new Array(n).fill(null);if(x.data?.forEach(z=>{const $=e.get(z.time);if($!==void 0){const v=z.options?.offset??x.options.offset??0,E=$+r+v;if(E>=0&&E<n){let I=z.value;const N=z.options?.color;k[E]=I;const F=z.options!=null&&"color"in z.options,Z=N===null||N==="na"||N==="NaN"||typeof N=="number"&&isNaN(N)||F&&N===void 0;Z&&(I=null),b[E]=I,C[E]=Z?null:N||x.options.color||he.DEFAULT_COLOR,A[E]=z.options||{}}}}),d.set(`${p}::${m}`,k),P)return;if(x.options?.style?.startsWith("style_")&&(x.options.style=x.options.style.replace("style_","")),x.options.style==="barcolor"){x.data?.forEach(z=>{const $=e.get(z.time);if($!==void 0){const v=z.options?.offset??x.options.offset??0,E=$+r+v;if(E>=0&&E<n){const I=z.options?.color||x.options.color||he.DEFAULT_COLOR;!(I===null||I==="na"||I==="NaN"||typeof I=="number"&&isNaN(I))&&z.value!==null&&z.value!==void 0&&(c[E]=I)}}});return}if(x.options.style==="table")return;if(x.options.style==="fill"&&x.options.gradient!==!0){const z=x.options.plot1?`${p}::${x.options.plot1}`:null,$=x.options.plot2?`${p}::${x.options.plot2}`:null;if(z&&$){const v=d.get(z),E=d.get($);if(v&&E){const{color:I,opacity:N}=lt.parseColor(x.options.color||"rgba(128, 128, 128, 0.2)"),F=A.some(H=>H&&H.color!==void 0),Z=[];for(let H=0;H<n;H++){const q=A[H];F&&q&&q.color!==void 0?Z[H]=lt.parseColor(q.color):Z[H]={color:I,opacity:N}}const R=`${D}:${S}`;g.has(R)||g.set(R,{entries:[],xAxisIndex:D,yAxisIndex:S}),g.get(R).entries.push({plot1Data:v,plot2Data:E,barColors:Z});return}}}{const z=x.options.color;let $=!1;if(z==null?$=!C.some(v=>v!=null):typeof z=="string"&<.parseColor(z).opacity<.01&&($=!C.some(v=>v==null?!1:lt.parseColor(v).opacity>=.01)),$)return}const G=wi.get(x.options.style).render({seriesName:w,xAxisIndex:D,yAxisIndex:S,dataArray:b,colorArray:C,optionsArray:A,plotOptions:x.options,candlestickData:s,plotDataArrays:d,indicatorId:p,plotName:m,dataIndexOffset:r,timeToIndex:e,marketData:y});G&&o.push(G)}),g.size>0){const m=new ue;g.forEach(({entries:x,xAxisIndex:P,yAxisIndex:w},D)=>{if(x.length>=2){const S=m.renderBatched(`${p}::fills_batch_${D}`,P,w,n,x);S&&o.push(S)}else if(x.length===1){const S=m.renderBatched(`${p}::fills_batch_${D}`,P,w,n,x);S&&o.push(S)}})}}),{series:o,barColors:c}}};ki(ge,"DEFAULT_COLOR","#2962ff");let _t=ge;class Di{static build(t,e,i,n=!1,r=null,s=[]){const l=[],a=t.pixelToPercent,o=t.mainPaneTop;if(!r||r==="main"){const c=10*a;if(l.push({type:"text",left:"8.5%",top:o+c+"%",z:10,style:{text:e.title||"",fill:e.titleColor||"#fff",font:`bold 16px ${e.fontFamily||"sans-serif"}`,textVerticalAlign:"top"}}),s.length>0){const d=20*a,u=16*a;s.forEach((p,f)=>{l.push({type:"text",left:"8.5%",top:o+c+d+f*u+"%",z:10,style:{text:p.id,fill:p.titleColor||"#9e9e9e",font:`bold 12px ${e.fontFamily||"sans-serif"}`,textVerticalAlign:"top"}})})}if(e.watermark!==!1){const d=t.mainPaneTop+t.mainPaneHeight;l.push({type:"text",right:"11%",top:d-3+"%",z:10,style:{text:"QFChart",fill:e.fontColor||"#cbd5e1",font:"bold 16px sans-serif",opacity:.1},cursor:"pointer",onclick:()=>{window.open("https://quantforge.org","_blank")}})}const y=[];if(e.controls?.collapse&&y.push({type:"group",children:[{type:"rect",shape:{width:20,height:20,r:2},style:{fill:"#334155",stroke:"#475569",lineWidth:1},onclick:()=>i("main","collapse")},{type:"text",style:{text:n?"+":"\u2212",fill:"#cbd5e1",font:`bold 14px ${e.fontFamily}`,x:10,y:10,textAlign:"center",textVerticalAlign:"middle"},silent:!0}]}),e.controls?.maximize){const d=r==="main",u=e.controls?.collapse?25:0;y.push({type:"group",x:u,children:[{type:"rect",shape:{width:20,height:20,r:2},style:{fill:"#334155",stroke:"#475569",lineWidth:1},onclick:()=>i("main","maximize")},{type:"text",style:{text:d?"\u2750":"\u25A1",fill:"#cbd5e1",font:`14px ${e.fontFamily}`,x:10,y:10,textAlign:"center",textVerticalAlign:"middle"},silent:!0}]})}if(e.controls?.fullscreen){let d=0;e.controls?.collapse&&(d+=25),e.controls?.maximize&&(d+=25),y.push({type:"group",x:d,children:[{type:"rect",shape:{width:20,height:20,r:2},style:{fill:"#334155",stroke:"#475569",lineWidth:1},onclick:()=>i("main","fullscreen")},{type:"text",style:{text:"\u26F6",fill:"#cbd5e1",font:`14px ${e.fontFamily}`,x:10,y:10,textAlign:"center",textVerticalAlign:"middle"},silent:!0}]})}y.length>0&&l.push({type:"group",right:"10.5%",top:o+"%",children:y})}if(!r&&t.paneBoundaries.length>0){const c=-8*a;for(const y of t.paneBoundaries)l.push({type:"group",left:"10%",top:y.yPercent+c+"%",children:[{type:"rect",shape:{width:5e3,height:12,y:-6},style:{fill:"transparent"},cursor:"row-resize"},{type:"rect",shape:{width:5e3,height:2,y:-1},style:{fill:"#475569",opacity:.7},cursor:"row-resize"}],z:50,onmouseover:function(){const d=this.children()[1];d&&(d.setStyle({fill:"#94a3b8",opacity:1}),d.setShape({height:3,y:-1.5}))},onmouseout:function(){const d=this.children()[1];d&&(d.setStyle({fill:"#475569",opacity:.7}),d.setShape({height:2,y:-1}))}})}return t.paneLayout.forEach(c=>{if(r&&c.indicatorId!==r)return;l.push({type:"text",left:"8.5%",top:c.top+10*a+"%",z:10,style:{text:c.indicatorId||"",fill:c.titleColor||"#fff",font:`bold 12px ${e.fontFamily||"sans-serif"}`,textVerticalAlign:"top"}});const y=[];if(c.controls?.collapse&&y.push({type:"group",children:[{type:"rect",shape:{width:20,height:20,r:2},style:{fill:"#334155",stroke:"#475569",lineWidth:1},onclick:()=>c.indicatorId&&i(c.indicatorId,"collapse")},{type:"text",style:{text:c.isCollapsed?"+":"\u2212",fill:"#cbd5e1",font:`bold 14px ${e.fontFamily}`,x:10,y:10,textAlign:"center",textVerticalAlign:"middle"},silent:!0}]}),c.controls?.maximize){const d=r===c.indicatorId,u=c.controls?.collapse?25:0;y.push({type:"group",x:u,children:[{type:"rect",shape:{width:20,height:20,r:2},style:{fill:"#334155",stroke:"#475569",lineWidth:1},onclick:()=>c.indicatorId&&i(c.indicatorId,"maximize")},{type:"text",style:{text:d?"\u2750":"\u25A1",fill:"#cbd5e1",font:`14px ${e.fontFamily}`,x:10,y:10,textAlign:"center",textVerticalAlign:"middle"},silent:!0}]})}y.length>0&&l.push({type:"group",right:"10.5%",top:c.top+"%",children:y})}),l}}class Mi{static format(t,e){if(!t||t.length===0)return"";const i=e.title||"",n=e.upColor||"#00da3c",r=e.downColor||"#ec0000",s=e.fontFamily||"sans-serif",l=t[0].axisValue;let a=`<div style="font-weight: bold; margin-bottom: 5px; color: #cbd5e1; font-family: ${s};">${l}</div>`;const o=t.find(y=>y.seriesType==="candlestick"),c=t.filter(y=>y.seriesType!=="candlestick");if(o){const[y,d,u,p,f]=o.value,g=u>=d?n:r;a+=`
|
|
21
|
+
<div style="margin-bottom: 8px; font-family: ${s};">
|
|
22
|
+
<div style="display:flex; justify-content:space-between; color:${g}; font-weight:bold;">
|
|
23
|
+
<span>${i}</span>
|
|
1721
24
|
</div>
|
|
1722
25
|
<div style="display: grid; grid-template-columns: auto auto; gap: 2px 15px; font-size: 0.9em; color: #cbd5e1;">
|
|
1723
|
-
<span>Open:</span> <span style="text-align: right; color: ${
|
|
1724
|
-
<span>High:</span> <span style="text-align: right; color: ${
|
|
1725
|
-
<span>Low:</span> <span style="text-align: right; color: ${
|
|
1726
|
-
<span>Close:</span> <span style="text-align: right; color: ${
|
|
26
|
+
<span>Open:</span> <span style="text-align: right; color: ${u>=d?n:r}">${d}</span>
|
|
27
|
+
<span>High:</span> <span style="text-align: right; color: ${n}">${f}</span>
|
|
28
|
+
<span>Low:</span> <span style="text-align: right; color: ${r}">${p}</span>
|
|
29
|
+
<span>Close:</span> <span style="text-align: right; color: ${u>=d?n:r}">${u}</span>
|
|
1727
30
|
</div>
|
|
1728
31
|
</div>
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
const indicators = {};
|
|
1734
|
-
indicatorParams.forEach((p) => {
|
|
1735
|
-
const parts = p.seriesName.split("::");
|
|
1736
|
-
const indId = parts.length > 1 ? parts[0] : "Unknown";
|
|
1737
|
-
const plotName = parts.length > 1 ? parts[1] : p.seriesName;
|
|
1738
|
-
if (!indicators[indId])
|
|
1739
|
-
indicators[indId] = [];
|
|
1740
|
-
indicators[indId].push({ ...p, displayName: plotName });
|
|
1741
|
-
});
|
|
1742
|
-
Object.keys(indicators).forEach((indId) => {
|
|
1743
|
-
html += `
|
|
1744
|
-
<div style="margin-top: 8px; font-family: ${fontFamily};">
|
|
1745
|
-
<div style="font-weight:bold; color: #fff; margin-bottom: 2px;">${indId}</div>
|
|
1746
|
-
`;
|
|
1747
|
-
indicators[indId].forEach((p) => {
|
|
1748
|
-
let val = p.value;
|
|
1749
|
-
if (Array.isArray(val)) {
|
|
1750
|
-
val = val[1];
|
|
1751
|
-
}
|
|
1752
|
-
if (val === null || val === void 0)
|
|
1753
|
-
return;
|
|
1754
|
-
const valStr = typeof val === "number" ? val.toLocaleString(void 0, { maximumFractionDigits: 4 }) : val;
|
|
1755
|
-
html += `
|
|
32
|
+
`}if(c.length>0){a+='<div style="border-top: 1px solid #334155; margin: 5px 0; padding-top: 5px;"></div>';const y={};c.forEach(d=>{const u=d.seriesName.split("::"),p=u.length>1?u[0]:"Unknown",f=u.length>1?u[1]:d.seriesName;y[p]||(y[p]=[]),y[p].push({...d,displayName:f})}),Object.keys(y).forEach(d=>{a+=`
|
|
33
|
+
<div style="margin-top: 8px; font-family: ${s};">
|
|
34
|
+
<div style="font-weight:bold; color: #fff; margin-bottom: 2px;">${d}</div>
|
|
35
|
+
`,y[d].forEach(u=>{let p=u.value;if(Array.isArray(p)&&(p=p[1]),p==null)return;const f=typeof p=="number"?p.toLocaleString(void 0,{maximumFractionDigits:4}):p;a+=`
|
|
1756
36
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 2px; padding-left: 8px;">
|
|
1757
|
-
<div>${
|
|
1758
|
-
<div style="font-size: 10px; color: #fff;padding-left:10px;">${
|
|
1759
|
-
</div>`;
|
|
1760
|
-
});
|
|
1761
|
-
html += `</div>`;
|
|
1762
|
-
});
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
__publicField$7(this, "toolbarContainer");
|
|
1780
|
-
__publicField$7(this, "tooltipElement", null);
|
|
1781
|
-
__publicField$7(this, "hideTimeout", null);
|
|
1782
|
-
this.context = context;
|
|
1783
|
-
this.toolbarContainer = toolbarContainer;
|
|
1784
|
-
this.createTooltip();
|
|
1785
|
-
this.renderToolbar();
|
|
1786
|
-
}
|
|
1787
|
-
createTooltip() {
|
|
1788
|
-
this.tooltipElement = document.createElement("div");
|
|
1789
|
-
Object.assign(this.tooltipElement.style, {
|
|
1790
|
-
position: "fixed",
|
|
1791
|
-
display: "none",
|
|
1792
|
-
backgroundColor: "#1e293b",
|
|
1793
|
-
color: "#e2e8f0",
|
|
1794
|
-
padding: "6px 10px",
|
|
1795
|
-
borderRadius: "6px",
|
|
1796
|
-
fontSize: "13px",
|
|
1797
|
-
lineHeight: "1.4",
|
|
1798
|
-
fontWeight: "500",
|
|
1799
|
-
border: "1px solid #334155",
|
|
1800
|
-
zIndex: "9999",
|
|
1801
|
-
pointerEvents: "none",
|
|
1802
|
-
whiteSpace: "nowrap",
|
|
1803
|
-
boxShadow: "0 4px 6px -1px rgba(0, 0, 0, 0.3), 0 2px 4px -1px rgba(0, 0, 0, 0.15)",
|
|
1804
|
-
fontFamily: this.context.getOptions().fontFamily || "sans-serif",
|
|
1805
|
-
transition: "opacity 0.15s ease-in-out, transform 0.15s ease-in-out",
|
|
1806
|
-
opacity: "0",
|
|
1807
|
-
transform: "translateX(-5px)"
|
|
1808
|
-
});
|
|
1809
|
-
document.body.appendChild(this.tooltipElement);
|
|
1810
|
-
}
|
|
1811
|
-
destroy() {
|
|
1812
|
-
if (this.tooltipElement && this.tooltipElement.parentNode) {
|
|
1813
|
-
this.tooltipElement.parentNode.removeChild(this.tooltipElement);
|
|
1814
|
-
}
|
|
1815
|
-
this.tooltipElement = null;
|
|
1816
|
-
}
|
|
1817
|
-
showTooltip(target, text) {
|
|
1818
|
-
if (!this.tooltipElement)
|
|
1819
|
-
return;
|
|
1820
|
-
if (this.hideTimeout) {
|
|
1821
|
-
clearTimeout(this.hideTimeout);
|
|
1822
|
-
this.hideTimeout = null;
|
|
1823
|
-
}
|
|
1824
|
-
const rect = target.getBoundingClientRect();
|
|
1825
|
-
this.tooltipElement.textContent = text;
|
|
1826
|
-
this.tooltipElement.style.display = "block";
|
|
1827
|
-
const tooltipRect = this.tooltipElement.getBoundingClientRect();
|
|
1828
|
-
const top = rect.top + (rect.height - tooltipRect.height) / 2;
|
|
1829
|
-
const left = rect.right + 10;
|
|
1830
|
-
this.tooltipElement.style.top = `${top}px`;
|
|
1831
|
-
this.tooltipElement.style.left = `${left}px`;
|
|
1832
|
-
requestAnimationFrame(() => {
|
|
1833
|
-
if (this.tooltipElement) {
|
|
1834
|
-
this.tooltipElement.style.opacity = "1";
|
|
1835
|
-
this.tooltipElement.style.transform = "translateX(0)";
|
|
1836
|
-
}
|
|
1837
|
-
});
|
|
1838
|
-
}
|
|
1839
|
-
hideTooltip() {
|
|
1840
|
-
if (!this.tooltipElement)
|
|
1841
|
-
return;
|
|
1842
|
-
this.tooltipElement.style.opacity = "0";
|
|
1843
|
-
this.tooltipElement.style.transform = "translateX(-5px)";
|
|
1844
|
-
if (this.hideTimeout) {
|
|
1845
|
-
clearTimeout(this.hideTimeout);
|
|
1846
|
-
}
|
|
1847
|
-
this.hideTimeout = setTimeout(() => {
|
|
1848
|
-
if (this.tooltipElement) {
|
|
1849
|
-
this.tooltipElement.style.display = "none";
|
|
1850
|
-
}
|
|
1851
|
-
this.hideTimeout = null;
|
|
1852
|
-
}, 150);
|
|
1853
|
-
}
|
|
1854
|
-
register(plugin) {
|
|
1855
|
-
if (this.plugins.has(plugin.id)) {
|
|
1856
|
-
console.warn(`Plugin with id ${plugin.id} is already registered.`);
|
|
1857
|
-
return;
|
|
1858
|
-
}
|
|
1859
|
-
this.plugins.set(plugin.id, plugin);
|
|
1860
|
-
plugin.init(this.context);
|
|
1861
|
-
this.addButton(plugin);
|
|
1862
|
-
}
|
|
1863
|
-
unregister(pluginId) {
|
|
1864
|
-
const plugin = this.plugins.get(pluginId);
|
|
1865
|
-
if (plugin) {
|
|
1866
|
-
if (this.activePluginId === pluginId) {
|
|
1867
|
-
this.deactivatePlugin();
|
|
1868
|
-
}
|
|
1869
|
-
plugin.destroy?.();
|
|
1870
|
-
this.plugins.delete(pluginId);
|
|
1871
|
-
this.removeButton(pluginId);
|
|
1872
|
-
}
|
|
1873
|
-
}
|
|
1874
|
-
activatePlugin(pluginId) {
|
|
1875
|
-
if (this.activePluginId === pluginId) {
|
|
1876
|
-
this.deactivatePlugin();
|
|
1877
|
-
return;
|
|
1878
|
-
}
|
|
1879
|
-
if (this.activePluginId) {
|
|
1880
|
-
this.deactivatePlugin();
|
|
1881
|
-
}
|
|
1882
|
-
const plugin = this.plugins.get(pluginId);
|
|
1883
|
-
if (plugin) {
|
|
1884
|
-
this.activePluginId = pluginId;
|
|
1885
|
-
this.setButtonActive(pluginId, true);
|
|
1886
|
-
plugin.activate?.();
|
|
1887
|
-
}
|
|
1888
|
-
}
|
|
1889
|
-
deactivatePlugin() {
|
|
1890
|
-
if (this.activePluginId) {
|
|
1891
|
-
const plugin = this.plugins.get(this.activePluginId);
|
|
1892
|
-
plugin?.deactivate?.();
|
|
1893
|
-
this.setButtonActive(this.activePluginId, false);
|
|
1894
|
-
this.activePluginId = null;
|
|
1895
|
-
}
|
|
1896
|
-
}
|
|
1897
|
-
// --- UI Handling ---
|
|
1898
|
-
renderToolbar() {
|
|
1899
|
-
this.toolbarContainer.innerHTML = "";
|
|
1900
|
-
this.toolbarContainer.classList.add("qfchart-toolbar");
|
|
1901
|
-
this.toolbarContainer.style.display = "flex";
|
|
1902
|
-
this.toolbarContainer.style.flexDirection = "column";
|
|
1903
|
-
this.toolbarContainer.style.width = "40px";
|
|
1904
|
-
this.toolbarContainer.style.backgroundColor = this.context.getOptions().backgroundColor || "#1e293b";
|
|
1905
|
-
this.toolbarContainer.style.borderRight = "1px solid #334155";
|
|
1906
|
-
this.toolbarContainer.style.padding = "5px";
|
|
1907
|
-
this.toolbarContainer.style.boxSizing = "border-box";
|
|
1908
|
-
this.toolbarContainer.style.gap = "5px";
|
|
1909
|
-
this.toolbarContainer.style.flexShrink = "0";
|
|
1910
|
-
}
|
|
1911
|
-
addButton(plugin) {
|
|
1912
|
-
const btn = document.createElement("button");
|
|
1913
|
-
btn.id = `qfchart-plugin-btn-${plugin.id}`;
|
|
1914
|
-
btn.style.width = "30px";
|
|
1915
|
-
btn.style.height = "30px";
|
|
1916
|
-
btn.style.padding = "4px";
|
|
1917
|
-
btn.style.border = "1px solid transparent";
|
|
1918
|
-
btn.style.borderRadius = "4px";
|
|
1919
|
-
btn.style.backgroundColor = "transparent";
|
|
1920
|
-
btn.style.cursor = "pointer";
|
|
1921
|
-
btn.style.color = this.context.getOptions().fontColor || "#cbd5e1";
|
|
1922
|
-
btn.style.display = "flex";
|
|
1923
|
-
btn.style.alignItems = "center";
|
|
1924
|
-
btn.style.justifyContent = "center";
|
|
1925
|
-
if (plugin.icon) {
|
|
1926
|
-
btn.innerHTML = plugin.icon;
|
|
1927
|
-
} else {
|
|
1928
|
-
btn.innerText = (plugin.name || plugin.id).substring(0, 2).toUpperCase();
|
|
1929
|
-
}
|
|
1930
|
-
btn.addEventListener("mouseenter", () => {
|
|
1931
|
-
if (this.activePluginId !== plugin.id) {
|
|
1932
|
-
btn.style.backgroundColor = "rgba(255, 255, 255, 0.1)";
|
|
1933
|
-
}
|
|
1934
|
-
this.showTooltip(btn, plugin.name || plugin.id);
|
|
1935
|
-
});
|
|
1936
|
-
btn.addEventListener("mouseleave", () => {
|
|
1937
|
-
if (this.activePluginId !== plugin.id) {
|
|
1938
|
-
btn.style.backgroundColor = "transparent";
|
|
1939
|
-
}
|
|
1940
|
-
this.hideTooltip();
|
|
1941
|
-
});
|
|
1942
|
-
btn.onclick = () => this.activatePlugin(plugin.id);
|
|
1943
|
-
this.toolbarContainer.appendChild(btn);
|
|
1944
|
-
}
|
|
1945
|
-
removeButton(pluginId) {
|
|
1946
|
-
const btn = this.toolbarContainer.querySelector(`#qfchart-plugin-btn-${pluginId}`);
|
|
1947
|
-
if (btn) {
|
|
1948
|
-
btn.remove();
|
|
1949
|
-
}
|
|
1950
|
-
}
|
|
1951
|
-
setButtonActive(pluginId, active) {
|
|
1952
|
-
const btn = this.toolbarContainer.querySelector(`#qfchart-plugin-btn-${pluginId}`);
|
|
1953
|
-
if (btn) {
|
|
1954
|
-
if (active) {
|
|
1955
|
-
btn.style.backgroundColor = "#2563eb";
|
|
1956
|
-
btn.style.color = "#ffffff";
|
|
1957
|
-
} else {
|
|
1958
|
-
btn.style.backgroundColor = "transparent";
|
|
1959
|
-
btn.style.color = this.context.getOptions().fontColor || "#cbd5e1";
|
|
1960
|
-
}
|
|
1961
|
-
}
|
|
1962
|
-
}
|
|
1963
|
-
}
|
|
1964
|
-
|
|
1965
|
-
var __defProp$6 = Object.defineProperty;
|
|
1966
|
-
var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1967
|
-
var __publicField$6 = (obj, key, value) => {
|
|
1968
|
-
__defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1969
|
-
return value;
|
|
1970
|
-
};
|
|
1971
|
-
class DrawingEditor {
|
|
1972
|
-
constructor(context) {
|
|
1973
|
-
__publicField$6(this, "context");
|
|
1974
|
-
__publicField$6(this, "isEditing", false);
|
|
1975
|
-
__publicField$6(this, "currentDrawing", null);
|
|
1976
|
-
__publicField$6(this, "editingPointIndex", null);
|
|
1977
|
-
__publicField$6(this, "zr");
|
|
1978
|
-
// Temporary ZRender elements for visual feedback during drag
|
|
1979
|
-
__publicField$6(this, "editGroup", null);
|
|
1980
|
-
__publicField$6(this, "editLine", null);
|
|
1981
|
-
__publicField$6(this, "editStartPoint", null);
|
|
1982
|
-
__publicField$6(this, "editEndPoint", null);
|
|
1983
|
-
__publicField$6(this, "isMovingShape", false);
|
|
1984
|
-
__publicField$6(this, "dragStart", null);
|
|
1985
|
-
__publicField$6(this, "initialPixelPoints", []);
|
|
1986
|
-
__publicField$6(this, "onDrawingMouseDown", (payload) => {
|
|
1987
|
-
if (this.isEditing)
|
|
1988
|
-
return;
|
|
1989
|
-
const drawing = this.context.getDrawing(payload.id);
|
|
1990
|
-
if (!drawing)
|
|
1991
|
-
return;
|
|
1992
|
-
this.isEditing = true;
|
|
1993
|
-
this.isMovingShape = true;
|
|
1994
|
-
this.currentDrawing = JSON.parse(JSON.stringify(drawing));
|
|
1995
|
-
this.dragStart = { x: payload.x, y: payload.y };
|
|
1996
|
-
this.initialPixelPoints = drawing.points.map((p) => {
|
|
1997
|
-
const pixel = this.context.coordinateConversion.dataToPixel(p);
|
|
1998
|
-
return pixel ? { x: pixel.x, y: pixel.y } : { x: 0, y: 0 };
|
|
1999
|
-
});
|
|
2000
|
-
this.context.lockChart();
|
|
2001
|
-
this.createEditGraphic();
|
|
2002
|
-
this.zr.on("mousemove", this.onMouseMove);
|
|
2003
|
-
this.zr.on("mouseup", this.onMouseUp);
|
|
2004
|
-
});
|
|
2005
|
-
__publicField$6(this, "onPointMouseDown", (payload) => {
|
|
2006
|
-
if (this.isEditing)
|
|
2007
|
-
return;
|
|
2008
|
-
const drawing = this.context.getDrawing(payload.id);
|
|
2009
|
-
if (!drawing)
|
|
2010
|
-
return;
|
|
2011
|
-
this.isEditing = true;
|
|
2012
|
-
this.currentDrawing = JSON.parse(JSON.stringify(drawing));
|
|
2013
|
-
this.editingPointIndex = payload.pointIndex;
|
|
2014
|
-
this.context.lockChart();
|
|
2015
|
-
this.createEditGraphic();
|
|
2016
|
-
this.zr.on("mousemove", this.onMouseMove);
|
|
2017
|
-
this.zr.on("mouseup", this.onMouseUp);
|
|
2018
|
-
});
|
|
2019
|
-
__publicField$6(this, "onMouseMove", (e) => {
|
|
2020
|
-
if (!this.isEditing || !this.currentDrawing)
|
|
2021
|
-
return;
|
|
2022
|
-
const x = e.offsetX;
|
|
2023
|
-
const y = e.offsetY;
|
|
2024
|
-
if (this.isMovingShape && this.dragStart) {
|
|
2025
|
-
const dx = x - this.dragStart.x;
|
|
2026
|
-
const dy = y - this.dragStart.y;
|
|
2027
|
-
const newP1 = {
|
|
2028
|
-
x: this.initialPixelPoints[0].x + dx,
|
|
2029
|
-
y: this.initialPixelPoints[0].y + dy
|
|
2030
|
-
};
|
|
2031
|
-
const newP2 = {
|
|
2032
|
-
x: this.initialPixelPoints[1].x + dx,
|
|
2033
|
-
y: this.initialPixelPoints[1].y + dy
|
|
2034
|
-
};
|
|
2035
|
-
this.editLine.setShape({
|
|
2036
|
-
x1: newP1.x,
|
|
2037
|
-
y1: newP1.y,
|
|
2038
|
-
x2: newP2.x,
|
|
2039
|
-
y2: newP2.y
|
|
2040
|
-
});
|
|
2041
|
-
this.editStartPoint.setShape({ cx: newP1.x, cy: newP1.y });
|
|
2042
|
-
this.editEndPoint.setShape({ cx: newP2.x, cy: newP2.y });
|
|
2043
|
-
} else if (this.editingPointIndex !== null) {
|
|
2044
|
-
if (this.editingPointIndex === 0) {
|
|
2045
|
-
this.editLine.setShape({ x1: x, y1: y });
|
|
2046
|
-
this.editStartPoint.setShape({ cx: x, cy: y });
|
|
2047
|
-
} else {
|
|
2048
|
-
this.editLine.setShape({ x2: x, y2: y });
|
|
2049
|
-
this.editEndPoint.setShape({ cx: x, cy: y });
|
|
2050
|
-
}
|
|
2051
|
-
}
|
|
2052
|
-
});
|
|
2053
|
-
__publicField$6(this, "onMouseUp", (e) => {
|
|
2054
|
-
if (!this.isEditing)
|
|
2055
|
-
return;
|
|
2056
|
-
this.finishEditing(e.offsetX, e.offsetY);
|
|
2057
|
-
});
|
|
2058
|
-
this.context = context;
|
|
2059
|
-
this.zr = this.context.getChart().getZr();
|
|
2060
|
-
this.bindEvents();
|
|
2061
|
-
}
|
|
2062
|
-
bindEvents() {
|
|
2063
|
-
this.context.events.on("drawing:point:mousedown", this.onPointMouseDown);
|
|
2064
|
-
this.context.events.on("drawing:mousedown", this.onDrawingMouseDown);
|
|
2065
|
-
}
|
|
2066
|
-
createEditGraphic() {
|
|
2067
|
-
if (!this.currentDrawing)
|
|
2068
|
-
return;
|
|
2069
|
-
this.editGroup = new echarts__namespace.graphic.Group();
|
|
2070
|
-
const p1Data = this.currentDrawing.points[0];
|
|
2071
|
-
const p2Data = this.currentDrawing.points[1];
|
|
2072
|
-
const p1 = this.context.coordinateConversion.dataToPixel(p1Data);
|
|
2073
|
-
const p2 = this.context.coordinateConversion.dataToPixel(p2Data);
|
|
2074
|
-
if (!p1 || !p2)
|
|
2075
|
-
return;
|
|
2076
|
-
this.editLine = new echarts__namespace.graphic.Line({
|
|
2077
|
-
shape: { x1: p1.x, y1: p1.y, x2: p2.x, y2: p2.y },
|
|
2078
|
-
style: {
|
|
2079
|
-
stroke: this.currentDrawing.style?.color || "#3b82f6",
|
|
2080
|
-
lineWidth: this.currentDrawing.style?.lineWidth || 2,
|
|
2081
|
-
lineDash: [4, 4]
|
|
2082
|
-
// Dashed to indicate editing
|
|
2083
|
-
},
|
|
2084
|
-
silent: true
|
|
2085
|
-
// Events pass through to handlers
|
|
2086
|
-
});
|
|
2087
|
-
this.editStartPoint = new echarts__namespace.graphic.Circle({
|
|
2088
|
-
shape: { cx: p1.x, cy: p1.y, r: 5 },
|
|
2089
|
-
style: { fill: "#fff", stroke: "#3b82f6", lineWidth: 2 },
|
|
2090
|
-
z: 1e3
|
|
2091
|
-
});
|
|
2092
|
-
this.editEndPoint = new echarts__namespace.graphic.Circle({
|
|
2093
|
-
shape: { cx: p2.x, cy: p2.y, r: 5 },
|
|
2094
|
-
style: { fill: "#fff", stroke: "#3b82f6", lineWidth: 2 },
|
|
2095
|
-
z: 1e3
|
|
2096
|
-
});
|
|
2097
|
-
this.editGroup.add(this.editLine);
|
|
2098
|
-
this.editGroup.add(this.editStartPoint);
|
|
2099
|
-
this.editGroup.add(this.editEndPoint);
|
|
2100
|
-
this.zr.add(this.editGroup);
|
|
2101
|
-
}
|
|
2102
|
-
finishEditing(finalX, finishY) {
|
|
2103
|
-
if (!this.currentDrawing)
|
|
2104
|
-
return;
|
|
2105
|
-
if (this.isMovingShape && this.dragStart) {
|
|
2106
|
-
const dx = finalX - this.dragStart.x;
|
|
2107
|
-
const dy = finishY - this.dragStart.y;
|
|
2108
|
-
const newPoints = this.initialPixelPoints.map((p, i) => {
|
|
2109
|
-
const newX = p.x + dx;
|
|
2110
|
-
const newY = p.y + dy;
|
|
2111
|
-
return this.context.coordinateConversion.pixelToData({
|
|
2112
|
-
x: newX,
|
|
2113
|
-
y: newY
|
|
2114
|
-
});
|
|
2115
|
-
});
|
|
2116
|
-
if (newPoints.every((p) => p !== null)) {
|
|
2117
|
-
if (newPoints[0] && newPoints[1]) {
|
|
2118
|
-
this.currentDrawing.points[0] = newPoints[0];
|
|
2119
|
-
this.currentDrawing.points[1] = newPoints[1];
|
|
2120
|
-
if (newPoints[0].paneIndex !== void 0) {
|
|
2121
|
-
this.currentDrawing.paneIndex = newPoints[0].paneIndex;
|
|
2122
|
-
}
|
|
2123
|
-
this.context.updateDrawing(this.currentDrawing);
|
|
2124
|
-
}
|
|
2125
|
-
}
|
|
2126
|
-
} else if (this.editingPointIndex !== null) {
|
|
2127
|
-
const newData = this.context.coordinateConversion.pixelToData({
|
|
2128
|
-
x: finalX,
|
|
2129
|
-
y: finishY
|
|
2130
|
-
});
|
|
2131
|
-
if (newData) {
|
|
2132
|
-
this.currentDrawing.points[this.editingPointIndex] = newData;
|
|
2133
|
-
if (this.editingPointIndex === 0 && newData.paneIndex !== void 0) {
|
|
2134
|
-
this.currentDrawing.paneIndex = newData.paneIndex;
|
|
2135
|
-
}
|
|
2136
|
-
this.context.updateDrawing(this.currentDrawing);
|
|
2137
|
-
}
|
|
2138
|
-
}
|
|
2139
|
-
this.isEditing = false;
|
|
2140
|
-
this.isMovingShape = false;
|
|
2141
|
-
this.dragStart = null;
|
|
2142
|
-
this.initialPixelPoints = [];
|
|
2143
|
-
this.currentDrawing = null;
|
|
2144
|
-
this.editingPointIndex = null;
|
|
2145
|
-
if (this.editGroup) {
|
|
2146
|
-
this.zr.remove(this.editGroup);
|
|
2147
|
-
this.editGroup = null;
|
|
2148
|
-
}
|
|
2149
|
-
this.zr.off("mousemove", this.onMouseMove);
|
|
2150
|
-
this.zr.off("mouseup", this.onMouseUp);
|
|
2151
|
-
this.context.unlockChart();
|
|
2152
|
-
}
|
|
2153
|
-
}
|
|
2154
|
-
|
|
2155
|
-
var __defProp$5 = Object.defineProperty;
|
|
2156
|
-
var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
2157
|
-
var __publicField$5 = (obj, key, value) => {
|
|
2158
|
-
__defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
2159
|
-
return value;
|
|
2160
|
-
};
|
|
2161
|
-
class EventBus {
|
|
2162
|
-
constructor() {
|
|
2163
|
-
__publicField$5(this, "handlers", /* @__PURE__ */ new Map());
|
|
2164
|
-
}
|
|
2165
|
-
on(event, handler) {
|
|
2166
|
-
if (!this.handlers.has(event)) {
|
|
2167
|
-
this.handlers.set(event, /* @__PURE__ */ new Set());
|
|
2168
|
-
}
|
|
2169
|
-
this.handlers.get(event).add(handler);
|
|
2170
|
-
}
|
|
2171
|
-
off(event, handler) {
|
|
2172
|
-
const handlers = this.handlers.get(event);
|
|
2173
|
-
if (handlers) {
|
|
2174
|
-
handlers.delete(handler);
|
|
2175
|
-
}
|
|
2176
|
-
}
|
|
2177
|
-
emit(event, payload) {
|
|
2178
|
-
const handlers = this.handlers.get(event);
|
|
2179
|
-
if (handlers) {
|
|
2180
|
-
handlers.forEach((handler) => {
|
|
2181
|
-
try {
|
|
2182
|
-
handler(payload);
|
|
2183
|
-
} catch (e) {
|
|
2184
|
-
console.error(`Error in EventBus handler for ${event}:`, e);
|
|
2185
|
-
}
|
|
2186
|
-
});
|
|
2187
|
-
}
|
|
2188
|
-
}
|
|
2189
|
-
clear() {
|
|
2190
|
-
this.handlers.clear();
|
|
2191
|
-
}
|
|
2192
|
-
}
|
|
2193
|
-
|
|
2194
|
-
var __defProp$4 = Object.defineProperty;
|
|
2195
|
-
var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
2196
|
-
var __publicField$4 = (obj, key, value) => {
|
|
2197
|
-
__defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
2198
|
-
return value;
|
|
2199
|
-
};
|
|
2200
|
-
class QFChart {
|
|
2201
|
-
constructor(container, options = {}) {
|
|
2202
|
-
__publicField$4(this, "chart");
|
|
2203
|
-
__publicField$4(this, "options");
|
|
2204
|
-
__publicField$4(this, "marketData", []);
|
|
2205
|
-
__publicField$4(this, "indicators", /* @__PURE__ */ new Map());
|
|
2206
|
-
__publicField$4(this, "timeToIndex", /* @__PURE__ */ new Map());
|
|
2207
|
-
__publicField$4(this, "pluginManager");
|
|
2208
|
-
__publicField$4(this, "drawingEditor");
|
|
2209
|
-
__publicField$4(this, "events", new EventBus());
|
|
2210
|
-
__publicField$4(this, "isMainCollapsed", false);
|
|
2211
|
-
__publicField$4(this, "maximizedPaneId", null);
|
|
2212
|
-
__publicField$4(this, "countdownInterval", null);
|
|
2213
|
-
__publicField$4(this, "selectedDrawingId", null);
|
|
2214
|
-
// Track selected drawing
|
|
2215
|
-
// Drawing System
|
|
2216
|
-
__publicField$4(this, "drawings", []);
|
|
2217
|
-
__publicField$4(this, "coordinateConversion", {
|
|
2218
|
-
pixelToData: (point) => {
|
|
2219
|
-
const option = this.chart.getOption();
|
|
2220
|
-
if (!option || !option.grid)
|
|
2221
|
-
return null;
|
|
2222
|
-
const gridCount = option.grid.length;
|
|
2223
|
-
for (let i = 0; i < gridCount; i++) {
|
|
2224
|
-
if (this.chart.containPixel({ gridIndex: i }, [point.x, point.y])) {
|
|
2225
|
-
this.chart.convertFromPixel({ seriesIndex: i }, [point.x, point.y]);
|
|
2226
|
-
const pGrid = this.chart.convertFromPixel({ gridIndex: i }, [point.x, point.y]);
|
|
2227
|
-
if (pGrid) {
|
|
2228
|
-
return { timeIndex: Math.round(pGrid[0]), value: pGrid[1], paneIndex: i };
|
|
2229
|
-
}
|
|
2230
|
-
}
|
|
2231
|
-
}
|
|
2232
|
-
return null;
|
|
2233
|
-
},
|
|
2234
|
-
dataToPixel: (point) => {
|
|
2235
|
-
const paneIdx = point.paneIndex || 0;
|
|
2236
|
-
const p = this.chart.convertToPixel({ gridIndex: paneIdx }, [point.timeIndex, point.value]);
|
|
2237
|
-
if (p) {
|
|
2238
|
-
return { x: p[0], y: p[1] };
|
|
2239
|
-
}
|
|
2240
|
-
return null;
|
|
2241
|
-
}
|
|
2242
|
-
});
|
|
2243
|
-
// Default colors and constants
|
|
2244
|
-
__publicField$4(this, "upColor", "#00da3c");
|
|
2245
|
-
__publicField$4(this, "downColor", "#ec0000");
|
|
2246
|
-
__publicField$4(this, "defaultPadding", 0);
|
|
2247
|
-
__publicField$4(this, "padding");
|
|
2248
|
-
__publicField$4(this, "dataIndexOffset", 0);
|
|
2249
|
-
// Offset for phantom padding data
|
|
2250
|
-
// DOM Elements for Layout
|
|
2251
|
-
__publicField$4(this, "rootContainer");
|
|
2252
|
-
__publicField$4(this, "layoutContainer");
|
|
2253
|
-
__publicField$4(this, "toolbarContainer");
|
|
2254
|
-
// New Toolbar
|
|
2255
|
-
__publicField$4(this, "leftSidebar");
|
|
2256
|
-
__publicField$4(this, "rightSidebar");
|
|
2257
|
-
__publicField$4(this, "chartContainer");
|
|
2258
|
-
__publicField$4(this, "onKeyDown", (e) => {
|
|
2259
|
-
if ((e.key === "Delete" || e.key === "Backspace") && this.selectedDrawingId) {
|
|
2260
|
-
this.removeDrawing(this.selectedDrawingId);
|
|
2261
|
-
this.selectedDrawingId = null;
|
|
2262
|
-
this.render();
|
|
2263
|
-
}
|
|
2264
|
-
});
|
|
2265
|
-
__publicField$4(this, "onFullscreenChange", () => {
|
|
2266
|
-
this.render();
|
|
2267
|
-
});
|
|
2268
|
-
// --- Interaction Locking ---
|
|
2269
|
-
__publicField$4(this, "isLocked", false);
|
|
2270
|
-
__publicField$4(this, "lockedState", null);
|
|
2271
|
-
this.rootContainer = container;
|
|
2272
|
-
this.options = {
|
|
2273
|
-
title: "Market",
|
|
2274
|
-
height: "600px",
|
|
2275
|
-
backgroundColor: "#1e293b",
|
|
2276
|
-
upColor: "#00da3c",
|
|
2277
|
-
downColor: "#ec0000",
|
|
2278
|
-
fontColor: "#cbd5e1",
|
|
2279
|
-
fontFamily: "sans-serif",
|
|
2280
|
-
padding: 0.01,
|
|
2281
|
-
dataZoom: {
|
|
2282
|
-
visible: true,
|
|
2283
|
-
position: "top",
|
|
2284
|
-
height: 6
|
|
2285
|
-
},
|
|
2286
|
-
layout: {
|
|
2287
|
-
mainPaneHeight: "50%",
|
|
2288
|
-
gap: 13
|
|
2289
|
-
},
|
|
2290
|
-
watermark: true,
|
|
2291
|
-
...options
|
|
2292
|
-
};
|
|
2293
|
-
if (this.options.upColor)
|
|
2294
|
-
this.upColor = this.options.upColor;
|
|
2295
|
-
if (this.options.downColor)
|
|
2296
|
-
this.downColor = this.options.downColor;
|
|
2297
|
-
this.padding = this.options.padding !== void 0 ? this.options.padding : this.defaultPadding;
|
|
2298
|
-
if (this.options.height) {
|
|
2299
|
-
if (typeof this.options.height === "number") {
|
|
2300
|
-
this.rootContainer.style.height = `${this.options.height}px`;
|
|
2301
|
-
} else {
|
|
2302
|
-
this.rootContainer.style.height = this.options.height;
|
|
2303
|
-
}
|
|
2304
|
-
}
|
|
2305
|
-
this.rootContainer.innerHTML = "";
|
|
2306
|
-
this.layoutContainer = document.createElement("div");
|
|
2307
|
-
this.layoutContainer.style.display = "flex";
|
|
2308
|
-
this.layoutContainer.style.width = "100%";
|
|
2309
|
-
this.layoutContainer.style.height = "100%";
|
|
2310
|
-
this.layoutContainer.style.overflow = "hidden";
|
|
2311
|
-
this.rootContainer.appendChild(this.layoutContainer);
|
|
2312
|
-
this.leftSidebar = document.createElement("div");
|
|
2313
|
-
this.leftSidebar.style.display = "none";
|
|
2314
|
-
this.leftSidebar.style.width = "250px";
|
|
2315
|
-
this.leftSidebar.style.flexShrink = "0";
|
|
2316
|
-
this.leftSidebar.style.overflowY = "auto";
|
|
2317
|
-
this.leftSidebar.style.backgroundColor = this.options.backgroundColor || "#1e293b";
|
|
2318
|
-
this.leftSidebar.style.borderRight = "1px solid #334155";
|
|
2319
|
-
this.leftSidebar.style.padding = "10px";
|
|
2320
|
-
this.leftSidebar.style.boxSizing = "border-box";
|
|
2321
|
-
this.leftSidebar.style.color = "#cbd5e1";
|
|
2322
|
-
this.leftSidebar.style.fontSize = "12px";
|
|
2323
|
-
this.leftSidebar.style.fontFamily = this.options.fontFamily || "sans-serif";
|
|
2324
|
-
this.layoutContainer.appendChild(this.leftSidebar);
|
|
2325
|
-
this.toolbarContainer = document.createElement("div");
|
|
2326
|
-
this.layoutContainer.appendChild(this.toolbarContainer);
|
|
2327
|
-
this.chartContainer = document.createElement("div");
|
|
2328
|
-
this.chartContainer.style.flexGrow = "1";
|
|
2329
|
-
this.chartContainer.style.height = "100%";
|
|
2330
|
-
this.chartContainer.style.overflow = "hidden";
|
|
2331
|
-
this.layoutContainer.appendChild(this.chartContainer);
|
|
2332
|
-
this.rightSidebar = document.createElement("div");
|
|
2333
|
-
this.rightSidebar.style.display = "none";
|
|
2334
|
-
this.rightSidebar.style.width = "250px";
|
|
2335
|
-
this.rightSidebar.style.flexShrink = "0";
|
|
2336
|
-
this.rightSidebar.style.overflowY = "auto";
|
|
2337
|
-
this.rightSidebar.style.backgroundColor = this.options.backgroundColor || "#1e293b";
|
|
2338
|
-
this.rightSidebar.style.borderLeft = "1px solid #334155";
|
|
2339
|
-
this.rightSidebar.style.padding = "10px";
|
|
2340
|
-
this.rightSidebar.style.boxSizing = "border-box";
|
|
2341
|
-
this.rightSidebar.style.color = "#cbd5e1";
|
|
2342
|
-
this.rightSidebar.style.fontSize = "12px";
|
|
2343
|
-
this.rightSidebar.style.fontFamily = this.options.fontFamily || "sans-serif";
|
|
2344
|
-
this.layoutContainer.appendChild(this.rightSidebar);
|
|
2345
|
-
this.chart = echarts__namespace.init(this.chartContainer);
|
|
2346
|
-
this.pluginManager = new PluginManager(this, this.toolbarContainer);
|
|
2347
|
-
this.drawingEditor = new DrawingEditor(this);
|
|
2348
|
-
this.chart.on("dataZoom", (params) => {
|
|
2349
|
-
this.events.emit("chart:dataZoom", params);
|
|
2350
|
-
const triggerOn = this.options.databox?.triggerOn;
|
|
2351
|
-
const position = this.options.databox?.position;
|
|
2352
|
-
if (triggerOn === "click" && position === "floating") {
|
|
2353
|
-
this.chart.dispatchAction({
|
|
2354
|
-
type: "hideTip"
|
|
2355
|
-
});
|
|
2356
|
-
}
|
|
2357
|
-
});
|
|
2358
|
-
this.chart.on("finished", (params) => this.events.emit("chart:updated", params));
|
|
2359
|
-
this.chart.getZr().on("mousedown", (params) => this.events.emit("mouse:down", params));
|
|
2360
|
-
this.chart.getZr().on("mousemove", (params) => this.events.emit("mouse:move", params));
|
|
2361
|
-
this.chart.getZr().on("mouseup", (params) => this.events.emit("mouse:up", params));
|
|
2362
|
-
this.chart.getZr().on("click", (params) => this.events.emit("mouse:click", params));
|
|
2363
|
-
const zr = this.chart.getZr();
|
|
2364
|
-
const originalSetCursorStyle = zr.setCursorStyle;
|
|
2365
|
-
zr.setCursorStyle = function(cursorStyle) {
|
|
2366
|
-
if (cursorStyle === "grab") {
|
|
2367
|
-
cursorStyle = "crosshair";
|
|
2368
|
-
}
|
|
2369
|
-
originalSetCursorStyle.call(this, cursorStyle);
|
|
2370
|
-
};
|
|
2371
|
-
this.bindDrawingEvents();
|
|
2372
|
-
window.addEventListener("resize", this.resize.bind(this));
|
|
2373
|
-
document.addEventListener("fullscreenchange", this.onFullscreenChange);
|
|
2374
|
-
document.addEventListener("keydown", this.onKeyDown);
|
|
2375
|
-
}
|
|
2376
|
-
bindDrawingEvents() {
|
|
2377
|
-
let hideTimeout = null;
|
|
2378
|
-
const getDrawingInfo = (params) => {
|
|
2379
|
-
if (!params || params.componentType !== "series" || !params.seriesName?.startsWith("drawings")) {
|
|
2380
|
-
return null;
|
|
2381
|
-
}
|
|
2382
|
-
params.seriesIndex;
|
|
2383
|
-
const match = params.seriesName.match(/drawings-pane-(\d+)/);
|
|
2384
|
-
if (!match)
|
|
2385
|
-
return null;
|
|
2386
|
-
const paneIdx = parseInt(match[1]);
|
|
2387
|
-
const paneDrawings = this.drawings.filter((d) => (d.paneIndex || 0) === paneIdx);
|
|
2388
|
-
const drawing = paneDrawings[params.dataIndex];
|
|
2389
|
-
if (!drawing)
|
|
2390
|
-
return null;
|
|
2391
|
-
const targetName = params.event?.target?.name;
|
|
2392
|
-
return { drawing, targetName, paneIdx };
|
|
2393
|
-
};
|
|
2394
|
-
this.chart.on("mouseover", (params) => {
|
|
2395
|
-
const info = getDrawingInfo(params);
|
|
2396
|
-
if (!info)
|
|
2397
|
-
return;
|
|
2398
|
-
const group = params.event?.target?.parent;
|
|
2399
|
-
if (group) {
|
|
2400
|
-
const isSelected = info.drawing.id === this.selectedDrawingId;
|
|
2401
|
-
if (hideTimeout) {
|
|
2402
|
-
clearTimeout(hideTimeout);
|
|
2403
|
-
hideTimeout = null;
|
|
2404
|
-
}
|
|
2405
|
-
if (!isSelected) {
|
|
2406
|
-
group.children().forEach((child) => {
|
|
2407
|
-
if (child.name && child.name.startsWith("point")) {
|
|
2408
|
-
child.attr("style", { opacity: 1 });
|
|
2409
|
-
}
|
|
2410
|
-
});
|
|
2411
|
-
}
|
|
2412
|
-
}
|
|
2413
|
-
if (info.targetName === "line") {
|
|
2414
|
-
this.events.emit("drawing:hover", {
|
|
2415
|
-
id: info.drawing.id,
|
|
2416
|
-
type: info.drawing.type
|
|
2417
|
-
});
|
|
2418
|
-
this.chart.getZr().setCursorStyle("move");
|
|
2419
|
-
} else if (info.targetName?.startsWith("point")) {
|
|
2420
|
-
const pointIdx = info.targetName === "point-start" ? 0 : 1;
|
|
2421
|
-
this.events.emit("drawing:point:hover", {
|
|
2422
|
-
id: info.drawing.id,
|
|
2423
|
-
pointIndex: pointIdx
|
|
2424
|
-
});
|
|
2425
|
-
this.chart.getZr().setCursorStyle("pointer");
|
|
2426
|
-
}
|
|
2427
|
-
});
|
|
2428
|
-
this.chart.on("mouseout", (params) => {
|
|
2429
|
-
const info = getDrawingInfo(params);
|
|
2430
|
-
if (!info)
|
|
2431
|
-
return;
|
|
2432
|
-
const group = params.event?.target?.parent;
|
|
2433
|
-
if (info.drawing.id === this.selectedDrawingId) {
|
|
2434
|
-
return;
|
|
2435
|
-
}
|
|
2436
|
-
hideTimeout = setTimeout(() => {
|
|
2437
|
-
if (group) {
|
|
2438
|
-
if (this.selectedDrawingId === info.drawing.id)
|
|
2439
|
-
return;
|
|
2440
|
-
group.children().forEach((child) => {
|
|
2441
|
-
if (child.name && child.name.startsWith("point")) {
|
|
2442
|
-
child.attr("style", { opacity: 0 });
|
|
2443
|
-
}
|
|
2444
|
-
});
|
|
2445
|
-
}
|
|
2446
|
-
}, 50);
|
|
2447
|
-
if (info.targetName === "line") {
|
|
2448
|
-
this.events.emit("drawing:mouseout", { id: info.drawing.id });
|
|
2449
|
-
} else if (info.targetName?.startsWith("point")) {
|
|
2450
|
-
const pointIdx = info.targetName === "point-start" ? 0 : 1;
|
|
2451
|
-
this.events.emit("drawing:point:mouseout", {
|
|
2452
|
-
id: info.drawing.id,
|
|
2453
|
-
pointIndex: pointIdx
|
|
2454
|
-
});
|
|
2455
|
-
}
|
|
2456
|
-
this.chart.getZr().setCursorStyle("default");
|
|
2457
|
-
});
|
|
2458
|
-
this.chart.on("mousedown", (params) => {
|
|
2459
|
-
const info = getDrawingInfo(params);
|
|
2460
|
-
if (!info)
|
|
2461
|
-
return;
|
|
2462
|
-
const event = params.event?.event || params.event;
|
|
2463
|
-
const x = event?.offsetX;
|
|
2464
|
-
const y = event?.offsetY;
|
|
2465
|
-
if (info.targetName === "line") {
|
|
2466
|
-
this.events.emit("drawing:mousedown", {
|
|
2467
|
-
id: info.drawing.id,
|
|
2468
|
-
x,
|
|
2469
|
-
y
|
|
2470
|
-
});
|
|
2471
|
-
} else if (info.targetName?.startsWith("point")) {
|
|
2472
|
-
const pointIdx = info.targetName === "point-start" ? 0 : 1;
|
|
2473
|
-
this.events.emit("drawing:point:mousedown", {
|
|
2474
|
-
id: info.drawing.id,
|
|
2475
|
-
pointIndex: pointIdx,
|
|
2476
|
-
x,
|
|
2477
|
-
y
|
|
2478
|
-
});
|
|
2479
|
-
}
|
|
2480
|
-
});
|
|
2481
|
-
this.chart.on("click", (params) => {
|
|
2482
|
-
const info = getDrawingInfo(params);
|
|
2483
|
-
if (!info)
|
|
2484
|
-
return;
|
|
2485
|
-
if (this.selectedDrawingId !== info.drawing.id) {
|
|
2486
|
-
this.selectedDrawingId = info.drawing.id;
|
|
2487
|
-
this.events.emit("drawing:selected", { id: info.drawing.id });
|
|
2488
|
-
this.render();
|
|
2489
|
-
}
|
|
2490
|
-
if (info.targetName === "line") {
|
|
2491
|
-
this.events.emit("drawing:click", { id: info.drawing.id });
|
|
2492
|
-
} else if (info.targetName?.startsWith("point")) {
|
|
2493
|
-
const pointIdx = info.targetName === "point-start" ? 0 : 1;
|
|
2494
|
-
this.events.emit("drawing:point:click", {
|
|
2495
|
-
id: info.drawing.id,
|
|
2496
|
-
pointIndex: pointIdx
|
|
2497
|
-
});
|
|
2498
|
-
}
|
|
2499
|
-
});
|
|
2500
|
-
this.chart.getZr().on("click", (params) => {
|
|
2501
|
-
if (!params.target) {
|
|
2502
|
-
if (this.selectedDrawingId) {
|
|
2503
|
-
this.events.emit("drawing:deselected", { id: this.selectedDrawingId });
|
|
2504
|
-
this.selectedDrawingId = null;
|
|
2505
|
-
this.render();
|
|
2506
|
-
}
|
|
2507
|
-
}
|
|
2508
|
-
});
|
|
2509
|
-
}
|
|
2510
|
-
// --- Plugin System Integration ---
|
|
2511
|
-
getChart() {
|
|
2512
|
-
return this.chart;
|
|
2513
|
-
}
|
|
2514
|
-
getMarketData() {
|
|
2515
|
-
return this.marketData;
|
|
2516
|
-
}
|
|
2517
|
-
getTimeToIndex() {
|
|
2518
|
-
return this.timeToIndex;
|
|
2519
|
-
}
|
|
2520
|
-
getOptions() {
|
|
2521
|
-
return this.options;
|
|
2522
|
-
}
|
|
2523
|
-
disableTools() {
|
|
2524
|
-
this.pluginManager.deactivatePlugin();
|
|
2525
|
-
}
|
|
2526
|
-
registerPlugin(plugin) {
|
|
2527
|
-
this.pluginManager.register(plugin);
|
|
2528
|
-
}
|
|
2529
|
-
// --- Drawing System ---
|
|
2530
|
-
addDrawing(drawing) {
|
|
2531
|
-
this.drawings.push(drawing);
|
|
2532
|
-
this.render();
|
|
2533
|
-
}
|
|
2534
|
-
removeDrawing(id) {
|
|
2535
|
-
const index = this.drawings.findIndex((d) => d.id === id);
|
|
2536
|
-
if (index !== -1) {
|
|
2537
|
-
const drawing = this.drawings[index];
|
|
2538
|
-
this.drawings.splice(index, 1);
|
|
2539
|
-
this.events.emit("drawing:deleted", { id: drawing.id });
|
|
2540
|
-
this.render();
|
|
2541
|
-
}
|
|
2542
|
-
}
|
|
2543
|
-
getDrawing(id) {
|
|
2544
|
-
return this.drawings.find((d) => d.id === id);
|
|
2545
|
-
}
|
|
2546
|
-
updateDrawing(drawing) {
|
|
2547
|
-
const index = this.drawings.findIndex((d) => d.id === drawing.id);
|
|
2548
|
-
if (index !== -1) {
|
|
2549
|
-
this.drawings[index] = drawing;
|
|
2550
|
-
this.render();
|
|
2551
|
-
}
|
|
2552
|
-
}
|
|
2553
|
-
lockChart() {
|
|
2554
|
-
if (this.isLocked)
|
|
2555
|
-
return;
|
|
2556
|
-
this.isLocked = true;
|
|
2557
|
-
const option = this.chart.getOption();
|
|
2558
|
-
this.chart.setOption({
|
|
2559
|
-
dataZoom: option.dataZoom.map((dz) => ({ ...dz, disabled: true })),
|
|
2560
|
-
tooltip: { show: false }
|
|
2561
|
-
// Hide tooltip during drag
|
|
2562
|
-
// We can also disable series interaction if needed, but custom series is handled by us.
|
|
2563
|
-
});
|
|
2564
|
-
}
|
|
2565
|
-
unlockChart() {
|
|
2566
|
-
if (!this.isLocked)
|
|
2567
|
-
return;
|
|
2568
|
-
this.isLocked = false;
|
|
2569
|
-
const option = this.chart.getOption();
|
|
2570
|
-
const dzConfig = this.options.dataZoom || {};
|
|
2571
|
-
dzConfig.visible ?? true;
|
|
2572
|
-
if (option.dataZoom) {
|
|
2573
|
-
this.chart.setOption({
|
|
2574
|
-
dataZoom: option.dataZoom.map((dz) => ({
|
|
2575
|
-
...dz,
|
|
2576
|
-
disabled: false
|
|
2577
|
-
})),
|
|
2578
|
-
tooltip: { show: true }
|
|
2579
|
-
});
|
|
2580
|
-
}
|
|
2581
|
-
}
|
|
2582
|
-
// --------------------------------
|
|
2583
|
-
setZoom(start, end) {
|
|
2584
|
-
this.chart.dispatchAction({
|
|
2585
|
-
type: "dataZoom",
|
|
2586
|
-
start,
|
|
2587
|
-
end
|
|
2588
|
-
});
|
|
2589
|
-
}
|
|
2590
|
-
setMarketData(data) {
|
|
2591
|
-
this.marketData = data;
|
|
2592
|
-
this.rebuildTimeIndex();
|
|
2593
|
-
this.render();
|
|
2594
|
-
}
|
|
2595
|
-
/**
|
|
2596
|
-
* Update market data incrementally without full re-render
|
|
2597
|
-
* Merges new/updated OHLCV data with existing data by timestamp
|
|
2598
|
-
*
|
|
2599
|
-
* @param data - Array of OHLCV data to merge
|
|
2600
|
-
*
|
|
2601
|
-
* @remarks
|
|
2602
|
-
* **Performance Optimization**: This method only triggers a chart update if the data array contains
|
|
2603
|
-
* new or modified bars. If an empty array is passed, no update occurs (expected behavior).
|
|
2604
|
-
*
|
|
2605
|
-
* **Usage Pattern for Updating Indicators**:
|
|
2606
|
-
* When updating both market data and indicators, follow this order:
|
|
2607
|
-
*
|
|
2608
|
-
* 1. Update indicator data first using `indicator.updateData(plots)`
|
|
2609
|
-
* 2. Then call `chart.updateData(newBars)` with the new/modified market data
|
|
2610
|
-
*
|
|
2611
|
-
* The chart update will trigger a re-render that includes the updated indicator data.
|
|
2612
|
-
*
|
|
2613
|
-
* **Important**: If you update indicator data without updating market data (e.g., recalculation
|
|
2614
|
-
* with same bars), you must still call `chart.updateData([...])` with at least one bar
|
|
2615
|
-
* to trigger the re-render. Calling with an empty array will NOT trigger an update.
|
|
2616
|
-
*
|
|
2617
|
-
* @example
|
|
2618
|
-
* ```typescript
|
|
2619
|
-
* // Step 1: Update indicator data
|
|
2620
|
-
* macdIndicator.updateData({
|
|
2621
|
-
* macd: { data: [{ time: 1234567890, value: 150 }], options: { style: 'line', color: '#2962FF' } }
|
|
2622
|
-
* });
|
|
2623
|
-
*
|
|
2624
|
-
* // Step 2: Update market data (triggers re-render with new indicator data)
|
|
2625
|
-
* chart.updateData([
|
|
2626
|
-
* { time: 1234567890, open: 100, high: 105, low: 99, close: 103, volume: 1000 }
|
|
2627
|
-
* ]);
|
|
2628
|
-
* ```
|
|
2629
|
-
*
|
|
2630
|
-
* @example
|
|
2631
|
-
* ```typescript
|
|
2632
|
-
* // If only updating existing bar (e.g., real-time tick updates):
|
|
2633
|
-
* const lastBar = { ...existingBar, close: newPrice, high: Math.max(existingBar.high, newPrice) };
|
|
2634
|
-
* chart.updateData([lastBar]); // Updates by timestamp
|
|
2635
|
-
* ```
|
|
2636
|
-
*/
|
|
2637
|
-
updateData(data) {
|
|
2638
|
-
if (data.length === 0)
|
|
2639
|
-
return;
|
|
2640
|
-
const existingTimeMap = /* @__PURE__ */ new Map();
|
|
2641
|
-
this.marketData.forEach((bar) => {
|
|
2642
|
-
existingTimeMap.set(bar.time, bar);
|
|
2643
|
-
});
|
|
2644
|
-
data.forEach((bar) => {
|
|
2645
|
-
if (!existingTimeMap.has(bar.time)) ;
|
|
2646
|
-
existingTimeMap.set(bar.time, bar);
|
|
2647
|
-
});
|
|
2648
|
-
this.marketData = Array.from(existingTimeMap.values()).sort((a, b) => a.time - b.time);
|
|
2649
|
-
this.rebuildTimeIndex();
|
|
2650
|
-
const paddingPoints = this.dataIndexOffset;
|
|
2651
|
-
const candlestickSeries = SeriesBuilder.buildCandlestickSeries(this.marketData, this.options);
|
|
2652
|
-
const emptyCandle = { value: [NaN, NaN, NaN, NaN], itemStyle: { opacity: 0 } };
|
|
2653
|
-
const paddedCandlestickData = [
|
|
2654
|
-
...Array(paddingPoints).fill(emptyCandle),
|
|
2655
|
-
...candlestickSeries.data,
|
|
2656
|
-
...Array(paddingPoints).fill(emptyCandle)
|
|
2657
|
-
];
|
|
2658
|
-
const categoryData = [
|
|
2659
|
-
...Array(paddingPoints).fill(""),
|
|
2660
|
-
...this.marketData.map((k) => new Date(k.time).toLocaleString()),
|
|
2661
|
-
...Array(paddingPoints).fill("")
|
|
2662
|
-
];
|
|
2663
|
-
const currentOption = this.chart.getOption();
|
|
2664
|
-
const layout = LayoutManager.calculate(
|
|
2665
|
-
this.chart.getHeight(),
|
|
2666
|
-
this.indicators,
|
|
2667
|
-
this.options,
|
|
2668
|
-
this.isMainCollapsed,
|
|
2669
|
-
this.maximizedPaneId,
|
|
2670
|
-
this.marketData
|
|
2671
|
-
);
|
|
2672
|
-
const paddedOHLCVForShapes = [...Array(paddingPoints).fill(null), ...this.marketData, ...Array(paddingPoints).fill(null)];
|
|
2673
|
-
const { series: indicatorSeries, barColors } = SeriesBuilder.buildIndicatorSeries(
|
|
2674
|
-
this.indicators,
|
|
2675
|
-
this.timeToIndex,
|
|
2676
|
-
layout.paneLayout,
|
|
2677
|
-
categoryData.length,
|
|
2678
|
-
paddingPoints,
|
|
2679
|
-
paddedOHLCVForShapes,
|
|
2680
|
-
// Pass padded OHLCV data
|
|
2681
|
-
layout.overlayYAxisMap,
|
|
2682
|
-
// Pass overlay Y-axis mapping
|
|
2683
|
-
layout.separatePaneYAxisOffset
|
|
2684
|
-
// Pass Y-axis offset for separate panes
|
|
2685
|
-
);
|
|
2686
|
-
const coloredCandlestickData = paddedCandlestickData.map((candle, i) => {
|
|
2687
|
-
if (barColors[i]) {
|
|
2688
|
-
return {
|
|
2689
|
-
value: candle.value || candle,
|
|
2690
|
-
itemStyle: {
|
|
2691
|
-
color: barColors[i],
|
|
2692
|
-
color0: barColors[i],
|
|
2693
|
-
borderColor: barColors[i],
|
|
2694
|
-
borderColor0: barColors[i]
|
|
2695
|
-
}
|
|
2696
|
-
};
|
|
2697
|
-
}
|
|
2698
|
-
return candle;
|
|
2699
|
-
});
|
|
2700
|
-
const updateOption = {
|
|
2701
|
-
xAxis: currentOption.xAxis.map((axis, index) => ({
|
|
2702
|
-
data: categoryData
|
|
2703
|
-
})),
|
|
2704
|
-
series: [
|
|
2705
|
-
{
|
|
2706
|
-
data: coloredCandlestickData,
|
|
2707
|
-
markLine: candlestickSeries.markLine
|
|
2708
|
-
// Ensure markLine is updated
|
|
2709
|
-
},
|
|
2710
|
-
...indicatorSeries.map((s) => {
|
|
2711
|
-
const update = { data: s.data };
|
|
2712
|
-
if (s.renderItem) {
|
|
2713
|
-
update.renderItem = s.renderItem;
|
|
2714
|
-
}
|
|
2715
|
-
return update;
|
|
2716
|
-
})
|
|
2717
|
-
]
|
|
2718
|
-
};
|
|
2719
|
-
this.chart.setOption(updateOption, { notMerge: false });
|
|
2720
|
-
this.startCountdown();
|
|
2721
|
-
}
|
|
2722
|
-
startCountdown() {
|
|
2723
|
-
this.stopCountdown();
|
|
2724
|
-
if (!this.options.lastPriceLine?.showCountdown || !this.options.interval || this.marketData.length === 0) {
|
|
2725
|
-
return;
|
|
2726
|
-
}
|
|
2727
|
-
const updateLabel = () => {
|
|
2728
|
-
if (this.marketData.length === 0)
|
|
2729
|
-
return;
|
|
2730
|
-
const lastBar = this.marketData[this.marketData.length - 1];
|
|
2731
|
-
const nextCloseTime = lastBar.time + (this.options.interval || 0);
|
|
2732
|
-
const now = Date.now();
|
|
2733
|
-
const diff = nextCloseTime - now;
|
|
2734
|
-
if (diff <= 0) {
|
|
2735
|
-
return;
|
|
2736
|
-
}
|
|
2737
|
-
const absDiff = Math.abs(diff);
|
|
2738
|
-
const hours = Math.floor(absDiff / 36e5);
|
|
2739
|
-
const minutes = Math.floor(absDiff % 36e5 / 6e4);
|
|
2740
|
-
const seconds = Math.floor(absDiff % 6e4 / 1e3);
|
|
2741
|
-
const timeString = `${hours > 0 ? hours.toString().padStart(2, "0") + ":" : ""}${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`;
|
|
2742
|
-
const currentOption = this.chart.getOption();
|
|
2743
|
-
if (!currentOption || !currentOption.series)
|
|
2744
|
-
return;
|
|
2745
|
-
const candleSeriesIndex = currentOption.series.findIndex((s) => s.type === "candlestick");
|
|
2746
|
-
if (candleSeriesIndex === -1)
|
|
2747
|
-
return;
|
|
2748
|
-
const candleSeries = currentOption.series[candleSeriesIndex];
|
|
2749
|
-
if (!candleSeries.markLine || !candleSeries.markLine.data || !candleSeries.markLine.data[0])
|
|
2750
|
-
return;
|
|
2751
|
-
const markLineData = candleSeries.markLine.data[0];
|
|
2752
|
-
markLineData.label.formatter;
|
|
2753
|
-
const price = markLineData.yAxis;
|
|
2754
|
-
let priceStr = "";
|
|
2755
|
-
if (this.options.yAxisLabelFormatter) {
|
|
2756
|
-
priceStr = this.options.yAxisLabelFormatter(price);
|
|
2757
|
-
} else {
|
|
2758
|
-
const decimals = this.options.yAxisDecimalPlaces !== void 0 ? this.options.yAxisDecimalPlaces : 2;
|
|
2759
|
-
priceStr = typeof price === "number" ? price.toFixed(decimals) : price;
|
|
2760
|
-
}
|
|
2761
|
-
const labelText = `${priceStr}
|
|
2762
|
-
${timeString}`;
|
|
2763
|
-
this.chart.setOption({
|
|
2764
|
-
series: [
|
|
2765
|
-
{
|
|
2766
|
-
name: this.options.title || "Market",
|
|
2767
|
-
markLine: {
|
|
2768
|
-
data: [
|
|
2769
|
-
{
|
|
2770
|
-
...markLineData,
|
|
2771
|
-
// Preserve lineStyle (color), symbol, yAxis, etc.
|
|
2772
|
-
label: {
|
|
2773
|
-
...markLineData.label,
|
|
2774
|
-
// Preserve existing label styles including backgroundColor
|
|
2775
|
-
formatter: labelText
|
|
2776
|
-
// Update only the text
|
|
2777
|
-
}
|
|
2778
|
-
}
|
|
2779
|
-
]
|
|
2780
|
-
}
|
|
2781
|
-
}
|
|
2782
|
-
]
|
|
2783
|
-
});
|
|
2784
|
-
};
|
|
2785
|
-
updateLabel();
|
|
2786
|
-
this.countdownInterval = setInterval(updateLabel, 1e3);
|
|
2787
|
-
}
|
|
2788
|
-
stopCountdown() {
|
|
2789
|
-
if (this.countdownInterval) {
|
|
2790
|
-
clearInterval(this.countdownInterval);
|
|
2791
|
-
this.countdownInterval = null;
|
|
2792
|
-
}
|
|
2793
|
-
}
|
|
2794
|
-
addIndicator(id, plots, options = {}) {
|
|
2795
|
-
const isOverlay = options.overlay !== void 0 ? options.overlay : options.isOverlay ?? false;
|
|
2796
|
-
let paneIndex = 0;
|
|
2797
|
-
if (!isOverlay) {
|
|
2798
|
-
let maxPaneIndex = 0;
|
|
2799
|
-
this.indicators.forEach((ind) => {
|
|
2800
|
-
if (ind.paneIndex > maxPaneIndex) {
|
|
2801
|
-
maxPaneIndex = ind.paneIndex;
|
|
2802
|
-
}
|
|
2803
|
-
});
|
|
2804
|
-
paneIndex = maxPaneIndex + 1;
|
|
2805
|
-
}
|
|
2806
|
-
const indicator = new Indicator(id, plots, paneIndex, {
|
|
2807
|
-
height: options.height,
|
|
2808
|
-
collapsed: false,
|
|
2809
|
-
titleColor: options.titleColor,
|
|
2810
|
-
controls: options.controls
|
|
2811
|
-
});
|
|
2812
|
-
this.indicators.set(id, indicator);
|
|
2813
|
-
this.render();
|
|
2814
|
-
return indicator;
|
|
2815
|
-
}
|
|
2816
|
-
/** @deprecated Use addIndicator instead */
|
|
2817
|
-
setIndicator(id, plot, isOverlay = false) {
|
|
2818
|
-
this.addIndicator(id, { [id]: plot }, { overlay: isOverlay });
|
|
2819
|
-
}
|
|
2820
|
-
removeIndicator(id) {
|
|
2821
|
-
this.indicators.delete(id);
|
|
2822
|
-
this.render();
|
|
2823
|
-
}
|
|
2824
|
-
toggleIndicator(id, action = "collapse") {
|
|
2825
|
-
if (action === "fullscreen") {
|
|
2826
|
-
if (document.fullscreenElement) {
|
|
2827
|
-
document.exitFullscreen();
|
|
2828
|
-
} else {
|
|
2829
|
-
this.rootContainer.requestFullscreen();
|
|
2830
|
-
}
|
|
2831
|
-
return;
|
|
2832
|
-
}
|
|
2833
|
-
if (action === "maximize") {
|
|
2834
|
-
if (this.maximizedPaneId === id) {
|
|
2835
|
-
this.maximizedPaneId = null;
|
|
2836
|
-
} else {
|
|
2837
|
-
this.maximizedPaneId = id;
|
|
2838
|
-
}
|
|
2839
|
-
this.render();
|
|
2840
|
-
return;
|
|
2841
|
-
}
|
|
2842
|
-
if (id === "main") {
|
|
2843
|
-
this.isMainCollapsed = !this.isMainCollapsed;
|
|
2844
|
-
this.render();
|
|
2845
|
-
return;
|
|
2846
|
-
}
|
|
2847
|
-
const indicator = this.indicators.get(id);
|
|
2848
|
-
if (indicator) {
|
|
2849
|
-
indicator.toggleCollapse();
|
|
2850
|
-
this.render();
|
|
2851
|
-
}
|
|
2852
|
-
}
|
|
2853
|
-
resize() {
|
|
2854
|
-
this.chart.resize();
|
|
2855
|
-
}
|
|
2856
|
-
destroy() {
|
|
2857
|
-
this.stopCountdown();
|
|
2858
|
-
window.removeEventListener("resize", this.resize.bind(this));
|
|
2859
|
-
document.removeEventListener("fullscreenchange", this.onFullscreenChange);
|
|
2860
|
-
document.removeEventListener("keydown", this.onKeyDown);
|
|
2861
|
-
this.pluginManager.deactivatePlugin();
|
|
2862
|
-
this.pluginManager.destroy();
|
|
2863
|
-
this.chart.dispose();
|
|
2864
|
-
}
|
|
2865
|
-
rebuildTimeIndex() {
|
|
2866
|
-
this.timeToIndex.clear();
|
|
2867
|
-
this.marketData.forEach((k, index) => {
|
|
2868
|
-
this.timeToIndex.set(k.time, index);
|
|
2869
|
-
});
|
|
2870
|
-
const dataLength = this.marketData.length;
|
|
2871
|
-
const paddingPoints = Math.ceil(dataLength * this.padding);
|
|
2872
|
-
this.dataIndexOffset = paddingPoints;
|
|
2873
|
-
}
|
|
2874
|
-
render() {
|
|
2875
|
-
if (this.marketData.length === 0)
|
|
2876
|
-
return;
|
|
2877
|
-
let currentZoomState = null;
|
|
2878
|
-
try {
|
|
2879
|
-
const currentOption = this.chart.getOption();
|
|
2880
|
-
if (currentOption && currentOption.dataZoom && currentOption.dataZoom.length > 0) {
|
|
2881
|
-
const zoomComponent = currentOption.dataZoom.find((dz) => dz.type === "slider" || dz.type === "inside");
|
|
2882
|
-
if (zoomComponent) {
|
|
2883
|
-
currentZoomState = {
|
|
2884
|
-
start: zoomComponent.start,
|
|
2885
|
-
end: zoomComponent.end
|
|
2886
|
-
};
|
|
2887
|
-
}
|
|
2888
|
-
}
|
|
2889
|
-
} catch (e) {
|
|
2890
|
-
}
|
|
2891
|
-
const tooltipPos = this.options.databox?.position;
|
|
2892
|
-
const prevLeftDisplay = this.leftSidebar.style.display;
|
|
2893
|
-
const prevRightDisplay = this.rightSidebar.style.display;
|
|
2894
|
-
const newLeftDisplay = tooltipPos === "left" ? "block" : "none";
|
|
2895
|
-
const newRightDisplay = tooltipPos === "right" ? "block" : "none";
|
|
2896
|
-
if (prevLeftDisplay !== newLeftDisplay || prevRightDisplay !== newRightDisplay) {
|
|
2897
|
-
this.leftSidebar.style.display = newLeftDisplay;
|
|
2898
|
-
this.rightSidebar.style.display = newRightDisplay;
|
|
2899
|
-
this.chart.resize();
|
|
2900
|
-
}
|
|
2901
|
-
const paddingPoints = this.dataIndexOffset;
|
|
2902
|
-
const categoryData = [
|
|
2903
|
-
...Array(paddingPoints).fill(""),
|
|
2904
|
-
// Left padding
|
|
2905
|
-
...this.marketData.map((k) => new Date(k.time).toLocaleString()),
|
|
2906
|
-
...Array(paddingPoints).fill("")
|
|
2907
|
-
// Right padding
|
|
2908
|
-
];
|
|
2909
|
-
const layout = LayoutManager.calculate(
|
|
2910
|
-
this.chart.getHeight(),
|
|
2911
|
-
this.indicators,
|
|
2912
|
-
this.options,
|
|
2913
|
-
this.isMainCollapsed,
|
|
2914
|
-
this.maximizedPaneId,
|
|
2915
|
-
this.marketData
|
|
2916
|
-
);
|
|
2917
|
-
if (!currentZoomState && layout.dataZoom && this.marketData.length > 0) {
|
|
2918
|
-
const realDataLength = this.marketData.length;
|
|
2919
|
-
const totalLength = categoryData.length;
|
|
2920
|
-
const paddingRatio = paddingPoints / totalLength;
|
|
2921
|
-
const dataRatio = realDataLength / totalLength;
|
|
2922
|
-
layout.dataZoom.forEach((dz) => {
|
|
2923
|
-
if (dz.start !== void 0) {
|
|
2924
|
-
const userStartFraction = dz.start / 100;
|
|
2925
|
-
const actualStartFraction = paddingRatio + userStartFraction * dataRatio;
|
|
2926
|
-
dz.start = actualStartFraction * 100;
|
|
2927
|
-
}
|
|
2928
|
-
if (dz.end !== void 0) {
|
|
2929
|
-
const userEndFraction = dz.end / 100;
|
|
2930
|
-
const actualEndFraction = paddingRatio + userEndFraction * dataRatio;
|
|
2931
|
-
dz.end = actualEndFraction * 100;
|
|
2932
|
-
}
|
|
2933
|
-
});
|
|
2934
|
-
}
|
|
2935
|
-
if (currentZoomState && layout.dataZoom) {
|
|
2936
|
-
layout.dataZoom.forEach((dz) => {
|
|
2937
|
-
dz.start = currentZoomState.start;
|
|
2938
|
-
dz.end = currentZoomState.end;
|
|
2939
|
-
});
|
|
2940
|
-
}
|
|
2941
|
-
layout.xAxis.forEach((axis) => {
|
|
2942
|
-
axis.data = categoryData;
|
|
2943
|
-
axis.boundaryGap = false;
|
|
2944
|
-
});
|
|
2945
|
-
const candlestickSeries = SeriesBuilder.buildCandlestickSeries(this.marketData, this.options);
|
|
2946
|
-
const emptyCandle = { value: [NaN, NaN, NaN, NaN], itemStyle: { opacity: 0 } };
|
|
2947
|
-
candlestickSeries.data = [...Array(paddingPoints).fill(emptyCandle), ...candlestickSeries.data, ...Array(paddingPoints).fill(emptyCandle)];
|
|
2948
|
-
const paddedOHLCVForShapes = [...Array(paddingPoints).fill(null), ...this.marketData, ...Array(paddingPoints).fill(null)];
|
|
2949
|
-
const { series: indicatorSeries, barColors } = SeriesBuilder.buildIndicatorSeries(
|
|
2950
|
-
this.indicators,
|
|
2951
|
-
this.timeToIndex,
|
|
2952
|
-
layout.paneLayout,
|
|
2953
|
-
categoryData.length,
|
|
2954
|
-
paddingPoints,
|
|
2955
|
-
paddedOHLCVForShapes,
|
|
2956
|
-
// Pass padded OHLCV
|
|
2957
|
-
layout.overlayYAxisMap,
|
|
2958
|
-
// Pass overlay Y-axis mapping
|
|
2959
|
-
layout.separatePaneYAxisOffset
|
|
2960
|
-
// Pass Y-axis offset for separate panes
|
|
2961
|
-
);
|
|
2962
|
-
candlestickSeries.data = candlestickSeries.data.map((candle, i) => {
|
|
2963
|
-
if (barColors[i]) {
|
|
2964
|
-
return {
|
|
2965
|
-
value: candle.value || candle,
|
|
2966
|
-
itemStyle: {
|
|
2967
|
-
color: barColors[i],
|
|
2968
|
-
color0: barColors[i],
|
|
2969
|
-
borderColor: barColors[i],
|
|
2970
|
-
borderColor0: barColors[i]
|
|
2971
|
-
}
|
|
2972
|
-
};
|
|
2973
|
-
}
|
|
2974
|
-
return candle;
|
|
2975
|
-
});
|
|
2976
|
-
const graphic = GraphicBuilder.build(layout, this.options, this.toggleIndicator.bind(this), this.isMainCollapsed, this.maximizedPaneId);
|
|
2977
|
-
const drawingsByPane = /* @__PURE__ */ new Map();
|
|
2978
|
-
this.drawings.forEach((d) => {
|
|
2979
|
-
const paneIdx = d.paneIndex || 0;
|
|
2980
|
-
if (!drawingsByPane.has(paneIdx)) {
|
|
2981
|
-
drawingsByPane.set(paneIdx, []);
|
|
2982
|
-
}
|
|
2983
|
-
drawingsByPane.get(paneIdx).push(d);
|
|
2984
|
-
});
|
|
2985
|
-
const drawingSeriesList = [];
|
|
2986
|
-
drawingsByPane.forEach((drawings, paneIndex) => {
|
|
2987
|
-
drawingSeriesList.push({
|
|
2988
|
-
type: "custom",
|
|
2989
|
-
name: `drawings-pane-${paneIndex}`,
|
|
2990
|
-
xAxisIndex: paneIndex,
|
|
2991
|
-
yAxisIndex: paneIndex,
|
|
2992
|
-
clip: true,
|
|
2993
|
-
renderItem: (params, api) => {
|
|
2994
|
-
const drawing = drawings[params.dataIndex];
|
|
2995
|
-
if (!drawing)
|
|
2996
|
-
return;
|
|
2997
|
-
const start = drawing.points[0];
|
|
2998
|
-
const end = drawing.points[1];
|
|
2999
|
-
if (!start || !end)
|
|
3000
|
-
return;
|
|
3001
|
-
const p1 = api.coord([start.timeIndex, start.value]);
|
|
3002
|
-
const p2 = api.coord([end.timeIndex, end.value]);
|
|
3003
|
-
const isSelected = drawing.id === this.selectedDrawingId;
|
|
3004
|
-
if (drawing.type === "line") {
|
|
3005
|
-
return {
|
|
3006
|
-
type: "group",
|
|
3007
|
-
children: [
|
|
3008
|
-
{
|
|
3009
|
-
type: "line",
|
|
3010
|
-
name: "line",
|
|
3011
|
-
shape: {
|
|
3012
|
-
x1: p1[0],
|
|
3013
|
-
y1: p1[1],
|
|
3014
|
-
x2: p2[0],
|
|
3015
|
-
y2: p2[1]
|
|
3016
|
-
},
|
|
3017
|
-
style: {
|
|
3018
|
-
stroke: drawing.style?.color || "#3b82f6",
|
|
3019
|
-
lineWidth: drawing.style?.lineWidth || 2
|
|
3020
|
-
}
|
|
3021
|
-
},
|
|
3022
|
-
{
|
|
3023
|
-
type: "circle",
|
|
3024
|
-
name: "point-start",
|
|
3025
|
-
shape: { cx: p1[0], cy: p1[1], r: 4 },
|
|
3026
|
-
style: {
|
|
3027
|
-
fill: "#fff",
|
|
3028
|
-
stroke: drawing.style?.color || "#3b82f6",
|
|
3029
|
-
lineWidth: 1,
|
|
3030
|
-
opacity: isSelected ? 1 : 0
|
|
3031
|
-
// Show if selected
|
|
3032
|
-
}
|
|
3033
|
-
},
|
|
3034
|
-
{
|
|
3035
|
-
type: "circle",
|
|
3036
|
-
name: "point-end",
|
|
3037
|
-
shape: { cx: p2[0], cy: p2[1], r: 4 },
|
|
3038
|
-
style: {
|
|
3039
|
-
fill: "#fff",
|
|
3040
|
-
stroke: drawing.style?.color || "#3b82f6",
|
|
3041
|
-
lineWidth: 1,
|
|
3042
|
-
opacity: isSelected ? 1 : 0
|
|
3043
|
-
// Show if selected
|
|
3044
|
-
}
|
|
3045
|
-
}
|
|
3046
|
-
]
|
|
3047
|
-
};
|
|
3048
|
-
} else if (drawing.type === "fibonacci") {
|
|
3049
|
-
const x1 = p1[0];
|
|
3050
|
-
const y1 = p1[1];
|
|
3051
|
-
const x2 = p2[0];
|
|
3052
|
-
const y2 = p2[1];
|
|
3053
|
-
const startX = Math.min(x1, x2);
|
|
3054
|
-
const endX = Math.max(x1, x2);
|
|
3055
|
-
const width = endX - startX;
|
|
3056
|
-
const diffY = y2 - y1;
|
|
3057
|
-
const levels = [0, 0.236, 0.382, 0.5, 0.618, 0.786, 1];
|
|
3058
|
-
const colors = ["#787b86", "#f44336", "#ff9800", "#4caf50", "#2196f3", "#00bcd4", "#787b86"];
|
|
3059
|
-
const children = [];
|
|
3060
|
-
children.push({
|
|
3061
|
-
type: "line",
|
|
3062
|
-
name: "line",
|
|
3063
|
-
// Use 'line' name to enable dragging logic in DrawingEditor
|
|
3064
|
-
shape: { x1, y1, x2, y2 },
|
|
3065
|
-
style: {
|
|
3066
|
-
stroke: "#999",
|
|
3067
|
-
lineWidth: 1,
|
|
3068
|
-
lineDash: [4, 4]
|
|
3069
|
-
}
|
|
3070
|
-
});
|
|
3071
|
-
children.push({
|
|
3072
|
-
type: "circle",
|
|
3073
|
-
name: "point-start",
|
|
3074
|
-
shape: { cx: x1, cy: y1, r: 4 },
|
|
3075
|
-
style: {
|
|
3076
|
-
fill: "#fff",
|
|
3077
|
-
stroke: drawing.style?.color || "#3b82f6",
|
|
3078
|
-
lineWidth: 1,
|
|
3079
|
-
opacity: isSelected ? 1 : 0
|
|
3080
|
-
},
|
|
3081
|
-
z: 100
|
|
3082
|
-
// Ensure on top
|
|
3083
|
-
});
|
|
3084
|
-
children.push({
|
|
3085
|
-
type: "circle",
|
|
3086
|
-
name: "point-end",
|
|
3087
|
-
shape: { cx: x2, cy: y2, r: 4 },
|
|
3088
|
-
style: {
|
|
3089
|
-
fill: "#fff",
|
|
3090
|
-
stroke: drawing.style?.color || "#3b82f6",
|
|
3091
|
-
lineWidth: 1,
|
|
3092
|
-
opacity: isSelected ? 1 : 0
|
|
3093
|
-
},
|
|
3094
|
-
z: 100
|
|
3095
|
-
});
|
|
3096
|
-
levels.forEach((level, index) => {
|
|
3097
|
-
const levelY = y2 - diffY * level;
|
|
3098
|
-
const color = colors[index % colors.length];
|
|
3099
|
-
children.push({
|
|
3100
|
-
type: "line",
|
|
3101
|
-
name: "fib-line",
|
|
3102
|
-
// distinct name, maybe we don't want to drag by clicking these lines? or yes? 'line' triggers drag. 'fib-line' won't unless we update logic.
|
|
3103
|
-
// The user asked for "fib levels between start and end".
|
|
3104
|
-
shape: { x1: startX, y1: levelY, x2: endX, y2: levelY },
|
|
3105
|
-
style: { stroke: color, lineWidth: 1 },
|
|
3106
|
-
silent: true
|
|
3107
|
-
// Make internal lines silent so clicks pass to background/diagonal?
|
|
3108
|
-
});
|
|
3109
|
-
const startVal = drawing.points[0].value;
|
|
3110
|
-
const endVal = drawing.points[1].value;
|
|
3111
|
-
const valDiff = endVal - startVal;
|
|
3112
|
-
const price = endVal - valDiff * level;
|
|
3113
|
-
children.push({
|
|
3114
|
-
type: "text",
|
|
3115
|
-
style: {
|
|
3116
|
-
text: `${level} (${price.toFixed(2)})`,
|
|
3117
|
-
x: startX + 5,
|
|
3118
|
-
y: levelY - 10,
|
|
3119
|
-
fill: color,
|
|
3120
|
-
fontSize: 10
|
|
3121
|
-
},
|
|
3122
|
-
silent: true
|
|
3123
|
-
});
|
|
3124
|
-
if (index < levels.length - 1) {
|
|
3125
|
-
const nextLevel = levels[index + 1];
|
|
3126
|
-
const nextY = y2 - diffY * nextLevel;
|
|
3127
|
-
const rectH = Math.abs(nextY - levelY);
|
|
3128
|
-
const rectY = Math.min(levelY, nextY);
|
|
3129
|
-
children.push({
|
|
3130
|
-
type: "rect",
|
|
3131
|
-
shape: { x: startX, y: rectY, width, height: rectH },
|
|
3132
|
-
style: {
|
|
3133
|
-
fill: colors[(index + 1) % colors.length],
|
|
3134
|
-
opacity: 0.1
|
|
3135
|
-
},
|
|
3136
|
-
silent: true
|
|
3137
|
-
// Let clicks pass through?
|
|
3138
|
-
});
|
|
3139
|
-
}
|
|
3140
|
-
});
|
|
3141
|
-
const backgrounds = [];
|
|
3142
|
-
const linesAndText = [];
|
|
3143
|
-
levels.forEach((level, index) => {
|
|
3144
|
-
const levelY = y2 - diffY * level;
|
|
3145
|
-
const color = colors[index % colors.length];
|
|
3146
|
-
linesAndText.push({
|
|
3147
|
-
type: "line",
|
|
3148
|
-
shape: { x1: startX, y1: levelY, x2: endX, y2: levelY },
|
|
3149
|
-
style: { stroke: color, lineWidth: 1 },
|
|
3150
|
-
silent: true
|
|
3151
|
-
});
|
|
3152
|
-
const startVal = drawing.points[0].value;
|
|
3153
|
-
const endVal = drawing.points[1].value;
|
|
3154
|
-
const valDiff = endVal - startVal;
|
|
3155
|
-
const price = endVal - valDiff * level;
|
|
3156
|
-
linesAndText.push({
|
|
3157
|
-
type: "text",
|
|
3158
|
-
style: {
|
|
3159
|
-
text: `${level} (${price.toFixed(2)})`,
|
|
3160
|
-
x: startX + 5,
|
|
3161
|
-
y: levelY - 10,
|
|
3162
|
-
fill: color,
|
|
3163
|
-
fontSize: 10
|
|
3164
|
-
},
|
|
3165
|
-
silent: true
|
|
3166
|
-
});
|
|
3167
|
-
if (index < levels.length - 1) {
|
|
3168
|
-
const nextLevel = levels[index + 1];
|
|
3169
|
-
const nextY = y2 - diffY * nextLevel;
|
|
3170
|
-
const rectH = Math.abs(nextY - levelY);
|
|
3171
|
-
const rectY = Math.min(levelY, nextY);
|
|
3172
|
-
backgrounds.push({
|
|
3173
|
-
type: "rect",
|
|
3174
|
-
name: "line",
|
|
3175
|
-
// Enable dragging by clicking background!
|
|
3176
|
-
shape: { x: startX, y: rectY, width, height: rectH },
|
|
3177
|
-
style: {
|
|
3178
|
-
fill: colors[(index + 1) % colors.length],
|
|
3179
|
-
opacity: 0.1
|
|
3180
|
-
}
|
|
3181
|
-
});
|
|
3182
|
-
}
|
|
3183
|
-
});
|
|
3184
|
-
return {
|
|
3185
|
-
type: "group",
|
|
3186
|
-
children: [
|
|
3187
|
-
...backgrounds,
|
|
3188
|
-
...linesAndText,
|
|
3189
|
-
{
|
|
3190
|
-
type: "line",
|
|
3191
|
-
name: "line",
|
|
3192
|
-
shape: { x1, y1, x2, y2 },
|
|
3193
|
-
style: { stroke: "#999", lineWidth: 1, lineDash: [4, 4] }
|
|
3194
|
-
},
|
|
3195
|
-
{
|
|
3196
|
-
type: "circle",
|
|
3197
|
-
name: "point-start",
|
|
3198
|
-
shape: { cx: x1, cy: y1, r: 4 },
|
|
3199
|
-
style: {
|
|
3200
|
-
fill: "#fff",
|
|
3201
|
-
stroke: drawing.style?.color || "#3b82f6",
|
|
3202
|
-
lineWidth: 1,
|
|
3203
|
-
opacity: isSelected ? 1 : 0
|
|
3204
|
-
},
|
|
3205
|
-
z: 100
|
|
3206
|
-
},
|
|
3207
|
-
{
|
|
3208
|
-
type: "circle",
|
|
3209
|
-
name: "point-end",
|
|
3210
|
-
shape: { cx: x2, cy: y2, r: 4 },
|
|
3211
|
-
style: {
|
|
3212
|
-
fill: "#fff",
|
|
3213
|
-
stroke: drawing.style?.color || "#3b82f6",
|
|
3214
|
-
lineWidth: 1,
|
|
3215
|
-
opacity: isSelected ? 1 : 0
|
|
3216
|
-
},
|
|
3217
|
-
z: 100
|
|
3218
|
-
}
|
|
3219
|
-
]
|
|
3220
|
-
};
|
|
3221
|
-
}
|
|
3222
|
-
},
|
|
3223
|
-
data: drawings.map((d) => [d.points[0].timeIndex, d.points[0].value, d.points[1].timeIndex, d.points[1].value]),
|
|
3224
|
-
z: 100,
|
|
3225
|
-
silent: false
|
|
3226
|
-
});
|
|
3227
|
-
});
|
|
3228
|
-
const tooltipFormatter = (params) => {
|
|
3229
|
-
const html = TooltipFormatter.format(params, this.options);
|
|
3230
|
-
const mode = this.options.databox?.position;
|
|
3231
|
-
if (mode === "left") {
|
|
3232
|
-
this.leftSidebar.innerHTML = html;
|
|
3233
|
-
return "";
|
|
3234
|
-
}
|
|
3235
|
-
if (mode === "right") {
|
|
3236
|
-
this.rightSidebar.innerHTML = html;
|
|
3237
|
-
return "";
|
|
3238
|
-
}
|
|
3239
|
-
if (!this.options.databox) {
|
|
3240
|
-
return "";
|
|
3241
|
-
}
|
|
3242
|
-
return `<div style="min-width: 200px;">${html}</div>`;
|
|
3243
|
-
};
|
|
3244
|
-
const option = {
|
|
3245
|
-
backgroundColor: this.options.backgroundColor,
|
|
3246
|
-
animation: false,
|
|
3247
|
-
legend: {
|
|
3248
|
-
show: false
|
|
3249
|
-
// Hide default legend as we use tooltip
|
|
3250
|
-
},
|
|
3251
|
-
tooltip: {
|
|
3252
|
-
show: true,
|
|
3253
|
-
showContent: !!this.options.databox,
|
|
3254
|
-
// Show content only if databox is present
|
|
3255
|
-
trigger: "axis",
|
|
3256
|
-
triggerOn: this.options.databox?.triggerOn ?? "mousemove",
|
|
3257
|
-
// Control when to show tooltip/crosshair
|
|
3258
|
-
axisPointer: { type: "cross", label: { backgroundColor: "#475569" } },
|
|
3259
|
-
backgroundColor: "rgba(30, 41, 59, 0.9)",
|
|
3260
|
-
borderWidth: 1,
|
|
3261
|
-
borderColor: "#334155",
|
|
3262
|
-
padding: 10,
|
|
3263
|
-
textStyle: {
|
|
3264
|
-
color: "#fff",
|
|
3265
|
-
fontFamily: this.options.fontFamily || "sans-serif"
|
|
3266
|
-
},
|
|
3267
|
-
formatter: tooltipFormatter,
|
|
3268
|
-
extraCssText: tooltipPos !== "floating" && tooltipPos !== void 0 ? "display: none !important;" : void 0,
|
|
3269
|
-
position: (pos, params, el, elRect, size) => {
|
|
3270
|
-
const mode = this.options.databox?.position;
|
|
3271
|
-
if (mode === "floating") {
|
|
3272
|
-
const obj = { top: 10 };
|
|
3273
|
-
obj[["left", "right"][+(pos[0] < size.viewSize[0] / 2)]] = 30;
|
|
3274
|
-
return obj;
|
|
3275
|
-
}
|
|
3276
|
-
return null;
|
|
3277
|
-
}
|
|
3278
|
-
},
|
|
3279
|
-
axisPointer: {
|
|
3280
|
-
link: { xAxisIndex: "all" },
|
|
3281
|
-
label: { backgroundColor: "#475569" }
|
|
3282
|
-
},
|
|
3283
|
-
graphic,
|
|
3284
|
-
grid: layout.grid,
|
|
3285
|
-
xAxis: layout.xAxis,
|
|
3286
|
-
yAxis: layout.yAxis,
|
|
3287
|
-
dataZoom: layout.dataZoom,
|
|
3288
|
-
series: [candlestickSeries, ...indicatorSeries, ...drawingSeriesList]
|
|
3289
|
-
};
|
|
3290
|
-
this.chart.setOption(option, true);
|
|
3291
|
-
}
|
|
3292
|
-
}
|
|
3293
|
-
|
|
3294
|
-
var __defProp$3 = Object.defineProperty;
|
|
3295
|
-
var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3296
|
-
var __publicField$3 = (obj, key, value) => {
|
|
3297
|
-
__defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
3298
|
-
return value;
|
|
3299
|
-
};
|
|
3300
|
-
class AbstractPlugin {
|
|
3301
|
-
constructor(config) {
|
|
3302
|
-
__publicField$3(this, "id");
|
|
3303
|
-
__publicField$3(this, "name");
|
|
3304
|
-
__publicField$3(this, "icon");
|
|
3305
|
-
__publicField$3(this, "context");
|
|
3306
|
-
__publicField$3(this, "eventListeners", []);
|
|
3307
|
-
this.id = config.id;
|
|
3308
|
-
this.name = config.name;
|
|
3309
|
-
this.icon = config.icon;
|
|
3310
|
-
}
|
|
3311
|
-
init(context) {
|
|
3312
|
-
this.context = context;
|
|
3313
|
-
this.onInit();
|
|
3314
|
-
}
|
|
3315
|
-
/**
|
|
3316
|
-
* Lifecycle hook called after context is initialized.
|
|
3317
|
-
* Override this instead of init().
|
|
3318
|
-
*/
|
|
3319
|
-
onInit() {
|
|
3320
|
-
}
|
|
3321
|
-
activate() {
|
|
3322
|
-
this.onActivate();
|
|
3323
|
-
this.context.events.emit("plugin:activated", this.id);
|
|
3324
|
-
}
|
|
3325
|
-
/**
|
|
3326
|
-
* Lifecycle hook called when the plugin is activated.
|
|
3327
|
-
*/
|
|
3328
|
-
onActivate() {
|
|
3329
|
-
}
|
|
3330
|
-
deactivate() {
|
|
3331
|
-
this.onDeactivate();
|
|
3332
|
-
this.context.events.emit("plugin:deactivated", this.id);
|
|
3333
|
-
}
|
|
3334
|
-
/**
|
|
3335
|
-
* Lifecycle hook called when the plugin is deactivated.
|
|
3336
|
-
*/
|
|
3337
|
-
onDeactivate() {
|
|
3338
|
-
}
|
|
3339
|
-
destroy() {
|
|
3340
|
-
this.removeAllListeners();
|
|
3341
|
-
this.onDestroy();
|
|
3342
|
-
}
|
|
3343
|
-
/**
|
|
3344
|
-
* Lifecycle hook called when the plugin is destroyed.
|
|
3345
|
-
*/
|
|
3346
|
-
onDestroy() {
|
|
3347
|
-
}
|
|
3348
|
-
// --- Helper Methods ---
|
|
3349
|
-
/**
|
|
3350
|
-
* Register an event listener that will be automatically cleaned up on destroy.
|
|
3351
|
-
*/
|
|
3352
|
-
on(event, handler) {
|
|
3353
|
-
this.context.events.on(event, handler);
|
|
3354
|
-
this.eventListeners.push({ event, handler });
|
|
3355
|
-
}
|
|
3356
|
-
/**
|
|
3357
|
-
* Remove a specific event listener.
|
|
3358
|
-
*/
|
|
3359
|
-
off(event, handler) {
|
|
3360
|
-
this.context.events.off(event, handler);
|
|
3361
|
-
this.eventListeners = this.eventListeners.filter(
|
|
3362
|
-
(l) => l.event !== event || l.handler !== handler
|
|
3363
|
-
);
|
|
3364
|
-
}
|
|
3365
|
-
/**
|
|
3366
|
-
* Remove all listeners registered by this plugin.
|
|
3367
|
-
*/
|
|
3368
|
-
removeAllListeners() {
|
|
3369
|
-
this.eventListeners.forEach(({ event, handler }) => {
|
|
3370
|
-
this.context.events.off(event, handler);
|
|
3371
|
-
});
|
|
3372
|
-
this.eventListeners = [];
|
|
3373
|
-
}
|
|
3374
|
-
/**
|
|
3375
|
-
* Access to the ECharts instance.
|
|
3376
|
-
*/
|
|
3377
|
-
get chart() {
|
|
3378
|
-
return this.context.getChart();
|
|
3379
|
-
}
|
|
3380
|
-
/**
|
|
3381
|
-
* Access to market data.
|
|
3382
|
-
*/
|
|
3383
|
-
get marketData() {
|
|
3384
|
-
return this.context.getMarketData();
|
|
3385
|
-
}
|
|
3386
|
-
}
|
|
3387
|
-
|
|
3388
|
-
var __defProp$2 = Object.defineProperty;
|
|
3389
|
-
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3390
|
-
var __publicField$2 = (obj, key, value) => {
|
|
3391
|
-
__defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
3392
|
-
return value;
|
|
3393
|
-
};
|
|
3394
|
-
class MeasureTool extends AbstractPlugin {
|
|
3395
|
-
// End Arrow
|
|
3396
|
-
constructor(options) {
|
|
3397
|
-
super({
|
|
3398
|
-
id: "measure",
|
|
3399
|
-
name: options?.name || "Measure",
|
|
3400
|
-
icon: options?.icon || `<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="M160-240q-33 0-56.5-23.5T80-320v-320q0-33 23.5-56.5T160-720h640q33 0 56.5 23.5T880-640v320q0 33-23.5 56.5T800-240H160Zm0-80h640v-320H680v160h-80v-160h-80v160h-80v-160h-80v160h-80v-160H160v320Zm120-160h80-80Zm160 0h80-80Zm160 0h80-80Zm-120 0Z"/></svg>`
|
|
3401
|
-
});
|
|
3402
|
-
__publicField$2(this, "zr");
|
|
3403
|
-
__publicField$2(this, "state", "idle");
|
|
3404
|
-
__publicField$2(this, "startPoint", null);
|
|
3405
|
-
__publicField$2(this, "endPoint", null);
|
|
3406
|
-
// ZRender Elements
|
|
3407
|
-
__publicField$2(this, "group", null);
|
|
3408
|
-
__publicField$2(this, "rect", null);
|
|
3409
|
-
// Measurement Box
|
|
3410
|
-
__publicField$2(this, "labelRect", null);
|
|
3411
|
-
// Label Background
|
|
3412
|
-
__publicField$2(this, "labelText", null);
|
|
3413
|
-
// Label Text
|
|
3414
|
-
__publicField$2(this, "lineV", null);
|
|
3415
|
-
// Vertical Arrow Line
|
|
3416
|
-
__publicField$2(this, "lineH", null);
|
|
3417
|
-
// Horizontal Arrow Line
|
|
3418
|
-
__publicField$2(this, "arrowStart", null);
|
|
3419
|
-
// Start Arrow
|
|
3420
|
-
__publicField$2(this, "arrowEnd", null);
|
|
3421
|
-
// --- Interaction Handlers ---
|
|
3422
|
-
__publicField$2(this, "onMouseDown", () => {
|
|
3423
|
-
if (this.state === "finished") {
|
|
3424
|
-
this.removeGraphic();
|
|
3425
|
-
}
|
|
3426
|
-
});
|
|
3427
|
-
__publicField$2(this, "onChartInteraction", () => {
|
|
3428
|
-
if (this.group) {
|
|
3429
|
-
this.removeGraphic();
|
|
3430
|
-
}
|
|
3431
|
-
});
|
|
3432
|
-
__publicField$2(this, "onClick", (params) => {
|
|
3433
|
-
if (this.state === "idle") {
|
|
3434
|
-
this.state = "drawing";
|
|
3435
|
-
this.startPoint = [params.offsetX, params.offsetY];
|
|
3436
|
-
this.endPoint = [params.offsetX, params.offsetY];
|
|
3437
|
-
this.initGraphic();
|
|
3438
|
-
this.updateGraphic();
|
|
3439
|
-
} else if (this.state === "drawing") {
|
|
3440
|
-
this.state = "finished";
|
|
3441
|
-
this.endPoint = [params.offsetX, params.offsetY];
|
|
3442
|
-
this.updateGraphic();
|
|
3443
|
-
this.context.disableTools();
|
|
3444
|
-
this.enableClearListeners();
|
|
3445
|
-
}
|
|
3446
|
-
});
|
|
3447
|
-
__publicField$2(this, "clearHandlers", {});
|
|
3448
|
-
__publicField$2(this, "onMouseMove", (params) => {
|
|
3449
|
-
if (this.state !== "drawing")
|
|
3450
|
-
return;
|
|
3451
|
-
this.endPoint = [params.offsetX, params.offsetY];
|
|
3452
|
-
this.updateGraphic();
|
|
3453
|
-
});
|
|
3454
|
-
}
|
|
3455
|
-
onInit() {
|
|
3456
|
-
this.zr = this.chart.getZr();
|
|
3457
|
-
}
|
|
3458
|
-
onActivate() {
|
|
3459
|
-
this.state = "idle";
|
|
3460
|
-
this.chart.getZr().setCursorStyle("crosshair");
|
|
3461
|
-
this.zr.on("click", this.onClick);
|
|
3462
|
-
this.zr.on("mousemove", this.onMouseMove);
|
|
3463
|
-
}
|
|
3464
|
-
onDeactivate() {
|
|
3465
|
-
this.state = "idle";
|
|
3466
|
-
this.chart.getZr().setCursorStyle("default");
|
|
3467
|
-
this.zr.off("click", this.onClick);
|
|
3468
|
-
this.zr.off("mousemove", this.onMouseMove);
|
|
3469
|
-
this.disableClearListeners();
|
|
3470
|
-
if (this.state === "drawing") {
|
|
3471
|
-
this.removeGraphic();
|
|
3472
|
-
}
|
|
3473
|
-
}
|
|
3474
|
-
onDestroy() {
|
|
3475
|
-
this.removeGraphic();
|
|
3476
|
-
}
|
|
3477
|
-
enableClearListeners() {
|
|
3478
|
-
const clickHandler = () => {
|
|
3479
|
-
this.removeGraphic();
|
|
3480
|
-
};
|
|
3481
|
-
setTimeout(() => {
|
|
3482
|
-
this.zr.on("click", clickHandler);
|
|
3483
|
-
}, 10);
|
|
3484
|
-
this.zr.on("mousedown", this.onMouseDown);
|
|
3485
|
-
this.context.events.on("chart:dataZoom", this.onChartInteraction);
|
|
3486
|
-
this.clearHandlers = {
|
|
3487
|
-
click: clickHandler,
|
|
3488
|
-
mousedown: this.onMouseDown,
|
|
3489
|
-
dataZoom: this.onChartInteraction
|
|
3490
|
-
};
|
|
3491
|
-
}
|
|
3492
|
-
disableClearListeners() {
|
|
3493
|
-
if (this.clearHandlers.click)
|
|
3494
|
-
this.zr.off("click", this.clearHandlers.click);
|
|
3495
|
-
if (this.clearHandlers.mousedown)
|
|
3496
|
-
this.zr.off("mousedown", this.clearHandlers.mousedown);
|
|
3497
|
-
if (this.clearHandlers.dataZoom) {
|
|
3498
|
-
this.context.events.off("chart:dataZoom", this.clearHandlers.dataZoom);
|
|
3499
|
-
}
|
|
3500
|
-
this.clearHandlers = {};
|
|
3501
|
-
}
|
|
3502
|
-
// --- Graphics ---
|
|
3503
|
-
initGraphic() {
|
|
3504
|
-
if (this.group)
|
|
3505
|
-
return;
|
|
3506
|
-
this.group = new echarts__namespace.graphic.Group();
|
|
3507
|
-
this.rect = new echarts__namespace.graphic.Rect({
|
|
3508
|
-
shape: { x: 0, y: 0, width: 0, height: 0 },
|
|
3509
|
-
style: { fill: "rgba(0,0,0,0)", stroke: "transparent", lineWidth: 0 },
|
|
3510
|
-
z: 100
|
|
3511
|
-
});
|
|
3512
|
-
this.lineV = new echarts__namespace.graphic.Line({
|
|
3513
|
-
shape: { x1: 0, y1: 0, x2: 0, y2: 0 },
|
|
3514
|
-
style: { stroke: "#fff", lineWidth: 1, lineDash: [4, 4] },
|
|
3515
|
-
z: 101
|
|
3516
|
-
});
|
|
3517
|
-
this.lineH = new echarts__namespace.graphic.Line({
|
|
3518
|
-
shape: { x1: 0, y1: 0, x2: 0, y2: 0 },
|
|
3519
|
-
style: { stroke: "#fff", lineWidth: 1, lineDash: [4, 4] },
|
|
3520
|
-
z: 101
|
|
3521
|
-
});
|
|
3522
|
-
this.arrowStart = new echarts__namespace.graphic.Polygon({
|
|
3523
|
-
shape: {
|
|
3524
|
-
points: [
|
|
3525
|
-
[0, 0],
|
|
3526
|
-
[-5, 10],
|
|
3527
|
-
[5, 10]
|
|
3528
|
-
]
|
|
3529
|
-
},
|
|
3530
|
-
style: { fill: "#fff" },
|
|
3531
|
-
z: 102
|
|
3532
|
-
});
|
|
3533
|
-
this.arrowEnd = new echarts__namespace.graphic.Polygon({
|
|
3534
|
-
shape: {
|
|
3535
|
-
points: [
|
|
3536
|
-
[0, 0],
|
|
3537
|
-
[-5, -10],
|
|
3538
|
-
[5, -10]
|
|
3539
|
-
]
|
|
3540
|
-
},
|
|
3541
|
-
style: { fill: "#fff" },
|
|
3542
|
-
z: 102
|
|
3543
|
-
});
|
|
3544
|
-
this.labelRect = new echarts__namespace.graphic.Rect({
|
|
3545
|
-
shape: { x: 0, y: 0, width: 0, height: 0, r: 4 },
|
|
3546
|
-
style: {
|
|
3547
|
-
fill: "transparent",
|
|
3548
|
-
stroke: "transparent",
|
|
3549
|
-
lineWidth: 0,
|
|
3550
|
-
shadowBlur: 5,
|
|
3551
|
-
shadowColor: "rgba(0,0,0,0.3)"
|
|
3552
|
-
},
|
|
3553
|
-
z: 102
|
|
3554
|
-
});
|
|
3555
|
-
this.labelText = new echarts__namespace.graphic.Text({
|
|
3556
|
-
style: {
|
|
3557
|
-
x: 0,
|
|
3558
|
-
y: 0,
|
|
3559
|
-
text: "",
|
|
3560
|
-
fill: "#fff",
|
|
3561
|
-
font: "12px sans-serif",
|
|
3562
|
-
align: "center",
|
|
3563
|
-
verticalAlign: "middle"
|
|
3564
|
-
},
|
|
3565
|
-
z: 103
|
|
3566
|
-
});
|
|
3567
|
-
this.group.add(this.rect);
|
|
3568
|
-
this.group.add(this.lineV);
|
|
3569
|
-
this.group.add(this.lineH);
|
|
3570
|
-
this.group.add(this.arrowStart);
|
|
3571
|
-
this.group.add(this.arrowEnd);
|
|
3572
|
-
this.group.add(this.labelRect);
|
|
3573
|
-
this.group.add(this.labelText);
|
|
3574
|
-
this.zr.add(this.group);
|
|
3575
|
-
}
|
|
3576
|
-
removeGraphic() {
|
|
3577
|
-
if (this.group) {
|
|
3578
|
-
this.zr.remove(this.group);
|
|
3579
|
-
this.group = null;
|
|
3580
|
-
this.disableClearListeners();
|
|
3581
|
-
}
|
|
3582
|
-
}
|
|
3583
|
-
updateGraphic() {
|
|
3584
|
-
if (!this.startPoint || !this.endPoint || !this.group)
|
|
3585
|
-
return;
|
|
3586
|
-
const [x1, y1] = this.startPoint;
|
|
3587
|
-
const [x2, y2] = this.endPoint;
|
|
3588
|
-
const p1 = this.context.coordinateConversion.pixelToData({ x: x1, y: y1 });
|
|
3589
|
-
const p2 = this.context.coordinateConversion.pixelToData({ x: x2, y: y2 });
|
|
3590
|
-
if (!p1 || !p2)
|
|
3591
|
-
return;
|
|
3592
|
-
const idx1 = Math.round(p1.timeIndex);
|
|
3593
|
-
const idx2 = Math.round(p2.timeIndex);
|
|
3594
|
-
const val1 = p1.value;
|
|
3595
|
-
const val2 = p2.value;
|
|
3596
|
-
const bars = idx2 - idx1;
|
|
3597
|
-
const priceDiff = val2 - val1;
|
|
3598
|
-
const priceChangePercent = priceDiff / val1 * 100;
|
|
3599
|
-
const isUp = priceDiff >= 0;
|
|
3600
|
-
const color = isUp ? "rgba(33, 150, 243, 0.2)" : "rgba(236, 0, 0, 0.2)";
|
|
3601
|
-
const strokeColor = isUp ? "#2196F3" : "#ec0000";
|
|
3602
|
-
this.rect.setShape({
|
|
3603
|
-
x: Math.min(x1, x2),
|
|
3604
|
-
y: Math.min(y1, y2),
|
|
3605
|
-
width: Math.abs(x2 - x1),
|
|
3606
|
-
height: Math.abs(y2 - y1)
|
|
3607
|
-
});
|
|
3608
|
-
this.rect.setStyle({ fill: color });
|
|
3609
|
-
const midX = (x1 + x2) / 2;
|
|
3610
|
-
const midY = (y1 + y2) / 2;
|
|
3611
|
-
this.lineV.setShape({ x1: midX, y1, x2: midX, y2 });
|
|
3612
|
-
this.lineV.setStyle({ stroke: strokeColor });
|
|
3613
|
-
this.lineH.setShape({ x1, y1: midY, x2, y2: midY });
|
|
3614
|
-
this.lineH.setStyle({ stroke: strokeColor });
|
|
3615
|
-
const topY = Math.min(y1, y2);
|
|
3616
|
-
const bottomY = Math.max(y1, y2);
|
|
3617
|
-
this.arrowStart.setStyle({ fill: "none" });
|
|
3618
|
-
this.arrowEnd.setStyle({ fill: "none" });
|
|
3619
|
-
if (isUp) {
|
|
3620
|
-
this.arrowStart.setShape({
|
|
3621
|
-
points: [
|
|
3622
|
-
[midX, topY],
|
|
3623
|
-
[midX - 4, topY + 6],
|
|
3624
|
-
[midX + 4, topY + 6]
|
|
3625
|
-
]
|
|
3626
|
-
});
|
|
3627
|
-
this.arrowStart.setStyle({ fill: strokeColor });
|
|
3628
|
-
} else {
|
|
3629
|
-
this.arrowEnd.setShape({
|
|
3630
|
-
points: [
|
|
3631
|
-
[midX, bottomY],
|
|
3632
|
-
[midX - 4, bottomY - 6],
|
|
3633
|
-
[midX + 4, bottomY - 6]
|
|
3634
|
-
]
|
|
3635
|
-
});
|
|
3636
|
-
this.arrowEnd.setStyle({ fill: strokeColor });
|
|
3637
|
-
}
|
|
3638
|
-
const textContent = [`${priceDiff.toFixed(2)} (${priceChangePercent.toFixed(2)}%)`, `${bars} bars, ${(bars * 0).toFixed(0)}d`].join("\n");
|
|
3639
|
-
const labelW = 140;
|
|
3640
|
-
const labelH = 40;
|
|
3641
|
-
const rectBottomY = Math.max(y1, y2);
|
|
3642
|
-
const rectTopY = Math.min(y1, y2);
|
|
3643
|
-
const rectCenterX = (x1 + x2) / 2;
|
|
3644
|
-
let labelX = rectCenterX - labelW / 2;
|
|
3645
|
-
let labelY = rectBottomY + 10;
|
|
3646
|
-
const canvasHeight = this.chart.getHeight();
|
|
3647
|
-
if (labelY + labelH > canvasHeight) {
|
|
3648
|
-
labelY = rectTopY - labelH - 10;
|
|
3649
|
-
}
|
|
3650
|
-
this.labelRect.setShape({
|
|
3651
|
-
x: labelX,
|
|
3652
|
-
y: labelY,
|
|
3653
|
-
width: labelW,
|
|
3654
|
-
height: labelH
|
|
3655
|
-
});
|
|
3656
|
-
this.labelRect.setStyle({
|
|
3657
|
-
fill: "#1e293b",
|
|
3658
|
-
stroke: strokeColor,
|
|
3659
|
-
lineWidth: 1
|
|
3660
|
-
});
|
|
3661
|
-
this.labelText.setStyle({
|
|
3662
|
-
x: labelX + labelW / 2,
|
|
3663
|
-
y: labelY + labelH / 2,
|
|
3664
|
-
text: textContent,
|
|
3665
|
-
fill: "#fff"
|
|
3666
|
-
});
|
|
3667
|
-
}
|
|
3668
|
-
}
|
|
3669
|
-
|
|
3670
|
-
var __defProp$1 = Object.defineProperty;
|
|
3671
|
-
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3672
|
-
var __publicField$1 = (obj, key, value) => {
|
|
3673
|
-
__defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
3674
|
-
return value;
|
|
3675
|
-
};
|
|
3676
|
-
class LineTool extends AbstractPlugin {
|
|
3677
|
-
constructor(options) {
|
|
3678
|
-
super({
|
|
3679
|
-
id: "trend-line",
|
|
3680
|
-
name: options?.name || "Trend Line",
|
|
3681
|
-
icon: options?.icon || `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="2" y1="22" x2="22" y2="2" /></svg>`
|
|
3682
|
-
});
|
|
3683
|
-
__publicField$1(this, "zr");
|
|
3684
|
-
__publicField$1(this, "state", "idle");
|
|
3685
|
-
__publicField$1(this, "startPoint", null);
|
|
3686
|
-
__publicField$1(this, "endPoint", null);
|
|
3687
|
-
// ZRender Elements
|
|
3688
|
-
__publicField$1(this, "group", null);
|
|
3689
|
-
__publicField$1(this, "line", null);
|
|
3690
|
-
__publicField$1(this, "startCircle", null);
|
|
3691
|
-
__publicField$1(this, "endCircle", null);
|
|
3692
|
-
// --- Interaction Handlers ---
|
|
3693
|
-
__publicField$1(this, "onMouseDown", () => {
|
|
3694
|
-
});
|
|
3695
|
-
__publicField$1(this, "onChartInteraction", () => {
|
|
3696
|
-
});
|
|
3697
|
-
__publicField$1(this, "onClick", (params) => {
|
|
3698
|
-
if (this.state === "idle") {
|
|
3699
|
-
this.state = "drawing";
|
|
3700
|
-
this.startPoint = [params.offsetX, params.offsetY];
|
|
3701
|
-
this.endPoint = [params.offsetX, params.offsetY];
|
|
3702
|
-
this.initGraphic();
|
|
3703
|
-
this.updateGraphic();
|
|
3704
|
-
} else if (this.state === "drawing") {
|
|
3705
|
-
this.state = "finished";
|
|
3706
|
-
this.endPoint = [params.offsetX, params.offsetY];
|
|
3707
|
-
this.updateGraphic();
|
|
3708
|
-
if (this.startPoint && this.endPoint) {
|
|
3709
|
-
const start = this.context.coordinateConversion.pixelToData({
|
|
3710
|
-
x: this.startPoint[0],
|
|
3711
|
-
y: this.startPoint[1]
|
|
3712
|
-
});
|
|
3713
|
-
const end = this.context.coordinateConversion.pixelToData({
|
|
3714
|
-
x: this.endPoint[0],
|
|
3715
|
-
y: this.endPoint[1]
|
|
3716
|
-
});
|
|
3717
|
-
if (start && end) {
|
|
3718
|
-
const paneIndex = start.paneIndex || 0;
|
|
3719
|
-
this.context.addDrawing({
|
|
3720
|
-
id: `line-${Date.now()}`,
|
|
3721
|
-
type: "line",
|
|
3722
|
-
points: [start, end],
|
|
3723
|
-
paneIndex,
|
|
3724
|
-
style: {
|
|
3725
|
-
color: "#3b82f6",
|
|
3726
|
-
lineWidth: 2
|
|
3727
|
-
}
|
|
3728
|
-
});
|
|
3729
|
-
}
|
|
3730
|
-
}
|
|
3731
|
-
this.removeGraphic();
|
|
3732
|
-
this.context.disableTools();
|
|
3733
|
-
}
|
|
3734
|
-
});
|
|
3735
|
-
__publicField$1(this, "clearHandlers", {});
|
|
3736
|
-
__publicField$1(this, "onMouseMove", (params) => {
|
|
3737
|
-
if (this.state !== "drawing")
|
|
3738
|
-
return;
|
|
3739
|
-
this.endPoint = [params.offsetX, params.offsetY];
|
|
3740
|
-
this.updateGraphic();
|
|
3741
|
-
});
|
|
3742
|
-
}
|
|
3743
|
-
onInit() {
|
|
3744
|
-
this.zr = this.chart.getZr();
|
|
3745
|
-
}
|
|
3746
|
-
onActivate() {
|
|
3747
|
-
this.state = "idle";
|
|
3748
|
-
this.chart.getZr().setCursorStyle("crosshair");
|
|
3749
|
-
this.zr.on("click", this.onClick);
|
|
3750
|
-
this.zr.on("mousemove", this.onMouseMove);
|
|
3751
|
-
}
|
|
3752
|
-
onDeactivate() {
|
|
3753
|
-
this.state = "idle";
|
|
3754
|
-
this.chart.getZr().setCursorStyle("default");
|
|
3755
|
-
this.zr.off("click", this.onClick);
|
|
3756
|
-
this.zr.off("mousemove", this.onMouseMove);
|
|
3757
|
-
this.disableClearListeners();
|
|
3758
|
-
if (this.state === "drawing") {
|
|
3759
|
-
this.removeGraphic();
|
|
3760
|
-
}
|
|
3761
|
-
}
|
|
3762
|
-
onDestroy() {
|
|
3763
|
-
this.removeGraphic();
|
|
3764
|
-
}
|
|
3765
|
-
saveDataCoordinates() {
|
|
3766
|
-
}
|
|
3767
|
-
updateGraphicFromData() {
|
|
3768
|
-
}
|
|
3769
|
-
enableClearListeners() {
|
|
3770
|
-
}
|
|
3771
|
-
disableClearListeners() {
|
|
3772
|
-
}
|
|
3773
|
-
// --- Graphics ---
|
|
3774
|
-
initGraphic() {
|
|
3775
|
-
if (this.group)
|
|
3776
|
-
return;
|
|
3777
|
-
this.group = new echarts__namespace.graphic.Group();
|
|
3778
|
-
this.line = new echarts__namespace.graphic.Line({
|
|
3779
|
-
shape: { x1: 0, y1: 0, x2: 0, y2: 0 },
|
|
3780
|
-
style: { stroke: "#3b82f6", lineWidth: 2 },
|
|
3781
|
-
z: 100
|
|
3782
|
-
});
|
|
3783
|
-
this.startCircle = new echarts__namespace.graphic.Circle({
|
|
3784
|
-
shape: { cx: 0, cy: 0, r: 4 },
|
|
3785
|
-
style: { fill: "#fff", stroke: "#3b82f6", lineWidth: 1 },
|
|
3786
|
-
z: 101
|
|
3787
|
-
});
|
|
3788
|
-
this.endCircle = new echarts__namespace.graphic.Circle({
|
|
3789
|
-
shape: { cx: 0, cy: 0, r: 4 },
|
|
3790
|
-
style: { fill: "#fff", stroke: "#3b82f6", lineWidth: 1 },
|
|
3791
|
-
z: 101
|
|
3792
|
-
});
|
|
3793
|
-
this.group.add(this.line);
|
|
3794
|
-
this.group.add(this.startCircle);
|
|
3795
|
-
this.group.add(this.endCircle);
|
|
3796
|
-
this.zr.add(this.group);
|
|
3797
|
-
}
|
|
3798
|
-
removeGraphic() {
|
|
3799
|
-
if (this.group) {
|
|
3800
|
-
this.zr.remove(this.group);
|
|
3801
|
-
this.group = null;
|
|
3802
|
-
this.disableClearListeners();
|
|
3803
|
-
}
|
|
3804
|
-
}
|
|
3805
|
-
updateGraphic() {
|
|
3806
|
-
if (!this.startPoint || !this.endPoint || !this.group)
|
|
3807
|
-
return;
|
|
3808
|
-
const [x1, y1] = this.startPoint;
|
|
3809
|
-
const [x2, y2] = this.endPoint;
|
|
3810
|
-
this.line.setShape({ x1, y1, x2, y2 });
|
|
3811
|
-
this.startCircle.setShape({ cx: x1, cy: y1 });
|
|
3812
|
-
this.endCircle.setShape({ cx: x2, cy: y2 });
|
|
3813
|
-
}
|
|
3814
|
-
}
|
|
3815
|
-
|
|
3816
|
-
var __defProp = Object.defineProperty;
|
|
3817
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3818
|
-
var __publicField = (obj, key, value) => {
|
|
3819
|
-
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
3820
|
-
return value;
|
|
3821
|
-
};
|
|
3822
|
-
class FibonacciTool extends AbstractPlugin {
|
|
3823
|
-
constructor(options = {}) {
|
|
3824
|
-
super({
|
|
3825
|
-
id: "fibonacci-tool",
|
|
3826
|
-
name: options.name || "Fibonacci Retracement",
|
|
3827
|
-
icon: options.icon || `<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="M120-80v-80h720v80H120Zm0-240v-80h720v80H120Zm0-240v-80h720v80H120Zm0-240v-80h720v80H120Z"/></svg>`
|
|
3828
|
-
});
|
|
3829
|
-
__publicField(this, "startPoint", null);
|
|
3830
|
-
__publicField(this, "endPoint", null);
|
|
3831
|
-
__publicField(this, "state", "idle");
|
|
3832
|
-
// Temporary ZRender elements
|
|
3833
|
-
__publicField(this, "graphicGroup", null);
|
|
3834
|
-
// Fib levels config
|
|
3835
|
-
__publicField(this, "levels", [0, 0.236, 0.382, 0.5, 0.618, 0.786, 1]);
|
|
3836
|
-
__publicField(this, "colors", [
|
|
3837
|
-
"#787b86",
|
|
3838
|
-
// 0
|
|
3839
|
-
"#f44336",
|
|
3840
|
-
// 0.236
|
|
3841
|
-
"#ff9800",
|
|
3842
|
-
// 0.382
|
|
3843
|
-
"#4caf50",
|
|
3844
|
-
// 0.5
|
|
3845
|
-
"#2196f3",
|
|
3846
|
-
// 0.618
|
|
3847
|
-
"#00bcd4",
|
|
3848
|
-
// 0.786
|
|
3849
|
-
"#787b86"
|
|
3850
|
-
// 1
|
|
3851
|
-
]);
|
|
3852
|
-
__publicField(this, "onClick", (params) => {
|
|
3853
|
-
if (this.state === "idle") {
|
|
3854
|
-
this.state = "drawing";
|
|
3855
|
-
this.startPoint = [params.offsetX, params.offsetY];
|
|
3856
|
-
this.endPoint = [params.offsetX, params.offsetY];
|
|
3857
|
-
this.initGraphic();
|
|
3858
|
-
this.updateGraphic();
|
|
3859
|
-
} else if (this.state === "drawing") {
|
|
3860
|
-
this.state = "finished";
|
|
3861
|
-
this.endPoint = [params.offsetX, params.offsetY];
|
|
3862
|
-
this.updateGraphic();
|
|
3863
|
-
this.saveDrawing();
|
|
3864
|
-
this.removeGraphic();
|
|
3865
|
-
this.context.disableTools();
|
|
3866
|
-
}
|
|
3867
|
-
});
|
|
3868
|
-
__publicField(this, "onMouseMove", (params) => {
|
|
3869
|
-
if (this.state === "drawing") {
|
|
3870
|
-
this.endPoint = [params.offsetX, params.offsetY];
|
|
3871
|
-
this.updateGraphic();
|
|
3872
|
-
}
|
|
3873
|
-
});
|
|
3874
|
-
}
|
|
3875
|
-
onActivate() {
|
|
3876
|
-
this.state = "idle";
|
|
3877
|
-
this.startPoint = null;
|
|
3878
|
-
this.endPoint = null;
|
|
3879
|
-
this.context.getChart().getZr().setCursorStyle("crosshair");
|
|
3880
|
-
this.bindEvents();
|
|
3881
|
-
}
|
|
3882
|
-
onDeactivate() {
|
|
3883
|
-
this.state = "idle";
|
|
3884
|
-
this.startPoint = null;
|
|
3885
|
-
this.endPoint = null;
|
|
3886
|
-
this.removeGraphic();
|
|
3887
|
-
this.unbindEvents();
|
|
3888
|
-
this.context.getChart().getZr().setCursorStyle("default");
|
|
3889
|
-
}
|
|
3890
|
-
bindEvents() {
|
|
3891
|
-
const zr = this.context.getChart().getZr();
|
|
3892
|
-
zr.on("click", this.onClick);
|
|
3893
|
-
zr.on("mousemove", this.onMouseMove);
|
|
3894
|
-
}
|
|
3895
|
-
unbindEvents() {
|
|
3896
|
-
const zr = this.context.getChart().getZr();
|
|
3897
|
-
zr.off("click", this.onClick);
|
|
3898
|
-
zr.off("mousemove", this.onMouseMove);
|
|
3899
|
-
}
|
|
3900
|
-
initGraphic() {
|
|
3901
|
-
this.graphicGroup = new echarts__namespace.graphic.Group();
|
|
3902
|
-
this.context.getChart().getZr().add(this.graphicGroup);
|
|
3903
|
-
}
|
|
3904
|
-
removeGraphic() {
|
|
3905
|
-
if (this.graphicGroup) {
|
|
3906
|
-
this.context.getChart().getZr().remove(this.graphicGroup);
|
|
3907
|
-
this.graphicGroup = null;
|
|
3908
|
-
}
|
|
3909
|
-
}
|
|
3910
|
-
updateGraphic() {
|
|
3911
|
-
if (!this.graphicGroup || !this.startPoint || !this.endPoint)
|
|
3912
|
-
return;
|
|
3913
|
-
this.graphicGroup.removeAll();
|
|
3914
|
-
const x1 = this.startPoint[0];
|
|
3915
|
-
const y1 = this.startPoint[1];
|
|
3916
|
-
const x2 = this.endPoint[0];
|
|
3917
|
-
const y2 = this.endPoint[1];
|
|
3918
|
-
const trendLine = new echarts__namespace.graphic.Line({
|
|
3919
|
-
shape: { x1, y1, x2, y2 },
|
|
3920
|
-
style: {
|
|
3921
|
-
stroke: "#999",
|
|
3922
|
-
lineWidth: 1,
|
|
3923
|
-
lineDash: [4, 4]
|
|
3924
|
-
},
|
|
3925
|
-
silent: true
|
|
3926
|
-
});
|
|
3927
|
-
this.graphicGroup.add(trendLine);
|
|
3928
|
-
const startX = Math.min(x1, x2);
|
|
3929
|
-
const endX = Math.max(x1, x2);
|
|
3930
|
-
const width = endX - startX;
|
|
3931
|
-
const diffY = y2 - y1;
|
|
3932
|
-
this.levels.forEach((level, index) => {
|
|
3933
|
-
const levelY = y2 - diffY * level;
|
|
3934
|
-
const color = this.colors[index % this.colors.length];
|
|
3935
|
-
const line = new echarts__namespace.graphic.Line({
|
|
3936
|
-
shape: { x1: startX, y1: levelY, x2: endX, y2: levelY },
|
|
3937
|
-
style: {
|
|
3938
|
-
stroke: color,
|
|
3939
|
-
lineWidth: 1
|
|
3940
|
-
},
|
|
3941
|
-
silent: true
|
|
3942
|
-
});
|
|
3943
|
-
this.graphicGroup.add(line);
|
|
3944
|
-
if (index < this.levels.length - 1) {
|
|
3945
|
-
const nextLevel = this.levels[index + 1];
|
|
3946
|
-
const nextY = y2 - diffY * nextLevel;
|
|
3947
|
-
const rectH = Math.abs(nextY - levelY);
|
|
3948
|
-
const rectY = Math.min(levelY, nextY);
|
|
3949
|
-
const rect = new echarts__namespace.graphic.Rect({
|
|
3950
|
-
shape: { x: startX, y: rectY, width, height: rectH },
|
|
3951
|
-
style: {
|
|
3952
|
-
fill: this.colors[(index + 1) % this.colors.length],
|
|
3953
|
-
// Use next level's color
|
|
3954
|
-
opacity: 0.1
|
|
3955
|
-
},
|
|
3956
|
-
silent: true
|
|
3957
|
-
});
|
|
3958
|
-
this.graphicGroup.add(rect);
|
|
3959
|
-
}
|
|
3960
|
-
});
|
|
3961
|
-
}
|
|
3962
|
-
saveDrawing() {
|
|
3963
|
-
if (!this.startPoint || !this.endPoint)
|
|
3964
|
-
return;
|
|
3965
|
-
const start = this.context.coordinateConversion.pixelToData({
|
|
3966
|
-
x: this.startPoint[0],
|
|
3967
|
-
y: this.startPoint[1]
|
|
3968
|
-
});
|
|
3969
|
-
const end = this.context.coordinateConversion.pixelToData({
|
|
3970
|
-
x: this.endPoint[0],
|
|
3971
|
-
y: this.endPoint[1]
|
|
3972
|
-
});
|
|
3973
|
-
if (start && end) {
|
|
3974
|
-
const paneIndex = start.paneIndex || 0;
|
|
3975
|
-
this.context.addDrawing({
|
|
3976
|
-
id: `fib-${Date.now()}`,
|
|
3977
|
-
type: "fibonacci",
|
|
3978
|
-
points: [start, end],
|
|
3979
|
-
paneIndex,
|
|
3980
|
-
style: {
|
|
3981
|
-
color: "#3b82f6",
|
|
3982
|
-
// Default color, though individual lines use specific colors
|
|
3983
|
-
lineWidth: 1
|
|
3984
|
-
}
|
|
3985
|
-
});
|
|
3986
|
-
}
|
|
3987
|
-
}
|
|
3988
|
-
}
|
|
3989
|
-
|
|
3990
|
-
exports.AbstractPlugin = AbstractPlugin;
|
|
3991
|
-
exports.FibonacciTool = FibonacciTool;
|
|
3992
|
-
exports.LineTool = LineTool;
|
|
3993
|
-
exports.MeasureTool = MeasureTool;
|
|
3994
|
-
exports.QFChart = QFChart;
|
|
3995
|
-
|
|
3996
|
-
}));
|
|
3997
|
-
//# sourceMappingURL=qfchart.dev.browser.js.map
|
|
37
|
+
<div>${u.marker} <span style="color: #cbd5e1;">${u.displayName}</span></div>
|
|
38
|
+
<div style="font-size: 10px; color: #fff;padding-left:10px;">${f}</div>
|
|
39
|
+
</div>`}),a+="</div>"})}return a}}var Ii=Object.defineProperty,Ai=(h,t,e)=>t in h?Ii(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,St=(h,t,e)=>(Ai(h,typeof t!="symbol"?t+"":t,e),e);class _i{constructor(t,e){St(this,"plugins",new Map),St(this,"activePluginId",null),St(this,"context"),St(this,"toolbarContainer"),St(this,"tooltipElement",null),St(this,"hideTimeout",null),this.context=t,this.toolbarContainer=e,this.createTooltip(),this.renderToolbar()}createTooltip(){this.tooltipElement=document.createElement("div"),Object.assign(this.tooltipElement.style,{position:"fixed",display:"none",backgroundColor:"#1e293b",color:"#e2e8f0",padding:"6px 10px",borderRadius:"6px",fontSize:"13px",lineHeight:"1.4",fontWeight:"500",border:"1px solid #334155",zIndex:"9999",pointerEvents:"none",whiteSpace:"nowrap",boxShadow:"0 4px 6px -1px rgba(0, 0, 0, 0.3), 0 2px 4px -1px rgba(0, 0, 0, 0.15)",fontFamily:this.context.getOptions().fontFamily||"sans-serif",transition:"opacity 0.15s ease-in-out, transform 0.15s ease-in-out",opacity:"0",transform:"translateX(-5px)"}),document.body.appendChild(this.tooltipElement)}destroy(){this.tooltipElement&&this.tooltipElement.parentNode&&this.tooltipElement.parentNode.removeChild(this.tooltipElement),this.tooltipElement=null}showTooltip(t,e){if(!this.tooltipElement)return;this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=null);const i=t.getBoundingClientRect();this.tooltipElement.textContent=e,this.tooltipElement.style.display="block";const n=this.tooltipElement.getBoundingClientRect(),r=i.top+(i.height-n.height)/2,s=i.right+10;this.tooltipElement.style.top=`${r}px`,this.tooltipElement.style.left=`${s}px`,requestAnimationFrame(()=>{this.tooltipElement&&(this.tooltipElement.style.opacity="1",this.tooltipElement.style.transform="translateX(0)")})}hideTooltip(){this.tooltipElement&&(this.tooltipElement.style.opacity="0",this.tooltipElement.style.transform="translateX(-5px)",this.hideTimeout&&clearTimeout(this.hideTimeout),this.hideTimeout=setTimeout(()=>{this.tooltipElement&&(this.tooltipElement.style.display="none"),this.hideTimeout=null},150))}register(t){if(this.plugins.has(t.id)){console.warn(`Plugin with id ${t.id} is already registered.`);return}this.plugins.set(t.id,t),t.init(this.context),this.addButton(t)}unregister(t){const e=this.plugins.get(t);e&&(this.activePluginId===t&&this.deactivatePlugin(),e.destroy?.(),this.plugins.delete(t),this.removeButton(t))}activatePlugin(t){if(this.activePluginId===t){this.deactivatePlugin();return}this.activePluginId&&this.deactivatePlugin();const e=this.plugins.get(t);e&&(this.activePluginId=t,this.setButtonActive(t,!0),e.activate?.())}deactivatePlugin(){this.activePluginId&&(this.plugins.get(this.activePluginId)?.deactivate?.(),this.setButtonActive(this.activePluginId,!1),this.activePluginId=null)}renderToolbar(){this.toolbarContainer.innerHTML="",this.toolbarContainer.classList.add("qfchart-toolbar"),this.toolbarContainer.style.display="flex",this.toolbarContainer.style.flexDirection="column",this.toolbarContainer.style.width="40px",this.toolbarContainer.style.backgroundColor=this.context.getOptions().backgroundColor||"#1e293b",this.toolbarContainer.style.borderRight="1px solid #334155",this.toolbarContainer.style.padding="5px",this.toolbarContainer.style.boxSizing="border-box",this.toolbarContainer.style.gap="5px",this.toolbarContainer.style.flexShrink="0"}addButton(t){const e=document.createElement("button");e.id=`qfchart-plugin-btn-${t.id}`,e.style.width="30px",e.style.height="30px",e.style.padding="4px",e.style.border="1px solid transparent",e.style.borderRadius="4px",e.style.backgroundColor="transparent",e.style.cursor="pointer",e.style.color=this.context.getOptions().fontColor||"#cbd5e1",e.style.display="flex",e.style.alignItems="center",e.style.justifyContent="center",t.icon?e.innerHTML=t.icon:e.innerText=(t.name||t.id).substring(0,2).toUpperCase(),e.addEventListener("mouseenter",()=>{this.activePluginId!==t.id&&(e.style.backgroundColor="rgba(255, 255, 255, 0.1)"),this.showTooltip(e,t.name||t.id)}),e.addEventListener("mouseleave",()=>{this.activePluginId!==t.id&&(e.style.backgroundColor="transparent"),this.hideTooltip()}),e.onclick=()=>this.activatePlugin(t.id),this.toolbarContainer.appendChild(e)}removeButton(t){const e=this.toolbarContainer.querySelector(`#qfchart-plugin-btn-${t}`);e&&e.remove()}setButtonActive(t,e){const i=this.toolbarContainer.querySelector(`#qfchart-plugin-btn-${t}`);i&&(e?(i.style.backgroundColor="#2563eb",i.style.color="#ffffff"):(i.style.backgroundColor="transparent",i.style.color=this.context.getOptions().fontColor||"#cbd5e1"))}}var Si=Object.defineProperty,zi=(h,t,e)=>t in h?Si(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,at=(h,t,e)=>(zi(h,typeof t!="symbol"?t+"":t,e),e);class $i{constructor(t){at(this,"context"),at(this,"isEditing",!1),at(this,"currentDrawing",null),at(this,"editingPointIndex",null),at(this,"zr"),at(this,"editGroup",null),at(this,"editLines",[]),at(this,"editPoints",[]),at(this,"isMovingShape",!1),at(this,"dragStart",null),at(this,"initialPixelPoints",[]),at(this,"onDrawingMouseDown",e=>{if(this.isEditing)return;const i=this.context.getDrawing(e.id);i&&(this.isEditing=!0,this.isMovingShape=!0,this.currentDrawing=JSON.parse(JSON.stringify(i)),this.dragStart={x:e.x,y:e.y},this.initialPixelPoints=i.points.map(n=>{const r=this.context.coordinateConversion.dataToPixel(n);return r?{x:r.x,y:r.y}:{x:0,y:0}}),this.context.lockChart(),this.createEditGraphic(),this.zr.on("mousemove",this.onMouseMove),this.zr.on("mouseup",this.onMouseUp),window.addEventListener("mouseup",this.onWindowMouseUp))}),at(this,"onPointMouseDown",e=>{if(this.isEditing)return;const i=this.context.getDrawing(e.id);i&&(this.isEditing=!0,this.currentDrawing=JSON.parse(JSON.stringify(i)),this.editingPointIndex=e.pointIndex,this.initialPixelPoints=i.points.map(n=>{const r=this.context.coordinateConversion.dataToPixel(n);return r?{x:r.x,y:r.y}:{x:0,y:0}}),this.context.lockChart(),this.createEditGraphic(),this.zr.on("mousemove",this.onMouseMove),this.zr.on("mouseup",this.onMouseUp),window.addEventListener("mouseup",this.onWindowMouseUp))}),at(this,"onMouseMove",e=>{if(!this.isEditing||!this.currentDrawing)return;const i=e.offsetX,n=e.offsetY;if(this.isMovingShape&&this.dragStart){const r=i-this.dragStart.x,s=n-this.dragStart.y,l=this.initialPixelPoints.map(a=>({x:a.x+r,y:a.y+s}));for(let a=0;a<this.editLines.length;a++)this.editLines[a].setShape({x1:l[a].x,y1:l[a].y,x2:l[a+1].x,y2:l[a+1].y});for(let a=0;a<this.editPoints.length;a++)this.editPoints[a].setShape({cx:l[a].x,cy:l[a].y})}else if(this.editingPointIndex!==null){const r=this.initialPixelPoints.map(s=>({x:s.x,y:s.y}));r[this.editingPointIndex]={x:i,y:n};for(let s=0;s<this.editLines.length;s++)this.editLines[s].setShape({x1:r[s].x,y1:r[s].y,x2:r[s+1].x,y2:r[s+1].y});this.editPoints[this.editingPointIndex].setShape({cx:i,cy:n})}}),at(this,"onMouseUp",e=>{this.isEditing&&this.finishEditing(e.offsetX,e.offsetY)}),at(this,"onWindowMouseUp",e=>{if(!this.isEditing)return;const i=this.zr.dom;if(i){const n=i.getBoundingClientRect(),r=e.clientX-n.left,s=e.clientY-n.top;this.finishEditing(r,s)}else this.finishEditing(this.dragStart?.x??0,this.dragStart?.y??0)}),this.context=t,this.zr=this.context.getChart().getZr(),this.bindEvents()}bindEvents(){this.context.events.on("drawing:point:mousedown",this.onPointMouseDown),this.context.events.on("drawing:mousedown",this.onDrawingMouseDown)}createEditGraphic(){if(!this.currentDrawing)return;this.editGroup=new _.graphic.Group,this.editLines=[],this.editPoints=[];const t=this.currentDrawing.points.map(i=>{const n=this.context.coordinateConversion.dataToPixel(i);return n?{x:n.x,y:n.y}:null});if(t.some(i=>!i))return;const e=t;for(let i=0;i<e.length-1;i++){const n=new _.graphic.Line({shape:{x1:e[i].x,y1:e[i].y,x2:e[i+1].x,y2:e[i+1].y},style:{stroke:this.currentDrawing.style?.color||"#3b82f6",lineWidth:this.currentDrawing.style?.lineWidth||2,lineDash:[4,4]},silent:!0});this.editLines.push(n),this.editGroup.add(n)}for(let i=0;i<e.length;i++){const n=new _.graphic.Circle({shape:{cx:e[i].x,cy:e[i].y,r:5},style:{fill:"#fff",stroke:"#3b82f6",lineWidth:2},z:1e3});this.editPoints.push(n),this.editGroup.add(n)}this.zr.add(this.editGroup)}pixelToDataForPane(t,e,i){const n=this.context.coordinateConversion.pixelToData({x:t,y:e});if(n)return n;try{const r=this.context.getChart(),s=r.convertFromPixel({gridIndex:i},[t,e]);if(s){const l=r.getOption()?.xAxis?.[i]?.data,a=this.context.getMarketData(),o=l?Math.round((l.length-a.length)/2):0;return{timeIndex:Math.round(s[0])-o,value:s[1],paneIndex:i}}}catch{}return null}finishEditing(t,e){if(!this.currentDrawing){this.cleanup();return}const i=this.currentDrawing.paneIndex||0;if(this.isMovingShape&&this.dragStart){const n=t-this.dragStart.x,r=e-this.dragStart.y,s=this.initialPixelPoints.map(l=>this.pixelToDataForPane(l.x+n,l.y+r,i));if(s.every(l=>l!==null)){for(let l=0;l<s.length;l++)this.currentDrawing.points[l]=s[l];s[0]?.paneIndex!==void 0&&(this.currentDrawing.paneIndex=s[0].paneIndex),this.context.updateDrawing(this.currentDrawing)}}else if(this.editingPointIndex!==null){const n=this.pixelToDataForPane(t,e,i);n&&(this.currentDrawing.points[this.editingPointIndex]=n,this.editingPointIndex===0&&n.paneIndex!==void 0&&(this.currentDrawing.paneIndex=n.paneIndex),this.context.updateDrawing(this.currentDrawing))}this.cleanup()}cleanup(){this.isEditing=!1,this.isMovingShape=!1,this.dragStart=null,this.initialPixelPoints=[],this.currentDrawing=null,this.editingPointIndex=null,this.editLines=[],this.editPoints=[],this.editGroup&&(this.zr.remove(this.editGroup),this.editGroup=null),this.zr.off("mousemove",this.onMouseMove),this.zr.off("mouseup",this.onMouseUp),window.removeEventListener("mouseup",this.onWindowMouseUp),this.context.unlockChart()}}var Gi=Object.defineProperty,Ei=(h,t,e)=>t in h?Gi(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,Li=(h,t,e)=>(Ei(h,typeof t!="symbol"?t+"":t,e),e);class ye{constructor(){Li(this,"renderers",new Map)}register(t){this.renderers.set(t.type,t)}get(t){return this.renderers.get(t)}}var Ti=Object.defineProperty,Wi=(h,t,e)=>t in h?Ti(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,Ni=(h,t,e)=>(Wi(h,typeof t!="symbol"?t+"":t,e),e);class Fi{constructor(){Ni(this,"handlers",new Map)}on(t,e){this.handlers.has(t)||this.handlers.set(t,new Set),this.handlers.get(t).add(e)}off(t,e){const i=this.handlers.get(t);i&&i.delete(e)}emit(t,e){const i=this.handlers.get(t);i&&i.forEach(n=>{try{n(e)}catch(r){console.error(`Error in EventBus handler for ${t}:`,r)}})}clear(){this.handlers.clear()}}class ht{static safeParseColor(t){if(!t||typeof t!="string")return{color:"#888888",opacity:1};const e=t.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);if(e){const i=e[4]?parseFloat(e[4]):1;return{color:`rgb(${e[1]},${e[2]},${e[3]})`,opacity:i}}return{color:t,opacity:1}}static render(t,e,i){ht.clearAll(t);const n=new Map;for(const r of e)r&&!r._deleted&&n.set(r.position,r);n.forEach(r=>{const s=r._paneIndex??0,l=i?i(s):void 0,a=ht.buildTable(r,l);ht.positionTable(a,r.position,l),t.appendChild(a)})}static clearAll(t){for(;t.firstChild;)t.removeChild(t.firstChild)}static buildTable(t,e){const i=document.createElement("table"),n=t.border_width??0,r=t.frame_width??0;if(n>0&&t.border_color||r>0&&t.frame_color?(i.style.borderCollapse="separate",i.style.borderSpacing="0"):i.style.borderCollapse="collapse",i.style.pointerEvents="none",i.style.fontSize="14px",i.style.lineHeight="1.4",i.style.fontFamily="sans-serif",i.style.margin="4px",e&&(i.style.maxHeight=e.height+"px",i.style.maxWidth=e.width+"px",i.style.overflow="hidden"),t.bgcolor){const{color:d,opacity:u}=ht.safeParseColor(t.bgcolor);i.style.backgroundColor=d,u<1&&(i.style.opacity=String(u))}if(r>0&&t.frame_color){const{color:d}=ht.safeParseColor(t.frame_color);i.style.border=`${r}px solid ${d}`}else i.style.border="none";const s=new Map,l=new Set;if(t.merges)for(const d of t.merges){const u=`${d.startCol},${d.startRow}`;s.set(u,{colspan:d.endCol-d.startCol+1,rowspan:d.endRow-d.startRow+1});for(let p=d.startRow;p<=d.endRow;p++)for(let f=d.startCol;f<=d.endCol;f++)p===d.startRow&&f===d.startCol||l.add(`${f},${p}`)}const a=n>0&&!!t.border_color,o=a?ht.safeParseColor(t.border_color).color:"",c=t.rows||0,y=t.columns||0;for(let d=0;d<c;d++){const u=document.createElement("tr");for(let p=0;p<y;p++){const f=`${p},${d}`;if(l.has(f))continue;const g=document.createElement("td"),m=s.get(f);m&&(m.colspan>1&&(g.colSpan=m.colspan),m.rowspan>1&&(g.rowSpan=m.rowspan)),a?g.style.border=`${n}px solid ${o}`:g.style.border="none";const x=t.cells?.[d]?.[p];if(x&&!x._merged){if(g.textContent=x.text||"",x.bgcolor&&typeof x.bgcolor=="string"&&x.bgcolor.length>0){const{color:w,opacity:D}=ht.safeParseColor(x.bgcolor);g.style.backgroundColor=w,D<1&&(g.style.backgroundColor=x.bgcolor)}if(x.text_color){const{color:w}=ht.safeParseColor(x.text_color);g.style.color=w}if(g.style.fontSize=ht.getSizePixels(x.text_size)+"px",g.style.textAlign=ht.mapHAlign(x.text_halign),g.style.verticalAlign=ht.mapVAlign(x.text_valign),x.text_font_family==="monospace"&&(g.style.fontFamily="monospace"),x.width>0)if(e){const w=Math.max(1,x.width*e.width/100);g.style.width=w+"px"}else g.style.width=x.width+"%";if(x.height>0)if(e){const w=Math.max(1,x.height*e.height/100);g.style.height=w+"px"}else g.style.height=x.height+"%";x.tooltip&&(g.title=x.tooltip)}const P=x?.height??0;P>0&&e&&P*e.height/100<4?g.style.padding="0":g.style.padding="4px 6px",g.style.whiteSpace="nowrap",u.appendChild(g)}i.appendChild(u)}return i}static positionTable(t,e,i){t.style.position="absolute";const n=8,r=i?i.y+"px":"0",s=i?i.x+"px":"0",l=i?i.y+i.height-n+"px":"0",a=i?i.x+i.width-n+"px":"0",o=i?i.x+i.width/2+"px":"50%",c=i?i.y+i.height/2+"px":"50%";switch(e){case"top_left":t.style.top=r,t.style.left=s;break;case"top_center":t.style.top=r,t.style.left=o,t.style.transform="translateX(-50%)";break;case"top_right":t.style.top=r,t.style.left=a,t.style.transform="translateX(-100%)";break;case"middle_left":t.style.top=c,t.style.left=s,t.style.transform="translateY(-50%)";break;case"middle_center":t.style.top=c,t.style.left=o,t.style.transform="translate(-50%, -50%)";break;case"middle_right":t.style.top=c,t.style.left=a,t.style.transform="translate(-100%, -50%)";break;case"bottom_left":t.style.top=l,t.style.left=s,t.style.transform="translateY(-100%)";break;case"bottom_center":t.style.top=l,t.style.left=o,t.style.transform="translate(-50%, -100%)";break;case"bottom_right":t.style.top=l,t.style.left=a,t.style.transform="translate(-100%, -100%)";break;default:t.style.top=r,t.style.left=a,t.style.transform="translateX(-100%)";break}}static getSizePixels(t){if(typeof t=="number"&&t>0)return t;switch(t){case"auto":case"size.auto":return 12;case"tiny":case"size.tiny":return 8;case"small":case"size.small":return 10;case"normal":case"size.normal":return 14;case"large":case"size.large":return 20;case"huge":case"size.huge":return 36;default:return 14}}static mapHAlign(t){switch(t){case"left":case"text.align_left":return"left";case"right":case"text.align_right":return"right";case"center":case"text.align_center":default:return"center"}}static mapVAlign(t){switch(t){case"top":case"text.align_top":return"top";case"bottom":case"text.align_bottom":return"bottom";case"center":case"text.align_center":default:return"middle"}}}class st{static parseColor(t){if(!t||typeof t!="string"||t.length===0)return{color:"",opacity:0};const e=t.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);if(e){const i=e[4]?parseFloat(e[4]):1;return{color:`rgb(${e[1]},${e[2]},${e[3]})`,opacity:i}}if(/^#[0-9a-fA-F]{8}$/.test(t)){const i=parseInt(t.slice(1,3),16),n=parseInt(t.slice(3,5),16),r=parseInt(t.slice(5,7),16),s=parseInt(t.slice(7,9),16)/255;return{color:`rgb(${i},${n},${r})`,opacity:s}}return{color:t,opacity:1}}static getSizePixels(t){if(typeof t=="number"&&t>0)return t;switch(t){case"auto":case"size.auto":return 11;case"tiny":case"size.tiny":return 8;case"small":case"size.small":return 10;case"normal":case"size.normal":return 12;case"large":case"size.large":return 16;case"huge":case"size.huge":return 24;default:return 12}}static mapHAlign(t){switch(t){case"left":case"text.align_left":return"left";case"right":case"text.align_right":return"right";default:return"center"}}static mapVAlign(t){switch(t){case"top":case"text.align_top":return"top";case"bottom":case"text.align_bottom":return"bottom";default:return"middle"}}static buildGraphicElements(t,e){if(!t||t.length===0)return[];const i=new Map;for(const r of t)r&&!r._deleted&&i.set(r.position,r);const n=[];return i.forEach(r=>{const s=r._paneIndex??0,l=e(s);if(!l)return;const a=st.buildTableElements(r,l);n.push(...a)}),n}static buildTableElements(t,e){const i=t.rows||0,n=t.columns||0;if(i===0||n===0)return[];const r=t.border_width??0,s=t.frame_width??0,l=r>0&&!!t.border_color,a=s>0&&!!t.frame_color,o=new Map,c=new Set;if(t.merges)for(const v of t.merges){o.set(`${v.startCol},${v.startRow}`,{colspan:v.endCol-v.startCol+1,rowspan:v.endRow-v.startRow+1});for(let E=v.startRow;E<=v.endRow;E++)for(let I=v.startCol;I<=v.endCol;I++)E===v.startRow&&I===v.startCol||c.add(`${I},${E}`)}const y=4,d=2,u=1.25,p=[];for(let v=0;v<i;v++){p[v]=[];for(let E=0;E<n;E++){if(c.has(`${E},${v}`)){p[v][E]={text:"",lines:[],fontSize:12,fontFamily:"sans-serif",textColor:{color:"",opacity:0},bgColor:{color:"",opacity:0},halign:"center",valign:"middle",explicitWidth:0,explicitHeight:0,colspan:1,rowspan:1,skip:!0,padX:0,padY:0};continue}const I=t.cells?.[v]?.[E],N=o.get(`${E},${v}`),F=N?.colspan??1,Z=N?.rowspan??1,R=I&&!I._merged&&I.text||"",H=R?R.split(`
|
|
40
|
+
`):[],q=I?st.getSizePixels(I.text_size):12,X=I?.text_font_family==="monospace"?"monospace":"sans-serif";let rt=0,tt=0;I?.width>0&&(rt=Math.max(1,I.width*e.width/100)),I?.height>0&&(tt=Math.max(1,I.height*e.height/100));const O=tt>0&&tt<4,Q=O?0:y,mt=O?0:d,Jt=I&&!I._merged&&I.bgcolor&&typeof I.bgcolor=="string"&&I.bgcolor.length>0?I.bgcolor:"",It=I?.text_color||"";p[v][E]={text:R,lines:H,fontSize:q,fontFamily:X,textColor:It?st.parseColor(It):{color:"#e0e0e0",opacity:1},bgColor:Jt?st.parseColor(Jt):{color:"",opacity:0},halign:I?st.mapHAlign(I.text_halign):"center",valign:I?st.mapVAlign(I.text_valign):"middle",explicitWidth:rt,explicitHeight:tt,colspan:F,rowspan:Z,skip:!1,padX:Q,padY:mt}}}const f=new Array(n).fill(0),g=new Array(i).fill(0);for(let v=0;v<i;v++)for(let E=0;E<n;E++){const I=p[v][E];if(I.skip||I.colspan>1||I.rowspan>1)continue;const N=st.measureMultiLineWidth(I.lines,I.fontSize,I.fontFamily),F=Math.max(I.lines.length,1),Z=I.explicitWidth>0?I.explicitWidth:N+I.padX*2,R=I.explicitHeight>0?I.explicitHeight:F*I.fontSize*u+I.padY*2;f[E]=Math.max(f[E],Z),g[v]=Math.max(g[v],R)}for(let v=0;v<n;v++)f[v]===0&&(f[v]=20);for(let v=0;v<i;v++)g[v]===0&&(g[v]=4);for(let v=0;v<i;v++)for(let E=0;E<n;E++){const I=p[v][E];if(I.skip)continue;const N=Math.max(I.lines.length,1),F=I.explicitHeight>0?I.explicitHeight:N*I.fontSize*u+I.padY*2;if(I.colspan>1){const Z=st.sumRange(f,E,I.colspan),R=st.measureMultiLineWidth(I.lines,I.fontSize,I.fontFamily),H=I.explicitWidth>0?I.explicitWidth:R+I.padX*2;if(H>Z){const q=(H-Z)/I.colspan;for(let X=0;X<I.colspan;X++)f[E+X]+=q}I.rowspan===1&&(g[v]=Math.max(g[v],F))}if(I.rowspan>1){const Z=st.sumRange(g,v,I.rowspan);if(F>Z){const R=(F-Z)/I.rowspan;for(let H=0;H<I.rowspan;H++)g[v+H]+=R}}}for(let v=0;v<n;v++)f[v]=Math.round(f[v]);for(let v=0;v<i;v++)g[v]=Math.round(g[v]);const m=new Array(n+1).fill(0);for(let v=0;v<n;v++)m[v+1]=m[v]+f[v];const x=new Array(i+1).fill(0);for(let v=0;v<i;v++)x[v+1]=x[v]+g[v];const P=a?s:0,w=m[n]+P*2,D=x[i]+P*2,S=Math.min(w,e.width),M=Math.min(D,e.height),b=st.computePosition(t.position,e,S,M),k=Math.round(b.x),C=Math.round(b.y),A=[],G=k+P,z=C+P;if(t.bgcolor){const{color:v,opacity:E}=st.parseColor(t.bgcolor);E>0&&A.push({type:"rect",shape:{x:k,y:C,width:S,height:M},style:{fill:v,opacity:E},silent:!0,z:0,z2:0})}if(a){const{color:v}=st.parseColor(t.frame_color),E=s/2;A.push({type:"rect",shape:{x:k+E,y:C+E,width:S-s,height:M-s},style:{fill:"none",stroke:v,lineWidth:s},silent:!0,z:0,z2:1})}const $=l?st.parseColor(t.border_color).color:"";for(let v=0;v<i;v++)for(let E=0;E<n;E++){const I=p[v][E];if(I.skip)continue;const N=G+m[E],F=z+x[v],Z=st.sumRange(f,E,I.colspan),R=st.sumRange(g,v,I.rowspan);if(N-k>=S||F-C>=M)continue;const H=Math.min(Z,S-(N-k)),q=Math.min(R,M-(F-C));if(I.bgColor.opacity>0&&A.push({type:"rect",shape:{x:N,y:F,width:H,height:q},style:{fill:I.bgColor.color,opacity:I.bgColor.opacity},silent:!0,z:0,z2:2}),l&&A.push({type:"rect",shape:{x:N,y:F,width:H,height:q},style:{fill:"none",stroke:$,lineWidth:r},silent:!0,z:0,z2:3}),I.text){let X,rt;switch(I.halign){case"left":X=N+I.padX,rt="left";break;case"right":X=N+H-I.padX,rt="right";break;default:X=N+H/2,rt="center";break}let tt,O;switch(I.valign){case"top":tt=F+I.padY,O="top";break;case"bottom":tt=F+q-I.padY,O="bottom";break;default:tt=F+q/2,O="middle";break}A.push({type:"text",x:X,y:tt,style:{text:I.text,fill:I.textColor.color,opacity:I.textColor.opacity,font:`${I.fontSize}px ${I.fontFamily}`,textAlign:rt,textVerticalAlign:O,lineHeight:Math.round(I.fontSize*u)},silent:!0,z:0,z2:4})}}return A}static computePosition(t,e,i,n){const r=e.x,s=e.y,l=e.width,a=e.height;switch(t){case"top_left":return{x:r+4,y:s+4};case"top_center":return{x:r+(l-i)/2,y:s+4};case"top_right":return{x:r+l-i-4,y:s+4};case"middle_left":return{x:r+4,y:s+(a-n)/2};case"middle_center":return{x:r+(l-i)/2,y:s+(a-n)/2};case"middle_right":return{x:r+l-i-4,y:s+(a-n)/2};case"bottom_left":return{x:r+4,y:s+a-n-4};case"bottom_center":return{x:r+(l-i)/2,y:s+a-n-4};case"bottom_right":return{x:r+l-i-4,y:s+a-n-4};default:return{x:r+l-i-4,y:s+4}}}static measureMultiLineWidth(t,e,i){if(!t||t.length===0)return 0;const n=i==="monospace"?.6:.55;let r=0;for(const s of t)r=Math.max(r,s.length*e*n);return r}static sumRange(t,e,i){let n=0;for(let r=e;r<e+i&&r<t.length;r++)n+=t[r];return n}}var Zi=Object.defineProperty,Ri=(h,t,e)=>t in h?Zi(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,W=(h,t,e)=>(Ri(h,typeof t!="symbol"?t+"":t,e),e);class Hi{constructor(t,e={}){W(this,"chart"),W(this,"options"),W(this,"marketData",[]),W(this,"indicators",new Map),W(this,"timeToIndex",new Map),W(this,"pluginManager"),W(this,"drawingEditor"),W(this,"events",new Fi),W(this,"isMainCollapsed",!1),W(this,"maximizedPaneId",null),W(this,"countdownInterval",null),W(this,"selectedDrawingId",null),W(this,"drawings",[]),W(this,"drawingRenderers",new ye),W(this,"coordinateConversion",{pixelToData:s=>{const l=this.chart.getOption();if(!l||!l.grid)return null;const a=l.grid.length;for(let o=0;o<a;o++)if(this.chart.containPixel({gridIndex:o},[s.x,s.y])){this.chart.convertFromPixel({seriesIndex:o},[s.x,s.y]);const c=this.chart.convertFromPixel({gridIndex:o},[s.x,s.y]);if(c)return{timeIndex:Math.round(c[0])-this.dataIndexOffset,value:c[1],paneIndex:o}}return null},dataToPixel:s=>{const l=s.paneIndex||0,a=this.chart.convertToPixel({gridIndex:l},[s.timeIndex+this.dataIndexOffset,s.value]);return a?{x:a[0],y:a[1]}:null}}),W(this,"upColor","#00da3c"),W(this,"downColor","#ec0000"),W(this,"defaultPadding",0),W(this,"padding"),W(this,"dataIndexOffset",0),W(this,"_paddingPoints",0),W(this,"LAZY_MIN_PADDING",5),W(this,"LAZY_MAX_PADDING",500),W(this,"LAZY_CHUNK_SIZE",50),W(this,"LAZY_EDGE_THRESHOLD",10),W(this,"_expandScheduled",!1),W(this,"rootContainer"),W(this,"layoutContainer"),W(this,"toolbarContainer"),W(this,"leftSidebar"),W(this,"rightSidebar"),W(this,"chartContainer"),W(this,"overlayContainer"),W(this,"_lastTables",[]),W(this,"_tableGraphicIds",[]),W(this,"_baseGraphics",[]),W(this,"_labelTooltipEl",null),W(this,"_lastLayout",null),W(this,"_mainHeightOverride",null),W(this,"_paneDragState",null),W(this,"_paneResizeRafId",null),W(this,"onKeyDown",s=>{(s.key==="Delete"||s.key==="Backspace")&&this.selectedDrawingId&&(this.removeDrawing(this.selectedDrawingId),this.selectedDrawingId=null,this.render())}),W(this,"onFullscreenChange",()=>{this.render()}),W(this,"isLocked",!1),W(this,"lockedState",null),this.rootContainer=t,this.options={title:void 0,height:"600px",backgroundColor:"#1e293b",upColor:"#00da3c",downColor:"#ec0000",fontColor:"#cbd5e1",fontFamily:"sans-serif",padding:.01,dataZoom:{visible:!0,position:"top",height:6},layout:{mainPaneHeight:"50%",gap:13},watermark:!0,...e},this.options.upColor&&(this.upColor=this.options.upColor),this.options.downColor&&(this.downColor=this.options.downColor),this.padding=this.options.padding!==void 0?this.options.padding:this.defaultPadding,this.options.height&&(typeof this.options.height=="number"?this.rootContainer.style.height=`${this.options.height}px`:this.rootContainer.style.height=this.options.height),this.rootContainer.innerHTML="",this.layoutContainer=document.createElement("div"),this.layoutContainer.style.display="flex",this.layoutContainer.style.width="100%",this.layoutContainer.style.height="100%",this.layoutContainer.style.overflow="hidden",this.rootContainer.appendChild(this.layoutContainer),this.leftSidebar=document.createElement("div"),this.leftSidebar.style.display="none",this.leftSidebar.style.width="250px",this.leftSidebar.style.flexShrink="0",this.leftSidebar.style.overflowY="auto",this.leftSidebar.style.backgroundColor=this.options.backgroundColor||"#1e293b",this.leftSidebar.style.borderRight="1px solid #334155",this.leftSidebar.style.padding="10px",this.leftSidebar.style.boxSizing="border-box",this.leftSidebar.style.color="#cbd5e1",this.leftSidebar.style.fontSize="12px",this.leftSidebar.style.fontFamily=this.options.fontFamily||"sans-serif",this.layoutContainer.appendChild(this.leftSidebar),this.toolbarContainer=document.createElement("div"),this.layoutContainer.appendChild(this.toolbarContainer),this.chartContainer=document.createElement("div"),this.chartContainer.style.flexGrow="1",this.chartContainer.style.height="100%",this.chartContainer.style.overflow="hidden",this.layoutContainer.appendChild(this.chartContainer),this.rightSidebar=document.createElement("div"),this.rightSidebar.style.display="none",this.rightSidebar.style.width="250px",this.rightSidebar.style.flexShrink="0",this.rightSidebar.style.overflowY="auto",this.rightSidebar.style.backgroundColor=this.options.backgroundColor||"#1e293b",this.rightSidebar.style.borderLeft="1px solid #334155",this.rightSidebar.style.padding="10px",this.rightSidebar.style.boxSizing="border-box",this.rightSidebar.style.color="#cbd5e1",this.rightSidebar.style.fontSize="12px",this.rightSidebar.style.fontFamily=this.options.fontFamily||"sans-serif",this.layoutContainer.appendChild(this.rightSidebar),this.chart=_.init(this.chartContainer),this.chartContainer.style.position="relative",this.overlayContainer=document.createElement("div"),this.overlayContainer.style.cssText="position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:100;overflow:hidden;",this.chartContainer.appendChild(this.overlayContainer),this.pluginManager=new _i(this,this.toolbarContainer),this.drawingEditor=new $i(this),this.chart.on("dataZoom",s=>{this.events.emit("chart:dataZoom",s);const l=this.options.databox?.triggerOn,a=this.options.databox?.position;l==="click"&&a==="floating"&&this.chart.dispatchAction({type:"hideTip"}),this._checkEdgeAndExpand()}),this.chart.on("finished",s=>this.events.emit("chart:updated",s)),this.chart.getZr().on("mousedown",s=>{this._paneDragState||this.events.emit("mouse:down",s)}),this.chart.getZr().on("mousemove",s=>{this._paneDragState||this.events.emit("mouse:move",s)}),this.chart.getZr().on("mouseup",s=>this.events.emit("mouse:up",s)),this.chart.getZr().on("click",s=>{this._paneDragState||this.events.emit("mouse:click",s)});const i=this.chart.getZr(),n=i.setCursorStyle,r=this;i.setCursorStyle=function(s){if(r._paneDragState){n.call(this,"row-resize");return}s==="grab"&&(s="crosshair"),n.call(this,s)},this.bindDrawingEvents(),this.bindPaneResizeEvents(),window.addEventListener("resize",this.resize.bind(this)),document.addEventListener("fullscreenchange",this.onFullscreenChange),document.addEventListener("keydown",this.onKeyDown)}bindPaneResizeEvents(){const t=this.chart.getZr(),e=n=>{if(!this._lastLayout||this._lastLayout.paneBoundaries.length===0||this.maximizedPaneId)return null;const r=this.chart.getHeight();if(r<=0)return null;for(const s of this._lastLayout.paneBoundaries){const l=s.yPercent/100*r;if(Math.abs(n-l)<=6){if(s.aboveId==="main"&&this.isMainCollapsed||this.indicators.get(s.belowId)?.collapsed||s.aboveId!=="main"&&this.indicators.get(s.aboveId)?.collapsed)continue;return s}}return null},i=n=>n==="main"?this._lastLayout?.mainPaneHeight??50:this.indicators.get(n)?.height??15;t.on("mousemove",n=>{if(this._paneDragState){const r=n.offsetY-this._paneDragState.startY,s=this.chart.getHeight();if(s<=0)return;const l=r/s*100,a=this._paneDragState.aboveId==="main"?10:5,o=5;let c=this._paneDragState.startAboveHeight+l,y=this._paneDragState.startBelowHeight-l;if(c<a&&(c=a,y=this._paneDragState.startAboveHeight+this._paneDragState.startBelowHeight-a),y<o&&(y=o,c=this._paneDragState.startAboveHeight+this._paneDragState.startBelowHeight-o),this._paneDragState.aboveId==="main")this._mainHeightOverride=c;else{const u=this.indicators.get(this._paneDragState.aboveId);u&&(u.height=c)}const d=this.indicators.get(this._paneDragState.belowId);d&&(d.height=y),this._paneResizeRafId||(this._paneResizeRafId=requestAnimationFrame(()=>{this._paneResizeRafId=null,this.render()})),t.setCursorStyle("row-resize"),n.stop?.();return}e(n.offsetY)&&t.setCursorStyle("row-resize")}),t.on("mousedown",n=>{const r=e(n.offsetY);r&&(this._paneDragState={startY:n.offsetY,aboveId:r.aboveId,belowId:r.belowId,startAboveHeight:i(r.aboveId),startBelowHeight:i(r.belowId)},t.setCursorStyle("row-resize"),n.stop?.())}),t.on("mouseup",()=>{this._paneDragState&&(this._paneDragState=null,this._paneResizeRafId&&(cancelAnimationFrame(this._paneResizeRafId),this._paneResizeRafId=null),this.render())})}bindDrawingEvents(){let t=null;const e=i=>{if(!i||i.componentType!=="series"||!i.seriesName?.startsWith("drawings"))return null;i.seriesIndex;const n=i.seriesName.match(/drawings-pane-(\d+)/);if(!n)return null;const r=parseInt(n[1]),s=this.drawings.filter(a=>(a.paneIndex||0)===r)[i.dataIndex];if(!s)return null;const l=i.event?.target?.name;return{drawing:s,targetName:l,paneIdx:r}};this.chart.on("mouseover",i=>{const n=e(i);if(!n)return;const r=i.event?.target?.parent;if(r){const s=n.drawing.id===this.selectedDrawingId;t&&(clearTimeout(t),t=null),s||r.children().forEach(l=>{l.name&&l.name.startsWith("point")&&l.attr("style",{opacity:1})})}if(n.targetName==="line")this.events.emit("drawing:hover",{id:n.drawing.id,type:n.drawing.type}),this.chart.getZr().setCursorStyle("move");else if(n.targetName?.startsWith("point-")){const s=parseInt(n.targetName.split("-")[1])||0;this.events.emit("drawing:point:hover",{id:n.drawing.id,pointIndex:s}),this.chart.getZr().setCursorStyle("pointer")}}),this.chart.on("mouseout",i=>{const n=e(i);if(!n)return;const r=i.event?.target?.parent;if(n.drawing.id!==this.selectedDrawingId){if(t=setTimeout(()=>{if(r){if(this.selectedDrawingId===n.drawing.id)return;r.children().forEach(s=>{s.name&&s.name.startsWith("point")&&s.attr("style",{opacity:0})})}},50),n.targetName==="line")this.events.emit("drawing:mouseout",{id:n.drawing.id});else if(n.targetName?.startsWith("point-")){const s=parseInt(n.targetName.split("-")[1])||0;this.events.emit("drawing:point:mouseout",{id:n.drawing.id,pointIndex:s})}this.chart.getZr().setCursorStyle("default")}}),this.chart.on("mousedown",i=>{const n=e(i);if(!n)return;const r=i.event?.event||i.event,s=r?.offsetX,l=r?.offsetY;if(n.targetName==="line")this.events.emit("drawing:mousedown",{id:n.drawing.id,x:s,y:l});else if(n.targetName?.startsWith("point-")){const a=parseInt(n.targetName.split("-")[1])||0;this.events.emit("drawing:point:mousedown",{id:n.drawing.id,pointIndex:a,x:s,y:l})}}),this.chart.on("click",i=>{const n=e(i);if(n){if(this.selectedDrawingId!==n.drawing.id&&(this.selectedDrawingId=n.drawing.id,this.events.emit("drawing:selected",{id:n.drawing.id}),this.render()),n.targetName==="line")this.events.emit("drawing:click",{id:n.drawing.id});else if(n.targetName?.startsWith("point-")){const r=parseInt(n.targetName.split("-")[1])||0;this.events.emit("drawing:point:click",{id:n.drawing.id,pointIndex:r})}}}),this.chart.getZr().on("click",i=>{i.target||this.selectedDrawingId&&(this.events.emit("drawing:deselected",{id:this.selectedDrawingId}),this.selectedDrawingId=null,this.render())}),this._labelTooltipEl=document.createElement("div"),this._labelTooltipEl.style.cssText="position:absolute;display:none;pointer-events:none;z-index:200;background:rgba(30,41,59,0.95);color:#fff;border:1px solid #475569;border-radius:4px;padding:6px 10px;font-size:12px;line-height:1.5;white-space:pre-wrap;max-width:350px;box-shadow:0 2px 8px rgba(0,0,0,0.3);font-family:"+(this.options.fontFamily||"sans-serif")+";",this.chartContainer.appendChild(this._labelTooltipEl),this.chart.on("mouseover",{seriesType:"scatter"},i=>{const n=i.data?._tooltipText;if(!n||!this._labelTooltipEl)return;this._labelTooltipEl.textContent=n,this._labelTooltipEl.style.display="block";const r=this.chartContainer.getBoundingClientRect(),s=i.event?.event;if(s){const l=s.clientX-r.left,a=s.clientY-r.top,o=this._labelTooltipEl.offsetWidth,c=Math.min(l-o/2,r.width-o-8);this._labelTooltipEl.style.left=Math.max(4,c)+"px",this._labelTooltipEl.style.top=a+18+"px"}}),this.chart.on("mouseout",{seriesType:"scatter"},()=>{this._labelTooltipEl&&(this._labelTooltipEl.style.display="none")})}getChart(){return this.chart}getMarketData(){return this.marketData}getTimeToIndex(){return this.timeToIndex}getOptions(){return this.options}disableTools(){this.pluginManager.deactivatePlugin()}registerPlugin(t){this.pluginManager.register(t)}registerDrawingRenderer(t){this.drawingRenderers.register(t)}snapToCandle(t){const e=this.coordinateConversion.pixelToData(t);if(!e)return t;const i=e.paneIndex||0;if(i!==0)return t;const n=Math.round(e.timeIndex);if(n<0||n>=this.marketData.length)return t;const r=this.marketData[n];if(!r)return t;const s=this.chart.convertToPixel({gridIndex:i},[n+this.dataIndexOffset,r.close]);if(!s)return t;const l=s[0],a=[r.open,r.high,r.low,r.close];let o=a[0],c=1/0;for(const d of a){const u=this.chart.convertToPixel({gridIndex:i},[n+this.dataIndexOffset,d]);if(u){const p=Math.abs(u[1]-t.y);p<c&&(c=p,o=d)}}const y=this.chart.convertToPixel({gridIndex:i},[n+this.dataIndexOffset,o]);return{x:l,y:y?y[1]:t.y}}addDrawing(t){this.drawings.push(t),this.render()}removeDrawing(t){const e=this.drawings.findIndex(i=>i.id===t);if(e!==-1){const i=this.drawings[e];this.drawings.splice(e,1),this.events.emit("drawing:deleted",{id:i.id}),this.render()}}getDrawing(t){return this.drawings.find(e=>e.id===t)}updateDrawing(t){const e=this.drawings.findIndex(i=>i.id===t.id);e!==-1&&(this.drawings[e]=t,this.render())}lockChart(){if(this.isLocked)return;this.isLocked=!0;const t=this.chart.getOption();this.chart.setOption({dataZoom:t.dataZoom.map(e=>({...e,disabled:!0})),tooltip:{show:!1}})}unlockChart(){if(!this.isLocked)return;this.isLocked=!1;const t=this.chart.getOption();(this.options.dataZoom||{}).visible,t.dataZoom&&this.chart.setOption({dataZoom:t.dataZoom.map(e=>({...e,disabled:!1})),tooltip:{show:!0}})}setZoom(t,e){this.chart.dispatchAction({type:"dataZoom",start:t,end:e})}setMarketData(t){this.marketData=t,this.rebuildTimeIndex(),this.render()}updateData(t){if(t.length===0)return;const e=new Map;this.marketData.forEach(m=>{e.set(m.time,m)}),t.forEach(m=>{e.has(m.time),e.set(m.time,m)}),this.marketData=Array.from(e.values()).sort((m,x)=>m.time-x.time),this.rebuildTimeIndex();const i=this.dataIndexOffset,n=_t.buildCandlestickSeries(this.marketData,this.options),r={value:[NaN,NaN,NaN,NaN],itemStyle:{opacity:0}},s=[...Array(i).fill(r),...n.data,...Array(i).fill(r)],l=[...Array(i).fill(""),...this.marketData.map(m=>new Date(m.time).toLocaleString()),...Array(i).fill("")],a=this.chart.getOption(),o=Qt.calculate(this.chart.getHeight(),this.indicators,this.options,this.isMainCollapsed,this.maximizedPaneId,this.marketData,this._mainHeightOverride??void 0);this._lastLayout=o;const c=[...Array(i).fill(null),...this.marketData,...Array(i).fill(null)],{series:y,barColors:d}=_t.buildIndicatorSeries(this.indicators,this.timeToIndex,o.paneLayout,l.length,i,c,o.overlayYAxisMap,o.separatePaneYAxisOffset),u=s.map((m,x)=>d[x]?{value:m.value||m,itemStyle:{color:d[x],color0:d[x]}}:m),p=this._buildDrawingRangeHints(o,i),f={xAxis:a.xAxis.map((m,x)=>({data:l})),series:[{data:u,markLine:n.markLine},...y,...p]};this.chart.setOption(f,{notMerge:!1});const g=[];this.indicators.forEach(m=>{Object.values(m.plots).forEach(x=>{x.options?.style==="table"&&x.data?.forEach(P=>{(Array.isArray(P.value)?P.value:[P.value]).forEach(w=>{w&&!w._deleted&&(w._paneIndex=w.force_overlay?0:m.paneIndex,g.push(w))})})})}),this._lastTables=g,this._renderTableOverlays(),this.startCountdown()}startCountdown(){if(this.stopCountdown(),!this.options.lastPriceLine?.showCountdown||this.marketData.length===0)return;let t=this.options.interval;if(!t&&this.marketData.length>=2){const i=this.marketData[this.marketData.length-1],n=this.marketData[this.marketData.length-2];t=i.time-n.time}if(!t)return;const e=()=>{if(this.marketData.length===0)return;const i=this.marketData[this.marketData.length-1].time+t,n=Date.now(),r=i-n;if(r<=0)return;const s=Math.abs(r),l=Math.floor(s/36e5),a=Math.floor(s%36e5/6e4),o=Math.floor(s%6e4/1e3),c=`${l>0?l.toString().padStart(2,"0")+":":""}${a.toString().padStart(2,"0")}:${o.toString().padStart(2,"0")}`,y=this.chart.getOption();if(!y||!y.series)return;const d=y.series.findIndex(x=>x.type==="candlestick");if(d===-1)return;const u=y.series[d];if(!u.markLine||!u.markLine.data||!u.markLine.data[0])return;const p=u.markLine.data[0];p.label.formatter;const f=p.yAxis;let g="";if(this.options.yAxisLabelFormatter)g=this.options.yAxisLabelFormatter(f);else{const x=this.options.yAxisDecimalPlaces!==void 0?this.options.yAxisDecimalPlaces:U.autoDetectDecimals(this.marketData);g=U.formatValue(f,x)}const m=`${g}
|
|
41
|
+
${c}`;this.chart.setOption({series:[{id:"__candlestick__",markLine:{data:[{...p,label:{...p.label,formatter:m}}]}}]})};e(),this.countdownInterval=setInterval(e,1e3)}stopCountdown(){this.countdownInterval&&(clearInterval(this.countdownInterval),this.countdownInterval=null)}addIndicator(t,e,i={}){const n=i.overlay!==void 0?i.overlay:i.isOverlay??!1;let r=0;if(!n){let l=0;this.indicators.forEach(a=>{a.paneIndex>l&&(l=a.paneIndex)}),r=l+1}const s=new ri(t,e,r,{height:i.height,collapsed:!1,titleColor:i.titleColor,controls:i.controls});return this.indicators.set(t,s),this.render(),s}setIndicator(t,e,i=!1){this.addIndicator(t,{[t]:e},{overlay:i})}removeIndicator(t){this.indicators.delete(t),this.render()}toggleIndicator(t,e="collapse"){if(e==="fullscreen"){document.fullscreenElement?document.exitFullscreen():this.rootContainer.requestFullscreen();return}if(e==="maximize"){this.maximizedPaneId===t?this.maximizedPaneId=null:this.maximizedPaneId=t,this.render();return}if(t==="main"){this.isMainCollapsed=!this.isMainCollapsed,this.render();return}const i=this.indicators.get(t);i&&(i.toggleCollapse(),this.render())}resize(){this.chart.resize(),this._renderTableOverlays()}_buildDrawingRangeHints(t,e){const i=[],n=new Map;for(const s of this.indicators){if(!s.plots)continue;const l=s.paneIndex??0;n.has(l)||n.set(l,{yMin:1/0,yMax:-1/0});const a=n.get(l);for(const[o,c]of Object.entries(s.plots)){if(!c||!c.options)continue;const y=c.options?.style;if(y==="drawing_line"&&c.data)for(const d of c.data){const u=d?.value?Array.isArray(d.value)?d.value:[d.value]:[];for(const p of u)!p||p._deleted||(typeof p.y1=="number"&&isFinite(p.y1)&&(a.yMin=Math.min(a.yMin,p.y1),a.yMax=Math.max(a.yMax,p.y1)),typeof p.y2=="number"&&isFinite(p.y2)&&(a.yMin=Math.min(a.yMin,p.y2),a.yMax=Math.max(a.yMax,p.y2)))}if(y==="drawing_box"&&c.data)for(const d of c.data){const u=d?.value?Array.isArray(d.value)?d.value:[d.value]:[];for(const p of u)!p||p._deleted||(typeof p.top=="number"&&isFinite(p.top)&&(a.yMin=Math.min(a.yMin,p.top),a.yMax=Math.max(a.yMax,p.top)),typeof p.bottom=="number"&&isFinite(p.bottom)&&(a.yMin=Math.min(a.yMin,p.bottom),a.yMax=Math.max(a.yMax,p.bottom)))}if(y==="label"&&c.data)for(const d of c.data){const u=d?.value?Array.isArray(d.value)?d.value:[d.value]:[];for(const p of u)!p||p._deleted||typeof p.y=="number"&&isFinite(p.y)&&(a.yMin=Math.min(a.yMin,p.y),a.yMax=Math.max(a.yMax,p.y))}if(y==="drawing_polyline"&&c.data)for(const d of c.data){const u=d?.value?Array.isArray(d.value)?d.value:[d.value]:[];for(const p of u)if(!(!p||p._deleted||!p._points))for(const f of p._points)typeof f?.price=="number"&&isFinite(f.price)&&(a.yMin=Math.min(a.yMin,f.price),a.yMax=Math.max(a.yMax,f.price))}}}const r=e+Math.floor((this.marketData?.length||0)/2);return n.forEach((s,l)=>{if(!isFinite(s.yMin)||!isFinite(s.yMax))return;const a=l===0?0:(t.separatePaneYAxisOffset||1)+(l-1);i.push({name:`_drawingRange_pane${l}`,type:"scatter",xAxisIndex:l,yAxisIndex:a,symbol:"none",symbolSize:0,silent:!0,animation:!1,data:[[r,s.yMin],[r,s.yMax]],tooltip:{show:!1}})}),i}_buildTableGraphics(){const t=this.chart.getModel(),e=n=>t.getComponent("grid",n)?.coordinateSystem?.getRect(),i=st.buildGraphicElements(this._lastTables,e);this._tableGraphicIds=[];for(let n=0;n<i.length;n++){const r=`__qf_table_${n}`;i[n].id=r,this._tableGraphicIds.push(r)}return i}_renderTableOverlays(){const t=this._buildTableGraphics(),e=[...this._baseGraphics,...t];this.chart.setOption({graphic:e},{replaceMerge:["graphic"]}),ht.clearAll(this.overlayContainer)}destroy(){this.stopCountdown(),window.removeEventListener("resize",this.resize.bind(this)),document.removeEventListener("fullscreenchange",this.onFullscreenChange),document.removeEventListener("keydown",this.onKeyDown),this.pluginManager.deactivatePlugin(),this.pluginManager.destroy(),this.chart.dispose()}rebuildTimeIndex(){this.timeToIndex.clear(),this.marketData.forEach((i,n)=>{this.timeToIndex.set(i.time,n)});const t=this.marketData.length,e=Math.ceil(t*this.padding);this._paddingPoints=Math.max(this._paddingPoints,e,this.LAZY_MIN_PADDING),this.dataIndexOffset=this._paddingPoints}expandPadding(t){this._resizePadding(t)}_resizePadding(t){const e=Math.ceil(this.marketData.length*this.padding);if(t=Math.max(t,e,this.LAZY_MIN_PADDING),t=Math.min(t,this.LAZY_MAX_PADDING),t===this._paddingPoints)return;const i=this._paddingPoints,n=this.marketData.length+2*i,r=this.chart.getOption(),s=r?.dataZoom?.find(C=>C.type==="slider"||C.type==="inside"),l=s?s.start/100*n:0,a=s?s.end/100*n:n,o=t-i;this._paddingPoints=t,this.dataIndexOffset=this._paddingPoints;const c=this._paddingPoints,y={value:[NaN,NaN,NaN,NaN],itemStyle:{opacity:0}},d=_t.buildCandlestickSeries(this.marketData,this.options),u=[...Array(c).fill(y),...d.data,...Array(c).fill(y)],p=[...Array(c).fill(""),...this.marketData.map(C=>new Date(C.time).toLocaleString()),...Array(c).fill("")],f=[...Array(c).fill(null),...this.marketData,...Array(c).fill(null)],g=Qt.calculate(this.chart.getHeight(),this.indicators,this.options,this.isMainCollapsed,this.maximizedPaneId,this.marketData,this._mainHeightOverride??void 0),{series:m,barColors:x}=_t.buildIndicatorSeries(this.indicators,this.timeToIndex,g.paneLayout,p.length,c,f,g.overlayYAxisMap,g.separatePaneYAxisOffset),P=u.map((C,A)=>x[A]?{value:C.value||C,itemStyle:{color:x[A],color0:x[A]}}:C),w=this.marketData.length+2*t,D=Math.max(0,(l+o)/w*100),S=Math.min(100,(a+o)/w*100),M=[],b=new Map;this.drawings.forEach(C=>{const A=C.paneIndex||0;b.has(A)||b.set(A,[]),b.get(A).push(C)}),b.forEach(C=>{M.push({data:C.map(A=>{const G=[];return A.points.forEach(z=>{G.push(z.timeIndex+this.dataIndexOffset,z.value)}),G})})});const k={xAxis:r.xAxis.map(()=>({data:p})),dataZoom:(r.dataZoom||[]).map(()=>({start:D,end:S})),series:[{data:P,markLine:d.markLine},...m.map(C=>{const A={data:C.data};return C.renderItem&&(A.renderItem=C.renderItem),A}),...M]};this.chart.setOption(k,{notMerge:!1})}_checkEdgeAndExpand(){if(this._expandScheduled)return;const t=this.chart.getOption()?.dataZoom?.find(f=>f.type==="slider"||f.type==="inside");if(!t)return;const e=this._paddingPoints,i=this.marketData.length,n=i+2*e,r=Math.round(t.start/100*n),s=Math.round(t.end/100*n),l=e,a=e+i-1,o=Math.max(0,Math.min(s,a)-Math.max(r,l)+1),c=r<this.LAZY_EDGE_THRESHOLD,y=s>n-this.LAZY_EDGE_THRESHOLD;if((c||y)&&e<this.LAZY_MAX_PADDING&&o>=3){this._expandScheduled=!0,requestAnimationFrame(()=>{this._expandScheduled=!1,this._resizePadding(e+this.LAZY_CHUNK_SIZE)});return}const d=Math.max(0,e-r),u=Math.max(0,s-(e+i-1)),p=Math.max(d+this.LAZY_CHUNK_SIZE,u+this.LAZY_CHUNK_SIZE);e>p+this.LAZY_CHUNK_SIZE&&(this._expandScheduled=!0,requestAnimationFrame(()=>{this._expandScheduled=!1,this._resizePadding(p)}))}render(){if(this.marketData.length===0)return;let t=null;try{const M=this.chart.getOption();if(M&&M.dataZoom&&M.dataZoom.length>0){const b=M.dataZoom.find(k=>k.type==="slider"||k.type==="inside");b&&(t={start:b.start,end:b.end})}}catch{}const e=this.options.databox?.position,i=this.leftSidebar.style.display,n=this.rightSidebar.style.display,r=e==="left"?"block":"none",s=e==="right"?"block":"none";(i!==r||n!==s)&&(this.leftSidebar.style.display=r,this.rightSidebar.style.display=s,this.chart.resize());const l=this.dataIndexOffset,a=[...Array(l).fill(""),...this.marketData.map(M=>new Date(M.time).toLocaleString()),...Array(l).fill("")],o=Qt.calculate(this.chart.getHeight(),this.indicators,this.options,this.isMainCollapsed,this.maximizedPaneId,this.marketData,this._mainHeightOverride??void 0);if(this._lastLayout=o,!t&&o.dataZoom&&this.marketData.length>0){const M=this.marketData.length,b=a.length,k=l/b,C=M/b;o.dataZoom.forEach(A=>{if(A.start!==void 0){const G=A.start/100,z=k+G*C;A.start=z*100}if(A.end!==void 0){const G=A.end/100,z=k+G*C;A.end=z*100}})}t&&o.dataZoom&&o.dataZoom.forEach(M=>{M.start=t.start,M.end=t.end}),o.xAxis.forEach(M=>{M.data=a,M.boundaryGap=!1});const c=_t.buildCandlestickSeries(this.marketData,this.options),y={value:[NaN,NaN,NaN,NaN],itemStyle:{opacity:0}};c.data=[...Array(l).fill(y),...c.data,...Array(l).fill(y)];const d=[...Array(l).fill(null),...this.marketData,...Array(l).fill(null)],{series:u,barColors:p}=_t.buildIndicatorSeries(this.indicators,this.timeToIndex,o.paneLayout,a.length,l,d,o.overlayYAxisMap,o.separatePaneYAxisOffset),f=this._buildDrawingRangeHints(o,l);c.data=c.data.map((M,b)=>p[b]?{value:M.value||M,itemStyle:{color:p[b],color0:p[b]}}:M);const g=[];this.indicators.forEach((M,b)=>{M.paneIndex===0&&g.push({id:b,titleColor:M.titleColor})});const m=Di.build(o,this.options,this.toggleIndicator.bind(this),this.isMainCollapsed,this.maximizedPaneId,g),x=new Map;this.drawings.forEach(M=>{const b=M.paneIndex||0;x.has(b)||x.set(b,[]),x.get(b).push(M)});const P=[];x.forEach((M,b)=>{P.push({type:"custom",name:`drawings-pane-${b}`,xAxisIndex:b,yAxisIndex:b,clip:!0,renderItem:(k,C)=>{const A=M[k.dataIndex];if(!A)return;const G=this.drawingRenderers.get(A.type);if(!G)return;const z=this.dataIndexOffset,$=A.points.map(v=>C.coord([v.timeIndex+z,v.value]));return G.render({drawing:A,pixelPoints:$,isSelected:A.id===this.selectedDrawingId,api:C,coordSys:k.coordSys})},data:M.map(k=>{const C=[];return k.points.forEach(A=>{C.push(A.timeIndex+this.dataIndexOffset,A.value)}),C}),encode:(()=>{const k=M.reduce((G,z)=>Math.max(G,z.points.length),0),C=Array.from({length:k},(G,z)=>z*2),A=Array.from({length:k},(G,z)=>z*2+1);return{x:C,y:A}})(),z:100,silent:!1})});const w=M=>{const b=Mi.format(M,this.options),k=this.options.databox?.position;return k==="left"?(this.leftSidebar.innerHTML=b,""):k==="right"?(this.rightSidebar.innerHTML=b,""):this.options.databox?`<div style="min-width: 200px;">${b}</div>`:""},D=[];this.indicators.forEach(M=>{Object.values(M.plots).forEach(b=>{b.options?.style==="table"&&b.data?.forEach(k=>{(Array.isArray(k.value)?k.value:[k.value]).forEach(C=>{C&&!C._deleted&&(C._paneIndex=C.force_overlay?0:M.paneIndex,D.push(C))})})})});const S={backgroundColor:this.options.backgroundColor,animation:!1,legend:{show:!1},tooltip:{show:!0,showContent:!!this.options.databox,trigger:"axis",triggerOn:this.options.databox?.triggerOn??"mousemove",axisPointer:{type:"cross",label:{backgroundColor:"#475569"}},backgroundColor:"rgba(30, 41, 59, 0.9)",borderWidth:1,borderColor:"#334155",padding:10,textStyle:{color:"#fff",fontFamily:this.options.fontFamily||"sans-serif"},formatter:w,extraCssText:e!=="floating"&&e!==void 0?"display: none !important;":void 0,position:(M,b,k,C,A)=>{if(this.options.databox?.position==="floating"){const G={top:10};return G[["left","right"][+(M[0]<A.viewSize[0]/2)]]=30,G}return null}},axisPointer:{link:{xAxisIndex:"all"},label:{backgroundColor:"#475569"}},graphic:m,grid:o.grid,xAxis:o.xAxis,yAxis:o.yAxis,dataZoom:o.dataZoom,series:[c,...u,...f,...P]};if(this.chart.setOption(S,!0),this._baseGraphics=m,this._lastTables=D,D.length>0){const M=this._buildTableGraphics();if(M.length>0){const b=[...m,...M];this.chart.setOption({graphic:b},{replaceMerge:["graphic"]})}}else this._tableGraphicIds=[];ht.clearAll(this.overlayContainer)}}var Oi=Object.defineProperty,Bi=(h,t,e)=>t in h?Oi(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,pt=(h,t,e)=>(Bi(h,typeof t!="symbol"?t+"":t,e),e);class K{constructor(t){pt(this,"id"),pt(this,"name"),pt(this,"icon"),pt(this,"context"),pt(this,"eventListeners",[]),pt(this,"_snapIndicator",null),pt(this,"_snapMoveHandler",null),pt(this,"_snapKeyDownHandler",null),pt(this,"_snapKeyUpHandler",null),pt(this,"_snapBlurHandler",null),pt(this,"_snapActive",!1),pt(this,"_lastMouseEvent",null),this.id=t.id,this.name=t.name,this.icon=t.icon}init(t){this.context=t,this.onInit()}onInit(){}activate(){this.onActivate(),this._bindSnapIndicator(),this.context.events.emit("plugin:activated",this.id)}onActivate(){}deactivate(){this._unbindSnapIndicator(),this.onDeactivate(),this.context.events.emit("plugin:deactivated",this.id)}onDeactivate(){}destroy(){this._unbindSnapIndicator(),this.removeAllListeners(),this.onDestroy()}onDestroy(){}on(t,e){this.context.events.on(t,e),this.eventListeners.push({event:t,handler:e})}off(t,e){this.context.events.off(t,e),this.eventListeners=this.eventListeners.filter(i=>i.event!==t||i.handler!==e)}removeAllListeners(){this.eventListeners.forEach(({event:t,handler:e})=>{this.context.events.off(t,e)}),this.eventListeners=[]}get chart(){return this.context.getChart()}get marketData(){return this.context.getMarketData()}getPoint(t){const e=t.offsetX,i=t.offsetY,n=t.event;if(n?.ctrlKey||n?.metaKey){const r=this.context.snapToCandle({x:e,y:i});return[r.x,r.y]}return[e,i]}_bindSnapIndicator(){const t=this.context.getChart().getZr();this._snapMoveHandler=e=>{this._lastMouseEvent=e,e.event?.ctrlKey||e.event?.metaKey?this._showSnapAt(e.offsetX,e.offsetY):this._hideSnap()},this._snapKeyDownHandler=e=>{(e.key==="Control"||e.key==="Meta")&&this._lastMouseEvent&&this._showSnapAt(this._lastMouseEvent.offsetX,this._lastMouseEvent.offsetY)},this._snapKeyUpHandler=e=>{(e.key==="Control"||e.key==="Meta")&&this._hideSnap()},this._snapBlurHandler=()=>{this._hideSnap()},t.on("mousemove",this._snapMoveHandler),window.addEventListener("keydown",this._snapKeyDownHandler),window.addEventListener("keyup",this._snapKeyUpHandler),window.addEventListener("blur",this._snapBlurHandler)}_unbindSnapIndicator(){if(this._snapMoveHandler){try{this.context.getChart().getZr().off("mousemove",this._snapMoveHandler)}catch{}this._snapMoveHandler=null}this._snapKeyDownHandler&&(window.removeEventListener("keydown",this._snapKeyDownHandler),this._snapKeyDownHandler=null),this._snapKeyUpHandler&&(window.removeEventListener("keyup",this._snapKeyUpHandler),this._snapKeyUpHandler=null),this._snapBlurHandler&&(window.removeEventListener("blur",this._snapBlurHandler),this._snapBlurHandler=null),this._removeSnapGraphic(),this._lastMouseEvent=null}_removeSnapGraphic(){if(this._snapIndicator){try{this.context.getChart().getZr().remove(this._snapIndicator)}catch{}this._snapIndicator=null,this._snapActive=!1}}_showSnapAt(t,e){const i=this.context.snapToCandle({x:t,y:e}),n=this.context.getChart().getZr();this._snapIndicator||(this._snapIndicator=new _.graphic.Circle({shape:{cx:0,cy:0,r:5},style:{fill:"rgba(59, 130, 246, 0.3)",stroke:"#3b82f6",lineWidth:1.5},z:9999,silent:!0}),n.add(this._snapIndicator)),this._snapIndicator.setShape({cx:i.x,cy:i.y}),this._snapIndicator.show(),this._snapActive=!0}_hideSnap(){this._snapIndicator&&this._snapActive&&(this._snapIndicator.hide(),this._snapActive=!1)}}var ji=Object.defineProperty,Yi=(h,t,e)=>t in h?ji(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,ot=(h,t,e)=>(Yi(h,typeof t!="symbol"?t+"":t,e),e);class Vi extends K{constructor(t={}){super({id:"measure",name:t?.name||"Measure",icon:t?.icon||'<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="M160-240q-33 0-56.5-23.5T80-320v-320q0-33 23.5-56.5T160-720h640q33 0 56.5 23.5T880-640v320q0 33-23.5 56.5T800-240H160Zm0-80h640v-320H680v160h-80v-160h-80v160h-80v-160h-80v160h-80v-160H160v320Zm120-160h80-80Zm160 0h80-80Zm160 0h80-80Zm-120 0Z"/></svg>'}),ot(this,"zr"),ot(this,"state","idle"),ot(this,"startPoint",null),ot(this,"endPoint",null),ot(this,"group",null),ot(this,"rect",null),ot(this,"labelRect",null),ot(this,"labelText",null),ot(this,"lineV",null),ot(this,"lineH",null),ot(this,"arrowStart",null),ot(this,"arrowEnd",null),ot(this,"onMouseDown",()=>{this.state==="finished"&&this.removeGraphic()}),ot(this,"onChartInteraction",()=>{this.group&&this.removeGraphic()}),ot(this,"onClick",e=>{this.state==="idle"?(this.state="drawing",this.startPoint=this.getPoint(e),this.endPoint=this.getPoint(e),this.initGraphic(),this.updateGraphic()):this.state==="drawing"&&(this.state="finished",this.endPoint=this.getPoint(e),this.updateGraphic(),this.context.disableTools(),this.enableClearListeners())}),ot(this,"clearHandlers",{}),ot(this,"onMouseMove",e=>{this.state==="drawing"&&(this.endPoint=this.getPoint(e),this.updateGraphic())})}onInit(){this.zr=this.chart.getZr()}onActivate(){this.state="idle",this.chart.getZr().setCursorStyle("crosshair"),this.zr.on("click",this.onClick),this.zr.on("mousemove",this.onMouseMove)}onDeactivate(){this.state="idle",this.chart.getZr().setCursorStyle("default"),this.zr.off("click",this.onClick),this.zr.off("mousemove",this.onMouseMove),this.disableClearListeners(),this.state==="drawing"&&this.removeGraphic()}onDestroy(){this.removeGraphic()}enableClearListeners(){const t=()=>{this.removeGraphic()};setTimeout(()=>{this.zr.on("click",t)},10),this.zr.on("mousedown",this.onMouseDown),this.context.events.on("chart:dataZoom",this.onChartInteraction),this.clearHandlers={click:t,mousedown:this.onMouseDown,dataZoom:this.onChartInteraction}}disableClearListeners(){this.clearHandlers.click&&this.zr.off("click",this.clearHandlers.click),this.clearHandlers.mousedown&&this.zr.off("mousedown",this.clearHandlers.mousedown),this.clearHandlers.dataZoom&&this.context.events.off("chart:dataZoom",this.clearHandlers.dataZoom),this.clearHandlers={}}initGraphic(){this.group||(this.group=new _.graphic.Group,this.rect=new _.graphic.Rect({shape:{x:0,y:0,width:0,height:0},style:{fill:"rgba(0,0,0,0)",stroke:"transparent",lineWidth:0},z:100}),this.lineV=new _.graphic.Line({shape:{x1:0,y1:0,x2:0,y2:0},style:{stroke:"#fff",lineWidth:1,lineDash:[4,4]},z:101}),this.lineH=new _.graphic.Line({shape:{x1:0,y1:0,x2:0,y2:0},style:{stroke:"#fff",lineWidth:1,lineDash:[4,4]},z:101}),this.arrowStart=new _.graphic.Polygon({shape:{points:[[0,0],[-5,10],[5,10]]},style:{fill:"#fff"},z:102}),this.arrowEnd=new _.graphic.Polygon({shape:{points:[[0,0],[-5,-10],[5,-10]]},style:{fill:"#fff"},z:102}),this.labelRect=new _.graphic.Rect({shape:{x:0,y:0,width:0,height:0,r:4},style:{fill:"transparent",stroke:"transparent",lineWidth:0,shadowBlur:5,shadowColor:"rgba(0,0,0,0.3)"},z:102}),this.labelText=new _.graphic.Text({style:{x:0,y:0,text:"",fill:"#fff",font:"12px sans-serif",align:"center",verticalAlign:"middle"},z:103}),this.group.add(this.rect),this.group.add(this.lineV),this.group.add(this.lineH),this.group.add(this.arrowStart),this.group.add(this.arrowEnd),this.group.add(this.labelRect),this.group.add(this.labelText),this.zr.add(this.group))}removeGraphic(){this.group&&(this.zr.remove(this.group),this.group=null,this.disableClearListeners())}updateGraphic(){if(!this.startPoint||!this.endPoint||!this.group)return;const[t,e]=this.startPoint,[i,n]=this.endPoint,r=this.context.coordinateConversion.pixelToData({x:t,y:e}),s=this.context.coordinateConversion.pixelToData({x:i,y:n});if(!r||!s)return;const l=Math.round(r.timeIndex),a=Math.round(s.timeIndex),o=r.value,c=s.value,y=a-l,d=c-o,u=d/o*100,p=d>=0,f=p?"rgba(33, 150, 243, 0.2)":"rgba(236, 0, 0, 0.2)",g=p?"#2196F3":"#ec0000";this.rect.setShape({x:Math.min(t,i),y:Math.min(e,n),width:Math.abs(i-t),height:Math.abs(n-e)}),this.rect.setStyle({fill:f});const m=(t+i)/2,x=(e+n)/2;this.lineV.setShape({x1:m,y1:e,x2:m,y2:n}),this.lineV.setStyle({stroke:g}),this.lineH.setShape({x1:t,y1:x,x2:i,y2:x}),this.lineH.setStyle({stroke:g});const P=Math.min(e,n),w=Math.max(e,n);this.arrowStart.setStyle({fill:"none"}),this.arrowEnd.setStyle({fill:"none"}),p?(this.arrowStart.setShape({points:[[m,P],[m-4,P+6],[m+4,P+6]]}),this.arrowStart.setStyle({fill:g})):(this.arrowEnd.setShape({points:[[m,w],[m-4,w-6],[m+4,w-6]]}),this.arrowEnd.setStyle({fill:g}));const D=[`${d.toFixed(2)} (${u.toFixed(2)}%)`,`${y} bars`].join(`
|
|
42
|
+
`),S=140,M=40,b=Math.max(e,n),k=Math.min(e,n);let C=(t+i)/2-S/2,A=b+10;const G=this.chart.getHeight();A+M>G&&(A=k-M-10),this.labelRect.setShape({x:C,y:A,width:S,height:M}),this.labelRect.setStyle({fill:"#1e293b",stroke:g,lineWidth:1}),this.labelText.setStyle({x:C+S/2,y:A+M/2,text:D,fill:"#fff"})}}var Xi=Object.defineProperty,qi=(h,t,e)=>t in h?Xi(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,Ui=(h,t,e)=>(qi(h,typeof t!="symbol"?t+"":t,e),e);class fe{constructor(){Ui(this,"type","line")}render(t){const{drawing:e,pixelPoints:i,isSelected:n}=t,[r,s]=i[0],[l,a]=i[1],o=e.style?.color||"#d1d4dc";return{type:"group",children:[{type:"line",name:"line",shape:{x1:r,y1:s,x2:l,y2:a},style:{stroke:o,lineWidth:e.style?.lineWidth||1}},{type:"circle",name:"point-0",shape:{cx:r,cy:s,r:4},style:{fill:"#fff",stroke:o,lineWidth:1,opacity:n?1:0}},{type:"circle",name:"point-1",shape:{cx:l,cy:a,r:4},style:{fill:"#fff",stroke:o,lineWidth:1,opacity:n?1:0}}]}}}var Ki=Object.defineProperty,Ji=(h,t,e)=>t in h?Ki(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,ft=(h,t,e)=>(Ji(h,typeof t!="symbol"?t+"":t,e),e);class Qi extends K{constructor(t={}){super({id:"trend-line",name:t?.name||"Trend Line",icon:t?.icon||'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="2" y1="22" x2="22" y2="2" /></svg>'}),ft(this,"zr"),ft(this,"state","idle"),ft(this,"startPoint",null),ft(this,"endPoint",null),ft(this,"group",null),ft(this,"line",null),ft(this,"startCircle",null),ft(this,"endCircle",null),ft(this,"onClick",e=>{if(this.state==="idle")this.state="drawing",this.startPoint=this.getPoint(e),this.endPoint=this.getPoint(e),this.initGraphic(),this.updateGraphic();else if(this.state==="drawing"){if(this.state="finished",this.endPoint=this.getPoint(e),this.updateGraphic(),this.startPoint&&this.endPoint){const i=this.context.coordinateConversion.pixelToData({x:this.startPoint[0],y:this.startPoint[1]}),n=this.context.coordinateConversion.pixelToData({x:this.endPoint[0],y:this.endPoint[1]});if(i&&n){const r=i.paneIndex||0;this.context.addDrawing({id:`line-${Date.now()}`,type:"line",points:[i,n],paneIndex:r,style:{color:"#d1d4dc",lineWidth:1}})}}this.removeGraphic(),this.context.disableTools()}}),ft(this,"onMouseMove",e=>{this.state==="drawing"&&(this.endPoint=this.getPoint(e),this.updateGraphic())})}onInit(){this.zr=this.chart.getZr(),this.context.registerDrawingRenderer(new fe)}onActivate(){this.state="idle",this.chart.getZr().setCursorStyle("crosshair"),this.zr.on("click",this.onClick),this.zr.on("mousemove",this.onMouseMove)}onDeactivate(){this.state="idle",this.chart.getZr().setCursorStyle("default"),this.zr.off("click",this.onClick),this.zr.off("mousemove",this.onMouseMove),this.state==="drawing"&&this.removeGraphic()}onDestroy(){this.removeGraphic()}initGraphic(){this.group||(this.group=new _.graphic.Group,this.line=new _.graphic.Line({shape:{x1:0,y1:0,x2:0,y2:0},style:{stroke:"#d1d4dc",lineWidth:1},z:100}),this.startCircle=new _.graphic.Circle({shape:{cx:0,cy:0,r:4},style:{fill:"#fff",stroke:"#d1d4dc",lineWidth:1},z:101}),this.endCircle=new _.graphic.Circle({shape:{cx:0,cy:0,r:4},style:{fill:"#fff",stroke:"#d1d4dc",lineWidth:1},z:101}),this.group.add(this.line),this.group.add(this.startCircle),this.group.add(this.endCircle),this.zr.add(this.group))}removeGraphic(){this.group&&(this.zr.remove(this.group),this.group=null)}updateGraphic(){if(!this.startPoint||!this.endPoint||!this.group)return;const[t,e]=this.startPoint,[i,n]=this.endPoint;this.line.setShape({x1:t,y1:e,x2:i,y2:n}),this.startCircle.setShape({cx:t,cy:e}),this.endCircle.setShape({cx:i,cy:n})}}var tn=Object.defineProperty,en=(h,t,e)=>t in h?tn(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,nn=(h,t,e)=>(en(h,typeof t!="symbol"?t+"":t,e),e);class xe{constructor(){nn(this,"type","ray")}render(t){const{drawing:e,pixelPoints:i,isSelected:n,coordSys:r}=t,[s,l]=i[0],[a,o]=i[1],c=e.style?.color||"#d1d4dc",[y,d]=this.extendToEdge(s,l,a,o,r);return{type:"group",children:[{type:"line",name:"line",shape:{x1:s,y1:l,x2:y,y2:d},style:{stroke:c,lineWidth:e.style?.lineWidth||1}},{type:"circle",name:"point-0",shape:{cx:s,cy:l,r:4},style:{fill:"#fff",stroke:c,lineWidth:1,opacity:n?1:0}},{type:"circle",name:"point-1",shape:{cx:a,cy:o,r:4},style:{fill:"#fff",stroke:c,lineWidth:1,opacity:n?1:0}}]}}extendToEdge(t,e,i,n,r){const s=i-t,l=n-e;if(s===0&&l===0)return[i,n];const a=r.x,o=r.x+r.width,c=r.y,y=r.y+r.height;let d=1/0;if(s!==0){const u=s>0?(o-t)/s:(a-t)/s;u>0&&(d=Math.min(d,u))}if(l!==0){const u=l>0?(y-e)/l:(c-e)/l;u>0&&(d=Math.min(d,u))}return isFinite(d)||(d=1),[t+d*s,e+d*l]}}var sn=Object.defineProperty,on=(h,t,e)=>t in h?sn(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,gt=(h,t,e)=>(on(h,typeof t!="symbol"?t+"":t,e),e);const Tt="#d1d4dc";class rn extends K{constructor(t={}){super({id:"ray-tool",name:t?.name||"Ray",icon:t?.icon||'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="3" y1="20" x2="21" y2="4"/><circle cx="21" cy="4" r="0" fill="currentColor"/><polyline points="16,4 21,4 21,9" stroke-width="1.5"/></svg>'}),gt(this,"zr"),gt(this,"state","idle"),gt(this,"startPoint",null),gt(this,"endPoint",null),gt(this,"group",null),gt(this,"line",null),gt(this,"dashLine",null),gt(this,"startCircle",null),gt(this,"endCircle",null),gt(this,"onClick",e=>{if(this.state==="idle")this.state="drawing",this.startPoint=this.getPoint(e),this.endPoint=this.getPoint(e),this.initGraphic(),this.updateGraphic();else if(this.state==="drawing"){if(this.state="finished",this.endPoint=this.getPoint(e),this.startPoint&&this.endPoint){const i=this.context.coordinateConversion.pixelToData({x:this.startPoint[0],y:this.startPoint[1]}),n=this.context.coordinateConversion.pixelToData({x:this.endPoint[0],y:this.endPoint[1]});i&&n&&this.context.addDrawing({id:`ray-${Date.now()}`,type:"ray",points:[i,n],paneIndex:i.paneIndex||0,style:{color:Tt,lineWidth:1}})}this.removeGraphic(),this.context.disableTools()}}),gt(this,"onMouseMove",e=>{this.state==="drawing"&&(this.endPoint=this.getPoint(e),this.updateGraphic())})}onInit(){this.zr=this.chart.getZr(),this.context.registerDrawingRenderer(new xe)}onActivate(){this.state="idle",this.chart.getZr().setCursorStyle("crosshair"),this.zr.on("click",this.onClick),this.zr.on("mousemove",this.onMouseMove)}onDeactivate(){this.state="idle",this.chart.getZr().setCursorStyle("default"),this.zr.off("click",this.onClick),this.zr.off("mousemove",this.onMouseMove),this.removeGraphic()}onDestroy(){this.removeGraphic()}initGraphic(){this.group||(this.group=new _.graphic.Group,this.line=new _.graphic.Line({shape:{x1:0,y1:0,x2:0,y2:0},style:{stroke:Tt,lineWidth:1},z:100}),this.dashLine=new _.graphic.Line({shape:{x1:0,y1:0,x2:0,y2:0},style:{stroke:Tt,lineWidth:1,lineDash:[4,4],opacity:.5},z:99}),this.startCircle=new _.graphic.Circle({shape:{cx:0,cy:0,r:4},style:{fill:"#fff",stroke:Tt,lineWidth:1},z:101}),this.endCircle=new _.graphic.Circle({shape:{cx:0,cy:0,r:4},style:{fill:"#fff",stroke:Tt,lineWidth:1},z:101}),this.group.add(this.dashLine),this.group.add(this.line),this.group.add(this.startCircle),this.group.add(this.endCircle),this.zr.add(this.group))}removeGraphic(){this.group&&(this.zr.remove(this.group),this.group=null)}updateGraphic(){if(!this.startPoint||!this.endPoint||!this.group)return;const[t,e]=this.startPoint,[i,n]=this.endPoint;this.line.setShape({x1:t,y1:e,x2:i,y2:n}),this.startCircle.setShape({cx:t,cy:e}),this.endCircle.setShape({cx:i,cy:n});const[r,s]=this.extendToEdge(t,e,i,n);this.dashLine.setShape({x1:i,y1:n,x2:r,y2:s})}extendToEdge(t,e,i,n){const r=i-t,s=n-e;if(r===0&&s===0)return[i,n];const l=this.chart.getWidth(),a=this.chart.getHeight();let o=1/0;if(r!==0){const c=r>0?(l-t)/r:-t/r;c>0&&(o=Math.min(o,c))}if(s!==0){const c=s>0?(a-e)/s:-e/s;c>0&&(o=Math.min(o,c))}return isFinite(o)||(o=1),[t+o*r,e+o*s]}}var an=Object.defineProperty,ln=(h,t,e)=>t in h?an(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,hn=(h,t,e)=>(ln(h,typeof t!="symbol"?t+"":t,e),e);class me{constructor(){hn(this,"type","info-line")}render(t){const{drawing:e,pixelPoints:i,isSelected:n}=t,[r,s]=i[0],[l,a]=i[1],o=e.style?.color||"#d1d4dc",c=e.points[0],y=e.points[1],d=y.value-c.value,u=c.value!==0?d/c.value*100:0,p=Math.abs(y.timeIndex-c.timeIndex),f=d>=0?"+":"",g=`${f}${d.toFixed(2)} (${f}${u.toFixed(2)}%) ${p} bars`,m=(r+l)/2,x=(s+a)/2,P=d>=0?"#26a69a":"#ef5350";return{type:"group",children:[{type:"line",name:"line",shape:{x1:r,y1:s,x2:l,y2:a},style:{stroke:o,lineWidth:e.style?.lineWidth||1}},{type:"rect",shape:{x:m-2,y:x-22,width:g.length*6.5+12,height:18,r:3},style:{fill:"#1e293b",stroke:"#475569",lineWidth:1,opacity:.9},z2:10},{type:"text",x:m+4,y:x-20,style:{text:g,fill:P,fontSize:11,fontFamily:"monospace"},z2:11},{type:"circle",name:"point-0",shape:{cx:r,cy:s,r:4},style:{fill:"#fff",stroke:o,lineWidth:1,opacity:n?1:0}},{type:"circle",name:"point-1",shape:{cx:l,cy:a,r:4},style:{fill:"#fff",stroke:o,lineWidth:1,opacity:n?1:0}}]}}}var cn=Object.defineProperty,dn=(h,t,e)=>t in h?cn(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,xt=(h,t,e)=>(dn(h,typeof t!="symbol"?t+"":t,e),e);class pn extends K{constructor(t={}){super({id:"info-line-tool",name:t?.name||"Info Line",icon:t?.icon||'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="2" y1="22" x2="22" y2="2"/><rect x="12" y="8" width="8" height="5" rx="1" fill="none" stroke-width="1.5"/></svg>'}),xt(this,"zr"),xt(this,"state","idle"),xt(this,"startPoint",null),xt(this,"endPoint",null),xt(this,"group",null),xt(this,"line",null),xt(this,"startCircle",null),xt(this,"endCircle",null),xt(this,"onClick",e=>{if(this.state==="idle")this.state="drawing",this.startPoint=this.getPoint(e),this.endPoint=this.getPoint(e),this.initGraphic(),this.updateGraphic();else if(this.state==="drawing"){if(this.state="finished",this.endPoint=this.getPoint(e),this.updateGraphic(),this.startPoint&&this.endPoint){const i=this.context.coordinateConversion.pixelToData({x:this.startPoint[0],y:this.startPoint[1]}),n=this.context.coordinateConversion.pixelToData({x:this.endPoint[0],y:this.endPoint[1]});i&&n&&this.context.addDrawing({id:`info-line-${Date.now()}`,type:"info-line",points:[i,n],paneIndex:i.paneIndex||0,style:{color:"#d1d4dc",lineWidth:1}})}this.removeGraphic(),this.context.disableTools()}}),xt(this,"onMouseMove",e=>{this.state==="drawing"&&(this.endPoint=this.getPoint(e),this.updateGraphic())})}onInit(){this.zr=this.chart.getZr(),this.context.registerDrawingRenderer(new me)}onActivate(){this.state="idle",this.chart.getZr().setCursorStyle("crosshair"),this.zr.on("click",this.onClick),this.zr.on("mousemove",this.onMouseMove)}onDeactivate(){this.state="idle",this.chart.getZr().setCursorStyle("default"),this.zr.off("click",this.onClick),this.zr.off("mousemove",this.onMouseMove),this.removeGraphic()}onDestroy(){this.removeGraphic()}initGraphic(){this.group||(this.group=new _.graphic.Group,this.line=new _.graphic.Line({shape:{x1:0,y1:0,x2:0,y2:0},style:{stroke:"#d1d4dc",lineWidth:1},z:100}),this.startCircle=new _.graphic.Circle({shape:{cx:0,cy:0,r:4},style:{fill:"#fff",stroke:"#d1d4dc",lineWidth:1},z:101}),this.endCircle=new _.graphic.Circle({shape:{cx:0,cy:0,r:4},style:{fill:"#fff",stroke:"#d1d4dc",lineWidth:1},z:101}),this.group.add(this.line),this.group.add(this.startCircle),this.group.add(this.endCircle),this.zr.add(this.group))}removeGraphic(){this.group&&(this.zr.remove(this.group),this.group=null)}updateGraphic(){if(!this.startPoint||!this.endPoint||!this.group)return;const[t,e]=this.startPoint,[i,n]=this.endPoint;this.line.setShape({x1:t,y1:e,x2:i,y2:n}),this.startCircle.setShape({cx:t,cy:e}),this.endCircle.setShape({cx:i,cy:n})}}var un=Object.defineProperty,gn=(h,t,e)=>t in h?un(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,yn=(h,t,e)=>(gn(h,typeof t!="symbol"?t+"":t,e),e);class be{constructor(){yn(this,"type","extended-line")}render(t){const{drawing:e,pixelPoints:i,isSelected:n,coordSys:r}=t,[s,l]=i[0],[a,o]=i[1],c=e.style?.color||"#d1d4dc",y=a-s,d=o-l;let u=s,p=l,f=a,g=o;if(y!==0||d!==0){const m=r.x,x=r.x+r.width,P=r.y,w=r.y+r.height;[f,g]=this.extendToEdge(s,l,y,d,m,x,P,w),[u,p]=this.extendToEdge(a,o,-y,-d,m,x,P,w)}return{type:"group",children:[{type:"line",name:"line",shape:{x1:u,y1:p,x2:f,y2:g},style:{stroke:c,lineWidth:e.style?.lineWidth||1}},{type:"circle",name:"point-0",shape:{cx:s,cy:l,r:4},style:{fill:"#fff",stroke:c,lineWidth:1,opacity:n?1:0}},{type:"circle",name:"point-1",shape:{cx:a,cy:o,r:4},style:{fill:"#fff",stroke:c,lineWidth:1,opacity:n?1:0}}]}}extendToEdge(t,e,i,n,r,s,l,a){let o=1/0;if(i!==0){const c=i>0?(s-t)/i:(r-t)/i;c>0&&(o=Math.min(o,c))}if(n!==0){const c=n>0?(a-e)/n:(l-e)/n;c>0&&(o=Math.min(o,c))}return isFinite(o)||(o=1),[t+o*i,e+o*n]}}var fn=Object.defineProperty,xn=(h,t,e)=>t in h?fn(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,ut=(h,t,e)=>(xn(h,typeof t!="symbol"?t+"":t,e),e);const zt="#d1d4dc";class mn extends K{constructor(t={}){super({id:"extended-line-tool",name:t?.name||"Extended Line",icon:t?.icon||'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="1" y1="23" x2="23" y2="1" stroke-dasharray="2,2" opacity="0.4"/><line x1="6" y1="18" x2="18" y2="6"/></svg>'}),ut(this,"zr"),ut(this,"state","idle"),ut(this,"startPoint",null),ut(this,"endPoint",null),ut(this,"group",null),ut(this,"line",null),ut(this,"dashLineForward",null),ut(this,"dashLineBackward",null),ut(this,"startCircle",null),ut(this,"endCircle",null),ut(this,"onClick",e=>{if(this.state==="idle")this.state="drawing",this.startPoint=this.getPoint(e),this.endPoint=this.getPoint(e),this.initGraphic(),this.updateGraphic();else if(this.state==="drawing"){if(this.state="finished",this.endPoint=this.getPoint(e),this.startPoint&&this.endPoint){const i=this.context.coordinateConversion.pixelToData({x:this.startPoint[0],y:this.startPoint[1]}),n=this.context.coordinateConversion.pixelToData({x:this.endPoint[0],y:this.endPoint[1]});i&&n&&this.context.addDrawing({id:`extended-line-${Date.now()}`,type:"extended-line",points:[i,n],paneIndex:i.paneIndex||0,style:{color:zt,lineWidth:1}})}this.removeGraphic(),this.context.disableTools()}}),ut(this,"onMouseMove",e=>{this.state==="drawing"&&(this.endPoint=this.getPoint(e),this.updateGraphic())})}onInit(){this.zr=this.chart.getZr(),this.context.registerDrawingRenderer(new be)}onActivate(){this.state="idle",this.chart.getZr().setCursorStyle("crosshair"),this.zr.on("click",this.onClick),this.zr.on("mousemove",this.onMouseMove)}onDeactivate(){this.state="idle",this.chart.getZr().setCursorStyle("default"),this.zr.off("click",this.onClick),this.zr.off("mousemove",this.onMouseMove),this.removeGraphic()}onDestroy(){this.removeGraphic()}initGraphic(){this.group||(this.group=new _.graphic.Group,this.line=new _.graphic.Line({shape:{x1:0,y1:0,x2:0,y2:0},style:{stroke:zt,lineWidth:1},z:100}),this.dashLineForward=new _.graphic.Line({shape:{x1:0,y1:0,x2:0,y2:0},style:{stroke:zt,lineWidth:1,lineDash:[4,4],opacity:.5},z:99}),this.dashLineBackward=new _.graphic.Line({shape:{x1:0,y1:0,x2:0,y2:0},style:{stroke:zt,lineWidth:1,lineDash:[4,4],opacity:.5},z:99}),this.startCircle=new _.graphic.Circle({shape:{cx:0,cy:0,r:4},style:{fill:"#fff",stroke:zt,lineWidth:1},z:101}),this.endCircle=new _.graphic.Circle({shape:{cx:0,cy:0,r:4},style:{fill:"#fff",stroke:zt,lineWidth:1},z:101}),this.group.add(this.dashLineBackward),this.group.add(this.dashLineForward),this.group.add(this.line),this.group.add(this.startCircle),this.group.add(this.endCircle),this.zr.add(this.group))}removeGraphic(){this.group&&(this.zr.remove(this.group),this.group=null)}updateGraphic(){if(!this.startPoint||!this.endPoint||!this.group)return;const[t,e]=this.startPoint,[i,n]=this.endPoint;this.line.setShape({x1:t,y1:e,x2:i,y2:n}),this.startCircle.setShape({cx:t,cy:e}),this.endCircle.setShape({cx:i,cy:n});const r=i-t,s=n-e;if(r===0&&s===0)return;const[l,a]=this.extendToEdge(t,e,r,s);this.dashLineForward.setShape({x1:i,y1:n,x2:l,y2:a});const[o,c]=this.extendToEdge(i,n,-r,-s);this.dashLineBackward.setShape({x1:t,y1:e,x2:o,y2:c})}extendToEdge(t,e,i,n){const r=this.chart.getWidth(),s=this.chart.getHeight();let l=1/0;if(i!==0){const a=i>0?(r-t)/i:-t/i;a>0&&(l=Math.min(l,a))}if(n!==0){const a=n>0?(s-e)/n:-e/n;a>0&&(l=Math.min(l,a))}return isFinite(l)||(l=1),[t+l*i,e+l*n]}}var bn=Object.defineProperty,vn=(h,t,e)=>t in h?bn(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,wn=(h,t,e)=>(vn(h,typeof t!="symbol"?t+"":t,e),e);class ve{constructor(){wn(this,"type","trend-angle")}render(t){const{drawing:e,pixelPoints:i,isSelected:n}=t,[r,s]=i[0],[l,a]=i[1],o=e.style?.color||"#d1d4dc",c=l-r,y=a-s,d=Math.atan2(-y,c),u=(d*(180/Math.PI)).toFixed(1),p=Math.min(30,Math.sqrt(c*c+y*y)*.3),f=r+Math.max(Math.abs(c),p+20),g=0,m=-d;return{type:"group",children:[{type:"line",name:"line",shape:{x1:r,y1:s,x2:l,y2:a},style:{stroke:o,lineWidth:e.style?.lineWidth||1}},{type:"line",shape:{x1:r,y1:s,x2:f,y2:s},style:{stroke:o,lineWidth:1,opacity:.4,lineDash:[4,4]}},{type:"arc",shape:{cx:r,cy:s,r:p,startAngle:Math.min(g,m),endAngle:Math.max(g,m)},style:{stroke:o,lineWidth:1.5,fill:"none"}},{type:"text",x:r+p+6,y:s+(y<0?-14:2),style:{text:`${u}\xB0`,fill:o,fontSize:11,fontFamily:"sans-serif"},z2:10},{type:"circle",name:"point-0",shape:{cx:r,cy:s,r:4},style:{fill:"#fff",stroke:o,lineWidth:1,opacity:n?1:0}},{type:"circle",name:"point-1",shape:{cx:l,cy:a,r:4},style:{fill:"#fff",stroke:o,lineWidth:1,opacity:n?1:0}}]}}}var Cn=Object.defineProperty,Pn=(h,t,e)=>t in h?Cn(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,dt=(h,t,e)=>(Pn(h,typeof t!="symbol"?t+"":t,e),e);const kt="#d1d4dc";class kn extends K{constructor(t={}){super({id:"trend-angle-tool",name:t?.name||"Trend Angle",icon:t?.icon||'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="3" y1="20" x2="21" y2="6"/><line x1="3" y1="20" x2="14" y2="20" opacity="0.4"/><path d="M8 20 A5 5 0 0 1 7 16" stroke-width="1.5"/></svg>'}),dt(this,"zr"),dt(this,"state","idle"),dt(this,"startPoint",null),dt(this,"endPoint",null),dt(this,"group",null),dt(this,"line",null),dt(this,"hRefLine",null),dt(this,"arc",null),dt(this,"angleText",null),dt(this,"startCircle",null),dt(this,"endCircle",null),dt(this,"onClick",e=>{if(this.state==="idle")this.state="drawing",this.startPoint=this.getPoint(e),this.endPoint=this.getPoint(e),this.initGraphic(),this.updateGraphic();else if(this.state==="drawing"){if(this.state="finished",this.endPoint=this.getPoint(e),this.startPoint&&this.endPoint){const i=this.context.coordinateConversion.pixelToData({x:this.startPoint[0],y:this.startPoint[1]}),n=this.context.coordinateConversion.pixelToData({x:this.endPoint[0],y:this.endPoint[1]});i&&n&&this.context.addDrawing({id:`trend-angle-${Date.now()}`,type:"trend-angle",points:[i,n],paneIndex:i.paneIndex||0,style:{color:kt,lineWidth:1}})}this.removeGraphic(),this.context.disableTools()}}),dt(this,"onMouseMove",e=>{this.state==="drawing"&&(this.endPoint=this.getPoint(e),this.updateGraphic())})}onInit(){this.zr=this.chart.getZr(),this.context.registerDrawingRenderer(new ve)}onActivate(){this.state="idle",this.chart.getZr().setCursorStyle("crosshair"),this.zr.on("click",this.onClick),this.zr.on("mousemove",this.onMouseMove)}onDeactivate(){this.state="idle",this.chart.getZr().setCursorStyle("default"),this.zr.off("click",this.onClick),this.zr.off("mousemove",this.onMouseMove),this.removeGraphic()}onDestroy(){this.removeGraphic()}initGraphic(){this.group||(this.group=new _.graphic.Group,this.line=new _.graphic.Line({shape:{x1:0,y1:0,x2:0,y2:0},style:{stroke:kt,lineWidth:1},z:100}),this.hRefLine=new _.graphic.Line({shape:{x1:0,y1:0,x2:0,y2:0},style:{stroke:kt,lineWidth:1,lineDash:[4,4],opacity:.4},z:99}),this.arc=new _.graphic.Arc({shape:{cx:0,cy:0,r:25,startAngle:0,endAngle:0},style:{stroke:kt,lineWidth:1,fill:"none"},z:99}),this.angleText=new _.graphic.Text({style:{text:"",fill:kt,fontSize:11,fontFamily:"sans-serif"},z:101}),this.startCircle=new _.graphic.Circle({shape:{cx:0,cy:0,r:4},style:{fill:"#fff",stroke:kt,lineWidth:1},z:101}),this.endCircle=new _.graphic.Circle({shape:{cx:0,cy:0,r:4},style:{fill:"#fff",stroke:kt,lineWidth:1},z:101}),this.group.add(this.hRefLine),this.group.add(this.arc),this.group.add(this.line),this.group.add(this.angleText),this.group.add(this.startCircle),this.group.add(this.endCircle),this.zr.add(this.group))}removeGraphic(){this.group&&(this.zr.remove(this.group),this.group=null)}updateGraphic(){if(!this.startPoint||!this.endPoint||!this.group)return;const[t,e]=this.startPoint,[i,n]=this.endPoint;this.line.setShape({x1:t,y1:e,x2:i,y2:n}),this.startCircle.setShape({cx:t,cy:e}),this.endCircle.setShape({cx:i,cy:n});const r=i-t,s=n-e,l=Math.max(Math.abs(r),40);this.hRefLine.setShape({x1:t,y1:e,x2:t+l,y2:e});const a=Math.atan2(-s,r)*(180/Math.PI),o=Math.min(25,Math.sqrt(r*r+s*s)*.3),c=Math.atan2(s,r),y=Math.min(0,c),d=Math.max(0,c);this.arc.setShape({cx:t,cy:e,r:o,startAngle:y,endAngle:d}),this.angleText.setStyle({text:`${a.toFixed(1)}\xB0`}),this.angleText.x=t+o+6,this.angleText.y=e+(s<0?-14:2),this.angleText.markRedraw()}}var Dn=Object.defineProperty,Mn=(h,t,e)=>t in h?Dn(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,In=(h,t,e)=>(Mn(h,typeof t!="symbol"?t+"":t,e),e);class we{constructor(){In(this,"type","horizontal-line")}render(t){const{drawing:e,pixelPoints:i,isSelected:n,coordSys:r}=t,[s,l]=i[0],a=e.style?.color||"#d1d4dc",o=r.x,c=r.x+r.width;return{type:"group",children:[{type:"line",name:"line",shape:{x1:o,y1:l,x2:c,y2:l},style:{stroke:a,lineWidth:e.style?.lineWidth||1}},{type:"rect",shape:{x:c-70,y:l-10,width:65,height:18,r:2},style:{fill:a,opacity:.9},z2:10},{type:"text",x:c-67,y:l-8,style:{text:e.points[0].value.toFixed(2),fill:"#fff",fontSize:10,fontFamily:"monospace"},z2:11},{type:"circle",name:"point-0",shape:{cx:s,cy:l,r:4},style:{fill:"#fff",stroke:a,lineWidth:1,opacity:n?1:0}}]}}}var An=Object.defineProperty,_n=(h,t,e)=>t in h?An(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,Ce=(h,t,e)=>(_n(h,typeof t!="symbol"?t+"":t,e),e);class Sn extends K{constructor(t={}){super({id:"horizontal-line-tool",name:t?.name||"Horizontal Line",icon:t?.icon||'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="2" y1="12" x2="22" y2="12"/><circle cx="12" cy="12" r="2" fill="currentColor"/></svg>'}),Ce(this,"zr"),Ce(this,"onClick",e=>{const i=this.getPoint(e);if(!i)return;const n=this.context.coordinateConversion.pixelToData({x:i[0],y:i[1]});n&&this.context.addDrawing({id:`hline-${Date.now()}`,type:"horizontal-line",points:[n],paneIndex:n.paneIndex||0,style:{color:"#d1d4dc",lineWidth:1}}),this.context.disableTools()})}onInit(){this.zr=this.chart.getZr(),this.context.registerDrawingRenderer(new we)}onActivate(){this.chart.getZr().setCursorStyle("crosshair"),this.zr.on("click",this.onClick)}onDeactivate(){this.chart.getZr().setCursorStyle("default"),this.zr.off("click",this.onClick)}onDestroy(){}}var zn=Object.defineProperty,$n=(h,t,e)=>t in h?zn(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,Gn=(h,t,e)=>($n(h,typeof t!="symbol"?t+"":t,e),e);class Pe{constructor(){Gn(this,"type","horizontal-ray")}render(t){const{drawing:e,pixelPoints:i,isSelected:n,coordSys:r}=t,[s,l]=i[0],a=e.style?.color||"#d1d4dc",o=r.x+r.width;return{type:"group",children:[{type:"line",name:"line",shape:{x1:s,y1:l,x2:o,y2:l},style:{stroke:a,lineWidth:e.style?.lineWidth||1}},{type:"circle",name:"point-0",shape:{cx:s,cy:l,r:4},style:{fill:"#fff",stroke:a,lineWidth:1,opacity:n?1:0}}]}}}var En=Object.defineProperty,Ln=(h,t,e)=>t in h?En(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,ke=(h,t,e)=>(Ln(h,typeof t!="symbol"?t+"":t,e),e);class Tn extends K{constructor(t={}){super({id:"horizontal-ray-tool",name:t?.name||"Horizontal Ray",icon:t?.icon||'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="4" y1="12" x2="22" y2="12"/><circle cx="4" cy="12" r="2" fill="currentColor"/></svg>'}),ke(this,"zr"),ke(this,"onClick",e=>{const i=this.getPoint(e);if(!i)return;const n=this.context.coordinateConversion.pixelToData({x:i[0],y:i[1]});n&&this.context.addDrawing({id:`hray-${Date.now()}`,type:"horizontal-ray",points:[n],paneIndex:n.paneIndex||0,style:{color:"#d1d4dc",lineWidth:1}}),this.context.disableTools()})}onInit(){this.zr=this.chart.getZr(),this.context.registerDrawingRenderer(new Pe)}onActivate(){this.chart.getZr().setCursorStyle("crosshair"),this.zr.on("click",this.onClick)}onDeactivate(){this.chart.getZr().setCursorStyle("default"),this.zr.off("click",this.onClick)}onDestroy(){}}var Wn=Object.defineProperty,Nn=(h,t,e)=>t in h?Wn(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,Fn=(h,t,e)=>(Nn(h,typeof t!="symbol"?t+"":t,e),e);class De{constructor(){Fn(this,"type","vertical-line")}render(t){const{drawing:e,pixelPoints:i,isSelected:n,coordSys:r}=t,[s,l]=i[0],a=e.style?.color||"#d1d4dc",o=r.y,c=r.y+r.height;return{type:"group",children:[{type:"line",name:"line",shape:{x1:s,y1:o,x2:s,y2:c},style:{stroke:a,lineWidth:e.style?.lineWidth||1}},{type:"circle",name:"point-0",shape:{cx:s,cy:l,r:4},style:{fill:"#fff",stroke:a,lineWidth:1,opacity:n?1:0}}]}}}var Zn=Object.defineProperty,Rn=(h,t,e)=>t in h?Zn(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,Me=(h,t,e)=>(Rn(h,typeof t!="symbol"?t+"":t,e),e);class Hn extends K{constructor(t={}){super({id:"vertical-line-tool",name:t?.name||"Vertical Line",icon:t?.icon||'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="2" x2="12" y2="22"/><circle cx="12" cy="12" r="2" fill="currentColor"/></svg>'}),Me(this,"zr"),Me(this,"onClick",e=>{const i=this.getPoint(e);if(!i)return;const n=this.context.coordinateConversion.pixelToData({x:i[0],y:i[1]});n&&this.context.addDrawing({id:`vline-${Date.now()}`,type:"vertical-line",points:[n],paneIndex:n.paneIndex||0,style:{color:"#d1d4dc",lineWidth:1}}),this.context.disableTools()})}onInit(){this.zr=this.chart.getZr(),this.context.registerDrawingRenderer(new De)}onActivate(){this.chart.getZr().setCursorStyle("crosshair"),this.zr.on("click",this.onClick)}onDeactivate(){this.chart.getZr().setCursorStyle("default"),this.zr.off("click",this.onClick)}onDestroy(){}}var On=Object.defineProperty,Bn=(h,t,e)=>t in h?On(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,jn=(h,t,e)=>(Bn(h,typeof t!="symbol"?t+"":t,e),e);class Ie{constructor(){jn(this,"type","cross-line")}render(t){const{drawing:e,pixelPoints:i,isSelected:n,coordSys:r}=t,[s,l]=i[0],a=e.style?.color||"#d1d4dc",o=r.x,c=r.x+r.width,y=r.y,d=r.y+r.height;return{type:"group",children:[{type:"line",name:"line-h",shape:{x1:o,y1:l,x2:c,y2:l},style:{stroke:a,lineWidth:e.style?.lineWidth||1}},{type:"line",name:"line-v",shape:{x1:s,y1:y,x2:s,y2:d},style:{stroke:a,lineWidth:e.style?.lineWidth||1}},{type:"circle",name:"point-0",shape:{cx:s,cy:l,r:4},style:{fill:"#fff",stroke:a,lineWidth:1,opacity:n?1:0}}]}}}var Yn=Object.defineProperty,Vn=(h,t,e)=>t in h?Yn(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,Ae=(h,t,e)=>(Vn(h,typeof t!="symbol"?t+"":t,e),e);class Xn extends K{constructor(t={}){super({id:"cross-line-tool",name:t?.name||"Cross Line",icon:t?.icon||'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="2" x2="12" y2="22"/><line x1="2" y1="12" x2="22" y2="12"/></svg>'}),Ae(this,"zr"),Ae(this,"onClick",e=>{const i=this.getPoint(e);if(!i)return;const n=this.context.coordinateConversion.pixelToData({x:i[0],y:i[1]});n&&this.context.addDrawing({id:`crossline-${Date.now()}`,type:"cross-line",points:[n],paneIndex:n.paneIndex||0,style:{color:"#d1d4dc",lineWidth:1}}),this.context.disableTools()})}onInit(){this.zr=this.chart.getZr(),this.context.registerDrawingRenderer(new Ie)}onActivate(){this.chart.getZr().setCursorStyle("crosshair"),this.zr.on("click",this.onClick)}onDeactivate(){this.chart.getZr().setCursorStyle("default"),this.zr.off("click",this.onClick)}onDestroy(){}}var qn=Object.defineProperty,Un=(h,t,e)=>t in h?qn(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,Kn=(h,t,e)=>(Un(h,typeof t!="symbol"?t+"":t,e),e);const ne=[0,.236,.382,.5,.618,.786,1],Vt=["#787b86","#f44336","#ff9800","#4caf50","#2196f3","#00bcd4","#787b86"];class _e{constructor(){Kn(this,"type","fibonacci")}render(t){const{drawing:e,pixelPoints:i,isSelected:n}=t,[r,s]=i[0],[l,a]=i[1],o=e.style?.color||"#3b82f6",c=Math.min(r,l),y=Math.max(r,l),d=y-c,u=a-s,p=e.points[0].value,f=e.points[1].value,g=f-p,m=[],x=[];return ne.forEach((P,w)=>{const D=a-u*P,S=Vt[w%Vt.length];x.push({type:"line",shape:{x1:c,y1:D,x2:y,y2:D},style:{stroke:S,lineWidth:1},silent:!0});const M=f-g*P;if(x.push({type:"text",style:{text:`${P} (${M.toFixed(2)})`,x:c+5,y:D-10,fill:S,fontSize:10},silent:!0}),w<ne.length-1){const b=ne[w+1],k=a-u*b,C=Math.abs(k-D),A=Math.min(D,k);m.push({type:"rect",name:"line",shape:{x:c,y:A,width:d,height:C},style:{fill:Vt[(w+1)%Vt.length],opacity:.1}})}}),{type:"group",children:[...m,...x,{type:"line",name:"line",shape:{x1:r,y1:s,x2:l,y2:a},style:{stroke:"#999",lineWidth:1,lineDash:[4,4]}},{type:"circle",name:"point-0",shape:{cx:r,cy:s,r:4},style:{fill:"#fff",stroke:o,lineWidth:1,opacity:n?1:0},z:100},{type:"circle",name:"point-1",shape:{cx:l,cy:a,r:4},style:{fill:"#fff",stroke:o,lineWidth:1,opacity:n?1:0},z:100}]}}}var Jn=Object.defineProperty,Qn=(h,t,e)=>t in h?Jn(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,wt=(h,t,e)=>(Qn(h,typeof t!="symbol"?t+"":t,e),e);class ts extends K{constructor(t={}){super({id:"fibonacci-tool",name:t.name||"Fibonacci Retracement",icon:t.icon||'<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="M120-80v-80h720v80H120Zm0-240v-80h720v80H120Zm0-240v-80h720v80H120Zm0-240v-80h720v80H120Z"/></svg>'}),wt(this,"startPoint",null),wt(this,"endPoint",null),wt(this,"state","idle"),wt(this,"graphicGroup",null),wt(this,"levels",[0,.236,.382,.5,.618,.786,1]),wt(this,"colors",["#787b86","#f44336","#ff9800","#4caf50","#2196f3","#00bcd4","#787b86"]),wt(this,"onClick",e=>{this.state==="idle"?(this.state="drawing",this.startPoint=this.getPoint(e),this.endPoint=this.getPoint(e),this.initGraphic(),this.updateGraphic()):this.state==="drawing"&&(this.state="finished",this.endPoint=this.getPoint(e),this.updateGraphic(),this.saveDrawing(),this.removeGraphic(),this.context.disableTools())}),wt(this,"onMouseMove",e=>{this.state==="drawing"&&(this.endPoint=this.getPoint(e),this.updateGraphic())})}onInit(){this.context.registerDrawingRenderer(new _e)}onActivate(){this.state="idle",this.startPoint=null,this.endPoint=null,this.context.getChart().getZr().setCursorStyle("crosshair"),this.bindEvents()}onDeactivate(){this.state="idle",this.startPoint=null,this.endPoint=null,this.removeGraphic(),this.unbindEvents(),this.context.getChart().getZr().setCursorStyle("default")}bindEvents(){const t=this.context.getChart().getZr();t.on("click",this.onClick),t.on("mousemove",this.onMouseMove)}unbindEvents(){const t=this.context.getChart().getZr();t.off("click",this.onClick),t.off("mousemove",this.onMouseMove)}initGraphic(){this.graphicGroup=new _.graphic.Group,this.context.getChart().getZr().add(this.graphicGroup)}removeGraphic(){this.graphicGroup&&(this.context.getChart().getZr().remove(this.graphicGroup),this.graphicGroup=null)}updateGraphic(){if(!this.graphicGroup||!this.startPoint||!this.endPoint)return;this.graphicGroup.removeAll();const t=this.startPoint[0],e=this.startPoint[1],i=this.endPoint[0],n=this.endPoint[1],r=new _.graphic.Line({shape:{x1:t,y1:e,x2:i,y2:n},style:{stroke:"#999",lineWidth:1,lineDash:[4,4]},silent:!0});this.graphicGroup.add(r);const s=Math.min(t,i),l=Math.max(t,i),a=l-s,o=n-e;this.levels.forEach((c,y)=>{const d=n-o*c,u=this.colors[y%this.colors.length],p=new _.graphic.Line({shape:{x1:s,y1:d,x2:l,y2:d},style:{stroke:u,lineWidth:1},silent:!0});if(this.graphicGroup.add(p),y<this.levels.length-1){const f=this.levels[y+1],g=n-o*f,m=Math.abs(g-d),x=Math.min(d,g),P=new _.graphic.Rect({shape:{x:s,y:x,width:a,height:m},style:{fill:this.colors[(y+1)%this.colors.length],opacity:.1},silent:!0});this.graphicGroup.add(P)}})}saveDrawing(){if(!this.startPoint||!this.endPoint)return;const t=this.context.coordinateConversion.pixelToData({x:this.startPoint[0],y:this.startPoint[1]}),e=this.context.coordinateConversion.pixelToData({x:this.endPoint[0],y:this.endPoint[1]});if(t&&e){const i=t.paneIndex||0;this.context.addDrawing({id:`fib-${Date.now()}`,type:"fibonacci",points:[t,e],paneIndex:i,style:{color:"#3b82f6",lineWidth:1}})}}}var es=Object.defineProperty,is=(h,t,e)=>t in h?es(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,ns=(h,t,e)=>(is(h,typeof t!="symbol"?t+"":t,e),e);const Xt=[0,.236,.382,.5,.618,.786,1],qt=["#787b86","#f44336","#ff9800","#4caf50","#2196f3","#00bcd4","#787b86"];class Se{constructor(){ns(this,"type","fibonacci_channel")}render(t){const{drawing:e,pixelPoints:i,isSelected:n}=t,[r,s]=i[0],[l,a]=i[1],[o,c]=i[2],y=e.style?.color||"#3b82f6",d=l-r,u=a-s,p=Math.sqrt(d*d+u*u);if(p===0)return;const f=-u/p,g=d/p,m=(o-r)*f+(c-s)*g,x=[],P=[];return Xt.forEach((w,D)=>{const S=f*m*w,M=g*m*w,b=r+S,k=s+M,C=l+S,A=a+M;if(P.push({lx1:b,ly1:k,lx2:C,ly2:A}),D<Xt.length-1){const G=Xt[D+1],z=f*m*G,$=g*m*G;x.push({type:"polygon",name:"line",shape:{points:[[b,k],[C,A],[l+z,a+$],[r+z,s+$]]},style:{fill:qt[(D+1)%qt.length],opacity:.1}})}}),P.forEach((w,D)=>{const S=qt[D%qt.length];x.push({type:"line",shape:{x1:w.lx1,y1:w.ly1,x2:w.lx2,y2:w.ly2},style:{stroke:S,lineWidth:1},silent:!0}),x.push({type:"text",style:{text:`${Xt[D]}`,x:w.lx2+5,y:w.ly2-5,fill:S,fontSize:10},silent:!0})}),x.push({type:"line",name:"line",shape:{x1:r,y1:s,x2:l,y2:a},style:{stroke:"#999",lineWidth:1,lineDash:[4,4]}}),x.push({type:"circle",name:"point-0",shape:{cx:r,cy:s,r:4},style:{fill:"#fff",stroke:y,lineWidth:1,opacity:n?1:0},z:100}),x.push({type:"circle",name:"point-1",shape:{cx:l,cy:a,r:4},style:{fill:"#fff",stroke:y,lineWidth:1,opacity:n?1:0},z:100}),x.push({type:"circle",name:"point-2",shape:{cx:o,cy:c,r:4},style:{fill:"#fff",stroke:y,lineWidth:1,opacity:n?1:0},z:100}),{type:"group",children:x}}}var ss=Object.defineProperty,os=(h,t,e)=>t in h?ss(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,bt=(h,t,e)=>(os(h,typeof t!="symbol"?t+"":t,e),e);class rs extends K{constructor(t={}){super({id:"fibonacci-channel-tool",name:t.name||"Fibonacci Channel",icon:t.icon||'<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="M120-200v-80l80-80H120v-80h160l120-120H120v-80h360l120-120H120v-80h720v80H520l-120 120h440v80H320L200-440h640v80H280l-80 80h640v80H120Z"/></svg>'}),bt(this,"startPoint",null),bt(this,"endPoint",null),bt(this,"widthPoint",null),bt(this,"state","idle"),bt(this,"graphicGroup",null),bt(this,"levels",[0,.236,.382,.5,.618,.786,1]),bt(this,"colors",["#787b86","#f44336","#ff9800","#4caf50","#2196f3","#00bcd4","#787b86"]),bt(this,"onClick",e=>{this.state==="idle"?(this.state="drawing-baseline",this.startPoint=this.getPoint(e),this.endPoint=this.getPoint(e),this.initGraphic(),this.updateGraphic()):this.state==="drawing-baseline"?(this.state="drawing-width",this.endPoint=this.getPoint(e),this.widthPoint=this.getPoint(e),this.updateGraphic()):this.state==="drawing-width"&&(this.state="finished",this.widthPoint=this.getPoint(e),this.updateGraphic(),this.saveDrawing(),this.removeGraphic(),this.context.disableTools())}),bt(this,"onMouseMove",e=>{this.state==="drawing-baseline"?(this.endPoint=this.getPoint(e),this.updateGraphic()):this.state==="drawing-width"&&(this.widthPoint=this.getPoint(e),this.updateGraphic())})}onInit(){this.context.registerDrawingRenderer(new Se)}onActivate(){this.state="idle",this.startPoint=null,this.endPoint=null,this.widthPoint=null,this.context.getChart().getZr().setCursorStyle("crosshair"),this.bindEvents()}onDeactivate(){this.state="idle",this.startPoint=null,this.endPoint=null,this.widthPoint=null,this.removeGraphic(),this.unbindEvents(),this.context.getChart().getZr().setCursorStyle("default")}bindEvents(){const t=this.context.getChart().getZr();t.on("click",this.onClick),t.on("mousemove",this.onMouseMove)}unbindEvents(){const t=this.context.getChart().getZr();t.off("click",this.onClick),t.off("mousemove",this.onMouseMove)}initGraphic(){this.graphicGroup=new _.graphic.Group,this.context.getChart().getZr().add(this.graphicGroup)}removeGraphic(){this.graphicGroup&&(this.context.getChart().getZr().remove(this.graphicGroup),this.graphicGroup=null)}updateGraphic(){if(!this.graphicGroup||!this.startPoint||!this.endPoint)return;this.graphicGroup.removeAll();const t=this.startPoint[0],e=this.startPoint[1],i=this.endPoint[0],n=this.endPoint[1];if(this.graphicGroup.add(new _.graphic.Line({shape:{x1:t,y1:e,x2:i,y2:n},style:{stroke:"#787b86",lineWidth:2},silent:!0})),this.widthPoint&&this.state!=="drawing-baseline"){const r=this.widthPoint,s=i-t,l=n-e,a=Math.sqrt(s*s+l*l);if(a===0)return;const o=-l/a,c=s/a,y=(r[0]-t)*o+(r[1]-e)*c;this.levels.forEach((d,u)=>{const p=o*y*d,f=c*y*d,g=t+p,m=e+f,x=i+p,P=n+f,w=this.colors[u%this.colors.length];if(this.graphicGroup.add(new _.graphic.Line({shape:{x1:g,y1:m,x2:x,y2:P},style:{stroke:w,lineWidth:1},silent:!0})),u<this.levels.length-1){const D=this.levels[u+1],S=o*y*D,M=c*y*D,b=t+S,k=e+M,C=i+S,A=n+M;this.graphicGroup.add(new _.graphic.Polygon({shape:{points:[[g,m],[x,P],[C,A],[b,k]]},style:{fill:this.colors[(u+1)%this.colors.length],opacity:.1},silent:!0}))}})}}saveDrawing(){if(!this.startPoint||!this.endPoint||!this.widthPoint)return;const t=this.context.coordinateConversion.pixelToData({x:this.startPoint[0],y:this.startPoint[1]}),e=this.context.coordinateConversion.pixelToData({x:this.endPoint[0],y:this.endPoint[1]}),i=this.context.coordinateConversion.pixelToData({x:this.widthPoint[0],y:this.widthPoint[1]});if(t&&e&&i){const n=t.paneIndex||0;this.context.addDrawing({id:`fib-channel-${Date.now()}`,type:"fibonacci_channel",points:[t,e,i],paneIndex:n,style:{color:"#3b82f6",lineWidth:1}})}}}var as=Object.defineProperty,ls=(h,t,e)=>t in h?as(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,hs=(h,t,e)=>(ls(h,typeof t!="symbol"?t+"":t,e),e);const se=[0,.236,.382,.5,.618,.786,1],Ct=["#787b86","#f44336","#ff9800","#4caf50","#2196f3","#00bcd4","#787b86"];class ze{constructor(){hs(this,"type","fib_speed_resistance_fan")}render(t){const{drawing:e,pixelPoints:i,isSelected:n}=t,[r,s]=i[0],[l,a]=i[1],o=e.style?.color||"#3b82f6",c=l-r,y=a-s,d=[],u=[],p=[];for(const f of se)u.push([r+c,s+y*f]),p.push([r+c*f,s+y]);for(let f=0;f<u.length-1;f++)d.push({type:"polygon",name:"line",shape:{points:[[r,s],u[f],u[f+1]]},style:{fill:Ct[(f+1)%Ct.length],opacity:.06}});for(let f=0;f<p.length-1;f++)d.push({type:"polygon",name:"line",shape:{points:[[r,s],p[f],p[f+1]]},style:{fill:Ct[(f+1)%Ct.length],opacity:.06}});return se.forEach((f,g)=>{const[m,x]=u[g],P=Ct[g%Ct.length];d.push({type:"line",shape:{x1:r,y1:s,x2:m,y2:x},style:{stroke:P,lineWidth:1},silent:!0}),d.push({type:"text",style:{text:`${f}`,x:m+3,y:x-2,fill:P,fontSize:9},silent:!0})}),se.forEach((f,g)=>{const[m,x]=p[g],P=Ct[g%Ct.length];d.push({type:"line",shape:{x1:r,y1:s,x2:m,y2:x},style:{stroke:P,lineWidth:1},silent:!0}),d.push({type:"text",style:{text:`${f}`,x:m-2,y:x+8,fill:P,fontSize:9},silent:!0})}),d.push({type:"line",name:"line",shape:{x1:l,y1:s,x2:l,y2:a},style:{stroke:"#555",lineWidth:1,lineDash:[3,3]}}),d.push({type:"line",name:"line",shape:{x1:r,y1:a,x2:l,y2:a},style:{stroke:"#555",lineWidth:1,lineDash:[3,3]}}),d.push({type:"line",name:"line",shape:{x1:r,y1:s,x2:l,y2:a},style:{stroke:"#999",lineWidth:1,lineDash:[4,4]}}),d.push({type:"circle",name:"point-0",shape:{cx:r,cy:s,r:4},style:{fill:"#fff",stroke:o,lineWidth:1,opacity:n?1:0},z:100}),d.push({type:"circle",name:"point-1",shape:{cx:l,cy:a,r:4},style:{fill:"#fff",stroke:o,lineWidth:1,opacity:n?1:0},z:100}),{type:"group",children:d}}}var cs=Object.defineProperty,ds=(h,t,e)=>t in h?cs(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,$t=(h,t,e)=>(ds(h,typeof t!="symbol"?t+"":t,e),e);const Dt=[0,.236,.382,.5,.618,.786,1],Gt=["#787b86","#f44336","#ff9800","#4caf50","#2196f3","#00bcd4","#787b86"];class ps extends K{constructor(t={}){super({id:"fib-speed-resistance-fan-tool",name:t.name||"Fib Speed Resistance Fan",icon:t.icon||'<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#e3e3e3"><path d="M2 21L22 3M2 21l20-6M2 21l20-9M2 21l20-12M2 21l20-15M2 21l6-18M2 21l9-18M2 21l12-18M2 21l15-18" stroke="#e3e3e3" stroke-width="1" fill="none"/></svg>'}),$t(this,"startPoint",null),$t(this,"endPoint",null),$t(this,"state","idle"),$t(this,"graphicGroup",null),$t(this,"onClick",e=>{this.state==="idle"?(this.state="drawing",this.startPoint=this.getPoint(e),this.endPoint=this.getPoint(e),this.initGraphic(),this.updateGraphic()):this.state==="drawing"&&(this.state="finished",this.endPoint=this.getPoint(e),this.updateGraphic(),this.saveDrawing(),this.removeGraphic(),this.context.disableTools())}),$t(this,"onMouseMove",e=>{this.state==="drawing"&&(this.endPoint=this.getPoint(e),this.updateGraphic())})}onInit(){this.context.registerDrawingRenderer(new ze)}onActivate(){this.state="idle",this.startPoint=null,this.endPoint=null,this.context.getChart().getZr().setCursorStyle("crosshair"),this.bindEvents()}onDeactivate(){this.state="idle",this.startPoint=null,this.endPoint=null,this.removeGraphic(),this.unbindEvents(),this.context.getChart().getZr().setCursorStyle("default")}bindEvents(){const t=this.context.getChart().getZr();t.on("click",this.onClick),t.on("mousemove",this.onMouseMove)}unbindEvents(){const t=this.context.getChart().getZr();t.off("click",this.onClick),t.off("mousemove",this.onMouseMove)}initGraphic(){this.graphicGroup=new _.graphic.Group,this.context.getChart().getZr().add(this.graphicGroup)}removeGraphic(){this.graphicGroup&&(this.context.getChart().getZr().remove(this.graphicGroup),this.graphicGroup=null)}updateGraphic(){if(!this.graphicGroup||!this.startPoint||!this.endPoint)return;this.graphicGroup.removeAll();const t=this.startPoint[0],e=this.startPoint[1],i=this.endPoint[0],n=this.endPoint[1],r=i-t,s=n-e;Dt.forEach((l,a)=>{const o=Gt[a%Gt.length];this.graphicGroup.add(new _.graphic.Line({shape:{x1:t,y1:e,x2:t+r,y2:e+s*l},style:{stroke:o,lineWidth:1},silent:!0})),this.graphicGroup.add(new _.graphic.Line({shape:{x1:t,y1:e,x2:t+r*l,y2:e+s},style:{stroke:o,lineWidth:1},silent:!0}))});for(let l=0;l<Dt.length-1;l++){const a=[t+r,e+s*Dt[l]],o=[t+r,e+s*Dt[l+1]];this.graphicGroup.add(new _.graphic.Polygon({shape:{points:[[t,e],a,o]},style:{fill:Gt[(l+1)%Gt.length],opacity:.06},silent:!0}))}for(let l=0;l<Dt.length-1;l++){const a=[t+r*Dt[l],e+s],o=[t+r*Dt[l+1],e+s];this.graphicGroup.add(new _.graphic.Polygon({shape:{points:[[t,e],a,o]},style:{fill:Gt[(l+1)%Gt.length],opacity:.06},silent:!0}))}this.graphicGroup.add(new _.graphic.Line({shape:{x1:i,y1:e,x2:i,y2:n},style:{stroke:"#555",lineWidth:1,lineDash:[3,3]},silent:!0})),this.graphicGroup.add(new _.graphic.Line({shape:{x1:t,y1:n,x2:i,y2:n},style:{stroke:"#555",lineWidth:1,lineDash:[3,3]},silent:!0})),this.graphicGroup.add(new _.graphic.Line({shape:{x1:t,y1:e,x2:i,y2:n},style:{stroke:"#999",lineWidth:1,lineDash:[4,4]},silent:!0}))}saveDrawing(){if(!this.startPoint||!this.endPoint)return;const t=this.context.coordinateConversion.pixelToData({x:this.startPoint[0],y:this.startPoint[1]}),e=this.context.coordinateConversion.pixelToData({x:this.endPoint[0],y:this.endPoint[1]});t&&e&&this.context.addDrawing({id:`fib-fan-${Date.now()}`,type:"fib_speed_resistance_fan",points:[t,e],paneIndex:t.paneIndex||0,style:{color:"#3b82f6",lineWidth:1}})}}var us=Object.defineProperty,gs=(h,t,e)=>t in h?us(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,ys=(h,t,e)=>(gs(h,typeof t!="symbol"?t+"":t,e),e);const $e=[0,.236,.382,.5,.618,.786,1,1.272,1.618,2,2.618],Ge=["#787b86","#f44336","#ff9800","#4caf50","#2196f3","#00bcd4","#787b86","#e91e63","#9c27b0","#673ab7","#3f51b5"];class Ee{constructor(){ys(this,"type","fib_trend_extension")}render(t){const{drawing:e,pixelPoints:i,isSelected:n,api:r}=t,s=e.style?.color||"#3b82f6";if(i.length<3)return;const[l,a]=i[0],[o,c]=i[1],[y,d]=i[2],u=e.points,p=u[1].value-u[0].value,f=Math.min(l,o,y),g=Math.max(l,o,y),m=(g-f)*.5,x=f,P=g+m,w=[],D=[];for(let b=0;b<$e.length;b++){const k=$e[b],C=u[2].value+p*k;r.coord([u[2].timeIndex+t.drawing.points[2].timeIndex-u[2].timeIndex,C]);const A=d+(c-a)*k;D.push({level:k,y:A,price:C,color:Ge[b%Ge.length]})}for(let b=0;b<D.length-1;b++){const k=D[b],C=D[b+1],A=Math.min(k.y,C.y),G=Math.abs(C.y-k.y);w.push({type:"rect",name:"line",shape:{x,y:A,width:P-x,height:G},style:{fill:C.color,opacity:.06}})}for(const b of D)w.push({type:"line",shape:{x1:x,y1:b.y,x2:P,y2:b.y},style:{stroke:b.color,lineWidth:1},silent:!0}),w.push({type:"text",style:{text:`${b.level} (${b.price.toFixed(2)})`,x:P+4,y:b.y-6,fill:b.color,fontSize:9},silent:!0});w.push({type:"line",name:"line",shape:{x1:l,y1:a,x2:o,y2:c},style:{stroke:"#2196f3",lineWidth:1.5,lineDash:[5,4]}}),w.push({type:"line",name:"line",shape:{x1:o,y1:c,x2:y,y2:d},style:{stroke:"#ff9800",lineWidth:1.5,lineDash:[5,4]}}),w.push({type:"circle",name:"point-0",shape:{cx:l,cy:a,r:4},style:{fill:"#fff",stroke:s,lineWidth:1,opacity:n?1:0},z:100}),w.push({type:"circle",name:"point-1",shape:{cx:o,cy:c,r:4},style:{fill:"#fff",stroke:s,lineWidth:1,opacity:n?1:0},z:100}),w.push({type:"circle",name:"point-2",shape:{cx:y,cy:d,r:4},style:{fill:"#fff",stroke:s,lineWidth:1,opacity:n?1:0},z:100});const S=["1","2","3"],M=[i[0],i[1],i[2]];for(let b=0;b<3;b++){const[k,C]=M[b],A=(b===0||C<=M[b-1][1])&&(b===2||C<=M[b+1]?.[1]);w.push({type:"text",style:{text:S[b],x:k,y:A?C-14:C+16,fill:"#e2e8f0",fontSize:12,fontWeight:"bold",align:"center",verticalAlign:"middle"},silent:!0})}return{type:"group",children:w}}}var fs=Object.defineProperty,xs=(h,t,e)=>t in h?fs(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,Wt=(h,t,e)=>(xs(h,typeof t!="symbol"?t+"":t,e),e);const Ut=[0,.236,.382,.5,.618,.786,1,1.272,1.618,2,2.618],Kt=["#787b86","#f44336","#ff9800","#4caf50","#2196f3","#00bcd4","#787b86","#e91e63","#9c27b0","#673ab7","#3f51b5"];class ms extends K{constructor(t={}){super({id:"fib-trend-extension-tool",name:t.name||"Fib Trend Extension",icon:t.icon||'<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="M120-80v-80h720v80H120Zm0-160v-80h720v80H120Zm0-160v-80h720v80H120Zm0-160v-80h720v80H120Zm0-160v-80h720v80H120Zm0-160v-80h720v80H120Z"/></svg>'}),Wt(this,"points",[]),Wt(this,"state","idle"),Wt(this,"graphicGroup",null),Wt(this,"onClick",e=>{const i=this.getPoint(e);this.state==="idle"?(this.state="drawing-trend",this.points=[i,[...i]],this.initGraphic(),this.updateGraphic()):this.state==="drawing-trend"?(this.state="drawing-retracement",this.points[1]=i,this.points.push([...i]),this.updateGraphic()):this.state==="drawing-retracement"&&(this.state="finished",this.points[2]=i,this.updateGraphic(),this.saveDrawing(),this.removeGraphic(),this.context.disableTools())}),Wt(this,"onMouseMove",e=>{this.state==="drawing-trend"?(this.points[1]=this.getPoint(e),this.updateGraphic()):this.state==="drawing-retracement"&&(this.points[2]=this.getPoint(e),this.updateGraphic())})}onInit(){this.context.registerDrawingRenderer(new Ee)}onActivate(){this.state="idle",this.points=[],this.context.getChart().getZr().setCursorStyle("crosshair"),this.bindEvents()}onDeactivate(){this.state="idle",this.points=[],this.removeGraphic(),this.unbindEvents(),this.context.getChart().getZr().setCursorStyle("default")}bindEvents(){const t=this.context.getChart().getZr();t.on("click",this.onClick),t.on("mousemove",this.onMouseMove)}unbindEvents(){const t=this.context.getChart().getZr();t.off("click",this.onClick),t.off("mousemove",this.onMouseMove)}initGraphic(){this.graphicGroup=new _.graphic.Group,this.context.getChart().getZr().add(this.graphicGroup)}removeGraphic(){this.graphicGroup&&(this.context.getChart().getZr().remove(this.graphicGroup),this.graphicGroup=null)}updateGraphic(){if(!this.graphicGroup)return;this.graphicGroup.removeAll();const[t,e]=this.points[0],[i,n]=this.points[1];if(this.graphicGroup.add(new _.graphic.Line({shape:{x1:t,y1:e,x2:i,y2:n},style:{stroke:"#2196f3",lineWidth:1.5,lineDash:[5,4]},silent:!0})),this.points.length>=3){const[r,s]=this.points[2];this.graphicGroup.add(new _.graphic.Line({shape:{x1:i,y1:n,x2:r,y2:s},style:{stroke:"#ff9800",lineWidth:1.5,lineDash:[5,4]},silent:!0}));const l=n-e,a=Math.min(t,i,r),o=Math.max(t,i,r),c=(o-a)*.5,y=a,d=o+c;for(let u=0;u<Ut.length;u++){const p=Ut[u],f=s+l*p,g=Kt[u%Kt.length];if(this.graphicGroup.add(new _.graphic.Line({shape:{x1:y,y1:f,x2:d,y2:f},style:{stroke:g,lineWidth:1},silent:!0})),this.graphicGroup.add(new _.graphic.Text({style:{text:`${p}`,x:d+4,y:f-6,fill:g,fontSize:9},silent:!0})),u<Ut.length-1){const m=s+l*Ut[u+1],x=Math.min(f,m),P=Math.abs(m-f);this.graphicGroup.add(new _.graphic.Rect({shape:{x:y,y:x,width:d-y,height:P},style:{fill:Kt[(u+1)%Kt.length],opacity:.06},silent:!0}))}}}for(const r of this.points)this.graphicGroup.add(new _.graphic.Circle({shape:{cx:r[0],cy:r[1],r:4},style:{fill:"#fff",stroke:"#3b82f6",lineWidth:1.5},z:101,silent:!0}))}saveDrawing(){const t=this.points.map(e=>this.context.coordinateConversion.pixelToData({x:e[0],y:e[1]}));t.every(e=>e!==null)&&this.context.addDrawing({id:`fib-ext-${Date.now()}`,type:"fib_trend_extension",points:t,paneIndex:t[0].paneIndex||0,style:{color:"#3b82f6",lineWidth:1}})}}var bs=Object.defineProperty,vs=(h,t,e)=>t in h?bs(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,ws=(h,t,e)=>(vs(h,typeof t!="symbol"?t+"":t,e),e);const Le=["X","A","B","C","D"],Te=["#2196f3","#ff9800","#4caf50","#f44336"],Cs="rgba(33, 150, 243, 0.08)",Ps="rgba(244, 67, 54, 0.08)";class We{constructor(){ws(this,"type","xabcd_pattern")}render(t){const{drawing:e,pixelPoints:i,isSelected:n}=t,r=e.style?.color||"#3b82f6";if(i.length<2)return;const s=[];i.length>=3&&s.push({type:"polygon",name:"line",shape:{points:i.slice(0,3).map(([a,o])=>[a,o])},style:{fill:Cs,opacity:1}}),i.length>=5&&s.push({type:"polygon",name:"line",shape:{points:i.slice(2,5).map(([a,o])=>[a,o])},style:{fill:Ps,opacity:1}});for(let a=0;a<i.length-1;a++){const[o,c]=i[a],[y,d]=i[a+1],u=Te[a%Te.length];s.push({type:"line",name:"line",shape:{x1:o,y1:c,x2:y,y2:d},style:{stroke:u,lineWidth:e.style?.lineWidth||2}})}const l=[[0,2],[1,3],[2,4]];for(const[a,o]of l)if(a<i.length&&o<i.length){const[c,y]=i[a],[d,u]=i[o];s.push({type:"line",shape:{x1:c,y1:y,x2:d,y2:u},style:{stroke:"#555",lineWidth:1,lineDash:[4,4]},silent:!0})}if(e.points.length>=3){const a=Math.abs(e.points[1].value-e.points[0].value),o=Math.abs(e.points[2].value-e.points[1].value);if(a!==0){const c=(o/a).toFixed(3),y=(i[1][0]+i[2][0])/2,d=(i[1][1]+i[2][1])/2;s.push({type:"text",style:{text:c,x:y+8,y:d,fill:"#ff9800",fontSize:10},silent:!0})}}if(e.points.length>=4){const a=Math.abs(e.points[2].value-e.points[1].value),o=Math.abs(e.points[3].value-e.points[2].value);if(a!==0){const c=(o/a).toFixed(3),y=(i[2][0]+i[3][0])/2,d=(i[2][1]+i[3][1])/2;s.push({type:"text",style:{text:c,x:y+8,y:d,fill:"#4caf50",fontSize:10},silent:!0})}}if(e.points.length>=5){const a=Math.abs(e.points[3].value-e.points[2].value),o=Math.abs(e.points[4].value-e.points[3].value);if(a!==0){const d=(o/a).toFixed(3),u=(i[3][0]+i[4][0])/2,p=(i[3][1]+i[4][1])/2;s.push({type:"text",style:{text:d,x:u+8,y:p,fill:"#f44336",fontSize:10},silent:!0})}const c=Math.abs(e.points[1].value-e.points[0].value),y=Math.abs(e.points[4].value-e.points[1].value);if(c!==0){const d=(y/c).toFixed(3),[u,p]=i[4];s.push({type:"text",style:{text:`AD/XA: ${d}`,x:u+10,y:p+14,fill:"#aaa",fontSize:9},silent:!0})}}for(let a=0;a<i.length&&a<Le.length;a++){const[o,c]=i[a],y=(a===0||c<=i[a-1][1])&&(a===i.length-1||c<=i[a+1]?.[1])?c-14:c+16;s.push({type:"text",style:{text:Le[a],x:o,y,fill:"#e2e8f0",fontSize:12,fontWeight:"bold",align:"center",verticalAlign:"middle"},silent:!0})}for(let a=0;a<i.length;a++){const[o,c]=i[a];s.push({type:"circle",name:`point-${a}`,shape:{cx:o,cy:c,r:4},style:{fill:"#fff",stroke:r,lineWidth:1,opacity:n?1:0},z:100})}return{type:"group",children:s}}}var ks=Object.defineProperty,Ds=(h,t,e)=>t in h?ks(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,Nt=(h,t,e)=>(Ds(h,typeof t!="symbol"?t+"":t,e),e);const Ne=["X","A","B","C","D"],Fe=["#2196f3","#ff9800","#4caf50","#f44336"],Ms=5;class Is extends K{constructor(t={}){super({id:"xabcd-pattern-tool",name:t.name||"XABCD Pattern",icon:t.icon||'<svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="#e3e3e3" stroke-width="1.5"><polyline points="2,18 6,6 11,14 16,4 21,16"/><circle cx="2" cy="18" r="1.5" fill="#e3e3e3"/><circle cx="6" cy="6" r="1.5" fill="#e3e3e3"/><circle cx="11" cy="14" r="1.5" fill="#e3e3e3"/><circle cx="16" cy="4" r="1.5" fill="#e3e3e3"/><circle cx="21" cy="16" r="1.5" fill="#e3e3e3"/></svg>'}),Nt(this,"points",[]),Nt(this,"state","idle"),Nt(this,"graphicGroup",null),Nt(this,"onClick",e=>{const i=this.getPoint(e);this.state==="idle"?(this.state="drawing",this.points=[i,[...i]],this.initGraphic(),this.updateGraphic()):this.state==="drawing"&&(this.points[this.points.length-1]=i,this.points.length>=Ms?(this.state="finished",this.updateGraphic(),this.saveDrawing(),this.removeGraphic(),this.context.disableTools()):(this.points.push([...i]),this.updateGraphic()))}),Nt(this,"onMouseMove",e=>{this.state!=="drawing"||this.points.length<2||(this.points[this.points.length-1]=this.getPoint(e),this.updateGraphic())})}onInit(){this.context.registerDrawingRenderer(new We)}onActivate(){this.state="idle",this.points=[],this.context.getChart().getZr().setCursorStyle("crosshair"),this.bindEvents()}onDeactivate(){this.state="idle",this.points=[],this.removeGraphic(),this.unbindEvents(),this.context.getChart().getZr().setCursorStyle("default")}bindEvents(){const t=this.context.getChart().getZr();t.on("click",this.onClick),t.on("mousemove",this.onMouseMove)}unbindEvents(){const t=this.context.getChart().getZr();t.off("click",this.onClick),t.off("mousemove",this.onMouseMove)}initGraphic(){this.graphicGroup=new _.graphic.Group,this.context.getChart().getZr().add(this.graphicGroup)}removeGraphic(){this.graphicGroup&&(this.context.getChart().getZr().remove(this.graphicGroup),this.graphicGroup=null)}updateGraphic(){if(!this.graphicGroup)return;this.graphicGroup.removeAll();const t=this.points;t.length>=3&&this.graphicGroup.add(new _.graphic.Polygon({shape:{points:t.slice(0,3)},style:{fill:"rgba(33, 150, 243, 0.08)"},silent:!0})),t.length>=5&&this.graphicGroup.add(new _.graphic.Polygon({shape:{points:t.slice(2,5)},style:{fill:"rgba(244, 67, 54, 0.08)"},silent:!0}));for(let i=0;i<t.length-1;i++){const[n,r]=t[i],[s,l]=t[i+1];this.graphicGroup.add(new _.graphic.Line({shape:{x1:n,y1:r,x2:s,y2:l},style:{stroke:Fe[i%Fe.length],lineWidth:2},silent:!0}))}const e=[[0,2],[1,3],[2,4]];for(const[i,n]of e)if(i<t.length&&n<t.length){const[r,s]=t[i],[l,a]=t[n];this.graphicGroup.add(new _.graphic.Line({shape:{x1:r,y1:s,x2:l,y2:a},style:{stroke:"#555",lineWidth:1,lineDash:[4,4]},silent:!0}))}for(let i=0;i<t.length&&i<Ne.length;i++){const[n,r]=t[i],s=(i===0||r<=t[i-1][1])&&(i===t.length-1||r<=t[i+1]?.[1])?r-14:r+16;this.graphicGroup.add(new _.graphic.Text({style:{text:Ne[i],x:n,y:s,fill:"#e2e8f0",fontSize:12,fontWeight:"bold",align:"center",verticalAlign:"middle"},silent:!0}))}for(let i=0;i<t.length;i++){const[n,r]=t[i];this.graphicGroup.add(new _.graphic.Circle({shape:{cx:n,cy:r,r:4},style:{fill:"#fff",stroke:"#3b82f6",lineWidth:1.5},z:101,silent:!0}))}}saveDrawing(){const t=this.points.map(e=>this.context.coordinateConversion.pixelToData({x:e[0],y:e[1]}));t.every(e=>e!==null)&&this.context.addDrawing({id:`xabcd-${Date.now()}`,type:"xabcd_pattern",points:t,paneIndex:t[0].paneIndex||0,style:{color:"#3b82f6",lineWidth:2}})}}var As=Object.defineProperty,_s=(h,t,e)=>t in h?As(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,Ss=(h,t,e)=>(_s(h,typeof t!="symbol"?t+"":t,e),e);const Ze=["A","B","C","D"],Re=["#2196f3","#ff9800","#4caf50"];class He{constructor(){Ss(this,"type","abcd_pattern")}render(t){const{drawing:e,pixelPoints:i,isSelected:n}=t,r=e.style?.color||"#3b82f6";if(i.length<2)return;const s=[];i.length>=3&&s.push({type:"polygon",name:"line",shape:{points:i.slice(0,3).map(([l,a])=>[l,a])},style:{fill:"rgba(33, 150, 243, 0.08)"}}),i.length>=4&&s.push({type:"polygon",name:"line",shape:{points:i.slice(1,4).map(([l,a])=>[l,a])},style:{fill:"rgba(244, 67, 54, 0.08)"}});for(let l=0;l<i.length-1;l++){const[a,o]=i[l],[c,y]=i[l+1];s.push({type:"line",name:"line",shape:{x1:a,y1:o,x2:c,y2:y},style:{stroke:Re[l%Re.length],lineWidth:e.style?.lineWidth||2}})}if(i.length>=3&&s.push({type:"line",shape:{x1:i[0][0],y1:i[0][1],x2:i[2][0],y2:i[2][1]},style:{stroke:"#555",lineWidth:1,lineDash:[4,4]},silent:!0}),i.length>=4&&s.push({type:"line",shape:{x1:i[1][0],y1:i[1][1],x2:i[3][0],y2:i[3][1]},style:{stroke:"#555",lineWidth:1,lineDash:[4,4]},silent:!0}),e.points.length>=3){const l=Math.abs(e.points[1].value-e.points[0].value),a=Math.abs(e.points[2].value-e.points[1].value);if(l!==0){const o=(a/l).toFixed(3),c=(i[1][0]+i[2][0])/2,y=(i[1][1]+i[2][1])/2;s.push({type:"text",style:{text:o,x:c+8,y,fill:"#ff9800",fontSize:10},silent:!0})}}if(e.points.length>=4){const l=Math.abs(e.points[2].value-e.points[1].value),a=Math.abs(e.points[3].value-e.points[2].value);if(l!==0){const o=(a/l).toFixed(3),c=(i[2][0]+i[3][0])/2,y=(i[2][1]+i[3][1])/2;s.push({type:"text",style:{text:o,x:c+8,y,fill:"#4caf50",fontSize:10},silent:!0})}}for(let l=0;l<i.length&&l<Ze.length;l++){const[a,o]=i[l],c=(l===0||o<=i[l-1][1])&&(l===i.length-1||o<=i[l+1]?.[1]);s.push({type:"text",style:{text:Ze[l],x:a,y:c?o-14:o+16,fill:"#e2e8f0",fontSize:12,fontWeight:"bold",align:"center",verticalAlign:"middle"},silent:!0})}for(let l=0;l<i.length;l++)s.push({type:"circle",name:`point-${l}`,shape:{cx:i[l][0],cy:i[l][1],r:4},style:{fill:"#fff",stroke:r,lineWidth:1,opacity:n?1:0},z:100});return{type:"group",children:s}}}var zs=Object.defineProperty,$s=(h,t,e)=>t in h?zs(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,Ft=(h,t,e)=>($s(h,typeof t!="symbol"?t+"":t,e),e);const Oe=["A","B","C","D"],Be=["#2196f3","#ff9800","#4caf50"],Gs=4;class Es extends K{constructor(t={}){super({id:"abcd-pattern-tool",name:t.name||"ABCD Pattern",icon:t.icon||'<svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="#e3e3e3" stroke-width="1.5"><polyline points="3,18 8,5 15,15 21,3"/><circle cx="3" cy="18" r="1.5" fill="#e3e3e3"/><circle cx="8" cy="5" r="1.5" fill="#e3e3e3"/><circle cx="15" cy="15" r="1.5" fill="#e3e3e3"/><circle cx="21" cy="3" r="1.5" fill="#e3e3e3"/></svg>'}),Ft(this,"points",[]),Ft(this,"state","idle"),Ft(this,"graphicGroup",null),Ft(this,"onClick",e=>{const i=this.getPoint(e);this.state==="idle"?(this.state="drawing",this.points=[i,[...i]],this.initGraphic(),this.updateGraphic()):this.state==="drawing"&&(this.points[this.points.length-1]=i,this.points.length>=Gs?(this.state="finished",this.updateGraphic(),this.saveDrawing(),this.removeGraphic(),this.context.disableTools()):(this.points.push([...i]),this.updateGraphic()))}),Ft(this,"onMouseMove",e=>{this.state!=="drawing"||this.points.length<2||(this.points[this.points.length-1]=this.getPoint(e),this.updateGraphic())})}onInit(){this.context.registerDrawingRenderer(new He)}onActivate(){this.state="idle",this.points=[],this.context.getChart().getZr().setCursorStyle("crosshair");const t=this.context.getChart().getZr();t.on("click",this.onClick),t.on("mousemove",this.onMouseMove)}onDeactivate(){this.state="idle",this.points=[],this.removeGraphic();const t=this.context.getChart().getZr();t.off("click",this.onClick),t.off("mousemove",this.onMouseMove),this.context.getChart().getZr().setCursorStyle("default")}initGraphic(){this.graphicGroup=new _.graphic.Group,this.context.getChart().getZr().add(this.graphicGroup)}removeGraphic(){this.graphicGroup&&(this.context.getChart().getZr().remove(this.graphicGroup),this.graphicGroup=null)}updateGraphic(){if(!this.graphicGroup)return;this.graphicGroup.removeAll();const t=this.points;t.length>=3&&this.graphicGroup.add(new _.graphic.Polygon({shape:{points:t.slice(0,3)},style:{fill:"rgba(33,150,243,0.08)"},silent:!0})),t.length>=4&&this.graphicGroup.add(new _.graphic.Polygon({shape:{points:t.slice(1,4)},style:{fill:"rgba(244,67,54,0.08)"},silent:!0}));for(let e=0;e<t.length-1;e++)this.graphicGroup.add(new _.graphic.Line({shape:{x1:t[e][0],y1:t[e][1],x2:t[e+1][0],y2:t[e+1][1]},style:{stroke:Be[e%Be.length],lineWidth:2},silent:!0}));t.length>=3&&this.graphicGroup.add(new _.graphic.Line({shape:{x1:t[0][0],y1:t[0][1],x2:t[2][0],y2:t[2][1]},style:{stroke:"#555",lineWidth:1,lineDash:[4,4]},silent:!0})),t.length>=4&&this.graphicGroup.add(new _.graphic.Line({shape:{x1:t[1][0],y1:t[1][1],x2:t[3][0],y2:t[3][1]},style:{stroke:"#555",lineWidth:1,lineDash:[4,4]},silent:!0}));for(let e=0;e<t.length&&e<Oe.length;e++){const[i,n]=t[e],r=(e===0||n<=t[e-1][1])&&(e===t.length-1||n<=t[e+1]?.[1]);this.graphicGroup.add(new _.graphic.Text({style:{text:Oe[e],x:i,y:r?n-14:n+16,fill:"#e2e8f0",fontSize:12,fontWeight:"bold",align:"center",verticalAlign:"middle"},silent:!0})),this.graphicGroup.add(new _.graphic.Circle({shape:{cx:i,cy:n,r:4},style:{fill:"#fff",stroke:"#3b82f6",lineWidth:1.5},z:101,silent:!0}))}}saveDrawing(){const t=this.points.map(e=>this.context.coordinateConversion.pixelToData({x:e[0],y:e[1]}));t.every(e=>e!==null)&&this.context.addDrawing({id:`abcd-${Date.now()}`,type:"abcd_pattern",points:t,paneIndex:t[0].paneIndex||0,style:{color:"#3b82f6",lineWidth:2}})}}var Ls=Object.defineProperty,Ts=(h,t,e)=>t in h?Ls(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,Ws=(h,t,e)=>(Ts(h,typeof t!="symbol"?t+"":t,e),e);const je=["X","A","B","C","D"],Ye=["#00bcd4","#e91e63","#8bc34a","#ff5722"];class Ve{constructor(){Ws(this,"type","cypher_pattern")}render(t){const{drawing:e,pixelPoints:i,isSelected:n}=t,r=e.style?.color||"#3b82f6";if(i.length<2)return;const s=[];i.length>=3&&s.push({type:"polygon",name:"line",shape:{points:i.slice(0,3).map(([o,c])=>[o,c])},style:{fill:"rgba(0, 188, 212, 0.08)"}}),i.length>=5&&s.push({type:"polygon",name:"line",shape:{points:i.slice(2,5).map(([o,c])=>[o,c])},style:{fill:"rgba(233, 30, 99, 0.08)"}});for(let o=0;o<i.length-1;o++){const[c,y]=i[o],[d,u]=i[o+1];s.push({type:"line",name:"line",shape:{x1:c,y1:y,x2:d,y2:u},style:{stroke:Ye[o%Ye.length],lineWidth:e.style?.lineWidth||2}})}const l=[[0,2],[0,3],[1,4]];for(const[o,c]of l)o<i.length&&c<i.length&&s.push({type:"line",shape:{x1:i[o][0],y1:i[o][1],x2:i[c][0],y2:i[c][1]},style:{stroke:"#555",lineWidth:1,lineDash:[4,4]},silent:!0});const a=e.points;if(a.length>=3){const o=Math.abs(a[1].value-a[0].value),c=Math.abs(a[2].value-a[1].value);if(o!==0){const y=(c/o).toFixed(3);s.push({type:"text",style:{text:y,x:(i[1][0]+i[2][0])/2+8,y:(i[1][1]+i[2][1])/2,fill:"#e91e63",fontSize:10},silent:!0})}}if(a.length>=4){const o=Math.abs(a[1].value-a[0].value),c=Math.abs(a[3].value-a[0].value);if(o!==0){const y=(c/o).toFixed(3);s.push({type:"text",style:{text:`XC/XA: ${y}`,x:(i[0][0]+i[3][0])/2+8,y:(i[0][1]+i[3][1])/2,fill:"#8bc34a",fontSize:10},silent:!0})}}if(a.length>=5){const o=Math.abs(a[3].value-a[0].value),c=Math.abs(a[4].value-a[3].value);if(o!==0){const y=(c/o).toFixed(3);s.push({type:"text",style:{text:y,x:(i[3][0]+i[4][0])/2+8,y:(i[3][1]+i[4][1])/2,fill:"#ff5722",fontSize:10},silent:!0})}}for(let o=0;o<i.length&&o<je.length;o++){const[c,y]=i[o],d=(o===0||y<=i[o-1][1])&&(o===i.length-1||y<=i[o+1]?.[1]);s.push({type:"text",style:{text:je[o],x:c,y:d?y-14:y+16,fill:"#e2e8f0",fontSize:12,fontWeight:"bold",align:"center",verticalAlign:"middle"},silent:!0})}for(let o=0;o<i.length;o++)s.push({type:"circle",name:`point-${o}`,shape:{cx:i[o][0],cy:i[o][1],r:4},style:{fill:"#fff",stroke:r,lineWidth:1,opacity:n?1:0},z:100});return{type:"group",children:s}}}var Ns=Object.defineProperty,Fs=(h,t,e)=>t in h?Ns(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,Zt=(h,t,e)=>(Fs(h,typeof t!="symbol"?t+"":t,e),e);const Xe=["X","A","B","C","D"],qe=["#00bcd4","#e91e63","#8bc34a","#ff5722"],Zs=5;class Rs extends K{constructor(t={}){super({id:"cypher-pattern-tool",name:t.name||"Cypher Pattern",icon:t.icon||'<svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="#e3e3e3" stroke-width="1.5"><polyline points="2,16 7,4 11,12 17,2 22,14"/><circle cx="2" cy="16" r="1.5" fill="#e3e3e3"/><circle cx="7" cy="4" r="1.5" fill="#e3e3e3"/><circle cx="11" cy="12" r="1.5" fill="#e3e3e3"/><circle cx="17" cy="2" r="1.5" fill="#e3e3e3"/><circle cx="22" cy="14" r="1.5" fill="#e3e3e3"/></svg>'}),Zt(this,"points",[]),Zt(this,"state","idle"),Zt(this,"graphicGroup",null),Zt(this,"onClick",e=>{const i=this.getPoint(e);this.state==="idle"?(this.state="drawing",this.points=[i,[...i]],this.initGraphic(),this.updateGraphic()):this.state==="drawing"&&(this.points[this.points.length-1]=i,this.points.length>=Zs?(this.state="finished",this.updateGraphic(),this.saveDrawing(),this.removeGraphic(),this.context.disableTools()):(this.points.push([...i]),this.updateGraphic()))}),Zt(this,"onMouseMove",e=>{this.state!=="drawing"||this.points.length<2||(this.points[this.points.length-1]=this.getPoint(e),this.updateGraphic())})}onInit(){this.context.registerDrawingRenderer(new Ve)}onActivate(){this.state="idle",this.points=[],this.context.getChart().getZr().setCursorStyle("crosshair");const t=this.context.getChart().getZr();t.on("click",this.onClick),t.on("mousemove",this.onMouseMove)}onDeactivate(){this.state="idle",this.points=[],this.removeGraphic();const t=this.context.getChart().getZr();t.off("click",this.onClick),t.off("mousemove",this.onMouseMove),t.setCursorStyle("default")}initGraphic(){this.graphicGroup=new _.graphic.Group,this.context.getChart().getZr().add(this.graphicGroup)}removeGraphic(){this.graphicGroup&&(this.context.getChart().getZr().remove(this.graphicGroup),this.graphicGroup=null)}updateGraphic(){if(!this.graphicGroup)return;this.graphicGroup.removeAll();const t=this.points;t.length>=3&&this.graphicGroup.add(new _.graphic.Polygon({shape:{points:t.slice(0,3)},style:{fill:"rgba(0,188,212,0.08)"},silent:!0})),t.length>=5&&this.graphicGroup.add(new _.graphic.Polygon({shape:{points:t.slice(2,5)},style:{fill:"rgba(233,30,99,0.08)"},silent:!0}));for(let e=0;e<t.length-1;e++)this.graphicGroup.add(new _.graphic.Line({shape:{x1:t[e][0],y1:t[e][1],x2:t[e+1][0],y2:t[e+1][1]},style:{stroke:qe[e%qe.length],lineWidth:2},silent:!0}));for(let e=0;e<t.length&&e<Xe.length;e++){const[i,n]=t[e],r=(e===0||n<=t[e-1][1])&&(e===t.length-1||n<=t[e+1]?.[1]);this.graphicGroup.add(new _.graphic.Text({style:{text:Xe[e],x:i,y:r?n-14:n+16,fill:"#e2e8f0",fontSize:12,fontWeight:"bold",align:"center",verticalAlign:"middle"},silent:!0})),this.graphicGroup.add(new _.graphic.Circle({shape:{cx:i,cy:n,r:4},style:{fill:"#fff",stroke:"#3b82f6",lineWidth:1.5},z:101,silent:!0}))}}saveDrawing(){const t=this.points.map(e=>this.context.coordinateConversion.pixelToData({x:e[0],y:e[1]}));t.every(e=>e!==null)&&this.context.addDrawing({id:`cypher-${Date.now()}`,type:"cypher_pattern",points:t,paneIndex:t[0].paneIndex||0,style:{color:"#3b82f6",lineWidth:2}})}}var Hs=Object.defineProperty,Os=(h,t,e)=>t in h?Hs(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,Bs=(h,t,e)=>(Os(h,typeof t!="symbol"?t+"":t,e),e);const oe=["","LS","","H","","RS",""];class Ue{constructor(){Bs(this,"type","head_and_shoulders")}render(t){const{drawing:e,pixelPoints:i,isSelected:n}=t,r=e.style?.color||"#3b82f6";if(i.length<2)return;const s=[];i.length>=3&&s.push({type:"polygon",name:"line",shape:{points:i.slice(0,3).map(([l,a])=>[l,a])},style:{fill:"rgba(33, 150, 243, 0.06)"}}),i.length>=5&&s.push({type:"polygon",name:"line",shape:{points:i.slice(2,5).map(([l,a])=>[l,a])},style:{fill:"rgba(244, 67, 54, 0.08)"}}),i.length>=7&&s.push({type:"polygon",name:"line",shape:{points:i.slice(4,7).map(([l,a])=>[l,a])},style:{fill:"rgba(33, 150, 243, 0.06)"}});for(let l=0;l<i.length-1;l++){const[a,o]=i[l],[c,y]=i[l+1];s.push({type:"line",name:"line",shape:{x1:a,y1:o,x2:c,y2:y},style:{stroke:"#2196f3",lineWidth:e.style?.lineWidth||2}})}if(i.length>=5){const[l,a]=i[2],[o,c]=i[4],y=o-l,d=c-a,u=.3,p=.3,f=l-y*u,g=a-d*u,m=o+y*p,x=c+d*p;s.push({type:"line",shape:{x1:f,y1:g,x2:m,y2:x},style:{stroke:"#ff9800",lineWidth:2,lineDash:[6,4]},silent:!0}),s.push({type:"text",style:{text:"Neckline",x:(l+o)/2,y:(a+c)/2+14,fill:"#ff9800",fontSize:10,align:"center"},silent:!0})}for(let l=0;l<i.length&&l<oe.length;l++){if(!oe[l])continue;const[a,o]=i[l],c=(l===0||o<=i[l-1][1])&&(l===i.length-1||o<=i[l+1]?.[1]);s.push({type:"text",style:{text:oe[l],x:a,y:c?o-14:o+16,fill:"#e2e8f0",fontSize:12,fontWeight:"bold",align:"center",verticalAlign:"middle"},silent:!0})}for(let l=0;l<i.length;l++)s.push({type:"circle",name:`point-${l}`,shape:{cx:i[l][0],cy:i[l][1],r:4},style:{fill:"#fff",stroke:r,lineWidth:1,opacity:n?1:0},z:100});return{type:"group",children:s}}}var js=Object.defineProperty,Ys=(h,t,e)=>t in h?js(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,Rt=(h,t,e)=>(Ys(h,typeof t!="symbol"?t+"":t,e),e);const re=["","LS","","H","","RS",""],Vs=7;class Xs extends K{constructor(t={}){super({id:"head-and-shoulders-tool",name:t.name||"Head & Shoulders",icon:t.icon||'<svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="#e3e3e3" stroke-width="1.5"><polyline points="1,18 4,10 7,14 12,3 17,14 20,10 23,18"/></svg>'}),Rt(this,"points",[]),Rt(this,"state","idle"),Rt(this,"graphicGroup",null),Rt(this,"onClick",e=>{const i=this.getPoint(e);this.state==="idle"?(this.state="drawing",this.points=[i,[...i]],this.initGraphic(),this.updateGraphic()):this.state==="drawing"&&(this.points[this.points.length-1]=i,this.points.length>=Vs?(this.state="finished",this.updateGraphic(),this.saveDrawing(),this.removeGraphic(),this.context.disableTools()):(this.points.push([...i]),this.updateGraphic()))}),Rt(this,"onMouseMove",e=>{this.state!=="drawing"||this.points.length<2||(this.points[this.points.length-1]=this.getPoint(e),this.updateGraphic())})}onInit(){this.context.registerDrawingRenderer(new Ue)}onActivate(){this.state="idle",this.points=[],this.context.getChart().getZr().setCursorStyle("crosshair");const t=this.context.getChart().getZr();t.on("click",this.onClick),t.on("mousemove",this.onMouseMove)}onDeactivate(){this.state="idle",this.points=[],this.removeGraphic();const t=this.context.getChart().getZr();t.off("click",this.onClick),t.off("mousemove",this.onMouseMove),t.setCursorStyle("default")}initGraphic(){this.graphicGroup=new _.graphic.Group,this.context.getChart().getZr().add(this.graphicGroup)}removeGraphic(){this.graphicGroup&&(this.context.getChart().getZr().remove(this.graphicGroup),this.graphicGroup=null)}updateGraphic(){if(!this.graphicGroup)return;this.graphicGroup.removeAll();const t=this.points;t.length>=3&&this.graphicGroup.add(new _.graphic.Polygon({shape:{points:t.slice(0,3)},style:{fill:"rgba(33,150,243,0.06)"},silent:!0})),t.length>=5&&this.graphicGroup.add(new _.graphic.Polygon({shape:{points:t.slice(2,5)},style:{fill:"rgba(244,67,54,0.08)"},silent:!0})),t.length>=7&&this.graphicGroup.add(new _.graphic.Polygon({shape:{points:t.slice(4,7)},style:{fill:"rgba(33,150,243,0.06)"},silent:!0}));for(let e=0;e<t.length-1;e++)this.graphicGroup.add(new _.graphic.Line({shape:{x1:t[e][0],y1:t[e][1],x2:t[e+1][0],y2:t[e+1][1]},style:{stroke:"#2196f3",lineWidth:2},silent:!0}));if(t.length>=5){const[e,i]=t[2],[n,r]=t[4],s=n-e,l=r-i;this.graphicGroup.add(new _.graphic.Line({shape:{x1:e-s*.3,y1:i-l*.3,x2:n+s*.3,y2:r+l*.3},style:{stroke:"#ff9800",lineWidth:2,lineDash:[6,4]},silent:!0}))}for(let e=0;e<t.length&&e<re.length;e++){const[i,n]=t[e],r=(e===0||n<=t[e-1][1])&&(e===t.length-1||n<=t[e+1]?.[1]);re[e]&&this.graphicGroup.add(new _.graphic.Text({style:{text:re[e],x:i,y:r?n-14:n+16,fill:"#e2e8f0",fontSize:12,fontWeight:"bold",align:"center",verticalAlign:"middle"},silent:!0})),this.graphicGroup.add(new _.graphic.Circle({shape:{cx:i,cy:n,r:4},style:{fill:"#fff",stroke:"#3b82f6",lineWidth:1.5},z:101,silent:!0}))}}saveDrawing(){const t=this.points.map(e=>this.context.coordinateConversion.pixelToData({x:e[0],y:e[1]}));t.every(e=>e!==null)&&this.context.addDrawing({id:`hs-${Date.now()}`,type:"head_and_shoulders",points:t,paneIndex:t[0].paneIndex||0,style:{color:"#3b82f6",lineWidth:2}})}}var qs=Object.defineProperty,Us=(h,t,e)=>t in h?qs(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,Ks=(h,t,e)=>(Us(h,typeof t!="symbol"?t+"":t,e),e);const Ke=["1","2","3","4","5"];class Je{constructor(){Ks(this,"type","triangle_pattern")}render(t){const{drawing:e,pixelPoints:i,isSelected:n}=t,r=e.style?.color||"#3b82f6";if(i.length<2)return;const s=[];i.length>=3&&s.push({type:"polygon",name:"line",shape:{points:i.map(([o,c])=>[o,c])},style:{fill:"rgba(156, 39, 176, 0.06)"}});const l=i.filter((o,c)=>c%2===0);if(l.length>=2){for(let o=0;o<l.length-1;o++)s.push({type:"line",name:"line",shape:{x1:l[o][0],y1:l[o][1],x2:l[o+1][0],y2:l[o+1][1]},style:{stroke:"#f44336",lineWidth:2}});if(l.length>=2){const o=l[l.length-1],c=l[l.length-2],y=o[0]-c[0],d=o[1]-c[1];if(y!==0){const u=o[0]+y*.5,p=o[1]+d*.5;s.push({type:"line",shape:{x1:o[0],y1:o[1],x2:u,y2:p},style:{stroke:"#f44336",lineWidth:1,lineDash:[4,4]},silent:!0})}}}const a=i.filter((o,c)=>c%2===1);if(a.length>=2){for(let o=0;o<a.length-1;o++)s.push({type:"line",name:"line",shape:{x1:a[o][0],y1:a[o][1],x2:a[o+1][0],y2:a[o+1][1]},style:{stroke:"#4caf50",lineWidth:2}});if(a.length>=2){const o=a[a.length-1],c=a[a.length-2],y=o[0]-c[0],d=o[1]-c[1];if(y!==0){const u=o[0]+y*.5,p=o[1]+d*.5;s.push({type:"line",shape:{x1:o[0],y1:o[1],x2:u,y2:p},style:{stroke:"#4caf50",lineWidth:1,lineDash:[4,4]},silent:!0})}}}for(let o=0;o<i.length-1;o++)s.push({type:"line",shape:{x1:i[o][0],y1:i[o][1],x2:i[o+1][0],y2:i[o+1][1]},style:{stroke:"#9c27b0",lineWidth:1,lineDash:[2,2]},silent:!0});for(let o=0;o<i.length&&o<Ke.length;o++){const[c,y]=i[o],d=o%2===0;s.push({type:"text",style:{text:Ke[o],x:c,y:d?y-14:y+16,fill:"#e2e8f0",fontSize:12,fontWeight:"bold",align:"center",verticalAlign:"middle"},silent:!0})}for(let o=0;o<i.length;o++)s.push({type:"circle",name:`point-${o}`,shape:{cx:i[o][0],cy:i[o][1],r:4},style:{fill:"#fff",stroke:r,lineWidth:1,opacity:n?1:0},z:100});return{type:"group",children:s}}}var Js=Object.defineProperty,Qs=(h,t,e)=>t in h?Js(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,Ht=(h,t,e)=>(Qs(h,typeof t!="symbol"?t+"":t,e),e);const Qe=["1","2","3","4","5"],to=5;class eo extends K{constructor(t={}){super({id:"triangle-pattern-tool",name:t.name||"Triangle Pattern",icon:t.icon||'<svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="#e3e3e3" stroke-width="1.5"><path d="M2,4 L22,4 L12,20 Z"/></svg>'}),Ht(this,"points",[]),Ht(this,"state","idle"),Ht(this,"graphicGroup",null),Ht(this,"onClick",e=>{const i=this.getPoint(e);this.state==="idle"?(this.state="drawing",this.points=[i,[...i]],this.initGraphic(),this.updateGraphic()):this.state==="drawing"&&(this.points[this.points.length-1]=i,this.points.length>=to?(this.state="finished",this.updateGraphic(),this.saveDrawing(),this.removeGraphic(),this.context.disableTools()):(this.points.push([...i]),this.updateGraphic()))}),Ht(this,"onMouseMove",e=>{this.state!=="drawing"||this.points.length<2||(this.points[this.points.length-1]=this.getPoint(e),this.updateGraphic())})}onInit(){this.context.registerDrawingRenderer(new Je)}onActivate(){this.state="idle",this.points=[],this.context.getChart().getZr().setCursorStyle("crosshair");const t=this.context.getChart().getZr();t.on("click",this.onClick),t.on("mousemove",this.onMouseMove)}onDeactivate(){this.state="idle",this.points=[],this.removeGraphic();const t=this.context.getChart().getZr();t.off("click",this.onClick),t.off("mousemove",this.onMouseMove),t.setCursorStyle("default")}initGraphic(){this.graphicGroup=new _.graphic.Group,this.context.getChart().getZr().add(this.graphicGroup)}removeGraphic(){this.graphicGroup&&(this.context.getChart().getZr().remove(this.graphicGroup),this.graphicGroup=null)}updateGraphic(){if(!this.graphicGroup)return;this.graphicGroup.removeAll();const t=this.points;t.length>=3&&this.graphicGroup.add(new _.graphic.Polygon({shape:{points:t},style:{fill:"rgba(156,39,176,0.06)"},silent:!0}));for(let n=0;n<t.length-1;n++)this.graphicGroup.add(new _.graphic.Line({shape:{x1:t[n][0],y1:t[n][1],x2:t[n+1][0],y2:t[n+1][1]},style:{stroke:"#9c27b0",lineWidth:2},silent:!0}));const e=t.filter((n,r)=>r%2===0);if(e.length>=2)for(let n=0;n<e.length-1;n++)this.graphicGroup.add(new _.graphic.Line({shape:{x1:e[n][0],y1:e[n][1],x2:e[n+1][0],y2:e[n+1][1]},style:{stroke:"#f44336",lineWidth:1,lineDash:[4,4]},silent:!0}));const i=t.filter((n,r)=>r%2===1);if(i.length>=2)for(let n=0;n<i.length-1;n++)this.graphicGroup.add(new _.graphic.Line({shape:{x1:i[n][0],y1:i[n][1],x2:i[n+1][0],y2:i[n+1][1]},style:{stroke:"#4caf50",lineWidth:1,lineDash:[4,4]},silent:!0}));for(let n=0;n<t.length&&n<Qe.length;n++){const[r,s]=t[n],l=n%2===0;this.graphicGroup.add(new _.graphic.Text({style:{text:Qe[n],x:r,y:l?s-14:s+16,fill:"#e2e8f0",fontSize:12,fontWeight:"bold",align:"center",verticalAlign:"middle"},silent:!0})),this.graphicGroup.add(new _.graphic.Circle({shape:{cx:r,cy:s,r:4},style:{fill:"#fff",stroke:"#3b82f6",lineWidth:1.5},z:101,silent:!0}))}}saveDrawing(){const t=this.points.map(e=>this.context.coordinateConversion.pixelToData({x:e[0],y:e[1]}));t.every(e=>e!==null)&&this.context.addDrawing({id:`triangle-${Date.now()}`,type:"triangle_pattern",points:t,paneIndex:t[0].paneIndex||0,style:{color:"#3b82f6",lineWidth:2}})}}var io=Object.defineProperty,no=(h,t,e)=>t in h?io(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,so=(h,t,e)=>(no(h,typeof t!="symbol"?t+"":t,e),e);const ae=["0","D1","C1","D2","C2","D3",""],ti=["#2196f3","#ff9800","#4caf50","#f44336","#00bcd4","#e91e63"];class ei{constructor(){so(this,"type","three_drives_pattern")}render(t){const{drawing:e,pixelPoints:i,isSelected:n}=t,r=e.style?.color||"#3b82f6";if(i.length<2)return;const s=[];i.length>=3&&s.push({type:"polygon",name:"line",shape:{points:i.slice(0,3).map(([o,c])=>[o,c])},style:{fill:"rgba(33, 150, 243, 0.06)"}}),i.length>=5&&s.push({type:"polygon",name:"line",shape:{points:i.slice(2,5).map(([o,c])=>[o,c])},style:{fill:"rgba(76, 175, 80, 0.06)"}}),i.length>=7&&s.push({type:"polygon",name:"line",shape:{points:i.slice(4,7).map(([o,c])=>[o,c])},style:{fill:"rgba(0, 188, 212, 0.06)"}});for(let o=0;o<i.length-1;o++){const[c,y]=i[o],[d,u]=i[o+1];s.push({type:"line",name:"line",shape:{x1:c,y1:y,x2:d,y2:u},style:{stroke:ti[o%ti.length],lineWidth:e.style?.lineWidth||2}})}const l=[[1,3],[3,5],[2,4]];for(const[o,c]of l)o<i.length&&c<i.length&&s.push({type:"line",shape:{x1:i[o][0],y1:i[o][1],x2:i[c][0],y2:i[c][1]},style:{stroke:"#555",lineWidth:1,lineDash:[4,4]},silent:!0});const a=e.points;if(a.length>=4){const o=Math.abs(a[1].value-a[0].value),c=Math.abs(a[3].value-a[2].value);if(o!==0){const y=(c/o).toFixed(3),d=(i[2][0]+i[3][0])/2,u=(i[2][1]+i[3][1])/2;s.push({type:"text",style:{text:`D2/D1: ${y}`,x:d+10,y:u,fill:"#4caf50",fontSize:9},silent:!0})}}if(a.length>=6){const o=Math.abs(a[3].value-a[2].value),c=Math.abs(a[5].value-a[4].value);if(o!==0){const y=(c/o).toFixed(3),d=(i[4][0]+i[5][0])/2,u=(i[4][1]+i[5][1])/2;s.push({type:"text",style:{text:`D3/D2: ${y}`,x:d+10,y:u,fill:"#00bcd4",fontSize:9},silent:!0})}}if(a.length>=3){const o=Math.abs(a[1].value-a[0].value),c=Math.abs(a[2].value-a[1].value);if(o!==0){const y=(c/o).toFixed(3),d=(i[1][0]+i[2][0])/2,u=(i[1][1]+i[2][1])/2;s.push({type:"text",style:{text:y,x:d+8,y:u,fill:"#ff9800",fontSize:10},silent:!0})}}for(let o=0;o<i.length&&o<ae.length;o++){if(!ae[o])continue;const[c,y]=i[o],d=(o===0||y<=i[o-1][1])&&(o===i.length-1||y<=i[o+1]?.[1]);s.push({type:"text",style:{text:ae[o],x:c,y:d?y-14:y+16,fill:"#e2e8f0",fontSize:11,fontWeight:"bold",align:"center",verticalAlign:"middle"},silent:!0})}for(let o=0;o<i.length;o++)s.push({type:"circle",name:`point-${o}`,shape:{cx:i[o][0],cy:i[o][1],r:4},style:{fill:"#fff",stroke:r,lineWidth:1,opacity:n?1:0},z:100});return{type:"group",children:s}}}var oo=Object.defineProperty,ro=(h,t,e)=>t in h?oo(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,Ot=(h,t,e)=>(ro(h,typeof t!="symbol"?t+"":t,e),e);const le=["0","D1","C1","D2","C2","D3",""],ii=["#2196f3","#ff9800","#4caf50","#f44336","#00bcd4","#e91e63"],ao=7;class lo extends K{constructor(t={}){super({id:"three-drives-pattern-tool",name:t.name||"Three Drives",icon:t.icon||'<svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="#e3e3e3" stroke-width="1.5"><polyline points="1,20 4,8 7,14 11,5 15,12 19,2 23,10"/></svg>'}),Ot(this,"points",[]),Ot(this,"state","idle"),Ot(this,"graphicGroup",null),Ot(this,"onClick",e=>{const i=this.getPoint(e);this.state==="idle"?(this.state="drawing",this.points=[i,[...i]],this.initGraphic(),this.updateGraphic()):this.state==="drawing"&&(this.points[this.points.length-1]=i,this.points.length>=ao?(this.state="finished",this.updateGraphic(),this.saveDrawing(),this.removeGraphic(),this.context.disableTools()):(this.points.push([...i]),this.updateGraphic()))}),Ot(this,"onMouseMove",e=>{this.state!=="drawing"||this.points.length<2||(this.points[this.points.length-1]=this.getPoint(e),this.updateGraphic())})}onInit(){this.context.registerDrawingRenderer(new ei)}onActivate(){this.state="idle",this.points=[],this.context.getChart().getZr().setCursorStyle("crosshair");const t=this.context.getChart().getZr();t.on("click",this.onClick),t.on("mousemove",this.onMouseMove)}onDeactivate(){this.state="idle",this.points=[],this.removeGraphic();const t=this.context.getChart().getZr();t.off("click",this.onClick),t.off("mousemove",this.onMouseMove),t.setCursorStyle("default")}initGraphic(){this.graphicGroup=new _.graphic.Group,this.context.getChart().getZr().add(this.graphicGroup)}removeGraphic(){this.graphicGroup&&(this.context.getChart().getZr().remove(this.graphicGroup),this.graphicGroup=null)}updateGraphic(){if(!this.graphicGroup)return;this.graphicGroup.removeAll();const t=this.points;t.length>=3&&this.graphicGroup.add(new _.graphic.Polygon({shape:{points:t.slice(0,3)},style:{fill:"rgba(33,150,243,0.06)"},silent:!0})),t.length>=5&&this.graphicGroup.add(new _.graphic.Polygon({shape:{points:t.slice(2,5)},style:{fill:"rgba(76,175,80,0.06)"},silent:!0})),t.length>=7&&this.graphicGroup.add(new _.graphic.Polygon({shape:{points:t.slice(4,7)},style:{fill:"rgba(0,188,212,0.06)"},silent:!0}));for(let i=0;i<t.length-1;i++)this.graphicGroup.add(new _.graphic.Line({shape:{x1:t[i][0],y1:t[i][1],x2:t[i+1][0],y2:t[i+1][1]},style:{stroke:ii[i%ii.length],lineWidth:2},silent:!0}));const e=[[1,3],[3,5],[2,4]];for(const[i,n]of e)i<t.length&&n<t.length&&this.graphicGroup.add(new _.graphic.Line({shape:{x1:t[i][0],y1:t[i][1],x2:t[n][0],y2:t[n][1]},style:{stroke:"#555",lineWidth:1,lineDash:[4,4]},silent:!0}));for(let i=0;i<t.length&&i<le.length;i++){const[n,r]=t[i],s=(i===0||r<=t[i-1][1])&&(i===t.length-1||r<=t[i+1]?.[1]);le[i]&&this.graphicGroup.add(new _.graphic.Text({style:{text:le[i],x:n,y:s?r-14:r+16,fill:"#e2e8f0",fontSize:11,fontWeight:"bold",align:"center",verticalAlign:"middle"},silent:!0})),this.graphicGroup.add(new _.graphic.Circle({shape:{cx:n,cy:r,r:4},style:{fill:"#fff",stroke:"#3b82f6",lineWidth:1.5},z:101,silent:!0}))}}saveDrawing(){const t=this.points.map(e=>this.context.coordinateConversion.pixelToData({x:e[0],y:e[1]}));t.every(e=>e!==null)&&this.context.addDrawing({id:`3drives-${Date.now()}`,type:"three_drives_pattern",points:t,paneIndex:t[0].paneIndex||0,style:{color:"#3b82f6",lineWidth:2}})}}var ho=Object.defineProperty,co=(h,t,e)=>t in h?ho(h,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):h[t]=e,Mt=(h,t,e)=>(co(h,typeof t!="symbol"?t+"":t,e),e);class po extends K{constructor(t){const e='<svg width="8" height="8" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="position: absolute; right: -4px; top: 50%; transform: translateY(-50%); opacity: 0.6;"><polyline points="9 18 15 12 9 6"></polyline></svg>';let i="";t.icon?i=`<div style="position: relative; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;">
|
|
43
|
+
<div style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;">
|
|
44
|
+
${t.icon}
|
|
45
|
+
</div>
|
|
46
|
+
${e}
|
|
47
|
+
</div>`:i=`<div style="position: relative; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;">
|
|
48
|
+
<span>${t.name.substring(0,2).toUpperCase()}</span>
|
|
49
|
+
${e}
|
|
50
|
+
</div>`,super({id:t.id||`group-${t.name.toLowerCase().replace(/\s+/g,"-")}`,name:t.name,icon:i}),Mt(this,"plugins",[]),Mt(this,"activeSubPlugin",null),Mt(this,"menuElement",null),Mt(this,"buttonElement",null),Mt(this,"originalIcon",""),Mt(this,"arrowSvg",""),Mt(this,"handleOutsideClick",n=>{this.menuElement&&!this.menuElement.contains(n.target)&&(this.hideMenu(),this.activeSubPlugin||this.buttonElement?.click())}),this.originalIcon=i,this.arrowSvg=e}add(t){this.plugins.push(t)}onInit(){this.plugins.forEach(t=>t.init(this.context))}onActivate(){this.showMenu()}onDeactivate(){this.hideMenu(),this.activeSubPlugin&&(this.activeSubPlugin.deactivate?.(),this.activeSubPlugin=null),this.buttonElement&&(this.buttonElement.innerHTML=this.originalIcon)}onDestroy(){this.hideMenu(),this.plugins.forEach(t=>t.destroy?.())}showMenu(){if(this.buttonElement=document.getElementById(`qfchart-plugin-btn-${this.id}`),!this.buttonElement)return;this.menuElement&&this.hideMenu(),this.menuElement=document.createElement("div"),Object.assign(this.menuElement.style,{position:"fixed",backgroundColor:"#1e293b",border:"1px solid #334155",borderRadius:"6px",padding:"4px",display:"flex",flexDirection:"column",gap:"2px",zIndex:"10000",boxShadow:"0 4px 6px -1px rgba(0, 0, 0, 0.3)",minWidth:"150px"}),this.plugins.forEach(e=>{const i=document.createElement("div");if(Object.assign(i.style,{display:"flex",alignItems:"center",padding:"8px 12px",cursor:"pointer",color:"#cbd5e1",borderRadius:"4px",fontSize:"13px",fontFamily:this.context.getOptions().fontFamily||"sans-serif",transition:"background-color 0.2s"}),i.addEventListener("mouseenter",()=>{i.style.backgroundColor="rgba(255, 255, 255, 0.1)"}),i.addEventListener("mouseleave",()=>{i.style.backgroundColor="transparent"}),e.icon){const r=document.createElement("div");r.innerHTML=e.icon,Object.assign(r.style,{width:"20px",height:"20px",marginRight:"10px",display:"flex",alignItems:"center",justifyContent:"center"});const s=r.querySelector("svg");s&&(s.style.width="100%",s.style.height="100%"),i.appendChild(r)}const n=document.createElement("span");n.textContent=e.name||e.id,i.appendChild(n),i.addEventListener("click",r=>{r.stopPropagation(),this.activateSubPlugin(e)}),this.menuElement.appendChild(i)}),document.body.appendChild(this.menuElement);const t=this.buttonElement.getBoundingClientRect();this.menuElement.style.top=`${t.top}px`,this.menuElement.style.left=`${t.right+5}px`,setTimeout(()=>{document.addEventListener("click",this.handleOutsideClick)},0)}hideMenu(){this.menuElement&&this.menuElement.parentNode&&this.menuElement.parentNode.removeChild(this.menuElement),this.menuElement=null,document.removeEventListener("click",this.handleOutsideClick)}activateSubPlugin(t){if(this.hideMenu(),this.activeSubPlugin&&this.activeSubPlugin.deactivate?.(),this.activeSubPlugin=t,this.activeSubPlugin.activate?.(),this.buttonElement){let e="";t.icon?e=`<div style="position: relative; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;">
|
|
51
|
+
<div style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;">
|
|
52
|
+
${t.icon}
|
|
53
|
+
</div>
|
|
54
|
+
${this.arrowSvg}
|
|
55
|
+
</div>`:e=`<div style="position: relative; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;">
|
|
56
|
+
<span>${(t.name||t.id).substring(0,2).toUpperCase()}</span>
|
|
57
|
+
${this.arrowSvg}
|
|
58
|
+
</div>`,this.buttonElement.innerHTML=e}}}T.ABCDPatternDrawingRenderer=He,T.ABCDPatternTool=Es,T.AbstractPlugin=K,T.CrossLineDrawingRenderer=Ie,T.CrossLineTool=Xn,T.CypherPatternDrawingRenderer=Ve,T.CypherPatternTool=Rs,T.DrawingRendererRegistry=ye,T.ExtendedLineDrawingRenderer=be,T.ExtendedLineTool=mn,T.FibSpeedResistanceFanDrawingRenderer=ze,T.FibSpeedResistanceFanTool=ps,T.FibTrendExtensionDrawingRenderer=Ee,T.FibTrendExtensionTool=ms,T.FibonacciChannelDrawingRenderer=Se,T.FibonacciChannelTool=rs,T.FibonacciDrawingRenderer=_e,T.FibonacciTool=ts,T.HeadAndShouldersDrawingRenderer=Ue,T.HeadAndShouldersTool=Xs,T.HorizontalLineDrawingRenderer=we,T.HorizontalLineTool=Sn,T.HorizontalRayDrawingRenderer=Pe,T.HorizontalRayTool=Tn,T.InfoLineDrawingRenderer=me,T.InfoLineTool=pn,T.LineDrawingRenderer=fe,T.LineTool=Qi,T.MeasureTool=Vi,T.QFChart=Hi,T.RayDrawingRenderer=xe,T.RayTool=rn,T.ThreeDrivesPatternDrawingRenderer=ei,T.ThreeDrivesPatternTool=lo,T.ToolGroup=po,T.TrendAngleDrawingRenderer=ve,T.TrendAngleTool=kn,T.TrianglePatternDrawingRenderer=Je,T.TrianglePatternTool=eo,T.VerticalLineDrawingRenderer=De,T.VerticalLineTool=Hn,T.XABCDPatternDrawingRenderer=We,T.XABCDPatternTool=Is});
|