@tradecanvas/chart 1.4.0 → 1.10.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.
Files changed (195) hide show
  1. package/README.md +352 -95
  2. package/dist/Chart.d.ts +621 -23
  3. package/dist/Chart.d.ts.map +1 -1
  4. package/dist/DataManager.d.ts +5 -0
  5. package/dist/DataManager.d.ts.map +1 -1
  6. package/dist/HistoryPager.d.ts +58 -0
  7. package/dist/HistoryPager.d.ts.map +1 -0
  8. package/dist/LayoutSession-BFqQwhvV.cjs +2 -0
  9. package/dist/LayoutSession-BFqQwhvV.cjs.map +1 -0
  10. package/dist/LayoutSession-P9Vb-Jpb.js +3995 -0
  11. package/dist/LayoutSession-P9Vb-Jpb.js.map +1 -0
  12. package/dist/ThemeManager.d.ts +5 -1
  13. package/dist/ThemeManager.d.ts.map +1 -1
  14. package/dist/chartA11y.d.ts +59 -0
  15. package/dist/chartA11y.d.ts.map +1 -0
  16. package/dist/charts/ChartTypeStrategy.d.ts +5 -4
  17. package/dist/charts/ChartTypeStrategy.d.ts.map +1 -1
  18. package/dist/grid/ChartGrid.d.ts +6 -1
  19. package/dist/grid/ChartGrid.d.ts.map +1 -1
  20. package/dist/i18n-CiQ8EDVs.js +1469 -0
  21. package/dist/i18n-CiQ8EDVs.js.map +1 -0
  22. package/dist/i18n-WsLA9SmD.cjs +2 -0
  23. package/dist/i18n-WsLA9SmD.cjs.map +1 -0
  24. package/dist/index.cjs +1 -1
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.d.ts +24 -5
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +34 -34
  29. package/dist/index.js.map +1 -1
  30. package/dist/indicatorLabel.d.ts +7 -0
  31. package/dist/indicatorLabel.d.ts.map +1 -0
  32. package/dist/layout/LayoutManager.d.ts +50 -0
  33. package/dist/layout/LayoutManager.d.ts.map +1 -1
  34. package/dist/layout/priceAxisWidth.d.ts +2 -0
  35. package/dist/layout/priceAxisWidth.d.ts.map +1 -1
  36. package/dist/regularHours.d.ts +10 -0
  37. package/dist/regularHours.d.ts.map +1 -0
  38. package/dist/state/LayoutSession.d.ts +101 -0
  39. package/dist/state/LayoutSession.d.ts.map +1 -0
  40. package/dist/state/layoutStorage.d.ts +46 -0
  41. package/dist/state/layoutStorage.d.ts.map +1 -0
  42. package/dist/trading/wireExecution.d.ts +7 -3
  43. package/dist/trading/wireExecution.d.ts.map +1 -1
  44. package/dist/widget/ChartWidget.d.ts +219 -10
  45. package/dist/widget/ChartWidget.d.ts.map +1 -1
  46. package/dist/widget/ChartWidgetGrid.d.ts +166 -0
  47. package/dist/widget/ChartWidgetGrid.d.ts.map +1 -0
  48. package/dist/widget/DrawingTemplateStore.d.ts +29 -8
  49. package/dist/widget/DrawingTemplateStore.d.ts.map +1 -1
  50. package/dist/widget/WatchlistStore.d.ts +65 -0
  51. package/dist/widget/WatchlistStore.d.ts.map +1 -0
  52. package/dist/widget/WidgetAccountPanel.d.ts +72 -0
  53. package/dist/widget/WidgetAccountPanel.d.ts.map +1 -0
  54. package/dist/widget/WidgetAlertsPanel.d.ts +50 -3
  55. package/dist/widget/WidgetAlertsPanel.d.ts.map +1 -1
  56. package/dist/widget/WidgetBracketBar.d.ts +3 -1
  57. package/dist/widget/WidgetBracketBar.d.ts.map +1 -1
  58. package/dist/widget/WidgetChartNav.d.ts +36 -0
  59. package/dist/widget/WidgetChartNav.d.ts.map +1 -0
  60. package/dist/widget/WidgetCommandPalette.d.ts +3 -1
  61. package/dist/widget/WidgetCommandPalette.d.ts.map +1 -1
  62. package/dist/widget/WidgetContextMenu.d.ts +40 -0
  63. package/dist/widget/WidgetContextMenu.d.ts.map +1 -0
  64. package/dist/widget/WidgetDataWindow.d.ts +3 -1
  65. package/dist/widget/WidgetDataWindow.d.ts.map +1 -1
  66. package/dist/widget/WidgetDepthLadder.d.ts +3 -1
  67. package/dist/widget/WidgetDepthLadder.d.ts.map +1 -1
  68. package/dist/widget/WidgetDrawingSettings.d.ts +108 -0
  69. package/dist/widget/WidgetDrawingSettings.d.ts.map +1 -0
  70. package/dist/widget/WidgetDrawingSidebar.d.ts +16 -1
  71. package/dist/widget/WidgetDrawingSidebar.d.ts.map +1 -1
  72. package/dist/widget/WidgetDrawingStyle.d.ts +3 -1
  73. package/dist/widget/WidgetDrawingStyle.d.ts.map +1 -1
  74. package/dist/widget/WidgetDropdown.d.ts.map +1 -1
  75. package/dist/widget/WidgetGoToDate.d.ts +5 -4
  76. package/dist/widget/WidgetGoToDate.d.ts.map +1 -1
  77. package/dist/widget/WidgetHistoryPill.d.ts +23 -0
  78. package/dist/widget/WidgetHistoryPill.d.ts.map +1 -0
  79. package/dist/widget/WidgetHotkeySheet.d.ts.map +1 -1
  80. package/dist/widget/WidgetIndicatorLegend.d.ts +31 -1
  81. package/dist/widget/WidgetIndicatorLegend.d.ts.map +1 -1
  82. package/dist/widget/WidgetIndicatorSettings.d.ts +62 -7
  83. package/dist/widget/WidgetIndicatorSettings.d.ts.map +1 -1
  84. package/dist/widget/WidgetIntervalInput.d.ts +34 -0
  85. package/dist/widget/WidgetIntervalInput.d.ts.map +1 -0
  86. package/dist/widget/WidgetLayoutsDialog.d.ts +39 -0
  87. package/dist/widget/WidgetLayoutsDialog.d.ts.map +1 -0
  88. package/dist/widget/WidgetLayoutsUI.d.ts +37 -0
  89. package/dist/widget/WidgetLayoutsUI.d.ts.map +1 -0
  90. package/dist/widget/WidgetNamePrompt.d.ts +31 -0
  91. package/dist/widget/WidgetNamePrompt.d.ts.map +1 -0
  92. package/dist/widget/WidgetObjectTree.d.ts +21 -3
  93. package/dist/widget/WidgetObjectTree.d.ts.map +1 -1
  94. package/dist/widget/WidgetOrderTicket.d.ts +49 -0
  95. package/dist/widget/WidgetOrderTicket.d.ts.map +1 -0
  96. package/dist/widget/WidgetReplayBar.d.ts +15 -0
  97. package/dist/widget/WidgetReplayBar.d.ts.map +1 -1
  98. package/dist/widget/WidgetSettings.d.ts +13 -1
  99. package/dist/widget/WidgetSettings.d.ts.map +1 -1
  100. package/dist/widget/WidgetStatusBar.d.ts +3 -0
  101. package/dist/widget/WidgetStatusBar.d.ts.map +1 -1
  102. package/dist/widget/WidgetStyles.d.ts +3 -1
  103. package/dist/widget/WidgetStyles.d.ts.map +1 -1
  104. package/dist/widget/WidgetSymbolInfo.d.ts +64 -0
  105. package/dist/widget/WidgetSymbolInfo.d.ts.map +1 -0
  106. package/dist/widget/WidgetSymbolSearch.d.ts +26 -5
  107. package/dist/widget/WidgetSymbolSearch.d.ts.map +1 -1
  108. package/dist/widget/WidgetToolbar.d.ts +30 -1
  109. package/dist/widget/WidgetToolbar.d.ts.map +1 -1
  110. package/dist/widget/WidgetWatchlist.d.ts +53 -13
  111. package/dist/widget/WidgetWatchlist.d.ts.map +1 -1
  112. package/dist/widget/chartMenu.d.ts +40 -0
  113. package/dist/widget/chartMenu.d.ts.map +1 -0
  114. package/dist/widget/drawingMenu.d.ts +21 -0
  115. package/dist/widget/drawingMenu.d.ts.map +1 -0
  116. package/dist/widget/focusTrap.d.ts +8 -0
  117. package/dist/widget/focusTrap.d.ts.map +1 -0
  118. package/dist/widget/i18n.d.ts +20 -89
  119. package/dist/widget/i18n.d.ts.map +1 -1
  120. package/dist/widget/iconSet.d.ts.map +1 -1
  121. package/dist/widget/index.cjs +1644 -376
  122. package/dist/widget/index.cjs.map +1 -1
  123. package/dist/widget/index.d.ts +15 -1
  124. package/dist/widget/index.d.ts.map +1 -1
  125. package/dist/widget/index.js +6389 -1228
  126. package/dist/widget/index.js.map +1 -1
  127. package/dist/widget/indicatorTemplates.d.ts +24 -0
  128. package/dist/widget/indicatorTemplates.d.ts.map +1 -0
  129. package/dist/widget/keyTarget.d.ts +11 -0
  130. package/dist/widget/keyTarget.d.ts.map +1 -0
  131. package/dist/widget/legendValues.d.ts +11 -6
  132. package/dist/widget/legendValues.d.ts.map +1 -1
  133. package/dist/widget/locales/ar.d.ts +4 -0
  134. package/dist/widget/locales/ar.d.ts.map +1 -0
  135. package/dist/widget/locales/de.d.ts +4 -0
  136. package/dist/widget/locales/de.d.ts.map +1 -0
  137. package/dist/widget/locales/en.d.ts +722 -0
  138. package/dist/widget/locales/en.d.ts.map +1 -0
  139. package/dist/widget/locales/es.d.ts +4 -0
  140. package/dist/widget/locales/es.d.ts.map +1 -0
  141. package/dist/widget/locales/fr.d.ts +4 -0
  142. package/dist/widget/locales/fr.d.ts.map +1 -0
  143. package/dist/widget/locales/he.d.ts +4 -0
  144. package/dist/widget/locales/he.d.ts.map +1 -0
  145. package/dist/widget/locales/id.d.ts +4 -0
  146. package/dist/widget/locales/id.d.ts.map +1 -0
  147. package/dist/widget/locales/index.cjs +2 -0
  148. package/dist/widget/locales/index.cjs.map +1 -0
  149. package/dist/widget/locales/index.d.ts +33 -0
  150. package/dist/widget/locales/index.d.ts.map +1 -0
  151. package/dist/widget/locales/index.js +10089 -0
  152. package/dist/widget/locales/index.js.map +1 -0
  153. package/dist/widget/locales/ja.d.ts +4 -0
  154. package/dist/widget/locales/ja.d.ts.map +1 -0
  155. package/dist/widget/locales/ko.d.ts +4 -0
  156. package/dist/widget/locales/ko.d.ts.map +1 -0
  157. package/dist/widget/locales/pt.d.ts +4 -0
  158. package/dist/widget/locales/pt.d.ts.map +1 -0
  159. package/dist/widget/locales/ru.d.ts +4 -0
  160. package/dist/widget/locales/ru.d.ts.map +1 -0
  161. package/dist/widget/locales/th.d.ts +4 -0
  162. package/dist/widget/locales/th.d.ts.map +1 -0
  163. package/dist/widget/locales/tr.d.ts +4 -0
  164. package/dist/widget/locales/tr.d.ts.map +1 -0
  165. package/dist/widget/locales/vi.d.ts +4 -0
  166. package/dist/widget/locales/vi.d.ts.map +1 -0
  167. package/dist/widget/locales/zh.d.ts +4 -0
  168. package/dist/widget/locales/zh.d.ts.map +1 -0
  169. package/dist/widget/locales/zhHant.d.ts +4 -0
  170. package/dist/widget/locales/zhHant.d.ts.map +1 -0
  171. package/dist/widget/orderTicket.d.ts +27 -0
  172. package/dist/widget/orderTicket.d.ts.map +1 -0
  173. package/dist/widget/settingsControls.d.ts +24 -0
  174. package/dist/widget/settingsControls.d.ts.map +1 -0
  175. package/dist/widget/types.d.ts +187 -6
  176. package/dist/widget/types.d.ts.map +1 -1
  177. package/dist/widget/widgetConfig.d.ts +4 -0
  178. package/dist/widget/widgetConfig.d.ts.map +1 -1
  179. package/dist/widget/widgetLayout.d.ts +22 -0
  180. package/dist/widget/widgetLayout.d.ts.map +1 -0
  181. package/dist/widget/widgetLocales.d.ts +17 -0
  182. package/dist/widget/widgetLocales.d.ts.map +1 -0
  183. package/dist/widget/widgetTimeframes.d.ts +8 -0
  184. package/dist/widget/widgetTimeframes.d.ts.map +1 -1
  185. package/dist/widget/widgetTimezones.d.ts +32 -0
  186. package/dist/widget/widgetTimezones.d.ts.map +1 -0
  187. package/dist/widget/widgetUI.d.ts +126 -0
  188. package/dist/widget/widgetUI.d.ts.map +1 -0
  189. package/package.json +8 -3
  190. package/dist/DragDropImporter-C5kgfbET.cjs +0 -2
  191. package/dist/DragDropImporter-C5kgfbET.cjs.map +0 -1
  192. package/dist/DragDropImporter-Dd9Mud5J.js +0 -2099
  193. package/dist/DragDropImporter-Dd9Mud5J.js.map +0 -1
  194. package/dist/charts/IndicatorPriceRange.d.ts +0 -20
  195. package/dist/charts/IndicatorPriceRange.d.ts.map +0 -1
