oakscriptjs 0.13.1 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/AGENTS.md +53 -0
  2. package/README.md +1 -1
  3. package/bin/oakscript.mjs +5 -0
  4. package/dist/cjs/check/checks.d.ts +78 -0
  5. package/dist/cjs/check/checks.d.ts.map +1 -0
  6. package/dist/cjs/check/checks.js +109 -0
  7. package/dist/cjs/check/checks.js.map +7 -0
  8. package/dist/cjs/check/format.d.ts +26 -0
  9. package/dist/cjs/check/format.d.ts.map +1 -0
  10. package/dist/cjs/check/format.js +106 -0
  11. package/dist/cjs/check/format.js.map +7 -0
  12. package/dist/cjs/check/harness.d.ts +94 -0
  13. package/dist/cjs/check/harness.d.ts.map +1 -0
  14. package/dist/cjs/check/harness.js +302 -0
  15. package/dist/cjs/check/harness.js.map +7 -0
  16. package/dist/cjs/check/index.d.ts +253 -0
  17. package/dist/cjs/check/index.d.ts.map +1 -0
  18. package/dist/cjs/check/index.js +466 -0
  19. package/dist/cjs/check/index.js.map +7 -0
  20. package/dist/cjs/check/node.d.ts +53 -0
  21. package/dist/cjs/check/node.d.ts.map +1 -0
  22. package/dist/cjs/check/node.js +318 -0
  23. package/dist/cjs/check/node.js.map +7 -0
  24. package/dist/cjs/check/spec.d.ts +44 -0
  25. package/dist/cjs/check/spec.d.ts.map +1 -0
  26. package/dist/cjs/check/spec.js +199 -0
  27. package/dist/cjs/check/spec.js.map +7 -0
  28. package/dist/cjs/index.d.ts +1 -1
  29. package/dist/cjs/index.js +1 -1
  30. package/dist/cjs/index.js.map +1 -1
  31. package/dist/cjs/runtime/series.d.ts +6 -0
  32. package/dist/cjs/runtime/series.d.ts.map +1 -1
  33. package/dist/cjs/runtime/series.js +15 -0
  34. package/dist/cjs/runtime/series.js.map +2 -2
  35. package/dist/cjs/script/constants.d.ts +200 -0
  36. package/dist/cjs/script/constants.d.ts.map +1 -0
  37. package/dist/cjs/script/constants.js +217 -0
  38. package/dist/cjs/script/constants.js.map +7 -0
  39. package/dist/cjs/script/drawing-args.d.ts +25 -0
  40. package/dist/cjs/script/drawing-args.d.ts.map +1 -0
  41. package/dist/cjs/script/drawing-args.js +203 -0
  42. package/dist/cjs/script/drawing-args.js.map +7 -0
  43. package/dist/cjs/script/globals.d.ts +127 -0
  44. package/dist/cjs/script/globals.d.ts.map +1 -0
  45. package/dist/cjs/script/globals.js +17 -0
  46. package/dist/cjs/script/globals.js.map +7 -0
  47. package/dist/cjs/script/index.d.ts +499 -166
  48. package/dist/cjs/script/index.d.ts.map +1 -1
  49. package/dist/cjs/script/index.js +236 -96
  50. package/dist/cjs/script/index.js.map +3 -3
  51. package/dist/esm/check/checks.d.ts +78 -0
  52. package/dist/esm/check/checks.d.ts.map +1 -0
  53. package/dist/esm/check/checks.js +95 -0
  54. package/dist/esm/check/checks.js.map +1 -0
  55. package/dist/esm/check/format.d.ts +26 -0
  56. package/dist/esm/check/format.d.ts.map +1 -0
  57. package/dist/esm/check/format.js +105 -0
  58. package/dist/esm/check/format.js.map +1 -0
  59. package/dist/esm/check/harness.d.ts +94 -0
  60. package/dist/esm/check/harness.d.ts.map +1 -0
  61. package/dist/esm/check/harness.js +317 -0
  62. package/dist/esm/check/harness.js.map +1 -0
  63. package/dist/esm/check/index.d.ts +253 -0
  64. package/dist/esm/check/index.d.ts.map +1 -0
  65. package/dist/esm/check/index.js +470 -0
  66. package/dist/esm/check/index.js.map +1 -0
  67. package/dist/esm/check/node.d.ts +53 -0
  68. package/dist/esm/check/node.d.ts.map +1 -0
  69. package/dist/esm/check/node.js +347 -0
  70. package/dist/esm/check/node.js.map +1 -0
  71. package/dist/esm/check/spec.d.ts +44 -0
  72. package/dist/esm/check/spec.d.ts.map +1 -0
  73. package/dist/esm/check/spec.js +198 -0
  74. package/dist/esm/check/spec.js.map +1 -0
  75. package/dist/esm/index.d.ts +1 -1
  76. package/dist/esm/index.js +1 -1
  77. package/dist/esm/runtime/series.d.ts +6 -0
  78. package/dist/esm/runtime/series.d.ts.map +1 -1
  79. package/dist/esm/runtime/series.js +14 -0
  80. package/dist/esm/runtime/series.js.map +1 -1
  81. package/dist/esm/script/constants.d.ts +200 -0
  82. package/dist/esm/script/constants.d.ts.map +1 -0
  83. package/dist/esm/script/constants.js +151 -0
  84. package/dist/esm/script/constants.js.map +1 -0
  85. package/dist/esm/script/drawing-args.d.ts +25 -0
  86. package/dist/esm/script/drawing-args.d.ts.map +1 -0
  87. package/dist/esm/script/drawing-args.js +171 -0
  88. package/dist/esm/script/drawing-args.js.map +1 -0
  89. package/dist/esm/script/globals.d.ts +127 -0
  90. package/dist/esm/script/globals.d.ts.map +1 -0
  91. package/dist/esm/script/globals.js +28 -0
  92. package/dist/esm/script/globals.js.map +1 -0
  93. package/dist/esm/script/index.d.ts +499 -166
  94. package/dist/esm/script/index.d.ts.map +1 -1
  95. package/dist/esm/script/index.js +256 -83
  96. package/dist/esm/script/index.js.map +1 -1
  97. package/package.json +33 -1
  98. package/skills/oakscript/SKILL.md +198 -0
  99. package/skills/oakscript/examples/ma-cross-strategy.js +57 -0
  100. package/skills/oakscript/examples/ma-cross.js +34 -0
  101. package/skills/oakscript/examples/macd-oscillator.js +29 -0
  102. package/skills/oakscript/examples/mtf-trend-filter.js +46 -0
  103. package/skills/oakscript/reference/check.md +150 -0
  104. package/skills/oakscript/reference/errors.md +92 -0
  105. package/skills/oakscript/reference/pine-differences.md +85 -0
  106. package/skills/oakscript/reference/plotting.md +199 -0
  107. package/skills/oakscript/reference/script-structure.md +185 -0
  108. package/skills/oakscript/reference/strategies.md +140 -0
  109. package/skills/oakscript/reference/timeframes-symbols.md +97 -0
  110. package/skills/oakscript/spec.schema.json +199 -0
  111. package/src/check/checks.ts +175 -0
  112. package/src/check/format.ts +117 -0
  113. package/src/check/harness.ts +372 -0
  114. package/src/check/index.ts +708 -0
  115. package/src/check/node.ts +368 -0
  116. package/src/check/spec.ts +200 -0
  117. package/src/index.ts +1 -1
  118. package/src/runtime/series.ts +19 -0
  119. package/src/script/constants.ts +169 -0
  120. package/src/script/drawing-args.ts +179 -0
  121. package/src/script/globals.ts +129 -0
  122. package/src/script/index.ts +457 -81
