変更履歴

チャート、ウィジェット、フレームワーク用コンポーネントの全リリースを新しい順に。

リリースノートは英語で書かれています。

未リリース

main に反映済み、次のリリースで公開7 件の変更

Collected on main for the next release. Not on npm yet.

One icon set, no emoji

  • Icons, not emoji. The alert line's label and the alert notice drew a bell emoji, the pinned tooltip a pushpin, trade zones ▲ and ▼, a favourite drawing tool ★, the palettes ⌕, ✓ and ⏎, close buttons ×, and the replay bar its own filled glyphs (now outlined, as the rest of the set). Emoji and symbol characters look different on every system and font; all of these now come from the TradeCanvas icon set, drawn the same everywhere at 1.75 px strokes on its 24 px grid.
  • The icon set moves to commons (UI_ICONS, DRAWING_TOOL_ICONS, CHART_TYPE_ICONS, iconSvg), so the chart's own canvas draws it too: drawIcon(ctx, icon, x, y, size, color) in core. New icons: pin, search, enter, step back and step forward.
  • widget.toast(message, kind, icon) takes an icon's name, shown before the text.
  • A test keeps emoji and symbol characters out of the sources.

Long ranges

  • The range bar shows all of a long range. A bar slot is never narrower than 0.25 px, so 5Y of daily bars, or All on decades of them, showed only the newest part. In the widget, a range the bars can't fit at 2 px each now switches to the timeframe they can: 5Y of days to weeks, All to months, a year of hourly bars to days. A short range goes back to the timeframe the user picked, and never finer. It only switches to timeframes the feed serves, or the bars on hand resample to; features: { 'statusBar.rangeTimeframe': false } keeps the timeframe.
  • minBarUnit (a chart option, or setMinBarUnit / getMinBarUnit) lets bar slots go from 0.25 px down to 0.02 px, so on a bare chart fitContent, zooming out and the 'All' range fit a long series, drawn a pixel column at a time. MIN_BAR_UNIT_LIMIT is exported.
  • The Vietnamese price limits are checked against integer arithmetic for every reference price from 1,000 to 300,000 dong on HOSE, HNX and UPCOM, and the VN30 futures, so a limit that falls exactly on a price step can't be rounded a step off.

1.26.0

コンポーネント 1.3.86 件の変更