package/README.md CHANGED
@@ -1,44 +1,42 @@
1
- # @tradecanvas/chart
1
+ <p align="center">
2
+ <a href="https://bonguynvan.github.io/tradecanvas/"><img src="https://raw.githubusercontent.com/bonguynvan/tradecanvas/main/.github/assets/banner.png" alt="TradeCanvas, the chart engine for trading apps" width="100%"></a>
3
+ </p>
4
+
5
+ <p align="center">
6
+ <a href="https://www.npmjs.com/package/@tradecanvas/chart"><img src="https://img.shields.io/npm/v/@tradecanvas/chart?style=flat-square&labelColor=0b0e13&color=f2a93b&label=npm" alt="npm version"></a>
7
+ <a href="https://www.npmjs.com/package/@tradecanvas/chart"><img src="https://img.shields.io/npm/dm/@tradecanvas/chart?style=flat-square&labelColor=0b0e13&color=3ccf91" alt="npm downloads"></a>
8
+ <a href="https://github.com/bonguynvan/tradecanvas/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/bonguynvan/tradecanvas/ci.yml?branch=main&style=flat-square&labelColor=0b0e13&label=CI" alt="CI status"></a>
9
+ <img src="https://img.shields.io/badge/third--party%20deps-0-3ccf91?style=flat-square&labelColor=0b0e13" alt="No third-party dependencies">
10
+ <img src="https://img.shields.io/badge/TypeScript-strict-4c8dff?style=flat-square&labelColor=0b0e13" alt="TypeScript">
11
+ <a href="https://github.com/bonguynvan/tradecanvas/blob/main/LICENSE"><img src="https://img.shields.io/github/license/bonguynvan/tradecanvas?style=flat-square&labelColor=0b0e13&color=a9b0bd" alt="MIT license"></a>
12
+ <a href="https://github.com/bonguynvan/tradecanvas/stargazers"><img src="https://img.shields.io/github/stars/bonguynvan/tradecanvas?style=flat-square&labelColor=0b0e13&color=f2a93b" alt="GitHub stars"></a>
13
+ </p>
14
+
15
+ <p align="center">
16
+ <b><a href="https://bonguynvan.github.io/tradecanvas/">Live demo</a></b> ·
17
+ <a href="https://bonguynvan.github.io/tradecanvas/docs/getting-started/">Docs</a> ·
18
+ <a href="https://bonguynvan.github.io/tradecanvas/examples/">Examples</a> ·
19
+ <a href="https://bonguynvan.github.io/tradecanvas/playground/">Playground</a> ·
20
+ <a href="https://github.com/bonguynvan/tradecanvas/blob/main/CHANGELOG.md">Changelog</a>
21
+ </p>
22
+
23
+ <p align="center">
24
+ <b>English</b> · <a href="https://github.com/bonguynvan/tradecanvas/blob/main/README.vi.md">Tiếng Việt</a> · <a href="https://github.com/bonguynvan/tradecanvas/blob/main/README.zh-CN.md">简体中文</a> · <a href="https://github.com/bonguynvan/tradecanvas/blob/main/README.ja.md">日本語</a> · <a href="https://github.com/bonguynvan/tradecanvas/blob/main/README.ko.md">한국어</a> · <a href="https://github.com/bonguynvan/tradecanvas/blob/main/README.es.md">Español</a>
25
+ </p>
26
+
27
+ **A complete trading chart for the web.** Candlesticks to Renko, 95 indicators, 69 drawing tools, live exchange feeds and orders on the chart, drawn on Canvas2D with zero dependencies. Drop in the full `ChartWidget`, or build your own UI on the headless `Chart`, in plain TypeScript, React, Vue or Svelte.
28
+
29
+ <p align="center">
30
+ <a href="https://bonguynvan.github.io/tradecanvas/"><img src="https://raw.githubusercontent.com/bonguynvan/tradecanvas/main/.github/assets/hero.png" alt="ChartWidget with live BTCUSDT from Binance: EMA 21 and 55, RSI, a trend line, a long position and a watchlist with live quotes" width="100%"></a>
31
+ </p>
2
32
 
