@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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { svg24, NEUTRAL, BEARISH, WARNING, BULLISH, INFO, ACCENT_BRIGHT, VALID, INVALID, MARKER, ACCENT, injectStyles, iconEl, announceSurface, holdForExit } from './chunk-
|
|
1
|
+
import { svg24, NEUTRAL, BEARISH, WARNING, BULLISH, INFO, ACCENT_BRIGHT, VALID, INVALID, MARKER, ACCENT, injectStyles, iconEl, announceSurface, holdForExit } from './chunk-I2U4NZD2.js';
|
|
2
2
|
|
|
3
3
|
// src/core/model/series.ts
|
|
4
4
|
function isLineLikeSeries(spec) {
|
|
@@ -42,6 +42,39 @@ function defaultText(value = "") {
|
|
|
42
42
|
return { value, size: "normal", hAlign: "left", vAlign: "top" };
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
// src/core/drawings/visibility.ts
|
|
46
|
+
var MIN = 6e4;
|
|
47
|
+
var HOUR = 60 * MIN;
|
|
48
|
+
var DAY = 24 * HOUR;
|
|
49
|
+
var TIMEFRAME_BANDS = [
|
|
50
|
+
{ key: "s", label: "Sec", fromMs: 0 },
|
|
51
|
+
{ key: "1", label: "1m", fromMs: MIN },
|
|
52
|
+
{ key: "5", label: "5m", fromMs: 5 * MIN },
|
|
53
|
+
{ key: "15", label: "15m", fromMs: 15 * MIN },
|
|
54
|
+
{ key: "60", label: "1H", fromMs: HOUR },
|
|
55
|
+
{ key: "240", label: "4H", fromMs: 4 * HOUR },
|
|
56
|
+
{ key: "D", label: "D", fromMs: DAY },
|
|
57
|
+
{ key: "W", label: "W", fromMs: 7 * DAY },
|
|
58
|
+
{ key: "M", label: "M", fromMs: 28 * DAY }
|
|
59
|
+
];
|
|
60
|
+
var BAND_KEYS = new Set(TIMEFRAME_BANDS.map((b) => b.key));
|
|
61
|
+
function timeframeBandOf(barMs) {
|
|
62
|
+
if (!(barMs > 0)) return null;
|
|
63
|
+
let key = null;
|
|
64
|
+
for (const band of TIMEFRAME_BANDS) if (barMs >= band.fromMs) key = band.key;
|
|
65
|
+
return key;
|
|
66
|
+
}
|
|
67
|
+
function shownOnTimeframe(showOn, barMs) {
|
|
68
|
+
if (!showOn) return true;
|
|
69
|
+
const band = timeframeBandOf(barMs);
|
|
70
|
+
return band === null || showOn.includes(band);
|
|
71
|
+
}
|
|
72
|
+
function sanitizeShowOn(v) {
|
|
73
|
+
if (!Array.isArray(v)) return void 0;
|
|
74
|
+
const wanted = new Set(v.filter((k) => typeof k === "string" && BAND_KEYS.has(k)));
|
|
75
|
+
return TIMEFRAME_BANDS.map((b) => b.key).filter((k) => wanted.has(k));
|
|
76
|
+
}
|
|
77
|
+
|
|
45
78
|
// src/core/drawings/Drawing.ts
|
|
46
79
|
var _Drawing = class _Drawing {
|
|
47
80
|
// Public so the registry can construct concrete subclasses; `abstract` still
|
|
@@ -58,6 +91,7 @@ var _Drawing = class _Drawing {
|
|
|
58
91
|
this.locked = init.locked ?? false;
|
|
59
92
|
this.visible = init.visible ?? true;
|
|
60
93
|
this.zIndex = init.zIndex ?? 0;
|
|
94
|
+
this.showOn = sanitizeShowOn(init.showOn);
|
|
61
95
|
this.createdAt = init.createdAt ?? Date.now();
|
|
62
96
|
if (init.props) this.readProps(init.props);
|
|
63
97
|
}
|
|
@@ -144,7 +178,10 @@ var _Drawing = class _Drawing {
|
|
|
144
178
|
visible: this.visible,
|
|
145
179
|
zIndex: this.zIndex,
|
|
146
180
|
createdAt: this.createdAt,
|
|
147
|
-
props: this.writeProps()
|
|
181
|
+
props: this.writeProps(),
|
|
182
|
+
// Always present (undefined = every timeframe) so an edit can lift a limit; JSON
|
|
183
|
+
// drops the undefined value, so unlimited drawings save as before.
|
|
184
|
+
showOn: this.showOn ? [...this.showOn] : void 0
|
|
148
185
|
};
|
|
149
186
|
}
|
|
150
187
|
/** Per-type extras to serialize into `props` (override in subclasses). */
|
|
@@ -290,9 +327,16 @@ var TrendLine = class extends Drawing {
|
|
|
290
327
|
if (y1 == null || y2 == null) return null;
|
|
291
328
|
return [proj.xOf(a.time), y1, proj.xOf(b.time), y2];
|
|
292
329
|
}
|
|
330
|
+
/** Which ends run on past the anchors. */
|
|
331
|
+
extension() {
|
|
332
|
+
const { extendLeft: l, extendRight: r } = this.style;
|
|
333
|
+
return l && r ? "both" : l ? "left" : r ? "right" : "none";
|
|
334
|
+
}
|
|
293
335
|
hitTest(px, py, proj, tol) {
|
|
294
336
|
const p = this.pixels(proj);
|
|
295
|
-
|
|
337
|
+
if (!p) return false;
|
|
338
|
+
const [x1, y1, x2, y2] = extendRay(p[0], p[1], p[2], p[3], this.extension(), proj.width, proj.height);
|
|
339
|
+
return distToSegment(px, py, x1, y1, x2, y2) <= tol;
|
|
296
340
|
}
|
|
297
341
|
handlePoints(proj) {
|
|
298
342
|
const p = this.pixels(proj);
|
|
@@ -319,6 +363,8 @@ var TrendLine = class extends Drawing {
|
|
|
319
363
|
fields: [
|
|
320
364
|
...LINE_FIELDS,
|
|
321
365
|
{ path: "style.arrowRight", label: "Arrow", kind: "boolean", group: "line" },
|
|
366
|
+
{ path: "style.extendLeft", label: "Extend left", kind: "boolean", group: "line" },
|
|
367
|
+
{ path: "style.extendRight", label: "Extend right", kind: "boolean", group: "line" },
|
|
322
368
|
...TEXT_FIELDS
|
|
323
369
|
]
|
|
324
370
|
};
|
|
@@ -2778,6 +2824,14 @@ var FibRatios = class extends Drawing {
|
|
|
2778
2824
|
|
|
2779
2825
|
// src/core/drawings/types/FibLevels.ts
|
|
2780
2826
|
var FibLevels = class extends FibRatios {
|
|
2827
|
+
// `declare`d: the base constructor reads saved props before these could be initialized.
|
|
2828
|
+
constructor(init) {
|
|
2829
|
+
super(init);
|
|
2830
|
+
if (this.showRatios === void 0) this.showRatios = true;
|
|
2831
|
+
if (this.showPrices === void 0) this.showPrices = true;
|
|
2832
|
+
if (this.labelSide === void 0) this.labelSide = "left";
|
|
2833
|
+
if (this.background === void 0) this.background = true;
|
|
2834
|
+
}
|
|
2781
2835
|
/** Price of a level for the two anchor prices; subclasses override to change which anchor ratio 0 sits on. */
|
|
2782
2836
|
levelPrice(ratio, p1, p2) {
|
|
2783
2837
|
return p1 + ratio * (p2 - p1);
|
|
@@ -2789,8 +2843,8 @@ var FibLevels = class extends FibRatios {
|
|
|
2789
2843
|
if (!a || !b) return null;
|
|
2790
2844
|
const xa = proj.xOf(a.time);
|
|
2791
2845
|
const xb = proj.xOf(b.time);
|
|
2792
|
-
const x1 = Math.min(xa, xb);
|
|
2793
|
-
const x2 = Math.max(xa, xb);
|
|
2846
|
+
const x1 = this.style.extendLeft ? 0 : Math.min(xa, xb);
|
|
2847
|
+
const x2 = this.style.extendRight ? proj.width : Math.max(xa, xb);
|
|
2794
2848
|
const out = [];
|
|
2795
2849
|
for (const lv of this.levels) {
|
|
2796
2850
|
if (!lv.enabled) continue;
|
|
@@ -2804,6 +2858,7 @@ var FibLevels = class extends FibRatios {
|
|
|
2804
2858
|
entryLines(proj) {
|
|
2805
2859
|
const lines = this.levelLines(proj);
|
|
2806
2860
|
if (!lines) return null;
|
|
2861
|
+
const right = this.labelSide === "right";
|
|
2807
2862
|
return lines.map((l) => ({
|
|
2808
2863
|
color: l.color,
|
|
2809
2864
|
label: l.label,
|
|
@@ -2811,16 +2866,24 @@ var FibLevels = class extends FibRatios {
|
|
|
2811
2866
|
y1: l.y,
|
|
2812
2867
|
x2: l.x2,
|
|
2813
2868
|
y2: l.y,
|
|
2814
|
-
numberText:
|
|
2815
|
-
numberX: l.x1 + 4,
|
|
2869
|
+
numberText: this.levelText(l.ratio, l.price),
|
|
2870
|
+
numberX: right ? l.x2 - 4 : l.x1 + 4,
|
|
2816
2871
|
numberY: l.y - 7,
|
|
2817
|
-
numberAlign: "left",
|
|
2872
|
+
numberAlign: right ? "right" : "left",
|
|
2818
2873
|
labelX: (l.x1 + l.x2) / 2,
|
|
2819
2874
|
labelY: l.y - 7
|
|
2820
2875
|
}));
|
|
2821
2876
|
}
|
|
2877
|
+
/** The text beside a level: its ratio, its price, both, or nothing. */
|
|
2878
|
+
levelText(ratio, price) {
|
|
2879
|
+
const p = price.toFixed(2);
|
|
2880
|
+
if (this.showRatios && this.showPrices) return `${ratio} (${p})`;
|
|
2881
|
+
if (this.showRatios) return String(ratio);
|
|
2882
|
+
return this.showPrices ? p : "";
|
|
2883
|
+
}
|
|
2822
2884
|
fillBands(proj) {
|
|
2823
|
-
|
|
2885
|
+
if (!this.background) return [];
|
|
2886
|
+
const lines = this.levelLines(proj)?.sort((p, q) => p.ratio - q.ratio);
|
|
2824
2887
|
if (!lines) return [];
|
|
2825
2888
|
const bands = [];
|
|
2826
2889
|
for (let i = 1; i < lines.length; i += 1) {
|
|
@@ -2838,6 +2901,26 @@ var FibLevels = class extends FibRatios {
|
|
|
2838
2901
|
if (prices.length === 0) return null;
|
|
2839
2902
|
return { min: Math.min(...prices), max: Math.max(...prices) };
|
|
2840
2903
|
}
|
|
2904
|
+
schema() {
|
|
2905
|
+
const base = super.schema();
|
|
2906
|
+
return {
|
|
2907
|
+
fields: [
|
|
2908
|
+
...base.fields,
|
|
2909
|
+
{ path: "style.extendLeft", label: "Extend left", kind: "boolean", group: "line" },
|
|
2910
|
+
{ path: "style.extendRight", label: "Extend right", kind: "boolean", group: "line" }
|
|
2911
|
+
]
|
|
2912
|
+
};
|
|
2913
|
+
}
|
|
2914
|
+
writeProps() {
|
|
2915
|
+
return { ...super.writeProps(), showRatios: this.showRatios, showPrices: this.showPrices, labelSide: this.labelSide, background: this.background };
|
|
2916
|
+
}
|
|
2917
|
+
readProps(props) {
|
|
2918
|
+
super.readProps(props);
|
|
2919
|
+
if (typeof props.showRatios === "boolean") this.showRatios = props.showRatios;
|
|
2920
|
+
if (typeof props.showPrices === "boolean") this.showPrices = props.showPrices;
|
|
2921
|
+
if (props.labelSide === "left" || props.labelSide === "right") this.labelSide = props.labelSide;
|
|
2922
|
+
if (typeof props.background === "boolean") this.background = props.background;
|
|
2923
|
+
}
|
|
2841
2924
|
};
|
|
2842
2925
|
|
|
2843
2926
|
// src/core/drawings/levelPalette.ts
|
|
@@ -2883,14 +2966,31 @@ var RATIO_COLORS = [
|
|
|
2883
2966
|
[0.75, LEVEL_BLUE],
|
|
2884
2967
|
[0.786, LEVEL_BLUE],
|
|
2885
2968
|
[1, LEVEL_ANCHOR],
|
|
2969
|
+
[0.705, LEVEL_AMBER],
|
|
2970
|
+
[0.886, LEVEL_PURPLE],
|
|
2886
2971
|
[1.272, LEVEL_BLUE],
|
|
2887
2972
|
[1.382, LEVEL_ORANGE],
|
|
2973
|
+
[1.414, LEVEL_AQUA],
|
|
2888
2974
|
[1.618, LEVEL_RED],
|
|
2889
2975
|
[2, LEVEL_ANCHOR],
|
|
2976
|
+
[2.272, LEVEL_VIOLET],
|
|
2890
2977
|
[2.382, LEVEL_ORANGE],
|
|
2978
|
+
[2.414, LEVEL_PINK],
|
|
2891
2979
|
[2.618, LEVEL_ORANGE],
|
|
2892
2980
|
[3, LEVEL_ANCHOR],
|
|
2981
|
+
[3.272, LEVEL_CORAL],
|
|
2982
|
+
[3.618, LEVEL_PURPLE],
|
|
2893
2983
|
[4.236, LEVEL_GREEN],
|
|
2984
|
+
[4.618, LEVEL_PINK],
|
|
2985
|
+
// Beyond the swing's end (targets): blues, deepening with distance.
|
|
2986
|
+
[-0.27, LEVEL_CYAN],
|
|
2987
|
+
[-0.272, LEVEL_CYAN],
|
|
2988
|
+
[-0.62, LEVEL_BLUE],
|
|
2989
|
+
[-0.618, LEVEL_BLUE],
|
|
2990
|
+
[-1, LEVEL_AQUA],
|
|
2991
|
+
[-1.5, LEVEL_VIOLET],
|
|
2992
|
+
[-2, LEVEL_PURPLE],
|
|
2993
|
+
[-2.5, LEVEL_PINK],
|
|
2894
2994
|
[6.854, LEVEL_TEAL],
|
|
2895
2995
|
[11.09, LEVEL_BLUE]
|
|
2896
2996
|
];
|
|
@@ -2917,8 +3017,41 @@ function cycleLevels(count, enabledCount = count) {
|
|
|
2917
3017
|
}));
|
|
2918
3018
|
}
|
|
2919
3019
|
|
|
3020
|
+
// src/core/drawings/fibPresets.ts
|
|
3021
|
+
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];
|
|
3022
|
+
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];
|
|
3023
|
+
function ladder(ratios, on, colors = {}) {
|
|
3024
|
+
return fibLevels(ratios.map((ratio) => ({ ratio, enabled: on.includes(ratio), color: colors[String(ratio)] })));
|
|
3025
|
+
}
|
|
3026
|
+
var FIB_PRESETS = [
|
|
3027
|
+
{
|
|
3028
|
+
key: "classic",
|
|
3029
|
+
label: "Classic",
|
|
3030
|
+
reverse: false,
|
|
3031
|
+
levels: ladder(LADDER, [0, 0.236, 0.382, 0.5, 0.618, 0.786, 1])
|
|
3032
|
+
},
|
|
3033
|
+
{
|
|
3034
|
+
key: "extension",
|
|
3035
|
+
label: "Extension",
|
|
3036
|
+
reverse: true,
|
|
3037
|
+
levels: ladder(LADDER, [0, 1, 1.272, 1.414, 1.618, 2, 2.618, 3.618, 4.236])
|
|
3038
|
+
},
|
|
3039
|
+
{
|
|
3040
|
+
key: "ote",
|
|
3041
|
+
label: "OTE",
|
|
3042
|
+
reverse: false,
|
|
3043
|
+
// The entry zone reads as one band.
|
|
3044
|
+
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 })
|
|
3045
|
+
}
|
|
3046
|
+
];
|
|
3047
|
+
function matchFibPreset(levels, reverse) {
|
|
3048
|
+
const key = (ls) => JSON.stringify(ls.map((l) => [l.ratio, l.color, l.enabled, l.label ?? ""]));
|
|
3049
|
+
const mine = key(levels);
|
|
3050
|
+
return FIB_PRESETS.find((p) => p.reverse === reverse && key(p.levels) === mine)?.key ?? null;
|
|
3051
|
+
}
|
|
3052
|
+
|
|
2920
3053
|
// src/core/drawings/types/FibRetracement.ts
|
|
2921
|
-
var LEVELS =
|
|
3054
|
+
var LEVELS = FIB_PRESETS[0].levels;
|
|
2922
3055
|
var FibRetracement = class extends FibLevels {
|
|
2923
3056
|
constructor(init) {
|
|
2924
3057
|
super(init);
|
|
@@ -2941,7 +3074,11 @@ var FibRetracement = class extends FibLevels {
|
|
|
2941
3074
|
};
|
|
2942
3075
|
|
|
2943
3076
|
// src/core/drawings/types/FibExtension.ts
|
|
2944
|
-
var LEVELS2 =
|
|
3077
|
+
var LEVELS2 = ladder(
|
|
3078
|
+
[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],
|
|
3079
|
+
[0, 0.382, 0.618, 1, 1.272, 1.618, 2.618],
|
|
3080
|
+
{ "2.618": LEVEL_PURPLE }
|
|
3081
|
+
);
|
|
2945
3082
|
var FibExtension = class extends FibLevels {
|
|
2946
3083
|
constructor() {
|
|
2947
3084
|
super(...arguments);
|
|
@@ -4528,20 +4665,20 @@ function signed(n) {
|
|
|
4528
4665
|
}
|
|
4529
4666
|
function formatDuration(ms) {
|
|
4530
4667
|
const m = Math.abs(ms);
|
|
4531
|
-
const
|
|
4668
|
+
const DAY2 = 864e5;
|
|
4532
4669
|
const HR = 36e5;
|
|
4533
|
-
const
|
|
4534
|
-
if (m >=
|
|
4535
|
-
const d = Math.floor(m /
|
|
4536
|
-
const h = Math.round(m %
|
|
4670
|
+
const MIN2 = 6e4;
|
|
4671
|
+
if (m >= DAY2) {
|
|
4672
|
+
const d = Math.floor(m / DAY2);
|
|
4673
|
+
const h = Math.round(m % DAY2 / HR);
|
|
4537
4674
|
return h ? `${d}d ${h}h` : `${d}d`;
|
|
4538
4675
|
}
|
|
4539
4676
|
if (m >= HR) {
|
|
4540
4677
|
const h = Math.floor(m / HR);
|
|
4541
|
-
const mn = Math.round(m % HR /
|
|
4678
|
+
const mn = Math.round(m % HR / MIN2);
|
|
4542
4679
|
return mn ? `${h}h ${mn}m` : `${h}h`;
|
|
4543
4680
|
}
|
|
4544
|
-
if (m >=
|
|
4681
|
+
if (m >= MIN2) return `${Math.round(m / MIN2)}m`;
|
|
4545
4682
|
return `${Math.round(m / 1e3)}s`;
|
|
4546
4683
|
}
|
|
4547
4684
|
var MeasureBox = class extends Drawing {
|
|
@@ -5021,6 +5158,11 @@ var MAGNIFIER_TIMEFRAME_OPTIONS = [
|
|
|
5021
5158
|
{ value: "240", label: "4h", ms: 144e5 },
|
|
5022
5159
|
{ value: "D", label: "1D", ms: 864e5 }
|
|
5023
5160
|
];
|
|
5161
|
+
function magnifierTimeframesBelow(chartMs) {
|
|
5162
|
+
if (!(chartMs > 0)) return [...MAGNIFIER_TIMEFRAME_OPTIONS];
|
|
5163
|
+
const lower = MAGNIFIER_TIMEFRAME_OPTIONS.filter((o) => o.ms > 0 && o.ms < chartMs);
|
|
5164
|
+
return lower.length > 0 ? [MAGNIFIER_TIMEFRAME_OPTIONS[0], ...lower] : [];
|
|
5165
|
+
}
|
|
5024
5166
|
function magnifierTimeframeLabel(value) {
|
|
5025
5167
|
const opt = MAGNIFIER_TIMEFRAME_OPTIONS.find((o) => o.value === value);
|
|
5026
5168
|
if (opt) return opt.label;
|
|
@@ -5115,6 +5257,393 @@ var Magnifier = class extends Drawing {
|
|
|
5115
5257
|
}
|
|
5116
5258
|
};
|
|
5117
5259
|
|
|
5260
|
+
// src/core/drawings/priceAction.ts
|
|
5261
|
+
var GAP_REACH = 3;
|
|
5262
|
+
function nearestBarIndex(bars, time) {
|
|
5263
|
+
if (bars.length === 0) return -1;
|
|
5264
|
+
let lo = 0;
|
|
5265
|
+
let hi = bars.length - 1;
|
|
5266
|
+
while (lo < hi) {
|
|
5267
|
+
const mid = lo + hi >> 1;
|
|
5268
|
+
if (bars[mid].time < time) lo = mid + 1;
|
|
5269
|
+
else hi = mid;
|
|
5270
|
+
}
|
|
5271
|
+
if (lo > 0 && Math.abs(bars[lo - 1].time - time) <= Math.abs(bars[lo].time - time)) return lo - 1;
|
|
5272
|
+
return lo;
|
|
5273
|
+
}
|
|
5274
|
+
function gapAt(bars, i) {
|
|
5275
|
+
const prev = bars[i - 1];
|
|
5276
|
+
const next = bars[i + 1];
|
|
5277
|
+
if (!prev || !next || !bars[i]) return null;
|
|
5278
|
+
if (next.low > prev.high) return { bull: true, top: next.low, bottom: prev.high };
|
|
5279
|
+
if (next.high < prev.low) return { bull: false, top: prev.low, bottom: next.high };
|
|
5280
|
+
return null;
|
|
5281
|
+
}
|
|
5282
|
+
function nearestGap(bars, i) {
|
|
5283
|
+
for (let k = 0; k <= GAP_REACH; k += 1) {
|
|
5284
|
+
for (const j of k === 0 ? [i] : [i - k, i + k]) {
|
|
5285
|
+
const g = gapAt(bars, j);
|
|
5286
|
+
if (g) return { index: j, ...g };
|
|
5287
|
+
}
|
|
5288
|
+
}
|
|
5289
|
+
return null;
|
|
5290
|
+
}
|
|
5291
|
+
function gapState(bars, i) {
|
|
5292
|
+
const g = nearestGap(bars, i);
|
|
5293
|
+
if (!g) return null;
|
|
5294
|
+
const { index, bull, top, bottom } = g;
|
|
5295
|
+
const mid = (top + bottom) / 2;
|
|
5296
|
+
let tested = null;
|
|
5297
|
+
let half = null;
|
|
5298
|
+
let filled = null;
|
|
5299
|
+
let inverted = null;
|
|
5300
|
+
for (let j = index + 2; j < bars.length && inverted === null; j += 1) {
|
|
5301
|
+
const b = bars[j];
|
|
5302
|
+
const reach = bull ? b.low : b.high;
|
|
5303
|
+
const into = (v) => bull ? reach <= v : reach >= v;
|
|
5304
|
+
if (tested === null && into(bull ? top : bottom)) tested = j;
|
|
5305
|
+
if (half === null && into(mid)) half = j;
|
|
5306
|
+
if (filled === null && into(bull ? bottom : top)) filled = j;
|
|
5307
|
+
if (filled !== null && (bull ? b.close < bottom : b.close > top)) inverted = j;
|
|
5308
|
+
}
|
|
5309
|
+
return { index, bull, top, bottom, mid, tested, half, filled, inverted };
|
|
5310
|
+
}
|
|
5311
|
+
function blockState(bars, i, range) {
|
|
5312
|
+
const c = bars[i];
|
|
5313
|
+
if (!c) return null;
|
|
5314
|
+
const bull = c.close < c.open;
|
|
5315
|
+
const top = range === "body" ? Math.max(c.open, c.close) : c.high;
|
|
5316
|
+
const bottom = range === "body" ? Math.min(c.open, c.close) : c.low;
|
|
5317
|
+
const mid = (top + bottom) / 2;
|
|
5318
|
+
let left = false;
|
|
5319
|
+
let tested = null;
|
|
5320
|
+
let half = null;
|
|
5321
|
+
let broken = null;
|
|
5322
|
+
let leftAfterBreak = false;
|
|
5323
|
+
let retest = null;
|
|
5324
|
+
for (let j = i + 1; j < bars.length && retest === null; j += 1) {
|
|
5325
|
+
const b = bars[j];
|
|
5326
|
+
if (broken === null) {
|
|
5327
|
+
if (!left) left = bull ? b.low > top : b.high < bottom;
|
|
5328
|
+
else {
|
|
5329
|
+
if (tested === null && (bull ? b.low <= top : b.high >= bottom)) tested = j;
|
|
5330
|
+
if (half === null && (bull ? b.low <= mid : b.high >= mid)) half = j;
|
|
5331
|
+
}
|
|
5332
|
+
if (bull ? b.close < bottom : b.close > top) broken = j;
|
|
5333
|
+
} else if (!leftAfterBreak) leftAfterBreak = bull ? b.high < bottom : b.low > top;
|
|
5334
|
+
else if (bull ? b.high >= bottom : b.low <= top) retest = j;
|
|
5335
|
+
}
|
|
5336
|
+
return { index: i, bull, top, bottom, mid, tested, half, broken, retest };
|
|
5337
|
+
}
|
|
5338
|
+
function liquidityState(bars, i, side) {
|
|
5339
|
+
const c = bars[i];
|
|
5340
|
+
if (!c) return null;
|
|
5341
|
+
const high = side === "high";
|
|
5342
|
+
const price = high ? c.high : c.low;
|
|
5343
|
+
let swept = null;
|
|
5344
|
+
let broken = null;
|
|
5345
|
+
for (let j = i + 1; j < bars.length && broken === null; j += 1) {
|
|
5346
|
+
const b = bars[j];
|
|
5347
|
+
if (high ? b.close > price : b.close < price) broken = j;
|
|
5348
|
+
else if (swept === null && (high ? b.high > price : b.low < price)) swept = j;
|
|
5349
|
+
}
|
|
5350
|
+
return { index: i, high, price, swept, broken };
|
|
5351
|
+
}
|
|
5352
|
+
|
|
5353
|
+
// src/core/drawings/types/PriceActionZone.ts
|
|
5354
|
+
var candlesSeen = /* @__PURE__ */ new WeakMap();
|
|
5355
|
+
var PriceActionTool = class extends Drawing {
|
|
5356
|
+
anchorSchema() {
|
|
5357
|
+
return { min: 1, max: 1, slots: [{ role: "candle", free: "x" }] };
|
|
5358
|
+
}
|
|
5359
|
+
/** The chart's candles, and the one nearest the anchor. */
|
|
5360
|
+
candles(proj) {
|
|
5361
|
+
const a = this.anchors[0];
|
|
5362
|
+
if (!a) return null;
|
|
5363
|
+
let bars = candlesSeen.get(proj);
|
|
5364
|
+
if (!bars) {
|
|
5365
|
+
bars = proj.barsInRange?.(Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY) ?? [];
|
|
5366
|
+
candlesSeen.set(proj, bars);
|
|
5367
|
+
}
|
|
5368
|
+
return bars.length > 0 ? { bars, at: nearestBarIndex(bars, a.time) } : null;
|
|
5369
|
+
}
|
|
5370
|
+
/** Half a candle's width at bar `i`, in pixels. */
|
|
5371
|
+
halfBar(proj, bars, i) {
|
|
5372
|
+
const a = bars[Math.max(0, i - 1)];
|
|
5373
|
+
const b = bars[Math.min(bars.length - 1, Math.max(1, i))];
|
|
5374
|
+
if (!a || !b || a === b) return 3;
|
|
5375
|
+
return Math.max(1, Math.abs(proj.xOf(b.time) - proj.xOf(a.time)) / 2);
|
|
5376
|
+
}
|
|
5377
|
+
/** Pixel x for the right edge of a zone that stops at bar `end`, or runs on to the chart's edge. */
|
|
5378
|
+
rightEdge(proj, bars, end) {
|
|
5379
|
+
if (end === null) return Math.max(proj.width, proj.xOf(bars[bars.length - 1].time));
|
|
5380
|
+
return proj.xOf(bars[end].time) + this.halfBar(proj, bars, end);
|
|
5381
|
+
}
|
|
5382
|
+
/** The anchor itself, for a tool with nothing on the candles to hang its handle on. */
|
|
5383
|
+
anchorHandle(proj) {
|
|
5384
|
+
const a = this.anchors[0];
|
|
5385
|
+
const y = a ? proj.yOf(a.price, this.paneId) : null;
|
|
5386
|
+
return a && y != null ? [[proj.xOf(a.time), y]] : [];
|
|
5387
|
+
}
|
|
5388
|
+
hitHandle(px, py, proj, tol) {
|
|
5389
|
+
return handleAt(px, py, this.handlePoints(proj), tol + 3);
|
|
5390
|
+
}
|
|
5391
|
+
priceRange() {
|
|
5392
|
+
return null;
|
|
5393
|
+
}
|
|
5394
|
+
};
|
|
5395
|
+
var PriceActionZone = class extends PriceActionTool {
|
|
5396
|
+
/** The zone's pixel layout, or null when the candles don't form one. */
|
|
5397
|
+
zone(proj) {
|
|
5398
|
+
const c = this.candles(proj);
|
|
5399
|
+
const f = c && this.formation(c.bars, c.at);
|
|
5400
|
+
if (!c || !f) return null;
|
|
5401
|
+
const yt = proj.yOf(f.top, this.paneId);
|
|
5402
|
+
const yb = proj.yOf(f.bottom, this.paneId);
|
|
5403
|
+
if (yt == null || yb == null) return null;
|
|
5404
|
+
const { bars } = c;
|
|
5405
|
+
const s = this.settings();
|
|
5406
|
+
const left = (i) => proj.xOf(bars[i].time) - this.halfBar(proj, bars, i);
|
|
5407
|
+
const yTop = Math.min(yt, yb);
|
|
5408
|
+
const yBottom = Math.max(yt, yb);
|
|
5409
|
+
const midY = proj.yOf(f.mid, this.paneId) ?? (yTop + yBottom) / 2;
|
|
5410
|
+
const flip = f.flip && { x1: left(f.flip.from), x2: this.rightEdge(proj, bars, f.flip.to), fill: f.bull ? s.downColor : s.upColor };
|
|
5411
|
+
const edge = s.extend === "tested" ? f.bull ? f.top : f.bottom : s.extend === "half" ? f.mid : f.bull ? f.bottom : f.top;
|
|
5412
|
+
const edgeY = proj.yOf(edge, this.paneId);
|
|
5413
|
+
return {
|
|
5414
|
+
x1: left(f.start),
|
|
5415
|
+
x2: this.rightEdge(proj, bars, f.end),
|
|
5416
|
+
yTop,
|
|
5417
|
+
yBottom,
|
|
5418
|
+
fill: f.bull ? s.upColor : s.downColor,
|
|
5419
|
+
border: s.border,
|
|
5420
|
+
midY: s.midline ? midY : null,
|
|
5421
|
+
faded: f.end !== null && s.fade && !flip,
|
|
5422
|
+
marker: f.end !== null && !flip && edgeY != null ? { x: proj.xOf(bars[f.end].time), y: edgeY } : null,
|
|
5423
|
+
flip,
|
|
5424
|
+
handle: [proj.xOf(bars[f.index].time), midY]
|
|
5425
|
+
};
|
|
5426
|
+
}
|
|
5427
|
+
hitTest(px, py, proj, tol) {
|
|
5428
|
+
const z = this.zone(proj);
|
|
5429
|
+
if (!z) {
|
|
5430
|
+
const a = this.anchors[0];
|
|
5431
|
+
return a != null && Math.abs(px - proj.xOf(a.time)) <= tol;
|
|
5432
|
+
}
|
|
5433
|
+
const inY = py >= z.yTop - tol && py <= z.yBottom + tol;
|
|
5434
|
+
if (inY && px >= z.x1 - tol && px <= z.x2 + tol) return true;
|
|
5435
|
+
return z.flip != null && inY && px >= z.flip.x1 - tol && px <= z.flip.x2 + tol;
|
|
5436
|
+
}
|
|
5437
|
+
handlePoints(proj) {
|
|
5438
|
+
const z = this.zone(proj);
|
|
5439
|
+
return z ? [z.handle] : this.anchorHandle(proj);
|
|
5440
|
+
}
|
|
5441
|
+
bounds(proj) {
|
|
5442
|
+
const z = this.zone(proj);
|
|
5443
|
+
if (!z) return null;
|
|
5444
|
+
const right = Math.min(proj.width, z.flip ? z.flip.x2 : z.x2);
|
|
5445
|
+
return { x: z.x1, y: z.yTop, w: Math.max(1, right - z.x1), h: Math.max(1, z.yBottom - z.yTop) };
|
|
5446
|
+
}
|
|
5447
|
+
};
|
|
5448
|
+
|
|
5449
|
+
// src/core/drawings/types/FairValueGap.ts
|
|
5450
|
+
var EXTEND_OPTIONS = [
|
|
5451
|
+
{ value: "tested", label: "Until tested" },
|
|
5452
|
+
{ value: "half", label: "Until 50%" },
|
|
5453
|
+
{ value: "filled", label: "Until filled" },
|
|
5454
|
+
{ value: "always", label: "Always" }
|
|
5455
|
+
];
|
|
5456
|
+
function defaults() {
|
|
5457
|
+
return { extend: "filled", upColor: `${BULLISH}33`, downColor: `${BEARISH}33`, midline: true, border: false, fade: true, inverse: false };
|
|
5458
|
+
}
|
|
5459
|
+
var FairValueGap = class extends PriceActionZone {
|
|
5460
|
+
constructor(init) {
|
|
5461
|
+
super(init);
|
|
5462
|
+
this.type = "fairvaluegap";
|
|
5463
|
+
if (!this.gap) this.gap = defaults();
|
|
5464
|
+
}
|
|
5465
|
+
settings() {
|
|
5466
|
+
return this.gap;
|
|
5467
|
+
}
|
|
5468
|
+
formation(bars, at) {
|
|
5469
|
+
const s = gapState(bars, at);
|
|
5470
|
+
if (!s) return null;
|
|
5471
|
+
const { extend, inverse } = this.gap;
|
|
5472
|
+
const flip = inverse && extend === "filled" && s.inverted !== null ? { from: s.inverted, to: null } : null;
|
|
5473
|
+
return { ...s, start: s.index - 1, end: extend === "always" ? null : s[extend], flip };
|
|
5474
|
+
}
|
|
5475
|
+
schema() {
|
|
5476
|
+
return {
|
|
5477
|
+
fields: [
|
|
5478
|
+
{ path: "gap.extend", label: "Extend right", kind: "select", options: EXTEND_OPTIONS, group: "behavior" },
|
|
5479
|
+
{ path: "gap.upColor", label: "Bullish", kind: "color", group: "fill" },
|
|
5480
|
+
{ path: "gap.downColor", label: "Bearish", kind: "color", group: "fill" },
|
|
5481
|
+
{ path: "gap.midline", label: "Midline", kind: "boolean", group: "line" },
|
|
5482
|
+
{ path: "gap.border", label: "Border", kind: "boolean", group: "line" },
|
|
5483
|
+
{ path: "gap.fade", label: "Fade at end", kind: "boolean", group: "behavior", when: { path: "gap.extend", in: ["tested", "half", "filled"] } },
|
|
5484
|
+
{ path: "gap.inverse", label: "Flip on close", kind: "boolean", group: "behavior", when: { path: "gap.extend", in: ["filled"] } }
|
|
5485
|
+
]
|
|
5486
|
+
};
|
|
5487
|
+
}
|
|
5488
|
+
writeProps() {
|
|
5489
|
+
return { ...this.gap };
|
|
5490
|
+
}
|
|
5491
|
+
readProps(props) {
|
|
5492
|
+
const d = defaults();
|
|
5493
|
+
const p = props;
|
|
5494
|
+
this.gap = {
|
|
5495
|
+
extend: EXTEND_OPTIONS.some((o) => o.value === p.extend) ? p.extend : d.extend,
|
|
5496
|
+
upColor: typeof p.upColor === "string" ? p.upColor : d.upColor,
|
|
5497
|
+
downColor: typeof p.downColor === "string" ? p.downColor : d.downColor,
|
|
5498
|
+
midline: typeof p.midline === "boolean" ? p.midline : d.midline,
|
|
5499
|
+
border: typeof p.border === "boolean" ? p.border : d.border,
|
|
5500
|
+
fade: typeof p.fade === "boolean" ? p.fade : d.fade,
|
|
5501
|
+
inverse: typeof p.inverse === "boolean" ? p.inverse : d.inverse
|
|
5502
|
+
};
|
|
5503
|
+
}
|
|
5504
|
+
};
|
|
5505
|
+
|
|
5506
|
+
// src/core/drawings/types/OrderBlock.ts
|
|
5507
|
+
var RANGE_OPTIONS = [
|
|
5508
|
+
{ value: "body", label: "Body" },
|
|
5509
|
+
{ value: "wick", label: "Full range" }
|
|
5510
|
+
];
|
|
5511
|
+
var EXTEND_OPTIONS2 = [
|
|
5512
|
+
{ value: "tested", label: "Until tested" },
|
|
5513
|
+
{ value: "half", label: "Until 50%" },
|
|
5514
|
+
{ value: "broken", label: "Until broken" },
|
|
5515
|
+
{ value: "always", label: "Always" }
|
|
5516
|
+
];
|
|
5517
|
+
function defaults2() {
|
|
5518
|
+
return { range: "body", extend: "broken", upColor: `${BULLISH}29`, downColor: `${BEARISH}29`, midline: true, border: true, fade: true, breaker: true };
|
|
5519
|
+
}
|
|
5520
|
+
var OrderBlock = class extends PriceActionZone {
|
|
5521
|
+
constructor(init) {
|
|
5522
|
+
super(init);
|
|
5523
|
+
this.type = "orderblock";
|
|
5524
|
+
if (!this.block) this.block = defaults2();
|
|
5525
|
+
}
|
|
5526
|
+
settings() {
|
|
5527
|
+
return this.block;
|
|
5528
|
+
}
|
|
5529
|
+
formation(bars, at) {
|
|
5530
|
+
const s = blockState(bars, at, this.block.range);
|
|
5531
|
+
if (!s) return null;
|
|
5532
|
+
const { extend, breaker } = this.block;
|
|
5533
|
+
const flip = breaker && extend === "broken" && s.broken !== null ? { from: s.broken, to: s.retest } : null;
|
|
5534
|
+
return { ...s, start: s.index, end: extend === "always" ? null : s[extend], flip };
|
|
5535
|
+
}
|
|
5536
|
+
schema() {
|
|
5537
|
+
return {
|
|
5538
|
+
fields: [
|
|
5539
|
+
{ path: "block.range", label: "Zone", kind: "select", options: RANGE_OPTIONS, group: "behavior" },
|
|
5540
|
+
{ path: "block.extend", label: "Extend right", kind: "select", options: EXTEND_OPTIONS2, group: "behavior" },
|
|
5541
|
+
{ path: "block.upColor", label: "Bullish", kind: "color", group: "fill" },
|
|
5542
|
+
{ path: "block.downColor", label: "Bearish", kind: "color", group: "fill" },
|
|
5543
|
+
{ path: "block.midline", label: "Midline", kind: "boolean", group: "line" },
|
|
5544
|
+
{ path: "block.border", label: "Border", kind: "boolean", group: "line" },
|
|
5545
|
+
{ path: "block.fade", label: "Fade at end", kind: "boolean", group: "behavior", when: { path: "block.extend", in: ["tested", "half", "broken"] } },
|
|
5546
|
+
{ path: "block.breaker", label: "Breaker", kind: "boolean", group: "behavior", when: { path: "block.extend", in: ["broken"] } }
|
|
5547
|
+
]
|
|
5548
|
+
};
|
|
5549
|
+
}
|
|
5550
|
+
writeProps() {
|
|
5551
|
+
return { ...this.block };
|
|
5552
|
+
}
|
|
5553
|
+
readProps(props) {
|
|
5554
|
+
const d = defaults2();
|
|
5555
|
+
const p = props;
|
|
5556
|
+
this.block = {
|
|
5557
|
+
range: p.range === "body" || p.range === "wick" ? p.range : d.range,
|
|
5558
|
+
extend: EXTEND_OPTIONS2.some((o) => o.value === p.extend) ? p.extend : d.extend,
|
|
5559
|
+
upColor: typeof p.upColor === "string" ? p.upColor : d.upColor,
|
|
5560
|
+
downColor: typeof p.downColor === "string" ? p.downColor : d.downColor,
|
|
5561
|
+
midline: typeof p.midline === "boolean" ? p.midline : d.midline,
|
|
5562
|
+
border: typeof p.border === "boolean" ? p.border : d.border,
|
|
5563
|
+
fade: typeof p.fade === "boolean" ? p.fade : d.fade,
|
|
5564
|
+
breaker: typeof p.breaker === "boolean" ? p.breaker : d.breaker
|
|
5565
|
+
};
|
|
5566
|
+
}
|
|
5567
|
+
};
|
|
5568
|
+
|
|
5569
|
+
// src/core/drawings/types/Liquidity.ts
|
|
5570
|
+
var EXTEND_OPTIONS3 = [
|
|
5571
|
+
{ value: "swept", label: "Until swept" },
|
|
5572
|
+
{ value: "broken", label: "Until broken" },
|
|
5573
|
+
{ value: "always", label: "Always" }
|
|
5574
|
+
];
|
|
5575
|
+
function defaults3() {
|
|
5576
|
+
return { extend: "swept", markSweep: true };
|
|
5577
|
+
}
|
|
5578
|
+
var Liquidity = class extends PriceActionTool {
|
|
5579
|
+
constructor(init) {
|
|
5580
|
+
super(init);
|
|
5581
|
+
this.type = "liquidity";
|
|
5582
|
+
if (!this.liq) this.liq = defaults3();
|
|
5583
|
+
}
|
|
5584
|
+
anchorSchema() {
|
|
5585
|
+
return { min: 1, max: 1, slots: [{ role: "candle", free: "both" }] };
|
|
5586
|
+
}
|
|
5587
|
+
state(proj) {
|
|
5588
|
+
const c = this.candles(proj);
|
|
5589
|
+
const a = this.anchors[0];
|
|
5590
|
+
if (!c || !a) return null;
|
|
5591
|
+
const bar = c.bars[c.at];
|
|
5592
|
+
return liquidityState(c.bars, c.at, a.price >= (bar.high + bar.low) / 2 ? "high" : "low");
|
|
5593
|
+
}
|
|
5594
|
+
line(proj) {
|
|
5595
|
+
const c = this.candles(proj);
|
|
5596
|
+
const s = this.state(proj);
|
|
5597
|
+
if (!c || !s) return null;
|
|
5598
|
+
const y = proj.yOf(s.price, this.paneId);
|
|
5599
|
+
if (y == null) return null;
|
|
5600
|
+
const { bars } = c;
|
|
5601
|
+
const { extend, markSweep } = this.liq;
|
|
5602
|
+
const end = extend === "always" ? null : extend === "broken" ? s.broken : s.swept ?? s.broken;
|
|
5603
|
+
const x1 = proj.xOf(bars[s.index].time);
|
|
5604
|
+
let sweep = null;
|
|
5605
|
+
if (markSweep && s.swept !== null && (end === null || s.swept <= end)) {
|
|
5606
|
+
const b = bars[s.swept];
|
|
5607
|
+
const wick = proj.yOf(s.high ? b.high : b.low, this.paneId);
|
|
5608
|
+
if (wick != null) sweep = { x: proj.xOf(b.time), y: wick + (s.high ? -9 : 9) };
|
|
5609
|
+
}
|
|
5610
|
+
return { x1, x2: this.rightEdge(proj, bars, end), y, sweep, handle: [x1, y] };
|
|
5611
|
+
}
|
|
5612
|
+
hitTest(px, py, proj, tol) {
|
|
5613
|
+
const l = this.line(proj);
|
|
5614
|
+
return l != null && px >= l.x1 - tol && px <= l.x2 + tol && Math.abs(py - l.y) <= tol;
|
|
5615
|
+
}
|
|
5616
|
+
handlePoints(proj) {
|
|
5617
|
+
const l = this.line(proj);
|
|
5618
|
+
return l ? [l.handle] : this.anchorHandle(proj);
|
|
5619
|
+
}
|
|
5620
|
+
bounds(proj) {
|
|
5621
|
+
const l = this.line(proj);
|
|
5622
|
+
if (!l) return null;
|
|
5623
|
+
return { x: l.x1, y: l.y - 4, w: Math.max(1, Math.min(proj.width, l.x2) - l.x1), h: 8 };
|
|
5624
|
+
}
|
|
5625
|
+
schema() {
|
|
5626
|
+
return {
|
|
5627
|
+
fields: [
|
|
5628
|
+
...LINE_FIELDS,
|
|
5629
|
+
{ path: "liq.extend", label: "Extend right", kind: "select", options: EXTEND_OPTIONS3, group: "behavior" },
|
|
5630
|
+
{ path: "liq.markSweep", label: "Mark sweep", kind: "boolean", group: "behavior" }
|
|
5631
|
+
]
|
|
5632
|
+
};
|
|
5633
|
+
}
|
|
5634
|
+
writeProps() {
|
|
5635
|
+
return { ...this.liq };
|
|
5636
|
+
}
|
|
5637
|
+
readProps(props) {
|
|
5638
|
+
const d = defaults3();
|
|
5639
|
+
const p = props;
|
|
5640
|
+
this.liq = {
|
|
5641
|
+
extend: EXTEND_OPTIONS3.some((o) => o.value === p.extend) ? p.extend : d.extend,
|
|
5642
|
+
markSweep: typeof p.markSweep === "boolean" ? p.markSweep : d.markSweep
|
|
5643
|
+
};
|
|
5644
|
+
}
|
|
5645
|
+
};
|
|
5646
|
+
|
|
5118
5647
|
// src/core/drawings/registry.ts
|
|
5119
5648
|
var REGISTRY2 = /* @__PURE__ */ new Map();
|
|
5120
5649
|
function registerDrawingType(meta) {
|
|
@@ -5808,6 +6337,36 @@ registerDrawingType({
|
|
|
5808
6337
|
defaultStyle: { lineColor: BULLISH, lineWidth: 1, lineStyle: "solid" },
|
|
5809
6338
|
create: (init) => new FixedRangeVolumeProfile(init)
|
|
5810
6339
|
});
|
|
6340
|
+
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"/>');
|
|
6341
|
+
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"/>');
|
|
6342
|
+
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"/>');
|
|
6343
|
+
registerDrawingType({
|
|
6344
|
+
type: "fairvaluegap",
|
|
6345
|
+
group: "priceaction",
|
|
6346
|
+
label: "Fair Value Gap",
|
|
6347
|
+
icon: FVG_ICON,
|
|
6348
|
+
defaultStyle: { lineColor: BULLISH, lineWidth: 1, lineStyle: "solid" },
|
|
6349
|
+
placementHint: "Click the middle candle of a gap",
|
|
6350
|
+
create: (init) => new FairValueGap(init)
|
|
6351
|
+
});
|
|
6352
|
+
registerDrawingType({
|
|
6353
|
+
type: "orderblock",
|
|
6354
|
+
group: "priceaction",
|
|
6355
|
+
label: "Order Block",
|
|
6356
|
+
icon: ORDER_BLOCK_ICON,
|
|
6357
|
+
defaultStyle: { lineColor: BULLISH, lineWidth: 1, lineStyle: "solid" },
|
|
6358
|
+
placementHint: "Click the candle that forms the block",
|
|
6359
|
+
create: (init) => new OrderBlock(init)
|
|
6360
|
+
});
|
|
6361
|
+
registerDrawingType({
|
|
6362
|
+
type: "liquidity",
|
|
6363
|
+
group: "priceaction",
|
|
6364
|
+
label: "Liquidity",
|
|
6365
|
+
icon: LIQUIDITY_ICON,
|
|
6366
|
+
defaultStyle: { lineColor: WARNING, lineWidth: 1, lineStyle: "solid" },
|
|
6367
|
+
placementHint: "Click near a candle's high or low",
|
|
6368
|
+
create: (init) => new Liquidity(init)
|
|
6369
|
+
});
|
|
5811
6370
|
|
|
5812
6371
|
// src/chart-types/registry.ts
|
|
5813
6372
|
function normalizeSettingsRow(r) {
|
|
@@ -5874,20 +6433,20 @@ function tickerModifierIds() {
|
|
|
5874
6433
|
}
|
|
5875
6434
|
|
|
5876
6435
|
// src/core/renderer-defaults.ts
|
|
5877
|
-
var
|
|
6436
|
+
var defaults4 = /* @__PURE__ */ new Map();
|
|
5878
6437
|
function registerRendererDefaults(values) {
|
|
5879
6438
|
const applied = Object.entries(values);
|
|
5880
|
-
for (const [key, value] of applied)
|
|
6439
|
+
for (const [key, value] of applied) defaults4.set(key, value);
|
|
5881
6440
|
return () => {
|
|
5882
|
-
for (const [key, value] of applied) if (
|
|
6441
|
+
for (const [key, value] of applied) if (defaults4.get(key) === value) defaults4.delete(key);
|
|
5883
6442
|
};
|
|
5884
6443
|
}
|
|
5885
6444
|
function unregisterRendererDefaults(...keys) {
|
|
5886
|
-
if (keys.length === 0)
|
|
5887
|
-
else for (const key of keys)
|
|
6445
|
+
if (keys.length === 0) defaults4.clear();
|
|
6446
|
+
else for (const key of keys) defaults4.delete(key);
|
|
5888
6447
|
}
|
|
5889
6448
|
function rendererDefaults() {
|
|
5890
|
-
return Object.fromEntries(
|
|
6449
|
+
return Object.fromEntries(defaults4);
|
|
5891
6450
|
}
|
|
5892
6451
|
|
|
5893
6452
|
// src/core/model/inputs.ts
|
|
@@ -6722,4 +7281,4 @@ var SidePanel = class {
|
|
|
6722
7281
|
}
|
|
6723
7282
|
};
|
|
6724
7283
|
|
|
6725
|
-
export { AnchoredVwap, ArrowMark, CONTEXT_MENU_BUILTIN_ORDER, Callout, CalloutBase, Comment, DEDEKIND_CURVATURE_OPTIONS, DEFAULT_DRAWING_COLOR, DEFAULT_PANEL_MAX_WIDTH, DEFAULT_PANEL_MIN_WIDTH, DEFAULT_PANEL_ORDER, DEFAULT_PANEL_WIDTH, DIRECTION_OPTIONS, DedekindTessellation, Drawing, FibRatios, FibRetracement, FibSpiral, FixedRangeVolumeProfile, GANN_SQUARE_ARCS, GLYPH_OPTIONS, GannSquare, GlyphStamp, LINE_STYLE_OPTIONS, MACH_NUMBER_OPTIONS, MACH_WAVE_COUNT_OPTIONS,
|
|
7284
|
+
export { AnchoredVwap, ArrowMark, CONTEXT_MENU_BUILTIN_ORDER, Callout, CalloutBase, Comment, DEDEKIND_CURVATURE_OPTIONS, DEFAULT_DRAWING_COLOR, DEFAULT_PANEL_MAX_WIDTH, DEFAULT_PANEL_MIN_WIDTH, DEFAULT_PANEL_ORDER, DEFAULT_PANEL_WIDTH, DIRECTION_OPTIONS, DedekindTessellation, Drawing, FIB_PRESETS, FibLevels, FibRatios, FibRetracement, FibSpiral, FixedRangeVolumeProfile, GANN_SQUARE_ARCS, GLYPH_OPTIONS, GannSquare, GlyphStamp, LINE_STYLE_OPTIONS, Liquidity, MACH_NUMBER_OPTIONS, MACH_WAVE_COUNT_OPTIONS, MachFigure, Magnifier, MeasureBox, Note, OVERRIDABLE_TOPBAR_IDS, PatternDrawing, PositionTool, PriceActionZone, PriceLabel, PriceNote, RadialFib, RegressionChannel, STAMP_SIZE_OPTIONS, SegmentDrawing, SidePanel, Signpost, TEXT_SIZE_OPTIONS, TIMEFRAME_BANDS, TIMEZONES, TOPBAR_BUILTIN_IDS, TOPBAR_DEFAULT_LEFT, TOPBAR_DEFAULT_RIGHT, TextLabel, TrendLine, bodyItems, chartType, chartTypes, clampPanelWidth, composeMenu, createDrawing, defaultText, deserializeDrawing, drawingTypes, foldBaseModulation, formatDuration, getDrawingType, getNativeIndicator, inputDeltas, inputVisible, invertWrite, isExchangeTimezone, isLineLikeSeries, legendActions, legendActionsProviderFor, legendCallouts, legendCalloutsProviderFor, lineSegmentIntersection, magnifierTimeframeLabel, magnifierTimeframesBelow, matchFibPreset, mobilePlacement, nativeIndicatorDescriptors, nativeIndicatorTypes, nativeInstanceChannel, normalizeSettingsRow, normalizeTimezone, paneScaleAt, pinnedTopbarActionIds, priceAxisItems, registerChartType, registerDefaultEngine, registerDrawingType, registerLegendAction, registerLegendCallout, registerNativeIndicator, registerRendererDefaults, registerRendererLayer, registerSidePanel, registerStatePersistence, registerSymbolRanking, registerWidgetAction, registerWidgetAttachment, rendererDefaults, rendererLayers, resetDrawingSettings, resolveEngines, resolveTimezone, resolveTopbarComposition, sanitizeShowOn, scaleChoiceOf, scaleWrites, seriesInScale, seriesShownOn, settingsRowValueKeys, settingsRowVisible, settingsSectionOf, shownOnTimeframe, sidePanels, stableSeriesId, statePersistenceHandlers, symbolRanking, tickerModifierIds, timeAxisItems, timeframeBandOf, timezoneMenuRows, topbarActionOverride, topbarHas, tzButtonLabel, tzMenuLabel, tzOffset, unregisterChartType, unregisterDefaultEngine, unregisterLegendAction, unregisterLegendCallout, unregisterNativeIndicator, unregisterRendererDefaults, unregisterRendererLayer, unregisterSidePanel, unregisterStatePersistence, unregisterWidgetAction, unregisterWidgetAttachment, widgetActions, widgetAttachments };
|