@alphacharts/indicators 0.0.0-stage → 0.1.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.
Files changed (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +95 -2
  3. package/dist/all-DeXJJd7D.js +21 -0
  4. package/dist/all-DeXJJd7D.js.map +1 -0
  5. package/dist/all.js +10 -0
  6. package/dist/all.js.map +1 -0
  7. package/dist/assets/worker-BrUuzTIJ.js +2 -0
  8. package/dist/assets/worker-BrUuzTIJ.js.map +1 -0
  9. package/dist/define-BPvQbaq9.js +472 -0
  10. package/dist/define-BPvQbaq9.js.map +1 -0
  11. package/dist/index.js +593 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/registry-CYZuqhXX.js +49 -0
  14. package/dist/registry-CYZuqhXX.js.map +1 -0
  15. package/dist/runner-DBP0M8z3.js +229 -0
  16. package/dist/runner-DBP0M8z3.js.map +1 -0
  17. package/dist/studies.js +1 -0
  18. package/dist/tv-volume-7hh6ajKt.js +3457 -0
  19. package/dist/tv-volume-7hh6ajKt.js.map +1 -0
  20. package/dist/types/all.d.ts +3 -0
  21. package/dist/types/chart/studies.d.ts +165 -0
  22. package/dist/types/define.d.ts +46 -0
  23. package/dist/types/engine/graph.d.ts +101 -0
  24. package/dist/types/engine/kernels.d.ts +9 -0
  25. package/dist/types/engine/study.d.ts +31 -0
  26. package/dist/types/index.d.ts +12 -0
  27. package/dist/types/registry.d.ts +7 -0
  28. package/dist/types/runner.d.ts +82 -0
  29. package/dist/types/studies/all.d.ts +2 -0
  30. package/dist/types/studies/cycle.d.ts +7 -0
  31. package/dist/types/studies/index.d.ts +13 -0
  32. package/dist/types/studies/ma.d.ts +26 -0
  33. package/dist/types/studies/math.d.ts +28 -0
  34. package/dist/types/studies/momentum.d.ts +30 -0
  35. package/dist/types/studies/overlap.d.ts +14 -0
  36. package/dist/types/studies/patterns.d.ts +62 -0
  37. package/dist/types/studies/price.d.ts +6 -0
  38. package/dist/types/studies/sar.d.ts +2 -0
  39. package/dist/types/studies/statistic.d.ts +9 -0
  40. package/dist/types/studies/tv-osc.d.ts +18 -0
  41. package/dist/types/studies/tv-trend.d.ts +20 -0
  42. package/dist/types/studies/tv-volume.d.ts +14 -0
  43. package/dist/types/studies/volatility.d.ts +3 -0
  44. package/dist/types/studies/volume.d.ts +3 -0
  45. package/dist/types/types.d.ts +133 -0
  46. package/dist/types/wasm.d.ts +2 -0
  47. package/dist/types/worker.d.ts +1 -0
  48. package/dist/worker.js +8 -0
  49. package/dist/worker.js.map +1 -0
  50. package/package.json +69 -3
package/dist/index.js ADDED
@@ -0,0 +1,593 @@
1
+ import { _ as e, g as t, h as n, i as r, m as i, v as a } from "./define-BPvQbaq9.js";
2
+ import { a as o, c as s, i as c, l, n as u, o as d, r as f, s as p, t as m } from "./runner-DBP0M8z3.js";
3
+ import { a as h, i as g, n as _, r as v, t as y } from "./registry-CYZuqhXX.js";
4
+ import { COL_C as b, COL_H as x, COL_L as S, COL_O as C, COL_V as w, cssColor as T, parseColor as E } from "@alphacharts/core";
5
+ import { loadKernels as D } from "@alphacharts/wasm";
6
+ //#region src/chart/studies.ts
7
+ var O = "alphacharts.studies", k = class {
8
+ host;
9
+ id;
10
+ source;
11
+ volume;
12
+ ownRunner;
13
+ onDispose;
14
+ def;
15
+ params;
16
+ engine;
17
+ outs = [];
18
+ lines = [];
19
+ styles = {};
20
+ shown = !0;
21
+ pane = 0;
22
+ scaleId = "right";
23
+ version = 0;
24
+ job = null;
25
+ dirty = !1;
26
+ structural = !1;
27
+ error = null;
28
+ ready_ = Promise.resolve();
29
+ disposed = !1;
30
+ decimals = 2;
31
+ persist = !0;
32
+ constructor(e, t, n, r, i, a, o, c, l) {
33
+ this.host = e, this.id = t, this.source = i, this.volume = a, this.ownRunner = c, this.onDispose = l, this.def = n, this.params = s(n, r), this.engine = new p(n, this.params), this.checkSource(), o?.styles && (this.styles = { ...o.styles }), o?.visible === !1 && (this.shown = !1), this.createSeries(), this.recompute();
34
+ }
35
+ inputs() {
36
+ return this.params;
37
+ }
38
+ get visible() {
39
+ return this.shown;
40
+ }
41
+ ready() {
42
+ return this.ready_;
43
+ }
44
+ refresh(e = !0) {
45
+ this.disposed || this.error || this.engine.length === 0 || (e ? this.tickSync() : this.syncAll(), this.host.api?.requestRender(!0));
46
+ }
47
+ series() {
48
+ return this.outs.map((e) => e.series);
49
+ }
50
+ setInputs(e) {
51
+ let t = s(this.def, {
52
+ ...this.params,
53
+ ...e
54
+ }), n = new p(this.def, t);
55
+ this.params = t, this.engine = n, this.retitle(), this.recompute(), this.host.changed();
56
+ }
57
+ setVisible(e) {
58
+ this.shown = e;
59
+ for (let t of this.outs) t.series.applyOptions({ visible: e });
60
+ this.host.changed();
61
+ }
62
+ setStyle(e, t) {
63
+ t.color !== void 0 && E(t.color), this.styles[e] = {
64
+ ...this.styles[e],
65
+ ...t
66
+ };
67
+ for (let t of this.outs) t.key.split(":")[0] === e && t.series.applyOptions(this.seriesOptions(t.plot, t.key));
68
+ this.host.changed();
69
+ }
70
+ remove() {
71
+ this.host.removeStudy(this.id);
72
+ }
73
+ lastValues() {
74
+ let e = this.engine.length, t = {};
75
+ return this.def.columns.forEach((n, r) => {
76
+ let i = e > 0 ? this.engine.column(r)[e - 1] : NaN;
77
+ t[n] = i === i ? i : void 0;
78
+ }), t;
79
+ }
80
+ column(e) {
81
+ let t = this.def.columns.indexOf(e);
82
+ if (t < 0) throw RangeError(`${this.def.id} has no column "${e}"`);
83
+ return this.engine.column(t);
84
+ }
85
+ times() {
86
+ return this.engine.graph.time.v.subarray(0, this.engine.length);
87
+ }
88
+ state() {
89
+ return {
90
+ id: this.id,
91
+ study: this.def.id,
92
+ inputs: { ...this.params },
93
+ source: this.source.options().id,
94
+ ...this.volume && { volume: this.volume.options().id },
95
+ visible: this.shown,
96
+ styles: this.styles
97
+ };
98
+ }
99
+ drop() {
100
+ this.disposed || this.onDispose?.(), this.disposed = !0, this.job?.cancel();
101
+ }
102
+ dispose(e) {
103
+ this.drop();
104
+ for (let { series: t, line: n } of this.lines) e.removePriceLine(t, n);
105
+ for (let t of this.outs) e.removeSeries(t.series);
106
+ this.outs = [], this.lines = [];
107
+ }
108
+ get ohlc() {
109
+ return this.source.data.shape === "ohlc";
110
+ }
111
+ checkSource() {
112
+ let e = this.def.needs;
113
+ if (!this.ohlc) {
114
+ if (e !== "value") throw TypeError(`${this.def.id} needs ${e} bars; the source series holds single values`);
115
+ if (this.params.source !== void 0 && this.params.source !== "close") throw RangeError(`${this.def.id}: a single-value source has only "close", not "${this.params.source}"`);
116
+ }
117
+ if (e === "ohlcv" && !this.volume) throw TypeError(`${this.def.id} needs volume: pass the volume series as options.volume`);
118
+ }
119
+ watches(e) {
120
+ return e === this.source.data ? "source" : this.volume && e === this.volume.data ? "volume" : null;
121
+ }
122
+ bars() {
123
+ let e = this.host.chart, t = this.source.data, n = t.store, r = 0;
124
+ for (let e = n.first; e < n.end; e++) t.has(e) && r++;
125
+ let i = new Float64Array(r), a = new Float64Array(r), o = this.ohlc, s = o ? new Float64Array(r) : void 0, c = o ? new Float64Array(r) : void 0, l = o ? new Float64Array(r) : void 0, u = this.volume ? new Float64Array(r) : void 0, d = 0;
126
+ for (let r = n.first; r < n.end; r++) t.has(r) && (i[d] = e.logicalToTime(r), o ? (s[d] = t.get(r, C), c[d] = t.get(r, x), l[d] = t.get(r, S), a[d] = t.get(r, b)) : a[d] = t.get(r, w), u && (u[d] = this.volume.data.get(r, w)), d++);
127
+ return {
128
+ time: i,
129
+ close: a,
130
+ ...o && {
131
+ open: s,
132
+ high: c,
133
+ low: l
134
+ },
135
+ ...u && { volume: u }
136
+ };
137
+ }
138
+ barAt(e) {
139
+ let t = this.source.data, n = NaN;
140
+ return {
141
+ time: this.host.chart.logicalToTime(e),
142
+ open: this.ohlc ? t.get(e, C) : n,
143
+ high: this.ohlc ? t.get(e, x) : n,
144
+ low: this.ohlc ? t.get(e, S) : n,
145
+ close: this.ohlc ? t.get(e, b) : t.get(e, w),
146
+ volume: this.volume ? this.volume.data.get(e, w) : n
147
+ };
148
+ }
149
+ onChange(e) {
150
+ if (this.disposed || this.error) return;
151
+ let t = this.watches(e.series);
152
+ if (e.series === null || !t) return;
153
+ if (this.job) {
154
+ e.kind === "update" ? this.dirty = !0 : this.structural = !0;
155
+ return;
156
+ }
157
+ if (e.kind !== "update") {
158
+ this.recompute();
159
+ return;
160
+ }
161
+ let n = this.source.data.lastIndex();
162
+ if (n === void 0) return this.recompute();
163
+ if (t === "volume" && e.lo > n) return;
164
+ if (t === "volume" && e.lo < n) return this.recompute();
165
+ let r = this.barAt(n), i = this.engine, a = i.length, o = a > 0 ? i.graph.time.v[a - 1] : NaN;
166
+ if (a > 0 && r.time === o) i.reviseLast(r);
167
+ else if (a === 0 || r.time > o) i.push(r);
168
+ else return this.recompute();
169
+ this.tickSync(), this.host.api?.requestRender();
170
+ }
171
+ recompute() {
172
+ this.version++, this.job?.cancel(), this.job = null, this.dirty = !1, this.structural = !1, this.error = null;
173
+ let e = this.bars(), t = this.ownRunner ?? this.host.runner;
174
+ if (!t || !t.canRun(this.def)) {
175
+ this.engine.load(e), this.syncAll(), this.ready_ = Promise.resolve();
176
+ return;
177
+ }
178
+ let n = this.version, r = t.run(this.def, {
179
+ studyId: this.def.id,
180
+ params: this.params,
181
+ bars: e
182
+ });
183
+ this.job = r, this.ready_ = r.promise.then((e) => {
184
+ n !== this.version || this.disposed || (this.job = null, this.engine.graph.adopt(e.buffers, e.n), this.structural ? this.recompute() : (this.dirty && (this.dirty = !1, this.catchUp()), this.syncAll()));
185
+ }, (e) => {
186
+ if (!(e instanceof u || n !== this.version || this.disposed)) throw this.job = null, this.error = e instanceof Error ? e : Error(String(e)), this.error;
187
+ });
188
+ }
189
+ catchUp() {
190
+ let e = this.engine, t = this.bars(), n = t.time.length;
191
+ if (e.length === 0 || n === 0) return this.fullLoad(t);
192
+ let r = e.graph.time.v[e.length - 1], i = j(t.time, n, r), a = (e) => ({
193
+ time: t.time[e],
194
+ open: t.open?.[e] ?? NaN,
195
+ high: t.high?.[e] ?? NaN,
196
+ low: t.low?.[e] ?? NaN,
197
+ close: t.close[e],
198
+ volume: t.volume?.[e] ?? NaN
199
+ });
200
+ if (i < n && t.time[i] === r) e.reviseLast(a(i++));
201
+ else if (i < n && i === 0) return this.fullLoad(t);
202
+ for (; i < n; i++) e.push(a(i));
203
+ }
204
+ fullLoad(e) {
205
+ this.engine.load(e);
206
+ }
207
+ title() {
208
+ let e = this.def.label?.(this.params);
209
+ return e ? `${this.def.name} (${e})` : this.def.name;
210
+ }
211
+ retitle() {
212
+ this.outs.forEach((e, t) => e.series.applyOptions({ title: t === 0 ? this.title() : e.plot.title }));
213
+ }
214
+ color(e) {
215
+ return this.styles[e.key]?.color ?? e.color;
216
+ }
217
+ seriesOptions(e, t) {
218
+ let n = this.styles[e.key], r = n?.color;
219
+ switch (e.kind) {
220
+ case "line": return {
221
+ color: r ?? e.color,
222
+ lineWidth: n?.width ?? e.width ?? 1.5
223
+ };
224
+ case "band": return {
225
+ color: r ?? e.color,
226
+ lineWidth: n?.width ?? e.width ?? 1
227
+ };
228
+ case "histogram": return { color: r ?? e.color };
229
+ case "area": {
230
+ let t = r ?? e.color;
231
+ return {
232
+ lineColor: t,
233
+ topColor: M(t, .28),
234
+ bottomColor: M(t, .02),
235
+ lineWidth: n?.width ?? 1.5
236
+ };
237
+ }
238
+ default: return {};
239
+ }
240
+ }
241
+ createSeries() {
242
+ let e = this.host.chart, t = this.source.options();
243
+ this.def.pane === "overlay" ? (this.pane = t.pane, this.scaleId = t.priceScaleId) : (this.pane = this.host.freePane(), this.scaleId = "right");
244
+ let n = this.def.pane === "overlay", r = this.def.columns, i = (i, a, o, s, c) => {
245
+ let l = e.addSeries(o, {
246
+ id: `study:${this.id}:${a}`,
247
+ pane: this.pane,
248
+ priceScaleId: this.scaleId,
249
+ title: this.outs.length === 0 ? this.title() : i.title,
250
+ lastValueVisible: !n,
251
+ priceLineVisible: !1,
252
+ visible: this.shown,
253
+ ...this.seriesOptions(i, a),
254
+ priceFormat: n ? t.priceFormat : {
255
+ type: "price",
256
+ minMove: this.def.minMove ?? 10 ** -this.decimals
257
+ }
258
+ });
259
+ this.outs.push({
260
+ plot: i,
261
+ key: a,
262
+ col: r.indexOf(s),
263
+ series: l,
264
+ offset: c,
265
+ lastTime: NaN
266
+ });
267
+ };
268
+ for (let e of this.def.plots) switch (e.kind) {
269
+ case "line":
270
+ A(e) || i(e, e.key, "line", e.col, e.offset ?? 0);
271
+ break;
272
+ case "histogram":
273
+ i(e, e.key, "histogram", e.col, 0);
274
+ break;
275
+ case "area":
276
+ i(e, e.key, "area", e.col, 0);
277
+ break;
278
+ case "band": i(e, `${e.key}:upper`, "line", e.upper, 0), i(e, `${e.key}:lower`, "line", e.lower, 0);
279
+ }
280
+ let a = this.outs[0]?.series;
281
+ if (a) for (let t of this.def.plots) {
282
+ if (t.kind !== "hline") continue;
283
+ let n = typeof t.value == "function" ? t.value(this.params) : t.value, r = e.createPriceLine(a, {
284
+ price: n,
285
+ color: t.color,
286
+ lineStyle: t.style ?? "dashed",
287
+ lineWidth: 1,
288
+ axisLabelVisible: !1
289
+ });
290
+ this.lines.push({
291
+ series: a,
292
+ line: r
293
+ });
294
+ }
295
+ }
296
+ syncAll() {
297
+ let e = this.engine, t = e.length, n = e.graph.time.v;
298
+ for (let r of this.outs) this.writeSeries(r, e.outputs[r.col].v, n, t);
299
+ this.host.api?.requestRender(!0);
300
+ }
301
+ writeSeries(e, t, n, r) {
302
+ let i = e.plot.kind === "histogram" && e.plot.colorDown ? {
303
+ up: E(this.color(e.plot)),
304
+ down: E(e.plot.colorDown)
305
+ } : null, a = 0;
306
+ for (let n = 0; n < r; n++) {
307
+ let i = n + e.offset;
308
+ i >= 0 && i < r && t[n] === t[n] && a++;
309
+ }
310
+ let o = new Float64Array(a), s = new Float64Array(a), c = i ? new Uint32Array(a) : void 0, l = 0;
311
+ for (let a = 0; a < r; a++) {
312
+ let u = a + e.offset;
313
+ u < 0 || u >= r || t[a] !== t[a] || (o[l] = n[u], s[l] = t[a], c && (c[l] = t[a] >= 0 ? i.up : i.down), l++);
314
+ }
315
+ let u = 0;
316
+ for (let e = 0; e < a; e++) u = Math.max(u, Math.abs(s[e]));
317
+ this.widen(u), e.series.setData({
318
+ time: o,
319
+ value: s,
320
+ ...c && { color: c }
321
+ }), e.lastTime = a > 0 ? o[a - 1] : NaN;
322
+ }
323
+ widen(e) {
324
+ if (this.def.pane === "overlay" || this.def.minMove !== void 0 || !(e > 0) || e >= 1) return;
325
+ let t = Math.min(8, 2 - Math.floor(Math.log10(e)));
326
+ if (!(t <= this.decimals)) {
327
+ this.decimals = t;
328
+ for (let e of this.outs) e.series.applyOptions({ priceFormat: {
329
+ type: "price",
330
+ minMove: 10 ** -t
331
+ } });
332
+ }
333
+ }
334
+ seriesOfColumn(e) {
335
+ let t = this.def.columns.indexOf(e);
336
+ return this.outs.find((e) => e.col === t)?.series;
337
+ }
338
+ tickSync() {
339
+ let e = this.engine, t = e.length, n = e.graph.time.v, r = n[t - 1];
340
+ for (let i of this.outs) {
341
+ let a = t - 1 - i.offset;
342
+ if (a < 0) continue;
343
+ let o = e.outputs[i.col].v, s = o[a];
344
+ if (s === s) {
345
+ this.widen(Math.abs(s));
346
+ let e = i.plot.kind === "histogram" && i.plot.colorDown;
347
+ i.series.update({
348
+ time: r,
349
+ value: s,
350
+ ...e && { color: s >= 0 ? this.color(i.plot) : e }
351
+ }), i.lastTime = r;
352
+ } else i.lastTime === r && this.writeSeries(i, o, n, t);
353
+ }
354
+ }
355
+ draw(e, t) {
356
+ if (!this.shown || t.pane !== this.pane) return;
357
+ let n = this.engine, r = n.length;
358
+ if (r === 0) return;
359
+ let i = n.graph.time.v, a = Math.max(0, j(i, r, t.xToTime(0)) - 1), o = Math.min(r, j(i, r, t.xToTime(t.width)) + 2);
360
+ if (o <= a) return;
361
+ let s = Math.max(1, Math.floor((o - a) / (t.width * 2))), c = (e) => t.timeToX(i[e]), l = (e) => t.priceToY(e, this.scaleId), u = (e) => n.outputs[this.def.columns.indexOf(e)].v;
362
+ for (let t of this.def.plots) switch (t.kind) {
363
+ case "band":
364
+ N(e, a, o, s, c, l, u(t.upper), u(t.lower), this.styles[t.key]?.color ?? t.fill, 0);
365
+ break;
366
+ case "fill":
367
+ N(e, a, o, s, c, l, u(t.a), u(t.b), this.styles[t.key]?.color ?? t.color, 0);
368
+ break;
369
+ case "line":
370
+ A(t) && P(e, a, o, s, r, c, l, u(t.col), t.offset ?? 0, !!t.connect, this.color(t), this.styles[t.key]?.width ?? t.width ?? 1.5);
371
+ break;
372
+ case "markers":
373
+ this.drawMarkers(e, t, a, o, c, l, u(t.col), r);
374
+ break;
375
+ case "zigzag": F(e, a, o, c, l, u(t.price), u(t.back), i, this.color(t), t.width ?? 1.5);
376
+ }
377
+ }
378
+ drawMarkers(e, t, n, r, i, a, o, s) {
379
+ let c = t.offset ?? 0, l = this.engine.graph.high.v, u = this.engine.graph.low.v, d = this.color(t);
380
+ e.save(), e.fillStyle = d, e.strokeStyle = d, e.font = "10px system-ui, sans-serif", e.textAlign = "center";
381
+ let f = 0;
382
+ for (let d = n; d < r && f < 4e3; d++) {
383
+ let n = o[d];
384
+ if (n !== n || t.text && n === 0) continue;
385
+ let r = d + c;
386
+ if (r < 0 || r >= s) continue;
387
+ let p = i(r), m = t.position === "sign" ? n > 0 ? "below" : "above" : t.position, h, g;
388
+ m === "value" ? (h = a(n), g = 1) : m === "above" ? (h = a(l[r]) - 8, g = -1) : (h = a(u[r]) + 8, g = 1), t.text ? (e.textBaseline = g < 0 ? "bottom" : "top", e.fillText(String(Math.round(n)), p, m === "above" ? h - 2 : h + 2)) : I(e, t.shape, p, h, m === "above" ? -1 : 1), f++;
389
+ }
390
+ e.restore();
391
+ }
392
+ };
393
+ function A(e) {
394
+ return (e.offset ?? 0) < 0 || !!e.connect;
395
+ }
396
+ function j(e, t, n) {
397
+ let r = 0, i = t;
398
+ for (; r < i;) {
399
+ let t = r + i >>> 1;
400
+ e[t] < n ? r = t + 1 : i = t;
401
+ }
402
+ return r;
403
+ }
404
+ function M(e, t) {
405
+ let n = E(e);
406
+ return T((n & 4294967040 | Math.round(t * 255)) >>> 0);
407
+ }
408
+ function N(e, t, n, r, i, a, o, s, c, l) {
409
+ e.save(), e.fillStyle = c;
410
+ let u = [], d = () => {
411
+ if (u.length > 1) {
412
+ e.beginPath(), e.moveTo(i(u[0]), a(o[u[0]]));
413
+ for (let t = 1; t < u.length; t++) e.lineTo(i(u[t]), a(o[u[t]]));
414
+ for (let t = u.length - 1; t >= 0; t--) e.lineTo(i(u[t]), a(s[u[t]]));
415
+ e.closePath(), e.fill();
416
+ }
417
+ u = [];
418
+ };
419
+ for (let e = t; e < n; e += r) o[e] === o[e] && s[e] === s[e] ? u.push(e) : d();
420
+ d(), e.restore();
421
+ }
422
+ function P(e, t, n, r, i, a, o, s, c, l, u, d) {
423
+ e.save(), e.strokeStyle = u, e.lineWidth = d, e.beginPath();
424
+ let f = !1;
425
+ for (let u = t; u < n; u += r) {
426
+ let t = s[u], n = u + c;
427
+ t !== t || n < 0 || n >= i ? l || (f = !1) : (f ? e.lineTo(a(n), o(t)) : e.moveTo(a(n), o(t)), f = !0);
428
+ }
429
+ e.stroke(), e.restore();
430
+ }
431
+ function F(e, t, n, r, i, a, o, s, c, l) {
432
+ e.save(), e.strokeStyle = c, e.lineWidth = l, e.beginPath();
433
+ let u = !1;
434
+ for (let s = Math.max(0, t - 2e3); s < n; s++) {
435
+ let t = a[s];
436
+ if (t !== t) continue;
437
+ let n = s - o[s];
438
+ u ? e.lineTo(r(n), i(t)) : e.moveTo(r(n), i(t)), u = !0;
439
+ }
440
+ e.stroke(), e.restore();
441
+ }
442
+ function I(e, t, n, r, i) {
443
+ switch (e.beginPath(), t) {
444
+ case "square":
445
+ e.rect(n - 4, r - 4, 8, 8), e.fill();
446
+ return;
447
+ case "diamond":
448
+ e.moveTo(n, r - 4 - 1), e.lineTo(n + 4 + 1, r), e.lineTo(n, r + 4 + 1), e.lineTo(n - 4 - 1, r), e.closePath(), e.fill();
449
+ return;
450
+ case "triangleUp":
451
+ case "arrowUp":
452
+ e.moveTo(n, r - 4), e.lineTo(n + 4, r + 4), e.lineTo(n - 4, r + 4), e.closePath(), e.fill();
453
+ return;
454
+ case "triangleDown":
455
+ case "arrowDown":
456
+ e.moveTo(n, r + 4), e.lineTo(n + 4, r - 4), e.lineTo(n - 4, r - 4), e.closePath(), e.fill();
457
+ return;
458
+ case "cross":
459
+ e.moveTo(n - 4, r - 4), e.lineTo(n + 4, r + 4), e.moveTo(n + 4, r - 4), e.lineTo(n - 4, r + 4), e.stroke();
460
+ return;
461
+ default: e.arc(n, r, 3, 0, Math.PI * 2), e.fill();
462
+ }
463
+ }
464
+ var L = class {
465
+ chart;
466
+ runner;
467
+ resolve;
468
+ id = O;
469
+ api = null;
470
+ studies = /* @__PURE__ */ new Map();
471
+ counter = 0;
472
+ constructor(e, t, n) {
473
+ this.chart = e, this.runner = t, this.resolve = n;
474
+ }
475
+ install(e) {
476
+ this.api = e;
477
+ }
478
+ uninstall() {
479
+ for (let e of [...this.studies.values()]) e.dispose(this.chart);
480
+ this.studies.clear(), this.api = null;
481
+ }
482
+ dataChanged(e) {
483
+ for (let t of this.studies.values()) t.onChange(e);
484
+ this.reap();
485
+ }
486
+ drawPane(e, t) {
487
+ for (let n of this.studies.values()) n.draw(e, t);
488
+ }
489
+ list() {
490
+ return [...this.studies.values()];
491
+ }
492
+ get(e) {
493
+ return this.studies.get(e);
494
+ }
495
+ changed() {
496
+ this.api?.requestRender(!0);
497
+ }
498
+ freePane() {
499
+ let e = new Set(this.chart.series().map((e) => e.options().pane)), t = 1;
500
+ for (; e.has(t);) t++;
501
+ return t;
502
+ }
503
+ add(e, t, n, r = {}, i) {
504
+ let a = r.id ?? this.nextId();
505
+ if (this.studies.has(a)) throw Error(`alphacharts: a study with id "${a}" already exists`);
506
+ let o = /^s(\d+)$/.exec(a);
507
+ o && (this.counter = Math.max(this.counter, Number(o[1])));
508
+ let s = new k(this, a, e, t, n, r.volume, i, r.runner, r.onDispose);
509
+ return s.persist = r.persist !== !1, this.studies.set(a, s), s;
510
+ }
511
+ removeStudy(e) {
512
+ let t = this.studies.get(e);
513
+ t && (this.studies.delete(e), t.dispose(this.chart), this.changed());
514
+ }
515
+ reap() {
516
+ let e = new Set(this.chart.series().map((e) => e.data));
517
+ for (let [t, n] of this.studies) {
518
+ let r = n;
519
+ (!e.has(r.source.data) || r.volume && !e.has(r.volume.data)) && (this.studies.delete(t), n.dispose(this.chart));
520
+ }
521
+ }
522
+ reserveIds(e) {
523
+ this.counter = Math.max(this.counter, e);
524
+ }
525
+ idHighWater() {
526
+ return this.counter;
527
+ }
528
+ nextId() {
529
+ return `s${++this.counter}`;
530
+ }
531
+ toJSON() {
532
+ return {
533
+ version: 1,
534
+ studies: [...this.studies.values()].filter((e) => e.persist).map((e) => e.state())
535
+ };
536
+ }
537
+ validateState(e, t) {
538
+ let n = e;
539
+ if (n?.version !== 1 || !Array.isArray(n.studies)) throw TypeError("alphacharts studies: unrecognised layout state");
540
+ let r = /* @__PURE__ */ new Set();
541
+ for (let e of n.studies) {
542
+ if (r.has(e.id)) throw Error(`alphacharts studies: the layout repeats study id "${e.id}"`);
543
+ if (r.add(e.id), !t.seriesIds.includes(e.source)) throw Error(`alphacharts studies: study "${e.id}" needs series "${e.source}", which the layout does not contain`);
544
+ if (e.volume && !t.seriesIds.includes(e.volume)) throw Error(`alphacharts studies: study "${e.id}" needs volume series "${e.volume}"`);
545
+ s(this.resolve(e.study), e.inputs);
546
+ }
547
+ }
548
+ fromJSON(e) {
549
+ let t = e;
550
+ if (t?.version !== 1 || !Array.isArray(t.studies)) throw TypeError("alphacharts studies: unrecognised layout state");
551
+ for (let e of this.studies.values()) e.drop();
552
+ this.studies.clear();
553
+ let n = new Map(this.chart.series().map((e) => [e.options().id, e]));
554
+ for (let e of t.studies) {
555
+ let t = n.get(e.source);
556
+ if (!t) throw Error(`alphacharts studies: study "${e.id}" needs series "${e.source}", which the layout does not contain`);
557
+ let r = e.volume ? n.get(e.volume) : void 0;
558
+ if (e.volume && !r) throw Error(`alphacharts studies: study "${e.id}" needs volume series "${e.volume}"`);
559
+ for (let t of [...n.values()]) t.options().id.startsWith(`study:${e.id}:`) && this.chart.removeSeries(t);
560
+ this.add(this.resolve(e.study), e.inputs, t, {
561
+ id: e.id,
562
+ ...r && { volume: r }
563
+ }, {
564
+ visible: e.visible,
565
+ styles: e.styles
566
+ });
567
+ }
568
+ let r = new Set([...this.studies.values()].flatMap((e) => e.series()));
569
+ for (let e of this.chart.series()) e.options().id.startsWith("study:") && !r.has(e) && this.chart.removeSeries(e);
570
+ }
571
+ };
572
+ function R(e, t = {}) {
573
+ let n = e.plugin(O);
574
+ if (n) return n;
575
+ let r = new L(e, t.runner, t.resolve ?? y);
576
+ return e.addPlugin(r), r;
577
+ }
578
+ function z(e, t, n, r = {}, i = {}) {
579
+ let a = typeof n == "string" ? y(n) : n;
580
+ return R(e, i.runner ? { runner: i.runner } : {}).add(a, r, t, i);
581
+ }
582
+ //#endregion
583
+ //#region src/wasm.ts
584
+ async function B() {
585
+ a(await D());
586
+ }
587
+ function V() {
588
+ a(null);
589
+ }
590
+ //#endregion
591
+ export { m as CHUNK, u as CancelledError, i as Col, n as Graph, f as InlineRunner, t as Node, O as PLUGIN_ID, e as SOURCE_NAMES, L as StudiesPlugin, k as Study, p as StudyEngine, c as WorkerRunner, z as addStudy, o as createRunner, r as defineStudy, V as disableWasm, B as enableWasm, y as getStudy, R as installStudies, _ as listStudies, v as registerStudies, g as registerStudy, s as resolveParams, l as runStudy, d as serveWorker, a as setKernels, h as validateDef };
592
+
593
+ //# sourceMappingURL=index.js.map