@luxalgo/vela 0.8.3 → 0.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{DataProvider-wbtJ3-Sa.d.cts → DataProvider-Bw58CjYy.d.cts} +1 -1
- package/dist/{DataProvider-oH78tYXL.d.ts → DataProvider-Byo8pEv0.d.ts} +1 -1
- package/dist/{chunk-KWI3YDBW.js → chunk-ALTGHKIM.js} +584 -25
- package/dist/{chunk-TO3GIK7Z.js → chunk-AUOB7A5Y.js} +2 -2
- package/dist/{chunk-VHGACEHO.js → chunk-I2U4NZD2.js} +7 -1
- package/dist/{chunk-2IPXYM4B.js → chunk-MOJ4T26N.js} +88 -5
- package/dist/{chunk-HMHA733L.js → chunk-UNUVPQFW.js} +1924 -734
- package/dist/{chunk-G7B7ZCBF.js → chunk-WY5H4S4I.js} +1 -1
- package/dist/{contributions-BhOBRenr.d.cts → contributions-BY3zSYiZ.d.ts} +56 -5
- package/dist/{contributions-HGqnNb_P.d.ts → contributions-DOm40g5-.d.cts} +56 -5
- package/dist/index.cjs +2583 -828
- package/dist/index.d.cts +9 -15
- package/dist/index.d.ts +9 -15
- package/dist/index.js +4 -4
- package/dist/{options-lMUwmRwh.d.cts → options-CSXbjMM5.d.cts} +64 -4
- package/dist/{options-lMUwmRwh.d.ts → options-CSXbjMM5.d.ts} +64 -4
- package/dist/{plugin-Cr2Pj8q8.d.ts → plugin-BDxUhGO3.d.ts} +3 -3
- package/dist/{plugin-Do5J5xuF.d.cts → plugin-CiQVyETg.d.cts} +3 -3
- package/dist/plugin.cjs +555 -17
- package/dist/plugin.d.cts +4 -4
- package/dist/plugin.d.ts +4 -4
- package/dist/plugin.js +2 -2
- package/dist/providers/binance.d.cts +2 -2
- package/dist/providers/binance.d.ts +2 -2
- package/dist/providers/coinbase.d.cts +2 -2
- package/dist/providers/coinbase.d.ts +2 -2
- package/dist/providers/hyperliquid.d.cts +2 -2
- package/dist/providers/hyperliquid.d.ts +2 -2
- package/dist/{statusline-model-B-2xGlB_.d.cts → statusline-model-C9tYXuux.d.ts} +19 -4
- package/dist/{statusline-model-CY1wzxHg.d.ts → statusline-model-DUBX6Fib.d.cts} +19 -4
- package/dist/ui.d.cts +1 -1
- package/dist/ui.d.ts +1 -1
- package/dist/ui.js +3 -3
- package/dist/vela.global.js +2590 -835
- package/dist/vela.global.min.js +124 -54
- package/dist/widget.cjs +2807 -969
- package/dist/widget.d.cts +6 -6
- package/dist/widget.d.ts +6 -6
- package/dist/widget.js +7 -7
- package/dist/workspace.cjs +2807 -969
- package/dist/workspace.d.cts +19 -5
- package/dist/workspace.d.ts +19 -5
- package/dist/workspace.js +6 -6
- package/package.json +1 -1
package/dist/plugin.cjs
CHANGED
|
@@ -453,6 +453,28 @@ function defaultText(value = "") {
|
|
|
453
453
|
return { value, size: "normal", hAlign: "left", vAlign: "top" };
|
|
454
454
|
}
|
|
455
455
|
|
|
456
|
+
// src/core/drawings/visibility.ts
|
|
457
|
+
var MIN = 6e4;
|
|
458
|
+
var HOUR = 60 * MIN;
|
|
459
|
+
var DAY = 24 * HOUR;
|
|
460
|
+
var TIMEFRAME_BANDS = [
|
|
461
|
+
{ key: "s", label: "Sec", fromMs: 0 },
|
|
462
|
+
{ key: "1", label: "1m", fromMs: MIN },
|
|
463
|
+
{ key: "5", label: "5m", fromMs: 5 * MIN },
|
|
464
|
+
{ key: "15", label: "15m", fromMs: 15 * MIN },
|
|
465
|
+
{ key: "60", label: "1H", fromMs: HOUR },
|
|
466
|
+
{ key: "240", label: "4H", fromMs: 4 * HOUR },
|
|
467
|
+
{ key: "D", label: "D", fromMs: DAY },
|
|
468
|
+
{ key: "W", label: "W", fromMs: 7 * DAY },
|
|
469
|
+
{ key: "M", label: "M", fromMs: 28 * DAY }
|
|
470
|
+
];
|
|
471
|
+
var BAND_KEYS = new Set(TIMEFRAME_BANDS.map((b) => b.key));
|
|
472
|
+
function sanitizeShowOn(v) {
|
|
473
|
+
if (!Array.isArray(v)) return void 0;
|
|
474
|
+
const wanted = new Set(v.filter((k) => typeof k === "string" && BAND_KEYS.has(k)));
|
|
475
|
+
return TIMEFRAME_BANDS.map((b) => b.key).filter((k) => wanted.has(k));
|
|
476
|
+
}
|
|
477
|
+
|
|
456
478
|
// src/core/drawings/Drawing.ts
|
|
457
479
|
var _Drawing = class _Drawing {
|
|
458
480
|
// Public so the registry can construct concrete subclasses; `abstract` still
|
|
@@ -469,6 +491,7 @@ var _Drawing = class _Drawing {
|
|
|
469
491
|
this.locked = init.locked ?? false;
|
|
470
492
|
this.visible = init.visible ?? true;
|
|
471
493
|
this.zIndex = init.zIndex ?? 0;
|
|
494
|
+
this.showOn = sanitizeShowOn(init.showOn);
|
|
472
495
|
this.createdAt = init.createdAt ?? Date.now();
|
|
473
496
|
if (init.props) this.readProps(init.props);
|
|
474
497
|
}
|
|
@@ -555,7 +578,10 @@ var _Drawing = class _Drawing {
|
|
|
555
578
|
visible: this.visible,
|
|
556
579
|
zIndex: this.zIndex,
|
|
557
580
|
createdAt: this.createdAt,
|
|
558
|
-
props: this.writeProps()
|
|
581
|
+
props: this.writeProps(),
|
|
582
|
+
// Always present (undefined = every timeframe) so an edit can lift a limit; JSON
|
|
583
|
+
// drops the undefined value, so unlimited drawings save as before.
|
|
584
|
+
showOn: this.showOn ? [...this.showOn] : void 0
|
|
559
585
|
};
|
|
560
586
|
}
|
|
561
587
|
/** Per-type extras to serialize into `props` (override in subclasses). */
|
|
@@ -690,9 +716,16 @@ var TrendLine = class extends Drawing {
|
|
|
690
716
|
if (y1 == null || y2 == null) return null;
|
|
691
717
|
return [proj.xOf(a.time), y1, proj.xOf(b.time), y2];
|
|
692
718
|
}
|
|
719
|
+
/** Which ends run on past the anchors. */
|
|
720
|
+
extension() {
|
|
721
|
+
const { extendLeft: l, extendRight: r } = this.style;
|
|
722
|
+
return l && r ? "both" : l ? "left" : r ? "right" : "none";
|
|
723
|
+
}
|
|
693
724
|
hitTest(px, py, proj, tol) {
|
|
694
725
|
const p = this.pixels(proj);
|
|
695
|
-
|
|
726
|
+
if (!p) return false;
|
|
727
|
+
const [x1, y1, x2, y2] = extendRay(p[0], p[1], p[2], p[3], this.extension(), proj.width, proj.height);
|
|
728
|
+
return distToSegment(px, py, x1, y1, x2, y2) <= tol;
|
|
696
729
|
}
|
|
697
730
|
handlePoints(proj) {
|
|
698
731
|
const p = this.pixels(proj);
|
|
@@ -719,6 +752,8 @@ var TrendLine = class extends Drawing {
|
|
|
719
752
|
fields: [
|
|
720
753
|
...LINE_FIELDS,
|
|
721
754
|
{ path: "style.arrowRight", label: "Arrow", kind: "boolean", group: "line" },
|
|
755
|
+
{ path: "style.extendLeft", label: "Extend left", kind: "boolean", group: "line" },
|
|
756
|
+
{ path: "style.extendRight", label: "Extend right", kind: "boolean", group: "line" },
|
|
722
757
|
...TEXT_FIELDS
|
|
723
758
|
]
|
|
724
759
|
};
|
|
@@ -3178,6 +3213,14 @@ var FibRatios = class extends Drawing {
|
|
|
3178
3213
|
|
|
3179
3214
|
// src/core/drawings/types/FibLevels.ts
|
|
3180
3215
|
var FibLevels = class extends FibRatios {
|
|
3216
|
+
// `declare`d: the base constructor reads saved props before these could be initialized.
|
|
3217
|
+
constructor(init) {
|
|
3218
|
+
super(init);
|
|
3219
|
+
if (this.showRatios === void 0) this.showRatios = true;
|
|
3220
|
+
if (this.showPrices === void 0) this.showPrices = true;
|
|
3221
|
+
if (this.labelSide === void 0) this.labelSide = "left";
|
|
3222
|
+
if (this.background === void 0) this.background = true;
|
|
3223
|
+
}
|
|
3181
3224
|
/** Price of a level for the two anchor prices; subclasses override to change which anchor ratio 0 sits on. */
|
|
3182
3225
|
levelPrice(ratio, p1, p2) {
|
|
3183
3226
|
return p1 + ratio * (p2 - p1);
|
|
@@ -3189,8 +3232,8 @@ var FibLevels = class extends FibRatios {
|
|
|
3189
3232
|
if (!a || !b) return null;
|
|
3190
3233
|
const xa = proj.xOf(a.time);
|
|
3191
3234
|
const xb = proj.xOf(b.time);
|
|
3192
|
-
const x1 = Math.min(xa, xb);
|
|
3193
|
-
const x2 = Math.max(xa, xb);
|
|
3235
|
+
const x1 = this.style.extendLeft ? 0 : Math.min(xa, xb);
|
|
3236
|
+
const x2 = this.style.extendRight ? proj.width : Math.max(xa, xb);
|
|
3194
3237
|
const out = [];
|
|
3195
3238
|
for (const lv of this.levels) {
|
|
3196
3239
|
if (!lv.enabled) continue;
|
|
@@ -3204,6 +3247,7 @@ var FibLevels = class extends FibRatios {
|
|
|
3204
3247
|
entryLines(proj) {
|
|
3205
3248
|
const lines = this.levelLines(proj);
|
|
3206
3249
|
if (!lines) return null;
|
|
3250
|
+
const right = this.labelSide === "right";
|
|
3207
3251
|
return lines.map((l) => ({
|
|
3208
3252
|
color: l.color,
|
|
3209
3253
|
label: l.label,
|
|
@@ -3211,16 +3255,24 @@ var FibLevels = class extends FibRatios {
|
|
|
3211
3255
|
y1: l.y,
|
|
3212
3256
|
x2: l.x2,
|
|
3213
3257
|
y2: l.y,
|
|
3214
|
-
numberText:
|
|
3215
|
-
numberX: l.x1 + 4,
|
|
3258
|
+
numberText: this.levelText(l.ratio, l.price),
|
|
3259
|
+
numberX: right ? l.x2 - 4 : l.x1 + 4,
|
|
3216
3260
|
numberY: l.y - 7,
|
|
3217
|
-
numberAlign: "left",
|
|
3261
|
+
numberAlign: right ? "right" : "left",
|
|
3218
3262
|
labelX: (l.x1 + l.x2) / 2,
|
|
3219
3263
|
labelY: l.y - 7
|
|
3220
3264
|
}));
|
|
3221
3265
|
}
|
|
3266
|
+
/** The text beside a level: its ratio, its price, both, or nothing. */
|
|
3267
|
+
levelText(ratio, price) {
|
|
3268
|
+
const p = price.toFixed(2);
|
|
3269
|
+
if (this.showRatios && this.showPrices) return `${ratio} (${p})`;
|
|
3270
|
+
if (this.showRatios) return String(ratio);
|
|
3271
|
+
return this.showPrices ? p : "";
|
|
3272
|
+
}
|
|
3222
3273
|
fillBands(proj) {
|
|
3223
|
-
|
|
3274
|
+
if (!this.background) return [];
|
|
3275
|
+
const lines = this.levelLines(proj)?.sort((p, q) => p.ratio - q.ratio);
|
|
3224
3276
|
if (!lines) return [];
|
|
3225
3277
|
const bands = [];
|
|
3226
3278
|
for (let i = 1; i < lines.length; i += 1) {
|
|
@@ -3238,6 +3290,26 @@ var FibLevels = class extends FibRatios {
|
|
|
3238
3290
|
if (prices.length === 0) return null;
|
|
3239
3291
|
return { min: Math.min(...prices), max: Math.max(...prices) };
|
|
3240
3292
|
}
|
|
3293
|
+
schema() {
|
|
3294
|
+
const base = super.schema();
|
|
3295
|
+
return {
|
|
3296
|
+
fields: [
|
|
3297
|
+
...base.fields,
|
|
3298
|
+
{ path: "style.extendLeft", label: "Extend left", kind: "boolean", group: "line" },
|
|
3299
|
+
{ path: "style.extendRight", label: "Extend right", kind: "boolean", group: "line" }
|
|
3300
|
+
]
|
|
3301
|
+
};
|
|
3302
|
+
}
|
|
3303
|
+
writeProps() {
|
|
3304
|
+
return { ...super.writeProps(), showRatios: this.showRatios, showPrices: this.showPrices, labelSide: this.labelSide, background: this.background };
|
|
3305
|
+
}
|
|
3306
|
+
readProps(props) {
|
|
3307
|
+
super.readProps(props);
|
|
3308
|
+
if (typeof props.showRatios === "boolean") this.showRatios = props.showRatios;
|
|
3309
|
+
if (typeof props.showPrices === "boolean") this.showPrices = props.showPrices;
|
|
3310
|
+
if (props.labelSide === "left" || props.labelSide === "right") this.labelSide = props.labelSide;
|
|
3311
|
+
if (typeof props.background === "boolean") this.background = props.background;
|
|
3312
|
+
}
|
|
3241
3313
|
};
|
|
3242
3314
|
|
|
3243
3315
|
// src/core/drawings/levelPalette.ts
|
|
@@ -3283,14 +3355,31 @@ var RATIO_COLORS = [
|
|
|
3283
3355
|
[0.75, LEVEL_BLUE],
|
|
3284
3356
|
[0.786, LEVEL_BLUE],
|
|
3285
3357
|
[1, LEVEL_ANCHOR],
|
|
3358
|
+
[0.705, LEVEL_AMBER],
|
|
3359
|
+
[0.886, LEVEL_PURPLE],
|
|
3286
3360
|
[1.272, LEVEL_BLUE],
|
|
3287
3361
|
[1.382, LEVEL_ORANGE],
|
|
3362
|
+
[1.414, LEVEL_AQUA],
|
|
3288
3363
|
[1.618, LEVEL_RED],
|
|
3289
3364
|
[2, LEVEL_ANCHOR],
|
|
3365
|
+
[2.272, LEVEL_VIOLET],
|
|
3290
3366
|
[2.382, LEVEL_ORANGE],
|
|
3367
|
+
[2.414, LEVEL_PINK],
|
|
3291
3368
|
[2.618, LEVEL_ORANGE],
|
|
3292
3369
|
[3, LEVEL_ANCHOR],
|
|
3370
|
+
[3.272, LEVEL_CORAL],
|
|
3371
|
+
[3.618, LEVEL_PURPLE],
|
|
3293
3372
|
[4.236, LEVEL_GREEN],
|
|
3373
|
+
[4.618, LEVEL_PINK],
|
|
3374
|
+
// Beyond the swing's end (targets): blues, deepening with distance.
|
|
3375
|
+
[-0.27, LEVEL_CYAN],
|
|
3376
|
+
[-0.272, LEVEL_CYAN],
|
|
3377
|
+
[-0.62, LEVEL_BLUE],
|
|
3378
|
+
[-0.618, LEVEL_BLUE],
|
|
3379
|
+
[-1, LEVEL_AQUA],
|
|
3380
|
+
[-1.5, LEVEL_VIOLET],
|
|
3381
|
+
[-2, LEVEL_PURPLE],
|
|
3382
|
+
[-2.5, LEVEL_PINK],
|
|
3294
3383
|
[6.854, LEVEL_TEAL],
|
|
3295
3384
|
[11.09, LEVEL_BLUE]
|
|
3296
3385
|
];
|
|
@@ -3317,8 +3406,36 @@ function cycleLevels(count, enabledCount = count) {
|
|
|
3317
3406
|
}));
|
|
3318
3407
|
}
|
|
3319
3408
|
|
|
3409
|
+
// src/core/drawings/fibPresets.ts
|
|
3410
|
+
var LADDER = [0, 0.236, 0.382, 0.5, 0.618, 0.705, 0.786, 0.886, 1, 1.272, 1.414, 1.618, 2, 2.272, 2.414, 2.618, 3, 3.272, 3.618, 4.236, 4.618, -0.272, -0.618, -1];
|
|
3411
|
+
var OTE_LADDER = [0, 0.236, 0.382, 0.5, 0.62, 0.705, 0.79, 0.886, 1, 1.272, 1.414, 1.618, 2, 2.618, 3, 3.618, 4.236, 4.618, -0.27, -0.62, -1, -1.5, -2, -2.5];
|
|
3412
|
+
function ladder(ratios, on, colors = {}) {
|
|
3413
|
+
return fibLevels(ratios.map((ratio) => ({ ratio, enabled: on.includes(ratio), color: colors[String(ratio)] })));
|
|
3414
|
+
}
|
|
3415
|
+
var FIB_PRESETS = [
|
|
3416
|
+
{
|
|
3417
|
+
key: "classic",
|
|
3418
|
+
label: "Classic",
|
|
3419
|
+
reverse: false,
|
|
3420
|
+
levels: ladder(LADDER, [0, 0.236, 0.382, 0.5, 0.618, 0.786, 1])
|
|
3421
|
+
},
|
|
3422
|
+
{
|
|
3423
|
+
key: "extension",
|
|
3424
|
+
label: "Extension",
|
|
3425
|
+
reverse: true,
|
|
3426
|
+
levels: ladder(LADDER, [0, 1, 1.272, 1.414, 1.618, 2, 2.618, 3.618, 4.236])
|
|
3427
|
+
},
|
|
3428
|
+
{
|
|
3429
|
+
key: "ote",
|
|
3430
|
+
label: "OTE",
|
|
3431
|
+
reverse: false,
|
|
3432
|
+
// The entry zone reads as one band.
|
|
3433
|
+
levels: ladder(OTE_LADDER, [0, 0.5, 0.62, 0.705, 0.79, 1, -0.27, -0.62], { "0.62": LEVEL_AMBER, "0.79": LEVEL_AMBER })
|
|
3434
|
+
}
|
|
3435
|
+
];
|
|
3436
|
+
|
|
3320
3437
|
// src/core/drawings/types/FibRetracement.ts
|
|
3321
|
-
var LEVELS =
|
|
3438
|
+
var LEVELS = FIB_PRESETS[0].levels;
|
|
3322
3439
|
var FibRetracement = class extends FibLevels {
|
|
3323
3440
|
constructor(init) {
|
|
3324
3441
|
super(init);
|
|
@@ -3341,7 +3458,11 @@ var FibRetracement = class extends FibLevels {
|
|
|
3341
3458
|
};
|
|
3342
3459
|
|
|
3343
3460
|
// src/core/drawings/types/FibExtension.ts
|
|
3344
|
-
var LEVELS2 =
|
|
3461
|
+
var LEVELS2 = ladder(
|
|
3462
|
+
[0, 0.236, 0.382, 0.5, 0.618, 0.786, 1, 1.272, 1.414, 1.618, 2, 2.272, 2.414, 2.618, 3, 3.272, 3.618, 4.236, 4.618],
|
|
3463
|
+
[0, 0.382, 0.618, 1, 1.272, 1.618, 2.618],
|
|
3464
|
+
{ "2.618": LEVEL_PURPLE }
|
|
3465
|
+
);
|
|
3345
3466
|
var FibExtension = class extends FibLevels {
|
|
3346
3467
|
constructor() {
|
|
3347
3468
|
super(...arguments);
|
|
@@ -4919,20 +5040,20 @@ function signed(n) {
|
|
|
4919
5040
|
}
|
|
4920
5041
|
function formatDuration(ms) {
|
|
4921
5042
|
const m = Math.abs(ms);
|
|
4922
|
-
const
|
|
5043
|
+
const DAY2 = 864e5;
|
|
4923
5044
|
const HR = 36e5;
|
|
4924
|
-
const
|
|
4925
|
-
if (m >=
|
|
4926
|
-
const d = Math.floor(m /
|
|
4927
|
-
const h = Math.round(m %
|
|
5045
|
+
const MIN2 = 6e4;
|
|
5046
|
+
if (m >= DAY2) {
|
|
5047
|
+
const d = Math.floor(m / DAY2);
|
|
5048
|
+
const h = Math.round(m % DAY2 / HR);
|
|
4928
5049
|
return h ? `${d}d ${h}h` : `${d}d`;
|
|
4929
5050
|
}
|
|
4930
5051
|
if (m >= HR) {
|
|
4931
5052
|
const h = Math.floor(m / HR);
|
|
4932
|
-
const mn = Math.round(m % HR /
|
|
5053
|
+
const mn = Math.round(m % HR / MIN2);
|
|
4933
5054
|
return mn ? `${h}h ${mn}m` : `${h}h`;
|
|
4934
5055
|
}
|
|
4935
|
-
if (m >=
|
|
5056
|
+
if (m >= MIN2) return `${Math.round(m / MIN2)}m`;
|
|
4936
5057
|
return `${Math.round(m / 1e3)}s`;
|
|
4937
5058
|
}
|
|
4938
5059
|
var MeasureBox = class extends Drawing {
|
|
@@ -5495,6 +5616,393 @@ var Magnifier = class extends Drawing {
|
|
|
5495
5616
|
}
|
|
5496
5617
|
};
|
|
5497
5618
|
|
|
5619
|
+
// src/core/drawings/priceAction.ts
|
|
5620
|
+
var GAP_REACH = 3;
|
|
5621
|
+
function nearestBarIndex(bars, time) {
|
|
5622
|
+
if (bars.length === 0) return -1;
|
|
5623
|
+
let lo = 0;
|
|
5624
|
+
let hi = bars.length - 1;
|
|
5625
|
+
while (lo < hi) {
|
|
5626
|
+
const mid = lo + hi >> 1;
|
|
5627
|
+
if (bars[mid].time < time) lo = mid + 1;
|
|
5628
|
+
else hi = mid;
|
|
5629
|
+
}
|
|
5630
|
+
if (lo > 0 && Math.abs(bars[lo - 1].time - time) <= Math.abs(bars[lo].time - time)) return lo - 1;
|
|
5631
|
+
return lo;
|
|
5632
|
+
}
|
|
5633
|
+
function gapAt(bars, i) {
|
|
5634
|
+
const prev = bars[i - 1];
|
|
5635
|
+
const next = bars[i + 1];
|
|
5636
|
+
if (!prev || !next || !bars[i]) return null;
|
|
5637
|
+
if (next.low > prev.high) return { bull: true, top: next.low, bottom: prev.high };
|
|
5638
|
+
if (next.high < prev.low) return { bull: false, top: prev.low, bottom: next.high };
|
|
5639
|
+
return null;
|
|
5640
|
+
}
|
|
5641
|
+
function nearestGap(bars, i) {
|
|
5642
|
+
for (let k = 0; k <= GAP_REACH; k += 1) {
|
|
5643
|
+
for (const j of k === 0 ? [i] : [i - k, i + k]) {
|
|
5644
|
+
const g = gapAt(bars, j);
|
|
5645
|
+
if (g) return { index: j, ...g };
|
|
5646
|
+
}
|
|
5647
|
+
}
|
|
5648
|
+
return null;
|
|
5649
|
+
}
|
|
5650
|
+
function gapState(bars, i) {
|
|
5651
|
+
const g = nearestGap(bars, i);
|
|
5652
|
+
if (!g) return null;
|
|
5653
|
+
const { index, bull, top, bottom } = g;
|
|
5654
|
+
const mid = (top + bottom) / 2;
|
|
5655
|
+
let tested = null;
|
|
5656
|
+
let half = null;
|
|
5657
|
+
let filled = null;
|
|
5658
|
+
let inverted = null;
|
|
5659
|
+
for (let j = index + 2; j < bars.length && inverted === null; j += 1) {
|
|
5660
|
+
const b = bars[j];
|
|
5661
|
+
const reach = bull ? b.low : b.high;
|
|
5662
|
+
const into = (v) => bull ? reach <= v : reach >= v;
|
|
5663
|
+
if (tested === null && into(bull ? top : bottom)) tested = j;
|
|
5664
|
+
if (half === null && into(mid)) half = j;
|
|
5665
|
+
if (filled === null && into(bull ? bottom : top)) filled = j;
|
|
5666
|
+
if (filled !== null && (bull ? b.close < bottom : b.close > top)) inverted = j;
|
|
5667
|
+
}
|
|
5668
|
+
return { index, bull, top, bottom, mid, tested, half, filled, inverted };
|
|
5669
|
+
}
|
|
5670
|
+
function blockState(bars, i, range) {
|
|
5671
|
+
const c = bars[i];
|
|
5672
|
+
if (!c) return null;
|
|
5673
|
+
const bull = c.close < c.open;
|
|
5674
|
+
const top = range === "body" ? Math.max(c.open, c.close) : c.high;
|
|
5675
|
+
const bottom = range === "body" ? Math.min(c.open, c.close) : c.low;
|
|
5676
|
+
const mid = (top + bottom) / 2;
|
|
5677
|
+
let left = false;
|
|
5678
|
+
let tested = null;
|
|
5679
|
+
let half = null;
|
|
5680
|
+
let broken = null;
|
|
5681
|
+
let leftAfterBreak = false;
|
|
5682
|
+
let retest = null;
|
|
5683
|
+
for (let j = i + 1; j < bars.length && retest === null; j += 1) {
|
|
5684
|
+
const b = bars[j];
|
|
5685
|
+
if (broken === null) {
|
|
5686
|
+
if (!left) left = bull ? b.low > top : b.high < bottom;
|
|
5687
|
+
else {
|
|
5688
|
+
if (tested === null && (bull ? b.low <= top : b.high >= bottom)) tested = j;
|
|
5689
|
+
if (half === null && (bull ? b.low <= mid : b.high >= mid)) half = j;
|
|
5690
|
+
}
|
|
5691
|
+
if (bull ? b.close < bottom : b.close > top) broken = j;
|
|
5692
|
+
} else if (!leftAfterBreak) leftAfterBreak = bull ? b.high < bottom : b.low > top;
|
|
5693
|
+
else if (bull ? b.high >= bottom : b.low <= top) retest = j;
|
|
5694
|
+
}
|
|
5695
|
+
return { index: i, bull, top, bottom, mid, tested, half, broken, retest };
|
|
5696
|
+
}
|
|
5697
|
+
function liquidityState(bars, i, side) {
|
|
5698
|
+
const c = bars[i];
|
|
5699
|
+
if (!c) return null;
|
|
5700
|
+
const high = side === "high";
|
|
5701
|
+
const price = high ? c.high : c.low;
|
|
5702
|
+
let swept = null;
|
|
5703
|
+
let broken = null;
|
|
5704
|
+
for (let j = i + 1; j < bars.length && broken === null; j += 1) {
|
|
5705
|
+
const b = bars[j];
|
|
5706
|
+
if (high ? b.close > price : b.close < price) broken = j;
|
|
5707
|
+
else if (swept === null && (high ? b.high > price : b.low < price)) swept = j;
|
|
5708
|
+
}
|
|
5709
|
+
return { index: i, high, price, swept, broken };
|
|
5710
|
+
}
|
|
5711
|
+
|
|
5712
|
+
// src/core/drawings/types/PriceActionZone.ts
|
|
5713
|
+
var candlesSeen = /* @__PURE__ */ new WeakMap();
|
|
5714
|
+
var PriceActionTool = class extends Drawing {
|
|
5715
|
+
anchorSchema() {
|
|
5716
|
+
return { min: 1, max: 1, slots: [{ role: "candle", free: "x" }] };
|
|
5717
|
+
}
|
|
5718
|
+
/** The chart's candles, and the one nearest the anchor. */
|
|
5719
|
+
candles(proj) {
|
|
5720
|
+
const a = this.anchors[0];
|
|
5721
|
+
if (!a) return null;
|
|
5722
|
+
let bars = candlesSeen.get(proj);
|
|
5723
|
+
if (!bars) {
|
|
5724
|
+
bars = proj.barsInRange?.(Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY) ?? [];
|
|
5725
|
+
candlesSeen.set(proj, bars);
|
|
5726
|
+
}
|
|
5727
|
+
return bars.length > 0 ? { bars, at: nearestBarIndex(bars, a.time) } : null;
|
|
5728
|
+
}
|
|
5729
|
+
/** Half a candle's width at bar `i`, in pixels. */
|
|
5730
|
+
halfBar(proj, bars, i) {
|
|
5731
|
+
const a = bars[Math.max(0, i - 1)];
|
|
5732
|
+
const b = bars[Math.min(bars.length - 1, Math.max(1, i))];
|
|
5733
|
+
if (!a || !b || a === b) return 3;
|
|
5734
|
+
return Math.max(1, Math.abs(proj.xOf(b.time) - proj.xOf(a.time)) / 2);
|
|
5735
|
+
}
|
|
5736
|
+
/** Pixel x for the right edge of a zone that stops at bar `end`, or runs on to the chart's edge. */
|
|
5737
|
+
rightEdge(proj, bars, end) {
|
|
5738
|
+
if (end === null) return Math.max(proj.width, proj.xOf(bars[bars.length - 1].time));
|
|
5739
|
+
return proj.xOf(bars[end].time) + this.halfBar(proj, bars, end);
|
|
5740
|
+
}
|
|
5741
|
+
/** The anchor itself, for a tool with nothing on the candles to hang its handle on. */
|
|
5742
|
+
anchorHandle(proj) {
|
|
5743
|
+
const a = this.anchors[0];
|
|
5744
|
+
const y = a ? proj.yOf(a.price, this.paneId) : null;
|
|
5745
|
+
return a && y != null ? [[proj.xOf(a.time), y]] : [];
|
|
5746
|
+
}
|
|
5747
|
+
hitHandle(px, py, proj, tol) {
|
|
5748
|
+
return handleAt(px, py, this.handlePoints(proj), tol + 3);
|
|
5749
|
+
}
|
|
5750
|
+
priceRange() {
|
|
5751
|
+
return null;
|
|
5752
|
+
}
|
|
5753
|
+
};
|
|
5754
|
+
var PriceActionZone = class extends PriceActionTool {
|
|
5755
|
+
/** The zone's pixel layout, or null when the candles don't form one. */
|
|
5756
|
+
zone(proj) {
|
|
5757
|
+
const c = this.candles(proj);
|
|
5758
|
+
const f = c && this.formation(c.bars, c.at);
|
|
5759
|
+
if (!c || !f) return null;
|
|
5760
|
+
const yt = proj.yOf(f.top, this.paneId);
|
|
5761
|
+
const yb = proj.yOf(f.bottom, this.paneId);
|
|
5762
|
+
if (yt == null || yb == null) return null;
|
|
5763
|
+
const { bars } = c;
|
|
5764
|
+
const s = this.settings();
|
|
5765
|
+
const left = (i) => proj.xOf(bars[i].time) - this.halfBar(proj, bars, i);
|
|
5766
|
+
const yTop = Math.min(yt, yb);
|
|
5767
|
+
const yBottom = Math.max(yt, yb);
|
|
5768
|
+
const midY = proj.yOf(f.mid, this.paneId) ?? (yTop + yBottom) / 2;
|
|
5769
|
+
const flip = f.flip && { x1: left(f.flip.from), x2: this.rightEdge(proj, bars, f.flip.to), fill: f.bull ? s.downColor : s.upColor };
|
|
5770
|
+
const edge = s.extend === "tested" ? f.bull ? f.top : f.bottom : s.extend === "half" ? f.mid : f.bull ? f.bottom : f.top;
|
|
5771
|
+
const edgeY = proj.yOf(edge, this.paneId);
|
|
5772
|
+
return {
|
|
5773
|
+
x1: left(f.start),
|
|
5774
|
+
x2: this.rightEdge(proj, bars, f.end),
|
|
5775
|
+
yTop,
|
|
5776
|
+
yBottom,
|
|
5777
|
+
fill: f.bull ? s.upColor : s.downColor,
|
|
5778
|
+
border: s.border,
|
|
5779
|
+
midY: s.midline ? midY : null,
|
|
5780
|
+
faded: f.end !== null && s.fade && !flip,
|
|
5781
|
+
marker: f.end !== null && !flip && edgeY != null ? { x: proj.xOf(bars[f.end].time), y: edgeY } : null,
|
|
5782
|
+
flip,
|
|
5783
|
+
handle: [proj.xOf(bars[f.index].time), midY]
|
|
5784
|
+
};
|
|
5785
|
+
}
|
|
5786
|
+
hitTest(px, py, proj, tol) {
|
|
5787
|
+
const z = this.zone(proj);
|
|
5788
|
+
if (!z) {
|
|
5789
|
+
const a = this.anchors[0];
|
|
5790
|
+
return a != null && Math.abs(px - proj.xOf(a.time)) <= tol;
|
|
5791
|
+
}
|
|
5792
|
+
const inY = py >= z.yTop - tol && py <= z.yBottom + tol;
|
|
5793
|
+
if (inY && px >= z.x1 - tol && px <= z.x2 + tol) return true;
|
|
5794
|
+
return z.flip != null && inY && px >= z.flip.x1 - tol && px <= z.flip.x2 + tol;
|
|
5795
|
+
}
|
|
5796
|
+
handlePoints(proj) {
|
|
5797
|
+
const z = this.zone(proj);
|
|
5798
|
+
return z ? [z.handle] : this.anchorHandle(proj);
|
|
5799
|
+
}
|
|
5800
|
+
bounds(proj) {
|
|
5801
|
+
const z = this.zone(proj);
|
|
5802
|
+
if (!z) return null;
|
|
5803
|
+
const right = Math.min(proj.width, z.flip ? z.flip.x2 : z.x2);
|
|
5804
|
+
return { x: z.x1, y: z.yTop, w: Math.max(1, right - z.x1), h: Math.max(1, z.yBottom - z.yTop) };
|
|
5805
|
+
}
|
|
5806
|
+
};
|
|
5807
|
+
|
|
5808
|
+
// src/core/drawings/types/FairValueGap.ts
|
|
5809
|
+
var EXTEND_OPTIONS = [
|
|
5810
|
+
{ value: "tested", label: "Until tested" },
|
|
5811
|
+
{ value: "half", label: "Until 50%" },
|
|
5812
|
+
{ value: "filled", label: "Until filled" },
|
|
5813
|
+
{ value: "always", label: "Always" }
|
|
5814
|
+
];
|
|
5815
|
+
function defaults2() {
|
|
5816
|
+
return { extend: "filled", upColor: `${BULLISH}33`, downColor: `${BEARISH}33`, midline: true, border: false, fade: true, inverse: false };
|
|
5817
|
+
}
|
|
5818
|
+
var FairValueGap = class extends PriceActionZone {
|
|
5819
|
+
constructor(init) {
|
|
5820
|
+
super(init);
|
|
5821
|
+
this.type = "fairvaluegap";
|
|
5822
|
+
if (!this.gap) this.gap = defaults2();
|
|
5823
|
+
}
|
|
5824
|
+
settings() {
|
|
5825
|
+
return this.gap;
|
|
5826
|
+
}
|
|
5827
|
+
formation(bars, at) {
|
|
5828
|
+
const s = gapState(bars, at);
|
|
5829
|
+
if (!s) return null;
|
|
5830
|
+
const { extend, inverse } = this.gap;
|
|
5831
|
+
const flip = inverse && extend === "filled" && s.inverted !== null ? { from: s.inverted, to: null } : null;
|
|
5832
|
+
return { ...s, start: s.index - 1, end: extend === "always" ? null : s[extend], flip };
|
|
5833
|
+
}
|
|
5834
|
+
schema() {
|
|
5835
|
+
return {
|
|
5836
|
+
fields: [
|
|
5837
|
+
{ path: "gap.extend", label: "Extend right", kind: "select", options: EXTEND_OPTIONS, group: "behavior" },
|
|
5838
|
+
{ path: "gap.upColor", label: "Bullish", kind: "color", group: "fill" },
|
|
5839
|
+
{ path: "gap.downColor", label: "Bearish", kind: "color", group: "fill" },
|
|
5840
|
+
{ path: "gap.midline", label: "Midline", kind: "boolean", group: "line" },
|
|
5841
|
+
{ path: "gap.border", label: "Border", kind: "boolean", group: "line" },
|
|
5842
|
+
{ path: "gap.fade", label: "Fade at end", kind: "boolean", group: "behavior", when: { path: "gap.extend", in: ["tested", "half", "filled"] } },
|
|
5843
|
+
{ path: "gap.inverse", label: "Flip on close", kind: "boolean", group: "behavior", when: { path: "gap.extend", in: ["filled"] } }
|
|
5844
|
+
]
|
|
5845
|
+
};
|
|
5846
|
+
}
|
|
5847
|
+
writeProps() {
|
|
5848
|
+
return { ...this.gap };
|
|
5849
|
+
}
|
|
5850
|
+
readProps(props) {
|
|
5851
|
+
const d = defaults2();
|
|
5852
|
+
const p = props;
|
|
5853
|
+
this.gap = {
|
|
5854
|
+
extend: EXTEND_OPTIONS.some((o) => o.value === p.extend) ? p.extend : d.extend,
|
|
5855
|
+
upColor: typeof p.upColor === "string" ? p.upColor : d.upColor,
|
|
5856
|
+
downColor: typeof p.downColor === "string" ? p.downColor : d.downColor,
|
|
5857
|
+
midline: typeof p.midline === "boolean" ? p.midline : d.midline,
|
|
5858
|
+
border: typeof p.border === "boolean" ? p.border : d.border,
|
|
5859
|
+
fade: typeof p.fade === "boolean" ? p.fade : d.fade,
|
|
5860
|
+
inverse: typeof p.inverse === "boolean" ? p.inverse : d.inverse
|
|
5861
|
+
};
|
|
5862
|
+
}
|
|
5863
|
+
};
|
|
5864
|
+
|
|
5865
|
+
// src/core/drawings/types/OrderBlock.ts
|
|
5866
|
+
var RANGE_OPTIONS = [
|
|
5867
|
+
{ value: "body", label: "Body" },
|
|
5868
|
+
{ value: "wick", label: "Full range" }
|
|
5869
|
+
];
|
|
5870
|
+
var EXTEND_OPTIONS2 = [
|
|
5871
|
+
{ value: "tested", label: "Until tested" },
|
|
5872
|
+
{ value: "half", label: "Until 50%" },
|
|
5873
|
+
{ value: "broken", label: "Until broken" },
|
|
5874
|
+
{ value: "always", label: "Always" }
|
|
5875
|
+
];
|
|
5876
|
+
function defaults3() {
|
|
5877
|
+
return { range: "body", extend: "broken", upColor: `${BULLISH}29`, downColor: `${BEARISH}29`, midline: true, border: true, fade: true, breaker: true };
|
|
5878
|
+
}
|
|
5879
|
+
var OrderBlock = class extends PriceActionZone {
|
|
5880
|
+
constructor(init) {
|
|
5881
|
+
super(init);
|
|
5882
|
+
this.type = "orderblock";
|
|
5883
|
+
if (!this.block) this.block = defaults3();
|
|
5884
|
+
}
|
|
5885
|
+
settings() {
|
|
5886
|
+
return this.block;
|
|
5887
|
+
}
|
|
5888
|
+
formation(bars, at) {
|
|
5889
|
+
const s = blockState(bars, at, this.block.range);
|
|
5890
|
+
if (!s) return null;
|
|
5891
|
+
const { extend, breaker } = this.block;
|
|
5892
|
+
const flip = breaker && extend === "broken" && s.broken !== null ? { from: s.broken, to: s.retest } : null;
|
|
5893
|
+
return { ...s, start: s.index, end: extend === "always" ? null : s[extend], flip };
|
|
5894
|
+
}
|
|
5895
|
+
schema() {
|
|
5896
|
+
return {
|
|
5897
|
+
fields: [
|
|
5898
|
+
{ path: "block.range", label: "Zone", kind: "select", options: RANGE_OPTIONS, group: "behavior" },
|
|
5899
|
+
{ path: "block.extend", label: "Extend right", kind: "select", options: EXTEND_OPTIONS2, group: "behavior" },
|
|
5900
|
+
{ path: "block.upColor", label: "Bullish", kind: "color", group: "fill" },
|
|
5901
|
+
{ path: "block.downColor", label: "Bearish", kind: "color", group: "fill" },
|
|
5902
|
+
{ path: "block.midline", label: "Midline", kind: "boolean", group: "line" },
|
|
5903
|
+
{ path: "block.border", label: "Border", kind: "boolean", group: "line" },
|
|
5904
|
+
{ path: "block.fade", label: "Fade at end", kind: "boolean", group: "behavior", when: { path: "block.extend", in: ["tested", "half", "broken"] } },
|
|
5905
|
+
{ path: "block.breaker", label: "Breaker", kind: "boolean", group: "behavior", when: { path: "block.extend", in: ["broken"] } }
|
|
5906
|
+
]
|
|
5907
|
+
};
|
|
5908
|
+
}
|
|
5909
|
+
writeProps() {
|
|
5910
|
+
return { ...this.block };
|
|
5911
|
+
}
|
|
5912
|
+
readProps(props) {
|
|
5913
|
+
const d = defaults3();
|
|
5914
|
+
const p = props;
|
|
5915
|
+
this.block = {
|
|
5916
|
+
range: p.range === "body" || p.range === "wick" ? p.range : d.range,
|
|
5917
|
+
extend: EXTEND_OPTIONS2.some((o) => o.value === p.extend) ? p.extend : d.extend,
|
|
5918
|
+
upColor: typeof p.upColor === "string" ? p.upColor : d.upColor,
|
|
5919
|
+
downColor: typeof p.downColor === "string" ? p.downColor : d.downColor,
|
|
5920
|
+
midline: typeof p.midline === "boolean" ? p.midline : d.midline,
|
|
5921
|
+
border: typeof p.border === "boolean" ? p.border : d.border,
|
|
5922
|
+
fade: typeof p.fade === "boolean" ? p.fade : d.fade,
|
|
5923
|
+
breaker: typeof p.breaker === "boolean" ? p.breaker : d.breaker
|
|
5924
|
+
};
|
|
5925
|
+
}
|
|
5926
|
+
};
|
|
5927
|
+
|
|
5928
|
+
// src/core/drawings/types/Liquidity.ts
|
|
5929
|
+
var EXTEND_OPTIONS3 = [
|
|
5930
|
+
{ value: "swept", label: "Until swept" },
|
|
5931
|
+
{ value: "broken", label: "Until broken" },
|
|
5932
|
+
{ value: "always", label: "Always" }
|
|
5933
|
+
];
|
|
5934
|
+
function defaults4() {
|
|
5935
|
+
return { extend: "swept", markSweep: true };
|
|
5936
|
+
}
|
|
5937
|
+
var Liquidity = class extends PriceActionTool {
|
|
5938
|
+
constructor(init) {
|
|
5939
|
+
super(init);
|
|
5940
|
+
this.type = "liquidity";
|
|
5941
|
+
if (!this.liq) this.liq = defaults4();
|
|
5942
|
+
}
|
|
5943
|
+
anchorSchema() {
|
|
5944
|
+
return { min: 1, max: 1, slots: [{ role: "candle", free: "both" }] };
|
|
5945
|
+
}
|
|
5946
|
+
state(proj) {
|
|
5947
|
+
const c = this.candles(proj);
|
|
5948
|
+
const a = this.anchors[0];
|
|
5949
|
+
if (!c || !a) return null;
|
|
5950
|
+
const bar = c.bars[c.at];
|
|
5951
|
+
return liquidityState(c.bars, c.at, a.price >= (bar.high + bar.low) / 2 ? "high" : "low");
|
|
5952
|
+
}
|
|
5953
|
+
line(proj) {
|
|
5954
|
+
const c = this.candles(proj);
|
|
5955
|
+
const s = this.state(proj);
|
|
5956
|
+
if (!c || !s) return null;
|
|
5957
|
+
const y = proj.yOf(s.price, this.paneId);
|
|
5958
|
+
if (y == null) return null;
|
|
5959
|
+
const { bars } = c;
|
|
5960
|
+
const { extend, markSweep } = this.liq;
|
|
5961
|
+
const end = extend === "always" ? null : extend === "broken" ? s.broken : s.swept ?? s.broken;
|
|
5962
|
+
const x1 = proj.xOf(bars[s.index].time);
|
|
5963
|
+
let sweep = null;
|
|
5964
|
+
if (markSweep && s.swept !== null && (end === null || s.swept <= end)) {
|
|
5965
|
+
const b = bars[s.swept];
|
|
5966
|
+
const wick = proj.yOf(s.high ? b.high : b.low, this.paneId);
|
|
5967
|
+
if (wick != null) sweep = { x: proj.xOf(b.time), y: wick + (s.high ? -9 : 9) };
|
|
5968
|
+
}
|
|
5969
|
+
return { x1, x2: this.rightEdge(proj, bars, end), y, sweep, handle: [x1, y] };
|
|
5970
|
+
}
|
|
5971
|
+
hitTest(px, py, proj, tol) {
|
|
5972
|
+
const l = this.line(proj);
|
|
5973
|
+
return l != null && px >= l.x1 - tol && px <= l.x2 + tol && Math.abs(py - l.y) <= tol;
|
|
5974
|
+
}
|
|
5975
|
+
handlePoints(proj) {
|
|
5976
|
+
const l = this.line(proj);
|
|
5977
|
+
return l ? [l.handle] : this.anchorHandle(proj);
|
|
5978
|
+
}
|
|
5979
|
+
bounds(proj) {
|
|
5980
|
+
const l = this.line(proj);
|
|
5981
|
+
if (!l) return null;
|
|
5982
|
+
return { x: l.x1, y: l.y - 4, w: Math.max(1, Math.min(proj.width, l.x2) - l.x1), h: 8 };
|
|
5983
|
+
}
|
|
5984
|
+
schema() {
|
|
5985
|
+
return {
|
|
5986
|
+
fields: [
|
|
5987
|
+
...LINE_FIELDS,
|
|
5988
|
+
{ path: "liq.extend", label: "Extend right", kind: "select", options: EXTEND_OPTIONS3, group: "behavior" },
|
|
5989
|
+
{ path: "liq.markSweep", label: "Mark sweep", kind: "boolean", group: "behavior" }
|
|
5990
|
+
]
|
|
5991
|
+
};
|
|
5992
|
+
}
|
|
5993
|
+
writeProps() {
|
|
5994
|
+
return { ...this.liq };
|
|
5995
|
+
}
|
|
5996
|
+
readProps(props) {
|
|
5997
|
+
const d = defaults4();
|
|
5998
|
+
const p = props;
|
|
5999
|
+
this.liq = {
|
|
6000
|
+
extend: EXTEND_OPTIONS3.some((o) => o.value === p.extend) ? p.extend : d.extend,
|
|
6001
|
+
markSweep: typeof p.markSweep === "boolean" ? p.markSweep : d.markSweep
|
|
6002
|
+
};
|
|
6003
|
+
}
|
|
6004
|
+
};
|
|
6005
|
+
|
|
5498
6006
|
// src/core/drawings/registry.ts
|
|
5499
6007
|
var REGISTRY2 = /* @__PURE__ */ new Map();
|
|
5500
6008
|
function registerDrawingType(meta) {
|
|
@@ -6164,6 +6672,36 @@ registerDrawingType({
|
|
|
6164
6672
|
defaultStyle: { lineColor: BULLISH, lineWidth: 1, lineStyle: "solid" },
|
|
6165
6673
|
create: (init) => new FixedRangeVolumeProfile(init)
|
|
6166
6674
|
});
|
|
6675
|
+
var FVG_ICON = svg24('<path d="M6 15v6M12 3v18M18 2v6"/><rect x="3.5" y="9.5" width="17" height="5" rx="1" fill="currentColor" fill-opacity="0.28" stroke-width="1.4"/>');
|
|
6676
|
+
var ORDER_BLOCK_ICON = svg24('<rect x="4" y="7.5" width="5" height="8" rx="1"/><path d="M6.5 4v3.5M6.5 15.5V19"/><rect x="9" y="7.5" width="11.5" height="8" rx="1" fill="currentColor" fill-opacity="0.22" stroke-width="1.4"/>');
|
|
6677
|
+
var LIQUIDITY_ICON = svg24('<path d="M3 8h12" stroke-dasharray="2.5 2.5"/><path d="m16.5 4.5 4 4m0-4-4 4"/><path d="M3.5 20 8 13.5l4 3.5 5-8"/>');
|
|
6678
|
+
registerDrawingType({
|
|
6679
|
+
type: "fairvaluegap",
|
|
6680
|
+
group: "priceaction",
|
|
6681
|
+
label: "Fair Value Gap",
|
|
6682
|
+
icon: FVG_ICON,
|
|
6683
|
+
defaultStyle: { lineColor: BULLISH, lineWidth: 1, lineStyle: "solid" },
|
|
6684
|
+
placementHint: "Click the middle candle of a gap",
|
|
6685
|
+
create: (init) => new FairValueGap(init)
|
|
6686
|
+
});
|
|
6687
|
+
registerDrawingType({
|
|
6688
|
+
type: "orderblock",
|
|
6689
|
+
group: "priceaction",
|
|
6690
|
+
label: "Order Block",
|
|
6691
|
+
icon: ORDER_BLOCK_ICON,
|
|
6692
|
+
defaultStyle: { lineColor: BULLISH, lineWidth: 1, lineStyle: "solid" },
|
|
6693
|
+
placementHint: "Click the candle that forms the block",
|
|
6694
|
+
create: (init) => new OrderBlock(init)
|
|
6695
|
+
});
|
|
6696
|
+
registerDrawingType({
|
|
6697
|
+
type: "liquidity",
|
|
6698
|
+
group: "priceaction",
|
|
6699
|
+
label: "Liquidity",
|
|
6700
|
+
icon: LIQUIDITY_ICON,
|
|
6701
|
+
defaultStyle: { lineColor: WARNING, lineWidth: 1, lineStyle: "solid" },
|
|
6702
|
+
placementHint: "Click near a candle's high or low",
|
|
6703
|
+
create: (init) => new Liquidity(init)
|
|
6704
|
+
});
|
|
6167
6705
|
|
|
6168
6706
|
// src/core/model/inputs.ts
|
|
6169
6707
|
function inputVisible(when, values) {
|