oakscriptjs 0.11.0 → 0.11.2
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 +8 -2
- package/dist/cjs/array/index.d.ts.map +1 -1
- package/dist/cjs/array/index.js +2 -1
- package/dist/cjs/array/index.js.map +2 -2
- package/dist/cjs/box/index.js +6 -6
- package/dist/cjs/box/index.js.map +2 -2
- package/dist/cjs/callsite/index.d.ts.map +1 -1
- package/dist/cjs/callsite/index.js +6 -3
- package/dist/cjs/callsite/index.js.map +2 -2
- package/dist/cjs/drawing/registry.d.ts +15 -6
- package/dist/cjs/drawing/registry.d.ts.map +1 -1
- package/dist/cjs/drawing/registry.js +16 -2
- package/dist/cjs/drawing/registry.js.map +2 -2
- package/dist/cjs/index.d.ts +4 -3
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +7 -1
- package/dist/cjs/index.js.map +2 -2
- package/dist/cjs/input.d.ts +9 -1
- package/dist/cjs/input.d.ts.map +1 -1
- package/dist/cjs/input.js +16 -0
- package/dist/cjs/input.js.map +2 -2
- package/dist/cjs/label/index.js +3 -3
- package/dist/cjs/label/index.js.map +2 -2
- package/dist/cjs/line/index.d.ts +10 -27
- package/dist/cjs/line/index.d.ts.map +1 -1
- package/dist/cjs/line/index.js +10 -27
- package/dist/cjs/line/index.js.map +2 -2
- package/dist/cjs/linefill/index.d.ts +3 -0
- package/dist/cjs/linefill/index.d.ts.map +1 -1
- package/dist/cjs/linefill/index.js +15 -1
- package/dist/cjs/linefill/index.js.map +3 -3
- package/dist/cjs/runtime/adapters/SimpleInputAdapter.js +1 -1
- package/dist/cjs/runtime/adapters/SimpleInputAdapter.js.map +2 -2
- package/dist/cjs/runtime/index.d.ts +1 -1
- package/dist/cjs/runtime/index.d.ts.map +1 -1
- package/dist/cjs/runtime/index.js +1 -0
- package/dist/cjs/runtime/index.js.map +2 -2
- package/dist/cjs/runtime/inputs.d.ts +9 -0
- package/dist/cjs/runtime/inputs.d.ts.map +1 -1
- package/dist/cjs/runtime/inputs.js +8 -0
- package/dist/cjs/runtime/inputs.js.map +2 -2
- package/dist/cjs/runtime/types.d.ts +1 -1
- package/dist/cjs/runtime/types.d.ts.map +1 -1
- package/dist/cjs/runtime/types.js.map +1 -1
- package/dist/cjs/script/index.d.ts +66 -13
- package/dist/cjs/script/index.d.ts.map +1 -1
- package/dist/cjs/script/index.js +139 -35
- package/dist/cjs/script/index.js.map +3 -3
- package/dist/cjs/security/other.d.ts +92 -0
- package/dist/cjs/security/other.d.ts.map +1 -0
- package/dist/cjs/security/other.js +164 -0
- package/dist/cjs/security/other.js.map +7 -0
- package/dist/cjs/session/bars.d.ts +10 -1
- package/dist/cjs/session/bars.d.ts.map +1 -1
- package/dist/cjs/session/bars.js +16 -2
- package/dist/cjs/session/bars.js.map +2 -2
- package/dist/cjs/session/calendar.d.ts +4 -1
- package/dist/cjs/session/calendar.d.ts.map +1 -1
- package/dist/cjs/session/calendar.js +12 -7
- package/dist/cjs/session/calendar.js.map +2 -2
- package/dist/cjs/session/context.d.ts +22 -5
- package/dist/cjs/session/context.d.ts.map +1 -1
- package/dist/cjs/session/context.js +67 -6
- package/dist/cjs/session/context.js.map +2 -2
- package/dist/cjs/str/floatingdecimal.d.ts +31 -0
- package/dist/cjs/str/floatingdecimal.d.ts.map +1 -0
- package/dist/cjs/str/floatingdecimal.js +298 -0
- package/dist/cjs/str/floatingdecimal.js.map +7 -0
- package/dist/cjs/str/index.d.ts +4 -3
- package/dist/cjs/str/index.d.ts.map +1 -1
- package/dist/cjs/str/index.js +1 -1
- package/dist/cjs/str/index.js.map +2 -2
- package/dist/cjs/str/numberformat.d.ts +6 -4
- package/dist/cjs/str/numberformat.d.ts.map +1 -1
- package/dist/cjs/str/numberformat.js +3 -2
- package/dist/cjs/str/numberformat.js.map +2 -2
- package/dist/cjs/ta/index.d.ts +64 -45
- package/dist/cjs/ta/index.d.ts.map +1 -1
- package/dist/cjs/ta/index.js +140 -126
- package/dist/cjs/ta/index.js.map +3 -3
- package/dist/cjs/ta/limits.d.ts +11 -0
- package/dist/cjs/ta/limits.d.ts.map +1 -1
- package/dist/cjs/ta/limits.js +15 -1
- package/dist/cjs/ta/limits.js.map +2 -2
- package/dist/cjs/ta/running-sum.js +1 -1
- package/dist/cjs/ta/running-sum.js.map +2 -2
- package/dist/cjs/ta-series.d.ts +1 -1
- package/dist/cjs/ta-series.d.ts.map +1 -1
- package/dist/cjs/ta-series.js +1 -1
- package/dist/cjs/ta-series.js.map +2 -2
- package/dist/cjs/table/index.d.ts +10 -3
- package/dist/cjs/table/index.d.ts.map +1 -1
- package/dist/cjs/table/index.js +11 -1
- package/dist/cjs/table/index.js.map +3 -3
- package/dist/cjs/time/session.d.ts +9 -0
- package/dist/cjs/time/session.d.ts.map +1 -1
- package/dist/cjs/time/session.js +42 -14
- package/dist/cjs/time/session.js.map +3 -3
- package/dist/cjs/time/timezone.d.ts +6 -1
- package/dist/cjs/time/timezone.d.ts.map +1 -1
- package/dist/cjs/time/timezone.js +2 -2
- package/dist/cjs/time/timezone.js.map +2 -2
- package/dist/cjs/types/metadata.d.ts +1 -1
- package/dist/cjs/types/metadata.d.ts.map +1 -1
- package/dist/cjs/types/metadata.js.map +1 -1
- package/dist/esm/array/index.d.ts +8 -2
- package/dist/esm/array/index.d.ts.map +1 -1
- package/dist/esm/array/index.js +12 -3
- package/dist/esm/array/index.js.map +1 -1
- package/dist/esm/box/index.js +6 -6
- package/dist/esm/box/index.js.map +1 -1
- package/dist/esm/callsite/index.d.ts.map +1 -1
- package/dist/esm/callsite/index.js +6 -3
- package/dist/esm/callsite/index.js.map +1 -1
- package/dist/esm/drawing/registry.d.ts +15 -6
- package/dist/esm/drawing/registry.d.ts.map +1 -1
- package/dist/esm/drawing/registry.js +30 -7
- package/dist/esm/drawing/registry.js.map +1 -1
- package/dist/esm/index.d.ts +4 -3
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +8 -5
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/input.d.ts +9 -1
- package/dist/esm/input.d.ts.map +1 -1
- package/dist/esm/input.js +16 -0
- package/dist/esm/input.js.map +1 -1
- package/dist/esm/label/index.js +3 -3
- package/dist/esm/label/index.js.map +1 -1
- package/dist/esm/line/index.d.ts +10 -27
- package/dist/esm/line/index.d.ts.map +1 -1
- package/dist/esm/line/index.js +20 -64
- package/dist/esm/line/index.js.map +1 -1
- package/dist/esm/linefill/index.d.ts +3 -0
- package/dist/esm/linefill/index.d.ts.map +1 -1
- package/dist/esm/linefill/index.js +20 -1
- package/dist/esm/linefill/index.js.map +1 -1
- package/dist/esm/runtime/adapters/SimpleInputAdapter.js +1 -1
- package/dist/esm/runtime/adapters/SimpleInputAdapter.js.map +1 -1
- package/dist/esm/runtime/index.d.ts +1 -1
- package/dist/esm/runtime/index.d.ts.map +1 -1
- package/dist/esm/runtime/index.js +1 -1
- package/dist/esm/runtime/index.js.map +1 -1
- package/dist/esm/runtime/inputs.d.ts +9 -0
- package/dist/esm/runtime/inputs.d.ts.map +1 -1
- package/dist/esm/runtime/inputs.js +15 -0
- package/dist/esm/runtime/inputs.js.map +1 -1
- package/dist/esm/runtime/types.d.ts +1 -1
- package/dist/esm/runtime/types.d.ts.map +1 -1
- package/dist/esm/script/index.d.ts +66 -13
- package/dist/esm/script/index.d.ts.map +1 -1
- package/dist/esm/script/index.js +187 -54
- package/dist/esm/script/index.js.map +1 -1
- package/dist/esm/security/other.d.ts +92 -0
- package/dist/esm/security/other.d.ts.map +1 -0
- package/dist/esm/security/other.js +211 -0
- package/dist/esm/security/other.js.map +1 -0
- package/dist/esm/session/bars.d.ts +10 -1
- package/dist/esm/session/bars.d.ts.map +1 -1
- package/dist/esm/session/bars.js +26 -1
- package/dist/esm/session/bars.js.map +1 -1
- package/dist/esm/session/calendar.d.ts +4 -1
- package/dist/esm/session/calendar.d.ts.map +1 -1
- package/dist/esm/session/calendar.js +23 -7
- package/dist/esm/session/calendar.js.map +1 -1
- package/dist/esm/session/context.d.ts +22 -5
- package/dist/esm/session/context.d.ts.map +1 -1
- package/dist/esm/session/context.js +86 -10
- package/dist/esm/session/context.js.map +1 -1
- package/dist/esm/str/floatingdecimal.d.ts +31 -0
- package/dist/esm/str/floatingdecimal.d.ts.map +1 -0
- package/dist/esm/str/floatingdecimal.js +272 -0
- package/dist/esm/str/floatingdecimal.js.map +1 -0
- package/dist/esm/str/index.d.ts +4 -3
- package/dist/esm/str/index.d.ts.map +1 -1
- package/dist/esm/str/index.js +6 -5
- package/dist/esm/str/index.js.map +1 -1
- package/dist/esm/str/numberformat.d.ts +6 -4
- package/dist/esm/str/numberformat.d.ts.map +1 -1
- package/dist/esm/str/numberformat.js +9 -5
- package/dist/esm/str/numberformat.js.map +1 -1
- package/dist/esm/ta/index.d.ts +64 -45
- package/dist/esm/ta/index.d.ts.map +1 -1
- package/dist/esm/ta/index.js +198 -228
- package/dist/esm/ta/index.js.map +1 -1
- package/dist/esm/ta/limits.d.ts +11 -0
- package/dist/esm/ta/limits.d.ts.map +1 -1
- package/dist/esm/ta/limits.js +27 -2
- package/dist/esm/ta/limits.js.map +1 -1
- package/dist/esm/ta/running-sum.js +1 -1
- package/dist/esm/ta/running-sum.js.map +1 -1
- package/dist/esm/ta-series.d.ts +1 -1
- package/dist/esm/ta-series.d.ts.map +1 -1
- package/dist/esm/ta-series.js +2 -1
- package/dist/esm/ta-series.js.map +1 -1
- package/dist/esm/table/index.d.ts +10 -3
- package/dist/esm/table/index.d.ts.map +1 -1
- package/dist/esm/table/index.js +23 -3
- package/dist/esm/table/index.js.map +1 -1
- package/dist/esm/time/session.d.ts +9 -0
- package/dist/esm/time/session.d.ts.map +1 -1
- package/dist/esm/time/session.js +53 -15
- package/dist/esm/time/session.js.map +1 -1
- package/dist/esm/time/timezone.d.ts +6 -1
- package/dist/esm/time/timezone.d.ts.map +1 -1
- package/dist/esm/time/timezone.js +8 -2
- package/dist/esm/time/timezone.js.map +1 -1
- package/dist/esm/types/metadata.d.ts +1 -1
- package/dist/esm/types/metadata.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/array/index.ts +11 -3
- package/src/box/index.ts +6 -6
- package/src/callsite/index.ts +6 -3
- package/src/drawing/registry.ts +30 -7
- package/src/index.ts +16 -3
- package/src/input.ts +18 -1
- package/src/label/index.ts +3 -3
- package/src/line/index.ts +20 -68
- package/src/linefill/index.ts +20 -1
- package/src/runtime/adapters/SimpleInputAdapter.ts +1 -1
- package/src/runtime/index.ts +1 -0
- package/src/runtime/inputs.ts +16 -0
- package/src/runtime/types.ts +1 -1
- package/src/script/index.ts +262 -58
- package/src/security/other.ts +269 -0
- package/src/session/bars.ts +24 -1
- package/src/session/calendar.ts +26 -7
- package/src/session/context.ts +104 -10
- package/src/str/floatingdecimal.ts +268 -0
- package/src/str/index.ts +6 -5
- package/src/str/numberformat.ts +11 -6
- package/src/ta/index.ts +200 -225
- package/src/ta/limits.ts +28 -1
- package/src/ta/running-sum.ts +1 -1
- package/src/ta-series.ts +3 -2
- package/src/table/index.ts +22 -3
- package/src/time/session.ts +58 -16
- package/src/time/timezone.ts +9 -2
- package/src/types/metadata.ts +1 -1
package/dist/cjs/script/index.js
CHANGED
|
@@ -29,6 +29,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
29
29
|
var script_exports = {};
|
|
30
30
|
__export(script_exports, {
|
|
31
31
|
BarData: () => import_series.BarData,
|
|
32
|
+
MissingSymbolDataError: () => MissingSymbolDataError,
|
|
32
33
|
STRATEGY_DEFAULTS: () => import_strategy2.STRATEGY_DEFAULTS,
|
|
33
34
|
Series: () => import_series.Series,
|
|
34
35
|
alertcondition: () => alertcondition,
|
|
@@ -126,9 +127,10 @@ var import_numberformat = require("../str/numberformat.js");
|
|
|
126
127
|
var import_calendar = require("../session/calendar.js");
|
|
127
128
|
var import_bars = require("../session/bars.js");
|
|
128
129
|
var import_resample = require("../security/resample.js");
|
|
130
|
+
var import_other = require("../security/other.js");
|
|
129
131
|
var import_types = require("../types/index.js");
|
|
130
132
|
var import_strategy = require("../strategy/index.js");
|
|
131
|
-
var
|
|
133
|
+
var import_context = require("../session/context.js");
|
|
132
134
|
var import_strategy2 = require("../strategy/index.js");
|
|
133
135
|
var compare = __toESM(require("../compare/index.js"), 1);
|
|
134
136
|
var import_input_active = require("../runtime/input-active.js");
|
|
@@ -185,8 +187,10 @@ function executeScript(body, barsInput, inputs = {}, chart2 = {}, options = {})
|
|
|
185
187
|
ctx = freshCollector(inputs);
|
|
186
188
|
(0, import_registry.resetDrawings)();
|
|
187
189
|
mathCore.resetRandom();
|
|
190
|
+
missingSymbols = [];
|
|
188
191
|
try {
|
|
189
192
|
body();
|
|
193
|
+
if (missingSymbols.length) throw new MissingSymbolDataError(missingSymbols);
|
|
190
194
|
const c = ctx;
|
|
191
195
|
return {
|
|
192
196
|
metadata: {
|
|
@@ -310,6 +314,10 @@ const input = {
|
|
|
310
314
|
"input_session"
|
|
311
315
|
);
|
|
312
316
|
},
|
|
317
|
+
/** Ticker id ("NASDAQ:MSFT"), for `request.security` of another symbol (#180). */
|
|
318
|
+
symbol(defval, title, opts = {}) {
|
|
319
|
+
return registerInput({ type: "symbol", defval, title, options: opts.options, ...common(opts) }, "input_symbol");
|
|
320
|
+
},
|
|
313
321
|
/** Date and time as a UNIX time in milliseconds, e.g. `input.time(timestamp('2024-01-01'), 'Start')`. */
|
|
314
322
|
time(defval, title, opts = {}) {
|
|
315
323
|
const v = registerInput({ type: "time", defval, title, ...common(opts) }, "input_time");
|
|
@@ -361,11 +369,12 @@ const ta = {
|
|
|
361
369
|
highestbars: (sourceOrLength, length) => typeof sourceOrLength === "number" ? taSeries.highestbars(high, sourceOrLength) : taSeries.highestbars(sourceOrLength, length),
|
|
362
370
|
/** `ta.lowestbars(source, length)` or `ta.lowestbars(length)` (source = low); offsets are 0 or negative. */
|
|
363
371
|
lowestbars: (sourceOrLength, length) => typeof sourceOrLength === "number" ? taSeries.lowestbars(low, sourceOrLength) : taSeries.lowestbars(sourceOrLength, length),
|
|
364
|
-
/** `ta.vwap(source, anchor?, stdev_mult?)` with the chart volume; the default anchor is a new trading
|
|
365
|
-
*
|
|
366
|
-
*
|
|
372
|
+
/** `ta.vwap(source, anchor?, stdev_mult?)` with the chart volume; the default anchor is a new trading day
|
|
373
|
+
* and the first bar: as in PineScript, the first loaded bars (a day in progress) have a value. On D / W / M
|
|
374
|
+
* charts every bar is a new day (no time zone or session needed); on intraday charts it needs the chart context
|
|
375
|
+
* (timeframe, time zone, session). */
|
|
367
376
|
vwap: ((source, anchor, stdev_mult) => {
|
|
368
|
-
const a = anchor ??
|
|
377
|
+
const a = anchor ?? vwapAnchor();
|
|
369
378
|
return stdev_mult === void 0 ? taSeries.vwap(source, volume, a) : taSeries.vwapBands(source, volume, a, stdev_mult);
|
|
370
379
|
}),
|
|
371
380
|
/** `ta.mfi(source, length)` with the chart volume (PineScript takes 2 arguments). */
|
|
@@ -765,7 +774,7 @@ function eachBar(fn) {
|
|
|
765
774
|
for (idx = 0; idx < b.length; idx++) {
|
|
766
775
|
if (pendingError && pendingError.bar === idx) throw new Error((0, import_series.historyError)(idx, pendingError.barsBack));
|
|
767
776
|
currentBar = idx;
|
|
768
|
-
(0, import_registry.setDrawingBar)(idx, idx === b.length - 1);
|
|
777
|
+
(0, import_registry.setDrawingBar)(idx, idx === b.length - 1, b.length - 1);
|
|
769
778
|
const r = fn(ctx2);
|
|
770
779
|
out[idx] = typeof r === "number" ? r : typeof r === "boolean" ? r ? 1 : 0 : NaN;
|
|
771
780
|
for (const buffer of buffers.values()) {
|
|
@@ -927,6 +936,17 @@ const strategy = Object.defineProperties(
|
|
|
927
936
|
Object.assign((title, options) => declareStrategy(title, options), strategyMembers),
|
|
928
937
|
variableGetters
|
|
929
938
|
);
|
|
939
|
+
class MissingSymbolDataError extends Error {
|
|
940
|
+
constructor(requests) {
|
|
941
|
+
super(
|
|
942
|
+
`request.security needs the bars of ${requests.map((r) => `${r.symbol} (${r.timeframe})`).join(", ")}: pass them with ChartContext.bars.`
|
|
943
|
+
);
|
|
944
|
+
this.requests = requests;
|
|
945
|
+
this.name = "MissingSymbolDataError";
|
|
946
|
+
}
|
|
947
|
+
requests;
|
|
948
|
+
}
|
|
949
|
+
let missingSymbols = [];
|
|
930
950
|
let chartCtx = {};
|
|
931
951
|
function chartTimeframe() {
|
|
932
952
|
collector();
|
|
@@ -1047,6 +1067,12 @@ const syminfo = {
|
|
|
1047
1067
|
},
|
|
1048
1068
|
get currency() {
|
|
1049
1069
|
return chartText("currency", "syminfo.currency");
|
|
1070
|
+
},
|
|
1071
|
+
get basecurrency() {
|
|
1072
|
+
return chartText("basecurrency", "syminfo.basecurrency");
|
|
1073
|
+
},
|
|
1074
|
+
get root() {
|
|
1075
|
+
return chartText("root", "syminfo.root");
|
|
1050
1076
|
}
|
|
1051
1077
|
};
|
|
1052
1078
|
function calendar(fn) {
|
|
@@ -1108,23 +1134,6 @@ function sessionBars() {
|
|
|
1108
1134
|
}
|
|
1109
1135
|
return sessionCache;
|
|
1110
1136
|
}
|
|
1111
|
-
function calendarFor(session2, timezone) {
|
|
1112
|
-
const { bars: bars2 } = sessionBars();
|
|
1113
|
-
if (!session2 && !timezone) return { bars: bars2, test: false };
|
|
1114
|
-
const tz = timezone ?? exchangeTimezone();
|
|
1115
|
-
if (session2 !== void 0 && (0, import_session.parsePineSession)(session2) === null) {
|
|
1116
|
-
const name = session2.trim();
|
|
1117
|
-
const symbol = name === "regular" && chartCtx.regularSession ? chartCtx.regularSession : chartCtx.session;
|
|
1118
|
-
return { bars: new import_bars.SessionBars(new import_calendar.TradingCalendar(tz, { session: toSpec(symbol).session }, "symbol"), bars2.chart.period), test: true };
|
|
1119
|
-
}
|
|
1120
|
-
const spec = session2 ? { session: session2 } : { session: toSpec(chartCtx.session).session };
|
|
1121
|
-
return {
|
|
1122
|
-
bars: new import_bars.SessionBars(new import_calendar.TradingCalendar(tz, spec, session2 ? "pine" : "symbol"), bars2.chart.period),
|
|
1123
|
-
test: true,
|
|
1124
|
-
// a PineScript session string: the rules of time.inSession (runs ending at 0000, days around a clock change)
|
|
1125
|
-
inside: session2 ? (time2) => timeCore.inSession(time2, session2, tz, timeframeCore.in_seconds(bars2.chart.period) * 1e3) : void 0
|
|
1126
|
-
};
|
|
1127
|
-
}
|
|
1128
1137
|
function perBar(fn) {
|
|
1129
1138
|
const times = ctxBars.bars.map(barTime);
|
|
1130
1139
|
return import_series.Series.fromArray(ctxBars, times.map((t, i) => fn(t, i, times)));
|
|
@@ -1134,17 +1143,19 @@ function callableSeries(series, fn) {
|
|
|
1134
1143
|
Object.assign(fn, series);
|
|
1135
1144
|
return fn;
|
|
1136
1145
|
}
|
|
1146
|
+
function chartSessionPeriods(timeframeString, session2, timezone) {
|
|
1147
|
+
const { bars: bars2 } = sessionBars();
|
|
1148
|
+
return (0, import_context.sessionPeriods)(bars2, { ...chartCtx, timezone: exchangeTimezone() }, timeframeString, session2, timezone);
|
|
1149
|
+
}
|
|
1137
1150
|
function timeFunction(tf, session2, timezone) {
|
|
1138
1151
|
collector();
|
|
1139
|
-
const {
|
|
1140
|
-
|
|
1141
|
-
return perBar((t) => test && !(inside ? inside(t) : bars2.inside(t)) ? NaN : bars2.timeOf(t, timeframeString));
|
|
1152
|
+
const { open: open2 } = chartSessionPeriods(tf || chartTimeframe().period, session2, timezone);
|
|
1153
|
+
return perBar((t) => open2(t));
|
|
1142
1154
|
}
|
|
1143
1155
|
function timeCloseFunction(tf, session2, timezone) {
|
|
1144
1156
|
collector();
|
|
1145
|
-
const {
|
|
1146
|
-
|
|
1147
|
-
return perBar((t) => test && !(inside ? inside(t) : bars2.inside(t)) ? NaN : bars2.closeOf(t, timeframeString));
|
|
1157
|
+
const { close: close2 } = chartSessionPeriods(tf || chartTimeframe().period, session2, timezone);
|
|
1158
|
+
return perBar((t) => close2(t));
|
|
1148
1159
|
}
|
|
1149
1160
|
let runNow = NaN;
|
|
1150
1161
|
const timenow = new import_series.Series(ctxBars, () => runNow);
|
|
@@ -1159,6 +1170,19 @@ function changeOf(tf, firstBar = false) {
|
|
|
1159
1170
|
const changed = (a, b) => !Number.isNaN(a) && !Number.isNaN(b) && a !== b;
|
|
1160
1171
|
return perBar((t, i, times) => (i > 0 ? changed(bars2.timeOf(t, tf), bars2.timeOf(times[i - 1], tf)) : firstBar) ? 1 : 0);
|
|
1161
1172
|
}
|
|
1173
|
+
function vwapAnchor() {
|
|
1174
|
+
if (chartTimeframe().isdwm) return barFlag(() => true);
|
|
1175
|
+
const { bars: bars2 } = sessionBars();
|
|
1176
|
+
let last = NaN;
|
|
1177
|
+
let previous = NaN;
|
|
1178
|
+
return perBar((t, i) => {
|
|
1179
|
+
const day = bars2.timeOf(t, "1D");
|
|
1180
|
+
const isNew = i === 0 || (Number.isNaN(day) ? Number.isNaN(previous) : day !== last);
|
|
1181
|
+
if (!Number.isNaN(day)) last = day;
|
|
1182
|
+
previous = day;
|
|
1183
|
+
return isNew ? 1 : 0;
|
|
1184
|
+
});
|
|
1185
|
+
}
|
|
1162
1186
|
function flag(key) {
|
|
1163
1187
|
const { bars: bars2, regular } = sessionBars();
|
|
1164
1188
|
const values = (0, import_bars.sessionFlags)(ctxBars.bars.map(barTime), bars2, regular)[key];
|
|
@@ -1244,17 +1268,17 @@ function valuesOf(value, length) {
|
|
|
1244
1268
|
}
|
|
1245
1269
|
return value.toArray().slice();
|
|
1246
1270
|
}
|
|
1247
|
-
function security(symbol, timeframe2, expression, gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_off) {
|
|
1271
|
+
function security(symbol, timeframe2, expression, gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_off, ignore_invalid_symbol = false) {
|
|
1248
1272
|
collector();
|
|
1249
1273
|
const heikin = symbol.startsWith(HEIKIN_ASHI);
|
|
1250
1274
|
const base = heikin ? symbol.slice(HEIKIN_ASHI.length) : symbol;
|
|
1251
|
-
if (base !== "" && base !== chartCtx.tickerid) {
|
|
1252
|
-
throw new Error(`request.security: "${symbol}" is not the chart symbol; other symbols need external data.`);
|
|
1253
|
-
}
|
|
1254
1275
|
const chart2 = chartTimeframe();
|
|
1255
1276
|
const tf = timeframeCore.info(timeframe2 || chart2.period).period;
|
|
1277
|
+
if (base !== "" && base !== chartCtx.tickerid) {
|
|
1278
|
+
return externalSecurity(base, heikin, tf, expression, gaps, lookahead, ignore_invalid_symbol, false);
|
|
1279
|
+
}
|
|
1256
1280
|
if (timeframeCore.in_seconds(tf) < timeframeCore.in_seconds(chart2.period)) {
|
|
1257
|
-
|
|
1281
|
+
return externalSecurity(chartCtx.tickerid ?? "", heikin, tf, expression, gaps, lookahead, ignore_invalid_symbol, true);
|
|
1258
1282
|
}
|
|
1259
1283
|
const chartBars = ctxBars.bars;
|
|
1260
1284
|
const times = chartBars.map(barTime);
|
|
@@ -1274,6 +1298,8 @@ function security(symbol, timeframe2, expression, gaps = barmerge.gaps_off, look
|
|
|
1274
1298
|
const periods = at ? calendar2.calendar.periods(at.date) : [];
|
|
1275
1299
|
return periods.length ? calendar2.timeOf(periods[0][0], tf) : starts[i];
|
|
1276
1300
|
});
|
|
1301
|
+
const tfInfo = timeframeCore.info(tf);
|
|
1302
|
+
(0, import_bars.strayPeriods)(starts, dayPeriods, times, loaded, tfInfo.isdwm ? null : timeframeCore.in_seconds(tf) * 1e3);
|
|
1277
1303
|
const reaches = times.map((t) => loaded.closeOf(t, chart2.period) >= calendar2.periodEnd(t, tf));
|
|
1278
1304
|
({ group, latest } = (0, import_resample.periodsOf)(starts, dayPeriods, reaches));
|
|
1279
1305
|
const unit = chartCtx.timeUnit === "ms" ? 1 : 1e3;
|
|
@@ -1300,7 +1326,85 @@ function security(symbol, timeframe2, expression, gaps = barmerge.gaps_off, look
|
|
|
1300
1326
|
);
|
|
1301
1327
|
return Array.isArray(result) ? mapped : mapped[0];
|
|
1302
1328
|
}
|
|
1303
|
-
|
|
1329
|
+
function runExternal(symbol, heikin, tf, expression, ignoreInvalid, own) {
|
|
1330
|
+
let bars2 = chartCtx.bars?.(symbol, tf);
|
|
1331
|
+
if (bars2 === void 0 && !missingSymbols.some((r) => r.symbol === symbol && r.timeframe === tf)) {
|
|
1332
|
+
missingSymbols.push({ symbol, timeframe: tf });
|
|
1333
|
+
}
|
|
1334
|
+
if (bars2 !== void 0 && bars2.length === 0 && !ignoreInvalid) throw new Error(`Invalid symbol: ${symbol}`);
|
|
1335
|
+
bars2 ??= [];
|
|
1336
|
+
if (heikin) bars2 = (0, import_resample.heikinAshi)(bars2);
|
|
1337
|
+
const given2 = chartCtx.symbolInfo?.(symbol);
|
|
1338
|
+
const info = own ? { ...chartCtx, ...given2 } : given2 ?? {};
|
|
1339
|
+
const chartBars = ctxBars.bars;
|
|
1340
|
+
const savedCtx = chartCtx;
|
|
1341
|
+
let result;
|
|
1342
|
+
let values;
|
|
1343
|
+
ctxBars.setAll(bars2);
|
|
1344
|
+
chartCtx = {
|
|
1345
|
+
...chartCtx,
|
|
1346
|
+
tickerid: symbol,
|
|
1347
|
+
timeframe: tf,
|
|
1348
|
+
timezone: info.timezone,
|
|
1349
|
+
session: info.session,
|
|
1350
|
+
regularSession: info.regularSession,
|
|
1351
|
+
mintick: info.mintick,
|
|
1352
|
+
minmove: info.minmove,
|
|
1353
|
+
pricescale: info.pricescale,
|
|
1354
|
+
pointvalue: info.pointvalue,
|
|
1355
|
+
mincontract: info.mincontract,
|
|
1356
|
+
symbolType: info.symbolType,
|
|
1357
|
+
currency: info.currency,
|
|
1358
|
+
basecurrency: info.basecurrency,
|
|
1359
|
+
root: info.root
|
|
1360
|
+
};
|
|
1361
|
+
try {
|
|
1362
|
+
result = expression();
|
|
1363
|
+
const parts = Array.isArray(result) ? result : [result];
|
|
1364
|
+
values = parts.map((p) => valuesOf(p, bars2.length));
|
|
1365
|
+
} finally {
|
|
1366
|
+
ctxBars.setAll(chartBars);
|
|
1367
|
+
chartCtx = savedCtx;
|
|
1368
|
+
}
|
|
1369
|
+
return { bars: bars2, info, result, values };
|
|
1370
|
+
}
|
|
1371
|
+
function mergeChart() {
|
|
1372
|
+
return {
|
|
1373
|
+
timeframe: chartTimeframe().period,
|
|
1374
|
+
timezone: chartCtx.timezone,
|
|
1375
|
+
session: chartCtx.session,
|
|
1376
|
+
timeUnit: chartCtx.timeUnit,
|
|
1377
|
+
// the realtime rule applies to a last bar that receives live updates
|
|
1378
|
+
lastBarConfirmed: chartCtx.realtime !== true
|
|
1379
|
+
};
|
|
1380
|
+
}
|
|
1381
|
+
function externalSecurity(symbol, heikin, tf, expression, gaps, lookahead, ignoreInvalid, own) {
|
|
1382
|
+
const { bars: bars2, info, result, values } = runExternal(symbol, heikin, tf, expression, ignoreInvalid, own);
|
|
1383
|
+
const index = (0, import_other.securityOther)(ctxBars.bars, bars2, tf, mergeChart(), {
|
|
1384
|
+
gaps: gaps === barmerge.gaps_on,
|
|
1385
|
+
lookahead: lookahead === barmerge.lookahead_on,
|
|
1386
|
+
other: info
|
|
1387
|
+
});
|
|
1388
|
+
const mapped = values.map((v) => import_series.Series.fromArray(ctxBars, index.map((j) => j < 0 ? NaN : v[j] ?? NaN)));
|
|
1389
|
+
return Array.isArray(result) ? mapped : mapped[0];
|
|
1390
|
+
}
|
|
1391
|
+
function security_lower_tf(symbol, timeframe2, expression, ignore_invalid_symbol = false) {
|
|
1392
|
+
collector();
|
|
1393
|
+
const heikin = symbol.startsWith(HEIKIN_ASHI);
|
|
1394
|
+
const base = heikin ? symbol.slice(HEIKIN_ASHI.length) : symbol;
|
|
1395
|
+
const chart2 = chartTimeframe();
|
|
1396
|
+
const tf = timeframeCore.info(timeframe2 || chart2.period).period;
|
|
1397
|
+
if (timeframeCore.in_seconds(tf) > timeframeCore.in_seconds(chart2.period)) {
|
|
1398
|
+
throw new Error(`request.security_lower_tf: timeframe "${tf}" is higher than the chart timeframe "${chart2.period}".`);
|
|
1399
|
+
}
|
|
1400
|
+
const own = base === "" || base === chartCtx.tickerid;
|
|
1401
|
+
const ticker2 = own ? chartCtx.tickerid ?? "" : base;
|
|
1402
|
+
const { bars: bars2, info, result, values } = runExternal(ticker2, heikin, tf, expression, ignore_invalid_symbol, own);
|
|
1403
|
+
const ranges = (0, import_other.securityLowerTf)(ctxBars.bars, bars2, tf, mergeChart(), { other: info });
|
|
1404
|
+
const mapped = values.map((v) => ranges.map(([from, to]) => v.slice(from, to)));
|
|
1405
|
+
return Array.isArray(result) ? mapped : mapped[0];
|
|
1406
|
+
}
|
|
1407
|
+
const request = { security, security_lower_tf };
|
|
1304
1408
|
const line = {
|
|
1305
1409
|
...lineCore,
|
|
1306
1410
|
get all() {
|