oakscriptjs 0.8.0 → 0.8.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/README.md +1 -1
- package/dist/array/index.d.ts.map +1 -1
- package/dist/callsite/index.d.ts +1 -0
- package/dist/callsite/index.d.ts.map +1 -1
- package/dist/color/index.d.ts +4 -4
- package/dist/color/index.d.ts.map +1 -1
- package/dist/index.cjs +95 -132
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +95 -132
- package/dist/runtime/index.cjs +1 -1
- package/dist/runtime/index.mjs +1 -1
- package/dist/runtime/types.d.ts +17 -1
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/script/index.cjs +185 -138
- package/dist/script/index.d.ts +67 -16
- package/dist/script/index.d.ts.map +1 -1
- package/dist/script/index.mjs +185 -138
- package/dist/strategy/index.d.ts.map +1 -1
- package/dist/ta/index.d.ts.map +1 -1
- package/dist/types/metadata.d.ts +9 -1
- package/dist/types/metadata.d.ts.map +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/script/index.cjs
CHANGED
|
@@ -26,6 +26,7 @@ __export(index_exports, {
|
|
|
26
26
|
alertcondition: () => alertcondition,
|
|
27
27
|
barcolor: () => barcolor,
|
|
28
28
|
barmerge: () => barmerge,
|
|
29
|
+
barstate: () => barstate,
|
|
29
30
|
bgcolor: () => bgcolor,
|
|
30
31
|
box: () => box,
|
|
31
32
|
chart: () => chart,
|
|
@@ -59,6 +60,7 @@ __export(index_exports, {
|
|
|
59
60
|
ohlc4: () => ohlc4,
|
|
60
61
|
open: () => open,
|
|
61
62
|
plot: () => plot,
|
|
63
|
+
plotarrow: () => plotarrow,
|
|
62
64
|
plotchar: () => plotchar,
|
|
63
65
|
plotshape: () => plotshape,
|
|
64
66
|
polyline: () => polyline,
|
|
@@ -338,7 +340,7 @@ var Series = class _Series {
|
|
|
338
340
|
return new _Series(this.dataSource, (bar, i, data) => {
|
|
339
341
|
const a = this.extractor(bar, i, data);
|
|
340
342
|
const b2 = typeof other === "number" ? other : other.extractor(bar, i, data);
|
|
341
|
-
return
|
|
343
|
+
return a / b2;
|
|
342
344
|
});
|
|
343
345
|
}
|
|
344
346
|
/**
|
|
@@ -711,7 +713,7 @@ function sma(source, length2) {
|
|
|
711
713
|
const window = [];
|
|
712
714
|
for (let i = 0; i < source.length; i++) {
|
|
713
715
|
const v = source[i];
|
|
714
|
-
if (v !== void 0 && v !== null &&
|
|
716
|
+
if (v !== void 0 && v !== null && Number.isFinite(v)) {
|
|
715
717
|
window.push(v);
|
|
716
718
|
if (window.length > len) window.shift();
|
|
717
719
|
}
|
|
@@ -1055,7 +1057,7 @@ function lowest(source, length2) {
|
|
|
1055
1057
|
function cum(source) {
|
|
1056
1058
|
let sum2 = 0;
|
|
1057
1059
|
return source.map((v) => {
|
|
1058
|
-
if (Number.
|
|
1060
|
+
if (!Number.isFinite(v)) return NaN;
|
|
1059
1061
|
sum2 += v;
|
|
1060
1062
|
return sum2;
|
|
1061
1063
|
});
|
|
@@ -1073,41 +1075,24 @@ function cross(source1, source2) {
|
|
|
1073
1075
|
}
|
|
1074
1076
|
return result;
|
|
1075
1077
|
}
|
|
1076
|
-
function
|
|
1078
|
+
function monotonic(source, length2, step) {
|
|
1077
1079
|
const result = [];
|
|
1080
|
+
const values = [];
|
|
1078
1081
|
for (let i = 0; i < source.length; i++) {
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
isRising = false;
|
|
1086
|
-
break;
|
|
1087
|
-
}
|
|
1088
|
-
}
|
|
1089
|
-
result.push(isRising);
|
|
1090
|
-
}
|
|
1082
|
+
const v = source[i];
|
|
1083
|
+
if (!Number.isNaN(v)) values.push(v);
|
|
1084
|
+
const n = values.length;
|
|
1085
|
+
let ok = n > length2;
|
|
1086
|
+
for (let j = 1; ok && j <= length2; j++) ok = step(values[n - j], values[n - j - 1]);
|
|
1087
|
+
result.push(ok);
|
|
1091
1088
|
}
|
|
1092
1089
|
return result;
|
|
1093
1090
|
}
|
|
1091
|
+
function rising(source, length2) {
|
|
1092
|
+
return monotonic(source, length2, gt);
|
|
1093
|
+
}
|
|
1094
1094
|
function falling(source, length2) {
|
|
1095
|
-
|
|
1096
|
-
for (let i = 0; i < source.length; i++) {
|
|
1097
|
-
if (i < length2) {
|
|
1098
|
-
result.push(false);
|
|
1099
|
-
} else {
|
|
1100
|
-
let isFalling = true;
|
|
1101
|
-
for (let j = 1; j <= length2; j++) {
|
|
1102
|
-
if (source[i - j + 1] >= source[i - j]) {
|
|
1103
|
-
isFalling = false;
|
|
1104
|
-
break;
|
|
1105
|
-
}
|
|
1106
|
-
}
|
|
1107
|
-
result.push(isFalling);
|
|
1108
|
-
}
|
|
1109
|
-
}
|
|
1110
|
-
return result;
|
|
1095
|
+
return monotonic(source, length2, lt);
|
|
1111
1096
|
}
|
|
1112
1097
|
function roc(source, length2) {
|
|
1113
1098
|
const result = [];
|
|
@@ -1331,33 +1316,16 @@ function correlation(source1, source2, length2) {
|
|
|
1331
1316
|
function percentrank(source, length2) {
|
|
1332
1317
|
const result = [];
|
|
1333
1318
|
for (let i = 0; i < source.length; i++) {
|
|
1334
|
-
|
|
1319
|
+
const currentValue = source[i];
|
|
1320
|
+
if (i < length2 || Number.isNaN(currentValue)) {
|
|
1335
1321
|
result.push(NaN);
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
let hasNaN = false;
|
|
1342
|
-
for (let j = 1; j <= length2; j++) {
|
|
1343
|
-
if (isNaN(source[i - j])) {
|
|
1344
|
-
hasNaN = true;
|
|
1345
|
-
break;
|
|
1346
|
-
}
|
|
1347
|
-
}
|
|
1348
|
-
if (hasNaN) {
|
|
1349
|
-
result.push(NaN);
|
|
1350
|
-
} else {
|
|
1351
|
-
const currentValue = source[i];
|
|
1352
|
-
let countLessOrEqual = 0;
|
|
1353
|
-
for (let j = 1; j <= length2; j++) {
|
|
1354
|
-
if (source[i - j] <= currentValue) {
|
|
1355
|
-
countLessOrEqual++;
|
|
1356
|
-
}
|
|
1357
|
-
}
|
|
1358
|
-
result.push(countLessOrEqual / length2 * 100);
|
|
1359
|
-
}
|
|
1322
|
+
continue;
|
|
1323
|
+
}
|
|
1324
|
+
let countLessOrEqual = 0;
|
|
1325
|
+
for (let j = 1; j <= length2; j++) {
|
|
1326
|
+
if (le(source[i - j], currentValue)) countLessOrEqual++;
|
|
1360
1327
|
}
|
|
1328
|
+
result.push(countLessOrEqual / length2 * 100);
|
|
1361
1329
|
}
|
|
1362
1330
|
return result;
|
|
1363
1331
|
}
|
|
@@ -1884,63 +1852,36 @@ function mode(source, length2) {
|
|
|
1884
1852
|
return result;
|
|
1885
1853
|
}
|
|
1886
1854
|
function percentile_linear_interpolation(source, length2, percentage) {
|
|
1855
|
+
return sortedWindow(source, length2, (s) => {
|
|
1856
|
+
const pos2 = percentage / 100 * length2 - 0.5;
|
|
1857
|
+
if (pos2 <= 0) return s[0];
|
|
1858
|
+
if (pos2 >= length2 - 1) return s[length2 - 1];
|
|
1859
|
+
const lo = Math.floor(pos2);
|
|
1860
|
+
return s[lo] + (pos2 - lo) * (s[lo + 1] - s[lo]);
|
|
1861
|
+
});
|
|
1862
|
+
}
|
|
1863
|
+
function sortedWindow(source, length2, fn) {
|
|
1887
1864
|
const result = [];
|
|
1865
|
+
const values = [];
|
|
1866
|
+
const bars2 = [];
|
|
1888
1867
|
for (let i = 0; i < source.length; i++) {
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
const
|
|
1896
|
-
values.
|
|
1897
|
-
|
|
1898
|
-
if (values.some((v) => isNaN(v))) {
|
|
1899
|
-
result.push(NaN);
|
|
1900
|
-
continue;
|
|
1901
|
-
}
|
|
1902
|
-
const sorted = [...values].sort((a, b2) => a - b2);
|
|
1903
|
-
const position = percentage / 100 * (sorted.length - 1);
|
|
1904
|
-
const lowerIndex = Math.floor(position);
|
|
1905
|
-
const upperIndex = Math.ceil(position);
|
|
1906
|
-
if (lowerIndex === upperIndex) {
|
|
1907
|
-
result.push(sorted[lowerIndex]);
|
|
1908
|
-
} else {
|
|
1909
|
-
const fraction = position - lowerIndex;
|
|
1910
|
-
const interpolated = sorted[lowerIndex] + fraction * (sorted[upperIndex] - sorted[lowerIndex]);
|
|
1911
|
-
result.push(interpolated);
|
|
1868
|
+
const v = source[i];
|
|
1869
|
+
let k = 0;
|
|
1870
|
+
while (k < values.length && !(values[k] >= v)) k++;
|
|
1871
|
+
values.splice(k, 0, v);
|
|
1872
|
+
bars2.splice(k, 0, i);
|
|
1873
|
+
if (i >= length2) {
|
|
1874
|
+
const old = bars2.indexOf(i - length2);
|
|
1875
|
+
values.splice(old, 1);
|
|
1876
|
+
bars2.splice(old, 1);
|
|
1912
1877
|
}
|
|
1878
|
+
result.push(i < length2 - 1 ? NaN : fn(values));
|
|
1913
1879
|
}
|
|
1914
1880
|
return result;
|
|
1915
1881
|
}
|
|
1916
1882
|
function percentile_nearest_rank(source, length2, percentage) {
|
|
1917
|
-
const
|
|
1918
|
-
|
|
1919
|
-
if (i < length2 - 1) {
|
|
1920
|
-
result.push(NaN);
|
|
1921
|
-
continue;
|
|
1922
|
-
}
|
|
1923
|
-
const values = [];
|
|
1924
|
-
for (let j = 0; j < length2; j++) {
|
|
1925
|
-
const value = source[i - j];
|
|
1926
|
-
if (!isNaN(value)) {
|
|
1927
|
-
values.push(value);
|
|
1928
|
-
}
|
|
1929
|
-
}
|
|
1930
|
-
if (values.length === 0) {
|
|
1931
|
-
result.push(NaN);
|
|
1932
|
-
continue;
|
|
1933
|
-
}
|
|
1934
|
-
const sorted = [...values].sort((a, b2) => a - b2);
|
|
1935
|
-
if (percentage >= 100) {
|
|
1936
|
-
result.push(sorted[sorted.length - 1]);
|
|
1937
|
-
continue;
|
|
1938
|
-
}
|
|
1939
|
-
const rank = Math.ceil(percentage / 100 * sorted.length);
|
|
1940
|
-
const index = Math.max(0, rank - 1);
|
|
1941
|
-
result.push(sorted[index]);
|
|
1942
|
-
}
|
|
1943
|
-
return result;
|
|
1883
|
+
const rank = Math.min(length2, Math.max(1, Math.ceil(percentage / 100 * length2)));
|
|
1884
|
+
return sortedWindow(source, length2, (s) => s[rank - 1]);
|
|
1944
1885
|
}
|
|
1945
1886
|
function rci(source, length2) {
|
|
1946
1887
|
const result = [];
|
|
@@ -2806,11 +2747,13 @@ __export(color_exports, {
|
|
|
2806
2747
|
white: () => white,
|
|
2807
2748
|
yellow: () => yellow
|
|
2808
2749
|
});
|
|
2750
|
+
var channel = (v) => v === null || v === void 0 || Number.isNaN(v) ? 0 : Math.max(0, Math.min(255, Math.trunc(v)));
|
|
2751
|
+
var alphaOf = (transp) => transp === null || Number.isNaN(transp) ? 0 : 1 - Math.max(0, Math.min(100, transp)) / 100;
|
|
2809
2752
|
function rgb(red2, green2, blue2, transp) {
|
|
2810
|
-
const r2 =
|
|
2811
|
-
const g2 =
|
|
2812
|
-
const b2 =
|
|
2813
|
-
const a = transp !== void 0 ?
|
|
2753
|
+
const r2 = channel(red2);
|
|
2754
|
+
const g2 = channel(green2);
|
|
2755
|
+
const b2 = channel(blue2);
|
|
2756
|
+
const a = transp !== void 0 ? alphaOf(transp) : 1;
|
|
2814
2757
|
if (a === 1) {
|
|
2815
2758
|
return `rgb(${r2}, ${g2}, ${b2})`;
|
|
2816
2759
|
}
|
|
@@ -2837,7 +2780,8 @@ function b(clr) {
|
|
|
2837
2780
|
return parseColor(clr).b;
|
|
2838
2781
|
}
|
|
2839
2782
|
function t(clr) {
|
|
2840
|
-
|
|
2783
|
+
const alpha = Math.round((1 - parseColor(clr).t / 100) * 255);
|
|
2784
|
+
return Math.round((1 - alpha / 255) * 100);
|
|
2841
2785
|
}
|
|
2842
2786
|
function parseColor(clr) {
|
|
2843
2787
|
if (typeof clr === "string") {
|
|
@@ -2890,13 +2834,12 @@ function from_gradient(value, bottom_value, top_value, bottom_color, top_color)
|
|
|
2890
2834
|
};
|
|
2891
2835
|
const c1 = rgba(bottom_color);
|
|
2892
2836
|
const c2 = rgba(top_color);
|
|
2893
|
-
const
|
|
2894
|
-
const w2 = c2.a * k;
|
|
2895
|
-
const a = w1 + w2;
|
|
2837
|
+
const a = c1.a * (1 - k) + c2.a * k;
|
|
2896
2838
|
if (a === 0) return transparent;
|
|
2897
|
-
const mix = (x1, x2) => Math.floor((x1 *
|
|
2839
|
+
const mix = (x1, x2) => Math.floor((x1 / 255 * c1.a * (1 - k) + x2 / 255 * c2.a * k) / (a / 255));
|
|
2898
2840
|
const [r2, g2, b2] = [mix(c1.r, c2.r), mix(c1.g, c2.g), mix(c1.b, c2.b)];
|
|
2899
|
-
|
|
2841
|
+
const alpha = Math.floor(a);
|
|
2842
|
+
return alpha === 255 ? `rgb(${r2}, ${g2}, ${b2})` : `rgba(${r2}, ${g2}, ${b2}, ${alpha / 255})`;
|
|
2900
2843
|
}
|
|
2901
2844
|
|
|
2902
2845
|
// src/drawing/registry.ts
|
|
@@ -2960,7 +2903,7 @@ function setDrawingLimits(newLimits) {
|
|
|
2960
2903
|
|
|
2961
2904
|
// src/utils/index.ts
|
|
2962
2905
|
function isNA(value) {
|
|
2963
|
-
return value === null || value === void 0 || Number.isNaN(value) || isDeleted(value);
|
|
2906
|
+
return value === null || value === void 0 || Number.isNaN(value) || value === Infinity || value === -Infinity || isDeleted(value);
|
|
2964
2907
|
}
|
|
2965
2908
|
function nz(value, defaultValue = 0) {
|
|
2966
2909
|
return isNA(value) ? defaultValue : value;
|
|
@@ -2969,7 +2912,7 @@ function fixnan(source) {
|
|
|
2969
2912
|
let last;
|
|
2970
2913
|
let seen = false;
|
|
2971
2914
|
return source.map((v) => {
|
|
2972
|
-
if (!
|
|
2915
|
+
if (!(v === null || v === void 0 || Number.isNaN(v) || isDeleted(v))) {
|
|
2973
2916
|
last = v;
|
|
2974
2917
|
seen = true;
|
|
2975
2918
|
return v;
|
|
@@ -5344,9 +5287,10 @@ var STRATEGY_DEFAULTS = {
|
|
|
5344
5287
|
calc_on_order_fills: false,
|
|
5345
5288
|
calc_on_every_tick: false,
|
|
5346
5289
|
backtest_fill_limits_assumption: 0,
|
|
5347
|
-
|
|
5348
|
-
|
|
5349
|
-
|
|
5290
|
+
// v6 values; PineScript v5: fixed / 1 / 1000000 and margins 0
|
|
5291
|
+
default_qty_type: "percent_of_equity",
|
|
5292
|
+
default_qty_value: 100,
|
|
5293
|
+
initial_capital: 1e5,
|
|
5350
5294
|
slippage: 0,
|
|
5351
5295
|
commission_type: "percent",
|
|
5352
5296
|
commission_value: 0,
|
|
@@ -5420,6 +5364,8 @@ function freshCollector(inputValues) {
|
|
|
5420
5364
|
fillConfig: [],
|
|
5421
5365
|
shapeConfig: [],
|
|
5422
5366
|
markers: [],
|
|
5367
|
+
arrowConfig: [],
|
|
5368
|
+
arrows: [],
|
|
5423
5369
|
barColorConfig: [],
|
|
5424
5370
|
bgcolors: [],
|
|
5425
5371
|
barcolors: [],
|
|
@@ -5457,6 +5403,7 @@ function executeScript(body, barsInput, inputs = {}, chart2 = {}, options = {})
|
|
|
5457
5403
|
hlineConfig: c.hlineConfig,
|
|
5458
5404
|
fillConfig: c.fillConfig,
|
|
5459
5405
|
shapeConfig: c.shapeConfig,
|
|
5406
|
+
arrowConfig: c.arrowConfig,
|
|
5460
5407
|
barColorConfig: c.barColorConfig,
|
|
5461
5408
|
defaultInputs: c.defaultInputs,
|
|
5462
5409
|
alertConfig: c.alertConfig,
|
|
@@ -5466,6 +5413,7 @@ function executeScript(body, barsInput, inputs = {}, chart2 = {}, options = {})
|
|
|
5466
5413
|
plots: c.plots,
|
|
5467
5414
|
fills: c.fills.length ? c.fills : void 0,
|
|
5468
5415
|
markers: c.markers.length ? c.markers : void 0,
|
|
5416
|
+
arrows: c.arrows.length ? c.arrows : void 0,
|
|
5469
5417
|
bgcolors: c.bgcolors.length ? c.bgcolors : void 0,
|
|
5470
5418
|
barcolors: c.barcolors.length ? c.barcolors : void 0,
|
|
5471
5419
|
alerts: c.alerts.length ? c.alerts : void 0
|
|
@@ -5496,6 +5444,15 @@ function declare(c, kind) {
|
|
|
5496
5444
|
}
|
|
5497
5445
|
c.declaration = kind;
|
|
5498
5446
|
}
|
|
5447
|
+
function common(opts) {
|
|
5448
|
+
const out = {};
|
|
5449
|
+
if (opts.group !== void 0) out.group = opts.group;
|
|
5450
|
+
if (opts.inline !== void 0) out.inline = opts.inline;
|
|
5451
|
+
if (opts.tooltip !== void 0) out.tooltip = opts.tooltip;
|
|
5452
|
+
if (opts.confirm !== void 0) out.confirm = opts.confirm;
|
|
5453
|
+
if (opts.display !== void 0) out.display = opts.display;
|
|
5454
|
+
return out;
|
|
5455
|
+
}
|
|
5499
5456
|
function registerInput(config, fallbackId) {
|
|
5500
5457
|
const c = collector();
|
|
5501
5458
|
const id = slugId(config.title, fallbackId, c.inputIds);
|
|
@@ -5506,7 +5463,7 @@ function registerInput(config, fallbackId) {
|
|
|
5506
5463
|
}
|
|
5507
5464
|
function registerNumeric(type, defval, title, opts = {}) {
|
|
5508
5465
|
const v = registerInput(
|
|
5509
|
-
{ type, defval, title, min: opts.minval, max: opts.maxval, step: opts.step },
|
|
5466
|
+
{ type, defval, title, min: opts.minval, max: opts.maxval, step: opts.step, ...common(opts) },
|
|
5510
5467
|
`input_${type}`
|
|
5511
5468
|
);
|
|
5512
5469
|
return typeof v === "number" ? v : defval;
|
|
@@ -5518,31 +5475,37 @@ var input = {
|
|
|
5518
5475
|
float(defval, title, opts = {}) {
|
|
5519
5476
|
return registerNumeric("float", defval, title, opts);
|
|
5520
5477
|
},
|
|
5521
|
-
bool(defval, title) {
|
|
5522
|
-
return registerInput({ type: "bool", defval, title }, "input_bool");
|
|
5478
|
+
bool(defval, title, opts = {}) {
|
|
5479
|
+
return registerInput({ type: "bool", defval, title, ...common(opts) }, "input_bool");
|
|
5523
5480
|
},
|
|
5524
5481
|
string(defval, title, opts = {}) {
|
|
5525
|
-
return registerInput({ type: "string", defval, title, options: opts.options }, "input_string");
|
|
5482
|
+
return registerInput({ type: "string", defval, title, options: opts.options, ...common(opts) }, "input_string");
|
|
5526
5483
|
},
|
|
5527
|
-
color(defval, title) {
|
|
5528
|
-
return registerInput({ type: "color", defval, title }, "input_color");
|
|
5484
|
+
color(defval, title, opts = {}) {
|
|
5485
|
+
return registerInput({ type: "color", defval, title, ...common(opts) }, "input_color");
|
|
5529
5486
|
},
|
|
5530
5487
|
/** Declares a source input and returns it as a Series. */
|
|
5531
|
-
source(defval = "close", title) {
|
|
5532
|
-
const name = registerInput({ type: "source", defval, title }, "input_source");
|
|
5488
|
+
source(defval = "close", title, opts = {}) {
|
|
5489
|
+
const name = registerInput({ type: "source", defval, title, ...common(opts) }, "input_source");
|
|
5533
5490
|
return sourceSeries(name);
|
|
5534
5491
|
},
|
|
5535
5492
|
/** Timeframe string ("60", "1D", "W"). As in PineScript, "" means the chart timeframe. */
|
|
5536
5493
|
timeframe(defval, title, opts = {}) {
|
|
5537
|
-
return registerInput(
|
|
5494
|
+
return registerInput(
|
|
5495
|
+
{ type: "timeframe", defval, title, options: opts.options, ...common(opts) },
|
|
5496
|
+
"input_timeframe"
|
|
5497
|
+
);
|
|
5538
5498
|
},
|
|
5539
5499
|
/** Session string ("0930-1600", "0930-1600:23456"). */
|
|
5540
5500
|
session(defval, title, opts = {}) {
|
|
5541
|
-
return registerInput(
|
|
5501
|
+
return registerInput(
|
|
5502
|
+
{ type: "session", defval, title, options: opts.options, ...common(opts) },
|
|
5503
|
+
"input_session"
|
|
5504
|
+
);
|
|
5542
5505
|
},
|
|
5543
5506
|
/** Date and time as a UNIX time in milliseconds, e.g. `input.time(timestamp('2024-01-01'), 'Start')`. */
|
|
5544
|
-
time(defval, title) {
|
|
5545
|
-
const v = registerInput({ type: "time", defval, title }, "input_time");
|
|
5507
|
+
time(defval, title, opts = {}) {
|
|
5508
|
+
const v = registerInput({ type: "time", defval, title, ...common(opts) }, "input_time");
|
|
5546
5509
|
return typeof v === "number" ? v : defval;
|
|
5547
5510
|
}
|
|
5548
5511
|
};
|
|
@@ -5596,6 +5559,8 @@ var ta2 = {
|
|
|
5596
5559
|
const a = anchor ?? changeOf("1D");
|
|
5597
5560
|
return stdev_mult === void 0 ? vwap2(source, volume, a) : vwapBands(source, volume, a, stdev_mult);
|
|
5598
5561
|
}),
|
|
5562
|
+
/** `ta.mfi(source, length)` with the chart volume (PineScript takes 2 arguments). */
|
|
5563
|
+
mfi: (source, length2) => mfi2(source, length2, volume),
|
|
5599
5564
|
/** `ta.pivothigh(source, leftbars, rightbars)` or `ta.pivothigh(leftbars, rightbars)` (source = high).
|
|
5600
5565
|
* The value appears `rightbars` bars after the pivot bar, as in PineScript. */
|
|
5601
5566
|
pivothigh: (sourceOrLeft, leftOrRight, rightbars) => typeof sourceOrLeft === "number" ? pivothigh2(high, sourceOrLeft, leftOrRight) : pivothigh2(sourceOrLeft, leftOrRight, rightbars),
|
|
@@ -5622,7 +5587,7 @@ var color = {
|
|
|
5622
5587
|
new: new_color,
|
|
5623
5588
|
when: colorWhen
|
|
5624
5589
|
};
|
|
5625
|
-
function
|
|
5590
|
+
function plotImpl(series, title, options = {}) {
|
|
5626
5591
|
const c = collector();
|
|
5627
5592
|
const id = `plot${c.plotConfig.length}`;
|
|
5628
5593
|
const perBar2 = Array.isArray(options.color) ? options.color : void 0;
|
|
@@ -5633,6 +5598,7 @@ function plot(series, title, options = {}) {
|
|
|
5633
5598
|
color: staticColor,
|
|
5634
5599
|
lineWidth: options.linewidth,
|
|
5635
5600
|
style: options.style,
|
|
5601
|
+
linestyle: options.linestyle,
|
|
5636
5602
|
display: options.display,
|
|
5637
5603
|
histbase: options.histbase
|
|
5638
5604
|
});
|
|
@@ -5641,13 +5607,29 @@ function plot(series, title, options = {}) {
|
|
|
5641
5607
|
const data = [];
|
|
5642
5608
|
for (let i = 0; i < b2.length; i++) {
|
|
5643
5609
|
const value = values[i];
|
|
5644
|
-
if (value === void 0 || Number.
|
|
5610
|
+
if (value === void 0 || !Number.isFinite(value)) continue;
|
|
5645
5611
|
data.push(perBar2 ? { time: b2[i].time, value, color: perBar2[i] } : { time: b2[i].time, value });
|
|
5646
5612
|
}
|
|
5647
5613
|
c.plots[id] = data;
|
|
5648
5614
|
return { id, kind: "plot" };
|
|
5649
5615
|
}
|
|
5650
|
-
|
|
5616
|
+
var plot = Object.assign(plotImpl, {
|
|
5617
|
+
style_line: "line",
|
|
5618
|
+
style_linebr: "linebr",
|
|
5619
|
+
style_stepline: "stepline",
|
|
5620
|
+
style_steplinebr: "steplinebr",
|
|
5621
|
+
style_stepline_diamond: "stepline_diamond",
|
|
5622
|
+
style_histogram: "histogram",
|
|
5623
|
+
style_columns: "columns",
|
|
5624
|
+
style_area: "area",
|
|
5625
|
+
style_areabr: "areabr",
|
|
5626
|
+
style_circles: "circles",
|
|
5627
|
+
style_cross: "cross",
|
|
5628
|
+
linestyle_solid: "solid",
|
|
5629
|
+
linestyle_dotted: "dotted",
|
|
5630
|
+
linestyle_dashed: "dashed"
|
|
5631
|
+
});
|
|
5632
|
+
function hlineImpl(price, title, options = {}) {
|
|
5651
5633
|
const c = collector();
|
|
5652
5634
|
const id = `hline${c.hlineConfig.length}`;
|
|
5653
5635
|
c.hlineConfig.push({
|
|
@@ -5655,11 +5637,16 @@ function hline(price, title, options = {}) {
|
|
|
5655
5637
|
price,
|
|
5656
5638
|
title,
|
|
5657
5639
|
color: options.color,
|
|
5658
|
-
linestyle: options.linestyle,
|
|
5640
|
+
linestyle: options.linestyle ?? "dashed",
|
|
5659
5641
|
linewidth: options.linewidth
|
|
5660
5642
|
});
|
|
5661
5643
|
return { id, kind: "hline" };
|
|
5662
5644
|
}
|
|
5645
|
+
var hline = Object.assign(hlineImpl, {
|
|
5646
|
+
style_solid: "solid",
|
|
5647
|
+
style_dotted: "dotted",
|
|
5648
|
+
style_dashed: "dashed"
|
|
5649
|
+
});
|
|
5663
5650
|
function perBarValues(v, n) {
|
|
5664
5651
|
return v instanceof Series ? v.toArray().slice(0, n) : new Array(n).fill(v);
|
|
5665
5652
|
}
|
|
@@ -5762,6 +5749,35 @@ function plotshape(condition, title, options = {}) {
|
|
|
5762
5749
|
function plotchar(condition, title, options = {}) {
|
|
5763
5750
|
emitMarkers("char", condition, title, options);
|
|
5764
5751
|
}
|
|
5752
|
+
function plotarrow(series, title, options = {}) {
|
|
5753
|
+
const c = collector();
|
|
5754
|
+
const id = `arrow${c.arrowConfig.length}`;
|
|
5755
|
+
const pick = (col2, fallback, i) => col2 === void 0 ? fallback : typeof col2 === "string" ? col2 : col2[i];
|
|
5756
|
+
const colorup = typeof options.colorup === "string" ? options.colorup : "#00FF00";
|
|
5757
|
+
const colordown = typeof options.colordown === "string" ? options.colordown : "#FF0000";
|
|
5758
|
+
c.arrowConfig.push({
|
|
5759
|
+
id,
|
|
5760
|
+
title,
|
|
5761
|
+
colorup,
|
|
5762
|
+
colordown,
|
|
5763
|
+
minheight: options.minheight ?? 5,
|
|
5764
|
+
maxheight: options.maxheight ?? 100,
|
|
5765
|
+
offset: options.offset,
|
|
5766
|
+
display: options.display
|
|
5767
|
+
});
|
|
5768
|
+
const values = series.toArray();
|
|
5769
|
+
const b2 = bars();
|
|
5770
|
+
const off = options.offset ?? 0;
|
|
5771
|
+
for (let i = 0; i < b2.length; i++) {
|
|
5772
|
+
const v = values[i];
|
|
5773
|
+
if (v === void 0 || Number.isNaN(v) || v === 0) continue;
|
|
5774
|
+
const j = i + off;
|
|
5775
|
+
if (j < 0 || j >= b2.length) continue;
|
|
5776
|
+
const color2 = v > 0 ? pick(options.colorup, "#00FF00", i) : pick(options.colordown, "#FF0000", i);
|
|
5777
|
+
if (color2 === void 0) continue;
|
|
5778
|
+
c.arrows.push({ time: b2[j].time, id, value: v, color: color2 });
|
|
5779
|
+
}
|
|
5780
|
+
}
|
|
5765
5781
|
function emitBarColors(kind, colors, options) {
|
|
5766
5782
|
const c = collector();
|
|
5767
5783
|
const id = `${kind}${c.barColorConfig.filter((x) => x.kind === kind).length}`;
|
|
@@ -6163,6 +6179,37 @@ function flag(key) {
|
|
|
6163
6179
|
const values = sessionFlags(ctxBars.bars.map(barTime), bars2, regular)[key];
|
|
6164
6180
|
return Series.fromArray(ctxBars, values.map((v) => v ? 1 : 0));
|
|
6165
6181
|
}
|
|
6182
|
+
function barFlag(test) {
|
|
6183
|
+
const n = ctxBars.bars.length;
|
|
6184
|
+
return Series.fromArray(ctxBars, Array.from({ length: n }, (_, i) => test(i, n) ? 1 : 0));
|
|
6185
|
+
}
|
|
6186
|
+
var lastRealtime = (i, n) => i === n - 1 && chartCtx.realtime === true;
|
|
6187
|
+
var barstate = {
|
|
6188
|
+
get isfirst() {
|
|
6189
|
+
return barFlag((i) => i === 0);
|
|
6190
|
+
},
|
|
6191
|
+
get islast() {
|
|
6192
|
+
return barFlag((i, n) => i === n - 1);
|
|
6193
|
+
},
|
|
6194
|
+
get isconfirmed() {
|
|
6195
|
+
return barFlag((i, n) => i < n - 1 || chartCtx.lastBarConfirmed === true);
|
|
6196
|
+
},
|
|
6197
|
+
get isrealtime() {
|
|
6198
|
+
return barFlag(lastRealtime);
|
|
6199
|
+
},
|
|
6200
|
+
get ishistory() {
|
|
6201
|
+
return barFlag((i, n) => !lastRealtime(i, n));
|
|
6202
|
+
},
|
|
6203
|
+
get isnew() {
|
|
6204
|
+
return barFlag((i, n) => !lastRealtime(i, n) || chartCtx.lastBarNew !== false);
|
|
6205
|
+
},
|
|
6206
|
+
get islastconfirmedhistory() {
|
|
6207
|
+
return barFlag((i, n) => {
|
|
6208
|
+
const lastConfirmed = chartCtx.lastBarConfirmed === true && chartCtx.realtime !== true;
|
|
6209
|
+
return i === (lastConfirmed ? n - 1 : n - 2);
|
|
6210
|
+
});
|
|
6211
|
+
}
|
|
6212
|
+
};
|
|
6166
6213
|
var session = {
|
|
6167
6214
|
regular: "regular",
|
|
6168
6215
|
extended: "extended",
|