oakscriptjs 0.9.5 → 0.9.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/dist/cjs/array/index.d.ts +84 -27
  2. package/dist/cjs/array/index.d.ts.map +1 -1
  3. package/dist/cjs/array/index.js +235 -78
  4. package/dist/cjs/array/index.js.map +3 -3
  5. package/dist/cjs/callsite/index.d.ts +81 -2
  6. package/dist/cjs/callsite/index.d.ts.map +1 -1
  7. package/dist/cjs/callsite/index.js +62 -1
  8. package/dist/cjs/callsite/index.js.map +2 -2
  9. package/dist/cjs/color/index.d.ts +7 -3
  10. package/dist/cjs/color/index.d.ts.map +1 -1
  11. package/dist/cjs/color/index.js +6 -1
  12. package/dist/cjs/color/index.js.map +2 -2
  13. package/dist/cjs/index.d.ts +1 -1
  14. package/dist/cjs/index.js +1 -1
  15. package/dist/cjs/index.js.map +1 -1
  16. package/dist/cjs/label/index.d.ts.map +1 -1
  17. package/dist/cjs/label/index.js +2 -1
  18. package/dist/cjs/label/index.js.map +2 -2
  19. package/dist/cjs/linefill/index.d.ts.map +1 -1
  20. package/dist/cjs/linefill/index.js +1 -0
  21. package/dist/cjs/linefill/index.js.map +2 -2
  22. package/dist/cjs/math/index.d.ts +76 -21
  23. package/dist/cjs/math/index.d.ts.map +1 -1
  24. package/dist/cjs/math/index.js +155 -41
  25. package/dist/cjs/math/index.js.map +3 -3
  26. package/dist/cjs/matrix/index.d.ts.map +1 -1
  27. package/dist/cjs/matrix/index.js +42 -36
  28. package/dist/cjs/matrix/index.js.map +2 -2
  29. package/dist/cjs/runtime/series.d.ts +9 -0
  30. package/dist/cjs/runtime/series.d.ts.map +1 -1
  31. package/dist/cjs/runtime/series.js +16 -2
  32. package/dist/cjs/runtime/series.js.map +2 -2
  33. package/dist/cjs/script/index.d.ts +15 -31
  34. package/dist/cjs/script/index.d.ts.map +1 -1
  35. package/dist/cjs/script/index.js +32 -0
  36. package/dist/cjs/script/index.js.map +2 -2
  37. package/dist/cjs/session/calendar.d.ts.map +1 -1
  38. package/dist/cjs/session/calendar.js +15 -2
  39. package/dist/cjs/session/calendar.js.map +2 -2
  40. package/dist/cjs/str/index.d.ts +50 -38
  41. package/dist/cjs/str/index.d.ts.map +1 -1
  42. package/dist/cjs/str/index.js +43 -15
  43. package/dist/cjs/str/index.js.map +2 -2
  44. package/dist/cjs/str/messageformat.d.ts +2 -1
  45. package/dist/cjs/str/messageformat.d.ts.map +1 -1
  46. package/dist/cjs/str/messageformat.js +4 -1
  47. package/dist/cjs/str/messageformat.js.map +2 -2
  48. package/dist/cjs/str/numberformat.d.ts +4 -0
  49. package/dist/cjs/str/numberformat.d.ts.map +1 -1
  50. package/dist/cjs/str/numberformat.js +26 -4
  51. package/dist/cjs/str/numberformat.js.map +3 -3
  52. package/dist/cjs/ta/index.d.ts +86 -43
  53. package/dist/cjs/ta/index.d.ts.map +1 -1
  54. package/dist/cjs/ta/index.js +173 -267
  55. package/dist/cjs/ta/index.js.map +3 -3
  56. package/dist/cjs/ta/running-sum.d.ts +54 -2
  57. package/dist/cjs/ta/running-sum.d.ts.map +1 -1
  58. package/dist/cjs/ta/running-sum.js +132 -52
  59. package/dist/cjs/ta/running-sum.js.map +2 -2
  60. package/dist/cjs/ta-series.d.ts +4 -4
  61. package/dist/cjs/ta-series.d.ts.map +1 -1
  62. package/dist/cjs/ta-series.js +4 -3
  63. package/dist/cjs/ta-series.js.map +2 -2
  64. package/dist/cjs/time/datestring.d.ts +1 -0
  65. package/dist/cjs/time/datestring.d.ts.map +1 -1
  66. package/dist/cjs/time/datestring.js +7 -0
  67. package/dist/cjs/time/datestring.js.map +2 -2
  68. package/dist/cjs/time/index.d.ts.map +1 -1
  69. package/dist/cjs/time/index.js +2 -1
  70. package/dist/cjs/time/index.js.map +2 -2
  71. package/dist/cjs/time/session.d.ts +28 -9
  72. package/dist/cjs/time/session.d.ts.map +1 -1
  73. package/dist/cjs/time/session.js +74 -28
  74. package/dist/cjs/time/session.js.map +2 -2
  75. package/dist/cjs/time/timezone.d.ts +5 -0
  76. package/dist/cjs/time/timezone.d.ts.map +1 -1
  77. package/dist/cjs/time/timezone.js +15 -1
  78. package/dist/cjs/time/timezone.js.map +2 -2
  79. package/dist/esm/array/index.d.ts +84 -27
  80. package/dist/esm/array/index.d.ts.map +1 -1
  81. package/dist/esm/array/index.js +373 -111
  82. package/dist/esm/array/index.js.map +1 -1
  83. package/dist/esm/callsite/index.d.ts +81 -2
  84. package/dist/esm/callsite/index.d.ts.map +1 -1
  85. package/dist/esm/callsite/index.js +145 -3
  86. package/dist/esm/callsite/index.js.map +1 -1
  87. package/dist/esm/color/index.d.ts +7 -3
  88. package/dist/esm/color/index.d.ts.map +1 -1
  89. package/dist/esm/color/index.js +15 -3
  90. package/dist/esm/color/index.js.map +1 -1
  91. package/dist/esm/index.d.ts +1 -1
  92. package/dist/esm/index.js +1 -1
  93. package/dist/esm/label/index.d.ts.map +1 -1
  94. package/dist/esm/label/index.js +2 -1
  95. package/dist/esm/label/index.js.map +1 -1
  96. package/dist/esm/linefill/index.d.ts.map +1 -1
  97. package/dist/esm/linefill/index.js +3 -0
  98. package/dist/esm/linefill/index.js.map +1 -1
  99. package/dist/esm/math/index.d.ts +76 -21
  100. package/dist/esm/math/index.d.ts.map +1 -1
  101. package/dist/esm/math/index.js +227 -61
  102. package/dist/esm/math/index.js.map +1 -1
  103. package/dist/esm/matrix/index.d.ts.map +1 -1
  104. package/dist/esm/matrix/index.js +57 -43
  105. package/dist/esm/matrix/index.js.map +1 -1
  106. package/dist/esm/runtime/series.d.ts +9 -0
  107. package/dist/esm/runtime/series.d.ts.map +1 -1
  108. package/dist/esm/runtime/series.js +18 -1
  109. package/dist/esm/runtime/series.js.map +1 -1
  110. package/dist/esm/script/index.d.ts +15 -31
  111. package/dist/esm/script/index.d.ts.map +1 -1
  112. package/dist/esm/script/index.js +44 -1
  113. package/dist/esm/script/index.js.map +1 -1
  114. package/dist/esm/session/calendar.d.ts.map +1 -1
  115. package/dist/esm/session/calendar.js +22 -2
  116. package/dist/esm/session/calendar.js.map +1 -1
  117. package/dist/esm/str/index.d.ts +50 -38
  118. package/dist/esm/str/index.d.ts.map +1 -1
  119. package/dist/esm/str/index.js +103 -52
  120. package/dist/esm/str/index.js.map +1 -1
  121. package/dist/esm/str/messageformat.d.ts +2 -1
  122. package/dist/esm/str/messageformat.d.ts.map +1 -1
  123. package/dist/esm/str/messageformat.js +7 -2
  124. package/dist/esm/str/messageformat.js.map +1 -1
  125. package/dist/esm/str/numberformat.d.ts +4 -0
  126. package/dist/esm/str/numberformat.d.ts.map +1 -1
  127. package/dist/esm/str/numberformat.js +38 -4
  128. package/dist/esm/str/numberformat.js.map +1 -1
  129. package/dist/esm/ta/index.d.ts +86 -43
  130. package/dist/esm/ta/index.d.ts.map +1 -1
  131. package/dist/esm/ta/index.js +296 -348
  132. package/dist/esm/ta/index.js.map +1 -1
  133. package/dist/esm/ta/running-sum.d.ts +54 -2
  134. package/dist/esm/ta/running-sum.d.ts.map +1 -1
  135. package/dist/esm/ta/running-sum.js +166 -71
  136. package/dist/esm/ta/running-sum.js.map +1 -1
  137. package/dist/esm/ta-series.d.ts +4 -4
  138. package/dist/esm/ta-series.d.ts.map +1 -1
  139. package/dist/esm/ta-series.js +5 -4
  140. package/dist/esm/ta-series.js.map +1 -1
  141. package/dist/esm/time/datestring.d.ts +1 -0
  142. package/dist/esm/time/datestring.d.ts.map +1 -1
  143. package/dist/esm/time/datestring.js +12 -0
  144. package/dist/esm/time/datestring.js.map +1 -1
  145. package/dist/esm/time/index.d.ts.map +1 -1
  146. package/dist/esm/time/index.js +3 -1
  147. package/dist/esm/time/index.js.map +1 -1
  148. package/dist/esm/time/session.d.ts +28 -9
  149. package/dist/esm/time/session.d.ts.map +1 -1
  150. package/dist/esm/time/session.js +113 -42
  151. package/dist/esm/time/session.js.map +1 -1
  152. package/dist/esm/time/timezone.d.ts +5 -0
  153. package/dist/esm/time/timezone.d.ts.map +1 -1
  154. package/dist/esm/time/timezone.js +21 -1
  155. package/dist/esm/time/timezone.js.map +1 -1
  156. package/package.json +1 -1
  157. package/src/array/index.ts +352 -127
  158. package/src/callsite/index.ts +147 -3
  159. package/src/color/index.ts +15 -5
  160. package/src/index.ts +1 -1
  161. package/src/label/index.ts +2 -1
  162. package/src/linefill/index.ts +2 -0
  163. package/src/math/index.ts +256 -74
  164. package/src/matrix/index.ts +52 -52
  165. package/src/runtime/series.ts +22 -1
  166. package/src/script/index.ts +53 -1
  167. package/src/session/calendar.ts +22 -2
  168. package/src/str/index.ts +95 -51
  169. package/src/str/messageformat.ts +7 -2
  170. package/src/str/numberformat.ts +39 -4
  171. package/src/ta/index.ts +306 -386
  172. package/src/ta/running-sum.ts +187 -74
  173. package/src/ta-series.ts +8 -7
  174. package/src/time/datestring.ts +10 -0
  175. package/src/time/index.ts +3 -1
  176. package/src/time/session.ts +97 -47
  177. package/src/time/timezone.ts +21 -1