3
- High-performance canvas trading chart with built-in indicators, drawing tools, and real-time streaming. Zero external dependencies.
4
-
5
- **[Live Demo](https://bonguynvan.github.io/tradecanvas/)** | **[GitHub](https://github.com/bonguynvan/tradecanvas)** | **[npm](https://www.npmjs.com/package/@tradecanvas/chart)**
6
-
7
- ## Why TradeCanvas?
8
-
9
- Most chart libraries make you choose: pretty charts with no trading features, or trading features with an ugly API. TradeCanvas gives you both.
10
-
11
- - **70 built-in indicators** — SMA, EMA, TEMA, VWMA, Hull MA, RSI, MACD, Bollinger, Envelope, Ichimoku, Pivot Points, Anchored VWAP, ZigZag, Linear Regression Channel, Awesome / Chaikin Oscillator, and more. No separate calculation library needed.
12
- - **40 drawing tools** — Trendlines (info line, trend angle, cross line), Fibonacci (retracement, extension, channel, time zones, speed resistance fan), horizontal/vertical lines, channels, pitchforks (Andrews, Schiff, modified Schiff), Gann fans / boxes, cyclic lines, harmonic patterns (XABCD, ABCD, head and shoulders, Elliott waves), date & price range, Long/Short Position, Volume Profile range. With undo/redo and full serialization.
13
- - **17 chart types** — Candlestick, line, area, bar, hollow candle, baseline, Heikin-Ashi, Renko, Kagi, Line Break, Point & Figure, Range Bars, Volume Candles, **Equivolume**, HLC Area, Step Line, Line+Markers.
14
- - **Pro-grade interaction** — pan freely past the last bar into empty future space (drawings can go there too), drag the price/time axes to scale, double-click to auto-fit, `Ctrl/⌘+drag` to select several drawings (then move, restyle or delete them together), `Shift+drag` to measure (bars × price Δ × %), `Alt+click` to pin a comparison tooltip, context cursors (crosshair, grabbing hand, resize arrows), axis-following price/time pill labels under the cursor, bar-hover highlight.
15
- - **Trading overlay** — Render open positions with entry line, P&L zone, and SL/TP markers. Orders as dashed lines. Drag SL/TP to modify. Cleanly opt-out via `features.trading: false` for non-trading projects.
16
- - **Real-time streaming** — Built-in Binance adapter. Plug in your own data source with the adapter interface.
17
- - **Strategy backtester** — `@tradecanvas/analytics` ships a bar-by-bar `Backtester` with virtual fills, commission/slippage models, portfolio tracking, and risk metrics (Sharpe, Sortino, Calmar, max drawdown). **Now with 4 ready-to-use reference strategies + Monte Carlo path-dependence analysis.**
18
- - **Replay mode** — `ReplayController` drives historical bars forward at controlled speed with start / pause / step / seek / setSpeed. *(new in 0.9)* The widget now ships a floating bottom scrubber UI (play/pause/step/seek + 0.5×–100× speed) on top of it.
19
- - **Volume Profile** *(new in 0.9)* — optional horizontal histogram of traded volume bucketed by price over the visible range, with point-of-control highlighting.
20
- - **Watchlist sidebar** *(new in 0.9)* — opt-in vertical panel listing symbols with last price, % change, mini sparkline. Click a row to switch chart.
21
- - **CSV / JSON drag-and-drop** *(new in 0.9)* — drop a file onto the chart, it parses and loads instantly. Detects header layouts, ISO/unix-s/unix-ms timestamps, and array-vs-object JSON shapes.
22
- - **Saved layouts** *(new in 0.9)* — opt-in per-symbol persistence of chart type + indicator stack + drawings + alerts to localStorage. Switch symbol, switch back, your setup is intact.
23
- - **Multi-chart grid** — `ChartGrid` for synchronized 2×2 / 2×3 layouts with linked crosshairs and shared time axis.
24
- - **Signal markers & trade zones** — render bot/algorithm output (directional arrows, entry→exit rectangles) as a first-class chart layer.
25
- - **Hotkey sheet** *(new in 0.9)* — press `?` in the widget to open a categorized keyboard-shortcut reference.
26
- - **Save/load chart state** — Persist drawings, indicators, theme, and chart type to JSON. Restore with one call.
27
- - **Zero dependencies** — The entire library is self-contained. No `d3`, no `chart.js`, no `fancy-canvas`.
28
-
29
- ## Install
33
+ ## Quick Start
30
34
 
31
35
  ```bash
32
- npm install @tradecanvas/chart
33
- # or
34
- pnpm add @tradecanvas/chart
35
- # or
36
- yarn add @tradecanvas/chart
36
+ npm install @tradecanvas/chart # or: pnpm add / yarn add
37
37
  ```
38
38
 
39
- ## Quick Start
40
-
41
- The fastest path is `ChartWidget` — drop-in component with a full trading UI (toolbar, drawing sidebar, settings dialog, status bar). Zero framework dependency.
39
+ `ChartWidget` is the whole trading UI in one component: toolbar, drawing sidebar, settings dialog and status bar.
42
40
 
43
41
  ```typescript
44
42
  import { ChartWidget } from '@tradecanvas/chart/widget'
@@ -48,12 +46,74 @@ const widget = new ChartWidget(document.getElementById('chart')!, {
48
46
  symbol: 'BTCUSDT',
49
47
  timeframe: '5m',
50
48
  theme: 'dark',
51
- adapter: new BinanceAdapter(),
49
+ adapter: new BinanceAdapter(), // live data, no API key
52
50
  trading: true,
53
51
  })
54
52
  ```
55
53
 
56
- That's it. Live data, all 70 indicators, all 40 drawing tools, command palette (`Ctrl+K`), symbol search (`Ctrl+P`), hotkey sheet (`?`), shift-drag measure, alt-click tooltip pin, and drag-drop CSV/JSON loading.
54
+ That's it. Live data, all 95 indicators, all 69 drawing tools, command palette (`Ctrl+K`), symbol search (`Ctrl+P`), hotkey sheet (`?`), shift-drag measure, alt-click tooltip pin, and drag-drop CSV/JSON loading.
55
+
56
+ Using a framework? [`@tradecanvas/react`](https://github.com/bonguynvan/tradecanvas/tree/main/packages/react/), [`@tradecanvas/vue`](https://github.com/bonguynvan/tradecanvas/tree/main/packages/vue/) and [`@tradecanvas/svelte`](https://github.com/bonguynvan/tradecanvas/tree/main/packages/svelte/) wrap the headless `Chart` as a component, and the widget above mounts the same way in any framework; see [Framework Integration](#framework-integration). Or fork a [StackBlitz sandbox](https://bonguynvan.github.io/tradecanvas/examples/) and start from there.
57
+
58
+ ## A Look Around
59
+
60
+ <table>
61
+ <tr>
62
+ <td width="50%" valign="top">
63
+ <a href="https://raw.githubusercontent.com/bonguynvan/tradecanvas/main/.github/assets/drawings.png"><img src="https://raw.githubusercontent.com/bonguynvan/tradecanvas/main/.github/assets/drawings.png" alt="Drawing tools: a Fibonacci retracement with a note, a trend line, an Elliott impulse wave and a long position"></a>
64
+ <br><b>69 drawing tools</b><br>
65
+ Fibonacci, Gann, pitchforks, Elliott waves, harmonic patterns, notes and brushes, and a Long/Short position that sizes the trade. Alerts on trend lines, groups, undo and redo.
66
+ </td>
67
+ <td width="50%" valign="top">
68
+ <a href="https://raw.githubusercontent.com/bonguynvan/tradecanvas/main/.github/assets/trading.png"><img src="https://raw.githubusercontent.com/bonguynvan/tradecanvas/main/.github/assets/trading.png" alt="Trading on the chart: a long position with stop-loss and take-profit, a buy stop and a sell limit, and the account panel"></a>
69
+ <br><b>Trading on the chart</b><br>
70
+ Positions with live P&amp;L, orders you drag to a new price, SL and TP, reverse and close buttons, an order ticket and an account panel. A paper broker is built in; connect your own.
71
+ </td>
72
+ </tr>
73
+ <tr>
74
+ <td width="50%" valign="top">
75
+ <a href="https://raw.githubusercontent.com/bonguynvan/tradecanvas/main/.github/assets/grid.png"><img src="https://raw.githubusercontent.com/bonguynvan/tradecanvas/main/.github/assets/grid.png" alt="A two-by-two workspace of BTC, ETH, SOL and BNB charts on mixed intervals"></a>
76
+ <br><b>Multi-chart workspace</b><br>
77
+ Up to six full charts side by side, linked by symbol, interval, crosshair, time or drawings, and saved as one layout.
78
+ </td>
79
+ <td width="50%" valign="top">
80
+ <a href="https://raw.githubusercontent.com/bonguynvan/tradecanvas/main/.github/assets/looks.png"><img src="https://raw.githubusercontent.com/bonguynvan/tradecanvas/main/.github/assets/looks.png" alt="One chart in three looks: studio, terminal, and capsule on the light theme"></a>
81
+ <br><b>Your own look</b><br>
82
+ Three presets (studio, terminal, capsule) or your own corner radius, density, fonts, toolbar and price tags, on light and dark themes.
83
+ </td>
84
+ </tr>
85
+ </table>
86
+
87
+ ## Why TradeCanvas?
88
+
89
+ Most chart libraries make you choose: pretty charts with no trading features, or trading features with an ugly API. TradeCanvas gives you both.
90
+
91
+ - **95 built-in indicators** — SMA, EMA, TEMA, VWMA, Hull MA, RSI, MACD, Bollinger, Envelope, Ichimoku, Pivot Points, Anchored VWAP, ZigZag, Linear Regression Channel, Awesome / Chaikin Oscillator, and more. Any indicator can read another one's line (an SMA of RSI). No separate calculation library needed.
92
+ - **69 drawing tools** — Trendlines (info line, trend angle, cross line), Fibonacci (retracement, extension, channel, time zones, speed resistance fan and arcs, circles, spiral, wedge), horizontal/vertical lines, channels, pitchforks and pitchfan, Gann fan / box / square, cycles, harmonic patterns (XABCD, cypher, ABCD, three drives, head and shoulders), Elliott waves, notes, callouts and marks, brush and path, forecast and projection, Long/Short Position with position sizing, Volume Profile range. Each with its own settings, alerts on trend lines, groups and layers, undo/redo and full serialization.
93
+ - **18 chart types** — Candlestick, line, area, bar, hollow candle, baseline, High-Low, Heikin-Ashi, Renko, Kagi, Line Break, Point & Figure, Range Bars, Volume Candles, **Equivolume**, HLC Area, Step Line, Line+Markers. Renko's box, Kagi's reversal and the like are yours to set.
94
+ - **Pro-grade interaction** — pan freely past the last bar into empty future space (drawings can go there too), drag the price/time axes to scale, double-click to auto-fit, `Ctrl/⌘+drag` to select several drawings (then move, restyle or delete them together), `Shift+drag` to measure (bars × price Δ × %), `Alt+click` to pin a comparison tooltip, context cursors (crosshair, grabbing hand, resize arrows), axis-following price/time pill labels under the cursor, bar-hover highlight.
95
+ - **Trading overlay** — Render open positions with entry line, P&L zone, and SL/TP markers. Orders as dashed lines. Drag SL/TP to modify, cancel / close / reverse from the buttons on each line, and see every fill marked on its bar. ChartWidget adds an order ticket that checks the order as you fill it in, and an account panel with positions, working orders and history. Cleanly opt-out via `features.trading: false` for non-trading projects.
96
+ - **Real-time streaming** — Built-in Binance, Coinbase, Bybit, and Kraken adapters, plus generic `WebSocketAdapter` / `PollingAdapter` bases so any feed plugs in with ~20 lines. Older bars load as you scroll back, any interval (`7m`, `90m`, `2d`) is built from the feed's own, tick charts (`100T`) from its trades, and symbol search and quotes come from the feed.
97
+ - **Time zones** — any IANA zone with daylight saving time (`'America/New_York'`), a fixed offset, or the exchange's own zone, for the axis, crosshair, day breaks and session hours.
98
+ - **16 languages** — `ChartWidget` in English, Vietnamese, Simplified and Traditional Chinese, Japanese, Korean, Spanish, Portuguese, French, German, Russian, Turkish, Indonesian, Thai, Arabic and Hebrew; Arabic and Hebrew mirror right to left.
99
+ - **Accessible** — keyboard navigation, zoom and scroll buttons over the chart, and a screen-reader summary that reads the view and the bars one at a time.
100
+ - **Live execution** — connect an `ExecutionAdapter` to turn the trading overlay into a real trading surface, drag on the chart to create orders, and reconcile fills. Ships a `PaperExecutionAdapter` sandbox.
101
+ - **Plugin SDK** — register custom indicators, drawing tools, chart types, and overlays — globally or per-chart.
102
+ - **Strategy backtester** — `@tradecanvas/analytics` ships a bar-by-bar `Backtester` with virtual fills, commission/slippage models, portfolio tracking, and risk metrics (Sharpe, Sortino, Calmar, max drawdown). **Now with 4 ready-to-use reference strategies + Monte Carlo path-dependence analysis.**
103
+ - **Replay mode** — replay the chart's own bars from any point, in finer steps if you like (an hourly chart forming from 5-minute bars), with play / pause / step / seek / speed, and paper-trade on the replayed prices. The widget has a replay bar for it; `ReplayController` drives bars headless too.
104
+ - **Alerts** — on a price level, an indicator line, a drawing, or one line crossing another; on a move of some percent within some bars; only on closed bars; with an expiry. The widget's alerts panel sets all of them.
105
+ - **Compare and spread** — other symbols in percent on the price scale, on a scale or pane of their own, or as a spread or ratio, lined up with the chart by time.
106
+ - **Price formats** — prices in your own format or in fractions of a point (a bond in 32nds: 110'165) on every label; times your way; extended hours on or off; data export with the indicator lines.
107
+ - **Volume Profile** — optional horizontal histogram of traded volume bucketed by price over the visible range, with point-of-control highlighting.
108
+ - **Watchlists and symbol info** — lists of symbols to switch between, edit and reorder, with live quotes; a symbol panel with price, the market's status, the day's numbers, hours and news.
109
+ - **CSV / JSON drag-and-drop** — drop a file onto the chart, it parses and loads instantly. Detects header layouts, ISO/unix-s/unix-ms timestamps, and array-vs-object JSON shapes.
110
+ - **Named layouts** — save the chart under a name (symbol, interval, scale, indicators, drawings, alerts), open, rename, delete, auto-save the open one, `Ctrl/⌘+S`. Kept in the browser, or on your server through a four-call `LayoutStorage`. Per-symbol auto-persistence (`persistLayouts`) is there too.
111
+ - **Multi-chart** — `ChartWidgetGrid` puts up to six full widgets side by side, linked by symbol, interval, crosshair, time or drawings as you choose, and saves them as one layout. `ChartGrid` does the same for bare charts.
112
+ - **Signal markers & trade zones** — render bot/algorithm output (directional arrows, entry→exit rectangles) as a first-class chart layer.
113
+ - **Hotkey sheet** — press `?` in the widget to open a categorized keyboard-shortcut reference.
114
+ - **Extensible widget** — add your own toolbar buttons and right-click menu entries (`addToolbarButton`, `chartMenuItems`).
115
+ - **Save/load chart state** — Persist drawings, indicators, theme, and chart type to JSON. Restore with one call.
116
+ - **Zero dependencies** — The entire library is self-contained. No `d3`, no `chart.js`, no `fancy-canvas`.
57
117
 
58
118
  ## Headless Chart
59
119
 
@@ -96,14 +156,14 @@ chart.connect({ adapter, symbol: 'BTCUSDT', timeframe: '5m', historyLimit: 300 }
96
156
  | `fullscreen` | `boolean` | `true` | Fullscreen button in the toolbar |
97
157
  | `symbols` | `string[]` | BTC/ETH/SOL/BNB | Searchable symbol catalog |
98
158
  | `timeframes` | `TimeFrame[]` | 1m to 1M | Timeframes on offer; pin favourites from the ▾ menu |
99
- | `chartTypes` | `ChartType[]` | 11 types | Available chart types |
159
+ | `chartTypes` | `ChartType[]` | 18 types | Available chart types |
100
160
  | `watchlist` | `boolean` | `false` | Right-side watchlist sidebar |
101
161
  | `dragDropImport` | `boolean` | `true` | Drop CSV / JSON files onto the chart to load data |
102
162
  | `persistLayouts` | `boolean \| { keyPrefix, debounceMs }` | `false` | Save per-symbol indicators / drawings / chart type to localStorage |
103
163
  | `onSymbolChange` | `(symbol) => void` | — | Symbol change callback |
104
164
  | `onTimeframeChange` | `(tf) => void` | — | Timeframe change callback |
105
165
  | `onReady` | `(chart) => void` | — | Fired when chart is ready |
106
- | `locale` | `string` | `'en'` | UI chrome language — built-in `'en'` / `'vi'`, see **Widget i18n** below |
166
+ | `locale` | `string` | `'en'` | UI language — `'en'` and `'vi'` built in, 12 more from the locales entry, see **Widget i18n** below |
107
167
  | `messages` | `Partial<Record<MessageKey, string>>` | — | Override or add individual UI strings on top of `locale` |
108
168
 
109
169
  ### Icons
@@ -119,25 +179,25 @@ button.innerHTML = createToolIcon('fibRetracement', 16)
119
179
 
120
180
  ### Widget i18n
121
181
 
122
- `locale` and `messages` translate `ChartWidget`'s own chrome — toolbar, watchlist, indicator-picker section headers (Popular/All, overlay/panel tags), status bar, settings panel (titles/tabs/section headers), and hotkey sheet (title/group headers). Set at construction; not currently hot-swappable at runtime.
182
+ `ChartWidget` speaks 16 languages: English, Vietnamese, Simplified and Traditional Chinese, Japanese, Korean, Spanish, Portuguese, French, German, Russian, Turkish, Indonesian, Thai, Arabic and Hebrew (the last two right to left; `dir` sets the direction yourself). Every string it shows is translated: toolbar, settings, drawing tools, alerts, dialogs, the command palette, the hotkey sheet and notices. Indicator names (SMA, RSI…) stay as they are. Set at construction.
183
+
184
+ English and Vietnamese are built in. The others load from `@tradecanvas/chart/widget/locales`, so a page ships only the languages it imports:
123
185
 
124
186
  ```ts
187
+ import { ja } from '@tradecanvas/chart/widget/locales'
188
+
125
189
  new ChartWidget(el, {
126
- locale: 'vi', // built-in Vietnamese table
127
- messages: { 'watchlist.title': 'Theo dõi' }, // override/add individual keys — always wins
128
- chartOptions: { numberLocale: 'vi-VN' }, // separate: number/date formatting (see below)
190
+ locale: 'ja',
191
+ messages: ja, // or registerWidgetLocales() for all of them
192
+ chartOptions: { numberLocale: 'ja-JP' }, // separate: number/date formatting (see below)
129
193
  });
130
194
  ```
131
195
 
132
- `locale`/`messages` only cover chrome **text**; they're independent of `chartOptions.numberLocale`, which controls number/date **formatting** (price axis, legend, watchlist prices, current-price tag, session-break dates) via `Intl`/`toLocaleString`.
196
+ `messages` also overrides single keys on top of `locale` (`{ 'watchlist.title': 'Theo dõi' }`). A locale with a region falls back to its language (`ja-JP` → `ja`; `zh-TW` → Traditional Chinese).
133
197
 
134
- Not yet covered by `locale` (still English; PRs welcome, or override via `messages`/your own CSS):
135
- - Indicator and drawing-tool **names** (SMA, Bollinger Bands, Trend Line, …) — these come from `widgetConfig.ts`'s data tables, not the message catalog.
136
- - Individual settings rows beyond the tab/section level (e.g. "Up Body", "Grid Lines").
137
- - Individual hotkey-sheet shortcut labels and key-cap text (group titles are translated).
138
- - Alerts panel, symbol search, command palette, data window, depth ladder, bracket bar, replay bar, drawing-style panel, object tree.
198
+ `locale`/`messages` cover the **text**; `chartOptions.numberLocale` controls number and date **formatting** (price axis, legend, watchlist prices, current-price tag, session-break dates) via `Intl`.
139
199
 
140
- See `packages/library/src/widget/i18n.ts` for the full key list (`MessageKey`) and the English/Vietnamese tables.
200
+ See `packages/library/src/widget/locales/en.ts` for the full key list (`MessageKey`).
141
201
 
142
202
  ### Widget vs Headless
143
203
 
@@ -150,6 +210,17 @@ See `packages/library/src/widget/i18n.ts` for the full key list (`MessageKey`) a
150
210
  | Customization | Full control | Toggle sections on/off |
151
211
  | Advanced access | Direct API | `widget.getChart()` for direct API |
152
212
 
213
+ ### Widget Look
214
+
215
+ The widget's shapes and sizes — corners, control heights, type, borders, shadows, how a chosen button shows, bars docked or floating — are a look of their own, apart from the colours. Three presets: **Studio** (the default), **Terminal** (dense and square) and **Capsule** (pills, floating bars). Start from one and change what you like:
216
+
217
+ ```ts
218
+ const widget = new ChartWidget(host, { ui: 'terminal' });
219
+ widget.setUI({ preset: 'studio', radius: { md: 10 }, density: 'compact', toolbar: 'floating', active: 'solid' });
220
+ ```
221
+
222
+ The chart's price tags take the same corners (`tagRadius`; on a bare `Chart`, `chart.setShapes({ tagRadius })`). The widget loads no fonts: load the ones a look names. See [Styling](https://bonguynvan.github.io/tradecanvas/docs/styling).
223
+
153
224
  ### Widget Theming
154
225
 
155
226
  `ChartWidget`'s own chrome (toolbar, sidebars, settings panel, watchlist — everything *outside* the canvas) is styled entirely through CSS custom properties on `.tcw-root`, the widget's own root element. These are a **stable, documented contract**: additive-only across minor/patch releases — a property is never renamed or removed without a major version bump. Override them from the host page; no build step or theme object needed.
@@ -189,12 +260,19 @@ See `packages/library/src/widget/i18n.ts` for the full key list (`MessageKey`) a
189
260
  | `--tcw-divider` | `rgba(255,255,255,.06)` | Hairline dividers |
190
261
  | `--tcw-ease` / `--tcw-ease-out` | cubic-bezier | Transition easing |
191
262
  | `--tcw-dur-fast` / `-normal` / `-slow` | `120ms` / `180ms` / `260ms` | Transition durations |
192
- | `--tcw-radius-sm` / `-base` / `-lg` / `-xl` | `4px` / `6px` / `10px` / `14px` | Corner radii — set to `0` for a square look |
263
+ | `--tcw-radius-xs` / `-sm` / `--tcw-radius` / `-lg` / `-xl` | `3px` / `5px` / `7px` / `11px` / `16px` | The corner scale — set to `0` for a square look |
264
+ | `--tcw-control-radius` / `--tcw-input-radius` / `--tcw-menu-radius` / `--tcw-dialog-radius` / `--tcw-panel-radius` / `--tcw-tooltip-radius` / `--tcw-tag-radius` / `--tcw-toast-radius` | from the scale | Each kind of part's corners |
265
+ | `--tcw-toolbar-h` / `--tcw-control-h` / `--tcw-control-h-sm` / `--tcw-icon` / `--tcw-sidebar-w` / `--tcw-menu-item-h` | `46px` / `30px` / `24px` / `18px` / `48px` / `30px` | Sizes |
266
+ | `--tcw-font` / `--tcw-font-size` / `--tcw-weight` / `--tcw-weight-strong` | `'Manrope', 'Inter', …` / `13px` / `500` / `600` | Type |
267
+ | `--tcw-label-case` / `--tcw-label-tracking` | `none` / `0em` | Small labels (section titles) |
268
+ | `--tcw-border-w` / `--tcw-sep-w` | `1px` / `0px` | Border width; rules between toolbar groups |
269
+ | `--tcw-menu-shadow` / `--tcw-dialog-shadow` / `--tcw-tooltip-shadow` | the elevation shadows | Shadows of menus, dialogs, tooltips |
270
+ | `--tcw-blur` / `--tcw-surface-opacity` | `0px` / `100%` | Frosted menus |
193
271
  | `--tcw-shadow-sm` / `-md` / `-lg` / `-xl` | box-shadow values | Elevation |
194
272
  | `--tcw-ring` | `0 0 0 2px rgba(242,169,59,.45)` | Focus ring |
195
273
  | `--tcw-font-mono` | `'JetBrains Mono', …` | Monospace font stack (price ladder, code) |
196
274
 
197
- Light theme (`[data-tcw-theme="light"]`) redefines the color group (`--tcw-bg*`, `--tcw-border*`, `--tcw-text*`, `--tcw-accent*`, `--tcw-hover-bg`, `--tcw-active-bg`, `--tcw-divider`, `--tcw-shadow*`) with its own defaults — override both selectors if you support both themes.
275
+ Light theme (`[data-tcw-theme="light"]`) redefines the color group (`--tcw-bg*`, `--tcw-border*`, `--tcw-text*`, `--tcw-accent*`, `--tcw-hover-bg`, `--tcw-active-bg`, `--tcw-divider`, `--tcw-shadow*`) with its own defaults — override both selectors if you support both themes. With the `ui` option set, the widget writes its look's variables on the element, so they win over your CSS; without it they stay yours to set.
198
276
 
199
277
  ## Features
200
278
 
@@ -233,8 +311,22 @@ const grid = new ChartGrid(document.getElementById('grid')!, {
233
311
  syncTimeAxis: true,
234
312
  })
235
313
 
236
- const adapter = new BinanceAdapter()
237
- grid.connectAll(adapter, ['BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT'], '5m')
314
+ // An adapter keeps one stream: give each chart its own
315
+ grid.connectAll(() => new BinanceAdapter(), ['BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT'], '5m')
316
+ ```
317
+
318
+ With the full widget on each chart, a bar to pick the arrangement and sync, and the whole grid saved as a named layout:
319
+
320
+ ```typescript
321
+ import { ChartWidgetGrid } from '@tradecanvas/chart/widget'
322
+
323
+ const workspace = new ChartWidgetGrid(document.getElementById('grid')!, {
324
+ layout: '1x2',
325
+ adapter: () => new BinanceAdapter(),
326
+ cells: [{ symbol: 'BTCUSDT' }, { symbol: 'ETHUSDT', timeframe: '1h' }],
327
+ sync: { crosshair: true, interval: false, symbol: false, time: false, drawings: false },
328
+ })
329
+ workspace.setSync({ time: true })
238
330
  ```
239
331
 
240
332
  Supported layouts: `'1x1'`, `'1x2'`, `'2x1'`, `'2x2'`, `'1x3'`, `'3x1'`, `'2x3'`, `'3x2'`.
@@ -300,13 +392,34 @@ gauge.setValue(85) // animates smoothly
300
392
 
301
393
  ### Indicators (built-in)
302
394
 
303
- **Overlay** (drawn on the price chart):
304
- SMA, EMA, Hull MA, Bollinger Bands, Keltner Channel, Donchian Channel, Ichimoku Cloud, Parabolic SAR, Supertrend, VWAP, Anchored VWAP, Pivot Points (Classic), ZigZag, Linear Regression Channel
395
+ 95 indicators — moving averages (SMA, EMA, WMA, Hull, DEMA, TEMA, ALMA, KAMA,
396
+ LSMA, McGinley, SMMA, MA Cross, MTF MA), bands and channels (Bollinger,
397
+ Keltner, Donchian, Envelope, Linear Regression), trend and stops (Ichimoku,
398
+ Supertrend, Parabolic SAR, Chandelier, Chande Kroll Stop, Alligator, ZigZag,
399
+ Fractals, Pivot Points), VWAPs and Volume Profile on the price pane; RSI, MACD,
400
+ Stochastic, ATR, ADX, CCI, OBV, MFI, Bollinger %B and BandWidth, Historical
401
+ Volatility, Ulcer Index and 40 more oscillators, volume and volatility
402
+ indicators in panes. The [indicator catalog](https://bonguynvan.github.io/tradecanvas/docs/indicators)
403
+ lists every id with its inputs, lines and levels.
305
404
 
306
- **Panel** (separate sub-chart):
307
- RSI, MACD, Stochastic, ATR, ADX, CCI, CMF, MFI, OBV, ROC, TSI, Williams %R, Awesome Oscillator, Chaikin Oscillator, Volume Profile, VROC, Standard Deviation, Accumulation/Distribution, Aroon
405
+ ```typescript
406
+ import { indicatorSource } from '@tradecanvas/chart'
308
407
 
309
- All indicator parameters are validated at runtime — invalid values (NaN, Infinity, non-numeric strings, missing keys) fall back to documented defaults instead of silently propagating to calculations.
408
+ const rsi = chart.addIndicator('rsi', { period: 14 })!
409
+ chart.addIndicator('ema', { period: 21, source: 'hlc3' }) // another price
410
+ chart.addIndicator('sma', { period: 9, source: indicatorSource(rsi, 'value') }) // RSI's own average, in RSI's pane
411
+ chart.setIndicatorLevels(rsi, [20, 50, 80])
412
+ ```
413
+
414
+ - **Sources**: close, open, high, low, hl2, hlc3, ohlc4, hlcc4, or another indicator's line.
415
+ - **Panes**: one value scale per pane for lines, levels, axis and crosshair; move an indicator into another pane, a new one or back to the price pane; fold, maximise and reorder panes (`moveIndicatorToPane`, `setPaneCollapsed`, `setMaximizedPane`, `movePane`).
416
+ - **Undo and templates**: Ctrl/Cmd+Z undoes indicator changes, in the same history as drawings; ChartWidget saves the indicators as named templates (`getIndicatorSetup` / `applyIndicatorSetup`).
417
+ - **Levels**: editable per instance (RSI 30/70, CCI ±100 …), kept in saved layouts.
418
+ - **Value tags**: each line's latest value on its axis, in its colour.
419
+ - **Custom indicators** declare their lines (`plots`), scale, levels and inputs; the chart draws and labels them.
420
+
421
+ Invalid parameters (NaN, Infinity, non-numeric strings, missing keys) fall back
422
+ to the defaults instead of reaching the calculations.
310
423
 
311
424
  ### Drawing Tools
312
425
 
@@ -360,6 +473,11 @@ chart.setTradingConfig({
360
473
  // Listen for user drag-to-modify
361
474
  chart.on('positionModify', (e) => console.log('SL/TP moved:', e.payload))
362
475
  chart.on('orderModify', (e) => console.log('Order moved:', e.payload))
476
+
477
+ // The × and ⇅ buttons on the lines raise these; so can your own UI
478
+ chart.cancelOrderIntent('order-1')
479
+ chart.reversePositionIntent('pos-1')
480
+ chart.on('executionFill', (e) => console.log(e.payload.reason, e.payload.pnl))
363
481
  ```
364
482
 
365
483
  ### Signal Markers
@@ -427,43 +545,91 @@ chart.updateLastBar(updatedBar)
427
545
  chart.setCurrentPrice(3500.42)
428
546
  ```
429
547
 
430
- ### Web Worker indicator pipeline
548
+ **Built-in adapters** (all free, no API key): `BinanceAdapter`, `CoinbaseAdapter`, `BybitAdapter`, `KrakenAdapter`, plus `MockAdapter` for offline/testing.
431
549
 
432
- Heavy charts (1,000+ bars × 10+ indicators) can stutter when `calculate()` runs on the main thread. `IndicatorWorkerHost` offloads calculation to a worker so the render loop stays smooth.
550
+ ```typescript
551
+ import { BybitAdapter, KrakenAdapter, CoinbaseAdapter } from '@tradecanvas/chart'
552
+
553
+ chart.connect({ adapter: new BybitAdapter(), symbol: 'BTCUSDT', timeframe: '1m' })
554
+ chart.connect({ adapter: new KrakenAdapter(), symbol: 'BTC/USD', timeframe: '5m' })
555
+ chart.connect({ adapter: new CoinbaseAdapter(), symbol: 'BTC-USD', timeframe: '15m' })
556
+ ```
557
+
558
+ **Any feed in ~20 lines.** Extend `WebSocketAdapter` (live + REST history) or `PollingAdapter` (REST-only feeds) — the base handles the connection lifecycle, reconnect, decoding, and event emission. You supply a URL and a parse function:
433
559
 
434
560
  ```typescript
435
- import { IndicatorWorkerHost } from '@tradecanvas/core'
561
+ import { WebSocketAdapter } from '@tradecanvas/chart'
562
+
563
+ const myAdapter = new WebSocketAdapter({
564
+ name: 'myexchange',
565
+ wsUrl: (c) => `wss://api.myexchange.com/ws/${c.symbol}@kline_${c.timeframe}`,
566
+ fetchHistory: (symbol, tf, limit) => fetch(`/candles?...`).then((r) => r.json()),
567
+ parseMessage: (raw) => ({ bar: toBar(raw), closed: raw.k.x }),
568
+ })
569
+ ```
570
+
571
+ ### Live Execution
436
572
 
437
- // Bundler-supported worker URL (Vite, webpack 5, esbuild, etc.)
438
- const worker = new Worker(
439
- new URL('@tradecanvas/core/dist/indicator.worker.js', import.meta.url),
440
- { type: 'module' },
441
- )
442
- const host = new IndicatorWorkerHost(worker, { timeoutMs: 30_000 })
573
+ Connect an `ExecutionAdapter` to turn the display-only trading overlay into a real trading surface. The chart routes its order/position intents into the adapter, and renders the authoritative `orders` / `positions` the adapter emits back — the **adapter is the single source of truth**. With no adapter connected, those intents stay plain events (backward-compatible).
443
574
 
444
- const output = await host.calculate(
445
- 'rsi',
446
- { id: 'rsi', instanceId: 'rsi-1', params: { period: 14 } },
447
- bars,
448
- )
575
+ ```typescript
576
+ import { PaperExecutionAdapter } from '@tradecanvas/chart'
449
577
 
450
- // Health check / cleanup
451
- await host.ping()
452
- host.terminate()
578
+ chart.connectExecution(new PaperExecutionAdapter({ markPrice: 64000 }))
579
+
580
+ // Drag-to-create an order, then confirm:
581
+ chart.startOrderDraft('buy') // draggable line at the latest close
582
+ chart.confirmOrderDraft() // emits orderPlace → adapter fills → chart renders the position
583
+ // chart.cancelOrderDraft()
584
+
585
+ // One channel for failures (adapter-reported or a failed command):
586
+ chart.on('executionError', (e) => toast(e.payload.message))
453
587
  ```
454
588
 
455
- No worker available (SSR, tests, or as a safety net)? Pass `null` and register fallback plugins for synchronous calculation:
589
+ Implement `ExecutionAdapter` (it mirrors `DataAdapter`) to wire a real broker / OMS: `placeOrder`, `modifyOrder`, `cancelOrder`, `modifyPosition`, `closePosition`, plus `orders` / `positions` / `fill` / `error` events. `PaperExecutionAdapter` is a virtual-fill sandbox for demos and tests. The order type of a drag-to-create order (limit vs stop) is inferred from where you drop the line relative to the current price.
590
+
591
+ ### Plugins — extend the chart
592
+
593
+ Register custom **indicators**, **drawing tools**, **chart types**, and **overlays** — globally (every chart created afterward inherits) or per-chart.
594
+
595
+ ```typescript
596
+ import { Chart, registerPlugin, IndicatorBase } from '@tradecanvas/chart'
597
+
598
+ class MyIndicator extends IndicatorBase { /* descriptor, calculate(), render() */ }
599
+
600
+ // 1) Global — available to every chart created afterward:
601
+ registerPlugin({ kind: 'indicator', plugin: new MyIndicator() })
602
+
603
+ // 2) Per-chart at construction:
604
+ const chart = new Chart(el, { plugins: [{ kind: 'overlay', plugin: myHeatmap }] })
605
+
606
+ // 3) Imperative on an instance:
607
+ chart.plugins.register({ kind: 'chartType', plugin: myCustomCandles })
608
+ chart.setChartType('my-custom-candles') // custom chart types render via the plugin
609
+ ```
610
+
611
+ | Plugin kind | Contract |
612
+ |---|---|
613
+ | `indicator` | `IndicatorPlugin` — `calculate()` + `render()` |
614
+ | `drawing` | `DrawingPlugin` — `render()` + `hitTest()` |
615
+ | `chartType` | `ChartTypePlugin` — `createRenderer()` + optional `transform()` |
616
+ | `overlay` | `OverlayPlugin` — `render(ctx, { viewport, data, theme })` on the `main` / `overlay` / `ui` layer |
617
+
618
+ ### Indicators outside the chart
619
+
620
+ `IndicatorWorkerHost` computes an indicator from bars with the same messages a
621
+ Web Worker would use. The worker script is not part of the published packages
622
+ yet; pass `null` and register the plugins to compute in place (SSR, tests,
623
+ scripts):
456
624
 
457
625
  ```typescript
458
626
  import { IndicatorWorkerHost, RSIIndicator } from '@tradecanvas/core'
459
627
 
460
628
  const host = new IndicatorWorkerHost(null)
461
629
  host.registerFallbackPlugin(new RSIIndicator())
462
- const output = await host.calculate('rsi', config, bars) // runs synchronously
630
+ const output = await host.calculate('rsi', { id: 'rsi', instanceId: 'rsi-1', params: { period: 14 } }, bars)
463
631
  ```
464
632
 
465
- Render still happens on the main thread (it needs `CanvasRenderingContext2D`). Only the heavy compute moves off-thread.
466
-
467
633
  ### Save / Load
468
634
 
469
635
  ```typescript
@@ -486,7 +652,7 @@ colours, visibility) and alerts, including alerts on indicator lines.
486
652
  ### Themes
487
653
 
488
654
  ```typescript
489
- import { DARK_THEME, LIGHT_THEME, DARK_TERMINAL } from '@tradecanvas/chart'
655
+ import { DARK_THEME, LIGHT_THEME, DARK_TERMINAL, volumeColor } from '@tradecanvas/chart'
490
656
 
491
657
  // Built-in presets: DARK_THEME, LIGHT_THEME, DARK_TERMINAL
492
658
  chart.setTheme(DARK_TERMINAL) // fintech terminal: #0E0E0E bg, #00FF87/#FF3B4D candles, monospace
@@ -496,6 +662,8 @@ chart.setTheme({
496
662
  ...DARK_THEME,
497
663
  candleUp: '#1fa874',
498
664
  candleDown: '#e8505b',
665
+ volumeUp: volumeColor('#1fa874'), // volume bars: the candle colour, see-through
666
+ volumeDown: volumeColor('#e8505b'),
499
667
  background: '#0a0a0f',
500
668
  })
501
669
  ```
@@ -508,6 +676,7 @@ chart.on('crosshairLeave', () => { /* the pointer left the plot */ })
508
676
  chart.on('drawingToolChange', (e) => { /* { tool } — null once a drawing is finished or cancelled */ })
509
677
  chart.on('indicatorUpdate', (e) => { /* { from } — indicator values recomputed from this bar on */ })
510
678
  chart.on('paneResize', (e) => { /* { instanceId, size } — an indicator pane was resized */ })
679
+ chart.on('indicatorChange', (e) => { /* { instanceId, change } — shown/hidden, restyled, levels, inputs or pane changed */ })
511
680
  chart.on('barClick', (e) => { /* { bar, barIndex, point } */ })
512
681
  chart.on('visibleRangeChange', (e) => { /* { from, to } — bar indices, not timestamps */ })
513
682
  chart.on('priceRangeChange', (e) => { /* { min, max } — visible price bounds */ })
@@ -559,6 +728,7 @@ Every gesture you'd expect from a desktop trading chart is built in:
559
728
  | Double-click price axis | Re-enable auto-scale |
560
729
  | Double-click time axis | Fit all data to viewport |
561
730
  | Wheel | Zoom around cursor |
731
+ | Drag a pane divider | Resize the indicator pane (`ns-resize` cursor on hover) |
562
732
  | `Shift` + drag | Measure ruler (bars × time × price Δ × %) |
563
733
  | `Alt` + click | Pin OHLC tooltip; live crosshair shows Δ to pinned bar |
564
734
  | Hover | Price + time pill labels follow on both axes |
@@ -610,8 +780,7 @@ console.log(result.equityCurve) // → feed into the chart via Equity
610
780
 
611
781
  Returns: `fills`, closed `trades`, `equityCurve`, `metrics` (Sharpe, Sortino, Calmar, CAGR, max drawdown, win rate, profit factor, expectancy). See the [live backtest demo](https://bonguynvan.github.io/tradecanvas/docs/analytics/).
612
782
 
613
- #### Strategy library (new in 0.9)
614
-
783
+ #### Strategy library
615
784
  Four drop-in reference strategies — each returns a `StrategyFn` ready to feed
616
785
  `Backtester.run()`:
617
786
 
@@ -629,8 +798,7 @@ bt.run(bars, smaCrossStrategy({ fastPeriod: 10, slowPeriod: 30 }))
629
798
  bt.run(bars, donchianBreakoutStrategy({ entryPeriod: 20, exitPeriod: 10 }))
630
799
  ```
631
800
 
632
- #### Monte Carlo path-dependence (new in 0.9)
633
-
801
+ #### Monte Carlo path-dependence
634
802
  Shuffle realised trade order N times to expose whether a strategy depends on
635
803
  lucky sequencing. Tight P5/P95 band = robust edge; wide band = path-dependent.
636
804
 
@@ -650,17 +818,17 @@ mc.worstMaxDrawdownPct
650
818
 
651
819
  | Feature | @tradecanvas/chart | lightweight-charts | chart.js | Highcharts Stock |
652
820
  |---|---|---|---|---|
653
- | Chart types | 17 + 6 finance | 4 | 8 (non-financial) | 10+ |
821
+ | Chart types | 18 + 6 finance | 4 | 8 (non-financial) | 10+ |
654
822
  | Finance charts | Sparkline, Depth, Equity, Heatmap, Waterfall, Gauge | None | None | Some |
655
- | Built-in indicators | 33 | 0 | 0 | ~30 |
656
- | Drawing tools | 24 | 0 | 0 | Some |
823
+ | Built-in indicators | 95 | 0 | 0 | ~30 |
824
+ | Drawing tools | 69 | 0 | 0 | Some |
657
825
  | Trading overlay | Full (pos + orders + drag) | None | None | None |
658
826
  | Real-time streaming | Built-in (Binance) | Manual | Manual | Built-in |
659
827
  | Save/load state | Yes | No | No | Yes |
660
828
  | Replay mode | Yes (`ReplayController`) | No | No | No |
661
829
  | Backtester | Yes (`@tradecanvas/analytics`) | No | No | No |
662
830
  | Multi-chart grid | Yes (`ChartGrid`) | No | No | Yes |
663
- | Bundle (gzip) | ~56 KB core | ~45 KB | ~70 KB | ~200 KB |
831
+ | Bundle (gzip) | ~100 KB core | ~45 KB | ~70 KB | ~200 KB |
664
832
  | Dependencies | 0 | 1 | 0 | 0 |
665
833
  | Widget (complete UI) | Yes (`ChartWidget`) | No | No | No |
666
834
  | License | MIT | Apache 2.0 | MIT | Commercial |
@@ -717,6 +885,8 @@ chart.setNumberLocale('de-DE') // 65.234,00
717
885
  | `saveState(key?)` | Serialize chart state |
718
886
  | `loadState(json)` | Restore chart state |
719
887
  | `screenshot()` | Download chart as image |
888
+ | `setRenderer(mode)` | Draw with `'canvas'` (default), `'webgl'` or `'auto'`; resolves to what draws now |
889
+ | `getRenderer()` | `'canvas'` or `'webgl'` |
720
890
  | `on(event, handler)` | Subscribe to events |
721
891
  | `destroy()` | Clean up all resources |
722
892
 
@@ -724,7 +894,7 @@ chart.setNumberLocale('de-DE') // 65.234,00
724
894
 
725
895
  ```typescript
726
896
  interface OHLCBar {
727
- time: number // Unix timestamp (seconds)
897
+ time: number // Unix time in ms or seconds (up to 1e12 is read as seconds); ascending
728
898
  open: number
729
899
  high: number
730
900
  low: number
@@ -737,9 +907,20 @@ interface OHLCBar {
737
907
 
738
908
  | Example | Description |
739
909
  |---|---|
740
- | [Live demo](https://bonguynvan.github.io/tradecanvas/) | Feature Lab: drawing tools, indicators, trading, replay, sub-cent prices + Vietnamese UI, 200k bars, slow-network switching — each on a live chart |
910
+ | [Live demo](https://bonguynvan.github.io/tradecanvas/) | Feature Lab: drawing tools, indicators, trading, ranges, paged history, replay, 16 languages with sub-cent prices, watchlists with live quotes, 200k bars, slow-network switching — each on a live chart. The site and docs are also in Vietnamese, Chinese, Japanese, Korean and Spanish |
741
911
  | [StackBlitz sandboxes](https://bonguynvan.github.io/tradecanvas/examples/) | One-click, forkable: vanilla `Chart`, `ChartWidget`, React / Vue / Svelte wrappers, finance charts |
742
- | [`@tradecanvas/react`](https://www.npmjs.com/package/@tradecanvas/react) · [`/vue`](https://www.npmjs.com/package/@tradecanvas/vue) · [`/svelte`](https://www.npmjs.com/package/@tradecanvas/svelte) | Framework components — reactive props, typed, zero boilerplate |
912
+ | [`@tradecanvas/react`](https://github.com/bonguynvan/tradecanvas/tree/main/packages/react/) · [`/vue`](https://github.com/bonguynvan/tradecanvas/tree/main/packages/vue/) · [`/svelte`](https://github.com/bonguynvan/tradecanvas/tree/main/packages/svelte/) | Framework components — reactive props, typed, zero boilerplate |
913
+
914
+ ## AI coding tools
915
+
916
+ - [`llms.txt`](https://bonguynvan.github.io/tradecanvas/llms.txt) and
917
+ [`llms-full.txt`](https://bonguynvan.github.io/tradecanvas/llms-full.txt) give
918
+ assistants the docs in one place.
919
+ - An agent skill, [`skills/tradecanvas`](https://github.com/bonguynvan/tradecanvas/blob/main/skills/tradecanvas/SKILL.md), teaches
920
+ coding agents to build with TradeCanvas: the entry points, the rules that
921
+ avoid most bugs, and worked examples that CI type-checks against the library.
922
+ Copy the folder into your project's `.claude/skills/` (or your agent's skills
923
+ folder) to use it.
743
924
 
744
925
  ## Browser Support
745
926
 
@@ -747,7 +928,23 @@ Chrome 80+, Firefox 80+, Safari 14+, Edge 80+
747
928
 
748
929
  ## Framework Integration
749
930
 
750
- TradeCanvas is framework-agnostic. The `Chart` class takes a DOM element and manages its own canvas layers.
931
+ Official wrapper components — reactive props, refs, zero boilerplate. Published at `1.x` alongside the core:
932
+
933
+ ```bash
934
+ npm install @tradecanvas/react # or @tradecanvas/vue · @tradecanvas/svelte
935
+ ```
936
+
937
+ ```tsx
938
+ import { TradeCanvas } from '@tradecanvas/react'
939
+
940
+ <TradeCanvas symbol="BTCUSDT" timeframe="5m" theme="dark" indicators={['rsi', 'macd']} />
941
+ ```
942
+
943
+ All three share the same prop surface and hand you the underlying `Chart` (for drawings, trading, execution, plugins) via `onReady` / ref / `bind:chart`. See the [frameworks docs](https://bonguynvan.github.io/tradecanvas/docs/frameworks).
944
+
945
+ ### Headless (own the lifecycle)
946
+
947
+ The `Chart` class also takes a DOM element directly — framework-agnostic:
751
948
 
752
949
  **React:**
753
950
 
@@ -840,6 +1037,60 @@ onUnmounted(() => chart?.destroy())
840
1037
  </script>
841
1038
  ```
842
1039
 
1040
+ ## Performance
1041
+
1042
+ A two-canvas Canvas2D pipeline: a hover repaints only the thin top canvas, never the scene. Five things keep large data fast:
1043
+
1044
+ - **LTTB downsampling** — line / area charts automatically downsample the visible range to ~2 points per pixel using Largest-Triangle-Three-Buckets when there are far more bars than pixels. The line stays visually identical while drawing dozens of times fewer points; a no-op at normal zoom. The `lttbDownsample` utility is exported for your own use.
1045
+ - **Indicators zoomed out** — below a pixel per bar, indicator lines, bands and histograms draw one span per pixel column instead of a stroke through thousands of points: much the same look for a fraction of the raster work (about 54 → 21 ms a frame zoomed out on 200,000 bars with four indicators, on integrated graphics). `node scripts/bench-render.mjs` measures it on your machine.
1046
+ - **Visible-range rendering** — every renderer iterates only the bars in view, never the whole series. Hover and pan frame cost stays flat from 500 to 100,000 loaded bars.
1047
+ - **Incremental indicators on live ticks** — a tick only changes the forming bar, so built-in indicators that implement `update()` (SMA, EMA, WMA, VWMA, Bollinger, Envelope, RSI, MACD, ATR, OBV, Stochastic) recompute just that bar instead of the whole history. Others fall back to a full recalculation. Custom plugins can opt in via `IndicatorPlugin.update`.
1048
+ - **Cheap full loads** — a symbol/timeframe switch recomputes every indicator once. Their per-bar `values` lookup is an `IndicatorValueMap` (array-backed while bars arrive in time order, ~3x cheaper to build than a `Map` keyed by timestamps), and `setData` reuses already well-formed bars instead of copying each one.
1049
+
1050
+ BB + EMA + RSI + MACD (`pnpm bench`, single core):
1051
+
1052
+ | History | Full recalculation (switch / `setData`) | Incremental `update()` (live tick) |
1053
+ |---|---|---|
1054
+ | 20,000 bars | ~5 ms | ~0.0005 ms |
1055
+ | 100,000 bars | ~27 ms | ~0.001 ms |
1056
+
1057
+ Downsampling throughput (`pnpm bench`, single core):
1058
+
1059
+ | Visible points → 1600 | Time / frame | Throughput |
1060
+ |---|---|---|
1061
+ | 10,000 | ~0.025 ms | 39,600 / s |
1062
+ | 100,000 | ~0.32 ms | 3,100 / s |
1063
+ | 1,000,000 | ~2.6 ms | 380 / s |
1064
+
1065
+ A 100k-bar line chart downsamples in ~0.3 ms — well inside a 16.6 ms frame budget — then draws ~62× fewer points (100k → 1600).
1066
+
1067
+ ### WebGL renderer (preview)
1068
+
1069
+ `renderer: 'webgl'` draws the plot and indicator panes with WebGL 2, on a canvas under the 2D scene: the grid, sessions, candles and volume directly, and the Canvas 2D drawing of indicators, compare lines and most chart types recorded as GPU strokes, fills and rectangles, antialiased at their edges as Canvas 2D is. Text, drawings, orders, axes and the crosshair stay on Canvas 2D, as does anything the GPU wouldn't draw the same (left to Canvas 2D in order, so the stacking doesn't change); custom indicator plugins come along without changes. Candles match Canvas 2D to within 2/255; lines and fills differ only on a few antialiased edge pixels. The WebGL code is a chunk of its own (about 17 KB gzipped), loaded on first use; where WebGL 2 is missing, or its context is lost, the chart carries on with Canvas 2D.
1070
+
1071
+ ```typescript
1072
+ const chart = new Chart(el, { renderer: 'webgl' }) // or 'auto': WebGL on a hardware GPU only
1073
+
1074
+ chart.on('rendererChange', (e) => console.log(e.payload))
1075
+ // { renderer: 'webgl' }, or { renderer: 'canvas', reason: 'unsupported' | 'contextLost' }
1076
+
1077
+ await chart.setRenderer('canvas') // resolves to what draws now
1078
+ ```
1079
+
1080
+ Frame time while panning, on integrated graphics (Intel UHD; 16.7 ms is 60 fps):
1081
+
1082
+ | Chart | Pixel ratio | Canvas 2D | WebGL |
1083
+ |---|---|---|---|
1084
+ | 1600×900, 500 candles + 4 indicators | 2 | 27.4 ms | 19.6 ms |
1085
+ | 1600×900, zoomed out on 200,000 bars + 4 indicators | 2 | 34.5 ms | 20.2 ms |
1086
+ | Six charts, 500 candles and two indicators each | 2 | 23.5 ms | 17.2 ms |
1087
+ | 2560×1400, 2,000 candles + 4 indicators | 1 | 41.6 ms | 17.7 ms |
1088
+ | 2560×1400, 2,000 candles + 4 indicators | 1.5 | 70.8 ms | 17.6 ms |
1089
+ | 2560×1400, 2,000 candles + 4 indicators | 2 | 114.5 ms | 29.1 ms |
1090
+ | 2560×1400, 2,000 candles | 2 | 33.1 ms | 20.9 ms |
1091
+
1092
+ Most WebGL frames above land on 16.7 ms; the averages carry a few longer ones. At a pixel ratio of 2 on a 2560×1400 chart, the browser's compositing of the full-size layers alone takes about 23 ms on this GPU. `node scripts/bench-render.mjs --renderer=webgl` runs these numbers on your own machine.
1093
+
843
1094
  ## Architecture
844
1095
 
845
1096
  Two stacked canvases — a hover repaints only the thin top one:
@@ -853,6 +1104,12 @@ Two stacked canvases — a hover repaints only the thin top one:
853
1104
 
854
1105
  - **[bo-grid](https://github.com/bonguynvan/bo-grid)** — tiny, fast **Svelte 5** data grid for fintech UIs: canvas sparklines, batched realtime cell updates, virtual scrolling, grouping / pivot / tree data, and Excel export, with a core that gzips to ~32 KB. The table half of the same toolkit — pair it with TradeCanvas for a full trading desk. **[Live demo](https://bonguynvan.github.io/bo-grid/)**
855
1106
 
1107
+ ## Contributing
1108
+
1109
+ Bug reports, ideas and pull requests are welcome. [CONTRIBUTING.md](https://github.com/bonguynvan/tradecanvas/blob/main/CONTRIBUTING.md) covers the setup (`pnpm install && pnpm build && pnpm test`), how the repo is laid out and what a pull request needs. Found a security issue? Please follow [SECURITY.md](https://github.com/bonguynvan/tradecanvas/blob/main/SECURITY.md) instead of opening an issue.
1110
+
1111
+ If TradeCanvas saves you time, a star on GitHub helps other developers find it.
1112
+
856
1113
  ## License
857
1114
 
858
- [MIT](./LICENSE)
1115
+ [MIT](https://github.com/bonguynvan/tradecanvas/blob/main/LICENSE)