@alphacharts/indicators 0.1.0 → 0.1.1

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/dist/index.js CHANGED
@@ -1,10 +1,21 @@
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";
1
+ import { S as e, _ as t, b as n, g as r, h as i, i as a, m as o, v as s, x as c, y as l } from "./define-XUgQMhSl.js";
2
+ import { a as u, c as d, i as f, l as p, n as m, o as h, r as g, s as _, t as v } from "./runner-B53M0IsJ.js";
3
+ import { a as y, i as b, n as x, r as S, t as C } from "./registry-DdYYyZN_.js";
4
+ import { BarShading as w, COL_C as T, COL_H as E, COL_L as D, COL_O as O, COL_V as k, cssColor as A, parseColor as j } from "@alphacharts/core";
5
+ import { loadKernels as M } from "@alphacharts/wasm";
6
+ //#region src/chart/marker-floor.ts
7
+ var N = (e, t) => e !== void 0 && e === e && !(t && e === 0);
8
+ function P(e, t, n) {
9
+ let r = n.within === void 0 ? 0 : Math.max(0, t - n.within);
10
+ if (n.last !== void 0) {
11
+ let i = 0;
12
+ for (let a = t - 1; a >= r; a--) if (N(e[a], !!n.text) && ++i === n.last) return a;
13
+ }
14
+ return r;
15
+ }
16
+ //#endregion
6
17
  //#region src/chart/studies.ts
