@tradecanvas/chart 1.4.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/LICENSE +21 -21
- package/README.md +910 -858
- package/dist/Chart.d.ts +606 -23
- 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/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 +5 -4
- package/dist/charts/ChartTypeStrategy.d.ts.map +1 -1
- package/dist/grid/ChartGrid.d.ts +6 -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 +22 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +31 -31
- 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 +219 -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 +3 -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 +14 -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 +5 -4
- package/dist/widget/WidgetGoToDate.d.ts.map +1 -1
- package/dist/widget/WidgetHistoryPill.d.ts +23 -0
- package/dist/widget/WidgetHistoryPill.d.ts.map +1 -0
- package/dist/widget/WidgetHotkeySheet.d.ts.map +1 -1
- package/dist/widget/WidgetIndicatorLegend.d.ts +31 -1
- package/dist/widget/WidgetIndicatorLegend.d.ts.map +1 -1
- 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/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 +15 -0
- package/dist/widget/WidgetReplayBar.d.ts.map +1 -1
- package/dist/widget/WidgetSettings.d.ts +13 -1
- package/dist/widget/WidgetSettings.d.ts.map +1 -1
- package/dist/widget/WidgetStatusBar.d.ts +3 -0
- 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 +26 -5
- package/dist/widget/WidgetSymbolSearch.d.ts.map +1 -1
- package/dist/widget/WidgetToolbar.d.ts +30 -1
- package/dist/widget/WidgetToolbar.d.ts.map +1 -1
- 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/focusTrap.d.ts +8 -0
- package/dist/widget/focusTrap.d.ts.map +1 -0
- package/dist/widget/i18n.d.ts +20 -89
- package/dist/widget/i18n.d.ts.map +1 -1
- package/dist/widget/iconSet.d.ts.map +1 -1
- package/dist/widget/index.cjs +4294 -3028
- package/dist/widget/index.cjs.map +1 -1
- package/dist/widget/index.d.ts +15 -1
- package/dist/widget/index.d.ts.map +1 -1
- package/dist/widget/index.js +6326 -1185
- 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 +11 -6
- package/dist/widget/legendValues.d.ts.map +1 -1
- 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 +182 -6
- package/dist/widget/types.d.ts.map +1 -1
- 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 +8 -0
- package/dist/widget/widgetTimeframes.d.ts.map +1 -1
- 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-C5kgfbET.cjs +0 -2
- package/dist/DragDropImporter-C5kgfbET.cjs.map +0 -1
- package/dist/DragDropImporter-Dd9Mud5J.js +0 -2099
- package/dist/DragDropImporter-Dd9Mud5J.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.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';\nimport { Chart } from '../Chart.js';\n\nexport type GridLayout = '1x1' | '1x2' | '2x1' | '2x2' | '1x3' | '3x1' | '2x3' | '3x2';\n\nexport interface GridCellConfig {\n symbol?: string;\n timeframe?: TimeFrame;\n chartOptions?: Partial<ChartOptions>;\n}\n\nexport interface ChartGridOptions {\n layout?: GridLayout;\n theme?: ChartOptions['theme'];\n syncCrosshair?: boolean;\n syncTimeAxis?: boolean;\n gap?: number;\n cells?: GridCellConfig[];\n chartOptions?: Partial<ChartOptions>;\n}\n\ninterface GridCell {\n container: HTMLDivElement;\n chart: Chart;\n symbol: string;\n timeframe: TimeFrame;\n}\n\nconst LAYOUT_MAP: Record<GridLayout, { cols: number; rows: number }> = {\n '1x1': { cols: 1, rows: 1 },\n '1x2': { cols: 2, rows: 1 },\n '2x1': { cols: 1, rows: 2 },\n '2x2': { cols: 2, rows: 2 },\n '1x3': { cols: 3, rows: 1 },\n '3x1': { cols: 1, rows: 3 },\n '2x3': { cols: 3, rows: 2 },\n '3x2': { cols: 2, rows: 3 },\n};\n\nexport class ChartGrid {\n private root: HTMLDivElement;\n private cells: GridCell[] = [];\n private layout: GridLayout;\n private options: ChartGridOptions;\n private destroyed = false;\n private syncing = false;\n\n constructor(container: HTMLElement, options: ChartGridOptions = {}) {\n this.options = options;\n this.layout = options.layout ?? '2x2';\n\n this.root = document.createElement('div');\n this.root.style.cssText = 'display:grid;width:100%;height:100%;overflow:hidden;';\n container.appendChild(this.root);\n\n this.applyLayout();\n this.createCells();\n }\n\n private applyLayout(): void {\n const { cols, rows } = LAYOUT_MAP[this.layout];\n const gap = this.options.gap ?? 1;\n this.root.style.gridTemplateColumns = `repeat(${cols}, 1fr)`;\n this.root.style.gridTemplateRows = `repeat(${rows}, 1fr)`;\n this.root.style.gap = `${gap}px`;\n }\n\n private createCells(): void {\n const { cols, rows } = LAYOUT_MAP[this.layout];\n const count = cols * rows;\n for (let i = 0; i < count; i++) this.cells.push(this.createCell(i));\n }\n\n private createCell(i: number): GridCell {\n const cellConfig = this.options.cells?.[i] ?? {};\n\n const cellEl = document.createElement('div');\n cellEl.style.cssText = 'position:relative;overflow:hidden;min-width:0;min-height:0;';\n this.root.appendChild(cellEl);\n\n const chartOpts: ChartOptions = {\n chartType: 'candlestick',\n autoScale: true,\n features: {\n crosshair: true,\n keyboard: true,\n volume: true,\n legend: true,\n priceAxis: true,\n timeAxis: true,\n grid: true,\n },\n ...this.options.chartOptions,\n ...cellConfig.chartOptions,\n theme: this.options.theme,\n };\n\n const chart = new Chart(cellEl, chartOpts);\n\n const cell: GridCell = {\n container: cellEl,\n chart,\n symbol: cellConfig.symbol ?? `Chart ${i + 1}`,\n timeframe: cellConfig.timeframe ?? '5m',\n };\n\n // Charts can differ in symbol and timeframe, so the crosshair is linked by\n // time: the others show a vertical line on the bar containing that time.\n if (this.options.syncCrosshair !== false) {\n chart.on('crosshairMove', (e) => {\n const time = e.payload.bar?.time;\n if (time === undefined) return;\n for (const other of this.cells) {\n if (other.chart !== chart) other.chart.setCrosshairTime(time);\n }\n });\n chart.on('crosshairLeave', () => {\n for (const other of this.cells) {\n if (other.chart !== chart) other.chart.setCrosshairTime(null);\n }\n });\n }\n\n if (this.options.syncTimeAxis !== false) {\n chart.on('visibleRangeChange', (e) => {\n if (this.syncing) return;\n this.syncing = true;\n const { from, to } = e.payload;\n const srcData = chart.getData();\n if (srcData.length > 0 && from >= 0 && to < srcData.length) {\n const fromTime = srcData[from]?.time;\n const toTime = srcData[to]?.time;\n if (fromTime && toTime) {\n for (const other of this.cells) {\n if (other.chart !== chart) {\n other.chart.setVisibleRange(fromTime, toTime);\n }\n }\n }\n }\n this.syncing = false;\n });\n }\n\n return cell;\n }\n\n setLayout(layout: GridLayout): void {\n if (layout === this.layout) return;\n const oldCount = this.cells.length;\n const { cols, rows } = LAYOUT_MAP[layout];\n const newCount = cols * rows;\n\n if (newCount < oldCount) {\n for (let i = oldCount - 1; i >= newCount; i--) {\n const cell = this.cells[i];\n cell.chart.destroy();\n cell.container.remove();\n this.cells.pop();\n }\n }\n\n this.layout = layout;\n this.applyLayout();\n\n // New cells get the same options and linking as the first ones.\n for (let i = oldCount; i < newCount; i++) this.cells.push(this.createCell(i));\n }\n\n getChart(index: number): Chart | null {\n return this.cells[index]?.chart ?? null;\n }\n\n getCharts(): Chart[] {\n return this.cells.map(c => c.chart);\n }\n\n getCellCount(): number {\n return this.cells.length;\n }\n\n setData(index: number, data: DataSeries): void {\n this.cells[index]?.chart.setData(data);\n }\n\n setAllData(data: DataSeries): void {\n for (const cell of this.cells) {\n cell.chart.setData(data);\n }\n }\n\n async connectCell(index: number, config: StreamConfig): Promise<void> {\n const cell = this.cells[index];\n if (!cell) return;\n cell.symbol = config.symbol;\n cell.timeframe = config.timeframe;\n await cell.chart.connect(config);\n }\n\n async connectAll(adapter: DataAdapter, symbols: string[], timeframe: TimeFrame, historyLimit = 500): Promise<void> {\n const promises: Promise<void>[] = [];\n for (let i = 0; i < this.cells.length && i < symbols.length; i++) {\n promises.push(this.connectCell(i, {\n adapter,\n symbol: symbols[i],\n timeframe,\n historyLimit,\n }));\n }\n await Promise.all(promises);\n }\n\n setTheme(theme: Theme): void {\n for (const cell of this.cells) {\n cell.chart.setTheme(theme);\n }\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n for (const cell of this.cells) {\n cell.chart.destroy();\n cell.container.remove();\n }\n this.cells = [];\n this.root.remove();\n }\n}\n","import type { SparklineOptions, Theme } from '@tradecanvas/commons';\nimport { BaseFinanceChart, renderSparkline } from '@tradecanvas/core';\n\nexport class SparklineChart extends BaseFinanceChart {\n private options: SparklineOptions;\n\n constructor(container: HTMLElement, options: SparklineOptions) {\n super(container, options.theme);\n this.options = options;\n this.requestRender();\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n renderSparkline(ctx, width, height, this.options, theme);\n }\n\n update(data: number[]): void {\n this.options = { ...this.options, data };\n this.requestRender();\n }\n\n setOptions(opts: Partial<SparklineOptions>): void {\n this.options = { ...this.options, ...opts };\n this.requestRender();\n }\n}\n","import type { DepthChartOptions, DepthData, Theme } from '@tradecanvas/commons';\nimport { BaseFinanceChart, FinanceCrosshair, renderDepthChart } from '@tradecanvas/core';\n\nexport class DepthChart extends BaseFinanceChart {\n private options: DepthChartOptions;\n private crosshair: FinanceCrosshair | null = null;\n\n constructor(container: HTMLElement, options: DepthChartOptions) {\n super(container, options.theme);\n this.options = options;\n\n if (options.crosshair !== false) {\n this.crosshair = new FinanceCrosshair(this.canvas, () => this.requestRender());\n }\n\n this.requestRender();\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n const pos = this.crosshair?.getPosition() ?? null;\n renderDepthChart(ctx, width, height, this.options, theme, pos);\n }\n\n update(data: DepthData): void {\n this.options = { ...this.options, data };\n this.requestRender();\n }\n\n setOptions(opts: Partial<DepthChartOptions>): void {\n this.options = { ...this.options, ...opts };\n this.requestRender();\n }\n\n destroy(): void {\n this.crosshair?.destroy();\n super.destroy();\n }\n}\n","import type { EquityCurveOptions, EquityPoint, Theme } from '@tradecanvas/commons';\nimport { BaseFinanceChart, FinanceCrosshair, renderEquityCurve } from '@tradecanvas/core';\n\nexport class EquityCurveChart extends BaseFinanceChart {\n private options: EquityCurveOptions;\n private crosshair: FinanceCrosshair | null = null;\n\n constructor(container: HTMLElement, options: EquityCurveOptions) {\n super(container, options.theme);\n this.options = options;\n\n if (options.crosshair !== false) {\n this.crosshair = new FinanceCrosshair(this.canvas, () => this.requestRender());\n }\n\n this.requestRender();\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n const pos = this.crosshair?.getPosition() ?? null;\n renderEquityCurve(ctx, width, height, this.options, theme, pos);\n }\n\n update(data: EquityPoint[], benchmark?: EquityPoint[]): void {\n this.options = { ...this.options, data };\n if (benchmark !== undefined) {\n this.options = { ...this.options, benchmark };\n }\n this.requestRender();\n }\n\n setOptions(opts: Partial<EquityCurveOptions>): void {\n this.options = { ...this.options, ...opts };\n this.requestRender();\n }\n\n destroy(): void {\n this.crosshair?.destroy();\n super.destroy();\n }\n}\n","import type { HeatmapCell, HeatmapOptions, Theme } from '@tradecanvas/commons';\nimport {\n BaseFinanceChart,\n FinanceCrosshair,\n layoutUniformGrid,\n layoutSquarifiedTreemap,\n renderHeatmap,\n} from '@tradecanvas/core';\nimport type { LayoutRect } from '@tradecanvas/core';\n\nexport class HeatmapChart extends BaseFinanceChart {\n private options: HeatmapOptions;\n private crosshair: FinanceCrosshair | null = null;\n private cachedRects: LayoutRect[] = [];\n private currentData: HeatmapCell[] = [];\n private lastLayoutWidth = 0;\n private lastLayoutHeight = 0;\n private handleClick: ((e: MouseEvent) => void) | null = null;\n\n constructor(container: HTMLElement, options: HeatmapOptions) {\n super(container, options.theme);\n this.options = options;\n this.currentData = options.data ?? [];\n\n if (options.crosshair !== false) {\n this.crosshair = new FinanceCrosshair(this.canvas, () => this.requestRender());\n }\n\n if (options.onCellClick) {\n this.handleClick = (e: MouseEvent) => {\n const rect = this.canvas.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n this.onCanvasClick(x, y);\n };\n this.canvas.addEventListener('click', this.handleClick);\n }\n\n this.recomputeLayout();\n this.requestRender();\n }\n\n private recomputeLayout(): void {\n const bounds = { x: 0, y: 0, width: this.width, height: this.height };\n const padding = this.options.cellPadding ?? 2;\n this.lastLayoutWidth = this.width;\n this.lastLayoutHeight = this.height;\n\n if (this.options.weighted) {\n const weighted = this.currentData.map(c => ({\n id: c.id,\n weight: c.weight ?? (Math.abs(c.value) || 1),\n }));\n this.cachedRects = layoutSquarifiedTreemap(weighted, bounds, padding);\n } else {\n this.cachedRects = layoutUniformGrid(\n this.currentData.map(c => ({ id: c.id })),\n bounds,\n padding,\n );\n }\n }\n\n private onCanvasClick(x: number, y: number): void {\n if (!this.options.onCellClick) return;\n\n for (const lr of this.cachedRects) {\n const r = lr.rect;\n if (x >= r.x && x <= r.x + r.width && y >= r.y && y <= r.y + r.height) {\n const cell = this.currentData.find(c => c.id === lr.id);\n if (cell) this.options.onCellClick(cell);\n return;\n }\n }\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n if (width !== this.lastLayoutWidth || height !== this.lastLayoutHeight) {\n this.recomputeLayout();\n }\n\n const pos = this.crosshair?.getPosition() ?? null;\n renderHeatmap(ctx, width, height, this.currentData, this.cachedRects, this.options, theme, pos);\n }\n\n update(data: HeatmapCell[]): void {\n this.currentData = data;\n this.options = { ...this.options, data };\n this.recomputeLayout();\n this.requestRender();\n }\n\n setOptions(opts: Partial<HeatmapOptions>): void {\n this.options = { ...this.options, ...opts };\n if (opts.data) {\n this.currentData = opts.data;\n }\n this.recomputeLayout();\n this.requestRender();\n }\n\n destroy(): void {\n this.crosshair?.destroy();\n if (this.handleClick) {\n this.canvas.removeEventListener('click', this.handleClick);\n }\n super.destroy();\n }\n}\n","import type { Theme, WaterfallBar, WaterfallOptions } from '@tradecanvas/commons';\nimport { BaseFinanceChart, FinanceCrosshair, renderWaterfall } from '@tradecanvas/core';\n\nexport class WaterfallChart extends BaseFinanceChart {\n private options: WaterfallOptions;\n private crosshair: FinanceCrosshair | null = null;\n\n constructor(container: HTMLElement, options: WaterfallOptions) {\n super(container, options.theme);\n this.options = options;\n\n if (options.crosshair !== false) {\n this.crosshair = new FinanceCrosshair(this.canvas, () => this.requestRender());\n }\n\n this.requestRender();\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n const pos = this.crosshair?.getPosition() ?? null;\n renderWaterfall(ctx, width, height, this.options, theme, pos);\n }\n\n update(data: WaterfallBar[]): void {\n this.options = { ...this.options, data };\n this.requestRender();\n }\n\n setOptions(opts: Partial<WaterfallOptions>): void {\n this.options = { ...this.options, ...opts };\n this.requestRender();\n }\n\n destroy(): void {\n this.crosshair?.destroy();\n super.destroy();\n }\n}\n","import type { GaugeOptions, Theme } from '@tradecanvas/commons';\nimport { BaseFinanceChart, renderGauge } from '@tradecanvas/core';\n\nconst DEFAULT_ANIMATION_MS = 500;\n\nfunction easeOutCubic(t: number): number {\n const inv = 1 - t;\n return 1 - inv * inv * inv;\n}\n\nexport class GaugeChart extends BaseFinanceChart {\n private options: GaugeOptions;\n private currentValue: number;\n private targetValue: number;\n private animationStart: number | null = null;\n private animationFrom = 0;\n private animationFrameId: number | null = null;\n\n constructor(container: HTMLElement, options: GaugeOptions) {\n super(container, options.theme);\n this.options = options;\n this.currentValue = options.value;\n this.targetValue = options.value;\n this.requestRender();\n }\n\n protected renderChart(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n theme: Theme,\n ): void {\n renderGauge(ctx, width, height, this.options, theme, this.currentValue);\n }\n\n setValue(value: number): void {\n const animate = this.options.animate !== false;\n if (!animate) {\n this.cancelAnimation();\n this.currentValue = value;\n this.targetValue = value;\n this.options = { ...this.options, value };\n this.requestRender();\n return;\n }\n\n this.targetValue = value;\n this.animationFrom = this.currentValue;\n this.animationStart = performance.now();\n this.options = { ...this.options, value };\n this.startAnimationLoop();\n }\n\n setOptions(opts: Partial<GaugeOptions>): void {\n const next = { ...this.options, ...opts };\n // If `value` is part of the partial, route through animation path\n if (opts.value !== undefined && opts.value !== this.targetValue) {\n this.options = next;\n this.setValue(opts.value);\n return;\n }\n this.options = next;\n this.requestRender();\n }\n\n private startAnimationLoop(): void {\n if (this.animationFrameId !== null) return;\n const step = (): void => {\n this.animationFrameId = null;\n if (this.animationStart === null) return;\n\n const duration = this.options.animationDuration ?? DEFAULT_ANIMATION_MS;\n const elapsed = performance.now() - this.animationStart;\n const t = Math.min(1, elapsed / Math.max(1, duration));\n const eased = easeOutCubic(t);\n this.currentValue = this.animationFrom + (this.targetValue - this.animationFrom) * eased;\n\n this.requestRender();\n\n if (t < 1) {\n this.animationFrameId = requestAnimationFrame(step);\n } else {\n this.currentValue = this.targetValue;\n this.animationStart = null;\n }\n };\n this.animationFrameId = requestAnimationFrame(step);\n }\n\n private cancelAnimation(): void {\n if (this.animationFrameId !== null) {\n cancelAnimationFrame(this.animationFrameId);\n this.animationFrameId = null;\n }\n this.animationStart = null;\n }\n\n destroy(): void {\n this.cancelAnimation();\n super.destroy();\n }\n}\n","import type { EquityPoint, HeatmapCell } from '@tradecanvas/commons';\nimport { timeframeBucketStart } from '@tradecanvas/commons';\n\n/** Minimal equity sample shape — structurally satisfied by analytics' EquityPoint. */\nexport interface EquitySample {\n time: number;\n equity: number;\n}\n\n/** Subset of analytics RiskMetrics needed to render the stats strip. */\nexport interface RiskMetricsLike {\n totalReturnPct: number;\n cagr: number;\n sharpe: number;\n sortino: number;\n maxDrawdownPct: number;\n winRate: number;\n profitFactor: number;\n trades: number;\n}\n\nexport interface DashboardStat {\n label: string;\n value: string;\n tone: 'positive' | 'negative' | 'neutral';\n}\n\nconst MONTH_LABELS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\n\n/** Map an analytics equity curve to the finance EquityCurveChart point shape. */\nexport function toEquityPoints(curve: ReadonlyArray<EquitySample>): EquityPoint[] {\n return curve.map((p) => ({ time: p.time, value: p.equity }));\n}\n\n/**\n * Underwater drawdown curve as a percentage (<= 0). Each point is the equity's\n * shortfall from the running peak: `equity / peak - 1`, expressed in percent.\n */\nexport function computeDrawdownCurve(curve: ReadonlyArray<EquitySample>): EquityPoint[] {\n let peak = -Infinity;\n return curve.map((p) => {\n if (p.equity > peak) peak = p.equity;\n const dd = peak > 0 ? (p.equity / peak - 1) * 100 : 0;\n return { time: p.time, value: dd };\n });\n}\n\n/**\n * Calendar-month returns as heatmap cells. Each month's return is chained off\n * the prior month's closing equity (the first month chains off its own opening\n * equity), so the series reads as sequential monthly performance. `group` is\n * the year and `value` is the return in percent.\n */\nexport function computeMonthlyReturns(curve: ReadonlyArray<EquitySample>): HeatmapCell[] {\n if (curve.length === 0) return [];\n\n // Collapse the curve to one closing equity per calendar month, in order.\n const months: { key: number; close: number }[] = [];\n for (const p of curve) {\n const key = timeframeBucketStart(p.time, '1M');\n const last = months[months.length - 1];\n if (last && last.key === key) {\n last.close = p.equity;\n } else {\n months.push({ key, close: p.equity });\n }\n }\n\n let prevClose = curve[0].equity;\n const cells: HeatmapCell[] = [];\n for (const m of months) {\n const base = prevClose === 0 ? 1 : prevClose;\n const returnPct = (m.close / base - 1) * 100;\n prevClose = m.close;\n const d = new Date(m.key);\n const year = d.getUTCFullYear();\n const month = d.getUTCMonth();\n cells.push({\n id: `${year}-${String(month + 1).padStart(2, '0')}`,\n label: MONTH_LABELS[month],\n group: String(year),\n value: returnPct,\n });\n }\n return cells;\n}\n\nfunction pct(value: number): string {\n const sign = value > 0 ? '+' : '';\n return `${sign}${value.toFixed(2)}%`;\n}\n\nfunction tone(value: number): DashboardStat['tone'] {\n if (value > 0) return 'positive';\n if (value < 0) return 'negative';\n return 'neutral';\n}\n\n/** The headline stats rendered as cards above the charts. */\nexport function selectKeyStats(metrics: RiskMetricsLike): DashboardStat[] {\n return [\n { label: 'Total Return', value: pct(metrics.totalReturnPct), tone: tone(metrics.totalReturnPct) },\n { label: 'CAGR', value: pct(metrics.cagr * 100), tone: tone(metrics.cagr) },\n { label: 'Sharpe', value: metrics.sharpe.toFixed(2), tone: tone(metrics.sharpe) },\n { label: 'Sortino', value: metrics.sortino.toFixed(2), tone: tone(metrics.sortino) },\n { label: 'Max Drawdown', value: pct(metrics.maxDrawdownPct), tone: 'negative' },\n { label: 'Win Rate', value: `${(metrics.winRate * 100).toFixed(1)}%`, tone: 'neutral' },\n { label: 'Profit Factor', value: Number.isFinite(metrics.profitFactor) ? metrics.profitFactor.toFixed(2) : '∞', tone: tone(metrics.profitFactor - 1) },\n { label: 'Trades', value: String(metrics.trades), tone: 'neutral' },\n ];\n}\n","import type { Theme, ThemeName } from '@tradecanvas/commons';\nimport { DARK_THEME, LIGHT_THEME } from '@tradecanvas/commons';\nimport { EquityCurveChart } from './EquityCurveChart.js';\nimport { HeatmapChart } from './HeatmapChart.js';\nimport {\n toEquityPoints,\n computeDrawdownCurve,\n computeMonthlyReturns,\n selectKeyStats,\n type EquitySample,\n type RiskMetricsLike,\n type DashboardStat,\n} from './performanceData.js';\n\n/** Structurally satisfied by analytics' `BacktestResult`. */\nexport interface PerformanceResult {\n equityCurve: ReadonlyArray<EquitySample>;\n metrics: RiskMetricsLike;\n}\n\nexport interface PerformanceDashboardOptions {\n result: PerformanceResult;\n theme?: ThemeName | Theme;\n title?: string;\n subtitle?: string;\n}\n\nfunction resolveTheme(theme?: ThemeName | Theme): Theme {\n if (!theme || theme === 'dark') return DARK_THEME;\n if (theme === 'light') return LIGHT_THEME;\n return theme as Theme;\n}\n\n/**\n * A composed strategy-performance dashboard: a headline stats strip, an equity\n * curve, an underwater drawdown panel, and a monthly-returns heatmap. Built\n * entirely from a backtest `result`, reusing the finance chart renderers.\n *\n * ```ts\n * const result = new Backtester(opts).run(bars, strategy);\n * const dash = new PerformanceDashboard(el, { result, theme: 'dark' });\n * ```\n */\nexport class PerformanceDashboard {\n private options: PerformanceDashboardOptions;\n private theme: Theme;\n private root: HTMLDivElement;\n private equityChart: EquityCurveChart | null = null;\n private drawdownChart: EquityCurveChart | null = null;\n private heatmap: HeatmapChart | null = null;\n\n constructor(container: HTMLElement, options: PerformanceDashboardOptions) {\n this.options = options;\n this.theme = resolveTheme(options.theme);\n this.root = document.createElement('div');\n this.build();\n container.appendChild(this.root);\n }\n\n private build(): void {\n const t = this.theme;\n const { result, title, subtitle } = this.options;\n const surface = this.panelBackground();\n const border = t.grid;\n\n this.root.style.cssText = [\n 'display:flex',\n 'flex-direction:column',\n 'gap:14px',\n 'width:100%',\n 'box-sizing:border-box',\n 'padding:16px',\n `background:${t.background}`,\n `color:${t.text}`,\n `font-family:${t.font.family}`,\n ].join(';');\n\n if (title || subtitle) {\n const header = document.createElement('div');\n if (title) {\n const h = document.createElement('div');\n h.textContent = title;\n h.style.cssText = `font-size:${t.font.sizeLarge}px;font-weight:600;letter-spacing:-0.01em;`;\n header.appendChild(h);\n }\n if (subtitle) {\n const s = document.createElement('div');\n s.textContent = subtitle;\n s.style.cssText = `font-size:${t.font.sizeSmall}px;color:${t.textSecondary};margin-top:2px;`;\n header.appendChild(s);\n }\n this.root.appendChild(header);\n }\n\n // Stats strip\n this.root.appendChild(this.buildStatsStrip(selectKeyStats(result.metrics), surface, border));\n\n // Chart grid\n const grid = document.createElement('div');\n grid.style.cssText = [\n 'display:grid',\n 'grid-template-columns:repeat(auto-fit, minmax(280px, 1fr))',\n 'grid-auto-rows:220px',\n 'gap:14px',\n ].join(';');\n this.root.appendChild(grid);\n\n const equityPanel = this.buildPanel('Equity Curve', surface, border);\n equityPanel.wrap.style.gridColumn = '1 / -1';\n grid.appendChild(equityPanel.wrap);\n this.equityChart = new EquityCurveChart(equityPanel.body, {\n data: toEquityPoints(result.equityCurve),\n theme: t,\n lineColor: t.candleUp,\n fillArea: true,\n crosshair: true,\n });\n\n const ddPanel = this.buildPanel('Drawdown', surface, border);\n grid.appendChild(ddPanel.wrap);\n this.drawdownChart = new EquityCurveChart(ddPanel.body, {\n data: computeDrawdownCurve(result.equityCurve),\n theme: t,\n lineColor: t.candleDown,\n fillArea: true,\n crosshair: true,\n valueFormat: (v) => `${v.toFixed(1)}%`,\n });\n\n const monthlyCells = computeMonthlyReturns(result.equityCurve);\n const heatPanel = this.buildPanel('Monthly Returns', surface, border);\n grid.appendChild(heatPanel.wrap);\n this.heatmap = new HeatmapChart(heatPanel.body, {\n data: monthlyCells,\n theme: t,\n showValues: true,\n valueFormat: (v) => `${v >= 0 ? '+' : ''}${v.toFixed(1)}`,\n colorScale: { negative: t.candleDown, zero: surface, positive: t.candleUp },\n });\n }\n\n private buildStatsStrip(stats: DashboardStat[], surface: string, border: string): HTMLDivElement {\n const strip = document.createElement('div');\n strip.style.cssText = [\n 'display:grid',\n 'grid-template-columns:repeat(auto-fit, minmax(120px, 1fr))',\n 'gap:10px',\n ].join(';');\n\n const t = this.theme;\n for (const stat of stats) {\n const card = document.createElement('div');\n card.style.cssText = [\n `background:${surface}`,\n `border:1px solid ${border}`,\n 'border-radius:10px',\n 'padding:10px 12px',\n 'display:flex',\n 'flex-direction:column',\n 'gap:4px',\n ].join(';');\n\n const label = document.createElement('div');\n label.textContent = stat.label;\n label.style.cssText = `font-size:${t.font.sizeSmall}px;color:${t.textSecondary};text-transform:uppercase;letter-spacing:0.04em;`;\n\n const value = document.createElement('div');\n value.textContent = stat.value;\n const color = stat.tone === 'positive' ? t.candleUp : stat.tone === 'negative' ? t.candleDown : t.text;\n value.style.cssText = `font-size:${t.font.sizeLarge}px;font-weight:600;color:${color};font-variant-numeric:tabular-nums;`;\n\n card.appendChild(label);\n card.appendChild(value);\n strip.appendChild(card);\n }\n return strip;\n }\n\n private buildPanel(title: string, surface: string, border: string): { wrap: HTMLDivElement; body: HTMLDivElement } {\n const t = this.theme;\n const wrap = document.createElement('div');\n wrap.style.cssText = [\n `background:${surface}`,\n `border:1px solid ${border}`,\n 'border-radius:10px',\n 'overflow:hidden',\n 'display:flex',\n 'flex-direction:column',\n ].join(';');\n\n const head = document.createElement('div');\n head.textContent = title;\n head.style.cssText = [\n `font-size:${t.font.sizeSmall}px`,\n 'font-weight:600',\n `color:${t.textSecondary}`,\n 'padding:8px 12px',\n `border-bottom:1px solid ${border}`,\n 'text-transform:uppercase',\n 'letter-spacing:0.04em',\n ].join(';');\n\n const body = document.createElement('div');\n body.style.cssText = 'flex:1;min-height:0;position:relative;';\n\n wrap.appendChild(head);\n wrap.appendChild(body);\n return { wrap, body };\n }\n\n /** A subtle surface tint distinct from the page background, per theme. */\n private panelBackground(): string {\n return this.theme.name === 'light' ? 'rgba(0,0,0,0.02)' : 'rgba(255,255,255,0.03)';\n }\n\n /** Replace the displayed result and re-render all panels. */\n update(result: PerformanceResult): void {\n this.options = { ...this.options, result };\n this.destroyCharts();\n this.root.replaceChildren();\n this.build();\n }\n\n setTheme(theme: ThemeName | Theme): void {\n this.theme = resolveTheme(theme);\n this.options = { ...this.options, theme };\n this.destroyCharts();\n this.root.replaceChildren();\n this.build();\n }\n\n private destroyCharts(): void {\n this.equityChart?.destroy();\n this.drawdownChart?.destroy();\n this.heatmap?.destroy();\n this.equityChart = null;\n this.drawdownChart = null;\n this.heatmap = null;\n }\n\n destroy(): void {\n this.destroyCharts();\n this.root.remove();\n }\n}\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"}
|
|
@@ -1,16 +1,66 @@
|
|
|
1
1
|
import { PanelPosition, PanelConfig, ResolvedLayout, Rect } from '@tradecanvas/commons';
|
|
2
|
+
/** What a folded pane keeps: its header, with the indicator's name and the pane's buttons. */
|
|
3
|
+
export declare const COLLAPSED_PANE_HEIGHT = 20;
|
|
4
|
+
/** The least the price pane keeps while a pane is maximised. */
|
|
5
|
+
export declare const MIN_MAIN_HEIGHT_WITH_MAXIMIZED = 48;
|
|
2
6
|
export declare class LayoutManager {
|
|
3
7
|
private panels;
|
|
4
8
|
private containerWidth;
|
|
5
9
|
private containerHeight;
|
|
6
10
|
private priceAxisWidth;
|
|
11
|
+
/** Width of the left price scale; 0 while it is hidden. */
|
|
12
|
+
private leftAxisWidth;
|
|
13
|
+
/** The pane that takes the room of the others (they fold to their headers), or null. */
|
|
14
|
+
private maximized;
|
|
7
15
|
resize(width: number, height: number): void;
|
|
8
16
|
addPanel(instanceId: string, position?: PanelPosition, size?: number): void;
|
|
17
|
+
/** Hand a pane to another indicator, keeping its place and size. */
|
|
18
|
+
renamePanel(fromId: string, toId: string): void;
|
|
9
19
|
removePanel(instanceId: string): void;
|
|
20
|
+
/**
|
|
21
|
+
* Fold a top or bottom pane to its header, or open it again. While a pane
|
|
22
|
+
* is maximised this puts the layout back to normal first (the other panes
|
|
23
|
+
* show folded then). False when nothing changed.
|
|
24
|
+
*/
|
|
25
|
+
setPanelCollapsed(instanceId: string, collapsed: boolean): boolean;
|
|
26
|
+
/** Folded as set (see `isPanelShownCollapsed` for how it shows). */
|
|
27
|
+
isPanelCollapsed(instanceId: string): boolean;
|
|
28
|
+
/** Shown folded: folded as set, or another pane is maximised. */
|
|
29
|
+
isPanelShownCollapsed(instanceId: string): boolean;
|
|
30
|
+
/** A pane's value scale: logarithmic, upside down, in percent. False when nothing changed. */
|
|
31
|
+
setPanelScale(instanceId: string, scale: {
|
|
32
|
+
log?: boolean;
|
|
33
|
+
invert?: boolean;
|
|
34
|
+
percent?: boolean;
|
|
35
|
+
}): boolean;
|
|
36
|
+
/** Whether `movePanel(instanceId, delta)` would move it. */
|
|
37
|
+
canMovePanel(instanceId: string, delta: -1 | 1): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Let one top or bottom pane take the room: the others fold to their
|
|
40
|
+
* headers and the price pane keeps a strip. `null` puts them back.
|
|
41
|
+
*/
|
|
42
|
+
setMaximizedPanel(instanceId: string | null): boolean;
|
|
43
|
+
getMaximizedPanel(): string | null;
|
|
44
|
+
/**
|
|
45
|
+
* Move a pane one place up (`-1`) or down (`1`) among the panes on its side
|
|
46
|
+
* of the price pane. False at the end of the line.
|
|
47
|
+
*/
|
|
48
|
+
movePanel(instanceId: string, delta: -1 | 1): boolean;
|
|
49
|
+
/** Put the panes on each side in the order of `ids` (others keep their place after them). */
|
|
50
|
+
orderPanels(ids: readonly string[]): void;
|
|
51
|
+
/** A pane's height (or width) on screen: folded, maximised or as set. */
|
|
52
|
+
private shownSize;
|
|
10
53
|
setPanelPosition(instanceId: string, position: PanelPosition): void;
|
|
54
|
+
/**
|
|
55
|
+
* Resize a pane; a folded pane opens, and a maximised layout goes back to
|
|
56
|
+
* normal. A height is kept within the room there is (a stored layout may ask
|
|
57
|
+
* for more).
|
|
58
|
+
*/
|
|
11
59
|
setPanelSize(instanceId: string, size: number): void;
|
|
12
60
|
/** Width reserved for the price axis right of the main chart. */
|
|
13
61
|
setPriceAxisWidth(width: number): void;
|
|
62
|
+
/** Width reserved left of the plot for the left price scale (0 = none). */
|
|
63
|
+
setLeftAxisWidth(width: number): void;
|
|
14
64
|
getPanels(): PanelConfig[];
|
|
15
65
|
resolve(): ResolvedLayout;
|
|
16
66
|
getMainChartRect(): Rect;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LayoutManager.d.ts","sourceRoot":"","sources":["../../src/layout/LayoutManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAA8B,IAAI,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"LayoutManager.d.ts","sourceRoot":"","sources":["../../src/layout/LayoutManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAA8B,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAKzH,8FAA8F;AAC9F,eAAO,MAAM,qBAAqB,KAAK,CAAC;AACxC,gEAAgE;AAChE,eAAO,MAAM,8BAA8B,KAAK,CAAC;AAIjD,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,cAAc,CAAoB;IAC1C,2DAA2D;IAC3D,OAAO,CAAC,aAAa,CAAK;IAC1B,wFAAwF;IACxF,OAAO,CAAC,SAAS,CAAuB;IAExC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAK3C,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,GAAE,aAAwB,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAarF,oEAAoE;IACpE,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAQ/C,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAKrC;;;;OAIG;IACH,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,OAAO;IASlE,oEAAoE;IACpE,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAI7C,iEAAiE;IACjE,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAMlD,8FAA8F;IAC9F,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,GAAG,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO;IAmBzG,4DAA4D;IAC5D,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,OAAO;IAOxD;;;OAGG;IACH,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO;IASrD,iBAAiB,IAAI,MAAM,GAAG,IAAI;IAIlC;;;OAGG;IACH,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,OAAO;IAgBrD,6FAA6F;IAC7F,WAAW,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI;IAQzC,yEAAyE;IACzE,OAAO,CAAC,SAAS;IAMjB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,IAAI;IAkBnE;;;;OAIG;IACH,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAWpD,iEAAiE;IACjE,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAItC,2EAA2E;IAC3E,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAIrC,SAAS,IAAI,WAAW,EAAE;IAI1B,OAAO,IAAI,cAAc;IAgGzB,gBAAgB,IAAI,IAAI;CAGzB"}
|
|
@@ -7,6 +7,8 @@ export interface PriceAxisWidthInput {
|
|
|
7
7
|
/** Decimals for the price tags (a market's `pricePrecision`), or null to follow the axis. */
|
|
8
8
|
tagPrecision: number | null;
|
|
9
9
|
locale: string;
|
|
10
|
+
/** The chart's price format, when it has one: labels and tags print with it. */
|
|
11
|
+
format?: ((price: number) => string) | null;
|
|
10
12
|
fontFamily: string;
|
|
11
13
|
fontSizeSmall: number;
|
|
12
14
|
measure: (text: string, font: string) => number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"priceAxisWidth.d.ts","sourceRoot":"","sources":["../../src/layout/priceAxisWidth.ts"],"names":[],"mappings":"AAUA,8FAA8F;AAC9F,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAEpC,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,6FAA6F;IAC7F,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACjD;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,mBAAmB,GAAG,MAAM,CAoBzE;AAED,uFAAuF;AACvF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAI5E"}
|
|
1
|
+
{"version":3,"file":"priceAxisWidth.d.ts","sourceRoot":"","sources":["../../src/layout/priceAxisWidth.ts"],"names":[],"mappings":"AAUA,8FAA8F;AAC9F,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAEpC,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,6FAA6F;IAC7F,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,gFAAgF;IAChF,MAAM,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,IAAI,CAAC;IAC5C,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACjD;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,mBAAmB,GAAG,MAAM,CAoBzE;AAED,uFAAuF;AACvF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAI5E"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { SymbolInfo } from '@tradecanvas/commons';
|
|
2
|
+
/**
|
|
3
|
+
* Which bar times fall in `info`'s regular hours, for bars like `data`'s
|
|
4
|
+
* (by the time each bar opens). Null when there is nothing to leave out:
|
|
5
|
+
* the symbol has no hours or no zone, or the bars are a day or longer.
|
|
6
|
+
*/
|
|
7
|
+
export declare function regularHoursFilter(info: SymbolInfo | null, data: readonly {
|
|
8
|
+
time: number;
|
|
9
|
+
}[]): ((time: number) => boolean) | null;
|
|
10
|
+
//# sourceMappingURL=regularHours.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"regularHours.d.ts","sourceRoot":"","sources":["../src/regularHours.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAQvD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,UAAU,GAAG,IAAI,EACvB,IAAI,EAAE,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,GAChC,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,IAAI,CAiBpC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { LayoutStorage, SavedLayout, SavedLayoutSummary } from './layoutStorage.js';
|
|
2
|
+
/** The longest a layout's name may be. */
|
|
3
|
+
export declare const MAX_LAYOUT_NAME = 80;
|
|
4
|
+
/** A layout name trimmed, with runs of spaces folded and capped in length; `null` when nothing is left. */
|
|
5
|
+
export declare function cleanLayoutName(name: string): string | null;
|
|
6
|
+
/** What a session saves and opens: the widget, or a grid of widgets. */
|
|
7
|
+
export interface LayoutSessionHost {
|
|
8
|
+
/** What to save now, with the symbol and interval a list shows. */
|
|
9
|
+
capture(): {
|
|
10
|
+
content: string;
|
|
11
|
+
symbol?: string;
|
|
12
|
+
timeframe?: string;
|
|
13
|
+
};
|
|
14
|
+
/** Show a saved layout; throw when its content can't be shown. */
|
|
15
|
+
apply(layout: SavedLayout): Promise<void> | void;
|
|
16
|
+
}
|
|
17
|
+
export interface LayoutSessionOptions {
|
|
18
|
+
/** Save the current layout by itself once changes settle. Default `true`. */
|
|
19
|
+
autoSave?: boolean;
|
|
20
|
+
/** How long changes must settle before an auto-save. Default 1500 ms. */
|
|
21
|
+
debounceMs?: number;
|
|
22
|
+
/**
|
|
23
|
+
* What this session saves (`'chart'`, the default, or `'grid'`): it lists
|
|
24
|
+
* and opens only layouts of its kind, so both can share one storage.
|
|
25
|
+
*/
|
|
26
|
+
kind?: string;
|
|
27
|
+
/** The current layout, its saved state or the auto-save switch changed. */
|
|
28
|
+
onChange?: () => void;
|
|
29
|
+
/** An auto-save failed (a full storage, a server down). */
|
|
30
|
+
onError?: (error: unknown) => void;
|
|
31
|
+
now?: () => number;
|
|
32
|
+
newId?: () => string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Named layouts over a {@link LayoutStorage}: the one showing now, save it,
|
|
36
|
+
* save it under a new name, open, rename and remove. Changes reported with
|
|
37
|
+
* `changed()` are auto-saved into the current layout once they settle, and
|
|
38
|
+
* only when what would be saved differs from what was.
|
|
39
|
+
*
|
|
40
|
+
* Every operation runs in turn, and reads the current layout and captures
|
|
41
|
+
* the chart when its turn comes: a save never lands in a layout opened after
|
|
42
|
+
* it was asked for, and never holds a half-opened chart. What storage hands
|
|
43
|
+
* back is checked before it is used.
|
|
44
|
+
*/
|
|
45
|
+
export declare class LayoutSession {
|
|
46
|
+
private readonly storage;
|
|
47
|
+
private readonly host;
|
|
48
|
+
private readonly options;
|
|
49
|
+
private currentLayout;
|
|
50
|
+
/** What the current layout holds in storage (as captured), to tell a real change. */
|
|
51
|
+
private savedContent;
|
|
52
|
+
private dirty;
|
|
53
|
+
private autoSave;
|
|
54
|
+
private readonly debounceMs;
|
|
55
|
+
private readonly kind;
|
|
56
|
+
private timer;
|
|
57
|
+
private applying;
|
|
58
|
+
/** Operations waiting or running; a change while one runs is looked at after. */
|
|
59
|
+
private busy;
|
|
60
|
+
private changedWhileBusy;
|
|
61
|
+
private tail;
|
|
62
|
+
private destroyed;
|
|
63
|
+
private readonly now;
|
|
64
|
+
private readonly newId;
|
|
65
|
+
constructor(storage: LayoutStorage, host: LayoutSessionHost, options?: LayoutSessionOptions);
|
|
66
|
+
/** The layout showing now, or `null` before one is saved or opened. */
|
|
67
|
+
current(): SavedLayoutSummary | null;
|
|
68
|
+
/** The chart differs from the current layout as saved (auto-save off, failed, or not yet run). */
|
|
69
|
+
isDirty(): boolean;
|
|
70
|
+
isAutoSave(): boolean;
|
|
71
|
+
setAutoSave(on: boolean): void;
|
|
72
|
+
/** Every saved layout of this session's kind, newest first; entries that aren't layouts are left out. */
|
|
73
|
+
list(): Promise<SavedLayoutSummary[]>;
|
|
74
|
+
/** Save into the current layout; `null` when there is none yet (ask for a name, then `saveAs`). */
|
|
75
|
+
save(): Promise<SavedLayoutSummary | null>;
|
|
76
|
+
/** Save as a new layout called `name`, and make it the current one. */
|
|
77
|
+
saveAs(name: string): Promise<SavedLayoutSummary>;
|
|
78
|
+
/**
|
|
79
|
+
* Show a saved layout. `false` when there is no such layout (or it isn't
|
|
80
|
+
* one of this kind); rejects when it could not be shown, and then no layout
|
|
81
|
+
* is current (the chart may be part way).
|
|
82
|
+
*/
|
|
83
|
+
open(id: string): Promise<boolean>;
|
|
84
|
+
rename(id: string, name: string): Promise<void>;
|
|
85
|
+
remove(id: string): Promise<void>;
|
|
86
|
+
/** Something a layout holds may have changed: check once things settle, and auto-save. */
|
|
87
|
+
changed(): void;
|
|
88
|
+
/** Stop. A change still waiting to be auto-saved is saved now. */
|
|
89
|
+
destroy(): void;
|
|
90
|
+
/** The changes have settled: save them into the current layout, or mark it changed. */
|
|
91
|
+
private settle;
|
|
92
|
+
/** Store the chart as layout `id` and make it the current one (runs inside the queue). */
|
|
93
|
+
private write;
|
|
94
|
+
/** No layout is current any more. */
|
|
95
|
+
private forget;
|
|
96
|
+
/** Run operations one after another; a failed one does not stop the next. */
|
|
97
|
+
private queue;
|
|
98
|
+
private cancelTimer;
|
|
99
|
+
private notify;
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=LayoutSession.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LayoutSession.d.ts","sourceRoot":"","sources":["../../src/state/LayoutSession.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/** A saved layout as a list shows it. */
|
|
2
|
+
export interface SavedLayoutSummary {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
/** The symbol it opens on. */
|
|
6
|
+
symbol?: string;
|
|
7
|
+
/** The interval it opens on. */
|
|
8
|
+
timeframe?: string;
|
|
9
|
+
/** When it was last saved, in ms since the epoch. */
|
|
10
|
+
updatedAt: number;
|
|
11
|
+
/** What saved it: `'chart'` (a widget, the default) or `'grid'` (a grid of charts). */
|
|
12
|
+
kind?: string;
|
|
13
|
+
}
|
|
14
|
+
/** A saved layout: its summary and what it holds, as the widget wrote it (JSON). */
|
|
15
|
+
export interface SavedLayout extends SavedLayoutSummary {
|
|
16
|
+
content: string;
|
|
17
|
+
}
|
|
18
|
+
type MaybePromise<T> = T | Promise<T>;
|
|
19
|
+
/**
|
|
20
|
+
* Where named layouts live. The widget ships one for `localStorage` and one in
|
|
21
|
+
* memory; a host keeps layouts on its server by implementing these four calls
|
|
22
|
+
* (each may return a promise).
|
|
23
|
+
*/
|
|
24
|
+
export interface LayoutStorage {
|
|
25
|
+
/** Every layout, newest first. */
|
|
26
|
+
list(): MaybePromise<SavedLayoutSummary[]>;
|
|
27
|
+
/** One layout, or `null` when there is no such layout. */
|
|
28
|
+
load(id: string): MaybePromise<SavedLayout | null>;
|
|
29
|
+
/** Save a layout, replacing one with the same id. */
|
|
30
|
+
save(layout: SavedLayout): MaybePromise<void>;
|
|
31
|
+
remove(id: string): MaybePromise<void>;
|
|
32
|
+
}
|
|
33
|
+
/** A summary read back from storage (or a host's server), or null when it is not one. */
|
|
34
|
+
export declare function readLayoutSummary(value: unknown): SavedLayoutSummary | null;
|
|
35
|
+
/** A whole layout read back from storage, or null when it is not one. */
|
|
36
|
+
export declare function readSavedLayout(value: unknown): SavedLayout | null;
|
|
37
|
+
/** Layouts kept in memory: for tests, or a page that does not keep them. */
|
|
38
|
+
export declare function memoryLayouts(initial?: readonly SavedLayout[]): LayoutStorage;
|
|
39
|
+
/**
|
|
40
|
+
* Layouts in the browser's `localStorage`: an index of summaries under
|
|
41
|
+
* `<prefix>index` and each layout's content under `<prefix>item:<id>`.
|
|
42
|
+
* Entries it cannot read are skipped.
|
|
43
|
+
*/
|
|
44
|
+
export declare function localStorageLayouts(prefix?: string): LayoutStorage;
|
|
45
|
+
export {};
|
|
46
|
+
//# sourceMappingURL=layoutStorage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layoutStorage.d.ts","sourceRoot":"","sources":["../../src/state/layoutStorage.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gCAAgC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,SAAS,EAAE,MAAM,CAAC;IAClB,uFAAuF;IACvF,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,oFAAoF;AACpF,MAAM,WAAW,WAAY,SAAQ,kBAAkB;IACrD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAEtC;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,kCAAkC;IAClC,IAAI,IAAI,YAAY,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAC3C,0DAA0D;IAC1D,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACnD,qDAAqD;IACrD,IAAI,CAAC,MAAM,EAAE,WAAW,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAC9C,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;CACxC;AAYD,yFAAyF;AACzF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,kBAAkB,GAAG,IAAI,CAY3E;AAED,yEAAyE;AACzE,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,GAAG,IAAI,CAIlE;AAED,4EAA4E;AAC5E,wBAAgB,aAAa,CAAC,OAAO,GAAE,SAAS,WAAW,EAAO,GAAG,aAAa,CAejF;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,SAAiB,GAAG,aAAa,CAiC1E"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ExecutionAdapter, ExecutionError, TradingOrder, TradingPosition } from '@tradecanvas/commons';
|
|
2
|
-
/** The
|
|
3
|
-
export type ExecutionIntentType = 'orderPlace' | 'orderModify' | 'orderCancel' | 'positionModify' | 'positionClose';
|
|
1
|
+
import { ExecutionAdapter, ExecutionError, TradingOrder, TradingPosition, FillEvent } from '@tradecanvas/commons';
|
|
2
|
+
/** The order/position intents the chart emits and an adapter consumes. */
|
|
3
|
+
export type ExecutionIntentType = 'orderPlace' | 'orderModify' | 'orderCancel' | 'positionModify' | 'positionClose' | 'positionReverse';
|
|
4
4
|
/**
|
|
5
5
|
* Surface the host (the Chart) provides so execution can be bridged without
|
|
6
6
|
* the helper knowing anything about chart internals — which keeps it pure and
|
|
@@ -15,6 +15,10 @@ export interface ExecutionHost {
|
|
|
15
15
|
setPositions(positions: TradingPosition[]): void;
|
|
16
16
|
/** Surface an execution failure (adapter-reported or a failed command). */
|
|
17
17
|
onError(error: ExecutionError): void;
|
|
18
|
+
/** An order filled or a position closed (the adapter's `fill`). */
|
|
19
|
+
onFill?(fill: FillEvent): void;
|
|
20
|
+
/** The positions on the chart, until the adapter reports its own. */
|
|
21
|
+
getPositions?(): readonly TradingPosition[];
|
|
18
22
|
}
|
|
19
23
|
/**
|
|
20
24
|
* Bridge an `ExecutionAdapter` to a host: render the adapter's authoritative
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wireExecution.d.ts","sourceRoot":"","sources":["../../src/trading/wireExecution.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAEhB,cAAc,EACd,YAAY,EACZ,eAAe,
|
|
1
|
+
{"version":3,"file":"wireExecution.d.ts","sourceRoot":"","sources":["../../src/trading/wireExecution.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAEhB,cAAc,EACd,YAAY,EACZ,eAAe,EAOf,SAAS,EACV,MAAM,sBAAsB,CAAC;AAE9B,0EAA0E;AAC1E,MAAM,MAAM,mBAAmB,GAC3B,YAAY,GACZ,aAAa,GACb,aAAa,GACb,gBAAgB,GAChB,eAAe,GACf,iBAAiB,CAAC;AAEtB;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,uEAAuE;IACvE,QAAQ,CAAC,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACrF,yDAAyD;IACzD,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;IACxC,yDAAyD;IACzD,YAAY,CAAC,SAAS,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC;IACjD,2EAA2E;IAC3E,OAAO,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IACrC,mEAAmE;IACnE,MAAM,CAAC,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,CAAC;IAC/B,qEAAqE;IACrE,YAAY,CAAC,IAAI,SAAS,eAAe,EAAE,CAAC;CAC7C;AAsDD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,aAAa,GAAG,MAAM,IAAI,CA6CxF"}
|