@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.
Files changed (44) hide show
  1. package/dist/{DataProvider-wbtJ3-Sa.d.cts → DataProvider-Bw58CjYy.d.cts} +1 -1
  2. package/dist/{DataProvider-oH78tYXL.d.ts → DataProvider-Byo8pEv0.d.ts} +1 -1
  3. package/dist/{chunk-KWI3YDBW.js → chunk-ALTGHKIM.js} +584 -25
  4. package/dist/{chunk-TO3GIK7Z.js → chunk-AUOB7A5Y.js} +2 -2
  5. package/dist/{chunk-VHGACEHO.js → chunk-I2U4NZD2.js} +7 -1
  6. package/dist/{chunk-2IPXYM4B.js → chunk-MOJ4T26N.js} +88 -5
  7. package/dist/{chunk-HMHA733L.js → chunk-UNUVPQFW.js} +1924 -734
  8. package/dist/{chunk-G7B7ZCBF.js → chunk-WY5H4S4I.js} +1 -1
  9. package/dist/{contributions-BhOBRenr.d.cts → contributions-BY3zSYiZ.d.ts} +56 -5
  10. package/dist/{contributions-HGqnNb_P.d.ts → contributions-DOm40g5-.d.cts} +56 -5
  11. package/dist/index.cjs +2583 -828
  12. package/dist/index.d.cts +9 -15
  13. package/dist/index.d.ts +9 -15
  14. package/dist/index.js +4 -4
  15. package/dist/{options-lMUwmRwh.d.cts → options-CSXbjMM5.d.cts} +64 -4
  16. package/dist/{options-lMUwmRwh.d.ts → options-CSXbjMM5.d.ts} +64 -4
  17. package/dist/{plugin-Cr2Pj8q8.d.ts → plugin-BDxUhGO3.d.ts} +3 -3
  18. package/dist/{plugin-Do5J5xuF.d.cts → plugin-CiQVyETg.d.cts} +3 -3
  19. package/dist/plugin.cjs +555 -17
  20. package/dist/plugin.d.cts +4 -4
  21. package/dist/plugin.d.ts +4 -4
  22. package/dist/plugin.js +2 -2
  23. package/dist/providers/binance.d.cts +2 -2
  24. package/dist/providers/binance.d.ts +2 -2
  25. package/dist/providers/coinbase.d.cts +2 -2
  26. package/dist/providers/coinbase.d.ts +2 -2
  27. package/dist/providers/hyperliquid.d.cts +2 -2
  28. package/dist/providers/hyperliquid.d.ts +2 -2
  29. package/dist/{statusline-model-B-2xGlB_.d.cts → statusline-model-C9tYXuux.d.ts} +19 -4
  30. package/dist/{statusline-model-CY1wzxHg.d.ts → statusline-model-DUBX6Fib.d.cts} +19 -4
  31. package/dist/ui.d.cts +1 -1
  32. package/dist/ui.d.ts +1 -1
  33. package/dist/ui.js +3 -3
  34. package/dist/vela.global.js +2590 -835
  35. package/dist/vela.global.min.js +124 -54
  36. package/dist/widget.cjs +2807 -969
  37. package/dist/widget.d.cts +6 -6
  38. package/dist/widget.d.ts +6 -6
  39. package/dist/widget.js +7 -7
  40. package/dist/workspace.cjs +2807 -969
  41. package/dist/workspace.d.cts +19 -5
  42. package/dist/workspace.d.ts +19 -5
  43. package/dist/workspace.js +6 -6
  44. 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-VHGACEHO.js';
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
- return p != null && distToSegment(px, py, p[0], p[1], p[2], p[3]) <= tol;
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: `${l.ratio} (${l.price.toFixed(2)})`,
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
- const lines = this.levelLines(proj);
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 = fibLevels([0, 0.236, 0.382, 0.5, 0.618, 0.786, 1]);
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 = fibLevels([0, 0.382, 0.618, 1, 1.272, 1.618, { ratio: 2.618, color: LEVEL_PURPLE }]);
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 DAY = 864e5;
4668
+ const DAY2 = 864e5;
4532
4669
  const HR = 36e5;
4533
- const MIN = 6e4;
4534
- if (m >= DAY) {
4535
- const d = Math.floor(m / DAY);
4536
- const h = Math.round(m % DAY / HR);
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 / MIN);
4678
+ const mn = Math.round(m % HR / MIN2);
4542
4679
  return mn ? `${h}h ${mn}m` : `${h}h`;
4543
4680
  }
4544
- if (m >= MIN) return `${Math.round(m / MIN)}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 defaults = /* @__PURE__ */ new Map();
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) defaults.set(key, value);
6439
+ for (const [key, value] of applied) defaults4.set(key, value);
5881
6440
  return () => {
5882
- for (const [key, value] of applied) if (defaults.get(key) === value) defaults.delete(key);
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) defaults.clear();
5887
- else for (const key of keys) defaults.delete(key);
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(defaults);
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, MAGNIFIER_TIMEFRAME_OPTIONS, MachFigure, Magnifier, MeasureBox, Note, OVERRIDABLE_TOPBAR_IDS, PatternDrawing, PositionTool, PriceLabel, PriceNote, RadialFib, RegressionChannel, STAMP_SIZE_OPTIONS, SegmentDrawing, SidePanel, Signpost, TEXT_SIZE_OPTIONS, TIMEZONES, TOPBAR_BUILTIN_IDS, TOPBAR_DEFAULT_LEFT, TOPBAR_DEFAULT_RIGHT, TextLabel, bodyItems, chartType, chartTypes, clampPanelWidth, composeMenu, createDrawing, deserializeDrawing, drawingTypes, foldBaseModulation, formatDuration, getDrawingType, getNativeIndicator, inputDeltas, inputVisible, invertWrite, isExchangeTimezone, isLineLikeSeries, legendActions, legendActionsProviderFor, legendCallouts, legendCalloutsProviderFor, lineSegmentIntersection, magnifierTimeframeLabel, 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, scaleChoiceOf, scaleWrites, seriesInScale, seriesShownOn, settingsRowValueKeys, settingsRowVisible, settingsSectionOf, sidePanels, stableSeriesId, statePersistenceHandlers, symbolRanking, tickerModifierIds, timeAxisItems, timezoneMenuRows, topbarActionOverride, topbarHas, tzButtonLabel, tzMenuLabel, tzOffset, unregisterChartType, unregisterDefaultEngine, unregisterLegendAction, unregisterLegendCallout, unregisterNativeIndicator, unregisterRendererDefaults, unregisterRendererLayer, unregisterSidePanel, unregisterStatePersistence, unregisterWidgetAction, unregisterWidgetAttachment, widgetActions, widgetAttachments };
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 };