@tradecanvas/chart 1.3.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +131 -49
- package/dist/Chart.d.ts +724 -18
- package/dist/Chart.d.ts.map +1 -1
- package/dist/DataManager.d.ts +5 -0
- package/dist/DataManager.d.ts.map +1 -1
- package/dist/HistoryPager.d.ts +58 -0
- package/dist/HistoryPager.d.ts.map +1 -0
- package/dist/LayoutSession-CTZB90NX.cjs +2 -0
- package/dist/LayoutSession-CTZB90NX.cjs.map +1 -0
- package/dist/LayoutSession-CWn3sdbs.js +3967 -0
- package/dist/LayoutSession-CWn3sdbs.js.map +1 -0
- package/dist/PaneManager.d.ts.map +1 -1
- package/dist/ThemeManager.d.ts +5 -1
- package/dist/ThemeManager.d.ts.map +1 -1
- package/dist/chartA11y.d.ts +59 -0
- package/dist/chartA11y.d.ts.map +1 -0
- package/dist/charts/ChartTypeStrategy.d.ts +11 -4
- package/dist/charts/ChartTypeStrategy.d.ts.map +1 -1
- package/dist/grid/ChartGrid.d.ts +7 -1
- package/dist/grid/ChartGrid.d.ts.map +1 -1
- package/dist/i18n-CiQ8EDVs.js +1469 -0
- package/dist/i18n-CiQ8EDVs.js.map +1 -0
- package/dist/i18n-WsLA9SmD.cjs +2 -0
- package/dist/i18n-WsLA9SmD.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +24 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +74 -89
- package/dist/index.js.map +1 -1
- package/dist/indicatorLabel.d.ts +7 -0
- package/dist/indicatorLabel.d.ts.map +1 -0
- package/dist/layout/LayoutManager.d.ts +50 -0
- package/dist/layout/LayoutManager.d.ts.map +1 -1
- package/dist/layout/priceAxisWidth.d.ts +2 -0
- package/dist/layout/priceAxisWidth.d.ts.map +1 -1
- package/dist/regularHours.d.ts +10 -0
- package/dist/regularHours.d.ts.map +1 -0
- package/dist/state/LayoutSession.d.ts +101 -0
- package/dist/state/LayoutSession.d.ts.map +1 -0
- package/dist/state/layoutStorage.d.ts +46 -0
- package/dist/state/layoutStorage.d.ts.map +1 -0
- package/dist/trading/wireExecution.d.ts +7 -3
- package/dist/trading/wireExecution.d.ts.map +1 -1
- package/dist/widget/ChartWidget.d.ts +283 -10
- package/dist/widget/ChartWidget.d.ts.map +1 -1
- package/dist/widget/ChartWidgetGrid.d.ts +166 -0
- package/dist/widget/ChartWidgetGrid.d.ts.map +1 -0
- package/dist/widget/DrawingTemplateStore.d.ts +29 -8
- package/dist/widget/DrawingTemplateStore.d.ts.map +1 -1
- package/dist/widget/WatchlistStore.d.ts +65 -0
- package/dist/widget/WatchlistStore.d.ts.map +1 -0
- package/dist/widget/WidgetAccountPanel.d.ts +72 -0
- package/dist/widget/WidgetAccountPanel.d.ts.map +1 -0
- package/dist/widget/WidgetAlertsPanel.d.ts +50 -3
- package/dist/widget/WidgetAlertsPanel.d.ts.map +1 -1
- package/dist/widget/WidgetBracketBar.d.ts +3 -1
- package/dist/widget/WidgetBracketBar.d.ts.map +1 -1
- package/dist/widget/WidgetChartNav.d.ts +36 -0
- package/dist/widget/WidgetChartNav.d.ts.map +1 -0
- package/dist/widget/WidgetCommandPalette.d.ts +5 -1
- package/dist/widget/WidgetCommandPalette.d.ts.map +1 -1
- package/dist/widget/WidgetContextMenu.d.ts +40 -0
- package/dist/widget/WidgetContextMenu.d.ts.map +1 -0
- package/dist/widget/WidgetDataWindow.d.ts +3 -1
- package/dist/widget/WidgetDataWindow.d.ts.map +1 -1
- package/dist/widget/WidgetDepthLadder.d.ts +3 -1
- package/dist/widget/WidgetDepthLadder.d.ts.map +1 -1
- package/dist/widget/WidgetDrawingSettings.d.ts +108 -0
- package/dist/widget/WidgetDrawingSettings.d.ts.map +1 -0
- package/dist/widget/WidgetDrawingSidebar.d.ts +26 -1
- package/dist/widget/WidgetDrawingSidebar.d.ts.map +1 -1
- package/dist/widget/WidgetDrawingStyle.d.ts +3 -1
- package/dist/widget/WidgetDrawingStyle.d.ts.map +1 -1
- package/dist/widget/WidgetDropdown.d.ts.map +1 -1
- package/dist/widget/WidgetGoToDate.d.ts +46 -0
- package/dist/widget/WidgetGoToDate.d.ts.map +1 -0
- package/dist/widget/WidgetHistoryPill.d.ts +23 -0
- package/dist/widget/WidgetHistoryPill.d.ts.map +1 -0
- package/dist/widget/WidgetHotkeySheet.d.ts +3 -1
- package/dist/widget/WidgetHotkeySheet.d.ts.map +1 -1
- package/dist/widget/WidgetIndicatorLegend.d.ts +98 -0
- package/dist/widget/WidgetIndicatorLegend.d.ts.map +1 -0
- package/dist/widget/WidgetIndicatorSettings.d.ts +62 -7
- package/dist/widget/WidgetIndicatorSettings.d.ts.map +1 -1
- package/dist/widget/WidgetIntervalInput.d.ts +34 -0
- package/dist/widget/WidgetIntervalInput.d.ts.map +1 -0
- package/dist/widget/WidgetLayoutsDialog.d.ts +39 -0
- package/dist/widget/WidgetLayoutsDialog.d.ts.map +1 -0
- package/dist/widget/WidgetLayoutsUI.d.ts +37 -0
- package/dist/widget/WidgetLayoutsUI.d.ts.map +1 -0
- package/dist/widget/WidgetLoadingOverlay.d.ts.map +1 -1
- package/dist/widget/WidgetNamePrompt.d.ts +31 -0
- package/dist/widget/WidgetNamePrompt.d.ts.map +1 -0
- package/dist/widget/WidgetObjectTree.d.ts +21 -3
- package/dist/widget/WidgetObjectTree.d.ts.map +1 -1
- package/dist/widget/WidgetOrderTicket.d.ts +49 -0
- package/dist/widget/WidgetOrderTicket.d.ts.map +1 -0
- package/dist/widget/WidgetReplayBar.d.ts +52 -7
- package/dist/widget/WidgetReplayBar.d.ts.map +1 -1
- package/dist/widget/WidgetSettings.d.ts +26 -2
- package/dist/widget/WidgetSettings.d.ts.map +1 -1
- package/dist/widget/WidgetStatusBar.d.ts +19 -1
- package/dist/widget/WidgetStatusBar.d.ts.map +1 -1
- package/dist/widget/WidgetStyles.d.ts +3 -1
- package/dist/widget/WidgetStyles.d.ts.map +1 -1
- package/dist/widget/WidgetSymbolInfo.d.ts +64 -0
- package/dist/widget/WidgetSymbolInfo.d.ts.map +1 -0
- package/dist/widget/WidgetSymbolSearch.d.ts +28 -5
- package/dist/widget/WidgetSymbolSearch.d.ts.map +1 -1
- package/dist/widget/WidgetToolbar.d.ts +42 -4
- package/dist/widget/WidgetToolbar.d.ts.map +1 -1
- package/dist/widget/WidgetTooltip.d.ts +43 -0
- package/dist/widget/WidgetTooltip.d.ts.map +1 -0
- package/dist/widget/WidgetWatchlist.d.ts +53 -13
- package/dist/widget/WidgetWatchlist.d.ts.map +1 -1
- package/dist/widget/chartMenu.d.ts +40 -0
- package/dist/widget/chartMenu.d.ts.map +1 -0
- package/dist/widget/drawingMenu.d.ts +21 -0
- package/dist/widget/drawingMenu.d.ts.map +1 -0
- package/dist/widget/escapeHtml.d.ts +3 -0
- package/dist/widget/escapeHtml.d.ts.map +1 -0
- package/dist/widget/focusTrap.d.ts +8 -0
- package/dist/widget/focusTrap.d.ts.map +1 -0
- package/dist/widget/i18n.d.ts +20 -63
- package/dist/widget/i18n.d.ts.map +1 -1
- package/dist/widget/iconSet.d.ts +26 -0
- package/dist/widget/iconSet.d.ts.map +1 -0
- package/dist/widget/icons.d.ts +5 -0
- package/dist/widget/icons.d.ts.map +1 -1
- package/dist/widget/index.cjs +2145 -405
- package/dist/widget/index.cjs.map +1 -1
- package/dist/widget/index.d.ts +18 -1
- package/dist/widget/index.d.ts.map +1 -1
- package/dist/widget/index.js +7376 -1274
- package/dist/widget/index.js.map +1 -1
- package/dist/widget/indicatorTemplates.d.ts +24 -0
- package/dist/widget/indicatorTemplates.d.ts.map +1 -0
- package/dist/widget/keyTarget.d.ts +11 -0
- package/dist/widget/keyTarget.d.ts.map +1 -0
- package/dist/widget/legendValues.d.ts +19 -0
- package/dist/widget/legendValues.d.ts.map +1 -0
- package/dist/widget/locales/ar.d.ts +4 -0
- package/dist/widget/locales/ar.d.ts.map +1 -0
- package/dist/widget/locales/de.d.ts +4 -0
- package/dist/widget/locales/de.d.ts.map +1 -0
- package/dist/widget/locales/en.d.ts +722 -0
- package/dist/widget/locales/en.d.ts.map +1 -0
- package/dist/widget/locales/es.d.ts +4 -0
- package/dist/widget/locales/es.d.ts.map +1 -0
- package/dist/widget/locales/fr.d.ts +4 -0
- package/dist/widget/locales/fr.d.ts.map +1 -0
- package/dist/widget/locales/he.d.ts +4 -0
- package/dist/widget/locales/he.d.ts.map +1 -0
- package/dist/widget/locales/id.d.ts +4 -0
- package/dist/widget/locales/id.d.ts.map +1 -0
- package/dist/widget/locales/index.cjs +2 -0
- package/dist/widget/locales/index.cjs.map +1 -0
- package/dist/widget/locales/index.d.ts +33 -0
- package/dist/widget/locales/index.d.ts.map +1 -0
- package/dist/widget/locales/index.js +10089 -0
- package/dist/widget/locales/index.js.map +1 -0
- package/dist/widget/locales/ja.d.ts +4 -0
- package/dist/widget/locales/ja.d.ts.map +1 -0
- package/dist/widget/locales/ko.d.ts +4 -0
- package/dist/widget/locales/ko.d.ts.map +1 -0
- package/dist/widget/locales/pt.d.ts +4 -0
- package/dist/widget/locales/pt.d.ts.map +1 -0
- package/dist/widget/locales/ru.d.ts +4 -0
- package/dist/widget/locales/ru.d.ts.map +1 -0
- package/dist/widget/locales/th.d.ts +4 -0
- package/dist/widget/locales/th.d.ts.map +1 -0
- package/dist/widget/locales/tr.d.ts +4 -0
- package/dist/widget/locales/tr.d.ts.map +1 -0
- package/dist/widget/locales/vi.d.ts +4 -0
- package/dist/widget/locales/vi.d.ts.map +1 -0
- package/dist/widget/locales/zh.d.ts +4 -0
- package/dist/widget/locales/zh.d.ts.map +1 -0
- package/dist/widget/locales/zhHant.d.ts +4 -0
- package/dist/widget/locales/zhHant.d.ts.map +1 -0
- package/dist/widget/orderTicket.d.ts +27 -0
- package/dist/widget/orderTicket.d.ts.map +1 -0
- package/dist/widget/settingsControls.d.ts +24 -0
- package/dist/widget/settingsControls.d.ts.map +1 -0
- package/dist/widget/types.d.ts +215 -13
- package/dist/widget/types.d.ts.map +1 -1
- package/dist/widget/widgetConfig.d.ts +1 -5
- package/dist/widget/widgetConfig.d.ts.map +1 -1
- package/dist/widget/widgetLayout.d.ts +22 -0
- package/dist/widget/widgetLayout.d.ts.map +1 -0
- package/dist/widget/widgetLocales.d.ts +17 -0
- package/dist/widget/widgetLocales.d.ts.map +1 -0
- package/dist/widget/widgetTimeframes.d.ts +28 -0
- package/dist/widget/widgetTimeframes.d.ts.map +1 -0
- package/dist/widget/widgetTimezones.d.ts +32 -0
- package/dist/widget/widgetTimezones.d.ts.map +1 -0
- package/dist/widget/widgetUI.d.ts +126 -0
- package/dist/widget/widgetUI.d.ts.map +1 -0
- package/package.json +8 -3
- package/dist/DragDropImporter-BazeSQPD.cjs +0 -2
- package/dist/DragDropImporter-BazeSQPD.cjs.map +0 -1
- package/dist/DragDropImporter-cURSpfUb.js +0 -1883
- package/dist/DragDropImporter-cURSpfUb.js.map +0 -1
- package/dist/charts/IndicatorPriceRange.d.ts +0 -20
- package/dist/charts/IndicatorPriceRange.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { DARK_TERMINAL as
|
|
3
|
-
import { AlertManager as
|
|
1
|
+
import { S as e, _ as t, a as n, b as r, c as i, d as a, f as o, g as s, h as c, i as l, l as u, m as ee, n as te, o as ne, p as re, r as ie, s as ae, t as oe, u as se, v as ce, x as le, y as ue } from "./LayoutSession-CWn3sdbs.js";
|
|
2
|
+
import { DARK_TERMINAL as de, DARK_THEME as fe, DARK_THEME as pe, DEFAULT_DRAWING_STYLE as d, DEFAULT_RECONNECT as f, DEFAULT_SIGNAL_STYLE as p, DEFAULT_STREAM_CONFIG as m, DEFAULT_TIMEFRAME_FAVORITES as h, DEFAULT_TRADE_ZONE_STYLE as g, DEFAULT_TRADING_CONFIG as _, LIGHT_THEME as v, LIGHT_THEME as y, MARKET_CRYPTO as b, MARKET_HNX as x, MARKET_HOSE as S, MARKET_NYSE as C, MARKET_UPCOM as w, PRICE_SOURCES as T, TC_PALETTE as E, TC_SERIES_COLORS as D, TIMEFRAMES_CRYPTO as O, TIMEFRAMES_FOREX as k, TIMEFRAMES_STOCK as A, VN_COLORS as j, computePriceLimits as M, createVNTheme as N, formatFraction as P, formatNumber as F, formatVND as I, formatVolumeLoc as L, fractionTick as R, getCurrentSession as z, getLocale as B, indicatorSource as me, isPriceSource as he, isTimeFrame as ge, isValidTimeZone as _e, marketStatus as ve, normalizeBar as ye, normalizeBarTime as be, offsetAt as xe, parseIndicatorSource as Se, parseTimeframe as Ce, pickBaseTimeframe as we, priceFormatterFor as Te, rankSymbols as Ee, readNews as De, readQuote as Oe, registerLocale as ke, resampleBars as Ae, setLocale as je, sourcePrice as Me, stepDecimals as Ne, t as Pe, tickBarCount as Fe, timeframeBucketStart as Ie, timeframeToMs as Le, wallToUtc as Re, zoneOffsetMinutes as ze } from "@tradecanvas/commons";
|
|
3
|
+
import { AlertManager as Be, Animator as Ve, BarCountdown as He, BaseFinanceChart as V, BinanceAdapter as Ue, BybitAdapter as We, ChartLegend as Ge, ChartStateManager as Ke, CoinbaseAdapter as qe, CompareRenderer as Je, CrosshairTooltip as Ye, CurrentPriceLine as Xe, DEFAULT_LEGEND_CONFIG as Ze, DEFAULT_SESSION_HOURS as Qe, DataExporter as $e, DrawingBase as et, Easing as tt, FinanceCrosshair as H, IndicatorBase as nt, IndicatorValueMap as rt, KeyboardHandler as it, KrakenAdapter as at, MAX_ALERT_BARS as ot, MIN_ALERT_BARS as st, MockAdapter as ct, PaperExecutionAdapter as lt, PollingAdapter as ut, RANGE_PRESETS as dt, ReplayManager as ft, ResamplingAdapter as pt, Screenshot as mt, SessionBreaks as ht, SessionShading as gt, SignalMarkerManager as _t, StreamManager as vt, TickAggregator as yt, TickBarAdapter as bt, TickBarBuilder as xt, TradeZoneManager as St, UndoRedoManager as Ct, VolumeRenderer as wt, Watermark as Tt, WebSocketAdapter as Et, formatTooltipTime as Dt, isPriceLevelAlert as Ot, layoutSquarifiedTreemap as kt, layoutUniformGrid as At, lttbDownsample as jt, lttbVisibleIndices as Mt, rangePresetStart as Nt, renderDepthChart as Pt, renderEquityCurve as Ft, renderGauge as It, renderHeatmap as Lt, renderSparkline as Rt, renderWaterfall as zt, servesTimeframe as Bt, toHeikinAshi as Vt, toKagi as Ht, toLineBreak as Ut, toPointAndFigure as Wt, toRangeBars as Gt, toRenko as Kt, withResampling as qt, withTickBars as Jt } from "@tradecanvas/core";
|
|
4
4
|
//#region src/grid/ChartGrid.ts
|
|
5
5
|
var U = {
|
|
6
6
|
"1x1": {
|
|
@@ -35,7 +35,7 @@ var U = {
|
|
|
35
35
|
cols: 2,
|
|
36
36
|
rows: 3
|
|
37
37
|
}
|
|
38
|
-
},
|
|
38
|
+
}, Yt = class {
|
|
39
39
|
root;
|
|
40
40
|
cells = [];
|
|
41
41
|
layout;
|
|
@@ -51,47 +51,47 @@ var U = {
|
|
|
51
51
|
}
|
|
52
52
|
createCells() {
|
|
53
53
|
let { cols: e, rows: t } = U[this.layout], n = e * t;
|
|
54
|
-
for (let e = 0; e < n; e++)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
54
|
+
for (let e = 0; e < n; e++) this.cells.push(this.createCell(e));
|
|
55
|
+
}
|
|
56
|
+
createCell(e) {
|
|
57
|
+
let t = this.options.cells?.[e] ?? {}, n = document.createElement("div");
|
|
58
|
+
n.style.cssText = "position:relative;overflow:hidden;min-width:0;min-height:0;", this.root.appendChild(n);
|
|
59
|
+
let r = new i(n, {
|
|
60
|
+
chartType: "candlestick",
|
|
61
|
+
autoScale: !0,
|
|
62
|
+
features: {
|
|
63
|
+
crosshair: !0,
|
|
64
|
+
keyboard: !0,
|
|
65
|
+
volume: !0,
|
|
66
|
+
legend: !0,
|
|
67
|
+
priceAxis: !0,
|
|
68
|
+
timeAxis: !0,
|
|
69
|
+
grid: !0
|
|
70
|
+
},
|
|
71
|
+
...this.options.chartOptions,
|
|
72
|
+
...t.chartOptions,
|
|
73
|
+
theme: this.options.theme
|
|
74
|
+
}), a = {
|
|
75
|
+
container: n,
|
|
76
|
+
chart: r,
|
|
77
|
+
symbol: t.symbol ?? `Chart ${e + 1}`,
|
|
78
|
+
timeframe: t.timeframe ?? "5m"
|
|
79
|
+
};
|
|
80
|
+
return this.options.syncCrosshair !== !1 && (r.on("crosshairMove", (e) => {
|
|
81
|
+
let t = e.payload.bar?.time;
|
|
82
|
+
if (t !== void 0) for (let e of this.cells) e.chart !== r && e.chart.setCrosshairTime(t);
|
|
83
|
+
}), r.on("crosshairLeave", () => {
|
|
84
|
+
for (let e of this.cells) e.chart !== r && e.chart.setCrosshairTime(null);
|
|
85
|
+
})), this.options.syncTimeAxis !== !1 && r.on("visibleRangeChange", (e) => {
|
|
86
|
+
if (this.syncing) return;
|
|
87
|
+
this.syncing = !0;
|
|
88
|
+
let { from: t, to: n } = e.payload, i = r.getData();
|
|
89
|
+
if (i.length > 0 && t >= 0 && n < i.length) {
|
|
90
|
+
let e = i[t]?.time, a = i[n]?.time;
|
|
91
|
+
if (e && a) for (let t of this.cells) t.chart !== r && t.chart.setVisibleRange(e, a);
|
|
92
|
+
}
|
|
93
|
+
this.syncing = !1;
|
|
94
|
+
}), a;
|
|
95
95
|
}
|
|
96
96
|
setLayout(e) {
|
|
97
97
|
if (e === this.layout) return;
|
|
@@ -100,23 +100,8 @@ var U = {
|
|
|
100
100
|
let t = this.cells[e];
|
|
101
101
|
t.chart.destroy(), t.container.remove(), this.cells.pop();
|
|
102
102
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
n.style.cssText = "position:relative;overflow:hidden;min-width:0;min-height:0;", this.root.appendChild(n);
|
|
106
|
-
let r = new u(n, {
|
|
107
|
-
chartType: "candlestick",
|
|
108
|
-
autoScale: !0,
|
|
109
|
-
...this.options.chartOptions,
|
|
110
|
-
...t.chartOptions,
|
|
111
|
-
theme: this.options.theme
|
|
112
|
-
});
|
|
113
|
-
this.cells.push({
|
|
114
|
-
container: n,
|
|
115
|
-
chart: r,
|
|
116
|
-
symbol: t.symbol ?? `Chart ${e + 1}`,
|
|
117
|
-
timeframe: t.timeframe ?? "5m"
|
|
118
|
-
});
|
|
119
|
-
}
|
|
103
|
+
this.layout = e, this.applyLayout();
|
|
104
|
+
for (let e = t; e < i; e++) this.cells.push(this.createCell(e));
|
|
120
105
|
}
|
|
121
106
|
getChart(e) {
|
|
122
107
|
return this.cells[e]?.chart ?? null;
|
|
@@ -140,7 +125,7 @@ var U = {
|
|
|
140
125
|
async connectAll(e, t, n, r = 500) {
|
|
141
126
|
let i = [];
|
|
142
127
|
for (let a = 0; a < this.cells.length && a < t.length; a++) i.push(this.connectCell(a, {
|
|
143
|
-
adapter: e,
|
|
128
|
+
adapter: typeof e == "function" ? e(t[a], a) : e,
|
|
144
129
|
symbol: t[a],
|
|
145
130
|
timeframe: n,
|
|
146
131
|
historyLimit: r
|
|
@@ -157,13 +142,13 @@ var U = {
|
|
|
157
142
|
this.cells = [], this.root.remove();
|
|
158
143
|
}
|
|
159
144
|
}
|
|
160
|
-
},
|
|
145
|
+
}, W = class extends V {
|
|
161
146
|
options;
|
|
162
147
|
constructor(e, t) {
|
|
163
148
|
super(e, t.theme), this.options = t, this.requestRender();
|
|
164
149
|
}
|
|
165
150
|
renderChart(e, t, n, r) {
|
|
166
|
-
|
|
151
|
+
Rt(e, t, n, this.options, r);
|
|
167
152
|
}
|
|
168
153
|
update(e) {
|
|
169
154
|
this.options = {
|
|
@@ -177,7 +162,7 @@ var U = {
|
|
|
177
162
|
...e
|
|
178
163
|
}, this.requestRender();
|
|
179
164
|
}
|
|
180
|
-
},
|
|
165
|
+
}, Xt = class extends V {
|
|
181
166
|
options;
|
|
182
167
|
crosshair = null;
|
|
183
168
|
constructor(e, t) {
|
|
@@ -185,7 +170,7 @@ var U = {
|
|
|
185
170
|
}
|
|
186
171
|
renderChart(e, t, n, r) {
|
|
187
172
|
let i = this.crosshair?.getPosition() ?? null;
|
|
188
|
-
|
|
173
|
+
Pt(e, t, n, this.options, r, i);
|
|
189
174
|
}
|
|
190
175
|
update(e) {
|
|
191
176
|
this.options = {
|
|
@@ -202,7 +187,7 @@ var U = {
|
|
|
202
187
|
destroy() {
|
|
203
188
|
this.crosshair?.destroy(), super.destroy();
|
|
204
189
|
}
|
|
205
|
-
},
|
|
190
|
+
}, G = class extends V {
|
|
206
191
|
options;
|
|
207
192
|
crosshair = null;
|
|
208
193
|
constructor(e, t) {
|
|
@@ -210,7 +195,7 @@ var U = {
|
|
|
210
195
|
}
|
|
211
196
|
renderChart(e, t, n, r) {
|
|
212
197
|
let i = this.crosshair?.getPosition() ?? null;
|
|
213
|
-
|
|
198
|
+
Ft(e, t, n, this.options, r, i);
|
|
214
199
|
}
|
|
215
200
|
update(e, t) {
|
|
216
201
|
this.options = {
|
|
@@ -230,7 +215,7 @@ var U = {
|
|
|
230
215
|
destroy() {
|
|
231
216
|
this.crosshair?.destroy(), super.destroy();
|
|
232
217
|
}
|
|
233
|
-
},
|
|
218
|
+
}, K = class extends V {
|
|
234
219
|
options;
|
|
235
220
|
crosshair = null;
|
|
236
221
|
cachedRects = [];
|
|
@@ -256,8 +241,8 @@ var U = {
|
|
|
256
241
|
id: e.id,
|
|
257
242
|
weight: e.weight ?? (Math.abs(e.value) || 1)
|
|
258
243
|
}));
|
|
259
|
-
this.cachedRects =
|
|
260
|
-
} else this.cachedRects =
|
|
244
|
+
this.cachedRects = kt(n, e, t);
|
|
245
|
+
} else this.cachedRects = At(this.currentData.map((e) => ({ id: e.id })), e, t);
|
|
261
246
|
}
|
|
262
247
|
onCanvasClick(e, t) {
|
|
263
248
|
if (this.options.onCellClick) for (let n of this.cachedRects) {
|
|
@@ -272,7 +257,7 @@ var U = {
|
|
|
272
257
|
renderChart(e, t, n, r) {
|
|
273
258
|
(t !== this.lastLayoutWidth || n !== this.lastLayoutHeight) && this.recomputeLayout();
|
|
274
259
|
let i = this.crosshair?.getPosition() ?? null;
|
|
275
|
-
|
|
260
|
+
Lt(e, t, n, this.currentData, this.cachedRects, this.options, r, i);
|
|
276
261
|
}
|
|
277
262
|
update(e) {
|
|
278
263
|
this.currentData = e, this.options = {
|
|
@@ -289,7 +274,7 @@ var U = {
|
|
|
289
274
|
destroy() {
|
|
290
275
|
this.crosshair?.destroy(), this.handleClick && this.canvas.removeEventListener("click", this.handleClick), super.destroy();
|
|
291
276
|
}
|
|
292
|
-
},
|
|
277
|
+
}, Zt = class extends V {
|
|
293
278
|
options;
|
|
294
279
|
crosshair = null;
|
|
295
280
|
constructor(e, t) {
|
|
@@ -297,7 +282,7 @@ var U = {
|
|
|
297
282
|
}
|
|
298
283
|
renderChart(e, t, n, r) {
|
|
299
284
|
let i = this.crosshair?.getPosition() ?? null;
|
|
300
|
-
|
|
285
|
+
zt(e, t, n, this.options, r, i);
|
|
301
286
|
}
|
|
302
287
|
update(e) {
|
|
303
288
|
this.options = {
|
|
@@ -314,12 +299,12 @@ var U = {
|
|
|
314
299
|
destroy() {
|
|
315
300
|
this.crosshair?.destroy(), super.destroy();
|
|
316
301
|
}
|
|
317
|
-
},
|
|
318
|
-
function
|
|
302
|
+
}, Qt = 500;
|
|
303
|
+
function $t(e) {
|
|
319
304
|
let t = 1 - e;
|
|
320
305
|
return 1 - t * t * t;
|
|
321
306
|
}
|
|
322
|
-
var
|
|
307
|
+
var en = class extends V {
|
|
323
308
|
options;
|
|
324
309
|
currentValue;
|
|
325
310
|
targetValue;
|
|
@@ -330,7 +315,7 @@ var ft = class extends B {
|
|
|
330
315
|
super(e, t.theme), this.options = t, this.currentValue = t.value, this.targetValue = t.value, this.requestRender();
|
|
331
316
|
}
|
|
332
317
|
renderChart(e, t, n, r) {
|
|
333
|
-
|
|
318
|
+
It(e, t, n, this.options, r, this.currentValue);
|
|
334
319
|
}
|
|
335
320
|
setValue(e) {
|
|
336
321
|
if (this.options.animate === !1) {
|
|
@@ -360,7 +345,7 @@ var ft = class extends B {
|
|
|
360
345
|
if (this.animationFrameId !== null) return;
|
|
361
346
|
let e = () => {
|
|
362
347
|
if (this.animationFrameId = null, this.animationStart === null) return;
|
|
363
|
-
let t = this.options.animationDuration ??
|
|
348
|
+
let t = this.options.animationDuration ?? Qt, n = performance.now() - this.animationStart, r = Math.min(1, n / Math.max(1, t)), i = $t(r);
|
|
364
349
|
this.currentValue = this.animationFrom + (this.targetValue - this.animationFrom) * i, this.requestRender(), r < 1 ? this.animationFrameId = requestAnimationFrame(e) : (this.currentValue = this.targetValue, this.animationStart = null);
|
|
365
350
|
};
|
|
366
351
|
this.animationFrameId = requestAnimationFrame(e);
|
|
@@ -371,7 +356,7 @@ var ft = class extends B {
|
|
|
371
356
|
destroy() {
|
|
372
357
|
this.cancelAnimation(), super.destroy();
|
|
373
358
|
}
|
|
374
|
-
},
|
|
359
|
+
}, tn = [
|
|
375
360
|
"Jan",
|
|
376
361
|
"Feb",
|
|
377
362
|
"Mar",
|
|
@@ -406,7 +391,7 @@ function Y(e) {
|
|
|
406
391
|
if (e.length === 0) return [];
|
|
407
392
|
let t = [];
|
|
408
393
|
for (let n of e) {
|
|
409
|
-
let e =
|
|
394
|
+
let e = Ie(n.time, "1M"), r = t[t.length - 1];
|
|
410
395
|
r && r.key === e ? r.close = n.equity : t.push({
|
|
411
396
|
key: e,
|
|
412
397
|
close: n.equity
|
|
@@ -419,7 +404,7 @@ function Y(e) {
|
|
|
419
404
|
let a = new Date(e.key), o = a.getUTCFullYear(), s = a.getUTCMonth();
|
|
420
405
|
r.push({
|
|
421
406
|
id: `${o}-${String(s + 1).padStart(2, "0")}`,
|
|
422
|
-
label:
|
|
407
|
+
label: tn[s],
|
|
423
408
|
group: String(o),
|
|
424
409
|
value: i
|
|
425
410
|
});
|
|
@@ -479,9 +464,9 @@ function Q(e) {
|
|
|
479
464
|
//#endregion
|
|
480
465
|
//#region src/finance/PerformanceDashboard.ts
|
|
481
466
|
function $(e) {
|
|
482
|
-
return !e || e === "dark" ?
|
|
467
|
+
return !e || e === "dark" ? pe : e === "light" ? y : e;
|
|
483
468
|
}
|
|
484
|
-
var
|
|
469
|
+
var nn = class {
|
|
485
470
|
options;
|
|
486
471
|
theme;
|
|
487
472
|
root;
|
|
@@ -524,7 +509,7 @@ var mt = class {
|
|
|
524
509
|
"gap:14px"
|
|
525
510
|
].join(";"), this.root.appendChild(o);
|
|
526
511
|
let s = this.buildPanel("Equity Curve", i, a);
|
|
527
|
-
s.wrap.style.gridColumn = "1 / -1", o.appendChild(s.wrap), this.equityChart = new
|
|
512
|
+
s.wrap.style.gridColumn = "1 / -1", o.appendChild(s.wrap), this.equityChart = new G(s.body, {
|
|
528
513
|
data: q(t.equityCurve),
|
|
529
514
|
theme: e,
|
|
530
515
|
lineColor: e.candleUp,
|
|
@@ -532,7 +517,7 @@ var mt = class {
|
|
|
532
517
|
crosshair: !0
|
|
533
518
|
});
|
|
534
519
|
let c = this.buildPanel("Drawdown", i, a);
|
|
535
|
-
o.appendChild(c.wrap), this.drawdownChart = new
|
|
520
|
+
o.appendChild(c.wrap), this.drawdownChart = new G(c.body, {
|
|
536
521
|
data: J(t.equityCurve),
|
|
537
522
|
theme: e,
|
|
538
523
|
lineColor: e.candleDown,
|
|
@@ -541,7 +526,7 @@ var mt = class {
|
|
|
541
526
|
valueFormat: (e) => `${e.toFixed(1)}%`
|
|
542
527
|
});
|
|
543
528
|
let l = Y(t.equityCurve), u = this.buildPanel("Monthly Returns", i, a);
|
|
544
|
-
o.appendChild(u.wrap), this.heatmap = new
|
|
529
|
+
o.appendChild(u.wrap), this.heatmap = new K(u.body, {
|
|
545
530
|
data: l,
|
|
546
531
|
theme: e,
|
|
547
532
|
showValues: !0,
|
|
@@ -630,6 +615,6 @@ var mt = class {
|
|
|
630
615
|
}
|
|
631
616
|
};
|
|
632
617
|
//#endregion
|
|
633
|
-
export {
|
|
618
|
+
export { Be as AlertManager, Ve as Animator, He as BarCountdown, Ue as BinanceAdapter, We as BybitAdapter, i as Chart, Yt as ChartGrid, Ge as ChartLegend, Ke as ChartStateManager, qe as CoinbaseAdapter, Je as CompareRenderer, Ye as CrosshairTooltip, Xe as CurrentPriceLine, de as DARK_TERMINAL, fe as DARK_THEME, d as DEFAULT_DRAWING_STYLE, r as DEFAULT_HISTORY_PAGE_SIZE, Ze as DEFAULT_LEGEND_CONFIG, f as DEFAULT_RECONNECT, Qe as DEFAULT_SESSION_HOURS, p as DEFAULT_SIGNAL_STYLE, m as DEFAULT_STREAM_CONFIG, h as DEFAULT_TIMEFRAME_FAVORITES, g as DEFAULT_TRADE_ZONE_STYLE, _ as DEFAULT_TRADING_CONFIG, $e as DataExporter, e as DataManager, Xt as DepthChart, ne as DragDropImporter, et as DrawingBase, u as EXCHANGE_TIMEZONE, tt as Easing, G as EquityCurveChart, en as GaugeChart, le as HISTORY_RETRY_MS, K as HeatmapChart, nt as IndicatorBase, rt as IndicatorValueMap, it as KeyboardHandler, at as KrakenAdapter, v as LIGHT_THEME, ce as LayoutManager, oe as LayoutSession, b as MARKET_CRYPTO, x as MARKET_HNX, S as MARKET_HOSE, C as MARKET_NYSE, w as MARKET_UPCOM, ot as MAX_ALERT_BARS, te as MAX_LAYOUT_NAME, st as MIN_ALERT_BARS, ct as MockAdapter, c as PLUGIN_API_VERSION, T as PRICE_SOURCES, lt as PaperExecutionAdapter, nn as PerformanceDashboard, se as PluginManager, ut as PollingAdapter, dt as RANGE_PRESETS, ft as ReplayManager, pt as ResamplingAdapter, mt as Screenshot, ht as SessionBreaks, gt as SessionShading, _t as SignalMarkerManager, W as SparklineChart, vt as StreamManager, E as TC_PALETTE, D as TC_SERIES_COLORS, O as TIMEFRAMES_CRYPTO, k as TIMEFRAMES_FOREX, A as TIMEFRAMES_STOCK, ue as ThemeManager, yt as TickAggregator, bt as TickBarAdapter, xt as TickBarBuilder, St as TradeZoneManager, Ct as UndoRedoManager, j as VN_COLORS, wt as VolumeRenderer, Zt as WaterfallChart, Tt as Watermark, Et as WebSocketAdapter, ie as cleanLayoutName, a as clearGlobalPlugins, J as computeDrawdownCurve, Y as computeMonthlyReturns, M as computePriceLimits, N as createVNTheme, P as formatFraction, F as formatNumber, Dt as formatTooltipTime, I as formatVND, L as formatVolumeLoc, R as fractionTick, z as getCurrentSession, o as getGlobalPlugins, B as getLocale, me as indicatorSource, Ot as isPriceLevelAlert, he as isPriceSource, ge as isTimeFrame, _e as isValidTimeZone, l as localStorageLayouts, jt as lttbDownsample, Mt as lttbVisibleIndices, ve as marketStatus, n as memoryLayouts, ye as normalizeBar, be as normalizeBarTime, xe as offsetAt, s as overlaysForLayer, Se as parseIndicatorSource, ae as parseOHLCV, Ce as parseTimeframe, we as pickBaseTimeframe, t as pluginKey, Te as priceFormatterFor, Nt as rangePresetStart, Ee as rankSymbols, De as readNews, Oe as readQuote, ke as registerLocale, re as registerPlugin, Ae as resampleBars, Q as selectKeyStats, Bt as servesTimeframe, je as setLocale, Me as sourcePrice, Ne as stepDecimals, Pe as t, Fe as tickBarCount, Le as timeframeToMs, q as toEquityPoints, Vt as toHeikinAshi, Ht as toKagi, Ut as toLineBreak, Wt as toPointAndFigure, Gt as toRangeBars, Kt as toRenko, ee as unregisterPlugin, Re as wallToUtc, qt as withResampling, Jt as withTickBars, ze as zoneOffsetMinutes };
|
|
634
619
|
|
|
635
620
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/grid/ChartGrid.ts","../src/finance/SparklineChart.ts","../src/finance/DepthChart.ts","../src/finance/EquityCurveChart.ts","../src/finance/HeatmapChart.ts","../src/finance/WaterfallChart.ts","../src/finance/GaugeChart.ts","../src/finance/performanceData.ts","../src/finance/PerformanceDashboard.ts"],"sourcesContent":["import type { ChartOptions, Theme, TimeFrame, DataSeries, DataAdapter, StreamConfig } from '@tradecanvas/commons';\r\nimport { Chart } from '../Chart.js';\r\n\r\nexport type GridLayout = '1x1' | '1x2' | '2x1' | '2x2' | '1x3' | '3x1' | '2x3' | '3x2';\r\n\r\nexport interface GridCellConfig {\r\n symbol?: string;\r\n timeframe?: TimeFrame;\r\n chartOptions?: Partial<ChartOptions>;\r\n}\r\n\r\nexport interface ChartGridOptions {\r\n layout?: GridLayout;\r\n theme?: ChartOptions['theme'];\r\n syncCrosshair?: boolean;\r\n syncTimeAxis?: boolean;\r\n gap?: number;\r\n cells?: GridCellConfig[];\r\n chartOptions?: Partial<ChartOptions>;\r\n}\r\n\r\ninterface GridCell {\r\n container: HTMLDivElement;\r\n chart: Chart;\r\n symbol: string;\r\n timeframe: TimeFrame;\r\n}\r\n\r\nconst LAYOUT_MAP: Record<GridLayout, { cols: number; rows: number }> = {\r\n '1x1': { cols: 1, rows: 1 },\r\n '1x2': { cols: 2, rows: 1 },\r\n '2x1': { cols: 1, rows: 2 },\r\n '2x2': { cols: 2, rows: 2 },\r\n '1x3': { cols: 3, rows: 1 },\r\n '3x1': { cols: 1, rows: 3 },\r\n '2x3': { cols: 3, rows: 2 },\r\n '3x2': { cols: 2, rows: 3 },\r\n};\r\n\r\nexport class ChartGrid {\r\n private root: HTMLDivElement;\r\n private cells: GridCell[] = [];\r\n private layout: GridLayout;\r\n private options: ChartGridOptions;\r\n private destroyed = false;\r\n private syncing = false;\r\n\r\n constructor(container: HTMLElement, options: ChartGridOptions = {}) {\r\n this.options = options;\r\n this.layout = options.layout ?? '2x2';\r\n\r\n this.root = document.createElement('div');\r\n this.root.style.cssText = 'display:grid;width:100%;height:100%;overflow:hidden;';\r\n container.appendChild(this.root);\r\n\r\n this.applyLayout();\r\n this.createCells();\r\n }\r\n\r\n private applyLayout(): void {\r\n const { cols, rows } = LAYOUT_MAP[this.layout];\r\n const gap = this.options.gap ?? 1;\r\n this.root.style.gridTemplateColumns = `repeat(${cols}, 1fr)`;\r\n this.root.style.gridTemplateRows = `repeat(${rows}, 1fr)`;\r\n this.root.style.gap = `${gap}px`;\r\n }\r\n\r\n private createCells(): void {\r\n const { cols, rows } = LAYOUT_MAP[this.layout];\r\n const count = cols * rows;\r\n\r\n for (let i = 0; i < count; i++) {\r\n const cellConfig = this.options.cells?.[i] ?? {};\r\n\r\n const cellEl = document.createElement('div');\r\n cellEl.style.cssText = 'position:relative;overflow:hidden;min-width:0;min-height:0;';\r\n this.root.appendChild(cellEl);\r\n\r\n const chartOpts: ChartOptions = {\r\n chartType: 'candlestick',\r\n autoScale: true,\r\n features: {\r\n crosshair: true,\r\n keyboard: true,\r\n volume: true,\r\n legend: true,\r\n priceAxis: true,\r\n timeAxis: true,\r\n grid: true,\r\n },\r\n ...this.options.chartOptions,\r\n ...cellConfig.chartOptions,\r\n theme: this.options.theme,\r\n };\r\n\r\n const chart = new Chart(cellEl, chartOpts);\r\n\r\n const cell: GridCell = {\r\n container: cellEl,\r\n chart,\r\n symbol: cellConfig.symbol ?? `Chart ${i + 1}`,\r\n timeframe: cellConfig.timeframe ?? '5m',\r\n };\r\n\r\n if (this.options.syncCrosshair !== false) {\r\n chart.on('crosshairMove', (e) => {\r\n if (this.syncing) return;\r\n this.syncing = true;\r\n for (const other of this.cells) {\r\n if (other.chart !== chart) {\r\n other.chart.setCrosshairPosition(e.payload.point);\r\n }\r\n }\r\n this.syncing = false;\r\n });\r\n }\r\n\r\n if (this.options.syncTimeAxis !== false) {\r\n chart.on('visibleRangeChange', (e) => {\r\n if (this.syncing) return;\r\n this.syncing = true;\r\n const { from, to } = e.payload;\r\n const srcData = chart.getData();\r\n if (srcData.length > 0 && from >= 0 && to < srcData.length) {\r\n const fromTime = srcData[from]?.time;\r\n const toTime = srcData[to]?.time;\r\n if (fromTime && toTime) {\r\n for (const other of this.cells) {\r\n if (other.chart !== chart) {\r\n other.chart.setVisibleRange(fromTime, toTime);\r\n }\r\n }\r\n }\r\n }\r\n this.syncing = false;\r\n });\r\n }\r\n\r\n this.cells.push(cell);\r\n }\r\n }\r\n\r\n setLayout(layout: GridLayout): void {\r\n if (layout === this.layout) return;\r\n const oldCount = this.cells.length;\r\n const { cols, rows } = LAYOUT_MAP[layout];\r\n const newCount = cols * rows;\r\n\r\n if (newCount < oldCount) {\r\n for (let i = oldCount - 1; i >= newCount; i--) {\r\n const cell = this.cells[i];\r\n cell.chart.destroy();\r\n cell.container.remove();\r\n this.cells.pop();\r\n }\r\n }\r\n\r\n this.layout = layout;\r\n this.applyLayout();\r\n\r\n if (newCount > oldCount) {\r\n for (let i = oldCount; i < newCount; i++) {\r\n const cellConfig = this.options.cells?.[i] ?? {};\r\n const cellEl = document.createElement('div');\r\n cellEl.style.cssText = 'position:relative;overflow:hidden;min-width:0;min-height:0;';\r\n this.root.appendChild(cellEl);\r\n\r\n const chart = new Chart(cellEl, {\r\n chartType: 'candlestick',\r\n autoScale: true,\r\n ...this.options.chartOptions,\r\n ...cellConfig.chartOptions,\r\n theme: this.options.theme,\r\n });\r\n\r\n this.cells.push({\r\n container: cellEl,\r\n chart,\r\n symbol: cellConfig.symbol ?? `Chart ${i + 1}`,\r\n timeframe: cellConfig.timeframe ?? '5m',\r\n });\r\n }\r\n }\r\n }\r\n\r\n getChart(index: number): Chart | null {\r\n return this.cells[index]?.chart ?? null;\r\n }\r\n\r\n getCharts(): Chart[] {\r\n return this.cells.map(c => c.chart);\r\n }\r\n\r\n getCellCount(): number {\r\n return this.cells.length;\r\n }\r\n\r\n setData(index: number, data: DataSeries): void {\r\n this.cells[index]?.chart.setData(data);\r\n }\r\n\r\n setAllData(data: DataSeries): void {\r\n for (const cell of this.cells) {\r\n cell.chart.setData(data);\r\n }\r\n }\r\n\r\n async connectCell(index: number, config: StreamConfig): Promise<void> {\r\n const cell = this.cells[index];\r\n if (!cell) return;\r\n cell.symbol = config.symbol;\r\n cell.timeframe = config.timeframe;\r\n await cell.chart.connect(config);\r\n }\r\n\r\n async connectAll(adapter: DataAdapter, symbols: string[], timeframe: TimeFrame, historyLimit = 500): Promise<void> {\r\n const promises: Promise<void>[] = [];\r\n for (let i = 0; i < this.cells.length && i < symbols.length; i++) {\r\n promises.push(this.connectCell(i, {\r\n adapter,\r\n symbol: symbols[i],\r\n timeframe,\r\n historyLimit,\r\n }));\r\n }\r\n await Promise.all(promises);\r\n }\r\n\r\n setTheme(theme: Theme): void {\r\n for (const cell of this.cells) {\r\n cell.chart.setTheme(theme);\r\n }\r\n }\r\n\r\n destroy(): void {\r\n if (this.destroyed) return;\r\n this.destroyed = true;\r\n for (const cell of this.cells) {\r\n cell.chart.destroy();\r\n cell.container.remove();\r\n }\r\n this.cells = [];\r\n this.root.remove();\r\n }\r\n}\r\n","import type { SparklineOptions, Theme } from '@tradecanvas/commons';\r\nimport { BaseFinanceChart, renderSparkline } from '@tradecanvas/core';\r\n\r\nexport class SparklineChart extends BaseFinanceChart {\r\n private options: SparklineOptions;\r\n\r\n constructor(container: HTMLElement, options: SparklineOptions) {\r\n super(container, options.theme);\r\n this.options = options;\r\n this.requestRender();\r\n }\r\n\r\n protected renderChart(\r\n ctx: CanvasRenderingContext2D,\r\n width: number,\r\n height: number,\r\n theme: Theme,\r\n ): void {\r\n renderSparkline(ctx, width, height, this.options, theme);\r\n }\r\n\r\n update(data: number[]): void {\r\n this.options = { ...this.options, data };\r\n this.requestRender();\r\n }\r\n\r\n setOptions(opts: Partial<SparklineOptions>): void {\r\n this.options = { ...this.options, ...opts };\r\n this.requestRender();\r\n }\r\n}\r\n","import type { DepthChartOptions, DepthData, Theme } from '@tradecanvas/commons';\r\nimport { BaseFinanceChart, FinanceCrosshair, renderDepthChart } from '@tradecanvas/core';\r\n\r\nexport class DepthChart extends BaseFinanceChart {\r\n private options: DepthChartOptions;\r\n private crosshair: FinanceCrosshair | null = null;\r\n\r\n constructor(container: HTMLElement, options: DepthChartOptions) {\r\n super(container, options.theme);\r\n this.options = options;\r\n\r\n if (options.crosshair !== false) {\r\n this.crosshair = new FinanceCrosshair(this.canvas, () => this.requestRender());\r\n }\r\n\r\n this.requestRender();\r\n }\r\n\r\n protected renderChart(\r\n ctx: CanvasRenderingContext2D,\r\n width: number,\r\n height: number,\r\n theme: Theme,\r\n ): void {\r\n const pos = this.crosshair?.getPosition() ?? null;\r\n renderDepthChart(ctx, width, height, this.options, theme, pos);\r\n }\r\n\r\n update(data: DepthData): void {\r\n this.options = { ...this.options, data };\r\n this.requestRender();\r\n }\r\n\r\n setOptions(opts: Partial<DepthChartOptions>): void {\r\n this.options = { ...this.options, ...opts };\r\n this.requestRender();\r\n }\r\n\r\n destroy(): void {\r\n this.crosshair?.destroy();\r\n super.destroy();\r\n }\r\n}\r\n","import type { EquityCurveOptions, EquityPoint, Theme } from '@tradecanvas/commons';\r\nimport { BaseFinanceChart, FinanceCrosshair, renderEquityCurve } from '@tradecanvas/core';\r\n\r\nexport class EquityCurveChart extends BaseFinanceChart {\r\n private options: EquityCurveOptions;\r\n private crosshair: FinanceCrosshair | null = null;\r\n\r\n constructor(container: HTMLElement, options: EquityCurveOptions) {\r\n super(container, options.theme);\r\n this.options = options;\r\n\r\n if (options.crosshair !== false) {\r\n this.crosshair = new FinanceCrosshair(this.canvas, () => this.requestRender());\r\n }\r\n\r\n this.requestRender();\r\n }\r\n\r\n protected renderChart(\r\n ctx: CanvasRenderingContext2D,\r\n width: number,\r\n height: number,\r\n theme: Theme,\r\n ): void {\r\n const pos = this.crosshair?.getPosition() ?? null;\r\n renderEquityCurve(ctx, width, height, this.options, theme, pos);\r\n }\r\n\r\n update(data: EquityPoint[], benchmark?: EquityPoint[]): void {\r\n this.options = { ...this.options, data };\r\n if (benchmark !== undefined) {\r\n this.options = { ...this.options, benchmark };\r\n }\r\n this.requestRender();\r\n }\r\n\r\n setOptions(opts: Partial<EquityCurveOptions>): void {\r\n this.options = { ...this.options, ...opts };\r\n this.requestRender();\r\n }\r\n\r\n destroy(): void {\r\n this.crosshair?.destroy();\r\n super.destroy();\r\n }\r\n}\r\n","import type { HeatmapCell, HeatmapOptions, Theme } from '@tradecanvas/commons';\r\nimport {\r\n BaseFinanceChart,\r\n FinanceCrosshair,\r\n layoutUniformGrid,\r\n layoutSquarifiedTreemap,\r\n renderHeatmap,\r\n} from '@tradecanvas/core';\r\nimport type { LayoutRect } from '@tradecanvas/core';\r\n\r\nexport class HeatmapChart extends BaseFinanceChart {\r\n private options: HeatmapOptions;\r\n private crosshair: FinanceCrosshair | null = null;\r\n private cachedRects: LayoutRect[] = [];\r\n private currentData: HeatmapCell[] = [];\r\n private lastLayoutWidth = 0;\r\n private lastLayoutHeight = 0;\r\n private handleClick: ((e: MouseEvent) => void) | null = null;\r\n\r\n constructor(container: HTMLElement, options: HeatmapOptions) {\r\n super(container, options.theme);\r\n this.options = options;\r\n this.currentData = options.data ?? [];\r\n\r\n if (options.crosshair !== false) {\r\n this.crosshair = new FinanceCrosshair(this.canvas, () => this.requestRender());\r\n }\r\n\r\n if (options.onCellClick) {\r\n this.handleClick = (e: MouseEvent) => {\r\n const rect = this.canvas.getBoundingClientRect();\r\n const x = e.clientX - rect.left;\r\n const y = e.clientY - rect.top;\r\n this.onCanvasClick(x, y);\r\n };\r\n this.canvas.addEventListener('click', this.handleClick);\r\n }\r\n\r\n this.recomputeLayout();\r\n this.requestRender();\r\n }\r\n\r\n private recomputeLayout(): void {\r\n const bounds = { x: 0, y: 0, width: this.width, height: this.height };\r\n const padding = this.options.cellPadding ?? 2;\r\n this.lastLayoutWidth = this.width;\r\n this.lastLayoutHeight = this.height;\r\n\r\n if (this.options.weighted) {\r\n const weighted = this.currentData.map(c => ({\r\n id: c.id,\r\n weight: c.weight ?? (Math.abs(c.value) || 1),\r\n }));\r\n this.cachedRects = layoutSquarifiedTreemap(weighted, bounds, padding);\r\n } else {\r\n this.cachedRects = layoutUniformGrid(\r\n this.currentData.map(c => ({ id: c.id })),\r\n bounds,\r\n padding,\r\n );\r\n }\r\n }\r\n\r\n private onCanvasClick(x: number, y: number): void {\r\n if (!this.options.onCellClick) return;\r\n\r\n for (const lr of this.cachedRects) {\r\n const r = lr.rect;\r\n if (x >= r.x && x <= r.x + r.width && y >= r.y && y <= r.y + r.height) {\r\n const cell = this.currentData.find(c => c.id === lr.id);\r\n if (cell) this.options.onCellClick(cell);\r\n return;\r\n }\r\n }\r\n }\r\n\r\n protected renderChart(\r\n ctx: CanvasRenderingContext2D,\r\n width: number,\r\n height: number,\r\n theme: Theme,\r\n ): void {\r\n if (width !== this.lastLayoutWidth || height !== this.lastLayoutHeight) {\r\n this.recomputeLayout();\r\n }\r\n\r\n const pos = this.crosshair?.getPosition() ?? null;\r\n renderHeatmap(ctx, width, height, this.currentData, this.cachedRects, this.options, theme, pos);\r\n }\r\n\r\n update(data: HeatmapCell[]): void {\r\n this.currentData = data;\r\n this.options = { ...this.options, data };\r\n this.recomputeLayout();\r\n this.requestRender();\r\n }\r\n\r\n setOptions(opts: Partial<HeatmapOptions>): void {\r\n this.options = { ...this.options, ...opts };\r\n if (opts.data) {\r\n this.currentData = opts.data;\r\n }\r\n this.recomputeLayout();\r\n this.requestRender();\r\n }\r\n\r\n destroy(): void {\r\n this.crosshair?.destroy();\r\n if (this.handleClick) {\r\n this.canvas.removeEventListener('click', this.handleClick);\r\n }\r\n super.destroy();\r\n }\r\n}\r\n","import type { Theme, WaterfallBar, WaterfallOptions } from '@tradecanvas/commons';\r\nimport { BaseFinanceChart, FinanceCrosshair, renderWaterfall } from '@tradecanvas/core';\r\n\r\nexport class WaterfallChart extends BaseFinanceChart {\r\n private options: WaterfallOptions;\r\n private crosshair: FinanceCrosshair | null = null;\r\n\r\n constructor(container: HTMLElement, options: WaterfallOptions) {\r\n super(container, options.theme);\r\n this.options = options;\r\n\r\n if (options.crosshair !== false) {\r\n this.crosshair = new FinanceCrosshair(this.canvas, () => this.requestRender());\r\n }\r\n\r\n this.requestRender();\r\n }\r\n\r\n protected renderChart(\r\n ctx: CanvasRenderingContext2D,\r\n width: number,\r\n height: number,\r\n theme: Theme,\r\n ): void {\r\n const pos = this.crosshair?.getPosition() ?? null;\r\n renderWaterfall(ctx, width, height, this.options, theme, pos);\r\n }\r\n\r\n update(data: WaterfallBar[]): void {\r\n this.options = { ...this.options, data };\r\n this.requestRender();\r\n }\r\n\r\n setOptions(opts: Partial<WaterfallOptions>): void {\r\n this.options = { ...this.options, ...opts };\r\n this.requestRender();\r\n }\r\n\r\n destroy(): void {\r\n this.crosshair?.destroy();\r\n super.destroy();\r\n }\r\n}\r\n","import type { GaugeOptions, Theme } from '@tradecanvas/commons';\r\nimport { BaseFinanceChart, renderGauge } from '@tradecanvas/core';\r\n\r\nconst DEFAULT_ANIMATION_MS = 500;\r\n\r\nfunction easeOutCubic(t: number): number {\r\n const inv = 1 - t;\r\n return 1 - inv * inv * inv;\r\n}\r\n\r\nexport class GaugeChart extends BaseFinanceChart {\r\n private options: GaugeOptions;\r\n private currentValue: number;\r\n private targetValue: number;\r\n private animationStart: number | null = null;\r\n private animationFrom = 0;\r\n private animationFrameId: number | null = null;\r\n\r\n constructor(container: HTMLElement, options: GaugeOptions) {\r\n super(container, options.theme);\r\n this.options = options;\r\n this.currentValue = options.value;\r\n this.targetValue = options.value;\r\n this.requestRender();\r\n }\r\n\r\n protected renderChart(\r\n ctx: CanvasRenderingContext2D,\r\n width: number,\r\n height: number,\r\n theme: Theme,\r\n ): void {\r\n renderGauge(ctx, width, height, this.options, theme, this.currentValue);\r\n }\r\n\r\n setValue(value: number): void {\r\n const animate = this.options.animate !== false;\r\n if (!animate) {\r\n this.cancelAnimation();\r\n this.currentValue = value;\r\n this.targetValue = value;\r\n this.options = { ...this.options, value };\r\n this.requestRender();\r\n return;\r\n }\r\n\r\n this.targetValue = value;\r\n this.animationFrom = this.currentValue;\r\n this.animationStart = performance.now();\r\n this.options = { ...this.options, value };\r\n this.startAnimationLoop();\r\n }\r\n\r\n setOptions(opts: Partial<GaugeOptions>): void {\r\n const next = { ...this.options, ...opts };\r\n // If `value` is part of the partial, route through animation path\r\n if (opts.value !== undefined && opts.value !== this.targetValue) {\r\n this.options = next;\r\n this.setValue(opts.value);\r\n return;\r\n }\r\n this.options = next;\r\n this.requestRender();\r\n }\r\n\r\n private startAnimationLoop(): void {\r\n if (this.animationFrameId !== null) return;\r\n const step = (): void => {\r\n this.animationFrameId = null;\r\n if (this.animationStart === null) return;\r\n\r\n const duration = this.options.animationDuration ?? DEFAULT_ANIMATION_MS;\r\n const elapsed = performance.now() - this.animationStart;\r\n const t = Math.min(1, elapsed / Math.max(1, duration));\r\n const eased = easeOutCubic(t);\r\n this.currentValue = this.animationFrom + (this.targetValue - this.animationFrom) * eased;\r\n\r\n this.requestRender();\r\n\r\n if (t < 1) {\r\n this.animationFrameId = requestAnimationFrame(step);\r\n } else {\r\n this.currentValue = this.targetValue;\r\n this.animationStart = null;\r\n }\r\n };\r\n this.animationFrameId = requestAnimationFrame(step);\r\n }\r\n\r\n private cancelAnimation(): void {\r\n if (this.animationFrameId !== null) {\r\n cancelAnimationFrame(this.animationFrameId);\r\n this.animationFrameId = null;\r\n }\r\n this.animationStart = null;\r\n }\r\n\r\n destroy(): void {\r\n this.cancelAnimation();\r\n super.destroy();\r\n }\r\n}\r\n","import type { EquityPoint, HeatmapCell } from '@tradecanvas/commons';\r\nimport { timeframeBucketStart } from '@tradecanvas/commons';\r\n\r\n/** Minimal equity sample shape — structurally satisfied by analytics' EquityPoint. */\r\nexport interface EquitySample {\r\n time: number;\r\n equity: number;\r\n}\r\n\r\n/** Subset of analytics RiskMetrics needed to render the stats strip. */\r\nexport interface RiskMetricsLike {\r\n totalReturnPct: number;\r\n cagr: number;\r\n sharpe: number;\r\n sortino: number;\r\n maxDrawdownPct: number;\r\n winRate: number;\r\n profitFactor: number;\r\n trades: number;\r\n}\r\n\r\nexport interface DashboardStat {\r\n label: string;\r\n value: string;\r\n tone: 'positive' | 'negative' | 'neutral';\r\n}\r\n\r\nconst MONTH_LABELS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\r\n\r\n/** Map an analytics equity curve to the finance EquityCurveChart point shape. */\r\nexport function toEquityPoints(curve: ReadonlyArray<EquitySample>): EquityPoint[] {\r\n return curve.map((p) => ({ time: p.time, value: p.equity }));\r\n}\r\n\r\n/**\r\n * Underwater drawdown curve as a percentage (<= 0). Each point is the equity's\r\n * shortfall from the running peak: `equity / peak - 1`, expressed in percent.\r\n */\r\nexport function computeDrawdownCurve(curve: ReadonlyArray<EquitySample>): EquityPoint[] {\r\n let peak = -Infinity;\r\n return curve.map((p) => {\r\n if (p.equity > peak) peak = p.equity;\r\n const dd = peak > 0 ? (p.equity / peak - 1) * 100 : 0;\r\n return { time: p.time, value: dd };\r\n });\r\n}\r\n\r\n/**\r\n * Calendar-month returns as heatmap cells. Each month's return is chained off\r\n * the prior month's closing equity (the first month chains off its own opening\r\n * equity), so the series reads as sequential monthly performance. `group` is\r\n * the year and `value` is the return in percent.\r\n */\r\nexport function computeMonthlyReturns(curve: ReadonlyArray<EquitySample>): HeatmapCell[] {\r\n if (curve.length === 0) return [];\r\n\r\n // Collapse the curve to one closing equity per calendar month, in order.\r\n const months: { key: number; close: number }[] = [];\r\n for (const p of curve) {\r\n const key = timeframeBucketStart(p.time, '1M');\r\n const last = months[months.length - 1];\r\n if (last && last.key === key) {\r\n last.close = p.equity;\r\n } else {\r\n months.push({ key, close: p.equity });\r\n }\r\n }\r\n\r\n let prevClose = curve[0].equity;\r\n const cells: HeatmapCell[] = [];\r\n for (const m of months) {\r\n const base = prevClose === 0 ? 1 : prevClose;\r\n const returnPct = (m.close / base - 1) * 100;\r\n prevClose = m.close;\r\n const d = new Date(m.key);\r\n const year = d.getUTCFullYear();\r\n const month = d.getUTCMonth();\r\n cells.push({\r\n id: `${year}-${String(month + 1).padStart(2, '0')}`,\r\n label: MONTH_LABELS[month],\r\n group: String(year),\r\n value: returnPct,\r\n });\r\n }\r\n return cells;\r\n}\r\n\r\nfunction pct(value: number): string {\r\n const sign = value > 0 ? '+' : '';\r\n return `${sign}${value.toFixed(2)}%`;\r\n}\r\n\r\nfunction tone(value: number): DashboardStat['tone'] {\r\n if (value > 0) return 'positive';\r\n if (value < 0) return 'negative';\r\n return 'neutral';\r\n}\r\n\r\n/** The headline stats rendered as cards above the charts. */\r\nexport function selectKeyStats(metrics: RiskMetricsLike): DashboardStat[] {\r\n return [\r\n { label: 'Total Return', value: pct(metrics.totalReturnPct), tone: tone(metrics.totalReturnPct) },\r\n { label: 'CAGR', value: pct(metrics.cagr * 100), tone: tone(metrics.cagr) },\r\n { label: 'Sharpe', value: metrics.sharpe.toFixed(2), tone: tone(metrics.sharpe) },\r\n { label: 'Sortino', value: metrics.sortino.toFixed(2), tone: tone(metrics.sortino) },\r\n { label: 'Max Drawdown', value: pct(metrics.maxDrawdownPct), tone: 'negative' },\r\n { label: 'Win Rate', value: `${(metrics.winRate * 100).toFixed(1)}%`, tone: 'neutral' },\r\n { label: 'Profit Factor', value: Number.isFinite(metrics.profitFactor) ? metrics.profitFactor.toFixed(2) : '∞', tone: tone(metrics.profitFactor - 1) },\r\n { label: 'Trades', value: String(metrics.trades), tone: 'neutral' },\r\n ];\r\n}\r\n","import type { Theme, ThemeName } from '@tradecanvas/commons';\r\nimport { DARK_THEME, LIGHT_THEME } from '@tradecanvas/commons';\r\nimport { EquityCurveChart } from './EquityCurveChart.js';\r\nimport { HeatmapChart } from './HeatmapChart.js';\r\nimport {\r\n toEquityPoints,\r\n computeDrawdownCurve,\r\n computeMonthlyReturns,\r\n selectKeyStats,\r\n type EquitySample,\r\n type RiskMetricsLike,\r\n type DashboardStat,\r\n} from './performanceData.js';\r\n\r\n/** Structurally satisfied by analytics' `BacktestResult`. */\r\nexport interface PerformanceResult {\r\n equityCurve: ReadonlyArray<EquitySample>;\r\n metrics: RiskMetricsLike;\r\n}\r\n\r\nexport interface PerformanceDashboardOptions {\r\n result: PerformanceResult;\r\n theme?: ThemeName | Theme;\r\n title?: string;\r\n subtitle?: string;\r\n}\r\n\r\nfunction resolveTheme(theme?: ThemeName | Theme): Theme {\r\n if (!theme || theme === 'dark') return DARK_THEME;\r\n if (theme === 'light') return LIGHT_THEME;\r\n return theme as Theme;\r\n}\r\n\r\n/**\r\n * A composed strategy-performance dashboard: a headline stats strip, an equity\r\n * curve, an underwater drawdown panel, and a monthly-returns heatmap. Built\r\n * entirely from a backtest `result`, reusing the finance chart renderers.\r\n *\r\n * ```ts\r\n * const result = new Backtester(opts).run(bars, strategy);\r\n * const dash = new PerformanceDashboard(el, { result, theme: 'dark' });\r\n * ```\r\n */\r\nexport class PerformanceDashboard {\r\n private options: PerformanceDashboardOptions;\r\n private theme: Theme;\r\n private root: HTMLDivElement;\r\n private equityChart: EquityCurveChart | null = null;\r\n private drawdownChart: EquityCurveChart | null = null;\r\n private heatmap: HeatmapChart | null = null;\r\n\r\n constructor(container: HTMLElement, options: PerformanceDashboardOptions) {\r\n this.options = options;\r\n this.theme = resolveTheme(options.theme);\r\n this.root = document.createElement('div');\r\n this.build();\r\n container.appendChild(this.root);\r\n }\r\n\r\n private build(): void {\r\n const t = this.theme;\r\n const { result, title, subtitle } = this.options;\r\n const surface = this.panelBackground();\r\n const border = t.grid;\r\n\r\n this.root.style.cssText = [\r\n 'display:flex',\r\n 'flex-direction:column',\r\n 'gap:14px',\r\n 'width:100%',\r\n 'box-sizing:border-box',\r\n 'padding:16px',\r\n `background:${t.background}`,\r\n `color:${t.text}`,\r\n `font-family:${t.font.family}`,\r\n ].join(';');\r\n\r\n if (title || subtitle) {\r\n const header = document.createElement('div');\r\n if (title) {\r\n const h = document.createElement('div');\r\n h.textContent = title;\r\n h.style.cssText = `font-size:${t.font.sizeLarge}px;font-weight:600;letter-spacing:-0.01em;`;\r\n header.appendChild(h);\r\n }\r\n if (subtitle) {\r\n const s = document.createElement('div');\r\n s.textContent = subtitle;\r\n s.style.cssText = `font-size:${t.font.sizeSmall}px;color:${t.textSecondary};margin-top:2px;`;\r\n header.appendChild(s);\r\n }\r\n this.root.appendChild(header);\r\n }\r\n\r\n // Stats strip\r\n this.root.appendChild(this.buildStatsStrip(selectKeyStats(result.metrics), surface, border));\r\n\r\n // Chart grid\r\n const grid = document.createElement('div');\r\n grid.style.cssText = [\r\n 'display:grid',\r\n 'grid-template-columns:repeat(auto-fit, minmax(280px, 1fr))',\r\n 'grid-auto-rows:220px',\r\n 'gap:14px',\r\n ].join(';');\r\n this.root.appendChild(grid);\r\n\r\n const equityPanel = this.buildPanel('Equity Curve', surface, border);\r\n equityPanel.wrap.style.gridColumn = '1 / -1';\r\n grid.appendChild(equityPanel.wrap);\r\n this.equityChart = new EquityCurveChart(equityPanel.body, {\r\n data: toEquityPoints(result.equityCurve),\r\n theme: t,\r\n lineColor: t.candleUp,\r\n fillArea: true,\r\n crosshair: true,\r\n });\r\n\r\n const ddPanel = this.buildPanel('Drawdown', surface, border);\r\n grid.appendChild(ddPanel.wrap);\r\n this.drawdownChart = new EquityCurveChart(ddPanel.body, {\r\n data: computeDrawdownCurve(result.equityCurve),\r\n theme: t,\r\n lineColor: t.candleDown,\r\n fillArea: true,\r\n crosshair: true,\r\n valueFormat: (v) => `${v.toFixed(1)}%`,\r\n });\r\n\r\n const monthlyCells = computeMonthlyReturns(result.equityCurve);\r\n const heatPanel = this.buildPanel('Monthly Returns', surface, border);\r\n grid.appendChild(heatPanel.wrap);\r\n this.heatmap = new HeatmapChart(heatPanel.body, {\r\n data: monthlyCells,\r\n theme: t,\r\n showValues: true,\r\n valueFormat: (v) => `${v >= 0 ? '+' : ''}${v.toFixed(1)}`,\r\n colorScale: { negative: t.candleDown, zero: surface, positive: t.candleUp },\r\n });\r\n }\r\n\r\n private buildStatsStrip(stats: DashboardStat[], surface: string, border: string): HTMLDivElement {\r\n const strip = document.createElement('div');\r\n strip.style.cssText = [\r\n 'display:grid',\r\n 'grid-template-columns:repeat(auto-fit, minmax(120px, 1fr))',\r\n 'gap:10px',\r\n ].join(';');\r\n\r\n const t = this.theme;\r\n for (const stat of stats) {\r\n const card = document.createElement('div');\r\n card.style.cssText = [\r\n `background:${surface}`,\r\n `border:1px solid ${border}`,\r\n 'border-radius:10px',\r\n 'padding:10px 12px',\r\n 'display:flex',\r\n 'flex-direction:column',\r\n 'gap:4px',\r\n ].join(';');\r\n\r\n const label = document.createElement('div');\r\n label.textContent = stat.label;\r\n label.style.cssText = `font-size:${t.font.sizeSmall}px;color:${t.textSecondary};text-transform:uppercase;letter-spacing:0.04em;`;\r\n\r\n const value = document.createElement('div');\r\n value.textContent = stat.value;\r\n const color = stat.tone === 'positive' ? t.candleUp : stat.tone === 'negative' ? t.candleDown : t.text;\r\n value.style.cssText = `font-size:${t.font.sizeLarge}px;font-weight:600;color:${color};font-variant-numeric:tabular-nums;`;\r\n\r\n card.appendChild(label);\r\n card.appendChild(value);\r\n strip.appendChild(card);\r\n }\r\n return strip;\r\n }\r\n\r\n private buildPanel(title: string, surface: string, border: string): { wrap: HTMLDivElement; body: HTMLDivElement } {\r\n const t = this.theme;\r\n const wrap = document.createElement('div');\r\n wrap.style.cssText = [\r\n `background:${surface}`,\r\n `border:1px solid ${border}`,\r\n 'border-radius:10px',\r\n 'overflow:hidden',\r\n 'display:flex',\r\n 'flex-direction:column',\r\n ].join(';');\r\n\r\n const head = document.createElement('div');\r\n head.textContent = title;\r\n head.style.cssText = [\r\n `font-size:${t.font.sizeSmall}px`,\r\n 'font-weight:600',\r\n `color:${t.textSecondary}`,\r\n 'padding:8px 12px',\r\n `border-bottom:1px solid ${border}`,\r\n 'text-transform:uppercase',\r\n 'letter-spacing:0.04em',\r\n ].join(';');\r\n\r\n const body = document.createElement('div');\r\n body.style.cssText = 'flex:1;min-height:0;position:relative;';\r\n\r\n wrap.appendChild(head);\r\n wrap.appendChild(body);\r\n return { wrap, body };\r\n }\r\n\r\n /** A subtle surface tint distinct from the page background, per theme. */\r\n private panelBackground(): string {\r\n return this.theme.name === 'light' ? 'rgba(0,0,0,0.02)' : 'rgba(255,255,255,0.03)';\r\n }\r\n\r\n /** Replace the displayed result and re-render all panels. */\r\n update(result: PerformanceResult): void {\r\n this.options = { ...this.options, result };\r\n this.destroyCharts();\r\n this.root.replaceChildren();\r\n this.build();\r\n }\r\n\r\n setTheme(theme: ThemeName | Theme): void {\r\n this.theme = resolveTheme(theme);\r\n this.options = { ...this.options, theme };\r\n this.destroyCharts();\r\n this.root.replaceChildren();\r\n this.build();\r\n }\r\n\r\n private destroyCharts(): void {\r\n this.equityChart?.destroy();\r\n this.drawdownChart?.destroy();\r\n this.heatmap?.destroy();\r\n this.equityChart = null;\r\n this.drawdownChart = null;\r\n this.heatmap = null;\r\n }\r\n\r\n destroy(): void {\r\n this.destroyCharts();\r\n this.root.remove();\r\n }\r\n}\r\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/grid/ChartGrid.ts","../src/finance/SparklineChart.ts","../src/finance/DepthChart.ts","../src/finance/EquityCurveChart.ts","../src/finance/HeatmapChart.ts","../src/finance/WaterfallChart.ts","../src/finance/GaugeChart.ts","../src/finance/performanceData.ts","../src/finance/PerformanceDashboard.ts"],"sourcesContent":["import type { ChartOptions, Theme, TimeFrame, DataSeries, DataAdapter, StreamConfig } from '@tradecanvas/commons';\r\nimport { Chart } from '../Chart.js';\r\n\r\nexport type GridLayout = '1x1' | '1x2' | '2x1' | '2x2' | '1x3' | '3x1' | '2x3' | '3x2';\r\n\r\nexport interface GridCellConfig {\r\n symbol?: string;\r\n timeframe?: TimeFrame;\r\n chartOptions?: Partial<ChartOptions>;\r\n}\r\n\r\nexport interface ChartGridOptions {\r\n layout?: GridLayout;\r\n theme?: ChartOptions['theme'];\r\n syncCrosshair?: boolean;\r\n syncTimeAxis?: boolean;\r\n gap?: number;\r\n cells?: GridCellConfig[];\r\n chartOptions?: Partial<ChartOptions>;\r\n}\r\n\r\ninterface GridCell {\r\n container: HTMLDivElement;\r\n chart: Chart;\r\n symbol: string;\r\n timeframe: TimeFrame;\r\n}\r\n\r\nconst LAYOUT_MAP: Record<GridLayout, { cols: number; rows: number }> = {\r\n '1x1': { cols: 1, rows: 1 },\r\n '1x2': { cols: 2, rows: 1 },\r\n '2x1': { cols: 1, rows: 2 },\r\n '2x2': { cols: 2, rows: 2 },\r\n '1x3': { cols: 3, rows: 1 },\r\n '3x1': { cols: 1, rows: 3 },\r\n '2x3': { cols: 3, rows: 2 },\r\n '3x2': { cols: 2, rows: 3 },\r\n};\r\n\r\nexport class ChartGrid {\r\n private root: HTMLDivElement;\r\n private cells: GridCell[] = [];\r\n private layout: GridLayout;\r\n private options: ChartGridOptions;\r\n private destroyed = false;\r\n private syncing = false;\r\n\r\n constructor(container: HTMLElement, options: ChartGridOptions = {}) {\r\n this.options = options;\r\n this.layout = options.layout ?? '2x2';\r\n\r\n this.root = document.createElement('div');\r\n this.root.style.cssText = 'display:grid;width:100%;height:100%;overflow:hidden;';\r\n container.appendChild(this.root);\r\n\r\n this.applyLayout();\r\n this.createCells();\r\n }\r\n\r\n private applyLayout(): void {\r\n const { cols, rows } = LAYOUT_MAP[this.layout];\r\n const gap = this.options.gap ?? 1;\r\n this.root.style.gridTemplateColumns = `repeat(${cols}, 1fr)`;\r\n this.root.style.gridTemplateRows = `repeat(${rows}, 1fr)`;\r\n this.root.style.gap = `${gap}px`;\r\n }\r\n\r\n private createCells(): void {\r\n const { cols, rows } = LAYOUT_MAP[this.layout];\r\n const count = cols * rows;\r\n for (let i = 0; i < count; i++) this.cells.push(this.createCell(i));\r\n }\r\n\r\n private createCell(i: number): GridCell {\r\n const cellConfig = this.options.cells?.[i] ?? {};\r\n\r\n const cellEl = document.createElement('div');\r\n cellEl.style.cssText = 'position:relative;overflow:hidden;min-width:0;min-height:0;';\r\n this.root.appendChild(cellEl);\r\n\r\n const chartOpts: ChartOptions = {\r\n chartType: 'candlestick',\r\n autoScale: true,\r\n features: {\r\n crosshair: true,\r\n keyboard: true,\r\n volume: true,\r\n legend: true,\r\n priceAxis: true,\r\n timeAxis: true,\r\n grid: true,\r\n },\r\n ...this.options.chartOptions,\r\n ...cellConfig.chartOptions,\r\n theme: this.options.theme,\r\n };\r\n\r\n const chart = new Chart(cellEl, chartOpts);\r\n\r\n const cell: GridCell = {\r\n container: cellEl,\r\n chart,\r\n symbol: cellConfig.symbol ?? `Chart ${i + 1}`,\r\n timeframe: cellConfig.timeframe ?? '5m',\r\n };\r\n\r\n // Charts can differ in symbol and timeframe, so the crosshair is linked by\r\n // time: the others show a vertical line on the bar containing that time.\r\n if (this.options.syncCrosshair !== false) {\r\n chart.on('crosshairMove', (e) => {\r\n const time = e.payload.bar?.time;\r\n if (time === undefined) return;\r\n for (const other of this.cells) {\r\n if (other.chart !== chart) other.chart.setCrosshairTime(time);\r\n }\r\n });\r\n chart.on('crosshairLeave', () => {\r\n for (const other of this.cells) {\r\n if (other.chart !== chart) other.chart.setCrosshairTime(null);\r\n }\r\n });\r\n }\r\n\r\n if (this.options.syncTimeAxis !== false) {\r\n chart.on('visibleRangeChange', (e) => {\r\n if (this.syncing) return;\r\n this.syncing = true;\r\n const { from, to } = e.payload;\r\n const srcData = chart.getData();\r\n if (srcData.length > 0 && from >= 0 && to < srcData.length) {\r\n const fromTime = srcData[from]?.time;\r\n const toTime = srcData[to]?.time;\r\n if (fromTime && toTime) {\r\n for (const other of this.cells) {\r\n if (other.chart !== chart) {\r\n other.chart.setVisibleRange(fromTime, toTime);\r\n }\r\n }\r\n }\r\n }\r\n this.syncing = false;\r\n });\r\n }\r\n\r\n return cell;\r\n }\r\n\r\n setLayout(layout: GridLayout): void {\r\n if (layout === this.layout) return;\r\n const oldCount = this.cells.length;\r\n const { cols, rows } = LAYOUT_MAP[layout];\r\n const newCount = cols * rows;\r\n\r\n if (newCount < oldCount) {\r\n for (let i = oldCount - 1; i >= newCount; i--) {\r\n const cell = this.cells[i];\r\n cell.chart.destroy();\r\n cell.container.remove();\r\n this.cells.pop();\r\n }\r\n }\r\n\r\n this.layout = layout;\r\n this.applyLayout();\r\n\r\n // New cells get the same options and linking as the first ones.\r\n for (let i = oldCount; i < newCount; i++) this.cells.push(this.createCell(i));\r\n }\r\n\r\n getChart(index: number): Chart | null {\r\n return this.cells[index]?.chart ?? null;\r\n }\r\n\r\n getCharts(): Chart[] {\r\n return this.cells.map(c => c.chart);\r\n }\r\n\r\n getCellCount(): number {\r\n return this.cells.length;\r\n }\r\n\r\n setData(index: number, data: DataSeries): void {\r\n this.cells[index]?.chart.setData(data);\r\n }\r\n\r\n setAllData(data: DataSeries): void {\r\n for (const cell of this.cells) {\r\n cell.chart.setData(data);\r\n }\r\n }\r\n\r\n async connectCell(index: number, config: StreamConfig): Promise<void> {\r\n const cell = this.cells[index];\r\n if (!cell) return;\r\n cell.symbol = config.symbol;\r\n cell.timeframe = config.timeframe;\r\n await cell.chart.connect(config);\r\n }\r\n\r\n /**\r\n * Connect each chart to a symbol. An adapter keeps one stream, so pass a\r\n * function that makes one per chart (`() => new BinanceAdapter()`); a single\r\n * adapter object serves one chart only.\r\n */\r\n async connectAll(\r\n adapter: DataAdapter | ((symbol: string, index: number) => DataAdapter),\r\n symbols: string[],\r\n timeframe: TimeFrame,\r\n historyLimit = 500,\r\n ): Promise<void> {\r\n const promises: Promise<void>[] = [];\r\n for (let i = 0; i < this.cells.length && i < symbols.length; i++) {\r\n promises.push(this.connectCell(i, {\r\n adapter: typeof adapter === 'function' ? adapter(symbols[i], i) : adapter,\r\n symbol: symbols[i],\r\n timeframe,\r\n historyLimit,\r\n }));\r\n }\r\n await Promise.all(promises);\r\n }\r\n\r\n setTheme(theme: Theme): void {\r\n for (const cell of this.cells) {\r\n cell.chart.setTheme(theme);\r\n }\r\n }\r\n\r\n destroy(): void {\r\n if (this.destroyed) return;\r\n this.destroyed = true;\r\n for (const cell of this.cells) {\r\n cell.chart.destroy();\r\n cell.container.remove();\r\n }\r\n this.cells = [];\r\n this.root.remove();\r\n }\r\n}\r\n","import type { SparklineOptions, Theme } from '@tradecanvas/commons';\r\nimport { BaseFinanceChart, renderSparkline } from '@tradecanvas/core';\r\n\r\nexport class SparklineChart extends BaseFinanceChart {\r\n private options: SparklineOptions;\r\n\r\n constructor(container: HTMLElement, options: SparklineOptions) {\r\n super(container, options.theme);\r\n this.options = options;\r\n this.requestRender();\r\n }\r\n\r\n protected renderChart(\r\n ctx: CanvasRenderingContext2D,\r\n width: number,\r\n height: number,\r\n theme: Theme,\r\n ): void {\r\n renderSparkline(ctx, width, height, this.options, theme);\r\n }\r\n\r\n update(data: number[]): void {\r\n this.options = { ...this.options, data };\r\n this.requestRender();\r\n }\r\n\r\n setOptions(opts: Partial<SparklineOptions>): void {\r\n this.options = { ...this.options, ...opts };\r\n this.requestRender();\r\n }\r\n}\r\n","import type { DepthChartOptions, DepthData, Theme } from '@tradecanvas/commons';\r\nimport { BaseFinanceChart, FinanceCrosshair, renderDepthChart } from '@tradecanvas/core';\r\n\r\nexport class DepthChart extends BaseFinanceChart {\r\n private options: DepthChartOptions;\r\n private crosshair: FinanceCrosshair | null = null;\r\n\r\n constructor(container: HTMLElement, options: DepthChartOptions) {\r\n super(container, options.theme);\r\n this.options = options;\r\n\r\n if (options.crosshair !== false) {\r\n this.crosshair = new FinanceCrosshair(this.canvas, () => this.requestRender());\r\n }\r\n\r\n this.requestRender();\r\n }\r\n\r\n protected renderChart(\r\n ctx: CanvasRenderingContext2D,\r\n width: number,\r\n height: number,\r\n theme: Theme,\r\n ): void {\r\n const pos = this.crosshair?.getPosition() ?? null;\r\n renderDepthChart(ctx, width, height, this.options, theme, pos);\r\n }\r\n\r\n update(data: DepthData): void {\r\n this.options = { ...this.options, data };\r\n this.requestRender();\r\n }\r\n\r\n setOptions(opts: Partial<DepthChartOptions>): void {\r\n this.options = { ...this.options, ...opts };\r\n this.requestRender();\r\n }\r\n\r\n destroy(): void {\r\n this.crosshair?.destroy();\r\n super.destroy();\r\n }\r\n}\r\n","import type { EquityCurveOptions, EquityPoint, Theme } from '@tradecanvas/commons';\r\nimport { BaseFinanceChart, FinanceCrosshair, renderEquityCurve } from '@tradecanvas/core';\r\n\r\nexport class EquityCurveChart extends BaseFinanceChart {\r\n private options: EquityCurveOptions;\r\n private crosshair: FinanceCrosshair | null = null;\r\n\r\n constructor(container: HTMLElement, options: EquityCurveOptions) {\r\n super(container, options.theme);\r\n this.options = options;\r\n\r\n if (options.crosshair !== false) {\r\n this.crosshair = new FinanceCrosshair(this.canvas, () => this.requestRender());\r\n }\r\n\r\n this.requestRender();\r\n }\r\n\r\n protected renderChart(\r\n ctx: CanvasRenderingContext2D,\r\n width: number,\r\n height: number,\r\n theme: Theme,\r\n ): void {\r\n const pos = this.crosshair?.getPosition() ?? null;\r\n renderEquityCurve(ctx, width, height, this.options, theme, pos);\r\n }\r\n\r\n update(data: EquityPoint[], benchmark?: EquityPoint[]): void {\r\n this.options = { ...this.options, data };\r\n if (benchmark !== undefined) {\r\n this.options = { ...this.options, benchmark };\r\n }\r\n this.requestRender();\r\n }\r\n\r\n setOptions(opts: Partial<EquityCurveOptions>): void {\r\n this.options = { ...this.options, ...opts };\r\n this.requestRender();\r\n }\r\n\r\n destroy(): void {\r\n this.crosshair?.destroy();\r\n super.destroy();\r\n }\r\n}\r\n","import type { HeatmapCell, HeatmapOptions, Theme } from '@tradecanvas/commons';\r\nimport {\r\n BaseFinanceChart,\r\n FinanceCrosshair,\r\n layoutUniformGrid,\r\n layoutSquarifiedTreemap,\r\n renderHeatmap,\r\n} from '@tradecanvas/core';\r\nimport type { LayoutRect } from '@tradecanvas/core';\r\n\r\nexport class HeatmapChart extends BaseFinanceChart {\r\n private options: HeatmapOptions;\r\n private crosshair: FinanceCrosshair | null = null;\r\n private cachedRects: LayoutRect[] = [];\r\n private currentData: HeatmapCell[] = [];\r\n private lastLayoutWidth = 0;\r\n private lastLayoutHeight = 0;\r\n private handleClick: ((e: MouseEvent) => void) | null = null;\r\n\r\n constructor(container: HTMLElement, options: HeatmapOptions) {\r\n super(container, options.theme);\r\n this.options = options;\r\n this.currentData = options.data ?? [];\r\n\r\n if (options.crosshair !== false) {\r\n this.crosshair = new FinanceCrosshair(this.canvas, () => this.requestRender());\r\n }\r\n\r\n if (options.onCellClick) {\r\n this.handleClick = (e: MouseEvent) => {\r\n const rect = this.canvas.getBoundingClientRect();\r\n const x = e.clientX - rect.left;\r\n const y = e.clientY - rect.top;\r\n this.onCanvasClick(x, y);\r\n };\r\n this.canvas.addEventListener('click', this.handleClick);\r\n }\r\n\r\n this.recomputeLayout();\r\n this.requestRender();\r\n }\r\n\r\n private recomputeLayout(): void {\r\n const bounds = { x: 0, y: 0, width: this.width, height: this.height };\r\n const padding = this.options.cellPadding ?? 2;\r\n this.lastLayoutWidth = this.width;\r\n this.lastLayoutHeight = this.height;\r\n\r\n if (this.options.weighted) {\r\n const weighted = this.currentData.map(c => ({\r\n id: c.id,\r\n weight: c.weight ?? (Math.abs(c.value) || 1),\r\n }));\r\n this.cachedRects = layoutSquarifiedTreemap(weighted, bounds, padding);\r\n } else {\r\n this.cachedRects = layoutUniformGrid(\r\n this.currentData.map(c => ({ id: c.id })),\r\n bounds,\r\n padding,\r\n );\r\n }\r\n }\r\n\r\n private onCanvasClick(x: number, y: number): void {\r\n if (!this.options.onCellClick) return;\r\n\r\n for (const lr of this.cachedRects) {\r\n const r = lr.rect;\r\n if (x >= r.x && x <= r.x + r.width && y >= r.y && y <= r.y + r.height) {\r\n const cell = this.currentData.find(c => c.id === lr.id);\r\n if (cell) this.options.onCellClick(cell);\r\n return;\r\n }\r\n }\r\n }\r\n\r\n protected renderChart(\r\n ctx: CanvasRenderingContext2D,\r\n width: number,\r\n height: number,\r\n theme: Theme,\r\n ): void {\r\n if (width !== this.lastLayoutWidth || height !== this.lastLayoutHeight) {\r\n this.recomputeLayout();\r\n }\r\n\r\n const pos = this.crosshair?.getPosition() ?? null;\r\n renderHeatmap(ctx, width, height, this.currentData, this.cachedRects, this.options, theme, pos);\r\n }\r\n\r\n update(data: HeatmapCell[]): void {\r\n this.currentData = data;\r\n this.options = { ...this.options, data };\r\n this.recomputeLayout();\r\n this.requestRender();\r\n }\r\n\r\n setOptions(opts: Partial<HeatmapOptions>): void {\r\n this.options = { ...this.options, ...opts };\r\n if (opts.data) {\r\n this.currentData = opts.data;\r\n }\r\n this.recomputeLayout();\r\n this.requestRender();\r\n }\r\n\r\n destroy(): void {\r\n this.crosshair?.destroy();\r\n if (this.handleClick) {\r\n this.canvas.removeEventListener('click', this.handleClick);\r\n }\r\n super.destroy();\r\n }\r\n}\r\n","import type { Theme, WaterfallBar, WaterfallOptions } from '@tradecanvas/commons';\r\nimport { BaseFinanceChart, FinanceCrosshair, renderWaterfall } from '@tradecanvas/core';\r\n\r\nexport class WaterfallChart extends BaseFinanceChart {\r\n private options: WaterfallOptions;\r\n private crosshair: FinanceCrosshair | null = null;\r\n\r\n constructor(container: HTMLElement, options: WaterfallOptions) {\r\n super(container, options.theme);\r\n this.options = options;\r\n\r\n if (options.crosshair !== false) {\r\n this.crosshair = new FinanceCrosshair(this.canvas, () => this.requestRender());\r\n }\r\n\r\n this.requestRender();\r\n }\r\n\r\n protected renderChart(\r\n ctx: CanvasRenderingContext2D,\r\n width: number,\r\n height: number,\r\n theme: Theme,\r\n ): void {\r\n const pos = this.crosshair?.getPosition() ?? null;\r\n renderWaterfall(ctx, width, height, this.options, theme, pos);\r\n }\r\n\r\n update(data: WaterfallBar[]): void {\r\n this.options = { ...this.options, data };\r\n this.requestRender();\r\n }\r\n\r\n setOptions(opts: Partial<WaterfallOptions>): void {\r\n this.options = { ...this.options, ...opts };\r\n this.requestRender();\r\n }\r\n\r\n destroy(): void {\r\n this.crosshair?.destroy();\r\n super.destroy();\r\n }\r\n}\r\n","import type { GaugeOptions, Theme } from '@tradecanvas/commons';\r\nimport { BaseFinanceChart, renderGauge } from '@tradecanvas/core';\r\n\r\nconst DEFAULT_ANIMATION_MS = 500;\r\n\r\nfunction easeOutCubic(t: number): number {\r\n const inv = 1 - t;\r\n return 1 - inv * inv * inv;\r\n}\r\n\r\nexport class GaugeChart extends BaseFinanceChart {\r\n private options: GaugeOptions;\r\n private currentValue: number;\r\n private targetValue: number;\r\n private animationStart: number | null = null;\r\n private animationFrom = 0;\r\n private animationFrameId: number | null = null;\r\n\r\n constructor(container: HTMLElement, options: GaugeOptions) {\r\n super(container, options.theme);\r\n this.options = options;\r\n this.currentValue = options.value;\r\n this.targetValue = options.value;\r\n this.requestRender();\r\n }\r\n\r\n protected renderChart(\r\n ctx: CanvasRenderingContext2D,\r\n width: number,\r\n height: number,\r\n theme: Theme,\r\n ): void {\r\n renderGauge(ctx, width, height, this.options, theme, this.currentValue);\r\n }\r\n\r\n setValue(value: number): void {\r\n const animate = this.options.animate !== false;\r\n if (!animate) {\r\n this.cancelAnimation();\r\n this.currentValue = value;\r\n this.targetValue = value;\r\n this.options = { ...this.options, value };\r\n this.requestRender();\r\n return;\r\n }\r\n\r\n this.targetValue = value;\r\n this.animationFrom = this.currentValue;\r\n this.animationStart = performance.now();\r\n this.options = { ...this.options, value };\r\n this.startAnimationLoop();\r\n }\r\n\r\n setOptions(opts: Partial<GaugeOptions>): void {\r\n const next = { ...this.options, ...opts };\r\n // If `value` is part of the partial, route through animation path\r\n if (opts.value !== undefined && opts.value !== this.targetValue) {\r\n this.options = next;\r\n this.setValue(opts.value);\r\n return;\r\n }\r\n this.options = next;\r\n this.requestRender();\r\n }\r\n\r\n private startAnimationLoop(): void {\r\n if (this.animationFrameId !== null) return;\r\n const step = (): void => {\r\n this.animationFrameId = null;\r\n if (this.animationStart === null) return;\r\n\r\n const duration = this.options.animationDuration ?? DEFAULT_ANIMATION_MS;\r\n const elapsed = performance.now() - this.animationStart;\r\n const t = Math.min(1, elapsed / Math.max(1, duration));\r\n const eased = easeOutCubic(t);\r\n this.currentValue = this.animationFrom + (this.targetValue - this.animationFrom) * eased;\r\n\r\n this.requestRender();\r\n\r\n if (t < 1) {\r\n this.animationFrameId = requestAnimationFrame(step);\r\n } else {\r\n this.currentValue = this.targetValue;\r\n this.animationStart = null;\r\n }\r\n };\r\n this.animationFrameId = requestAnimationFrame(step);\r\n }\r\n\r\n private cancelAnimation(): void {\r\n if (this.animationFrameId !== null) {\r\n cancelAnimationFrame(this.animationFrameId);\r\n this.animationFrameId = null;\r\n }\r\n this.animationStart = null;\r\n }\r\n\r\n destroy(): void {\r\n this.cancelAnimation();\r\n super.destroy();\r\n }\r\n}\r\n","import type { EquityPoint, HeatmapCell } from '@tradecanvas/commons';\r\nimport { timeframeBucketStart } from '@tradecanvas/commons';\r\n\r\n/** Minimal equity sample shape — structurally satisfied by analytics' EquityPoint. */\r\nexport interface EquitySample {\r\n time: number;\r\n equity: number;\r\n}\r\n\r\n/** Subset of analytics RiskMetrics needed to render the stats strip. */\r\nexport interface RiskMetricsLike {\r\n totalReturnPct: number;\r\n cagr: number;\r\n sharpe: number;\r\n sortino: number;\r\n maxDrawdownPct: number;\r\n winRate: number;\r\n profitFactor: number;\r\n trades: number;\r\n}\r\n\r\nexport interface DashboardStat {\r\n label: string;\r\n value: string;\r\n tone: 'positive' | 'negative' | 'neutral';\r\n}\r\n\r\nconst MONTH_LABELS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\r\n\r\n/** Map an analytics equity curve to the finance EquityCurveChart point shape. */\r\nexport function toEquityPoints(curve: ReadonlyArray<EquitySample>): EquityPoint[] {\r\n return curve.map((p) => ({ time: p.time, value: p.equity }));\r\n}\r\n\r\n/**\r\n * Underwater drawdown curve as a percentage (<= 0). Each point is the equity's\r\n * shortfall from the running peak: `equity / peak - 1`, expressed in percent.\r\n */\r\nexport function computeDrawdownCurve(curve: ReadonlyArray<EquitySample>): EquityPoint[] {\r\n let peak = -Infinity;\r\n return curve.map((p) => {\r\n if (p.equity > peak) peak = p.equity;\r\n const dd = peak > 0 ? (p.equity / peak - 1) * 100 : 0;\r\n return { time: p.time, value: dd };\r\n });\r\n}\r\n\r\n/**\r\n * Calendar-month returns as heatmap cells. Each month's return is chained off\r\n * the prior month's closing equity (the first month chains off its own opening\r\n * equity), so the series reads as sequential monthly performance. `group` is\r\n * the year and `value` is the return in percent.\r\n */\r\nexport function computeMonthlyReturns(curve: ReadonlyArray<EquitySample>): HeatmapCell[] {\r\n if (curve.length === 0) return [];\r\n\r\n // Collapse the curve to one closing equity per calendar month, in order.\r\n const months: { key: number; close: number }[] = [];\r\n for (const p of curve) {\r\n const key = timeframeBucketStart(p.time, '1M');\r\n const last = months[months.length - 1];\r\n if (last && last.key === key) {\r\n last.close = p.equity;\r\n } else {\r\n months.push({ key, close: p.equity });\r\n }\r\n }\r\n\r\n let prevClose = curve[0].equity;\r\n const cells: HeatmapCell[] = [];\r\n for (const m of months) {\r\n const base = prevClose === 0 ? 1 : prevClose;\r\n const returnPct = (m.close / base - 1) * 100;\r\n prevClose = m.close;\r\n const d = new Date(m.key);\r\n const year = d.getUTCFullYear();\r\n const month = d.getUTCMonth();\r\n cells.push({\r\n id: `${year}-${String(month + 1).padStart(2, '0')}`,\r\n label: MONTH_LABELS[month],\r\n group: String(year),\r\n value: returnPct,\r\n });\r\n }\r\n return cells;\r\n}\r\n\r\nfunction pct(value: number): string {\r\n const sign = value > 0 ? '+' : '';\r\n return `${sign}${value.toFixed(2)}%`;\r\n}\r\n\r\nfunction tone(value: number): DashboardStat['tone'] {\r\n if (value > 0) return 'positive';\r\n if (value < 0) return 'negative';\r\n return 'neutral';\r\n}\r\n\r\n/** The headline stats rendered as cards above the charts. */\r\nexport function selectKeyStats(metrics: RiskMetricsLike): DashboardStat[] {\r\n return [\r\n { label: 'Total Return', value: pct(metrics.totalReturnPct), tone: tone(metrics.totalReturnPct) },\r\n { label: 'CAGR', value: pct(metrics.cagr * 100), tone: tone(metrics.cagr) },\r\n { label: 'Sharpe', value: metrics.sharpe.toFixed(2), tone: tone(metrics.sharpe) },\r\n { label: 'Sortino', value: metrics.sortino.toFixed(2), tone: tone(metrics.sortino) },\r\n { label: 'Max Drawdown', value: pct(metrics.maxDrawdownPct), tone: 'negative' },\r\n { label: 'Win Rate', value: `${(metrics.winRate * 100).toFixed(1)}%`, tone: 'neutral' },\r\n { label: 'Profit Factor', value: Number.isFinite(metrics.profitFactor) ? metrics.profitFactor.toFixed(2) : '∞', tone: tone(metrics.profitFactor - 1) },\r\n { label: 'Trades', value: String(metrics.trades), tone: 'neutral' },\r\n ];\r\n}\r\n","import type { Theme, ThemeName } from '@tradecanvas/commons';\r\nimport { DARK_THEME, LIGHT_THEME } from '@tradecanvas/commons';\r\nimport { EquityCurveChart } from './EquityCurveChart.js';\r\nimport { HeatmapChart } from './HeatmapChart.js';\r\nimport {\r\n toEquityPoints,\r\n computeDrawdownCurve,\r\n computeMonthlyReturns,\r\n selectKeyStats,\r\n type EquitySample,\r\n type RiskMetricsLike,\r\n type DashboardStat,\r\n} from './performanceData.js';\r\n\r\n/** Structurally satisfied by analytics' `BacktestResult`. */\r\nexport interface PerformanceResult {\r\n equityCurve: ReadonlyArray<EquitySample>;\r\n metrics: RiskMetricsLike;\r\n}\r\n\r\nexport interface PerformanceDashboardOptions {\r\n result: PerformanceResult;\r\n theme?: ThemeName | Theme;\r\n title?: string;\r\n subtitle?: string;\r\n}\r\n\r\nfunction resolveTheme(theme?: ThemeName | Theme): Theme {\r\n if (!theme || theme === 'dark') return DARK_THEME;\r\n if (theme === 'light') return LIGHT_THEME;\r\n return theme as Theme;\r\n}\r\n\r\n/**\r\n * A composed strategy-performance dashboard: a headline stats strip, an equity\r\n * curve, an underwater drawdown panel, and a monthly-returns heatmap. Built\r\n * entirely from a backtest `result`, reusing the finance chart renderers.\r\n *\r\n * ```ts\r\n * const result = new Backtester(opts).run(bars, strategy);\r\n * const dash = new PerformanceDashboard(el, { result, theme: 'dark' });\r\n * ```\r\n */\r\nexport class PerformanceDashboard {\r\n private options: PerformanceDashboardOptions;\r\n private theme: Theme;\r\n private root: HTMLDivElement;\r\n private equityChart: EquityCurveChart | null = null;\r\n private drawdownChart: EquityCurveChart | null = null;\r\n private heatmap: HeatmapChart | null = null;\r\n\r\n constructor(container: HTMLElement, options: PerformanceDashboardOptions) {\r\n this.options = options;\r\n this.theme = resolveTheme(options.theme);\r\n this.root = document.createElement('div');\r\n this.build();\r\n container.appendChild(this.root);\r\n }\r\n\r\n private build(): void {\r\n const t = this.theme;\r\n const { result, title, subtitle } = this.options;\r\n const surface = this.panelBackground();\r\n const border = t.grid;\r\n\r\n this.root.style.cssText = [\r\n 'display:flex',\r\n 'flex-direction:column',\r\n 'gap:14px',\r\n 'width:100%',\r\n 'box-sizing:border-box',\r\n 'padding:16px',\r\n `background:${t.background}`,\r\n `color:${t.text}`,\r\n `font-family:${t.font.family}`,\r\n ].join(';');\r\n\r\n if (title || subtitle) {\r\n const header = document.createElement('div');\r\n if (title) {\r\n const h = document.createElement('div');\r\n h.textContent = title;\r\n h.style.cssText = `font-size:${t.font.sizeLarge}px;font-weight:600;letter-spacing:-0.01em;`;\r\n header.appendChild(h);\r\n }\r\n if (subtitle) {\r\n const s = document.createElement('div');\r\n s.textContent = subtitle;\r\n s.style.cssText = `font-size:${t.font.sizeSmall}px;color:${t.textSecondary};margin-top:2px;`;\r\n header.appendChild(s);\r\n }\r\n this.root.appendChild(header);\r\n }\r\n\r\n // Stats strip\r\n this.root.appendChild(this.buildStatsStrip(selectKeyStats(result.metrics), surface, border));\r\n\r\n // Chart grid\r\n const grid = document.createElement('div');\r\n grid.style.cssText = [\r\n 'display:grid',\r\n 'grid-template-columns:repeat(auto-fit, minmax(280px, 1fr))',\r\n 'grid-auto-rows:220px',\r\n 'gap:14px',\r\n ].join(';');\r\n this.root.appendChild(grid);\r\n\r\n const equityPanel = this.buildPanel('Equity Curve', surface, border);\r\n equityPanel.wrap.style.gridColumn = '1 / -1';\r\n grid.appendChild(equityPanel.wrap);\r\n this.equityChart = new EquityCurveChart(equityPanel.body, {\r\n data: toEquityPoints(result.equityCurve),\r\n theme: t,\r\n lineColor: t.candleUp,\r\n fillArea: true,\r\n crosshair: true,\r\n });\r\n\r\n const ddPanel = this.buildPanel('Drawdown', surface, border);\r\n grid.appendChild(ddPanel.wrap);\r\n this.drawdownChart = new EquityCurveChart(ddPanel.body, {\r\n data: computeDrawdownCurve(result.equityCurve),\r\n theme: t,\r\n lineColor: t.candleDown,\r\n fillArea: true,\r\n crosshair: true,\r\n valueFormat: (v) => `${v.toFixed(1)}%`,\r\n });\r\n\r\n const monthlyCells = computeMonthlyReturns(result.equityCurve);\r\n const heatPanel = this.buildPanel('Monthly Returns', surface, border);\r\n grid.appendChild(heatPanel.wrap);\r\n this.heatmap = new HeatmapChart(heatPanel.body, {\r\n data: monthlyCells,\r\n theme: t,\r\n showValues: true,\r\n valueFormat: (v) => `${v >= 0 ? '+' : ''}${v.toFixed(1)}`,\r\n colorScale: { negative: t.candleDown, zero: surface, positive: t.candleUp },\r\n });\r\n }\r\n\r\n private buildStatsStrip(stats: DashboardStat[], surface: string, border: string): HTMLDivElement {\r\n const strip = document.createElement('div');\r\n strip.style.cssText = [\r\n 'display:grid',\r\n 'grid-template-columns:repeat(auto-fit, minmax(120px, 1fr))',\r\n 'gap:10px',\r\n ].join(';');\r\n\r\n const t = this.theme;\r\n for (const stat of stats) {\r\n const card = document.createElement('div');\r\n card.style.cssText = [\r\n `background:${surface}`,\r\n `border:1px solid ${border}`,\r\n 'border-radius:10px',\r\n 'padding:10px 12px',\r\n 'display:flex',\r\n 'flex-direction:column',\r\n 'gap:4px',\r\n ].join(';');\r\n\r\n const label = document.createElement('div');\r\n label.textContent = stat.label;\r\n label.style.cssText = `font-size:${t.font.sizeSmall}px;color:${t.textSecondary};text-transform:uppercase;letter-spacing:0.04em;`;\r\n\r\n const value = document.createElement('div');\r\n value.textContent = stat.value;\r\n const color = stat.tone === 'positive' ? t.candleUp : stat.tone === 'negative' ? t.candleDown : t.text;\r\n value.style.cssText = `font-size:${t.font.sizeLarge}px;font-weight:600;color:${color};font-variant-numeric:tabular-nums;`;\r\n\r\n card.appendChild(label);\r\n card.appendChild(value);\r\n strip.appendChild(card);\r\n }\r\n return strip;\r\n }\r\n\r\n private buildPanel(title: string, surface: string, border: string): { wrap: HTMLDivElement; body: HTMLDivElement } {\r\n const t = this.theme;\r\n const wrap = document.createElement('div');\r\n wrap.style.cssText = [\r\n `background:${surface}`,\r\n `border:1px solid ${border}`,\r\n 'border-radius:10px',\r\n 'overflow:hidden',\r\n 'display:flex',\r\n 'flex-direction:column',\r\n ].join(';');\r\n\r\n const head = document.createElement('div');\r\n head.textContent = title;\r\n head.style.cssText = [\r\n `font-size:${t.font.sizeSmall}px`,\r\n 'font-weight:600',\r\n `color:${t.textSecondary}`,\r\n 'padding:8px 12px',\r\n `border-bottom:1px solid ${border}`,\r\n 'text-transform:uppercase',\r\n 'letter-spacing:0.04em',\r\n ].join(';');\r\n\r\n const body = document.createElement('div');\r\n body.style.cssText = 'flex:1;min-height:0;position:relative;';\r\n\r\n wrap.appendChild(head);\r\n wrap.appendChild(body);\r\n return { wrap, body };\r\n }\r\n\r\n /** A subtle surface tint distinct from the page background, per theme. */\r\n private panelBackground(): string {\r\n return this.theme.name === 'light' ? 'rgba(0,0,0,0.02)' : 'rgba(255,255,255,0.03)';\r\n }\r\n\r\n /** Replace the displayed result and re-render all panels. */\r\n update(result: PerformanceResult): void {\r\n this.options = { ...this.options, result };\r\n this.destroyCharts();\r\n this.root.replaceChildren();\r\n this.build();\r\n }\r\n\r\n setTheme(theme: ThemeName | Theme): void {\r\n this.theme = resolveTheme(theme);\r\n this.options = { ...this.options, theme };\r\n this.destroyCharts();\r\n this.root.replaceChildren();\r\n this.build();\r\n }\r\n\r\n private destroyCharts(): void {\r\n this.equityChart?.destroy();\r\n this.drawdownChart?.destroy();\r\n this.heatmap?.destroy();\r\n this.equityChart = null;\r\n this.drawdownChart = null;\r\n this.heatmap = null;\r\n }\r\n\r\n destroy(): void {\r\n this.destroyCharts();\r\n this.root.remove();\r\n }\r\n}\r\n"],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "EMA 20", "BB 20 2", "MACD 12 26 9": the short name (`shortName`, else the
|
|
3
|
+
* id in capitals) plus up to three numeric parameters, in the indicator's own
|
|
4
|
+
* order, so two instances of the same indicator can be told apart.
|
|
5
|
+
*/
|
|
6
|
+
export declare function indicatorChipLabel(id: string, params: Record<string, unknown>, defaults?: Record<string, unknown>, shortName?: string): string;
|
|
7
|
+
//# sourceMappingURL=indicatorLabel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"indicatorLabel.d.ts","sourceRoot":"","sources":["../src/indicatorLabel.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClC,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CAWR"}
|