oakscriptjs 0.12.2 → 0.13.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.
- package/dist/cjs/drawing/registry.d.ts +37 -0
- package/dist/cjs/drawing/registry.d.ts.map +1 -1
- package/dist/cjs/drawing/registry.js +40 -0
- package/dist/cjs/drawing/registry.js.map +2 -2
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/math/index.d.ts +4 -0
- package/dist/cjs/math/index.d.ts.map +1 -1
- package/dist/cjs/math/index.js +9 -0
- package/dist/cjs/math/index.js.map +2 -2
- package/dist/cjs/runtime/types.d.ts +6 -0
- 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 +52 -1
- package/dist/cjs/script/index.d.ts.map +1 -1
- package/dist/cjs/script/index.js +217 -11
- package/dist/cjs/script/index.js.map +3 -3
- package/dist/cjs/strategy/index.d.ts +3 -0
- package/dist/cjs/strategy/index.d.ts.map +1 -1
- package/dist/cjs/strategy/index.js +1 -0
- package/dist/cjs/strategy/index.js.map +2 -2
- package/dist/esm/drawing/registry.d.ts +37 -0
- package/dist/esm/drawing/registry.d.ts.map +1 -1
- package/dist/esm/drawing/registry.js +41 -0
- package/dist/esm/drawing/registry.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/math/index.d.ts +4 -0
- package/dist/esm/math/index.d.ts.map +1 -1
- package/dist/esm/math/index.js +10 -0
- package/dist/esm/math/index.js.map +1 -1
- package/dist/esm/runtime/types.d.ts +6 -0
- package/dist/esm/runtime/types.d.ts.map +1 -1
- package/dist/esm/script/index.d.ts +52 -1
- package/dist/esm/script/index.d.ts.map +1 -1
- package/dist/esm/script/index.js +254 -10
- package/dist/esm/script/index.js.map +1 -1
- package/dist/esm/strategy/index.d.ts +3 -0
- package/dist/esm/strategy/index.d.ts.map +1 -1
- package/dist/esm/strategy/index.js +1 -0
- package/dist/esm/strategy/index.js.map +1 -1
- package/package.json +1 -1
- package/src/drawing/registry.ts +56 -0
- package/src/index.ts +1 -1
- package/src/math/index.ts +11 -0
- package/src/runtime/types.ts +6 -0
- package/src/script/index.ts +338 -10
- package/src/strategy/index.ts +4 -0
package/dist/cjs/script/index.js
CHANGED
|
@@ -34,6 +34,7 @@ __export(script_exports, {
|
|
|
34
34
|
MissingSymbolDataError: () => MissingSymbolDataError,
|
|
35
35
|
STRATEGY_DEFAULTS: () => import_strategy2.STRATEGY_DEFAULTS,
|
|
36
36
|
Series: () => import_series.Series,
|
|
37
|
+
StrategyRecorder: () => StrategyRecorder,
|
|
37
38
|
alert: () => alert,
|
|
38
39
|
alertcondition: () => alertcondition,
|
|
39
40
|
barcolor: () => barcolor,
|
|
@@ -48,6 +49,7 @@ __export(script_exports, {
|
|
|
48
49
|
dayofmonth: () => dayofmonth,
|
|
49
50
|
dayofweek: () => dayofweek,
|
|
50
51
|
eachBar: () => eachBar,
|
|
52
|
+
executeIntrabar: () => executeIntrabar,
|
|
51
53
|
executeScript: () => executeScript,
|
|
52
54
|
fill: () => fill,
|
|
53
55
|
fixnan: () => fixnan,
|
|
@@ -100,6 +102,7 @@ __export(script_exports, {
|
|
|
100
102
|
timenow: () => timenow,
|
|
101
103
|
timestamp: () => timestamp,
|
|
102
104
|
varDrawing: () => import_registry2.varDrawing,
|
|
105
|
+
varip: () => varip,
|
|
103
106
|
volume: () => volume,
|
|
104
107
|
weekofyear: () => weekofyear,
|
|
105
108
|
year: () => year
|
|
@@ -187,12 +190,55 @@ function slugId(title, fallback, taken) {
|
|
|
187
190
|
return id;
|
|
188
191
|
}
|
|
189
192
|
let scriptOptions = {};
|
|
193
|
+
let intrabarRun = null;
|
|
194
|
+
class StrategyRecorder {
|
|
195
|
+
/** Per bar: the values the engine returned to the strategy.eachBar() callback (strategy.*, trades...), in order. */
|
|
196
|
+
answers = [];
|
|
197
|
+
/** Per bar: the `varip` values when the bar's strategy.eachBar() callback started in the main run. */
|
|
198
|
+
varipStarts = [];
|
|
199
|
+
/** Current `varip` values: kept through the intrabar runs (no rollback). */
|
|
200
|
+
varip = [];
|
|
201
|
+
}
|
|
202
|
+
function saveRunState() {
|
|
203
|
+
return {
|
|
204
|
+
bars: ctxBars.bars,
|
|
205
|
+
ctx,
|
|
206
|
+
chartCtx,
|
|
207
|
+
runNow,
|
|
208
|
+
scriptOptions,
|
|
209
|
+
currentBar,
|
|
210
|
+
missingSymbols,
|
|
211
|
+
sessionCache,
|
|
212
|
+
intrabarRun,
|
|
213
|
+
varip: varipRun,
|
|
214
|
+
drawings: (0, import_registry.saveDrawingState)(),
|
|
215
|
+
random: mathCore.saveRandom()
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
function restoreRunState(st) {
|
|
219
|
+
ctxBars.setAll(st.bars);
|
|
220
|
+
ctx = st.ctx;
|
|
221
|
+
chartCtx = st.chartCtx;
|
|
222
|
+
runNow = st.runNow;
|
|
223
|
+
scriptOptions = st.scriptOptions;
|
|
224
|
+
currentBar = st.currentBar;
|
|
225
|
+
missingSymbols = st.missingSymbols;
|
|
226
|
+
sessionCache = st.sessionCache;
|
|
227
|
+
intrabarRun = st.intrabarRun;
|
|
228
|
+
varipRun = st.varip;
|
|
229
|
+
(0, import_registry.restoreDrawingState)(st.drawings);
|
|
230
|
+
mathCore.restoreRandom(st.random);
|
|
231
|
+
}
|
|
190
232
|
function executeScript(body, barsInput, inputs = {}, chart2 = {}, options = {}) {
|
|
233
|
+
const outer = ctx ? saveRunState() : null;
|
|
191
234
|
ctxBars.setAll(barsInput);
|
|
192
235
|
chartCtx = { ...chart2 };
|
|
193
236
|
runNow = chart2.now ?? Date.now();
|
|
194
237
|
scriptOptions = options;
|
|
195
238
|
ctx = freshCollector(inputs);
|
|
239
|
+
intrabarRun = null;
|
|
240
|
+
varipRun = { slot: 0, recorder: options.recorder ?? null, mode: "live", scratch: null };
|
|
241
|
+
currentBar = -1;
|
|
196
242
|
(0, import_registry.resetDrawings)();
|
|
197
243
|
mathCore.resetRandom();
|
|
198
244
|
missingSymbols = [];
|
|
@@ -240,7 +286,56 @@ function executeScript(body, barsInput, inputs = {}, chart2 = {}, options = {})
|
|
|
240
286
|
};
|
|
241
287
|
} finally {
|
|
242
288
|
ctx = null;
|
|
289
|
+
if (outer) restoreRunState(outer);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
function executeIntrabar(body, bars2, inputs, chart2, options) {
|
|
293
|
+
const run = {
|
|
294
|
+
bar: options.bar,
|
|
295
|
+
lastBarIndex: options.lastBarIndex,
|
|
296
|
+
engine: options.engine,
|
|
297
|
+
recorder: options.recorder
|
|
298
|
+
};
|
|
299
|
+
executeScript(
|
|
300
|
+
() => {
|
|
301
|
+
intrabarRun = run;
|
|
302
|
+
varipRun = { slot: 0, recorder: options.recorder, mode: "live", scratch: null };
|
|
303
|
+
body();
|
|
304
|
+
},
|
|
305
|
+
bars2,
|
|
306
|
+
inputs,
|
|
307
|
+
// History bars are confirmed, also on their ticks (the reference app: a barstate.isconfirmed entry fills on them).
|
|
308
|
+
{ ...chart2, lastBarConfirmed: true, realtime: false },
|
|
309
|
+
{ strategyEngine: () => options.engine }
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
let varipRun = { slot: 0, recorder: null, mode: "live", scratch: null };
|
|
313
|
+
function varip(initial) {
|
|
314
|
+
collector();
|
|
315
|
+
const slot = varipRun.slot++;
|
|
316
|
+
const state = varipRun;
|
|
317
|
+
const rec = state.recorder;
|
|
318
|
+
if (!rec) {
|
|
319
|
+
let current = initial;
|
|
320
|
+
return {
|
|
321
|
+
get value() {
|
|
322
|
+
return current;
|
|
323
|
+
},
|
|
324
|
+
set value(v) {
|
|
325
|
+
current = v;
|
|
326
|
+
}
|
|
327
|
+
};
|
|
243
328
|
}
|
|
329
|
+
if (rec.varip.length <= slot) rec.varip[slot] = initial;
|
|
330
|
+
const store = () => state.mode === "replay" && state.scratch ? state.scratch : rec.varip;
|
|
331
|
+
return {
|
|
332
|
+
get value() {
|
|
333
|
+
return store()[slot];
|
|
334
|
+
},
|
|
335
|
+
set value(v) {
|
|
336
|
+
store()[slot] = v;
|
|
337
|
+
}
|
|
338
|
+
};
|
|
244
339
|
}
|
|
245
340
|
function indicator(title, options = {}) {
|
|
246
341
|
const c = collector();
|
|
@@ -418,10 +513,21 @@ const ta = {
|
|
|
418
513
|
wvad: barsSeries(taSeries.wvad)
|
|
419
514
|
};
|
|
420
515
|
function fixnan(source) {
|
|
421
|
-
|
|
516
|
+
if (source instanceof import_series.Series) return import_series.Series.fromArray(ctxBars, (0, import_utils.fixnan)(source.toArray()));
|
|
517
|
+
return withPalette((0, import_utils.fixnan)(source), colorPalettes.get(source));
|
|
518
|
+
}
|
|
519
|
+
const colorPalettes = /* @__PURE__ */ new WeakMap();
|
|
520
|
+
function withPalette(colors, palette) {
|
|
521
|
+
if (palette?.length) colorPalettes.set(colors, palette);
|
|
522
|
+
return colors;
|
|
523
|
+
}
|
|
524
|
+
function paletteOfColors(col) {
|
|
525
|
+
return typeof col === "object" && col !== null ? colorPalettes.get(col) : void 0;
|
|
422
526
|
}
|
|
423
527
|
function colorWhen(cond, colorTrue, colorFalse) {
|
|
424
|
-
|
|
528
|
+
const colors = cond.toArray().map((v) => !(0, import_utils.isNA)(v) && v !== 0 ? colorTrue : colorFalse);
|
|
529
|
+
const palette = [colorTrue, ...colorFalse !== void 0 && colorFalse !== colorTrue ? [colorFalse] : []];
|
|
530
|
+
return withPalette(colors, palette);
|
|
425
531
|
}
|
|
426
532
|
const color = {
|
|
427
533
|
...colorCore,
|
|
@@ -456,7 +562,8 @@ function plotImpl(series, title = DEFAULT_OUTPUT_TITLES.plot, options = {}) {
|
|
|
456
562
|
display: options.display,
|
|
457
563
|
histbase: options.histbase,
|
|
458
564
|
forceOverlay: options.force_overlay,
|
|
459
|
-
...options.editable === false ? { editable: false } : {}
|
|
565
|
+
...options.editable === false ? { editable: false } : {},
|
|
566
|
+
...paletteOfColors(perBar2) ? { palette: paletteOfColors(perBar2) } : {}
|
|
460
567
|
});
|
|
461
568
|
c.outputs.push({ kind: "plot", id, title });
|
|
462
569
|
const values = series.toArray();
|
|
@@ -524,6 +631,7 @@ function fill(a, b, ...args) {
|
|
|
524
631
|
let title;
|
|
525
632
|
let gradient;
|
|
526
633
|
let editable;
|
|
634
|
+
let perBarArg;
|
|
527
635
|
if (typeof third === "number" || third instanceof import_series.Series) {
|
|
528
636
|
const n = ctxBars.bars.length;
|
|
529
637
|
gradient = {
|
|
@@ -537,12 +645,14 @@ function fill(a, b, ...args) {
|
|
|
537
645
|
} else if (third !== null && typeof third === "object" && !Array.isArray(third)) {
|
|
538
646
|
const options = third;
|
|
539
647
|
perBar2 = Array.isArray(options.color) ? options.color : void 0;
|
|
648
|
+
perBarArg = perBar2;
|
|
540
649
|
staticColor2 = typeof options.color === "string" ? options.color : void 0;
|
|
541
650
|
title = options.title;
|
|
542
651
|
editable = options.editable;
|
|
543
652
|
} else {
|
|
544
653
|
const color2 = third;
|
|
545
654
|
perBar2 = Array.isArray(color2) ? color2.map((x) => x ?? "") : void 0;
|
|
655
|
+
perBarArg = Array.isArray(color2) ? color2 : void 0;
|
|
546
656
|
staticColor2 = typeof color2 === "string" ? color2 : void 0;
|
|
547
657
|
title = args[1];
|
|
548
658
|
editable = args[2];
|
|
@@ -562,7 +672,8 @@ function fill(a, b, ...args) {
|
|
|
562
672
|
title,
|
|
563
673
|
...topColor ? { topColor } : {},
|
|
564
674
|
...bottomColor ? { bottomColor } : {},
|
|
565
|
-
...editable === false ? { editable: false } : {}
|
|
675
|
+
...editable === false ? { editable: false } : {},
|
|
676
|
+
...paletteOfColors(perBarArg) ? { palette: paletteOfColors(perBarArg) } : {}
|
|
566
677
|
});
|
|
567
678
|
if (hlines) return;
|
|
568
679
|
c.fills.push({
|
|
@@ -710,8 +821,8 @@ function emitBarColors(kind, colors, options) {
|
|
|
710
821
|
title: options.title ?? DEFAULT_OUTPUT_TITLES[kind],
|
|
711
822
|
offset: options.offset,
|
|
712
823
|
forceOverlay: options.force_overlay,
|
|
713
|
-
// a constant colour is a palette of one colour (PineScript)
|
|
714
|
-
...typeof colors === "string" ? { palette: [colors] } : {},
|
|
824
|
+
// a constant colour is a palette of one colour (PineScript); per-bar colours from constants keep theirs
|
|
825
|
+
...typeof colors === "string" ? { palette: [colors] } : paletteOfColors(colors) ? { palette: paletteOfColors(colors) } : {},
|
|
715
826
|
...options.editable === false ? { editable: false } : {},
|
|
716
827
|
outputIndex: c.outputs.length
|
|
717
828
|
});
|
|
@@ -751,6 +862,14 @@ function ohlcRows(o, h, l, cl) {
|
|
|
751
862
|
}
|
|
752
863
|
const staticColor = (col) => typeof col === "string" ? col : void 0;
|
|
753
864
|
const DEFAULT_CANDLE_COLORS = { color: "#2962FF", wickColor: "#737375", borderColor: "#000000" };
|
|
865
|
+
function candlePalettes(cols) {
|
|
866
|
+
const palettes = {};
|
|
867
|
+
for (const k of ["color", "wickColor", "borderColor"]) {
|
|
868
|
+
const pal = paletteOfColors(cols[k]);
|
|
869
|
+
if (pal) palettes[k] = pal;
|
|
870
|
+
}
|
|
871
|
+
return Object.keys(palettes).length ? { palettes } : {};
|
|
872
|
+
}
|
|
754
873
|
const orDefault = (col, fallback) => col === void 0 ? fallback : col;
|
|
755
874
|
function plotcandle(open2, high2, low2, close2, title, options = {}) {
|
|
756
875
|
const c = collector();
|
|
@@ -766,6 +885,7 @@ function plotcandle(open2, high2, low2, close2, title, options = {}) {
|
|
|
766
885
|
color: staticColor(color2),
|
|
767
886
|
wickColor: staticColor(wickcolor),
|
|
768
887
|
borderColor: staticColor(bordercolor),
|
|
888
|
+
...candlePalettes({ color: color2, wickColor: wickcolor, borderColor: bordercolor }),
|
|
769
889
|
display: options.display,
|
|
770
890
|
forceOverlay: options.force_overlay,
|
|
771
891
|
...options.editable === false ? { editable: false } : {}
|
|
@@ -794,6 +914,7 @@ function plotbar(open2, high2, low2, close2, title, options = {}) {
|
|
|
794
914
|
kind: "bar",
|
|
795
915
|
title,
|
|
796
916
|
color: staticColor(barColor),
|
|
917
|
+
...candlePalettes({ color: barColor }),
|
|
797
918
|
display: options.display,
|
|
798
919
|
forceOverlay: options.force_overlay,
|
|
799
920
|
...options.editable === false ? { editable: false } : {}
|
|
@@ -813,6 +934,7 @@ const HISTORY_GROWTH = 1.618034;
|
|
|
813
934
|
function eachBar(fn) {
|
|
814
935
|
collector();
|
|
815
936
|
const b = bars();
|
|
937
|
+
const lastIndex = intrabarRun ? intrabarRun.lastBarIndex : b.length - 1;
|
|
816
938
|
const out = new Array(b.length).fill(NaN);
|
|
817
939
|
const cache = /* @__PURE__ */ new Map();
|
|
818
940
|
const buffers = /* @__PURE__ */ new Map();
|
|
@@ -822,7 +944,7 @@ function eachBar(fn) {
|
|
|
822
944
|
get i() {
|
|
823
945
|
return idx;
|
|
824
946
|
},
|
|
825
|
-
n:
|
|
947
|
+
n: lastIndex + 1,
|
|
826
948
|
get time() {
|
|
827
949
|
return b[idx].time;
|
|
828
950
|
},
|
|
@@ -867,7 +989,7 @@ function eachBar(fn) {
|
|
|
867
989
|
for (idx = 0; idx < b.length; idx++) {
|
|
868
990
|
if (pendingError && pendingError.bar === idx) throw new Error((0, import_series.historyError)(idx, pendingError.barsBack));
|
|
869
991
|
currentBar = idx;
|
|
870
|
-
(0, import_registry.setDrawingBar)(idx, idx ===
|
|
992
|
+
(0, import_registry.setDrawingBar)(idx, idx === lastIndex, lastIndex);
|
|
871
993
|
const r = fn(ctx2);
|
|
872
994
|
out[idx] = typeof r === "number" ? r : typeof r === "boolean" ? r ? 1 : 0 : NaN;
|
|
873
995
|
for (const buffer of buffers.values()) {
|
|
@@ -929,6 +1051,7 @@ function strategyVariable(name) {
|
|
|
929
1051
|
return value;
|
|
930
1052
|
}
|
|
931
1053
|
function riskRule(rule) {
|
|
1054
|
+
if (intrabarRun) return;
|
|
932
1055
|
const engine = strategyEngine(`strategy.risk.${rule.rule}()`);
|
|
933
1056
|
if (!engine.risk) throw new Error(`strategy.risk.${rule.rule}() is not provided by the strategy engine.`);
|
|
934
1057
|
engine.risk(rule);
|
|
@@ -966,17 +1089,95 @@ function strategyEachBar(fn) {
|
|
|
966
1089
|
const engine = strategyEngine("strategy.eachBar()");
|
|
967
1090
|
if (run.looped) throw new Error("strategy.eachBar() runs once per script run.");
|
|
968
1091
|
run.looped = true;
|
|
1092
|
+
const intrabar = intrabarRun;
|
|
1093
|
+
if (intrabar) {
|
|
1094
|
+
const varipState = varipRun;
|
|
1095
|
+
return eachBar((c) => {
|
|
1096
|
+
const replay = c.i < intrabar.bar;
|
|
1097
|
+
run.engine = replay ? replayEngine(intrabar.recorder.answers[c.i] ?? []) : intrabar.engine;
|
|
1098
|
+
varipState.mode = replay ? "replay" : "live";
|
|
1099
|
+
varipState.scratch = replay ? [...intrabar.recorder.varipStarts[c.i] ?? intrabar.recorder.varip] : null;
|
|
1100
|
+
run.inLoop = true;
|
|
1101
|
+
try {
|
|
1102
|
+
return fn(c);
|
|
1103
|
+
} finally {
|
|
1104
|
+
run.inLoop = false;
|
|
1105
|
+
run.engine = intrabar.engine;
|
|
1106
|
+
varipState.mode = "live";
|
|
1107
|
+
varipState.scratch = null;
|
|
1108
|
+
}
|
|
1109
|
+
});
|
|
1110
|
+
}
|
|
1111
|
+
const recorder = scriptOptions.recorder;
|
|
969
1112
|
return eachBar((c) => {
|
|
970
1113
|
engine.processBar(c.i);
|
|
1114
|
+
if (recorder) {
|
|
1115
|
+
recorder.varipStarts[c.i] = [...recorder.varip];
|
|
1116
|
+
run.engine = recordingEngine(engine, recorder.answers[c.i] = []);
|
|
1117
|
+
}
|
|
971
1118
|
run.inLoop = true;
|
|
972
1119
|
try {
|
|
973
1120
|
return fn(c);
|
|
974
1121
|
} finally {
|
|
975
1122
|
run.inLoop = false;
|
|
1123
|
+
run.engine = engine;
|
|
976
1124
|
engine.processClose(c.i);
|
|
977
1125
|
}
|
|
978
1126
|
});
|
|
979
1127
|
}
|
|
1128
|
+
function recordingEngine(engine, log) {
|
|
1129
|
+
const keep = (v) => {
|
|
1130
|
+
log.push(v);
|
|
1131
|
+
return v;
|
|
1132
|
+
};
|
|
1133
|
+
return {
|
|
1134
|
+
...forward(engine),
|
|
1135
|
+
get: (name) => keep(engine.get(name)),
|
|
1136
|
+
openTrade: (index) => keep(engine.openTrade(index)),
|
|
1137
|
+
closedTrade: (index) => keep(engine.closedTrade(index)),
|
|
1138
|
+
defaultEntryQty: engine.defaultEntryQty ? (price) => keep(engine.defaultEntryQty(price)) : void 0
|
|
1139
|
+
};
|
|
1140
|
+
}
|
|
1141
|
+
function replayEngine(log) {
|
|
1142
|
+
let k = 0;
|
|
1143
|
+
const next = () => log[k++];
|
|
1144
|
+
const none = () => {
|
|
1145
|
+
};
|
|
1146
|
+
return {
|
|
1147
|
+
processBar: none,
|
|
1148
|
+
processClose: none,
|
|
1149
|
+
entry: none,
|
|
1150
|
+
order: none,
|
|
1151
|
+
exit: none,
|
|
1152
|
+
close: none,
|
|
1153
|
+
close_all: none,
|
|
1154
|
+
cancel: none,
|
|
1155
|
+
cancel_all: none,
|
|
1156
|
+
risk: none,
|
|
1157
|
+
get: () => next(),
|
|
1158
|
+
openTrade: () => next(),
|
|
1159
|
+
closedTrade: () => next(),
|
|
1160
|
+
defaultEntryQty: () => next()
|
|
1161
|
+
};
|
|
1162
|
+
}
|
|
1163
|
+
function forward(engine) {
|
|
1164
|
+
return {
|
|
1165
|
+
processBar: (bar) => engine.processBar(bar),
|
|
1166
|
+
processClose: (bar) => engine.processClose(bar),
|
|
1167
|
+
entry: (id, direction, options) => engine.entry(id, direction, options),
|
|
1168
|
+
order: (id, direction, options) => engine.order(id, direction, options),
|
|
1169
|
+
exit: (id, options) => engine.exit(id, options),
|
|
1170
|
+
close: (id, options) => engine.close(id, options),
|
|
1171
|
+
close_all: (options) => engine.close_all(options),
|
|
1172
|
+
cancel: (id) => engine.cancel(id),
|
|
1173
|
+
cancel_all: () => engine.cancel_all(),
|
|
1174
|
+
risk: engine.risk ? (rule) => engine.risk(rule) : void 0,
|
|
1175
|
+
get: (name) => engine.get(name),
|
|
1176
|
+
openTrade: (index) => engine.openTrade(index),
|
|
1177
|
+
closedTrade: (index) => engine.closedTrade(index),
|
|
1178
|
+
defaultEntryQty: engine.defaultEntryQty ? (price) => engine.defaultEntryQty(price) : void 0
|
|
1179
|
+
};
|
|
1180
|
+
}
|
|
980
1181
|
const strategyMembers = {
|
|
981
1182
|
...import_strategy.STRATEGY_CONSTANTS,
|
|
982
1183
|
eachBar: strategyEachBar,
|
|
@@ -1288,13 +1489,14 @@ function barFlag(test) {
|
|
|
1288
1489
|
const n = ctxBars.bars.length;
|
|
1289
1490
|
return import_series.Series.fromArray(ctxBars, Array.from({ length: n }, (_, i) => test(i, n) ? 1 : 0));
|
|
1290
1491
|
}
|
|
1492
|
+
const chartBarCount = (n) => intrabarRun ? intrabarRun.lastBarIndex + 1 : n;
|
|
1291
1493
|
const lastRealtime = (i, n) => i === n - 1 && chartCtx.realtime === true;
|
|
1292
1494
|
const barstate = {
|
|
1293
1495
|
get isfirst() {
|
|
1294
1496
|
return barFlag((i) => i === 0);
|
|
1295
1497
|
},
|
|
1296
1498
|
get islast() {
|
|
1297
|
-
return barFlag((i, n) => i === n - 1);
|
|
1499
|
+
return barFlag((i, n) => i === chartBarCount(n) - 1);
|
|
1298
1500
|
},
|
|
1299
1501
|
get isconfirmed() {
|
|
1300
1502
|
return barFlag((i, n) => i < n - 1 || chartCtx.lastBarConfirmed === true);
|
|
@@ -1311,7 +1513,8 @@ const barstate = {
|
|
|
1311
1513
|
get islastconfirmedhistory() {
|
|
1312
1514
|
return barFlag((i, n) => {
|
|
1313
1515
|
const lastConfirmed = chartCtx.lastBarConfirmed === true && chartCtx.realtime !== true;
|
|
1314
|
-
|
|
1516
|
+
const count = chartBarCount(n);
|
|
1517
|
+
return i === (lastConfirmed ? count - 1 : count - 2);
|
|
1315
1518
|
});
|
|
1316
1519
|
}
|
|
1317
1520
|
};
|
|
@@ -1600,8 +1803,11 @@ const alert = Object.assign(alertImpl, {
|
|
|
1600
1803
|
freq_once_per_bar: "once_per_bar",
|
|
1601
1804
|
freq_once_per_bar_close: "once_per_bar_close"
|
|
1602
1805
|
});
|
|
1806
|
+
const { saveRandom: _saveRandom, restoreRandom: _restoreRandom, ...mathScript } = mathCore;
|
|
1807
|
+
void _saveRandom;
|
|
1808
|
+
void _restoreRandom;
|
|
1603
1809
|
const math = {
|
|
1604
|
-
...
|
|
1810
|
+
...mathScript,
|
|
1605
1811
|
round_to_mintick: ((number, mintick) => {
|
|
1606
1812
|
const tick = mintick ?? syminfo.mintick;
|
|
1607
1813
|
return number instanceof import_series.Series ? mathCore.round_to_mintick(number, tick) : mathCore.round_to_mintick(number, tick);
|