@@ -35,8 +35,10 @@ __export(script_exports, {
35
35
  STRATEGY_DEFAULTS: () => import_strategy2.STRATEGY_DEFAULTS,
36
36
  Series: () => import_series.Series,
37
37
  StrategyRecorder: () => StrategyRecorder,
38
+ adjustment: () => adjustment,
38
39
  alert: () => alert,
39
40
  alertcondition: () => alertcondition,
41
+ bar_index: () => bar_index,
40
42
  barcolor: () => barcolor,
41
43
  barmerge: () => barmerge,
42
44
  barstate: () => barstate,
@@ -46,13 +48,18 @@ __export(script_exports, {
46
48
  close: () => close,
47
49
  color: () => color,
48
50
  compare: () => compare,
51
+ currency: () => currency,
49
52
  dayofmonth: () => dayofmonth,
50
53
  dayofweek: () => dayofweek,
54
+ display: () => display,
51
55
  eachBar: () => eachBar,
52
56
  executeIntrabar: () => executeIntrabar,
53
57
  executeScript: () => executeScript,
58
+ extend: () => extend,
54
59
  fill: () => fill,
55
60
  fixnan: () => fixnan,
61
+ font: () => font,
62
+ format: () => format,
56
63
  high: () => high,
57
64
  hl2: () => hl2,
58
65
  hlc3: () => hlc3,
@@ -65,8 +72,10 @@ __export(script_exports, {
65
72
  input: () => input,
66
73
  isInputActive: () => import_input_active.isInputActive,
67
74
  label: () => label,
75
+ last_bar_index: () => last_bar_index,
68
76
  line: () => line,
69
77
  linefill: () => linefill,
78
+ location: () => location,
70
79
  low: () => low,
71
80
  math: () => math,
72
81
  minute: () => minute,
@@ -75,6 +84,7 @@ __export(script_exports, {
75
84
  nz: () => import_utils.nz,
76
85
  ohlc4: () => ohlc4,
77
86
  open: () => open,
87
+ order: () => order,
78
88
  plot: () => plot,
79
89
  plotarrow: () => plotarrow,
80
90
  plotbar: () => plotbar,
@@ -85,9 +95,12 @@ __export(script_exports, {
85
95
  position: () => import_types.position,
86
96
  releaseDrawing: () => import_registry2.releaseDrawing,
87
97
  request: () => request,
98
+ scale: () => scale,
88
99
  second: () => second,
89
100
  seriesOf: () => seriesOf,
90
101
  session: () => session,
102
+ shape: () => shape,
103
+ size: () => size,
91
104
  str: () => str,
92
105
  strategy: () => strategy,
93
106
  syminfo: () => syminfo,
@@ -105,11 +118,15 @@ __export(script_exports, {
105
118
  varip: () => varip,
106
119
  volume: () => volume,
107
120
  weekofyear: () => weekofyear,
108
- year: () => year
121
+ xloc: () => xloc,
122
+ year: () => year,
123
+ yloc: () => yloc
109
124
  });
110
125
  module.exports = __toCommonJS(script_exports);
111
126
  var import_series = require("../runtime/series.js");
112
127
  var taSeries = __toESM(require("../ta-series.js"), 1);
128
+ var pineConstants = __toESM(require("./constants.js"), 1);
129
+ var import_drawing_args = require("./drawing-args.js");
113
130
  var colorCore = __toESM(require("../color/index.js"), 1);
114
131
  var import_parse = require("../color/parse.js");
115
132
  var import_utils = require("../utils/index.js");
@@ -154,7 +171,7 @@ function collector() {
154
171
  function freshCollector(inputValues) {
155
172
  return {
156
173
  title: "Untitled",
157
- overlay: true,
174
+ overlay: false,
158
175
  inputValues,
159
176
  inputConfig: [],
160
177
  inputIds: /* @__PURE__ */ new Set(),
@@ -253,7 +270,8 @@ function executeScript(body, barsInput, inputs = {}, chart2 = {}, options = {})
253
270
  shortTitle: c.shortTitle,
254
271
  overlay: c.overlay,
255
272
  precision: c.precision,
256
- format: c.format
273
+ format: c.format,
274
+ ...c.scale ? { scale: c.scale } : {}
257
275
  },
258
276
  inputConfig: c.inputConfig,
259
277
  plotConfig: c.plotConfig,
@@ -343,9 +361,10 @@ function indicator(title, options = {}) {
343
361
  declare(c, "indicator");
344
362
  c.title = title;
345
363
  c.shortTitle = options.shorttitle;
346
- c.overlay = options.overlay ?? true;
364
+ c.overlay = options.overlay ?? false;
347
365
  c.precision = options.precision;
348
366
  c.format = options.format;
367
+ c.scale = options.scale;
349
368
  (0, import_registry.setDrawingLimits)({
350
369
  line: options.max_lines_count,
351
370
  label: options.max_labels_count,
@@ -384,60 +403,113 @@ function registerNumeric(type, defval, title, opts = {}) {
384
403
  );
385
404
  return typeof v === "number" ? v : defval;
386
405
  }
387
- const input = {
388
- int(defval, title, opts = {}) {
389
- return Math.round(registerNumeric("int", defval, title, opts));
406
+ const COMMON_INPUT_KEYS = ["tooltip", "inline", "group", "confirm", "display", "active"];
407
+ const INPUT_KEYS = {
408
+ int: ["defval", "title", "minval", "maxval", "step", ...COMMON_INPUT_KEYS],
409
+ float: ["defval", "title", "minval", "maxval", "step", ...COMMON_INPUT_KEYS],
410
+ price: ["defval", "title", ...COMMON_INPUT_KEYS],
411
+ bool: ["defval", "title", ...COMMON_INPUT_KEYS],
412
+ string: ["defval", "title", "options", ...COMMON_INPUT_KEYS],
413
+ text_area: ["defval", "title", ...COMMON_INPUT_KEYS],
414
+ color: ["defval", "title", ...COMMON_INPUT_KEYS],
415
+ source: ["defval", "title", ...COMMON_INPUT_KEYS],
416
+ timeframe: ["defval", "title", "options", ...COMMON_INPUT_KEYS],
417
+ session: ["defval", "title", "options", ...COMMON_INPUT_KEYS],
418
+ symbol: ["defval", "title", "options", ...COMMON_INPUT_KEYS],
419
+ time: ["defval", "title", ...COMMON_INPUT_KEYS]
420
+ };
421
+ function inputArgs(kind, defvalOrArgs, titleOrArgs, opts) {
422
+ const name = `input.${kind}`;
423
+ const keys = INPUT_KEYS[kind];
424
+ let named = {};
425
+ let defval = defvalOrArgs;
426
+ let title = titleOrArgs;
427
+ if ((0, import_drawing_args.isPlainObject)(defvalOrArgs)) {
428
+ named = { ...defvalOrArgs };
429
+ defval = named.defval;
430
+ title = void 0;
431
+ } else if ((0, import_drawing_args.isPlainObject)(titleOrArgs)) {
432
+ named = { ...titleOrArgs };
433
+ title = void 0;
434
+ }
435
+ if (opts !== void 0) {
436
+ if (!(0, import_drawing_args.isPlainObject)(opts)) throw new TypeError(`${name}(): the options are an object, e.g. { tooltip: "..." }.`);
437
+ named = { ...named, ...opts };
438
+ }
439
+ for (const key of Object.keys(named)) if (!keys.includes(key)) throw (0, import_drawing_args.unknownArgument)(name, key, keys);
440
+ if (title !== void 0 && typeof title !== "string") {
441
+ throw new TypeError(`${name}(): the title is a string, got ${typeof title}.`);
442
+ }
443
+ const { defval: namedDefval, title: namedTitle, ...rest } = named;
444
+ return {
445
+ defval: defval ?? namedDefval,
446
+ title: title ?? namedTitle,
447
+ opts: rest
448
+ };
449
+ }
450
+ const input = strictNamespace("input", {
451
+ int(defval, title, opts) {
452
+ const a = inputArgs("int", defval, title, opts);
453
+ return Math.round(registerNumeric("int", a.defval, a.title, a.opts));
390
454
  },
391
- float(defval, title, opts = {}) {
392
- return registerNumeric("float", defval, title, opts);
455
+ float(defval, title, opts) {
456
+ const a = inputArgs("float", defval, title, opts);
457
+ return registerNumeric("float", a.defval, a.title, a.opts);
393
458
  },
394
- bool(defval, title, opts = {}) {
395
- return registerInput({ type: "bool", defval, title, ...common(opts) }, "input_bool");
459
+ bool(defval, title, opts) {
460
+ const a = inputArgs("bool", defval, title, opts);
461
+ return registerInput({ type: "bool", defval: a.defval, title: a.title, ...common(a.opts) }, "input_bool");
396
462
  },
397
- string(defval, title, opts = {}) {
398
- return registerInput({ type: "string", defval, title, options: opts.options, ...common(opts) }, "input_string");
463
+ string(defval, title, opts) {
464
+ const a = inputArgs("string", defval, title, opts);
465
+ return registerInput({ type: "string", defval: a.defval, title: a.title, options: a.opts.options, ...common(a.opts) }, "input_string");
399
466
  },
400
- /** Multi-line text ("
401
- " between the lines), e.g. a list a script parses (#184). */
402
- text_area(defval, title, opts = {}) {
403
- return registerInput({ type: "text_area", defval, title, ...common(opts) }, "input_text_area");
467
+ /** Multi-line text (lines separated by a newline), e.g. a list a script parses (#184). */
468
+ text_area(defval, title, opts) {
469
+ const a = inputArgs("text_area", defval, title, opts);
470
+ return registerInput({ type: "text_area", defval: a.defval, title: a.title, ...common(a.opts) }, "input_text_area");
404
471
  },
405
472
  /**
406
473
  * Declares a colour input. As in PineScript, the default keeps an alpha of 2 decimals: an input default
407
474
  * `color.new(c, 90)` has the alpha byte 26 (25 in the script). A value given by the host is not changed.
408
475
  */
409
- color(defval, title, opts = {}) {
410
- return registerInput({ type: "color", defval: (0, import_parse.inputColorDefault)(defval), title, ...common(opts) }, "input_color");
476
+ color(defval, title, opts) {
477
+ const a = inputArgs("color", defval, title, opts);
478
+ return registerInput({ type: "color", defval: (0, import_parse.inputColorDefault)(a.defval), title: a.title, ...common(a.opts) }, "input_color");
411
479
  },
412
480
  /** Declares a source input and returns it as a Series. */
413
- source(defval = "close", title, opts = {}) {
414
- const name = registerInput({ type: "source", defval, title, ...common(opts) }, "input_source");
481
+ source(defval = "close", title, opts) {
482
+ const a = inputArgs("source", defval, title, opts);
483
+ const name = registerInput({ type: "source", defval: sourceName(a.defval ?? "close"), title: a.title, ...common(a.opts) }, "input_source");
415
484
  return sourceSeries(name);
416
485
  },
417
486
  /** Timeframe string ("60", "1D", "W"). As in PineScript, "" means the chart timeframe. */
418
- timeframe(defval, title, opts = {}) {
419
- return registerInput(
420
- { type: "timeframe", defval, title, options: opts.options, ...common(opts) },
421
- "input_timeframe"
422
- );
487
+ timeframe(defval, title, opts) {
488
+ const a = inputArgs("timeframe", defval, title, opts);
489
+ return registerInput({ type: "timeframe", defval: a.defval, title: a.title, options: a.opts.options, ...common(a.opts) }, "input_timeframe");
423
490
  },
424
491
  /** Session string ("0930-1600", "0930-1600:23456"). */
425
- session(defval, title, opts = {}) {
426
- return registerInput(
427
- { type: "session", defval, title, options: opts.options, ...common(opts) },
428
- "input_session"
429
- );
492
+ session(defval, title, opts) {
493
+ const a = inputArgs("session", defval, title, opts);
494
+ return registerInput({ type: "session", defval: a.defval, title: a.title, options: a.opts.options, ...common(a.opts) }, "input_session");
430
495
  },
431
496
  /** Ticker id ("NASDAQ:MSFT"), for `request.security` of another symbol (#180). */
432
- symbol(defval, title, opts = {}) {
433
- return registerInput({ type: "symbol", defval, title, options: opts.options, ...common(opts) }, "input_symbol");
497
+ symbol(defval, title, opts) {
498
+ const a = inputArgs("symbol", defval, title, opts);
499
+ return registerInput({ type: "symbol", defval: a.defval, title: a.title, options: a.opts.options, ...common(a.opts) }, "input_symbol");
500
+ },
501
+ /** PineScript `input.price`: a price level, a float input (the host shows it as a number). */
502
+ price(defval, title, opts) {
503
+ const a = inputArgs("price", defval, title, opts);
504
+ return registerNumeric("float", a.defval, a.title, a.opts);
434
505
  },
435
506
  /** Date and time as a UNIX time in milliseconds, e.g. `input.time(timestamp('2024-01-01'), 'Start')`. */
436
- time(defval, title, opts = {}) {
437
- const v = registerInput({ type: "time", defval, title, ...common(opts) }, "input_time");
438
- return typeof v === "number" ? v : defval;
507
+ time(defval, title, opts) {
508
+ const a = inputArgs("time", defval, title, opts);
509
+ const v = registerInput({ type: "time", defval: a.defval, title: a.title, ...common(a.opts) }, "input_time");
510
+ return typeof v === "number" ? v : a.defval;
439
511
  }
440
- };
512
+ });
441
513
  const open = import_series.Series.fromBars(ctxBars, "open");
442
514
  const high = import_series.Series.fromBars(ctxBars, "high");
443
515
  const low = import_series.Series.fromBars(ctxBars, "low");
@@ -447,8 +519,20 @@ const hl2 = new import_series.Series(ctxBars, (b) => (b.high + b.low) / 2);
447
519
  const hlc3 = new import_series.Series(ctxBars, (b) => (b.high + b.low + b.close) / 3);
448
520
  const ohlc4 = new import_series.Series(ctxBars, (b) => (b.open + b.high + b.low + b.close) / 4);
449
521
  const hlcc4 = new import_series.Series(ctxBars, (b) => (b.high + b.low + b.close + b.close) / 4);
522
+ const bar_index = new import_series.Series(ctxBars, (_b, i) => i);
523
+ bar_index.fullHistory = true;
524
+ const last_bar_index = new import_series.Series(ctxBars, (_b, _i, data) => data.length - 1);
525
+ last_bar_index.fullHistory = true;
450
526
  for (const s of [hl2, hlc3, ohlc4, hlcc4]) s.fullHistory = true;
451
527
  const SOURCES = { open, high, low, close, volume, hl2, hlc3, ohlc4, hlcc4 };
528
+ function sourceName(defval) {
529
+ if (typeof defval === "string") return defval;
530
+ const name = Object.keys(SOURCES).find((k) => SOURCES[k] === defval);
531
+ if (!name) {
532
+ throw new Error("input.source(): the default must be a built-in source (open, high, low, close, volume, hl2, hlc3, ohlc4, hlcc4).");
533
+ }
534
+ return name;
535
+ }
452
536
  function sourceSeries(name) {
453
537
  const builtin = SOURCES[name];
454
538
  if (builtin) return builtin;
@@ -469,7 +553,58 @@ function barsSeries(compute) {
469
553
  return values[i] ?? NaN;
470
554
  });
471
555
  }
472
- const ta = {
556
+ function editDistance(a, b) {
557
+ const row = Array.from({ length: b.length + 1 }, (_, j) => j);
558
+ for (let i = 1; i <= a.length; i++) {
559
+ let diag = row[0];
560
+ row[0] = i;
561
+ for (let j = 1; j <= b.length; j++) {
562
+ const up = row[j];
563
+ row[j] = Math.min(up + 1, row[j - 1] + 1, diag + (a[i - 1] === b[j - 1] ? 0 : 1));
564
+ diag = up;
565
+ }
566
+ }
567
+ return row[b.length];
568
+ }
569
+ const PROBED_NAMES = /* @__PURE__ */ new Set(["then", "toJSON", "asymmetricMatch", "nodeType", "tagName", "inspect", "default"]);
570
+ function strictNamespace(name, members) {
571
+ return new Proxy(members, {
572
+ get(target, prop, receiver) {
573
+ if (typeof prop === "symbol" || prop in target || PROBED_NAMES.has(prop) || /^[_$@]/.test(prop)) {
574
+ return Reflect.get(target, prop, receiver);
575
+ }
576
+ const keys = Object.keys(target);
577
+ const lower = prop.toLowerCase();
578
+ const ranked = keys.map((k) => ({ k, d: editDistance(lower, k.toLowerCase()) })).filter(({ k, d }) => {
579
+ const key = k.toLowerCase();
580
+ return d <= Math.max(1, Math.floor(prop.length / 3)) || key.includes(lower) || key.length >= 3 && lower.includes(key);
581
+ }).sort((x, y) => x.d - y.d).slice(0, 3).map(({ k }) => `${name}.${k}`);
582
+ throw new TypeError(
583
+ `${name}.${prop} does not exist.` + (ranked.length ? ` Did you mean ${ranked.join(", ")}?` : "") + " See docs/inventory.md for the supported functions."
584
+ );
585
+ }
586
+ });
587
+ }
588
+ function outsideBarLoops(members) {
589
+ const out = {};
590
+ for (const [key, value] of Object.entries(members)) {
591
+ if (typeof value !== "function") {
592
+ out[key] = value;
593
+ continue;
594
+ }
595
+ const fn = value;
596
+ out[key] = function(...args) {
597
+ if (currentBar >= 0) {
598
+ throw new Error(
599
+ `ta.${key}() was called inside eachBar(): a ta.* call computes the whole Series at once. Compute it before the loop (const x = ta.${key}(...)) and read the bar's value with c.get(x). For a Pine ta.* call inside an if block or a for loop, use the callsite.* call sites.`
600
+ );
601
+ }
602
+ return fn.apply(this, args);
603
+ };
604
+ }
605
+ return out;
606
+ }
607
+ const ta = strictNamespace("ta", outsideBarLoops({
473
608
  ...taSeries,
474
609
  tr: (handleNa = false) => taSeries.tr(bars(), handleNa),
475
610
  atr: (length) => taSeries.atr(bars(), length),
@@ -496,6 +631,8 @@ const ta = {
496
631
  const a = anchor ?? vwapAnchor();
497
632
  return stdev_mult === void 0 ? taSeries.vwap(source, volume, a) : taSeries.vwapBands(source, volume, a, stdev_mult);
498
633
  }),
634
+ /** `ta.vwma(source, length)` with the chart volume, as PineScript; a third argument gives another volume. */
635
+ vwma: (source, length, vol) => taSeries.vwma(source, length, vol ?? volume),
499
636
  /** `ta.mfi(source, length)` with the chart volume (PineScript takes 2 arguments). */
500
637
  mfi: (source, length) => taSeries.mfi(source, length, volume),
501
638
  /** `ta.pivothigh(source, leftbars, rightbars)` or `ta.pivothigh(leftbars, rightbars)` (source = high).
@@ -512,7 +649,7 @@ const ta = {
512
649
  iii: barsSeries(taSeries.iii),
513
650
  wad: barsSeries(taSeries.wad),
514
651
  wvad: barsSeries(taSeries.wvad)
515
- };
652
+ }));
516
653
  function fixnan(source) {
517
654
  if (source instanceof import_series.Series) return import_series.Series.fromArray(ctxBars, (0, import_utils.fixnan)(source.toArray()));
518
655
  return withPalette((0, import_utils.fixnan)(source), colorPalettes.get(source));
@@ -530,11 +667,11 @@ function colorWhen(cond, colorTrue, colorFalse) {
530
667
  const palette = [colorTrue, ...colorFalse !== void 0 && colorFalse !== colorTrue ? [colorFalse] : []];
531
668
  return withPalette(colors, palette);
532
669
  }
533
- const color = {
670
+ const color = strictNamespace("color", {
534
671
  ...colorCore,
535
672
  new: colorCore.new_color,
536
673
  when: colorWhen
537
- };
674
+ });
538
675
  const DEFAULT_OUTPUT_TITLES = {
539
676
  plot: "Plot",
540
677
  hline: "Level",
@@ -571,10 +708,12 @@ function plotImpl(series, title = DEFAULT_OUTPUT_TITLES.plot, options = {}) {
571
708
  const values = series.toArray();
572
709
  const b = bars();
573
710
  const data = [];
574
- for (let i = 0; i < b.length; i++) {
711
+ const off = Math.trunc(options.offset ?? 0);
712
+ for (let j = Math.max(0, off); j < b.length && j - off < b.length; j++) {
713
+ const i = j - off;
575
714
  const value = values[i];
576
715
  if (value === void 0 || !Number.isFinite(value)) continue;
577
- data.push(perBar2 ? { time: b[i].time, value, color: perBar2[i] } : { time: b[i].time, value });
716
+ data.push(perBar2 ? { time: b[j].time, value, color: perBar2[i] } : { time: b[j].time, value });
578
717
  }
579
718
  c.plots[id] = data;
580
719
  return { id, kind: "plot" };
@@ -702,8 +841,8 @@ const MARKER_SHAPES = {
702
841
  square: "square",
703
842
  diamond: "diamond"
704
843
  };
705
- function markerPosition(location, shape) {
706
- switch (location) {
844
+ function markerPosition(location2, shape2) {
845
+ switch (location2) {
707
846
  case "abovebar":
708
847
  return "aboveBar";
709
848
  case "belowbar":
@@ -713,7 +852,7 @@ function markerPosition(location, shape) {
713
852
  case "bottom":
714
853
  return "bottom";
715
854
  case "absolute":
716
- return shape === "labeldown" ? "atPriceTop" : shape === "labelup" ? "atPriceBottom" : "atPriceMiddle";
855
+ return shape2 === "labeldown" ? "atPriceTop" : shape2 === "labelup" ? "atPriceBottom" : "atPriceMiddle";
717
856
  }
718
857
  }
719
858
  const MARKER_COLOR = "#2962FF";
@@ -733,14 +872,14 @@ function emitMarkers(kind, condition, title, options) {
733
872
  title ??= DEFAULT_OUTPUT_TITLES[kind];
734
873
  const style = kind === "shape" ? options.style ?? "xcross" : "char";
735
874
  const char = kind === "char" ? options.char ?? "*" : void 0;
736
- const location = options.location ?? "abovebar";
875
+ const location2 = options.location ?? "abovebar";
737
876
  c.shapeConfig.push({
738
877
  id,
739
878
  kind,
740
879
  title,
741
880
  style: kind === "shape" ? style : void 0,
742
881
  char,
743
- location,
882
+ location: location2,
744
883
  color: options.color,
745
884
  text: options.text,
746
885
  textcolor: options.textcolor,
@@ -752,7 +891,7 @@ function emitMarkers(kind, condition, title, options) {
752
891
  c.outputs.push({ kind, id, title });
753
892
  const shapeStyle = kind === "shape" ? style : void 0;
754
893
  const template = {
755
- position: markerPosition(location, shapeStyle),
894
+ position: markerPosition(location2, shapeStyle),
756
895
  shape: shapeStyle ? MARKER_SHAPES[shapeStyle] : "circle",
757
896
  color: options.color ?? MARKER_COLOR,
758
897
  id
@@ -773,7 +912,7 @@ function emitMarkers(kind, condition, title, options) {
773
912
  const j = i + off;
774
913
  if (j < 0 || j >= b.length) continue;
775
914
  const time2 = b[j].time;
776
- c.markers.push(location === "absolute" ? { time: time2, ...template, price: v } : { time: time2, ...template });
915
+ c.markers.push(location2 === "absolute" ? { time: time2, ...template, price: v } : { time: time2, ...template });
777
916
  }
778
917
  }
779
918
  function plotshape(condition, title, options = {}) {
@@ -1337,8 +1476,8 @@ function symbolScale() {
1337
1476
  collector();
1338
1477
  const { minmove, pricescale } = chartCtx;
1339
1478
  if (minmove !== void 0 && pricescale !== void 0) return [minmove, pricescale];
1340
- const [move, scale] = (0, import_numberformat.tickScale)(symbolProperty("mintick"), pricescale);
1341
- return [minmove ?? move, scale];
1479
+ const [move, scale2] = (0, import_numberformat.tickScale)(symbolProperty("mintick"), pricescale);
1480
+ return [minmove ?? move, scale2];
1342
1481
  }
1343
1482
  const syminfo = {
1344
1483
  get mintick() {
@@ -1396,7 +1535,7 @@ const year = calendar(timeCore.year);
1396
1535
  const month = calendar(timeCore.month);
1397
1536
  const weekofyear = calendar(timeCore.weekofyear);
1398
1537
  const dayofmonth = calendar(timeCore.dayofmonth);
1399
- const dayofweek = calendar(timeCore.dayofweek);
1538
+ const dayofweek = Object.assign(calendar(timeCore.dayofweek), pineConstants.daysOfWeek);
1400
1539
  const hour = calendar(timeCore.hour);
1401
1540
  const minute = calendar(timeCore.minute);
1402
1541
  const second = calendar(timeCore.second);
@@ -1412,17 +1551,17 @@ function timestamp(first, ...rest) {
1412
1551
  function inSession(time2, session2, timezone) {
1413
1552
  return timeCore.inSession(time2, session2, timezone ?? exchangeTimezone());
1414
1553
  }
1415
- const str = {
1554
+ const str = strictNamespace("str", {
1416
1555
  ...strCore,
1417
1556
  // format.mintick uses the chart symbol's tick and price scale (syminfo.mintick, syminfo.pricescale)
1418
- tostring: ((value, format, mintick, pricescale) => format === "mintick" && mintick === void 0 ? strCore.tostring(value, format, syminfo.mintick, pricescale ?? syminfo.pricescale) : strCore.tostring(value, format, mintick, pricescale)),
1419
- format_time(time2, format = "yyyy-MM-dd'T'HH:mm:ssZ", timezone) {
1420
- return strCore.format_time(time2, format, timezone ?? exchangeTimezone());
1557
+ tostring: ((value, format2, mintick, pricescale) => format2 === "mintick" && mintick === void 0 ? strCore.tostring(value, format2, syminfo.mintick, pricescale ?? syminfo.pricescale) : strCore.tostring(value, format2, mintick, pricescale)),
1558
+ format_time(time2, format2 = "yyyy-MM-dd'T'HH:mm:ssZ", timezone) {
1559
+ return strCore.format_time(time2, format2, timezone ?? exchangeTimezone());
1421
1560
  },
1422
1561
  format(pattern, ...args) {
1423
1562
  return (0, import_messageformat.formatMessage)(pattern, args, exchangeTimezone);
1424
1563
  }
1425
- };
1564
+ });
1426
1565
  function barTime(bar) {
1427
1566
  return bar.time * (chartCtx.timeUnit === "ms" ? 1 : 1e3);
1428
1567
  }
@@ -1734,44 +1873,45 @@ function security_lower_tf(symbol, timeframe2, expression, ignore_invalid_symbol
1734
1873
  const mapped = values.map((v) => ranges.map(([from, to]) => v.slice(from, to)));
1735
1874
  return Array.isArray(result) ? mapped : mapped[0];
1736
1875
  }
1737
- const request = { security, security_lower_tf };
1738
- const line = {
1739
- ...lineCore,
1740
- get all() {
1741
- return lineCore.all();
1742
- }
1743
- };
1744
- const label = {
1745
- ...labelCore,
1746
- get all() {
1747
- return labelCore.all();
1876
+ const SECURITY_PARAMETERS = ["symbol", "timeframe", "expression", "gaps", "lookahead", "ignore_invalid_symbol", "currency", "calc_bars_count"];
1877
+ const SECURITY_LOWER_TF_PARAMETERS = ["symbol", "timeframe", "expression", "ignore_invalid_symbol", "currency", "ignore_invalid_timeframe", "calc_bars_count"];
1878
+ function unsupportedSecurityArgs(name, currency2, calcBarsCount) {
1879
+ if (currency2 !== void 0 && currency2 !== "" && currency2 !== "NONE") {
1880
+ throw new Error(`${name}(): the currency argument (conversion of the values) is not supported.`);
1748
1881
  }
1749
- };
1750
- const box = {
1751
- ...boxCore,
1752
- get all() {
1753
- return boxCore.all();
1754
- }
1755
- };
1756
- const linefill = {
1757
- ...linefillCore,
1758
- get all() {
1759
- return linefillCore.all();
1760
- }
1761
- };
1762
- const polyline = {
1763
- ...polylineCore,
1764
- get all() {
1765
- return polylineCore.all();
1766
- }
1767
- };
1768
- const table = {
1769
- ...tableCore,
1770
- get all() {
1771
- return tableCore.all();
1772
- }
1773
- };
1882
+ if (calcBarsCount !== void 0) throw new Error(`${name}(): the calc_bars_count argument is not supported.`);
1883
+ }
1884
+ function securityCall(...args) {
1885
+ const a = (0, import_drawing_args.namedArguments)("request.security", SECURITY_PARAMETERS, args);
1886
+ unsupportedSecurityArgs("request.security", a[6], a[7]);
1887
+ return security(a[0], a[1], a[2], a[3], a[4], a[5]);
1888
+ }
1889
+ function securityLowerTfCall(...args) {
1890
+ const a = (0, import_drawing_args.namedArguments)("request.security_lower_tf", SECURITY_LOWER_TF_PARAMETERS, args);
1891
+ unsupportedSecurityArgs("request.security_lower_tf", a[4], a[6]);
1892
+ if (a[5] !== void 0 && a[5] !== false) throw new Error("request.security_lower_tf(): the ignore_invalid_timeframe argument is not supported.");
1893
+ return security_lower_tf(a[0], a[1], a[2], a[3]);
1894
+ }
1895
+ const request = strictNamespace("request", { security: securityCall, security_lower_tf: securityLowerTfCall });
1896
+ const loopBar = () => currentBar;
1897
+ function drawings(name, members, all) {
1898
+ const out = (0, import_drawing_args.drawingNamespace)(name, members, loopBar);
1899
+ return Object.defineProperty(out, "all", { get: all, enumerable: true });
1900
+ }
1901
+ const lineNs = drawings("line", { ...lineCore, ...pineConstants.lineStyles }, () => lineCore.all());
1902
+ const line = lineNs;
1903
+ const labelNs = drawings("label", { ...labelCore, ...pineConstants.labelStyles }, () => labelCore.all());
1904
+ const label = labelNs;
1905
+ const boxNs = drawings("box", { ...boxCore }, () => boxCore.all());
1906
+ const box = boxNs;
1907
+ const linefillNs = drawings("linefill", { ...linefillCore }, () => linefillCore.all());
1908
+ const linefill = linefillNs;
1909
+ const polylineNs = drawings("polyline", { ...polylineCore }, () => polylineCore.all());
1910
+ const polyline = polylineNs;
1911
+ const tableNs = drawings("table", { ...tableCore }, () => tableCore.all());
1912
+ const table = tableNs;
1774
1913
  const text = { ...textCore };
1914
+ const { shape, location, size, xloc, yloc, extend, display, format, font, scale, order, currency, adjustment } = pineConstants;
1775
1915
  const chart = {
1776
1916
  /** Chart foreground colour (PineScript `chart.fg_color`), from the chart context. */
1777
1917
  get fg_color() {
@@ -1836,11 +1976,11 @@ const alert = Object.assign(alertImpl, {
1836
1976
  const { saveRandom: _saveRandom, restoreRandom: _restoreRandom, ...mathScript } = mathCore;
1837
1977
  void _saveRandom;
1838
1978
  void _restoreRandom;
1839
- const math = {
1979
+ const math = strictNamespace("math", {
1840
1980
  ...mathScript,
1841
1981
  round_to_mintick: ((number, mintick) => {
1842
1982
  const tick = mintick ?? syminfo.mintick;
1843
1983
  return number instanceof import_series.Series ? mathCore.round_to_mintick(number, tick) : mathCore.round_to_mintick(number, tick);
1844
1984
  })
1845
- };
1985
+ });
1846
1986
  //# sourceMappingURL=index.js.map