@@ -92,18 +92,13 @@ module.exports = __toCommonJS(ta_exports);
92
92
  var import_compare = require("../compare/index.js");
93
93
  var import_running_sum = require("./running-sum.js");
94
94
  function sma(source, length) {
95
+ if (typeof length !== "number") {
96
+ const sums = (0, import_running_sum.runningSumSeries)(source, length, "ta.sma");
97
+ return sums.map((sum, i) => sum / Math.floor(length[i]));
98
+ }
95
99
  const len = Math.floor(length);
96
100
  return (0, import_running_sum.runningSum)(source, len).map((sum) => sum / len);
97
101
  }
98
- function strictWindowMean(source, length) {
99
- const len = Math.floor(length);
100
- return Array.from({ length: source.length }, (_, i) => {
101
- if (i < len - 1) return NaN;
102
- let sum = 0;
103
- for (let j = 0; j < len; j++) sum += source[i - j];
104
- return sum / len;
105
- });
106
- }
107
102
  function ema(source, length) {
108
103
  const result = [];
109
104
  const len = Math.floor(length);
@@ -185,7 +180,7 @@ function bb(series, length, mult) {
185
180
  return [basis, upper, lower];
186
181
  }
187
182
  function stdev(source, length, biased = true) {
188
- return variance(source, length, biased).map((v) => Number.isNaN(v) ? NaN : v > 0 ? Math.sqrt(v) : 0);
183
+ return varianceOf(source, length, biased, "ta.stdev").map((v) => Number.isNaN(v) ? NaN : v > 0 ? Math.sqrt(v) : 0);
189
184
  }
190
185
  function lastValues(source, i, length) {
191
186
  const values = [];
@@ -365,20 +360,15 @@ function rma(source, length) {
365
360
  const len = Math.floor(length);
366
361
  let firstValidIndex = -1;
367
362
  let validCount = 0;
368
- let initSum = 0;
369
363
  for (let i = 0; i < source.length; i++) {
370
364
  const val = source[i];
371
- if (val !== void 0 && Number.isFinite(val)) {
372
- initSum += val;
373
- validCount++;
374
- if (validCount === len) {
375
- firstValidIndex = i;
376
- break;
377
- }
365
+ if (val !== void 0 && Number.isFinite(val) && ++validCount === len) {
366
+ firstValidIndex = i;
367
+ break;
378
368
  }
379
369
  }
380
- let rmaValue = validCount > 0 ? initSum / validCount : NaN;
381
370
  const rmaInitialized = firstValidIndex >= 0;
371
+ let rmaValue = rmaInitialized ? (0, import_running_sum.runningSum)(source.slice(0, firstValidIndex + 1), len)[firstValidIndex] / len : NaN;
382
372
  for (let i = 0; i < source.length; i++) {
383
373
  if (!rmaInitialized || i < firstValidIndex) {
384
374
  result.push(NaN);
@@ -396,6 +386,10 @@ function rma(source, length) {
396
386
  }
397
387
  return result;
398
388
  }
389
+ function wmaAdd(a, b) {
390
+ const sum = a + b;
391
+ return Math.abs(sum) <= 1e-10 * Math.max(1, Math.abs(a) + Math.abs(b)) ? 0 : sum;
392
+ }
399
393
  function wma(source, length) {
400
394
  const result = [];
401
395
  const len = Math.floor(length);
@@ -418,7 +412,7 @@ function wma(source, length) {
418
412
  let weightSum = 0;
419
413
  for (let j = len - 1; j >= 0; j--) {
420
414
  const weight = len - j;
421
- sum += filled[i - j] * weight;
415
+ sum = wmaAdd(sum, filled[i - j] * weight);
422
416
  weightSum += weight;
423
417
  }
424
418
  result.push(sum / weightSum);
@@ -440,18 +434,29 @@ function cum(source) {
440
434
  });
441
435
  }
442
436
  function cross(source1, source2) {
443
- return crossTest(source1, source2, (a, b, pa, pb) => a > b && pa <= pb || a < b && pa >= pb);
437
+ const result = [];
438
+ let side = 0;
439
+ for (let i = 0; i < source1.length; i++) {
440
+ const a = source1[i];
441
+ const b = source2[i];
442
+ if (Number.isNaN(a) || Number.isNaN(b)) {
443
+ result.push(false);
444
+ continue;
445
+ }
446
+ result.push(side < 0 && a > b || side > 0 && a < b);
447
+ if (a < b) side = -1;
448
+ else if (a > b) side = 1;
449
+ }
450
+ return result;
444
451
  }
445
452
  function monotonic(source, length, step) {
446
453
  const result = [];
447
- const values = [];
454
+ let count = 0;
448
455
  for (let i = 0; i < source.length; i++) {
449
456
  const v = source[i];
450
- if (!Number.isNaN(v)) values.push(v);
451
- const n = values.length;
452
- let ok = n > length;
453
- for (let j = 1; ok && j <= length; j++) ok = step(values[n - j], values[n - j - 1]);
454
- result.push(ok);
457
+ const prev = i > 0 ? source[i - 1] : NaN;
458
+ if (!Number.isNaN(v) && !Number.isNaN(prev)) count = step(v, prev) ? count + 1 : 0;
459
+ result.push(count >= length);
455
460
  }
456
461
  return result;
457
462
  }
@@ -494,24 +499,22 @@ function mom(source, length) {
494
499
  return result;
495
500
  }
496
501
  function dev(source, length) {
497
- const result = [];
498
- const meanValues = strictWindowMean(source, length);
499
- for (let i = 0; i < source.length; i++) {
500
- if (i < length - 1 || isNaN(meanValues[i])) {
501
- result.push(NaN);
502
- } else {
503
- let sum = 0;
504
- for (let j = 0; j < length; j++) {
505
- if (!isNaN(source[i - j])) {
506
- sum += Math.abs(source[i - j] - meanValues[i]);
507
- }
508
- }
509
- result.push(sum / length);
510
- }
511
- }
512
- return result;
502
+ const len = Math.floor(length);
503
+ return sma(source, len).map((mean, i) => {
504
+ if (i < len - 1 || Number.isNaN(mean)) return NaN;
505
+ let sum = 0;
506
+ for (let k = 0; k < len; k++) sum += Math.abs(source[i - k] - mean);
507
+ return sum / len;
508
+ });
513
509
  }
514
510
  function variance(source, length, biased = true) {
511
+ return varianceOf(source, length, biased, "ta.variance");
512
+ }
513
+ function varianceOf(source, length, biased, name) {
514
+ if (typeof length !== "number") {
515
+ const result = (0, import_running_sum.runningVarianceSeries)(source, length, biased, name);
516
+ return biased ? result : result.map((v, i) => Math.floor(length[i]) > 1 ? v : NaN);
517
+ }
515
518
  const len = Math.floor(length);
516
519
  if ((biased ? len : len - 1) <= 0) return source.map(() => NaN);
517
520
  return (0, import_running_sum.runningVariance)(source, len, biased);
@@ -547,20 +550,10 @@ function median(source, length) {
547
550
  return out;
548
551
  }
549
552
  function swma(source) {
550
- const result = [];
551
- for (let i = 0; i < source.length; i++) {
552
- if (i < 3) {
553
- result.push(NaN);
554
- } else {
555
- if (isNaN(source[i]) || isNaN(source[i - 1]) || isNaN(source[i - 2]) || isNaN(source[i - 3])) {
556
- result.push(NaN);
557
- } else {
558
- const value = source[i - 3] * (1 / 6) + source[i - 2] * (2 / 6) + source[i - 1] * (2 / 6) + source[i] * (1 / 6);
559
- result.push(value);
560
- }
561
- }
562
- }
563
- return result;
553
+ return Array.from(
554
+ { length: source.length },
555
+ (_, i) => i < 3 ? NaN : (source[i] + 2 * source[i - 1] + 2 * source[i - 2] + source[i - 3]) / 6
556
+ );
564
557
  }
565
558
  function vwma(source, length, volume) {
566
559
  if (!volume) {
@@ -606,68 +599,39 @@ function linreg(source, length, offset = 0) {
606
599
  let sumXY = 0;
607
600
  let sumX2 = 0;
608
601
  for (let j = 0; j < len; j++) {
609
- const x2 = j;
602
+ const x = j + 1;
610
603
  const y = source[i - (len - 1 - j)];
611
- sumX += x2;
604
+ sumX += x;
612
605
  sumY += y;
613
- sumXY += x2 * y;
614
- sumX2 += x2 * x2;
606
+ sumXY += x * y;
607
+ sumX2 += x * x;
615
608
  }
616
609
  const slope = (len * sumXY - sumX * sumY) / (len * sumX2 - sumX * sumX);
617
- const intercept = (sumY - slope * sumX) / len;
618
- const x = len - 1 - offset;
619
- result.push(intercept + slope * x);
610
+ const intercept = sumY / len - slope * sumX / len + slope;
611
+ result.push(intercept + slope * (len - 1 - offset));
620
612
  }
621
613
  }
622
614
  }
623
615
  return result;
624
616
  }
625
617
  function correlation(source1, source2, length) {
626
- const result = [];
627
- const span = length > 0 ? Math.ceil(length) : 0;
628
- const a = new Float64Array(span);
629
- const b = new Float64Array(span);
630
- for (let i = 0; i < source1.length; i++) {
631
- if (i < length - 1) {
632
- result.push(NaN);
633
- continue;
634
- }
635
- let m = 0;
636
- for (let j = 0; j < length; j++) {
637
- const v1 = source1[i - j];
638
- const v2 = source2[i - j];
639
- if (!isNaN(v1) && !isNaN(v2)) {
640
- a[m] = v1;
641
- b[m] = v2;
642
- m++;
643
- }
644
- }
645
- if (m === 0) {
646
- result.push(NaN);
647
- continue;
648
- }
649
- let sum1 = 0;
650
- let sum2 = 0;
651
- for (let k = 0; k < m; k++) {
652
- sum1 += a[k];
653
- sum2 += b[k];
654
- }
655
- const mean1 = sum1 / m;
656
- const mean2 = sum2 / m;
657
- let numerator = 0;
658
- let sum1Sq = 0;
659
- let sum2Sq = 0;
660
- for (let k = 0; k < m; k++) {
661
- const dev1 = a[k] - mean1;
662
- const dev2 = b[k] - mean2;
663
- numerator += dev1 * dev2;
664
- sum1Sq += dev1 * dev1;
665
- sum2Sq += dev2 * dev2;
666
- }
667
- const denominator = Math.sqrt(sum1Sq * sum2Sq);
668
- result.push(denominator === 0 ? NaN : numerator / denominator);
669
- }
670
- return result;
618
+ const product = Array.from({ length: source1.length }, (_, i) => {
619
+ const v1 = source1[i];
620
+ const v2 = source2[i];
621
+ return v1 === null || v1 === void 0 || v2 === null || v2 === void 0 ? NaN : v1 * v2;
622
+ });
623
+ const meanXY = sma(product, length);
624
+ const meanX = sma(source1, length);
625
+ const meanY = sma(source2, length);
626
+ const varX = variance(source1, length);
627
+ const varY = variance(source2, length);
628
+ return meanXY.map((mxy, i) => {
629
+ const cov = mxy - meanX[i] * meanY[i];
630
+ if (Number.isNaN(cov)) return NaN;
631
+ if (Math.abs(cov) <= 1e-10) return 0;
632
+ const denominator = Math.sqrt(varX[i] * varY[i]);
633
+ return denominator === 0 ? NaN : cov / denominator;
634
+ });
671
635
  }
672
636
  function percentrank(source, length) {
673
637
  const result = [];
@@ -686,37 +650,27 @@ function percentrank(source, length) {
686
650
  return result;
687
651
  }
688
652
  function cci(source, length) {
689
- const result = [];
690
653
  const smaValues = sma(source, length);
691
654
  const devValues = dev(source, length);
692
- for (let i = 0; i < source.length; i++) {
693
- if (isNaN(smaValues[i]) || isNaN(devValues[i])) {
694
- result.push(NaN);
695
- } else if ((0, import_compare.eq)(devValues[i], 0)) {
696
- result.push(i > 0 ? result[i - 1] : NaN);
697
- } else {
698
- const cci2 = (source[i] - smaValues[i]) / (0.015 * devValues[i]);
699
- result.push(cci2);
700
- }
701
- }
702
- return result;
655
+ let last = 0;
656
+ return smaValues.map((mean, i) => {
657
+ const d = devValues[i];
658
+ if (Number.isNaN(mean) || Number.isNaN(d)) return NaN;
659
+ if (!(0, import_compare.eq)(d, 0)) last = (source[i] - mean) / (0.015 * d);
660
+ return last;
661
+ });
703
662
  }
704
663
  function stoch(source, high, low, length) {
705
664
  const result = [];
706
665
  const lowestValues = lowest(low, length);
707
666
  const highestValues = highest(high, length);
667
+ let previous = NaN;
708
668
  for (let i = 0; i < source.length; i++) {
709
- if (isNaN(lowestValues[i]) || isNaN(highestValues[i])) {
710
- result.push(NaN);
711
- } else {
712
- const range2 = highestValues[i] - lowestValues[i];
713
- if (range2 === 0) {
714
- result.push(NaN);
715
- } else {
716
- const stochValue = 100 * (source[i] - lowestValues[i]) / range2;
717
- result.push(stochValue);
718
- }
719
- }
669
+ const value = source[i];
670
+ const lo = lowestValues[i];
671
+ const range2 = highestValues[i] - lo;
672
+ if (!Number.isNaN(value) && !Number.isNaN(range2) && range2 !== 0) previous = 100 * (value - lo) / range2;
673
+ result.push(previous);
720
674
  }
721
675
  return result;
722
676
  }
@@ -736,11 +690,14 @@ function mfi(source, length, volume) {
736
690
  }
737
691
  const upper = (0, import_running_sum.runningSum)(upperFlow, length);
738
692
  const lower = (0, import_running_sum.runningSum)(lowerFlow, length);
739
- return upper.map((u, i) => {
740
- const l = lower[i];
693
+ const zero = (x) => Math.abs(x) <= 1e-10 ? 0 : x;
694
+ return upper.map((sumUp, i) => {
695
+ const u = zero(sumUp);
696
+ const l = zero(lower[i]);
741
697
  if (Number.isNaN(u) || Number.isNaN(l)) return NaN;
742
698
  if (l === 0) return 100;
743
- return 100 - 100 / (1 + u / l);
699
+ const ratio = 1 + u / l;
700
+ return ratio === 0 ? NaN : 100 - 100 / ratio;
744
701
  });
745
702
  }
746
703
  function hma(source, length) {
@@ -945,15 +902,10 @@ function tsi(source, shortLength, longLength) {
945
902
  const smoothedMomentum = ema(ema(momentum, longLength), shortLength);
946
903
  const absMomentum = momentum.map(Math.abs);
947
904
  const smoothedAbsMomentum = ema(ema(absMomentum, longLength), shortLength);
948
- const result = [];
949
- for (let i = 0; i < source.length; i++) {
950
- if (smoothedAbsMomentum[i] === 0) {
951
- result.push(0);
952
- } else {
953
- result.push(smoothedMomentum[i] / smoothedAbsMomentum[i] * 100);
954
- }
955
- }
956
- return result;
905
+ return smoothedMomentum.map((m, i) => {
906
+ const d = smoothedAbsMomentum[i];
907
+ return d === 0 ? NaN : m / d;
908
+ });
957
909
  }
958
910
  function cmo(source, length) {
959
911
  const up = [];
@@ -1007,27 +959,13 @@ function bbw(source, length, mult) {
1007
959
  return result;
1008
960
  }
1009
961
  function wpr(high, low, close, length = 14) {
1010
- const result = [];
1011
- for (let i = 0; i < close.length; i++) {
1012
- if (i < length - 1) {
1013
- result.push(NaN);
1014
- continue;
1015
- }
1016
- let highestHigh = high[i - length + 1];
1017
- let lowestLow = low[i - length + 1];
1018
- for (let j = i - length + 2; j <= i; j++) {
1019
- if (high[j] > highestHigh) highestHigh = high[j];
1020
- if (low[j] < lowestLow) lowestLow = low[j];
1021
- }
1022
- const range2 = highestHigh - lowestLow;
1023
- if (range2 === 0) {
1024
- result.push(NaN);
1025
- } else {
1026
- const wprValue = (highestHigh - close[i]) / range2 * -100;
1027
- result.push(wprValue);
1028
- }
1029
- }
1030
- return result;
962
+ const highs = highest(high, length);
963
+ const lows = lowest(low, length);
964
+ return Array.from({ length: close.length }, (_, i) => {
965
+ const hmax = highs[i];
966
+ const range2 = hmax - lows[i];
967
+ return range2 === 0 ? NaN : 100 * (close[i] - hmax) / range2;
968
+ });
1031
969
  }
1032
970
  function vwap(source, volume, anchor, stdev_mult) {
1033
971
  if (source.length !== volume.length) {
@@ -1036,18 +974,17 @@ function vwap(source, volume, anchor, stdev_mult) {
1036
974
  const mid = [];
1037
975
  const upper = [];
1038
976
  const lower = [];
1039
- let sumPV = 0;
1040
- let sumV = 0;
1041
- let sumPPV = 0;
977
+ let sumPV = NaN;
978
+ let sumV = NaN;
979
+ let sumPPV = NaN;
1042
980
  for (let i = 0; i < source.length; i++) {
1043
- if (anchor && anchor[i]) {
1044
- sumPV = 0;
1045
- sumV = 0;
1046
- sumPPV = 0;
1047
- }
1048
981
  const s = source[i];
1049
982
  const v = volume[i];
1050
- if (!Number.isNaN(s) && !Number.isNaN(v)) {
983
+ if (anchor ? anchor[i] : i === 0) {
984
+ sumPV = s * v;
985
+ sumV = v;
986
+ sumPPV = s * s * v;
987
+ } else {
1051
988
  sumPV += s * v;
1052
989
  sumV += v;
1053
990
  sumPPV += s * s * v;
@@ -1096,8 +1033,7 @@ function kcw(source, length = 20, mult = 2, useTrueRange = true, high, low, clos
1096
1033
  if (isNaN(basis[i]) || basis[i] === 0) {
1097
1034
  result.push(NaN);
1098
1035
  } else {
1099
- const width = (upper[i] - lower[i]) / basis[i] * 100;
1100
- result.push(width);
1036
+ result.push((upper[i] - lower[i]) / basis[i]);
1101
1037
  }
1102
1038
  }
1103
1039
  return result;
@@ -1129,47 +1065,26 @@ function min(source) {
1129
1065
  });
1130
1066
  }
1131
1067
  function cog(source, length = 10) {
1132
- const result = [];
1133
- for (let i = 0; i < source.length; i++) {
1134
- if (i < length - 1) {
1135
- result.push(NaN);
1136
- continue;
1137
- }
1138
- let numerator = 0;
1139
- let denominator = 0;
1140
- for (let j = 0; j < length; j++) {
1141
- const weight = j + 1;
1142
- const price = source[i - length + 1 + j];
1143
- numerator += weight * price;
1144
- denominator += price;
1145
- }
1146
- if (denominator === 0) {
1147
- result.push(NaN);
1148
- } else {
1149
- const cog2 = -1 * (numerator / denominator) + (length + 1) / 2;
1150
- result.push(cog2);
1151
- }
1152
- }
1153
- return result;
1068
+ const len = Math.floor(length);
1069
+ return (0, import_running_sum.runningSum)(source, len).map((sum, i) => {
1070
+ if (i < len - 1 || Number.isNaN(sum) || sum === 0) return NaN;
1071
+ let num = 0;
1072
+ for (let k = 0; k < len; k++) num += source[i - k] * (k + 1);
1073
+ return -num / sum;
1074
+ });
1154
1075
  }
1155
1076
  function mode(source, length) {
1156
1077
  const result = [];
1078
+ const len = Math.floor(length);
1079
+ const seen = [];
1157
1080
  for (let i = 0; i < source.length; i++) {
1158
- if (i < length - 1) {
1159
- result.push(NaN);
1160
- continue;
1161
- }
1162
- const values = [];
1163
- for (let j = 0; j < length; j++) {
1164
- const value = source[i - j];
1165
- if (!isNaN(value)) {
1166
- values.push(value);
1167
- }
1168
- }
1169
- if (values.length === 0) {
1081
+ const v = source[i];
1082
+ if (!Number.isNaN(v)) seen.push(v);
1083
+ if (seen.length < len) {
1170
1084
  result.push(NaN);
1171
1085
  continue;
1172
1086
  }
1087
+ const values = seen.slice(seen.length - len);
1173
1088
  const frequencyMap = /* @__PURE__ */ new Map();
1174
1089
  for (const value of values) {
1175
1090
  frequencyMap.set(value, (frequencyMap.get(value) || 0) + 1);
@@ -1223,64 +1138,54 @@ function percentile_nearest_rank(source, length, percentage) {
1223
1138
  return sortedWindow(source, length, (s) => s[rank - 1]);
1224
1139
  }
1225
1140
  function rci(source, length) {
1141
+ const len = Math.floor(length);
1226
1142
  const result = [];
1143
+ const ring = new Array(len + 1).fill(0);
1227
1144
  for (let i = 0; i < source.length; i++) {
1228
- if (i < length - 1) {
1229
- result.push(NaN);
1145
+ const v = source[i];
1146
+ if (Number.isNaN(v)) {
1147
+ result.push(i > 0 ? result[i - 1] : NaN);
1230
1148
  continue;
1231
1149
  }
1232
- const values = [];
1233
- for (let j = 0; j < length; j++) {
1234
- values.push(source[i - length + 1 + j]);
1235
- }
1236
- if (values.some((v) => isNaN(v))) {
1150
+ ring[i % (len + 1)] = v;
1151
+ if (i < len) {
1237
1152
  result.push(NaN);
1238
1153
  continue;
1239
1154
  }
1240
- const indexed = values.map((value, index) => ({ value, index }));
1241
- const sorted = [...indexed].sort((a, b) => a.value - b.value);
1242
- const ranks = new Array(length).fill(0);
1243
- let currentRank = 1;
1244
- for (let j = 0; j < sorted.length; j++) {
1245
- let tieCount = 1;
1246
- while (j + tieCount < sorted.length && sorted[j].value === sorted[j + tieCount].value) {
1247
- tieCount++;
1248
- }
1249
- const avgRank = (currentRank + (currentRank + tieCount - 1)) / 2;
1250
- for (let k = 0; k < tieCount; k++) {
1251
- ranks[sorted[j + k].index] = avgRank;
1252
- }
1253
- j += tieCount - 1;
1254
- currentRank += tieCount;
1255
- }
1256
- let sumSquaredDiff = 0;
1257
- for (let j = 0; j < length; j++) {
1258
- const timeRank = j + 1;
1259
- const diff = ranks[j] - timeRank;
1260
- sumSquaredDiff += diff * diff;
1261
- }
1262
- const n = length;
1263
- const base = (n * n * n - n) / 12;
1264
- let tieCorrection = 0;
1265
- for (let j = 0; j < sorted.length; ) {
1266
- let tieCount = 1;
1267
- while (j + tieCount < sorted.length && sorted[j].value === sorted[j + tieCount].value) {
1268
- tieCount++;
1269
- }
1270
- if (tieCount > 1) {
1271
- tieCorrection += (tieCount * tieCount * tieCount - tieCount) / 12;
1272
- }
1273
- j += tieCount;
1274
- }
1275
- const A = base - tieCorrection;
1276
- const B = base;
1277
- let rho;
1278
- if (A === 0 || B === 0) {
1279
- rho = 0;
1280
- } else {
1281
- rho = (A + B - sumSquaredDiff) / (2 * Math.sqrt(A * B));
1155
+ const values = Array.from({ length: len }, (_, j) => ring[(i - j) % (len + 1)]);
1156
+ const order = values.map((_, j) => j).sort((a, b) => values[a] - values[b]);
1157
+ const ranks = new Array(len);
1158
+ for (let g = 0; g < len; ) {
1159
+ const anchor = values[order[g]];
1160
+ let end = g + 1;
1161
+ while (end < len && values[order[end]] - anchor < 1e-10) end++;
1162
+ const avgRank = len - 1 - (g + g + (end - g) - 1) / 2;
1163
+ for (let k = g; k < end; k++) ranks[order[k]] = avgRank;
1164
+ g = end;
1165
+ }
1166
+ let sumX = 0;
1167
+ let sumY = 0;
1168
+ let sumX2 = 0;
1169
+ let sumY2 = 0;
1170
+ for (let k = 0; k < len; k++) {
1171
+ const y = ranks[k];
1172
+ sumX += k;
1173
+ sumY += y;
1174
+ sumX2 += k * k;
1175
+ sumY2 += y * y;
1176
+ }
1177
+ const meanX = sumX / len;
1178
+ const meanY = sumY / len;
1179
+ const varX = sumX2 / len - meanX * meanX;
1180
+ const varY = sumY2 / len - meanY * meanY;
1181
+ if (!(varX > 0) || !(varY > 0)) {
1182
+ result.push(NaN);
1183
+ continue;
1282
1184
  }
1283
- result.push(rho * 100);
1185
+ let cov = 0;
1186
+ for (let k = 0; k < len; k++) cov += (k - meanX) * (ranks[k] - meanY);
1187
+ cov /= len;
1188
+ result.push(100 * cov / (Math.sqrt(varX) * Math.sqrt(varY)));
1284
1189
  }
1285
1190
  return result;
1286
1191
  }
@@ -1627,13 +1532,14 @@ function pvt(close, volume) {
1627
1532
  );
1628
1533
  }
1629
1534
  function accdist(high, low, close, volume) {
1630
- return cum(
1631
- close.map((c, i) => {
1632
- const h = high[i];
1633
- const l = low[i];
1634
- return h === l ? 0 : (2 * c - l - h) / (h - l) * volume[i];
1635
- })
1636
- );
1535
+ let ad = 0;
1536
+ return close.map((c, i) => {
1537
+ const h = high[i];
1538
+ const l = low[i];
1539
+ const mfv = (c - l - (h - c)) / (h - l) * volume[i];
1540
+ if (Number.isFinite(mfv)) ad += mfv;
1541
+ return ad;
1542
+ });
1637
1543
  }
1638
1544
  function iii(high, low, close, volume) {
1639
1545
  return close.map((c, i) => {