oakscriptjs 0.9.4 → 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 +88 -27
  2. package/dist/cjs/array/index.d.ts.map +1 -1
  3. package/dist/cjs/array/index.js +257 -117
  4. package/dist/cjs/array/index.js.map +3 -3
  5. package/dist/cjs/callsite/index.d.ts +122 -4
  6. package/dist/cjs/callsite/index.d.ts.map +1 -1
  7. package/dist/cjs/callsite/index.js +102 -3
  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 +79 -22
  23. package/dist/cjs/math/index.d.ts.map +1 -1
  24. package/dist/cjs/math/index.js +157 -43
  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 +95 -46
  53. package/dist/cjs/ta/index.d.ts.map +1 -1
  54. package/dist/cjs/ta/index.js +193 -318
  55. package/dist/cjs/ta/index.js.map +3 -3
  56. package/dist/cjs/ta/running-sum.d.ts +54 -1
  57. package/dist/cjs/ta/running-sum.d.ts.map +1 -1
  58. package/dist/cjs/ta/running-sum.js +132 -47
  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 +88 -27
  80. package/dist/esm/array/index.d.ts.map +1 -1
  81. package/dist/esm/array/index.js +408 -157
  82. package/dist/esm/array/index.js.map +1 -1
  83. package/dist/esm/callsite/index.d.ts +122 -4
  84. package/dist/esm/callsite/index.d.ts.map +1 -1
  85. package/dist/esm/callsite/index.js +228 -8
  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 +79 -22
  100. package/dist/esm/math/index.d.ts.map +1 -1
  101. package/dist/esm/math/index.js +229 -63
  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 +95 -46
  130. package/dist/esm/ta/index.d.ts.map +1 -1
  131. package/dist/esm/ta/index.js +341 -414
  132. package/dist/esm/ta/index.js.map +1 -1
  133. package/dist/esm/ta/running-sum.d.ts +54 -1
  134. package/dist/esm/ta/running-sum.d.ts.map +1 -1
  135. package/dist/esm/ta/running-sum.js +166 -60
  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 +2 -2
  157. package/src/array/index.ts +382 -174
  158. package/src/callsite/index.ts +232 -8
  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 +261 -77
  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 +356 -458
  172. package/src/ta/running-sum.ts +187 -62
  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,38 +92,28 @@ 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);
110
105
  const multiplier = 2 / (len + 1);
111
106
  let firstValidIndex = -1;
112
107
  let validCount = 0;
