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.
- package/dist/cjs/array/index.d.ts +88 -27
- package/dist/cjs/array/index.d.ts.map +1 -1
- package/dist/cjs/array/index.js +257 -117
- package/dist/cjs/array/index.js.map +3 -3
- package/dist/cjs/callsite/index.d.ts +122 -4
- package/dist/cjs/callsite/index.d.ts.map +1 -1
- package/dist/cjs/callsite/index.js +102 -3
- package/dist/cjs/callsite/index.js.map +2 -2
- package/dist/cjs/color/index.d.ts +7 -3
- package/dist/cjs/color/index.d.ts.map +1 -1
- package/dist/cjs/color/index.js +6 -1
- package/dist/cjs/color/index.js.map +2 -2
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/label/index.d.ts.map +1 -1
- package/dist/cjs/label/index.js +2 -1
- package/dist/cjs/label/index.js.map +2 -2
- package/dist/cjs/linefill/index.d.ts.map +1 -1
- package/dist/cjs/linefill/index.js +1 -0
- package/dist/cjs/linefill/index.js.map +2 -2
- package/dist/cjs/math/index.d.ts +79 -22
- package/dist/cjs/math/index.d.ts.map +1 -1
- package/dist/cjs/math/index.js +157 -43
- package/dist/cjs/math/index.js.map +3 -3
- package/dist/cjs/matrix/index.d.ts.map +1 -1
- package/dist/cjs/matrix/index.js +42 -36
- package/dist/cjs/matrix/index.js.map +2 -2
- package/dist/cjs/runtime/series.d.ts +9 -0
- package/dist/cjs/runtime/series.d.ts.map +1 -1
- package/dist/cjs/runtime/series.js +16 -2
- package/dist/cjs/runtime/series.js.map +2 -2
- package/dist/cjs/script/index.d.ts +15 -31
- package/dist/cjs/script/index.d.ts.map +1 -1
- package/dist/cjs/script/index.js +32 -0
- package/dist/cjs/script/index.js.map +2 -2
- package/dist/cjs/session/calendar.d.ts.map +1 -1
- package/dist/cjs/session/calendar.js +15 -2
- package/dist/cjs/session/calendar.js.map +2 -2
- package/dist/cjs/str/index.d.ts +50 -38
- package/dist/cjs/str/index.d.ts.map +1 -1
- package/dist/cjs/str/index.js +43 -15
- package/dist/cjs/str/index.js.map +2 -2
- package/dist/cjs/str/messageformat.d.ts +2 -1
- package/dist/cjs/str/messageformat.d.ts.map +1 -1
- package/dist/cjs/str/messageformat.js +4 -1
- package/dist/cjs/str/messageformat.js.map +2 -2
- package/dist/cjs/str/numberformat.d.ts +4 -0
- package/dist/cjs/str/numberformat.d.ts.map +1 -1
- package/dist/cjs/str/numberformat.js +26 -4
- package/dist/cjs/str/numberformat.js.map +3 -3
- package/dist/cjs/ta/index.d.ts +95 -46
- package/dist/cjs/ta/index.d.ts.map +1 -1
- package/dist/cjs/ta/index.js +193 -318
- package/dist/cjs/ta/index.js.map +3 -3
- package/dist/cjs/ta/running-sum.d.ts +54 -1
- package/dist/cjs/ta/running-sum.d.ts.map +1 -1
- package/dist/cjs/ta/running-sum.js +132 -47
- package/dist/cjs/ta/running-sum.js.map +2 -2
- package/dist/cjs/ta-series.d.ts +4 -4
- package/dist/cjs/ta-series.d.ts.map +1 -1
- package/dist/cjs/ta-series.js +4 -3
- package/dist/cjs/ta-series.js.map +2 -2
- package/dist/cjs/time/datestring.d.ts +1 -0
- package/dist/cjs/time/datestring.d.ts.map +1 -1
- package/dist/cjs/time/datestring.js +7 -0
- package/dist/cjs/time/datestring.js.map +2 -2
- package/dist/cjs/time/index.d.ts.map +1 -1
- package/dist/cjs/time/index.js +2 -1
- package/dist/cjs/time/index.js.map +2 -2
- package/dist/cjs/time/session.d.ts +28 -9
- package/dist/cjs/time/session.d.ts.map +1 -1
- package/dist/cjs/time/session.js +74 -28
- package/dist/cjs/time/session.js.map +2 -2
- package/dist/cjs/time/timezone.d.ts +5 -0
- package/dist/cjs/time/timezone.d.ts.map +1 -1
- package/dist/cjs/time/timezone.js +15 -1
- package/dist/cjs/time/timezone.js.map +2 -2
- package/dist/esm/array/index.d.ts +88 -27
- package/dist/esm/array/index.d.ts.map +1 -1
- package/dist/esm/array/index.js +408 -157
- package/dist/esm/array/index.js.map +1 -1
- package/dist/esm/callsite/index.d.ts +122 -4
- package/dist/esm/callsite/index.d.ts.map +1 -1
- package/dist/esm/callsite/index.js +228 -8
- package/dist/esm/callsite/index.js.map +1 -1
- package/dist/esm/color/index.d.ts +7 -3
- package/dist/esm/color/index.d.ts.map +1 -1
- package/dist/esm/color/index.js +15 -3
- package/dist/esm/color/index.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/label/index.d.ts.map +1 -1
- package/dist/esm/label/index.js +2 -1
- package/dist/esm/label/index.js.map +1 -1
- package/dist/esm/linefill/index.d.ts.map +1 -1
- package/dist/esm/linefill/index.js +3 -0
- package/dist/esm/linefill/index.js.map +1 -1
- package/dist/esm/math/index.d.ts +79 -22
- package/dist/esm/math/index.d.ts.map +1 -1
- package/dist/esm/math/index.js +229 -63
- package/dist/esm/math/index.js.map +1 -1
- package/dist/esm/matrix/index.d.ts.map +1 -1
- package/dist/esm/matrix/index.js +57 -43
- package/dist/esm/matrix/index.js.map +1 -1
- package/dist/esm/runtime/series.d.ts +9 -0
- package/dist/esm/runtime/series.d.ts.map +1 -1
- package/dist/esm/runtime/series.js +18 -1
- package/dist/esm/runtime/series.js.map +1 -1
- package/dist/esm/script/index.d.ts +15 -31
- package/dist/esm/script/index.d.ts.map +1 -1
- package/dist/esm/script/index.js +44 -1
- package/dist/esm/script/index.js.map +1 -1
- package/dist/esm/session/calendar.d.ts.map +1 -1
- package/dist/esm/session/calendar.js +22 -2
- package/dist/esm/session/calendar.js.map +1 -1
- package/dist/esm/str/index.d.ts +50 -38
- package/dist/esm/str/index.d.ts.map +1 -1
- package/dist/esm/str/index.js +103 -52
- package/dist/esm/str/index.js.map +1 -1
- package/dist/esm/str/messageformat.d.ts +2 -1
- package/dist/esm/str/messageformat.d.ts.map +1 -1
- package/dist/esm/str/messageformat.js +7 -2
- package/dist/esm/str/messageformat.js.map +1 -1
- package/dist/esm/str/numberformat.d.ts +4 -0
- package/dist/esm/str/numberformat.d.ts.map +1 -1
- package/dist/esm/str/numberformat.js +38 -4
- package/dist/esm/str/numberformat.js.map +1 -1
- package/dist/esm/ta/index.d.ts +95 -46
- package/dist/esm/ta/index.d.ts.map +1 -1
- package/dist/esm/ta/index.js +341 -414
- package/dist/esm/ta/index.js.map +1 -1
- package/dist/esm/ta/running-sum.d.ts +54 -1
- package/dist/esm/ta/running-sum.d.ts.map +1 -1
- package/dist/esm/ta/running-sum.js +166 -60
- package/dist/esm/ta/running-sum.js.map +1 -1
- package/dist/esm/ta-series.d.ts +4 -4
- package/dist/esm/ta-series.d.ts.map +1 -1
- package/dist/esm/ta-series.js +5 -4
- package/dist/esm/ta-series.js.map +1 -1
- package/dist/esm/time/datestring.d.ts +1 -0
- package/dist/esm/time/datestring.d.ts.map +1 -1
- package/dist/esm/time/datestring.js +12 -0
- package/dist/esm/time/datestring.js.map +1 -1
- package/dist/esm/time/index.d.ts.map +1 -1
- package/dist/esm/time/index.js +3 -1
- package/dist/esm/time/index.js.map +1 -1
- package/dist/esm/time/session.d.ts +28 -9
- package/dist/esm/time/session.d.ts.map +1 -1
- package/dist/esm/time/session.js +113 -42
- package/dist/esm/time/session.js.map +1 -1
- package/dist/esm/time/timezone.d.ts +5 -0
- package/dist/esm/time/timezone.d.ts.map +1 -1
- package/dist/esm/time/timezone.js +21 -1
- package/dist/esm/time/timezone.js.map +1 -1
- package/package.json +2 -2
- package/src/array/index.ts +382 -174
- package/src/callsite/index.ts +232 -8
- package/src/color/index.ts +15 -5
- package/src/index.ts +1 -1
- package/src/label/index.ts +2 -1
- package/src/linefill/index.ts +2 -0
- package/src/math/index.ts +261 -77
- package/src/matrix/index.ts +52 -52
- package/src/runtime/series.ts +22 -1
- package/src/script/index.ts +53 -1
- package/src/session/calendar.ts +22 -2
- package/src/str/index.ts +95 -51
- package/src/str/messageformat.ts +7 -2
- package/src/str/numberformat.ts +39 -4
- package/src/ta/index.ts +356 -458
- package/src/ta/running-sum.ts +187 -62
- package/src/ta-series.ts +8 -7
- package/src/time/datestring.ts +10 -0
- package/src/time/index.ts +3 -1
- package/src/time/session.ts +97 -47
- package/src/time/timezone.ts +21 -1
package/dist/cjs/ta/index.js
CHANGED
|
@@ -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
|
-
|
|
118
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
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
|
-
|
|
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
|
-
|
|
379
|
-
|
|
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
|
|
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
|
-
|
|
440
|
+
const a = source1[i];
|
|
441
|
+
const b = source2[i];
|
|
442
|
+
if (Number.isNaN(a) || Number.isNaN(b)) {
|
|
452
443
|
result.push(false);
|
|
453
|
-
|
|
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
|
-
|
|
454
|
+
let count = 0;
|
|
464
455
|
for (let i = 0; i < source.length; i++) {
|
|
465
456
|
const v = source[i];
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
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
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
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
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
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
|
|
602
|
+
const x = j + 1;
|
|
626
603
|
const y = source[i - (len - 1 - j)];
|
|
627
|
-
sumX +=
|
|
604
|
+
sumX += x;
|
|
628
605
|
sumY += y;
|
|
629
|
-
sumXY +=
|
|
630
|
-
sumX2 +=
|
|
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 =
|
|
634
|
-
|
|
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
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
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
|
|
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
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
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
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
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
|
-
|
|
756
|
-
|
|
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
|
-
|
|
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
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
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
|
|
911
|
+
const up = [];
|
|
912
|
+
const down = [];
|
|
976
913
|
for (let i = 0; i < source.length; i++) {
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
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
|
-
|
|
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
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
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 =
|
|
1071
|
-
let sumV =
|
|
1072
|
-
let sumPPV =
|
|
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 (
|
|
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
|
-
|
|
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
|
|
1164
|
-
|
|
1165
|
-
if (i <
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
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
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
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
|
-
|
|
1260
|
-
|
|
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
|
-
|
|
1264
|
-
|
|
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
|
|
1272
|
-
const
|
|
1273
|
-
const ranks = new Array(
|
|
1274
|
-
let
|
|
1275
|
-
|
|
1276
|
-
let
|
|
1277
|
-
while (
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
}
|
|
1293
|
-
const
|
|
1294
|
-
const
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
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) => {
|