oakscriptjs 0.11.1 → 0.11.3

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 (75) hide show
  1. package/dist/cjs/callsite/index.d.ts.map +1 -1
  2. package/dist/cjs/callsite/index.js +5 -2
  3. package/dist/cjs/callsite/index.js.map +2 -2
  4. package/dist/cjs/drawing/output.d.ts +2 -1
  5. package/dist/cjs/drawing/output.d.ts.map +1 -1
  6. package/dist/cjs/drawing/output.js +5 -0
  7. package/dist/cjs/drawing/output.js.map +2 -2
  8. package/dist/cjs/index.d.ts +2 -2
  9. package/dist/cjs/index.d.ts.map +1 -1
  10. package/dist/cjs/index.js +2 -1
  11. package/dist/cjs/index.js.map +2 -2
  12. package/dist/cjs/script/index.d.ts +1 -1
  13. package/dist/cjs/script/index.d.ts.map +1 -1
  14. package/dist/cjs/script/index.js +6 -51
  15. package/dist/cjs/script/index.js.map +2 -2
  16. package/dist/cjs/session/calendar.d.ts.map +1 -1
  17. package/dist/cjs/session/calendar.js +1 -0
  18. package/dist/cjs/session/calendar.js.map +2 -2
  19. package/dist/cjs/session/context.d.ts +20 -4
  20. package/dist/cjs/session/context.d.ts.map +1 -1
  21. package/dist/cjs/session/context.js +65 -5
  22. package/dist/cjs/session/context.js.map +2 -2
  23. package/dist/cjs/ta/index.d.ts +31 -29
  24. package/dist/cjs/ta/index.d.ts.map +1 -1
  25. package/dist/cjs/ta/index.js +10 -12
  26. package/dist/cjs/ta/index.js.map +3 -3
  27. package/dist/cjs/table/index.d.ts +10 -5
  28. package/dist/cjs/table/index.d.ts.map +1 -1
  29. package/dist/cjs/table/index.js +11 -2
  30. package/dist/cjs/table/index.js.map +2 -2
  31. package/dist/cjs/types/metadata.d.ts +16 -0
  32. package/dist/cjs/types/metadata.d.ts.map +1 -1
  33. package/dist/cjs/types/metadata.js.map +1 -1
  34. package/dist/esm/callsite/index.d.ts.map +1 -1
  35. package/dist/esm/callsite/index.js +5 -2
  36. package/dist/esm/callsite/index.js.map +1 -1
  37. package/dist/esm/drawing/output.d.ts +2 -1
  38. package/dist/esm/drawing/output.d.ts.map +1 -1
  39. package/dist/esm/drawing/output.js +8 -1
  40. package/dist/esm/drawing/output.js.map +1 -1
  41. package/dist/esm/index.d.ts +2 -2
  42. package/dist/esm/index.d.ts.map +1 -1
  43. package/dist/esm/index.js +5 -4
  44. package/dist/esm/index.js.map +1 -1
  45. package/dist/esm/script/index.d.ts +1 -1
  46. package/dist/esm/script/index.d.ts.map +1 -1
  47. package/dist/esm/script/index.js +7 -62
  48. package/dist/esm/script/index.js.map +1 -1
  49. package/dist/esm/session/calendar.d.ts.map +1 -1
  50. package/dist/esm/session/calendar.js +4 -0
  51. package/dist/esm/session/calendar.js.map +1 -1
  52. package/dist/esm/session/context.d.ts +20 -4
  53. package/dist/esm/session/context.d.ts.map +1 -1
  54. package/dist/esm/session/context.js +81 -7
  55. package/dist/esm/session/context.js.map +1 -1
  56. package/dist/esm/ta/index.d.ts +31 -29
  57. package/dist/esm/ta/index.d.ts.map +1 -1
  58. package/dist/esm/ta/index.js +45 -45
  59. package/dist/esm/ta/index.js.map +1 -1
  60. package/dist/esm/table/index.d.ts +10 -5
  61. package/dist/esm/table/index.d.ts.map +1 -1
  62. package/dist/esm/table/index.js +23 -8
  63. package/dist/esm/table/index.js.map +1 -1
  64. package/dist/esm/types/metadata.d.ts +16 -0
  65. package/dist/esm/types/metadata.d.ts.map +1 -1
  66. package/package.json +1 -1
  67. package/src/callsite/index.ts +5 -2
  68. package/src/drawing/output.ts +9 -1
  69. package/src/index.ts +6 -3
  70. package/src/script/index.ts +7 -65
  71. package/src/session/calendar.ts +3 -0
  72. package/src/session/context.ts +99 -7
  73. package/src/ta/index.ts +46 -45
  74. package/src/table/index.ts +22 -6
  75. package/src/types/metadata.ts +16 -0