113
- let initSum = 0;
114
108
  for (let i = 0; i < source.length; i++) {
115
109
  const val = source[i];
116
- if (val !== void 0 && Number.isFinite(val)) {
117
- initSum += val;
118
- validCount++;
119
- if (validCount === len) {
120
- firstValidIndex = i;
121
- break;
122
- }
110
+ if (val !== void 0 && Number.isFinite(val) && ++validCount === len) {
111
+ firstValidIndex = i;
112
+ break;
123
113
  }
124
114
  }
125
- let emaValue = validCount > 0 ? initSum / validCount : NaN;
126
115
  const emaInitialized = firstValidIndex >= 0;
116
+ let emaValue = emaInitialized ? (0, import_running_sum.runningSum)(source.slice(0, firstValidIndex + 1), len)[firstValidIndex] / len : NaN;
127
117
  for (let i = 0; i < source.length; i++) {
128
118
  if (!emaInitialized || i < firstValidIndex) {
129
119
  result.push(NaN);
@@ -190,7 +180,7 @@ function bb(series, length, mult) {
190
180
  return [basis, upper, lower];
191
181
  }
192
182
  function stdev(source, length, biased = true) {
193
- 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);
194
184
  }
195
185
  function lastValues(source, i, length) {
196
186
  const values = [];
@@ -248,27 +238,26 @@ function extremeValue(source, length, lowest2) {
248
238
  return v === 0 && zeros[i] ? lowest2 ? -0 : 0 : v;
249
239
  });
250
240
  }
251
- function crossover(series1, series2) {
241
+ function crossTest(series1, series2, test) {
252
242
  const result = [];
243
+ let prevA = NaN;
244
+ let prevB = NaN;
253
245
  for (let i = 0; i < series1.length; i++) {
254
- if (i === 0) {
255
- result.push(false);
256
- } else {
257
- result.push(series1[i] > series2[i] && series1[i - 1] <= series2[i - 1]);
246
+ const a = series1[i];
247
+ const b = series2[i];
248
+ result.push(test(a, b, prevA, prevB));
249
+ if (!Number.isNaN(a) && !Number.isNaN(b)) {
250
+ prevA = a;
251
+ prevB = b;
258
252
  }
259
253
  }
260
254
  return result;
261
255
  }
256
+ function crossover(series1, series2) {
257
+ return crossTest(series1, series2, (a, b, pa, pb) => a > b && pa <= pb);
258
+ }
262
259
  function crossunder(series1, series2) {
263
- const result = [];
264
- for (let i = 0; i < series1.length; i++) {
265
- if (i === 0) {
266
- result.push(false);
267
- } else {
268
- result.push(series1[i] < series2[i] && series1[i - 1] >= series2[i - 1]);
269
- }
270
- }
271
- return result;
260
+ return crossTest(series1, series2, (a, b, pa, pb) => a < b && pa >= pb);
272
261
  }
273
262
  function change(source, length = 1) {
274
263
  const result = [];
@@ -371,20 +360,15 @@ function rma(source, length) {
371
360
  const len = Math.floor(length);
372
361
  let firstValidIndex = -1;
373
362
  let validCount = 0;
374
- let initSum = 0;
375
363
  for (let i = 0; i < source.length; i++) {
376
364
  const val = source[i];
377
- if (val !== void 0 && Number.isFinite(val)) {
378
- initSum += val;
379
- validCount++;
380
- if (validCount === len) {
381
- firstValidIndex = i;
382
- break;
383
- }
365
+ if (val !== void 0 && Number.isFinite(val) && ++validCount === len) {
366
+ firstValidIndex = i;
367
+ break;
384
368
  }
385
369
  }
386
- let rmaValue = validCount > 0 ? initSum / validCount : NaN;
387
370
  const rmaInitialized = firstValidIndex >= 0;
371
+ let rmaValue = rmaInitialized ? (0, import_running_sum.runningSum)(source.slice(0, firstValidIndex + 1), len)[firstValidIndex] / len : NaN;
388
372
  for (let i = 0; i < source.length; i++) {
389
373
  if (!rmaInitialized || i < firstValidIndex) {
390
374
  result.push(NaN);
@@ -402,6 +386,10 @@ function rma(source, length) {
402
386
  }
403
387
  return result;
404
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
+ }
405
393
  function wma(source, length) {
406
394
  const result = [];
407
395
  const len = Math.floor(length);
@@ -424,7 +412,7 @@ function wma(source, length) {
424
412
  let weightSum = 0;
425
413
  for (let j = len - 1; j >= 0; j--) {
426
414
  const weight = len - j;
427
- sum += filled[i - j] * weight;
415
+ sum = wmaAdd(sum, filled[i - j] * weight);
428
416
  weightSum += weight;
429
417
  }
430
418
  result.push(sum / weightSum);
@@ -447,27 +435,28 @@ function cum(source) {
447
435
  }
448
436
  function cross(source1, source2) {
449
437
  const result = [];
438
+ let side = 0;
450
439
  for (let i = 0; i < source1.length; i++) {
451
- if (i === 0) {
440
+ const a = source1[i];
441
+ const b = source2[i];
442
+ if (Number.isNaN(a) || Number.isNaN(b)) {
452
443
  result.push(false);
453
- } else {
454
- const crossedUp = source1[i] > source2[i] && source1[i - 1] <= source2[i - 1];
455
- const crossedDown = source1[i] < source2[i] && source1[i - 1] >= source2[i - 1];
456
- result.push(crossedUp || crossedDown);
444
+ continue;
457
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;
458
449
  }
459
450
  return result;
460
451
  }
461
452
  function monotonic(source, length, step) {
462
453
  const result = [];
463
- const values = [];
454
+ let count = 0;
464
455
  for (let i = 0; i < source.length; i++) {
465
456
  const v = source[i];
466
- if (!Number.isNaN(v)) values.push(v);
467
- const n = values.length;
468
- let ok = n > length;
469
- for (let j = 1; ok && j <= length; j++) ok = step(values[n - j], values[n - j - 1]);
470
- 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);
471
460
  }
472
461
  return result;
473
462
  }
@@ -510,24 +499,22 @@ function mom(source, length) {
510
499
  return result;
511
500
  }
512
501
  function dev(source, length) {
513
- const result = [];
514
- const meanValues = strictWindowMean(source, length);
515
- for (let i = 0; i < source.length; i++) {
516
- if (i < length - 1 || isNaN(meanValues[i])) {
517
- result.push(NaN);
518
- } else {
519
- let sum = 0;
520
- for (let j = 0; j < length; j++) {
521
- if (!isNaN(source[i - j])) {
522
- sum += Math.abs(source[i - j] - meanValues[i]);
523
- }
524
- }
525
- result.push(sum / length);
526
- }
527
- }
528
- 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
+ });
529
509
  }
530
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
+ }
531
518
  const len = Math.floor(length);
532
519
  if ((biased ? len : len - 1) <= 0) return source.map(() => NaN);
533
520
  return (0, import_running_sum.runningVariance)(source, len, biased);
@@ -563,20 +550,10 @@ function median(source, length) {
563
550
  return out;
564
551
  }
565
552
  function swma(source) {
566
- const result = [];
567
- for (let i = 0; i < source.length; i++) {
568
- if (i < 3) {
569
- result.push(NaN);
570
- } else {
571
- if (isNaN(source[i]) || isNaN(source[i - 1]) || isNaN(source[i - 2]) || isNaN(source[i - 3])) {
572
- result.push(NaN);
573
- } else {
574
- const value = source[i - 3] * (1 / 6) + source[i - 2] * (2 / 6) + source[i - 1] * (2 / 6) + source[i] * (1 / 6);
575
- result.push(value);
576
- }
577
- }
578
- }
579
- 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
+ );
580
557
  }
581
558
  function vwma(source, length, volume) {
582
559
  if (!volume) {
@@ -622,68 +599,39 @@ function linreg(source, length, offset = 0) {
622
599
  let sumXY = 0;
623
600
  let sumX2 = 0;
624
601
  for (let j = 0; j < len; j++) {
625
- const x2 = j;
602
+ const x = j + 1;
626
603
  const y = source[i - (len - 1 - j)];
627
- sumX += x2;
604
+ sumX += x;
628
605
  sumY += y;
629
- sumXY += x2 * y;
630
- sumX2 += x2 * x2;
606
+ sumXY += x * y;
607
+ sumX2 += x * x;
631
608
  }
632
609
  const slope = (len * sumXY - sumX * sumY) / (len * sumX2 - sumX * sumX);
633
- const intercept = (sumY - slope * sumX) / len;
634
- const x = len - 1 - offset;
635
- result.push(intercept + slope * x);
610
+ const intercept = sumY / len - slope * sumX / len + slope;
611
+ result.push(intercept + slope * (len - 1 - offset));
636
612
  }
637
613
  }
638
614
  }
639
615
  return result;
640
616
  }
641
617
  function correlation(source1, source2, length) {
642
- const result = [];
643
- const span = length > 0 ? Math.ceil(length) : 0;
644
- const a = new Float64Array(span);
645
- const b = new Float64Array(span);
646
- for (let i = 0; i < source1.length; i++) {
647
- if (i < length - 1) {
648
- result.push(NaN);
649
- continue;
650
- }
651
- let m = 0;
652
- for (let j = 0; j < length; j++) {
653
- const v1 = source1[i - j];
654
- const v2 = source2[i - j];
655
- if (!isNaN(v1) && !isNaN(v2)) {
656
- a[m] = v1;
657
- b[m] = v2;
658
- m++;
659
- }
660
- }
661
- if (m === 0) {
662
- result.push(NaN);
663
- continue;
664
- }
665
- let sum1 = 0;
666
- let sum2 = 0;
667
- for (let k = 0; k < m; k++) {
668
- sum1 += a[k];
669
- sum2 += b[k];
670
- }
671
- const mean1 = sum1 / m;
672
- const mean2 = sum2 / m;
673
- let numerator = 0;
674
- let sum1Sq = 0;
675
- let sum2Sq = 0;
676
- for (let k = 0; k < m; k++) {
677
- const dev1 = a[k] - mean1;
678
- const dev2 = b[k] - mean2;
679
- numerator += dev1 * dev2;
680
- sum1Sq += dev1 * dev1;
681
- sum2Sq += dev2 * dev2;
682
- }
683
- const denominator = Math.sqrt(sum1Sq * sum2Sq);
684
- result.push(denominator === 0 ? NaN : numerator / denominator);
685
- }
686
- 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
+ });
687
635
  }
688
636
  function percentrank(source, length) {
689
637
  const result = [];
@@ -697,42 +645,32 @@ function percentrank(source, length) {
697
645
  for (let j = 1; j <= length; j++) {
698
646
  if ((0, import_compare.le)(source[i - j], currentValue)) countLessOrEqual++;
699
647
  }
700
- result.push(countLessOrEqual / length * 100);
648
+ result.push(countLessOrEqual * 100 / length);
701
649
  }
702
650
  return result;
703
651
  }
704
652
  function cci(source, length) {
705
- const result = [];
706
653
  const smaValues = sma(source, length);
707
654
  const devValues = dev(source, length);
708
- for (let i = 0; i < source.length; i++) {
709
- if (isNaN(smaValues[i]) || isNaN(devValues[i])) {
710
- result.push(NaN);
711
- } else if ((0, import_compare.eq)(devValues[i], 0)) {
712
- result.push(i > 0 ? result[i - 1] : NaN);
713
- } else {
714
- const cci2 = (source[i] - smaValues[i]) / (0.015 * devValues[i]);
715
- result.push(cci2);
716
- }
717
- }
718
- 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
+ });
719
662
  }
720
663
  function stoch(source, high, low, length) {
721
664
  const result = [];
722
665
  const lowestValues = lowest(low, length);
723
666
  const highestValues = highest(high, length);
667
+ let previous = NaN;
724
668
  for (let i = 0; i < source.length; i++) {
725
- if (isNaN(lowestValues[i]) || isNaN(highestValues[i])) {
726
- result.push(NaN);
727
- } else {
728
- const range2 = highestValues[i] - lowestValues[i];
729
- if (range2 === 0) {
730
- result.push(NaN);
731
- } else {
732
- const stochValue = 100 * (source[i] - lowestValues[i]) / range2;
733
- result.push(stochValue);
734
- }
735
- }
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);
736
674
  }
737
675
  return result;
738
676
  }