7
- var O = "alphacharts.studies", k = class {
18
+ var F = "alphacharts.studies", I = class {
8
19
  host;
9
20
  id;
10
21
  source;
@@ -16,6 +27,9 @@ var O = "alphacharts.studies", k = class {
16
27
  engine;
17
28
  outs = [];
18
29
  lines = [];
30
+ shades = [];
31
+ feeds = /* @__PURE__ */ new Map();
32
+ sameScale = !0;
19
33
  styles = {};
20
34
  shown = !0;
21
35
  pane = 0;
@@ -29,8 +43,8 @@ var O = "alphacharts.studies", k = class {
29
43
  disposed = !1;
30
44
  decimals = 2;
31
45
  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();
46
+ constructor(e, t, n, r, i, a, o, s, c) {
47
+ this.host = e, this.id = t, this.source = i, this.volume = a, this.ownRunner = s, this.onDispose = c, this.def = n, this.params = d(n, r), this.engine = new _(n, this.params), this.checkSource(), o?.styles && (this.styles = { ...o.styles }), o?.visible === !1 && (this.shown = !1), this.createSeries(), this.recompute();
34
48
  }
35
49
  inputs() {
36
50
  return this.params;
@@ -47,25 +61,32 @@ var O = "alphacharts.studies", k = class {
47
61
  series() {
48
62
  return this.outs.map((e) => e.series);
49
63
  }
50
- setInputs(e) {
51
- let t = s(this.def, {
52
- ...this.params,
64
+ setInputs(e, t = []) {
65
+ let n = { ...this.params };
66
+ for (let e of t) delete n[e];
67
+ let r = d(this.def, {
68
+ ...n,
53
69
  ...e
54
- }), n = new p(this.def, t);
55
- this.params = t, this.engine = n, this.retitle(), this.recompute(), this.host.changed();
70
+ });
71
+ for (let e of this.def.plots) if (e.kind === "line" && typeof e.offset == "function" && R(e, this.params) !== R(e, r)) throw TypeError(`${e.title}: this input would move its line between the pane and the overlay; add the study again`);
72
+ let i = new _(this.def, r);
73
+ this.params = r;
74
+ for (let e of this.outs) e.plot.kind === "line" && (e.offset = L(e.plot, r));
75
+ this.engine = i, this.retitle(), this.recompute(), this.host.changed();
56
76
  }
57
77
  setVisible(e) {
58
78
  this.shown = e;
59
79
  for (let t of this.outs) t.series.applyOptions({ visible: e });
60
- this.host.changed();
80
+ for (let t of this.shades) t.prim.setVisible(e);
81
+ this.hasBarColor() && this.host.syncBarColors(this.source), this.host.changed();
61
82
  }
62
83
  setStyle(e, t) {
63
- t.color !== void 0 && E(t.color), this.styles[e] = {
84
+ t.color !== void 0 && j(t.color), this.styles[e] = {
64
85
  ...this.styles[e],
65
86
  ...t
66
87
  };
67
88
  for (let t of this.outs) t.key.split(":")[0] === e && t.series.applyOptions(this.seriesOptions(t.plot, t.key));
68
- this.host.changed();
89
+ !this.job && this.engine.length > 0 && (this.shades.length > 0 || this.hasBarColor()) && this.syncOverlays(), this.host.changed();
69
90
  }
70
91
  remove() {
71
92
  this.host.removeStudy(this.id);
@@ -102,8 +123,62 @@ var O = "alphacharts.studies", k = class {
102
123
  dispose(e) {
103
124
  this.drop();
104
125
  for (let { series: t, line: n } of this.lines) e.removePriceLine(t, n);
126
+ for (let e of this.shades) e.anchor.detachPrimitive(e.prim);
105
127
  for (let t of this.outs) e.removeSeries(t.series);
106
- this.outs = [], this.lines = [];
128
+ this.outs = [], this.lines = [], this.shades = [];
129
+ }
130
+ setFeed(e, t, r) {
131
+ let i = this.feeds.get(e);
132
+ i || this.feeds.set(e, i = new n()), i.load(t, r, `outside series ${e}`), this.recompute(), this.host.changed();
133
+ }
134
+ feedKeys() {
135
+ return [...this.feeds.keys()];
136
+ }
137
+ pushFeedBar(e, t) {
138
+ let n = this.feeds.get(e);
139
+ if (!n) throw RangeError(`${this.def.id}: no outside series "${e}"; give it with setFeed first`);
140
+ if (n.apply(t, `outside series ${e}`), this.disposed || this.error) return;
141
+ if (this.job) {
142
+ this.structural = !0;
143
+ return;
144
+ }
145
+ let r = this.ownRunner ?? this.host.runner;
146
+ r?.canRun(this.def) ? r.feedBar?.(this.def, e, t) : this.engine.pushFeed(e, t) && (this.tickSync(), this.host.api?.requestRender());
147
+ }
148
+ hasBarColor() {
149
+ return this.def.plots.some((e) => e.kind === "barcolor");
150
+ }
151
+ barColorSource() {
152
+ return this.source;
153
+ }
154
+ barColorAt(e) {
155
+ let t = this.engine, n = 0;
156
+ if (e < 0) return n;
157
+ for (let r of this.def.plots) {
158
+ if (r.kind !== "barcolor") continue;
159
+ let i = t.outputs[this.def.columns.indexOf(r.col)].v[e];
160
+ i === i && i !== 0 && (n = j(this.color(r)));
161
+ }
162
+ return n;
163
+ }
164
+ barColors() {
165
+ let e = this.engine.length, t = new Uint32Array(e);
166
+ for (let n = 0; n < e; n++) t[n] = this.barColorAt(n);
167
+ return {
168
+ time: this.engine.graph.time.v.slice(0, e),
169
+ color: t
170
+ };
171
+ }
172
+ rowOf(e) {
173
+ let t = this.engine.length;
174
+ return t > 0 && this.engine.graph.time.v[t - 1] === e ? t - 1 : -1;
175
+ }
176
+ lastTime() {
177
+ let e = this.engine.length;
178
+ return e > 0 ? this.engine.graph.time.v[e - 1] : NaN;
179
+ }
180
+ get isShown() {
181
+ return this.shown && !this.error && !this.disposed;
107
182
  }
108
183
  get ohlc() {
109
184
  return this.source.data.shape === "ohlc";
@@ -115,6 +190,7 @@ var O = "alphacharts.studies", k = class {
115
190
  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
191
  }
117
192
  if (e === "ohlcv" && !this.volume) throw TypeError(`${this.def.id} needs volume: pass the volume series as options.volume`);
193
+ if (!this.ohlc && this.def.plots.some((e) => e.kind === "barcolor")) throw TypeError(`${this.def.id} colours bars; the source series holds single values, not candles or bars`);
118
194
  }
119
195
  watches(e) {
120
196
  return e === this.source.data ? "source" : this.volume && e === this.volume.data ? "volume" : null;
@@ -123,7 +199,7 @@ var O = "alphacharts.studies", k = class {
123
199
  let e = this.host.chart, t = this.source.data, n = t.store, r = 0;
124
200
  for (let e = n.first; e < n.end; e++) t.has(e) && r++;
125
201
  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++);
202
+ for (let r = n.first; r < n.end; r++) t.has(r) && (i[d] = e.logicalToTime(r), o ? (s[d] = t.get(r, O), c[d] = t.get(r, E), l[d] = t.get(r, D), a[d] = t.get(r, T)) : a[d] = t.get(r, k), u && (u[d] = this.volume.data.get(r, k)), d++);
127
203
  return {
128
204
  time: i,
129
205
  close: a,
@@ -139,15 +215,15 @@ var O = "alphacharts.studies", k = class {
139
215
  let t = this.source.data, n = NaN;
140
216
  return {
141
217
  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
218
+ open: this.ohlc ? t.get(e, O) : n,
219
+ high: this.ohlc ? t.get(e, E) : n,
220
+ low: this.ohlc ? t.get(e, D) : n,
221
+ close: this.ohlc ? t.get(e, T) : t.get(e, k),
222
+ volume: this.volume ? this.volume.data.get(e, k) : n
147
223
  };
148
224
  }
149
225
  onChange(e) {
150
- if (this.disposed || this.error) return;
226
+ if (this.disposed || this.error || e.kind === "color") return;
151
227
  let t = this.watches(e.series);
152
228
  if (e.series === null || !t) return;
153
229
  if (this.job) {
@@ -172,24 +248,30 @@ var O = "alphacharts.studies", k = class {
172
248
  this.version++, this.job?.cancel(), this.job = null, this.dirty = !1, this.structural = !1, this.error = null;
173
249
  let e = this.bars(), t = this.ownRunner ?? this.host.runner;
174
250
  if (!t || !t.canRun(this.def)) {
251
+ for (let [e, t] of this.feeds) this.engine.setFeed(e, t.snapshot(), t);
175
252
  this.engine.load(e), this.syncAll(), this.ready_ = Promise.resolve();
176
253
  return;
177
254
  }
178
- let n = this.version, r = t.run(this.def, {
255
+ let n = this.version, r = this.feeds.size > 0 ? Object.fromEntries([...this.feeds].map(([e, t]) => [e, {
256
+ align: t.align,
257
+ spanMs: t.spanMs,
258
+ bars: t.snapshot()
259
+ }])) : void 0, i = t.run(this.def, {
179
260
  studyId: this.def.id,
180
261
  params: this.params,
181
- bars: e
262
+ bars: e,
263
+ ...r && { feeds: r }
182
264
  });
183
- this.job = r, this.ready_ = r.promise.then((e) => {
265
+ this.job = i, this.ready_ = i.promise.then((e) => {
184
266
  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
267
  }, (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;
268
+ if (!(e instanceof m || n !== this.version || this.disposed)) throw this.job = null, this.error = e instanceof Error ? e : Error(String(e)), this.error;
187
269
  });
188
270
  }
189
271
  catchUp() {
190
272
  let e = this.engine, t = this.bars(), n = t.time.length;
191
273
  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) => ({
274
+ let r = e.graph.time.v[e.length - 1], i = z(t.time, n, r), a = (e) => ({
193
275
  time: t.time[e],
194
276
  open: t.open?.[e] ?? NaN,
195
277
  high: t.high?.[e] ?? NaN,
@@ -230,8 +312,8 @@ var O = "alphacharts.studies", k = class {
230
312
  let t = r ?? e.color;
231
313
  return {
232
314
  lineColor: t,
233
- topColor: M(t, .28),
234
- bottomColor: M(t, .02),
315
+ topColor: B(t, .28),
316
+ bottomColor: B(t, .02),
235
317
  lineWidth: n?.width ?? 1.5
236
318
  };
237
319
  }
@@ -240,34 +322,36 @@ var O = "alphacharts.studies", k = class {
240
322
  }
241
323
  createSeries() {
242
324
  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}`,
325
+ this.def.pane === "overlay" ? (this.pane = t.pane, this.scaleId = this.def.scale ?? t.priceScaleId) : (this.pane = this.host.freePane(), this.scaleId = this.def.scale ?? "right");
326
+ let n = this.def.pane === "overlay";
327
+ this.sameScale = n && this.scaleId === t.priceScaleId;
328
+ let r = this.def.columns, i = (n, i, a, o, s) => {
329
+ let c = e.addSeries(a, {
330
+ id: `study:${this.id}:${i}`,
247
331
  pane: this.pane,
248
332
  priceScaleId: this.scaleId,
249
- title: this.outs.length === 0 ? this.title() : i.title,
250
- lastValueVisible: !n,
333
+ title: this.outs.length === 0 ? this.title() : n.title,
334
+ lastValueVisible: !this.sameScale,
251
335
  priceLineVisible: !1,
252
336
  visible: this.shown,
253
- ...this.seriesOptions(i, a),
254
- priceFormat: n ? t.priceFormat : {
337
+ ...this.seriesOptions(n, i),
338
+ priceFormat: this.sameScale ? t.priceFormat : {
255
339
  type: "price",
256
340
  minMove: this.def.minMove ?? 10 ** -this.decimals
257
341
  }
258
342
  });
259
343
  this.outs.push({
260
- plot: i,
261
- key: a,
262
- col: r.indexOf(s),
263
- series: l,
264
- offset: c,
344
+ plot: n,
345
+ key: i,
346
+ col: r.indexOf(o),
347
+ series: c,
348
+ offset: s,
265
349
  lastTime: NaN
266
350
  });
267
351
  };
268
352
  for (let e of this.def.plots) switch (e.kind) {
269
353
  case "line":
270
- A(e) || i(e, e.key, "line", e.col, e.offset ?? 0);
354
+ R(e, this.params) || i(e, e.key, "line", e.col, L(e, this.params));
271
355
  break;
272
356
  case "histogram":
273
357
  i(e, e.key, "histogram", e.col, 0);
@@ -278,6 +362,18 @@ var O = "alphacharts.studies", k = class {
278
362
  case "band": i(e, `${e.key}:upper`, "line", e.upper, 0), i(e, `${e.key}:lower`, "line", e.lower, 0);
279
363
  }
280
364
  let a = this.outs[0]?.series;
365
+ for (let e of this.def.plots) {
366
+ if (e.kind !== "bgcolor") continue;
367
+ let t = n ? this.source : a;
368
+ if (!t) throw TypeError(`${this.def.id}: bgcolor shades the study's pane, and a study in its own pane needs a plot to hold it`);
369
+ let i = new w();
370
+ i.setVisible(this.shown), t.attachPrimitive(i), this.shades.push({
371
+ plot: e,
372
+ col: r.indexOf(e.col),
373
+ prim: i,
374
+ anchor: t
375
+ });
376
+ }
281
377
  if (a) for (let t of this.def.plots) {
282
378
  if (t.kind !== "hline") continue;
283
379
  let n = typeof t.value == "function" ? t.value(this.params) : t.value, r = e.createPriceLine(a, {
@@ -296,32 +392,44 @@ var O = "alphacharts.studies", k = class {
296
392
  syncAll() {
297
393
  let e = this.engine, t = e.length, n = e.graph.time.v;
298
394
  for (let r of this.outs) this.writeSeries(r, e.outputs[r.col].v, n, t);
299
- this.host.api?.requestRender(!0);
395
+ this.syncOverlays(), this.host.api?.requestRender(!0);
396
+ }
397
+ syncOverlays() {
398
+ let e = this.engine, t = e.length, n = e.graph.time.v;
399
+ for (let r of this.shades) {
400
+ let i = e.outputs[r.col].v, a = j(this.color(r.plot)), o = new Uint32Array(t);
401
+ for (let e = 0; e < t; e++) o[e] = i[e] === i[e] && i[e] !== 0 ? a : 0;
402
+ r.prim.set(n.slice(0, t), o);
403
+ }
404
+ this.hasBarColor() && this.host.syncBarColors(this.source);
300
405
  }
301
406
  writeSeries(e, t, n, r) {
302
407
  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;
408
+ up: j(this.color(e.plot)),
409
+ down: j(e.plot.colorDown)
410
+ } : null, a = e.plot.kind === "line" && e.plot.colorBy ? {
411
+ col: this.engine.outputs[this.def.columns.indexOf(e.plot.colorBy.col)].v,
412
+ color: j(e.plot.colorBy.color)
413
+ } : null, o = 0;
306
414
  for (let n = 0; n < r; n++) {
307
415
  let i = n + e.offset;
308
- i >= 0 && i < r && t[n] === t[n] && a++;
416
+ i >= 0 && i < r && t[n] === t[n] && o++;
309
417
  }
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++);
418
+ let s = new Float64Array(o), c = new Float64Array(o), l = i || a ? new Uint32Array(o) : void 0, u = 0;
419
+ for (let o = 0; o < r; o++) {
420
+ let d = o + e.offset;
421
+ d < 0 || d >= r || t[o] !== t[o] || (s[u] = n[d], c[u] = t[o], i ? l[u] = t[o] >= 0 ? i.up : i.down : a && (l[u] = a.col[o] === a.col[o] && a.col[o] !== 0 ? a.color : 0), u++);
314
422
  }
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;
423
+ let d = 0;
424
+ for (let e = 0; e < o; e++) d = Math.max(d, Math.abs(c[e]));
425
+ this.widen(d), e.series.setData({
426
+ time: s,
427
+ value: c,
428
+ ...l && { color: l }
429
+ }), e.lastTime = o > 0 ? s[o - 1] : NaN;
322
430
  }
323
431
  widen(e) {
324
- if (this.def.pane === "overlay" || this.def.minMove !== void 0 || !(e > 0) || e >= 1) return;
432
+ if (this.sameScale || this.def.minMove !== void 0 || !(e > 0) || e >= 1) return;
325
433
  let t = Math.min(8, 2 - Math.floor(Math.log10(e)));
326
434
  if (!(t <= this.decimals)) {
327
435
  this.decimals = t;
@@ -336,64 +444,73 @@ var O = "alphacharts.studies", k = class {
336
444
  return this.outs.find((e) => e.col === t)?.series;
337
445
  }
338
446
  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({
447
+ let e = this.engine, t = e.length, n = e.graph.time.v, r = n[t - 1], i = this.def.columns;
448
+ for (let n of this.shades) {
449
+ let i = e.outputs[n.col].v[t - 1];
450
+ n.prim.setAt(r, i === i && i !== 0 ? j(this.color(n.plot)) : 0);
451
+ }
452
+ this.hasBarColor() && this.host.syncBarColors(this.source, !0);
453
+ for (let a of this.outs) {
454
+ let o = t - 1 - a.offset;
455
+ if (o < 0) continue;
456
+ let s = e.outputs[a.col].v, c = s[o];
457
+ if (c === c) {
458
+ this.widen(Math.abs(c));
459
+ let t = a.plot.kind === "histogram" && a.plot.colorDown, n = a.plot.kind === "line" ? a.plot.colorBy : void 0, s = n ? e.outputs[i.indexOf(n.col)].v[o] : NaN, l = n && s === s && s !== 0 ? n.color : void 0;
460
+ a.series.update({
348
461
  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);
462
+ value: c,
463
+ ...t && { color: c >= 0 ? this.color(a.plot) : t },
464
+ ...l && { color: l }
465
+ }), a.lastTime = r;
466
+ } else a.lastTime === r && this.writeSeries(a, s, n, t);
353
467
  }
354
468
  }
355
469
  draw(e, t) {
356
470
  if (!this.shown || t.pane !== this.pane) return;
357
471
  let n = this.engine, r = n.length;
358
472
  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);
473
+ let i = n.graph.time.v, a = Math.max(0, z(i, r, t.xToTime(0)) - 1), o = Math.min(r, z(i, r, t.xToTime(t.width)) + 2);
360
474
  if (o <= a) return;
361
475
  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
476
  for (let t of this.def.plots) switch (t.kind) {
363
477
  case "band":
364
- N(e, a, o, s, c, l, u(t.upper), u(t.lower), this.styles[t.key]?.color ?? t.fill, 0);
478
+ V(e, a, o, s, c, l, u(t.upper), u(t.lower), this.styles[t.key]?.color ?? t.fill, 0);
365
479
  break;
366
480
  case "fill":
367
- N(e, a, o, s, c, l, u(t.a), u(t.b), this.styles[t.key]?.color ?? t.color, 0);
481
+ V(e, a, o, s, c, l, u(t.a), u(t.b), this.styles[t.key]?.color ?? t.color, 0);
368
482
  break;
369
483
  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);
484
+ R(t, this.params) && H(e, a, o, s, r, c, l, u(t.col), L(t, this.params), !!t.connect, this.color(t), this.styles[t.key]?.width ?? t.width ?? 1.5);
371
485
  break;
372
486
  case "markers":
373
487
  this.drawMarkers(e, t, a, o, c, l, u(t.col), r);
374
488
  break;
375
- case "zigzag": F(e, a, o, c, l, u(t.price), u(t.back), i, this.color(t), t.width ?? 1.5);
489
+ case "zigzag": U(e, a, o, c, l, u(t.price), u(t.back), i, this.color(t), t.width ?? 1.5);
376
490
  }
377
491
  }
378
492
  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);
493
+ let c = L(t, this.params), l = this.engine.graph.high.v, u = this.engine.graph.low.v, d = this.color(t);
380
494
  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++;
495
+ let f = 0, p = Math.max(n, P(o, s, t));
496
+ for (let n = p; n < r && f < 4e3; n++) {
497
+ let r = o[n];
498
+ if (r !== r || t.text && r === 0) continue;
499
+ let d = n + c;
500
+ if (d < 0 || d >= s) continue;
501
+ let p = i(d), m = t.position === "sign" ? r > 0 ? "below" : "above" : t.position, h, g;
502
+ m === "value" ? (h = a(r), g = 1) : m === "above" ? (h = a(l[d]) - 8, g = -1) : (h = a(u[d]) + 8, g = 1), t.text ? (e.textBaseline = g < 0 ? "bottom" : "top", e.fillText(String(Math.round(r)), p, m === "above" ? h - 2 : h + 2)) : W(e, t.shape, p, h, m === "above" ? -1 : 1), f++;
389
503
  }
390
504
  e.restore();
391
505
  }
392
506
  };
393
- function A(e) {
394
- return (e.offset ?? 0) < 0 || !!e.connect;
507
+ function L(e, t) {
508
+ return typeof e.offset == "function" ? e.offset(t) : e.offset ?? 0;
509
+ }
510
+ function R(e, t) {
511
+ return L(e, t) < 0 || !!e.connect;
395
512
  }
396
- function j(e, t, n) {
513
+ function z(e, t, n) {
397
514
  let r = 0, i = t;
398
515
  for (; r < i;) {
399
516
  let t = r + i >>> 1;
@@ -401,11 +518,11 @@ function j(e, t, n) {
401
518
  }
402
519
  return r;
403
520
  }
404
- function M(e, t) {
405
- let n = E(e);
406
- return T((n & 4294967040 | Math.round(t * 255)) >>> 0);
521
+ function B(e, t) {
522
+ let n = j(e);
523
+ return A((n & 4294967040 | Math.round(t * 255)) >>> 0);
407
524
  }
408
- function N(e, t, n, r, i, a, o, s, c, l) {
525
+ function V(e, t, n, r, i, a, o, s, c, l) {
409
526
  e.save(), e.fillStyle = c;
410
527
  let u = [], d = () => {
411
528
  if (u.length > 1) {
@@ -419,7 +536,7 @@ function N(e, t, n, r, i, a, o, s, c, l) {
419
536
  for (let e = t; e < n; e += r) o[e] === o[e] && s[e] === s[e] ? u.push(e) : d();
420
537
  d(), e.restore();
421
538
  }
422
- function P(e, t, n, r, i, a, o, s, c, l, u, d) {
539
+ function H(e, t, n, r, i, a, o, s, c, l, u, d) {
423
540
  e.save(), e.strokeStyle = u, e.lineWidth = d, e.beginPath();
424
541
  let f = !1;
425
542
  for (let u = t; u < n; u += r) {
@@ -428,7 +545,7 @@ function P(e, t, n, r, i, a, o, s, c, l, u, d) {
428
545
  }
429
546
  e.stroke(), e.restore();
430
547
  }
431
- function F(e, t, n, r, i, a, o, s, c, l) {
548
+ function U(e, t, n, r, i, a, o, s, c, l) {
432
549
  e.save(), e.strokeStyle = c, e.lineWidth = l, e.beginPath();
433
550
  let u = !1;
434
551
  for (let s = Math.max(0, t - 2e3); s < n; s++) {
@@ -439,7 +556,7 @@ function F(e, t, n, r, i, a, o, s, c, l) {
439
556
  }
440
557
  e.stroke(), e.restore();
441
558
  }
442
- function I(e, t, n, r, i) {
559
+ function W(e, t, n, r, i) {
443
560
  switch (e.beginPath(), t) {
444
561
  case "square":
445
562
  e.rect(n - 4, r - 4, 8, 8), e.fill();
@@ -461,14 +578,15 @@ function I(e, t, n, r, i) {
461
578
  default: e.arc(n, r, 3, 0, Math.PI * 2), e.fill();
462
579
  }
463
580
  }
464
- var L = class {
581
+ var G = class {
465
582
  chart;
466
583
  runner;
467
584
  resolve;
468
- id = O;
585
+ id = F;
469
586
  api = null;
470
587
  studies = /* @__PURE__ */ new Map();
471
588
  counter = 0;
589
+ coloured = /* @__PURE__ */ new Set();
472
590
  constructor(e, t, n) {
473
591
  this.chart = e, this.runner = t, this.resolve = n;
474
592
  }
@@ -476,8 +594,41 @@ var L = class {
476
594
  this.api = e;
477
595
  }
478
596
  uninstall() {
597
+ let e = [...this.coloured];
479
598
  for (let e of [...this.studies.values()]) e.dispose(this.chart);
480
- this.studies.clear(), this.api = null;
599
+ this.studies.clear();
600
+ for (let t of e) this.syncBarColors(t);
601
+ this.api = null;
602
+ }
603
+ syncBarColors(e, t = !1) {
604
+ let n = [...this.studies.values()].filter((t) => t.barColorSource() === e && t.hasBarColor() && t.isShown), r = e;
605
+ if (n.length === 0) {
606
+ this.coloured.delete(e) && r.clearBarColors();
607
+ return;
608
+ }
609
+ if (this.coloured.add(e), t) {
610
+ let e = n[0].lastTime();
611
+ if (e !== e) return;
612
+ let t = 0;
613
+ for (let r of n) r.lastTime() === e && (t = r.barColorAt(r.rowOf(e)) || t);
614
+ r.setBarColors({
615
+ time: Float64Array.of(e),
616
+ color: Uint32Array.of(t)
617
+ });
618
+ return;
619
+ }
620
+ let i = n[0].barColors(), a = i.time, o = i.color;
621
+ for (let e = 1; e < n.length; e++) {
622
+ let t = n[e].barColors(), r = 0;
623
+ for (let e = 0; e < t.time.length; e++) {
624
+ for (; r < a.length && a[r] < t.time[e];) r++;
625
+ r < a.length && a[r] === t.time[e] && t.color[e] !== 0 && (o[r] = t.color[e]);
626
+ }
627
+ }
628
+ r.setBarColors({
629
+ time: a,
630
+ color: o
631
+ });
481
632
  }
482
633
  dataChanged(e) {
483
634
  for (let t of this.studies.values()) t.onChange(e);
@@ -505,18 +656,18 @@ var L = class {
505
656
  if (this.studies.has(a)) throw Error(`alphacharts: a study with id "${a}" already exists`);
506
657
  let o = /^s(\d+)$/.exec(a);
507
658
  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;
659
+ let s = new I(this, a, e, t, n, r.volume, i, r.runner, r.onDispose);
660
+ return s.persist = r.persist !== !1, this.studies.set(a, s), s.hasBarColor() && this.syncBarColors(n), s;
510
661
  }
511
662
  removeStudy(e) {
512
663
  let t = this.studies.get(e);
513
- t && (this.studies.delete(e), t.dispose(this.chart), this.changed());
664
+ t && (this.studies.delete(e), t.dispose(this.chart), t.hasBarColor() && this.syncBarColors(t.barColorSource()), this.changed());
514
665
  }
515
666
  reap() {
516
667
  let e = new Set(this.chart.series().map((e) => e.data));
517
668
  for (let [t, n] of this.studies) {
518
669
  let r = n;
519
- (!e.has(r.source.data) || r.volume && !e.has(r.volume.data)) && (this.studies.delete(t), n.dispose(this.chart));
670
+ (!e.has(r.source.data) || r.volume && !e.has(r.volume.data)) && (this.studies.delete(t), n.dispose(this.chart), e.has(r.source.data) ? n.hasBarColor() && this.syncBarColors(r.source) : this.coloured.delete(r.source));
520
671
  }
521
672
  }
522
673
  reserveIds(e) {
@@ -542,7 +693,7 @@ var L = class {
542
693
  if (r.has(e.id)) throw Error(`alphacharts studies: the layout repeats study id "${e.id}"`);
543
694
  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
695
  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);
696
+ d(this.resolve(e.study), e.inputs);
546
697
  }
547
698
  }
548
699
  fromJSON(e) {
@@ -569,25 +720,25 @@ var L = class {
569
720
  for (let e of this.chart.series()) e.options().id.startsWith("study:") && !r.has(e) && this.chart.removeSeries(e);
570
721
  }
571
722
  };
572
- function R(e, t = {}) {
573
- let n = e.plugin(O);
723
+ function K(e, t = {}) {
724
+ let n = e.plugin(F);
574
725
  if (n) return n;
575
- let r = new L(e, t.runner, t.resolve ?? y);
726
+ let r = new G(e, t.runner, t.resolve ?? C);
576
727
  return e.addPlugin(r), r;
577
728
  }
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);
729
+ function q(e, t, n, r = {}, i = {}) {
730
+ let a = typeof n == "string" ? C(n) : n;
731
+ return K(e, i.runner ? { runner: i.runner } : {}).add(a, r, t, i);
581
732
  }
582
733
  //#endregion
583
734
  //#region src/wasm.ts
584
- async function B() {
585
- a(await D());
735
+ async function J() {
736
+ s(await M());
586
737
  }
587
- function V() {
588
- a(null);
738
+ function Y() {
739
+ s(null);
589
740
  }
590
741
  //#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 };
742
+ export { v as CHUNK, m as CancelledError, o as Col, l as FEED_FIELDS, n as Feed, i as Graph, g as InlineRunner, r as Node, F as PLUGIN_ID, t as SOURCE_NAMES, G as StudiesPlugin, I as Study, _ as StudyEngine, f as WorkerRunner, q as addStudy, u as createRunner, a as defineStudy, c as describeJoin, Y as disableWasm, J as enableWasm, C as getStudy, K as installStudies, e as joinFeed, x as listStudies, P as markerFloor, S as registerStudies, b as registerStudy, d as resolveParams, p as runStudy, h as serveWorker, s as setKernels, y as validateDef };
592
743
 
593
744
  //# sourceMappingURL=index.js.map