@@ -111,8 +111,7 @@ export function rsi(source, length) {
111
111
  return 100;
112
112
  if (eq(x, 0))
113
113
  return 0;
114
- const r = 100 - 100 / (1 + x / y);
115
- return Number.isFinite(r) ? r : NaN;
114
+ return 100 - 100 / (1 + x / y);
116
115
  });
117
116
  }
118
117
  checkPositiveLength('rsi', length, 0, 'y');
@@ -228,14 +227,14 @@ export function stdev(source, length, biased = true) {
228
227
  return varianceOf(source, length, biased, 'ta.stdev').map((v) => (Number.isNaN(v) ? NaN : v > 0 ? Math.sqrt(v) : 0));
229
228
  }
230
229
  /**
231
- * The last `length` non-na values up to bar `i` (the bar itself may be na), or null when fewer exist.
232
- * `isNa` tells which values are skipped (NaN by default).
230
+ * The last `length` non-na values up to bar `i` (the bar itself may be na), or null when fewer exist. +/-Infinity
231
+ * counts as na (#183).
233
232
  */
234
233
  function lastValues(source, i, length) {
235
234
  const values = [];
236
235
  for (let j = i; j >= 0 && values.length < length; j--) {
237
236
  const x = source[j];
238
- if (!Number.isNaN(x))
237
+ if (Number.isFinite(x))
239
238
  values.push(x);
240
239
  }
241
240
  return values.length === length ? values : null;
@@ -294,7 +293,7 @@ function windowExtremes(source, length, lowest, newest = false) {
294
293
  /**
295
294
  * The non-na values of `source` with their bars, and for each bar the position of its last non-na value (-1 when
296
295
  * there is none yet). PineScript's ta.highest / ta.lowest / ta.highestbars / ta.lowestbars / ta.pivothigh /
297
- * ta.pivotlow keep the non-na values they receive and nothing else.
296
+ * ta.pivotlow keep the non-na values they receive and nothing else; +/-Infinity is skipped like na (#183).
298
297
  */
299
298
  function keptValues(source) {
300
299
  const values = [];
@@ -302,7 +301,7 @@ function keptValues(source) {
302
301
  const last = new Int32Array(source.length);
303
302
  for (let i = 0; i < source.length; i++) {
304
303
  const x = source[i];
305
- if (!Number.isNaN(x)) {
304
+ if (Number.isFinite(x)) {
306
305
  values.push(x);
307
306
  bars.push(i);
308
307
  }
@@ -798,9 +797,9 @@ export function wma(source, length) {
798
797
  * @returns Highest value series (na on the first `length - 1` bars)
799
798
  *
800
799
  * @remarks
801
- * As in PineScript: `na` values are skipped. The result is the highest of the last `length` non-na values (of all
802
- * of them when there are fewer), also on a bar whose own value is `na`; `na` before bar `length - 1` and while no
803
- * value was received. A fractional length is truncated (7.5 is 7 bars).
800
+ * As in PineScript: `na` values (also +/-Infinity, #183) are skipped. The result is the highest of the last `length`
801
+ * non-na values (of all of them when there are fewer), also on a bar whose own value is `na`; `na` before bar
802
+ * `length - 1` and while no value was received. A fractional length is truncated (7.5 is 7 bars).
804
803
  * `length` can be an array (a length per bar, PineScript series length), also for `ta.lowest`, `ta.highestbars`
805
804
  * and `ta.lowestbars`: each bar uses its own length.
806
805
  * A length above 15,000 throws the PineScript runtime error (also `ta.lowest`, `ta.highestbars`, `ta.lowestbars`).
@@ -817,9 +816,9 @@ export function highest(source, length) {
817
816
  * @returns Lowest value series (na on the first `length - 1` bars)
818
817
  *
819
818
  * @remarks
820
- * As in PineScript: `na` values are skipped. The result is the lowest of the last `length` non-na values (of all
821
- * of them when there are fewer), also on a bar whose own value is `na`; `na` before bar `length - 1` and while no
822
- * value was received.
819
+ * As in PineScript: `na` values (also +/-Infinity, #183) are skipped. The result is the lowest of the last `length`
820
+ * non-na values (of all of them when there are fewer), also on a bar whose own value is `na`; `na` before bar
821
+ * `length - 1` and while no value was received.
823
822
  */
824
823
  export function lowest(source, length) {
825
824
  return extremeValue(source, length, true);
@@ -905,7 +904,7 @@ function monotonic(source, length, step) {
905
904
  for (let i = 0; i < source.length; i++) {
906
905
  const v = source[i];
907
906
  const prev = i > 0 ? source[i - 1] : NaN;
908
- if (!Number.isNaN(v) && !Number.isNaN(prev))
907
+ if (Number.isFinite(v) && Number.isFinite(prev))
909
908
  count = step(v, prev) ? count + 1 : 0;
910
909
  result.push(count >= length);
911
910
  }
@@ -922,8 +921,8 @@ function monotonic(source, length, step) {
922
921
  * PineScript rules:
923
922
  * - a counter of rises from the previous bar (a rise is larger than the 1e-10 tolerance); a step that is not a rise
924
923
  * resets it to 0
925
- * - a step from or to an `na` bar leaves the counter unchanged (so an `na` bar, and the bar after it, keep the
926
- * result of the bar before the `na`)
924
+ * - a step from or to an `na` (or +/-Infinity) bar leaves the counter unchanged (so an `na` bar, and the bar after
925
+ * it, keep the result of the bar before the `na`)
927
926
  * - true when the counter is at least `length` (false at the start)
928
927
  *
929
928
  * @example
@@ -947,8 +946,8 @@ export function rising(source, length) {
947
946
  * PineScript rules:
948
947
  * - a counter of falls from the previous bar (a fall is larger than the 1e-10 tolerance); a step that is not a fall
949
948
  * resets it to 0
950
- * - a step from or to an `na` bar leaves the counter unchanged (so an `na` bar, and the bar after it, keep the
951
- * result of the bar before the `na`)
949
+ * - a step from or to an `na` (or +/-Infinity) bar leaves the counter unchanged (so an `na` bar, and the bar after
950
+ * it, keep the result of the bar before the `na`)
952
951
  * - true when the counter is at least `length` (false at the start)
953
952
  *
954
953
  * @example
@@ -1125,7 +1124,7 @@ function varianceOf(source, length, biased, name) {
1125
1124
  * @remarks
1126
1125
  * - Returns the middle value when values are sorted
1127
1126
  * - For an even length, returns the average of the two middle values
1128
- * - As in PineScript: `na` values are skipped, the window holds the last `length` non-na values
1127
+ * - As in PineScript: `na` values (also +/-Infinity) are skipped, the window holds the last `length` non-na values
1129
1128
  * (going back as many bars as needed), and a bar whose own value is `na` still gets a result
1130
1129
  * - Returns NaN until `length` non-na values exist
1131
1130
  * - More robust to outliers than mean (SMA)
@@ -1164,7 +1163,7 @@ export function median(source, length) {
1164
1163
  const mid = Math.floor(len / 2);
1165
1164
  for (let i = 0; i < n; i++) {
1166
1165
  const x = source[i];
1167
- if (!Number.isNaN(x)) {
1166
+ if (Number.isFinite(x)) {
1168
1167
  kept[count++] = x;
1169
1168
  sorted.splice(bound(x, false), 0, x); // before the equal values: the newest first
1170
1169
  // the value leaving the window is the oldest, so the last of its equal values
@@ -1468,8 +1467,9 @@ export function cci(source, length) {
1468
1467
  * - Measures where close is relative to the high-low range
1469
1468
  * - Values above 80 typically indicate overbought
1470
1469
  * - Values below 20 typically indicate oversold
1471
- * - As PineScript: when the source, \`highest(high, length)\` or \`lowest(low, length)\` is \`na\`, or the range is 0, the
1472
- * result is the previous result of the call (\`na\` until a first value)
1470
+ * - As PineScript: when the source, \`highest(high, length)\` or \`lowest(low, length)\` is \`na\`, or the range and
1471
+ * \`source - lowest\` are both 0, the result is the previous result of the call (\`na\` until a first value); a zero
1472
+ * range with another source value gives +/-Infinity (plotted as \`na\`)
1473
1473
  *
1474
1474
  * @example
1475
1475
  * \`\`\`typescript
@@ -1483,14 +1483,14 @@ export function stoch(source, high, low, length) {
1483
1483
  const result = [];
1484
1484
  const lowestValues = lowest(low, length);
1485
1485
  const highestValues = highest(high, length);
1486
- // PineScript: an na input or a zero range keeps the previous result
1486
+ // PineScript: an na (NaN) result keeps the previous one: an na input, or 0 / 0 on a zero range; a non-zero value
1487
+ // over a zero range gives +/-Infinity (#183)
1487
1488
  let previous = NaN;
1488
1489
  for (let i = 0; i < source.length; i++) {
1489
- const value = source[i];
1490
1490
  const lo = lowestValues[i];
1491
- const range = highestValues[i] - lo;
1492
- if (!Number.isNaN(value) && !Number.isNaN(range) && range !== 0)
1493
- previous = (100 * (value - lo)) / range;
1491
+ const k = (100 * (source[i] - lo)) / (highestValues[i] - lo);
1492
+ if (!Number.isNaN(k))
1493
+ previous = k;
1494
1494
  result.push(previous);
1495
1495
  }
1496
1496
  return result;
@@ -1738,8 +1738,8 @@ function pivot(source, leftbars, rightbars, isHigh) {
1738
1738
  * - As in PineScript, the value appears `rightbars` bars after the pivot bar: the pivot bar
1739
1739
  * index is `i - rightbars`
1740
1740
  * - A pivot high may equal values on its left but must be higher than all values on its right
1741
- * - `na` values are skipped: the window is the last `leftbars + rightbars + 1` non-na values, and the highest of
1742
- * them must be on the bar `rightbars` bars back
1741
+ * - `na` values (also +/-Infinity) are skipped: the window is the last `leftbars + rightbars + 1` non-na values,
1742
+ * and the highest of them must be on the bar `rightbars` bars back
1743
1743
  * - `leftbars` / `rightbars` can be arrays (a length per bar, PineScript series length), also for `ta.pivotlow`:
1744
1744
  * each bar uses its own lengths
1745
1745
  *
@@ -1772,8 +1772,8 @@ export function pivothigh(sourceOrLeftbars, leftbarsOrRightbars, rightbars, high
1772
1772
  * - As in PineScript, the value appears `rightbars` bars after the pivot bar: the pivot bar
1773
1773
  * index is `i - rightbars`
1774
1774
  * - A pivot low may equal values on its left but must be lower than all values on its right
1775
- * - `na` values are skipped: the window is the last `leftbars + rightbars + 1` non-na values, and the lowest of
1776
- * them must be on the bar `rightbars` bars back
1775
+ * - `na` values (also +/-Infinity) are skipped: the window is the last `leftbars + rightbars + 1` non-na values,
1776
+ * and the lowest of them must be on the bar `rightbars` bars back
1777
1777
  *
1778
1778
  * @example
1779
1779
  * ```typescript
@@ -2267,7 +2267,7 @@ export function kcw(source, length = 20, mult = 2, useTrueRange = true, high, lo
2267
2267
  * (PineScript `ta.range(source, length)`).
2268
2268
  *
2269
2269
  * @remarks
2270
- * As in PineScript: `na` values are skipped (the window holds the last `length` non-na
2270
+ * As in PineScript: `na` values (also +/-Infinity) are skipped (the window holds the last `length` non-na
2271
2271
  * values), and a bar whose own value is `na` still gets a result.
2272
2272
  */
2273
2273
  export function range(source, length) {
@@ -2282,9 +2282,9 @@ export function range(source, length) {
2282
2282
  * -1 for the previous bar, and so on (as in PineScript, the offset is negative).
2283
2283
  *
2284
2284
  * @remarks
2285
- * As in PineScript: the best of the last `length` non-na values, the newest one on equal values; the offset is the
2286
- * distance in bars to its bar, so it is below `-(length - 1)` when `na` values were skipped. `na` before bar
2287
- * `length - 1` and while no value was received; a fractional length is truncated.
2285
+ * As in PineScript: the best of the last `length` non-na values (+/-Infinity skipped), the newest one on equal
2286
+ * values; the offset is the distance in bars to its bar, so it is below `-(length - 1)` when `na` values were
2287
+ * skipped. `na` before bar `length - 1` and while no value was received; a fractional length is truncated.
2288
2288
  */
2289
2289
  export function highestbars(source, length) {
2290
2290
  return extremeOffset(source, length, false);
@@ -2294,9 +2294,9 @@ export function highestbars(source, length) {
2294
2294
  * -1 for the previous bar, and so on (as in PineScript, the offset is negative).
2295
2295
  *
2296
2296
  * @remarks
2297
- * As in PineScript: the best of the last `length` non-na values, the newest one on equal values; the offset is the
2298
- * distance in bars to its bar, so it is below `-(length - 1)` when `na` values were skipped. `na` before bar
2299
- * `length - 1` and while no value was received; a fractional length is truncated.
2297
+ * As in PineScript: the best of the last `length` non-na values (+/-Infinity skipped), the newest one on equal
2298
+ * values; the offset is the distance in bars to its bar, so it is below `-(length - 1)` when `na` values were
2299
+ * skipped. `na` before bar `length - 1` and while no value was received; a fractional length is truncated.
2300
2300
  */
2301
2301
  export function lowestbars(source, length) {
2302
2302
  return extremeOffset(source, length, true);
@@ -2305,13 +2305,13 @@ export function lowestbars(source, length) {
2305
2305
  * All-time highest value of `source` up to each bar (PineScript `ta.max(source)`).
2306
2306
  *
2307
2307
  * @remarks
2308
- * As in PineScript: `na` values are skipped, the value carries over `na` bars, and the
2308
+ * As in PineScript: `na` values (also +/-Infinity) are skipped, the value carries over `na` bars, and the
2309
2309
  * result is `na` until the first non-na value.
2310
2310
  */
2311
2311
  export function max(source) {
2312
2312
  let best = NaN;
2313
2313
  return source.map((x) => {
2314
- if (!Number.isNaN(x) && !(x <= best))
2314
+ if (Number.isFinite(x) && !(x <= best))
2315
2315
  best = x;
2316
2316
  return best;
2317
2317
  });
@@ -2320,13 +2320,13 @@ export function max(source) {
2320
2320
  * All-time lowest value of `source` up to each bar (PineScript `ta.min(source)`).
2321
2321
  *
2322
2322
  * @remarks
2323
- * As in PineScript: `na` values are skipped, the value carries over `na` bars, and the
2323
+ * As in PineScript: `na` values (also +/-Infinity) are skipped, the value carries over `na` bars, and the
2324
2324
  * result is `na` until the first non-na value.
2325
2325
  */
2326
2326
  export function min(source) {
2327
2327
  let best = NaN;
2328
2328
  return source.map((x) => {
2329
- if (!Number.isNaN(x) && !(x >= best))
2329
+ if (Number.isFinite(x) && !(x >= best))
2330
2330
  best = x;
2331
2331
  return best;
2332
2332
  });
@@ -2383,8 +2383,8 @@ export function cog(source, length = 10) {
2383
2383
  *
2384
2384
  * @remarks
2385
2385
  * PineScript rules:
2386
- * - the window is the last `length` non-`na` values (an `na` bar does not enter it, and gets the mode of the
2387
- * window it keeps)
2386
+ * - the window is the last `length` non-`na` values (an `na` or +/-Infinity bar does not enter it, and gets the mode
2387
+ * of the window it keeps)
2388
2388
  * - NaN until `length` non-`na` values exist
2389
2389
  * - If no mode exists, returns the smallest value
2390
2390
  */
@@ -2395,7 +2395,7 @@ export function mode(source, length) {
2395
2395
  const seen = []; // non-na values so far
2396
2396
  for (let i = 0; i < source.length; i++) {
2397
2397
  const v = source[i];
2398
- if (!Number.isNaN(v))
2398
+ if (Number.isFinite(v))
2399
2399
  seen.push(v);
2400
2400
  if (seen.length < len) {
2401
2401
  result.push(NaN);