@@ -752,11 +690,14 @@ function mfi(source, length, volume) {
752
690
  }
753
691
  const upper = (0, import_running_sum.runningSum)(upperFlow, length);
754
692
  const lower = (0, import_running_sum.runningSum)(lowerFlow, length);
755
- return upper.map((u, i) => {
756
- 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]);
757
697
  if (Number.isNaN(u) || Number.isNaN(l)) return NaN;
758
698
  if (l === 0) return 100;
759
- return 100 - 100 / (1 + u / l);
699
+ const ratio = 1 + u / l;
700
+ return ratio === 0 ? NaN : 100 - 100 / ratio;
760
701
  });
761
702
  }
762
703
  function hma(source, length) {
@@ -961,42 +902,22 @@ function tsi(source, shortLength, longLength) {
961
902
  const smoothedMomentum = ema(ema(momentum, longLength), shortLength);
962
903
  const absMomentum = momentum.map(Math.abs);
963
904
  const smoothedAbsMomentum = ema(ema(absMomentum, longLength), shortLength);
964
- const result = [];
965
- for (let i = 0; i < source.length; i++) {
966
- if (smoothedAbsMomentum[i] === 0) {
967
- result.push(0);
968
- } else {
969
- result.push(smoothedMomentum[i] / smoothedAbsMomentum[i] * 100);
970
- }
971
- }
972
- return result;
905
+ return smoothedMomentum.map((m, i) => {
906
+ const d = smoothedAbsMomentum[i];
907
+ return d === 0 ? NaN : m / d;
908
+ });
973
909
  }
974
910
  function cmo(source, length) {
975
- const result = [];
911
+ const up = [];
912
+ const down = [];
976
913
  for (let i = 0; i < source.length; i++) {
977
- if (i < length) {
978
- result.push(NaN);
979
- continue;
980
- }
981
- let sumGains = 0;
982
- let sumLosses = 0;
983
- for (let j = 0; j < length; j++) {
984
- const change2 = source[i - j] - source[i - j - 1];
985
- if (change2 > 0) {
986
- sumGains += change2;
987
- } else {
988
- sumLosses += Math.abs(change2);
989
- }
990
- }
991
- const totalMovement = sumGains + sumLosses;
992
- if (totalMovement === 0) {
993
- result.push(NaN);
994
- } else {
995
- const cmoValue = (sumGains - sumLosses) / totalMovement * 100;
996
- result.push(cmoValue);
997
- }
914
+ const mom2 = i > 0 ? source[i] - source[i - 1] : NaN;
915
+ up.push(mom2 >= 0 ? mom2 : 0);
916
+ down.push(mom2 >= 0 ? 0 : -mom2);
998
917
  }
999
- return result;
918
+ const sm1 = (0, import_running_sum.runningSum)(up, length);
919
+ const sm2 = (0, import_running_sum.runningSum)(down, length);
920
+ return sm1.map((s1, i) => 100 * (s1 - sm2[i]) / (s1 + sm2[i]));
1000
921
  }
1001
922
  function kc(source, length, mult, useTrueRange = true, high, low, close) {
1002
923
  const middle = ema(source, length);
@@ -1038,27 +959,13 @@ function bbw(source, length, mult) {
1038
959
  return result;
1039
960
  }
1040
961
  function wpr(high, low, close, length = 14) {
1041
- const result = [];
1042
- for (let i = 0; i < close.length; i++) {
1043
- if (i < length - 1) {
1044
- result.push(NaN);
1045
- continue;
1046
- }
1047
- let highestHigh = high[i - length + 1];
1048
- let lowestLow = low[i - length + 1];
1049
- for (let j = i - length + 2; j <= i; j++) {
1050
- if (high[j] > highestHigh) highestHigh = high[j];
1051
- if (low[j] < lowestLow) lowestLow = low[j];
1052
- }
1053
- const range2 = highestHigh - lowestLow;
1054
- if (range2 === 0) {
1055
- result.push(NaN);
1056
- } else {
1057
- const wprValue = (highestHigh - close[i]) / range2 * -100;
1058
- result.push(wprValue);
1059
- }
1060
- }
1061
- 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
+ });
1062
969
  }
