oakscriptjs 0.11.0 → 0.11.1
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.js +1 -1
- 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 +3 -2
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +6 -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 +65 -12
- package/dist/cjs/script/index.d.ts.map +1 -1
- package/dist/cjs/script/index.js +168 -19
- 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 +11 -7
- package/dist/cjs/session/calendar.js.map +2 -2
- package/dist/cjs/session/context.d.ts +2 -1
- package/dist/cjs/session/context.d.ts.map +1 -1
- package/dist/cjs/session/context.js +2 -1
- 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 +34 -17
- package/dist/cjs/ta/index.d.ts.map +1 -1
- package/dist/cjs/ta/index.js +132 -116
- package/dist/cjs/ta/index.js.map +2 -2
- 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 +3 -1
- package/dist/cjs/table/index.d.ts.map +1 -1
- package/dist/cjs/table/index.js +1 -0
- 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.js +1 -1
- 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 +3 -2
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +4 -2
- 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 +65 -12
- package/dist/esm/script/index.d.ts.map +1 -1
- package/dist/esm/script/index.js +217 -29
- 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 +19 -7
- package/dist/esm/session/calendar.js.map +1 -1
- package/dist/esm/session/context.d.ts +2 -1
- package/dist/esm/session/context.d.ts.map +1 -1
- package/dist/esm/session/context.js +5 -3
- 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 +34 -17
- package/dist/esm/ta/index.d.ts.map +1 -1
- package/dist/esm/ta/index.js +155 -185
- 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 +3 -1
- package/dist/esm/table/index.d.ts.map +1 -1
- package/dist/esm/table/index.js +6 -1
- 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 +1 -1
- package/src/drawing/registry.ts +30 -7
- package/src/index.ts +11 -1
- 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 +292 -30
- package/src/security/other.ts +269 -0
- package/src/session/bars.ts +24 -1
- package/src/session/calendar.ts +23 -7
- package/src/session/context.ts +5 -3
- 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 +157 -183
- 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 +4 -1
- 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,6 +127,7 @@ 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
133
|
var import_session = require("../time/session.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,7 +1134,7 @@ function sessionBars() {
|
|
|
1108
1134
|
}
|
|
1109
1135
|
return sessionCache;
|
|
1110
1136
|
}
|
|
1111
|
-
function calendarFor(session2, timezone) {
|
|
1137
|
+
function calendarFor(session2, timezone, dayPlacement = false) {
|
|
1112
1138
|
const { bars: bars2 } = sessionBars();
|
|
1113
1139
|
if (!session2 && !timezone) return { bars: bars2, test: false };
|
|
1114
1140
|
const tz = timezone ?? exchangeTimezone();
|
|
@@ -1119,7 +1145,7 @@ function calendarFor(session2, timezone) {
|
|
|
1119
1145
|
}
|
|
1120
1146
|
const spec = session2 ? { session: session2 } : { session: toSpec(chartCtx.session).session };
|
|
1121
1147
|
return {
|
|
1122
|
-
bars: new import_bars.SessionBars(new import_calendar.TradingCalendar(tz, spec, session2 ? "pine" : "symbol"), bars2.chart.period),
|
|
1148
|
+
bars: new import_bars.SessionBars(new import_calendar.TradingCalendar(tz, spec, session2 ? "pine" : "symbol", dayPlacement), bars2.chart.period),
|
|
1123
1149
|
test: true,
|
|
1124
1150
|
// a PineScript session string: the rules of time.inSession (runs ending at 0000, days around a clock change)
|
|
1125
1151
|
inside: session2 ? (time2) => timeCore.inSession(time2, session2, tz, timeframeCore.in_seconds(bars2.chart.period) * 1e3) : void 0
|
|
@@ -1134,17 +1160,47 @@ function callableSeries(series, fn) {
|
|
|
1134
1160
|
Object.assign(fn, series);
|
|
1135
1161
|
return fn;
|
|
1136
1162
|
}
|
|
1163
|
+
function sessionPeriods(timeframeString, session2, timezone) {
|
|
1164
|
+
const tf = timeframeCore.info(timeframeString);
|
|
1165
|
+
const { bars: bars2, test, inside } = calendarFor(session2, timezone, !tf.isintraday);
|
|
1166
|
+
const open2 = (t) => bars2.timeOf(t, timeframeString);
|
|
1167
|
+
const close2 = (t) => bars2.closeOf(t, timeframeString);
|
|
1168
|
+
if (!test) return { open: open2, close: close2 };
|
|
1169
|
+
if (tf.isintraday) {
|
|
1170
|
+
if (session2 !== void 0 && (0, import_session.parsePineSession)(session2) !== null && !bars2.chart.isdwm) {
|
|
1171
|
+
const tz = timezone ?? exchangeTimezone();
|
|
1172
|
+
const barMs = timeframeCore.in_seconds(bars2.chart.period) * 1e3;
|
|
1173
|
+
const ms = timeframeCore.in_seconds(tf.period) * 1e3;
|
|
1174
|
+
const run = (t) => (0, import_session.sessionRun)(t, session2, tz, barMs);
|
|
1175
|
+
const start = (t, r) => r[0] + Math.floor((t - r[0]) / ms) * ms;
|
|
1176
|
+
return {
|
|
1177
|
+
open: (t) => {
|
|
1178
|
+
const r = run(t);
|
|
1179
|
+
return r ? start(t, r) : NaN;
|
|
1180
|
+
},
|
|
1181
|
+
close: (t) => {
|
|
1182
|
+
const r = run(t);
|
|
1183
|
+
return r ? Math.min(start(t, r) + ms, r[1]) : NaN;
|
|
1184
|
+
}
|
|
1185
|
+
};
|
|
1186
|
+
}
|
|
1187
|
+
const isIn = (t) => inside ? inside(t) : bars2.inside(t);
|
|
1188
|
+
return { open: (t) => isIn(t) ? open2(t) : NaN, close: (t) => isIn(t) ? close2(t) : NaN };
|
|
1189
|
+
}
|
|
1190
|
+
if (tf.isdaily && tf.multiplier === 1) {
|
|
1191
|
+
return { open: (t) => bars2.inside(t) ? open2(t) : NaN, close: (t) => bars2.inside(t) ? close2(t) : NaN };
|
|
1192
|
+
}
|
|
1193
|
+
return { open: open2, close: close2 };
|
|
1194
|
+
}
|
|
1137
1195
|
function timeFunction(tf, session2, timezone) {
|
|
1138
1196
|
collector();
|
|
1139
|
-
const {
|
|
1140
|
-
|
|
1141
|
-
return perBar((t) => test && !(inside ? inside(t) : bars2.inside(t)) ? NaN : bars2.timeOf(t, timeframeString));
|
|
1197
|
+
const { open: open2 } = sessionPeriods(tf || chartTimeframe().period, session2, timezone);
|
|
1198
|
+
return perBar((t) => open2(t));
|
|
1142
1199
|
}
|
|
1143
1200
|
function timeCloseFunction(tf, session2, timezone) {
|
|
1144
1201
|
collector();
|
|
1145
|
-
const {
|
|
1146
|
-
|
|
1147
|
-
return perBar((t) => test && !(inside ? inside(t) : bars2.inside(t)) ? NaN : bars2.closeOf(t, timeframeString));
|
|
1202
|
+
const { close: close2 } = sessionPeriods(tf || chartTimeframe().period, session2, timezone);
|
|
1203
|
+
return perBar((t) => close2(t));
|
|
1148
1204
|
}
|
|
1149
1205
|
let runNow = NaN;
|
|
1150
1206
|
const timenow = new import_series.Series(ctxBars, () => runNow);
|
|
@@ -1159,6 +1215,19 @@ function changeOf(tf, firstBar = false) {
|
|
|
1159
1215
|
const changed = (a, b) => !Number.isNaN(a) && !Number.isNaN(b) && a !== b;
|
|
1160
1216
|
return perBar((t, i, times) => (i > 0 ? changed(bars2.timeOf(t, tf), bars2.timeOf(times[i - 1], tf)) : firstBar) ? 1 : 0);
|
|
1161
1217
|
}
|
|
1218
|
+
function vwapAnchor() {
|
|
1219
|
+
if (chartTimeframe().isdwm) return barFlag(() => true);
|
|
1220
|
+
const { bars: bars2 } = sessionBars();
|
|
1221
|
+
let last = NaN;
|
|
1222
|
+
let previous = NaN;
|
|
1223
|
+
return perBar((t, i) => {
|
|
1224
|
+
const day = bars2.timeOf(t, "1D");
|
|
1225
|
+
const isNew = i === 0 || (Number.isNaN(day) ? Number.isNaN(previous) : day !== last);
|
|
1226
|
+
if (!Number.isNaN(day)) last = day;
|
|
1227
|
+
previous = day;
|
|
1228
|
+
return isNew ? 1 : 0;
|
|
1229
|
+
});
|
|
1230
|
+
}
|
|
1162
1231
|
function flag(key) {
|
|
1163
1232
|
const { bars: bars2, regular } = sessionBars();
|
|
1164
1233
|
const values = (0, import_bars.sessionFlags)(ctxBars.bars.map(barTime), bars2, regular)[key];
|
|
@@ -1244,17 +1313,17 @@ function valuesOf(value, length) {
|
|
|
1244
1313
|
}
|
|
1245
1314
|
return value.toArray().slice();
|
|
1246
1315
|
}
|
|
1247
|
-
function security(symbol, timeframe2, expression, gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_off) {
|
|
1316
|
+
function security(symbol, timeframe2, expression, gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_off, ignore_invalid_symbol = false) {
|
|
1248
1317
|
collector();
|
|
1249
1318
|
const heikin = symbol.startsWith(HEIKIN_ASHI);
|
|
1250
1319
|
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
1320
|
const chart2 = chartTimeframe();
|
|
1255
1321
|
const tf = timeframeCore.info(timeframe2 || chart2.period).period;
|
|
1322
|
+
if (base !== "" && base !== chartCtx.tickerid) {
|
|
1323
|
+
return externalSecurity(base, heikin, tf, expression, gaps, lookahead, ignore_invalid_symbol, false);
|
|
1324
|
+
}
|
|
1256
1325
|
if (timeframeCore.in_seconds(tf) < timeframeCore.in_seconds(chart2.period)) {
|
|
1257
|
-
|
|
1326
|
+
return externalSecurity(chartCtx.tickerid ?? "", heikin, tf, expression, gaps, lookahead, ignore_invalid_symbol, true);
|
|
1258
1327
|
}
|
|
1259
1328
|
const chartBars = ctxBars.bars;
|
|
1260
1329
|
const times = chartBars.map(barTime);
|
|
@@ -1274,6 +1343,8 @@ function security(symbol, timeframe2, expression, gaps = barmerge.gaps_off, look
|
|
|
1274
1343
|
const periods = at ? calendar2.calendar.periods(at.date) : [];
|
|
1275
1344
|
return periods.length ? calendar2.timeOf(periods[0][0], tf) : starts[i];
|
|
1276
1345
|
});
|
|
1346
|
+
const tfInfo = timeframeCore.info(tf);
|
|
1347
|
+
(0, import_bars.strayPeriods)(starts, dayPeriods, times, loaded, tfInfo.isdwm ? null : timeframeCore.in_seconds(tf) * 1e3);
|
|
1277
1348
|
const reaches = times.map((t) => loaded.closeOf(t, chart2.period) >= calendar2.periodEnd(t, tf));
|
|
1278
1349
|
({ group, latest } = (0, import_resample.periodsOf)(starts, dayPeriods, reaches));
|
|
1279
1350
|
const unit = chartCtx.timeUnit === "ms" ? 1 : 1e3;
|
|
@@ -1300,7 +1371,85 @@ function security(symbol, timeframe2, expression, gaps = barmerge.gaps_off, look
|
|
|
1300
1371
|
);
|
|
1301
1372
|
return Array.isArray(result) ? mapped : mapped[0];
|
|
1302
1373
|
}
|
|
1303
|
-
|
|
1374
|
+
function runExternal(symbol, heikin, tf, expression, ignoreInvalid, own) {
|
|
1375
|
+
let bars2 = chartCtx.bars?.(symbol, tf);
|
|
1376
|
+
if (bars2 === void 0 && !missingSymbols.some((r) => r.symbol === symbol && r.timeframe === tf)) {
|
|
1377
|
+
missingSymbols.push({ symbol, timeframe: tf });
|
|
1378
|
+
}
|
|
1379
|
+
if (bars2 !== void 0 && bars2.length === 0 && !ignoreInvalid) throw new Error(`Invalid symbol: ${symbol}`);
|
|
1380
|
+
bars2 ??= [];
|
|
1381
|
+
if (heikin) bars2 = (0, import_resample.heikinAshi)(bars2);
|
|
1382
|
+
const given2 = chartCtx.symbolInfo?.(symbol);
|
|
1383
|
+
const info = own ? { ...chartCtx, ...given2 } : given2 ?? {};
|
|
1384
|
+
const chartBars = ctxBars.bars;
|
|
1385
|
+
const savedCtx = chartCtx;
|
|
1386
|
+
let result;
|
|
1387
|
+
let values;
|
|
1388
|
+
ctxBars.setAll(bars2);
|
|
1389
|
+
chartCtx = {
|
|
1390
|
+
...chartCtx,
|
|
1391
|
+
tickerid: symbol,
|
|
1392
|
+
timeframe: tf,
|
|
1393
|
+
timezone: info.timezone,
|
|
1394
|
+
session: info.session,
|
|
1395
|
+
regularSession: info.regularSession,
|
|
1396
|
+
mintick: info.mintick,
|
|
1397
|
+
minmove: info.minmove,
|
|
1398
|
+
pricescale: info.pricescale,
|
|
1399
|
+
pointvalue: info.pointvalue,
|
|
1400
|
+
mincontract: info.mincontract,
|
|
1401
|
+
symbolType: info.symbolType,
|
|
1402
|
+
currency: info.currency,
|
|
1403
|
+
basecurrency: info.basecurrency,
|
|
1404
|
+
root: info.root
|
|
1405
|
+
};
|
|
1406
|
+
try {
|
|
1407
|
+
result = expression();
|
|
1408
|
+
const parts = Array.isArray(result) ? result : [result];
|
|
1409
|
+
values = parts.map((p) => valuesOf(p, bars2.length));
|
|
1410
|
+
} finally {
|
|
1411
|
+
ctxBars.setAll(chartBars);
|
|
1412
|
+
chartCtx = savedCtx;
|
|
1413
|
+
}
|
|
1414
|
+
return { bars: bars2, info, result, values };
|
|
1415
|
+
}
|
|
1416
|
+
function mergeChart() {
|
|
1417
|
+
return {
|
|
1418
|
+
timeframe: chartTimeframe().period,
|
|
1419
|
+
timezone: chartCtx.timezone,
|
|
1420
|
+
session: chartCtx.session,
|
|
1421
|
+
timeUnit: chartCtx.timeUnit,
|
|
1422
|
+
// the realtime rule applies to a last bar that receives live updates
|
|
1423
|
+
lastBarConfirmed: chartCtx.realtime !== true
|
|
1424
|
+
};
|
|
1425
|
+
}
|
|
1426
|
+
function externalSecurity(symbol, heikin, tf, expression, gaps, lookahead, ignoreInvalid, own) {
|
|
1427
|
+
const { bars: bars2, info, result, values } = runExternal(symbol, heikin, tf, expression, ignoreInvalid, own);
|
|
1428
|
+
const index = (0, import_other.securityOther)(ctxBars.bars, bars2, tf, mergeChart(), {
|
|
1429
|
+
gaps: gaps === barmerge.gaps_on,
|
|
1430
|
+
lookahead: lookahead === barmerge.lookahead_on,
|
|
1431
|
+
other: info
|
|
1432
|
+
});
|
|
1433
|
+
const mapped = values.map((v) => import_series.Series.fromArray(ctxBars, index.map((j) => j < 0 ? NaN : v[j] ?? NaN)));
|
|
1434
|
+
return Array.isArray(result) ? mapped : mapped[0];
|
|
1435
|
+
}
|
|
1436
|
+
function security_lower_tf(symbol, timeframe2, expression, ignore_invalid_symbol = false) {
|
|
1437
|
+
collector();
|
|
1438
|
+
const heikin = symbol.startsWith(HEIKIN_ASHI);
|
|
1439
|
+
const base = heikin ? symbol.slice(HEIKIN_ASHI.length) : symbol;
|
|
1440
|
+
const chart2 = chartTimeframe();
|
|
1441
|
+
const tf = timeframeCore.info(timeframe2 || chart2.period).period;
|
|
1442
|
+
if (timeframeCore.in_seconds(tf) > timeframeCore.in_seconds(chart2.period)) {
|
|
1443
|
+
throw new Error(`request.security_lower_tf: timeframe "${tf}" is higher than the chart timeframe "${chart2.period}".`);
|
|
1444
|
+
}
|
|
1445
|
+
const own = base === "" || base === chartCtx.tickerid;
|
|
1446
|
+
const ticker2 = own ? chartCtx.tickerid ?? "" : base;
|
|
1447
|
+
const { bars: bars2, info, result, values } = runExternal(ticker2, heikin, tf, expression, ignore_invalid_symbol, own);
|
|
1448
|
+
const ranges = (0, import_other.securityLowerTf)(ctxBars.bars, bars2, tf, mergeChart(), { other: info });
|
|
1449
|
+
const mapped = values.map((v) => ranges.map(([from, to]) => v.slice(from, to)));
|
|
1450
|
+
return Array.isArray(result) ? mapped : mapped[0];
|
|
1451
|
+
}
|
|
1452
|
+
const request = { security, security_lower_tf };
|
|
1304
1453
|
const line = {
|
|
1305
1454
|
...lineCore,
|
|
1306
1455
|
get all() {
|