Axes that read at every zoom

  • Time axis labels by the calendar. The axis labels the bars that start the largest calendar steps: a new year (in bold), a quarter or month, a day, a round hour or minute, at least 80 px apart, as 2024, Mar, 15, 13:00. At 5Y it reads 2022 · Jul · 2023 · Jul; on hourly bars over years it still shows the years, which it never did. The labels belong to bars, not to the screen: they move with their bars when panning and stay where they were when history is loaded in front, where they used to jump. Month names follow setNumberLocale; bars within a minute show their seconds (13:05:30), and labels wider than the spacing (a long month name, a formatter's own text) give way instead of running together. A time formatter now hears kind: 'year' | 'month' | 'day' | 'time'; 'date' is no longer given by the axis (deprecated): a daily bar's label is 'day', 'month' or 'year' by the step it starts.
  • The grid follows the labels. Its vertical lines are at the time axis's labels and its horizontal lines at the price scale's, on the 2D grid and the GPU's alike; they could fall between them before.
  • Price labels fit the height. The price scale and the indicator panes fit as many labels as their height does, at least 30 px apart: a short pane no longer stacks eleven labels, a tall chart no longer shows eight.
  • Log scale. Its labels step with the price, so the lower part of the scale is labelled as well as the top (from 100 to 120,000 only the top quarter was, with labels overlapping). Autoscale pads a log scale by ratio (padPriceRange), so a series that rose more than about 13 times no longer drops to a linear scale when the padding went below zero.
  • Percent and indexed scales label round percents (-5.00%, 0.00%, +5.00%) and round index points from the baseline, not prices turned into odd percents.
  • Session breaks zoomed out. Their lines keep 6 px apart, the less significant giving way, and their labels (years, then months, then weeks) no longer pile up into a smear.

1.25.0

コンポーネント 1.3.77 件の変更

Dates on the time axis

  • Right dates far back in history. A series' time unit, milliseconds or seconds, is now decided once from its newest bar (barTimeUnit(data)) instead of guessed for each time. Millisecond bars before September 2001 are below 1e12 and were read as seconds, so after a 5Y view a scroll back dated them around the year 32,000: on the time axis, the crosshair, the tooltips, the measure tool, session breaks, data export and CSV import. barTimeUnit and MS_TIME_THRESHOLD are exported, and normalizeBarTime(time, unit) takes the series' unit.
  • The time axis leaves the space before the oldest bar unlabelled (the bars there are not loaded yet), and shows the date wherever the date changes: a label a month later on the same day of the month showed only a time.
  • Times before the oldest bar (the crosshair, drawings placed there) follow the average spacing of the first bars, weekends and nights included, so 50 daily bars back is about ten weeks, not 50 days.
  • Renko, Kagi, Point & Figure and Line Break: setVisibleRange, the zoom area and fitContent work on the bricks shown, not on the bars under them, and the crosshair reads the brick under it: on these types crosshairMove now gives the brick and its index in the series drawn (it gave the data bar at that index, which was another bar). Heikin-Ashi and the other one-bar-per-bar types still give the data bar.
  • The legend's change on hover is from the bar before the hovered one; it was from the series' last bars.
  • Drawings saved in seconds before 2001 no longer pass for old bar-index anchors.
  • A bar or tick in the other unit than its series (a stream in milliseconds on bars in seconds) is stored in the series' unit, so it can't make the series read as that unit.

1.24.0

コンポーネント 1.3.63 件の変更

Drawings and the legend

  • A toolbar over the selected drawing. Clicking a drawing in the widget shows a small toolbar right over it: colour, line width and line style, then settings, an alert on its line, lock, the full drawing menu and delete. Nothing hides behind a right-click any more. With several drawings selected it sits over all of them and changes each. It follows the drawing while it is moved, panned, zoomed or rescaled, steps aside while a drawing tool, the eraser or the zoom area is on, goes when nothing is selected, and works with the keyboard (one tab stop, arrow keys along it and through the pickers, Escape back to it). Colours, widths and line styles from saved layouts are checked before they are shown. features: { selectionToolbar: false } turns it off.
  • chart.getDrawingRect(id) gives the box a drawing covers on screen, cut to the plot (lines across the whole plot span it), or null when it is hidden or off screen: for hosts that put their own controls or notes over a drawing.
  • The OHLCV legend takes a fontFamily (chart.setLegend({ fontFamily }), the theme's font by default). Its volume and indicator rows are drawn at the OHLC size, and each value keeps its place while its digits change width, so the row no longer jitters on live ticks. In the widget the legend follows the look's font, at the size of the indicator rows listed under it.

1.23.0

コンポーネント 1.3.53 件の変更

Candlestick patterns

  • detectCandlePatterns(bars, options) finds 64 patterns of one to five bars, each on the bar it ends on: dojis, hammers, shooting stars, marubozu and belt holds; engulfing, harami, piercing line and dark cloud cover, tweezers, kicking, counterattack, necks and separating lines; morning and evening stars, abandoned babies, three white soldiers and black crows, three inside and outside, two crows, tri-stars, tasuki gaps, stick sandwich, advance block; three-line strikes, rising and falling three methods, mat hold, breakaways, concealing baby swallow, ladder bottom. Reversals count only after the trend they reverse; bodies are long or short against the average body before. CANDLE_PATTERNS lists them with names, short labels, direction and kind.
  • The candlepatterns indicator (134 indicators in all) draws an arrow under each bullish pattern and over each bearish one, with its short name once the bars are wide enough; a live bar recomputes only the last bars. Reversals, continuations and indecision can be turned on and off.
  • Docs: the Indicators page in six languages; a Feature Lab scene on Vietnamese stocks with the patterns, the Psychological Line and Volume Ratio.

1.22.0

コンポーネント 1.3.45 件の変更

Indicators from Asian price boards

22 more indicators, 133 in all, in the widget's indicator list too:

  • Sentiment and volume: Psychological Line (psy, with 25 and 75 marked) and New Psychological Line (newpsy), Volume Ratio (vr), AB Ratio (abratio, A and B lines), Intraday Intensity in percent (iii), Volume vs Average (volpct), Volume Change (volchange, each bar coloured against the one before), Trade Value (tradevalue, close × volume as an estimate of the value traded), Negative and Positive Volume Index (nvi, pvi, with an EMA signal).
  • Trend and momentum: Sonar with its signal (sonar), Sigma, the close in standard deviations from its average (sigma), Binary Wave, four trend votes from −4 to 4 (binarywave), Smoothed Rate of Change (sroc), Vertical Horizontal Filter (vhf), R-Squared (rsquared), Random Walk Index (rwi), True Range (tr).
  • On the price pane: Time Series Forecast (tsf), Weighted Close (wclose), the DeMark projected high and low for each bar (demark), and a moving-average Rainbow of up to 20 lines from a first period by a step (rainbow).

Counter-clock chart

  • CounterClockChart: average price against average volume, bar by bar, joined in time order and fading with age, with no time axis. getPhase() and counterClockPhase(points) name the last move's direction in eight phases, counter-clockwise from volume rising; counterClockPoints(bars, period) gives the points. Tooltip, onPointClick, a screen-reader label, dark and light themes.
  • Docs: the Finance charts page and the Indicators page in six languages; the site's finance section shows the chart.

1.21.0

コンポーネント 1.3.310 件の変更

Charts for dashboards

  • BarChart: values by category, series side by side (mode: 'grouped') or stacked with positives up and negatives down from zero, upright or sideways (orientation: 'horizontal'), coloured by sign for net flows (colorBySign), values on the bars (showValues). Hovering a category shows each series' value; onBarClick gets the category, series, value and index. Labels that don't fit along the bottom show every few categories.
  • DonutChart: parts of a whole clockwise from twelve o'clock, a pie with innerRadius: 0, a caption and figure in the hole, each slice's share where it has room, a legend beside or under the ring; onSliceClick.
  • ScatterChart: points on two value axes, bubbles whose area follows size, axis titles, labels, lines at zero; the axes leave room for the largest bubble; onPointClick.
  • HistogramChart: values counted into bins (bins, binWidth on a grid from 0, or Sturges' rule), coloured by sign, with labelled marker lines (a mean, a VaR) that move a row down when they would overlap. histogramBins(values, options) is exported, and niceScale(min, max) for axes of your own.
  • All four follow the pointer with a tooltip, describe themselves to screen readers (an image role and a label, ariaLabel in your words) and draw in the dark or light theme; setOptions, update, setTheme, destroy. The other finance charts' canvases get the image role and setLabel too.
  • CalendarChart: a value a day, YYYY-MM-DD, in week columns and weekday rows, a calendar year to a band and ten years at most (the oldest give way on a short chart); Monday to Friday with weekdays: 5, weeks from Sunday with weekStart: 0, month and day names in locale, a colour bar under it; onDayClick.
  • MatrixChart: a coloured value for each row and column, square cells with the value printed where it fits, column names turned when they don't fit, half of a square matrix with triangle: 'lower' | 'upper'; onCellClick. correlationMatrix(series) gives Pearson correlations, pairing the positions both series have.
  • Market map by sector: HeatmapChart's grouped: true gathers cells by group, each group in a tile sized by its weights under its name and weighted change. The heatmap now describes itself to screen readers too (ariaLabel in your words).
  • ColorScale is a type of its own, shared by the heatmap, calendar and matrix; a colour left out keeps the chart's default (the theme's up and down colours on the newer charts).
  • Docs: the Finance charts page rewritten in six languages with the classes as they are (it showed renderer classes that don't exist), with the calendar, the matrix and the sector map; the site's finance section shows all seven new charts.

1.20.0

コンポーネント 1.3.214 件の変更

Vietnamese markets

Checked against the exchanges' rules of May 2025: the HOSE trading rules of 26 April 2025 and the HNX, UPCoM and VN30 futures rules.

  • Price steps by price band: MarketConfig.priceSteps: [{ from, step }]. HOSE shares step 10 dong below 10,000, 50 dong to 49,950 and 100 dong from 50,000; priceStepAt(price, market) and roundToPriceStep(price, market, 'nearest' | 'down' | 'up') read them.
  • Ceiling and floor as the exchanges set them: computePriceLimits rounds the ceiling down and the floor up to a valid price; a limit that would land on the reference moves one step off it, and a reference of one step keeps the floor there. chart.getPriceLimits() gives the day's prices.
  • Presets: MARKET_HOSE (±7%, lots of 100, sessions from the 9:00 opening auction to the 14:30 closing one), MARKET_HOSE_ETF (ETFs and covered warrants, 10 dong at every price), MARKET_HNX (±10%, a closing auction and a post-close session to 15:00), MARKET_UPCOM (±15%, continuous trading 9:15–11:30 and 13:00–14:30) and MARKET_VN30F (VN30 index futures: 0.1 a point, ±7%, 100,000 dong a point, from the 8:45 opening auction). Each names timeZone: 'Asia/Ho_Chi_Minh'. Prices are in thousands of dong, as price boards show them; scaleMarketPrices(MARKET_HOSE, 1000) reads them in dong.
  • VN30 futures: vn30fLastTradingDay(year, month, isHoliday?) (the third Thursday, earlier when that is a holiday) and vn30fContracts(now) (this month's, the next, and the last months of the two quarters after: VN30F2611…).
  • Sessions on the exchange's clock: getCurrentSession(sessions, now, timeZone), by the time of day (weekends and holidays are the caller's); without a zone it reads this computer's clock, as before, and a zone it doesn't know gives null. Sessions can be postClose, and markets futures. The chart's session shading still comes from setSymbolInfo.
  • The chart follows the band: with a market set, chart.roundPrice and chart.getPriceStep(price?) use the step of the price's band (at the last close without a price), so prices from the chart's menus and the "+" by the price axis are valid ones. A symbol's minTick still comes first.
  • Order ticket: with a market set, the widget's ticket keeps the price, stop-loss and take-profit on the market's step and the order's price between the day's floor and ceiling, starts at one lot, and above one lot takes whole lots (fewer shares are an odd-lot order of their own). The three messages are in the widget's 30 languages.
  • Docs: the API page's Markets section and the Trading page, six languages; a Feature Lab scene with HPG, FPT and a VN30F contract.

Looks different after the update

  • VN_COLORS and createVNTheme use the price board's colours: green up, red down, purple ceiling, cyan floor, yellow reference. They were red up and blue down.
  • MARKET_HOSE trades in lots of 100 (it said 10), HNX and UPCoM start continuous trading at 9:15, and UPCoM has no closing auction.
  • MARKET_NYSE's after-hours session is postClose (it was preClose), and the preset names timeZone: 'America/New_York'.

Fixes

  • chart.setPriceLimits changed the market object it was given, so every chart sharing a preset got the same reference price. It now keeps its own copy.

Project

  • npm provenance: releases are published with provenance, so npm shows the workflow run that built each version.
  • SECURITY.md names the supported releases as the latest 1.x of each package, instead of version numbers that went stale.

1.19.1

コンポーネント 1.3.1

Preview builds: every pull request and every commit on main is published to pkg.pr.new (npm install https://pkg.pr.new/@tradecanvas/chart@<pull request or commit>), so a change can be tried before it is released. Shorter READMEs, in all six languages: what the library does, install, a quick start, frameworks, and links into the docs, which keep the API in detail. The npm page follows.

1.19.0

コンポーネント 1.3.04 件の変更

A frame on request, and overlays switched off

  • chart.requestRender() draws a frame soon, though nothing the chart knows of changed: after a plugin's own setting changed (an overlay's display mode, say), in a quiet market with no ticks to redraw it. The frame refits the scales to the data as a tick's would; requests before it make one frame, and a destroyed chart ignores them.
  • enabled: false on an overlay plugin leaves it registered but undrawn; it is read every frame, so switching it and calling requestRender() shows the change at once.
  • options on the React, Vue and Svelte components: chart options the props don't cover (maxBarSpacing, rightMargin, renderer…), merged over the component's defaults at mount; chartType, theme and autoScale still come from their props. A footprint chart's wide bars need a larger maxBarSpacing than the default 30.
  • Docs: the Plugins and Frameworks pages, six languages; the agent skill's overlay recipe.

1.18.1

コンポーネント 1.2.61 件の変更

Fixes

  • No made-up times beside tick bars: on a tick timeframe ('100T') with a few bars, the empty space left of the first bar was labelled with times extrapolated from the bars' spacing ("01:44, 03:02…" before a market that opens at 9:00), and the crosshair showed one there too. Tick bars are not evenly spaced in time, so the time axis and the crosshair now give times to the bars only. The same holds on Renko, Kagi, point & figure, line break and range-bar charts. Time timeframes still label the empty future right of the newest bar. The Realtime page says so, in six languages.

1.18.0

コンポーネント 1.2.55 件の変更

Prices on the market's grid, and a scale for plugins

  • The drawing settings' Coordinates tab shows prices on the market's grid: a point dragged to 534.86074226 reads 534.75 with a step of 0.25, or 22,000 on a stock that moves in 10 dong, and an edited price lands on the grid. A point you don't edit keeps its exact place. The field's arrows move by the price step.
  • chart.getPriceStep(): the smallest step prices move in, the one roundPrice rounds to: the symbol's minTick, a fraction's unit (priceFormat: { denominator: 32 }), else one unit of the decimals prices show.
  • overlayScale(context) for overlay plugins: in render(ctx, context), it places things where the chart draws them: timeToX / xToTime by bar time (between bars and past the newest in proportion), indexToX / xToIndex, priceToY / yToPrice on a log or inverted scale too, barWidth, and visible, the bars on screen (type FrameScale). Its bars are those of context.data, the series on screen: a Renko or Kagi chart's bricks, not the feed's bars. The plugin contracts don't change.
  • The scale functions are exported from @tradecanvas/chart for renderers that get the viewport alone (an indicator's own render, a chart type's renderer): priceToY, priceToYMapper, yToPrice, barIndexToX, xToBarIndex, timeToX, xToTime, timestampToBarIndex.
  • Docs: the Plugins page shows an overlay drawn with overlayScale, and the API page getPriceStep, six languages; a recipe in the agent skill.

1.17.0

コンポーネント 1.2.43 件の変更

The price scale in the symbol's decimals, and symbol details learned later

  • The price scale follows the symbol's precision: its labels took the decimals of the visible range ("22,000.00") while the legend, price tags and crosshair took the symbol's pricePrecision or the market's ("22,000"). They all agree now, and the axis width is measured in those decimals. With a minTick, the scale's ticks stay on whole price steps: a stock that moves in 10 dong never shows 21,705.
  • Symbol details the feed learns later: a chart asks resolveSymbol once when it connects. An adapter that learns the symbol's details afterwards (on its first message, say) sends a symbolInfo event with the SymbolInfo, and the chart applies it: decimals, price step, hours. No need to remount a framework component to pass them. PollingAdapter subclasses can send it with emitEvent, as WebSocketAdapter ones already could.
  • Docs: the event on the Realtime page, six languages; the agent skill's recipe.

1.16.1

コンポーネント 1.2.33 件の変更

Fixes

  • The Settings' tabs keep their height (broken in 1.16.0): with the Style tab's longer list, the tab bar was squashed to half its height. A dialog's tab bar now keeps its height and wraps on a narrow screen rather than scroll; the indicator and drawing settings, which share it, too.
  • Dialogs span a phone screen: the indicator settings, drawing settings, order ticket, layouts and name dialogs were held to 360px wide on a phone, short of the screen; they are sheets across it like the other dialogs.
  • Checked by opening every dialog, panel and menu of the widget at 1366×768, 1280×600 and 390×844, in the Studio, Terminal and Capsule looks. The demo's embed page takes ?ui=terminal or ?ui=capsule for such checks.

1.16.0

9 件の変更

React, Vue and Svelte components: 1.2.2. 1.15.0 was versioned but never published on its own; its changes (the second section below) ship in 1.16.0.

Every key of the look in the widget's Settings

  • The Style tab sets every key, on the user's layer: the chart type on view gets a section of its own with its colours and widths (Heikin-Ashi's bodies and wicks, Kagi's up and down, a line's colour and width, an area's fills, Baseline's above and below), next to its settings (Renko's box, Kagi's reversal…). Then the background, panes and legend, the watermark, the grid and crosshair each way with their widths, the crosshair's labels, the scales, the last price's colours and width, the volume, the session breaks and the high and low lines.
  • A Trading tab for the colours of orders and positions (buy, sell, profit, loss, entry), signal markers and trade zones, and a selected drawing's handles on the Style tab. They keep their own colours until one is picked: the row shows Auto, its picker starts from the colour drawn, and Auto takes it back. The orders' colours are left out on a chart without trading.
  • Undo, Reset and the theme switch cover every key, every chart type's included: Reset takes them all back to the theme's, and widths and dashes go with the user to the other theme as the rest of the look that isn't a colour. An undo puts back only the keys its change touched, so overrides set since on the user's layer stay. Rows a change moves (a wick with its body) show it at once, the Style tab follows the chart type, the tabs scroll on a narrow screen and read as tabs, and a colour in hsl(), oklch(), a name or with transparency shows in its swatch.
  • Docs: the Settings' tabs on the Styling page, six languages; 21 new widget strings in 30 languages. The agent skill now covers WebGL, the 30 languages, signals, trade zones and replay, the Settings' tabs, and the styleChange and rendererChange events.

More of the look by key, the Settings to change it, and your own shortcuts

  • Orders, positions, signal markers, trade zones and drawing handles by key: 12 more style keys, 101 in all. trading.buyColor, .sellColor, .profitColor, .lossColor and .entryColor colour the orders and positions on the chart and their tags on the price axis, over the trading config's colours. markers.longColor, .shortColor and .neutralColor colour the signal markers, and tradeZones.profitColor, .lossColor and .activeColor the trade zones, over their own styles. drawings.handleColor fills a selected drawing's handles, white without it. The order ticket's and the bracket tool's previews take the trading colours too. Like the rest, they come on the host's layer or the user's, and read back with getStyleValue.
  • The widget's Settings change more of the look, on the user's layer and kept with the theme: the grid each way (shown or not, colour, solid, dashed or dotted), the crosshair's colour and dash, the scales' text and lines, the last price's line (shown or not, its dash), the panes' separator and the legend's text. Undo and Reset take them back as they do the colours. What isn't a colour (a grid hidden, a dash) goes with the user to the other theme; the colours stay with the theme they were picked on. The controls carry their names for screen readers, and the switches read as switches.
  • Shortcuts of your own: widget.addHotkey({ keys: 'Alt+N', label: 'New note', onPress }). A shortcut runs while the widget was used last, not while typing in a field, composing text (an IME) or in a dialog; one without Ctrl or Alt only while focus is on the widget or nowhere. A letter is the one the keyboard layout types (Ctrl+Y is the Y key on a German keyboard too), by its place with Alt. It replaces a widget shortcut on the same keys; the chart's own keys (arrows, Delete, Ctrl+Z) still run, and addHotkey warns of those. It goes with the hotkeys switch and is listed in the shortcut sheet (?), which now leaves out the keys that do nothing (switched off, or a dialog the widget hasn't got) and the ones you replaced.
  • Your own CSS, on stable hooks: --tcw-* variables, [data-tcw-part] (a part's switch names), [data-tcw-off] on the root, and [data-host-button] / [data-host-item] stay as they are through 1.x.
  • Docs: the new keys on the Styling page; shortcuts and CSS on the Customization page; six languages. The Feature Lab's parts scene adds a shortcut (Alt+X).

1.14.0

コンポーネント 1.2.011 件の変更

Replay for apps, and components that wait for your bars

  • Marks as the replay reaches them: during chart.replayStart(), signal markers show once their bar is shown and trade zones once entered, each drawn open (no exit, no result) until its exit is reached. They all come back with replayStop(). revealMarks: false shows them all through the replay. The widget's replay does the same.
  • Where a replay starts: startTime starts at the first bar at or after a time; hideHistory leaves the bars before the start out while the replay runs, so the chart shows only what it replays, and puts them back on replayStop().
  • As quick as you like: duration plays from where the replay is to the end in about that long, however many bars (30 days of 5-minute bars take as long as a day of them). A replay quicker than a bar a frame now runs on animation frames, several bars a frame, instead of a timer the browser holds to a few milliseconds a tick; a frame that comes late slows it rather than skip ahead.
  • Events: replayComplete ({ barIndex, time }) when the replay reaches its last bar, and replayStep now says how many bars the replay goes through (total).
  • React, Vue and Svelte components:
  • indicators takes { id, params, position } as well as ids; one whose inputs change is put back with them (syncIndicators, exported for your own components);
  • with data at mount a component opens no stream; stream={false} never opens one (and closes one it had), so a chart mounted before its bars arrive doesn't start the default Binance feed;
  • features follows its changes after mount.
  • The widget's replay shows the marks as it reaches them too: markers and trade zones you put on the chart wait for the replay. replayRevealMarks: false shows them all, as before.
  • With hideHistory, the replay's indices (replayStep, getReplayBarIndex, a restart's startIndex) count from its start, a restart keeps the window, and indicators begin at the window's first bar.
  • Docs: a replay for your own app, and the components' props, in six languages; the Feature Lab's replay shows buys, sells and a trade appearing as it goes.

1.13.0

26 件の変更

The widget, part by part: switches and your own parts

  • 112 feature switches, every one on until turned off and changeable while the widget runs: new ChartWidget(el, { features: { 'toolbar.replay': false, hotkeys: false } }), then widget.setFeatures({ sidebar: false }), getFeatures(), isFeatureOn(name). The names are listed in WIDGET_FEATURES and checked by TypeScript:
  • a name without a dot is a whole capability, off wherever it shows: its button, its menu entries, its command in the command palette, its keys (alerts, settings, replay, symbolSearch, hotkeys, toasts…);
  • a dotted name is one place: a toolbar button (toolbar.screenshot), a section of drawing tools (sidebar.fibonacci), a status bar item (statusBar.market), a button on an indicator's row or a pane (indicatorLegend.remove, pane.maximize), a menu entry (menu.chart.order, menu.drawing.lock), a key (hotkeys.tools).
  • The older options are the same switches: toolbar: false, drawingTools: false, statusBar: false, rangeBar: false, alerts: false and the rest work as before. The parts they leave out are now built and hidden, so they can be switched on later, and addToolbarButton puts a button on a toolbar switched off, to show with it (it used to return null with toolbar: false). drawingTools: false also switches the drawing settings off, and accountPanel: false the order ticket, as before. trading, watchlist, depthLadder and layouts stay options, as they bring data or storage; switches hide their buttons.
  • Your own parts in the widget's bars: addToolbarDropdown (a menu button, its entries asked for each time it opens), addSidebarButton, addStatusBarItem (text, or a button), and getSlot(name) for anything else: beside the toolbar's chart controls or its panel buttons, under the drawing sidebar's switches, on either end of the status bar, or over the chart. They follow the widget's theme and look.
  • Your entries in more menus: drawingMenuItems and indicatorMenuItems add entries at the end of a drawing's right-click menu and of an indicator's "more" menu, beside chartMenuItems.
  • Every chart of a grid: ChartWidgetGrid.setFeatures(patch), for the charts it adds later too.
  • A switch turned off while its part is in use closes it: a replay ends, a panel, dialog or menu closes; the public toggles open nothing switched off. Separators left with nothing to separate hide with the buttons around them, and the chart takes the room of a bar switched off at once. With toasts off the widget's errors still show.
  • Docs: a Customization page gathers every way to customise (colours, looks, style overrides, switches, your parts, words, plugins), in six languages; a Feature Lab scene switches parts on a live widget.

Style overrides: the chart's look by key

  • Any part of the look, apart from the theme: chart.applyOverrides({ 'grid.vertical.visible': false, 'series.candlestick.upColor': '#26a69a' }). 89 keys, listed in CHART_STYLE_KEYS and checked by TypeScript:
  • the grid's lines each way and the crosshair's: shown or not, colour, solid / dashed / dotted, width;
  • the crosshair's labels, each axis's line and labels, the panes' background, separator and name;
  • the legend, the last price (shown, colours, dash, width), the volume, the session breaks, the high and low lines, the watermark;
  • the main series as each of the 18 chart types draws it: up and down colours, wicks, line colour and width, area fills. Up and down colours fall back to the candles', lines to the line chart's, fills to the area's, then to the theme.
  • Two layers: your app's (layer: 'host') stay through theme switches and are never saved; the user's (layer: 'user') win over them, are kept with the theme they were made on, and are saved with saveState() (snapshot version 3; version 2 saves still load). setOverrides puts a whole layer in place, resetOverrides takes keys away, getStyleValue(key) tells what a key resolves to, getStyle() gives the resolved looks, and styleChange says when they changed. getTheme() returns the theme as set, so setTheme(getTheme()) never bakes the overrides in.
  • Everywhere a chart is: the overrides option, ChartWidgetGrid.applyOverrides (every chart, and the charts it adds later), and an overrides prop on the React, Vue and Svelte components. The grid and crosshair options (grid.hLineColor, crosshair.vLine.style…), which were typed but did nothing, are now shorthand for their keys.
  • Indicator plots and panes: each plot's dash and visibility by its key (updateIndicatorStyle(id, { plots: { signal: { lineStyle: 'dashed' } } })); a hidden plot shows no value tag and no legend value, and stretches no scale. setIndicatorDefaults(id, style) sets what every indicator of a kind starts with. setPaneStyle(instanceId, { background, separator }) gives a pane its own look, saved with its indicator and undone with it.
  • On the GPU too: the WebGL renderer draws the grid each way as it is styled, and hands it to Canvas 2D when it is dashed, wider than a pixel or two colours.
  • The widget's Settings write the user's layer: the colours picked stay with their theme. Reset puts back the current theme's colours; it used to put the dark theme's on any theme.
  • Fixes:
  • the widget's theme toggle brings back the host's own theme when toggled back to its mode; it used to swap it for a built-in one for good;
  • a baseline chart's fills work with rgb() and named colours (they appended a hex alpha to the colour);
  • loading a save that names a theme of its own leaves the chart's theme as it is; it used to break it;
  • a pane's crosshair value pill takes the crosshair label colours, as the price axis's does.
  • Feature Lab: a style overrides scene; the Styling docs explain every key, in six languages.
  • The README and llms.txt say the charts draw with Canvas 2D or WebGL.

1.12.0

10 件の変更

Indicators and languages: 111 indicators, 30 languages

  • 16 more indicators, 111 in all: Average Price, Median Price and Typical Price; Moving Average Channel, Hamming, Double and Triple; Volatility Index (Wilder's stop and reverse on the average true range); Accumulative Swing Index, Advance/Decline, Majority Rule, Chop Zone, SMI Ergodic and Price Oscillator; Volatility O-H-L-C and Zero Trend Close-to-Close.
  • Correlation with another symbol: Correlation Coefficient and Correlation Log (of returns), beside Compare and Spread/Ratio among the indicators that read a second symbol; the widget offers them when you compare with one.
  • Pivot Points in six kinds: traditional (as before), Fibonacci, Woodie, classic, Camarilla and DeMark (type). Its name loses "(Classic)": its levels were the traditional ones all along.
  • MA Cross takes a simple average against an exponential one (type: 'sma-ema').
  • ChartWidget in 30 languages: Italian, Dutch, Polish, Czech, Slovak, Hungarian, Romanian, Greek, Swedish, Danish, Norwegian Bokmål (also for no and nn), Estonian, Malay and Persian join the 16, Persian right to left.

WebGL: back after a lost context, many charts, every browser

  • Back after a lost context: when the browser hands a lost WebGL context back (after a GPU reset, say), the chart draws with WebGL again and says so: rendererChange with { renderer: 'webgl', reason: 'contextRestored' }. Before, it stayed on Canvas 2D for good.
  • Many charts on a page: Chrome and Safari keep about 16 WebGL contexts a page and drop the oldest past that, a live chart's or a map's, never to hand it back. At most 8 charts now draw with WebGL at once; one past that draws with Canvas 2D (rendererChange with reason: 'limit') and takes WebGL as soon as another chart lets go of its context, as a chart whose context was lost does. setMaxWebGLCharts(n), from the package, sets the limit (Infinity for none).
  • Every browser: checked in Chrome, Firefox and WebKit (the engine of Safari): WebGL draws, loses and gets back its context, and keeps to the limit in all three, with the same pixels against Canvas 2D. Firefox no longer warns about the deprecated WEBGL_debug_renderer_info: the GPU's name comes from RENDERER where that gives one.
  • Baseline, Kagi and point & figure on the GPU too. Their lines are drawn whole and round where they bend (baseline, Kagi) where they were drawn in pieces that left notches at each bend, and the two strokes of an X are drawn apart. Zoomed out on 200,000 bars at a pixel ratio of 2, a baseline chart takes 23.2 ms a frame instead of 27.6.
  • Point & figure boxes: the chart drew every column in boxes of 1, whatever the box its columns were built with (1% of the average close unless set), so at a price of 30,000 a column was thousands of overlapping specks instead of a stack of Xs or Os. It draws them the size of the box now.

1.11.0

7 件の変更

WebGL: the heatmap and profiles on the GPU

  • Under the bars, on the GPU: with renderer: 'webgl', the depth heatmap, the volume profile and the market profile draw with WebGL too, under the bars, with volume under a profile as in Canvas 2D. A market profile showing its stats readout or TPO letters stays with Canvas 2D: text can't go between the GPU's background and its bars. The 2D canvas under the GPU's is now only there for that, a watermark, or what the GPU can't take.
  • Faster: panning on integrated graphics at a pixel ratio of 2, a depth heatmap of 240 snapshots by 80 levels takes 16.8 ms a frame instead of 25.5 (60 fps), and zoomed out on 1,000,000 bars with four indicators 16.7 instead of 34.5. Rectangles filled one by one, as heatmap cells are, are recorded straight to the GPU and drawn together.
  • Same pixels: candles and volume land on the same device pixels with Canvas 2D and WebGL at any scaling. Bars exactly on half a device pixel (a round bar step such as 5.1 px at 200%) could land one pixel apart; rounding now turns up from a hair under the half on both.
  • Sharp volume candles: wicks and bodies on whole device pixels, as candles are, the wick in the middle of a body as wide as the bar's volume.
  • Order books for older bars: chart.pushDepthSnapshot(book, time) stamps a heatmap snapshot at time, to fill in books recorded earlier, oldest first; without time it takes the latest bar's, as before.
  • Feature Lab: a liquidity heatmap scene, 240 order books of 80 levels each, with the Canvas 2D / WebGL switch.
  • pnpm bench:render has two more scenes: zoomed out on 1,000,000 bars with four indicators, and a depth heatmap.

1.10.0

26 件の変更

Everything since 1.7.0 in one release (1.8.0 and 1.9.0 weren't published on their own).

WebGL renderer (preview)

  • renderer: 'webgl' draws the plot and indicator panes with WebGL 2, on a canvas under the 2D scene: the grid, session shading and break lines, candles and volume directly, and indicators, indicator panes, compare lines and most other chart types (line, area, bars, Heikin-Ashi, hollow candles, Renko, line break, range bars, HLC area, step line, line with markers, equivolume, high-low) through their Canvas 2D drawing, 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. 'auto' takes WebGL only on a hardware GPU; Canvas 2D stays the default.
  • Same look: the GPU follows the 2D rules for whole device pixels and antialiased edges, so candles match Canvas 2D to within 2/255 at 100%, 125%, 150% and 200% scaling, and lines and fills differ only on a few edge pixels. Anything the GPU wouldn't draw the same (images, patterns, rotated or non-rectangular clips, sharp mitered corners, overlapping pieces of one path, shapes other than bands and areas) is left to Canvas 2D, in order, so the stacking doesn't change. Baseline, Kagi and point & figure charts stay on Canvas 2D for now.
  • Faster where it counts: panning on integrated graphics at a pixel ratio of 2, 2,000 candles on a 1600×900 chart take 17.6 ms a frame instead of 23.3 (60 fps), 500 candles with four indicators 19.6 instead of 27.4, zoomed out on 200,000 bars with four indicators 20.2 instead of 34.5, six charts side by side 17.2 instead of 23.5, and a 2560×1400 chart with four indicators 29.1 instead of 114.5. At 150% scaling that chart pans at 60 fps (70.8 → 17.6 ms).
  • Safe to try: chart.setRenderer(mode) switches at runtime and resolves to what draws, chart.getRenderer() says which, and rendererChange reports each change and why ('unsupported', 'contextLost'). Where WebGL 2 is missing, or its context is lost, the chart carries on with Canvas 2D; a failure to load or compile is logged as a warning. The WebGL code is a chunk of its own (about 17 KB gzipped), loaded on first use, and a destroyed chart hands its GPU context back at once. Screenshots include what the GPU drew.
  • Custom indicators come along: a plugin's render draws on the recording context like on any other, and falls back to Canvas 2D by itself where it needs to. Its render may then run twice in a frame, so it should draw without side effects. Text it draws goes on the 2D canvas, over the lines of the indicators drawn with it.
  • Session break labels now draw over the bars and indicators instead of under them, inside the plot, with Canvas 2D or WebGL. SessionBreaks.render() still draws lines and labels; renderLines() draws the lines alone.
  • Feature Lab: the 200,000-bar scene has a Canvas 2D / WebGL switch, and times a short pan on each switch.
  • pnpm bench:render --renderer=webgl (or --renderer=auto) measures the WebGL path.

Faster when zoomed out

  • Faster when zoomed out: once each bar takes less than a pixel, indicator lines, bands (Bollinger and the like) 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: zoomed out on 200,000 bars with Bollinger Bands, EMA, RSI and MACD, a frame went from about 54 ms to about 21 ms on integrated graphics (85 → 38 ms at 2x). Supertrend draws one line per colour instead of one stroke per bar.
  • pnpm bench:render measures frames in headless Chrome on your own GPU, scene by scene.

Sharper, calmer charts

  • Sharp at any screen scale: candles, bars, volume and the drawings' horizontal and vertical lines land on whole device pixels. A one-pixel wick is one sharp pixel at 100%, 125% or 200% scaling; it used to spread over two at half strength.
  • Volume as a backdrop: the bars keep to the bottom 15% of the chart (20% before) in the theme's own volumeUp / volumeDown, which were ignored. A theme that only changes the candle colours (or the widget's settings) gets volume in those colours. volumeColor(candleColor) gives the matching shade.
  • A calmer dark palette: softer up and down colours and quieter axis labels.
  • Drawings:
  • Fibonacci levels each come in their own colour with soft bands between them, and their labels sit above the lines. The drawing's colour goes to its trend line; each level's is set in its levels.
  • Drawing text uses the theme's font, on a halo of the background so it reads over bars.
  • Lines turn corners round.
  • Long/Short labels are tags just outside their zones that never overlap.
  • Price axis: indicator value tags step around the last-price, high/low and order tags, and scale labels under any tag are hidden instead of showing half-covered.
  • Dates: on an intraday chart a bar at midnight is labelled with its day on the time axis and the crosshair, not with its year as if it were a daily bar.
  • Lines on the pixel: the crosshair, vertical lines and wicks share one device-pixel column, so a line drawn on a bar runs through its wick.
  • Widget: the drawing tools sit in sections with a divider between them: lines; Fibonacci, Gann and cycles; patterns and Elliott waves; forecasting and measuring; shapes, brushes and notes. The tools below are grouped too: modes, undo and redo, clear all.
  • Looks different after the update: the dark theme's colours, the volume's height, new Fibonacci drawings' colours and the order of the drawing tool groups change without any change of yours. Set candleUp / candleDown on the theme to keep the old candle colours.

Fixes

  • A position's stop-loss or take-profit priced outside the visible range no longer draws over the time axis or the panes below the chart, and can't be grabbed there by accident (nor can an order line off the plot); an entry scrolled out of view no longer leaves its price tag on the axis.
  • The npm page shows the full README again (it had fallen behind the repository's), with screenshots; the demo's link previews now carry an image on every network.
  • Panning by dragging no longer stops halfway with a "no drop" cursor: quick presses could leave text on the chart selected, and the next press then started the browser's own drag of it. The chart's text can't be selected now, and such drags are cancelled.

1.7.0

72 件の変更

Everything since 1.4.0 in one release (1.5.0 and 1.6.0 were never published): the drawing toolkit, trading and workspace, panes and undo, alerts and replay, scales and comparisons, the widget's look, and watchlists, symbol info, tick charts and access. Wrappers (@tradecanvas/react / vue / svelte) 1.0.10 pick up the new core. The widget looks different after the update: Studio is the new default look (see *The widget's look* below); ui: 'terminal' is the closest to a square, ruled look.

Workspace, markets and access

  • Watchlists: several lists of symbols to switch between, create, rename and delete; add symbols from the search, remove them, drag them into order. Rows fill with live quotes from the feed (Binance sends them), from a quote source of yours, or from what you push.
  • Symbol info: a panel with the symbol's price and move, whether its market is open and when that changes, the day's open, range and volume, its trading hours and news. The status bar shows when the market is closed.
  • Tick charts: type 100T for a bar per 100 trades, built from the feed's trades (Binance streams them).
  • Undo for settings: Ctrl/Cmd+Z takes back settings and chart type changes too, with drawings and indicators; recordUndo adds changes of your own.
  • Zoom and scroll buttons over the chart, shown while the mouse is on it.
  • For screen readers: the chart says what it shows, what is on screen after the keys move it, and reads the bars one at a time (comma and period).
  • Arabic and Hebrew, right to left: the widget in 16 languages.
  • Ten more indicators (95 in all): Stochastic Momentum Index, Relative Volatility Index, Trend Strength Index, Linear Regression Slope, Standard Error and its bands, Guppy Multiple Moving Average, Moving Average Ribbon, Average Day Range and Net Volume.
  • New events: the chart type, symbol or timeframe changed, the undo history changed, drawings were selected.
  • A live bar that closes keeps its final values (it used to keep the ones before its last update).

The widget's look

  • Three looks, and yours: the widget's corners, sizes, type, borders, shadows and bars are a look apart from its colours. Studio is the new default (rounded controls, spaced groups, the interval buttons in a segmented track), Terminal is dense and square with capital labels, Capsule is all pills with the toolbar and drawing tools floating as islands. Start from one and change what you like with the ui option or setUI, on one chart or a whole grid.
  • The chart's price tags take the same corners: square, rounded or pills, along with the axis and crosshair pills and the order badges (chart.setShapes).
  • Every part of the widget follows the look's CSS variables; without ui they stay yours to set in CSS (the widget's stylesheet now goes first in the page, so your rules win a tie). Menus grow to fit their labels instead of wrapping them.
  • Looks different after the update: Studio is the new default, so an existing widget changes look without any change of yours — slightly rounder corners, a taller toolbar, wider drawing tools, the interval buttons in a track, no rules between toolbar groups, labels as written rather than in capitals, rounded price tags. Use ui: 'terminal' for a square, ruled look, or set any token yourself.

Scales, formats and comparisons

  • Price formats: prices in your own format, or in fractions of a point (a bond in 32nds: 110'165), on every label of the price scale — axis, crosshair, legend, tooltips, orders, alerts, drawings (priceFormat). Times your way too (timeFormatter).
  • Compare, spread and ratio: another symbol on a price scale or pane of its own, or the spread or ratio to it, lined up with the chart by time; compare lines count in the auto scale and line up by time as well.
  • Percent panes: a pane can read in percent of its first value on screen.
  • High-Low bars, settings for Renko, Line Break, Kagi, Point & Figure and range bars, a hidden main series, lines at the visible high and low, and bid/ask lines.
  • Extended hours on or off: bars outside a symbol's regular hours are kept aside while hidden.
  • Data export with every indicator line in a column of its own (CSV or JSON); bars timed in seconds no longer export as 1970.
  • Replay across a grid: replaying one chart takes the others along to the same time.

Alerts, replay and panes

  • More kinds of alert: a line crossing another line (the price and a moving average, MACD and its signal), a move of some percent within some bars, only on closed bars (no firing on a wick that comes back), and an expiry. All in the alerts panel and in addAlert's options.
  • Replay in finer steps: pick 5m under an hourly chart and watch each bar form, step by step (replayStart({ steps })).
  • Paper trading in a replay: a paper account fills on the replayed prices (each step's high and low too), and its fills land on the replayed bars.
  • Alerts on a connected feed: price alerts now check on every price a connect()ed feed sends, not only on setCurrentPrice.
  • Signal markers say what they are when the pointer is on them, and report clicks (signalMarkerHover, signalMarkerClick).
  • Each pane can have its own logarithmic or inverted scale (right-click the pane, or setPaneScale).

Panes, templates and undo

  • Move an indicator to another pane — into the pane above or below, a pane of its own, or back to the price pane — from the ⋯ button on its legend row, or chart.moveIndicatorToPane. The pane's other indicators stay, and those reading its lines follow it.
  • Fold, maximise and reorder panes with buttons at each pane's top right (setPaneCollapsed, setMaximizedPane, movePane). Saved layouts keep each pane's size, order, fold and maximise.
  • Undo for indicators: Ctrl/Cmd+Z takes back adding, removing, editing and moving indicators, in the same history as drawings. An indicator comes back under its own id, so alerts on its lines still match.
  • Indicator templates: save the chart's indicators (inputs, style, levels, panes) under a name from the indicators menu and apply them in one go.
  • Type a number to change the interval (5, 15m, 1h, 1D, Enter), and Alt+T / H / J / V / C / F for the trend line, horizontal line and ray, vertical line, cross line and Fibonacci retracement.
  • Prices offered by the chart's menus and the order ticket sit on the market's price grid (chart.roundPrice).

Trading and workspace

  • Act on orders and positions from the chart: × on an order line cancels it, × on a position closes it, ⇅ reverses it, × on a stop-loss or take-profit removes it. They raise the usual intents (a new positionReverse among them), so a connected adapter acts on them; an adapter without reversePosition gets a close and a market order the other way. Orders take a stop-loss, a take-profit and a time in force that carry over to the position. Adapter authors: PositionModifyIntent.stopLoss / takeProfit can now be null, meaning remove it (a missing field still means keep it).
  • Fills on the chart: a mark on the bar of each fill, solid where it opened a position and hollow where it closed one. executionFill says why (order, close, reverse, stop-loss, take-profit) and the P&L realised.
  • Right-click menus that know where you clicked: the plot, a pane, the price axis or the time axis, with the price and time there. A "+" by the price axis follows the crosshair. ChartWidget offers an alert, a buy and a sell at the price (a limit where it would wait, else a stop), an order ticket and a horizontal line on the plot, the scale switches on the price axis, and go to date on the time axis.
  • Order ticket and account panel in ChartWidget: open positions with their P&L, working orders and the fills so far, each with close, reverse or cancel; an order ticket that checks the order as you fill it in and shows the reward:risk.
  • Named layouts: save the chart under a name (symbol, interval, scale, chart type, indicators, drawings, alerts), open, rename, delete, auto-save the open one, Ctrl/Cmd+S. Kept in the browser, or on your server through a four-call LayoutStorage.
  • ChartWidgetGrid: up to six charts side by side, linked by symbol, interval, crosshair, time or drawings as you choose, saved together as one layout.
  • Your own toolbar buttons and menu entries: widget.addToolbarButton() and chartMenuItems.
  • Fixed: ChartGrid.connectAll with one adapter object sent every chart the last symbol's bars (an adapter keeps one stream). It now takes a function that makes one per chart, as does ChartWidgetGrid's adapter option.
  • New events ordersChange, positionsChange and stateChange. With several widgets on a page, Ctrl/Cmd+K and +P now go to the one used last instead of all of them.

Drawing toolkit

  • Each tool has its own settings: Fibonacci levels (edit, hide, add, colour), prices and percentages, labels left or right, extending lines either way, backgrounds, a wave degree, an icon. Double-clicking a drawing in ChartWidget opens its settings (style, the tool's settings, its points in the chart's time zone); changes show as you make them and Cancel takes them back. "Save as default" keeps a tool's settings for the next drawing, and templates keep settings as well as style. API: getDrawingOptions / setDrawingOptions, updateDrawing, beginDrawingEdit / endDrawingEdit, setDrawingToolDefaults.
  • Long/Short Position works out the size from the account and the risk (a percent or an amount): quantity, reward:risk, and each line's price, distance and profit or loss. The target's handle sets the ratio.
  • Alerts on drawings: addDrawingAlert(id, …) fires when the price crosses a trend line, ray, horizontal line or a channel's lines where they are by then, as drawn on the chart (log scale included). The alert goes with its drawing and comes back with it on undo.
  • Order, groups and a right-click menu: bring forward or send back (Ctrl+] / [), group drawings to select, hide and lock them together (Ctrl+G), and a menu on each drawing with settings, an alert, order, group, lock, hide, duplicate and delete. The object tree lists groups with their drawings.
  • 29 new tools (69 in all): note, callout, flag, arrow mark and icons; brush, highlighter, path and polyline (a point per click, a double-click or Enter ends them), curve and arc; Fibonacci circles, spiral, speed resistance arcs and wedge, pitchfan, Gann square; Elliott impulse, correction, triangle and combination waves; three drives and cypher patterns; time cycles and sine line; forecast, projection and bars pattern.
  • An eraser, a zoom tool and a strong magnet, in the API and the widget's sidebar. On a short screen the sidebar scrolls, and its menus open beside it and work from the keyboard.
  • Fixed on the way: Anchored VWAP and Fixed Range Volume Profile drew nothing (they were never handed the bars); Ctrl+Shift+Z undid instead of redoing; dragging a drawing on a log scale bent it; drawing shortcuts fired inside dialogs.

Data and time

  • Zoom out until every loaded bar fits. Below the old 2 px bar + 2 px gap floor, the bar and its gap keep shrinking (down to a quarter pixel) as long as the loaded bars don't fit yet; a short series still stops at the old floor. Below a pixel per bar, candles, OHLC bars and volume merge per pixel column, so thousands of bars stay readable and cheap to draw. "All" and the 1Y / 5Y presets are no longer capped at about 200 bars.
  • Older bars load as you scroll back. Adapters can implement fetchHistoryBefore(symbol, timeframe, before, limit); Binance, Bybit and Mock do, and WebSocketAdapter / PollingAdapter take it as an option. A connected chart loads a page when less than a screen of bars is left of the view, one request at a time, keeping the same bars on screen; it backs off after failures, and a reconnect keeps the paged-in history. New chart.prependBars(), setHistoryLoader(), loadMoreHistory(), hasMoreHistory(), isLoadingHistory(), the historyLoad event and StreamConfig.historyPageSize. ChartWidget shows a small pill while older bars load.
  • Any interval. TimeFrame takes any whole count of a unit ('7m', '90m', '2d'); parseTimeframe / isTimeFrame check one. Adapters list the timeframes their feed serves (supportedTimeframes), and the chart builds the others from the coarsest one that divides them: history, live bars and older pages alike (ResamplingAdapter, withResampling, resampleBars, pickBaseTimeframe). This also fixes Binance's 45m, 2d, 3M and other intervals it lacks, which used to fall back to 15m bars; a timeframe the feed cannot build is refused instead. TimeFrame now accepts any ${number}${unit}: exhaustive switches over it should use KnownTimeFrame. ChartWidget's timeframe menu takes a typed interval (7, 90, 2h, 3D), keeps it with a star and an × to remove it, and lists it in the command palette.
  • Time zones with daylight saving time: chart.setTimezone('America/New_York') (or a fixed offset, or null for the browser's) and ChartOptions.timeZone set the zone for the time axis, crosshair, tooltip, day breaks, range presets and go-to-date. Day breaks used to follow the browser's zone whatever the chart showed. Session hours take a timeZone too. ChartWidget's settings list 28 zones by city with the offset in force. YTD now starts on the 1 January bar.
  • A left price scale: an overlay can go on a scale of its own on the left (addIndicator(…, { scale: 'left' }), setIndicatorScale), fit to its values, so a volume-like line no longer squashes the candles; setLeftPriceScaleVisible(true) mirrors the price scale on both sides. ChartWidget has a switch in its settings and a choice in each overlay's Style tab.
  • Symbol search and symbol info:
  • Adapters can implement searchSymbols and resolveSymbol. They return a symbol's name, exchange, price precision and step, exchange time zone and trading hours. Binance does.
  • A connected chart resolves its symbol by itself: prices take its precision, setTimezone('exchange') follows its exchange, and its hours feed the session shading.
  • ChartWidget's symbol search asks the feed as you type, with names and exchanges.
  • ChartWidget in 14 languages: English, Vietnamese, Simplified and Traditional Chinese, Japanese, Korean, Spanish, Portuguese, French, German, Russian, Turkish, Indonesian and Thai. Every string the widget shows now goes through its translations; settings, drawing tools, alerts, dialogs and toasts used to stay English. Translations live in @tradecanvas/chart/widget/locales so a page loads only what it imports. Number formats for each language are in the settings.
  • The replay bar sits above the time axis, so its dates stay readable.
  • Pinch-zoom on touch screens follows the fingers: spreading them twice as far apart doubles the bar width. A pinch used to move the zoom by about a twentieth of that, so it seemed not to work. The chart also sets touch-action: none on its surface, so the page doesn't zoom instead.
  • Dragging inside an indicator pane pans the chart. It used to zoom time as if the time axis had been dragged, and the whole pane showed the time-axis cursor.

Indicators in depth

  • One scale per pane: a pane's lines, levels, axis labels and crosshair share one value scale (RSI's 30 line used to read as 38). The price scale no longer stretches to fields that are not drawn.
  • Declared plots: descriptors declare what they draw (plots), their pane scale, default levels and how inputs are edited; a custom indicator needs no rendering code.
  • Sources and indicators on indicators: 38 indicators take a price source or another indicator's line (indicatorSource(instanceId, key)), e.g. an SMA of RSI in RSI's pane.
  • Shared panes, editable levels and value tags on the axis, all kept in saved layouts.
  • 15 new indicators (85 in all): DEMA, SMMA, ALMA, KAMA, LSMA, McGinley Dynamic, MA Cross, Williams Fractals, Chande Kroll Stop, Bollinger %B, Bollinger BandWidth, Momentum, Historical Volatility, Volume Oscillator, Ulcer Index.
  • ChartWidget: an indicator settings dialog with Inputs, Style and Levels tabs; the legend colours each value as its line.

Site and docs

  • The site speaks 14 languages: the home page, menus and the Feature Lab, whose live charts switch to the same language. The docs and the README are in English, Vietnamese, Simplified Chinese, Japanese, Korean and Spanish; the other languages show the English docs with a note.
  • Each language has its own address (/ja/docs/api/), with hreflang links and a sitemap covering every language.

For AI coding tools

  • skills/tradecanvas: an agent skill with entry points, rules, recipes and a generated indicator reference.
  • llms.txt and llms-full.txt on the site; the indicator catalog on the docs site is generated from the registry, and CI checks that the generated files are current and that the skill's examples type-check.

1.4.0

9 件の変更

Layouts that come back whole, ranges and dates, scale options, indicators listed on the chart, an icon set and reworked bar replay. Wrappers (@tradecanvas/react / vue / svelte) 1.0.7 pick up the new core.

Layouts, ranges and scales

  • Saved layouts restore indicators and alerts: inputs, panes, colours, visibility; alerts keep their channel, repeat and label. Indicator changes trigger the auto-save.
  • Ranges and dates: setVisibleRangePreset('1D' … 'All') and goToTime(); ChartWidget shows the presets under the chart with a go-to-date button (Alt+G).
  • Inverted price scale (setInvertScale, Alt+I), and the log scale now applies to candles, axis and grid as well as drawings and indicators.
  • Timeframe favourites in ChartWidget, and feature flags that used to do nothing now apply (drawingMagnet, barCountdown, compareSymbols, dataExport, logScale, timeframes).
  • Drawing: stay-in-drawing mode, and Ctrl/⌘+C / Ctrl/⌘+V copy drawings, also between charts. ChartGrid links the crosshair by time.

Indicators on the chart

  • ChartWidget lists each indicator on the chart, under the OHLCV legend or at the top of its pane, with its value at the hovered bar and show/hide, settings and remove actions. Several instances of one indicator each get their own colour.

Icons and tooltips

  • Every drawing tool and chart type has its own icon; the interface icons share one grid. createIcon, createToolIcon, createChartTypeIcon and the icon maps are exported.
  • Tooltips on the widget's controls replace the browser's.

Replay

  • Live data stays out of the replay and comes back with replayStop(); the replay ends paused on its last bar. ChartWidget asks for a start bar, offers a random bar, speeds in bars per second and "Back to realtime".

1.3.0

17 件の変更

Dragging that never sticks, a lighter two-canvas renderer, the TradeCanvas look by default, a redesigned gauge, crosshair tooltip and loader, and replay that follows its newest bar. Wrappers (@tradecanvas/react / vue / svelte) 1.0.6 pick up the new core.

Dragging and panning

  • The press that selects a drawing also grabs it: no second drag needed; locked drawings let the press pan the chart. Clicks that only select no longer move the drawing or add an undo step.
  • Drags are followed outside the chart until the button is released (also axis scaling, pane resizing, drawings and trading lines); price drags are pinned to the plot's edge; a release outside the window is detected.
  • A sloppy horizontal drag keeps auto-scale on: vertical panning needs a deliberate move (> 24 px and at least half the horizontal travel).
  • Momentum is measured over the last 100 ms, ignored after a rest, capped and stopped by any new gesture.
  • Free panning past the newest bar into empty future space, or past the oldest bar, down to panLimits.minVisibleBars; the time axis, grid, crosshair and drawings (magnet included) extend into the future. freePan: false keeps the old clamp. setVisibleRange() / fitContent() show exactly the requested range.
  • Context cursors: crosshair, grabbing hand, hand over drawings, move over handles, resize arrows over axes, pane dividers and draggable lines.
  • Ctrl/⌘-drag selects drawings in a box, Ctrl/⌘-click toggles one; the group moves, restyles and deletes together as one undo step.
  • The right-click order menu is off by default (features.tradingContextMenu: true to opt in).

Rendering

  • Two canvases instead of four: a scene canvas and a thin top canvas for pointer-tied visuals. A hover repaints only the top canvas and the browser composites two surfaces instead of four. New LayerType.Hover.
  • After the page or a scrolling container scrolls, the crosshair follows the pointer exactly (it used to stay offset until the next click).
  • The price-axis tick label under the last-price tag is hidden instead of half-covered; Anchored VWAP caches its series.

TradeCanvas look

  • Default palette: DARK_THEME / LIGHT_THEME, indicators, orders, signal markers, drawing tools and the ChartWidget chrome share one palette — ink ground, mint/coral candles, amber accent. New TC_PALETTE and TC_SERIES_COLORS. Tests keep theme-neutral colours at 3:1 on both backgrounds and widget text at 4.5:1.
  • Armed price alerts are blue, triggered ones amber; comparison lines no longer start with an orange that blends into the main line.
  • Gauge redesign: a thin ring with rounded ends and zone gaps, bright up to the value and dimmed beyond it; a knob marks the value so the number is never crossed by a needle; the current zone's label shows above it; text fits small dials. pointer: 'needle' keeps the classic needle. New defaults: 240° sweep, thickness 0.14.
  • Crosshair tooltip redesign: bar time and a change pill (vs the previous close), an aligned O/H/L/C grid with only the close coloured, and volume; the chart's precision (sub-cent prices no longer show 0.00), locale, timezone and bar spacing; stays inside the plot. New setLocale, setPricePrecision, setTimezoneOffset, CrosshairTooltipContext and formatTooltipTime.
  • Loader redesign (ChartWidget): a run of candles lit one after another over a sweeping accent line; the "Loading chart…" text is for screen readers only (shown under reduced motion and on failure).

Replay

  • Replay follows the newest bar again: the first step and every seek show the replay position; each new bar keeps the view at the latest bar while it rests there, and panning back into history pauses the follow.

1.2.0

16 件の変更

More indicators and drawing tools, and a performance pass measured in a live browser profiler. Wrappers (@tradecanvas/react / vue / svelte) 1.0.5 pick up the new core.

Drawing tools — 26 → 40

  • New: Info Line, Trend Angle, Cross Line, Fib Channel, Fib Speed Resistance Fan, Schiff and Modified Schiff Pitchforks, XABCD and ABCD patterns, Head and Shoulders, Circle, Date and Price Range (with volume traded), Cyclic Lines, Price Label. Earlier in this release: Horizontal Ray and Long/Short Position.
  • Widget toolbar regrouped by tool family (Lines, Horizontal/Vertical, Channels, Fibonacci, Shapes, Gann & Pitchforks, Patterns, Measure, Annotation, Forecasting) — also surfaces Fib Time Zones, Anchored VWAP and Fixed Range Volume Profile, which were registered but missing from the toolbar.
  • Measuring labels use a precision that fits the price level instead of a fixed 2 decimals.

Indicators — 70

  • New: VWMA, Envelope, TEMA, Weighted MA.
  • Incremental updates on live ticks — new optional IndicatorPlugin.update(); built-ins recompute only the forming bar (a tick with 4 indicators at 100k bars: ~96 ms → ~0.001 ms).
  • IndicatorValueMap — array-backed drop-in Map for indicator values; full recalculation on a symbol/timeframe switch is ~2.5–3.5× faster.

Performance

  • Viewport.getState() snapshots are cached instead of deep-cloned 8–10× per frame; indicator auto-scale scans only the visible range; Intl number/date formatters are cached (hover frames ~0.64 → ~0.23 ms).
  • The price scale no longer jumps while live data streams in; new bars don't yank you out of history.

Sub-cent prices

  • Legend, crosshair pill and last-price tag follow the market's pricePrecision (or the axis's precision) in the configured numberLocale — PEPE-class prices no longer show "0.00".
  • The price axis auto-widens to fit long labels instead of clipping them; ordinary prices keep the 70px default.

Symbol / timeframe switching

  • Smooth loading — fast switches swap in place with no flash; slow ones veil the previous chart with a loading card after 200 ms; failures say so and recover on retry.
  • Race-free — superseded history responses are dropped (StreamManager, ChartWidget, Chart.connect); adapters detach every socket handler on disconnect.
  • setData resets auto-scale so each switch fits the new data.

Widget

  • locale / messages i18n with built-in Vietnamese; numberLocale fixes; watchlist refPrice precedence.
  • widget.toggleReplay() opens bar replay from code.
  • The cursor-following OHLCV popup is off by default (the legend shows the same data); chartOptions.features no longer wipes the other feature defaults.

1.0.1

3 件の変更

Patch release for the core packages, plus the first public release of the framework wrappers.

Fixes

  • visibleRangeChange now fires — along with the sibling priceRangeChange and zoomChange events. All three were typed and documented but never emitted anywhere in Chart; they now fire on every pan, zoom, resize, and data update, but only when that slice of viewport state actually changed. visibleRangeChange payload is { from, to } bar indices, priceRangeChange is { min, max }, zoomChange is { barWidth } CSS pixels per bar.
  • Sparse-series panning — a chart whose loaded bars don't fill the pane (e.g. a Year view with a handful of candles) could not be panned at all; the offset was welded to a single value. The view still rests at the same right-aligned position by default, it's just no longer locked there. Dense series are unaffected.

Framework wrappers

  • @tradecanvas/react, @tradecanvas/vue, and @tradecanvas/svelte are now public (1.0.0) — thin reactive <TradeCanvas> components around @tradecanvas/chart with props for symbol / timeframe / theme / chart type / indicators / data / adapter / signal markers / trade zones, lifecycle cleanup, and access to the underlying Chart via onReady / ref / bind:chart. Pinned to @tradecanvas/chart@^1.

1.0.0

10 件の変更

First stable release — everything an open-source trading chart needs, batteries-included and zero-dependency. The public API is now semver-stable for the 1.x line. Cumulative since 0.9.0 (0.10–0.14 added 30+ indicators and several chart types); the headline additions:

Data

  • Coinbase, Bybit, and Kraken adapters (free, no API key) join the built-in Binance adapter.
  • Generic adapter bases — WebSocketAdapter (live + REST history) and PollingAdapter (REST-only feeds) let any source plug in with ~20 lines: a URL and a parse function. The base handles the connection lifecycle, reconnect, decoding, and event emission.

Trading

  • Live execution — chart.connectExecution(adapter) turns the display-only trading overlay into a real trading surface. The chart routes its order/position intents into an ExecutionAdapter and renders the authoritative orders/positions it reports back (the adapter is the single source of truth). Ships a PaperExecutionAdapter sandbox; failures surface on a single executionError event.
  • Drag-to-create orders — chart.startOrderDraft(side) drops a draggable order line; drag it to a level and confirmOrderDraft() places it (limit vs stop inferred from the level relative to the current price).

Extensibility

  • Plugin SDK — register custom indicators, drawing tools, chart types, and overlays: globally via registerPlugin, per-chart via new Chart(el, { plugins }), or imperatively via chart.plugins.register. Custom chart types and overlays render through the engine.

Layout

  • Resizable panes — drag the divider between the main chart and an indicator pane (or between panes) to resize it, with mouse or touch; each pane keeps an independent price scale.

Performance

  • LTTB downsampling — line and area charts downsample the visible range to ~2 points per pixel (Largest-Triangle-Three-Buckets) when the bar count far exceeds the pixel width, keeping 100k+ bar charts smooth. Visually identical, and a no-op at normal zoom.
  • Benchmark harness — a new pnpm bench (vitest bench). Downsampling 100k points to 1,600 runs in ~0.32 ms.

Frozen contracts

The DataAdapter, ExecutionAdapter, and Plugin SDK interfaces (IndicatorPlugin / DrawingPlugin / ChartTypePlugin / OverlayPlugin), plus the chart event names and payloads, are now semver-stable for the 1.x line.

Breaking changes

  • chart.replay() is renamed to chart.replayStart(), for consistency with replayPause / replayResume / replayStop / replaySeek.

Notes

  • The React / Vue / Svelte wrapper packages remain private and are deferred to 1.1.

0.9.0

27 件の変更

Major UX upgrade — pro-grade interaction across the board, with new analytics depth and workflow features.

Chart interaction

  • Axis-drag scaling: drag the price axis vertically to compress / expand the price scale; drag the time axis to zoom. Double-click either axis to reset (auto-scale / fit-content).
  • Shift+drag measure ruler: transient overlay showing bars × time × price Δ × % between two points. Tracks data through pan/zoom.
  • Alt+click pinned tooltip: anchor an OHLC tooltip at a bar; the live crosshair tooltip then shows the price / % / bar-count delta to the pinned bar. Esc unpins.
  • Hover axis pills: Price (right) + time (bottom) pill badges follow the crosshair with a triangular notch pointing at the line. Inverted theme colors so they always pop.
  • Bar hover highlight: subtle translucent column behind the crosshair marks which bar the cursor is on — disambiguates dense candle charts.
  • Cursor hints: ns-resize over the price axis strip, ew-resize over the time axis strip.

Widget

  • Symbol search modal: clicking the toolbar symbol (or pressing Ctrl/⌘+P) opens a fuzzy-search picker over the configured symbols[]. Replaces the previous click-to-cycle behaviour.
  • Hotkey sheet (?): categorized keyboard-shortcut reference.
  • Replay scrubber UI: toolbar play button toggles a floating bottom scrubber bar — play/pause, step-back/step-forward, draggable progress, speed select (0.5×–100× bars/sec). Drives the existing chart.replay*() API.
  • Watchlist sidebar (watchlist: true): right-side panel listing the widget's symbols with last price, % change, and a mini sparkline. Click a row to switch chart.
  • Saved layouts (persistLayouts: true): per-symbol indicator stack, drawings, alerts, and chart type persist to localStorage. Switch symbol → state is auto-saved; switch back → state is restored. widget.clearSavedLayout(symbol?) resets.
  • Drag-and-drop CSV / JSON (dragDropImport: true, default): drop an OHLCV file onto the chart and it loads instantly. Toast feedback for success / failure. New parseOHLCV exported for programmatic use.
  • Toast helper: widget.toast(msg, kind?) for transient feedback.
  • Premium CSS refresh: new design tokens (motion, elevation, shape), Inter + JetBrains Mono stacks, smoother cubic-bezier transitions, refined hover/active/focus states, gradient toolbar/sidebar surfaces, larger radii on modals/palette, animated connected status pulse, refined scrollbars, reduced-motion support.

Chart visuals

  • Volume Profile: optional horizontal histogram of traded volume bucketed by price over the visible range, with point-of-control highlighting. chart.setVolumeProfileVisible(true).
  • Day-separator dividers: faint vertical lines at day boundaries on intraday data, heavier at week/month/year with inline date labels (Mar 4, Apr '26, 2027). Auto-suppressed on daily-or-coarser timeframes.
  • In-canvas axis polish: price + time axes now render with subtle dividers, thin tick notches, and refined typography weight (dropped the heavy per-label background rectangles for a cleaner feel).

Analytics

  • Strategy library: four reference strategies under @tradecanvas/analytics — smaCrossStrategy, rsiReversionStrategy, donchianBreakoutStrategy, bollingerReversionStrategy. All return a StrategyFn ready to feed Backtester.run().
  • Monte Carlo simulation: runMonteCarlo(initialCash, trades, opts) shuffles realised trade order N times to expose path-dependence. Returns per-step P5/P25/P50/P75/P95 equity bands, final-equity percentiles, probability-of-profit, and worst-case max drawdown. Deterministic with a seed.

Internals & exports

  • New Viewport.scalePriceRange(factor) and AxisDragHandler for custom axis interactions.
  • New MeasureOverlay and PinnedTooltip exports from @tradecanvas/core.
  • New VolumeProfileRenderer export from @tradecanvas/core.
  • New parseOHLCV, DragDropImporter exports from @tradecanvas/chart.
  • ReplayManager.seekTo now emits a synchronous bar event so seeking while paused immediately repaints the chart slice.

Behavioural notes

  • Toolbar symbol-click now opens the search modal (was: cycle through symbols). Hold the same prop name in your code; behaviour upgrades.
  • dragDropImport is enabled by default in the widget — pass false if a parent surface already handles drops.
  • SessionBreaks auto-suppresses its lines on daily-or-coarser timeframes so weekly charts don't paint a wall of separators.

0.8.1

3 件の変更

Bug fixes

  • features.tradingContextMenu flag is now wired through to the right-click handler. Previously the flag existed in FeaturesConfig but InteractionManager always called preventDefault() and routed to the trading manager regardless of whether the custom menu would render. The result: projects setting tradingContextMenu: false (or any config that kept trading on but the menu off) suppressed the native browser context menu without showing a replacement, leaving users with no right-click affordance at all
  • Chart.ts now passes features.tradingContextMenu into the TradingManager config (contextMenu.enabled)
  • InteractionManager.onContextMenu only calls preventDefault() when the trading context menu actually opens

Usage

Projects that don't use trading can now opt out cleanly:

new Chart(host, { features: { trading: false } })            // no trading at all
new Chart(host, { features: { tradingContextMenu: false } }) // keep orders/positions, drop the menu

In both cases, native browser right-click works on the chart as expected.

0.8.0

18 件の変更

Features

  • Strategy backtester — new @tradecanvas/analytics package with a bar-by-bar Backtester. Strategy fn runs at close of each bar; orders placed on bar N fill on bar N+1 (market → next-bar open, limit/stop → when the next bar trades through the trigger). Returns fills, closed trades, equity curve, and summary metrics
  • Portfolio tracking — Portfolio class tracks cash, one net position, realized P&L, and the equity curve. Supports partial closes and position flips with correct realized-PnL accounting
  • Risk metrics — computeRiskMetrics() returns Sharpe, Sortino, Calmar, CAGR, max drawdown, win rate, profit factor, expectancy, average win/loss. Periods per year auto-detected from equity-curve timestamps; configurable risk-free rate
  • Commission & slippage models — FixedCommission, PercentCommission, PerShareCommission, NO_SLIPPAGE, PercentSlippage, RangeBasedSlippage. Pluggable via Backtester constructor
  • Replay mode — new ReplayController in @tradecanvas/core. Decoupled from Chart so it can drive both UI playback and headless backtests. Supports start / pause / resume / step(n) / seek(index) / setSpeed(barsPerSecond) with typed bar / finished / stateChange events
  • Equivolume chart type — full-range boxes with width proportional to volume share; color tracks close vs prior close (Richard Arms style). Switch via chart.setChartType('equivolume')
  • Fibonacci Time Zones drawing — fibTimeZones tool draws vertical Fibonacci-interval lines (1, 2, 3, 5, 8, 13, 21, 34, 55) projected from a two-anchor time span. Useful for forecasting future swing points based on prior cycle duration
  • Multi-page SvelteKit docs site — replaced single-page demo with 18 prerendered routes (/, /docs/*, /examples, /playground, /changelog, /embed) using @sveltejs/adapter-static. SEO-friendly per-page metadata, sitemap, robots.txt
  • Live backtest demo — /docs/analytics includes a runnable backtest panel (SMA(10/30) cross on 365 days of deterministic synthetic data) with equity-curve canvas, drawdown shading, play/pause/scrub controls, and 8 live metric tiles

API additions

  • New package @tradecanvas/analytics exporting Backtester, Portfolio, computeRiskMetrics, FixedCommission, PercentCommission, PerShareCommission, ZERO_COMMISSION, NO_SLIPPAGE, PercentSlippage, RangeBasedSlippage, plus StrategyContext, StrategyFn, BacktestResult, RiskMetrics, Fill, ClosedTrade, PortfolioPosition, EquityPoint, Side, OrderType, OrderStatus, TimeInForce
  • ReplayController exported from @tradecanvas/core and @tradecanvas/chart along with ReplayBarEvent, ReplayEventMap, ReplayOptions, ReplayStateChangeEvent, ReplayStatus
  • EquivolumeRenderer exported from @tradecanvas/core
  • FibTimeZonesTool exported and auto-registered by registerBuiltInDrawingTools
  • 'equivolume' added to ChartType; 'fibTimeZones' added to DrawingToolType
  • Widget catalog (CHART_TYPES) lists Equivolume

Test coverage

  • New @tradecanvas/analytics package ships with 22 unit tests across Backtester, Portfolio, and RiskMetrics
  • New ReplayController test suite (8 tests) covering step, seek, start/pause/resume, fake-timer playback, and startIndex
  • Total project tests: 273 passing across 41 test files

0.7.1

1 件の変更

Bug fixes

  • Drawings persist correctly across timeframe / symbol switch — drawing manager state was being cleared when the live stream reconnected. Drawings now survive timeframe and symbol changes when persistDrawings is enabled

0.7.0

14 件の変更

Features

  • Multi-Chart Grid — new ChartGrid class for 2/4/6 synchronized charts with linked crosshairs and shared time axis. Layouts: '1x2', '2x2', '2x3' and more. connectAll() for bulk data source binding
  • 4 new chart types — Volume Candles (width proportional to volume), HLC Area (high-low-close band), Step Line (staircase pattern), Line with Markers (dots at data points). Total: 16 chart types
  • Command Palette — Ctrl+K / Cmd+K quick search inside ChartWidget for indicators, chart types, drawing tools, timeframes, and actions (screenshot, theme toggle, settings). Keyboard navigation with arrow keys and Enter
  • Visual Price Alerts — AlertManager.render() now wired into the overlay layer. Alert lines show bell icon, price label, and triggered/pending color states on the live chart
  • Signal Markers API — chart.addSignalMarker() renders directional arrows on the overlay with confidence-based sizing, per-source color coding, and labels. Designed for bot/signal trading integrations
  • Trade Zones — chart.addTradeZone() visualizes entry→exit rectangles with P&L coloring, direction badges, and exit labels. Supports active (open) and closed trades with updateTradeZone()

API additions

  • chart.getData() — public access to raw OHLC data series
  • chart.setCrosshairPosition(point) — programmatic crosshair placement for cross-chart sync
  • ChartGrid.connectAll(adapter, symbols, timeframe) — bulk connect all grid cells to live data
  • ChartGrid.setLayout(layout) — dynamically switch grid layout, adding/removing charts as needed
  • chart.addSignalMarker(marker) / setSignalMarkers() / clearSignalMarkers() / setSignalMarkerStyle()
  • chart.addTradeZone(zone) / updateTradeZone() / setTradeZones() / clearTradeZones() / setTradeZoneStyle()
  • New event types: signalMarkerAdd, signalMarkerRemove, tradeZoneAdd, tradeZoneRemove
  • New types: SignalMarker, SignalDirection, SignalMarkerStyle, TradeZone, TradeZoneDirection, TradeZoneStyle

0.6.0

32 件の変更

Features

  • 7 new indicators
  • Hull MA (overlay) — low-lag WMA-of-WMA-diff smoothing
  • Pivot Points (Classic) (overlay) — S3/S2/S1/PP/R1/R2/R3 with configurable lookback window
  • Anchored VWAP (overlay) — VWAP that resets at a chosen anchorTime
  • ZigZag (overlay) — swing-pivot connector with percentage-deviation threshold
  • Linear Regression Channel (overlay) — least-squares fit + std-dev bands
  • Awesome Oscillator (panel) — fast/slow median histogram with up/down coloring
  • Chaikin Oscillator (panel) — EMA(ADL, fast) − EMA(ADL, slow), exposes cumulative ADL
  • Range Bars chart type ('rangeBars') — fixed price-range bars (each bar's high − low equals a configured range), with toRangeBars transform
  • Trading overlay customization (additive, no breaking changes)
  • TradingPosition.closedQuantity — partial-close visualization as a left-edge dim band proportional to closed fraction
  • TradingConfig.pnlThresholds: PnLThreshold[] — multi-stop color gradient driven by live P&L
  • TradingConfig.positionLabel: string | (ctx) => string — token templating ({side}, {qty}, {openQty}, {closedQty}, {entry}, {price}, {pnl}, {pnlPct}, {pnlSign})
  • Web Worker indicator pipeline — new IndicatorWorkerHost and bundled indicator.worker.js register all 33 built-in indicators. Promise-based host.calculate(...) offloads heavy compute off the render loop. Pass null for the worker to use the synchronous fallback (SSR, tests, safety net). Per-request timeout, ping() health check, terminate() cleans up pending work

Type safety

  • New getNumberParam / getIntParam helpers exported from @tradecanvas/core
  • All 25 existing indicators migrated to the helpers — invalid params (NaN, Infinity, missing keys, non-numeric strings) now fall back to documented defaults instead of silently propagating to calculations
  • BinanceAdapter REST and WS payloads now flow through typed parseRestKline / parseWsKline validators; any[] and any casts are gone
  • TextAnnotationTool text resolution moved to a pure resolveAnnotationText helper (no more as string cast)
  • ChartStateManager.deserialize validates the parsed shape — malformed drawings/orders/positions/indicators are filtered, missing or wrong-typed viewport fields fall back to defaults

Internal refactor

  • WidgetStyles.ts (764 LOC of CSS-in-string) extracted into a sibling WidgetStyles.css file, imported via Vite's ?raw query and inlined at build time. The TS shim is now 31 LOC; CSS is editable as CSS (syntax highlighting, linting). Public API (injectWidgetStyles / removeWidgetStyles) unchanged.
  • Chart-type dispatch (createChartRenderer and getDisplayData) extracted from Chart.ts into a new ChartTypeStrategy module with createRendererFor, transformDisplayData, and isTransformedChartType helpers
  • Auto-save debounce extracted into AutoSaveScheduler (testable state machine, owner injects the save callback)
  • Indicator panel scaling math extracted into computeIndicatorPriceRange (now correctly skips NaN/Infinity values)
  • Removed duplicate timeframeToMs private method from Chart.ts; uses the shared helper from @tradecanvas/commons
  • Chart.ts: 1632 → 1536 LOC

Test coverage

  • 267 tests across 40 files (Vitest scaffolded in @tradecanvas/core and @tradecanvas/chart)
  • 25/33 indicators with direct test coverage
  • New tests for: indicator math (Hull MA, Pivot Points, Anchored VWAP, ZigZag, LRC, Awesome / Chaikin Oscillator, BB, ATR, Stochastic, OBV, VWAP, Ichimoku, Supertrend, Keltner, Donchian, ADX, CCI, MFI, Williams %R, Parabolic SAR), range-bar transform, trading position formatting, drawing-tool hit-test geometry, DrawingManager CRUD, Binance kline parsers, ReconnectManager backoff/cap/give-up, TickAggregator (tick + pre-formed-bar paths, ring buffer eviction), ChartState JSON + localStorage round-trip + validator, IndicatorWorkerHost (worker + fallback), ChartTypeStrategy, AutoSaveScheduler, IndicatorPriceRange
  • GitHub Actions CI workflow added under .github/workflows/test.yml (Node 20.19, pnpm 9.15, builds commons, runs pnpm test)
  • Root pnpm test runs both packages

Demo

  • Chart-types dropdown extended with Renko, Kagi, Line Break, Point & Figure, Range Bars
  • Indicator picker extended with Hull MA, Anchored VWAP, Pivot Points, ZigZag, Linear Regression Channel, Awesome Oscillator, Chaikin Oscillator (all 33 indicators selectable)

0.5.0

12 件の変更

Features

  • ChartWidget — built-in trading UI — new @tradecanvas/chart/widget subpath export. One-line embed with complete toolbar, drawing sidebar, settings modal, and status bar. Zero framework dependencies, CSS scoped with tcw- prefix
  • Typed event payloads — chart.on('orderModify', e => e.payload.orderId) infers payload type via ChartEventMap. Includes OrderModifyPayload, PositionModifyPayload, OrderPlacePayload, and 10 more typed payloads
  • Timestamp normalization — normalizeBar({ t, o, h, l, c, v }) converts wire format to OHLCBar. normalizeBarTime() auto-detects seconds vs milliseconds
  • chart.setTimeframe(tf) — switch timeframes on active stream without destroy/rebuild
  • chart.appendBars(bars) — bulk append for reconnect catch-up (single indicator recalculate)
  • chart.setStatusText(text) — display status in chart legend area (e.g. "LIVE · 8ms")
  • chart.setCurrentPrice(price, pulseColor?) — optional pulse color
  • DARK_TERMINAL theme — fintech terminal palette (#0E0E0E bg, #00FF87/#FF3B4D candles, monospace font)
  • DataAdapterEventType exported — adapters can implements DataAdapter with full type safety

Documentation

  • JSDoc on DataAdapter interface clarifying observer pattern (reconnect to switch)
  • OHLCBar.time documented as milliseconds
  • All event payload types exported from main index

0.4.0

12 件の変更

Features

  • Locale-aware number formatting — new numberLocale option on Chart (BCP 47 format like 'en-US', 'de-DE', 'vi-VN')
  • 'en-US' → 65,234.00
  • 'de-DE' → 65.234,00
  • 'vi-VN' → 65.234,00
  • Runtime change: chart.setNumberLocale('de-DE')
  • Affects price axis, crosshair tooltip, indicator legend, trading overlay

Bug Fixes

  • Keyboard shortcuts were broken — KeyboardHandler was constructed then discarded with void new. Arrow keys, +/-, Home/End, and Space did nothing. Now properly wired to window with focus-aware handling (ignores keystrokes in inputs/textareas)
  • Streaming indicators froze until bar close — updateLastBar() and updateLastBarFromTick() now recalculate indicators on every tick. Moving averages, Bollinger Bands, RSI, etc. now update in real-time
  • StreamManager listener leak — adapter listeners accumulated on reconnect because unsubscribers weren't tracked. Now properly cleaned up across connect/disconnect cycles
  • Price formatting without thousand separators — formatPrice() now uses toLocaleString for readability (65,234.00 vs 65234.00)

Performance

  • getBoundingClientRect cached in InteractionManager — was called on every mousemove. Now invalidated only on pointerdown, resize, and scroll. Major reduction in layout flushes during pan/crosshair
  • structuredClone replaced in drag/resize hot paths with hand-rolled shallow clone (5-10x faster for DrawingState shape)

0.3.0

14 件の変更

Features

  • WaterfallChart — Running cumulative visualization with positive/negative/total bar types. Perfect for P&L attribution, revenue bridges, cash flow analysis
  • Auto-detects bar type from value sign (explicit type always wins)
  • Dashed/solid/none connector lines between bars
  • Value labels, category labels, crosshair tooltip with cumulative total
  • GaugeChart — Speedometer-style gauge for KPIs, risk scores, sentiment
  • Colored zones for value ranges
  • Smooth setValue() animation with easeOutCubic
  • Configurable arc angles and thickness
  • Center value label + optional subtitle

Performance

  • Batched path operations grouped by color (single fill per color group)
  • Integer pixel rounding for crisp 1px lines
  • Cached trig calculations in gauge rendering
  • rAF-coalesced animation (safe on rapid setValue calls)
  • No per-element beginPath+stroke loops

0.2.0

13 件の変更

Features

  • Finance Chart Components — 4 new standalone chart types:
  • SparklineChart — tiny inline line/area chart for dashboards and KPI cards
  • DepthChart — bid/ask order book visualization with cumulative volume areas
  • EquityCurveChart — portfolio equity with drawdown shading and benchmark comparison
  • HeatmapChart — colored cell grid with treemap layout (weighted by market cap)
  • Client-side order matching engine — auto-fills limit/stop orders with configurable spread and commission
  • Trade history — tracks fills, SL/TP triggers, manual closes with win rate and PnL stats
  • Toast notifications — animated alerts for order fills and SL/TP triggers
  • StackBlitz sandboxes — "Open in StackBlitz" for Vanilla JS, React, Svelte, Vue
  • Finance charts demo section — live sparklines, equity curve, depth chart, heatmap on demo page

Bug Fixes

  • Sparkline container bindings in Svelte 5 — use plain array for bind:this in {#each}
  • BaseFinanceChart re-measures dimensions if 0 on first render (initial mount race)
  • Rename version and release scripts (npm reserved lifecycle names)

0.1.3

8 件の変更

Bug Fixes

  • Panel indicators not rendering until chart interaction — addIndicator() now calls updateViewportAndRender() for panel indicators so they appear immediately
  • Stop orders showing LIMIT label — context menu orders now preserve the correct type (LIMIT, STOP, STOP LIMIT)
  • npm publish with workspace:\* deps — previous versions were published via npm publish which doesn't convert workspace:*. Now using pnpm publish for proper version resolution

Features

  • Auto-scale includes overlay indicator values — main chart Y-axis expands to fit Bollinger Bands, Ichimoku, Keltner, etc. instead of clipping them
  • TC prefix on all generated IDs — indicator instances (tc_sma_1), drawings (tc_drawing_1), alerts (tc_alert_1) to prevent collisions
  • Trade-on-chart via built-in context menu — right-click to place Buy Limit, Sell Limit, Buy Stop, Sell Stop at clicked price
  • Viewport.setPriceRange() — new public method for direct price range control
  • IndicatorEngine.getOverlayPriceRange() — compute min/max of visible overlay indicator values

0.1.2

12 件の変更

Features

  • Demo site — Svelte 5 demo with a full trading UI (live chart, drawing sidebar, dropdowns, settings modal)
  • Developer documentation — 11 guide sections: Getting Started, Data, Adapter, Themes, Indicators, Drawings, Trading, Features, Events, State, API Reference
  • StackBlitz sandboxes — interactive "Open in StackBlitz" for Vanilla JS, React, Svelte, Vue
  • Paper trading panel — fake buy/sell with balance, PnL, localStorage persistence
  • Replay button — play/pause/stop in toolbar header
  • Package manager switcher — npm/pnpm/yarn tabs on install command

Examples

  • Updated examples/basic and examples/vanilla-static with modern UI
  • Added examples/svelte (Svelte 5 + Vite)
  • Added examples/vue (Vue 3 + Composition API)
  • Updated examples/react with toggle buttons and chart type dropdown

Documentation

  • README with Svelte and Vue framework integration examples
  • Per-package READMEs for npm pages (@tradecanvas/commons, @tradecanvas/core, @tradecanvas/chart)

0.1.1

5 件の変更

Bug Fixes

  • Fix repository URLs pointing to wrong GitHub repo
  • Fix all TypeScript declaration errors (unused imports, missing index signatures, missing TimeFrame entries)
  • Fix volume type mismatch in DataManager sanitizeBar
  • Add publishConfig.access: "public" for scoped packages
  • Add prepublishOnly build scripts

0.1.0

Initial release of @tradecanvas/chart, @tradecanvas/core, and @tradecanvas/commons.