1063
970
  function vwap(source, volume, anchor, stdev_mult) {
1064
971
  if (source.length !== volume.length) {
@@ -1067,18 +974,17 @@ function vwap(source, volume, anchor, stdev_mult) {
1067
974
  const mid = [];
1068
975
  const upper = [];
1069
976
  const lower = [];
1070
- let sumPV = 0;
1071
- let sumV = 0;
1072
- let sumPPV = 0;
977
+ let sumPV = NaN;
978
+ let sumV = NaN;
979
+ let sumPPV = NaN;
1073
980
  for (let i = 0; i < source.length; i++) {
1074
- if (anchor && anchor[i]) {
1075
- sumPV = 0;
1076
- sumV = 0;
1077
- sumPPV = 0;
1078
- }
1079
981
  const s = source[i];
1080
982
  const v = volume[i];
1081
- 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 {
1082
988
  sumPV += s * v;
1083
989
  sumV += v;
1084
990
  sumPPV += s * s * v;
@@ -1127,8 +1033,7 @@ function kcw(source, length = 20, mult = 2, useTrueRange = true, high, low, clos
1127
1033
  if (isNaN(basis[i]) || basis[i] === 0) {
1128
1034
  result.push(NaN);
1129
1035
  } else {
1130
- const width = (upper[i] - lower[i]) / basis[i] * 100;
1131
- result.push(width);
1036
+ result.push((upper[i] - lower[i]) / basis[i]);
1132
1037
  }
1133
1038
  }
1134
1039
  return result;
@@ -1160,47 +1065,26 @@ function min(source) {
1160
1065
  });
1161
1066
  }
1162
1067
  function cog(source, length = 10) {
1163
- const result = [];
1164
- for (let i = 0; i < source.length; i++) {
1165
- if (i < length - 1) {
1166
- result.push(NaN);
1167
- continue;
1168
- }
1169
- let numerator = 0;
1170
- let denominator = 0;
1171
- for (let j = 0; j < length; j++) {
1172
- const weight = j + 1;
1173
- const price = source[i - length + 1 + j];
1174
- numerator += weight * price;
1175
- denominator += price;
1176
- }
1177
- if (denominator === 0) {
1178
- result.push(NaN);
1179
- } else {
1180
- const cog2 = -1 * (numerator / denominator) + (length + 1) / 2;
1181
- result.push(cog2);
1182
- }
1183
- }
1184
- 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
+ });
1185
1075
  }
1186
1076
  function mode(source, length) {
1187
1077
  const result = [];
1078
+ const len = Math.floor(length);
1079
+ const seen = [];
1188
1080
  for (let i = 0; i < source.length; i++) {
1189
- if (i < length - 1) {
1190
- result.push(NaN);
1191
- continue;
1192
- }
1193
- const values = [];
1194
- for (let j = 0; j < length; j++) {
1195
- const value = source[i - j];
1196
- if (!isNaN(value)) {
1197
- values.push(value);
1198
- }
1199
- }
1200
- if (values.length === 0) {
1081
+ const v = source[i];
1082
+ if (!Number.isNaN(v)) seen.push(v);
1083
+ if (seen.length < len) {
1201
1084
  result.push(NaN);
1202
1085
  continue;
1203
1086
  }
1087
+ const values = seen.slice(seen.length - len);
1204
1088
  const frequencyMap = /* @__PURE__ */ new Map();
1205
1089
  for (const value of values) {
1206
1090
  frequencyMap.set(value, (frequencyMap.get(value) || 0) + 1);
@@ -1254,64 +1138,54 @@ function percentile_nearest_rank(source, length, percentage) {
1254
1138
  return sortedWindow(source, length, (s) => s[rank - 1]);
1255
1139
  }
1256
1140
  function rci(source, length) {
1141
+ const len = Math.floor(length);
1257
1142
  const result = [];
1143
+ const ring = new Array(len + 1).fill(0);
1258
1144
  for (let i = 0; i < source.length; i++) {
1259
- if (i < length - 1) {
1260
- result.push(NaN);
1145
+ const v = source[i];
1146
+ if (Number.isNaN(v)) {
1147
+ result.push(i > 0 ? result[i - 1] : NaN);
1261
1148
  continue;
1262
1149
  }
1263
- const values = [];
1264
- for (let j = 0; j < length; j++) {
1265
- values.push(source[i - length + 1 + j]);
1266
- }
1267
- if (values.some((v) => isNaN(v))) {
1150
+ ring[i % (len + 1)] = v;
1151
+ if (i < len) {
1268
1152
  result.push(NaN);
1269
1153
  continue;
1270
1154
  }
1271
- const indexed = values.map((value, index) => ({ value, index }));
1272
- const sorted = [...indexed].sort((a, b) => a.value - b.value);
1273
- const ranks = new Array(length).fill(0);
1274
- let currentRank = 1;
1275
- for (let j = 0; j < sorted.length; j++) {
1276
- let tieCount = 1;
1277
- while (j + tieCount < sorted.length && sorted[j].value === sorted[j + tieCount].value) {
1278
- tieCount++;
1279
- }
1280
- const avgRank = (currentRank + (currentRank + tieCount - 1)) / 2;
1281
- for (let k = 0; k < tieCount; k++) {
1282
- ranks[sorted[j + k].index] = avgRank;
1283
- }
1284
- j += tieCount - 1;
1285
- currentRank += tieCount;
1286
- }
1287
- let sumSquaredDiff = 0;
1288
- for (let j = 0; j < length; j++) {
1289
- const timeRank = j + 1;
1290
- const diff = ranks[j] - timeRank;
1291
- sumSquaredDiff += diff * diff;
1292
- }
1293
- const n = length;
1294
- const base = (n * n * n - n) / 12;
1295
- let tieCorrection = 0;
1296
- for (let j = 0; j < sorted.length; ) {
1297
- let tieCount = 1;
1298
- while (j + tieCount < sorted.length && sorted[j].value === sorted[j + tieCount].value) {
1299
- tieCount++;
1300
- }
1301
- if (tieCount > 1) {
1302
- tieCorrection += (tieCount * tieCount * tieCount - tieCount) / 12;
1303
- }
1304
- j += tieCount;
1305
- }
1306
- const A = base - tieCorrection;
1307
- const B = base;
1308
- let rho;
1309
- if (A === 0 || B === 0) {
1310
- rho = 0;
1311
- } else {
1312
- 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;
1313
1184
  }
1314
- 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)));
1315
1189
  }
1316
1190
  return result;
1317
1191
  }
@@ -1658,13 +1532,14 @@ function pvt(close, volume) {
1658
1532
  );
1659
1533
  }
1660
1534
  function accdist(high, low, close, volume) {
1661
- return cum(
1662
- close.map((c, i) => {
1663
- const h = high[i];
1664
- const l = low[i];
1665
- return h === l ? 0 : (2 * c - l - h) / (h - l) * volume[i];
1666
- })
1667
- );
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
+ });
1668
1543
  }
1669
1544
  function iii(high, low, close, volume) {
1670
1545
  return close.map((c, i) => {