@hoox-sh/pynets 0.3.0 → 0.4.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/CHANGELOG.md +17 -0
- package/README.md +5 -5
- package/dist/browser.js +66 -66
- package/dist/index.js +1532 -38
- package/package.json +1 -1
- package/src/cli/rich.ts +1 -1
- package/src/runtime/compile/collections.ts +4 -0
- package/src/runtime/compile/draw.ts +609 -19
- package/src/runtime/compile/emit.ts +81 -1
- package/src/runtime/compile/emit_call.ts +312 -9
- package/src/runtime/compile/runtime.ts +20 -0
- package/src/runtime/compile/strategy.ts +253 -1
- package/src/runtime/interpret.ts +151 -0
- package/src/runtime/ta.ts +392 -0
package/dist/index.js
CHANGED
|
@@ -42191,6 +42191,367 @@ class TaEngine {
|
|
|
42191
42191
|
const direction = recentHigh === oldest ? 1 : -1;
|
|
42192
42192
|
return { high: recentHigh, low: recentLow, dir: pct > th ? 1 : direction };
|
|
42193
42193
|
}
|
|
42194
|
+
accelSites = new Map;
|
|
42195
|
+
coerceTaInt(value, message) {
|
|
42196
|
+
if (value === null || !Number.isFinite(value))
|
|
42197
|
+
throw new Error(`${message}. Got: na`);
|
|
42198
|
+
const nearest = Math.round(value);
|
|
42199
|
+
if (Math.abs(value - nearest) <= PERIOD_INT_EPS)
|
|
42200
|
+
return nearest;
|
|
42201
|
+
return Math.floor(value);
|
|
42202
|
+
}
|
|
42203
|
+
hammer(open, high, low, close) {
|
|
42204
|
+
if (open === null || high === null || low === null || close === null) {
|
|
42205
|
+
throw new Error("bad operand type for abs(): 'NoneType'");
|
|
42206
|
+
}
|
|
42207
|
+
const body = Math.abs(close - open);
|
|
42208
|
+
const range = high - low;
|
|
42209
|
+
const lower = Math.min(open, close) - low;
|
|
42210
|
+
const upper = high - Math.max(open, close);
|
|
42211
|
+
const isDoji = body < range * 0.1;
|
|
42212
|
+
const isHammer = body > 0 && lower > body * 2 && upper < body;
|
|
42213
|
+
let strength = 0;
|
|
42214
|
+
if (isDoji)
|
|
42215
|
+
strength = 1 - body / (range + 0.0001);
|
|
42216
|
+
else if (isHammer)
|
|
42217
|
+
strength = Math.min(1, lower / (range + 0.0001));
|
|
42218
|
+
return taRec({
|
|
42219
|
+
is_hammer: isHammer,
|
|
42220
|
+
is_doji: isDoji,
|
|
42221
|
+
pattern_strength: Number.isFinite(strength) ? strength : null
|
|
42222
|
+
});
|
|
42223
|
+
}
|
|
42224
|
+
gapDetector(high, low, prevClose) {
|
|
42225
|
+
const none = taRec({ gap_size: 0, gap_type: 0, gap_percent: 0 });
|
|
42226
|
+
if (prevClose === null)
|
|
42227
|
+
return none;
|
|
42228
|
+
if (high === null || low === null) {
|
|
42229
|
+
throw new Error("unsupported operand type(s) for -: 'float' and 'NoneType'");
|
|
42230
|
+
}
|
|
42231
|
+
const upside = Math.max(0, low - prevClose);
|
|
42232
|
+
const downside = Math.max(0, prevClose - high);
|
|
42233
|
+
if (upside > downside) {
|
|
42234
|
+
const pct = prevClose !== 0 ? upside / prevClose * 100 : 0;
|
|
42235
|
+
return taRec({
|
|
42236
|
+
gap_size: upside,
|
|
42237
|
+
gap_type: 1,
|
|
42238
|
+
gap_percent: Number.isFinite(pct) ? pct : null
|
|
42239
|
+
});
|
|
42240
|
+
}
|
|
42241
|
+
if (downside > 0) {
|
|
42242
|
+
const pct = prevClose !== 0 ? downside / prevClose * 100 : 0;
|
|
42243
|
+
return taRec({
|
|
42244
|
+
gap_size: downside,
|
|
42245
|
+
gap_type: -1,
|
|
42246
|
+
gap_percent: Number.isFinite(pct) ? pct : null
|
|
42247
|
+
});
|
|
42248
|
+
}
|
|
42249
|
+
return none;
|
|
42250
|
+
}
|
|
42251
|
+
macdSignal(macdLine, signalLine) {
|
|
42252
|
+
if (macdLine === null || signalLine === null)
|
|
42253
|
+
return null;
|
|
42254
|
+
return finiteOut2(macdLine - signalLine);
|
|
42255
|
+
}
|
|
42256
|
+
accelerationFactor(site, source, period) {
|
|
42257
|
+
const p = this.coerceTaInt(period, "ta.acceleration_factor() requires 2 arguments");
|
|
42258
|
+
let samples = this.accelSites.get(site);
|
|
42259
|
+
if (samples === undefined) {
|
|
42260
|
+
samples = [];
|
|
42261
|
+
this.accelSites.set(site, samples);
|
|
42262
|
+
}
|
|
42263
|
+
pushCap(samples, finiteCell2(source), 1000);
|
|
42264
|
+
if (samples.length < p + 1 || p <= 0)
|
|
42265
|
+
return 0;
|
|
42266
|
+
const oldest = samples.slice(0, p + 1);
|
|
42267
|
+
const newestFirst = [];
|
|
42268
|
+
for (let i = oldest.length - 1;i >= 0; i--) {
|
|
42269
|
+
const v = oldest[i];
|
|
42270
|
+
if (v !== null)
|
|
42271
|
+
newestFirst.push(v);
|
|
42272
|
+
}
|
|
42273
|
+
if (newestFirst.length < 2)
|
|
42274
|
+
return 0;
|
|
42275
|
+
let oldSum = 0;
|
|
42276
|
+
for (let i = 0;i < newestFirst.length - 1; i++)
|
|
42277
|
+
oldSum += newestFirst[i];
|
|
42278
|
+
const oldMom = oldSum / (newestFirst.length - 1);
|
|
42279
|
+
if (Math.abs(oldMom) < 0.0000000001)
|
|
42280
|
+
return 0;
|
|
42281
|
+
const newMom = newestFirst[newestFirst.length - 1];
|
|
42282
|
+
let acc = (newMom - oldMom) / oldMom;
|
|
42283
|
+
if (acc < -2)
|
|
42284
|
+
acc = -2;
|
|
42285
|
+
if (acc > 2)
|
|
42286
|
+
acc = 2;
|
|
42287
|
+
return finiteOut2(acc);
|
|
42288
|
+
}
|
|
42289
|
+
stochSmooth(high, low, close, period, smoothK, smoothD) {
|
|
42290
|
+
const p = this.coerceTaInt(period, "ta.stoch_smooth period must be integer");
|
|
42291
|
+
const k = this.coerceTaInt(smoothK, "ta.stoch_smooth smooth_k must be integer");
|
|
42292
|
+
const d = this.coerceTaInt(smoothD, "ta.stoch_smooth smooth_d must be integer");
|
|
42293
|
+
if (p <= 0)
|
|
42294
|
+
throw new Error("max() iterable argument is empty");
|
|
42295
|
+
if (high === null || low === null || close === null) {
|
|
42296
|
+
throw new Error("unsupported operand type(s) for /: 'float' and 'NoneType'");
|
|
42297
|
+
}
|
|
42298
|
+
if (k !== 1 || d !== 1)
|
|
42299
|
+
return null;
|
|
42300
|
+
const span = high - low;
|
|
42301
|
+
const stoch = span !== 0 ? 100 * (close - low) / span : 50;
|
|
42302
|
+
return finiteOut2(stoch);
|
|
42303
|
+
}
|
|
42304
|
+
engulfing() {
|
|
42305
|
+
return taRec({ is_bullish: false, is_bearish: false, pattern_strength: 0 });
|
|
42306
|
+
}
|
|
42307
|
+
insideBarPattern() {
|
|
42308
|
+
return false;
|
|
42309
|
+
}
|
|
42310
|
+
doubleTopBottom(period) {
|
|
42311
|
+
if (period === null || !Number.isFinite(period)) {
|
|
42312
|
+
throw new Error("period must be integer. Got: na");
|
|
42313
|
+
}
|
|
42314
|
+
return taRec({ pattern_type: "none", strength: 0, breakout_level: 0 });
|
|
42315
|
+
}
|
|
42316
|
+
cumDeltaSites = new Map;
|
|
42317
|
+
volMomSites = new Map;
|
|
42318
|
+
volProfileLowSites = new Map;
|
|
42319
|
+
volThrustSites = new Map;
|
|
42320
|
+
asCount(value) {
|
|
42321
|
+
if (!Number.isFinite(value))
|
|
42322
|
+
return null;
|
|
42323
|
+
const nearest = Math.round(value);
|
|
42324
|
+
return Math.abs(value - nearest) <= PERIOD_INT_EPS ? nearest : Math.floor(value);
|
|
42325
|
+
}
|
|
42326
|
+
pushChrono(buf, value) {
|
|
42327
|
+
buf.push(value !== null && Number.isFinite(value) ? value : null);
|
|
42328
|
+
if (buf.length > 1000)
|
|
42329
|
+
buf.shift();
|
|
42330
|
+
}
|
|
42331
|
+
nf(buf, i) {
|
|
42332
|
+
const v = buf[-i - 1];
|
|
42333
|
+
return v === undefined ? null : v;
|
|
42334
|
+
}
|
|
42335
|
+
voi(buy, sell) {
|
|
42336
|
+
const b = buy !== null && Number.isFinite(buy) ? buy : 0;
|
|
42337
|
+
const s = sell !== null && Number.isFinite(sell) ? sell : 0;
|
|
42338
|
+
const total = b + s;
|
|
42339
|
+
if (total === 0)
|
|
42340
|
+
return 0;
|
|
42341
|
+
return finiteOut2((b - s) / total);
|
|
42342
|
+
}
|
|
42343
|
+
bidAskImbalance(bidSize, askSize, bidPrice, askPrice) {
|
|
42344
|
+
const bid = bidSize !== null && Number.isFinite(bidSize) ? bidSize : 0;
|
|
42345
|
+
const ask = askSize !== null && Number.isFinite(askSize) ? askSize : 0;
|
|
42346
|
+
const bidPx = bidPrice !== null && Number.isFinite(bidPrice) ? bidPrice : 0;
|
|
42347
|
+
const askPx = askPrice !== null && Number.isFinite(askPrice) ? askPrice : 0;
|
|
42348
|
+
const total = bid + ask;
|
|
42349
|
+
if (total === 0)
|
|
42350
|
+
return taRec({ imbalance_ratio: 0, spread: 0 });
|
|
42351
|
+
return taRec({
|
|
42352
|
+
imbalance_ratio: finiteOut2((bid - ask) / total),
|
|
42353
|
+
spread: finiteOut2(bidPx > 0 ? askPx - bidPx : 0)
|
|
42354
|
+
});
|
|
42355
|
+
}
|
|
42356
|
+
rsiOversoldOverbought(rsi, oversold, overbought) {
|
|
42357
|
+
if (rsi === null || !Number.isFinite(rsi)) {
|
|
42358
|
+
return taRec({ is_oversold: false, is_overbought: false, rsi: null });
|
|
42359
|
+
}
|
|
42360
|
+
const os = this.asCount(oversold);
|
|
42361
|
+
const ob = this.asCount(overbought);
|
|
42362
|
+
if (os === null || ob === null) {
|
|
42363
|
+
return taRec({ is_oversold: false, is_overbought: false, rsi });
|
|
42364
|
+
}
|
|
42365
|
+
return taRec({ is_oversold: rsi < os, is_overbought: rsi > ob, rsi });
|
|
42366
|
+
}
|
|
42367
|
+
rsiDivergence(series, period) {
|
|
42368
|
+
const p = this.asCount(period);
|
|
42369
|
+
if (p === null || series.length === 0)
|
|
42370
|
+
return null;
|
|
42371
|
+
let last = 0;
|
|
42372
|
+
for (let i = 0;i < series.length; i++) {
|
|
42373
|
+
if (i < p) {
|
|
42374
|
+
last = 0;
|
|
42375
|
+
continue;
|
|
42376
|
+
}
|
|
42377
|
+
const start = Math.max(0, i - p);
|
|
42378
|
+
const vals = [];
|
|
42379
|
+
for (let j = start;j <= i; j++) {
|
|
42380
|
+
const v = series[j];
|
|
42381
|
+
if (v !== null && Number.isFinite(v))
|
|
42382
|
+
vals.push(v);
|
|
42383
|
+
}
|
|
42384
|
+
if (vals.length < 2) {
|
|
42385
|
+
last = 0;
|
|
42386
|
+
continue;
|
|
42387
|
+
}
|
|
42388
|
+
let rsiMin = vals[0];
|
|
42389
|
+
let rsiMax = vals[0];
|
|
42390
|
+
for (const v of vals) {
|
|
42391
|
+
if (v < rsiMin)
|
|
42392
|
+
rsiMin = v;
|
|
42393
|
+
if (v > rsiMax)
|
|
42394
|
+
rsiMax = v;
|
|
42395
|
+
}
|
|
42396
|
+
const cur = series[i];
|
|
42397
|
+
const range = rsiMax - rsiMin;
|
|
42398
|
+
if (cur === null || !Number.isFinite(cur) || range <= 0) {
|
|
42399
|
+
last = 0;
|
|
42400
|
+
continue;
|
|
42401
|
+
}
|
|
42402
|
+
last = (cur - rsiMin) / range * 2 - 1;
|
|
42403
|
+
}
|
|
42404
|
+
return finiteOut2(last);
|
|
42405
|
+
}
|
|
42406
|
+
cumulativeDelta(site, close, volume, period) {
|
|
42407
|
+
const n = this.asCount(period);
|
|
42408
|
+
let st = this.cumDeltaSites.get(site);
|
|
42409
|
+
if (st === undefined) {
|
|
42410
|
+
st = { close: [], volume: [] };
|
|
42411
|
+
this.cumDeltaSites.set(site, st);
|
|
42412
|
+
}
|
|
42413
|
+
this.pushChrono(st.close, close);
|
|
42414
|
+
this.pushChrono(st.volume, volume);
|
|
42415
|
+
if (n === null || n <= 0 || st.close.length < n || st.volume.length < n)
|
|
42416
|
+
return 0;
|
|
42417
|
+
let delta = 0;
|
|
42418
|
+
for (let i = -n;i < 0; i++) {
|
|
42419
|
+
const cRaw = this.nf(st.close, i);
|
|
42420
|
+
const vRaw = this.nf(st.volume, i);
|
|
42421
|
+
const c = cRaw !== null && Number.isFinite(cRaw) ? cRaw : 0;
|
|
42422
|
+
const v = vRaw !== null && Number.isFinite(vRaw) ? vRaw : 0;
|
|
42423
|
+
if (i > -n) {
|
|
42424
|
+
const prevRaw = this.nf(st.close, i - 1);
|
|
42425
|
+
const prev = prevRaw !== null && Number.isFinite(prevRaw) ? prevRaw : c;
|
|
42426
|
+
if (c > prev)
|
|
42427
|
+
delta += v;
|
|
42428
|
+
else if (c < prev)
|
|
42429
|
+
delta -= v;
|
|
42430
|
+
}
|
|
42431
|
+
}
|
|
42432
|
+
return finiteOut2(delta);
|
|
42433
|
+
}
|
|
42434
|
+
volumeMomentum(site, volume, period) {
|
|
42435
|
+
const n = this.asCount(period);
|
|
42436
|
+
let st = this.volMomSites.get(site);
|
|
42437
|
+
if (st === undefined) {
|
|
42438
|
+
st = { volume: [] };
|
|
42439
|
+
this.volMomSites.set(site, st);
|
|
42440
|
+
}
|
|
42441
|
+
this.pushChrono(st.volume, volume);
|
|
42442
|
+
if (n === null || n <= 0 || st.volume.length < n + 1)
|
|
42443
|
+
return 0;
|
|
42444
|
+
const clean = [];
|
|
42445
|
+
for (let i = 0;i < n + 1; i++) {
|
|
42446
|
+
const v = st.volume[i];
|
|
42447
|
+
if (v !== null && Number.isFinite(v))
|
|
42448
|
+
clean.push(v);
|
|
42449
|
+
}
|
|
42450
|
+
if (clean.length < 2)
|
|
42451
|
+
return 0;
|
|
42452
|
+
const newVol = clean[0];
|
|
42453
|
+
let sum = 0;
|
|
42454
|
+
for (let i = 1;i < clean.length; i++)
|
|
42455
|
+
sum += clean[i];
|
|
42456
|
+
const oldVol = sum / (clean.length - 1);
|
|
42457
|
+
if (oldVol === 0)
|
|
42458
|
+
return 0;
|
|
42459
|
+
let momentum = (newVol - oldVol) / oldVol * 100;
|
|
42460
|
+
if (momentum > 100)
|
|
42461
|
+
momentum = 100;
|
|
42462
|
+
if (momentum < -100)
|
|
42463
|
+
momentum = -100;
|
|
42464
|
+
return finiteOut2(momentum);
|
|
42465
|
+
}
|
|
42466
|
+
volumeProfileHigh(prices, volumes) {
|
|
42467
|
+
if (prices.length === 0 || volumes.length === 0 || prices.length !== volumes.length)
|
|
42468
|
+
return 0;
|
|
42469
|
+
let maxVol = 0;
|
|
42470
|
+
let maxPrice = 0;
|
|
42471
|
+
for (let i = 0;i < prices.length; i++) {
|
|
42472
|
+
const v = volumes[i];
|
|
42473
|
+
if (v === null || !Number.isFinite(v) || !(v > maxVol))
|
|
42474
|
+
continue;
|
|
42475
|
+
maxVol = v;
|
|
42476
|
+
const p = prices[i];
|
|
42477
|
+
maxPrice = p !== null && Number.isFinite(p) ? p : 0;
|
|
42478
|
+
}
|
|
42479
|
+
return finiteOut2(maxPrice);
|
|
42480
|
+
}
|
|
42481
|
+
volumeProfileLow(site, close, volume, period, levels) {
|
|
42482
|
+
const p = this.asCount(period);
|
|
42483
|
+
const lv = this.asCount(levels);
|
|
42484
|
+
let st = this.volProfileLowSites.get(site);
|
|
42485
|
+
if (st === undefined) {
|
|
42486
|
+
st = { close: [], volume: [] };
|
|
42487
|
+
this.volProfileLowSites.set(site, st);
|
|
42488
|
+
}
|
|
42489
|
+
this.pushChrono(st.close, close);
|
|
42490
|
+
this.pushChrono(st.volume, volume);
|
|
42491
|
+
const oldest = st.close.length > 0 ? st.close[0] : null;
|
|
42492
|
+
const fallback = st.close.length === 0 ? 100 : oldest !== null && Number.isFinite(oldest) ? oldest : null;
|
|
42493
|
+
if (p === null || lv === null || p <= 0 || lv <= 0 || st.close.length < p)
|
|
42494
|
+
return fallback;
|
|
42495
|
+
const prices = [];
|
|
42496
|
+
const vols = [];
|
|
42497
|
+
for (let i = -p;i < 0; i++) {
|
|
42498
|
+
const c = this.nf(st.close, i);
|
|
42499
|
+
const v = this.nf(st.volume, i);
|
|
42500
|
+
if (c !== null && Number.isFinite(c) && v !== null && Number.isFinite(v)) {
|
|
42501
|
+
prices.push(c);
|
|
42502
|
+
vols.push(v);
|
|
42503
|
+
}
|
|
42504
|
+
}
|
|
42505
|
+
if (prices.length === 0)
|
|
42506
|
+
return fallback;
|
|
42507
|
+
let minP = prices[0];
|
|
42508
|
+
let maxP = prices[0];
|
|
42509
|
+
for (const c of prices) {
|
|
42510
|
+
if (c < minP)
|
|
42511
|
+
minP = c;
|
|
42512
|
+
if (c > maxP)
|
|
42513
|
+
maxP = c;
|
|
42514
|
+
}
|
|
42515
|
+
if (minP === maxP)
|
|
42516
|
+
return minP;
|
|
42517
|
+
const bucket = (maxP - minP) / lv;
|
|
42518
|
+
const buckets = new Array(lv).fill(0);
|
|
42519
|
+
for (let k = 0;k < prices.length; k++) {
|
|
42520
|
+
let idx = Math.trunc((prices[k] - minP) / bucket);
|
|
42521
|
+
if (idx > lv - 1)
|
|
42522
|
+
idx = lv - 1;
|
|
42523
|
+
if (idx < 0)
|
|
42524
|
+
idx = 0;
|
|
42525
|
+
buckets[idx] = (buckets[idx] ?? 0) + vols[k];
|
|
42526
|
+
}
|
|
42527
|
+
let minIdx = 0;
|
|
42528
|
+
for (let i = 1;i < lv; i++) {
|
|
42529
|
+
if ((buckets[i] ?? 0) < (buckets[minIdx] ?? 0))
|
|
42530
|
+
minIdx = i;
|
|
42531
|
+
}
|
|
42532
|
+
return finiteOut2(minP + minIdx * bucket);
|
|
42533
|
+
}
|
|
42534
|
+
volumeThrust(site, close, volume, volSma, sensitivity) {
|
|
42535
|
+
const sens = Number.isFinite(sensitivity) ? sensitivity : 0.3;
|
|
42536
|
+
let st = this.volThrustSites.get(site);
|
|
42537
|
+
if (st === undefined) {
|
|
42538
|
+
st = { close: [], volume: [], sma: [] };
|
|
42539
|
+
this.volThrustSites.set(site, st);
|
|
42540
|
+
}
|
|
42541
|
+
this.pushChrono(st.close, close);
|
|
42542
|
+
this.pushChrono(st.volume, volume);
|
|
42543
|
+
this.pushChrono(st.sma, volSma);
|
|
42544
|
+
if (st.close.length === 0 || st.volume.length === 0 || st.sma.length === 0)
|
|
42545
|
+
return 0;
|
|
42546
|
+
const numOr = (v, fallback) => v !== null && Number.isFinite(v) ? v : fallback;
|
|
42547
|
+
const cVal = numOr(this.nf(st.close, -1), 100);
|
|
42548
|
+
const cPrev = st.close.length > 1 ? numOr(this.nf(st.close, -2), 100) : 100;
|
|
42549
|
+
const vVal = numOr(this.nf(st.volume, -1), 1000);
|
|
42550
|
+
const vsVal = numOr(this.nf(st.sma, -1), 1000);
|
|
42551
|
+
const spike = vVal > vsVal * (1 + sens);
|
|
42552
|
+
const move = cPrev !== 0 ? Math.abs(cVal - cPrev) / cPrev > 0.01 : false;
|
|
42553
|
+
return spike && move ? 1 : 0;
|
|
42554
|
+
}
|
|
42194
42555
|
}
|
|
42195
42556
|
function spearmanRho(vals) {
|
|
42196
42557
|
const n = vals.length;
|
|
@@ -42660,7 +43021,24 @@ var TA_METHODS = new Set([
|
|
|
42660
43021
|
"emv",
|
|
42661
43022
|
"fractal",
|
|
42662
43023
|
"atr_stop",
|
|
42663
|
-
"zigzag"
|
|
43024
|
+
"zigzag",
|
|
43025
|
+
"hammer",
|
|
43026
|
+
"gap_detector",
|
|
43027
|
+
"macd_signal",
|
|
43028
|
+
"acceleration_factor",
|
|
43029
|
+
"stoch_smooth",
|
|
43030
|
+
"engulfing",
|
|
43031
|
+
"inside_bar_pattern",
|
|
43032
|
+
"double_top_bottom",
|
|
43033
|
+
"voi",
|
|
43034
|
+
"bid_ask_imbalance",
|
|
43035
|
+
"rsi_oversold_overbought",
|
|
43036
|
+
"rsi_divergence",
|
|
43037
|
+
"cumulative_delta",
|
|
43038
|
+
"volume_momentum",
|
|
43039
|
+
"volume_profile_high",
|
|
43040
|
+
"volume_profile_low",
|
|
43041
|
+
"volume_thrust"
|
|
42664
43042
|
]);
|
|
42665
43043
|
var TA_BARE_ATTRS = new Set([
|
|
42666
43044
|
"accdist",
|
|
@@ -42862,8 +43240,17 @@ function emitCall2(ctx, node, visit) {
|
|
|
42862
43240
|
const msg = pick(args, 0, ["message", "msg"], `"runtime.error"`);
|
|
42863
43241
|
return `(() => { throw new Error(String(${msg})); })()`;
|
|
42864
43242
|
}
|
|
42865
|
-
if (name === "
|
|
43243
|
+
if (name === "max_bars_back")
|
|
42866
43244
|
return "null";
|
|
43245
|
+
if (name === "timenow")
|
|
43246
|
+
return "__h.timenow(time_arr)";
|
|
43247
|
+
if (name === "alertcondition") {
|
|
43248
|
+
ctx.usesDrawings = true;
|
|
43249
|
+
const cond = pick(args, 0, ["condition"], "null");
|
|
43250
|
+
const title = hasArg(args, 1, ["title"]) ? pick(args, 1, ["title"], `"Alert"`) : `"Alert"`;
|
|
43251
|
+
const message = hasArg(args, 2, ["message"]) ? pick(args, 2, ["message"], `"Alert"`) : `"Alert"`;
|
|
43252
|
+
return `__h.draw.alertcondition(__bar_idx, ${cond}, ${title}, ${message})`;
|
|
43253
|
+
}
|
|
42867
43254
|
if (name === "str_tostring" || name === "tostring") {
|
|
42868
43255
|
const x = pick(args, 0, ["value", "source", "x"], "null");
|
|
42869
43256
|
return `String(${x} ?? "")`;
|
|
@@ -43002,6 +43389,12 @@ function periodGate(expr, fb) {
|
|
|
43002
43389
|
function finiteOr2(expr, fb) {
|
|
43003
43390
|
return `((__v) => (__v != null && Number.isFinite(__v) ? __v : ${fb}))(${expr})`;
|
|
43004
43391
|
}
|
|
43392
|
+
function cellOf(expr) {
|
|
43393
|
+
return `((__c) => (__c == null ? null : typeof __c === "boolean" ? (__c ? 1 : 0) : (typeof __c === "number" && Number.isFinite(__c) ? __c : null)))(${expr})`;
|
|
43394
|
+
}
|
|
43395
|
+
function cellList(expr) {
|
|
43396
|
+
return `(() => { const __v = ${expr}; const __cell = (e) => (e == null ? null : typeof e === "boolean" ? (e ? 1 : 0) : (typeof e === "number" && Number.isFinite(e) ? e : null)); if (__v != null && typeof __v.size === "function" && typeof __v.get === "function") { const __n = __v.size(); const __o = []; for (let __i = 0; __i < __n; __i++) __o.push(__cell(__v.get(__i))); return __o; } return [__cell(__v)]; })()`;
|
|
43397
|
+
}
|
|
43005
43398
|
var DRAW_KINDS = new Set(["label", "line", "box", "table", "polyline", "linefill"]);
|
|
43006
43399
|
var ARRAY_SIGS = {
|
|
43007
43400
|
new: [["size"], ["initial_value", "initial"]],
|
|
@@ -43172,6 +43565,10 @@ function emitArray(name, args) {
|
|
|
43172
43565
|
const raw = nsMethod(name, "array_");
|
|
43173
43566
|
if (raw == null)
|
|
43174
43567
|
return null;
|
|
43568
|
+
if (raw === "from") {
|
|
43569
|
+
const parts = args.pos.length > 0 ? args.pos : Object.values(args.kw);
|
|
43570
|
+
return `__h.array.from([${parts.join(", ")}])`;
|
|
43571
|
+
}
|
|
43175
43572
|
const method = ctorMethod(raw);
|
|
43176
43573
|
const params = ARRAY_SIGS[method];
|
|
43177
43574
|
if (params == null)
|
|
@@ -43216,11 +43613,24 @@ var DRAW_METHODS = {
|
|
|
43216
43613
|
label: {
|
|
43217
43614
|
set_text: [["id"], ["text"]],
|
|
43218
43615
|
set_xy: [["id"], ["x"], ["y"]],
|
|
43616
|
+
set_x: [["id"], ["x"]],
|
|
43617
|
+
set_y: [["id"], ["y"]],
|
|
43219
43618
|
set_color: [["id"], ["color"]],
|
|
43220
43619
|
set_style: [["id"], ["style"]],
|
|
43221
43620
|
set_size: [["id"], ["size"]],
|
|
43222
43621
|
set_tooltip: [["id"], ["tooltip"]],
|
|
43223
43622
|
set_textalign: [["id"], ["textalign"]],
|
|
43623
|
+
set_textcolor: [["id"], ["color", "textcolor"]],
|
|
43624
|
+
set_text_font_family: [["id"], ["font_family", "text_font_family"]],
|
|
43625
|
+
set_text_halign: [["id"], ["halign", "text_halign"]],
|
|
43626
|
+
set_text_valign: [["id"], ["valign", "text_valign"]],
|
|
43627
|
+
set_text_size: [["id"], ["size", "text_size"]],
|
|
43628
|
+
set_text_formatting: [["id"], ["formatting", "text_formatting"]],
|
|
43629
|
+
set_border_color: [["id"], ["color"]],
|
|
43630
|
+
set_border_width: [["id"], ["width"]],
|
|
43631
|
+
set_border_style: [["id"], ["style"]],
|
|
43632
|
+
set_xloc: [["id"], ["xloc"]],
|
|
43633
|
+
set_yloc: [["id"], ["yloc"]],
|
|
43224
43634
|
delete: [["id"]],
|
|
43225
43635
|
get_text: [["id"]],
|
|
43226
43636
|
get_x: [["id"]],
|
|
@@ -43228,12 +43638,17 @@ var DRAW_METHODS = {
|
|
|
43228
43638
|
},
|
|
43229
43639
|
line: {
|
|
43230
43640
|
set_xy: [["id"], ["x1"], ["y1"], ["x2"], ["y2"]],
|
|
43231
|
-
set_xy1: [["id"], ["x1"], ["y1"]],
|
|
43232
|
-
set_xy2: [["id"], ["x2"], ["y2"]],
|
|
43641
|
+
set_xy1: [["id"], ["x1", "x"], ["y1", "y"]],
|
|
43642
|
+
set_xy2: [["id"], ["x2", "x"], ["y2", "y"]],
|
|
43643
|
+
set_x1: [["id"], ["x1", "x"]],
|
|
43644
|
+
set_y1: [["id"], ["y1", "y"]],
|
|
43645
|
+
set_x2: [["id"], ["x2", "x"]],
|
|
43646
|
+
set_y2: [["id"], ["y2", "y"]],
|
|
43233
43647
|
set_color: [["id"], ["color"]],
|
|
43234
43648
|
set_width: [["id"], ["width"]],
|
|
43235
43649
|
set_style: [["id"], ["style"]],
|
|
43236
43650
|
set_extend: [["id"], ["extend"]],
|
|
43651
|
+
set_xloc: [["id"], ["xloc"]],
|
|
43237
43652
|
delete: [["id"]],
|
|
43238
43653
|
get_price: [["id"], ["x"]],
|
|
43239
43654
|
get_x1: [["id"]],
|
|
@@ -43244,44 +43659,137 @@ var DRAW_METHODS = {
|
|
|
43244
43659
|
box: {
|
|
43245
43660
|
set_corners: [["id"], ["left", "x1"], ["top", "y1"], ["right", "x2"], ["bottom", "y2"]],
|
|
43246
43661
|
set_lefttop: [["id"], ["left", "x1"], ["top", "y1"], ["right", "x2"], ["bottom", "y2"]],
|
|
43662
|
+
set_left: [["id"], ["left"]],
|
|
43663
|
+
set_right: [["id"], ["right"]],
|
|
43664
|
+
set_top: [["id"], ["top"]],
|
|
43665
|
+
set_bottom: [["id"], ["bottom"]],
|
|
43247
43666
|
set_bgcolor: [["id"], ["bgcolor", "color"]],
|
|
43248
43667
|
set_border_color: [["id"], ["color", "border_color"]],
|
|
43668
|
+
set_border_width: [["id"], ["width"]],
|
|
43669
|
+
set_border_style: [["id"], ["style"]],
|
|
43249
43670
|
set_text: [["id"], ["text"]],
|
|
43671
|
+
set_text_color: [["id"], ["color", "text_color"]],
|
|
43672
|
+
set_text_font_family: [["id"], ["font_family"]],
|
|
43673
|
+
set_text_halign: [["id"], ["halign"]],
|
|
43674
|
+
set_text_valign: [["id"], ["valign"]],
|
|
43675
|
+
set_text_size: [["id"], ["size"]],
|
|
43676
|
+
set_text_formatting: [["id"], ["formatting"]],
|
|
43677
|
+
set_text_wrap: [["id"], ["wrap"]],
|
|
43250
43678
|
set_extend: [["id"], ["extend"]],
|
|
43679
|
+
set_closed: [["id"], ["closed"]],
|
|
43680
|
+
set_rightbottom: [["id"], ["right"], ["bottom"]],
|
|
43681
|
+
get_left: [["id"]],
|
|
43682
|
+
get_right: [["id"]],
|
|
43683
|
+
get_top: [["id"]],
|
|
43684
|
+
get_bottom: [["id"]],
|
|
43251
43685
|
delete: [["id"]]
|
|
43252
43686
|
},
|
|
43253
43687
|
table: {
|
|
43254
43688
|
cell: [["id"], ["column", "col"], ["row"], ["text"]],
|
|
43255
|
-
cell_set_text: [["id"], ["
|
|
43689
|
+
cell_set_text: [["id"], ["row"], ["column", "col"], ["text"]],
|
|
43690
|
+
cell_get_text: [["id"], ["row"], ["column", "col"]],
|
|
43691
|
+
cell_set_text_color: [["id"], ["row"], ["column", "col"], ["color", "text"]],
|
|
43692
|
+
cell_set_bgcolor: [["id"], ["row"], ["column", "col"], ["color"]],
|
|
43693
|
+
cell_set_border_color: [["id"], ["row"], ["column", "col"], ["color"]],
|
|
43694
|
+
cell_set_border_width: [["id"], ["row"], ["column", "col"], ["width"]],
|
|
43695
|
+
cell_set_tooltip: [["id"], ["row"], ["column", "col"], ["tooltip", "text"]],
|
|
43696
|
+
cell_set_width: [["id"], ["column", "col"], ["row"], ["width"]],
|
|
43697
|
+
cell_set_height: [["id"], ["column", "col"], ["row"], ["height"]],
|
|
43698
|
+
cell_set_text_halign: [["id"], ["column", "col"], ["row"], ["halign"]],
|
|
43699
|
+
cell_set_text_valign: [["id"], ["column", "col"], ["row"], ["valign"]],
|
|
43700
|
+
cell_set_text_size: [["id"], ["column", "col"], ["row"], ["size"]],
|
|
43701
|
+
cell_set_text_font_family: [["id"], ["column", "col"], ["row"], ["font_family"]],
|
|
43702
|
+
cell_set_text_formatting: [["id"], ["column", "col"], ["row"], ["formatting"]],
|
|
43256
43703
|
set_position: [["id"], ["position"]],
|
|
43704
|
+
set_bgcolor: [["id"], ["color", "bgcolor"]],
|
|
43705
|
+
set_border_color: [["id"], ["color"]],
|
|
43706
|
+
set_border_width: [["id"], ["width"]],
|
|
43707
|
+
set_frame_color: [["id"], ["color"]],
|
|
43708
|
+
set_frame_width: [["id"], ["width"]],
|
|
43709
|
+
merge_cells: [["id"], ["start_row"], ["start_column", "start_col"], ["end_row"], ["end_column", "end_col"]],
|
|
43257
43710
|
delete: [["id"]]
|
|
43258
43711
|
},
|
|
43259
43712
|
polyline: {
|
|
43260
|
-
delete: [["id"]]
|
|
43713
|
+
delete: [["id"]],
|
|
43714
|
+
get_points: [["id"]],
|
|
43715
|
+
set_points: [["id"], ["points"]],
|
|
43716
|
+
set_line_color: [["id"], ["color"]],
|
|
43717
|
+
set_line_width: [["id"], ["width"]],
|
|
43718
|
+
set_line_style: [["id"], ["style"]],
|
|
43719
|
+
set_fill_color: [["id"], ["fill_color", "color"]],
|
|
43720
|
+
set_curved: [["id"], ["curved"]],
|
|
43721
|
+
set_force_overlay: [["id"], ["force_overlay"]],
|
|
43722
|
+
set_closed: [["id"], ["closed"]],
|
|
43723
|
+
set_xloc: [["id"], ["xloc"]]
|
|
43261
43724
|
},
|
|
43262
43725
|
linefill: {
|
|
43263
43726
|
set_color: [["id"], ["color"]],
|
|
43264
|
-
delete: [["id"]]
|
|
43727
|
+
delete: [["id"]],
|
|
43728
|
+
get_line1: [["id"]],
|
|
43729
|
+
get_line2: [["id"]]
|
|
43265
43730
|
}
|
|
43266
43731
|
};
|
|
43732
|
+
function emitChartPoint(name, args) {
|
|
43733
|
+
const meth = name.slice("chart_point_".length);
|
|
43734
|
+
if (meth === "new" || meth === "from_time") {
|
|
43735
|
+
return `__h.draw.point_new(${pick(args, 0, ["time"], "null")}, ${pick(args, 1, ["price"], "0")})`;
|
|
43736
|
+
}
|
|
43737
|
+
if (meth === "from_index") {
|
|
43738
|
+
return `__h.draw.point_from_index(${pick(args, 0, ["index"], "null")}, ${pick(args, 1, ["price"], "0")})`;
|
|
43739
|
+
}
|
|
43740
|
+
if (meth === "now") {
|
|
43741
|
+
return `__h.draw.point_now(__bar_idx, time, ${pick(args, 0, ["price"], "0")})`;
|
|
43742
|
+
}
|
|
43743
|
+
if (meth === "copy") {
|
|
43744
|
+
return `__h.draw.point_copy(${pick(args, 0, ["point"], "null")})`;
|
|
43745
|
+
}
|
|
43746
|
+
return null;
|
|
43747
|
+
}
|
|
43267
43748
|
function emitDraw(ctx, name, methodSrc, args) {
|
|
43268
43749
|
if (name === "alert" && methodSrc == null) {
|
|
43269
43750
|
ctx.usesDrawings = true;
|
|
43270
43751
|
return `__h.draw.alert(__bar_idx, ${pick(args, 0, ["message"], "null")})`;
|
|
43271
43752
|
}
|
|
43753
|
+
if (name.startsWith("chart_point_")) {
|
|
43754
|
+
const point = emitChartPoint(name, args);
|
|
43755
|
+
if (point != null)
|
|
43756
|
+
ctx.usesDrawings = true;
|
|
43757
|
+
return point;
|
|
43758
|
+
}
|
|
43272
43759
|
const parsed = drawKindAndMethod(name, methodSrc);
|
|
43273
43760
|
if (parsed == null)
|
|
43274
43761
|
return null;
|
|
43275
43762
|
const { kind, method } = parsed;
|
|
43276
43763
|
let code = null;
|
|
43277
|
-
if (method === "
|
|
43764
|
+
if (method === "all") {
|
|
43765
|
+
code = `__h.draw.all(${JSON.stringify(kind)})`;
|
|
43766
|
+
} else if (method === "copy" && (kind === "line" || kind === "label" || kind === "box" || kind === "polyline")) {
|
|
43767
|
+
code = `__h.draw.copy(${pick(args, 0, ["id"], "null")})`;
|
|
43768
|
+
} else if (method === "new") {
|
|
43278
43769
|
if (kind === "label") {
|
|
43279
|
-
code = `__h.draw.label_new(__bar_idx, ${pick(args, 2, ["text"], "null")})`;
|
|
43770
|
+
code = `__h.draw.label_new(__bar_idx, ${pick(args, 2, ["text"], "null")}, ${pick(args, 0, ["x"], "0")}, ${pick(args, 1, ["y"], "0")})`;
|
|
43771
|
+
} else if (kind === "line") {
|
|
43772
|
+
code = `__h.draw.line_new(__bar_idx, ${pick(args, 0, ["x1"], "0")}, ${pick(args, 1, ["y1"], "0")}, ${pick(args, 2, ["x2"], "0")}, ${pick(args, 3, ["y2"], "0")})`;
|
|
43773
|
+
} else if (kind === "box") {
|
|
43774
|
+
code = `__h.draw.box_new(__bar_idx, ${pick(args, 0, ["left"], "0")}, ${pick(args, 1, ["top"], "0")}, ${pick(args, 2, ["right"], "0")}, ${pick(args, 3, ["bottom"], "0")})`;
|
|
43775
|
+
} else if (kind === "polyline") {
|
|
43776
|
+
code = `__h.draw.polyline_new(__bar_idx, ${pick(args, 0, ["points"], "null")})`;
|
|
43280
43777
|
} else if (kind === "linefill") {
|
|
43281
|
-
|
|
43778
|
+
const color = hasArg(args, 2, ["color"]) ? pick(args, 2, ["color"], "null") : "null";
|
|
43779
|
+
code = `__h.draw.linefill_new(__bar_idx, ${pick(args, 0, ["id1", "line1"], "null")}, ${pick(args, 1, ["id2", "line2"], "null")}, ${color})`;
|
|
43282
43780
|
} else if (DRAW_KINDS.has(kind)) {
|
|
43283
43781
|
code = `__h.draw.${kind}_new(__bar_idx)`;
|
|
43284
43782
|
}
|
|
43783
|
+
} else if (kind === "line" && method === "fill") {
|
|
43784
|
+
const color = hasArg(args, 2, ["color"]) ? pick(args, 2, ["color"], "null") : "null";
|
|
43785
|
+
code = `__h.draw.linefill_new(__bar_idx, ${pick(args, 0, ["id1", "line1"], "null")}, ${pick(args, 1, ["id2", "line2"], "null")}, ${color})`;
|
|
43786
|
+
} else if (kind === "line" && (method === "set_first_point" || method === "set_second_point") || kind === "label" && method === "set_point" || kind === "box" && (method === "set_top_left_point" || method === "set_bottom_right_point")) {
|
|
43787
|
+
code = `__h.draw.${kind}_${method}(${pick(args, 0, ["id"], "null")}, ${pick(args, 1, ["point"], "null")})`;
|
|
43788
|
+
} else if (kind === "box" && method === "set_xloc") {
|
|
43789
|
+
code = `__h.draw.box_set_xloc(${pick(args, 0, ["id"], "null")}, ${pick(args, 1, ["left"], "null")}, ${pick(args, 2, ["right"], "null")}, ${pick(args, 3, ["xloc"], "null")})`;
|
|
43790
|
+
} else if (kind === "table" && method === "clear") {
|
|
43791
|
+
const id = pick(args, 0, ["id", "table_id"], "null");
|
|
43792
|
+
code = hasArg(args, 1, ["start_row"]) ? `__h.draw.table_clear(${id}, ${pick(args, 1, ["start_row"], "null")}, ${pick(args, 2, ["start_column", "start_col"], "null")}, ${pick(args, 3, ["end_row"], "null")}, ${pick(args, 4, ["end_column", "end_col"], "null")})` : `__h.draw.table_clear(${id})`;
|
|
43285
43793
|
} else {
|
|
43286
43794
|
const aliased = kind === "box" && method === "set_lefttop" ? "set_corners" : method;
|
|
43287
43795
|
const params = DRAW_METHODS[kind]?.[method] ?? DRAW_METHODS[kind]?.[aliased];
|
|
@@ -43330,6 +43838,7 @@ function emitUdt(ctx, name, methodSrc, args) {
|
|
|
43330
43838
|
}
|
|
43331
43839
|
var SECURITY_FUNCS = new Set([
|
|
43332
43840
|
"security",
|
|
43841
|
+
"security_lower_tf",
|
|
43333
43842
|
"request_security",
|
|
43334
43843
|
"request_security_lower_tf",
|
|
43335
43844
|
"request_seed"
|
|
@@ -43480,6 +43989,7 @@ function emitStrategyDecl(ctx, args) {
|
|
|
43480
43989
|
add(["default_qty_type"], "default_qty_type");
|
|
43481
43990
|
add(["default_qty_value"], "default_qty_value");
|
|
43482
43991
|
add(["initial_capital"], "initial_capital");
|
|
43992
|
+
add(["currency"], "currency");
|
|
43483
43993
|
return `__h.strategy.configure({${fields.join(", ")}})`;
|
|
43484
43994
|
}
|
|
43485
43995
|
function emitStrategyEntry(method, args) {
|
|
@@ -43550,8 +44060,48 @@ function emitStrategy(ctx, name, args) {
|
|
|
43550
44060
|
case "margin_liquidation_price":
|
|
43551
44061
|
case "position_avg_price":
|
|
43552
44062
|
case "initial_capital":
|
|
44063
|
+
case "cash":
|
|
44064
|
+
case "position_entry_name":
|
|
44065
|
+
case "account_currency":
|
|
44066
|
+
case "max_contracts_held_all":
|
|
44067
|
+
case "max_contracts_held_long":
|
|
44068
|
+
case "max_contracts_held_short":
|
|
44069
|
+
case "wintrades":
|
|
44070
|
+
case "losstrades":
|
|
44071
|
+
case "eventrades":
|
|
44072
|
+
case "grossprofit":
|
|
44073
|
+
case "grossloss":
|
|
44074
|
+
case "avg_trade":
|
|
44075
|
+
case "avg_winning_trade":
|
|
44076
|
+
case "avg_losing_trade":
|
|
44077
|
+
case "netprofit_percent":
|
|
44078
|
+
case "openprofit_percent":
|
|
44079
|
+
case "grossprofit_percent":
|
|
44080
|
+
case "grossloss_percent":
|
|
44081
|
+
case "avg_trade_percent":
|
|
44082
|
+
case "avg_winning_trade_percent":
|
|
44083
|
+
case "avg_losing_trade_percent":
|
|
44084
|
+
case "max_drawdown":
|
|
44085
|
+
case "max_drawdown_percent":
|
|
44086
|
+
case "max_runup":
|
|
44087
|
+
case "max_runup_percent":
|
|
44088
|
+
case "percent_profitable":
|
|
44089
|
+
case "winrate":
|
|
44090
|
+
case "profitfactor":
|
|
44091
|
+
case "profit_factor":
|
|
44092
|
+
case "capital_held":
|
|
44093
|
+
case "closedtrades_first_index":
|
|
43553
44094
|
ctx.usesStrategy = true;
|
|
43554
44095
|
return `__h.strategy.${method}()`;
|
|
44096
|
+
case "commission":
|
|
44097
|
+
return "0";
|
|
44098
|
+
case "default_entry_qty":
|
|
44099
|
+
ctx.usesStrategy = true;
|
|
44100
|
+
return hasArg(args, 0, ["percent_equity"]) ? `__h.strategy.default_entry_qty(${pick(args, 0, ["percent_equity"], "null")})` : `__h.strategy.default_entry_qty()`;
|
|
44101
|
+
case "convert_to_account":
|
|
44102
|
+
case "convert_to_symbol":
|
|
44103
|
+
ctx.usesStrategy = true;
|
|
44104
|
+
return hasArg(args, 0, ["value"]) ? `__h.strategy.convert_to(${pick(args, 0, ["value"], "null")})` : "1";
|
|
43555
44105
|
case "risk_allow_entry_in":
|
|
43556
44106
|
ctx.usesStrategy = true;
|
|
43557
44107
|
return `__h.strategy.risk_allow_entry_in(${pick(args, 0, ["value"], "null")})`;
|
|
@@ -43561,10 +44111,36 @@ function emitStrategy(ctx, name, args) {
|
|
|
43561
44111
|
case "risk_max_drawdown":
|
|
43562
44112
|
ctx.usesStrategy = true;
|
|
43563
44113
|
return `__h.strategy.risk_max_drawdown(${pick(args, 0, ["value"], "null")}, ${pick(args, 1, ["type"], "null")})`;
|
|
43564
|
-
default:
|
|
44114
|
+
default: {
|
|
44115
|
+
if (method.startsWith("direction_")) {
|
|
44116
|
+
const tail = method.slice("direction_".length);
|
|
44117
|
+
if (tail === "long" || tail === "short" || tail === "all")
|
|
44118
|
+
return JSON.stringify(tail);
|
|
44119
|
+
}
|
|
44120
|
+
if (method.startsWith("oca_")) {
|
|
44121
|
+
const tail = method.slice("oca_".length);
|
|
44122
|
+
if (tail === "none" || tail === "cancel" || tail === "reduce")
|
|
44123
|
+
return JSON.stringify(tail);
|
|
44124
|
+
}
|
|
44125
|
+
if (method.startsWith("commission_")) {
|
|
44126
|
+
const tail = method.slice("commission_".length);
|
|
44127
|
+
if (tail === "percent" || tail === "cash_per_order" || tail === "cash_per_contract") {
|
|
44128
|
+
return JSON.stringify(tail);
|
|
44129
|
+
}
|
|
44130
|
+
}
|
|
44131
|
+
if (method.startsWith("closedtrades_") || method.startsWith("opentrades_")) {
|
|
44132
|
+
ctx.usesStrategy = true;
|
|
44133
|
+
if (method === "opentrades_capital_held")
|
|
44134
|
+
return "__h.strategy.capital_held()";
|
|
44135
|
+
if (method === "closedtrades_first_index")
|
|
44136
|
+
return "__h.strategy.closedtrades_first_index()";
|
|
44137
|
+
const idx = hasArg(args, 0, ["trade_num", "trade_index", "index"]) ? pick(args, 0, ["trade_num", "trade_index", "index"], "0") : "0";
|
|
44138
|
+
return `__h.strategy.${method}(${idx})`;
|
|
44139
|
+
}
|
|
43565
44140
|
if (isStrategyAction(name, method))
|
|
43566
44141
|
ctx.usesStrategy = true;
|
|
43567
44142
|
return "null";
|
|
44143
|
+
}
|
|
43568
44144
|
}
|
|
43569
44145
|
}
|
|
43570
44146
|
function seriesNameRef(ctx, id) {
|
|
@@ -43624,7 +44200,7 @@ function emitPlot(ctx, fname, args) {
|
|
|
43624
44200
|
const series = ohlc ? pick(args, 3, ["close"], "null") : pick(args, 0, ["series", "source", "price"], "null");
|
|
43625
44201
|
const i = ctx.plots.length;
|
|
43626
44202
|
ctx.plots.push({ title });
|
|
43627
|
-
return `plot_${i}[__bar_idx] = __h.
|
|
44203
|
+
return `plot_${i}[__bar_idx] = __h.plotNum(${series})`;
|
|
43628
44204
|
}
|
|
43629
44205
|
function emitColor(name, args) {
|
|
43630
44206
|
if (name === "color_r")
|
|
@@ -44180,6 +44756,79 @@ function emitTa(ctx, method, args) {
|
|
|
44180
44756
|
]);
|
|
44181
44757
|
return `(() => { const __r = ${call}; return [__r.high, __r.low, __r.dir]; })()`;
|
|
44182
44758
|
}
|
|
44759
|
+
if (method === "hammer") {
|
|
44760
|
+
return `__h.ta.hammer(${cellOf(pick(args, 0, ["open"], "null"))}, ${cellOf(pick(args, 1, ["high"], "null"))}, ${cellOf(pick(args, 2, ["low"], "null"))}, ${cellOf(pick(args, 3, ["close"], "null"))})`;
|
|
44761
|
+
}
|
|
44762
|
+
if (method === "gap_detector") {
|
|
44763
|
+
return `__h.ta.gapDetector(${cellOf(pick(args, 0, ["high"], "null"))}, ${cellOf(pick(args, 1, ["low"], "null"))}, ${cellOf(pick(args, 2, ["prev_close", "prev"], "null"))})`;
|
|
44764
|
+
}
|
|
44765
|
+
if (method === "macd_signal") {
|
|
44766
|
+
return `__h.ta.macdSignal(${cellOf(pick(args, 0, ["macd_line", "macd"], "null"))}, ${cellOf(pick(args, 1, ["signal_line", "signal"], "null"))})`;
|
|
44767
|
+
}
|
|
44768
|
+
if (method === "acceleration_factor") {
|
|
44769
|
+
return taCall("accelerationFactor", site, [
|
|
44770
|
+
cellOf(pick(args, 0, ["momentum_list", "momentum", "source", "series"], "null")),
|
|
44771
|
+
cellOf(pick(args, 1, ["period", "length"], "null"))
|
|
44772
|
+
]);
|
|
44773
|
+
}
|
|
44774
|
+
if (method === "stoch_smooth") {
|
|
44775
|
+
return `__h.ta.stochSmooth(${cellOf(pick(args, 0, ["high"], "null"))}, ${cellOf(pick(args, 1, ["low"], "null"))}, ${cellOf(pick(args, 2, ["close"], "null"))}, ${cellOf(pick(args, 3, ["period", "length"], "null"))}, ${cellOf(pick(args, 4, ["smooth_k", "k"], "null"))}, ${cellOf(pick(args, 5, ["smooth_d", "d"], "null"))})`;
|
|
44776
|
+
}
|
|
44777
|
+
if (method === "engulfing") {
|
|
44778
|
+
return `(() => { ${cellOf(pick(args, 0, ["open"], "null"))}; ${cellOf(pick(args, 1, ["high"], "null"))}; ${cellOf(pick(args, 2, ["low"], "null"))}; ${cellOf(pick(args, 3, ["close"], "null"))}; return __h.ta.engulfing(); })()`;
|
|
44779
|
+
}
|
|
44780
|
+
if (method === "inside_bar_pattern") {
|
|
44781
|
+
return `(() => { ${cellOf(pick(args, 0, ["high"], "null"))}; ${cellOf(pick(args, 1, ["low"], "null"))}; return __h.ta.insideBarPattern(); })()`;
|
|
44782
|
+
}
|
|
44783
|
+
if (method === "double_top_bottom") {
|
|
44784
|
+
return `(() => { ${cellOf(pick(args, 0, ["high"], "null"))}; ${cellOf(pick(args, 1, ["low"], "null"))}; return __h.ta.doubleTopBottom(${cellOf(pick(args, 2, ["period", "length"], "null"))}); })()`;
|
|
44785
|
+
}
|
|
44786
|
+
if (method === "voi") {
|
|
44787
|
+
return `__h.ta.voi(${cellOf(pick(args, 0, ["buy_volume", "buy"], "null"))}, ${cellOf(pick(args, 1, ["sell_volume", "sell"], "null"))})`;
|
|
44788
|
+
}
|
|
44789
|
+
if (method === "bid_ask_imbalance") {
|
|
44790
|
+
return `__h.ta.bidAskImbalance(${cellOf(pick(args, 0, ["bid_size", "bid"], "null"))}, ${cellOf(pick(args, 1, ["ask_size", "ask"], "null"))}, ${cellOf(pick(args, 2, ["bid_price"], "null"))}, ${cellOf(pick(args, 3, ["ask_price"], "null"))})`;
|
|
44791
|
+
}
|
|
44792
|
+
if (method === "rsi_oversold_overbought") {
|
|
44793
|
+
return `__h.ta.rsiOversoldOverbought(${cellOf(pick(args, 0, ["rsi_series", "rsi", "source"], "null"))}, ${cellOf(pick(args, 1, ["oversold_level", "oversold"], "null"))}, ${cellOf(pick(args, 2, ["overbought_level", "overbought"], "null"))})`;
|
|
44794
|
+
}
|
|
44795
|
+
if (method === "rsi_divergence") {
|
|
44796
|
+
const period = `((__n) => (__n == null ? 0 : __n))(${cellOf(pick(args, 1, ["period", "length"], "null"))})`;
|
|
44797
|
+
return `__h.ta.rsiDivergence(${cellList(pick(args, 0, ["rsi_series", "series", "source"], "null"))}, ${period})`;
|
|
44798
|
+
}
|
|
44799
|
+
if (method === "cumulative_delta") {
|
|
44800
|
+
return taCall("cumulativeDelta", site, [
|
|
44801
|
+
cellOf(pick(args, 0, ["close", "source"], "null")),
|
|
44802
|
+
cellOf(pick(args, 1, ["volume"], "null")),
|
|
44803
|
+
cellOf(pick(args, 2, ["period", "length"], "null"))
|
|
44804
|
+
]);
|
|
44805
|
+
}
|
|
44806
|
+
if (method === "volume_momentum") {
|
|
44807
|
+
return taCall("volumeMomentum", site, [
|
|
44808
|
+
cellOf(pick(args, 0, ["volume", "source"], "null")),
|
|
44809
|
+
cellOf(pick(args, 1, ["period", "length"], "null"))
|
|
44810
|
+
]);
|
|
44811
|
+
}
|
|
44812
|
+
if (method === "volume_profile_high") {
|
|
44813
|
+
return `__h.ta.volumeProfileHigh(${cellList(pick(args, 0, ["close", "price", "source", "series"], "null"))}, ${cellList(pick(args, 1, ["volume"], "null"))})`;
|
|
44814
|
+
}
|
|
44815
|
+
if (method === "volume_profile_low") {
|
|
44816
|
+
return taCall("volumeProfileLow", site, [
|
|
44817
|
+
cellOf(pick(args, 0, ["close", "source"], "null")),
|
|
44818
|
+
cellOf(pick(args, 1, ["volume"], "null")),
|
|
44819
|
+
cellOf(pick(args, 2, ["period", "length"], "null")),
|
|
44820
|
+
cellOf(pick(args, 3, ["levels"], "null"))
|
|
44821
|
+
]);
|
|
44822
|
+
}
|
|
44823
|
+
if (method === "volume_thrust") {
|
|
44824
|
+
const sens = cellOf(pick(args, 3, ["sensitivity"], "null"));
|
|
44825
|
+
return taCall("volumeThrust", site, [
|
|
44826
|
+
cellOf(pick(args, 0, ["close", "source"], "null")),
|
|
44827
|
+
cellOf(pick(args, 1, ["volume"], "null")),
|
|
44828
|
+
cellOf(pick(args, 2, ["volume_sma", "vol_sma", "sma"], "null")),
|
|
44829
|
+
`((__n) => (__n == null ? 0.3 : __n))(${sens})`
|
|
44830
|
+
]);
|
|
44831
|
+
}
|
|
44183
44832
|
return "null";
|
|
44184
44833
|
}
|
|
44185
44834
|
|
|
@@ -44557,6 +45206,8 @@ function emitName(state, node) {
|
|
|
44557
45206
|
return id;
|
|
44558
45207
|
if (state.ctx.enumTypes.has(id))
|
|
44559
45208
|
return JSON.stringify(id);
|
|
45209
|
+
if (id === "timenow")
|
|
45210
|
+
return "__h.timenow(time_arr)";
|
|
44560
45211
|
return safeIdent2(id);
|
|
44561
45212
|
}
|
|
44562
45213
|
function emitConstant2(node) {
|
|
@@ -44673,8 +45324,53 @@ var STRATEGY_QUERY_ATTRS = new Set([
|
|
|
44673
45324
|
"leverage",
|
|
44674
45325
|
"margin_liquidation_price",
|
|
44675
45326
|
"position_avg_price",
|
|
44676
|
-
"initial_capital"
|
|
45327
|
+
"initial_capital",
|
|
45328
|
+
"cash",
|
|
45329
|
+
"position_entry_name",
|
|
45330
|
+
"account_currency",
|
|
45331
|
+
"default_entry_qty",
|
|
45332
|
+
"max_contracts_held_all",
|
|
45333
|
+
"max_contracts_held_long",
|
|
45334
|
+
"max_contracts_held_short",
|
|
45335
|
+
"wintrades",
|
|
45336
|
+
"losstrades",
|
|
45337
|
+
"eventrades",
|
|
45338
|
+
"grossprofit",
|
|
45339
|
+
"grossloss",
|
|
45340
|
+
"avg_trade",
|
|
45341
|
+
"avg_winning_trade",
|
|
45342
|
+
"avg_losing_trade",
|
|
45343
|
+
"netprofit_percent",
|
|
45344
|
+
"openprofit_percent",
|
|
45345
|
+
"grossprofit_percent",
|
|
45346
|
+
"grossloss_percent",
|
|
45347
|
+
"avg_trade_percent",
|
|
45348
|
+
"avg_winning_trade_percent",
|
|
45349
|
+
"avg_losing_trade_percent",
|
|
45350
|
+
"max_drawdown",
|
|
45351
|
+
"max_drawdown_percent",
|
|
45352
|
+
"max_runup",
|
|
45353
|
+
"max_runup_percent",
|
|
45354
|
+
"percent_profitable",
|
|
45355
|
+
"winrate",
|
|
45356
|
+
"profitfactor",
|
|
45357
|
+
"profit_factor"
|
|
44677
45358
|
]);
|
|
45359
|
+
var STRATEGY_NESTED_CONSTS = {
|
|
45360
|
+
"strategy.direction.long": "long",
|
|
45361
|
+
"strategy.direction.short": "short",
|
|
45362
|
+
"strategy.direction.all": "all",
|
|
45363
|
+
"strategy.oca.none": "none",
|
|
45364
|
+
"strategy.oca.cancel": "cancel",
|
|
45365
|
+
"strategy.oca.reduce": "reduce",
|
|
45366
|
+
"strategy.commission.percent": "percent",
|
|
45367
|
+
"strategy.commission.cash_per_order": "cash_per_order",
|
|
45368
|
+
"strategy.commission.cash_per_contract": "cash_per_contract"
|
|
45369
|
+
};
|
|
45370
|
+
var STRATEGY_NESTED_CALLS = {
|
|
45371
|
+
"strategy.closedtrades.first_index": "closedtrades_first_index",
|
|
45372
|
+
"strategy.opentrades.capital_held": "capital_held"
|
|
45373
|
+
};
|
|
44678
45374
|
var ATTR_NAMESPACES = new Set([
|
|
44679
45375
|
"ta",
|
|
44680
45376
|
"math",
|
|
@@ -44778,6 +45474,9 @@ var ATTR_CONSTANTS = {
|
|
|
44778
45474
|
"hline.style_solid": "solid",
|
|
44779
45475
|
"hline.style_dashed": "dashed",
|
|
44780
45476
|
"hline.style_dotted": "dotted",
|
|
45477
|
+
"plot.linestyle_solid": "linestyle_solid",
|
|
45478
|
+
"plot.linestyle_dashed": "linestyle_dashed",
|
|
45479
|
+
"plot.linestyle_dotted": "linestyle_dotted",
|
|
44781
45480
|
"dayofweek.sunday": 1,
|
|
44782
45481
|
"dayofweek.monday": 2,
|
|
44783
45482
|
"dayofweek.tuesday": 3,
|
|
@@ -44813,6 +45512,7 @@ var ATTR_CONST_NS = new Set([
|
|
|
44813
45512
|
"display",
|
|
44814
45513
|
"position",
|
|
44815
45514
|
"hline",
|
|
45515
|
+
"plot",
|
|
44816
45516
|
"dayofweek",
|
|
44817
45517
|
"month"
|
|
44818
45518
|
]);
|
|
@@ -44959,16 +45659,24 @@ function emitAttribute(state, node) {
|
|
|
44959
45659
|
return `"futures"`;
|
|
44960
45660
|
if (attr === "avg_price_inverse")
|
|
44961
45661
|
return `"inverse"`;
|
|
44962
|
-
if (attr === "cash")
|
|
44963
|
-
return `"cash"`;
|
|
44964
45662
|
if (attr === "fixed")
|
|
44965
45663
|
return `"fixed"`;
|
|
44966
45664
|
if (attr === "percent_of_equity")
|
|
44967
45665
|
return `"percent_of_equity"`;
|
|
45666
|
+
if (attr === "commission")
|
|
45667
|
+
return "0";
|
|
44968
45668
|
if (STRATEGY_QUERY_ATTRS.has(attr)) {
|
|
44969
45669
|
state.ctx.usesStrategy = true;
|
|
44970
45670
|
return `__h.strategy.${attr}()`;
|
|
44971
45671
|
}
|
|
45672
|
+
return "null";
|
|
45673
|
+
}
|
|
45674
|
+
if (node.attr === "all" && node.value.kind === "Name") {
|
|
45675
|
+
const kind = node.value.id;
|
|
45676
|
+
if (kind === "line" || kind === "label" || kind === "box" || kind === "table" || kind === "polyline" || kind === "linefill") {
|
|
45677
|
+
state.ctx.usesDrawings = true;
|
|
45678
|
+
return `__h.draw.all(${JSON.stringify(kind)})`;
|
|
45679
|
+
}
|
|
44972
45680
|
}
|
|
44973
45681
|
if (node.value.kind === "Name") {
|
|
44974
45682
|
const members = state.ctx.enumTypes.get(node.value.id);
|
|
@@ -44978,6 +45686,16 @@ function emitAttribute(state, node) {
|
|
|
44978
45686
|
}
|
|
44979
45687
|
const qn = attrQualifiedName(node);
|
|
44980
45688
|
if (qn != null) {
|
|
45689
|
+
const nested = STRATEGY_NESTED_CONSTS[qn];
|
|
45690
|
+
if (nested !== undefined)
|
|
45691
|
+
return JSON.stringify(nested);
|
|
45692
|
+
const nestedCall = STRATEGY_NESTED_CALLS[qn];
|
|
45693
|
+
if (nestedCall != null) {
|
|
45694
|
+
state.ctx.usesStrategy = true;
|
|
45695
|
+
return `__h.strategy.${nestedCall}()`;
|
|
45696
|
+
}
|
|
45697
|
+
if (qn.startsWith("strategy.") && qn.split(".").length > 2)
|
|
45698
|
+
return "null";
|
|
44981
45699
|
const dot = qn.indexOf(".");
|
|
44982
45700
|
const root = dot < 0 ? qn : qn.slice(0, dot);
|
|
44983
45701
|
if (ATTR_CONST_NS.has(root)) {
|
|
@@ -45737,6 +46455,9 @@ var compileArray = {
|
|
|
45737
46455
|
new(size, initial) {
|
|
45738
46456
|
return new PineArray(n2(size, 0), store(initial));
|
|
45739
46457
|
},
|
|
46458
|
+
from(values) {
|
|
46459
|
+
return wrapCells(Array.isArray(values) ? values : []) ?? new PineArray;
|
|
46460
|
+
},
|
|
45740
46461
|
get(id, index) {
|
|
45741
46462
|
return asArray(id)?.get(n2(index, 0)) ?? null;
|
|
45742
46463
|
},
|
|
@@ -46177,26 +46898,114 @@ function n3(v, fallback = 0) {
|
|
|
46177
46898
|
function idOf(v) {
|
|
46178
46899
|
return n3(v, -1);
|
|
46179
46900
|
}
|
|
46901
|
+
function idNum(v) {
|
|
46902
|
+
if (typeof v === "boolean")
|
|
46903
|
+
return v ? 1 : 0;
|
|
46904
|
+
if (typeof v === "number" && Number.isFinite(v))
|
|
46905
|
+
return Math.trunc(v);
|
|
46906
|
+
return null;
|
|
46907
|
+
}
|
|
46908
|
+
function putNum(extra, key, v) {
|
|
46909
|
+
const x = naNum(v);
|
|
46910
|
+
if (x != null)
|
|
46911
|
+
extra[key] = x;
|
|
46912
|
+
}
|
|
46913
|
+
function pointsOf(v) {
|
|
46914
|
+
if (v instanceof PineArray)
|
|
46915
|
+
return v.toValues().filter((p) => p != null);
|
|
46916
|
+
if (Array.isArray(v))
|
|
46917
|
+
return v.filter((p) => p != null);
|
|
46918
|
+
return [];
|
|
46919
|
+
}
|
|
46920
|
+
function isPoint(v) {
|
|
46921
|
+
return typeof v === "object" && v !== null && v.__chartPoint === true;
|
|
46922
|
+
}
|
|
46923
|
+
function makePoint(index, time, price) {
|
|
46924
|
+
return { __chartPoint: true, index, time, x: index ?? time, y: price, price };
|
|
46925
|
+
}
|
|
46926
|
+
function pointXY(v) {
|
|
46927
|
+
if (!isPoint(v))
|
|
46928
|
+
return null;
|
|
46929
|
+
return { x: v.index ?? v.time ?? v.x ?? 0, y: v.price ?? v.y ?? 0 };
|
|
46930
|
+
}
|
|
46931
|
+
function truthy(v) {
|
|
46932
|
+
if (typeof v === "boolean")
|
|
46933
|
+
return v;
|
|
46934
|
+
if (typeof v === "number")
|
|
46935
|
+
return Number.isFinite(v) && v !== 0;
|
|
46936
|
+
return false;
|
|
46937
|
+
}
|
|
46938
|
+
function alertText(v, fallback) {
|
|
46939
|
+
if (v == null)
|
|
46940
|
+
return fallback;
|
|
46941
|
+
if (typeof v === "string")
|
|
46942
|
+
return v;
|
|
46943
|
+
if (typeof v === "boolean")
|
|
46944
|
+
return v ? "1" : "0";
|
|
46945
|
+
if (typeof v === "number")
|
|
46946
|
+
return Number.isFinite(v) ? String(v) : fallback;
|
|
46947
|
+
return fallback;
|
|
46948
|
+
}
|
|
46949
|
+
var DRAW_KINDS2 = new Set(["line", "label", "box", "table", "polyline", "linefill"]);
|
|
46180
46950
|
|
|
46181
46951
|
class CompileDraw {
|
|
46182
46952
|
book = new DrawingBook;
|
|
46183
|
-
|
|
46184
|
-
|
|
46953
|
+
alertKeys = new Map;
|
|
46954
|
+
label_new(bar, text, x, y) {
|
|
46955
|
+
const extra = {};
|
|
46956
|
+
putNum(extra, "x", x);
|
|
46957
|
+
putNum(extra, "y", y);
|
|
46958
|
+
const t = text == null ? "" : String(text);
|
|
46959
|
+
return this.book.labelNew(n3(bar, 0), t, Object.keys(extra).length ? extra : undefined);
|
|
46185
46960
|
}
|
|
46186
|
-
line_new(bar) {
|
|
46187
|
-
|
|
46961
|
+
line_new(bar, x1, y1, x2, y2) {
|
|
46962
|
+
const extra = {};
|
|
46963
|
+
putNum(extra, "x1", x1);
|
|
46964
|
+
putNum(extra, "y1", y1);
|
|
46965
|
+
putNum(extra, "x2", x2);
|
|
46966
|
+
putNum(extra, "y2", y2);
|
|
46967
|
+
return this.book.lineNew(n3(bar, 0), Object.keys(extra).length ? extra : undefined);
|
|
46188
46968
|
}
|
|
46189
|
-
box_new(bar) {
|
|
46190
|
-
|
|
46969
|
+
box_new(bar, left, top, right, bottom) {
|
|
46970
|
+
const extra = {};
|
|
46971
|
+
putNum(extra, "left", left);
|
|
46972
|
+
putNum(extra, "top", top);
|
|
46973
|
+
putNum(extra, "right", right);
|
|
46974
|
+
putNum(extra, "bottom", bottom);
|
|
46975
|
+
return this.book.boxNew(n3(bar, 0), Object.keys(extra).length ? extra : undefined);
|
|
46191
46976
|
}
|
|
46192
46977
|
table_new(bar) {
|
|
46193
46978
|
return this.book.tableNew(n3(bar, 0));
|
|
46194
46979
|
}
|
|
46195
|
-
polyline_new(bar) {
|
|
46196
|
-
|
|
46980
|
+
polyline_new(bar, points) {
|
|
46981
|
+
const pts = pointsOf(points);
|
|
46982
|
+
return this.book.polylineNew(n3(bar, 0), pts.length ? { points: pts } : undefined);
|
|
46197
46983
|
}
|
|
46198
|
-
linefill_new(bar,
|
|
46199
|
-
|
|
46984
|
+
linefill_new(bar, id1, id2, color) {
|
|
46985
|
+
const extra = {};
|
|
46986
|
+
const a = idNum(id1);
|
|
46987
|
+
const b = idNum(id2);
|
|
46988
|
+
if (a != null)
|
|
46989
|
+
extra.id1 = a;
|
|
46990
|
+
if (b != null)
|
|
46991
|
+
extra.id2 = b;
|
|
46992
|
+
if (color != null)
|
|
46993
|
+
extra.color = color;
|
|
46994
|
+
return this.book.linefillNew(n3(bar, 0), Object.keys(extra).length ? extra : undefined);
|
|
46995
|
+
}
|
|
46996
|
+
all(kind) {
|
|
46997
|
+
const arr = new PineArray;
|
|
46998
|
+
if (typeof kind === "string" && DRAW_KINDS2.has(kind)) {
|
|
46999
|
+
for (const id of this.book.allIds(kind))
|
|
47000
|
+
arr.push(id);
|
|
47001
|
+
}
|
|
47002
|
+
return arr;
|
|
47003
|
+
}
|
|
47004
|
+
copy(id) {
|
|
47005
|
+
const i = idNum(id);
|
|
47006
|
+
if (i == null)
|
|
47007
|
+
return null;
|
|
47008
|
+
return this.book.copy(i);
|
|
46200
47009
|
}
|
|
46201
47010
|
label_set_text(id, text) {
|
|
46202
47011
|
this.book.labelSetText(idOf(id), text == null ? "" : String(text));
|
|
@@ -46250,13 +47059,38 @@ class CompileDraw {
|
|
|
46250
47059
|
this.book.labelSetTooltip(idOf(id), tooltip);
|
|
46251
47060
|
}
|
|
46252
47061
|
label_get_x(id) {
|
|
46253
|
-
|
|
47062
|
+
const i = idNum(id);
|
|
47063
|
+
if (i == null)
|
|
47064
|
+
return 0;
|
|
47065
|
+
return this.book.labelGetX(i) ?? 0;
|
|
46254
47066
|
}
|
|
46255
47067
|
label_get_y(id) {
|
|
46256
|
-
|
|
47068
|
+
const i = idNum(id);
|
|
47069
|
+
if (i == null)
|
|
47070
|
+
return 0;
|
|
47071
|
+
return this.book.labelGetY(i) ?? 0;
|
|
46257
47072
|
}
|
|
46258
47073
|
label_get_text(id) {
|
|
46259
|
-
|
|
47074
|
+
const i = idNum(id);
|
|
47075
|
+
if (i == null)
|
|
47076
|
+
return "";
|
|
47077
|
+
return this.book.labelGetText(i) ?? "";
|
|
47078
|
+
}
|
|
47079
|
+
line_get_x1(id) {
|
|
47080
|
+
const i = idNum(id);
|
|
47081
|
+
return i == null ? null : this.book.lineGetX1(i);
|
|
47082
|
+
}
|
|
47083
|
+
line_get_y1(id) {
|
|
47084
|
+
const i = idNum(id);
|
|
47085
|
+
return i == null ? null : this.book.lineGetY1(i);
|
|
47086
|
+
}
|
|
47087
|
+
line_get_x2(id) {
|
|
47088
|
+
const i = idNum(id);
|
|
47089
|
+
return i == null ? null : this.book.lineGetX2(i);
|
|
47090
|
+
}
|
|
47091
|
+
line_get_y2(id) {
|
|
47092
|
+
const i = idNum(id);
|
|
47093
|
+
return i == null ? null : this.book.lineGetY2(i);
|
|
46260
47094
|
}
|
|
46261
47095
|
box_delete(id) {
|
|
46262
47096
|
this.book.boxDelete(idOf(id));
|
|
@@ -46282,8 +47116,18 @@ class CompileDraw {
|
|
|
46282
47116
|
table_cell(id, column, row, text) {
|
|
46283
47117
|
this.book.tableCell(idOf(id), column, row, text);
|
|
46284
47118
|
}
|
|
46285
|
-
table_cell_set_text(id,
|
|
46286
|
-
|
|
47119
|
+
table_cell_set_text(id, row, column, text) {
|
|
47120
|
+
const i = idNum(id);
|
|
47121
|
+
if (i == null)
|
|
47122
|
+
return null;
|
|
47123
|
+
this.book.tableCellSetText(i, column, row, text == null ? "" : String(text));
|
|
47124
|
+
return null;
|
|
47125
|
+
}
|
|
47126
|
+
table_cell_get_text(id, row, column) {
|
|
47127
|
+
const i = idNum(id);
|
|
47128
|
+
if (i == null)
|
|
47129
|
+
return "";
|
|
47130
|
+
return this.book.tableCellGetText(i, column, row) ?? "";
|
|
46287
47131
|
}
|
|
46288
47132
|
table_set_position(id, position) {
|
|
46289
47133
|
this.book.tableSetPosition(idOf(id), position);
|
|
@@ -46294,6 +47138,361 @@ class CompileDraw {
|
|
|
46294
47138
|
alert(bar, message) {
|
|
46295
47139
|
this.book.alert(n3(bar, 0), message == null ? "" : String(message));
|
|
46296
47140
|
}
|
|
47141
|
+
alertcondition(bar, condition, title, message) {
|
|
47142
|
+
if (!truthy(condition))
|
|
47143
|
+
return null;
|
|
47144
|
+
const t = alertText(title, "Alert");
|
|
47145
|
+
const m = alertText(message, "Alert");
|
|
47146
|
+
const b = n3(bar, 0);
|
|
47147
|
+
const key = `alertcondition|${t}|${m}|once_per_bar`;
|
|
47148
|
+
if (this.alertKeys.get(key) === b)
|
|
47149
|
+
return null;
|
|
47150
|
+
this.alertKeys.set(key, b);
|
|
47151
|
+
this.book.alert(b, m);
|
|
47152
|
+
const ev = this.book.items[this.book.items.length - 1];
|
|
47153
|
+
if (ev != null)
|
|
47154
|
+
ev.extra = { source: "alertcondition", title: t, freq: "once_per_bar" };
|
|
47155
|
+
return null;
|
|
47156
|
+
}
|
|
47157
|
+
line_set_x1(id, x) {
|
|
47158
|
+
return this.kindNum("lineSetX1", id, x);
|
|
47159
|
+
}
|
|
47160
|
+
line_set_y1(id, y) {
|
|
47161
|
+
return this.kindNum("lineSetY1", id, y);
|
|
47162
|
+
}
|
|
47163
|
+
line_set_x2(id, x) {
|
|
47164
|
+
return this.kindNum("lineSetX2", id, x);
|
|
47165
|
+
}
|
|
47166
|
+
line_set_y2(id, y) {
|
|
47167
|
+
return this.kindNum("lineSetY2", id, y);
|
|
47168
|
+
}
|
|
47169
|
+
line_set_xloc(id, xloc) {
|
|
47170
|
+
return this.kindAny("lineSetXloc", id, xloc);
|
|
47171
|
+
}
|
|
47172
|
+
line_set_first_point(id, point) {
|
|
47173
|
+
const i = idNum(id);
|
|
47174
|
+
const xy = pointXY(point);
|
|
47175
|
+
if (i != null && xy)
|
|
47176
|
+
this.book.lineSetXy1(i, xy.x, xy.y);
|
|
47177
|
+
return null;
|
|
47178
|
+
}
|
|
47179
|
+
line_set_second_point(id, point) {
|
|
47180
|
+
const i = idNum(id);
|
|
47181
|
+
const xy = pointXY(point);
|
|
47182
|
+
if (i != null && xy)
|
|
47183
|
+
this.book.lineSetXy2(i, xy.x, xy.y);
|
|
47184
|
+
return null;
|
|
47185
|
+
}
|
|
47186
|
+
label_set_x(id, x) {
|
|
47187
|
+
return this.kindAny("labelSetX", id, x);
|
|
47188
|
+
}
|
|
47189
|
+
label_set_y(id, y) {
|
|
47190
|
+
return this.kindAny("labelSetY", id, y);
|
|
47191
|
+
}
|
|
47192
|
+
label_set_textcolor(id, color) {
|
|
47193
|
+
return this.kindAny("labelSetTextcolor", id, color);
|
|
47194
|
+
}
|
|
47195
|
+
label_set_text_font_family(id, font) {
|
|
47196
|
+
return this.kindAny("labelSetTextFontFamily", id, font);
|
|
47197
|
+
}
|
|
47198
|
+
label_set_text_halign(id, halign) {
|
|
47199
|
+
return this.kindAny("labelSetTextHalign", id, halign);
|
|
47200
|
+
}
|
|
47201
|
+
label_set_text_valign(id, valign) {
|
|
47202
|
+
return this.kindAny("labelSetTextValign", id, valign);
|
|
47203
|
+
}
|
|
47204
|
+
label_set_text_size(id, size) {
|
|
47205
|
+
return this.kindAny("labelSetTextSize", id, size);
|
|
47206
|
+
}
|
|
47207
|
+
label_set_text_formatting(id, formatting) {
|
|
47208
|
+
return this.kindAny("labelSetTextFormatting", id, formatting);
|
|
47209
|
+
}
|
|
47210
|
+
label_set_border_color(id, color) {
|
|
47211
|
+
return this.kindAny("labelSetBorderColor", id, color);
|
|
47212
|
+
}
|
|
47213
|
+
label_set_border_width(id, width) {
|
|
47214
|
+
return this.kindAny("labelSetBorderWidth", id, width);
|
|
47215
|
+
}
|
|
47216
|
+
label_set_border_style(id, style) {
|
|
47217
|
+
return this.kindAny("labelSetBorderStyle", id, style);
|
|
47218
|
+
}
|
|
47219
|
+
label_set_xloc(id, xloc) {
|
|
47220
|
+
return this.kindAny("labelSetXloc", id, xloc);
|
|
47221
|
+
}
|
|
47222
|
+
label_set_yloc(id, yloc) {
|
|
47223
|
+
return this.kindAny("labelSetYloc", id, yloc);
|
|
47224
|
+
}
|
|
47225
|
+
label_set_point(id, point) {
|
|
47226
|
+
const i = idNum(id);
|
|
47227
|
+
const xy = pointXY(point);
|
|
47228
|
+
if (i != null && xy)
|
|
47229
|
+
this.book.labelSetXy(i, xy.x, xy.y);
|
|
47230
|
+
return null;
|
|
47231
|
+
}
|
|
47232
|
+
box_get_left(id) {
|
|
47233
|
+
return this.boxGet("boxGetLeft", id);
|
|
47234
|
+
}
|
|
47235
|
+
box_get_right(id) {
|
|
47236
|
+
return this.boxGet("boxGetRight", id);
|
|
47237
|
+
}
|
|
47238
|
+
box_get_top(id) {
|
|
47239
|
+
return this.boxGet("boxGetTop", id);
|
|
47240
|
+
}
|
|
47241
|
+
box_get_bottom(id) {
|
|
47242
|
+
return this.boxGet("boxGetBottom", id);
|
|
47243
|
+
}
|
|
47244
|
+
box_set_left(id, left) {
|
|
47245
|
+
return this.kindAny("boxSetLeft", id, left);
|
|
47246
|
+
}
|
|
47247
|
+
box_set_right(id, right) {
|
|
47248
|
+
return this.kindAny("boxSetRight", id, right);
|
|
47249
|
+
}
|
|
47250
|
+
box_set_top(id, top) {
|
|
47251
|
+
return this.kindAny("boxSetTop", id, top);
|
|
47252
|
+
}
|
|
47253
|
+
box_set_bottom(id, bottom) {
|
|
47254
|
+
return this.kindAny("boxSetBottom", id, bottom);
|
|
47255
|
+
}
|
|
47256
|
+
box_set_border_width(id, width) {
|
|
47257
|
+
return this.kindAny("boxSetBorderWidth", id, width);
|
|
47258
|
+
}
|
|
47259
|
+
box_set_border_style(id, style) {
|
|
47260
|
+
return this.kindAny("boxSetBorderStyle", id, style);
|
|
47261
|
+
}
|
|
47262
|
+
box_set_closed(id, closed) {
|
|
47263
|
+
return this.kindAny("boxSetClosed", id, closed);
|
|
47264
|
+
}
|
|
47265
|
+
box_set_rightbottom(id, right, bottom) {
|
|
47266
|
+
const i = idNum(id);
|
|
47267
|
+
if (i != null)
|
|
47268
|
+
this.book.boxSetRightBottom(i, right, bottom);
|
|
47269
|
+
return null;
|
|
47270
|
+
}
|
|
47271
|
+
box_set_text_color(id, color) {
|
|
47272
|
+
return this.kindAny("boxSetTextColor", id, color);
|
|
47273
|
+
}
|
|
47274
|
+
box_set_text_font_family(id, font) {
|
|
47275
|
+
return this.kindAny("boxSetTextFontFamily", id, font);
|
|
47276
|
+
}
|
|
47277
|
+
box_set_text_halign(id, halign) {
|
|
47278
|
+
return this.kindAny("boxSetTextHalign", id, halign);
|
|
47279
|
+
}
|
|
47280
|
+
box_set_text_valign(id, valign) {
|
|
47281
|
+
return this.kindAny("boxSetTextValign", id, valign);
|
|
47282
|
+
}
|
|
47283
|
+
box_set_text_size(id, size) {
|
|
47284
|
+
return this.kindAny("boxSetTextSize", id, size);
|
|
47285
|
+
}
|
|
47286
|
+
box_set_text_formatting(id, formatting) {
|
|
47287
|
+
return this.kindAny("boxSetTextFormatting", id, formatting);
|
|
47288
|
+
}
|
|
47289
|
+
box_set_text_wrap(id, wrap) {
|
|
47290
|
+
return this.kindAny("boxSetTextWrap", id, wrap);
|
|
47291
|
+
}
|
|
47292
|
+
box_set_xloc(id, left, right, xloc) {
|
|
47293
|
+
const i = idNum(id);
|
|
47294
|
+
if (i == null)
|
|
47295
|
+
return null;
|
|
47296
|
+
this.book.boxSetLeft(i, left);
|
|
47297
|
+
this.book.boxSetRight(i, right);
|
|
47298
|
+
this.book.boxSetXloc(i, xloc);
|
|
47299
|
+
return null;
|
|
47300
|
+
}
|
|
47301
|
+
box_set_top_left_point(id, point) {
|
|
47302
|
+
const i = idNum(id);
|
|
47303
|
+
const xy = pointXY(point);
|
|
47304
|
+
if (i != null && xy)
|
|
47305
|
+
this.book.boxSetLeftTop(i, xy.x, xy.y);
|
|
47306
|
+
return null;
|
|
47307
|
+
}
|
|
47308
|
+
box_set_bottom_right_point(id, point) {
|
|
47309
|
+
const i = idNum(id);
|
|
47310
|
+
const xy = pointXY(point);
|
|
47311
|
+
if (i != null && xy)
|
|
47312
|
+
this.book.boxSetRightBottom(i, xy.x, xy.y);
|
|
47313
|
+
return null;
|
|
47314
|
+
}
|
|
47315
|
+
table_delete(id) {
|
|
47316
|
+
const i = idNum(id);
|
|
47317
|
+
if (i != null)
|
|
47318
|
+
this.book.tableDelete(i);
|
|
47319
|
+
return null;
|
|
47320
|
+
}
|
|
47321
|
+
table_set_bgcolor(id, color) {
|
|
47322
|
+
return this.kindAny("tableSetBgcolor", id, color);
|
|
47323
|
+
}
|
|
47324
|
+
table_set_border_color(id, color) {
|
|
47325
|
+
return this.kindAny("tableSetBorderColor", id, color);
|
|
47326
|
+
}
|
|
47327
|
+
table_set_border_width(id, width) {
|
|
47328
|
+
return this.kindAny("tableSetBorderWidth", id, width);
|
|
47329
|
+
}
|
|
47330
|
+
table_set_frame_color(id, color) {
|
|
47331
|
+
return this.kindAny("tableSetFrameColor", id, color);
|
|
47332
|
+
}
|
|
47333
|
+
table_set_frame_width(id, width) {
|
|
47334
|
+
return this.kindAny("tableSetFrameWidth", id, width);
|
|
47335
|
+
}
|
|
47336
|
+
table_clear(id, startRow, startCol, endRow, endCol) {
|
|
47337
|
+
const i = idNum(id);
|
|
47338
|
+
if (i == null)
|
|
47339
|
+
return null;
|
|
47340
|
+
if (arguments.length < 2)
|
|
47341
|
+
this.book.tableClear(i);
|
|
47342
|
+
else
|
|
47343
|
+
this.book.tableClear(i, startRow, startCol, endRow, endCol);
|
|
47344
|
+
return null;
|
|
47345
|
+
}
|
|
47346
|
+
table_merge_cells(id, startRow, startCol, endRow, endCol) {
|
|
47347
|
+
const i = idNum(id);
|
|
47348
|
+
if (i != null)
|
|
47349
|
+
this.book.tableMergeCells(i, startRow, startCol, endRow, endCol);
|
|
47350
|
+
return null;
|
|
47351
|
+
}
|
|
47352
|
+
table_cell_set_text_color(id, row, column, value) {
|
|
47353
|
+
return this.cellField(id, column, row, "text_color", value);
|
|
47354
|
+
}
|
|
47355
|
+
table_cell_set_bgcolor(id, row, column, value) {
|
|
47356
|
+
return this.cellField(id, column, row, "bgcolor", value);
|
|
47357
|
+
}
|
|
47358
|
+
table_cell_set_border_color(id, row, column, value) {
|
|
47359
|
+
return this.cellField(id, column, row, "border_color", value);
|
|
47360
|
+
}
|
|
47361
|
+
table_cell_set_border_width(id, row, column, value) {
|
|
47362
|
+
return this.cellField(id, column, row, "border_width", value);
|
|
47363
|
+
}
|
|
47364
|
+
table_cell_set_tooltip(id, row, column, value) {
|
|
47365
|
+
return this.cellField(id, column, row, "tooltip", value);
|
|
47366
|
+
}
|
|
47367
|
+
table_cell_set_width(id, column, row, value) {
|
|
47368
|
+
return this.cellField(id, column, row, "width", value);
|
|
47369
|
+
}
|
|
47370
|
+
table_cell_set_height(id, column, row, value) {
|
|
47371
|
+
return this.cellField(id, column, row, "height", value);
|
|
47372
|
+
}
|
|
47373
|
+
table_cell_set_text_halign(id, column, row, value) {
|
|
47374
|
+
return this.cellField(id, column, row, "text_halign", value);
|
|
47375
|
+
}
|
|
47376
|
+
table_cell_set_text_valign(id, column, row, value) {
|
|
47377
|
+
return this.cellField(id, column, row, "text_valign", value);
|
|
47378
|
+
}
|
|
47379
|
+
table_cell_set_text_size(id, column, row, value) {
|
|
47380
|
+
return this.cellField(id, column, row, "text_size", value);
|
|
47381
|
+
}
|
|
47382
|
+
table_cell_set_text_font_family(id, column, row, value) {
|
|
47383
|
+
return this.cellField(id, column, row, "text_font_family", value);
|
|
47384
|
+
}
|
|
47385
|
+
table_cell_set_text_formatting(id, column, row, value) {
|
|
47386
|
+
return this.cellField(id, column, row, "text_formatting", value);
|
|
47387
|
+
}
|
|
47388
|
+
polyline_delete(id) {
|
|
47389
|
+
const i = idNum(id);
|
|
47390
|
+
if (i != null)
|
|
47391
|
+
this.book.polylineDelete(i);
|
|
47392
|
+
return null;
|
|
47393
|
+
}
|
|
47394
|
+
polyline_get_points(id) {
|
|
47395
|
+
const arr = new PineArray;
|
|
47396
|
+
const i = idNum(id);
|
|
47397
|
+
if (i == null)
|
|
47398
|
+
return arr;
|
|
47399
|
+
for (const p of this.book.polylineGetPoints(i))
|
|
47400
|
+
arr.push(p);
|
|
47401
|
+
return arr;
|
|
47402
|
+
}
|
|
47403
|
+
polyline_set_points(id, points) {
|
|
47404
|
+
const i = idNum(id);
|
|
47405
|
+
if (i != null)
|
|
47406
|
+
this.book.polylineSetPoints(i, pointsOf(points));
|
|
47407
|
+
return null;
|
|
47408
|
+
}
|
|
47409
|
+
polyline_set_line_color(id, color) {
|
|
47410
|
+
return this.kindAny("polylineSetLineColor", id, color);
|
|
47411
|
+
}
|
|
47412
|
+
polyline_set_line_width(id, width) {
|
|
47413
|
+
return this.kindAny("polylineSetLineWidth", id, width);
|
|
47414
|
+
}
|
|
47415
|
+
polyline_set_line_style(id, style) {
|
|
47416
|
+
return this.kindAny("polylineSetLineStyle", id, style);
|
|
47417
|
+
}
|
|
47418
|
+
polyline_set_fill_color(id, color) {
|
|
47419
|
+
return this.kindAny("polylineSetFillColor", id, color);
|
|
47420
|
+
}
|
|
47421
|
+
polyline_set_curved(id, curved) {
|
|
47422
|
+
return this.kindAny("polylineSetCurved", id, curved);
|
|
47423
|
+
}
|
|
47424
|
+
polyline_set_force_overlay(id, force) {
|
|
47425
|
+
return this.kindAny("polylineSetForceOverlay", id, force);
|
|
47426
|
+
}
|
|
47427
|
+
polyline_set_closed(id, closed) {
|
|
47428
|
+
return this.kindAny("polylineSetClosed", id, closed);
|
|
47429
|
+
}
|
|
47430
|
+
polyline_set_xloc(id, xloc) {
|
|
47431
|
+
return this.kindAny("polylineSetXloc", id, xloc);
|
|
47432
|
+
}
|
|
47433
|
+
linefill_delete(id) {
|
|
47434
|
+
const i = idNum(id);
|
|
47435
|
+
if (i != null)
|
|
47436
|
+
this.book.linefillDelete(i);
|
|
47437
|
+
return null;
|
|
47438
|
+
}
|
|
47439
|
+
linefill_get_line1(id) {
|
|
47440
|
+
const i = idNum(id);
|
|
47441
|
+
return i == null ? null : this.book.linefillGetLine1(i);
|
|
47442
|
+
}
|
|
47443
|
+
linefill_get_line2(id) {
|
|
47444
|
+
const i = idNum(id);
|
|
47445
|
+
return i == null ? null : this.book.linefillGetLine2(i);
|
|
47446
|
+
}
|
|
47447
|
+
point_new(time, price) {
|
|
47448
|
+
const p = naNum(price);
|
|
47449
|
+
if (p == null)
|
|
47450
|
+
return null;
|
|
47451
|
+
return makePoint(null, naNum(time), p);
|
|
47452
|
+
}
|
|
47453
|
+
point_from_index(index, price) {
|
|
47454
|
+
const ix = naNum(index);
|
|
47455
|
+
const p = naNum(price);
|
|
47456
|
+
if (ix == null || p == null)
|
|
47457
|
+
return null;
|
|
47458
|
+
return makePoint(Math.trunc(ix), null, p);
|
|
47459
|
+
}
|
|
47460
|
+
point_now(bar, time, price) {
|
|
47461
|
+
const p = naNum(price);
|
|
47462
|
+
if (p == null)
|
|
47463
|
+
return null;
|
|
47464
|
+
const ix = naNum(bar);
|
|
47465
|
+
return makePoint(ix == null ? null : Math.trunc(ix), naNum(time), p);
|
|
47466
|
+
}
|
|
47467
|
+
point_copy(raw) {
|
|
47468
|
+
if (isPoint(raw))
|
|
47469
|
+
return makePoint(raw.index, raw.time, raw.price);
|
|
47470
|
+
return makePoint(null, null, 0);
|
|
47471
|
+
}
|
|
47472
|
+
kindNum(method, id, value) {
|
|
47473
|
+
const i = idNum(id);
|
|
47474
|
+
if (i != null)
|
|
47475
|
+
this.book[method](i, value);
|
|
47476
|
+
return null;
|
|
47477
|
+
}
|
|
47478
|
+
kindAny(method, id, value) {
|
|
47479
|
+
const i = idNum(id);
|
|
47480
|
+
if (i != null)
|
|
47481
|
+
this.book[method](i, value);
|
|
47482
|
+
return null;
|
|
47483
|
+
}
|
|
47484
|
+
boxGet(method, id) {
|
|
47485
|
+
const i = idNum(id);
|
|
47486
|
+
if (i == null)
|
|
47487
|
+
return 0;
|
|
47488
|
+
return this.book[method](i) ?? 0;
|
|
47489
|
+
}
|
|
47490
|
+
cellField(id, column, row, field, value) {
|
|
47491
|
+
const i = idNum(id);
|
|
47492
|
+
if (i != null)
|
|
47493
|
+
this.book.tableCellSetField(i, column, row, field, value);
|
|
47494
|
+
return null;
|
|
47495
|
+
}
|
|
46297
47496
|
extras() {
|
|
46298
47497
|
return { __drawings: this.book.items.slice() };
|
|
46299
47498
|
}
|
|
@@ -46388,11 +47587,14 @@ class CompileStrategy {
|
|
|
46388
47587
|
const ms = optNum(rec.margin_short);
|
|
46389
47588
|
if (ms != null)
|
|
46390
47589
|
broker.margin_short = ms;
|
|
46391
|
-
if (typeof rec.default_qty_type === "string")
|
|
47590
|
+
if (typeof rec.default_qty_type === "string" || isStrategyCashAmount(rec.default_qty_type)) {
|
|
46392
47591
|
broker.default_qty_type = rec.default_qty_type;
|
|
47592
|
+
}
|
|
46393
47593
|
const dqv = optNum(rec.default_qty_value);
|
|
46394
47594
|
if (dqv != null)
|
|
46395
47595
|
broker.default_qty_value = dqv;
|
|
47596
|
+
if (typeof rec.currency === "string" && rec.currency !== "")
|
|
47597
|
+
broker.currency = rec.currency;
|
|
46396
47598
|
if (Object.keys(broker).length)
|
|
46397
47599
|
this.book.configure(broker);
|
|
46398
47600
|
const capital = optNum(rec.initial_capital);
|
|
@@ -46487,6 +47689,192 @@ class CompileStrategy {
|
|
|
46487
47689
|
initial_capital() {
|
|
46488
47690
|
return this.book.initialCapital;
|
|
46489
47691
|
}
|
|
47692
|
+
cash() {
|
|
47693
|
+
return strategyCashAmount(this.book.cash(this.mark));
|
|
47694
|
+
}
|
|
47695
|
+
position_entry_name() {
|
|
47696
|
+
return this.book.position_entry_name;
|
|
47697
|
+
}
|
|
47698
|
+
account_currency() {
|
|
47699
|
+
return this.book.account_currency;
|
|
47700
|
+
}
|
|
47701
|
+
default_entry_qty(percent) {
|
|
47702
|
+
const pct = arguments.length === 0 || percent === undefined ? 100 : naNum(percent);
|
|
47703
|
+
if (pct == null)
|
|
47704
|
+
return null;
|
|
47705
|
+
return this.book.initialCapital * (pct / 100) / 100;
|
|
47706
|
+
}
|
|
47707
|
+
convert_to(value) {
|
|
47708
|
+
if (arguments.length === 0 || value === undefined)
|
|
47709
|
+
return 1;
|
|
47710
|
+
return naNum(value);
|
|
47711
|
+
}
|
|
47712
|
+
max_contracts_held_all() {
|
|
47713
|
+
return this.book.maxContractsHeldAll();
|
|
47714
|
+
}
|
|
47715
|
+
max_contracts_held_long() {
|
|
47716
|
+
return this.book.maxContractsHeldLong();
|
|
47717
|
+
}
|
|
47718
|
+
max_contracts_held_short() {
|
|
47719
|
+
return this.book.maxContractsHeldShort();
|
|
47720
|
+
}
|
|
47721
|
+
capital_held() {
|
|
47722
|
+
return this.book.capitalHeld();
|
|
47723
|
+
}
|
|
47724
|
+
closedtrades_first_index() {
|
|
47725
|
+
return this.book.closedtrades_first_index;
|
|
47726
|
+
}
|
|
47727
|
+
wintrades() {
|
|
47728
|
+
return this.book.wintrades;
|
|
47729
|
+
}
|
|
47730
|
+
losstrades() {
|
|
47731
|
+
return this.book.losstrades;
|
|
47732
|
+
}
|
|
47733
|
+
eventrades() {
|
|
47734
|
+
return this.book.eventrades;
|
|
47735
|
+
}
|
|
47736
|
+
grossprofit() {
|
|
47737
|
+
return this.book.grossprofit;
|
|
47738
|
+
}
|
|
47739
|
+
grossloss() {
|
|
47740
|
+
return this.book.grossloss;
|
|
47741
|
+
}
|
|
47742
|
+
avg_trade() {
|
|
47743
|
+
return this.book.avgTrade();
|
|
47744
|
+
}
|
|
47745
|
+
avg_winning_trade() {
|
|
47746
|
+
return this.book.avgWinningTrade();
|
|
47747
|
+
}
|
|
47748
|
+
avg_losing_trade() {
|
|
47749
|
+
return this.book.avgLosingTrade();
|
|
47750
|
+
}
|
|
47751
|
+
netprofit_percent() {
|
|
47752
|
+
return this.book.netprofitPercent(this.mark);
|
|
47753
|
+
}
|
|
47754
|
+
openprofit_percent() {
|
|
47755
|
+
return this.book.openprofitPercent(this.mark);
|
|
47756
|
+
}
|
|
47757
|
+
grossprofit_percent() {
|
|
47758
|
+
return this.book.grossprofitPercent();
|
|
47759
|
+
}
|
|
47760
|
+
grossloss_percent() {
|
|
47761
|
+
return this.book.grosslossPercent();
|
|
47762
|
+
}
|
|
47763
|
+
avg_trade_percent() {
|
|
47764
|
+
return this.book.avgTradePercent();
|
|
47765
|
+
}
|
|
47766
|
+
avg_winning_trade_percent() {
|
|
47767
|
+
return this.book.avgWinningTradePercent();
|
|
47768
|
+
}
|
|
47769
|
+
avg_losing_trade_percent() {
|
|
47770
|
+
return this.book.avgLosingTradePercent();
|
|
47771
|
+
}
|
|
47772
|
+
max_drawdown() {
|
|
47773
|
+
return this.book.maxDrawdown();
|
|
47774
|
+
}
|
|
47775
|
+
max_drawdown_percent() {
|
|
47776
|
+
return this.book.maxDrawdownPercent();
|
|
47777
|
+
}
|
|
47778
|
+
max_runup() {
|
|
47779
|
+
return this.book.maxRunup();
|
|
47780
|
+
}
|
|
47781
|
+
max_runup_percent() {
|
|
47782
|
+
return this.book.maxRunupPercent();
|
|
47783
|
+
}
|
|
47784
|
+
percent_profitable() {
|
|
47785
|
+
return this.book.percentProfitable();
|
|
47786
|
+
}
|
|
47787
|
+
winrate() {
|
|
47788
|
+
return this.book.percentProfitable();
|
|
47789
|
+
}
|
|
47790
|
+
profitfactor() {
|
|
47791
|
+
return this.book.profitFactor();
|
|
47792
|
+
}
|
|
47793
|
+
profit_factor() {
|
|
47794
|
+
return this.book.profitFactor();
|
|
47795
|
+
}
|
|
47796
|
+
closedtrades_entry_bar_index(i) {
|
|
47797
|
+
return this.book.closedEntryBar(this.idx(i)) ?? 0;
|
|
47798
|
+
}
|
|
47799
|
+
closedtrades_entry_price(i) {
|
|
47800
|
+
return this.book.closedEntryPrice(this.idx(i)) ?? 0;
|
|
47801
|
+
}
|
|
47802
|
+
closedtrades_exit_bar_index(i) {
|
|
47803
|
+
return this.book.closedExitBar(this.idx(i)) ?? 0;
|
|
47804
|
+
}
|
|
47805
|
+
closedtrades_exit_price(i) {
|
|
47806
|
+
return this.book.closedExitPrice(this.idx(i)) ?? 0;
|
|
47807
|
+
}
|
|
47808
|
+
closedtrades_profit(i) {
|
|
47809
|
+
return this.book.closedProfit(this.idx(i)) ?? 0;
|
|
47810
|
+
}
|
|
47811
|
+
closedtrades_size(i) {
|
|
47812
|
+
return this.book.closedSize(this.idx(i)) ?? 0;
|
|
47813
|
+
}
|
|
47814
|
+
closedtrades_entry_id(i) {
|
|
47815
|
+
return this.book.closedId(this.idx(i)) ?? "";
|
|
47816
|
+
}
|
|
47817
|
+
closedtrades_exit_id(i) {
|
|
47818
|
+
return this.book.closedId(this.idx(i)) ?? "";
|
|
47819
|
+
}
|
|
47820
|
+
closedtrades_commission(i) {
|
|
47821
|
+
return this.book.closedCommission(this.idx(i)) ?? 0;
|
|
47822
|
+
}
|
|
47823
|
+
closedtrades_entry_time(i) {
|
|
47824
|
+
return this.book.closedEntryTime(this.idx(i));
|
|
47825
|
+
}
|
|
47826
|
+
closedtrades_exit_time(i) {
|
|
47827
|
+
return this.book.closedExitTime(this.idx(i));
|
|
47828
|
+
}
|
|
47829
|
+
closedtrades_entry_comment(i) {
|
|
47830
|
+
return this.book.closedEntryComment(this.idx(i));
|
|
47831
|
+
}
|
|
47832
|
+
closedtrades_exit_comment(i) {
|
|
47833
|
+
return this.book.closedExitComment(this.idx(i));
|
|
47834
|
+
}
|
|
47835
|
+
closedtrades_max_drawdown(i) {
|
|
47836
|
+
return this.book.closedMaxDrawdown(this.idx(i));
|
|
47837
|
+
}
|
|
47838
|
+
closedtrades_max_runup(i) {
|
|
47839
|
+
return this.book.closedMaxRunup(this.idx(i));
|
|
47840
|
+
}
|
|
47841
|
+
opentrades_entry_bar_index(i) {
|
|
47842
|
+
return this.book.openEntryBar(this.idx(i)) ?? 0;
|
|
47843
|
+
}
|
|
47844
|
+
opentrades_entry_price(i) {
|
|
47845
|
+
return this.book.openEntryPrice(this.idx(i)) ?? 0;
|
|
47846
|
+
}
|
|
47847
|
+
opentrades_size(i) {
|
|
47848
|
+
return this.book.openSize(this.idx(i)) ?? 0;
|
|
47849
|
+
}
|
|
47850
|
+
opentrades_entry_id(i) {
|
|
47851
|
+
return this.book.openId(this.idx(i)) ?? "";
|
|
47852
|
+
}
|
|
47853
|
+
opentrades_profit(i) {
|
|
47854
|
+
return this.book.openProfit(this.idx(i), this.mark) ?? 0;
|
|
47855
|
+
}
|
|
47856
|
+
opentrades_entry_time(i) {
|
|
47857
|
+
return this.book.openEntryTime(this.idx(i));
|
|
47858
|
+
}
|
|
47859
|
+
opentrades_entry_comment(i) {
|
|
47860
|
+
return this.book.openEntryComment(this.idx(i));
|
|
47861
|
+
}
|
|
47862
|
+
opentrades_commission(i) {
|
|
47863
|
+
return this.book.openCommission(this.idx(i));
|
|
47864
|
+
}
|
|
47865
|
+
opentrades_max_drawdown(i) {
|
|
47866
|
+
return this.book.openMaxDrawdown(this.idx(i));
|
|
47867
|
+
}
|
|
47868
|
+
opentrades_max_runup(i) {
|
|
47869
|
+
return this.book.openMaxRunup(this.idx(i));
|
|
47870
|
+
}
|
|
47871
|
+
idx(i) {
|
|
47872
|
+
if (typeof i === "boolean")
|
|
47873
|
+
return i ? 1 : 0;
|
|
47874
|
+
if (typeof i === "number" && Number.isFinite(i))
|
|
47875
|
+
return Math.trunc(i);
|
|
47876
|
+
return 0;
|
|
47877
|
+
}
|
|
46490
47878
|
risk_allow_entry_in(value) {
|
|
46491
47879
|
this.book.riskAllowEntryIn(value);
|
|
46492
47880
|
}
|
|
@@ -46556,6 +47944,8 @@ function createCompileHelpers(opts) {
|
|
|
46556
47944
|
na: NA_FN,
|
|
46557
47945
|
nz,
|
|
46558
47946
|
naNum,
|
|
47947
|
+
plotNum,
|
|
47948
|
+
timenow,
|
|
46559
47949
|
isNa: isNaCell,
|
|
46560
47950
|
eq: pineEq,
|
|
46561
47951
|
ne: pineNe,
|
|
@@ -46705,6 +48095,19 @@ function iff(cond, thenV, elseV) {
|
|
|
46705
48095
|
return cond ? thenV : elseV;
|
|
46706
48096
|
return mathIff(cond, thenV, elseV);
|
|
46707
48097
|
}
|
|
48098
|
+
function plotNum(v) {
|
|
48099
|
+
if (isStrategyCashAmount(v))
|
|
48100
|
+
return Number.isFinite(v.value) ? v.value : null;
|
|
48101
|
+
return naNum(v);
|
|
48102
|
+
}
|
|
48103
|
+
function timenow(timeArr) {
|
|
48104
|
+
if (!Array.isArray(timeArr) || timeArr.length === 0)
|
|
48105
|
+
return 0;
|
|
48106
|
+
const last = timeArr[timeArr.length - 1];
|
|
48107
|
+
if (typeof last === "number" && Number.isFinite(last))
|
|
48108
|
+
return last;
|
|
48109
|
+
return (timeArr.length - 1) * 60000;
|
|
48110
|
+
}
|
|
46708
48111
|
function NA_FN(v) {
|
|
46709
48112
|
if (arguments.length === 0)
|
|
46710
48113
|
return null;
|
|
@@ -50030,6 +51433,97 @@ function evalExtraTa(fname, node, env, site) {
|
|
|
50030
51433
|
const z = env.ta.zigzag(site, srcArg(node, env), th);
|
|
50031
51434
|
return tupleOf([z.high, z.low, z.dir]);
|
|
50032
51435
|
}
|
|
51436
|
+
const wave10aArg = (index, names, message) => {
|
|
51437
|
+
const arg = callArg(node.args, index, names);
|
|
51438
|
+
if (arg == null)
|
|
51439
|
+
runtimeError(message);
|
|
51440
|
+
return arg;
|
|
51441
|
+
};
|
|
51442
|
+
if (fname === "ta.hammer" || fname === "hammer") {
|
|
51443
|
+
const msg = "ta.hammer() requires 4 arguments: open, high, low, close";
|
|
51444
|
+
return env.ta.hammer(unwrap2(evalExpr(wave10aArg(0, ["open"], msg), env)), unwrap2(evalExpr(wave10aArg(1, ["high"], msg), env)), unwrap2(evalExpr(wave10aArg(2, ["low"], msg), env)), unwrap2(evalExpr(wave10aArg(3, ["close"], msg), env)));
|
|
51445
|
+
}
|
|
51446
|
+
if (fname === "ta.engulfing" || fname === "engulfing") {
|
|
51447
|
+
const msg = "ta.engulfing() requires 4 arguments: open, high, low, close";
|
|
51448
|
+
unwrap2(evalExpr(wave10aArg(0, ["open"], msg), env));
|
|
51449
|
+
unwrap2(evalExpr(wave10aArg(1, ["high"], msg), env));
|
|
51450
|
+
unwrap2(evalExpr(wave10aArg(2, ["low"], msg), env));
|
|
51451
|
+
unwrap2(evalExpr(wave10aArg(3, ["close"], msg), env));
|
|
51452
|
+
return env.ta.engulfing();
|
|
51453
|
+
}
|
|
51454
|
+
if (fname === "ta.gap_detector" || fname === "gap_detector") {
|
|
51455
|
+
const msg = "ta.gap_detector() requires 3 arguments: high, low, prev_close";
|
|
51456
|
+
return env.ta.gapDetector(unwrap2(evalExpr(wave10aArg(0, ["high"], msg), env)), unwrap2(evalExpr(wave10aArg(1, ["low"], msg), env)), unwrap2(evalExpr(wave10aArg(2, ["prev_close", "prev"], msg), env)));
|
|
51457
|
+
}
|
|
51458
|
+
if (fname === "ta.double_top_bottom" || fname === "double_top_bottom") {
|
|
51459
|
+
const msg = "ta.double_top_bottom() requires 3 arguments";
|
|
51460
|
+
unwrap2(evalExpr(wave10aArg(0, ["high"], msg), env));
|
|
51461
|
+
unwrap2(evalExpr(wave10aArg(1, ["low"], msg), env));
|
|
51462
|
+
return env.ta.doubleTopBottom(unwrap2(evalExpr(wave10aArg(2, ["period", "length"], msg), env)));
|
|
51463
|
+
}
|
|
51464
|
+
if (fname === "ta.inside_bar_pattern" || fname === "inside_bar_pattern") {
|
|
51465
|
+
const msg = "ta.inside_bar_pattern() requires 2 arguments";
|
|
51466
|
+
unwrap2(evalExpr(wave10aArg(0, ["high"], msg), env));
|
|
51467
|
+
unwrap2(evalExpr(wave10aArg(1, ["low"], msg), env));
|
|
51468
|
+
return env.ta.insideBarPattern();
|
|
51469
|
+
}
|
|
51470
|
+
if (fname === "ta.macd_signal" || fname === "macd_signal") {
|
|
51471
|
+
const msg = "ta.macd_signal() requires 2 arguments: macd_line, signal_line";
|
|
51472
|
+
return env.ta.macdSignal(unwrap2(evalExpr(wave10aArg(0, ["macd_line", "macd"], msg), env)), unwrap2(evalExpr(wave10aArg(1, ["signal_line", "signal"], msg), env)));
|
|
51473
|
+
}
|
|
51474
|
+
if (fname === "ta.acceleration_factor" || fname === "acceleration_factor") {
|
|
51475
|
+
const msg = "ta.acceleration_factor() requires 2 arguments";
|
|
51476
|
+
return env.ta.accelerationFactor(site, unwrap2(evalExpr(wave10aArg(0, ["momentum_list", "momentum", "source", "series"], msg), env)), unwrap2(evalExpr(wave10aArg(1, ["period", "length"], msg), env)));
|
|
51477
|
+
}
|
|
51478
|
+
if (fname === "ta.stoch_smooth" || fname === "stoch_smooth") {
|
|
51479
|
+
const msg = "ta.stoch_smooth() requires 6 arguments: high, low, close, period, smooth_k, smooth_d";
|
|
51480
|
+
return env.ta.stochSmooth(unwrap2(evalExpr(wave10aArg(0, ["high"], msg), env)), unwrap2(evalExpr(wave10aArg(1, ["low"], msg), env)), unwrap2(evalExpr(wave10aArg(2, ["close"], msg), env)), unwrap2(evalExpr(wave10aArg(3, ["period", "length"], msg), env)), unwrap2(evalExpr(wave10aArg(4, ["smooth_k", "k"], msg), env)), unwrap2(evalExpr(wave10aArg(5, ["smooth_d", "d"], msg), env)));
|
|
51481
|
+
}
|
|
51482
|
+
const wave10bList = (index, names) => {
|
|
51483
|
+
const raw = evalExpr(callArg(node.args, index, names), env);
|
|
51484
|
+
const arr = asArray2(raw);
|
|
51485
|
+
if (arr == null)
|
|
51486
|
+
return [unwrap2(raw)];
|
|
51487
|
+
const out = [];
|
|
51488
|
+
for (let i = 0;i < arr.size(); i++)
|
|
51489
|
+
out.push(arr.get(i));
|
|
51490
|
+
return out;
|
|
51491
|
+
};
|
|
51492
|
+
if (fname === "ta.voi" || fname === "voi") {
|
|
51493
|
+
return env.ta.voi(unwrap2(evalExpr(callArg(node.args, 0, ["buy_volume", "buy"]), env)), unwrap2(evalExpr(callArg(node.args, 1, ["sell_volume", "sell"]), env)));
|
|
51494
|
+
}
|
|
51495
|
+
if (fname === "ta.bid_ask_imbalance" || fname === "bid_ask_imbalance") {
|
|
51496
|
+
return env.ta.bidAskImbalance(unwrap2(evalExpr(callArg(node.args, 0, ["bid_size", "bid"]), env)), unwrap2(evalExpr(callArg(node.args, 1, ["ask_size", "ask"]), env)), unwrap2(evalExpr(callArg(node.args, 2, ["bid_price"]), env)), unwrap2(evalExpr(callArg(node.args, 3, ["ask_price"]), env)));
|
|
51497
|
+
}
|
|
51498
|
+
if (fname === "ta.rsi_oversold_overbought" || fname === "rsi_oversold_overbought") {
|
|
51499
|
+
const os = unwrap2(evalExpr(callArg(node.args, 1, ["oversold_level", "oversold"]), env));
|
|
51500
|
+
const ob = unwrap2(evalExpr(callArg(node.args, 2, ["overbought_level", "overbought"]), env));
|
|
51501
|
+
return env.ta.rsiOversoldOverbought(unwrap2(evalExpr(callArg(node.args, 0, ["rsi_series", "rsi", "source"]), env)), os ?? Number.NaN, ob ?? Number.NaN);
|
|
51502
|
+
}
|
|
51503
|
+
if (fname === "ta.rsi_divergence" || fname === "rsi_divergence") {
|
|
51504
|
+
const period = unwrap2(evalExpr(callArg(node.args, 1, ["period", "length"]), env));
|
|
51505
|
+
return env.ta.rsiDivergence(wave10bList(0, ["rsi_series", "series", "source"]), period ?? 0);
|
|
51506
|
+
}
|
|
51507
|
+
if (fname === "ta.cumulative_delta" || fname === "cumulative_delta") {
|
|
51508
|
+
const period = unwrap2(evalExpr(callArg(node.args, 2, ["period", "length"]), env));
|
|
51509
|
+
return env.ta.cumulativeDelta(site, unwrap2(evalExpr(callArg(node.args, 0, ["close", "source"]), env)), unwrap2(evalExpr(callArg(node.args, 1, ["volume"]), env)), period ?? 0);
|
|
51510
|
+
}
|
|
51511
|
+
if (fname === "ta.volume_momentum" || fname === "volume_momentum") {
|
|
51512
|
+
const period = unwrap2(evalExpr(callArg(node.args, 1, ["period", "length"]), env));
|
|
51513
|
+
return env.ta.volumeMomentum(site, unwrap2(evalExpr(callArg(node.args, 0, ["volume", "source"]), env)), period ?? 0);
|
|
51514
|
+
}
|
|
51515
|
+
if (fname === "ta.volume_profile_high" || fname === "volume_profile_high") {
|
|
51516
|
+
return env.ta.volumeProfileHigh(wave10bList(0, ["close", "price", "source", "series"]), wave10bList(1, ["volume"]));
|
|
51517
|
+
}
|
|
51518
|
+
if (fname === "ta.volume_profile_low" || fname === "volume_profile_low") {
|
|
51519
|
+
const period = unwrap2(evalExpr(callArg(node.args, 2, ["period", "length"]), env));
|
|
51520
|
+
const levels = unwrap2(evalExpr(callArg(node.args, 3, ["levels"]), env));
|
|
51521
|
+
return env.ta.volumeProfileLow(site, unwrap2(evalExpr(callArg(node.args, 0, ["close", "source"]), env)), unwrap2(evalExpr(callArg(node.args, 1, ["volume"]), env)), period ?? 0, levels ?? 0);
|
|
51522
|
+
}
|
|
51523
|
+
if (fname === "ta.volume_thrust" || fname === "volume_thrust") {
|
|
51524
|
+
const sens = unwrap2(evalExpr(callArg(node.args, 3, ["sensitivity"]), env));
|
|
51525
|
+
return env.ta.volumeThrust(site, unwrap2(evalExpr(callArg(node.args, 0, ["close", "source"]), env)), unwrap2(evalExpr(callArg(node.args, 1, ["volume"]), env)), unwrap2(evalExpr(callArg(node.args, 2, ["volume_sma", "vol_sma", "sma"]), env)), sens ?? 0.3);
|
|
51526
|
+
}
|
|
50033
51527
|
return;
|
|
50034
51528
|
}
|
|
50035
51529
|
function hlc3(env) {
|
|
@@ -50842,7 +52336,7 @@ function optionalCoord(node, env, index, names, fallback) {
|
|
|
50842
52336
|
return fallback;
|
|
50843
52337
|
return unwrap2(evalExpr(e, env));
|
|
50844
52338
|
}
|
|
50845
|
-
function
|
|
52339
|
+
function pointXY2(p) {
|
|
50846
52340
|
const x = p.index ?? p.time ?? p.x ?? 0;
|
|
50847
52341
|
const y = p.price ?? p.y ?? 0;
|
|
50848
52342
|
return { x: x ?? 0, y: y ?? 0 };
|
|
@@ -50889,7 +52383,7 @@ function evalDrawingCall(fname, node, env) {
|
|
|
50889
52383
|
const extra = {};
|
|
50890
52384
|
let text;
|
|
50891
52385
|
if (isChartPoint(v0)) {
|
|
50892
|
-
const xy =
|
|
52386
|
+
const xy = pointXY2(v0);
|
|
50893
52387
|
extra.x = xy.x;
|
|
50894
52388
|
extra.y = xy.y;
|
|
50895
52389
|
text = drawText(node, env, pointKw != null ? 0 : 1, ["text"]);
|
|
@@ -51170,7 +52664,7 @@ function evalDrawingCall(fname, node, env) {
|
|
|
51170
52664
|
const id = drawId(node, env);
|
|
51171
52665
|
const p = evalExpr(callArg(node.args, 1, ["point"]), env);
|
|
51172
52666
|
if (id != null && isChartPoint(p)) {
|
|
51173
|
-
const xy =
|
|
52667
|
+
const xy = pointXY2(p);
|
|
51174
52668
|
book.lineSetXy1(id, xy.x, xy.y);
|
|
51175
52669
|
}
|
|
51176
52670
|
return NA;
|
|
@@ -51179,7 +52673,7 @@ function evalDrawingCall(fname, node, env) {
|
|
|
51179
52673
|
const id = drawId(node, env);
|
|
51180
52674
|
const p = evalExpr(callArg(node.args, 1, ["point"]), env);
|
|
51181
52675
|
if (id != null && isChartPoint(p)) {
|
|
51182
|
-
const xy =
|
|
52676
|
+
const xy = pointXY2(p);
|
|
51183
52677
|
book.lineSetXy2(id, xy.x, xy.y);
|
|
51184
52678
|
}
|
|
51185
52679
|
return NA;
|
|
@@ -51308,7 +52802,7 @@ function evalDrawingCall(fname, node, env) {
|
|
|
51308
52802
|
const id = drawId(node, env);
|
|
51309
52803
|
const p = evalExpr(callArg(node.args, 1, ["point"]), env);
|
|
51310
52804
|
if (id != null && isChartPoint(p)) {
|
|
51311
|
-
const xy =
|
|
52805
|
+
const xy = pointXY2(p);
|
|
51312
52806
|
book.labelSetXy(id, xy.x, xy.y);
|
|
51313
52807
|
}
|
|
51314
52808
|
return NA;
|
|
@@ -51447,7 +52941,7 @@ function evalDrawingCall(fname, node, env) {
|
|
|
51447
52941
|
const id = drawId(node, env);
|
|
51448
52942
|
const p = evalExpr(callArg(node.args, 1, ["point"]), env);
|
|
51449
52943
|
if (id != null && isChartPoint(p)) {
|
|
51450
|
-
const xy =
|
|
52944
|
+
const xy = pointXY2(p);
|
|
51451
52945
|
book.boxSetLeftTop(id, xy.x, xy.y);
|
|
51452
52946
|
}
|
|
51453
52947
|
return NA;
|
|
@@ -51456,7 +52950,7 @@ function evalDrawingCall(fname, node, env) {
|
|
|
51456
52950
|
const id = drawId(node, env);
|
|
51457
52951
|
const p = evalExpr(callArg(node.args, 1, ["point"]), env);
|
|
51458
52952
|
if (id != null && isChartPoint(p)) {
|
|
51459
|
-
const xy =
|
|
52953
|
+
const xy = pointXY2(p);
|
|
51460
52954
|
book.boxSetRightBottom(id, xy.x, xy.y);
|
|
51461
52955
|
}
|
|
51462
52956
|
return NA;
|