oakscriptjs 0.3.0 → 0.5.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.
@@ -0,0 +1,3630 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/script/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ BarData: () => BarData,
24
+ Series: () => Series,
25
+ alertcondition: () => alertcondition,
26
+ barcolor: () => barcolor,
27
+ bgcolor: () => bgcolor,
28
+ close: () => close,
29
+ color: () => color,
30
+ eachBar: () => eachBar,
31
+ executeScript: () => executeScript,
32
+ fill: () => fill,
33
+ high: () => high,
34
+ hl2: () => hl2,
35
+ hlc3: () => hlc3,
36
+ hlcc4: () => hlcc4,
37
+ hline: () => hline,
38
+ indicator: () => indicator,
39
+ input: () => input,
40
+ low: () => low,
41
+ math: () => math_exports,
42
+ na: () => isNA,
43
+ nz: () => nz,
44
+ ohlc4: () => ohlc4,
45
+ open: () => open,
46
+ plot: () => plot,
47
+ plotchar: () => plotchar,
48
+ plotshape: () => plotshape,
49
+ seriesOf: () => seriesOf,
50
+ ta: () => ta2,
51
+ volume: () => volume
52
+ });
53
+ module.exports = __toCommonJS(index_exports);
54
+
55
+ // src/runtime/series.ts
56
+ var BarData = class _BarData {
57
+ _bars;
58
+ _version = 0;
59
+ /**
60
+ * Create a new BarData wrapper
61
+ * @param bars - Initial bar data (defaults to empty array)
62
+ */
63
+ constructor(bars2 = []) {
64
+ this._bars = bars2;
65
+ }
66
+ /**
67
+ * Get the current version number
68
+ * Version increments whenever data is mutated
69
+ */
70
+ get version() {
71
+ return this._version;
72
+ }
73
+ /**
74
+ * Get the underlying bar array
75
+ * Note: Direct mutations to this array will NOT increment version
76
+ * Use the provided mutation methods instead
77
+ */
78
+ get bars() {
79
+ return this._bars;
80
+ }
81
+ /**
82
+ * Get the number of bars
83
+ */
84
+ get length() {
85
+ return this._bars.length;
86
+ }
87
+ /**
88
+ * Add a new bar to the end
89
+ * @param bar - Bar to add
90
+ */
91
+ push(bar) {
92
+ this._bars.push(bar);
93
+ this._version++;
94
+ }
95
+ /**
96
+ * Remove and return the last bar
97
+ * @returns The removed bar, or undefined if empty
98
+ */
99
+ pop() {
100
+ const bar = this._bars.pop();
101
+ if (bar !== void 0) {
102
+ this._version++;
103
+ }
104
+ return bar;
105
+ }
106
+ /**
107
+ * Replace a bar at a specific index
108
+ * @param index - Index to update
109
+ * @param bar - New bar data
110
+ */
111
+ set(index, bar) {
112
+ if (index >= 0 && index < this._bars.length) {
113
+ this._bars[index] = bar;
114
+ this._version++;
115
+ }
116
+ }
117
+ /**
118
+ * Update the last bar (useful for real-time/streaming updates)
119
+ * @param bar - New bar data
120
+ */
121
+ updateLast(bar) {
122
+ if (this._bars.length > 0) {
123
+ this._bars[this._bars.length - 1] = bar;
124
+ this._version++;
125
+ }
126
+ }
127
+ /**
128
+ * Replace all bars with new data
129
+ * @param bars - New bar array
130
+ */
131
+ setAll(bars2) {
132
+ this._bars = bars2;
133
+ this._version++;
134
+ }
135
+ /**
136
+ * Manually increment version (for advanced use cases)
137
+ * Call this after direct mutations to the bars array
138
+ */
139
+ invalidate() {
140
+ this._version++;
141
+ }
142
+ /**
143
+ * Get a bar at a specific index
144
+ * @param index - Bar index
145
+ * @returns Bar at that index, or undefined
146
+ */
147
+ at(index) {
148
+ return this._bars[index];
149
+ }
150
+ /**
151
+ * Create a BarData from an existing Bar array
152
+ * @param bars - Bar array
153
+ * @returns New BarData instance
154
+ */
155
+ static from(bars2) {
156
+ return new _BarData(bars2);
157
+ }
158
+ };
159
+ var Series = class _Series {
160
+ extractor;
161
+ dataSource;
162
+ cached = null;
163
+ cachedVersion = -1;
164
+ /**
165
+ * Create a new Series
166
+ *
167
+ * @param data - Bar data (Bar[] or BarData)
168
+ * @param extractor - Function to extract/compute value for each bar
169
+ */
170
+ constructor(data, extractor) {
171
+ this.dataSource = data instanceof BarData ? data : new BarData(data);
172
+ this.extractor = extractor;
173
+ }
174
+ /**
175
+ * Get the underlying bar data
176
+ * @returns Bar array
177
+ */
178
+ get bars() {
179
+ return this.dataSource.bars;
180
+ }
181
+ /**
182
+ * Get the underlying BarData source
183
+ * @returns BarData instance
184
+ */
185
+ get barData() {
186
+ return this.dataSource;
187
+ }
188
+ // ============================================
189
+ // Static Factory Methods
190
+ // ============================================
191
+ /**
192
+ * Create Series from bar data by extracting a specific field
193
+ * @param bars - Bar data (Bar[] or BarData)
194
+ * @param field - Field to extract ('open', 'high', 'low', 'close', 'volume')
195
+ * @returns Series with extracted field values
196
+ */
197
+ static fromBars(bars2, field) {
198
+ return new _Series(bars2, (bar) => bar[field] ?? NaN);
199
+ }
200
+ /**
201
+ * Create a constant series (same value for all bars)
202
+ * @param bars - Bar data (Bar[] or BarData)
203
+ * @param value - Constant value
204
+ * @returns Series with constant value
205
+ */
206
+ static constant(bars2, value) {
207
+ return new _Series(bars2, () => value);
208
+ }
209
+ /**
210
+ * Create series from array of values
211
+ * @param bars - Bar data (Bar[] or BarData) for time alignment
212
+ * @param values - Array of values
213
+ * @returns Series
214
+ */
215
+ static fromArray(bars2, values) {
216
+ return new _Series(bars2, (_bar, i) => values[i] ?? NaN);
217
+ }
218
+ // ============================================
219
+ // Arithmetic Operations
220
+ // ============================================
221
+ /**
222
+ * Add two series or a series and a number
223
+ * @param other - Series or number to add
224
+ * @returns New Series representing the sum
225
+ */
226
+ add(other) {
227
+ return new _Series(this.dataSource, (bar, i, data) => {
228
+ const a = this.extractor(bar, i, data);
229
+ const b2 = typeof other === "number" ? other : other.extractor(bar, i, data);
230
+ return a + b2;
231
+ });
232
+ }
233
+ /**
234
+ * Subtract two series or subtract a number from a series
235
+ * @param other - Series or number to subtract
236
+ * @returns New Series representing the difference
237
+ */
238
+ sub(other) {
239
+ return new _Series(this.dataSource, (bar, i, data) => {
240
+ const a = this.extractor(bar, i, data);
241
+ const b2 = typeof other === "number" ? other : other.extractor(bar, i, data);
242
+ return a - b2;
243
+ });
244
+ }
245
+ /**
246
+ * Multiply two series or a series by a number
247
+ * @param other - Series or number to multiply
248
+ * @returns New Series representing the product
249
+ */
250
+ mul(other) {
251
+ return new _Series(this.dataSource, (bar, i, data) => {
252
+ const a = this.extractor(bar, i, data);
253
+ const b2 = typeof other === "number" ? other : other.extractor(bar, i, data);
254
+ return a * b2;
255
+ });
256
+ }
257
+ /**
258
+ * Raise the series to a power (PineScript math.pow on a series)
259
+ * @param exponent - Series or number exponent
260
+ * @returns New Series representing base ** exponent
261
+ */
262
+ pow(exponent) {
263
+ return new _Series(this.dataSource, (bar, i, data) => {
264
+ const a = this.extractor(bar, i, data);
265
+ const b2 = typeof exponent === "number" ? exponent : exponent.extractor(bar, i, data);
266
+ return Math.pow(a, b2);
267
+ });
268
+ }
269
+ /**
270
+ * Divide two series or a series by a number
271
+ * @param other - Series or number to divide by
272
+ * @returns New Series representing the quotient
273
+ */
274
+ div(other) {
275
+ return new _Series(this.dataSource, (bar, i, data) => {
276
+ const a = this.extractor(bar, i, data);
277
+ const b2 = typeof other === "number" ? other : other.extractor(bar, i, data);
278
+ return b2 !== 0 ? a / b2 : NaN;
279
+ });
280
+ }
281
+ /**
282
+ * Modulo operation
283
+ * @param other - Series or number for modulo
284
+ * @returns New Series representing the remainder
285
+ */
286
+ mod(other) {
287
+ return new _Series(this.dataSource, (bar, i, data) => {
288
+ const a = this.extractor(bar, i, data);
289
+ const b2 = typeof other === "number" ? other : other.extractor(bar, i, data);
290
+ return b2 !== 0 ? a % b2 : NaN;
291
+ });
292
+ }
293
+ /**
294
+ * Negation
295
+ * @returns New Series with negated values
296
+ */
297
+ neg() {
298
+ return new _Series(this.dataSource, (bar, i, data) => {
299
+ return -this.extractor(bar, i, data);
300
+ });
301
+ }
302
+ // ============================================
303
+ // Comparison Operations
304
+ // ============================================
305
+ /**
306
+ * Greater than comparison
307
+ * @param other - Series or number to compare
308
+ * @returns New Series with 1 where true, 0 where false
309
+ */
310
+ gt(other) {
311
+ return new _Series(this.dataSource, (bar, i, data) => {
312
+ const a = this.extractor(bar, i, data);
313
+ const b2 = typeof other === "number" ? other : other.extractor(bar, i, data);
314
+ return a > b2 ? 1 : 0;
315
+ });
316
+ }
317
+ /**
318
+ * Greater than or equal comparison
319
+ * @param other - Series or number to compare
320
+ * @returns New Series with 1 where true, 0 where false
321
+ */
322
+ gte(other) {
323
+ return new _Series(this.dataSource, (bar, i, data) => {
324
+ const a = this.extractor(bar, i, data);
325
+ const b2 = typeof other === "number" ? other : other.extractor(bar, i, data);
326
+ return a >= b2 ? 1 : 0;
327
+ });
328
+ }
329
+ /**
330
+ * Less than comparison
331
+ * @param other - Series or number to compare
332
+ * @returns New Series with 1 where true, 0 where false
333
+ */
334
+ lt(other) {
335
+ return new _Series(this.dataSource, (bar, i, data) => {
336
+ const a = this.extractor(bar, i, data);
337
+ const b2 = typeof other === "number" ? other : other.extractor(bar, i, data);
338
+ return a < b2 ? 1 : 0;
339
+ });
340
+ }
341
+ /**
342
+ * Less than or equal comparison
343
+ * @param other - Series or number to compare
344
+ * @returns New Series with 1 where true, 0 where false
345
+ */
346
+ lte(other) {
347
+ return new _Series(this.dataSource, (bar, i, data) => {
348
+ const a = this.extractor(bar, i, data);
349
+ const b2 = typeof other === "number" ? other : other.extractor(bar, i, data);
350
+ return a <= b2 ? 1 : 0;
351
+ });
352
+ }
353
+ /**
354
+ * Equality comparison
355
+ * @param other - Series or number to compare
356
+ * @returns New Series with 1 where true, 0 where false
357
+ */
358
+ eq(other) {
359
+ return new _Series(this.dataSource, (bar, i, data) => {
360
+ const a = this.extractor(bar, i, data);
361
+ const b2 = typeof other === "number" ? other : other.extractor(bar, i, data);
362
+ return a === b2 ? 1 : 0;
363
+ });
364
+ }
365
+ /**
366
+ * Not equal comparison
367
+ * @param other - Series or number to compare
368
+ * @returns New Series with 1 where true, 0 where false
369
+ */
370
+ neq(other) {
371
+ return new _Series(this.dataSource, (bar, i, data) => {
372
+ const a = this.extractor(bar, i, data);
373
+ const b2 = typeof other === "number" ? other : other.extractor(bar, i, data);
374
+ return a !== b2 ? 1 : 0;
375
+ });
376
+ }
377
+ // ============================================
378
+ // Logical Operations (for boolean series)
379
+ // ============================================
380
+ /**
381
+ * Logical AND
382
+ * @param other - Series or number (truthy/falsy)
383
+ * @returns New Series with 1 where both true, 0 otherwise
384
+ */
385
+ and(other) {
386
+ return new _Series(this.dataSource, (bar, i, data) => {
387
+ const a = this.extractor(bar, i, data);
388
+ const b2 = typeof other === "number" ? other : other.extractor(bar, i, data);
389
+ return a && b2 ? 1 : 0;
390
+ });
391
+ }
392
+ /**
393
+ * Logical OR
394
+ * @param other - Series or number (truthy/falsy)
395
+ * @returns New Series with 1 where either true, 0 otherwise
396
+ */
397
+ or(other) {
398
+ return new _Series(this.dataSource, (bar, i, data) => {
399
+ const a = this.extractor(bar, i, data);
400
+ const b2 = typeof other === "number" ? other : other.extractor(bar, i, data);
401
+ return a || b2 ? 1 : 0;
402
+ });
403
+ }
404
+ /**
405
+ * Logical NOT
406
+ * @returns New Series with inverted boolean values
407
+ */
408
+ not() {
409
+ return new _Series(this.dataSource, (bar, i, data) => {
410
+ const a = this.extractor(bar, i, data);
411
+ return !a ? 1 : 0;
412
+ });
413
+ }
414
+ // ============================================
415
+ // Conditional Selection
416
+ // ============================================
417
+ /**
418
+ * Bar-by-bar conditional selection (ternary operator for Series)
419
+ * Uses this Series as the condition (truthy = nonzero, falsy = zero/NaN)
420
+ *
421
+ * @param trueValue - Value or Series to use when condition is truthy
422
+ * @param falseValue - Value or Series to use when condition is falsy
423
+ * @returns New Series with bar-by-bar selected values
424
+ *
425
+ * @example
426
+ * ```typescript
427
+ * // PineScript: result = condition ? trueVal : falseVal
428
+ * const result = condition.iff(trueVal, falseVal);
429
+ *
430
+ * // Example: RSI formula uses ternary for edge cases
431
+ * // rsi = down == 0 ? 100 : up == 0 ? 0 : formula
432
+ * const rsi = down.eq(0).iff(100, up.eq(0).iff(0, formula));
433
+ * ```
434
+ */
435
+ iff(trueValue, falseValue) {
436
+ return new _Series(this.dataSource, (bar, i, data) => {
437
+ const condition = this.extractor(bar, i, data);
438
+ const isTruthy = condition !== 0 && !Number.isNaN(condition);
439
+ if (isTruthy) {
440
+ return typeof trueValue === "number" ? trueValue : trueValue.extractor(bar, i, data);
441
+ } else {
442
+ return typeof falseValue === "number" ? falseValue : falseValue.extractor(bar, i, data);
443
+ }
444
+ });
445
+ }
446
+ // ============================================
447
+ // Offset/History
448
+ // ============================================
449
+ /**
450
+ * Access previous bars (like close[1] in PineScript)
451
+ * @param offset - Number of bars back (positive = past)
452
+ * @returns New Series with offset values
453
+ */
454
+ offset(offset) {
455
+ return new _Series(this.dataSource, (_bar, i, data) => {
456
+ const targetIndex = i - offset;
457
+ if (targetIndex < 0 || targetIndex >= data.length) {
458
+ return NaN;
459
+ }
460
+ return this.extractor(data[targetIndex], targetIndex, data);
461
+ });
462
+ }
463
+ // ============================================
464
+ // Computation & Access
465
+ // ============================================
466
+ /**
467
+ * Compute all values for the series
468
+ *
469
+ * Now includes automatic cache invalidation:
470
+ * - Checks if dataSource version has changed since cache was computed
471
+ * - Recomputes if version mismatch detected
472
+ * - Stores version when cache is created
473
+ *
474
+ * @returns Array of computed values
475
+ */
476
+ toArray() {
477
+ if (this.cached !== null && this.cachedVersion === this.dataSource.version) {
478
+ return this.cached;
479
+ }
480
+ const bars2 = this.dataSource.bars;
481
+ this.cached = bars2.map((bar, i) => this.extractor(bar, i, bars2));
482
+ this.cachedVersion = this.dataSource.version;
483
+ return this.cached;
484
+ }
485
+ /**
486
+ * Materialize this Series by eagerly computing values and breaking closure chain
487
+ *
488
+ * This method addresses the closure chain memory leak issue:
489
+ * - Computes all values immediately
490
+ * - Creates a new Series that stores values directly
491
+ * - Breaks references to parent Series objects
492
+ * - Useful for complex expressions to free intermediate Series memory
493
+ *
494
+ * @example
495
+ * ```typescript
496
+ * // Without materialize: keeps a, b, c, d in memory via closures
497
+ * const result = a.add(b).mul(c).div(d).sub(e);
498
+ *
499
+ * // With materialize: breaks chain, frees a, b, c memory
500
+ * const result = a.add(b).mul(c).materialize().div(d).sub(e);
501
+ * ```
502
+ *
503
+ * @returns New Series with computed values and no closure dependencies
504
+ */
505
+ materialize() {
506
+ const values = this.toArray();
507
+ const valuesCopy = [...values];
508
+ return _Series.fromArray(this.dataSource, valuesCopy);
509
+ }
510
+ /**
511
+ * Invalidate cache (when data changes)
512
+ *
513
+ * Note: With BarData versioning, manual invalidation is rarely needed.
514
+ * The cache is automatically invalidated when the underlying BarData changes.
515
+ * This method is kept for backward compatibility and advanced use cases.
516
+ *
517
+ * @internal
518
+ */
519
+ _invalidate() {
520
+ this.cached = null;
521
+ this.cachedVersion = -1;
522
+ }
523
+ /**
524
+ * Compute all values (alias for toArray)
525
+ * @returns Array of computed values
526
+ * @internal
527
+ */
528
+ _compute() {
529
+ return this.toArray();
530
+ }
531
+ /**
532
+ * Get value at specific index
533
+ * @param index - Bar index
534
+ * @returns Value at that index
535
+ */
536
+ get(index) {
537
+ const values = this.toArray();
538
+ return values[index] ?? NaN;
539
+ }
540
+ /**
541
+ * Get the last value (most recent bar)
542
+ * @returns Most recent value
543
+ */
544
+ last() {
545
+ const values = this.toArray();
546
+ return values[values.length - 1] ?? NaN;
547
+ }
548
+ /**
549
+ * Get number of values
550
+ * @returns Length of series
551
+ */
552
+ length() {
553
+ return this.dataSource.length;
554
+ }
555
+ /**
556
+ * Convert series to time-value pairs for charting
557
+ * @returns Array of { time, value } objects
558
+ */
559
+ toTimeValuePairs() {
560
+ const values = this.toArray();
561
+ const bars2 = this.dataSource.bars;
562
+ return bars2.map((bar, i) => ({
563
+ time: bar.time,
564
+ value: values[i]
565
+ })).filter((point) => !Number.isNaN(point.value));
566
+ }
567
+ };
568
+
569
+ // src/ta-series.ts
570
+ var ta_series_exports = {};
571
+ __export(ta_series_exports, {
572
+ alma: () => alma2,
573
+ atr: () => atr2,
574
+ barssince: () => barssince2,
575
+ bb: () => bb2,
576
+ bbw: () => bbw2,
577
+ cci: () => cci2,
578
+ change: () => change2,
579
+ cmo: () => cmo2,
580
+ cog: () => cog2,
581
+ correlation: () => correlation2,
582
+ cross: () => cross2,
583
+ crossover: () => crossover2,
584
+ crossunder: () => crossunder2,
585
+ cum: () => cum2,
586
+ dev: () => dev2,
587
+ dmi: () => dmi2,
588
+ ema: () => ema2,
589
+ falling: () => falling2,
590
+ highest: () => highest2,
591
+ highestbars: () => highestbars2,
592
+ hma: () => hma2,
593
+ ichimoku: () => ichimoku2,
594
+ kc: () => kc2,
595
+ kcw: () => kcw2,
596
+ linreg: () => linreg2,
597
+ lowest: () => lowest2,
598
+ lowestbars: () => lowestbars2,
599
+ macd: () => macd2,
600
+ max: () => max2,
601
+ median: () => median2,
602
+ mfi: () => mfi2,
603
+ min: () => min2,
604
+ mode: () => mode2,
605
+ mom: () => mom2,
606
+ percentile_linear_interpolation: () => percentile_linear_interpolation2,
607
+ percentile_nearest_rank: () => percentile_nearest_rank2,
608
+ percentrank: () => percentrank2,
609
+ pivothigh: () => pivothigh2,
610
+ pivotlow: () => pivotlow2,
611
+ range: () => range2,
612
+ rci: () => rci2,
613
+ rising: () => rising2,
614
+ rma: () => rma2,
615
+ roc: () => roc2,
616
+ rsi: () => rsi2,
617
+ sar: () => sar2,
618
+ sma: () => sma2,
619
+ stdev: () => stdev2,
620
+ stoch: () => stoch2,
621
+ supertrend: () => supertrend2,
622
+ swma: () => swma2,
623
+ ta: () => ta,
624
+ tr: () => tr2,
625
+ tsi: () => tsi2,
626
+ valuewhen: () => valuewhen2,
627
+ variance: () => variance2,
628
+ vwap: () => vwap2,
629
+ vwma: () => vwma2,
630
+ wma: () => wma2,
631
+ wpr: () => wpr2,
632
+ zigzag: () => zigzag2
633
+ });
634
+
635
+ // src/ta/index.ts
636
+ function sma(source, length) {
637
+ const result = [];
638
+ const len = Math.floor(length);
639
+ for (let i = 0; i < source.length; i++) {
640
+ if (i < len - 1) {
641
+ result.push(NaN);
642
+ } else {
643
+ let sum2 = 0;
644
+ for (let j = 0; j < len; j++) {
645
+ sum2 += source[i - j];
646
+ }
647
+ result.push(sum2 / len);
648
+ }
649
+ }
650
+ return result;
651
+ }
652
+ function ema(source, length) {
653
+ const result = [];
654
+ const len = Math.floor(length);
655
+ const multiplier = 2 / (len + 1);
656
+ let firstValidIndex = -1;
657
+ let validCount = 0;
658
+ let initSum = 0;
659
+ for (let i = 0; i < source.length; i++) {
660
+ const val = source[i];
661
+ if (val !== void 0 && !isNaN(val)) {
662
+ initSum += val;
663
+ validCount++;
664
+ if (validCount === len) {
665
+ firstValidIndex = i;
666
+ break;
667
+ }
668
+ }
669
+ }
670
+ let emaValue = validCount > 0 ? initSum / validCount : NaN;
671
+ const emaInitialized = firstValidIndex >= 0;
672
+ for (let i = 0; i < source.length; i++) {
673
+ if (!emaInitialized || i < firstValidIndex) {
674
+ result.push(NaN);
675
+ } else if (i === firstValidIndex) {
676
+ result.push(emaValue);
677
+ } else {
678
+ const val = source[i];
679
+ if (val !== void 0 && !isNaN(val)) {
680
+ emaValue = (val - emaValue) * multiplier + emaValue;
681
+ }
682
+ result.push(emaValue);
683
+ }
684
+ }
685
+ return result;
686
+ }
687
+ function rsi(source, length) {
688
+ const result = [];
689
+ const changes = [];
690
+ for (let i = 1; i < source.length; i++) {
691
+ changes.push(source[i] - source[i - 1]);
692
+ }
693
+ const gains = changes.map((c) => c > 0 ? c : 0);
694
+ const losses = changes.map((c) => c < 0 ? -c : 0);
695
+ const avgGains = rma(gains, length);
696
+ const avgLosses = rma(losses, length);
697
+ result.push(NaN);
698
+ for (let i = 0; i < avgGains.length; i++) {
699
+ if (avgLosses[i] === 0) {
700
+ result.push(100);
701
+ } else {
702
+ const rs = avgGains[i] / avgLosses[i];
703
+ result.push(100 - 100 / (1 + rs));
704
+ }
705
+ }
706
+ return result;
707
+ }
708
+ function macd(source, fastLength, slowLength, signalLength) {
709
+ const fastEma = ema(source, fastLength);
710
+ const slowEma = ema(source, slowLength);
711
+ const macdLine = [];
712
+ for (let i = 0; i < source.length; i++) {
713
+ macdLine.push(fastEma[i] - slowEma[i]);
714
+ }
715
+ const signalLine = ema(macdLine, signalLength);
716
+ const histogram = [];
717
+ for (let i = 0; i < source.length; i++) {
718
+ histogram.push(macdLine[i] - signalLine[i]);
719
+ }
720
+ return [macdLine, signalLine, histogram];
721
+ }
722
+ function bb(series, length, mult) {
723
+ const basis = sma(series, length);
724
+ const dev3 = stdev(series, length);
725
+ const upper = [];
726
+ const lower = [];
727
+ for (let i = 0; i < series.length; i++) {
728
+ upper.push(basis[i] + mult * dev3[i]);
729
+ lower.push(basis[i] - mult * dev3[i]);
730
+ }
731
+ return [basis, upper, lower];
732
+ }
733
+ function stdev(source, length) {
734
+ const result = [];
735
+ const len = Math.floor(length);
736
+ const avg2 = sma(source, len);
737
+ for (let i = 0; i < source.length; i++) {
738
+ if (i < len - 1) {
739
+ result.push(NaN);
740
+ } else {
741
+ let sumSquares = 0;
742
+ for (let j = 0; j < len; j++) {
743
+ const diff = source[i - j] - avg2[i];
744
+ sumSquares += diff * diff;
745
+ }
746
+ result.push(Math.sqrt(sumSquares / len));
747
+ }
748
+ }
749
+ return result;
750
+ }
751
+ function crossover(series1, series2) {
752
+ const result = [];
753
+ for (let i = 0; i < series1.length; i++) {
754
+ if (i === 0) {
755
+ result.push(false);
756
+ } else {
757
+ result.push(series1[i] > series2[i] && series1[i - 1] <= series2[i - 1]);
758
+ }
759
+ }
760
+ return result;
761
+ }
762
+ function crossunder(series1, series2) {
763
+ const result = [];
764
+ for (let i = 0; i < series1.length; i++) {
765
+ if (i === 0) {
766
+ result.push(false);
767
+ } else {
768
+ result.push(series1[i] < series2[i] && series1[i - 1] >= series2[i - 1]);
769
+ }
770
+ }
771
+ return result;
772
+ }
773
+ function change(source, length = 1) {
774
+ const result = [];
775
+ for (let i = 0; i < source.length; i++) {
776
+ if (i < length) {
777
+ result.push(NaN);
778
+ } else {
779
+ result.push(source[i] - source[i - length]);
780
+ }
781
+ }
782
+ return result;
783
+ }
784
+ function tr(handle_na = false, high2, low2, close2) {
785
+ if (!high2 || !low2 || !close2) {
786
+ throw new Error(
787
+ "ta.tr() requires high, low, and close series. Either pass them explicitly or use createContext({ chart: { high, low, close } }) for implicit data."
788
+ );
789
+ }
790
+ const result = [];
791
+ for (let i = 0; i < high2.length; i++) {
792
+ if (i === 0) {
793
+ result.push(high2[i] - low2[i]);
794
+ } else {
795
+ const prevClose = close2[i - 1];
796
+ if (isNaN(prevClose)) {
797
+ if (handle_na) {
798
+ result.push(high2[i] - low2[i]);
799
+ } else {
800
+ result.push(NaN);
801
+ }
802
+ } else {
803
+ const tr3 = Math.max(
804
+ high2[i] - low2[i],
805
+ Math.abs(high2[i] - prevClose),
806
+ Math.abs(low2[i] - prevClose)
807
+ );
808
+ result.push(tr3);
809
+ }
810
+ }
811
+ }
812
+ return result;
813
+ }
814
+ function atr(length, high2, low2, close2) {
815
+ if (!high2 || !low2 || !close2) {
816
+ throw new Error(
817
+ "ta.atr() requires high, low, and close series. Either pass them explicitly or use createContext({ chart: { high, low, close } }) for implicit data."
818
+ );
819
+ }
820
+ const trueRange = tr(false, high2, low2, close2);
821
+ return rma(trueRange, length);
822
+ }
823
+ function supertrend(factor, atrPeriod, high2, low2, close2, wicks = false) {
824
+ if (!high2 || !low2 || !close2) {
825
+ throw new Error(
826
+ "ta.supertrend() requires high, low, and close series. Either pass them explicitly or use createContext({ chart: { high, low, close } }) for implicit data."
827
+ );
828
+ }
829
+ const supertrendValues = [];
830
+ const directions = [];
831
+ const source = [];
832
+ for (let i = 0; i < high2.length; i++) {
833
+ source.push((high2[i] + low2[i]) / 2);
834
+ }
835
+ const atrValues = atr(atrPeriod, high2, low2, close2);
836
+ let prevLowerBand = NaN;
837
+ let prevUpperBand = NaN;
838
+ let prevSuperTrend = NaN;
839
+ for (let i = 0; i < source.length; i++) {
840
+ const atrValue = atrValues[i] * factor;
841
+ if (isNaN(atrValue)) {
842
+ supertrendValues.push(NaN);
843
+ directions.push(1);
844
+ continue;
845
+ }
846
+ let upperBand = source[i] + atrValue;
847
+ let lowerBand = source[i] - atrValue;
848
+ const highPrice = wicks ? high2[i] : close2[i];
849
+ const lowPrice = wicks ? low2[i] : close2[i];
850
+ const prevLowPrice = i > 0 ? wicks ? low2[i - 1] : close2[i - 1] : 0;
851
+ const prevHighPrice = i > 0 ? wicks ? high2[i - 1] : close2[i - 1] : 0;
852
+ if (i > 0 && !isNaN(prevLowerBand) && !isNaN(prevUpperBand)) {
853
+ lowerBand = lowerBand > prevLowerBand || prevLowPrice < prevLowerBand ? lowerBand : prevLowerBand;
854
+ upperBand = upperBand < prevUpperBand || prevHighPrice > prevUpperBand ? upperBand : prevUpperBand;
855
+ }
856
+ let currentDirection;
857
+ if (isNaN(prevSuperTrend)) {
858
+ currentDirection = 1;
859
+ } else if (prevSuperTrend === prevUpperBand) {
860
+ currentDirection = highPrice > upperBand ? -1 : 1;
861
+ } else {
862
+ currentDirection = lowPrice < lowerBand ? 1 : -1;
863
+ }
864
+ const superTrendValue = currentDirection === -1 ? lowerBand : upperBand;
865
+ supertrendValues.push(superTrendValue);
866
+ directions.push(currentDirection);
867
+ prevLowerBand = lowerBand;
868
+ prevUpperBand = upperBand;
869
+ prevSuperTrend = superTrendValue;
870
+ }
871
+ return [supertrendValues, directions];
872
+ }
873
+ function rma(source, length) {
874
+ const result = [];
875
+ const len = Math.floor(length);
876
+ const alpha = 1 / len;
877
+ let firstValidIndex = -1;
878
+ let validCount = 0;
879
+ let initSum = 0;
880
+ for (let i = 0; i < source.length; i++) {
881
+ const val = source[i];
882
+ if (val !== void 0 && !isNaN(val)) {
883
+ initSum += val;
884
+ validCount++;
885
+ if (validCount === len) {
886
+ firstValidIndex = i;
887
+ break;
888
+ }
889
+ }
890
+ }
891
+ let rmaValue = validCount > 0 ? initSum / validCount : NaN;
892
+ const rmaInitialized = firstValidIndex >= 0;
893
+ for (let i = 0; i < source.length; i++) {
894
+ if (!rmaInitialized || i < firstValidIndex) {
895
+ result.push(NaN);
896
+ } else if (i === firstValidIndex) {
897
+ result.push(rmaValue);
898
+ } else {
899
+ const val = source[i];
900
+ if (val !== void 0 && !isNaN(val)) {
901
+ rmaValue = alpha * val + (1 - alpha) * rmaValue;
902
+ }
903
+ result.push(rmaValue);
904
+ }
905
+ }
906
+ return result;
907
+ }
908
+ function wma(source, length) {
909
+ const result = [];
910
+ const len = Math.floor(length);
911
+ for (let i = 0; i < source.length; i++) {
912
+ if (i < len - 1) {
913
+ result.push(NaN);
914
+ } else {
915
+ let sum2 = 0;
916
+ let weightSum = 0;
917
+ for (let j = 0; j < len; j++) {
918
+ const weight = len - j;
919
+ sum2 += source[i - j] * weight;
920
+ weightSum += weight;
921
+ }
922
+ result.push(sum2 / weightSum);
923
+ }
924
+ }
925
+ return result;
926
+ }
927
+ function highest(source, length) {
928
+ const result = [];
929
+ for (let i = 0; i < source.length; i++) {
930
+ if (i < length - 1) {
931
+ result.push(NaN);
932
+ } else {
933
+ let max4 = -Infinity;
934
+ for (let j = 0; j < length; j++) {
935
+ if (!isNaN(source[i - j])) {
936
+ max4 = Math.max(max4, source[i - j]);
937
+ }
938
+ }
939
+ result.push(max4 === -Infinity ? NaN : max4);
940
+ }
941
+ }
942
+ return result;
943
+ }
944
+ function lowest(source, length) {
945
+ const result = [];
946
+ for (let i = 0; i < source.length; i++) {
947
+ if (i < length - 1) {
948
+ result.push(NaN);
949
+ } else {
950
+ let min4 = Infinity;
951
+ for (let j = 0; j < length; j++) {
952
+ if (!isNaN(source[i - j])) {
953
+ min4 = Math.min(min4, source[i - j]);
954
+ }
955
+ }
956
+ result.push(min4 === Infinity ? NaN : min4);
957
+ }
958
+ }
959
+ return result;
960
+ }
961
+ function cum(source) {
962
+ const result = [];
963
+ let sum2 = 0;
964
+ for (let i = 0; i < source.length; i++) {
965
+ sum2 += source[i];
966
+ result.push(sum2);
967
+ }
968
+ return result;
969
+ }
970
+ function cross(source1, source2) {
971
+ const result = [];
972
+ for (let i = 0; i < source1.length; i++) {
973
+ if (i === 0) {
974
+ result.push(false);
975
+ } else {
976
+ const crossedUp = source1[i] > source2[i] && source1[i - 1] <= source2[i - 1];
977
+ const crossedDown = source1[i] < source2[i] && source1[i - 1] >= source2[i - 1];
978
+ result.push(crossedUp || crossedDown);
979
+ }
980
+ }
981
+ return result;
982
+ }
983
+ function rising(source, length) {
984
+ const result = [];
985
+ for (let i = 0; i < source.length; i++) {
986
+ if (i < length) {
987
+ result.push(false);
988
+ } else {
989
+ let isRising = true;
990
+ for (let j = 1; j <= length; j++) {
991
+ if (source[i - j + 1] <= source[i - j]) {
992
+ isRising = false;
993
+ break;
994
+ }
995
+ }
996
+ result.push(isRising);
997
+ }
998
+ }
999
+ return result;
1000
+ }
1001
+ function falling(source, length) {
1002
+ const result = [];
1003
+ for (let i = 0; i < source.length; i++) {
1004
+ if (i < length) {
1005
+ result.push(false);
1006
+ } else {
1007
+ let isFalling = true;
1008
+ for (let j = 1; j <= length; j++) {
1009
+ if (source[i - j + 1] >= source[i - j]) {
1010
+ isFalling = false;
1011
+ break;
1012
+ }
1013
+ }
1014
+ result.push(isFalling);
1015
+ }
1016
+ }
1017
+ return result;
1018
+ }
1019
+ function roc(source, length) {
1020
+ const result = [];
1021
+ for (let i = 0; i < source.length; i++) {
1022
+ if (i < length) {
1023
+ result.push(NaN);
1024
+ } else {
1025
+ const oldValue = source[i - length];
1026
+ if (oldValue === 0 || isNaN(oldValue) || isNaN(source[i])) {
1027
+ result.push(NaN);
1028
+ } else {
1029
+ const changeValue = source[i] - oldValue;
1030
+ result.push(100 * changeValue / oldValue);
1031
+ }
1032
+ }
1033
+ }
1034
+ return result;
1035
+ }
1036
+ function mom(source, length) {
1037
+ const result = [];
1038
+ for (let i = 0; i < source.length; i++) {
1039
+ if (i < length) {
1040
+ result.push(NaN);
1041
+ } else {
1042
+ if (isNaN(source[i]) || isNaN(source[i - length])) {
1043
+ result.push(NaN);
1044
+ } else {
1045
+ result.push(source[i] - source[i - length]);
1046
+ }
1047
+ }
1048
+ }
1049
+ return result;
1050
+ }
1051
+ function dev(source, length) {
1052
+ const result = [];
1053
+ const meanValues = sma(source, length);
1054
+ for (let i = 0; i < source.length; i++) {
1055
+ if (i < length - 1 || isNaN(meanValues[i])) {
1056
+ result.push(NaN);
1057
+ } else {
1058
+ let sum2 = 0;
1059
+ for (let j = 0; j < length; j++) {
1060
+ if (!isNaN(source[i - j])) {
1061
+ sum2 += Math.abs(source[i - j] - meanValues[i]);
1062
+ }
1063
+ }
1064
+ result.push(sum2 / length);
1065
+ }
1066
+ }
1067
+ return result;
1068
+ }
1069
+ function variance(source, length, biased = true) {
1070
+ const result = [];
1071
+ const meanValues = sma(source, length);
1072
+ for (let i = 0; i < source.length; i++) {
1073
+ if (i < length - 1 || isNaN(meanValues[i])) {
1074
+ result.push(NaN);
1075
+ } else {
1076
+ let sumSquares = 0;
1077
+ let count = 0;
1078
+ for (let j = 0; j < length; j++) {
1079
+ if (!isNaN(source[i - j])) {
1080
+ const diff = source[i - j] - meanValues[i];
1081
+ sumSquares += diff * diff;
1082
+ count++;
1083
+ }
1084
+ }
1085
+ const divisor = biased ? count : count - 1;
1086
+ result.push(divisor > 0 ? sumSquares / divisor : NaN);
1087
+ }
1088
+ }
1089
+ return result;
1090
+ }
1091
+ function median(source, length) {
1092
+ const result = [];
1093
+ for (let i = 0; i < source.length; i++) {
1094
+ if (i < length - 1) {
1095
+ result.push(NaN);
1096
+ } else {
1097
+ const values = [];
1098
+ for (let j = 0; j < length; j++) {
1099
+ if (!isNaN(source[i - j])) {
1100
+ values.push(source[i - j]);
1101
+ }
1102
+ }
1103
+ if (values.length === 0) {
1104
+ result.push(NaN);
1105
+ } else {
1106
+ values.sort((a, b2) => a - b2);
1107
+ const mid = Math.floor(values.length / 2);
1108
+ if (values.length % 2 === 0) {
1109
+ result.push((values[mid - 1] + values[mid]) / 2);
1110
+ } else {
1111
+ result.push(values[mid]);
1112
+ }
1113
+ }
1114
+ }
1115
+ }
1116
+ return result;
1117
+ }
1118
+ function swma(source) {
1119
+ const result = [];
1120
+ for (let i = 0; i < source.length; i++) {
1121
+ if (i < 3) {
1122
+ result.push(NaN);
1123
+ } else {
1124
+ if (isNaN(source[i]) || isNaN(source[i - 1]) || isNaN(source[i - 2]) || isNaN(source[i - 3])) {
1125
+ result.push(NaN);
1126
+ } else {
1127
+ const value = source[i - 3] * (1 / 6) + source[i - 2] * (2 / 6) + source[i - 1] * (2 / 6) + source[i] * (1 / 6);
1128
+ result.push(value);
1129
+ }
1130
+ }
1131
+ }
1132
+ return result;
1133
+ }
1134
+ function vwma(source, length, volume2) {
1135
+ if (!volume2) {
1136
+ throw new Error(
1137
+ "ta.vwma() requires volume series. Either pass it explicitly or use createContext({ chart: { ..., volume } }) for implicit data."
1138
+ );
1139
+ }
1140
+ const sourceTimesVolume = [];
1141
+ for (let i = 0; i < source.length; i++) {
1142
+ sourceTimesVolume.push(source[i] * volume2[i]);
1143
+ }
1144
+ const numerator = sma(sourceTimesVolume, length);
1145
+ const denominator = sma(volume2, length);
1146
+ const result = [];
1147
+ for (let i = 0; i < source.length; i++) {
1148
+ if (denominator[i] === 0 || isNaN(denominator[i])) {
1149
+ result.push(NaN);
1150
+ } else {
1151
+ result.push(numerator[i] / denominator[i]);
1152
+ }
1153
+ }
1154
+ return result;
1155
+ }
1156
+ function linreg(source, length, offset = 0) {
1157
+ const result = [];
1158
+ const len = Math.floor(length);
1159
+ for (let i = 0; i < source.length; i++) {
1160
+ if (i < len - 1) {
1161
+ result.push(NaN);
1162
+ } else {
1163
+ let hasNaN = false;
1164
+ for (let j = 0; j < len; j++) {
1165
+ if (isNaN(source[i - j])) {
1166
+ hasNaN = true;
1167
+ break;
1168
+ }
1169
+ }
1170
+ if (hasNaN) {
1171
+ result.push(NaN);
1172
+ } else {
1173
+ let sumX = 0;
1174
+ let sumY = 0;
1175
+ let sumXY = 0;
1176
+ let sumX2 = 0;
1177
+ for (let j = 0; j < len; j++) {
1178
+ const x2 = j;
1179
+ const y = source[i - (len - 1 - j)];
1180
+ sumX += x2;
1181
+ sumY += y;
1182
+ sumXY += x2 * y;
1183
+ sumX2 += x2 * x2;
1184
+ }
1185
+ const slope = (len * sumXY - sumX * sumY) / (len * sumX2 - sumX * sumX);
1186
+ const intercept = (sumY - slope * sumX) / len;
1187
+ const x = len - 1 - offset;
1188
+ result.push(intercept + slope * x);
1189
+ }
1190
+ }
1191
+ }
1192
+ return result;
1193
+ }
1194
+ function correlation(source1, source2, length) {
1195
+ const result = [];
1196
+ for (let i = 0; i < source1.length; i++) {
1197
+ if (i < length - 1) {
1198
+ result.push(NaN);
1199
+ } else {
1200
+ const pairs = [];
1201
+ for (let j = 0; j < length; j++) {
1202
+ if (!isNaN(source1[i - j]) && !isNaN(source2[i - j])) {
1203
+ pairs.push([source1[i - j], source2[i - j]]);
1204
+ }
1205
+ }
1206
+ if (pairs.length === 0) {
1207
+ result.push(NaN);
1208
+ } else {
1209
+ let sum1 = 0;
1210
+ let sum2 = 0;
1211
+ for (const [v1, v2] of pairs) {
1212
+ sum1 += v1;
1213
+ sum2 += v2;
1214
+ }
1215
+ const mean1 = sum1 / pairs.length;
1216
+ const mean2 = sum2 / pairs.length;
1217
+ let numerator = 0;
1218
+ let sum1Sq = 0;
1219
+ let sum2Sq = 0;
1220
+ for (const [v1, v2] of pairs) {
1221
+ const dev1 = v1 - mean1;
1222
+ const dev22 = v2 - mean2;
1223
+ numerator += dev1 * dev22;
1224
+ sum1Sq += dev1 * dev1;
1225
+ sum2Sq += dev22 * dev22;
1226
+ }
1227
+ const denominator = Math.sqrt(sum1Sq * sum2Sq);
1228
+ if (denominator === 0) {
1229
+ result.push(NaN);
1230
+ } else {
1231
+ result.push(numerator / denominator);
1232
+ }
1233
+ }
1234
+ }
1235
+ }
1236
+ return result;
1237
+ }
1238
+ function percentrank(source, length) {
1239
+ const result = [];
1240
+ for (let i = 0; i < source.length; i++) {
1241
+ if (i < length) {
1242
+ result.push(NaN);
1243
+ } else {
1244
+ if (isNaN(source[i])) {
1245
+ result.push(NaN);
1246
+ continue;
1247
+ }
1248
+ let hasNaN = false;
1249
+ for (let j = 1; j <= length; j++) {
1250
+ if (isNaN(source[i - j])) {
1251
+ hasNaN = true;
1252
+ break;
1253
+ }
1254
+ }
1255
+ if (hasNaN) {
1256
+ result.push(NaN);
1257
+ } else {
1258
+ const currentValue = source[i];
1259
+ let countLessOrEqual = 0;
1260
+ for (let j = 1; j <= length; j++) {
1261
+ if (source[i - j] <= currentValue) {
1262
+ countLessOrEqual++;
1263
+ }
1264
+ }
1265
+ result.push(countLessOrEqual / length * 100);
1266
+ }
1267
+ }
1268
+ }
1269
+ return result;
1270
+ }
1271
+ function cci(source, length) {
1272
+ const result = [];
1273
+ const smaValues = sma(source, length);
1274
+ const devValues = dev(source, length);
1275
+ for (let i = 0; i < source.length; i++) {
1276
+ if (isNaN(smaValues[i]) || isNaN(devValues[i]) || devValues[i] === 0) {
1277
+ result.push(NaN);
1278
+ } else {
1279
+ const cci3 = (source[i] - smaValues[i]) / (0.015 * devValues[i]);
1280
+ result.push(cci3);
1281
+ }
1282
+ }
1283
+ return result;
1284
+ }
1285
+ function stoch(source, high2, low2, length) {
1286
+ const result = [];
1287
+ const lowestValues = lowest(low2, length);
1288
+ const highestValues = highest(high2, length);
1289
+ for (let i = 0; i < source.length; i++) {
1290
+ if (isNaN(lowestValues[i]) || isNaN(highestValues[i])) {
1291
+ result.push(NaN);
1292
+ } else {
1293
+ const range3 = highestValues[i] - lowestValues[i];
1294
+ if (range3 === 0) {
1295
+ result.push(NaN);
1296
+ } else {
1297
+ const stochValue = 100 * (source[i] - lowestValues[i]) / range3;
1298
+ result.push(stochValue);
1299
+ }
1300
+ }
1301
+ }
1302
+ return result;
1303
+ }
1304
+ function mfi(source, length, volume2) {
1305
+ if (!volume2) {
1306
+ throw new Error(
1307
+ "ta.mfi() requires volume series. Either pass it explicitly or use createContext({ chart: { ..., volume } }) for implicit data."
1308
+ );
1309
+ }
1310
+ const result = [];
1311
+ const changes = [NaN];
1312
+ for (let i = 1; i < source.length; i++) {
1313
+ changes.push(source[i] - source[i - 1]);
1314
+ }
1315
+ const positiveFlow = [];
1316
+ const negativeFlow = [];
1317
+ for (let i = 0; i < source.length; i++) {
1318
+ if (i === 0 || isNaN(changes[i])) {
1319
+ positiveFlow.push(0);
1320
+ negativeFlow.push(0);
1321
+ } else if (changes[i] > 0) {
1322
+ positiveFlow.push(volume2[i] * source[i]);
1323
+ negativeFlow.push(0);
1324
+ } else if (changes[i] < 0) {
1325
+ positiveFlow.push(0);
1326
+ negativeFlow.push(volume2[i] * source[i]);
1327
+ } else {
1328
+ positiveFlow.push(0);
1329
+ negativeFlow.push(0);
1330
+ }
1331
+ }
1332
+ for (let i = 0; i < source.length; i++) {
1333
+ if (i < length) {
1334
+ result.push(NaN);
1335
+ } else {
1336
+ let posSum = 0;
1337
+ let negSum = 0;
1338
+ for (let j = 0; j < length; j++) {
1339
+ posSum += positiveFlow[i - j];
1340
+ negSum += negativeFlow[i - j];
1341
+ }
1342
+ if (negSum === 0) {
1343
+ result.push(100);
1344
+ } else {
1345
+ const moneyRatio = posSum / negSum;
1346
+ const mfiValue = 100 - 100 / (1 + moneyRatio);
1347
+ result.push(mfiValue);
1348
+ }
1349
+ }
1350
+ }
1351
+ return result;
1352
+ }
1353
+ function hma(source, length) {
1354
+ const halfLength = Math.floor(length / 2);
1355
+ const sqrtLength = Math.floor(Math.sqrt(length));
1356
+ const wmaHalf = wma(source, halfLength);
1357
+ const wmaFull = wma(source, length);
1358
+ const diff = [];
1359
+ for (let i = 0; i < source.length; i++) {
1360
+ diff.push(2 * wmaHalf[i] - wmaFull[i]);
1361
+ }
1362
+ return wma(diff, sqrtLength);
1363
+ }
1364
+ function sar(start, inc, max4, high2, low2, close2) {
1365
+ if (!high2 || !low2 || !close2) {
1366
+ throw new Error(
1367
+ "ta.sar() requires high, low, and close series. Either pass them explicitly or use createContext({ chart: { high, low, close } }) for implicit data."
1368
+ );
1369
+ }
1370
+ const result = [];
1371
+ let sarValue = NaN;
1372
+ let extremePoint = NaN;
1373
+ let acceleration = start;
1374
+ let isUpTrend = false;
1375
+ let isFirstTrendBar = false;
1376
+ for (let i = 0; i < close2.length; i++) {
1377
+ if (i === 0) {
1378
+ result.push(NaN);
1379
+ continue;
1380
+ }
1381
+ if (i === 1) {
1382
+ if (close2[i] > close2[i - 1]) {
1383
+ isUpTrend = true;
1384
+ extremePoint = high2[i];
1385
+ sarValue = low2[i - 1];
1386
+ } else {
1387
+ isUpTrend = false;
1388
+ extremePoint = low2[i];
1389
+ sarValue = high2[i - 1];
1390
+ }
1391
+ isFirstTrendBar = true;
1392
+ acceleration = start;
1393
+ }
1394
+ sarValue = sarValue + acceleration * (extremePoint - sarValue);
1395
+ if (isUpTrend) {
1396
+ if (sarValue > low2[i]) {
1397
+ isFirstTrendBar = true;
1398
+ isUpTrend = false;
1399
+ sarValue = Math.max(high2[i], extremePoint);
1400
+ extremePoint = low2[i];
1401
+ acceleration = start;
1402
+ }
1403
+ } else {
1404
+ if (sarValue < high2[i]) {
1405
+ isFirstTrendBar = true;
1406
+ isUpTrend = true;
1407
+ sarValue = Math.min(low2[i], extremePoint);
1408
+ extremePoint = high2[i];
1409
+ acceleration = start;
1410
+ }
1411
+ }
1412
+ if (!isFirstTrendBar) {
1413
+ if (isUpTrend) {
1414
+ if (high2[i] > extremePoint) {
1415
+ extremePoint = high2[i];
1416
+ acceleration = Math.min(acceleration + inc, max4);
1417
+ }
1418
+ } else {
1419
+ if (low2[i] < extremePoint) {
1420
+ extremePoint = low2[i];
1421
+ acceleration = Math.min(acceleration + inc, max4);
1422
+ }
1423
+ }
1424
+ }
1425
+ if (isUpTrend) {
1426
+ sarValue = Math.min(sarValue, low2[i - 1]);
1427
+ if (i > 1) {
1428
+ sarValue = Math.min(sarValue, low2[i - 2]);
1429
+ }
1430
+ } else {
1431
+ sarValue = Math.max(sarValue, high2[i - 1]);
1432
+ if (i > 1) {
1433
+ sarValue = Math.max(sarValue, high2[i - 2]);
1434
+ }
1435
+ }
1436
+ result.push(sarValue);
1437
+ isFirstTrendBar = false;
1438
+ }
1439
+ return result;
1440
+ }
1441
+ function pivothigh(sourceOrLeftbars, leftbarsOrRightbars, rightbars, high2) {
1442
+ let source;
1443
+ let leftbars;
1444
+ let right;
1445
+ if (rightbars === void 0) {
1446
+ if (!high2) {
1447
+ throw new Error("ta.pivothigh() requires high series when using two-parameter version.");
1448
+ }
1449
+ source = high2;
1450
+ leftbars = sourceOrLeftbars;
1451
+ right = leftbarsOrRightbars;
1452
+ } else {
1453
+ source = sourceOrLeftbars;
1454
+ leftbars = leftbarsOrRightbars;
1455
+ right = rightbars;
1456
+ }
1457
+ const result = [];
1458
+ for (let i = 0; i < source.length; i++) {
1459
+ if (i < leftbars || i + right >= source.length) {
1460
+ result.push(NaN);
1461
+ continue;
1462
+ }
1463
+ const centerValue = source[i];
1464
+ let isPivot = true;
1465
+ for (let j = 1; j <= leftbars; j++) {
1466
+ if (source[i - j] >= centerValue) {
1467
+ isPivot = false;
1468
+ break;
1469
+ }
1470
+ }
1471
+ if (isPivot) {
1472
+ for (let j = 1; j <= right; j++) {
1473
+ if (source[i + j] >= centerValue) {
1474
+ isPivot = false;
1475
+ break;
1476
+ }
1477
+ }
1478
+ }
1479
+ result.push(isPivot ? centerValue : NaN);
1480
+ }
1481
+ return result;
1482
+ }
1483
+ function pivotlow(sourceOrLeftbars, leftbarsOrRightbars, rightbars, low2) {
1484
+ let source;
1485
+ let leftbars;
1486
+ let right;
1487
+ if (rightbars === void 0) {
1488
+ if (!low2) {
1489
+ throw new Error("ta.pivotlow() requires low series when using two-parameter version.");
1490
+ }
1491
+ source = low2;
1492
+ leftbars = sourceOrLeftbars;
1493
+ right = leftbarsOrRightbars;
1494
+ } else {
1495
+ source = sourceOrLeftbars;
1496
+ leftbars = leftbarsOrRightbars;
1497
+ right = rightbars;
1498
+ }
1499
+ const result = [];
1500
+ for (let i = 0; i < source.length; i++) {
1501
+ if (i < leftbars || i + right >= source.length) {
1502
+ result.push(NaN);
1503
+ continue;
1504
+ }
1505
+ const centerValue = source[i];
1506
+ let isPivot = true;
1507
+ for (let j = 1; j <= leftbars; j++) {
1508
+ if (source[i - j] <= centerValue) {
1509
+ isPivot = false;
1510
+ break;
1511
+ }
1512
+ }
1513
+ if (isPivot) {
1514
+ for (let j = 1; j <= right; j++) {
1515
+ if (source[i + j] <= centerValue) {
1516
+ isPivot = false;
1517
+ break;
1518
+ }
1519
+ }
1520
+ }
1521
+ result.push(isPivot ? centerValue : NaN);
1522
+ }
1523
+ return result;
1524
+ }
1525
+ function barssince(condition) {
1526
+ const result = [];
1527
+ let barsSinceTrue = NaN;
1528
+ for (let i = 0; i < condition.length; i++) {
1529
+ if (condition[i]) {
1530
+ barsSinceTrue = 0;
1531
+ } else if (!isNaN(barsSinceTrue)) {
1532
+ barsSinceTrue++;
1533
+ }
1534
+ result.push(barsSinceTrue);
1535
+ }
1536
+ return result;
1537
+ }
1538
+ function valuewhen(condition, source, occurrence) {
1539
+ const result = [];
1540
+ for (let i = 0; i < condition.length; i++) {
1541
+ let occurrenceCount = 0;
1542
+ let foundValue = NaN;
1543
+ for (let j = i; j >= 0; j--) {
1544
+ if (condition[j]) {
1545
+ if (occurrenceCount === occurrence) {
1546
+ foundValue = source[j];
1547
+ break;
1548
+ }
1549
+ occurrenceCount++;
1550
+ }
1551
+ }
1552
+ result.push(foundValue);
1553
+ }
1554
+ return result;
1555
+ }
1556
+ function dmi(diLength, adxSmoothing, high2, low2, close2) {
1557
+ const len = Math.max(high2.length, low2.length, close2.length);
1558
+ const plusDM = [];
1559
+ const minusDM = [];
1560
+ const trueRangeValues = tr(false, high2, low2, close2);
1561
+ for (let i = 0; i < len; i++) {
1562
+ if (i === 0) {
1563
+ plusDM.push(0);
1564
+ minusDM.push(0);
1565
+ } else {
1566
+ const upMove = high2[i] - high2[i - 1];
1567
+ const downMove = low2[i - 1] - low2[i];
1568
+ let plusDMVal = 0;
1569
+ let minusDMVal = 0;
1570
+ if (upMove > downMove && upMove > 0) {
1571
+ plusDMVal = upMove;
1572
+ }
1573
+ if (downMove > upMove && downMove > 0) {
1574
+ minusDMVal = downMove;
1575
+ }
1576
+ plusDM.push(plusDMVal);
1577
+ minusDM.push(minusDMVal);
1578
+ }
1579
+ }
1580
+ const smoothedPlusDM = rma(plusDM, diLength);
1581
+ const smoothedMinusDM = rma(minusDM, diLength);
1582
+ const smoothedTR = rma(trueRangeValues, diLength);
1583
+ const plusDI = [];
1584
+ const minusDI = [];
1585
+ for (let i = 0; i < len; i++) {
1586
+ if (smoothedTR[i] === 0) {
1587
+ plusDI.push(0);
1588
+ minusDI.push(0);
1589
+ } else {
1590
+ plusDI.push(smoothedPlusDM[i] / smoothedTR[i] * 100);
1591
+ minusDI.push(smoothedMinusDM[i] / smoothedTR[i] * 100);
1592
+ }
1593
+ }
1594
+ const dx = [];
1595
+ for (let i = 0; i < len; i++) {
1596
+ const sum2 = plusDI[i] + minusDI[i];
1597
+ if (sum2 === 0) {
1598
+ dx.push(0);
1599
+ } else {
1600
+ dx.push(Math.abs(plusDI[i] - minusDI[i]) / sum2 * 100);
1601
+ }
1602
+ }
1603
+ const adx = rma(dx, adxSmoothing);
1604
+ return [plusDI, minusDI, adx];
1605
+ }
1606
+ function tsi(source, shortLength, longLength) {
1607
+ const momentum = [];
1608
+ for (let i = 0; i < source.length; i++) {
1609
+ if (i === 0) {
1610
+ momentum.push(NaN);
1611
+ } else {
1612
+ momentum.push(source[i] - source[i - 1]);
1613
+ }
1614
+ }
1615
+ const smoothedMomentum = ema(ema(momentum, longLength), shortLength);
1616
+ const absMomentum = momentum.map(Math.abs);
1617
+ const smoothedAbsMomentum = ema(ema(absMomentum, longLength), shortLength);
1618
+ const result = [];
1619
+ for (let i = 0; i < source.length; i++) {
1620
+ if (smoothedAbsMomentum[i] === 0) {
1621
+ result.push(0);
1622
+ } else {
1623
+ result.push(smoothedMomentum[i] / smoothedAbsMomentum[i] * 100);
1624
+ }
1625
+ }
1626
+ return result;
1627
+ }
1628
+ function cmo(source, length) {
1629
+ const result = [];
1630
+ for (let i = 0; i < source.length; i++) {
1631
+ if (i < length) {
1632
+ result.push(NaN);
1633
+ continue;
1634
+ }
1635
+ let sumGains = 0;
1636
+ let sumLosses = 0;
1637
+ for (let j = 0; j < length; j++) {
1638
+ const change3 = source[i - j] - source[i - j - 1];
1639
+ if (change3 > 0) {
1640
+ sumGains += change3;
1641
+ } else {
1642
+ sumLosses += Math.abs(change3);
1643
+ }
1644
+ }
1645
+ const totalMovement = sumGains + sumLosses;
1646
+ if (totalMovement === 0) {
1647
+ result.push(0);
1648
+ } else {
1649
+ const cmoValue = (sumGains - sumLosses) / totalMovement * 100;
1650
+ result.push(cmoValue);
1651
+ }
1652
+ }
1653
+ return result;
1654
+ }
1655
+ function kc(source, length, mult, useTrueRange = true, high2, low2, close2) {
1656
+ const middle = ema(source, length);
1657
+ let range3;
1658
+ if (useTrueRange) {
1659
+ if (!high2 || !low2 || !close2) {
1660
+ throw new Error("ta.kc() with useTrueRange=true requires high, low, and close data");
1661
+ }
1662
+ range3 = tr(false, high2, low2, close2);
1663
+ } else {
1664
+ if (!high2 || !low2) {
1665
+ throw new Error("ta.kc() requires high and low data");
1666
+ }
1667
+ range3 = [];
1668
+ for (let i = 0; i < high2.length; i++) {
1669
+ range3.push(high2[i] - low2[i]);
1670
+ }
1671
+ }
1672
+ const rangeEma = ema(range3, length);
1673
+ const upper = [];
1674
+ const lower = [];
1675
+ for (let i = 0; i < middle.length; i++) {
1676
+ upper.push(middle[i] + rangeEma[i] * mult);
1677
+ lower.push(middle[i] - rangeEma[i] * mult);
1678
+ }
1679
+ return [middle, upper, lower];
1680
+ }
1681
+ function bbw(source, length, mult) {
1682
+ const [basis, upper, lower] = bb(source, length, mult);
1683
+ const result = [];
1684
+ for (let i = 0; i < source.length; i++) {
1685
+ if (basis[i] === 0) {
1686
+ result.push(NaN);
1687
+ } else {
1688
+ const width = (upper[i] - lower[i]) / basis[i] * 100;
1689
+ result.push(width);
1690
+ }
1691
+ }
1692
+ return result;
1693
+ }
1694
+ function wpr(high2, low2, close2, length = 14) {
1695
+ const result = [];
1696
+ for (let i = 0; i < close2.length; i++) {
1697
+ if (i < length - 1) {
1698
+ result.push(NaN);
1699
+ continue;
1700
+ }
1701
+ let highestHigh = high2[i - length + 1];
1702
+ let lowestLow = low2[i - length + 1];
1703
+ for (let j = i - length + 2; j <= i; j++) {
1704
+ if (high2[j] > highestHigh) highestHigh = high2[j];
1705
+ if (low2[j] < lowestLow) lowestLow = low2[j];
1706
+ }
1707
+ const range3 = highestHigh - lowestLow;
1708
+ if (range3 === 0) {
1709
+ result.push(NaN);
1710
+ } else {
1711
+ const wprValue = (highestHigh - close2[i]) / range3 * -100;
1712
+ result.push(wprValue);
1713
+ }
1714
+ }
1715
+ return result;
1716
+ }
1717
+ function vwap(source, volume2) {
1718
+ if (source.length !== volume2.length) {
1719
+ throw new Error("ta.vwap: source and volume must have the same length");
1720
+ }
1721
+ const result = [];
1722
+ let cumulativePV = 0;
1723
+ let cumulativeVolume = 0;
1724
+ for (let i = 0; i < source.length; i++) {
1725
+ if (isNaN(source[i]) || isNaN(volume2[i])) {
1726
+ result.push(NaN);
1727
+ continue;
1728
+ }
1729
+ cumulativePV += source[i] * volume2[i];
1730
+ cumulativeVolume += volume2[i];
1731
+ if (cumulativeVolume === 0) {
1732
+ result.push(NaN);
1733
+ } else {
1734
+ result.push(cumulativePV / cumulativeVolume);
1735
+ }
1736
+ }
1737
+ return result;
1738
+ }
1739
+ function alma(source, length = 9, offset = 0.85, sigma = 6, floor2 = false) {
1740
+ const result = [];
1741
+ const m = floor2 ? Math.floor(offset * (length - 1)) : offset * (length - 1);
1742
+ const s = length / sigma;
1743
+ const weights = [];
1744
+ let weightSum = 0;
1745
+ for (let i = 0; i < length; i++) {
1746
+ const weight = Math.exp(-1 * Math.pow(i - m, 2) / (2 * Math.pow(s, 2)));
1747
+ weights.push(weight);
1748
+ weightSum += weight;
1749
+ }
1750
+ for (let i = 0; i < length; i++) {
1751
+ weights[i] /= weightSum;
1752
+ }
1753
+ for (let i = 0; i < source.length; i++) {
1754
+ if (i < length - 1) {
1755
+ result.push(NaN);
1756
+ continue;
1757
+ }
1758
+ let almaValue = 0;
1759
+ for (let j = 0; j < length; j++) {
1760
+ almaValue += source[i - length + 1 + j] * weights[j];
1761
+ }
1762
+ result.push(almaValue);
1763
+ }
1764
+ return result;
1765
+ }
1766
+ function kcw(source, length = 20, mult = 2, useTrueRange = true, high2, low2, close2) {
1767
+ const [basis, upper, lower] = kc(source, length, mult, useTrueRange, high2, low2, close2);
1768
+ const result = [];
1769
+ for (let i = 0; i < source.length; i++) {
1770
+ if (isNaN(basis[i]) || basis[i] === 0) {
1771
+ result.push(NaN);
1772
+ } else {
1773
+ const width = (upper[i] - lower[i]) / basis[i] * 100;
1774
+ result.push(width);
1775
+ }
1776
+ }
1777
+ return result;
1778
+ }
1779
+ function range(high2, low2) {
1780
+ if (high2.length !== low2.length) {
1781
+ throw new Error("ta.range: high and low must have the same length");
1782
+ }
1783
+ const result = [];
1784
+ for (let i = 0; i < high2.length; i++) {
1785
+ if (isNaN(high2[i]) || isNaN(low2[i])) {
1786
+ result.push(NaN);
1787
+ } else {
1788
+ result.push(high2[i] - low2[i]);
1789
+ }
1790
+ }
1791
+ return result;
1792
+ }
1793
+ function highestbars(source, length) {
1794
+ const result = [];
1795
+ for (let i = 0; i < source.length; i++) {
1796
+ if (i < length - 1) {
1797
+ result.push(NaN);
1798
+ continue;
1799
+ }
1800
+ let highestValue = source[i - length + 1];
1801
+ let highestOffset = length - 1;
1802
+ for (let j = i - length + 2; j <= i; j++) {
1803
+ if (source[j] > highestValue) {
1804
+ highestValue = source[j];
1805
+ highestOffset = i - j;
1806
+ }
1807
+ }
1808
+ result.push(highestOffset);
1809
+ }
1810
+ return result;
1811
+ }
1812
+ function lowestbars(source, length) {
1813
+ const result = [];
1814
+ for (let i = 0; i < source.length; i++) {
1815
+ if (i < length - 1) {
1816
+ result.push(NaN);
1817
+ continue;
1818
+ }
1819
+ let lowestValue = source[i - length + 1];
1820
+ let lowestOffset = length - 1;
1821
+ for (let j = i - length + 2; j <= i; j++) {
1822
+ if (source[j] < lowestValue) {
1823
+ lowestValue = source[j];
1824
+ lowestOffset = i - j;
1825
+ }
1826
+ }
1827
+ result.push(lowestOffset);
1828
+ }
1829
+ return result;
1830
+ }
1831
+ function max(source1, source2) {
1832
+ if (source1.length !== source2.length) {
1833
+ throw new Error("ta.max: source1 and source2 must have the same length");
1834
+ }
1835
+ const result = [];
1836
+ for (let i = 0; i < source1.length; i++) {
1837
+ if (isNaN(source1[i]) || isNaN(source2[i])) {
1838
+ result.push(NaN);
1839
+ } else {
1840
+ result.push(Math.max(source1[i], source2[i]));
1841
+ }
1842
+ }
1843
+ return result;
1844
+ }
1845
+ function min(source1, source2) {
1846
+ if (source1.length !== source2.length) {
1847
+ throw new Error("ta.min: source1 and source2 must have the same length");
1848
+ }
1849
+ const result = [];
1850
+ for (let i = 0; i < source1.length; i++) {
1851
+ if (isNaN(source1[i]) || isNaN(source2[i])) {
1852
+ result.push(NaN);
1853
+ } else {
1854
+ result.push(Math.min(source1[i], source2[i]));
1855
+ }
1856
+ }
1857
+ return result;
1858
+ }
1859
+ function cog(source, length = 10) {
1860
+ const result = [];
1861
+ for (let i = 0; i < source.length; i++) {
1862
+ if (i < length - 1) {
1863
+ result.push(NaN);
1864
+ continue;
1865
+ }
1866
+ let numerator = 0;
1867
+ let denominator = 0;
1868
+ for (let j = 0; j < length; j++) {
1869
+ const weight = j + 1;
1870
+ const price = source[i - length + 1 + j];
1871
+ numerator += weight * price;
1872
+ denominator += price;
1873
+ }
1874
+ if (denominator === 0) {
1875
+ result.push(NaN);
1876
+ } else {
1877
+ const cog3 = -1 * (numerator / denominator) + (length + 1) / 2;
1878
+ result.push(cog3);
1879
+ }
1880
+ }
1881
+ return result;
1882
+ }
1883
+ function mode(source, length) {
1884
+ const result = [];
1885
+ for (let i = 0; i < source.length; i++) {
1886
+ if (i < length - 1) {
1887
+ result.push(NaN);
1888
+ continue;
1889
+ }
1890
+ const values = [];
1891
+ for (let j = 0; j < length; j++) {
1892
+ const value = source[i - j];
1893
+ if (!isNaN(value)) {
1894
+ values.push(value);
1895
+ }
1896
+ }
1897
+ if (values.length === 0) {
1898
+ result.push(NaN);
1899
+ continue;
1900
+ }
1901
+ const frequencyMap = /* @__PURE__ */ new Map();
1902
+ for (const value of values) {
1903
+ frequencyMap.set(value, (frequencyMap.get(value) || 0) + 1);
1904
+ }
1905
+ let maxFrequency = 0;
1906
+ frequencyMap.forEach((freq) => {
1907
+ if (freq > maxFrequency) {
1908
+ maxFrequency = freq;
1909
+ }
1910
+ });
1911
+ const modesWithMaxFreq = [];
1912
+ frequencyMap.forEach((freq, value) => {
1913
+ if (freq === maxFrequency) {
1914
+ modesWithMaxFreq.push(value);
1915
+ }
1916
+ });
1917
+ result.push(Math.min(...modesWithMaxFreq));
1918
+ }
1919
+ return result;
1920
+ }
1921
+ function percentile_linear_interpolation(source, length, percentage) {
1922
+ const result = [];
1923
+ for (let i = 0; i < source.length; i++) {
1924
+ if (i < length - 1) {
1925
+ result.push(NaN);
1926
+ continue;
1927
+ }
1928
+ const values = [];
1929
+ for (let j = 0; j < length; j++) {
1930
+ const value = source[i - j];
1931
+ values.push(value);
1932
+ }
1933
+ if (values.some((v) => isNaN(v))) {
1934
+ result.push(NaN);
1935
+ continue;
1936
+ }
1937
+ const sorted = [...values].sort((a, b2) => a - b2);
1938
+ const position = percentage / 100 * (sorted.length - 1);
1939
+ const lowerIndex = Math.floor(position);
1940
+ const upperIndex = Math.ceil(position);
1941
+ if (lowerIndex === upperIndex) {
1942
+ result.push(sorted[lowerIndex]);
1943
+ } else {
1944
+ const fraction = position - lowerIndex;
1945
+ const interpolated = sorted[lowerIndex] + fraction * (sorted[upperIndex] - sorted[lowerIndex]);
1946
+ result.push(interpolated);
1947
+ }
1948
+ }
1949
+ return result;
1950
+ }
1951
+ function percentile_nearest_rank(source, length, percentage) {
1952
+ const result = [];
1953
+ for (let i = 0; i < source.length; i++) {
1954
+ if (i < length - 1) {
1955
+ result.push(NaN);
1956
+ continue;
1957
+ }
1958
+ const values = [];
1959
+ for (let j = 0; j < length; j++) {
1960
+ const value = source[i - j];
1961
+ if (!isNaN(value)) {
1962
+ values.push(value);
1963
+ }
1964
+ }
1965
+ if (values.length === 0) {
1966
+ result.push(NaN);
1967
+ continue;
1968
+ }
1969
+ const sorted = [...values].sort((a, b2) => a - b2);
1970
+ if (percentage >= 100) {
1971
+ result.push(sorted[sorted.length - 1]);
1972
+ continue;
1973
+ }
1974
+ const rank = Math.ceil(percentage / 100 * sorted.length);
1975
+ const index = Math.max(0, rank - 1);
1976
+ result.push(sorted[index]);
1977
+ }
1978
+ return result;
1979
+ }
1980
+ function rci(source, length) {
1981
+ const result = [];
1982
+ for (let i = 0; i < source.length; i++) {
1983
+ if (i < length - 1) {
1984
+ result.push(NaN);
1985
+ continue;
1986
+ }
1987
+ const values = [];
1988
+ for (let j = 0; j < length; j++) {
1989
+ values.push(source[i - length + 1 + j]);
1990
+ }
1991
+ if (values.some((v) => isNaN(v))) {
1992
+ result.push(NaN);
1993
+ continue;
1994
+ }
1995
+ const indexed = values.map((value, index) => ({ value, index }));
1996
+ const sorted = [...indexed].sort((a, b2) => a.value - b2.value);
1997
+ const ranks = new Array(length).fill(0);
1998
+ let currentRank = 1;
1999
+ for (let j = 0; j < sorted.length; j++) {
2000
+ let tieCount = 1;
2001
+ while (j + tieCount < sorted.length && sorted[j].value === sorted[j + tieCount].value) {
2002
+ tieCount++;
2003
+ }
2004
+ const avgRank = (currentRank + (currentRank + tieCount - 1)) / 2;
2005
+ for (let k = 0; k < tieCount; k++) {
2006
+ ranks[sorted[j + k].index] = avgRank;
2007
+ }
2008
+ j += tieCount - 1;
2009
+ currentRank += tieCount;
2010
+ }
2011
+ let sumSquaredDiff = 0;
2012
+ for (let j = 0; j < length; j++) {
2013
+ const timeRank = j + 1;
2014
+ const diff = ranks[j] - timeRank;
2015
+ sumSquaredDiff += diff * diff;
2016
+ }
2017
+ const n = length;
2018
+ const base = (n * n * n - n) / 12;
2019
+ let tieCorrection = 0;
2020
+ for (let j = 0; j < sorted.length; ) {
2021
+ let tieCount = 1;
2022
+ while (j + tieCount < sorted.length && sorted[j].value === sorted[j + tieCount].value) {
2023
+ tieCount++;
2024
+ }
2025
+ if (tieCount > 1) {
2026
+ tieCorrection += (tieCount * tieCount * tieCount - tieCount) / 12;
2027
+ }
2028
+ j += tieCount;
2029
+ }
2030
+ const A = base - tieCorrection;
2031
+ const B = base;
2032
+ let rho;
2033
+ if (A === 0 || B === 0) {
2034
+ rho = 0;
2035
+ } else {
2036
+ rho = (A + B - sumSquaredDiff) / (2 * Math.sqrt(A * B));
2037
+ }
2038
+ result.push(rho * 100);
2039
+ }
2040
+ return result;
2041
+ }
2042
+ function ichimoku(conversionPeriods, basePeriods, laggingSpan2Periods, displacement, high2, low2, close2) {
2043
+ const length = high2.length;
2044
+ const highestConversion = highest(high2, conversionPeriods);
2045
+ const lowestConversion = lowest(low2, conversionPeriods);
2046
+ const tenkanSen = [];
2047
+ for (let i = 0; i < length; i++) {
2048
+ if (isNaN(highestConversion[i]) || isNaN(lowestConversion[i])) {
2049
+ tenkanSen.push(NaN);
2050
+ } else {
2051
+ tenkanSen.push((highestConversion[i] + lowestConversion[i]) / 2);
2052
+ }
2053
+ }
2054
+ const highestBase = highest(high2, basePeriods);
2055
+ const lowestBase = lowest(low2, basePeriods);
2056
+ const kijunSen = [];
2057
+ for (let i = 0; i < length; i++) {
2058
+ if (isNaN(highestBase[i]) || isNaN(lowestBase[i])) {
2059
+ kijunSen.push(NaN);
2060
+ } else {
2061
+ kijunSen.push((highestBase[i] + lowestBase[i]) / 2);
2062
+ }
2063
+ }
2064
+ const senkouSpanA = [];
2065
+ for (let i = 0; i < length; i++) {
2066
+ const sourceIndex = i - displacement;
2067
+ if (sourceIndex < 0 || isNaN(tenkanSen[sourceIndex]) || isNaN(kijunSen[sourceIndex])) {
2068
+ senkouSpanA.push(NaN);
2069
+ } else {
2070
+ senkouSpanA.push((tenkanSen[sourceIndex] + kijunSen[sourceIndex]) / 2);
2071
+ }
2072
+ }
2073
+ const highestLagging = highest(high2, laggingSpan2Periods);
2074
+ const lowestLagging = lowest(low2, laggingSpan2Periods);
2075
+ const senkouSpanB = [];
2076
+ for (let i = 0; i < length; i++) {
2077
+ const sourceIndex = i - displacement;
2078
+ if (sourceIndex < 0 || isNaN(highestLagging[sourceIndex]) || isNaN(lowestLagging[sourceIndex])) {
2079
+ senkouSpanB.push(NaN);
2080
+ } else {
2081
+ senkouSpanB.push((highestLagging[sourceIndex] + lowestLagging[sourceIndex]) / 2);
2082
+ }
2083
+ }
2084
+ const chikouSpan = [];
2085
+ for (let i = 0; i < length; i++) {
2086
+ const sourceIndex = i + displacement;
2087
+ if (sourceIndex >= length || isNaN(close2[sourceIndex])) {
2088
+ chikouSpan.push(NaN);
2089
+ } else {
2090
+ chikouSpan.push(close2[sourceIndex]);
2091
+ }
2092
+ }
2093
+ return [tenkanSen, kijunSen, senkouSpanA, senkouSpanB, chikouSpan];
2094
+ }
2095
+ function zigzag(deviation = 5, depth = 10, backstep = 3, source, high2, low2) {
2096
+ let highSource;
2097
+ let lowSource;
2098
+ if (high2 && low2) {
2099
+ highSource = high2;
2100
+ lowSource = low2;
2101
+ } else if (source) {
2102
+ highSource = source;
2103
+ lowSource = source;
2104
+ } else {
2105
+ throw new Error(
2106
+ "ta.zigzag() requires either source series or high/low series. Either pass them explicitly or use createContext({ chart: { high, low, close } }) for implicit data."
2107
+ );
2108
+ }
2109
+ const length = highSource.length;
2110
+ if (lowSource.length !== length) {
2111
+ throw new Error("ta.zigzag: high and low must have the same length");
2112
+ }
2113
+ const zigzagValues = new Array(length).fill(NaN);
2114
+ const directions = new Array(length).fill(0);
2115
+ const isPivot = new Array(length).fill(false);
2116
+ const getDeviation = (price1, price2) => {
2117
+ if (Math.abs(price1) < 1e-10 || isNaN(price1) || isNaN(price2)) return 0;
2118
+ return Math.abs((price2 - price1) / price1) * 100;
2119
+ };
2120
+ let lastConfirmedPivot = null;
2121
+ let potentialPivot = null;
2122
+ let currentDirection = 0;
2123
+ const confirmedPivots = [];
2124
+ let startIndex;
2125
+ let initialHighest = -Infinity;
2126
+ let initialLowest = Infinity;
2127
+ let initialHighIndex = -1;
2128
+ let initialLowIndex = -1;
2129
+ for (let i = 0; i < Math.min(depth, length); i++) {
2130
+ if (!isNaN(highSource[i]) && highSource[i] > initialHighest) {
2131
+ initialHighest = highSource[i];
2132
+ initialHighIndex = i;
2133
+ }
2134
+ if (!isNaN(lowSource[i]) && lowSource[i] < initialLowest) {
2135
+ initialLowest = lowSource[i];
2136
+ initialLowIndex = i;
2137
+ }
2138
+ }
2139
+ if (initialHighIndex >= 0 && initialLowIndex >= 0) {
2140
+ if (initialLowIndex <= initialHighIndex) {
2141
+ lastConfirmedPivot = { index: initialLowIndex, price: initialLowest, type: "low" };
2142
+ currentDirection = 1;
2143
+ } else {
2144
+ lastConfirmedPivot = { index: initialHighIndex, price: initialHighest, type: "high" };
2145
+ currentDirection = -1;
2146
+ }
2147
+ confirmedPivots.push(lastConfirmedPivot);
2148
+ startIndex = lastConfirmedPivot.index + 1;
2149
+ } else {
2150
+ startIndex = depth;
2151
+ }
2152
+ for (let i = Math.max(startIndex, depth); i < length; i++) {
2153
+ const currentHigh = highSource[i];
2154
+ const currentLow = lowSource[i];
2155
+ if (isNaN(currentHigh) || isNaN(currentLow)) {
2156
+ directions[i] = currentDirection;
2157
+ continue;
2158
+ }
2159
+ let isPotentialHigh = true;
2160
+ for (let j = 1; j <= backstep && i - j >= 0; j++) {
2161
+ if (!isNaN(highSource[i - j]) && highSource[i - j] >= currentHigh) {
2162
+ isPotentialHigh = false;
2163
+ break;
2164
+ }
2165
+ }
2166
+ let isPotentialLow = true;
2167
+ for (let j = 1; j <= backstep && i - j >= 0; j++) {
2168
+ if (!isNaN(lowSource[i - j]) && lowSource[i - j] <= currentLow) {
2169
+ isPotentialLow = false;
2170
+ break;
2171
+ }
2172
+ }
2173
+ if (currentDirection === 1) {
2174
+ if (isPotentialHigh) {
2175
+ if (potentialPivot === null || potentialPivot.type !== "high") {
2176
+ if (lastConfirmedPivot && getDeviation(lastConfirmedPivot.price, currentHigh) >= deviation) {
2177
+ potentialPivot = { index: i, price: currentHigh, type: "high" };
2178
+ }
2179
+ } else {
2180
+ if (currentHigh > potentialPivot.price) {
2181
+ potentialPivot = { index: i, price: currentHigh, type: "high" };
2182
+ }
2183
+ }
2184
+ }
2185
+ if (potentialPivot && potentialPivot.type === "high") {
2186
+ const deviationFromPotential = getDeviation(potentialPivot.price, currentLow);
2187
+ if (deviationFromPotential >= deviation && i - potentialPivot.index >= backstep) {
2188
+ confirmedPivots.push(potentialPivot);
2189
+ lastConfirmedPivot = potentialPivot;
2190
+ currentDirection = -1;
2191
+ potentialPivot = null;
2192
+ }
2193
+ }
2194
+ } else if (currentDirection === -1) {
2195
+ if (isPotentialLow) {
2196
+ if (potentialPivot === null || potentialPivot.type !== "low") {
2197
+ if (lastConfirmedPivot && getDeviation(lastConfirmedPivot.price, currentLow) >= deviation) {
2198
+ potentialPivot = { index: i, price: currentLow, type: "low" };
2199
+ }
2200
+ } else {
2201
+ if (currentLow < potentialPivot.price) {
2202
+ potentialPivot = { index: i, price: currentLow, type: "low" };
2203
+ }
2204
+ }
2205
+ }
2206
+ if (potentialPivot && potentialPivot.type === "low") {
2207
+ const deviationFromPotential = getDeviation(potentialPivot.price, currentHigh);
2208
+ if (deviationFromPotential >= deviation && i - potentialPivot.index >= backstep) {
2209
+ confirmedPivots.push(potentialPivot);
2210
+ lastConfirmedPivot = potentialPivot;
2211
+ currentDirection = 1;
2212
+ potentialPivot = null;
2213
+ }
2214
+ }
2215
+ } else {
2216
+ if (lastConfirmedPivot) {
2217
+ if (lastConfirmedPivot.type === "low" && getDeviation(lastConfirmedPivot.price, currentHigh) >= deviation) {
2218
+ currentDirection = 1;
2219
+ } else if (lastConfirmedPivot.type === "high" && getDeviation(lastConfirmedPivot.price, currentLow) >= deviation) {
2220
+ currentDirection = -1;
2221
+ }
2222
+ }
2223
+ }
2224
+ directions[i] = currentDirection;
2225
+ }
2226
+ const lastPotentialWasAdded = potentialPivot !== null;
2227
+ if (potentialPivot) {
2228
+ confirmedPivots.push(potentialPivot);
2229
+ }
2230
+ for (const pivot of confirmedPivots) {
2231
+ zigzagValues[pivot.index] = pivot.price;
2232
+ isPivot[pivot.index] = true;
2233
+ }
2234
+ let currentDir = 0;
2235
+ let pivotIdx = 0;
2236
+ const numConfirmed = lastPotentialWasAdded ? confirmedPivots.length - 1 : confirmedPivots.length;
2237
+ for (let i = 0; i < length; i++) {
2238
+ while (pivotIdx < numConfirmed && confirmedPivots[pivotIdx].index <= i) {
2239
+ const pivot = confirmedPivots[pivotIdx];
2240
+ currentDir = pivot.type === "low" ? 1 : -1;
2241
+ pivotIdx++;
2242
+ }
2243
+ directions[i] = currentDir;
2244
+ }
2245
+ return [zigzagValues, directions, isPivot];
2246
+ }
2247
+
2248
+ // src/ta-series.ts
2249
+ function sma2(source, length) {
2250
+ const bars2 = source.bars;
2251
+ const sourceValues = source.toArray();
2252
+ const result = sma(sourceValues, length);
2253
+ return Series.fromArray(bars2, result);
2254
+ }
2255
+ function ema2(source, length) {
2256
+ const bars2 = source.bars;
2257
+ const sourceValues = source.toArray();
2258
+ const result = ema(sourceValues, length);
2259
+ return Series.fromArray(bars2, result);
2260
+ }
2261
+ function wma2(source, length) {
2262
+ const bars2 = source.bars;
2263
+ const sourceValues = source.toArray();
2264
+ const result = wma(sourceValues, length);
2265
+ return Series.fromArray(bars2, result);
2266
+ }
2267
+ function rma2(source, length) {
2268
+ const bars2 = source.bars;
2269
+ const sourceValues = source.toArray();
2270
+ const result = rma(sourceValues, length);
2271
+ return Series.fromArray(bars2, result);
2272
+ }
2273
+ function rsi2(source, length) {
2274
+ const bars2 = source.bars;
2275
+ const sourceValues = source.toArray();
2276
+ const result = rsi(sourceValues, length);
2277
+ return Series.fromArray(bars2, result);
2278
+ }
2279
+ function macd2(source, fastLength, slowLength, signalLength) {
2280
+ const bars2 = source.bars;
2281
+ const sourceValues = source.toArray();
2282
+ const [macdVals, signalVals, histVals] = macd(sourceValues, fastLength, slowLength, signalLength);
2283
+ const macdSeries = Series.fromArray(bars2, macdVals);
2284
+ const signalSeries = Series.fromArray(bars2, signalVals);
2285
+ const histSeries = Series.fromArray(bars2, histVals);
2286
+ return [macdSeries, signalSeries, histSeries];
2287
+ }
2288
+ function bb2(source, length, mult) {
2289
+ const bars2 = source.bars;
2290
+ const sourceValues = source.toArray();
2291
+ const [upperVals, basisVals, lowerVals] = bb(sourceValues, length, mult);
2292
+ const upperSeries = Series.fromArray(bars2, upperVals);
2293
+ const basisSeries = Series.fromArray(bars2, basisVals);
2294
+ const lowerSeries = Series.fromArray(bars2, lowerVals);
2295
+ return [upperSeries, basisSeries, lowerSeries];
2296
+ }
2297
+ function stdev2(source, length) {
2298
+ const bars2 = source.bars;
2299
+ const sourceValues = source.toArray();
2300
+ const result = stdev(sourceValues, length);
2301
+ return Series.fromArray(bars2, result);
2302
+ }
2303
+ function atr2(bars2, length) {
2304
+ const high2 = bars2.map((b2) => b2.high);
2305
+ const low2 = bars2.map((b2) => b2.low);
2306
+ const close2 = bars2.map((b2) => b2.close);
2307
+ const result = atr(length, high2, low2, close2);
2308
+ return Series.fromArray(bars2, result);
2309
+ }
2310
+ function tr2(bars2, handle_na = false) {
2311
+ const high2 = bars2.map((b2) => b2.high);
2312
+ const low2 = bars2.map((b2) => b2.low);
2313
+ const close2 = bars2.map((b2) => b2.close);
2314
+ const result = tr(handle_na, high2, low2, close2);
2315
+ return Series.fromArray(bars2, result);
2316
+ }
2317
+ function stoch2(source, high2, low2, length) {
2318
+ const bars2 = source.bars;
2319
+ const sourceValues = source.toArray();
2320
+ const highValues = high2.toArray();
2321
+ const lowValues = low2.toArray();
2322
+ const result = stoch(sourceValues, highValues, lowValues, length);
2323
+ return Series.fromArray(bars2, result);
2324
+ }
2325
+ function crossover2(source1, source2) {
2326
+ const bars2 = source1.bars;
2327
+ const vals1 = source1.toArray();
2328
+ const vals2 = typeof source2 === "number" ? Array(bars2.length).fill(source2) : source2.toArray();
2329
+ const result = crossover(vals1, vals2);
2330
+ const numResult = result.map((b2) => b2 ? 1 : 0);
2331
+ return Series.fromArray(bars2, numResult);
2332
+ }
2333
+ function crossunder2(source1, source2) {
2334
+ const bars2 = source1.bars;
2335
+ const vals1 = source1.toArray();
2336
+ const vals2 = typeof source2 === "number" ? Array(bars2.length).fill(source2) : source2.toArray();
2337
+ const result = crossunder(vals1, vals2);
2338
+ const numResult = result.map((b2) => b2 ? 1 : 0);
2339
+ return Series.fromArray(bars2, numResult);
2340
+ }
2341
+ function cross2(source1, source2) {
2342
+ const bars2 = source1.bars;
2343
+ const vals1 = source1.toArray();
2344
+ const vals2 = typeof source2 === "number" ? Array(bars2.length).fill(source2) : source2.toArray();
2345
+ const result = cross(vals1, vals2);
2346
+ const numResult = result.map((b2) => b2 ? 1 : 0);
2347
+ return Series.fromArray(bars2, numResult);
2348
+ }
2349
+ function change2(source, length = 1) {
2350
+ const bars2 = source.bars;
2351
+ const sourceValues = source.toArray();
2352
+ const result = change(sourceValues, length);
2353
+ return Series.fromArray(bars2, result);
2354
+ }
2355
+ function mom2(source, length) {
2356
+ const bars2 = source.bars;
2357
+ const sourceValues = source.toArray();
2358
+ const result = mom(sourceValues, length);
2359
+ return Series.fromArray(bars2, result);
2360
+ }
2361
+ function roc2(source, length) {
2362
+ const bars2 = source.bars;
2363
+ const sourceValues = source.toArray();
2364
+ const result = roc(sourceValues, length);
2365
+ return Series.fromArray(bars2, result);
2366
+ }
2367
+ function highest2(source, length) {
2368
+ const bars2 = source.bars;
2369
+ const sourceValues = source.toArray();
2370
+ const result = highest(sourceValues, length);
2371
+ return Series.fromArray(bars2, result);
2372
+ }
2373
+ function lowest2(source, length) {
2374
+ const bars2 = source.bars;
2375
+ const sourceValues = source.toArray();
2376
+ const result = lowest(sourceValues, length);
2377
+ return Series.fromArray(bars2, result);
2378
+ }
2379
+ function rising2(source, length) {
2380
+ const bars2 = source.bars;
2381
+ const sourceValues = source.toArray();
2382
+ const result = rising(sourceValues, length);
2383
+ const numResult = result.map((b2) => b2 ? 1 : 0);
2384
+ return Series.fromArray(bars2, numResult);
2385
+ }
2386
+ function falling2(source, length) {
2387
+ const bars2 = source.bars;
2388
+ const sourceValues = source.toArray();
2389
+ const result = falling(sourceValues, length);
2390
+ const numResult = result.map((b2) => b2 ? 1 : 0);
2391
+ return Series.fromArray(bars2, numResult);
2392
+ }
2393
+ function cum2(source) {
2394
+ const bars2 = source.bars;
2395
+ const sourceValues = source.toArray();
2396
+ const result = cum(sourceValues);
2397
+ return Series.fromArray(bars2, result);
2398
+ }
2399
+ function supertrend2(bars2, factor, atrLength) {
2400
+ const high2 = bars2.map((b2) => b2.high);
2401
+ const low2 = bars2.map((b2) => b2.low);
2402
+ const close2 = bars2.map((b2) => b2.close);
2403
+ const [trendVals, dirVals] = supertrend(factor, atrLength, high2, low2, close2);
2404
+ const trendSeries = Series.fromArray(bars2, trendVals);
2405
+ const dirSeries = Series.fromArray(bars2, dirVals);
2406
+ return [trendSeries, dirSeries];
2407
+ }
2408
+ function vwap2(source, volume2) {
2409
+ const bars2 = source.bars;
2410
+ const sourceValues = source.toArray();
2411
+ const volumeValues = volume2.toArray();
2412
+ const result = vwap(sourceValues, volumeValues);
2413
+ return Series.fromArray(bars2, result);
2414
+ }
2415
+ function ichimoku2(bars2, conversionPeriods, basePeriods, laggingSpan2Periods, displacement) {
2416
+ const high2 = bars2.map((b2) => b2.high);
2417
+ const low2 = bars2.map((b2) => b2.low);
2418
+ const close2 = bars2.map((b2) => b2.close);
2419
+ const [tenkan, kijun, senkouA, senkouB, chikou] = ichimoku(
2420
+ conversionPeriods,
2421
+ basePeriods,
2422
+ laggingSpan2Periods,
2423
+ displacement,
2424
+ high2,
2425
+ low2,
2426
+ close2
2427
+ );
2428
+ return [
2429
+ Series.fromArray(bars2, tenkan),
2430
+ Series.fromArray(bars2, kijun),
2431
+ Series.fromArray(bars2, senkouA),
2432
+ Series.fromArray(bars2, senkouB),
2433
+ Series.fromArray(bars2, chikou)
2434
+ ];
2435
+ }
2436
+ function vwma2(source, length, volume2) {
2437
+ const bars2 = source.bars;
2438
+ const sourceValues = source.toArray();
2439
+ const volumeValues = volume2.toArray();
2440
+ const result = vwma(sourceValues, length, volumeValues);
2441
+ return Series.fromArray(bars2, result);
2442
+ }
2443
+ function linreg2(source, length, offset = 0) {
2444
+ const bars2 = source.bars;
2445
+ const sourceValues = source.toArray();
2446
+ const result = linreg(sourceValues, length, offset);
2447
+ return Series.fromArray(bars2, result);
2448
+ }
2449
+ function alma2(source, length = 9, offset = 0.85, sigma = 6, floor2 = false) {
2450
+ const bars2 = source.bars;
2451
+ const sourceValues = source.toArray();
2452
+ const result = alma(sourceValues, length, offset, sigma, floor2);
2453
+ return Series.fromArray(bars2, result);
2454
+ }
2455
+ function zigzag2(bars2, deviation = 5, depth = 10, backstep = 3) {
2456
+ const high2 = bars2.map((b2) => b2.high);
2457
+ const low2 = bars2.map((b2) => b2.low);
2458
+ const [zigzagVals, dirVals, pivotVals] = zigzag(
2459
+ deviation,
2460
+ depth,
2461
+ backstep,
2462
+ void 0,
2463
+ high2,
2464
+ low2
2465
+ );
2466
+ return [
2467
+ Series.fromArray(bars2, zigzagVals),
2468
+ Series.fromArray(bars2, dirVals),
2469
+ Series.fromArray(bars2, pivotVals.map((b2) => b2 ? 1 : 0))
2470
+ ];
2471
+ }
2472
+ function cci2(source, length) {
2473
+ const bars2 = source.bars;
2474
+ const sourceValues = source.toArray();
2475
+ const result = cci(sourceValues, length);
2476
+ return Series.fromArray(bars2, result);
2477
+ }
2478
+ function sar2(bars2, start = 0.02, inc = 0.02, max4 = 0.2) {
2479
+ const high2 = bars2.map((b2) => b2.high);
2480
+ const low2 = bars2.map((b2) => b2.low);
2481
+ const close2 = bars2.map((b2) => b2.close);
2482
+ const result = sar(start, inc, max4, high2, low2, close2);
2483
+ return Series.fromArray(bars2, result);
2484
+ }
2485
+ function dev2(source, length) {
2486
+ const bars2 = source.bars;
2487
+ const result = dev(source.toArray(), length);
2488
+ return Series.fromArray(bars2, result);
2489
+ }
2490
+ function variance2(source, length, biased = true) {
2491
+ const bars2 = source.bars;
2492
+ const result = variance(source.toArray(), length, biased);
2493
+ return Series.fromArray(bars2, result);
2494
+ }
2495
+ function median2(source, length) {
2496
+ const bars2 = source.bars;
2497
+ const result = median(source.toArray(), length);
2498
+ return Series.fromArray(bars2, result);
2499
+ }
2500
+ function swma2(source) {
2501
+ const bars2 = source.bars;
2502
+ const result = swma(source.toArray());
2503
+ return Series.fromArray(bars2, result);
2504
+ }
2505
+ function correlation2(source1, source2, length) {
2506
+ const bars2 = source1.bars;
2507
+ const result = correlation(source1.toArray(), source2.toArray(), length);
2508
+ return Series.fromArray(bars2, result);
2509
+ }
2510
+ function percentrank2(source, length) {
2511
+ const bars2 = source.bars;
2512
+ const result = percentrank(source.toArray(), length);
2513
+ return Series.fromArray(bars2, result);
2514
+ }
2515
+ function mfi2(source, length, volume2) {
2516
+ const bars2 = source.bars;
2517
+ const result = mfi(source.toArray(), length, volume2.toArray());
2518
+ return Series.fromArray(bars2, result);
2519
+ }
2520
+ function hma2(source, length) {
2521
+ const bars2 = source.bars;
2522
+ const result = hma(source.toArray(), length);
2523
+ return Series.fromArray(bars2, result);
2524
+ }
2525
+ function pivothigh2(source, leftbars, rightbars) {
2526
+ const bars2 = source.bars;
2527
+ const result = pivothigh(source.toArray(), leftbars, rightbars);
2528
+ return Series.fromArray(bars2, result);
2529
+ }
2530
+ function pivotlow2(source, leftbars, rightbars) {
2531
+ const bars2 = source.bars;
2532
+ const result = pivotlow(source.toArray(), leftbars, rightbars);
2533
+ return Series.fromArray(bars2, result);
2534
+ }
2535
+ function barssince2(condition) {
2536
+ const bars2 = condition.bars;
2537
+ const boolValues = condition.toArray().map((v) => v === 1);
2538
+ const result = barssince(boolValues);
2539
+ return Series.fromArray(bars2, result);
2540
+ }
2541
+ function valuewhen2(condition, source, occurrence) {
2542
+ const bars2 = condition.bars;
2543
+ const boolValues = condition.toArray().map((v) => v === 1);
2544
+ const result = valuewhen(boolValues, source.toArray(), occurrence);
2545
+ return Series.fromArray(bars2, result);
2546
+ }
2547
+ function dmi2(bars2, diLength, adxSmoothing) {
2548
+ const high2 = bars2.map((b2) => b2.high);
2549
+ const low2 = bars2.map((b2) => b2.low);
2550
+ const close2 = bars2.map((b2) => b2.close);
2551
+ const [plusDI, minusDI, adx] = dmi(diLength, adxSmoothing, high2, low2, close2);
2552
+ return [
2553
+ Series.fromArray(bars2, plusDI),
2554
+ Series.fromArray(bars2, minusDI),
2555
+ Series.fromArray(bars2, adx)
2556
+ ];
2557
+ }
2558
+ function tsi2(source, shortLength, longLength) {
2559
+ const bars2 = source.bars;
2560
+ const result = tsi(source.toArray(), shortLength, longLength);
2561
+ return Series.fromArray(bars2, result);
2562
+ }
2563
+ function cmo2(source, length) {
2564
+ const bars2 = source.bars;
2565
+ const result = cmo(source.toArray(), length);
2566
+ return Series.fromArray(bars2, result);
2567
+ }
2568
+ function kc2(bars2, source, length, mult, useTrueRange = true) {
2569
+ const high2 = bars2.map((b2) => b2.high);
2570
+ const low2 = bars2.map((b2) => b2.low);
2571
+ const close2 = bars2.map((b2) => b2.close);
2572
+ const [middle, upper, lower] = kc(source.toArray(), length, mult, useTrueRange, high2, low2, close2);
2573
+ return [
2574
+ Series.fromArray(bars2, middle),
2575
+ Series.fromArray(bars2, upper),
2576
+ Series.fromArray(bars2, lower)
2577
+ ];
2578
+ }
2579
+ function bbw2(source, length, mult) {
2580
+ const bars2 = source.bars;
2581
+ const result = bbw(source.toArray(), length, mult);
2582
+ return Series.fromArray(bars2, result);
2583
+ }
2584
+ function wpr2(bars2, length = 14) {
2585
+ const high2 = bars2.map((b2) => b2.high);
2586
+ const low2 = bars2.map((b2) => b2.low);
2587
+ const close2 = bars2.map((b2) => b2.close);
2588
+ const result = wpr(high2, low2, close2, length);
2589
+ return Series.fromArray(bars2, result);
2590
+ }
2591
+ function kcw2(bars2, source, length = 20, mult = 2, useTrueRange = true) {
2592
+ const high2 = bars2.map((b2) => b2.high);
2593
+ const low2 = bars2.map((b2) => b2.low);
2594
+ const close2 = bars2.map((b2) => b2.close);
2595
+ const result = kcw(source.toArray(), length, mult, useTrueRange, high2, low2, close2);
2596
+ return Series.fromArray(bars2, result);
2597
+ }
2598
+ function range2(high2, low2) {
2599
+ const bars2 = high2.bars;
2600
+ const result = range(high2.toArray(), low2.toArray());
2601
+ return Series.fromArray(bars2, result);
2602
+ }
2603
+ function highestbars2(source, length) {
2604
+ const bars2 = source.bars;
2605
+ const result = highestbars(source.toArray(), length);
2606
+ return Series.fromArray(bars2, result);
2607
+ }
2608
+ function lowestbars2(source, length) {
2609
+ const bars2 = source.bars;
2610
+ const result = lowestbars(source.toArray(), length);
2611
+ return Series.fromArray(bars2, result);
2612
+ }
2613
+ function max2(source1, source2) {
2614
+ const bars2 = source1.bars;
2615
+ const result = max(source1.toArray(), source2.toArray());
2616
+ return Series.fromArray(bars2, result);
2617
+ }
2618
+ function min2(source1, source2) {
2619
+ const bars2 = source1.bars;
2620
+ const result = min(source1.toArray(), source2.toArray());
2621
+ return Series.fromArray(bars2, result);
2622
+ }
2623
+ function cog2(source, length = 10) {
2624
+ const bars2 = source.bars;
2625
+ const result = cog(source.toArray(), length);
2626
+ return Series.fromArray(bars2, result);
2627
+ }
2628
+ function mode2(source, length) {
2629
+ const bars2 = source.bars;
2630
+ const result = mode(source.toArray(), length);
2631
+ return Series.fromArray(bars2, result);
2632
+ }
2633
+ function percentile_linear_interpolation2(source, length, percentage) {
2634
+ const bars2 = source.bars;
2635
+ const result = percentile_linear_interpolation(source.toArray(), length, percentage);
2636
+ return Series.fromArray(bars2, result);
2637
+ }
2638
+ function percentile_nearest_rank2(source, length, percentage) {
2639
+ const bars2 = source.bars;
2640
+ const result = percentile_nearest_rank(source.toArray(), length, percentage);
2641
+ return Series.fromArray(bars2, result);
2642
+ }
2643
+ function rci2(source, length) {
2644
+ const bars2 = source.bars;
2645
+ const result = rci(source.toArray(), length);
2646
+ return Series.fromArray(bars2, result);
2647
+ }
2648
+ var ta = {
2649
+ sma: sma2,
2650
+ ema: ema2,
2651
+ wma: wma2,
2652
+ vwma: vwma2,
2653
+ rma: rma2,
2654
+ rsi: rsi2,
2655
+ macd: macd2,
2656
+ bb: bb2,
2657
+ stdev: stdev2,
2658
+ atr: atr2,
2659
+ tr: tr2,
2660
+ stoch: stoch2,
2661
+ crossover: crossover2,
2662
+ crossunder: crossunder2,
2663
+ cross: cross2,
2664
+ change: change2,
2665
+ mom: mom2,
2666
+ roc: roc2,
2667
+ highest: highest2,
2668
+ lowest: lowest2,
2669
+ rising: rising2,
2670
+ falling: falling2,
2671
+ cum: cum2,
2672
+ supertrend: supertrend2,
2673
+ vwap: vwap2,
2674
+ ichimoku: ichimoku2,
2675
+ linreg: linreg2,
2676
+ alma: alma2,
2677
+ zigzag: zigzag2,
2678
+ cci: cci2,
2679
+ sar: sar2,
2680
+ dev: dev2,
2681
+ variance: variance2,
2682
+ median: median2,
2683
+ swma: swma2,
2684
+ correlation: correlation2,
2685
+ percentrank: percentrank2,
2686
+ mfi: mfi2,
2687
+ hma: hma2,
2688
+ pivothigh: pivothigh2,
2689
+ pivotlow: pivotlow2,
2690
+ barssince: barssince2,
2691
+ valuewhen: valuewhen2,
2692
+ dmi: dmi2,
2693
+ tsi: tsi2,
2694
+ cmo: cmo2,
2695
+ kc: kc2,
2696
+ bbw: bbw2,
2697
+ wpr: wpr2,
2698
+ kcw: kcw2,
2699
+ range: range2,
2700
+ highestbars: highestbars2,
2701
+ lowestbars: lowestbars2,
2702
+ max: max2,
2703
+ min: min2,
2704
+ cog: cog2,
2705
+ mode: mode2,
2706
+ percentile_linear_interpolation: percentile_linear_interpolation2,
2707
+ percentile_nearest_rank: percentile_nearest_rank2,
2708
+ rci: rci2
2709
+ };
2710
+
2711
+ // src/color/index.ts
2712
+ var color_exports = {};
2713
+ __export(color_exports, {
2714
+ aqua: () => aqua,
2715
+ b: () => b,
2716
+ black: () => black,
2717
+ blue: () => blue,
2718
+ from_gradient: () => from_gradient,
2719
+ from_hex: () => from_hex,
2720
+ fuchsia: () => fuchsia,
2721
+ g: () => g,
2722
+ gray: () => gray,
2723
+ green: () => green,
2724
+ lime: () => lime,
2725
+ maroon: () => maroon,
2726
+ navy: () => navy,
2727
+ new: () => new_color,
2728
+ new_color: () => new_color,
2729
+ olive: () => olive,
2730
+ orange: () => orange,
2731
+ purple: () => purple,
2732
+ r: () => r,
2733
+ red: () => red,
2734
+ rgb: () => rgb,
2735
+ silver: () => silver,
2736
+ t: () => t,
2737
+ teal: () => teal,
2738
+ white: () => white,
2739
+ yellow: () => yellow
2740
+ });
2741
+ function rgb(red2, green2, blue2, transp) {
2742
+ const r2 = Math.max(0, Math.min(255, red2));
2743
+ const g2 = Math.max(0, Math.min(255, green2));
2744
+ const b2 = Math.max(0, Math.min(255, blue2));
2745
+ const a = transp !== void 0 ? 1 - transp / 100 : 1;
2746
+ if (a === 1) {
2747
+ return `rgb(${r2}, ${g2}, ${b2})`;
2748
+ }
2749
+ return `rgba(${r2}, ${g2}, ${b2}, ${a})`;
2750
+ }
2751
+ function from_hex(hex, transp) {
2752
+ hex = hex.replace("#", "");
2753
+ const r2 = parseInt(hex.substring(0, 2), 16);
2754
+ const g2 = parseInt(hex.substring(2, 4), 16);
2755
+ const b2 = parseInt(hex.substring(4, 6), 16);
2756
+ return rgb(r2, g2, b2, transp);
2757
+ }
2758
+ function new_color(baseColor, transp) {
2759
+ const rgba = parseColor(baseColor);
2760
+ return rgb(rgba.r, rgba.g, rgba.b, transp);
2761
+ }
2762
+ function r(clr) {
2763
+ return parseColor(clr).r;
2764
+ }
2765
+ function g(clr) {
2766
+ return parseColor(clr).g;
2767
+ }
2768
+ function b(clr) {
2769
+ return parseColor(clr).b;
2770
+ }
2771
+ function t(clr) {
2772
+ return parseColor(clr).t;
2773
+ }
2774
+ function parseColor(clr) {
2775
+ if (typeof clr === "string") {
2776
+ const match = clr.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);
2777
+ if (match) {
2778
+ return {
2779
+ r: parseInt(match[1]),
2780
+ g: parseInt(match[2]),
2781
+ b: parseInt(match[3]),
2782
+ t: match[4] ? (1 - parseFloat(match[4])) * 100 : 0
2783
+ };
2784
+ }
2785
+ }
2786
+ return { r: 0, g: 0, b: 0, t: 0 };
2787
+ }
2788
+ var aqua = "#00FFFF";
2789
+ var black = "#000000";
2790
+ var blue = "#0000FF";
2791
+ var fuchsia = "#FF00FF";
2792
+ var gray = "#808080";
2793
+ var green = "#00FF00";
2794
+ var lime = "#00FF00";
2795
+ var maroon = "#800000";
2796
+ var navy = "#000080";
2797
+ var olive = "#808000";
2798
+ var orange = "#FFA500";
2799
+ var purple = "#800080";
2800
+ var red = "#FF0000";
2801
+ var silver = "#C0C0C0";
2802
+ var teal = "#008080";
2803
+ var white = "#FFFFFF";
2804
+ var yellow = "#FFFF00";
2805
+ function from_gradient(value, bottom_value, top_value, bottom_color, top_color) {
2806
+ const parseColor2 = (col) => {
2807
+ if (typeof col === "string") {
2808
+ if (col.startsWith("#")) {
2809
+ const hex = col.slice(1);
2810
+ const r4 = parseInt(hex.slice(0, 2), 16);
2811
+ const g4 = parseInt(hex.slice(2, 4), 16);
2812
+ const b4 = parseInt(hex.slice(4, 6), 16);
2813
+ return [r4, g4, b4, 1];
2814
+ }
2815
+ const match = col.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);
2816
+ if (match) {
2817
+ return [
2818
+ parseInt(match[1]),
2819
+ parseInt(match[2]),
2820
+ parseInt(match[3]),
2821
+ match[4] ? parseFloat(match[4]) : 1
2822
+ ];
2823
+ }
2824
+ }
2825
+ return [0, 0, 0, 1];
2826
+ };
2827
+ const [r1, g1, b1, a1] = parseColor2(bottom_color);
2828
+ const [r2, g2, b2, a2] = parseColor2(top_color);
2829
+ let t2;
2830
+ if (value <= bottom_value) {
2831
+ t2 = 0;
2832
+ } else if (value >= top_value) {
2833
+ t2 = 1;
2834
+ } else {
2835
+ t2 = (value - bottom_value) / (top_value - bottom_value);
2836
+ }
2837
+ const r3 = Math.round(r1 + (r2 - r1) * t2);
2838
+ const g3 = Math.round(g1 + (g2 - g1) * t2);
2839
+ const b3 = Math.round(b1 + (b2 - b1) * t2);
2840
+ const a = a1 + (a2 - a1) * t2;
2841
+ if (a === 1) {
2842
+ return `rgb(${r3}, ${g3}, ${b3})`;
2843
+ }
2844
+ return `rgba(${r3}, ${g3}, ${b3}, ${a})`;
2845
+ }
2846
+
2847
+ // src/utils/index.ts
2848
+ function isNA(value) {
2849
+ return value === null || value === void 0 || Number.isNaN(value);
2850
+ }
2851
+ function nz(value, defaultValue = 0) {
2852
+ return isNA(value) ? defaultValue : value;
2853
+ }
2854
+
2855
+ // src/math/index.ts
2856
+ var math_exports = {};
2857
+ __export(math_exports, {
2858
+ abs: () => abs,
2859
+ acos: () => acos,
2860
+ asin: () => asin,
2861
+ atan: () => atan,
2862
+ avg: () => avg,
2863
+ ceil: () => ceil,
2864
+ cos: () => cos,
2865
+ e: () => e,
2866
+ exp: () => exp,
2867
+ floor: () => floor,
2868
+ log: () => log,
2869
+ log10: () => log10,
2870
+ max: () => max3,
2871
+ min: () => min3,
2872
+ phi: () => phi,
2873
+ pi: () => pi,
2874
+ pow: () => pow,
2875
+ random: () => random,
2876
+ round: () => round,
2877
+ round_to_mintick: () => round_to_mintick,
2878
+ rphi: () => rphi,
2879
+ sign: () => sign,
2880
+ sin: () => sin,
2881
+ sqrt: () => sqrt,
2882
+ sum: () => sum,
2883
+ tan: () => tan,
2884
+ todegrees: () => todegrees,
2885
+ toradians: () => toradians
2886
+ });
2887
+ function abs(value) {
2888
+ if (value instanceof Series) {
2889
+ const bars2 = value.bars;
2890
+ const valueArray = value.toArray();
2891
+ const length = bars2.length;
2892
+ const result = [];
2893
+ for (let i = 0; i < length; i++) {
2894
+ const v = valueArray[i] ?? NaN;
2895
+ result.push(Math.abs(v));
2896
+ }
2897
+ return Series.fromArray(bars2, result);
2898
+ }
2899
+ return Math.abs(value);
2900
+ }
2901
+ function ceil(value) {
2902
+ if (value instanceof Series) {
2903
+ const bars2 = value.bars;
2904
+ const valueArray = value.toArray();
2905
+ const length = bars2.length;
2906
+ const result = [];
2907
+ for (let i = 0; i < length; i++) {
2908
+ const v = valueArray[i] ?? NaN;
2909
+ result.push(Math.ceil(v));
2910
+ }
2911
+ return Series.fromArray(bars2, result);
2912
+ }
2913
+ return Math.ceil(value);
2914
+ }
2915
+ function floor(value) {
2916
+ if (value instanceof Series) {
2917
+ const bars2 = value.bars;
2918
+ const valueArray = value.toArray();
2919
+ const length = bars2.length;
2920
+ const result = [];
2921
+ for (let i = 0; i < length; i++) {
2922
+ const v = valueArray[i] ?? NaN;
2923
+ result.push(Math.floor(v));
2924
+ }
2925
+ return Series.fromArray(bars2, result);
2926
+ }
2927
+ return Math.floor(value);
2928
+ }
2929
+ function round(value, precision) {
2930
+ if (value instanceof Series) {
2931
+ const bars2 = value.bars;
2932
+ const valueArray = value.toArray();
2933
+ const length = bars2.length;
2934
+ const result = [];
2935
+ if (precision === void 0) {
2936
+ for (let i = 0; i < length; i++) {
2937
+ const v = valueArray[i] ?? NaN;
2938
+ result.push(Math.round(v));
2939
+ }
2940
+ } else {
2941
+ const multiplier2 = Math.pow(10, precision);
2942
+ for (let i = 0; i < length; i++) {
2943
+ const v = valueArray[i] ?? NaN;
2944
+ result.push(Math.round(v * multiplier2) / multiplier2);
2945
+ }
2946
+ }
2947
+ return Series.fromArray(bars2, result);
2948
+ }
2949
+ if (precision === void 0) {
2950
+ return Math.round(value);
2951
+ }
2952
+ const multiplier = Math.pow(10, precision);
2953
+ return Math.round(value * multiplier) / multiplier;
2954
+ }
2955
+ function max3(...values) {
2956
+ const hasSeries = values.some((v) => v instanceof Series);
2957
+ if (!hasSeries) {
2958
+ return Math.max(...values);
2959
+ }
2960
+ const firstSeries = values.find((v) => v instanceof Series);
2961
+ const bars2 = firstSeries.bars;
2962
+ const length = bars2.length;
2963
+ const valueArrays = values.map(
2964
+ (v) => v instanceof Series ? v.toArray() : null
2965
+ );
2966
+ const result = [];
2967
+ for (let i = 0; i < length; i++) {
2968
+ const nums = values.map(
2969
+ (v, idx) => valueArrays[idx] ? valueArrays[idx][i] ?? NaN : v
2970
+ );
2971
+ result.push(Math.max(...nums));
2972
+ }
2973
+ return Series.fromArray(bars2, result);
2974
+ }
2975
+ function min3(...values) {
2976
+ const hasSeries = values.some((v) => v instanceof Series);
2977
+ if (!hasSeries) {
2978
+ return Math.min(...values);
2979
+ }
2980
+ const firstSeries = values.find((v) => v instanceof Series);
2981
+ const bars2 = firstSeries.bars;
2982
+ const length = bars2.length;
2983
+ const valueArrays = values.map(
2984
+ (v) => v instanceof Series ? v.toArray() : null
2985
+ );
2986
+ const result = [];
2987
+ for (let i = 0; i < length; i++) {
2988
+ const nums = values.map(
2989
+ (v, idx) => valueArrays[idx] ? valueArrays[idx][i] ?? NaN : v
2990
+ );
2991
+ result.push(Math.min(...nums));
2992
+ }
2993
+ return Series.fromArray(bars2, result);
2994
+ }
2995
+ function avg(...values) {
2996
+ const hasSeries = values.some((v) => v instanceof Series);
2997
+ if (!hasSeries) {
2998
+ return values.reduce((a, b2) => a + b2, 0) / values.length;
2999
+ }
3000
+ const firstSeries = values.find((v) => v instanceof Series);
3001
+ const bars2 = firstSeries.bars;
3002
+ const length = bars2.length;
3003
+ const valueArrays = values.map(
3004
+ (v) => v instanceof Series ? v.toArray() : null
3005
+ );
3006
+ const result = [];
3007
+ for (let i = 0; i < length; i++) {
3008
+ const nums = values.map(
3009
+ (v, idx) => valueArrays[idx] ? valueArrays[idx][i] ?? NaN : v
3010
+ );
3011
+ const sum2 = nums.reduce((a, b2) => a + b2, 0);
3012
+ result.push(sum2 / nums.length);
3013
+ }
3014
+ return Series.fromArray(bars2, result);
3015
+ }
3016
+ function sum(source, length) {
3017
+ const sourceArray = source instanceof Series ? source.toArray() : source;
3018
+ const result = [];
3019
+ for (let i = 0; i < sourceArray.length; i++) {
3020
+ if (i < length - 1) {
3021
+ result.push(NaN);
3022
+ } else {
3023
+ let total = 0;
3024
+ for (let j = 0; j < length; j++) {
3025
+ total += sourceArray[i - j];
3026
+ }
3027
+ result.push(total);
3028
+ }
3029
+ }
3030
+ if (source instanceof Series) {
3031
+ return Series.fromArray(source.bars, result);
3032
+ }
3033
+ return result;
3034
+ }
3035
+ function sqrt(value) {
3036
+ if (value instanceof Series) {
3037
+ const bars2 = value.bars;
3038
+ const valueArray = value.toArray();
3039
+ const length = bars2.length;
3040
+ const result = [];
3041
+ for (let i = 0; i < length; i++) {
3042
+ const v = valueArray[i] ?? NaN;
3043
+ result.push(Math.sqrt(v));
3044
+ }
3045
+ return Series.fromArray(bars2, result);
3046
+ }
3047
+ return Math.sqrt(value);
3048
+ }
3049
+ function pow(base, exponent) {
3050
+ const baseIsSeries = base instanceof Series;
3051
+ const expIsSeries = exponent instanceof Series;
3052
+ if (!baseIsSeries && !expIsSeries) {
3053
+ return Math.pow(base, exponent);
3054
+ }
3055
+ const bars2 = baseIsSeries ? base.bars : exponent.bars;
3056
+ const baseArray = baseIsSeries ? base.toArray() : null;
3057
+ const expArray = expIsSeries ? exponent.toArray() : null;
3058
+ const length = bars2.length;
3059
+ const result = [];
3060
+ for (let i = 0; i < length; i++) {
3061
+ const b2 = baseArray ? baseArray[i] ?? NaN : base;
3062
+ const e2 = expArray ? expArray[i] ?? NaN : exponent;
3063
+ result.push(Math.pow(b2, e2));
3064
+ }
3065
+ return Series.fromArray(bars2, result);
3066
+ }
3067
+ function exp(value) {
3068
+ if (value instanceof Series) {
3069
+ const bars2 = value.bars;
3070
+ const valueArray = value.toArray();
3071
+ const length = bars2.length;
3072
+ const result = [];
3073
+ for (let i = 0; i < length; i++) {
3074
+ const v = valueArray[i] ?? NaN;
3075
+ result.push(Math.exp(v));
3076
+ }
3077
+ return Series.fromArray(bars2, result);
3078
+ }
3079
+ return Math.exp(value);
3080
+ }
3081
+ function log(value) {
3082
+ if (value instanceof Series) {
3083
+ const bars2 = value.bars;
3084
+ const valueArray = value.toArray();
3085
+ const length = bars2.length;
3086
+ const result = [];
3087
+ for (let i = 0; i < length; i++) {
3088
+ const v = valueArray[i] ?? NaN;
3089
+ result.push(Math.log(v));
3090
+ }
3091
+ return Series.fromArray(bars2, result);
3092
+ }
3093
+ return Math.log(value);
3094
+ }
3095
+ function log10(value) {
3096
+ if (value instanceof Series) {
3097
+ const bars2 = value.bars;
3098
+ const valueArray = value.toArray();
3099
+ const length = bars2.length;
3100
+ const result = [];
3101
+ for (let i = 0; i < length; i++) {
3102
+ const v = valueArray[i] ?? NaN;
3103
+ result.push(Math.log10(v));
3104
+ }
3105
+ return Series.fromArray(bars2, result);
3106
+ }
3107
+ return Math.log10(value);
3108
+ }
3109
+ function sin(value) {
3110
+ if (value instanceof Series) {
3111
+ const bars2 = value.bars;
3112
+ const valueArray = value.toArray();
3113
+ const length = bars2.length;
3114
+ const result = [];
3115
+ for (let i = 0; i < length; i++) {
3116
+ const v = valueArray[i] ?? NaN;
3117
+ result.push(Math.sin(v));
3118
+ }
3119
+ return Series.fromArray(bars2, result);
3120
+ }
3121
+ return Math.sin(value);
3122
+ }
3123
+ function cos(value) {
3124
+ if (value instanceof Series) {
3125
+ const bars2 = value.bars;
3126
+ const valueArray = value.toArray();
3127
+ const length = bars2.length;
3128
+ const result = [];
3129
+ for (let i = 0; i < length; i++) {
3130
+ const v = valueArray[i] ?? NaN;
3131
+ result.push(Math.cos(v));
3132
+ }
3133
+ return Series.fromArray(bars2, result);
3134
+ }
3135
+ return Math.cos(value);
3136
+ }
3137
+ function tan(value) {
3138
+ if (value instanceof Series) {
3139
+ const bars2 = value.bars;
3140
+ const valueArray = value.toArray();
3141
+ const length = bars2.length;
3142
+ const result = [];
3143
+ for (let i = 0; i < length; i++) {
3144
+ const v = valueArray[i] ?? NaN;
3145
+ result.push(Math.tan(v));
3146
+ }
3147
+ return Series.fromArray(bars2, result);
3148
+ }
3149
+ return Math.tan(value);
3150
+ }
3151
+ function asin(value) {
3152
+ if (value instanceof Series) {
3153
+ const bars2 = value.bars;
3154
+ const valueArray = value.toArray();
3155
+ const length = bars2.length;
3156
+ const result = [];
3157
+ for (let i = 0; i < length; i++) {
3158
+ const v = valueArray[i] ?? NaN;
3159
+ result.push(Math.asin(v));
3160
+ }
3161
+ return Series.fromArray(bars2, result);
3162
+ }
3163
+ return Math.asin(value);
3164
+ }
3165
+ function acos(value) {
3166
+ if (value instanceof Series) {
3167
+ const bars2 = value.bars;
3168
+ const valueArray = value.toArray();
3169
+ const length = bars2.length;
3170
+ const result = [];
3171
+ for (let i = 0; i < length; i++) {
3172
+ const v = valueArray[i] ?? NaN;
3173
+ result.push(Math.acos(v));
3174
+ }
3175
+ return Series.fromArray(bars2, result);
3176
+ }
3177
+ return Math.acos(value);
3178
+ }
3179
+ function atan(value) {
3180
+ if (value instanceof Series) {
3181
+ const bars2 = value.bars;
3182
+ const valueArray = value.toArray();
3183
+ const length = bars2.length;
3184
+ const result = [];
3185
+ for (let i = 0; i < length; i++) {
3186
+ const v = valueArray[i] ?? NaN;
3187
+ result.push(Math.atan(v));
3188
+ }
3189
+ return Series.fromArray(bars2, result);
3190
+ }
3191
+ return Math.atan(value);
3192
+ }
3193
+ function toradians(degrees) {
3194
+ if (degrees instanceof Series) {
3195
+ const bars2 = degrees.bars;
3196
+ const valueArray = degrees.toArray();
3197
+ const length = bars2.length;
3198
+ const result = [];
3199
+ for (let i = 0; i < length; i++) {
3200
+ const v = valueArray[i] ?? NaN;
3201
+ result.push(v * (Math.PI / 180));
3202
+ }
3203
+ return Series.fromArray(bars2, result);
3204
+ }
3205
+ return degrees * (Math.PI / 180);
3206
+ }
3207
+ function todegrees(radians) {
3208
+ if (radians instanceof Series) {
3209
+ const bars2 = radians.bars;
3210
+ const valueArray = radians.toArray();
3211
+ const length = bars2.length;
3212
+ const result = [];
3213
+ for (let i = 0; i < length; i++) {
3214
+ const v = valueArray[i] ?? NaN;
3215
+ result.push(v * (180 / Math.PI));
3216
+ }
3217
+ return Series.fromArray(bars2, result);
3218
+ }
3219
+ return radians * (180 / Math.PI);
3220
+ }
3221
+ function random(min4, max4, _seed) {
3222
+ const rand = Math.random();
3223
+ if (min4 !== void 0 && max4 !== void 0) {
3224
+ return min4 + rand * (max4 - min4);
3225
+ }
3226
+ return rand;
3227
+ }
3228
+ function sign(value) {
3229
+ if (value instanceof Series) {
3230
+ const bars2 = value.bars;
3231
+ const valueArray = value.toArray();
3232
+ const length = bars2.length;
3233
+ const result = [];
3234
+ for (let i = 0; i < length; i++) {
3235
+ const v = valueArray[i] ?? NaN;
3236
+ result.push(v > 0 ? 1 : v < 0 ? -1 : 0);
3237
+ }
3238
+ return Series.fromArray(bars2, result);
3239
+ }
3240
+ return value > 0 ? 1 : value < 0 ? -1 : 0;
3241
+ }
3242
+ function round_to_mintick(number, mintick) {
3243
+ if (number instanceof Series) {
3244
+ const bars2 = number.bars;
3245
+ const valueArray = number.toArray();
3246
+ const length = bars2.length;
3247
+ if (mintick === void 0) {
3248
+ throw new Error(
3249
+ "math.round_to_mintick() requires mintick value. Either pass it explicitly or use createContext({ syminfo: { mintick } }) for implicit data."
3250
+ );
3251
+ }
3252
+ const result = [];
3253
+ if (mintick === 0) {
3254
+ for (let i = 0; i < length; i++) {
3255
+ result.push(valueArray[i] ?? NaN);
3256
+ }
3257
+ } else {
3258
+ for (let i = 0; i < length; i++) {
3259
+ const v = valueArray[i];
3260
+ if (v === void 0 || isNaN(v)) {
3261
+ result.push(NaN);
3262
+ } else {
3263
+ result.push(Math.round(v / mintick) * mintick);
3264
+ }
3265
+ }
3266
+ }
3267
+ return Series.fromArray(bars2, result);
3268
+ }
3269
+ if (isNaN(number)) {
3270
+ return NaN;
3271
+ }
3272
+ if (mintick === void 0) {
3273
+ throw new Error(
3274
+ "math.round_to_mintick() requires mintick value. Either pass it explicitly or use createContext({ syminfo: { mintick } }) for implicit data."
3275
+ );
3276
+ }
3277
+ if (mintick === 0) {
3278
+ return number;
3279
+ }
3280
+ return Math.round(number / mintick) * mintick;
3281
+ }
3282
+ var pi = Math.PI;
3283
+ var e = Math.E;
3284
+ var phi = 1.618033988749895;
3285
+ var rphi = 0.618033988749895;
3286
+
3287
+ // src/script/index.ts
3288
+ var ctxBars = new BarData([]);
3289
+ var ctx = null;
3290
+ function collector() {
3291
+ if (!ctx) {
3292
+ throw new Error(
3293
+ "oakscriptjs/script functions can only run inside executeScript() \u2014 the host (chart/worker) drives script execution."
3294
+ );
3295
+ }
3296
+ return ctx;
3297
+ }
3298
+ function freshCollector(inputValues) {
3299
+ return {
3300
+ title: "Untitled",
3301
+ overlay: true,
3302
+ inputValues,
3303
+ inputConfig: [],
3304
+ inputIds: /* @__PURE__ */ new Set(),
3305
+ defaultInputs: {},
3306
+ plotConfig: [],
3307
+ plots: {},
3308
+ hlineConfig: [],
3309
+ fills: [],
3310
+ fillConfig: [],
3311
+ shapeConfig: [],
3312
+ markers: [],
3313
+ barColorConfig: [],
3314
+ bgcolors: [],
3315
+ barcolors: [],
3316
+ alertConfig: [],
3317
+ alerts: []
3318
+ };
3319
+ }
3320
+ function slugId(title, fallback, taken) {
3321
+ const base = (title ?? "").toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "") || fallback;
3322
+ let id = base;
3323
+ for (let n = 2; taken.has(id); n++) id = `${base}_${n}`;
3324
+ taken.add(id);
3325
+ return id;
3326
+ }
3327
+ function executeScript(body, barsInput, inputs = {}) {
3328
+ ctxBars.setAll(barsInput);
3329
+ ctx = freshCollector(inputs);
3330
+ try {
3331
+ body();
3332
+ const c = ctx;
3333
+ return {
3334
+ metadata: {
3335
+ title: c.title,
3336
+ shortTitle: c.shortTitle,
3337
+ overlay: c.overlay,
3338
+ precision: c.precision,
3339
+ format: c.format
3340
+ },
3341
+ inputConfig: c.inputConfig,
3342
+ plotConfig: c.plotConfig,
3343
+ hlineConfig: c.hlineConfig,
3344
+ fillConfig: c.fillConfig,
3345
+ shapeConfig: c.shapeConfig,
3346
+ barColorConfig: c.barColorConfig,
3347
+ defaultInputs: c.defaultInputs,
3348
+ alertConfig: c.alertConfig,
3349
+ result: {
3350
+ metadata: { title: c.title, shorttitle: c.shortTitle, overlay: c.overlay, precision: c.precision },
3351
+ plots: c.plots,
3352
+ fills: c.fills.length ? c.fills : void 0,
3353
+ markers: c.markers.length ? c.markers : void 0,
3354
+ bgcolors: c.bgcolors.length ? c.bgcolors : void 0,
3355
+ barcolors: c.barcolors.length ? c.barcolors : void 0,
3356
+ alerts: c.alerts.length ? c.alerts : void 0
3357
+ }
3358
+ };
3359
+ } finally {
3360
+ ctx = null;
3361
+ }
3362
+ }
3363
+ function indicator(title, options = {}) {
3364
+ const c = collector();
3365
+ c.title = title;
3366
+ c.shortTitle = options.shorttitle;
3367
+ c.overlay = options.overlay ?? true;
3368
+ c.precision = options.precision;
3369
+ c.format = options.format;
3370
+ }
3371
+ function registerInput(config, fallbackId) {
3372
+ const c = collector();
3373
+ const id = slugId(config.title, fallbackId, c.inputIds);
3374
+ c.inputConfig.push({ id, ...config });
3375
+ c.defaultInputs[id] = config.defval;
3376
+ const value = c.inputValues[id];
3377
+ return value === void 0 ? config.defval : value;
3378
+ }
3379
+ function registerNumeric(type, defval, title, opts = {}) {
3380
+ const v = registerInput(
3381
+ { type, defval, title, min: opts.minval, max: opts.maxval, step: opts.step },
3382
+ `input_${type}`
3383
+ );
3384
+ return typeof v === "number" ? v : defval;
3385
+ }
3386
+ var input = {
3387
+ int(defval, title, opts = {}) {
3388
+ return Math.round(registerNumeric("int", defval, title, opts));
3389
+ },
3390
+ float(defval, title, opts = {}) {
3391
+ return registerNumeric("float", defval, title, opts);
3392
+ },
3393
+ bool(defval, title) {
3394
+ return registerInput({ type: "bool", defval, title }, "input_bool");
3395
+ },
3396
+ string(defval, title, opts = {}) {
3397
+ return registerInput({ type: "string", defval, title, options: opts.options }, "input_string");
3398
+ },
3399
+ color(defval, title) {
3400
+ return registerInput({ type: "color", defval, title }, "input_color");
3401
+ },
3402
+ /** Declares a source input and returns it as a Series. */
3403
+ source(defval = "close", title) {
3404
+ const name = registerInput({ type: "source", defval, title }, "input_source");
3405
+ return sourceSeries(name);
3406
+ }
3407
+ };
3408
+ var open = Series.fromBars(ctxBars, "open");
3409
+ var high = Series.fromBars(ctxBars, "high");
3410
+ var low = Series.fromBars(ctxBars, "low");
3411
+ var close = Series.fromBars(ctxBars, "close");
3412
+ var volume = Series.fromBars(ctxBars, "volume");
3413
+ var hl2 = new Series(ctxBars, (b2) => (b2.high + b2.low) / 2);
3414
+ var hlc3 = new Series(ctxBars, (b2) => (b2.high + b2.low + b2.close) / 3);
3415
+ var ohlc4 = new Series(ctxBars, (b2) => (b2.open + b2.high + b2.low + b2.close) / 4);
3416
+ var hlcc4 = new Series(ctxBars, (b2) => (b2.high + b2.low + b2.close + b2.close) / 4);
3417
+ var SOURCES = { open, high, low, close, volume, hl2, hlc3, ohlc4, hlcc4 };
3418
+ function sourceSeries(name) {
3419
+ return SOURCES[name] ?? close;
3420
+ }
3421
+ var bars = () => ctxBars.bars;
3422
+ var ta2 = {
3423
+ ...ta_series_exports,
3424
+ tr: (handleNa = false) => tr2(bars(), handleNa),
3425
+ atr: (length) => atr2(bars(), length),
3426
+ sar: (start, inc, max4) => sar2(bars(), start, inc, max4),
3427
+ wpr: (length) => wpr2(bars(), length),
3428
+ supertrend: (factor, atrLength) => supertrend2(bars(), factor, atrLength),
3429
+ dmi: (diLength, adxSmoothing) => dmi2(bars(), diLength, adxSmoothing),
3430
+ kc: (source, length, mult, useTrueRange) => kc2(bars(), source, length, mult, useTrueRange),
3431
+ kcw: (source, length, mult, useTrueRange) => kcw2(bars(), source, length, mult, useTrueRange),
3432
+ ichimoku: (conversionPeriods, basePeriods, laggingSpan2Periods, displacement) => ichimoku2(bars(), conversionPeriods, basePeriods, laggingSpan2Periods, displacement)
3433
+ };
3434
+ function colorWhen(cond, colorTrue, colorFalse) {
3435
+ return cond.toArray().map((v) => !isNA(v) && v !== 0 ? colorTrue : colorFalse);
3436
+ }
3437
+ var color = {
3438
+ ...color_exports,
3439
+ new: new_color,
3440
+ when: colorWhen
3441
+ };
3442
+ function plot(series, title, options = {}) {
3443
+ const c = collector();
3444
+ const id = `plot${c.plotConfig.length}`;
3445
+ const perBar = Array.isArray(options.color) ? options.color : void 0;
3446
+ const staticColor = typeof options.color === "string" ? options.color : perBar?.[perBar.length - 1] ?? "#2962FF";
3447
+ c.plotConfig.push({
3448
+ id,
3449
+ title: title ?? id,
3450
+ color: staticColor,
3451
+ lineWidth: options.linewidth,
3452
+ style: options.style,
3453
+ display: options.display,
3454
+ histbase: options.histbase
3455
+ });
3456
+ const values = series.toArray();
3457
+ const b2 = bars();
3458
+ const data = [];
3459
+ for (let i = 0; i < b2.length; i++) {
3460
+ const value = values[i];
3461
+ if (value === void 0 || Number.isNaN(value)) continue;
3462
+ data.push(perBar ? { time: b2[i].time, value, color: perBar[i] } : { time: b2[i].time, value });
3463
+ }
3464
+ c.plots[id] = data;
3465
+ return { id, kind: "plot" };
3466
+ }
3467
+ function hline(price, title, options = {}) {
3468
+ const c = collector();
3469
+ const id = `hline${c.hlineConfig.length}`;
3470
+ c.hlineConfig.push({
3471
+ id,
3472
+ price,
3473
+ title,
3474
+ color: options.color,
3475
+ linestyle: options.linestyle,
3476
+ linewidth: options.linewidth
3477
+ });
3478
+ return { id, kind: "hline" };
3479
+ }
3480
+ function fill(a, b2, options = {}) {
3481
+ const c = collector();
3482
+ const perBar = Array.isArray(options.color) ? options.color : void 0;
3483
+ const staticColor = typeof options.color === "string" ? options.color : void 0;
3484
+ if (a.kind === "hline" && b2.kind === "hline") {
3485
+ c.fillConfig.push({
3486
+ id: `fill${c.fillConfig.length}`,
3487
+ plot1: a.id,
3488
+ plot2: b2.id,
3489
+ color: staticColor,
3490
+ colors: perBar,
3491
+ title: options.title
3492
+ });
3493
+ return;
3494
+ }
3495
+ c.fills.push({
3496
+ plot1: a.id,
3497
+ plot2: b2.id,
3498
+ options: { color: staticColor, title: options.title },
3499
+ colors: perBar
3500
+ });
3501
+ }
3502
+ function emitMarkers(kind, condition, title, options) {
3503
+ const c = collector();
3504
+ const id = `${kind}${c.shapeConfig.filter((s) => s.kind === kind).length}`;
3505
+ const style = kind === "shape" ? options.style ?? "xcross" : "char";
3506
+ const char = kind === "char" ? options.char ?? "*" : void 0;
3507
+ const location = options.location ?? "abovebar";
3508
+ c.shapeConfig.push({
3509
+ id,
3510
+ kind,
3511
+ title,
3512
+ style: kind === "shape" ? style : void 0,
3513
+ char,
3514
+ location,
3515
+ color: options.color,
3516
+ text: options.text,
3517
+ textcolor: options.textcolor,
3518
+ size: options.size,
3519
+ offset: options.offset
3520
+ });
3521
+ const values = condition.toArray();
3522
+ const b2 = bars();
3523
+ const off = options.offset ?? 0;
3524
+ for (let i = 0; i < b2.length; i++) {
3525
+ const v = values[i];
3526
+ if (v === void 0 || Number.isNaN(v) || v === 0) continue;
3527
+ const j = i + off;
3528
+ if (j < 0 || j >= b2.length) continue;
3529
+ c.markers.push({
3530
+ time: b2[j].time,
3531
+ id,
3532
+ location,
3533
+ style,
3534
+ char,
3535
+ color: options.color,
3536
+ text: options.text,
3537
+ textcolor: options.textcolor,
3538
+ size: options.size,
3539
+ tooltip: options.tooltip,
3540
+ price: location === "absolute" ? v : void 0
3541
+ });
3542
+ }
3543
+ }
3544
+ function plotshape(condition, title, options = {}) {
3545
+ emitMarkers("shape", condition, title, options);
3546
+ }
3547
+ function plotchar(condition, title, options = {}) {
3548
+ emitMarkers("char", condition, title, options);
3549
+ }
3550
+ function emitBarColors(kind, colors, options) {
3551
+ const c = collector();
3552
+ const id = `${kind}${c.barColorConfig.filter((x) => x.kind === kind).length}`;
3553
+ c.barColorConfig.push({ id, kind, title: options.title, offset: options.offset });
3554
+ const b2 = bars();
3555
+ const off = options.offset ?? 0;
3556
+ const target = kind === "bgcolor" ? c.bgcolors : c.barcolors;
3557
+ for (let i = 0; i < b2.length; i++) {
3558
+ const col = typeof colors === "string" ? colors : colors[i];
3559
+ if (!col) continue;
3560
+ const j = i + off;
3561
+ if (j < 0 || j >= b2.length) continue;
3562
+ target.push({ time: b2[j].time, color: col });
3563
+ }
3564
+ }
3565
+ function bgcolor(colors, options = {}) {
3566
+ emitBarColors("bgcolor", colors, options);
3567
+ }
3568
+ function barcolor(colors, options = {}) {
3569
+ emitBarColors("barcolor", colors, options);
3570
+ }
3571
+ function eachBar(fn) {
3572
+ collector();
3573
+ const b2 = bars();
3574
+ const out = new Array(b2.length).fill(NaN);
3575
+ const cache = /* @__PURE__ */ new Map();
3576
+ let idx = 0;
3577
+ const ctx2 = {
3578
+ get i() {
3579
+ return idx;
3580
+ },
3581
+ n: b2.length,
3582
+ get time() {
3583
+ return b2[idx].time;
3584
+ },
3585
+ get open() {
3586
+ return b2[idx].open;
3587
+ },
3588
+ get high() {
3589
+ return b2[idx].high;
3590
+ },
3591
+ get low() {
3592
+ return b2[idx].low;
3593
+ },
3594
+ get close() {
3595
+ return b2[idx].close;
3596
+ },
3597
+ get volume() {
3598
+ return b2[idx].volume ?? NaN;
3599
+ },
3600
+ get(src, offset = 0) {
3601
+ let vals = cache.get(src);
3602
+ if (!vals) {
3603
+ vals = src.toArray();
3604
+ cache.set(src, vals);
3605
+ }
3606
+ const j = idx - offset;
3607
+ return j >= 0 && j < vals.length ? vals[j] ?? NaN : NaN;
3608
+ },
3609
+ prev(offset = 1) {
3610
+ const j = idx - Math.max(1, offset);
3611
+ return j >= 0 ? out[j] : NaN;
3612
+ }
3613
+ };
3614
+ for (idx = 0; idx < b2.length; idx++) {
3615
+ const r2 = fn(ctx2);
3616
+ out[idx] = typeof r2 === "number" ? r2 : typeof r2 === "boolean" ? r2 ? 1 : 0 : NaN;
3617
+ }
3618
+ return Series.fromArray(ctxBars, out);
3619
+ }
3620
+ function seriesOf(values) {
3621
+ collector();
3622
+ return Series.fromArray(ctxBars, values);
3623
+ }
3624
+ function alertcondition(condition, title, message) {
3625
+ const c = collector();
3626
+ const id = `alert${c.alertConfig.length}`;
3627
+ c.alertConfig.push({ id, title, message });
3628
+ const last = condition.length() ? condition.last() : NaN;
3629
+ c.alerts.push({ id, title, message, triggered: !isNA(last) && last !== 0 });
3630
+ }