@luxalgo/vela 0.7.5 → 0.7.7
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-Dut6lXGM.d.cts → DataProvider-CGa4KHRa.d.cts} +1 -1
- package/dist/{DataProvider-DLeFs1gE.d.ts → DataProvider-CmWUtDVL.d.ts} +1 -1
- package/dist/{chunk-ZADTVRUO.js → chunk-PVGWNF7V.js} +1 -1
- package/dist/{chunk-MCLI6B3S.js → chunk-RVQWJOEE.js} +277 -120
- package/dist/{chunk-BKHSQ4YM.js → chunk-WTWGEB7K.js} +23 -9
- package/dist/{chunk-MNG5XPLV.js → chunk-ZA2XWTGH.js} +94 -37
- package/dist/{contributions-DYtiRtES.d.cts → contributions-DF_Ea07m.d.cts} +25 -2
- package/dist/{contributions-CEkgJKTU.d.ts → contributions-nKOSeLy8.d.ts} +25 -2
- package/dist/index.cjs +285 -127
- package/dist/index.d.cts +22 -7
- package/dist/index.d.ts +22 -7
- package/dist/index.js +2 -2
- package/dist/{options-DNBoMKkX.d.ts → options-D1AJKsn_.d.cts} +10 -0
- package/dist/{options-DNBoMKkX.d.cts → options-D1AJKsn_.d.ts} +10 -0
- package/dist/{plugin-CLn--oP6.d.ts → plugin-0oFDnexb.d.ts} +3 -3
- package/dist/{plugin-DtkeQVAO.d.cts → plugin-DPyVJFoA.d.cts} +3 -3
- package/dist/plugin.d.cts +4 -4
- package/dist/plugin.d.ts +4 -4
- 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-gA__yaog.d.cts → statusline-model-BoWJ3cWQ.d.cts} +18 -5
- package/dist/{statusline-model-DypGXjtr.d.ts → statusline-model-DAFyqVmR.d.ts} +18 -5
- package/dist/ui.cjs +23 -9
- package/dist/ui.d.cts +20 -3
- package/dist/ui.d.ts +20 -3
- package/dist/ui.js +2 -2
- package/dist/vela.global.js +285 -127
- package/dist/vela.global.min.js +59 -49
- package/dist/widget.cjs +389 -161
- package/dist/widget.d.cts +7 -7
- package/dist/widget.d.ts +7 -7
- package/dist/widget.js +5 -5
- package/dist/workspace.cjs +389 -161
- package/dist/workspace.d.cts +40 -8
- package/dist/workspace.d.ts +40 -8
- package/dist/workspace.js +4 -4
- package/package.json +21 -1
|
@@ -2177,7 +2177,8 @@ function addRecent(hex6) {
|
|
|
2177
2177
|
recents.unshift(hex6);
|
|
2178
2178
|
if (recents.length > 10) recents.length = 10;
|
|
2179
2179
|
}
|
|
2180
|
-
function buildColorPicker(color, theme, onChange) {
|
|
2180
|
+
function buildColorPicker(color, theme, onChange, options = {}) {
|
|
2181
|
+
const commit = options.commit ?? "live";
|
|
2181
2182
|
const parsed = splitColor(color);
|
|
2182
2183
|
let curHex = parsed.hex6;
|
|
2183
2184
|
let curAlpha = parsed.alpha;
|
|
@@ -2260,7 +2261,12 @@ function buildColorPicker(color, theme, onChange) {
|
|
|
2260
2261
|
const r = track.getBoundingClientRect();
|
|
2261
2262
|
curAlpha = Math.max(0, Math.min(1, (clientX - r.left) / r.width));
|
|
2262
2263
|
paintOpacity();
|
|
2263
|
-
emit();
|
|
2264
|
+
if (commit === "live") emit();
|
|
2265
|
+
};
|
|
2266
|
+
const endDrag = () => {
|
|
2267
|
+
if (!dragging) return;
|
|
2268
|
+
dragging = false;
|
|
2269
|
+
if (commit === "release") emit();
|
|
2264
2270
|
};
|
|
2265
2271
|
track.addEventListener("pointerdown", (e) => {
|
|
2266
2272
|
e.stopPropagation();
|
|
@@ -2271,7 +2277,8 @@ function buildColorPicker(color, theme, onChange) {
|
|
|
2271
2277
|
track.addEventListener("pointermove", (e) => {
|
|
2272
2278
|
if (dragging) onDrag(e.clientX);
|
|
2273
2279
|
});
|
|
2274
|
-
track.addEventListener("pointerup",
|
|
2280
|
+
track.addEventListener("pointerup", endDrag);
|
|
2281
|
+
track.addEventListener("pointercancel", endDrag);
|
|
2275
2282
|
function emit() {
|
|
2276
2283
|
onChange(combineColor(curHex, curAlpha));
|
|
2277
2284
|
}
|
|
@@ -2294,7 +2301,7 @@ function buildColorPicker(color, theme, onChange) {
|
|
|
2294
2301
|
return root;
|
|
2295
2302
|
}
|
|
2296
2303
|
function colorField(theme, getVal, onVal, opts) {
|
|
2297
|
-
return new ColorField({ theme, getVal, onVal, shape: opts?.shape, id: opts?.id, popover: opts?.popover }).el;
|
|
2304
|
+
return new ColorField({ theme, getVal, onVal, shape: opts?.shape, id: opts?.id, popover: opts?.popover, commit: opts?.commit }).el;
|
|
2298
2305
|
}
|
|
2299
2306
|
var ColorField = class {
|
|
2300
2307
|
constructor(opts) {
|
|
@@ -2303,6 +2310,7 @@ var ColorField = class {
|
|
|
2303
2310
|
this.getVal = opts.getVal;
|
|
2304
2311
|
this.onVal = opts.onVal;
|
|
2305
2312
|
this.popoverOpts = opts.popover;
|
|
2313
|
+
this.commit = opts.commit;
|
|
2306
2314
|
const trigger = document.createElement("button");
|
|
2307
2315
|
trigger.type = "button";
|
|
2308
2316
|
if (opts.id) trigger.id = opts.id;
|
|
@@ -2342,10 +2350,15 @@ var ColorField = class {
|
|
|
2342
2350
|
boundary: this.popoverOpts?.boundary,
|
|
2343
2351
|
zIndex: this.popoverOpts?.zIndex,
|
|
2344
2352
|
className: "vela-color-field-pop",
|
|
2345
|
-
content: buildColorPicker(
|
|
2346
|
-
this.
|
|
2347
|
-
this.
|
|
2348
|
-
|
|
2353
|
+
content: buildColorPicker(
|
|
2354
|
+
this.getVal(),
|
|
2355
|
+
this.theme,
|
|
2356
|
+
(val) => {
|
|
2357
|
+
this.onVal(val);
|
|
2358
|
+
this.paint();
|
|
2359
|
+
},
|
|
2360
|
+
{ commit: this.commit }
|
|
2361
|
+
)
|
|
2349
2362
|
});
|
|
2350
2363
|
pop.show();
|
|
2351
2364
|
}
|
|
@@ -2829,7 +2842,8 @@ function buildFieldControl(desc) {
|
|
|
2829
2842
|
const el2 = colorField(desc.theme, desc.get, desc.onChange, {
|
|
2830
2843
|
shape: "circle",
|
|
2831
2844
|
id: desc.id,
|
|
2832
|
-
popover: desc.popover
|
|
2845
|
+
popover: desc.popover,
|
|
2846
|
+
commit: desc.commit
|
|
2833
2847
|
});
|
|
2834
2848
|
if (desc.title) el2.title = desc.title;
|
|
2835
2849
|
return { el: el2 };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { parseSymbol, priceStyleIds, BUILTIN_PRICE_STYLES, tzButtonLabel, SecondClock,
|
|
1
|
+
import { parseSymbol, priceStyleIds, BUILTIN_PRICE_STYLES, tzButtonLabel, SecondClock, resolveTimezone, timezoneMenuRows, isGroupRow, defaultMemberOf, groupKeyOf, groupMembers, LEGEND_AT_TOP_ATTR, normalizeSession, Vela, normalizeTimezone, TypedEventBus, MultiProviderFeed, registerBuiltinChartTypes, resolveTheme, buildToolbar, createCustomMark, createAttributionMark, DrawingToolbar, applyAttributionMarkTheme, sharedBarStore, timeframeToMs } from './chunk-RVQWJOEE.js';
|
|
2
2
|
import { chartType, resolveTopbarComposition, topbarActionOverride, TOPBAR_BUILTIN_IDS, widgetActions, SidePanel, sidePanels, DEFAULT_PANEL_ORDER, symbolRanking, resolveEngines, legendActionsProviderFor, legendCalloutsProviderFor, statePersistenceHandlers, topbarHas, rendererDefaults, widgetAttachments, getDrawingType, inputDeltas } from './chunk-BFA32GOU.js';
|
|
3
|
-
import { Tooltip, KeymapManager, isEditableTarget, Drawer } from './chunk-
|
|
4
|
-
import { Menu, Dialog, CalloutBubble, applyPlotOverlayTokens, ensureUIHost } from './chunk-
|
|
3
|
+
import { Tooltip, KeymapManager, isEditableTarget, Drawer } from './chunk-PVGWNF7V.js';
|
|
4
|
+
import { Menu, Dialog, CalloutBubble, applyPlotOverlayTokens, ensureUIHost } from './chunk-WTWGEB7K.js';
|
|
5
5
|
import { registerIcon, svg16, injectStyles, iconEl, iconMarkup, iconAt, SESSION_OFF, SESSION_POST, SESSION_PRE, icon, categoricalColor } from './chunk-CAFCLMPF.js';
|
|
6
6
|
import { baseOf } from './chunk-W4EJWLEO.js';
|
|
7
7
|
|
|
@@ -1087,6 +1087,7 @@ var Bottombar = class {
|
|
|
1087
1087
|
this.sessionButtons = /* @__PURE__ */ new Map();
|
|
1088
1088
|
this.sessionEl = null;
|
|
1089
1089
|
this.timezone = opts.timezone;
|
|
1090
|
+
this.exchangeTimezone = opts.exchangeTimezone;
|
|
1090
1091
|
const doc = host.ownerDocument;
|
|
1091
1092
|
injectStyles(STYLE_ID3, CSS3, doc);
|
|
1092
1093
|
this.el = doc.createElement("div");
|
|
@@ -1110,7 +1111,7 @@ var Bottombar = class {
|
|
|
1110
1111
|
this.clockEl = doc.createElement("span");
|
|
1111
1112
|
this.clockEl.className = "vela-bb-clock";
|
|
1112
1113
|
this.tzLabelEl = doc.createElement("span");
|
|
1113
|
-
this.tzLabelEl.textContent = tzButtonLabel(this.
|
|
1114
|
+
this.tzLabelEl.textContent = tzButtonLabel(this.displayZone);
|
|
1114
1115
|
this.tzButton.append(this.clockEl, this.tzLabelEl);
|
|
1115
1116
|
const session = doc.createElement("span");
|
|
1116
1117
|
session.className = "vela-bb-session";
|
|
@@ -1145,19 +1146,32 @@ var Bottombar = class {
|
|
|
1145
1146
|
placement: "top-end",
|
|
1146
1147
|
items: this.tzItems(),
|
|
1147
1148
|
onSelect: (zone) => {
|
|
1148
|
-
this.setTimezone(zone);
|
|
1149
|
+
this.setTimezone(zone, this.exchangeTimezone);
|
|
1149
1150
|
opts.onTimezone(zone);
|
|
1150
1151
|
}
|
|
1151
1152
|
});
|
|
1152
1153
|
this.tick();
|
|
1153
1154
|
this.unsubClock = (opts.clock ?? new SecondClock()).onTick(() => this.tick());
|
|
1154
1155
|
}
|
|
1155
|
-
|
|
1156
|
+
/**
|
|
1157
|
+
* Reflect the stored choice AND the active chart's market zone. The clock and the
|
|
1158
|
+
* offset label read the RESOLVED zone, so a workspace on the exchange rule re-labels
|
|
1159
|
+
* when the active cell (or its symbol) changes market — the host re-projects on
|
|
1160
|
+
* both. Idempotent: unchanged inputs leave the menu alone.
|
|
1161
|
+
*/
|
|
1162
|
+
setTimezone(zone, exchangeTimezone) {
|
|
1163
|
+
if (zone === this.timezone && exchangeTimezone === this.exchangeTimezone) return;
|
|
1164
|
+
const choiceChanged = zone !== this.timezone;
|
|
1156
1165
|
this.timezone = zone;
|
|
1157
|
-
this.
|
|
1158
|
-
this.
|
|
1166
|
+
this.exchangeTimezone = exchangeTimezone;
|
|
1167
|
+
this.tzLabelEl.textContent = tzButtonLabel(this.displayZone);
|
|
1168
|
+
if (choiceChanged) this.tzMenu.setItems(this.tzItems());
|
|
1159
1169
|
this.tick();
|
|
1160
1170
|
}
|
|
1171
|
+
/** The zone the bar's clock and label render in. */
|
|
1172
|
+
get displayZone() {
|
|
1173
|
+
return resolveTimezone(this.timezone, this.exchangeTimezone);
|
|
1174
|
+
}
|
|
1161
1175
|
/** Highlight (or clear with null) the active range chip — cleared on manual tf changes. */
|
|
1162
1176
|
setActiveRange(id) {
|
|
1163
1177
|
for (const [key, b] of this.rangeButtons) {
|
|
@@ -1185,11 +1199,7 @@ var Bottombar = class {
|
|
|
1185
1199
|
this.el.remove();
|
|
1186
1200
|
}
|
|
1187
1201
|
tzItems() {
|
|
1188
|
-
return
|
|
1189
|
-
id: t.value,
|
|
1190
|
-
label: tzMenuLabel(t.value, t.label),
|
|
1191
|
-
checked: t.value === normalizeTimezone(this.timezone)
|
|
1192
|
-
}));
|
|
1202
|
+
return timezoneMenuRows(this.timezone).map((r) => ({ id: r.value, label: r.label, checked: r.checked }));
|
|
1193
1203
|
}
|
|
1194
1204
|
tick() {
|
|
1195
1205
|
try {
|
|
@@ -1198,7 +1208,7 @@ var Bottombar = class {
|
|
|
1198
1208
|
minute: "2-digit",
|
|
1199
1209
|
second: "2-digit",
|
|
1200
1210
|
hour12: false,
|
|
1201
|
-
timeZone: this.
|
|
1211
|
+
timeZone: this.displayZone
|
|
1202
1212
|
}).format(/* @__PURE__ */ new Date());
|
|
1203
1213
|
} catch {
|
|
1204
1214
|
this.clockEl.textContent = "";
|
|
@@ -4756,12 +4766,11 @@ function priceAxisItems(s) {
|
|
|
4756
4766
|
];
|
|
4757
4767
|
}
|
|
4758
4768
|
function timeAxisItems(timezone) {
|
|
4759
|
-
const active = timezone === "UTC" ? "Etc/UTC" : timezone;
|
|
4760
4769
|
return [
|
|
4761
4770
|
{
|
|
4762
4771
|
id: "timezone",
|
|
4763
4772
|
label: "Time zone",
|
|
4764
|
-
submenu:
|
|
4773
|
+
submenu: timezoneMenuRows(timezone).map((r) => ({ id: `tz:${r.value}`, label: r.label, checked: r.checked }))
|
|
4765
4774
|
},
|
|
4766
4775
|
settingsItem("time-axis", "More settings\u2026")
|
|
4767
4776
|
];
|
|
@@ -4882,7 +4891,7 @@ var ChartContextMenu = class {
|
|
|
4882
4891
|
} else if (id.startsWith("tz:")) {
|
|
4883
4892
|
const zone = id.slice("tz:".length);
|
|
4884
4893
|
if (this.cbs.setTimezone) this.cbs.setTimezone(zone);
|
|
4885
|
-
else chart.renderer.set("timezone", zone);
|
|
4894
|
+
else chart.renderer.set("timezone", resolveTimezone(zone, void 0));
|
|
4886
4895
|
} else if (id === "auto") {
|
|
4887
4896
|
chart.renderer.set("autoScale", chart.renderer.get("autoScale") === false);
|
|
4888
4897
|
} else if (id === "invert") {
|
|
@@ -5641,7 +5650,7 @@ var ChartCell = class {
|
|
|
5641
5650
|
this.history.onChart(this.inner);
|
|
5642
5651
|
this.inner.renderer.onConfigChanged(() => {
|
|
5643
5652
|
const zone = this.inner?.renderer.get("timezone");
|
|
5644
|
-
if (typeof zone === "string" && normalizeTimezone(zone) !== normalizeTimezone(this.
|
|
5653
|
+
if (typeof zone === "string" && normalizeTimezone(zone) !== normalizeTimezone(this.displayTimezone)) {
|
|
5645
5654
|
this.deps.setTimezone(normalizeTimezone(zone));
|
|
5646
5655
|
}
|
|
5647
5656
|
const style = this.priceStyle;
|
|
@@ -5683,8 +5692,7 @@ var ChartCell = class {
|
|
|
5683
5692
|
this.refreshSessionShading();
|
|
5684
5693
|
});
|
|
5685
5694
|
this.inner.on("viewport:changed", (range) => this.sessionShading.updateRange(range));
|
|
5686
|
-
|
|
5687
|
-
if (tz !== "Etc/UTC") this.inner.renderer.set("timezone", tz);
|
|
5695
|
+
this.applyTimezone();
|
|
5688
5696
|
this.indicatorTitlesOn = seed.indicatorTitles ?? true;
|
|
5689
5697
|
if (!this.indicatorTitlesOn) this.inner.renderer.set("indicatorTitles", false);
|
|
5690
5698
|
this.indicatorValuesOn = seed.indicatorValues ?? true;
|
|
@@ -5706,7 +5714,7 @@ var ChartCell = class {
|
|
|
5706
5714
|
this.statusline?.setSymbol(this.state.symbol);
|
|
5707
5715
|
this.statusline?.setMeta(this.state.timeframe ?? "60", this.inner.data.displayPrefix(this.state.symbol) ?? this.state.provider ?? "");
|
|
5708
5716
|
}
|
|
5709
|
-
this.
|
|
5717
|
+
this.refreshSymbolMetadata();
|
|
5710
5718
|
if (this.inner && this.state.symbol) this.marketStatus?.track(this.inner.data, this.state.symbol);
|
|
5711
5719
|
});
|
|
5712
5720
|
this.syncStatuslineColors();
|
|
@@ -5780,7 +5788,7 @@ var ChartCell = class {
|
|
|
5780
5788
|
this.offMarket = this.inner.on("market:changed", ({ symbol: symbol2, timeframe }) => {
|
|
5781
5789
|
this.projectMarket(symbol2, timeframe);
|
|
5782
5790
|
this.refreshNativeCatalog();
|
|
5783
|
-
this.
|
|
5791
|
+
this.refreshSymbolMetadata();
|
|
5784
5792
|
if (this.inner) this.marketStatus?.track(this.inner.data, symbol2);
|
|
5785
5793
|
this.deps.onMarketChanged(this.id);
|
|
5786
5794
|
});
|
|
@@ -5821,7 +5829,35 @@ var ChartCell = class {
|
|
|
5821
5829
|
this.deps.onStateDirty();
|
|
5822
5830
|
void this.inner?.setMarket({ session });
|
|
5823
5831
|
}
|
|
5824
|
-
|
|
5832
|
+
/**
|
|
5833
|
+
* The symbol's own trading zone, once its metadata has landed — what the exchange
|
|
5834
|
+
* rule resolves to on this cell (the workspace labels the shared bottom bar with the
|
|
5835
|
+
* ACTIVE cell's). Undefined = unknown or undeclared (the rule then renders UTC).
|
|
5836
|
+
*/
|
|
5837
|
+
get exchangeTimezone() {
|
|
5838
|
+
return this.exchangeZone;
|
|
5839
|
+
}
|
|
5840
|
+
/** The IANA zone this cell's axis renders in: the workspace choice, resolved. */
|
|
5841
|
+
get displayTimezone() {
|
|
5842
|
+
return resolveTimezone(this.deps.timezone(), this.exchangeZone);
|
|
5843
|
+
}
|
|
5844
|
+
/**
|
|
5845
|
+
* Push the resolved zone to the renderer — on the workspace choice changing, and on
|
|
5846
|
+
* this cell's market zone changing under the exchange rule. Skips the write when the
|
|
5847
|
+
* renderer already holds it (its config default is the bare `'UTC'` alias).
|
|
5848
|
+
*/
|
|
5849
|
+
applyTimezone() {
|
|
5850
|
+
const chart = this.inner;
|
|
5851
|
+
if (!chart) return;
|
|
5852
|
+
const zone = this.displayTimezone;
|
|
5853
|
+
const current = chart.renderer.get("timezone");
|
|
5854
|
+
const held = typeof current === "string" && current ? current : "UTC";
|
|
5855
|
+
if (normalizeTimezone(held) === normalizeTimezone(zone)) return;
|
|
5856
|
+
chart.renderer.set("timezone", zone);
|
|
5857
|
+
}
|
|
5858
|
+
/** Re-read the symbol's metadata: session posture (RTH/ETH toggle, shading) and its
|
|
5859
|
+
* trading zone (the exchange rule). Async — the workspace re-projects when a verdict lands. */
|
|
5860
|
+
refreshSymbolMetadata() {
|
|
5825
5861
|
const chart = this.inner;
|
|
5826
5862
|
const symbol = this.state.symbol;
|
|
5827
5863
|
if (!chart || !symbol) return;
|
|
@@ -5829,7 +5865,13 @@ var ChartCell = class {
|
|
|
5829
5865
|
if (this.inner !== chart) return;
|
|
5830
5866
|
const available = typeof si?.session === "string" && si.session !== "" && si.session !== "24x7";
|
|
5831
5867
|
const overnight = parseSessionSpec(si)?.overnight === true;
|
|
5832
|
-
|
|
5868
|
+
const zone = typeof si?.timezone === "string" && si.timezone !== "" ? si.timezone : void 0;
|
|
5869
|
+
const zoneChanged = zone !== this.exchangeZone;
|
|
5870
|
+
if (zoneChanged) {
|
|
5871
|
+
this.exchangeZone = zone;
|
|
5872
|
+
this.applyTimezone();
|
|
5873
|
+
}
|
|
5874
|
+
if (available !== this.sessionAvailableFlag || overnight !== this.sessionOvernightFlag || zoneChanged) {
|
|
5833
5875
|
this.sessionAvailableFlag = available;
|
|
5834
5876
|
this.sessionOvernightFlag = overnight;
|
|
5835
5877
|
this.deps.onMarketChanged(this.id);
|
|
@@ -6288,16 +6330,19 @@ var ChartCell = class {
|
|
|
6288
6330
|
* a persistence handler's `restore` runs silently, a user-driven call records.
|
|
6289
6331
|
*/
|
|
6290
6332
|
addExternalIndicator(entry) {
|
|
6333
|
+
const { id, inputs, props, hidden, ...script } = entry;
|
|
6291
6334
|
this.addManifestInstance(
|
|
6292
|
-
{ ...
|
|
6293
|
-
{ external: true, ...
|
|
6335
|
+
{ ...script, enabled: true },
|
|
6336
|
+
{ external: true, ...id !== void 0 ? { id } : {}, ...inputs ? { inputs } : {}, ...props ? { props } : {}, ...hidden ? { hidden: true } : {} }
|
|
6294
6337
|
);
|
|
6295
6338
|
}
|
|
6296
6339
|
/** Add ONE instance of a manifest entry (repeatable — duplicates are legitimate). */
|
|
6297
6340
|
addManifestInstance(entry, opts = {}) {
|
|
6298
6341
|
if (this.destroyed) return;
|
|
6299
6342
|
const values = opts.inputs || opts.props ? { inputs: opts.inputs, props: opts.props } : void 0;
|
|
6300
|
-
const
|
|
6343
|
+
const handle = this.addToChart(entry, values, opts.id);
|
|
6344
|
+
if (!handle) return;
|
|
6345
|
+
const it = { entry, handle, id: handle.id, ...opts.external ? { external: true } : {}, ...values ? { values } : {} };
|
|
6301
6346
|
if (opts.hidden) it.handle?.setVisible(false);
|
|
6302
6347
|
this.instances.push(it);
|
|
6303
6348
|
this.deps.onIndicatorsChanged(this.id);
|
|
@@ -6306,7 +6351,7 @@ var ChartCell = class {
|
|
|
6306
6351
|
this.history.push({
|
|
6307
6352
|
undo: () => this.dropInstance(snapshot),
|
|
6308
6353
|
redo: () => {
|
|
6309
|
-
snapshot.handle = this.addToChart(snapshot.entry, snapshot.values);
|
|
6354
|
+
snapshot.handle = this.addToChart(snapshot.entry, snapshot.values, snapshot.id);
|
|
6310
6355
|
this.instances.push(snapshot);
|
|
6311
6356
|
this.deps.onIndicatorsChanged(this.id);
|
|
6312
6357
|
}
|
|
@@ -6319,7 +6364,7 @@ var ChartCell = class {
|
|
|
6319
6364
|
const snapshot = it;
|
|
6320
6365
|
this.history.push({
|
|
6321
6366
|
undo: () => {
|
|
6322
|
-
snapshot.handle = this.addToChart(snapshot.entry, snapshot.values);
|
|
6367
|
+
snapshot.handle = this.addToChart(snapshot.entry, snapshot.values, snapshot.id);
|
|
6323
6368
|
this.instances.push(snapshot);
|
|
6324
6369
|
this.deps.onIndicatorsChanged(this.id);
|
|
6325
6370
|
},
|
|
@@ -6409,9 +6454,10 @@ var ChartCell = class {
|
|
|
6409
6454
|
this.deps.onIndicatorsChanged(this.id);
|
|
6410
6455
|
});
|
|
6411
6456
|
}
|
|
6412
|
-
addToChart(entry, values) {
|
|
6457
|
+
addToChart(entry, values, id) {
|
|
6413
6458
|
try {
|
|
6414
6459
|
return this.inner?.addIndicator(entry.script, {
|
|
6460
|
+
...id !== void 0 ? { id } : {},
|
|
6415
6461
|
...entry.language !== void 0 ? { language: entry.language } : {},
|
|
6416
6462
|
...values?.inputs ? { inputs: values.inputs } : {},
|
|
6417
6463
|
...values?.props ? { props: values.props } : {}
|
|
@@ -7731,15 +7777,14 @@ var TimezoneDrawer = class {
|
|
|
7731
7777
|
this.drawer.body.replaceChildren();
|
|
7732
7778
|
const list = doc.createElement("div");
|
|
7733
7779
|
list.className = "vela-tzd-list";
|
|
7734
|
-
const
|
|
7735
|
-
for (const tz of TIMEZONES) {
|
|
7780
|
+
for (const tz of timezoneMenuRows(this.opts.timezone())) {
|
|
7736
7781
|
const row = doc.createElement("div");
|
|
7737
7782
|
row.className = "vela-tzd-row";
|
|
7738
7783
|
const label = doc.createElement("span");
|
|
7739
7784
|
label.className = "vela-tzd-row-label";
|
|
7740
|
-
label.textContent =
|
|
7785
|
+
label.textContent = tz.label;
|
|
7741
7786
|
row.appendChild(label);
|
|
7742
|
-
if (tz.
|
|
7787
|
+
if (tz.checked) row.appendChild(iconEl("check", doc));
|
|
7743
7788
|
row.addEventListener("click", () => {
|
|
7744
7789
|
this.opts.onTimezone(tz.value);
|
|
7745
7790
|
this.drawer.hide();
|
|
@@ -8847,13 +8892,23 @@ var VelaWorkspace = class {
|
|
|
8847
8892
|
}
|
|
8848
8893
|
}
|
|
8849
8894
|
}
|
|
8850
|
-
/**
|
|
8895
|
+
/**
|
|
8896
|
+
* Set the workspace-global display timezone — applied to EVERY cell. An IANA zone,
|
|
8897
|
+
* or `'exchange'` (the exchange rule): each cell then renders in its OWN market's
|
|
8898
|
+
* zone (Chicago for a CME future, New York for a US equity, UTC for crypto), and the
|
|
8899
|
+
* bottom bar follows the active cell's.
|
|
8900
|
+
*/
|
|
8851
8901
|
setTimezone(zone) {
|
|
8852
8902
|
this.timezone = zone;
|
|
8853
|
-
this.
|
|
8854
|
-
for (const cell of this.cellsById.values()) cell.
|
|
8903
|
+
this.projectTimezone();
|
|
8904
|
+
for (const cell of this.cellsById.values()) cell.applyTimezone();
|
|
8855
8905
|
this.markStateDirty();
|
|
8856
8906
|
}
|
|
8907
|
+
/** Bottom bar ⇐ the stored choice + the ACTIVE cell's market zone (labels the exchange row). */
|
|
8908
|
+
projectTimezone() {
|
|
8909
|
+
const active = this.activeId ? this.cellsById.get(this.activeId) : void 0;
|
|
8910
|
+
this.bottombar?.setTimezone(this.timezone, active?.exchangeTimezone);
|
|
8911
|
+
}
|
|
8857
8912
|
/**
|
|
8858
8913
|
* Swap the workspace theme at runtime — `'dark'`, `'light'`, or a full custom theme,
|
|
8859
8914
|
* applied to the shared chrome (topbar, panels, drawing toolbar) and EVERY cell.
|
|
@@ -9058,6 +9113,7 @@ var VelaWorkspace = class {
|
|
|
9058
9113
|
this.dock.onChart(cell.chart);
|
|
9059
9114
|
this.bottombar?.setActiveRange(cell.activeRangeId);
|
|
9060
9115
|
this.bottombar?.setSession({ session: cell.session, enabled: cell.sessionAvailable });
|
|
9116
|
+
this.projectTimezone();
|
|
9061
9117
|
this.indicatorPicker?.sync();
|
|
9062
9118
|
this.glider.stop();
|
|
9063
9119
|
const d = cell.chart.drawings;
|
|
@@ -9642,6 +9698,7 @@ var VelaWorkspace = class {
|
|
|
9642
9698
|
this.mobileBar?.setTimeframe(cell.timeframe);
|
|
9643
9699
|
this.objectTree.setSymbol(cell.symbol);
|
|
9644
9700
|
this.bottombar?.setSession({ session: cell.session, enabled: cell.sessionAvailable });
|
|
9701
|
+
this.projectTimezone();
|
|
9645
9702
|
this.bottombar?.setActiveRange(cell.activeRangeId);
|
|
9646
9703
|
}
|
|
9647
9704
|
/** Trigger ② — a cell's price style changed: the topbar button/menu only if active.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { x as Millis, an as InputSchema, al as IndicatorMeta, P as PriceStyle, O as OHLCV, I as InputValue, l as IndicatorModel, k as MoveTarget, aH as PaneAxis, aW as SeriesSpec, aj as Fill, G as Background, aM as PriceLine, a6 as DrawingLine, a2 as DrawingBox, a5 as DrawingLabel, aa as DrawingPolyline, a7 as DrawingLinefill, af as DrawingTable, h as IndicatorStatus, a as VisibleRange, c as VelaTheme, S as SerializedDrawing, z as DrawingTypeKey, y as SnapMode, a8 as DrawingMode, u as MarkClickEvent, e as IChartRenderer, R as RendererCapabilities, o as LegendActionView, p as LegendCalloutView, U as Unsubscribe, C as CrosshairEvent, A as AxisLongPressEvent, v as DataWindowReadout, n as SymbolPickerFn, W as WallClock, bc as PaneInfo, ai as DrawingsOption, ac as DrawingSeriesGateway, D as Drawing, s as TimelineMark, t as MarkGroup, b as VelaOptions, E as AddIndicatorOptions, aG as MarketSwitch, aF as MarketSnapshot, V as VisibleRangePreset, T as ThemeName } from './options-
|
|
2
|
-
import { S as SymbolInfo, B as BarRange, M as MarketDataFeed, D as DataProvider, P as ProviderInfo, a as SymbolDescriptor, b as ProviderCapabilities } from './DataProvider-
|
|
1
|
+
import { x as Millis, an as InputSchema, al as IndicatorMeta, P as PriceStyle, O as OHLCV, I as InputValue, l as IndicatorModel, k as MoveTarget, aH as PaneAxis, aW as SeriesSpec, aj as Fill, G as Background, aM as PriceLine, a6 as DrawingLine, a2 as DrawingBox, a5 as DrawingLabel, aa as DrawingPolyline, a7 as DrawingLinefill, af as DrawingTable, h as IndicatorStatus, a as VisibleRange, c as VelaTheme, S as SerializedDrawing, z as DrawingTypeKey, y as SnapMode, a8 as DrawingMode, u as MarkClickEvent, e as IChartRenderer, R as RendererCapabilities, o as LegendActionView, p as LegendCalloutView, U as Unsubscribe, C as CrosshairEvent, A as AxisLongPressEvent, v as DataWindowReadout, n as SymbolPickerFn, W as WallClock, bc as PaneInfo, ai as DrawingsOption, ac as DrawingSeriesGateway, D as Drawing, s as TimelineMark, t as MarkGroup, b as VelaOptions, E as AddIndicatorOptions, aG as MarketSwitch, aF as MarketSnapshot, V as VisibleRangePreset, T as ThemeName } from './options-D1AJKsn_.cjs';
|
|
2
|
+
import { S as SymbolInfo, B as BarRange, M as MarketDataFeed, D as DataProvider, P as ProviderInfo, a as SymbolDescriptor, b as ProviderCapabilities } from './DataProvider-CGa4KHRa.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* A strategy's broker state at ONE bar — the flat summary a host reads while a script
|
|
@@ -47,6 +47,23 @@ interface StrategyTrade {
|
|
|
47
47
|
exit?: StrategyFill;
|
|
48
48
|
/** Still open at the last computed bar. */
|
|
49
49
|
open: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Realized P&L of this round trip in account currency, net of commission. Absent
|
|
52
|
+
* while the trade is open, and for an engine that reports no per-trade ledger.
|
|
53
|
+
*/
|
|
54
|
+
pnl?: number;
|
|
55
|
+
/** Commission charged on this trade, in account currency. */
|
|
56
|
+
commission?: number;
|
|
57
|
+
/**
|
|
58
|
+
* Worst / best unrealized excursion of THIS trade from its entry, in account
|
|
59
|
+
* currency (positive magnitudes). Read `maxDrawdown` as the adverse excursion and
|
|
60
|
+
* `maxRunup` as the favorable one — the per-trade counterparts of the account-level
|
|
61
|
+
* {@link StrategyState.maxDrawdown} / {@link StrategyState.maxRunup}. An engine
|
|
62
|
+
* defines the exact convention (intrabar extremes, commission handling); absent when
|
|
63
|
+
* it does not track them.
|
|
64
|
+
*/
|
|
65
|
+
maxDrawdown?: number;
|
|
66
|
+
maxRunup?: number;
|
|
50
67
|
}
|
|
51
68
|
/** One side of a {@link StrategyTrade}. */
|
|
52
69
|
interface StrategyFill {
|
|
@@ -1684,6 +1701,12 @@ interface ExternalIndicatorEntry {
|
|
|
1684
1701
|
name: string;
|
|
1685
1702
|
/** The script source (the recorded undo/redo action re-adds from it). */
|
|
1686
1703
|
script: string;
|
|
1704
|
+
/** The indicator's id on the chart (see `AddIndicatorOptions.id`) — what a persistence
|
|
1705
|
+
* handler stores and hands back on restore so the indicator comes back under the id
|
|
1706
|
+
* its document knows. Omitted: the chart mints one. Either way undo/redo re-add the
|
|
1707
|
+
* indicator under the id it first ran with. An id already live on the cell's chart
|
|
1708
|
+
* is rejected (a warning; nothing is added). */
|
|
1709
|
+
id?: string;
|
|
1687
1710
|
/** Engine language (default: the chart's default engine). */
|
|
1688
1711
|
language?: string;
|
|
1689
1712
|
/** Input-value overrides applied at add time (what a persistence handler restores). */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { x as Millis, an as InputSchema, al as IndicatorMeta, P as PriceStyle, O as OHLCV, I as InputValue, l as IndicatorModel, k as MoveTarget, aH as PaneAxis, aW as SeriesSpec, aj as Fill, G as Background, aM as PriceLine, a6 as DrawingLine, a2 as DrawingBox, a5 as DrawingLabel, aa as DrawingPolyline, a7 as DrawingLinefill, af as DrawingTable, h as IndicatorStatus, a as VisibleRange, c as VelaTheme, S as SerializedDrawing, z as DrawingTypeKey, y as SnapMode, a8 as DrawingMode, u as MarkClickEvent, e as IChartRenderer, R as RendererCapabilities, o as LegendActionView, p as LegendCalloutView, U as Unsubscribe, C as CrosshairEvent, A as AxisLongPressEvent, v as DataWindowReadout, n as SymbolPickerFn, W as WallClock, bc as PaneInfo, ai as DrawingsOption, ac as DrawingSeriesGateway, D as Drawing, s as TimelineMark, t as MarkGroup, b as VelaOptions, E as AddIndicatorOptions, aG as MarketSwitch, aF as MarketSnapshot, V as VisibleRangePreset, T as ThemeName } from './options-
|
|
2
|
-
import { S as SymbolInfo, B as BarRange, M as MarketDataFeed, D as DataProvider, P as ProviderInfo, a as SymbolDescriptor, b as ProviderCapabilities } from './DataProvider-
|
|
1
|
+
import { x as Millis, an as InputSchema, al as IndicatorMeta, P as PriceStyle, O as OHLCV, I as InputValue, l as IndicatorModel, k as MoveTarget, aH as PaneAxis, aW as SeriesSpec, aj as Fill, G as Background, aM as PriceLine, a6 as DrawingLine, a2 as DrawingBox, a5 as DrawingLabel, aa as DrawingPolyline, a7 as DrawingLinefill, af as DrawingTable, h as IndicatorStatus, a as VisibleRange, c as VelaTheme, S as SerializedDrawing, z as DrawingTypeKey, y as SnapMode, a8 as DrawingMode, u as MarkClickEvent, e as IChartRenderer, R as RendererCapabilities, o as LegendActionView, p as LegendCalloutView, U as Unsubscribe, C as CrosshairEvent, A as AxisLongPressEvent, v as DataWindowReadout, n as SymbolPickerFn, W as WallClock, bc as PaneInfo, ai as DrawingsOption, ac as DrawingSeriesGateway, D as Drawing, s as TimelineMark, t as MarkGroup, b as VelaOptions, E as AddIndicatorOptions, aG as MarketSwitch, aF as MarketSnapshot, V as VisibleRangePreset, T as ThemeName } from './options-D1AJKsn_.js';
|
|
2
|
+
import { S as SymbolInfo, B as BarRange, M as MarketDataFeed, D as DataProvider, P as ProviderInfo, a as SymbolDescriptor, b as ProviderCapabilities } from './DataProvider-CmWUtDVL.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* A strategy's broker state at ONE bar — the flat summary a host reads while a script
|
|
@@ -47,6 +47,23 @@ interface StrategyTrade {
|
|
|
47
47
|
exit?: StrategyFill;
|
|
48
48
|
/** Still open at the last computed bar. */
|
|
49
49
|
open: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Realized P&L of this round trip in account currency, net of commission. Absent
|
|
52
|
+
* while the trade is open, and for an engine that reports no per-trade ledger.
|
|
53
|
+
*/
|
|
54
|
+
pnl?: number;
|
|
55
|
+
/** Commission charged on this trade, in account currency. */
|
|
56
|
+
commission?: number;
|
|
57
|
+
/**
|
|
58
|
+
* Worst / best unrealized excursion of THIS trade from its entry, in account
|
|
59
|
+
* currency (positive magnitudes). Read `maxDrawdown` as the adverse excursion and
|
|
60
|
+
* `maxRunup` as the favorable one — the per-trade counterparts of the account-level
|
|
61
|
+
* {@link StrategyState.maxDrawdown} / {@link StrategyState.maxRunup}. An engine
|
|
62
|
+
* defines the exact convention (intrabar extremes, commission handling); absent when
|
|
63
|
+
* it does not track them.
|
|
64
|
+
*/
|
|
65
|
+
maxDrawdown?: number;
|
|
66
|
+
maxRunup?: number;
|
|
50
67
|
}
|
|
51
68
|
/** One side of a {@link StrategyTrade}. */
|
|
52
69
|
interface StrategyFill {
|
|
@@ -1684,6 +1701,12 @@ interface ExternalIndicatorEntry {
|
|
|
1684
1701
|
name: string;
|
|
1685
1702
|
/** The script source (the recorded undo/redo action re-adds from it). */
|
|
1686
1703
|
script: string;
|
|
1704
|
+
/** The indicator's id on the chart (see `AddIndicatorOptions.id`) — what a persistence
|
|
1705
|
+
* handler stores and hands back on restore so the indicator comes back under the id
|
|
1706
|
+
* its document knows. Omitted: the chart mints one. Either way undo/redo re-add the
|
|
1707
|
+
* indicator under the id it first ran with. An id already live on the cell's chart
|
|
1708
|
+
* is rejected (a warning; nothing is added). */
|
|
1709
|
+
id?: string;
|
|
1687
1710
|
/** Engine language (default: the chart's default engine). */
|
|
1688
1711
|
language?: string;
|
|
1689
1712
|
/** Input-value overrides applied at add time (what a persistence handler restores). */
|