Release notes
All notable changes to this project are documented in this file. The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
-
The channel studies open with their usual inputs and fill their bands. Envelopes opens at 10% and fills the band between its upper and lower lines. Keltner Channels take a source (close by default), an exponential or simple middle line (exponential by default) and a band style,
KeltnerBand: Wilder’s average true range (the default), the bar’s own true range, or Wilder’s average of the bar’s high minus low over the middle line’s length; the default inputs give the former values bit for bit.LinearRegressionChannelopens at 100 bars, takes separate upper and lower deviations (2 each;with_multiplierssets them andnewsets both) and fills the band above and the band below its middle line. MA Channel draws the simple average of the highs as its upper line and of the lows as its lower line, each with its own length (20) and bar offset (0), and fills the band between them. All fills use the faint shade Bollinger Bands and Keltner Channels already use, and a colour list with at least as many entries as the study has lines replaces that many leading colours, so a list without the fill colours keeps the fills. Saved templates and layouts keep loading:StudyTemplate::create_withupgrades a regression channel saved with onemultiplierto both deviations and loads an MA Channel saved before this change as Envelopes with its length, percentage, a simple average and its styles, which draws exactly the lines it had. (#1492) -
Long and short position drawings are edited by level. Their Inputs tab lists Entry price, Target price and Stop price, and Target and Stop distances in ticks that follow the prices, using the tick size of the chart’s instrument; without one the tick rows are disabled and the tab says the tick size is unavailable. Changing the entry moves the target and the stop with it and keeps their distances, and a position with two anchors gains an explicit stop, mirrored from the target about the entry, only when a level is edited. Target colour and Stop colour set the zone and level colours; they are saved with the drawing, its templates and defaults and carried through previews, cancellation and undo, and without them the former colours apply, so saved drawings keep their look. The entry, target and stop prices are tagged on the price scale of the pane that owns the drawing, the target and stop in their colours, with the scale’s own formatting, contrast and overlap handling, whether or not the drawing is selected and only while the drawing is visible. (#1408)
-
SymbolSearchDialog::open_with_selected_queryopens symbol search with the supplied text selected on its first focused frame, so typing replaces it, whereopen_with_querykeeps the text of a typed shortcut with the cursor after it. The demo and terminal pass the current symbol when the user opens search explicitly, and a clear control in the query row empties the query. (#1561) -
A drawing can be shown on ranges of intervals of every unit. A drawing limited to some intervals could be shown only on nine fixed intervals, from 1min to 1M, so it disappeared on 2h, 3min, seconds, ticks, ranges and every other interval, and a level drawn on a 4h chart could not also be kept on the 2h chart.
TimeframeVisibility::rangesholds, perTimeframeUnit, a range of values with both ends included, andis_visible_onreads the unit and value from the interval’s label asTimeframe::as_strwrites it (90minis 90 minutes, and a 24 hour interval labelled1Dis 1 day);rangeandset_rangeread and write a unit’s range, andset_rangereplaces that unit’s saved labels. Labels saved before ranges are still matched exactly. The Visibility tab has one row per unit (ticks, volume, range, delta, milliseconds, seconds, minutes, hours, days, weeks and months) with a checkbox and from and to values, and writes only the row the user edits, so the saved labels of other units keep their exact visibility. A filter that names no interval and holds no range loads as show on all, and a drawing restricted by ranges alone stays restricted after a reload. Files of drawings without ranges are written byte for byte as before. (#1368) -
examples/network_feed.rsconnects a chart to a network backend, natively and in the browser. It implementsDatafeedover HTTP:resolveandhistoryfetch JSON and answer theirReplyafter the call has returned, from a thread natively and from afetchtask on wasm32, andhistorysendsbefore,sinceandcount. HTTP statuses map toFeedErrorcategories whose recoverability decides whether the chart retries: a server error is aNetworkerror, 429 isRateLimitedwith itsRetry-After, and 404 isSymbolNotFound. Live trades arrive as server-sent events and go into the subscription’sSinkuntil it becomes inactive. The example starts its own backend of generated sample data on a local port, which fails every fourth history request on purpose so that scrolling back shows the retry, and--serveruns the backend alone on port 8090 for the browser build ofexamples/network_feed.html. The library’s dependency tree is unchanged: the native client is plain HTTP overstd::netand the browser client usesweb-sysas a wasm32 dev-dependency. The builder guide and the README list the example. (#1486) -
The drawing bar’s magnet button switches the magnet on and off with one click and keeps its strength, and a secondary click opens Off, Weak, Strong and Snap to indicators, where a menu selection was needed to switch it. The Hide menu gains Hide all and the Remove menu gains Remove drawings and indicators, through
DrawingToolbarAction::HideAllandDrawingToolbarAction::RemoveDrawingsAndIndicators; the terminal and demo apply each as one undoable operation. The Gann section lists box, fixed square, square and fan, in that order. (#1409) -
Instrument::profile_resolutionslets a feed suggest, fromDatafeed::resolve, the bars volume profile studies read: eachProfileResolutionnames an interval and the longest profile it serves, measured from the open of the profile’s first chart bar to the close of its last, or any length. While the Source interval input follows the chart and the new Feed suggested interval input is on, as it is by default, the visible range, fixed range, session, periodic, anchored and auto anchored profiles request the shortest suggested interval shorter than the chart’s that serves their length: the visible bars for the visible range profile, the longest period for session and periodic profiles. When the length crosses a limit the request changes and replies for the previous interval are dropped. Without suggestions the studies spread each chart bar’s volume as before. (#1087) -
The session volume profile adapts its rows to the zoom with the new Adapt rows to zoom input. Every session in view then takes one row height, the price range of their chart bars divided by Row count, raised to 1, 2 or 5 times a power of ten ticks of the instrument’s tick size, or of price without one, in place of the Height input. Zooming in to fewer sessions gives finer rows and zooming out coarser ones, each row a whole number of ticks on a grid from zero; volume, point of control and value area follow the same rules as before, and a flat range keeps the configured rows. (#1087)
-
The Style tab offers Line start and Line end choices (Plain or Arrow) on trend lines, rays, extended lines, info lines, trend angles, horizontal lines, horizontal rays, vertical lines, arrows, arrow markers, paths and polylines. Rectangles and parallel channels offer an optional thin dashed Middle line, off by default, that follows their extensions; the channel’s checkbox moves from its Inputs tab, which is no longer shown for it, to the Style tab. These settings use the existing drawing defaults, persistence and undo paths. The rows come from
DrawingToolType::supports_line_endsandsupports_middle_line, which a test compares with what each renderer paints, so the dialog cannot offer a row that does nothing or miss one a renderer honours. (#1372, #1453) -
Shift holds a trend line, ray or channel point to 45-degree steps while it is placed or dragged, makes a new ellipse a circle and keeps a moved drawing on its bars or on its prices. Ctrl/Cmd-drag on a drawing leaves it in place and drags a copy that one undo removes, and Ctrl/Cmd held during a gesture inverts the magnet for that gesture without changing the toolbar setting. With an unlocked drawing selected, Left and Right move it by one bar and Up and Down by one price step (the instrument’s tick size, else one unit of its last price decimal), each press one undoable edit; with none selected the arrows pan as before. (#1365)
-
Selected icons, emoji and stickers show a square frame with four corner handles that resize them around the centre within the shared font size bounds, as one undoable drag. (#1401)
-
Fibonacci time zones, trend-based time, speed resistance fans, circles and speed resistance arcs draw saved, editable levels, each in its own colour, and share the Inputs level grid with retracements, extensions, channels, wedges and pitchforks: visibility, value, colour, a line style and width where the level has one, one colour for every level, and background opacity in percent. Wedges show their level colours and background, and
PitchforkLevel::widthsets each pitchfork level’s width.FibonacciConfig::show_prices,show_levels,levels_as_percentandlabels_on_leftchoose whether labels show the price and the level, as a ratio or a percentage, and on which side they sit; labels are derived from the level value, and saved custom labels are kept. New drawings of the five tools start with their level tables (FibonacciConfig::for_tool); drawings saved without levels keep their fixed presentation, and wedges saved with levels now draw them in their saved colours.ChartView::y_to_pricegives channel labels the price at their displayed end on every scale. Migration:FibonacciConfigliterals addshow_prices: None,show_levels: None,levels_as_percent: trueandlabels_on_left: false, or use..Default::default();PitchforkLevelliterals addwidth: Noneto inherit the drawing width;ChartViewliterals addy_to_price, the inverse ofprice_to_y. (#1379) -
FloatingSelectionToolbar::show_and_applyfollows the selected drawing with the shared colour palette, fill or text colour where supported, line width and line style, applying each edit immediately with undo. The terminal and demo show the draggable toolbar beside the selection, keep it within the viewport, hide it while dialogs are open and offer settings, lock, delete and the drawing context menu in More. The drawing menus also offer Bring forward, Send backward and Copy; single-step moves cross exactly one neighbour even when layers are tied. (#1366) -
The account panel loads older history from the broker. Scrolling to the end of Order History, its executions, Balance History or Trading Journal, or showing one empty, asks
Broker::historyfor the entries before the oldest one listed, in a range that ends one second after it, then follows the page cursor until the broker has nothing older or the history lists 1,000 entries. An entry is listed once, whether a page or the live stream brings it first: orders are matched by id and other entries by value, each listed entry matching one entry of a page, so two equal fills stay two. Pages never replace working orders, positions or the account and raise no notification or sound, and an answer that arrives after the account changed or the stream restarted is dropped. A broker without history answersFeedError::NotSupported, which ends paging quietly; any other error is shown once and ends paging of that history until the broker connects again. (#1097) -
strategies::Backtest, behind the newstrategiesfeature, runs astrategies::Strategyover bars and returns a completeStrategyReport, so the report’s metrics,StrategyReportPaneland the CSV exports work on its output unchanged. A strategy computes what it needs from the whole run once inprepare, then decides on each closed bar inon_barthrough aStrategyContextthat shows only the bars up to that bar and the open position. It places named entries (market, limit, stop and stop-limit, long or short) and exits with a take profit, a stop loss or neither, and cancels them by name; an order placed with the id of a working order replaces it, keeping its original place among orders reached at the same point. Orders fill no earlier than the next bar, along its path from the open to the extreme nearer the open (the high first for ties within a few ulps), then the other extreme, then the close, at the order’s price or at the open after a gap, with the paper account’s fill rule;fill_on_closefills market orders at the close of the bar they were placed on instead. An exit fills whichever of its take profit and stop loss the path reaches first. It only reduces the position open when it is placed, or, placed while flat, the position the next entry opens, and is cancelled once that position is closed or reversed, as the paper account cancels its exits. An entry against an open position closes it before opening the other side. Each entry is a trade, closed first in first out with each partial exit its own trade, labelled with its entry and exit orders. Decimal closes and scaling out leave no dust trades. Flat positions and breakeven profits use positive zero, including in the trades CSV. The equity curve starts with the initial capital one interval before the first bar and marks the account at each bar’s close, stamped with the bar’s time. Bars with non-finite prices or with an open or close outside their high and low fill no orders and have no equity value. Fees, slippage, margin and pyramiding limits are not modelled. It needs no egui, so a server can run the same code. (#1151) -
services::OrderFlowDetectors, behind the new headlessdetectorsfeature, is a ready-madeSignalsservice that finds order-flow events in the events a host already pushes into the chart’sSink: the host callstrackwith eachInstrument(its tick size is required),pushwith eachdata::MarketEventtagged with its symbol and feed time, andpush_historywith loaded trades, and connects the service withChart::set_signal_source. Events of untracked symbols are ignored,untrackandresetdrop a symbol’s state, trades with an id already seen are dropped, so the trade of an order execution counts once. Grouping uses the aggressor id on the first copy: push the execution before its tape copy or carry the id on the print. Depth and order events keep the symbol’s book with theSink’s sequencing rules, a gap clearing it silently until the next snapshot. Every window runs on feed time, so replay gives the signals live data gave. Trade timestamps must be valid feed times: a far-future print can end zones at that time and block body or wick classification untilreset.subscribepushes the symbol’s most recent 5,000 detections, then each new one, removing evicted detections from live streams too, in one signal category perDetectionKind.DetectorSettingsholds per detector (Detector) whether it is enabled, whether its live detections should alert and play a sound, and its rule;set_settingsapplies to later events and panics on a fixed threshold that is not positive and finite. The first detector finds big trades (BigTradeRule): fills sharing an explicit aggressor order id form one trade, aggregated in constant space and work per fill, large once its size reaches aThreshold, fixed or automatically the 99th percentile of the symbol’s last 10,000 trade sizes, recomputed every 100 trades and inactive until 1,000 have been seen. A large trade is marked at its first fill time and volume-weighted price, coloured by its aggressor side, labelled with its size and updated as its fills arrive, and projects a zone over its fill prices, at least one tick high, until a trade at or after its start lies strictly beyond its far side. The latest subscription chooses one interval per symbol for all its charts: intraday bars use the exchange time zone and regular session, daily and longer bars use UTC, and display time zone and extended hours do not apply. Once the bar of that interval that holds it closes, a trade is in the bar’s body or a wick, andbody_zonesandwick_zoneschoose which zones stay. Zones in a bar not seen from its open, under a trade-based interval, or first detected after their first fill’s bar closed stay without body or wick classification. (#1142, #1143) -
The prelude exports
HistoryPageandSubscription, so a host can implementDatafeed::historyandsubscribewith the prelude as its only import. (#1317) -
TradingRules::pip_valuegives the value of one pip for one unit in the account’s currency, and the order ticket shows it as Pip value for the order, taken from the broker’s rules or else from the instrument’s pip size times the point value, and left out when neither is known.Trading::set_instrumentdescribes the other symbols of the account, so the account tables write their prices, and the order editor takes its decimals, from each row’s symbol instead of the chart’s decimals or two, andTrading::set_formattertakes aTradingFormatterwhose price, quantity, spread and pip value text, per symbol, replaces the built-in text in the ticket, depth ladder and account tables. Rules with a non-positive pip value are rejected like other invalid rules. (#1125) -
ChartBuilder::with_locale,with_time_formatter,with_price_formatter,with_percentage_formatter,with_volume_formatter,with_storageandwith_study_factoryinstall the chart’s locale, formatters, drawing storage and the study factory at construction, andChartBuilder::build_restoredbuilds the chart with them, then restores aChartSnapshotthrough the factory, so restored studies and series see the host’s formatters and storage before the chart is first used. A snapshot that cannot be restored returns an error and no chart; the drawings that could not be read come back with the chart, andChart::restored_series_idmaps the saved series to the new ones for the host to bind its data again. (#1102) -
ChartSnapshotsaves the bar series added withChart::add_series(ChartSnapshot::series: options, visibility, pane, markers, marker options and price lines) and the main series’ markers and price lines (main_annotations), andSavedLayoutdocuments are version 3; versions 1 and 2 still load and leave the chart’s added series in place.Chart::restorereplaces the added series with the saved ones, without bars and under new ids thatChart::restored_series_idmaps from the saved ones, so the host binds its data again withset_data.Chart::snapshot_withandChart::restore_withtake anIndicatorFactory, as doesStudyTemplate::create_with, so studies a host registers are saved and restored with their inputs, styles and links. Restore now checks before changing the chart that each study source names a saved study and a plot of it and that sources form no cycle, and that no series or study id repeats; a failing check leaves the chart as it was.Marker::coloris saved with the marker, andPriceLine,SeriesOptions,SeriesStyle(without its autoscale function),MarkerOptions,MarkerZOrderandPriceLineSourceare serializable. Migration:ChartSnapshotliterals addseriesandmain_annotations; a host that saves its own series metadata and adds the series again afterrestorenow gets them twice from a new snapshot, and setsseriestoNonebefore restoring to keep its handling. (#1058) -
Profilesis a host service for profiles and follow relations:watchpushesProfileEvents carryingProfiledetails and the host-reported follow state, andfollowfollows or unfollows aProfileId, which the host may refuse.ProfileDirectoryholds one account’s profiles, reports each request asFollowStatus::PendingorFailedthroughoperation, repeats nothing on its own, andset_servicedrops the previous account’s profiles and requests and ignores its late answers.Notification::targettakes aNotificationTarget::ProfileorRoom, which the notifications panel offers as an Open profile or Open room button and reports asNotificationsAction::OpenProfileorOpenRoomfor the host to perform.ui::profile::ProfileCardembeds the latest profile name, bio, avatar and follower count in any layout, sends Follow and Unfollow through the directory, disables the control while pending and shows host failures with retry and dismissal. It keeps no account details of its own; an unknown or removed profile shows as unavailable. Removing or clearing profiles also invalidates their follow requests, so late answers cannot settle a newer request for the same identifier. Accounts, authorization and delivery stay with the host. (#1123) -
Broker::historyanswers one page of finished history older than whatconnectpushed, throughHistoryRequest(aHistoryKindof orders, executions, balance changes or journal lines, an optional UTC range, a cursor and a page size) andHistoryPage. Pages come newest first with a cursor to the one before, hold only finished orders, fills, balance changes and journal lines, never working orders or positions, and may repeat live entries unchanged so a consumer can drop duplicates, orders by id and other entries by value. The default answersFeedError::NotSupported, so existing brokers are unchanged. (#1097) -
Storagecan keep document revisions:load_versioned,save_versionedandwatchhave defaults that refuse or push nothing, so existing hosts are unchanged. A host that implements them makes the library write a document only over the revision it read; a write over a newer revision changes nothing, answersSaveOutcome::Conflictwith the stored version and leaves the newest unsaved document in memory, never writing it until the user’sConflictChoicetakes effect: reload the stored version, save the unsaved one as<name> (local copy)(or<name> (local copy 2)and so on if that name is taken) and reload, or write over the stored version.SettingsStorereads a change another client made once nothing is unsaved and returns it frompolllike the first read; while settings are unsaved it reads nothing, so their write is refused instead, andconflictis true untilresolve_conflictapplies the user’s choice.ui::dialogs::StorageConflictDialogasks for that choice, and the terminal shows it when its settings conflict and performs the answer asAction::StorageConflict. A newStoragefor another account drops the old one’s pending answers and watch streams. (#1100) -
Session::overridesholdsSessionOverrideentries, the regular and extended windows of one trading date, for early closes, exceptional openings and closures; an override with no windows closes its date. An override replaces the weekly windows and a listed holiday of its date, and the first of two overrides for a date applies. Windows are named by their closing day and may cross midnight, as weekly ones. Bar clocks, history and session boundaries, daily bar closes, the countdown, extended-hours shading and the studies that anchor on trading dates all read the hours throughExchangeSessionProvider, so they follow the overrides across daylight-saving changes. (#1127) -
Alerts can test a value inside or outside an inclusive channel with
AlertCondition::InsideChannelandOutsideChannel, which hold on every evaluation while the value is in that state, unlike entering and exiting.AlertFrequency::OncePerMinuteallows one trigger per UTC clock minute.Alert::scheduleholds an optionalNotificationSchedule, a named time zone, weekdays and time windows, including windows that cross midnight and belong to the weekday they start on, andNotificationSchedule::allowstells whether a trigger time is inside it. The alert dialog edits the new conditions, the frequency and the schedule, rejects empty or malformed schedules, and presets keep them;Alertsdocuments the semantics for services, andAlertEngineevaluates the new conditions and frequency and callson_triggeronly for triggers the schedule allows. (#1047) -
HistoryRequest,TradeRequestandDepthRequestcarry an explicit range,since(inclusive) with the existingbefore(exclusive), alongsidecount.Chart::scroll_to_timebounds the pages it asks for by the target time. An emptyHistoryPage,TradePageorDepthPagemay namecontinue_before, where older data continues, so a weekend or other gap no longer ends history and the next request starts there instead of repeating; a continuation that does not lie before the request stops paging withFeedError::InvalidData. Charts page older trades into the held ones when the view reaches the oldest trade, while bubbles, a footprint or a study use them, merged by the existing id rules and retried and cancelled with the other requests, and study sources on other symbols follow continuations.FeedState::trade_history_completeanddepth_history_completereport whether more can be loaded. Migration:HistoryPageis now#[non_exhaustive]; replaceHistoryPage { bars, end_of_history }withHistoryPage::new(bars, end_of_history). (#1080) -
Chart::set_conversioncarries a host-chosen currency or unit through the feed:Datafeed::resolve_converteddescribes the symbol in it, andHistoryRequest,TradeRequest,DepthRequestandSubscriptiongainconversion, which also reaches the studies on other symbols. A changed choice drops the data held, discards replies and subscriptions of the previous choice and reloads, and the legend shows the resolved instrument’s currency and unit only once it arrives. A feed that cannot convert answersNotSupported(the default) and the chart shows no data instead of unconverted data. The library converts nothing. The request structs are#[non_exhaustive], so hosts that only read them need no change. (#1126) -
services::Sharinglets a host share layouts and watchlists:offersreports perShareKindwhetherlinkandcopyare available,linkanswers a view-onlyShareLinkthat says whether a recipient may save a copy, andcopysaves a copy and answers its name.LayoutMenu::set_sharingandWatchlistPanel::set_sharingadd Copy link and Save a copy rows only for what the host offers, disable them while an operation is pending, copy the link to the clipboard and show the reported copy policy, the saved name or the host’s rejection. A layout copy appears in the menu once re-listed fromStorage; a watchlist copy is added to the panel’s lists. Accounts and cloud storage stay with the host. (#1099) -
Datafeed::capabilitiesreports what a feed offers as a whole before any symbol resolves:FeedCapabilitieslists its intervals, exchanges, symbol classes and optionalFeedServices, each either unreported (None, which restricts nothing) or a list, where an empty list means none. The chart asks once when the feed attaches andChart::feed_capabilitiesreturns the answer.TimeframeSelector::set_feed_capabilitieslimits the interval choices to the feed’s, alongside a symbol’s ownset_supported_timeframes, andSymbolSearchDialog::set_feed_capabilitiestakes the source menu’s exchanges and the category tabs from the feed.FeedCapabilities::offerstells a host whether to show the controls of a service. The default answers nothing, so existing feeds are unchanged. (#1098) -
ChartMenus::series_click_pricereturns the price of the series menu’s last right-click, whichSeriesContextMenuAction::CopyPricedoes not carry. (#1214) -
WatchlistPanel::show_widedraws the active list as a wide table with everyWatchlistColumn::WIDEcolumn and Earnings, Dividends and News tabs filled from the host’sWatchlistDetails; its view button returnsWatchlistAction::CompactView, andAdvancedViewasks for the wide view. The tabs list the rows of the selected symbol, or of every shown symbol while none is selected, and clicking a symbol selects it. Selection, sorting, the active list and the flag filter belong to the panel, so switching views keeps them.SymbolDetailsPanelgains Performance and Seasonality sections:take_market_requestsreturns aMarketDetailRequestfor each section a symbol still lacks and marks it loading, and the host answers withset_period_returns(PeriodReturn) andset_seasonality(Seasonality,SeasonalityMonth); answers for another symbol are ignored. Every host-supplied section is aMarketDetailand says whether it is loading, empty, unavailable or failed. A host that never asks sees none of it. (#1056) -
Watchlists duplicate, filter by flag and show more quote columns. The list menu duplicates the active list as “Name copy” (
Watchlist::duplicate), keeping sections, symbol order and flags, and the Flagged symbols swatches show the symbols flagged one colour across every list, each once, so the red-flag view follows flag changes; a flag change or removal in that view applies to every list that flags the symbol that colour (WatchlistPanel::set_flag_filter,flag_filter);symbolsthen returns the flagged symbols so the quote subscription follows.WatchlistPanel::set_columnsaddsWatchlistColumn::Volume,ExtendedLast,ExtendedChangeandExtendedChangePercent, measured from the regular last price, which sort with missing figures last and show a dash when the quote lacks them; they follow the live quote stream.ChartMenus::set_watchlistsadds a submenu to the chart menu that returnsContextMenuAction::AddToWatchlist { list, symbol }, applied withWatchlistPanel::add_symbol_to, which refuses a symbol the list already holds.WatchlistColumnis now#[non_exhaustive]. Migration: matches onWatchlistColumnadd a wildcard arm. (#1055) -
The order ticket offers its risk percent sizing for limit, stop and stop-limit entries, sized from the entry price with the same validation as a market entry. Orders from the depth ladder take the ticket’s enabled take profit and stop loss, priced from the ladder order’s own side, entry and quantity, and the confirmation lists them; an invalid exit refuses the order and says why.
Capabilities::close,reverseandprevieware reported independently: the Close and Flatten controls, the Reverse controls and the new Preview order button appear only when set, and the ladder’s disabled buttons explain why.Broker::previewanswers anOrderPreview(cost, commission, margin and warnings) without placing the order; the ticket then confirms that exact request, and a refused preview shows an error. Migration: an account that closes and reverses positions through its market orders setscloseandreverse, whichPaperBrokernow does; without them the Close, Flatten and Reverse controls are hidden.Brokerimplementations need no other change. (#1054) -
The layout menu stars saved layouts and filters the list to the starred ones with a Favorites toggle, keeping the current layout selected.
LayoutMenu::favoritesholds the starred names, follows a rename, loses a deleted layout and is kept between sessions in the newUserSettings::layout_favorites; documents written before read with none. (#1051) -
AlertsPanelorders its list by name, symbol or status, ignoring case, in either direction, with equal values in arrival order, and offers a Duplicate button that returnsAlertPanelAction::DuplicateAlertwith a copy that has no identifier and is active, forAlertDialog::edit. A Quick alert form creates price, study-output and volume alerts with the dialog’s condition editor andAlert::is_valid, starts on the symbol given toAlertsPanel::set_symbol, offers the outputs given toAlertsPanel::set_sources, and sends them through the connectedAlertsservice; a save or removal waiting for the service is shown, a failure keeps the form and its error, and the list changes only when the service pushes. (#1046) -
The market heatmap shows a universe chosen from
MarketHeatmapPanel::universes, sizes its tiles by oneMarketHeatmapMetricand colours them by another, both chosen independently in the panel from the host’s metrics with their labels, units and availability, and draws a legend of the size metric and the colour scale.MarketHeatmapPanel::selection(MarketHeatmapSelection, alsoUserSettings::market_heatmap) holds the choices for settings restore; a chosen universe or metric the host does not offer or has no data for stays chosen and shows as unavailable. Migration: replaceMarketHeatmapPanel::entrieswithuniverses, put the formervalueandchange_percentof eachMarketHeatmapEntryintovaluesunder the identifiers of twoMarketHeatmapMetrics listed inmetrics(the second may setsaturation: Some(5.0)for the former fixed scale). (#1124) -
The screener sends the market, a text description and a page offset in
ScreenerQuery::universe,textandoffset.ScreenerPanel::set_universesoffers the host’sScreenerUniverses (stocks, funds, bonds, coins, exchange pairs) in a selector;set_text_queryadds a field whose description the feed interprets in the optionalDatafeed::screen_text, answering the rows with an explanation (ScreenerTextAnswer) shown above them; a full answer offers Show more for the next page.set_storagelets the user save, rename, load and delete named screens in the newStoreKind::Screens, each holding its universe, column set, filters, sort order and description, so a restored screen sends the same request. The chosen criteria stay through loading, failures, paging and CSV export. (#1096) -
Chatsoffers optional host operations, enabled throughChats::capabilities:find_usersto choose recipients,create_roomfor direct, private and group rooms (NewChatRoom), andadd_memberandremove_memberfor rooms whose members the host pushes withChatEvent::Members. Users and rooms keep the host’s stable identifiers (ChatUser). The chats panel header offers New chat and Members where the host allows them, shows each action while it is pending and when the host refuses it, keeps the form after a refusal, opens a created room once pushed, and clears the form, recipients and pending actions whenChatsPanel::set_serviceattaches another service. Accounts, authorization and delivery stay in the host. (#1094) -
StrategyReport::summary_csvwrites the summary metrics and run properties the report panel shows as a table with the columnssection,name,value,unitandcurrency: money in the report’s currency, percentages as 100 for 100%, and an empty cell for an unavailable value. The panel’s new Export summary CSV button returnsStrategyReportAction::ExportSummaryCsv { filename, content }beside the trades export. (#1121, #1157) -
NewsQuerycarriessymbols,topicsandproviders, and the news panel offers them:NewsPanel::set_symbolsadds symbols to the followed one, andset_topicsandset_providerslist the topic values and provider identifiers the feed supports. Every change sends the complete selection throughDatafeed::news, a superseded reply is ignored, and the choices stay selected through loading, empty and failed states and while the host offers the same values again. Migration: readNewsQuery::symbols, empty for the whole market, instead ofNewsQuery::symbol. (#1101) -
The depth ladder’s View menu shows columns for the order count of each side, the observed size change of each side and the volume traded at the bid and the ask, independently, beside the resting size and the last account fill. The hover text uses the same values: a change is one observed between book snapshots, not confirmed execution or cancellation, and an order count the feed did not send is shown as unavailable. The price column’s profile is total volume, delta or bid and ask volume, summed over the retained trades, the trades since the open of the current exchange session, or the trades since a manual reset, which later live trades extend. (#1077)
-
Order flow studies sum the same executions three more ways, added like any indicator: Multi-Range Delta (
OrderFlowKind::SizeDelta) gives the buy minus sell volume of three independent inclusive size ranges, Rolling Volume and Delta (FlowSum) sums the volume and the delta over a number of bars, drawn as histograms or lines, and Size-Filtered CVD (FilteredCvd) accumulates the delta of executions in a size range in its own pane. A bar without executions is a gap; a rolling sum over a gap or before its warm-up is a gap, and a cumulative sum carries over a gap. Trades of unknown side add to the volume but to no delta. Live updates, history merges and evictions follow the trade rate’s, andupdaterecomputes only from the first changed bar. (#1078) -
OrderFlowKind::AggressorRategives the bar total and the rolling and instant rates per second of distinct explicit aggressor order ids, counting an order once however many fills it has and neither merging nor counting fills without an id.OrderFlowKind::LevelsExecutedcounts the distinct prices that buy and sell executions printed at, per bar or over a rolling window, optionally restarting a side when its executions reverse; unlikeLevelsTradedThroughit ignores quote movement, so cancellations add nothing. Both are Order flow studies (Aggressor Rate, Levels Executed) and follow history merges and evictions as the trade rate does.CombinedTrade::consumedlists the resting orders (ConsumedOrder: id, price, size) that an aggressive order’s retained fills took, summing to its size, andCombinedTrade::completesays whether its aggressor and every resting order are named. Time and sales shows that breakdown when hovering a fill with an aggressor order id. (#1072) -
Trade profiles choose volume nodes through
FootprintConfig::node_sensitivity(NodeSensitivity):smoothingaverages each price row with that many rows on each side, andprominenceis the smallest rise or drop against the neighbouring plateaus, as a share of the largest smoothed volume. Untraded prices count as zero volume, so a gap between traded prices is a valley, found as one span however wide. Rows of equal smoothed volume form one plateau, reported once at its lowest row.TradeProfile::nodestakes the sensitivity, whose default compares neighbouring rows as before.FootprintConfig::value_area_highandvalue_area_lowdraw the VAH and VAL guides on the outer edges of the shaded rows, each with its ownStrokeor hidden withNone. Migration:FootprintConfigliterals addvalue_area_high,value_area_lowandnode_sensitivity, andTradeProfile::nodescallers passNodeSensitivity::default(). (#1079) -
Book size, the liquidity heatmap and the depth ladder count individual resting orders through one
data::OrderFilter: a minimum order size applied before aggregation, a minimum resting age measured from the placement time the feed supplies, and excluded participants.RestingOrder::with_participantandwith_placedcarry that metadata, never inferred.OrderFlowStudy::with_order_filter(and the study’s Minimum order size and Minimum resting seconds inputs) filter book size,DepthHistoryConfig::orderssamples the heatmap from the accepted orders instead of the aggregate prices, andChart::set_order_book_viewapplieschart::overlays::OrderBookViewto the heatmap’s profile and the ladder: the profile measures the total resting size or the largest known individual order at each price (BookProfile), and twoOrderSizeTiershighlight prices whose largest known order is notable or large, in the profile and the ladder’s size cells.OrderQueue::filteredgives hosts the same summed book. With aggregate depth only, or when no order carries the participant or placement time the filter needs, book size has no value, the heatmap has no column, the ladder shows no sizes and the pane says so (OrderFilterUnavailable), rather than showing unfiltered sizes. Migration:DepthHistoryConfigliterals addorders: Noneor use..Default::default();RestingOrderis#[non_exhaustive]and gainsparticipantandplaced. (#1073) -
cargo bench --bench heatmapmeasures the liquidity heatmap of a book of 1,000 levels a side at a 50 ms column cadence: sink time per delta, frame time, texture upload, textures and heap, with the history filled to every resolution.docs/order-flow.mddocuments the configuration, the measured budget on a stated machine (a frame under 5 ms and 56 MB of heap) and the degradation policy.DepthHistorynow shares its columns, soLiquidityHeatmaptells a changed column by identity instead of keeping a copy of every column and comparing each frame: for 1,000 levels a side and a full history its heap falls from 110 MB to 56 MB and its median frame from 9.8 ms to 2.1 ms. (#1112) -
Footprint studies take a
FootprintStudyConfigand report where each level stands.delta_percentandratiomark bars whose absolute delta, as a share of all volume with unknown side included, or buy-to-sell volume ratio reaches a threshold (equality counts; a side with volume against none meets any ratio) asFootprintStudyKind::DeltaAsk,DeltaBid,RatioAskandRatioBid, drawn as triangles above or below the bar.min_deltagives the delta POC a minimum absolute net delta, with ties still going to the lower price.UnfinishedAuctionis replaced byUnfinishedHigh, marked when sell volume traded at the bar’s high, andUnfinishedLow, when buy volume traded at its low, even with the other side empty; both extend into later bars until a revisit, like stacks and naked POCs, andextend_barsexpires any of them after that many later bars.diagonalfalse builds imbalance zones from the same price instead of the adjacent one.FootprintStudy::stateisLocal,Unvisited,RevisitedorExpired, andrender_footprint_studiesdims revisited and expired levels. Migration:footprint_studies(flow, ratio, stack, cluster_share, single_print_max)becomesfootprint_studies(flow, &FootprintStudyConfig { imbalance_ratio: ratio, stack, cluster_share: Some(share), single_print_max: Some(max), ..Default::default() }), where a share outside 0 to 1 or a maximum of zero is still off,UnfinishedAuctionmatches becomeUnfinishedHigh | UnfinishedLow, andFootprintStudyliterals addstate. (#1076) -
Footprint cells offer more presentation choices through
FootprintConfig.FootprintColor::Fixedfills every cell with the neutral colour andDeltaOpacitycolours by the sign of the delta with opacity following its share of the bar’s largest;FootprintMode::DominantSideshows only the larger of the sell and buy volume, at the left or right of the cell.abbreviatewrites 1.2K and 3.4M,show_zerofalse leaves zero volumes blank, andfont_sizesizes each row’s number by its volume between two limits held within 8 and 24 points, leaving out a number whose size exceeds its row’s height.extreme_ratiowrites the ask/bid ratio above the highest and below the lowest row of each bar, orA/B n/awhen the bid is zero, andpullbackoutlines the rows chosen byoverlays::pullback_range: from the close to the extreme the bar left, none when it closed on that extreme. Executed totals are never changed,Footprint::level_ofgives the level a price falls in, andFootprintConfigand its enums are serializable, with fields missing from older documents taking their defaults. Migration:FootprintConfigliterals add the new fields or use..Default::default(), and matches onFootprintModeandFootprintColoradd the new variants. (#1075) -
Volume bubbles take their grouping from
VolumeBubblesConfig::grouping:BubbleGrouping::Automatickeeps one bubble per bar and price level,Ungroupeddraws every execution at its own time and price, so fills of one instant and price stay separate circles,TimeWindowandExecutionsgroup by a window of time or a number of consecutive executions whatever the bar interval, andPriceStepsets the height of a level. Bubbles that do not sit on a bar’s centre are placed in its slot by their time; groups of executions keep their edges as the bounded trade store evicts the oldest trades.BubbleColorgainsSplit(a circle per side, sized by its own volume),AbsoluteDelta(the sign picks the side, the absolute delta sets the opacity against the largest visible one),DeltaPercent(the delta as a share of all volume, unknown side included) andVolume(one colour).VolumeBubblesConfigand its enums are serializable, and fields missing from older documents take their defaults. Migration:VolumeBubblesConfig::price_step: Some(step)becomesgrouping: BubbleGrouping::PriceStep(step);NonebecomesBubbleGrouping::Automatic. (#1074) -
services::AlertEngine, behind the newalert-enginefeature, is anAlertsservice that keeps alerts in memory and evaluates them on the bars the host feeds it throughupdate(symbol, timeframe, bars, now, value), wherevalueresolves study and drawing sources at a bar index. It needs no egui, so a server can run the same code. Crossings compare each value with the previous evaluation of the same alert and symbol, every rule is judged on the same bar, an update that changed nothing or whose newest bar is older than one already evaluated does nothing, so reloads, replay rewinds and timeframe switches never fire again, andtick(now)expires alerts without data.with_alertsandalertsrestore and persist the list, andset_watchlistsupplies the members of a watchlist alert.Alert::timeframenames the timeframe an alert is evaluated on; the engine fixes an alert that has none to the first timeframe it evaluates it on, and the demo fills it from the chart. Stored alerts load unchanged. (#1132) -
Chart::alert_value(source, bar)returns the value an alert source has at a bar of the main series: the close for price, the volume for volume, the study output named by its series identifier in decimal, and the level of a drawing named asDrawing::alert_sourcedoes, so a chart can feedAlertEngine::updateor any other evaluator.Chart::alert_sourceslists every output of every study and every level of every completed drawing with the names the alert dialog shows, forAlertDialog::sources. Both need thedrawingsfeature. The demo uses them instead of its own copies. (#1133) -
Alert::expand_messagefills{{symbol}},{{timeframe}},{{time}},{{open}},{{high}},{{low}},{{close}},{{volume}},{{value}}(the first source’s value) and{{output_N}}(output N of the first source’s study) from the evaluated bar; an unknown placeholder stays as written and a missing value becomes empty text.AlertEvent::TriggeredForSymbol::messagecarries the result, whichAlertEnginefills on every trigger, andAlertEngine::on_triggergives the host the alert and the event on each one, for email, push notifications or web requests. The alerts panel shows the message in the popup and the log,AlertTrigger::messagekeeps it and the CSV export gains a finalmessagecolumn.AlertsPanel::set_soundtakes the user’s alert sound, or none when sound is off, andtake_soundreturns it after a poll that received a trigger, asTrading::take_execution_sounddoes for fills; the demo plays it from there. Migration:AlertEvent::TriggeredForSymbolliterals and patterns addmessage(useString::new()or..);AlertTriggerliterals addmessage; readers of the CSV export expect five columns. (#1134) -
The demo evaluates alerts with
AlertEngineinstead of its own copy of the rules, so it shows what a host gets from the crate. The bars of each symbol and timeframe its alerts watch, from the hidden monitors of live charts, are fed to the engine once a frame throughChart::alert_value, and a chart in replay is not fed, so no alert fires again on entering or leaving replay.tickruns every frame and the demo repaints at least once a second while an alert with an expiry is active. The demo keeps the alerts with its other session data, restoring them withwith_alerts, and delivers trigger notifications throughon_trigger. (#1136) -
The volume profile studies take a Source interval input. A finer interval than the chart’s is requested from the host through
Indicator::data_requests, and each finer bar is distributed over its own price rows in place of the chart bar’s high to low estimate, for the visible range, fixed range, session, periodic, anchored and auto anchored profiles alike. A chart bar without finer bars keeps the estimate so no volume is lost, a reply for another interval is dropped, andprofile_inputsreturns for each profile the share of its bars the finer data covers. The default, chart bars, is unchanged. A connected feed pages that finer history back only to the first chart bar of the profiles in view, through the newIndicator::data_start, which states the oldest time a study reads from each history it requests; the chart pages again when the view moves to earlier profiles and requests nothing when it moves later. The default,None, keeps paging to the chart’s first bar, as do all histories on price-based chart types, whose studies run on elements. The six volume profile studies state the first chart bar of their profiles in view, or the newest bar when none is in view. (#1087, #1440) -
ChartPatterns::new(PatternFamily::Reversal), registered as Reversal Chart Patterns, finds cup and handle, inverted cup and handle, double and triple tops and bottoms, and head and shoulders and its inverse, on the same confirmed swing pivots, rules andformations()results as the continuation patterns. Tolerance, depth, handle pullback and length limits are study inputs and the rules are documented onChartPatterns. A formation confirms on the first close beyond its neckline or rim from the bar its last pivot is known, so a neckline broken before then confirms on that bar, and no confirmation reads a later bar. Reversal formations draw only their neckline or breakout level. (#1085) -
ChartPatterns::new(PatternFamily::Continuation), registered as Continuation Chart Patterns in the Patterns category, finds bull and bear flags and pennants, rectangles and ascending, descending and symmetrical triangles in the bars. Swing pivots confirmstrengthbars after the pivot; each formation’s pivots, boundary segments, direction and confirmation bar are returned byformations(), developing formations apart from confirmed ones, and a confirmed formation reads no bar after its confirmation bar. Strength, minimum and maximum length, tolerance, touches per boundary, pole size and a toggle per formation are study inputs, confirmations are marked and labelled, and boundaries are generated as drawings. The retained pivots, developing and confirmed formations are bounded. (#1084) -
BollingerBandstakes a basis, simple by default, throughwith_basisand the Basis MA type input: exponential, weighted, smoothed or volume weighted. It sets the middle band and the centre of both outer bands, while the deviation stays the population deviation about the window’s simple mean.BollingerBandsWidthadds Highest Expansion and Lowest Contraction outputs, the rolling highest and lowest width over lookbacks of 125 bars each by default, set throughwith_lookbacksand two inputs. A bar with a non-finite close is skipped in the width and its extrema, so later values equal those of the series without it. Migration:BollingerBandsWidthnow has three lines instead of one, so colour lists of one entry keep only the width colour. (#1088) -
ChartEvent::MarkClick { id, series, time }reports a primary click on a bar mark that has aMarker::id, throughChart::drain_events. The hit area is the one that shows the mark’s tooltip, so only visible marks respond; of overlapping marks the one painted on top is reported, and the click neither selects nor deselects a series or study. Drawing tools and the eraser take the click first. (#1106) -
KineticScrollOptions::mousecontinues a released mouse drag with the same damping, speed limits, minimum movement and cancellation as touch inertia, whichenabledkeeps controlling on its own. Migration:KineticScrollOptionsliterals addmouse: falseor use defaults. (#1065) -
The study catalogue lists Lunar Phases, which marks each new moon with an upward triangle at the low and each full moon with a downward triangle at the high of the bar whose interval holds it, the two styled and shown independently.
studies::lunar_phasesreturns the new and full moons between two UTC instants for 1900 to 2100 from the algorithm of Meeus, chapter 49, converted with the ΔT polynomials of Espenak and Meeus; its times are within about a minute of the published almanac times. Marks depend only on the bar times, so paging history, scrolling or restoring a template never repeats or moves a phase. (#1120) -
Woodies CCI columns show three stages by the run of CCI 14 values on one side of zero: a first value or a zero is neutral, two to five values are a transition, and six or more are established, in the columns colour above zero and the new Established down colour below it. Bars without a value are skipped and a zero ends the run. The established down, neutral and transition colours are study inputs, and a saved columns colour is kept. Columns were two-coloured by the five previous values before, so the bar that crosses zero after an established run is now neutral and the bars before an established run are no longer coloured by their sign. (#1118)
-
DrawingToolbar::show_floatinglists the favorite tools inToolbarState::favorites, so starring or unstarring one changes the strip at once, instead of six fixed tools. The strip can be dragged,ToolbarState::floating_posholds where it was left, and its close button clearsToolbarState::floating_visible.CrosshairStyle::MagicandCursorType::Magicselect a trail that follows the pointer while the primary button is held, which then does not pan the chart, and fades after release, without creating drawings; switching cursor drops the trail. Alt+Shift+R selects the rectangle tool by default, is listed in the shortcut help and is replaced by a rebinding inShortcutMap. Migration: match arms overCrosshairStyleandCursorTypeaddMagic;ToolbarStateliterals add the two floating fields. (#1052) -
DrawingToolbar::showandshow_with_actiondraw the favourite tools strip beside the toolbar and return a tool picked on it like one picked in the toolbar, so a host no longer has to place it;show_floatingremains for hosts that position the strip themselves and draws nothing a second time in the same pass. A dotted grip at the strip’s leading edge drags it, kept on screen, and tool buttons click without moving it. A star button after the Hide menu shows and hides the strip, selected while it is shown, and starring a tool shows it again. A newToolbarStatestarts with no favourites, so the strip appears with the first starred tool, and the strip no longer carries a magnet toggle or tool menu.UserSettings::drawing_favorites_hiddenanddrawing_favorites_poskeep the strip’s visibility and position withdrawing_favorites, and the demo restores them. (#1194) -
Ghost Feed projects candles along its clicked path:
GhostFeedConfig::spacingsets the bars each candle spans,wickthe extra wick as a fraction of its range, andGhostFeedConfig::candlesreturns the open, high, low and close of each, at mostMAX_GHOST_CANDLES. They are drawn through the active time and price scales, rising ones filled and falling ones hollow in the translucent drawing colour, and follow path edits, copy and paste, undo, templates and saved drawings because they are built from the path and the stored config. The drawing dialog edits the spacing and wick; non-finite values are refused on save. Migration:Drawingliterals addghost_feed. (#1109) -
Gann squares draw their grid, fan and arcs independently, each shown or hidden by
GannConfig::show_grid,show_fanandshow_arcs.fan_ratiosandfan_direction(forward from the first anchor, reverse from the opposite corner or both) set the fan lines, andarc_ratiossets arcs around the first anchor as fractions of the side, cut at the square’s edge. They replace the fixed diagonals, cross lines, circles and degree markers, are edited in the drawing dialog, are checked for positive finite ratios, and are kept in templates, undo and saved drawings; older saved drawings take the defaults. Migration:GannConfigliterals add the new fields or..Default::default(). (#1110) -
Four support and resistance studies join the catalogue.
IntradayPivotPointstakes the levels of each block of an exchange trading session, of a chosen number of minutes from the session’s first bar, from the block before it in the same session.ProjectedPivotPointsdraws, beyond the last bar, the levels the next period will use if the current one ended now, beside the confirmed lines of Pivot Points Standard.MissedPivotskeeps the swing highs and lows that price has not returned to, confirmedrightbars after their bar and revisited when a bar reaches them within a percentage tolerance, drawing each from its pivot to its revisit.KeyLevelsclusters swing highs and lows within a percentage tolerance into levels of a minimum number of touches, drawing each and listing it with its contributing pivots in a table. Left and right pivot bars, tolerance, touches and source period are study inputs that persist with templates. (#1091) -
Applied VWAP studies edit and persist their bands and event anchors through study inputs. “Bands” sets the number of bands, up to ten, and “Band n multiplier” each finite non-negative multiplier in the unit chosen by “Percentage bands”; new bands continue the sequence 1, 2, 3. “Event time zone” names the IANA zone or fixed offset in which “Events” and “Event n” write local times as
YYYY-MM-DD HH:MM:SS; the event anchor mode applies them sorted and deduplicated, a skipped local time is rejected and a repeated one takes its first occurrence. Templates, copies and undo restore both, andConfiguredStudy::apply_settingskeeps the styles of existing plots and gives plots added or removed by an input the study’s own styles.InputKind::TextandInputValue::Textcarry a single line of text a study parses itself, and the study settings dialog edits it.with_std_dev_bandsandwith_percentage_bandskeep at most ten bands. Migration: code matchingInputKindorInputValueadds aTextarm. (#1092) -
TrendStrengthIndexplots the rolling Pearson correlation of the source price with bar position over its own period, from -1 to 1 in its own pane with a zero line, and is listed in the catalogue as “Trend Strength Index”. A bar has no value during warmup, when its window holds a missing price, or when the window’s prices are all equal; the latest value equalsLinearRegressionChannel::correlationfor the same period. (#1115) -
PPO and PVO choose their short and long averages and their signal line independently as
OscillatorAverage::ExponentialorSimplethrough the “Oscillator MA” and “Signal MA” study inputs andwith_averages. Both default to exponential, which keeps the former values; the choices persist with the study inputs, templates and snapshots, and changing either recomputes the history. A simple average is the mean of the lastlengthdefined values and is defined once that many exist, like the exponential one. (#1116) -
Floating, held and tracking data readouts lead with the instrument’s symbol, and follow a change of instrument. The main series’ legend title row offers hide or show, settings and remove buttons that run the chart’s typed operations on
SeriesId::MAIN, leaving studies and other series in place; settings arrive throughChart::take_indicator_settings_requestasSeriesId::MAIN. A hidden main series keeps its dimmed title and buttons so it can be shown again, and the buttons are reachable with Tab. (#1063) -
SeriesStyle::alerts(SeriesAlerts:visible,labels,color) holds how one series’ alert levels are drawn, and the series settings dialog edits it under Scales and lines, Alert levels, throughSeriesSettings::alerts. The host passeslabelsandcolortorender_alert_levelsfor the alerts it resolves to the series and draws none whilevisibleis unset. The main series’ choice is read and applied byChart::series_settingsandapply_series_settings, kept byChartSnapshot::main_series_alerts(older layouts take the defaults) and by undo and redo, and another series’ choice is read and written throughChart::series_styleandseries_style_mut, which its options keep through undo. Migration:SeriesStyle,SeriesSettingsandChartSnapshotliterals add the new field or use defaults. (#1128) -
Chart::export_svgandTrading::export_svgwrite the frame ofexport_imageas an SVG document of the options’ size: text stays text, fades keep their gradients and the frame’s textures, such as legend icons, are embedded as PNG. Host paint callbacks, host-bound textures without supplied pixels, rotated or underlined text and gradient strokes return an error that names them instead of being left out, andexport_pnglikewise fails on host paint callbacks and host-bound textures without supplied pixels, such as a watermark image, that it used to leave out.ImageExportOptions::include_watermark(default on, as on screen) omits the symbol watermark andset_watermarktext independently of the title and timestamp, in PNG, SVG and frame exports, and the export dialog offers it as a checkbox andExportFormat::Svgto hosts that list it. Images now include the footprint, volume bubbles, order book and liquidity heatmap that the chart’s feed holds. Migration:ImageExportOptionsliterals insideegui-chartsaddinclude_watermark(the struct is non-exhaustive, so hosts are unaffected);matcharms overExportFormataddSvg. (#1050) -
ImageExportOptions::texturesholds the pixels of the textures a host binds itself, using linear filtering and edge clamping, soexport_pngandexport_svg(and theTradingvariants) draw images of them, such as a legend badge or watermark image from a user texture, instead of failing; a texture without an entry still fails with an error that names it. Invalid pixels and ids that collide with the offscreen frame return named errors;TextureId::Useravoids those collisions. Supplied pixels also travel withChartImageframes. SVG embeds each texture with its tint and opacity, so light-theme and toolbar icons export too.Chart::export_layout_image,export_layout_pngandexport_layout_svgcapture a whole layout of library widgets: the closure draws the toolbars, panels and trading overlays around the chart it is given and shows it, and the frame, encoders, options, feed-backed order-flow visuals and errors are those of the chart image. (#1050) -
Chart::data_tablereturns the cells ofexport_csvas aDataTable(headers,rows, andcsvandtsvof chosen columns), andDataTableDialoglists them with a column menu, copy of the displayed columns as tab-separated text and aDataTableAction::Exportcarrying their CSV for the host to save. Only the visible rows are painted, so a long history stays smooth, missing values show as an en dash and stay empty in copied and exported text, and the table lists only loaded bars, the replay cutoff’s bars during replay and the source bars on price-based chart types. The chart context menu offersContextMenuAction::OpenDataTable, which the host answers withDataTableDialog::open. The table rebuilds when the symbol, interval, bar count, first or last bar, replay cutoff or study list changes. Migration:matcharms overContextMenuActionaddOpenDataTable. (#1093) -
StudyEditoris a study source editing panel that embeds in any layout: it holds a document title and text, shows an unsaved-changes mark, lists hostDiagnostics (Severity, message and bytespan) and selects and scrolls to a span when its message is clicked.StudyEditorActioncarries the open, save and apply requests with the title and text; the host answers withopen_document,mark_saved,set_diagnosticsandapply_result, and a rejected apply leaves the edits in place. The library does not own the study language, files or compilation. (#1057) -
IdeasPanelis an ideas composer and feed that embeds in any layout: it edits a title, body and attach-chart choice for the symbol and interval set withset_context, listsIdeas and short posts (IdeaKind) with author, time, instrument and attachment, pages withadd_pageandIdeasAction::LoadMore, and emitsPublish,OpenandOpenChartintents. The host answers a publish withpublish_succeeded(identifier and link) orpublish_failed, which keeps the draft, andset_publishingandset_browsinghide the controls of a service the host does not offer. Accounts, storage and the network stay with the host. (#1095) -
PriceAxisOptions::show_symbol_nameandshow_study_names, and the Scales and lines settings checkboxes of the same names, write the symbol or study name before its last value tag on the price scale, so equal values of different series stay apart. They are off by default, independent of the legend titles and the value visibility flags, and persist with the settings. Added series write their own name on their tags. Migration:PriceAxisOptionsandScalesAndLinesSettingsliterals addshow_symbol_name: falseandshow_study_names: falseor use defaults. (#1064) -
Point and Figure builds from high/low input, as before, or from closes through
ChartTypeParams::pnf_sourceand the series settings Symbol tab. The choice is part of the cached build, so a change rebuilds the columns, and it persists with the chart type parameters. Migration:ChartTypeParamsliterals addpnf_source: PriceBasedSource::HighLowor use..Default::default(). (#1062) -
The HLC area chart’s fill opacity and close line width are set through
ChartTypeStyles::hlc_areaand the series settings Symbol tab, and persist with the chart type parameters. Defaults keep the former look; opacities outside 0 to 1 are clamped and a non-positive width hides the line. Migration:ChartTypeStylesliterals addhlc_area: HlcAreaStyle::default()or use..Default::default(). (#1103) -
A star on each chart type menu row adds the type to the favourites or removes it. The toolbar then shows a button for each favourite in menu order, the last selected non-favourite and a menu chevron, with the same rules as the interval buttons. A new selector has no favourites.
ChartTypeSelector::preferencesandset_preferencesexchange serializableChartTypePreferencesfor host user settings, andChartTypeAction::ToggleFavoritereports a toggle; the demo saves and restores them through application storage. (#1042) -
The documentation status page shows feature completion by area from the maintained feature list, as a feature map coloured by status and one table per area. The same build produces per-area status badges and the feature map image for embedding. (#1129)
-
Terminalof theegui-charts-terminalpackage interminal/assembles the top toolbar, the chart context menus and one or more chart slots in aChartLayouton the host’sDatafeed, and performs their actions: chart type, undo and redo across the whole chart history, the light and dark theme (following the system appearance until the user chooses one, on every slot) and fullscreen.Terminal::showperforms what the controls emitted in that frame, in order, and returns the actions the host intercepted throughwith_intercept, theHostentries of the toolbar and menus, and every action the terminal has no default for;Terminal::runperforms an action whatever the intercept says, waiting for the first frame when called before it.Actionwraps each component’s own action enum unchanged. Services are passed asArc<dyn Trait>(with_storage,with_marks, repeatablewith_signals,with_symbol_search,with_alerts, repeatablewith_broker,with_quotes,with_notifications,with_chats) and files and sounds as callbacks (with_file_export,with_sounds); withwith_storagethe theme, symbol and interval persist throughSettingsStore. Controls of features the terminal does not perform yet stay hidden, andhidehides any other.terminal/examples/terminal.rsruns it on the synthetic feed. The package uses only the library’s public API and is not published. (#205) -
Terminalperforms the indicator dialog, which also lists the metrics the feed offers, and indicator settings, chart settings from the top toolbar, the chart and series menus, a double click on the main series and the price axis, symbol search when the host passeswith_symbol_search, the keyboard shortcuts dialog and the study menu’s host entries (add a study from a study, add to favourites, copy, settings). Starred studies are saved withUserSettings::indicator_favorites, settings the chart rejects leave the previous ones in place and are reported, and the series menu’s Copy price copies the clicked price at the instrument’s precision. (#205) -
Chart::set_study_limitcaps the studies a chart takes from the interface, withChart::study_limitto read it andChart::try_add_indicator, which refuses a study beyond the cap with an error. Pasting a copied study respects it,add_indicatordoes not, andIndicatorDialog::set_fullmakes the dialog say so and add nothing. Hosts callterminal.chart_mut().set_study_limit(Some(n)). (#205) -
Terminalshows the drawing toolbar beside the chart and keeps it in step with the active chart every frame, and performs its actions, the drawing menu, the drawing properties dialog’s Delete and Clone, and the object tree’s actions as undoable chart edits; zoom stays outside undo, and a colour dragged in the object tree ends as one step when the pointer is released. The object tree and the data window open in the side panel from the rail’s Object Tree icon and from the chart and study menus, and the data window reads the hovered bar. Pasted drawing text is added through the chart’s drawing clipboard. The per-tool drawing defaults saved from the properties dialog persist inUserSettings::drawing_defaults. Hide all and lock all drawings set the state the toolbar shows instead of toggling the drawings’ current state. (#205) -
Chart::set_signal_sourcesconnects severalSignalsservices to one chart, each with its own stream, so that aClearor a lagged stream of one source leaves the signals of the others.set_signal_sourceremains for a single source. (#205) -
UserSettingskeeps indicator and interval favourites, drawing tool defaults, watchlists and the replay session to resume; documents written before read with their defaults. (#205) -
ElliottWave(“Elliott Wave”, Support and resistance) finds five-wave impulses in confirmed swing pivots under the supported rules: wave 2 stays above the start of wave 1, wave 3 passes the end of wave 1, wave 4 does not overlap wave 1 and wave 3 is not the shortest of waves 1, 3 and 5, mirrored for bearish impulses. A construction is developing from wave 3, with its wave number as the label of the latest anchor, and is invalidated by a close beyond the end of wave 1 or by a later pivot that breaks a rule. It is confirmed on the bar that confirms its fifth anchor, and confirmed constructions never change. The table lists the developing construction and the lasthistoryconfirmed ones with the price of every anchor and the confirmation time. (#1117) -
RisingWedgeandFallingWedge(“Rising Wedge” and “Falling Wedge”, Support and resistance) detect converging trendlines through confirmed swing pivots. The latesttouchespivot highs and lows must keep the wedge’s direction, the lines must converge by at leastconvergencepercent and the anchors span at mostmax_barsbars. The developing lines are output on every bar until the close leaves the wedge: below the lower line of a rising wedge or above the upper line of a falling one confirms it, the other side or the lines meeting ends it. The table lists the developing wedge and the lasthistoryconfirmed ones with their anchor and confirmation times. A found or confirmed wedge does not change with later bars, and a confirmed wedge consumes its pivots. (#1086) -
AdxBreakout(“ADX Breakout”, Trend),KnoxvilleDivergence(“Knoxville Divergence”, Momentum) andReversal(“Reversal”, Support and resistance) add signal studies with separate upward and downward outputs, editable periods and thresholds, and documented rules. ADX Breakout marks a close beyond the high or low of the lastrangebars after an ADX at or below the threshold. Knoxville Divergence compares consecutive price pivots with the momentum at them, gated by an oversold or overbought RSI, and marks the confirmation bar of the second pivot. Reversal marks a new extreme of the lookback that closes beyond the previous close. Each signal is final on the bar that shows it and does not depend on later bars. (#1090) -
Ratio,SpreadandCorrelation(“Ratio”, “Spread” and “Correlation Coefficient”, Statistics) combine two series, each a price source of the chart symbol or of a host-supplied symbol at the chart’s interval, chosen by thesymbol_0,source_0,symbol_1andsource_1inputs. Series align to chart bars by interval; a bar where either has no bar or a non-finite value has no output, and nothing is carried forward or taken from the chart in its place. The correlation is the Pearson correlation of the lastlengthvalues, or of log returns with thelog_returnsinput, and has no value while its window holds a missing bar. A zero ratio denominator, a non-positive price in the log-return mode and a series constant over the window are unavailable. Hosts supply the histories throughChart::study_data_requestsandset_study_data; no market data service is included. (#1081) -
TechnicalRatings(“Technical Ratings”, Momentum) scores the buy, sell and neutral votes of simple and exponential moving averages of three lengths and of the RSI, Stochastic, CCI, MACD and Momentum from -1 to 1 as separate moving-average, oscillator and summary outputs, each with its coverage, the share of enabled components that had a vote. A component in its warm-up or on a bar with a non-finite high, low or close has no vote, so it leaves the mean and lowers the coverage. Every component, its period and the toggles for the averages and oscillators are study inputs. The table shows the latest score, its Strong Buy, Buy, Neutral, Sell or Strong Sell rating at the thresholds of 0.5 and 0.1 and the coverage of each group. (#1119) -
Trading settings persist line extension, left, centre or right label placement, and whether
Trading::export_imageandexport_pnginclude visible trading overlays. Migration:TradingSettingsliterals addextend_lines: true,label_alignment: TradingLabelAlignment::Rightandinclude_in_image: false, or use defaults;TradingLineOptionsliterals addextend_linesandlabel_alignment. (#994) -
The snapshot menu offers Download image, Copy image and Open in new tab. Hosts with publishing enable
TopToolbarState::can_publish_imageand handle Copy link, Post image and Publish through their service. The demo copies images or opens them in a browser tab or native viewer. Migration:TopToolbarStateliterals addcan_publish_image: falseor use defaults. (#1006) -
The save menu offers Save layout, Download chart data, Create new layout and Open layout as 32-point rows, retaining rename, save-as, image export and autosave. The demo routes data download and layout opening through its existing handlers. Save and snapshot menus scroll in short windows. (#1005)
-
The object tree creates named folders from selected drawings, nests folders and moves selected drawings between folders or back to the root. Folder visibility and locking apply to all descendants as one undoable edit. Drawing folder paths persist with drawing identities, independently of host groups; hosts retain empty folders through
ObjectTreeState::folders. Migration:DrawingandSourceItemliterals addfolder: Vec::new();ObjectTreeStateliterals use..Default::default()for its folder and rendered-order state; copyDrawing::folderinto live drawing rows. Older saved drawings start at the root. (#978) -
Scales and lines settings expose currency and unit headers, scale-mode and price-action visibility, a numeric price-to-bar ratio lock, label overlap policy, and symbol, study and extended-session value colours and visibility. Units come from host metadata without converting data. (#993)
-
Alert settings filter active levels and set trigger notification lifetime. Inactive levels can be shown dimmed; the existing local sound controls apply the selected volume. (#995)
-
Event settings independently show earnings badges and dashed earnings breaks, news badges and host news notifications, and supplied ideas. The demo delivers enabled headlines through its notification service and suppresses repeated requests while they remain in its recent log. Economic-event visibility is preserved. (#996)
-
Symbol settings independently hide candle bodies, borders and wicks, colour candles by the previous close, and request dividend-adjusted history from the host. Candle borders draw inside the body; older saved settings retain borderless defaults. Status line settings show the supplied logo and last day change and set the study legend backdrop opacity, including studies in separate panes. Zero opacity hides the backdrop. (#992)
-
Alert expiry uses separate date and 24-hour time fields in
AlertDialog::timezone(UTC by default), with a No expiry choice. Invalid or past times block saving; skipped local times are rejected and newly entered repeated times use their first occurrence. (#981) -
ChartType::VolumeFootprintandChartType::SessionVolumeProfiledraw the bid and ask volume at each price of every bar, and the volume at each price of every session of the visible bars with its point of control, value area and developing point of control. Both are summed from the trades the feed sends and keep up with them while it streams. They need a time-based interval and the instrument’s tick size; unsupported intervals and bars before the first held trade draw as candles, and the session profile needs thestudiesfeature. The chart type menu lists them around Time Price Opportunity, followed by Heikin Ashi, Renko, Line break, Kagi, Point & Figure and Range, with 13 point gaps between its groups. The demo drops its synthetic footprint and trade profile menu items, which paused the feed, for the chart types. (#967) -
The broker picker’s compare button shows brokers side by side, two at first, with an Add broker control for other offered brokers and a Connect button under each.
BrokerTile::factssupplies their rows, such as pricing, leverage and features, asBrokerFact::ValueorBrokerFact::Supported. Each label gets one row across the brokers; a broker without it shows a dash read as not available, unlike the cross of an unsupported feature. The demo gives its brokers example facts. (#1003) -
ui::financials::FinancialsPanelshows a company’s host-suppliedCompanyFinancialsin place of the chart: a pill perFinancialPage, a column chart of the chosen row over the page’s periods and the table of all its rows, with a Back to chart button, and a message when the host has no figures. The symbol details panel’s More menu offers Financials, whichSymbolDetailsPanel::take_financials_requestreports. The demo opens synthetic statements and statistics for its stocks. (#1002) -
Symbol search validates arithmetic expressions such as
AAPL-MSFT, reports invalid symbols and syntax, and returns a synthetic instrument.services::SymbolExpressionevaluates expressions and aligns component histories by timestamp; the demo charts spreads in their own panes. (#976) -
Symbol search offers an exchange source menu through
SymbolSearchDialog::set_sourcesand expands instruments sharingInstrument::root. Results and recents retain separate exchange listings, and selection returns the exact instrument. The demo includes two futures expiries for drilldown. (#975) -
Compare lists recent symbols through
CompareSymbolsDialog::set_storage, including with a local catalog. Aligned 56-point rows show host marks, descriptions, type badges and optionalInstrument::country. Rows offer Same % scale, New price scale and New pane, with an Add menu in narrow windows. Migration: matchCompareAction::AddSymbol(symbol, placement);ComparePlacement::SamePercentScalepreserves the former behaviour. (#999, #962) -
The indicator templates menu has Indicators and Templates pages for one-click study additions and saved-template application. Hosts supply starred studies through
TopToolbar::favorite_indicatorsand handleTopToolbarAction::AddIndicator. Save indicator template remains available, and empty pages explain how to fill them. (#1004) -
Alt+Shift+Left and Home navigate to the first bar; Alt+Shift+Right and End return to the latest, preserving zoom. Period, Alt+D and Alt+Shift+E request Open layout, Data window and session switching through
ShortcutMap; text fields keep their keys. The demo scrolls its saved-layout chooser and toggles SAMPLE between regular and extended hours, including from its initial 24/7 session. Continuous markets retain their session. (#983) -
The drawing bar’s text group and the demo command search offer the image, post and idea drawings in a content section. Placing or double-clicking one opens an editor for its content, kept in the drawing’s text: an image drawing shows the picture at that address, fitted inside its frame, through the image loaders the host installs, with an empty, loading or failed state instead of sample art, and the post and idea cards show the supplied author or title on the first line and the text after it, growing to fit. The demo installs the PNG and JPEG file loaders. (#985)
-
The table drawing is offered with the text and note tools and in the demo command search. Placing or double-clicking a table opens a cell editor that adds and removes rows and columns; the cells are saved in the drawing’s text, one row per line and one tab-separated cell per column, and the table paints them with its first row as the header and each column as wide as its widest cell, instead of fixed sample cells. (#984)
-
The drawing bar’s projection group and the demo command search offer the ghost feed tool, which places and edits its path through the existing multi-point anchors. (#986)
-
The drawing context menu and the object tree row menu move a drawing to the price pane or another existing pane with
Chart::move_drawing_to_pane, as one undoable edit that keeps its anchors and style;Chart::drawing_panereports the pane drawing it andSourceItem::with_paneslists the choices of a tree row. Migration:SourceItemliterals addpanes: Vec::new(). (#977) -
The drawing context menu offers an alert on the price crossing a drawing with price levels, and
FloatingSelectionToolbar::set_alert_availableadds an Add alert button.Drawing::alert_levelsevaluates a line, a horizontal level, a rectangle’s top and bottom, a position’s entry, target and stop and each visible Fibonacci retracement or extension level at a bar;Drawing::alert_sourceandalert_levelname a level by the drawing’s stored identity, so alerts keep their level after a save and restore. The demo lists every level as an alert source and evaluates them from the current drawing geometry. (#980) -
Interval entries can be hidden and restored from the menu without changing the selected interval. Hidden entries are unpinned and persist through host-owned
TimeframePreferences, including across source changes. Migration:TimeframePreferencesliterals addhidden_timeframes: Vec::new()or use..Default::default(); older saved preferences default to no hidden entries. (#974) -
Chart::set_bar_limitoptionally keeps only the newest bars of each series, including feed history, streaming ticks and retained replay history. The default remains unlimited.remove_oldest_barsreturns evicted bars explicitly. Replay eviction also drops the matching finer-source slots. Studies restart their warm-up on the retained window, drawings keep their timestamps and the viewport keeps its time position where possible. Full windows pause feed scroll-back until the limit is raised or cleared; markers, raw trades and host data retain their independent lifetimes. (#945) -
Chart::forget_symbolreleases an inactive symbol’s drawings, markers and storage reader without deleting host storage. Pending local storage edits must finish first. Symbol changes no longer cache empty drawing managers, marker lists or inactive empty storage readers; pending drawing sync notifications are retained. (#949) -
The demo quick search runs a sample backtest on completed synthetic bars, marks equity at their closes and opens the strategy report below the chart. Reports can be replaced or cleared; selecting a trade restores its symbol and interval, scrolls to its bars and highlights its span. Entry and exit markers share the signals service with the API samples, including in newly added chart slots. Trades CSV is saved or downloaded by the host. Strategy execution, market data and storage remain host-owned. (#225)
-
The documentation site at
/egui-charts/docs/brings installation, first-chart and feature guides together with the all-feature Rust API reference at/egui-charts/docs/api/. Existing guides are included directly, Rust samples compile in CI, and the searchable guide follows system light/dark preferences with responsive navigation, installation steps and feature choices. The demo URLs are unchanged. (#929) -
Study menus publish source preselection through
Chart::take_indicator_source_request, read alert values from displayed price-based elements, and pin studies and overlay volume to shared right, left, additional or hidden scales withStudyScale::Shared. Shared groups keep their pane’s units and participate in scale fitting. Interval ranges also apply to custom durations and trade-count families throughStudyIntervalRange. Migration: exhaustiveStudyScalematches handleShared;StudySettingsliterals addinterval_range: Default::default(), while older saved settings retain their exact hidden intervals.IndicatorDialog::open_for_chartoffers price fields and chart study outputs as sources, with optional preselection for adding a study on another study. Added studies retain their source and edited parameters; unavailable outputs are rejected and studies without a source input cannot silently ignore a preselection. Host-supplied source inputs keep their own validation, and rejected inputs show an error without closing the dialog. Long source captions truncate within the configuration panel. Favorites appear first in each matching indicator list. The demo passes chart sources through toolbar, shortcut and study-menu opens. The Add control stays reachable in narrow windows. The demo routes study actions to its alert service, clipboard and selected object-tree row. (#850) -
Primitive::draw_mergedreceives the chart’s physical-pixel merge factor andPrimitiveView::point_groupssupplies aligned source ranges for custom aggregation, with no groups for empty views; existing renderers keep theirdrawbehavior. Hovered added series and mixed study/series panes followhovered_series_on_topwith timestamp-aware hit testing and visual ordering. Cached merge groups also supply exact visible price ranges without scanning every bar each frame. The demo saves encoded PNG bytes directly, with optional crosshair inclusion. (#834) -
Chart::set_volume_formatterformats volume readouts, widget-only volume axis tags and volume-formatted studies;set_series_formatteroverrides one bar series’ raw prices while relative scales keep the percentage formatter. Chart price and percentage hooks also reach OHLC legends and tooltips, and image exports retain the hooks.Indicator::set_value_formatterlets configured studies retain host formatting. Migration:Legendliterals addformatters: ValueFormatters::default()or useLegend::new;StudyValueliterals addformatted: None;render_tooltip_with_optionstakesValueFormatters::default()as its final argument for the existing formatting. Hosts supply numeric separators and currency conventions through their formatters. (#203) -
Pointer events include hidden added series and their payloads. Unchanged whitespace slots emit no repeated move events, while changes to their host payloads remain observable.
Chart::set_pointer_kindlets host input integrations identify pens, which egui does not distinguish from touch.Nonerestores automatic mouse/touch detection. The demo API samples render a host legend and its tooltip from the saved event alone. (#829) -
ui::strategy_report::StrategyReportPanelrenders a replaceable host report with summary metrics, equity and drawdown curves, a virtualized trade list and run properties. It returns original-index trade selection intents and valid-trade CSV for the host, and draws no controls without a report. Fill prices and timestamps retain their precision; undefined metrics and overflowing percentages display as N/A.StrategyPerformanceadds largest winning/losing trades and consecutive win/loss runs in exit order;StrategyReport::comparisoncomputes fee-free buy-and-hold and bar-resolution MAE/MFE from host source bars, counting invalid input.equity_curveshares curve validation with the view. The backtesting example opens the standalone report withuiand retains its headless workflow. Chart navigation and terminal mounting remain host integration work. (#225) -
localization::set_translatorinstalls a host-owned UI text lookup for one egui context;clear_translatorrestores English. Toolbars, menus, dialogs, panels, shared controls and accessibility names resolve text before layout, including when the language changes while a dialog is open. Missing translations retain the crate’s existing English text. Searches accept translated labels and original English names.localization::textshares the lookup with host controls, andformat_textsubstitutes named message values after translation without interpreting braces inside those values. Hosts supply other languages and fonts; chart date and number formatters remain independent. (#204) -
Standalone examples cover custom studies, timestamped drawing save/load, a host-run backtest, host script evaluation and UTC chart synchronization across intervals. The historical examples share one generated OHLCV helper, and existing CI checks compile every declared example. The demo retains its execution-based history. Data feeds, durable storage, strategy execution and scripting runtimes remain host-owned. (#249)
-
docs.rs builds all features and labels optional modules with their feature requirements. The builder guide is published in rustdoc and covers history, streaming, custom studies, drawing persistence, chart synchronization and host strategy and script integration. Study descriptions appear on their public types, and missing documentation is linted in
studies,drawings,widgetandext. (#248) -
A compact
frame_time --regression <scenario>suite covers three history sizes, smoothed candles, tick and new-bar frames with and without studies, batch study calculation and 500 drawings. Pull-request CI compares Cachegrind instruction deltas against the same workloads compiled with the base revision and rejects growth above 5%, subtracting setup and warm-up. The existing bare-chart check and baseline are unchanged. (#246) -
Datafeed::options_volumeoptionally streams complete call/put contract-volume snapshots at each strike for an underlying and an inclusive expiry range. Existing feeds supply none by default.OptionsVolumeProfile::newsubscribes explicitly with a host repaint callback and draws the figures on the price pane, calls and puts in separate colours, with lengths relative to the largest combined row total. Rows are centered on strike multiples of the chosen price height; coarser rows sum nearby strikes without spreading their volume. Snapshots replace earlier totals, empty snapshots clear the profile, and dropping the last study clone deactivates its sink.VolumeProfile::from_optionsexposes the same grouping for host calculations, with calls inup()and puts indown(). The demo’s “Options volume profile” quick-search action connects a live synthetic options feed. Options data and expiry selection remain host-owned; recreate the study to change its query. Profiles hide when chart metadata names another underlying; the demo retains options queries across symbol changes. (#550) -
Datafeed::metrics,metric_historyandsubscribe_metricexpose host-published instrument metrics with names, units and value formats; existing feeds offer none by default.MetricStudydraws each series in its own pane, holding the latest point at or before each chart bar without looking ahead, and its output can feed another study. Live corrections refresh both the metric and its consumers through the existing study subscription path.IndicatorDialog::set_metric_sourcelists the current instrument’s metrics and ignores old replies after a source change. The demo supplies synthetic five-minute open interest; external metrics remain host-owned. Migration:StudyDataRequestliterals addmetric: Nonefor price histories or the host’s metric key for metric histories; saved requests default to price histories. Direct hosts convertMetricPointintoBarforChart::set_study_data. (#547) -
studies::helpersexposes scalar-series simple, exponential (first-value and SMA-seeded), Wilder and weighted averages, rolling sum, highest, lowest, population standard deviation, change and crossing tests.studies::Stepperlets custom studies resume after a changed last bar or appended bars, including without thestudiesfeature. Built-in studies share these definitions while retaining their seeding and reference outputs; the driver example checks both update cases against a fresh calculation. (#545) -
data::ReplayClockmerges trades, quotes and depth for multiple symbols by timestamp and sequence, advances at a host-selected speed and seeks depth from periodic snapshots.ReplayEvent::push_touses the live feed path;Sink::reset_replayclears future bars, order flow, streaming study values and their heartbeat on rewind.RecordingWriterandRecordingReaderpersist compact versioned binary events through host-owned streams, preserving nanosecond times, ids and conditions. Seedocs/order-flow-replay.mdfor routing, recording and seek integration. (#240) -
Trade-based
Timeframe::Volume,RangeandDeltaintervals build bars directly from executions and appear in the interval menu, subject to the source interval list. Volume and absolute signed delta split fills exactly at the threshold; raw fills stay intact. Typed interval changes also update the demo interval button. Range is measured in instrument ticks and closes on the first real fill reaching it, with possible overshoot across skipped prices. Parse100v,10ror100delta; trade-based bars keep exact opening times and have no countdown or time-based resampling. Migration: exhaustiveTimeframeandTimeframeUnitmatches handle the new variants. (#239) -
Sink::push_order_snapshotandpush_order_eventaccept sequenced resting orders, modifications, cancellations and executions.Chart::order_queueexposes queue priority, the largest order at a price and levels filtered by minimum order size; the usual aggregated book and depth history continue to work. Known execution trades carryTick::resting_order_id. Gaps, invalid events and the 10,000-order per-side limit require a fresh snapshot, with bounded buffering during resync. (#555) -
Datafeed::depth_historyoptionally pages recorded depth throughDepthRequestandDepthPage. Charts with a depth history load past columns and request older pages when visible time reaches the oldest depth column, preserve live columns on overlap, retain time gaps and stop at the end of history or when a page adds no older column. Depth times whose cadence boundary exceeds the nanosecond range are rejected without overflowing. Feeds without recorded depth keep their existing behaviour. (#554) -
Tick::with_aggressor_order_ididentifies fills of one aggressive order.Chart::combined_tradesanddata::combine_tradesexpose their retained size, first and last prices, volume-weighted price and fill count; fills without an id stay separate, and raw trades continue to feed per-price volume. (#553) -
The factory adds “Quoted Spread” (last, arithmetic mean and maximum in instrument ticks), “Book Size” (last synchronized bid/ask sizes and their difference over a level count or price distance), “Trade Rate” (bar total, rolling and instant rates for execution count or volume) and “Levels Traded Through” (absolute bid/ask movement in ticks, per bar or rolling seconds). Each has a separate pane.
Indicator::order_flow_inputconnects their boundedOrderFlowInputbefore quotes and depth are coalesced; executions use the feed’s deduplicated historical/live join. Missing streams stay missing, book loss clears its current values and breaks the movement path, and heartbeats expire idle rates. Hosts can also push events through the input handle. Changed aggregation inputs start a new source; charts replay retained executions for newly added rates without resetting other live sources or their idle clock. Clearing a source or evicting its oldest bar also clears earlier cached plot values. Shared sources receive each event once. Heartbeats expire rates after queued trades are merged and expire rolling inside-market movement without consuming event capacity; newly attached rates keep that idle clock. See order-flow integration for definitions and retention limits. Order counts require host-side fill grouping using explicit aggressor order ids; Trade Rate counts raw executions. (#552) -
studies::{TradeProfileRanges, trade_profiles}builds bid/ask and delta profiles from exact footprint rows over host-supplied session ranges. Profiles retain unknown volume, developing POC, value area and local high/low volume nodes.chart::overlays::render_trade_profilesdraws them on the price pane, andui::trade_profile_menumerges neighbouring profiles or splits one at a selected bar boundary. The footprint demo exposes these commands for the last clicked bar and its profile. Session boundaries and historical/streaming trades remain host-owned. (#241) -
Chart::set_liquidity_heatmapdraws retained texture tiles from the feed’sDepthHistory, with logarithmic per-column contrast, sampled bid/ask paths and a current-book size column. New or changed columns use partial uploads; expired columns release their slots and tiles stay within the backend’s texture limit. The demo menu enables it with execution bubbles.HeatmapStrip::add_cellnow normalizes its cells andvolume_weighteduses volume for gradient intensity or solid opacity, and solid cells without delta stay transparent. (#235) -
VisibleAveragePrice(“Visible Average Price”) averages the selected price source, close by default, over the visible bars and follows pan, zoom and resize before the price scale is fitted.Indicator::set_visible_rangesupplies the end-exclusive source range and is forwarded by configured studies.UpDownVolume(“Up/Down Volume”) sums host-supplied intrabar volume by candle direction, using the previous intrabar close for dojis, with up volume above zero, down volume below and a delta marker coloured by the prevailing direction. The study declares intrabars throughIndicator::data_requestsand consumesupdate_data; connected feeds load and subscribe automatically, while hosts supplying bars directly useChart::study_data_requestsandset_study_data. Missing histories stay unavailable. Subsecond and tick-count charts have no lower-timeframe request. The library does not fetch a market data feed. (#176) -
Seasonalityadds its yearly monthly-change heatmap, including the developing month and the monthly average, population standard deviation and positive percentage. Its final projection reaches the next month boundary in future whitespace throughIndicator::projectionsandStudyProjection, with fractional time-axis endpoints so missing dates do not lengthen the box. Projected bands participate in selection and autoscaling, including future whitespace. Projection statistics still use earlier years only. Configured studies forward both tables and projections. (#176) -
Performanceshows percentage changes over one week, one, three and six months, year to date and one year in a labelled table on the chart. A period’s starting close is the last finite close on or before the target trading date in the instrument’s calendar, clamping shorter months to their last day; insufficient history or a zero starting close displays N/A. On an interval shorter than a day it declares the chart symbol’s daily bars inIndicator::data_requests, which a connected feed answers and other hosts supply withChart::set_study_data, so the longer periods fill without scrolling back. A period then starts from the later of the last daily close and the chart’s own last close on or before the target date, the daily one on the same date, so daily history that stops early or has gaps falls back to the chart’s bars. Daily and longer charts, and hosts that supply no daily bars, use the chart’s loaded bars, and daily bars out of time order count as not supplied.Indicator::tablesupplies aStudyTableindependently of plots, forwarded by configured studies and drawn over the pane and overlay plots, including image exports. Tables scroll within narrow or short panes and stack above the study geometry. (#568, #1495) -
ui::widget_bar::MarketHeatmapPanelrenders host-supplied symbols as a grouped weighted treemap, with theme-based diverging percentage colours, values on hover and a selected-symbol intent. Its public entries accept updates without reconstructing the panel.RightBarIcon::MarketHeatmapadds its rail entry, and the demo feeds synthetic weights and live quote changes. Layout checks use hand-computed tile areas across groups and updated weights, including large finite inputs. Market data remains host-owned. (#557) -
Charts consume
Signalsthroughset_signal_source, rendering host markers, levels and zones in theme colours with hover text and click callbacks. Time anchors follow history replacement, zoom and price-based elements, and priced markers can appear in visible whitespace; symbol and interval changes end old streams immediately, and lagged streams start fresh. The Signals menu hides categories without losing their data. The demo supplies live synthetic analytics through its feed when API samples are enabled. Analytics and external services remain host-owned. (#381) -
Datafeed::price_targetsoptionally answersservices::PriceTargets: high, average and low estimates, analyst count, publication and horizon dates. Unsupported feeds silently show nothing. The Symbol chart setting enables horizon-anchored projections from the last close, price and percentage labels and details on hover; stale symbol replies are ignored. Targets participate in automatic price fitting only where projections reach the visible time range, and their visibility participates in undo and layout copies. Labels use the host price formatter in instrument units on every scale, stay below the chart legend and quote controls in narrow views and retain their hover details when the horizon is offscreen. Hosts leave future whitespace in the logical range to show the horizon. The demo supplies targets for SAMPLE and has a daily-view quick-search action. Migration:ChartSettingsStateliterals addshow_price_targets: falseor use..Default::default(); saved settings default it to false. (#556) -
Symbol and comparison dialogs consume
services::SymbolSearch, ignore superseded replies and request another page as the user scrolls. Without a service the supplied symbol list still works. Symbol search keeps recently opened instruments throughStorageinStoreKind::RecentSymbols; failed reads prevent replacement. Empty searches with a category or exchange filter query the host catalog rather than restricting the results to recents. The demo connects its sample instrument catalog and application storage, including quick search. Migration:SymbolQueryliterals addoffset: 0; services applyoffsetbeforelimit. (#380) -
Right-clicking a TPO chart profile offers merging with the previous or next profile and splitting a composite back into its sessions. Commands update
ChartTypeParams::tpo_compositesas one undoable chart action, including neighbours outside the visible range; existing chart settings save the result. Hit testing shares the renderer’s placement and row widths, including profiles clipped at the plot’s left edge. Split extended-hours profiles can be merged across trading days. Migration: exhaustiveContextMenuActionmatches handleMergeTpoPrevious,MergeTpoNextandSplitTpoProfile;ChartMenushas already applied these actions before returning them. (#106) -
Studies declare source, colour, interval and symbol inputs alongside numbers, choices and toggles, with defaults retained separately from edited values. The settings dialog uses these declarations for editing, validation and resetting;
CustomIndicator::with_inputssupplies validated inputs to a host calculation.ConfiguredStudyexposes a source, plot offset and calculation symbol/interval for single-series studies. Price sources include open, high, low, close, hl2, hlc3 and ohlc4;StudySource::Studyselects another study’s undisplaced output by stable chart id and column. The chart calculates dependencies before their consumers, including hidden sources, and refreshes them after edits, live bars, undo and export. Substituting a source retains the input bars’ colours and host payloads.Chart::set_indicator_sourcerejects missing plots and cycles. Migration:StudyInputliterals adddefaultor useStudyInput::new(...).with_default(...); exhaustiveInputValueandInputKindmatches handleSource,Color,TimeframeandSymbol. Hosts restoring studies into a different chart remap stored source ids to the newly created studies. The demo stores template source positions and remaps them after loading; layout restoration uses its saved study-id map for source references as well as drawings. Single-study clipboard paste rejects chart-local study output references, which need host remapping. Existing numeric source choices remain accepted by studies that previously used them. (#168, #174) -
Indicator::data_requestsandupdate_datalet studies consume additional host histories. The chart resolves, loads and subscribes to requested symbols and intervals through its connectedDatafeed; hosts supplying bars directly useChart::study_data_requests,set_study_dataandstudy_data_error. Requested bars align by their calendar slots even when stamped inside them, missing slots leave gaps, and resuming a paused feed reloads missed history. Higher-interval calculations appear after the source bar closes; turning off “Wait for interval close” exposes the newest developing value on the latest chart bar. Advance/Decline Ratio divides advancing by declining issues, Advance/Decline Line accumulates their difference, and Cumulative Volume Index accumulates advancing minus declining volume. These studies use the close of each host-supplied market series, leave gaps for missing pairs and zero ratio denominators, and keep their running total across gaps. Hosts map the editable advancing/declining symbol keys to their own data service; no market data service is included. (#175) -
Visible, fixed, session, periodic, anchored and auto-anchored volume profile studies draw horizontal up/down histograms with total-based POC, value area, VAH and VAL. Visible profiles use only the current viewport; saved fixed and anchored times survive prepended history, and session/calendar profiles include the whole exchange trading period. Inputs set row count or price height, value area and volume display and retain their declared defaults for resetting; the host supplies bars and instrument session metadata.
VolumeProfile::from_barsalso computes distributions directly from host-supplied finer bars. Studies and drawings share the same calculation and rendering, including negative prices and flat bars. Migration: the old per-bar volume-bin columns ofVolProfileVisibleandVolProfileFixedare removed; readIndicator::volume_profiles(visible_range)for source spans, price boundaries, total/up/down volumes and POC/value area.VolProfileFixed::with_rangeandVolProfileAnchored::with_anchortake UTC times. (#167) -
Volume profile drawings can use a fixed price height per row through Inputs or
VolumeProfileConfig::with_row_size. Rows align to multiples of that height and grow at the edges on new highs and lows, reusing completed-bar volume. Equal rows over the span remain the default and old saved drawings retain it. Nonpositive or nonfinite heights are rejected; a span needing more than 10,000 fixed rows is not drawn. (#359) -
Volume profile drawings offer Total, Up / down and Delta displays. Rows split volume by bar direction (unchanged closes count as up), retain total-based POC and value area, and follow a forming bar when its direction changes. Display mode and direction colours are editable in Inputs and persist with the drawing; older files retain the Total default. (#565)
-
The
drawingsfeature separates drawing tools, geometry, hit tests, history and persistence fromwidget;uienables it, so default builds retain their tools. Widget-only charts keep series, studies, markers, primitives and keyboard action variants.configexportsDrawingToolType,DrawingInteractionMode,ParseToolTypeErrorandFontWeight; their existing drawing imports remain available withdrawings. Migration: applications using drawing APIs withdefault-features = falseadddrawingsalongsidewidget. Drawing keyboard actions do nothing without the feature; Delete still removes a selected study. (#449) -
DrawingToolRegistryregisters stable host ids, names, anchor counts and sharedDrawingRendererimplementations.Drawing::customretains the id and JSON settings; the manager supplies multi-click placement, coordinate projection, handles, undo and storage, dispatches rendering and authoritative hit tests, and applies the renderer’s settings editor throughshow_custom_settings. Unknown ids remain stored until their implementation is registered.ChartBuilder::with_drawing_registryinstalls the catalogue before construction. Built-in availability filters registry picker entries and rejects disabled creation; clone the registry intoDrawingToolbar::registryto hide or disable its drawing rows, glyphs, measure button and shortcuts. Hosts build custom pickers fromcustom_toolsand activate entries withset_custom_tool. Migration:Drawingliterals addcustom_tool: Noneandcustom_settings: serde_json::Value::Null, or useDrawing::new.DrawingRenderernow receives the current drawing and chart view; implementations providerender,hit_testand optionalsettings, while the manager supplies anchor handles. Its existing rendering-module import is retained. (#152) -
Chart::create_drawingcreates validated drawings from UTC times and prices usingDrawingfor style, locking, layer and study ownership.drawing_pointsandset_drawing_pointsround-trip and edit those anchors; the existingdrawing_point_atanddrawing_point_timeconversions are public.DrawingManager::add_drawingvalidates chart-coordinate creation and records undo. Drawings addselectable,saveable,listedand a host-definedgroup;listed_drawings,group_drawings,set_groupandselect_groupsupport host object lists and group actions. Non-saveable drawings stay out of chart saves and persistence notifications, including undo, while remaining visible. Existing anchored text and notes usescreen_anchorpane fractions. Hosts own durable storage and retain or remap study ids. Migration:Drawingliterals add the four fields, or useDrawing::new; older saved drawings default to selectable, saveable and listed, without a group. (#154) -
ZigZag::pivotsexposes the source-bar indices, prices and high/low kinds used by its drawn swings; the last pivot remains provisional. Withdrawingsandstudies,AutoDrawingregisters trend line, parallel channel, Fibonacci retracement and extension, and pitchfork studies, each with Swing size, ATR multiple, ATR period, Zig Zag deviation and depth inputs.AutoDrawing::with_atrsizes swings by volatility: a reversal counts when it moves from the last extreme by at least a multiple of the average true range over a period, taken as a percentage of the confirming bar’s close, and bars before the average is defined, or without a finite positive close, confirm none. The catalogue registers these studies with 3 times the 10-bar average and a depth of 10, so they draw on minute, hourly and daily bars alike, where a fixed 5% swing left short intervals empty, andAutoDrawing::newkeeps the fixed percentage. Editing the deviation or depth clears the study’s values, as theIndicator::set_inputcontract requires, and a template saved before the swing size input restores on the fixed percentage with its saved deviation, so saved studies keep their anchors. Trend lines join the latest same-kind pivots; channels pass their parallel through the intervening pivot; retracements use the latest confirmed swing and extensions project that swing from the moving last extreme.Indicator::drawingsexposes their results, and the study renderer and hit test reuse the existing drawing geometry and pane mapping. Updating host bars replaces the anchors. Anchor and Fibonacci level prices participate in autoscaling even when the anchors are outside the visible bars. Custom presentation wrappers forwarddrawings, asConfiguredStudydoes. (#178, #1496) -
FibonacciConfig::logarithmicmeasures retracement and trend-based extension levels in logarithmic price, with the same prices used for lines, labels, bands and hit testing in every price scale. It defaults to off, including in older saved drawings, and the Fibonacci properties page edits it. Nonpositive anchors retain arithmetic levels. Extensions project the logarithmic swing from the third anchor. Level labels sit above their lines and omit overlapping labels when levels crowd together. Migration:FibonacciConfigliterals addlogarithmic: falseor use..Default::default(). (#564) -
Trading::showdraws fills in the chart’s symbol as buy/sell arrows outside their bars. Fills on one side of a bar share a mark with up to ten chevrons; optional labels give total quantity and weighted average price, and crowded neighbouring labels group together. Hover lists every fill’s side, quantity, price and time. Marker labels retain the chart background for contrast.Trading::pollannounces fills, partial-fill progress and rejection reasons; the host plays requested execution sounds. (#551) -
Trading lines have joined quantity, P&L and close cells, separate reverse and dotted TP/SL controls, teal/orange brackets and connectors. Working orders have outlined price tags; projected orders offer Buy/Sell submit buttons. Drag previews remain until confirmation or discard. Hidden layers retain the account context needed to value brackets and avoid duplicate exits. The legend offers filled quote buttons, a quantity calculator and a ticket dropdown. Bid and Ask labels stay visible on either price axis. Trading notifications wrap in narrow windows.
-
The Trading settings tab controls positions, orders, executions and their labels, P&L units, reverse controls, quote labels, instant placement, notifications and host-provided execution sounds. Settings persist with
ChartSettingsState; omitted fields use their defaults. Migration: handleSettingsTab::Trading,TradingLineAction::ExitandQuoteSide::Ticketin exhaustive matches. The ticket intent opens a ticket even with instant placement enabled.Trading::one_clickmoves toTrading::display.instant_orders;TradingSettings::show_buy_sell_btnsis replaced byStatusLineOptions::show_quote_boxes.TradingLineOptionsliterals addshow_orders,show_positions,submit,reverse,take_profit,stop_loss,pnlandbracket_pnl; usesubmitonly for projected orders and handleTradingLines::submitted.TradingLines::outlinedidentifies outlined tags.UiColorsaddstake_profitandstop_loss;Toastadds optionaltradingdetails. Brokers push an order before its fills and preserveOrderRequest::position_bracketon position exits. The paper account keeps those exits from increasing exposure after a close or reversal and rejects exposure beyond the balance at its configured leverage. -
The order ticket is a panel beside the chart. Its header holds the symbol, a menu with the presets and one-click trading (the same
Trading::display.instant_orderssetting), and a close button above an Order and DOM switch. The Order tab shows the bid and ask as Sell and Buy halves with the spread on the seam, the chosen side filled; Market, Limit, Stop and Stop limit tabs; the price with its distance in ticks from the ask or bid, or the distance itself after the swap button; the quantity in units or as an amount with the order’s value, and on market orders the risk at the stop loss in percent of the account’s balance; collapsible exits with their risk to reward ratio, each exit switched on and off and entered as a price, ticks, a percentage or money while it keeps its price; the time in force; and the order’s estimated margin against the account’s balance, leverage, tick value, trade value, reward and risk, above a two-line send button in the side’s colour.BracketMode::Moneyenters an exit as the profit or loss at it,TimeInForce::{Week, Month}request expiry at the end of the week or the month from brokers that advertise them, andTradingRules::leverageestimates the margin an order needs. Migration: callTrading::show_ticketbefore laying out the chart, sinceTrading::showno longer draws the ticket; exhaustiveBracketModematches handleMoney. Risk sizing takes a percentage of the account’s balance instead of an amount of money. The broker contract accepts one exit pair per order. -
The ticket’s DOM tab is a depth ladder of the chart’s order book: the bid and ask sizes at each price as tinted cells, prices above the last trade in the sell colour and below it in the buy colour, the price of the last trade marked, a level’s order count and latest observed size change on hover, and the totals of the sizes in view. A profile behind the prices sums the feed trades retained by the chart; each level’s tooltip separates volume traded at bid, at ask and of unknown side. The latest account fill for the symbol is outlined separately from the last trade. Clicking a bid or ask cell places a limit order on the passive side of the market and a stop order beyond it, the user’s working orders show as
LIMITandSTOPtags in the margin of their side at their price, and dragging a tag moves its order and right-clicking it cancels it, each after confirmation. Orders at the same price share a tag with a chooser for the order to drag or cancel. The ladder centres on the current bid/ask midpoint, or the last trade without quotes, and scrolls, keeps prices fixed through a press or drag, and its lock keeps it from re-centring. Short panels scroll to the controls. Below it, the user cancels every buy or every sell, sees the position and its profit or loss, flattens, cancels all orders and reverses, buys and sells the ladder’s quantity at market and sets the time in force. Bulk cancellations also wait for confirmation. A new order from the ladder waits for confirmation unless one-click trading is on. (#236) -
Chart::snapshotandrestorekeep the symbol, interval, chart type, display and interaction settings, study inputs and styles, pane order and collapse state, manual scales, view and timestamped drawings.SavedLayoutwrites version 2 documents and reads version 1 with defaults for the newly saved fields. Unregistered studies fail before saving. The layout menu lists, opens, saves, renames and deletes layouts throughStorage, offers debounced autosave and handles Ctrl+S (Cmd+S on macOS) in the demo. Storage requests run in order. Migration: build snapshots throughChart::snapshot; literals ofChartSnapshotandSavedPaneneed the new fields, andSavedPaneis cloned rather than copied. (#197) -
Chart::set_storagesaves and restores timestamped drawings per symbol through the host service, including edits made while a read is pending or before switching symbols. Unreadable documents are kept intact and failed writes retain the drawings in memory and report one error per run of failures.SettingsStorerestores versionedUserSettingsfor the theme, last symbol and interval, drawing favourites and open layout, then saves after a one-second debounce. Its exit flush finishes available replies before writing the latest settings. The demo implementsStoragewith eframe persistence on native and web builds and imports its earlier drawings. (#198) -
ui::trading::BrokerPickeris the dialog in which the user chooses a broker: a grid of the host’sBrokerTiles, each with a name, an optional logo, subtitle or rating, a featured badge and a favourite star the user toggles, after the built-in paper account, with a search and a “Need a broker?” link that returnsBrokerPickerAction::NeedBroker. Picking a tile shows its connect card, whose Connect button returnsBrokerPickerAction::Connectwith the tile’s id for the host to connectTrading, such as to aPaperAccountforBrokerTile::PAPER.Trading::show_account_panelshows the account panel in a host panel: a tab named after the broker with a Trade button and minimize and maximize buttons, an account selector that switches between the host’sAccountPanel::accountsor disconnects, a currency, a settings button, and the account’s balance, equity, realised and unrealised profit and loss, margin, available funds and orders margin as the broker reports them. Its Positions, Orders, Order History, Balance History and Trading Journal tabs list what the broker pushes; Order History switches between orders and individual executions, each with its own CSV export, with right-aligned figures, profit and loss in the rising and falling colours, the chart’s symbol highlighted, a column chooser and an export as comma-separated values; clicking a symbol returnsAccountPanelAction::SelectSymbol, and a hovered position or order offers to close it or cancel it after confirmation, or to change an order’s quantity, prices and brackets.Trading::disconnectandis_connectedend and report the connection. The demo’s Trade button and Buy and Sell buttons open the picker until an account is connected, after which Trade shows or hides the account panel under the chart, and its settings button resets the paper account. (#220, #216) -
services::PaperAccountis a ready-madeBrokerthat simulates an account. The host chooses its currency and starting balance, and withleverageandcommissionthe leverage its margin follows and the commission each fill pays as a fraction of its value. Fed the last prices withset_price, live or replayed, it fills market orders at the last price and limit and stop orders at the first price that reaches them, a limit at that price or better, works a triggered stop-limit order on as a limit order, turns an order’s take profit and stop loss into exit orders that cancel each other, nets one position per symbol at its average price, and books the realised profit or loss and the commission of each fill to the balance. It reports the equity, the realised profit or loss, the margin of the positions and of the working orders and the available funds, values each position at the last price with its trade and market value, leverage and margin, and keeps the most recent 1,000 finished orders, executions, balance changes and journal entries, which it pushes again on every connection;resetreturns it to the starting balance.Accountgainsrealized_pnl,margin,orders_marginandavailable_funds,Positiongainslast_price,trade_value,market_value,leverage,marginandexpiration, andOrdergainsfill_price,placedandclosed, all optional, andAccountEvent::BalanceandAccountEvent::Journalcarry aBalanceChangeand aJournalEntryfor brokers that keep history; the terminal skips pushes with non-finite values. The demo trades the same paper account live and during replay, feeding every traversed replay close, including when playback skips several bars. During replay the order ticket uses that close instead of the live bid and ask. (#221) -
The top toolbar ends with Publish, Trade and a host call to action, as the right end of the default layout does. Publish, a light bulb with a plus, emits
TopToolbarAction::Publishfor the host to capture the chart withChart::export_imageand share it through its own service;Control::Publishhides it. Trade, an outlined pill, emitsTopToolbarAction::ToggleTrading, whichTrading::toggle_ticketanswers by opening the order ticket for the chart symbol or closing it; it shows only whileTopToolbarState::can_tradereports an attached broker andControl::Tradingleaves it visible.TopToolbar::call_to_actiontakes an id and label for a filled pill after the host actions that returnsTopToolbarAction::Host(id); it isNoneby default and then nothing is drawn. The demo copies a published image to the clipboard, turns Trade on with its paper account and keeps it available during replay, and reports its Upgrade call to action. Migration: exhaustive matches onTopToolbarActionhandle or ignorePublishandToggleTrading. (#844) -
A quote contract feeds the watchlist, the symbol details panel, the symbol header and the order ticket.
model::Quoteholds a symbol’s last price and previous close, from whichchangeandchange_percentfollow, its update time, session volume, best bid and ask, and latest pre-market or post-market trade (ExtendedHoursQuote). The host streams quotes through the newservices::Quotesservice:WatchlistPanel::set_serviceattaches it, andWatchlistPanel::poll, called each frame, subscribes to the symbols of the active list and the selected symbol, subscribes again with a new stream when they change or the stream lagged, which stops the previous one, and applies the pushed quotes.WatchlistPanel::quotereads a symbol’s quote back forSymbolDetailsPanel::set_quote,SymbolHeader::quoteand the newTrading::set_quote, with which the ticket enters a market buy at the ask and a market sell at the bid instead of the last price.WatchlistPanel::set_price_decimalssets a symbol’s price decimals. The demo streams its watchlist through a quote service. (#222) -
The
order_flowbench pushes the order flow of a busy instrument into a chart’s feed: a synthetic book of 200 levels a side with 2,000 trades a second, each followed by its depth delta, 6 orders added or cancelled near the touch and a quote, 18,000 messages a second, drawing a frame for every 1/60 s of market time. It checks that the chart’s book matches the generator’s and prints the messages pushed per second, the frame time, the heap allocations per message and the heap the chart holds, with the depth history sampled every second and with one filled to all its resolutions:cargo bench --bench order_flow. Over 300 s of market time it pushes about 6.5 million messages a second with 0.02 allocations per message, all from the per-frame trade queue, and holds 7.8 MB, or 22 MB with a filled depth history. The demo’s live feed pushes the same synthetic book: each trade takes the liquidity in its way, the book quotes again around the new last price, orders come and go near the touch, and the quote is the book’s best bid and ask with their sizes. (#228, #229) -
Chart::set_depth_historykeeps the order book the feed sends over time in adata::DepthHistory, read withChart::depth_history: columns of the resting size per price row on a fixed time grid, for liquidity heatmaps.DepthHistoryConfigsets the cadence (1 second by default), the rows kept per side nearest the touch (100), the ticks grouped per row (1) and the columns kept at each of 8 resolutions (600). The book is sampled as feed updates arrive, at the end of each period, so a column does not depend on the frame rate, a book that did not change for several periods gives one column spanning them, and an update stamped more than a minute after the feed’s time samples nothing. When the newest columns overflow, the two oldest merge into one spanning both, each row’s size averaged over their spans, so the history spans at least 42 hours in about 15 MB with the defaults.OrderBook::is_crossedreports a best bid above the best ask. (#229) -
Trades carry the sale conditions the exchange reports:
Tick::conditionsholdsTradeConditionsflags (OFF_EXCHANGE,AUCTION,ODD_LOT,OUT_OF_SEQUENCE,EXTENDED_HOURS), set withTick::with_conditionsand tested withintersects, so studies and overlays can leave out prints such as off-exchange or auction trades. (#228) -
Horizontal axes other than time, such as option strikes and yield curve maturities. A
scales::HorizontalScaledecides which keys of the horizontal axis are labelled, how they read and how the crosshair label reads, andChart::set_horizontal_scalesets one; the time-based chart uses the same trait through itsTimeFormatter. A key is thetimeof a bar, an instant that sorts as the key does, so price scales, panes, series, the crosshair, markers, price lines and drawings work on any scale, andscales::key_timeandscales::time_keyencode numeric keys.PriceHorizontalScalelabels prices with a set number of decimals, multiples of 100 first, then of 50, 25, 10, 5 and 1, then half prices.MaturityScalelabels months as3M,2Yor2Y6M, multiples of ten years first, and itswhitespacebars give the main series a slot every month, so curves added as series are spaced by maturity. On these scales the most significant marks in view are bold. Session breaks, extended-hours shading and the time spans of the measuring tools are drawn on the time scale only, andChart::format_timeand the time column ofChart::export_csvformat a key as the crosshair does. Thevolatility_smileandyield_curveexamples draw an implied volatility smile by strike and a yield curve by maturity with the public API alone. Migration:TickMarkliterals addbold, which the time axis sets for day, month and year marks;chart::render_crosshair_fulltakes a&dyn HorizontalScalein place of a&dyn TimeFormatter, so pass&formatterfor aBox<dyn TimeFormatter>;drawings::rendering::ChartViewliterals addtime_axis: true. (#835) -
Chart::set_time_formatter,set_price_formatterandset_percentage_formattertake host formatters for the time axis, crosshair, tooltip and price scale labels, andset_localeandset_date_formatset the language of month and weekday names and thestrftimepattern of crosshair and tooltip dates. A time formatter writes axis marks withTimeFormatter::format, which receives the tick mark type, and hover labels andChart::format_timewithformat_crosshair, in the chart’s time zone. The price formatter writes crosshair labels and price tags withPriceFormatter::formatand axis ticks with the newPriceFormatter::format_tick, which defaults toformat, on every price scale in the normal and logarithmic modes; the percentage formatter does the same with the percentage or index value in the percentage and indexed-to-100 modes. Studies keep their own formats.LocaleTimeFormatternow writes month and weekday names and the AM/PM marker in its locale’s language instead of English and honoursshow_seconds; the localized names come from chrono’s locale tables behind the newlocalescargo feature, on by default, and without it, as in a build withdefault-features = false, they stay English.TimeFormatterBuilder::with_date_formatandwith_formatterexpose the same options. Migration:DefaultTimeFormatterstruct literals adddate_format: Noneor use..Default::default(),LocaleTimeFormatterliterals addshow_seconds: trueanddate_format: None, andchart::price_axis_widthtakes the price formatter as a fourth argument; passNonefor the built-in labels. (#203) -
A
Barcan stand for a single value, hold an empty slot of the time axis, carry colours of its own and carry the host’s own data.Bar::from_valuemakes a point of a line, area, baseline or column series without filling OHLC.Bar::whitespace, whose values are all NaN (Bar::is_whitespace), keeps its slot when a series is loaded or updated, so a gap such as a halted session stays visible and a time of another series has a slot: nothing is drawn there, lines, areas and baselines break across it, the crosshair moves through it without a magnet snap, the legend and tooltip show no values for it, and the last-price line, countdown, previous close and percentage base use the nearest bar with a value. Studies take it as a bar without a value, as they take other non-finite input, price-based chart types and their ATR box sizes skip it, and trades in its slot fill it.Bar::colorsholds an optionalBarColors: the body (color), border and wick of a candle, the colour of an OHLC bar, a column or a line marker, the colour of the line from the bar to the next on line, step line, area and HLC area charts, and the top and bottom line and fill colours of a baseline segment; a candle border takes its colour when the series draws borders, and the last-value tag takes the bar’scolor.Bar::payloadholds anArc<serde_json::Value>the chart does not read, which comes back with the bar fromChart::barsand inChartPointer::barandseries_bars; at an empty slotChartPointer::baris the whitespace bar. JSON and CSV bars accept a date alone, such as2024-03-15, as midnight UTC, the open of its day bar. A JSON bar with missing ornullvalues is whitespace, and colours and payloads round-trip through JSON. Resampled bars leave out the colours and payloads of their source bars. Migration:Barliterals addcolors: None, payload: None, or useBar::new; struct updates from a borrowed bar,Bar { time, ..*bar }, become..bar.clone(), since the new fields are notCopy. A bar whose values are all NaN, formerly dropped as invalid, is now kept as whitespace. (#826) -
Chart::export_pngrenders the image ofChart::export_imageon the CPU and returns it encoded as PNG, so a host needs no renderer or GPU readback.ImageExportOptions::include_crosshairdraws the crosshair where the pointer last placed it over the plots, or whereChart::set_crosshair_positionor a synchronized chart placed it since, and the export dialog offers it as “Crosshair”. Migration: buildImageExportOptionswith..Default::default()where every field was listed. (#834) -
Chart options change at runtime:
Chart::set_chart_optionsreplaces the options thatChart::chart_optionsreads back and keeps the view unless the bar spacing, its bounds or the right offset change.Chart::set_sizegives the chart an explicit size in points instead of the spaceshowis given.Chart::set_crosshair_positionshows the crosshair at a time and a main-pane price, with the horizontal line and price label at that price.ChartOptions::hovered_series_on_topdraws the main series or overlay study under the pointer above the others, in the priority a click selects them. Migration: buildChartOptionswith..Default::default()where every field was listed. (#834) -
A study’s legend row adds a more-actions button after its hide, settings and remove buttons, and the remove button shows a bin. The button, or a secondary click on the row, outlines the row and opens the study’s menu, the one a secondary click on the study’s plot now opens, in the chart menu’s style with its icons and shortcut column. Its rows add an alert on the study’s value at the legend’s bar, open the indicators dialog, add the study to the dialog’s favorites, and open submenus for the visual order, the visibility on intervals (the chart’s interval and above, and below, alone, or every interval, kept in
StudySettings::hidden_intervals), moving the study to a new pane above or below its own, to another pane or to the main pane, and pinning it to the pane’s price scale, a new left scale or no scale. Copy, Hide, Remove, Object tree and Settings follow. Context menu rows can open submenus, which open beside their row on the side with room.ChartMenusapplies the chart’s own actions as one undoable user action and returns every action asChartContextAction::Study;StudyContextMenuAction::AddAlertcarries the boxedAlertfor the host’s alerts service, on the study’s output or, for volume, onAlertSource::Volume.Chart::reorder_indicatortakes aVisualOrderfor a study’s place in the draw order of its pane, where the main pane’s price series is one of the items and takes clicks before the studies drawn under it,Chart::set_indicator_scaleandIndicator::set_scalepin a study to aStudyScale, andChart::copy_indicatorandChart::paste_indicatorcarry a study with its inputs, styles, interval visibility, placement and scale to another chart as clipboard text. Delete and Backspace remove the selected study when no drawing is selected. The demo saves the alert, opens the indicators dialog, the favorites and the object tree with the study selected, and copies and pastes studies with Ctrl+C and Ctrl+V. Adding an indicator does not yet take the study as its source, studies have no shared left scale, and a volume overlay keeps its own band. Migration:PaneTarget::Paneuses the stablePaneIdof an existing pane;StudyActionaddsMenu { index, pos }and is no longerEq, andPaneInteractionaddsmenu; exhaustive matches onStudyActionandChartContextActionadd the new variants, and a host that handled a study’sChartContextAction::Seriesactions handlesChartContextAction::Study. (#850) -
Primitives draw host content inside the chart.
Chart::attach_primitiveattaches aPrimitiveto the main series, an added bar series or a study, and it draws in the pane of that series on its price scale: behind the series and studies, above them, or above the drawings as well (PrimitivePass), inside the price and time axes behind their labels, and asPriceAxisLabelandTimeAxisLabeltags that the axis labels give way to. Itsautoscalerange joins the fit of the series’ scale, itshit_testreports the pointer asPointerTarget::Primitiveand sets the cursor, and itsattached,detachedanddata_changedhooks follow the series, with the egui context to request repaints.Chart::add_custom_seriesadds a series type the host defines: a study supplies the values that the legend, crosshair, last-value tag and autoscale read, and a primitive draws its points in place of the study’s plots and hit tests them, selecting the series. Image exports draw the same primitives.examples/primitives.rsshades the regular session behind the bars with labels on the time axis, and draws the range of each bar as a custom series in its own pane. (#830, #88) -
The rest of the widget bar’s panel set.
HotlistsPanelshows the hotlists the host names (such as top gainers) through the newDatafeed::hotlist, answered asHotlistEntrysymbols with their last price, change in percent and optional price decimals, and returnsHotlistsAction::SelectSymbol.NotificationsPanelshows the log the newservices::Notificationsservice pushes asNotifications (time, title, text and symbol), keeps the most recent 1,000, counts entries not yet shown for the bar’s badge and starts over after a lagged stream.ChatsPanelshows the rooms and messages the newservices::Chatsservice pushes asChatEvents and posts what the user writes throughChats::send; a posted message appears once the host pushes it.ProductsPanellists the host’sProducts and returnsProductsAction::Open. Accounts, rooms, moderation and the products themselves stay with the host. The demo feeds every entry of the bar: synthetic hotlists, a log of its messages and alert triggers with a badge on the Notifications entry, two chat rooms that echo what the user posts, and a launcher of its own panels. (#845) -
ScreenerPanelshows the rows the feed answers through the newDatafeed::screenin a table with the host’s column sets (ScreenerColumnSetofScreenerColumns). The user picks a set, adds filters on its columns (ScreenerFilter: a column,ScreenerOp::AboveorBelow, a value) and sorts by clicking a heading; every change asks again with aScreenerQueryof the set’s columns, the filters and the sort, and the feed screens, sorts and limits.ScreenerRowcarries the symbol and one formatted value per column. The panel returnsScreenerAction::SelectSymbol,ExportCsvwith the shown rows (every field quoted) andSendToWatchlistwith their symbols. The demo screens its catalog symbols on their synthetic quotes and sends results to a new watchlist. (#224) -
CalendarPanelshows the economic, earnings, dividend and IPO calendars the feed answers through the newDatafeed::calendar, grouped by day with each event’s time, country, importance and figures. The user picks the calendar, the days (yesterday, today, tomorrow, or this or next Monday-to-Sunday week, in UTC), the least importance of economic events and, withCalendarPanel::set_countries, the countries; every change asks again with aCalendarQueryand the feed applies the filters.CalendarEventcarries the kind, time, country, title, symbol,Importanceand the actual, forecast and prior figures already formatted. A company event returnsCalendarAction::SelectSymbol. The demo answers synthetic releases, earnings, dividends and offerings. (#244) -
NewsPanelshows the headlines the feed answers through the newDatafeed::newsfor the chart’s symbol or the whole market, andNewsPanel::highlightsshows short summaries under their headlines in the same way.NewsQuerycarries the symbol (Nonefor the market), whether highlights are wanted and a limit, andNewsStorythe id, publication time, headline, source, text, symbols and link of a story. Each symbol or scope change asks again and only the latest answer shows; a feed keeping theFeedError::NotSupporteddefault gets a notice. An opened story shows its text and returnsNewsAction::ShowOnChartwith its time, which the host passes toChart::scroll_to_time, orNewsAction::OpenUrl. The demo shows synthetic highlights and headlines for its catalog symbols. (#243) -
The widget bar has built-in entries for the full panel set:
RightBarIcon::Watchlist(the watchlist with the symbol’s details) before Alerts and the Object Tree, and a second group at the foot of the bar ofHighlights,Screener,Hotlists,Calendar,News,Notifications,ChatsandProducts, above the line and Help.WidgetBar::defaultstill shows Alerts, the Object Tree and Help; a host adds the entry of each panel whose feed it supplies toWidgetBar::icons, and entries draw inRightBarIconorder whatever their order in that list. Products, the launcher, draws as a filled round button. New glyphs on the 24 unit grid:WIDGET_BAR_WATCHLIST,WIDGET_BAR_HIGHLIGHTS,WIDGET_BAR_SCREENER,WIDGET_BAR_HOTLISTS,WIDGET_BAR_NEWS,WIDGET_BAR_NOTIFICATIONS,WIDGET_BAR_CHATSandWIDGET_BAR_PRODUCTS. The demo shows the watchlist through the built-in entry and the data window in the Object Tree, and no longer has a Data Window entry. Migration:RightBarIconis#[non_exhaustive], so amatchon it adds a wildcard arm. -
Studies can draw price bands as
StudyZonevalues, a band between two source bars in the style of one of the study’s outputs, returned byIndicator::zonesand stored per zone instead of per bar. The visible zones of a study count in its price autoscale.Gapsdraws its gaps as zones, one per extent a gap has held, with “Up gaps” and “Down gaps” outputs for their style, so its memory follows the gaps shown rather than the bars and it shows up to 500 gaps. (#842) -
SeriesStylesets a bar series’ last value label, its price line’s visibility,PriceLineSource(the newest bar or the newest bar in view), colour, width and style, a base line at 0% or 100 on percentage and indexed scales, anAutoscaleProviderthat replaces the range the series contributes to its scale’s fit, and the click tolerance of the main series.Chart::series_styleandseries_style_mutreach the main series’ style and each host series’SeriesOptions::style; the chart-wideshow_symbol_last_valandshow_price_lineswitches still hide every label and price line. Host series draw a price line only when asked. Migration: struct literals ofSeriesOptionssetstyleor use..Default::default(). (#832) -
AreaStyle::invert_filled_areafills the Area chart from its line up to the pane top, and turning offrelative_gradientspreadstop_filltobottom_fillover the whole price pane instead of between the line’s visible extreme and the edge the fill reaches.ChartTypeParams::columns_basedraws Columns up and down from a price instead of up from the pane bottom. Migration: struct literals ofAreaStyleandChartTypeParamsset the new fields or use..Default::default(). (#832) -
LinePlotStyle::line_typedraws the Line, Line with markers, Area and Baseline charts asLineType::Curved, a Catmull-Rom spline through every point, or with straight segments.ChartTypeStyles::crosshair_marker_radiusmarks the hovered bar on the line of the line-based charts, ringed in the chart background, andlast_price_animationpulses at their last price continuously or once per update withLastPriceAnimation. Both are off by default. Migration: struct literals ofLinePlotStyleandChartTypeStylesset the new fields or use..Default::default(). (#832) -
ChartTypeStyles::barsstyles the Bars chart:BarsStyle::open_visiblehides the open tick, andthin_bars, on by default, draws bars with the chart’s wick width at every zoom level; without it the stroke is half the bar width, at least 1.5 points. Migration: struct literals ofChartTypeStylessetbarsor use..Default::default(). (#832) -
CrosshairMode::MagnetClosesnaps the price pane’s crosshair to the bar’s close only; volume and study panes snap to their values as withMagnet.CrosshairStyle::Hiddendraws neither crosshair lines nor axis labels while legends, the data window and tooltips keep following the pointer.CrosshairOptionsstyles each line withvert_line_styleandhorz_line_styleand colours each axis label withvert_label_background_color(time axis) andhorz_label_background_color(price axis). Migration: replaceline_stylewith both line style fields andlabel_background_colorwith both background fields; exhaustive matches onCrosshairModeandCrosshairStyleadd the new arms. The settings dialog’s single crosshair style sets both lines. (#832) -
ChartConfig::grid_line_stylesets the grid’s line style, dotted by default, andvertical_grid_line_styleoverrides it for vertical lines, asvertical_grid_colordoes for colour. Migration: struct literals ofChartConfigset both fields or use..Default::default(). (#832) -
LineStyle::LargeDashedandLineStyle::SparseDottedadd long dashes and widely spaced dots to drawings, series, price lines and their settings menus.CrosshairLineStyle,SessionBreakStyleand the studyPlotPatterngain the same two styles.LineStyle::namegives each style’s menu name. Migration: exhaustive matches on these enums add arms for the two styles. (#832) -
Panes are reachable from the API.
Chart::add_panecreates an empty pane,remove_paneremoves one with its series and studies,paneslists them from top to bottom withPaneId::MAINfor the price pane, andpane_seriesandseries_panemap panes to the series and studies they draw.move_series_to_paneplaces a host series or a study in any pane; below the price pane a host series uses the pane’s price scale and draws its line, price lines, markers, legend row and last-value tag there, and crosshair and click events report values in its units, snapping to its close in magnet mode.move_paneandswap_panesreorder panes, the price pane included, which the pane menu can now also move. Expanded panes share the height by stretch factor, 3 for the price pane and 1 for the others by default:set_pane_stretch_factorsets it,set_pane_heightturns a height in pixels into one, andpane_heightreads the height drawn in the last frame.set_preserve_empty_panekeeps a pane after its last series or study leaves it.PaneOptions, set withChart::with_pane_optionsorpane_options_mut, turns separator dragging off and sets the separator and hover colours. The demo’s quick search adds a symbol in a new pane above the price pane. (#827) -
ChartConfig::price_axistakesPriceAxisOptions, which draw a border between the plot and the price axis in the theme’s border colour or a chosen one, a tick beside each label, and labels for the prices at the top and bottom of the pane in place of the ticks next to them, and choose whether labels the pane edges cut are hidden (the default) or shown clipped.PriceScaleOptions::tick_marksgives each scale itsPriceMarkGeneratorConfig, sotarget_densitysets the number of labels and grid lines;PriceMap::marksgenerates them.Chart::price_axis_widthreturns the width of the left or right price axis at the last frame. Migration:render_price_labelsandrender_price_labels_at_postake thePriceAxisOptionsafter the colours;ChartConfigandPriceScaleOptionsliterals add the new fields or use..Default::default(). (#833) -
Chart::set_watermarkpaints a hostWatermarkbehind the series of the price pane, alongside the symbol watermark ofChartConfig: an optionalegui::Imageabove any number ofWatermarkLines, each with its own text, size,FontWeightand colour, aligned together at anyAlign2with a padding from the pane’s edges. The image fits the pane less the padding, keeping its aspect ratio, unless itsmax_sizeis smaller; itstintsets its opacity. Watermarks are kept in exported images. (#831) -
Chart::set_change_markersmarks, on a bar series, where a live update raised or lowered the close of a stored bar: a dot at the new close with a chevron above it for a rise or below it for a fall, in theChangeMarkersup and down colours, for itsduration(5 seconds by default). Updates fromupdateand from a connected feed count; unchanged closes, new bars and history do not, and replacing the bars withset_datadrops the marks. (#831) -
MarkerPos::{AtPriceTop, AtPriceBottom, AtPriceMiddle}anchor a marker toMarker::price(set withMarker::at_price) just above, just below or across that price instead of to its bar, on the main and on added series.Chart::set_marker_optionstakesMarkerOptionsper bar series:auto_scale(default true) widens the autoscaled range to the price-anchored markers in view, andz_orderpaints the markers with their series (Normal, the default), over every series and study (AboveSeries, where main series markers were painted before) or over the price lines and drawings too (Top).Chart::markersreads back the markers set on a series. Migration:Markerstruct literals addprice: None, and exhaustiveMarkerPosmatches handle the three new positions. (#831) -
Chart::add_price_lineadds one price line to a bar series and returns aPriceLineIdhandle;update_price_linemoves or restyles that line in place,remove_price_lineremoves it andprice_linereads it back.set_price_linesstill replaces the whole list and retires the handles of the lines it replaces. The demo moves or removes a level line through its handle from the chart menu. It opens on a plain chart; Toggle API samples in its quick search adds the level line at the recent high, marks a fill and a stop at their prices, marks live changes of the close and signal bars, and shows a two-line watermark with an image.PriceLine::axis_label_color,axis_label_text_colorandtitle_colorcolour the axis tag and the title independently of the line, on the main and the added series’ axes. Migration:PriceLinestruct literals add the three fields asNoneor use..PriceLine::new(price, color). (#831) -
Pointer events carry what a host legend, tooltip or context action shows.
ChartPointeradds the rendered slotindex, the UI-pointpos, thepanecounted from the top, the main seriesbarandprevious_closeat that slot, the bars of visible added series at its time, the visible study plots with the id of each study, the drawing, series or study line under the pointer as aPointerTargetin click priority, the heldmodifiersand thePointerKind.ChartEvent::DoubleClickfollows the click that completes a primary double click.CrosshairMovedalso reports a stationary cursor whose bar or modifiers change. egui reports pens as touch. The demo’s data window reads the hovered values from the crosshair payload. Migration:ChartPointeris no longerCopyand is#[non_exhaustive]; clone it where it was copied and read its fields rather than building it. (#829) -
The study catalogue adds eight oscillators under their conventional titles:
AcceleratorOscillator(“Accelerator Oscillator”, Bill Williams’ AO minus its 5-bar average, columns green when rising and red when falling or unchanged),AroonOscillator(Aroon Up minus Aroon Down over 14 bars, -100 to 100 with a zero level),AverageDailyRange(the 14-bar average of high minus low),BBTrend(John Bollinger’s comparison of 20 and 50-bar bands at 2 deviations, columns shaded by sign and direction),ChaikinOscillator(EMA 3 minus EMA 10 of the Accumulation/Distribution line, seeded with the first value),BullBearPower(high plus low minus twice the 13-bar EMA of the close, as Elder Ray seeds it),AdvanceDeclineRatioBars(“Advance/Decline Ratio (Bars)”, up bars over down bars against their open in the last 9 bars, without a value when no bar closed down) andUlcerIndex(Peter Martin’s root mean square drawdown from the 14-bar highest close). Their lengths are editable inputs, except the fixed 5, 34 and 5 of the Accelerator Oscillator; each skips bars with non-finite inputs and is checked against values computed independently from its published definition. (#176) -
Built-in oscillators
PriceMomentumOscillator(Swenlin’s doubly smoothed one-bar rate of change with an EMA signal, 35/20/10),PringsSpecialK(Pring’s twelve weighted rate-of-change averages with a twice-smoothed 100/100 signal),RciRibbon(short, middle and long rank correlation lines, 10/30/50, levels at +80, 0 and -80),RelativeVolatilityIndex(Dorsey’s RVI of the 10-bar close deviation with 14-bar EMAs, levels 80/50/20 with a filled band),SMIErgodicIndicatorandSMIErgodicOscillator(Blau’s true strength ratio with its EMA signal, and their difference as a histogram, 20/5/5) andWoodiesCCI(turbo 6 and 14-bar CCI of the close, with columns coloured by the five previous values, levels at +100, 0 and -100). Each is in the factory catalogue under its conventional title and checked bar by bar against an independent calculation. (#176) -
Six price studies join the catalogue.
WilliamsAlligatordraws Bill Williams’ jaw, teeth and lips, smoothed averages of the median price over 13, 8 and 5 bars displaced 8, 5 and 3 bars ahead, with editable lengths and offsets.ChandeKrollStopdraws Chande and Kroll’s short and long stops (ATR length 10, coefficient 1, stop length 9).VolatilityStopdraws Wilder’s ATR stop and reverse (length 20, multiplier 2) as crosses coloured by trend.Mediandraws the 3-bar nearest-rank median of the bar midpoint, its EMA with a green or violet fill between them, and bands two 14-bar ATRs away.ChopZonecolours a unit column per bar in nine bands by the angle of the 34-bar EMA of the close.BollingerBarsredraws each bar at full width throughIndicator::candles, with the wicks as blue blocks behind an up or down body. (#176) -
TimeWeightedAvgPrice(Time Weighted Average Price) is the mean of a price source, ohlc4 by default, over the bars since the start of each anchor period, andVwapAutoAnchored(VWAP Auto Anchored) draws one volume weighted average price, of hlc3 by default, from an anchor bar to the latest bar: the first bar of the last session, week, month, quarter, year, decade or century, or the most recent bar with the highest high, lowest low or highest volume among the lastlengthbars (20 by default). Its Auto anchor takes the period from the chart interval: the session below a day, the month at a day, the quarter up to 10 days, the year up to 60 days and the decade above. Both count periods in the instrument’s exchange trading days as VWAP does, throughAnchorPeriod. (#176) -
Volume24h(“24-hour Volume”) sums the volume of the bars opened in the last 24 hours on any intraday interval, giving the bar’s own volume on daily bars and no value on longer ones.RelativeVolumeAtTime(“Relative Volume at Time”) divides the volume of the current day, week or month so far (or of the bar alone in Regular mode) by its average at the same point of the previous 10 periods, with trading days from the instrument’s time zone and session, as columns around a level at 1.TradingSessions(“Trading Sessions”) shades the bars that open within the Tokyo, London and New York exchange hours, or three host-defined sessions in their own time zones, on intraday charts.Seasonalityprojects each month from the previous month’s close and the average change of that calendar month in earlier years, as a filled box with the average, standard deviation and month count as hidden plots; the yearly heatmap table and the future part of the current month are left to the host. (#176) -
CandlestickPatterns(“All Candlestick Patterns”) marks 44 bullish, bearish and neutral candlestick patterns, from doji, hammer and engulfing to the star, three-method and tasuki-gap formations, each with its own toggle. APatternTrendinput requires the conventional downtrend or uptrend against SMA(50), or SMA(50) and SMA(200), or ignores trend, and aPatternTypeinput limits the marks to bullish or bearish patterns. Bullish patterns are marked under the low, bearish over the high and neutral ones over the high, each labelled with the abbreviations of the patterns on the bar. (#177) -
Four event studies join the catalogue.
WilliamsFractals(“Williams Fractals”, 2 periods) marks Bill Williams’ fractals with up and down triangles, accepting up to four equal highs or lows just before the fractal bar.PivotPointsHighLow(“Pivot Points High Low”, 10 bars on each side for highs and lows) marks swing highs and lows and labels each with its price throughplot_text.Gaps(“Gaps”) draws each gap of at least 30% of the 14-bar average range as a green or red zone that extends until price enters it, with inputs to shrink a partly filled gap, cap the number of gaps shown (15, at most 500) and limit their length (300 bars, off).RsiDivergence(“RSI Divergence Indicator”, RSI 14, pivots 5 by 5, 5 to 60 bars apart) draws the RSI with its regular divergences, and optionally its hidden ones, as segments joining the two RSI pivots and “Bull” or “Bear” marks. (#176) -
Indicator::plot_textlabels a circle, cross or triangle plot at a source bar, drawing the text under an upward triangle and over the other shapes in the shape’s colour. Configured studies forward it, so pattern, fractal and pivot studies can name what they mark. (#176, #177) -
Chart::fit_content,reset_time_scale,scroll_to_real_timeandscroll_to_positionfit every bar, restore the configured bar spacing and right offset, and scroll to the latest bar or to a right offset in bars, optionally animated over 400 ms to the latest bar and one second to a position. Scrolling to the latest bar does not enable tracking mode, and any other change of the view ends an animation.visible_logical_rangeandset_visible_logical_rangeread and set the fractionalmodel::LogicalRange, including whitespace.index_to_time,time_to_index,index_to_xandx_to_indexconvert between UTC times, fractional logical indices and screen x, interpolating between bars and extrapolating into whitespace.time_scale_sizereturns the time axis size, anddrain_eventsreportsChartEvent::VisibleLogicalRangeChangedandChartEvent::TimeScaleResized.TimeScaleOptions::right_bar_stays_on_scrollnow keeps the right offset when zooming with the wheel, a pinch or the keyboard,uniform_distributionshows time marks of one weight all or none, andallow_bold_labelsturns off bold day, month and year labels. The newtick_mark_max_character_lengthspaces labels for longer custom formats,minimum_heightsets a minimum time axis height, andborder_visiblewithborder_colordraws a line along the top of the time axis.TickMarkGenerator::with_uniform_distributionexposes the same mark selection. Fitting the content, also through its shortcut, now leaves the configured right offset, in bars or pixels, free of bars, with every bar in view. Migration:TimeScaleOptionsliterals addtick_mark_max_character_length,minimum_height,border_visibleandborder_color, or use..Default::default();render_time_labelstakes&TimeScaleOptionsin place of itsticks_visibleflag. (#828) -
SymbolDetailsPanelshows the chart symbol in bold with layout, edit and more actions, its name and exchange with a link to the page inSymbolDetails::url, the host-supplied regular-session quote large with its currency, change and last update time in the time zone given toset_timezone, the pre-market or post-market trade given toset_extended_hourswith its change from the regular last price, the session and 30-day average volume given toset_volumeabove a bar split between the two, the key statistics and profile the feed answers through the newDatafeed::symbol_details, and the user’s notes on the symbol. The layout menu shows or hides the volume, statistics, profile and notes, and the edit button moves to the notes.SymbolDetailscarries statistics and profile as labelled values in display order; an empty section, or a feed keeping theFeedError::NotSupporteddefault, shows nothing, and an answer for an earlier symbol is ignored. Notes are kept per symbol in a versionedStoreKind::SymbolNotesdocument: read before the first write, written as they are edited with one write per document at a time, and never written over after a failed read. The demo shows the details of the chart symbol below its watchlist, with synthetic statistics, volume and notes kept in its app storage, and reports SAMPLE trades outside its regular hours as pre-market or post-market. -
The
TimePriceOpportunitystudy draws each session’s TPO profile on the price pane of a time-based chart, starting at the session’s first bar, as letters or blocks with the point of control, value area and initial balance, for the visible sessions or only the latest one. Its inputs set the period, ticks per row, value area percentage and extended-hours split.Indicator::tpohands itsTPOConfigto the chart, which builds the profiles through the TPO chart type’s code and cache, so a session’s profile equals the chart type’s under the same settings; the study plots no values. The demo lists it with the other studies. (#571) -
TPO profiles follow the chart’s sessions, the instrument’s exchange sessions or calendar days in its time zone, and calendar days in the chart’s time zone without one, instead of the UTC date, and cover the whole sessions of the visible bars instead of the visible bars alone.
TPOConfig::split_sessionsgives separate pre-market, regular and post-market profiles, andTPOConfig::compositescombines the sessions opening within a range into one profile: a range over adjacent sessions merges them, removing it splits them back, and a range over many sessions builds a composite. Periods are at least the bar interval, so hourly bars take the letters A, B and C instead of A, C and E. The value area shading spans the widest row instead of every period, the initial balance is drawn beside each profile, and a profile narrows its columns to fit within its session, switching to blocks when letters no longer fit. The Symbol tab edits the period, ticks per row, value area percentage and extended-hours split, which serialize with the chart type settings asChartTypeParams::{tpo_period_minutes, tpo_row_ticks, tpo_value_area, tpo_split_sessions, tpo_composites}. Migration:to_tpo_profilestakes the bars’BarClock, such asChart::bar_clock; pass&Timeframe::Min1.into()for the previous UTC days.render_live_tpotakes the full bars, the visible range and the clock.TPOConfigandChartTypeParamsliterals add the new fields or use..Default::default(), andCandleDataContextliterals addclockandtick_size. (#106) -
Trading::showdraws broker orders, brackets and positions with price tags, P&L, cancel, close and reverse actions. Accounts withCapabilities::modifycan drag lines to tick prices throughBroker::modify; its default reports unsupported. Changes require confirmation, which is discarded when the order or position changes.chart::render_trading_linesexposes the renderer without theuifeature. (#217) -
ui::trading::Tradingconnects Buy/Sell buttons to a broker-backed ticket with market, limit, stop and stop-limit orders, unit/value/risk sizing, price/tick/percent brackets, time in force and saved presets. Ticket and one-click quantities followBroker::rules; unsupported rules default to whole units and day orders. Prices snap to instrument ticks. The host persists presets and owns the connection; refusals and fills appear as notifications. The demo supplies a session-only paper account whose bracket exits reduce the remaining position. (#219) -
WatchlistPanelshows named watchlists fed by host quotes.WatchlistQuotesupplies the last price and the previous close, from which the panel derives the change and the change percent over the absolute previous close. Lists hold symbols and sections, sort by any column inside each section with missing values last, reorder by dragging while unsorted, take colour flags from the row menu, collapse and expand under their section titles, and import and export comma-separated text with###section titles throughWatchlist::from_textandto_text. The header shows the list name in bold as the list menu, then add symbol, advanced view and more buttons: add symbol returnsWatchlistAction::AddSymbolfor the host to pick a symbol and pass it toWatchlistPanel::add_symbol, advanced view returnsWatchlistAction::AdvancedView, and the more menu adds sections and imports or exports the list. Clicking a symbol, or the up and down arrow keys after a click, returnsWatchlistAction::SelectSymbol; file dialogs and persistence oflistsstay with the host. The demo feeds synthetic quotes, keeps its lists in application storage, switches the chart symbol from the panel and adds the symbols picked in its symbol search. (#223) -
TimeAndSalesPanellists the latest 10,000 trades the host pushes from its stream, newest first, with buys and sells in the rising and falling colours and trades of unknown side neutral. Size filters edited in the panel restrict the list to trades reaching one of them, andpushreturns the matching filter with sound that has the largest threshold, so the host can play its sound.TimeAndSalesConfigsets the price and size decimals and the time zone. The demo feeds the executions of its synthetic stream and shows a notification in place of a sound. (#237) -
HigherIntervalCandlesoverlays higher-period candle bodies and wicks across their source bars, coloured by direction, with editable interval and extended-hours inputs. It uses the shared session aggregation, includes the forming period and rebuilds on live corrections.Indicator::set_bar_clockshares the source calendar andIndicator::candlesexposes period OHLCV and source ranges;ConfiguredStudyretains the geometry through styling and cloning. The demo’s Indicators picker includes the study with daily defaults. Hosts supply the chart bars; another interval from a feed remains host-owned. (#546) -
data::resample_with_sessionderives intervals from host-owned base bars using the instrument’s exchange hours, holidays and overnight trading dates. Intraday buckets start at the first selected session window, and the short last bar stops at its session close. Calendar labels use UTC by default; pass source and targetBarClockvalues for another selected calendar. Inline parsed arguments name.parse::<Timeframe>(). Gaps remain empty and the forming period includes every available input.Instrument::native_timeframesreports the intervals a source supplies without aggregation; unknown metadata staysNone.BarClock::with_sessionand the chart feed preserve those intraday opens through historical and live merging. The demo declares its native minute history. Hosts own fetching and retaining their base data. (#97) -
Chart::export_csvexports loaded source bars with freshly calculated visible study plots, plot displacement, gaps, chart time zone offsets and instrument/study precision.Chart::export_imagerenders an isolated egui frame with chart title, export timestamp, pixel dimensions and transparent background options, retaining drawings, their interval visibility, comparisons, study panes, loaded source marks and typed events with their visibility settings without changing the live chart or polling feeds. Late image results do not change a reopened export dialog. Hosts render the returned meshes/textures and own encoding and delivery; the demo wires offscreen GPU rendering, PNG/clipboard delivery and CSV saving. The export dialog offers these implemented image options; SVG remains absent. Migration:ExportConfigliterals addimage: Default::default()or..Default::default(). (#200) -
Chart::set_mark_sourcerequests host bar annotations, time-axis badges and typed events throughservices::Marksfor the visible UTC range, including whitespace. Stale replies are ignored; empty answers clear source marks while manual markers remain independent. Hosts refresh withreload_marksand read failures withtake_mark_error. Bar marker hover text is displayed, and colliding time badges stack with independent hover and click targets. The demo supplies synthetic marks from its own bars and retains event visibility and sources in copied layouts. (#76) -
model::{TimeScaleEvent, EventKind, EventVisibility}describes host earnings, dividends, splits, economic releases and news with UTC timestamps, headlines, details and stable click IDs.Chart::set_time_scale_eventsaccepts events directly;event_visibilityand the settings dialog’s Events tab filter every category without discarding data. Accounts, news and economic data services remain host-owned. Migration: exhaustiveSettingsTabmatches needEvents;EventsSettingsis now an alias ofEventVisibility, and struct literals addshow_newsor use..Default::default(). Saved settings default missing event fields. (#242) -
Chart::set_replay_timeretains host history behind an exclusive completion cutoff, hides future bars and live quotes, and restores retained updates and the previous feed pause state on exit. Studies and price-based elements use the same window; rewinding clears future study results. Tick-derived overlays stay hidden during bar replay.set_replay_sourcebuilds partial chart candles from completed finer bars using the source calendar.ChartLayout::set_replay_timedrives one cursor across a synchronization group, including hidden slots.ReplayStartPickeremits chart-click, UTC-date, random, first-bar and resume intents.ReplayController::{cutoff, seek_cutoff, session, restore_session}connects source playback and serializable, symbol-checked checkpoints; restoration pauses and requires the saved timestamp. The demo wires these choices, offers minute updates on coarser charts and saves checkpoints through application storage. Hosts own historical/finer data, randomness and durable storage. Bar timestamps are authoritative inReplayController; its separate timestamp vector remains accepted for compatibility. Migration: exhaustiveReplayControlActionmatches needSetUpdateInterval(Timeframe); supply available source intervals throughFloatingReplayControl::set_update_intervals. (#213) -
WidgetBar::register_panelaccepts host widget metadata and a stateful content callback.show_panelrenders the active registered panel with the shared header, close button and a resizable width retained by egui. Host and built-in selections remain exclusive; replacing a registration preserves its strip position. Existing id-only widgets remain available. The demo registers session notes alongside the data window and built-in panels. Hosts own panel data and persistence. (#206) -
ChartMenus::host_entriesappends conditionalHostMenuEntryrows to the chart, series and drawing menus.ChartContextAction::Hostreturns the registered id and original target, UTC bar time and clicked value; time is absent outside loaded data.TopToolbar::host_entriesrenders themed buttons and dropdowns in registration order and returnsTopToolbarAction::Host. The demo lists its research and symbol-copy actions in its main menu; the research action reports the last chart click time and price. The strip scrolls when controls cannot fit. Dropdown choices are one level deep. Hosts supply the services behind these actions. Migration: exhaustive action matches handle the two newHostvariants. (#566) -
Controlnow names every top-toolbar button and the Object Tree and Help rail buttons.set_control_visibleremoves controls from the strip and overflow without leaving separators; hiding an active rail entry clears it. Chart and series menu rows share the Settings, Indicators and ObjectTree controls and add ResetView, CopyPrice and ExportData switches; axis menus honor Settings, TimeZone and Session. Empty menus close, and ContextMenus disables all turnkey menus.ChartOptionscontinues to govern interaction behavior.ChartBuilder::with_themenow retains the theme for local rendering, so text sizes and overlay palettes no longer come from another chart’s context theme.Chart::set_theme_overridereplaces or clears this local style;set_themestill themes egui and clears the local override. Component configs retain their public dimension overrides. (#202) -
Chart::drain_eventsreports UTC visible-range changes, crosshair moves and exits, plot clicks with time and pane values, successful history loads, and symbol and interval changes. Setter notifications retain occurrence order; unchanged views and stationary cursors emit nothing. Existing polling APIs remain independent.visible_time_rangeandapply_synced_time_rangealready read and set UTC plot edges, including whitespace. The basic example records host-owned click state. Hosts supply history and streaming data. (#201) -
Sectorcollects its center, radius endpoint and end ray, sweeping clockwise on screen with selectable borders and optional fill.ArrowMarkLeftandArrowMarkRightplace directional marks in one click.Stickerplaces bundled vector illustrations through the glyph picker. Path drawings end in an arrowhead by default. Arrow Marker already uses two points, and the presentation cursor already highlights pointer movement. Migration: exhaustiveDrawingToolTypematches need the four new variants. Their toolbar artwork is exported fromicons::iconsalongside the existing drawing icons. (#147) -
The Icons/Emojis flyout groups bundled vector icons, Unicode emoji and stickers in a searchable grid, with session recents first and an independent size control. Bundled icons and stickers render without host fonts or image loaders; Unicode emoji retain the host font fallback. The existing
Drawing::font_sizesaves the size, and keep-drawing mode retains the picked glyph and size. Migration: handleDrawingToolbarAction::InsertGlyph { icon_name, size }by callingDrawingManager::start_icon_insertionand setting the prepared drawing’sfont_size;InsertEmojiremains available for existing callers.ToolbarStateliterals addglyph_picker, or use..Default::default(). Hosts continue to own durable drawing storage. (#742) -
Chart::add_seriesattaches host-fed close-price lines with stable ids, independent history and streaming updates, markers and price lines.SeriesScaleassigns bar series to shared right or left axes, hidden overlays or additional labelled scales;set_series_scaleandseries_price_scale_mutalso accept the main series.add_comparisondefaults to a shared percent range with a separate first-visible-close reference for each member.set_series_visibleandremove_seriescover every bar series, including the main one; hidden members do not stretch auto-scale ranges. Removing the main series pauses its feed and retains its time axis for the remaining series and drawings. Secondary times project onto that axis, including whitespace and price-based elements. Hosts own data feeds. The demo uses native comparison series and retains them across layout copies. (#87) -
Added bar series take every time-based chart type of the main series through
SeriesOptions::chart_type, withup_coloranddown_colorfor rising and falling bars and the baseline sides, andcolumns_basefor Columns that rise and fall from a price, which their scale’s fit includes, asChartTypeParams::columns_basedoes for the main series; their scales fit the lows and highs of the OHLC types. In a pane other than the price pane a series keeps its chart type and draws the crosshair above its bars, its legend row hides or removes it or hands its id totake_indicator_settings_request, andseries_price_scalereturns the pane’s scale.set_series_optionschanges the options of an added series at runtime, andseries_orderandset_series_orderset the draw order thatseriesfollows.pop_barsremoves the last bars of any bar series,bar_index_atfinds the bar at a time or its nearest neighbour on either side, andbars_in_logical_rangereturns the bars inside a range of logical indices with the bars before and after it.ChartEvent::DataUpdatedreports live bars fromupdateor the chart’s feed and removals, once per series in a row.series_price_mapconverts between the prices of any bar series and pixels in whichever pane draws it, andformat_series_priceformats them as its scale does. The symbol the demo’s quick search adds in a new pane is drawn as candles, on the left scale once moved to the price pane, and keeps its pane across layout copies. Migration: struct literals ofSeriesOptionssetchart_type,up_color,down_colorandcolumns_baseor use..Default::default(). (#825) -
Renko, Kagi, Line Break, Point and Figure and range charts calculate a separate set of study results from element OHLC, retaining the source-bar results for hosts and time-based views. Element outputs share the existing refresh budget, update from the first changed element and drive overlays, pane scales, selection, magnets, legends and readouts. Markers and retained drawing times use element completion intervals, with quiet trailing history on the last element. Point and Figure uses column start intervals so quiet bars stay in the current column. Repeated completions choose the first slot unless a drawing already retains another matching slot. Newly placed drawing anchors retain element times across chart-type switches.
Chart::study_values_atreturns displayed element outputs;indicatorscontinues to expose source-bar results. The hidden-annotations notice is removed. (#712) -
Drawings can be created, selected, dragged, erased and edited in study panes using each pane’s own scale, including manual, inverted and logarithmic ranges. Pane ownership survives drawing storage, undo, pane resizing, maximisation and study merging; hidden or collapsed panes leave no drawing hit targets. Magnet targets use the studies in that pane.
Drawing::paneidentifies the owning study, withNoneretaining the main price pane; hosts restoring studies retain or remap those ids. Migration: addpane: NonetoDrawingliterals, or useDrawing::new. Older saved files default to the main pane. (#151) -
Drawing properties expose Inputs for Fibonacci levels, pitchfork levels, Gann divisions, position sizing, volume profile rows and value area, regression bands and channel midlines. Coordinates open with every anchor and accept finite prices and UTC times, retaining fractional and repeated-time anchors. Invalid drafts stay open without changing the chart.
DrawingPropertiesDialog::open_for_chartandshow_and_applyread and apply edits in the library with undo, lock checks and persistence notifications; Apply is then a notification the host must not apply again. Common style edits still reach the unlocked selection, tool inputs reach matching tools, and coordinate edits affect only the opened drawing. Save as default retains per-tool properties inDrawingManager::tool_defaults; the demo persists these through application storage. New drawings stay visible when the saved default came from a hidden drawing.DrawingTemplateis also available underdrawings, with its existing UI import retained. Hosts own durable storage. Migration: remove the unusedDrawingProps::show_pricefield; Fibonacci price labels are edited per level.DrawingPropsliterals addsymbol,tool_settings,coordinatesandsave_as_default, or use..Default::default(); constructCoordinatePointthroughDefault; dialog literals adderror, and exhaustivePropertiesTabmatches handleInputs. (#142) -
Indicator::value_formatdeclares price, abbreviated signed volume, percentage or fixed-decimal units;scalechooses the main scale, an independent scale or an independent fit without labels.CustomIndicatorsets both through builders. Pane axes, legends, cursor tags, tooltips and data-window rows share the format; settings precision overrides retain the units, and only price values inherit instrument precision. Built-in volume totals and percentage studies declare their units without changing placement. Independent overlays reserve separate left-axis gutters that shrink in narrow windows, share their mapping with selection and leave the main price range and magnet unchanged. Study units stay independent of instrument precision in overlay legends. Migration: addformattoStudyValueliterals. (#570) -
Studies declare step lines, pitch-sized columns, crosses, areas, triangles, per-bar colours, bar/background colouring and bands between plots or levels. Both pane and overlay renderers share the geometry, preserve gaps and apply per-output offsets, including scaling and selection in visible future whitespace. Crossing fills split at their intersection without seams between bars; bar colours preserve candle bodies on inverted scales. Displaced values also drive last-value tags, alerts and drawing magnets; pane markers use the displayed range. MACD uses columns, Awesome Oscillator colours columns by momentum and Parabolic SAR uses dots; Bollinger and Keltner bands have a 20% fill. Existing Supertrend direction outputs and RSI level shading are retained. Migration: handle the new
PlotTypevariants in exhaustive matches. Ichimokuvalues()now retains unshifted source calculations, including the latest leading spans; useplot_valuefor displayed values orplot_offsetwhen drawing. Displacement counts the current bar, so 26 periods shifts 25 bars. (#165) -
Placing or double-clicking a text annotation, note or callout opens an inline multiline editor. Ctrl/Cmd+Enter or a click outside commits one undoable edit; Escape discards the draft, and locked annotations cannot be edited. Long drafts scroll within narrow panes, and clicks inside the editor keep it open. Anchored text and notes retain a pane-relative position through pan, zoom, resize, dragging and persistence; older drawings adopt their first displayed position.
Drawing::update_pane_coordsandDrawingManager::update_pane_anchorssupport standalone rendering. Migration:Drawingstruct literals must setscreen_anchor: None, or useDrawing::new; saved files default the new field. Clones of anchored annotations move right by 2% of pane width. (#150) -
Shift-click toggles drawings in a group selection. Dragging a selected body moves the unlocked group without panning or snapping to its own anchors; deletion, cloning, and demo property edits apply to the group with one undo step.
DrawingManager::{selected_ids, is_selected, toggle_selection, edit_selected, paste_drawings}exposes the same operations to hosts.Chart::copy_selected_drawingsreturns versioned clipboard text with timestamp anchors, andpaste_drawingsvalidates it before adding fresh copies three bars to the right. The demo forwards native copy/paste events; clipboard text survives a lost session cache and maps to the current interval of the same symbol. (#148) -
Study panes have draggable separators, maximise/restore controls and menus for ordering, collapsing, removal, merging and moving studies between panes or the main chart. Initial and resized axis sizing retain the configured horizontal zoom policy. Heights survive collapse and maximisation; resizing keeps adjacent panes above their minimum size. Each pane has its own draggable price axis, double-click auto-scale reset, scale modes and inversion.
Chart::move_indicator_to_paneexposes study placement to hosts.Indicator::panesuppliesStudyPanedefaults and reference levels without matching names; custom presentation wrappers forward it and implementset_overlayto accept placement changes.ConfiguredStudyalready does both. Migration:RenderedIndicatorPaneliterals addmapping; use that complete mapping for vertical coordinates in manual, logarithmic, percentage and indexed scales.hit_test_pane_indicatortakes its range from that mapping; remove its two range arguments. Pane menu edits and study placement participate in chart undo and redo. (#89) -
Chart::save_drawingsexports the current symbol toDrawingStorage;load_drawingsrestores a JSON file with the chart’s time mapping and returns its skipped records. Restoring can run before history arrives and rejects a different symbol without changing drawings. Loading preserves drawing controls, and saving rejects timestamps that loading cannot retain. The demo saves and restores per-symbol drawings through application storage. Filesystem, accounts and cloud storage remain host-owned. (#373) -
Chart settings Save as prompts for a name.
SettingsDialog::templatesexposes its serializable settings catalog, andui::dialogs::templates::{TemplateStore, TemplateDialog, StudyTemplate, DrawingTemplate}supplies named save, list, load and delete for host chart, study and drawing templates throughStorage. Documents are versioned, writes wait for reads and outstanding requests, failed saves retain edits, failed deletes retain rows, and unreadable or unknown-version catalogs cannot be overwritten. The demo connects its settings dialog and study and drawing toolbar intents to application storage; drawing templates edit selected drawings without changing anchors or identity, and study templates retain typed inputs and presentation. Long names and catalogs fit short and narrow windows. Accounts and remote storage remain host-owned. Migration: replaceui::model::{TemplateManager, SettingsTemplate}withTemplateStore<ChartSettingsState>; handle the newStoreKind::{ChartTemplates, StudyTemplates, DrawingTemplates}namespaces in host storage andDrawingToolbarAction::ManageTemplatesto open a template catalog. (#199) -
studies::Volume, registered as “Volume”, draws up/down columns with an optional SMA or EMA, editable length, open or previous-close colouring and price-overlay or separate-pane placement. An unchanged close counts as up; the first previous-close comparison uses the bar’s open. Volume uses its own zero-based scale, 80% pitch columns and a one-pixel moving average with a magenta value tag. The demo uses a 12% overlay band. (#572) -
With the
studiesfeature,ChartConfig::show_volumeadds a default Volume study on the next frame; disabling it removes that study. User actions restore its settings and pane placement through undo and redo. Its stable id is available throughChart::indicatorsfor editing or removal; closing it clears the volume switch. Hosts supplying their own Volume study can turn off the default switch before adding it. Widget-only builds retain the volume band.Indicator::is_volumeidentifies the three volume outputs for independent scaling and interaction; custom study wrappers forward it. -
Chart::undo,redo,can_undoandcan_redoshare one ordered history for user drawing edits, study additions/removals/settings, chart type, interval and chart settings. Shortcuts, chart navigation buttons and the demo toolbar use this history; navigation undo restores the prior view and scale. Host UI/intent handlers wrap edits inChart::user_action(or pairedbegin_user_action/end_user_action); direct programmatic API calls and feed/data updates are not recorded. Unchanged actions keep redo; new user edits clear it. Undo restores the affected study or settings snapshot, preserves study ids and unrelated studies/drawings, and keeps drawing persistence notifications. Hosts usetake_history_changedto synchronize controls and reload their own interval data after undo/redo. Migration: use the chart history API for chart Undo/Redo;DrawingManagerhistory remains available for standalone drawing managers. (#108) -
Chart::shortcutsandshortcuts_mutexpose an editableShortcutMap, seeded fromconfig::KeyboardAction::shortcuts(egui::KeyboardShortcutvalues). The dispatcher consumes exact modifier combinations and shares bindings with menu hints and shortcut help. Earlier bindings take precedence in input and hints; shadowed bindings are omitted.take_shortcut_requestsreturns host actions, typed symbol and interval entry, and clipboard text; hosts supply their own dialogs, layouts and clipboard formats.dispatch_shortcutslets the active chart run before toolbars, andsuppress_shortcutsreserves a pass for host dialogs. The demo cycles keyboard focus through its visible chart slots, wires these intents and keeps drawing copies for the current symbol and interval within its session. (#113) -
Alerts retain a name, host watchlist, typed price, study, drawing or volume source and additional conditions required on the same bar. Conditions include channels, signed value and percentage moves and output comparisons; frequencies include once per bar and once per bar close. The shared dialog creates and edits
model::Alert, accepts host catalogs and persists named presets throughStorage. Its form fields fill the available control column, its default body height fits the editor, and smaller windows scroll before the shared Save/Cancel footer with validation feedback, in both themes. (#293) Old single-symbol alerts keep loading. Migration:Alertliterals addname,source,watchlistandadditional_conditions, or useAlert::new;AlertConditionis no longerCopy. DialogCreatecarriesBox<Alert>; replace the old string form structs and tab-specific data withAlertDialog::alert,sourcesandwatchlists;AlertDialog::open(symbol, price)now requires the last or hovered price;AlertTaband the obsoleteAlertDataalias are removed; usemodel::Alert.AlertDialogConfigretains onlywidthand the maximum scrolling-bodyheight. HandleAlertPanelAction::EditAlertand the new condition, frequency andStoreKind::AlertPresetsvariants. (#207, #209) -
Chart::study_values_atreturns each visible plot’s title, value, precision and colour, retaining gaps as missing values.DataWindowInfo::from_chartpopulates OHLCV, previous-close change, chart-formatted time and visible study rows from the hovered rendered bar, with latest-bar fallback. The demo uses this library population, and floating and tracking tooltips include the same study rows within their plot bounds. Price-based charts omit source-indexed studies. Migration:DataWindowInfoliterals includestudiesor useDefault. (#119) -
TimeframeSelector::set_supported_timeframesrestricts presets and custom choices to the connected source’s intervals, retaining unavailable saved preferences. Hosts update it when their source or symbol changes;Nonepermits all intervals.TopToolbarAction::ChartStyleSelectednow carriesmodel::ChartTypedirectly. Migration: consume that typed value instead of parsing a display string. (#103) -
Interval-menu stars pin and unpin presets and custom intervals without selecting them. Add retains custom intervals without duplicate rows.
TimeframeSelector::preferencesandset_preferencesexchange serializableTimeframePreferencesfor host user settings; unavailable favourites are retained. The demo saves and restores these lists through application storage. (#104) -
widget::ChartLayoutrenders one to sixteen host-owned charts in grid presets or tabs, with active-chart selection, a two-point inside border, two-point row gaps and edge-to-edge columns. Each chart retains its feed, studies, drawings and scales. Its corner menu assigns named synchronization groups and detaches charts into immediate viewports, embedded when the backend cannot create native windows.ui::multi_chartre-exports the working container and its types. (#115) -
Layout groups synchronize symbol and interval changes, crosshair timestamps, scrolling and zooming, explicit date ranges and drawing edits. Drawing anchors map by time between intervals; synchronization is limited to matching symbols and groups, preserves unrelated drawings and leaves host persistence queues intact. Hosts supplying bars directly replace them after synchronized symbol or interval changes.
-
The top toolbar shows the grid selector beside indicator templates and a named-layout menu at the right.
LayoutAction::SelectGridselects presets; save, save-as, rename, open and delete actions are host intents. The demo owns session layouts in a tab strip, routes its toolbars and range bar to the active chart and gives new charts independent synthetic subscriptions without regenerating their common history. Persistent and cloud storage remain host-owned. -
Migration: exhaustive
ChartLayoutModematches must cover the new five and seven through sixteen chart presets andTabs; exhaustiveLayoutActionmatches must handleSelectGrid.ChartSyncOptionsliterals must addsync_date_rangeor..Default::default().LayoutMenunow emits save and catalog intents without mutating host-owned names or lists; updatecurr_layoutandlayoutsafter handling an action. Its initial name isUnnamedand its initial catalog is empty. -
Price-based chart settings offer
BoxSizeMethod::Fixed, WilderAtr { period, multiplier }andPercentagefor Renko, Kagi, Point and Figure and Range.Chart::set_chart_type_paramsresolves the selected methods from loaded history, waiting for the ATR seed when needed, then freezes the sizes through streaming updates, corrections and feed prepends. Reapplying parameters or replacing the dataset withset_datarecalculates them; changing the symbol or interval reloads history and recalculates too. Percentage uses the absolute latest close, with 1 meaning 1%. Renko, Kagi and Line Break acceptPriceBasedSource::CloseorHighLow; without intrabar ordering, a continuation takes priority when both thresholds are crossed.renko_wickspaints the brick’s actual high and low; close input tracks close extremes and high/low input tracks bar extremes. The Symbol tab edits these parameters, which serialize with chart type settings. Migration: chart parameter literals add the method, source and wick fields or use defaults;RenkoConfig,KagiConfigandLineBreakConfigliterals addsourceor use their constructors;RenkoBrickliterals addhighandlow.SeriesSettingsAction::Applycarries its settings in aBox; callers constructing that action wrap settings withBox::new, and readers can borrow or dereference them.RenkoConfig::from_atrandKagiConfig::from_atrnow use Wilder smoothing and require a complete seed instead of averaging the latest ranges. (#633) -
ChartTypeParams::stylesretains independent line, step line, marker, area and baseline colours, widths and line styles; Area has separate top and bottom fill stops, Baseline has separate line and fill colours on each side, and markers have a configurable radius. The series settings Symbol tab edits the current type.Chart::series_settingsreads the current values for opening the dialog, and applying them leaves candle colours independent. Chart types, parameters and styles support serde for host-owned saved settings. Migration:ChartTypeParamsliterals addstylesor use..Default::default();SeriesSettingsliterals addchart_typeandchart_type_params, or use the defaults. (#562) -
Visible study outputs have last-value axis tags in their line colours, including separate panes and left axes; hiding both axes hides their tags. Tags are 15 px high at the default axis font size. Colliding tags move to the nearest free row. High/low and host bid/ask labels and lines have independent switches, and volume uses a magenta axis tag. Countdown labels advance with the feed’s server clock, respect session closes and calendar months, and accept
Chart::set_server_timeandset_bar_close_timefor direct-data and irregular-session hosts.set_right_marginand the settings dialog apply scale margins; the quick ratio-lock checkbox reaches the scale engine. Migration:ChartConfigliterals needshow_bid_ask,show_high_lowandlock_price_to_bar_ratio, or..Default::default(). Study ticks, legends and axis tags shareStudySettings::precision; bounded RSI and Stochastic presets retain two decimals by default. (#112) -
Right-clicking either price axis or the time axis opens scale and session controls through
ChartMenus. Price menus apply auto/manual scale, regular, percent, indexed and logarithmic modes, inversion, placement, label visibility and a price-to-bar ratio lock; time menus apply UTC, local or exchange time and session choices.PriceScaleexposes the ratio lock for hosts composing their own controls. Long axis menus scroll inside short windows. (#110) -
Price axes show the instrument currency in a tick-sized button above their labels. The menu checks the current currency and emits host conversion choices through
Chart::set_currency_choicesandtake_currency_choice; hosts supply converted bars and metadata together.chart::render_axis_currencysupports composed axes. (#734) -
ObjectTreePanel::apply_to_chartapplies drawing and study visibility, locking, duplication, removal, selection operations, one-step layer moves and drawing focus. Bind series rows withSourceItem::with_series_id, usingSeriesId::MAINfor the data source. Drawing names live inDrawing::label, survive storage and participate in undo; the shared prompt renames drawings. Layer moves are one undo step, including tied layers, and drawing copies have their own undo and save entry through the shared manager creation path. Selected drawings show handles together. Property dialogs and colour gestures remain host intents. Migration:SourceItemliterals setseries_id,Drawingliterals setlabel, and exhaustive matches onDrawingCommandhandleReorder. Constructors use the defaults. (#149) -
Chart::set_main_series_visiblehides the price series, volume, readout and hit targets while retaining its bars, studies and drawings;is_main_series_visiblereads it. The object tree’s main-series eye uses this operation. Main-series removal and duplication are not offered. -
Duplicating a study from the object tree retains its input caption. Locked drawings can be hidden or renamed while their geometry and style remain protected.
-
AlertsPanelconnects to a hostservices::Alertswithset_service, lists host-reported states and retains the latest 10,000 triggers with CSV export. Callpoll(ctx, &mut toasts)each frame, including while hidden, and render that shared notification list once. Stream recovery preserves pending save and removal replies. Creation returnsAlertPanelAction::CreateAlertfor the shared dialog;savesubmits the completedmodel::Alert, andExportLogcarries CSV for host delivery. The demo supplies session-only storage. Migration: replaceshow(ui, &AlertManager)withshow(ui), attach a service and poll each frame. The obsolete alert types andAlertManagerinui::model, inline forms and getters,AlertType,AlertStatusWidgetandAlertNotificationare removed; usemodel::Alert, the shared dialog and notification components.AlertsPanelConfignow contains onlymax_height. (#208) -
Chart::bar_clockshares the resolved chart, exchange or system-local calendar with host rebuilds.BarClock::with_timezoneandwith_local_timezonealign intraday and calendar windows, including repeated hours and short or long days.HistoryRequest::clockandSubscription::clockgive hosts the same boundaries as the chart; changing the chart timezone reloads the series.resampleandaggregate_tradesaccept either a timeframe for UTC or a supplied clock. Migration: inline parsed arguments to those functions specify.parse::<Timeframe>(); subscription destructuring includesclockor... -
Sink::advance_timeopens an empty current time bar on a trusted feed heartbeat, carrying the last close with zero volume until the first execution sets its OHLC. Count intervals wait for executions.data::aggregate_tradesrebuilds chronological trade history with the same aggregation, validation and duplicate-id rules as the live sink. -
The native and web demos backfill to the current clock and stream deterministic synthetic trades and best bid/ask quotes through the public feed API. The default one-minute candle grows on every execution; the interval menu rebuilds second and count bars from a bounded trade buffer, with seven days of minute history built from the same executions for coarse views. Session filtering uses the instrument windows and the chart’s extended-hours choice. A small pause/resume control freezes the feed. The footprint sample pauses streaming while it is inspected. Timed repaints follow executions and countdown seconds, with no worker thread.
-
Chart::set_feed_pausedsuspends requests and unsubscribes while a host supplies replay bars. Resuming reloads the selected symbol and interval from the host feed. The demo retains replay when switching intervals and restores the preceding pause state when leaving replay. -
Timeframe::Ticks(NonZeroU64)and the interval menu offer 1, 10, 100 and 1000 execution bars.Sink::push_tickcounts accepted trades across frames, retains exact OHLCV and keeps replayed ids from consuming a count. Replaying retained executions rebuilds the partial final bar when changing intervals. Count bar timestamps keep nanosecond precision, advancing by one nanosecond when opening times would collide. Migration: exhaustiveTimeframeandTimeframeUnitmatches need a tick arm.duration_ms()andduration()return zero for count intervals, which have no time duration; check the variant before stepping time.Timeframe::all()continues to list time intervals only. -
Applied studies expose typed
StudyInputschemas and validated setters, including independent average-combination lengths, formulas and sources.IndicatorSettingsDialogstages Inputs, per-plot Style and interval Visibility edits; Apply targets the original study id and Cancel discards them.ConfiguredStudyapplies complete edits atomically and retains serializableStudySettings, per-plot colour, width, stroke pattern, line/histogram/circle geometry, visibility and precision. Charts wrap studies once, report legend and pane settings intents throughtake_indicator_settings_request, and exclude hidden plots from scaling, snapping and selection. Hosts supply schemas for their own studies and persist settings themselves. The demo’s existing settings action edits the selected study. (#169) -
IndicatorDialog::preferencesandset_preferencesexport and restore serializableIndicatorPreferences, including favourites for temporarily unavailable host studies. Hosts save this value in their user settings whenToggleFavoritefires; the library owns no storage. Study defaults, editable Keltner and Stochastic parameters and tab filtering were already corrected in #692. (#170) -
MACombinationcombines two to fourteenAverageLines with independent simple, exponential, weighted, Wilder, volume-weighted or Hull formulas, lengths, sources and colours.MACross,EMACrossandMultipleMAshare its calculations with their existing defaults. The factory addsSMA/EMA Cross,Triple MAandMA Ribbon; the ribbon has twelve evenly spaced lengths, individual direction colours, a thicker slowest line and a fading purple bottom fill, with a muted variant available directly. Crossing markers identify changes of side, ignore touches and disappear when a live correction cancels the cross. (#549) -
LinearRegressionChannelfits the trailing window with upper, middle and lower lines, residual deviation bands with ann - 1denominator, selectable price source, Pearson correlation label and optional right extension. Updates clear expired bars and refit the trailing window on every live change, independently of history length. Right extensions project prices before mapping to the axis, including logarithmic and inverted scales. Drawings share the same headless least-squares maths. (#548) -
Charts pass instrument time zones and sessions to studies when added and when metadata arrives or changes, so a dialog-created VWAP follows the exchange session. Clearing metadata restores the study’s configured time zone and session. VWAP supports quarter and year anchors, percentage bands, and
with_event_anchorsfor earnings, dividend or split timestamps supplied by the host. Event anchors reset on the first bar at or after the timestamp, including after a market gap. (#163) -
data::Footprint,FootprintBarandFootprintLevelaggregate chronological executions per UTC bar and integer price row, with separate bid, ask and unknown volume, intrabar delta extremes, POC, contiguous value area, horizontal and diagonal imbalances and inclusive trade-size filtering. Invalid, out-of-order or overflowing executions return an error without changing the aggregation; executions with unknown aggressor never contribute to delta. -
studies::trade_deltacomputes exact execution-based delta and cumulative delta candles, with host-defined session or period resets and independent rolling volume and delta totals.chart::series::render_trade_deltadraws, in a supplied pane, delta histograms, per-bar candles (TradeDeltaStyle::BarCandles) or cumulative candles (TradeDeltaStyle::CumulativeCandles). A per-bar candle opens at zero, closes at the bar’s delta and has its wick from the lowest to the highest running delta of the bar’s executions, carried asTradeDeltaValue::delta_lowanddelta_high, so the wick spans the bar’s own range even when earlier bars leave a non-zero cumulative total. The existing bar-estimatedCVDremains available separately. (#1480) -
chart::overlays::render_footprintdraws up to four bid/ask, volume, delta or delta/volume columns per bar, with profile or cell fills, volume, delta or imbalance colours, POC and value-area highlights, manual or automatic row grouping and cached text layouts hidden below the minimum row height. Both dominant diagonals retain their side colours, and sub-unit volumes stay nonzero in labels.Chart::show_footprintreplaces the price series while keeping the legend, cursor and studies above it. The demo’s Menu exposes a Footprint toggle using deterministic synthetic executions from its fixture; turning it off restores the previous time scale. -
studies::footprint_studiesidentifies stacked diagonal imbalance zones, unfinished auctions, naked POCs, delta POCs, volume clusters strictly above the configured volume share and small extreme prints using a host-supplied size threshold. Stacks and naked POCs extend until the first later traded range revisits them.chart::overlays::render_footprint_studiesandrender_footprint_statisticspaint the annotations and per-bar volume, bid, ask, delta, delta extremes, cumulative delta, delta percentage and ask/bid ratio. -
data::Sink::push_quotecoalesces best bid/ask quotes per frame and connects the latest matching quote to the chart legend. Invalid, mismatched or older quotes do not replace the current or pending quote; reloading the feed clears it. -
Drawing::pitchforkstores per-level colour, visibility and line style, with mirrored levels at 0, 0.5, 1 and 1.5 and filled bands by default. Hidden levels remove both adjacent bands. Old drawings use the defaults. Parallel channels supportchannel_midline,fill_color,extend_leftandextend_right, with selection following the lines and filled area. Migration:Drawingstruct literals setpitchforkandchannel_midline, or useDrawing::new. -
Session::with_extended_windowsandwith_holidaysdescribe host-owned trading hours and closures.ExchangeSessionProviderstarts each trading date at its earliest regular or extended window, handles overnight sessions, and resolves repeated opens to their first instant and missing opens to the clock jump.Chart::set_session_provideraccepts host break logic. -
Extended-hours bars are shaded independently of session dividers, including throughout a repeated hour after an overnight open.
ChartConfig::show_extended_hoursswitches shading off, andextended_hours_coloroverrides the faint active-theme accent. Migration: chart configuration literals need these fields or..Default::default(). -
Chart::set_extended_hourschooses regular hours or regular and extended hours, reloading history and the stream together.HistoryRequest::extended_hoursandSubscription::extended_hourscarry that choice to the host feed, including older history pages. Migration: addextended_hoursto request and subscription literals and destructuring, or use..when ignoring it in a pattern. Feeds must honor the field (falserequests regular hours); hosts supplying bars directly replace their data after a choice. -
Chart settings now retain and apply title format, quote controls and independent study title/input/value visibility.
Chart::set_indicator_inputssupplies study input captions, retained through host templates; status-line volume no longer hides the histogram. The settings dialog keeps one top edge across tabs throughModal::top. -
Price scale placement and independent current/previous close labels and lines now reach rendering on either axis. Countdown visibility is honoured, with its default enabled to retain the existing displayed countdown. Migration: add
..Default::default()toChartConfig,settings_menu::data::StatusLineOptions,ScalesAndLinesSettingsandIndicatorPaneConfigliterals, or set the new visibility fields explicitly. ConstructLegendwithLegend::newand set its public fields; it has noDefaultimplementation. Previous close is the last bar before the latest trading date. -
TopToolbar::indicator_templatesaccepts host-owned saved study names and ids. Its anchored menu emits save/apply intents; the demo keeps cloned study sets in memory for the session. Migration: replaceTopToolbarAction::OpenIndicatorTemplatesmatches withSaveIndicatorTemplateandApplyIndicatorTemplate(id)handlers. Opening the popup emits no action. -
Symbol::with_marketsupplies an exchange and optional instrument kind for symbol search. Empty queries list the host catalog, with host-supplied recents first, category chips for available kinds and kind/exchange metadata in each row. Migration:Symbolstruct literals needexchangeandsymbol_type, or useSymbol::new. -
TabBar::pillsrenders rounded tab chips through the shared tab component; the indicator browser uses them. -
top_toolbar::buttons::toolbar_tooltipattaches compact toolbar tips with optional platform shortcut chips.Modal::roundingandModal::fillpreserve per-dialog styling, and an empty modal title lets a search row serve as the header. -
Chart::set_instrument,set_legend_badge,set_legend_statusesandset_quoteconnect host metadata and current bid/ask to the responsive legend. Historical OHLC and study values follow the pointer independently of quotes, including over the axis add cell.take_quote_actionretains buy/sell intents until taken; changing symbols clears supplied metadata and quotes. The demo labels generated data with SIM and records quote intents without submitting orders. -
Chart::set_session_quoteandset_eventsconnect independent session prices and event badges.take_event_clickandtake_scale_settings_requestroute clicks to the host; the price-tag add cell opens the existing context menu at the displayed price, including in Magnet mode. Current close tags include a countdown when a supplied quote belongs to that bar, and volume has a separate tag at the pane bottom. -
CrosshairStyle::DemonstrationandCursorType::Demonstrationdraw a fading pointer trail that expires while stationary.TooltipOptions::on_long_pressrestricts values to a held pointer, waiting half a second for touch; the floating panel shows OHLC, absolute and percentage change from the previous close, and volume, with one snapped guide and hollow series points.Chart::set_tooltip_enabledconnects the values switch. Migration: exhaustive cursor matches need a Demonstration arm; tooltip struct literals needon_long_pressor..Default::default(). -
The demo exposes the hovered Data Window in the right rail, quick search, a Trade intent notice and Publish through the existing export dialog.
show_data_windowis exported for hosts that display it independently of the object tree. -
icons::COMPARE_ADDandicons::LAYOUT_SINGLEprovide original comparison and single-pane layout glyphs. -
chart::render_event_banddraws host-suppliedMarkers as 22 px badges above a supplied time-axis baseline, aligned to the first bar at or after each event time. It uses the event’s text, colour, tooltip and ID, and returns the clicked ID to the host. Events outside the supplied data or plot are left out; existing bar annotations keep their appearance. -
chart::render_quote_tagspaints independent current close, host-suppliedmodel::quote::SessionQuoteand abbreviated volume readouts, separating colliding tags and returning each rectangle for input and tick occlusion.chart::price_axis_widthmeasures ticks and supplied formatted tag labels. Row spacing follows the host font, and off-scale prices do not hide the other quote values. Short panes keep the close before the session and volume rows. Hosts composing their own axes can routechart::crosshair_price_actionto an add-at-price menu andchart::axis_settings_buttonto scale settings; the two controls requireiconsand return clicks to the host. -
widget::Legendcomposes an in-pane instrument title, host badge and status marks, current outlined sell/buy quotes with spread, and collapsible volume and visible overlay study rows. Its bar and previous close are supplied independently of current quotes; quote clicks returnQuoteSidefor the host to handle. -
TextSizeshas separatechart_title,toolbar,ohlc,axis,price_tagandbottom_barroles, defaulting to 16, 14, 13, 12, 12 and 14 points, with matching constants instyles::typography.scaledscales them with the general size scale; missing serialised fields use their defaults. Migration: add the roles toTextSizesstruct literals or use..Default::default(). Component call sites choose the roles independently. -
WidgetBar::widgetsaccepts host widget icons, names, ids and top or bottom grouping. Clicks returnWidgetBarAction::WidgetClicked(id)and switch the active entry independently of the built-in panels. The bar scrolls when its entries do not fit. Migration: an exhaustive match onWidgetBarActionneeds aWidgetClickedarm. -
Chart::set_price_lines(series, lines)draws horizontal lines at prices on a series, such as an entry, a stop or a target. Amodel::PriceLinehas a price, a colour, a width, a line style, an optional title and a price axis label that can be turned off. The lines follow the series’ price scale in every mode, are hidden while their price is off the scale or not finite, and label the axis in the scale’s units. The setter accepts every bar series.model::LineStyleis the line style of drawings and price lines;drawings::LineStyleremains a re-export of the same type. -
Chart::scroll_to_timescrolls the bar nearest a time to the centre of the chart without changing the zoom. A time outside the data shows the nearest end, and with a feed, an older time loads history until it is reached. The demo’s go-to-date dialog uses it. -
The chart draws navigation buttons in a row at the bottom of the main pane: zoom out, zoom in, scroll left, scroll right, reset, and auto-scale, logarithmic and percent toggles that show the price scale’s current state. Zoom moves by
KeyboardOptions::zoom_steparound the right edge, scrolling by the visible bar count.ChartConfig::navigation_buttons(NavigationButtons::Always,OnHoverorNever,Neverby default) sets when they show, and the chart settings dialog’s Navigation row edits it. Migration:ChartConfigstruct literals must setnavigation_buttonsor use..ChartConfig::default(). -
IndicatorDialog::open_tabopens the indicator dialog on a given tab;openopens it on the Indicators tab. -
IndicatorDialogConfigimplementsDebugandClone. -
ui_kit::modal::Modal::heightfixes a modal’s outer height for content that fills it, such as a list in a scroll area. The modal keeps 24 px free above and below it in the window and follows the window when it shrinks;min_heightsets only a floor, so filling content keeps a modal at its largest size. -
studies::PercentageVolumeOscillator, registered inIndicatorFactoryas “PVO” with lengths 12, 26 and 9: the percentage oscillator of volume, its signal line and its histogram. -
Columns chart type: one column per bar from the bottom of the price pane to the close, coloured by the close versus the previous close.
-
ui_kit::EmptyState::iconshows an icon above the message,EmptyState::actionadds a primary button below the text, andEmptyState::fill_heightcentres the empty state vertically in the rest of theUi. The message is in the normal text colour at the body size; only the description is muted. -
icons::DUPLICATE, two overlapping squares, which the floating selection toolbar’s Duplicate button shows. -
tokens::SizingTokens::control_height, the minimum height of egui’s built-in controls, 18 inDESIGN_TOKENS;apply_to_eguiapplies it. -
Theme::high_contrast()is a distinct preset: black surfaces, white text, every text colour except disabled text at 7:1 or better on panels and windows, control outlines at 4.5:1, and a light blue accent with black text. It was a copy of the dark theme. -
Theme::with_accentsets the accent and derives its hover and pressed shades, the black or white text on it, and the selection colours.theme::presets()lists the three presets by name. -
Theme::text,Theme::spacingandTheme::radiushold the type, spacing and corner radius scales;apply_to_eguitakes the window and menu margins, item spacing and window and menu corner radii from them.TextSizes::scaledmultiplies the type scale. -
The
serdefeature derivesSerializeandDeserializeforTheme. The dark flag and complete colour palettes are required; omitted text, spacing and radius scales use their defaults. -
data::Datafeed, a callback contract for market data: a feed answers instrument and history requests once through adata::Reply(dropping it unanswered reportsFeedError::Unanswered) and pushes live bars, trades, status and errors through a per-subscriptiondata::Sink, from any thread, runtime or browser task. The sink rejects a bar or trade whose slot opens more than one slot and more than a minute after the feed’s current time (two weeks for bars of a day or longer), the time being reported throughSink::set_server_timeor else taken from the system clock. Pushes coalesce on arrival into one bar per time slot, so memory follows the bars that changed rather than the update rate. Supporting types:HistoryRequest,HistoryPage,Subscription,SubscriptionId,FeedStatus,FeedError,FeedStateandMaybeSendindata,InstrumentandBarClockinmodel.FeedError’s messages name no source, since the host services answer with it too:NotSupportedreads “not supported” andUnansweredreads “no answer”. A bar of a day or longer is identified by a period ofHistoryRequest::clock, in UTC by default, such as its day, week from Monday or calendar month, so a feed stamps it inside that period, for example at midnight on its trading date, rather than at a session open on the evening before. -
model::BarimplementsPartialEq. -
data::resamplebuilds bars of a coarser interval from bars of a finer one, aligned toBarClock, so a feed that serves one base interval can back intervals such as 7 minutes or 2 hours. It returnsNonewhen the finer bars do not nest in the coarser ones, as 5-minute bars do not in 7-minute bars, or when the bars of one slot do not combine into a valid bar, as when their volumes add up to infinity. -
theme::ThemeExt::active_theme, foregui::Contextandegui::Ui, returns the theme last passed toapply_to_egui, or the dark theme if none was, so components resolve colours while painting. -
tokens::UiSemanticTokensgainspanel_bg_floating_dark, the fill of popups, menus and windows in dark themes. Struct literals ofUiSemanticTokensmust set it. -
A theme toggle in the top toolbar emits
TopToolbarAction::ThemeToggle. -
Indicator::update(data, from)brings a study up to date after the bars fromfromonward changed or were appended, with exactly the valuescalculategives on the same bars, andIndicator::is_incrementalreports whether a last-bar update or an append costs time independent of the series length (an earlier change still recomputes in full).IndicatorRegistry::update_allupdates every study. Both methods have default implementations (a fullcalculate, andfalse), so existing implementors still compile.SMA,EMA,BollingerBands,RSI,MACD,Stochastic,ATR,VolumeWeightedAvgPrice,OnBalanceVolumeandSuperTrendupdate incrementally. -
Icons
CHECK,MINUS,CHEVRON_UP,CHEVRON_LEFT,CHEVRON_RIGHT,STAR_FILLED,CODE,USERS,CROWN,DATABASE,PENCILandTEMPLATEinicons::icons. -
ListItemContent::interactivelets content take its row out of pointer interaction. It defaults totrue; a disabledButtonContentreturnsfalse, so its row is neither highlighted nor clickable. -
data::Sink::push_tickalso keeps each trade, with its price, size, aggressor side and time, in a bounded store for order flow, andDatafeed::tradespages historical trades (TradeRequest,TradePage) so order flow can be rebuilt after a reload. The default answersFeedError::NotSupported. History and live trades join exactly when both carry the newTick::id(an exchange trade id or sequence number that never repeats for the symbol), and a live trade whose id the subscription already took is dropped and counted inFeedState::repeated_ticks, so a feed may replay its last trades after a reconnect; without ids, trades at the boundary instant may be dropped but are never counted twice. -
Order book depth on the
Datafeedcontract:Sink::push_depth_snapshotandSink::push_depth_deltacarry a sequence number; a gap, a delta before any snapshot or an invalid update clears the book until the feed pushes a new snapshot, which is asked for once throughDatafeed::request_depth_snapshot. A delta numbered at or below the last one applied is ignored, whatever it holds. Deltas pushed while the book waits are held, up to 10,000 levels, and the snapshot applies those numbered above it, so a snapshot fetched while the stream runs heals the book. A level with size 0 is removed, and a book is limited to 10,000 levels per side. Rejected updates are counted inFeedState::rejected_depth. -
model::Instrumentdescribes the full name (description), exchange, instrument type, tick size, price decimals, currency, exchange time zone (model::TimezoneId) and trading hours (model::Session,model::SessionWindow), each unknown by default and set with awith_method. -
Instrument::data_status(model::DataStatus: realtime, delayed or end of day), set withwith_data_status. The legend marks delayed data with D and end-of-day data with E, in the warning colour ahead of the host’s status marks, and names the status on hover. (#77) -
Instrument::supported_timeframes, set withwith_supported_timeframes, lists the intervals the feed answers history for;None, the default, keeps every interval available. A chart does not ask the feed for history of an interval its instrument rules out: it shows no bars, does not subscribe, and reportsFeedError::NotSupportedthroughFeedState::last_error. A page asked for before the symbol resolved is dropped, and an instrument that allows the interval again asks for it. Pass the list toTimeframeSelector::set_supported_timeframesso that the interval picker offers only those intervals. (#699) -
model::TickimplementsPartialEq. -
DialogFooter::dangerfills the primary action with the danger colour. -
scales::TimezoneMode, the time axis timezone mode, now lives next to the time formatters that use it.config::TimezoneModeremains as a re-export of the same type. -
ChartState::revisionidentifies the bars before the last one: it changes when one of them is corrected or bars are removed, and stays the same when bars are appended or the last bar updates. -
Per-drawing settings:
Drawing::volume_profile(drawings::VolumeProfileConfig, 1 to 1,000 price rows and the value area’s share of the volume, 24 rows and 70% by default),Drawing::regression_trend(drawings::RegressionTrendConfig, the band distance in standard deviations, above 0 and up to 10, 2 by default) andDrawing::position_size(drawings::PositionSize, a fixed quantity, or the quantity that loses a given amount or a percentage of an account size at the stop).Noneuses the defaults. The constructors of the two configs reject values out of bounds; a position size out of bounds reads as n/a. -
Drawing,DrawingToolType,LineStyle,ArrowStyle,FontWeight,TimeframeVisibility,FibonacciLevel,FibonacciConfig,VolumeProfileConfig,RegressionTrendConfigandPositionSizeimplement serdeSerializeandDeserialize. A tool type is written as its variant name; aDrawingleaves out its id, points and completion state; the volume profile and regression trend settings are checked against their bounds on load; the per-timeframe visibility set is written sorted, so saving the same drawings gives the same file. -
services::Storage, a callback contract through which the host keeps named JSON documents for the library: it lists, loads, saves and deletes the documents of aservices::StoreKind(SettingsorDrawings) and answers through adata::Reply, from any thread, runtime or browser task. Nothing calls it yet. (#198) -
services::SymbolSearch, a service the host implements to answer symbol searches from any source of instruments, separately from the feed: it takes aservices::SymbolQuery(the typed text, optional instrument type and exchange filters, and a result limit) and answers withInstruments through adata::Reply.Vec<Instrument>implements it: it matches the text against symbol and description ignoring case, applies the filters, and lists an exact symbol first, then symbols that start with the text. Nothing calls the service yet. (#380) -
services::Broker, a callback contract for one trading account at the host’s broker, real or simulated: it places and cancels orders, answering through adata::Reply, and pushes the account, orders, positions, executions and connection status asservices::AccountEvents into anEventsstream. The trading model is inmodel:OrderType,OrderRequest,Order,OrderStatus,Position(signed net quantity),Execution,AccountandCapabilities(the order types the account accepts). The library holds no balances or positions. Nothing calls the service yet. (#216) -
services::Signals, through which a host supplies markers, levels and zones from its own analytics (model::Signal,SignalShape,SignalId,Direction) asservices::SignalEvents, pushed from any thread into aservices::Eventsstream that holds at most 10,000 pushes between frames and ends when it lags or the chart stops listening (#381). -
model::StrategyReportdescribes a strategy run from any source: its trades, each with the net profit the host computed, its equity curve and the settings to show.StrategyReport::performancecomputes the metrics with one definition each: net, gross and average profit, profit factor, win rate, maximum drawdown in money and as a fraction of the peak, and the Sharpe and Sortino ratios, annualised by the steps per year the equity curve covers and unavailable for a curve spanning less than 13 weeks. An undefined metric isNone, invalid trades and equity points are skipped and counted, a non-finite number is saved asnullin JSON and loads back as NaN, so a report with one loads with the same metrics, andStrategyReport::trades_csvexports the valid trades. Supporting types:StrategyTrade,StrategyExit,OrderSideandStrategyPerformance. -
services::Alerts, through which the host keeps and evaluates price alerts: it pushes its alerts, their changes and their triggers asservices::AlertEvents into aservices::Eventsstream, including triggers that fired while the application was closed, and saves or removes the alerts the user edits, answering through adata::Reply. The alert model (model::Alert,AlertId,AlertCondition,AlertFrequency,AlertStatus) is serialisable so a server can store and evaluate the same type. The alerts panel consumes the service. (#211) -
The Negative and Positive Volume Index plot their signal line, the 255-bar EMA of the index seeded with its first value, so it starts at bar 0 like the index. The index is unchanged. Migration:
NegativeVolumeIndexandPositiveVolumeIndexoutputIndicatorValue::Multiple(vec![index, signal])instead ofSingle(index), and report two lines and two colours; code that matchedSinglereads the index as the first value. -
AlertKind::colorandToastKind::colorreturn the theme’s status colour for an alert or toast kind. -
MessageKind::Warning:status_messagedraws it in the theme’s warning colour. Migration: amatchonMessageKindneeds aWarningarm. -
TopToolbarState::can_undoandcan_redodisable the top toolbar’s undo and redo buttons, whose tooltips then read “Nothing to undo” and “Nothing to redo”; both default totrue. Migration: struct literals ofTopToolbarStateset both fields or use..Default::default(). -
Chart::set_data(series, bars)replaces the bars, for history or a replay window, andChart::update(series, bar)merges one bar by the rules a feed’sSink::push_barfollows, matched by open time, or by the slot of the timeframe for a chart built with a feed: a bar that matches a stored bar replaces it, a newer one is appended and an older one is inserted in order.Chart::bars(series)reads the bars, andChart::feed_state(SeriesId::MAIN).rejected_barscounts the bars dropped as invalid. OnlySeriesId::MAINholds bars; a call with another id is ignored with a warning.SeriesIdis re-exported fromwidget. -
Chartowns its studies and drawings.Chart::add_indicatorcomputes a study at once and returns aSeriesIdthat stays valid when other studies are removed;remove_series,set_indicator_visible,indicatorsandindicator_muttake that id.Chart::drawingsanddrawings_mutgive the drawing manager.ChartElementIdis re-exported fromwidget. -
Chart::config,Chart::chart_options,Chart::price_scale_mut,Chart::set_markers(series, markers)andChart::stategive access to what the public fields held. -
The
bare_chartexample shows one candlestick chart on generated sample data, with a live tick every frame and a new bar every 60, built from thewidgetfeature alone:cargo run --release --example bare_chart --no-default-features --features widget. Thebare_chartbench runs that example’s frame headlessly and prints its median and 95th percentile time:cargo bench --bench bare_chart --no-default-features --features widget. -
CI checks the bare-chart build: on ubuntu-24.04 with the MSRV toolchain it builds
examples/bare_chart.rsandbenches/bare_chart.rswith--no-default-features --features widgetand fails when the stripped size of the example grows by more than 1%, or the instructions of one bench frame under Cachegrind grow by more than 2%, over the figures committed inbenches/bare_chart.baseline. The job summary reports both figures with the unchecked median and 95th percentile frame time and prints the baseline lines a pull request commits to accept growth. (#441) -
The
frame_timebench renders one chart of 5,000,000 bars zoomed out and zoomed in, four charts of 100,000 bars and eight charts of 100,000 bars with ten studies each, headlessly on sample data, and prints the median frame and tessellation time of each as a Markdown table, then the first frame and the median and 95th percentile of steady frames, of frames with a tick on the last bar and of frames with a new bar, for candles and the Renko, Kagi, Line Break, Point and Figure and range bar charts on 1,000,000 one-minute bars:cargo bench --bench frame_time. CONTRIBUTING.md describes how to compare two commits with it. -
The
streambench feeds one chart 10,000 trades a second from a thread, with 10 or 30 studies on 100,000 and 1,000,000 bars and frames paced at 60 Hz on the wall clock, and prints the median, 99th percentile and longest frame of each, and how often a study that does not update incrementally is recomputed:cargo bench --bench stream. -
FloatingReplayControl::set_dock_rectdocks the floating replay bar in a rect, usually the chart’s: the bar opens centred 8 px above the rect’s bottom edge and can be dragged only within it. Without a dock rect the bar docks in the window’s content rect. -
ReplayColors::from_themebuilds the replay colours from a theme, andReplayColorsimplementsPartialEq. -
ui::context_menu::ChartMenusshows the chart, series and drawing context menus for anyChart(featureui): callmenus.show(ctx, &mut chart)afterchart.show(ui)to open the menu for the last right-click and read the chosen action. While a menu is open the chart draws no crosshair or tooltip under it. -
ChartBuilder::with_feeddrives a chart from adata::Datafeed. The chart asks for the instrument and the latest page of history without blocking, applies answers and live updates once per frame, asks for older pages as the user scrolls back until the feed reports the end of history, subscribes after the instrument resolves and unsubscribes on every symbol or timeframe change and when it is dropped. A push from any thread wakes the UI once per burst.Chart::feed_statereports loading, live status, the last error and dropped updates. After a history or instrument error the chart asks for nothing more until the symbol or timeframe changes. -
Chart::set_timeframe,Chart::symbol,Chart::timeframeandChart::instrument. -
Chart::tradesandChart::order_bookhold the trades and the order book the feed pushes; the chart asks the feed once for recent trades (Datafeed::trades) and for a new book snapshot when the book is lost. -
examples/live_feed.rs: a feed that serves pages of history and streams trades from a thread. -
ui::Controlandset_control_visibleonTopToolbar,DrawingToolbar,TimeframeToolbar,WidgetBar,ChartMenusandSettingsDialog: a host hides the controls it has no service for, such as alerts, trading, replay, layouts, templates, compare, time zone, session or dividend adjustment. A hidden control is not drawn and emits nothing, and a menu of it that is open closes; every control starts visible. In the chart settings dialog, Reset to defaults takes the place of the hidden template button. -
The drawing bar uses the chart’s shortcut map for tool keys and hints; standalone toolbars use
DrawingToolShortcuts.DrawingToolShortcuts::help_textformats those bindings as key labels such as “Alt+T”. Chart defaults and migration are listed below. -
A star in a drawing bar flyout row adds the tool to the favourites or removes it, without selecting the tool; a favourite shows a filled star in the warning colour.
-
ToolbarState::lock_allandToolbarState::hide_drawings,hide_indicators,hide_positionsandhide_ordershold what the Lock button and the Hide menu show: the lock button is filled with a closed padlock whilelock_allis set, and the Hide menu checks each hidden group. The bar sets them from the clicks it reports; a host that changes the chart’s state elsewhere sets them too. Migration: struct literals ofToolbarStateset the five fields or use..ToolbarState::default().
-
Time-synchronised charts of different intervals stay readable. A synchronised range was stored on the receiver as bar spacing and offset, so a coarser receiver turned a short span into a bar wider than the plot, a finer one dropped to the spacing floor, and a range with no bar in it left the receiver blank; an interval switch then reinterpreted the stale spacing at the new interval and broadcast it to the whole group.
Chart::apply_synced_time_rangenow ignores a range outside the chart’s loaded bar slots, stops the fitted spacing at the configured maximum, or 50 px when there is none, and centres short spans. AChartLayoutremembers each chart’s UTC edges, refits the chart to them once its bars for the new interval arrive and holds back its range broadcast until then; a chart still loading adopts the latest range the group broadcasts meanwhile, so its arrival does not pull every chart back to where it stood before the switch. The layout passes the active chart’s interval with each range, so charts of the same interval fit it as manual zoom does, bounded only by their configured maximum spacing, and only a receiver of another interval falls back to the 50 px cap. (#1538) -
Chart settings keeps its top edge in place across tabs, and its controls and the shared dialog chrome follow the theme. The dialog centred itself on every tab, so its top edge moved from y 142 on Symbol to y 30 and y 200 on the others and the tab list slid under a stationary pointer; it now takes the top edge of its tallest tab, centred in the window and recomputed on resize. Checkboxes are 18 px and fill with the text colour when checked, colour wells are 34 px, section headings are muted, and outlines and headings use the theme’s
border_controlandtext_muted. The dialog frame, title row, footer and sidebar take new insets, glyph size, button sizes and a 40 px row pitch, and the light dialog loses its outline for a tighter shadow while the dark and high-contrast dialogs keep theirs. Indicator settings scroll sideways instead of widening the dialog when their inputs, such as those of Vol Profile, are wider than the window leaves room for. (#1559, #1563) -
Quick search and symbol search are restyled. Quick search leaves the chart undimmed, spaces its search rules 41 px apart, drops the redundant placeholder and sets its centred instruction in the heading text size, and the close glyph of the shared title row is larger. Symbol search draws 56 px rows with 36 px discs, highlights matching substrings and keeps its category pills on one scrollable line beside the source filter, where dense results and wrapping categories pushed matches down the chooser; the host’s exchange choices, recents and root drilldown are kept. Light themes use a light veil behind the dialog and dark themes keep the dark modal overlay, and comparison captions and the placeholder follow the theme’s text roles. (#1557, #1561)
-
Undoing the removal of the main series brings the series back and resumes its feed. Removing it recorded only its visibility, so undo consumed the step while the series stayed absent and its feed stayed stopped. The history now keeps the series’ presence, price lines, formatter and bar limit and exchanges them before restoring visibility, retaining its bars and per-symbol markers. The host’s pause setting is tracked apart from removal and from replay pauses, so undo and redo resume the feed when they should, including after replay ends, and snapshots omit the retained markers while the series is absent. (#1351)
-
Fibonacci circles, speed resistance arcs, wedges and the spiral are built from the right points. Circles are ellipses around the midpoint of the swing between the anchors, scaled by its width and height, so they are round for a swing drawn at 45 degrees. Speed resistance arcs are centred on the first anchor, the level 1 arc passes through the second anchor, and they open towards its side. Circles, arcs and wedge arcs draw each level in its colour with its ratio, can shade the bands between levels and join the anchors with a trend line in the drawing’s style, and a new wedge has no radius 0 arc. The spiral also draws the ray from the first anchor through the second to the pane edge, which it is constructed from. Selection follows the painted shapes. (#1382)
-
Fibonacci time zones, speed resistance fans and trend-based time show their levels evenly. Time zone lines look alike in their level colour, the zones are shaded only when the background is on, each zone number, 0 included, sits at the bottom beside its line without a box, and a trend line in the drawing’s style joins the anchors. On the speed resistance fan, level 0 is the diagonal between the anchors and level 1 the horizontal (price rays) or vertical (time rays) through the first anchor, in either drawing direction; price and time rays share each level’s colour, the ratios are labelled at the edges of the box between the anchors, and the arcs and the extra trend line are gone. Trend-based time draws a line through its three anchors, labels each level at the bottom and can shade the zones between levels. (#1381)
-
Fibonacci retracements, extensions and channels measure and draw their levels as a trader reads them. Retracements and extensions draw a trend line through their anchors in the drawing’s colour, width and line style, dashed on new drawings, and level lines take a width and a line pattern of their own,
FibonacciConfig::level_widthandlevel_style, set with Level width and Level style under Inputs. Bands lie between levels adjacent by ratio, whatever order the levels were entered in. Extension levels run from the second to the third anchor, start without Extend and can be reversed, and channel levels move the base line towards the third anchor in time as well as price, so level 1 starts at the third anchor. Labels show the level and its price through the chart’s price formatter and sit outside the construction, beyond the end of each level line on the sidelabels_on_leftchooses (the left on new drawings), moving back inside the pane when that end is extended to the pane edge; new drawings label levels as ratios. Saved explicit settings, including saved extension choices, are kept, and selection follows the painted lines. (#1380) -
Order-flow studies update incrementally past 10,000 bars. Once an order-flow input held 10,000 bars, every new bar dropped the oldest one and reset the input, so the chart recalculated every study on that input from the first bar, cleared the sibling studies waiting for their turn for a frame, and moved the cumulative delta of every closed bar by the dropped bar’s delta. An input now keeps up to 11,000 bars and then drops its oldest down to the newest 10,000, the longest span of a flow sum, so the reset and the full recalculation come once per 1,001 new bars, and a bar that crosses no drop updates the studies from that bar and leaves closed bars unchanged. A cumulative sum such as Size-Filtered CVD starts again from the oldest retained bar after a drop. (#1282)
-
The drawing bar’s glyphs are even in size and its group rules are inset evenly. Glyphs ranged from 15 to 28 px of ink, the first one started 13.5 px below the bar’s top edge and the group rules were 36 px wide at x 8. Every default glyph is now sized so that its ink spans 22 to 23 px on the longer side, the 38 px button pitch is unchanged, the Text glyph is redrawn as a taller T that measures 15 by 18 px, and the group rules are 33 by 1 px, inset 9 px from the left edge and 10 px from the right. (#1523)
-
Chrome ink, hover tiles, the legend and the panel ground agree across the light and dark presets. The light preset draws text and axis text in black, with muted labels at #696969, disabled text at #7e7e7e and a lighter grid at #e5e5e5 while the watermark keeps its tone, and the dark border, the ground between panels, becomes #2e2e2e while the toolbar and bottom bar rules keep #4a4a4a. Unavailable history icons use the disabled colour without an extra fade, the two Save actions have independent hover and keyboard focus targets, default toolbar controls are 34 points and active widget bar entries take neutral fills. The legend insets its readout by large spacing, eight points by default, shows every study input in one muted colour, and draws its title and collapse button in the UI ink with a rule derived from the panel and text colours. Default chart titles are 13 points and bottom bar labels 12 points, where they were 16 and 14; saved explicit sizes and host overrides keep their values, and missing saved roles take the new defaults. Migration: set
chart_titleto 16 andbottom_barto 14 inTextSizesto keep the former defaults. The demo restores the panel gaps, reserving 52 points plus a four point margin for the drawing bar, and the chart’s radius four corner after the chart paints its rectangular background. (#1518, #1522, #1524) -
TPO profiles give the same point of control and value area on every build. The point of control was the last tied row in hash map order, so the same bars gave a different point of control and value area from one build to the next. Ties now take the lower price, as footprint bars and volume profiles do; when the two rows above and the two below hold equal TPO counts, the value area grows by one row on each side, as a volume profile does; and single prints are sorted by price. (#1280)
-
The TPO initial balance starts from the session’s first bar. An initial balance high of exactly zero was taken to mean that no bar had arrived yet, so the balance restarted at the next bar on instruments trading around zero. The session’s first bar now opens the balance and later bars of the initial balance period only extend it. (#1284)
-
Automatic TPO rows are whole instrument ticks. Rows fitted to the visible range ignored the instrument’s tick, so rows, counts and the point of control fell between tradable prices. The TPO chart type, the Time Price Opportunity study and the profile menu now round the fitted row up to whole ticks, within one part in a billion so that a row of exactly n ticks stays n ticks; a row height pinned in the settings is used as set. (#1281)
-
The account panel shows the broker’s connection status.
Trading::applydroppedAccountEvent::Status, so the account panel, the order ticket and the depth ladder looked the same whether the broker was live or had dropped, and a user learned of a lost connection only when an order was refused.Tradingnow keeps the last status the broker pushed on the current stream, and the account panel’s tab marks a broker that reports that it is connecting or disconnected with the library’s connection indicator, “Connecting…” or “Offline” beside the broker’s name, until the broker reports that it is live; the tab shows at every panel height, so a minimized panel shows the mark too. Each stream starts without a status, as it starts without the account’s state, so a new stream, a new broker anddisconnectclear it.Trading::has_brokertells whether a broker is set, connected or not, and the demo uses it to show the account panel and to choose between the broker picker and trading.Broker::connectdocuments the contract: a stream starts as connected, a status that is not live is pushed again on each new stream, and the orders the user confirms while the broker is not live are still sent, for the broker to refuse what cannot reach it. (#1484) -
The properties dialog of a freehand stroke no longer lists its samples as coordinates. A brush or highlighter stores one chart point per pointer sample, so its Coordinates tab listed every sample as an editable row, often hundreds of them, and editing one moved that sample out of the stroke. The tab is now left out for tools that draw continuously, following the tool’s interaction mode so that a future freehand tool follows without an edit, and
DrawingProps::from_drawingstages no coordinates for them, so neither the dialog norapply_to_chartcan move a single sample; every other tool keeps the tab. Migration: hosts that moved single samples of a stroke throughDrawingProps::coordinateseditDrawing::chart_pointsinstead. (#1469) -
A footprint passed to
Chart::show_footprintno longer slows the frame on a chart zoomed out below half a point per bar. The cells of such bars have no horizontal area, yet the renderer walked every visible bar and grouped its executions; they are now skipped before the executions are looked up. The default minimum bar spacing and wider views draw as before, and with executions on each of 100,000 visible bars at a minimum spacing of zero the frame takes about 3.8 ms instead of about 166 ms;cargo bench --bench frame_time -- footprint-hostmeasures it. (#1449) -
Depth history pages that fill a gap are merged to the resolution of the tier they join, whatever order the pages arrive in. Gap-fill samples took coarse-tier slots one by one, so pages that arrived out of order used up the history’s capacity much earlier and shortened its span. Contiguous finer runs now merge as scroll-back pages do, including the completion of a short held column at the newer boundary. Tier boundaries and overflow timing can still leave small differences in the retained span between arrival orders. (#1424)
-
An empty heartbeat candle opens at the close of the newest bar before it after a history page. A heartbeat candle took the last close the stream pushed through its sink, and history pages are merged by the chart and never reach the sink, so after a page whose newest bar was newer than anything the stream saw, the next empty candle opened at the stream’s older close and showed a gap until its first trade. After each merge that changes bars, every empty heartbeat candle from the first changed bar on now carries the close of the newest bar before it that is not whitespace, whether the heartbeat was merged after the page or the page was merged under candles already on the chart, for chart and study series alike. A candle with no such bar keeps the close the sink seeded. (#1421)
-
The horizontal, vertical and cross line shortcuts place their line at the pointer, through the pane’s coordinate and snap mapping, where they only armed the tool. A shortcut pressed with the pointer off the chart only selects the tool, and hovering later places nothing. Alt+C selects the cross line and Alt+J the horizontal ray, which had no bindings. (#1409)
-
Measure is a temporary ruler. It left a saved, undoable drawing behind; it now stays visible until the next chart click or cancellation, outside the saved drawings and undo, and finishing it returns to the selection tool even in keep-drawing mode. Shift-click on empty space starts a measurement, and Shift-click on a drawing still toggles its selection. (#1409)
-
Dashed and dotted lines lying just outside a pane edge keep the half of their stroke that overlaps the pane. The shared dash clipping bounds followed the centreline only, so a stroke whose centre lay outside the edge lost the half inside it, and a shallow crossing of a border was shortened. Both bounds are now widened by half the stroke width and square dots are reserved with the same bound, so overlapping strokes show on all four edges and fully hidden strokes still do not. (#1433)
-
The order ticket and the depth tab size and colour their controls consistently. Ticket fields and menus share one height, the quote box balances against the primary action, the header icons and exit switches are larger, and the order-type rail and its underline have the same thickness in both themes. Field outlines are softer at rest while keeping 3:1 contrast on the field background, stronger on hover and in the accent colour on focus, which is painted only for the field’s own layer so that a popup overlapping a field does not draw it; the time-in-force styling no longer reaches later controls, and disabled light fields are filled. Switches and the quote box take neutral surfaces derived from the theme, labels are muted, and text sizes, button text colours and hover fills come from the theme. The depth ladder uses a 20 point row pitch with body-size prices and sizes, shorter position boxes and footer actions, market buttons without outlines and a filled margin tag for the prospective order type, and reserves the actual height of the quantity field so that the footer controls stay reachable. (#1526, #1527, #1531)
-
The standalone indicator pane example takes a
CustomIndicator, so it compiles with thewidgetfeature alone, and documentation links to items behind a feature the build lacks point to the feature table or name the feature instead of failing to resolve. (#1314) -
Price tags on a scale without instrument precision take the decimals of the nearest tick label, at least two, instead of always two: the last price and countdown, the previous close and extended-session price, High, Low, Bid and Ask, price lines, study values and the tags of added series. A close of 1.08692 on a scale from 1.0845 to 1.0873 read 1.09. (#1221)
-
Study value tags and the High, Low, Bid and Ask tags and badges on the price axis choose black or white text for their fill, as price line tags do, so labels on pale fills such as gold and yellow study colours are readable. (#1273)
-
A dashed or dotted study line is dashed only where it can be seen. Study lines were split into dashes or dots along their whole length, including the part far outside the pane, so zooming the price scale in close to its minimum span stalled the frame; every further dashed or dotted line, such as the three Bollinger Bands lines, added the same cost. The patterns inside the pane are unchanged. In a 1,000 point pane, a dashed line crossing it from the scale’s top bound to its bottom bound paints about 100 dashes instead of 2,000,000. (#1338)
-
Drawing properties show Fill, Extend and the Text tab only for tools whose renderers use those settings. Edits preview on the chart while the dialog is open; Ok commits them as one undo step, and Cancel, Escape or closing restores the original properties without changing undo or redo. A Template menu in the footer saves named styles and the tool’s default, resets to defaults, and applies or deletes the saved templates of the same tool. Template rows no longer appear in the Hide flyout. (#1367)
-
Cyclic lines start at the first anchor and repeat only towards the second, using the drawing’s line width and style, without alternating fills or labels. Time cycles use closed half circles that honour the fill colour, without a period label; placement and handle drags keep both anchors on the first anchor’s baseline, with the second anchor changing only the period. Sine lines no longer draw centre and amplitude guides or labels. Cyclic lines and sine lines no longer offer a fill setting, since they paint no filled area. (#1390)
-
Table drawings use a plain theme background, equal-height rows and one-pixel grid lines and borders in the theme’s border colour. Cell text is left-aligned with padding and vertically centred, including the first row. Existing saved tables keep their cells and use the same appearance. (#1399)
-
Volume Footprint and Session Volume Profile charts zoomed out until several bars share a physical pixel draw the bars without executions merged, about one candle per pixel column as Candles charts do, instead of every bar; bars from the first execution on are still drawn from their executions. In builds without
studies, the volume beneath a footprint fromChart::show_footprintmerges the same way. A Volume Footprint chart with 1,000,000 bars in view paints 3,013 shapes instead of 2,001,055;cargo bench --bench frame_time -- "volume footprint"measures its frame time. (#1269) -
A frame visits only the markers and time scale events near the view: the lists given to
Chart::set_markers,Chart::set_eventsandChart::set_time_scale_eventsare indexed by time when set, so the markers drawn, hit and fitted to the price scale and the event badges are found by binary search instead of by reading every item, and manual markers are no longer copied each frame when a mark source supplies bar marks. Markers and badges are painted in the order supplied, as before.cargo bench --bench frame_time -- "200,000 bars"measures the frame time with a marker or a news event on every one of 200,000 bars. (#1271) -
Forecast drawings label both anchors with their price and date, format prices and the signed change with the instrument precision, and express the time to target in calendar units. Cards fit their text and follow the active theme; a success or failure badge appears below the target card only when decided. The forecast line ends in an arrowhead. (#1402)
-
Fixed range and anchored volume profile drawings leave more candles visible: the widest row uses one third of the measured span, the range has a faint tint instead of an outline, and up/down and delta rows outside the value area are dimmed. Anchored rows grow left from the pane’s right edge, with their width capped to one third of the pane when the anchor is offscreen. The point of control is a stronger solid line without a badge; value-area guides remain optional. Volume profile studies keep their existing presentation. (#1407)
-
Ghost Feed accepts any number of anchors and finishes on double-click or Enter. It projects one candle per bar with repeatable noise seeded by the saved drawing identity, uses tick-based average range and noise inputs, and paints translucent rising and falling candles along a thin grey path without a tag, permanent dots or a projection stub. Instrument tick size sets the price increment; without it, one price unit is one tick. Saved
spacingandwicksettings load with the new defaults. Migration: replaceGhostFeedConfig::spacingandwickwithaverage_range_ticksandnoise_ticks; calls toGhostFeedConfig::candlesnow also pass the tick size and persistent drawing id. (#1404) -
Ray and extended-line rendering, endpoint markers and hit areas now follow Extend left and right; new rays start extended right and new extended lines start extended both ways. Rectangle borders, fills and hit areas extend to either pane edge as configured. (#1372)
-
Regression trend selection handles sit on the fitted centre line and change only the bar range when dragged; the Coordinates tab edits time or bar coordinates without price fields. The Style tab exposes Fill and Extend. With Fill on, the channel fills its upper half in the fill colour and its lower half in the line colour; it draws solid boundaries in the accent colour at the drawing width and a dashed centre line, and Extend carries all three lines and both fills to the pane edge. A plain correlation value near the lower boundary replaces the boxed statistics. Existing saved bar ranges are retained. (#1378)
-
Sector drawings take the short arc between their radii in either direction, with the hit area following the same wedge. Projection move and target labels size their backgrounds to the text, so long prices stay inside their boxes. (#1405)
-
Trend angles show a signed angle with one decimal and a degree sign as plain text in the drawing colour and font size. The short horizontal guide and arc are dotted and share a radius that meets even a short leg. The label box, the permanent anchor and arc-end dots, the change and bar statistics and the unused fill setting are removed; selected handles and the first-anchor preview remain. (#1373)
-
Pattern, Elliott wave, cycle and Gann main lines honour the configured width, including 2 px, while ratio connectors, guides, grids and label outlines keep their own widths. Pattern and wave fills use the chosen colour and disappear when Fill is disabled, without recolouring their label boxes. Their point, wave and ratio labels use the configured font size, with backgrounds growing with the text. New tinted patterns, waves and Gann boxes store their tint as an enabled fill; tools without a fillable body no longer offer a Fill control. Other drawing families retain their configured body fills. Opening properties preserves an unchanged translucent fill, and version-1 patterns retain their saved line colour in their default tint. (#1370)
-
Disjoint channels mirror the first line’s slope through the third anchor over the same bars. Flat top/bottom channels end on those bars without overhang. Both draw only their two boundaries and the configured fill, without price or height labels, respect Fill and left/right Extend, and share their visible geometry with hit testing, including fills across a crossing. Parallel, flat top/bottom and disjoint channels offer a handle at each line end; the flat handles change only price, parallel boundary handles change width, and disjoint boundary handles keep the opposite ends fixed while mirroring the reshape. Disjoint drawing alerts follow the mirrored boundary on linear and logarithmic scales. Existing saved anchors use the corrected geometry without a storage migration. (#1377)
-
Bundled stickers retain their outline and eye colours when the drawing colour changes, and font icons and emoji no longer carry an extra dot. (#1401)
-
Pressing and dragging any unlocked drawing selects and moves it in one gesture without panning, in the price pane and study panes. Locked drawings and empty chart space still pan. Completed drawings are selected immediately, and drawing bodies and handles show pointer, move and resize cursors. Selection handles stay on anchors; rectangles replace their centre handle with four edge handles that resize only the grabbed side, and a body move remains one undoable edit. Migration: exhaustive matches on
HandlePosaddTop,Bottom,LeftandRight. (#1364) -
Time-scale spacing has a 0.000001 pixel floor, including when the configured minimum is zero or a positive maximum is smaller than the floor, so large or repeated zoom-outs leave finite scroll offsets and visible ranges and zooming back in still works.
TimeScale::set_min_bar_spacingandset_max_bar_spacingignore non-finite values and retain their previous limits. (#1349) -
Finished drawings show their lines, fills and labels without permanent anchor dots or rings. Selecting a drawing still shows its editing handles, and placement previews keep their anchor dots. (#1363)
-
Indicator::plot_styleandIndicator::line_styleaccept any line on every built-in study. MACD, PSAR, ADX Breakout, Rising Wedge, Falling Wedge, Knoxville Divergence, PPO, PVO, Woodies CCI and Elder Ray panicked on a line past their last, and so didline_styleofMACombinationand its presets, MA Ribbon among them; such a line now gets a style, also through theConfiguredStudythat a chart andStudyTemplate::createreturn. (#1326) -
A study template, a copied study and a saved layout recreate
CVD,CloseToCloseVol,HL2,HLC3,PriceChannel,EhlersFisherandMACombination, andChart::snapshotno longer fails on a chart that holds one:IndicatorFactory::createandhasresolve their names, whilelist,categoryandcountleave them out of the catalogue as before.MACombinationhas inputs for its number of averages, two to fourteen, its crossing pair and its colouring by direction, ahead of the inputs of each average; the moving average presets keep their average count and crossing pair fixed; MA Ribbon also offers colouring by direction. (#1327) -
StudyTemplatekeeps the study’s value scale inscaleand applies it, as the study clipboard does, so saved layouts keep it too; a template saved without it leaves the study’s own scale. Settings made through builder methods are inputs, so templates and layouts keep them: the session names and time zones ofTradingSessions, the time zone and trading day start ofVolumeWeightedAvgPrice, the Fibonacci levels, label settings and options ofAutoDrawing, and the colouring by direction of MA Ribbon.VolumeWeightedAvgPrice::with_sessionkeeps what the calculation reads, the earliest open of a window that spans midnight, to the minute;TradingSessions::with_sessionkeeps a session name on one line; andAutoDrawing::with_fibonacci_configkeeps up to 24 levels with finite ratios and one-line labels. A template that names an IANA time zone needs thetimezonesfeature to load, as VWAP event zones already do; the zones of the default trading sessions also load without it, as the fixed offsets the study uses there. (#1328) -
Double-clicking a non-text drawing opens its properties in the terminal and demo; annotations and supplied content keep their inline editor. (#1366)
-
Kinetic scrolling replaces non-finite damping coefficients and values outside
0.0..1.0with the default of0.997when chart options are applied. Non-finite velocity or overflowing motion stops the animation before an invalid offset can reach the time scale, and stopped animations no longer request another repaint. (#1350) -
Empty legend titles no longer reserve a gap or paint text with non-finite bounds. Floating tooltips omit empty cells, and tracking tooltips omit empty text when optional fields are disabled. (#1268)
-
Study values in floating tooltips and legends use the plot colour at full opacity, so translucent plots keep readable readouts, and a fully transparent one uses the theme’s text colour. Host-facing study colours retain their plot opacity. (#1275)
-
LocaleTimeFormatter::newdefaults to a 24-hour clock foren-GB, and underscore locale identifiers use the same hour cycle as their hyphenated forms, including the 12-hour clock foren_USanden_CA. Explicit clock preferences are unchanged. (#1231) -
Subsecond time-axis labels show milliseconds, including fractions within minute and midnight boundaries. At intervals of one second or more, clock marks retain their labels without fractions, including bars with sub-millisecond timestamp offsets. Subsecond crosshair labels place the fraction before the AM/PM marker in both built-in formatters and the
TimeFormatterdefault. (#1227, #1228) -
Intraday time axes with day or longer label intervals mark the first available bar of each Monday-anchored day bucket, including weeks whose opening day has no data. Missing Sunday bars no longer hide weekly labels. (#1219)
-
Daily time-axis labels use the first supplied bar at or after each calendar boundary, so weekends and holidays with no bar are not labelled. Candidates sharing a bar keep its strongest boundary, and candidates beyond the last bar are omitted. (#1234)
-
InMemoryToolsRepository::get_all_categoriesreturns the toolbar’sCATEGORY_ORDER, so it includes Cursors, and unknown category names no longer select Trend Line. Migration:drawings::categories::get_category_default_toolreturnsOption<DrawingToolType>,Nonefor an unknown name;DrawingToolType::by_categoryreturns an empty vector for an unknown name. To keep the old fallbacks, mapNonetoDrawingToolType::TrendLineand an empty vector tovec![DrawingToolType::TrendLine]. (#1334) -
The demo gives SAMPLE and its US stocks (AAPL, MSFT, NVDA, TSLA) US equity hours in America/New_York on weekdays, regular 09:30 to 16:00 and extended 04:00 to 09:30 and 16:00 to 20:00, so post-market trades stream until 20:00 New York time with extended hours on and the hours follow daylight saving. Before, SAMPLE had fixed UTC hours that ended its extended session at the pre-market and the stocks streamed around the clock. The session and dividend adjustment controls show for every symbol with trading hours and a dividend, the stocks and the fund, and adjustment applies a synthetic dividend of the symbol’s own, with distinct ex-date instants inside the retained live history so ADJ changes earlier prices; crypto, forex, the index and the future keep their behaviour. Closed-market quote lookups skip nights and weekends without scanning the retained trades. Extended quotes keep the latest price and time inside the extended windows when the market is closed. The session menu’s note gives the hours in New York time. (#1295)
-
Drawing anchors in whitespace use the known timeframe duration or the most common positive spacing among the outermost 16 loaded bars, so a weekend, overnight gap or partial opening bar no longer changes their step or moves them when the next regular bar arrives. Steps that divide an hour keep whitespace slots on the grid of the regular bars, including after a partial opening bar. Known month and year intervals advance by calendar months in the display time zone when the bars are keyed at its midnight and in UTC otherwise, and axis labels use the same full-history mapping at every zoom. Migration: hosts that store whitespace times from
Chart::index_to_timeorChart::visible_time_rangeget the new spacing; drawings saved past either end keep their stored instant and may need to be moved once. Their original placement cannot be recovered from the stored times. (#1254) -
services::PaperAccountremoves accumulated rounding dust when closing decimal quantities, so buying 0.1 and 0.2 then selling 0.3, or scaling out 1.0 in ten sells of 0.1, leaves no phantom position. (#1151) -
combine_tradesandChart::combined_tradesgive fills at one price exactly that price as their volume-weighted price, instead of a value one rounding step away. (#1143) -
MaturityScale::whitespacetreats a non-finite last maturity as the configured minimum range and caps a finite last maturity at 12,000 months before comparing it with that minimum. A larger explicit minimum range is preserved, while an invalid or extreme data-derived maturity no longer requests unbounded whitespace. Migration: a host that needs whitespace past 12,000 months setsminimum_rangeto that span. (#1307) -
TimeScaleignores non-finite widths, bar spacing, right offsets and scroll or zoom inputs, including options applied by chart construction, settings, synchronization and undo or redo. Invalid configured offsets retain the previous live-edge values, so returning to realtime remains safe.Chart::set_chart_optionsandChart::with_chart_optionsretain the previous finite spacing and offsets before storing options, so reapplying an invalid offset preserves a scrolled view. New spacing bounds still clamp the retained spacing. Box zoom rejects non-finite corners or widths before changing either scale or zoom history. Migration: infinite offsets, scrolls and zooms that previously clamped to the scroll or zoom limit are now ignored; pass a finite limit to reach an edge. (#1306) -
PriceScale::set_rangeignores non-finite, equal or reversed bounds and overflowing spans before changing the range, manual scaling or a locked price-to-bar ratio. Automatic scaling can still fit the next frame after a rejected range. (#1233) -
VolumeFormatterpromotes a rounded mantissa of 1000 to the next available unit, so values just below the K, M and B boundaries show1.00K,1.00Mand1.00Bat the default precision, including negative values. (#1230) -
Normal and logarithmic price-axis ticks respect multiples of
PriceMarkGeneratorConfig::min_price_step, including when label precision is set. Automatic labels retain the decimal places needed for fractional grid intervals, up to eight in fixed notation. Percentage and indexed intervals keep their own scale units. Floating-point noise in tiny tick sizes or precision units no longer increases an already round interval. (#1229) -
Percentage axis ticks and price labels show a positive zero when the value rounds to zero at the displayed precision, including scientific tick labels. (#1226)
-
A drawing copied or saved in a study pane is pasted or loaded into the pane holding the same studies on the target chart, or into the price pane when the chart has no such pane, instead of the pane of whichever study has the same id there, where it sat on another study’s scale, was drawn at a study’s price in the price pane, or was listed and saved but never drawn. Study ids are local to each chart, so
Chart::copy_selected_drawingsandChart::save_drawingsstore the pane’s identity inStoredDrawing::pane(aStoredPane: the names and inputs of the pane’s studies and its rank among the panes holding the same ones), andChart::paste_drawingsandChart::load_drawingsresolve it asChart::linked_panematches panes for linked charts. Records written before keep their study id and load as before. A study that takes another study’s output as its source names it by its local id, so its pane matches only on charts where that id names the same study, as with linked charts.Chart::linked_paneno longer answers the price pane when its overlays are the same studies, as documented. Migration:StoredDrawingliterals addpane: None, or useStoredDrawing::new. (#1252) -
Undoing a bulk drawing command reverts only the drawings it changed.
DrawingManager::edit_selected(the properties dialog),delete_selected(the Delete key),clear_all,set_group,set_visibility_all,toggle_lock_alland the end of a multi-selection drag recorded every drawing, so their undo also reverted changes made since to other drawings outside chart history, such as a linked chart’s edits or a host’sedit_drawing, and queued saves for all of them. They now record only the drawings they change or remove, with their list indices, which also keeps history from growing with the number of drawings. (#1251) -
Undo and redo put drawings back at their place in the drawing list, which decides which of two drawings with the same z-order is painted and hit on top. Undoing the deletion of a drawing no longer brings it above the drawings it was under, and redoing a paste no longer puts the copies beneath every other drawing. History records the list index of each drawing it takes out of the list and reinserts the drawing there. Migration:
DrawingCommand::Deleteis a struct variant withdrawingandindex,DrawingCommand::Snapshot::drawingspairs each drawing with its list index,HistoryService::push_deletetakes the index the drawing was removed from, andHistoryService::push_snapshottakes(index, drawing)pairs in list order. (#1250) -
Saved drawings, pasted drawings, host drawing edits, the drawing properties dialog and drawing templates, including the settings document’s drawing defaults, refuse a font size outside 1 to 256 points, a stroke width that is not above 0 and at most 100, and a pitchfork level beyond 100 times the tine distance;
DrawingStorage::to_jsonrefuses them as well, and loading skips such a drawing and reports it. The text, icon and inline editor renderers draw sizes outside the range at its nearest end, as do the tooltip, the watermark and the axis labels, andChart::restorerefuses a tooltip, watermark or axis font size outside it. Pitchfork levels beyond the bound are not drawn, and pane heights are shared from stretch fractions, so a stretch factor nearf32::MAXno longer overflows, andChart::restorerefuses stretch factors whose sum is not finite. A large font size in a saved document had panicked the glyph rasterizer, and huge or negative sizes had produced NaN geometry. (#1238, #1241) -
The vertical grid of a time-independent chart and of indicator panes keeps its lines at least 80 points apart at any bar spacing, so a tiny maximum bar spacing no longer makes a frame draw millions of lines. The two grids share one interval rounding.
Chart::restorerefuses minimum and maximum bar spacings that are not 0 or at least 0.01. (#1239) -
A layout that
Chart::restoreaccepts now saves a layout that loads again.Chart::restorerefuses a snapshot holding a number that is not finite, which the next save would write asnulland the next load refuse (for example anf32field ofconfigoroptionsgiven1e39), a crosshair width of zero or less and a scale font size of 0 in its settings, before changing the chart.Chart::snapshotreturns an error instead of a layout thatrestorewould refuse, and a price scale whose fit to the data overflows keeps its previous range, so a study with an extreme input no longer makes the chart’s layout unsaveable. (#1240) -
Editing an alert whose saved expiry has no local time in the dialog’s time zone, such as the last representable instant in a zone east of UTC, no longer panics: the dialog treats that expiry as changed, so a newly entered date and time replace it. (#1242)
-
Session dividers and the watermark follow the active theme:
ChartConfig::with_theme, and soChart::set_themeandset_theme_override, setsession_break_colorfrom the theme’s major grid colour andwatermark_colorfrom its grid colour, and a restored layout that still holds the previous palette’s values follows the theme too, while an edited colour is kept. They stayed at the dark preset’s colours, which made the dividers invisible on the light theme and the watermark a heavy dark mark. (#1272) -
Marker::newhas the colourColor32::PLACEHOLDER, which the markers and the time scale marks paint in the active theme’s text colour, shapes and text alike, so a marker withoutwith_colorreads on the light theme instead of painting white on white; a marker with a colour is unchanged, and layouts saved with white markers keep them white. (#1274) -
widget::ValueFormattersis publicly exported so hosts can name, store and pass the formatters used byLegend, andstyles::LayoutContext, whichResponsiveToolbarpasses to its content, is exported with theuifeature. Public signatures are checked by theunnameable_typeslint. (#1310) -
PaperAccount::newdocuments its panic whenbalanceis NaN or infinite under a Panics heading. (#1318) -
Migration for standalone renderers: pass
ticks_visiblebeforeslottorender_time_labels;falsepreserves the previous tick-free axis. -
Depth history pages keep held columns at their existing resolution: empty and fully overlapping pages leave every tier unchanged, older columns merge pairwise to the oldest held tier’s resolution, and columns inside gaps are placed by span and age. Adjacent pages complete a short oldest column so default paging retains at least 42 hours; accepted counts exclude discarded input columns. Live corrections replace overlapping columns without merging unrelated history again; full columns merge only in overflowing tiers. (#1247)
-
Replayed trades with order ids find their retained fills by id in constant time, including individual pushes, drained bursts and overlapping history pages, so reconnects no longer scan the trade store for every fill. Missing order ids are still completed without counting the fill again. A 100,000-fill replay is checked for instruction growth in CI, with annotation correctness checked independently of elapsed time. (#1245)
-
Depth deltas sort their changes and merge only the touched suffix of each side into reused buffers, so small updates near the touch do not copy the whole book or allocate once warm, and best-first batches no longer shift a growing side once per new level while holding the inbox lock. The last entry for a price still wins, and a resulting side beyond 10,000 levels is rejected before replacing either side. Larger batches of updates and removals remain accepted when their resulting sides fit. Change buffers with capacity beyond 10,000 entries are released after the delta. (#1246)
-
Heartbeats after a pushed whitespace bar keep the last real close for their zero-volume candles instead of creating invalid bars. Whitespace alone does not seed a heartbeat candle. (#1248)
-
History pages extend only their newest bar with trades already streamed in its slot, keeping the page open, the combined range and volume, and the latest trade close, for both chart and study series. Completed page bars and bars over heartbeat candles with no trades replace the tick bars; bars at or after the request’s
beforeare dropped, with a warning naming the feed on scroll-back. A scroll-back page with no valid older bar ends history with a warning. A heartbeat leaves an existing non-whitespace bar unchanged. The first trade after a heartbeat replaces only the carried candle and extends any page bar already in that slot, keeping its volume. Zero-size trades keep the forming candle’s open and range across drains and extend the newest page bar with their range and latest close when history arrives. Repeated pages do not count the trades again; an overflowing page bar is rejected and counted without discarding the trades. Migration: a feed that streams trades before answering history leaves them out of the page’s newest bar, or holds them until the page is answered. (#1243) -
WeeklySessionProviderbreaks at midnight UTC after its configuredbreak_dayand distinguishes weeks across years. Its default still starts weeks on Monday. Migration: the defaultbreak_dayis nowSun, and explicit weekdays now take effect instead of being ignored.CompositeSessionProvider::standard()gives monthly breaks priority over weekly and daily breaks; custom composites keep insertion-order priority. (#1224, #1319) -
Daily and longer session dividers use the trading date each bar carries, its UTC date or, for a bar opening at midnight in the session zone or at the first instant of a date in its clock’s calendar or session zone, its local date, including when midnight is skipped or repeated, so week boundaries and their labels agree with session closes across exchange zones. Monthly and multi-month bars shorter than a year show calendar-year dividers through
SessionBreakType::Yearly, with stronger yearly lines, while weekly and multi-day bars retain month dividers. Bars of a year or longer have no dividers. Custom intervals of exactly 24 hours receive daily week dividers and session closes, including for the countdown. Migration: exhaustive matches onSessionBreakTypeaddYearly. (#1222, #1225, #1232) -
BarClockkeeps intraday opens in chronological order across repeated hours for intervals longer than one hour, including a boundary inside the repeated hour. Session closes start a separate off-session bucket, so an after-close execution cannot change the final regular bar; shortened buckets and subsequent opens agree, including across adjacent trading windows. (#1220, #1223) -
A dashed or dotted drawing is dashed only where it can be seen. Rectangles, triangles, polylines, arrows, arcs, circles, ellipses, patterns and the other drawings restyled by their line style generated one shape per dash along their whole length, so a drawing reaching far beyond the view, after switching to a shorter interval, pasting into one or loading saved drawings, stalled the frame and could exhaust memory; the point of control line of volume profile drawings and studies did the same. The pattern stays anchored at the start of each stroke, so it does not shift as the view moves. In an 800 x 600 pane, a dashed rectangle reaching a million points beyond it paints fewer than 1,000 dashes instead of 333,000, and a frame with an anchored volume profile anchored 200,000 bars back paints about 500 shapes instead of 100,000. (#1237)
-
Body, centre-handle and multi-selection drags translate every drawing anchor in the price scale’s own units. Logarithmic drags preserve the shape and positive prices in either direction. Horizontal drags leave every valid price exactly unchanged, including anchors far outside a tightly zoomed range. Single handles retain their existing pointer clamping and magnet behavior. Migration:
DrawingManager::{update_drag_handle, update_drag_handle_with_coords}andHandleService::update_handlecallers pass a price-translation closure after the existing Y-to-price closure; it takes(price, from_y, to_y)and shifts the original price in scale units, asPriceMap::translate_pricedoes. (#1255) -
Selected drawing handles and bodies near a pane edge can be dragged outward from the first movement. The press origin starts the drag, and every update keeps the pointer on the pane, including a release outside it. (#1253)
-
Studies sourced from another study’s plot refresh from the first output value it changed, including earlier bars repainted by a new swing, fractal or pivot. Live appends and last-bar updates keep dependent histories in step with their source. (#1256)
-
Estimated volume profiles resolve tied points of control to the lower price row, as executed profiles do. Equal two-row volume sums expand the value area by one row on each side. Both tie rules are documented; a single bar spread over 24 equal rows has POC row 0 and a 70% value area of rows 0 through 16. (#1288)
-
Volume profiles built from executions centre each row on its price, so a trade at 100 with a tick of 1 spans 99.5 to 100.5, level with the footprint cells and trade, book and depth profile rows. Migration:
VolumeProfile::from_executions(bar, step, complete)becomesVolumeProfile::from_executions(bar, step, flow.tick_size(), complete), with the newFootprint::tick_size. (#1289) -
Footprint delta-percentage markers, level imbalances and bar bid/ask-ratio markers include exact threshold equality despite floating-point rounding, including fractional execution sizes summed trade by trade. All three comparisons use the same relative tolerance of one part in a billion; a value one lot below the threshold remains below it. (#1287)
-
Equal-row volume profiles that start flat rebuild as soon as a later bar changes the traded range, even inside the first row’s padding. Studies and drawings then use the requested rows and actual price boundaries, including a one-row configuration; repeated bars at the original flat price still extend without a rebuild. (#1283)
-
Footprint cells and annotations, trade profiles and their POC, value-area and node guides, live book profiles and liquidity heatmap rows extend half an instrument tick below their first tick and above their last tick. Grouped rows shift by half a tick rather than half a grouped row.
Footprint::tick_sizeexposes the original tick size. Migration:render_trade_profilescallers pass the instrument tick size after the groupedstep, for exampleflow.price_step(), flow.tick_size(), &config. (#1289) -
HeatmapStripkeeps cells aligned with the host’s bar positions at narrow zooms, widens a cell to the minimum width only up to the next cell so translucent cells never stack, clips their paint to the strip, appends cells in amortized constant time and finds visible cells by binary search. Delta and volume normalization use cached maxima over the complete history. Migration: callrender(ui, rect, (first, last), bar_spacing, |i| mapping.idx_to_x(i)), where the range is inclusive andiis an absolute bar index. Thecellsfield is private; read normalized copies withcells(), construct withneworwith_config, replace history withset_dataand add cells withadd_cell; both keep the cells ordered by bar index, and appending in that order is amortized constant time. (#1286, #1290) -
Volume bubbles follow each bar’s clock slot even when the feed stamps bars inside their intervals. Automatic and price-step groups stay on the bar centre; execution and time-window groups measure elapsed time from the slot open, and the first visible bar retains trades before its stamp. (#1285)
-
The layout menu’s Autosave toggle, the trading lines’ order types, take profit and stop loss labels, tick results, tooltips and Buy and Sell button, and the legend’s series and study controls, quote boxes, delayed and end-of-day marks and hints and copied values go through the context’s translator, so one that changes every key reaches them without recreating the chart. The volume tag on the price scale takes the applied theme’s rising or falling candle colour for the last bar instead of a fixed pink, marker outlines take the theme’s crosshair label text colour, and event break lines its info colour, so a custom palette reaches them; a marker’s own colour is unchanged. (#1059)
-
TPO charts and studies index cached profiles by session once per frame, so zoomed-out daily views no longer search and shift the entire cache for every session. Context-menu hit testing shares the same cache; profile reuse, session splits, composites and retention limits are unchanged. The frame benchmark and instruction regression check cover 400 and 1,600 daily sessions. (#1270)
-
A footprint built from the feed’s trades drops the contribution of each trade the bounded store evicts, summing the bar that lost trades again from those held so its delta high and low agree with them, and keeps at most 5,000 bars and 50,000 price rows, the oldest bars first.
Footprint::complete_fromgives the open of the oldest bar whose executions are all held; bars before it, cut by eviction or the budget, are drawn as candles instead of as complete footprint bars. (#1114) -
ADX shows +DI and -DI as soon as their period is full, and Stochastic and Stochastic RSI show %K while %D is still warming up. Each line starts where its own definition first gives a value; the slower line’s start is unchanged. Technical Ratings includes its default Stochastic vote two bars earlier. Reference rows, including short histories, follow independent rational calculations of those definitions. Migration: on those warm-up bars ADX rows are
Multiple([NaN, +DI, -DI])and Stochastic and Stochastic RSI rows areMultiple([%K, NaN])where they had no value;value(line, bar)still returnsNonefor the missing line. (#1259) -
Stochastic, Williams %R, Ultimate Oscillator, CCI, ADX, Stochastic RSI, ROC, Bollinger BandWidth and 52 Week High/Low keep their ratios when prices are rescaled below the former absolute zero thresholds. DMI, ADX Breakout, the Commodity Selection Index and Technical Ratings inherit the corrected values. ROC has no value when its previous close is exactly zero. VWAP, Anchored VWAP and VWAP Auto Anchored use every nonzero volume sum, including tiny volumes. (#1257)
-
Money Flow Index returns the neutral 50 when a window has no flow, including flat prices and zero volume, and keeps its ratios at small price scales. Flow magnitude uses the absolute typical price so negative prices retain the direction of their change. Elder Impulse reports bearish only when both its EMA and MACD histogram fall; unchanged inputs are neutral. (#1258)
-
Fixed range and anchored volume profile drawings use the executions of
ChartView::executionswhen they hold any in the selected bars:Footprint::profilesums the bars from the first anchor to the last, each price row shows its buy, sell and unclassified volume as executed, and the POC and value area followFootprintBar, so they equal the public exact profile and follow the anchors and any new trades.VolumeProfile::source(ProfileSource) tells an estimate from bars, labelled “Estimated from bars” on the chart, from executions, labelled “Partial executions” when none are held from the span’s first bar, andDrawing::volume_profile_ofreturns the profile a drawing shows. Executed profiles use the footprint’s price rows, so the drawing’s row count and row size apply to estimates only; its value area and display settings apply to both. The split display paints unclassified volume apart instead of as sell volume. The chart supplies the executions it holds while its chart type is the volume footprint or the session volume profile. Migration:ChartViewliterals addexecutions: None. (#1070) -
TPO charts highlight the rows touched by a single period behind their letters when
TPOConfig::show_single_printsis on, asChartTypeParams::tpo_single_prints(the series settings Symbol tab’s Single prints and the Time Price Opportunity study’s Single prints input) sets it, and hovering one names its price. The highlight colour isTpoRenderConfig::single_print_color. Turning it off leaves the letters, POC, value area and initial balance as they were. Migration:ChartTypeParamsliterals addtpo_single_prints: true. (#1113) -
Price scale labels that sit closer than a label is high, such as price lines, order and position lines, the previous close and the values of one study, stack in the order of their prices instead of in the order they were added, centred on where they wanted to be. The last price, extended session and volume labels keep their place, and labels further apart keep their exact positions. (#1172)
-
Long and short position tools keep their target and stop labels inside the plot: a label that would pass the right edge flips to the inner side of the line’s end, and placement elsewhere is unchanged. (#1171)
-
The upside and downside Tasuki gap patterns need the third candle to open strictly inside the second candle’s body and close strictly inside the gap, so an open outside the body, a close on either gap edge or a closed gap is no longer marked. (#1083)
-
A deselected rectangle draws its border, fill and label only. Its centre guides and size labels appear while it is selected or being drawn, and its corner dots, which duplicated the selection handles, are gone. (#1169)
-
Footprint cells and statistics columns at the edges of the plot show complete numbers or none; a number the plot edge would cut is left out. (#1170)
-
The magnet crosshair also snaps to the visible outputs of studies on shared, independent and unlabelled scales and to the values of visible comparison series, each converted through its own scale. Hidden, missing and non-finite values are skipped, and an equal distance keeps the bar’s own price first, then studies, then series. (#1107)
-
ChartLayoutcrosshair sync forwards the source chart’s main-pane price with its time, so synchronized charts show the horizontal line and price label at the same price. Over volume or an indicator pane only the time is shared, and both clear when the pointer leaves. (#1108) -
Chart undo covers a user’s symbol navigation and comparison edits.
Chart::set_symbolcalled insideChart::user_actionno longer clears history: undo and redo restore the symbol, interval and viewport and reload the feed for it, dropping answers still owed for the other symbol, and earlier steps stay with their own symbol’s drawings. Adding, removing, restyling, hiding, reordering and rescaling an added series or comparison are undo steps that keep itsSeriesId, scale assignment and removed bars. The demo records its symbol switches this way, so they keep earlier edits, and after undo and redo its symbol, synthetic feed, watchlist and session controls follow the chart: the restored bars reload and replay stops without recording another step. A symbol change outsideuser_actionstill clears history. Comparison data stays with the host: afterChart::take_history_changed, compareChart::serieswith the host’s own subscriptions bySeriesIdto restart or stop them. (#1053, #1352) -
Linked drawings in
ChartLayoutinclude study panes:Chart::linked_panemaps a study pane to the pane of another chart holding the same studies (equal names and inputs, then by order among identical panes), and drawings follow their timestamps into the mapped pane. Linked edits, unlocks and deletions now reach locked copies, so unlocking or deleting a drawing no longer leaves a locked copy in the other charts; direct edits of a locked drawing still meet its lock. (#1067) -
A typed comma opens interval entry, empty and under the same focus and text-field rules as a leading digit, instead of symbol search. In a multi-chart
ChartLayout, Alt+Enter shows the focused tile alone and a second press restores the preset with every slot, viewport and synchronization group unchanged, and a lone chart still hands the shortcut to the host. Double-clicking a study pane maximizes or restores it like its button; study settings stay on the legend button and the context menu. (#1066) -
The saved scale font size, axis line colour and pane button visibility apply:
ChartConfig::axis_font_sizesizes the price and time axis labels, the line colour draws the border of the main, added-series and study-pane price axes and the time axis, andChartConfig::pane_buttonsshows the pane maximize and menu buttons always, on hover or never, in maximized panes too. The settings dialog gains Lines, Font size and Pane buttons controls, and all three read back from the chart and survive snapshots and undo.ChartConfig::left_axis_scale_modesets the main scale when the left axis carries it, asright_axis_scale_modedoes on the right. Study pane menu buttons now show on hover by default, like the setting says. Migration:ChartConfigliterals addaxis_font_size: Noneandpane_buttons: NavigationButtons::OnHoveror use defaults. (#1060) -
During replay, studies that request another symbol or interval read only the bars their history completed by the replay cursor, so the chart’s unfinished bar no longer shows the closing value of the other history’s bar in the same slot; that slot has no value until its bar closes. Moving the cursor in either direction recalculates those studies, and leaving replay restores the full histories. Studies that read the bars alone, such as ATR and ADX, offer the Interval and Wait for interval close inputs as single-source studies do, with their own inputs unchanged; studies that request data of their own or read trades do not. (#1049)
-
The study Style tab lists every plot type, step line, histogram, columns, area, circles, crosses, triangles, bar colour and background colour, instead of line, histogram and circles. A type that cannot be drawn for the study stays visible but disabled with the reason in its tooltip: bar colour for a study outside the price chart, and the zero-based histogram, columns and area on the price scale; a saved choice is never removed.
PlotType::ALL,PlotType::nameandPlotType::incompatibilityexpose the list, the labels and the rule. New Net Volume studies draw columns, and new PPO and PVO studies draw their oscillator and signal as lines and their difference as columns; styles already saved keep their plot types. (#1082) -
Chart::restorekeeps the colours the user edited and lets the others follow the active theme, so a layout saved under a light theme no longer opens with a light chart under a dark one.ChartSnapshot::paletterecords the colours the configuration followed; layouts saved without it are compared with the built-in light and dark themes. Migration:ChartSnapshotliterals addpalette: None. (#1163) -
The triangle pattern draws both boundaries through its zigzag anchors, runs them on to the apex where they meet and fills between them up to it, instead of closing the anchors as one polygon. Boundaries that are parallel, diverge or meet before the first anchor stop at the last anchor, and a far apex is cut at the chart’s edge. (#1111)
-
Kagi lines change thickness where a continuing line crosses the prior shoulder or waist and are painted in two parts there, instead of only at reversals.
ChartTypeStyles::kagisets the thick and thin stroke widths, 2.5 and 1.5 points by default, which the series settings Symbol tab edits and which serialize with the chart type settings. Migration:KagiLineliterals addcrossing: None;ChartTypeStylesliterals addkagior use defaults. (#1061) -
RSI divergence pivots and divergences treat RSI values within 1e-9 as equal, so a flat bar, which leaves the RSI unchanged, no longer makes a tie between neighbouring pivots depend on floating-point rounding. (#1089)
-
RSI, Connors RSI and the RSI divergence study compute
100 * gain / (gain + loss)from Wilder’s averages, with no absolute loss floor, so rescaling the prices leaves the values unchanged. A window with no loss is 100, one with no gain is 0, and a fully flat window is 50, for the price and streak components of Connors RSI alike. (#1089) -
Value tags and legend values of added series use their own price scale’s decimals instead of a fixed two, while a host formatter set for the series still writes them. (#1064)
-
Volume candle bodies are as wide as the bar’s volume over the largest visible volume, with no hidden minimum: a zero or missing volume draws a body as thin as the wick, and without any visible volume every body keeps the full width. (#1104)
-
The demo page declares the project icon, so the tab shows it and no favicon request fails. The module preload no longer carries an integrity attribute, which browsers ignore for that destination and warn about. (#1044)
-
Range charts build their bars from the executions the feed supplied, in order with their timestamps and volume and with the incomplete last bar, so two execution paths with the same open, high, low and close show their own bars. History pages, corrections, live trades and the replay cursor rebuild them. Charts without executions keep the approximation from the bars’ open, high, low and close, and
Chart::range_bar_sourcereports which one is shown asmodel::RangeBarSource. (#1105) -
Drawing::alert_levelsresolves a sloping line as the drawing is painted: straight on the price axis, so it follows the geometric mean on a logarithmic scale, and gives no price for a vertical line or a non-positive price there. Parallel and disjoint channels return their base line and second line, and a flat top/bottom its trend line and flat line, as levels 0 and 1 under stable alert sources. Migration:Drawing::alert_levelstakes the chart’sPriceScaleModeas a second argument. (#1048) -
The Elliott impulse projects its 1.618 wave 3 target from the wave 2 end by the wave 1 price leg, rising or falling with wave 1 and unchanged by zoom;
fib_config.logarithmicprojects the leg’s log return instead. The Elliott triangle collects an origin and waves A to E, labelled 0 and A to E, with the fill, trendlines and handles on A to E. Migration:DrawingToolType::ElliottTriangleneeds and requires 6 anchors, and a triangle saved with 5 loads as a skipped drawing (Elliott Triangle needs 6 anchors, has 5) inDrawingStorage::from_json’s result rather than gaining an invented origin; redraw it. (#1068) -
Three drives labels each correction’s retracement of the drive before it and each drive’s extension of the correction before it, measured in price, and omits a ratio over a zero-length leg. The reversal zone is the price interval 1.272 to 1.618 second-correction lengths beyond the correction’s end, painted through the active price scale, in place of a fixed-size badge. (#1071)
-
Fibonacci retracement and extension fills span the same horizontal bounds as their level lines and hit regions. Channel levels extended left or right run on to the visible pane edge on that side and keep the anchor on a side that is not extended. (#1069)
-
Returning demo visitors follow the system appearance, including live changes, until they pick a theme. Palettes saved automatically by earlier releases are ignored without discarding other settings; new choices persist in the app and on the loading page. (#1043)
-
The interval toolbar starts without favourites and shows one button for the current interval. Starred intervals appear in menu order, followed by the last selected non-favourite and an icon-only menu trigger, without repeating an interval. Selecting a favourite retains the non-favourite button. Toolbar buttons abbreviate one day, week and month to
D,WandM. (#1041) -
Box zoom uses a faint fill and visible border from the active theme’s info colour, with unmultiplied alpha. Its handles and dimension labels follow the theme. (#608)
-
CurrencyFormatter::eur()writes1.234,56 €for1234.56. Matching thousands and decimal separators omit grouping. Migration:CurrencyFormatterliterals adddecimal_sep(','for EUR,'.'for USD, BTC and custom currencies), or use a constructor. (#676) -
The price axis menu offers Scale price chart only, and the quick setting applies
ChartConfig::scale_price_chart_only. It excludes overlay studies and their primitives from the main price range without hiding them; turning it off restores their individual autoscale participation. Other scales keep their own ranges. Saved configurations without the option default to including studies. (#964) -
Changing symbols returns the main price scale to autoscaling, clears its price-to-bar ratio lock and discards the previous symbol’s zoom history, so prices outside a manually fixed range remain visible. Repeating the symbol or replacing or reloading its data keeps manual scaling. Initial ratio-lock settings are preserved. (#955)
-
Maximized indicator panes keep plot dragging, wheel and pinch zoom, axis scaling and reset, clicks and drawing placement. Crosshair positions reach host readouts in either pane order. Restoring the layout retains the shared time position and zoom without moving the hidden price pane’s manual range. (#1030)
-
The demo follows the system light or dark appearance at startup and live until a theme is explicitly selected. Explicit choices remain saved between sessions, and the web loading screen uses the same saved choice or system appearance before the app starts. (#1032)
-
Drawing sync notifications coalesce repeated saves and updates per drawing, and automatic storage disables them, so the queue no longer grows with every edit. Migration: hosts consuming both paths call
chart.drawings_mut().set_sync_enabled(true)afterChart::set_storage. (#948) -
Saving an alert with unchanged expiry fields preserves its exact saved instant, including seconds and the later occurrence of a repeated local time when clocks go back. Edited date/time fields still resolve in the explicit entry zone and validate before saving. (#981)
-
Session volume profiles keep their histogram visible when the session opens before the viewport, retaining the whole session’s executed volumes and their proportions. (#967)
-
Broker comparisons keep long names on one line and values inside their columns, with full text available on hover, so host-supplied descriptions cannot overlap other brokers or misalign their Connect buttons. (#1003)
-
Financial views keep their return button visible and their tabs, chart and table scrollable in narrow or short windows. Long row names, period labels and figures stay inside their columns. Charts retain period labels for zero-only and unavailable rows, treat non-finite host values as unavailable and scale finite gains and losses without overflowing their range. (#1002)
-
Symbol search opens at 840 by 680 points, centred and constrained to the window, with 32-point rows and wrapping categories.
Instrument::logoandexchange_logosupply marks with text fallbacks. Search and Compare share 20-point corners and a light backdrop near #F1F1F1 over white; dark themes retain their overlay.Modal::backdropallows a host override. (#998, #1012) -
Quick search opens with an empty, focused query and an instruction to type. Commands are listed, and the best match highlighted, only once the query matches them; Enter still runs the highlighted match. (#1000)
-
Study appearance and input edits keep settings snapshots in chart undo history instead of copying calculated columns. Undo and redo restore the saved inputs and presentation and recompute against current data; removed studies retain their original implementation. (#944)
-
Drawing sync notifications coalesce per drawing and overflow after 1,024 actions into
DrawingSyncAction::ResyncRequired. Hosts replace their stored set with the manager’s saveable drawings, deleting absent records. Automatic storage disables notifications. Migration: hosts consuming both paths callchart.drawings_mut().set_sync_enabled(true)afterChart::set_storage; enabling requests a full replacement. (#948) -
Drawing autosave retains failed documents until storage acknowledges them, retries after one second of input time, and keeps the latest edits through delayed writes and symbol changes.
Chart::flush_stored_drawingsretries immediately and reports whether captured edits are acknowledged; storage remains host-owned. (#942) -
Starred intervals appear in the top toolbar as one-click buttons after the interval menu, in the menu’s order, with the current interval’s button pressed. Unstarring an interval removes its button, and intervals the source cannot serve are left out. (#973)
-
Table, post and idea drawings follow the active surface and text colours in both themes. Ghost feed labels keep readable text while the path fades. Image states, empty content prompts and ghost labels use the host translation lookup. (#984, #985, #986)
-
Table editors keep their cells and wrapping row and column controls within narrow panes by scrolling them together. (#984)
-
Drawing alert sources escape
%and#in stored drawing identities, keeping a drawing such asa#1distinct from level 1 of drawinga. Migration: regenerate saved alert sources containing those identity characters withDrawing::alert_source; numeric identities are unchanged. (#980) -
The demo loads image drawing addresses over HTTP and HTTPS as well as native files, so image input works in browser builds. The host still supplies image storage and access. (#985)
-
Drawing-menu alerts start on the first visible Fibonacci level even when level zero is hidden; drawings with no visible levels offer no alert. (#980)
-
The demo plays selected local execution and alert sounds with independent volume and mute controls. Test sound previews the selected tone and enables browser audio; playback failures are reported.
TradingSettingsliterals addexecution_sound_volume;AlertsSettingsliterals addplay_sound,soundandsound_volume, or use..Default::default(). Saved settings default the new fields. Native demo builds require a C++ compiler and CMake for the audio backend. External notification delivery remains host-owned. (#982) -
Demo alerts retain independent live symbol sources and their creation interval across symbol changes and replay. Watchlist members have separate occurrence state and log their actual triggering symbol through
AlertEvent::TriggeredForSymbol. Editing source references refreshes the retained study definitions without changing the alert’s clock or session; expiry also works with an empty watchlist. Monitoring lasts while the demo runs; durable evaluation, market feeds and remote delivery remain host-owned. (#961) -
The demo saves comparison symbols and arithmetic spreads, including styles, visibility, pane positions and price scales, beside each layout’s chart snapshots, and recreates their synthetic feed bindings on restore. Save As, rename and autosave retain these definitions; older layouts open without comparisons. (#960)
-
Chart settings use the active representation’s Symbol controls for line styles, area and baseline fills, and price-based construction inputs. The demo’s top gear, price-axis gear, main-series menu and main-series double-click open the same seven-tab dialog with current values.
ChartSettingsStateliterals addchart_type,chart_type_paramsandprice_source, or use..Default::default(); older saved settings retain the chart’s existing parameters.SettingsAction::ApplycarriesBox<ChartSettingsState>; dereference it when passing settings to an owned setter. (#965, #966) -
The demo selects Range bars with a range interval and sizes them in instrument ticks. Copy price writes the selected price to the clipboard at instrument precision. Fresh sessions start with both crosshair strokes; saved cursor choices are retained. (#968, #969, #970)
-
Built-in studies, including KST, Ichimoku and Parabolic SAR, update changed bars and appends without recalculating unaffected history. Retrospective studies refresh affected pivots, legs and calendar periods. Migration: direct callers of
Indicator::update_datamust passfrom = 0when a requested history changes; nonzerofromreuses requested histories. The chart supplies this invalidation. (#946) -
Point and Figure columns retain their price endpoints and saturate inclusive box counts at
usize::MAXrather than overflowing, including on 32-bit targets.PnfColumn::boxesrejects invalid geometry or expansion above two million boxes and reports allocation failures. Migration:boxes()now returnsResult<Vec<f64>, String>; handle the error before using the prices, or use the column endpoints without expanding. (#943) -
Cached Renko and range chart updates apply the same two-million-size work bound as fresh builds, reseeding after an excessive price move and resuming from that price on later bars. Whitespace does not bypass the bound. (#941)
-
Custom intervals retain positive week and calendar-month counts, with 3, 6 and 12 month presets. Bar boundaries follow the configured calendar timezone, so April 15 belongs to the quarter opening on April 1; session closes and strategy comparisons also retain calendar months. Month durations remain approximate for sizing, and previously saved
Custom(seconds)intervals keep their fixed-duration meaning. (#963) -
The drawing rail optically sizes its trend, Fibonacci and ruler glyphs within their existing button slots. Default light ink is black; dark and custom theme colours, disabled contrast and selected utility fills are retained. (#1001)
-
The magnet menu independently includes or excludes visible study targets through Snap to indicators, preserving OHLC, drawing anchors and the chosen magnet strength.
DrawingToolbarAction::SetSnapToIndicatorscarries the host preference; toolbar snapshots retain it and the demo applies it. Migration:DrawingManagerOptions,ToolbarStateandDrawingToolbarDomainStateliterals addsnap_to_indicators: true(or use defaults where available);MagnetButton::show_submenutakes that preference as its fourth argument. (#979) -
Position drawings size risk in lots using point value and lot size, round down to a configured quantity step, display its precision, convert profit and loss, and report required capital using leverage. Both position Inputs tabs expose the economics; saved drawings and defaults retain them, and older drawings keep unit sizing. Summaries wrap inside the chart, retain compact quantities at extreme magnitudes and disappear when panned out of view. Migration:
Drawingliterals addposition_sizing: PositionSizing::default()or useDrawing::new; hosts supply point values and lot conventions in the account currency. (#959) -
Two-point drawings accept successive primary clicks with a live preview as well as dragging; secondary drags leave the preview unfinished. Drag and freehand anchors retain the original press, including its snapping, and freehand strokes include the first movement and release. Holding Shift constrains rectangle previews and completed drawings to a square in screen points. Escape cancels unfinished placement. Existing interaction-mode queries and placement cursor feedback are retained. (#956, #957, #958)
-
Notifications default to the bottom-left corner with a 16-point inset. The demo fits notices beside the order ticket and hides them while no room remains; trading notices respect the configured width. Hosts can still select any corner with
NotificationPanel::position. (#1009) -
Held values show six base rows: time, open, high, low, close and total volume. Change remains in hover readouts. Volume study plots are opt-in through
TooltipOptions::show_volume_details; other study values and host data windows retain their existing rows. Older saved tooltip options default to hiding volume details. (#1008) -
Selecting a report trade in the demo restores the session used by its backtest after switching symbols, so the selected trade remains visible without changing the report scope.
-
The registry documentation guards its built-in study example with the
studiesfeature, so the documented headless configuration compiles every example. CI also runs doctests with no default features. (#951) -
Restoring a layout rejects main or pane scales requesting more than 1,000 tick marks before changing the chart. Direct tick generation caps the limit at 1,000, and built-in numeric formatters cap precision at 324 places even when fields are set directly, preventing overflow and formatting panics. Migration: lower saved
tick_marks.max_marksvalues above 1,000 before restoring; formatter precisions above 324 now produce at most 324 decimal places. (#947) -
Bar CSV/JSON imports and exports and
Chart::export_csvreturn errors withSend + Syncbounds, allowing results and original error values to cross worker-thread boundaries. Migration: update explicitly typed results, function pointers and error adapters fromBox<dyn std::error::Error>toBox<dyn std::error::Error + Send + Sync>. (#950) -
Session range lookup clips its final one-minute check to the requested end and uses checked timestamp addition, so sub-minute ranges do not report a later break and ranges at the maximum UTC timestamp do not panic. Empty and reversed ranges remain empty. (#953)
-
The example dependency locks replace yanked
clipboard-win5.4.1 with 5.4.3. CI checks advisories as well as licences and duplicate versions, rejecting yanked packages. Three unmaintained standalone D-Bus packages required by the egui 0.37 accessibility backend have explicit maintenance exceptions pending its migration to zbus 6; these are development/example dependencies and have no patched standalone releases. (#952) -
Numeric formatters omit the minus sign for negative zero and values that round to zero at their displayed precision. Currency amounts such as -0.001 dollars read
$0.00; price, volume and study labels follow the same rule, while percentage changes retain their positive-zero convention. (#938) -
CurrencyFormatterputs the minus sign of a negative amount before a leading currency symbol and no longer groups it: -123.45 in dollars reads-$123.45and -123456 reads-$123,456.00, where they read$-,123.45and$-,123,456.00. (#607) -
Selecting a drawing in the object tree reveals offscreen anchors by panning while keeping zoom and the price scale’s auto/manual state. Double-click and Zoom to object use the same navigation instead of fitting a manual range to one drawing.
Chart::reset_chart_viewrestores configured bar spacing and right margin, scrolls to the latest bar, cancels pending view motion and returns every price scale in every pane to auto-scaling. Chart-menu, keyboard, navigation-button and demo resets use this method. (#935) -
The command palette consumes Enter in search and Enter or Space on a focused row before returning a command, so a host can open an export dialog without also submitting its empty save path. (#834)
-
The scroll-to-latest button is a theme-aware 28-point double chevron at the bottom right of the main pane, clear of the legend and navigation, with matching paint and hit rectangles, a pointer cursor and “Scroll to the most recent bar” tooltip. Clicking or using the return shortcut animates to the configured right margin without changing zoom. The button is hidden at the live edge and available in history or future whitespace. Custom position, size, text and colours remain supported;
realtime_button_text: Noneselects the icon andColor32::PLACEHOLDERcolours follow the active theme. (#930) -
The study rotation regression checks that every study gets a refresh with both fast and slow recomputes, without assuming an exact count tied to the runner’s speed. (#927)
-
Replay resets clear remote-symbol, alternate-interval and metric study histories, tick-origin bookkeeping, errors and paging state before merging the new position, and invalidate dependent calculations. (#900)
-
Study sources retry recoverable resolve and history failures with exponential backoff capped at 60 seconds, honoring longer rate-limit delays. Retries retain the original page boundary and count, success clears the error, and paused or replaced sources cancel pending recovery. Replies from superseded requests are ignored. (#908)
-
Live subscriptions retain at most 100,000 undrained bar slots independently of raw trade capacity. Overflow evicts the oldest slots, increments
FeedState::rejected_barsand reportsInvalidDatathroughlast_error, asking the host to reload history. Explicit historical execution batches retain their complete output. (#901) -
Time-based streams reject executions older than the last accepted execution, including inside the forming candle and across frame drains, so delayed trades cannot overwrite the chronological close.
aggregate_tradesenforces the same ordering contract. Equal timestamps remain valid and replay seeks reset the watermark. (#903) -
Drawing saves retain the nanosecond remainder after each millisecond, preserving distinct execution-bar anchors when restored immediately, before history loads, through drawing paste or when older placements gain editable controls. Millisecond-only documents remain readable. Migration:
StoredCoordliterals addsubms_ns: 0, or useStoredCoord::newfor millisecond coordinates. (#899) -
Watchlist service pushes and
set_quotereject older timestamps and non-finite required or supplied numeric fields, retaining the last usable quote for the watchlist and host consumers. Equal timestamps can still correct prices. (#904) -
Depth snapshots resolve duplicate tick prices before removing zero sizes, so the last supplied level removes earlier liquidity on either side. (#909)
-
SettingsStore::flushretries unchanged settings after a failed save and confirms them only after a successful acknowledgement. Edits made during a pending save keep the latest choice; repeated failures are reported once until a write succeeds. (#907) -
The account panel keeps the newest 1,000 entries per completed-history category and releases expired order metadata. Active orders, cumulative partial fills and the latest fill per symbol survive eviction; older history remains host-owned. (#902)
-
PaperAccountchecks placement, modification and gap fills against account-wide equity, position margin, working orders and commissions. Refused modifications leave the order intact; reductions and position exits remain available with insufficient funds. Account summaries use the current marks and reserve working-order costs. (#905) -
PaperAccountaccepts only good-till-cancelled orders until session boundaries are available. Migration: direct callers setOrderRequest::time_in_forcetoTimeInForce::GoodTillCancelled. The ticket and confirmed position actions use the broker’s symbol rules, including for positions outside the chart’s symbol. (#906) -
Studies sourced from another study continue refreshing during continuous ticks, within the existing full-recompute budget. (#911)
-
Native trackpad pinches zoom around the pointer and stop tracking and kinetic scrolling. Contact input takes precedence when both are reported, and wheel zoom remains applied once. (#918)
-
Touch panning respects its horizontal and vertical permissions independently of mouse dragging and pinch scaling, including two-finger translation and the transition back to one finger. Price and time axis drags use their own scaling permissions even when plot panning is disabled and retain the gesture after leaving the axis; disabled axis gestures do not pan the plot. (#919, #920)
-
Small pans and anchored zooms retain fractional movement on large histories. Synchronized UTC ranges, added series and pointer actions keep sub-bar precision. Fitting and reading UTC ranges retain double-precision fractional bar spacing and indices at plot edges, avoiding magnified UTC rounding errors inside session gaps after long histories; the synchronization reference table covers one-day ranges inside three-day and 65.5-hour gaps at multiple widths. Scroll offsets retain double precision even far into history. Migration:
ChartMapping::right_offset,IndicatorCoordParams::right_offsetandZoomState::right_offsetare nowf64; convert storedf32values with.into()in struct literals. Existing constructors accept both types, andTimeScale::right_offset_precisereturns the retained offset alongside the legacyf32getter. (#916) -
Main and comparison series use the same ordinary-price fallback when their percentage or indexed reference is zero or unavailable, keeping drawable comparison coordinates finite. (#913)
-
Logarithmic autoscaling filters drawable positive OHLC prices before reducing their extrema, including opens and closes of bars whose lows cross zero, on the main and added series. (#914)
-
Each chart and added series retains its own Heikin Ashi history, so nine or more active histories reuse their transforms on unchanged frames and release them with their owners. Price fitting and painting share those transformed bars, including recursive opens carried across price gaps. Migration for low-level renderer callers: add
heikin_ashi: &cachetoCandleDataContextliterals, retaining onechart::rendering::candles::HeikinAshiCache::default()per series. The widget manages its caches automatically. (#912, #915) -
Automatic price tick labels derive precision from their spacing and use scientific notation beyond eight decimals, so sub-nano prices remain nonzero and distinct on normal and logarithmic axes. Explicit instrument precision is preserved. (#917)
-
A zero right margin keeps the newest candle and its streaming updates in the visible data and price fit, including when the right edge is fixed. Logical ranges include their rightmost bar slot when converted to end-exclusive slices. (#910)
-
Chart panning includes the first movement after a pointer press, so a drag completed in one movement frame moves by its full distance. Headless widget tests check the complete pan, pointer-anchored wheel zoom and finite, bounded frames for empty, single-bar and flat histories. (#245)
-
The indicator list and configuration panel share the dialog’s available width, keeping the Add button visible in narrow windows when selecting a metric or another study. (#547)
-
Scalar rolling sums recover small values after a much larger value leaves the window. (#545)
-
Force Index waits for a complete seed of price changes, including when the whole history is shorter than its period. It shares the SMA-seeded scalar EMA with the other studies. Envelopes, Guppy averages and the percentage oscillators also use the public scalar helpers while retaining their reference values. (#545)
-
Starting or rewinding replay in the demo resets the paper account and reconnects its trading view; forward playback keeps the account.
PaperAccount::set_replay_timetimestamps trading history at each traversed source bar, including skipped bars;Nonerestores the live clock on exit. Resetting the account retains its host-supplied prices and replay clock. Execution marks stay on revealed candles, including partial candles built from finer updates, and hide fills before history or at and beyond the exclusive cutoff. Replay holds no account of its own. (#215) -
Waiting for a higher study interval to close treats the latest chart bar as forming. Its scheduled end no longer confirms a source bar early; historical chart bars retain their close-time alignment. (#175)
-
VWAP uses the chart interval to distinguish intraday exchange sessions from UTC-labelled daily bars, retaining timestamp inference only without an interval. Changing the interval recalculates existing studies. The inferred Daily flag is hidden from inputs; saved legacy values remain accepted and are ignored. Hosts should supply the interval through
Indicator::set_timeframeorChart::set_timeframe. (#672) -
Custom toolbar buttons, drawing controls, tabs, menus, object rows and symbol lists report their accessible names, roles and selected, checked, expanded and disabled states. Dialogs expose their titles, and form rows, drawing and series settings, study inputs and alert fields associate their labels with their controls. The chart exposes a text summary of its symbol, interval, displayed history and latest or hovered OHLCV and study values, including gaps and empty history. Native examples with
uiand the demo enable the screen-reader bridge; widget-only examples opt in with--features widget,eframe/accesskit. Applications usingeframeenable itsaccesskitfeature. (#250, #280) -
Object tree rows use themed chevrons, drawing glyphs, settings and trash icons in place of letter and punctuation placeholders. (#279)
-
The right bar’s screener, hotlists, calendars, news, chats, alerts and object tree use flat dropdowns with thin chevrons and hover-filled text actions. Long dropdown menus scroll to keep every choice reachable in short windows. News and highlights keep the market scope reachable beside long symbols in narrow panels. Screener filters use the shared input style; market rows share the watchlist’s height and hover fill, with right-aligned tabular values. Calendars keep event metadata on one line and actual, forecast and prior in fixed columns, including missing figures. The screener, hotlists and news entries use fresh radar, mountain and feed glyphs. The demo’s Time and sales and Session notes entries appear only with Toggle API samples; hiding them closes an open sample panel and preserves session notes. (#863)
-
Marker text sits on a background in the chart’s colour, so it reads in full over the candles, bars and lines behind it. (#859)
-
A toast’s message wraps short of its close button, so the end of a long message, such as a broker’s reason for rejecting an order, is no longer drawn under the button.
-
A chart with a feed or server time repaints once a second only while its bar countdown is drawn, so a hidden price axis or a last price outside the visible range no longer keeps an idle chart repainting. (#852)
-
The Baseline chart fills both sides of its base without faint lines between neighbouring parts of the path, which a curved line made obvious. (#832)
-
The top toolbar’s layout button shows the cells of the current preset, one cell for a single chart, the matching grid otherwise and a tab strip for tabs, instead of a four-cell grid whatever the layout; each preset’s glyph is an
icons::LAYOUT_*constant. Quick Search has its own magnifier with a lightning bolt (icons::COMMAND_SEARCH), so it no longer repeats the symbol search glyph, and Settings uses a hex nut (icons::SETTINGS_NUT). (#844) -
The series legend’s values follow the title after one regular gap, and its flag and series actions appear after the values only while the pointer is over the row. The plot’s chart layout and overlay study menus appear only while the pointer is over the chart or a menu is open, and no longer draw a button frame at the edge of the plot. (#817)
-
The top toolbar labels Alert and Replay beside their icons, as it does Indicators, and places the chart layout selector at the right, directly before the layout name and Save. The demo lists its host actions in the main menu, so its default strip shows the built-in controls only. (#817)
-
Watchlist text rejects ambiguous symbols, row drags stay within their unsorted list, and long panel titles and values leave controls and neighbouring columns readable. Size filters scroll before they hide the trade tape. The demo keeps active-symbol quotes on the chart session and price basis, clears the tape when changing chart slots or layouts, and exports watchlists to a fixed filename. (#223, #237)
-
Continuous exchange sessions close their final intraday bucket at local midnight, so custom intervals retain their short final bar when resampled. (#97)
-
Higher-interval candles retain their full body and wick range and can be selected by that geometry after moving to a separate pane. (#546)
-
The main menu button of the top toolbar stays at the left edge while the narrow strip scrolls; only the controls after it move. (#810)
-
Icons draw their strokes one logical pixel wide at every icon size, two physical pixels at 2x, with horizontal and vertical segments on the pixel grid, so toolbar, rail and menu icons match the weight of separators and text instead of blurring across two or three pixels. Filled shapes keep their look. The chart installs the icon loader beside egui_extras’ loaders; an app that shows icons without a chart keeps rasterising them with egui_extras’ SVG loader as before. (#816)
-
The top toolbar keeps every control in its original group and order at narrow widths, scrolling horizontally with touch drags and horizontal wheel or trackpad input. The scroll bar and overflow dropdown are removed. A drag beginning on a button scrolls without activating it; taps and keyboard focus keep working, and focused controls scroll into view. (#806)
-
The web demo follows the dynamic viewport with a legacy height fallback, hides its right rail below 600 points with panels reachable from the main menu, and shows layout tabs only when there is more than one layout. Narrow legends show close and change instead of four OHLC fields, reserve space for pane actions, and keep title controls clear of values during hover. Study controls appear on pointer hover, keyboard focus or a touch row selection and dismiss on an outside tap. (#806)
-
Replay reapplies its cutoff on interval changes, includes newly added layout slots while paused, and restores checkpoints from their saved source interval. (#213)
-
Starting a feed reload no longer reports
DataLoadedbefore history arrives. Successful pages and explicit data replacements still notify the host. (#201) -
The basic chart example reserves its click readout above the plot and requests repaint after a host click event, keeping the feedback visible. (#201)
-
Switching between a local chart theme and the host theme retains the chart’s widget ids, keyboard focus and retained UI state. (#202)
-
Host pointer events use every visible magnet target in a merged study pane and retain the volume overlay mapping when a secondary click opens a menu. Volume magnet events report the bar volume rather than the raw pointer value. (#201)
-
Command palette labels and descriptions stay clear of categories and shortcuts in narrow windows. Long text is shortened to fit its column. (#308)
-
Shared comparison scales retain manual bounds when members are hidden, removed or reassigned. Comparison lines remain visible beyond the main history, relative axes retain their units in whitespace, and hidden study axes no longer consume comparison gutters. Removing the main series keeps its feed stopped when playback resumes. Copied layouts remap drawing pane ownership to the copied studies. (#87)
-
Applying drawing templates preserves the target study pane, and saved defaults omit pane ownership. Standalone drawing managers release cached geometry after drawings are deleted. Chart layouts keep study-owned drawings local rather than copying their chart-local study ids into another chart. (#151)
-
The study refresh regression checks one full recompute per frame without assuming measured update costs preserve registration order. Unequal refresh deadlines exercise that order independently of timer precision. (#747)
-
Drawing timestamps survive history replacement, interval changes and streaming inserts, including fractional indices and whitespace outside loaded bars. Undo/redo snapshots and linked charts use the same displayed-bar mapping. Drawings and markers are retained per symbol; switching symbols ends active drags and preserves drawing controls; markers between bars interpolate, with the nearest bar supplying their height. Migration: construct
ChartPointwithnewinstead of struct literals; its editablebar_idxandpricefields remain public. HandleSaveError::UnmappedAnchorin exhaustive matches. Switching symbols or replacing drawings throughload_drawingsclears chart undo history. (#81) -
Recoverable resolve and history failures retry the same request after 1, 2, 4, 8, 16, 32 and then at most every 60 seconds, respecting a longer
RateLimited.retry_after. Permanent failures remain exposed inFeedState::last_errorand stop paging until reload.Chart::reload_feedexplicitly reloads without changing the symbol;Sink::symbols_changedadvancesFeedState::symbol_catalog_revisionfor host search refreshes. Hosts still provide the feed and symbol catalog. (#71) -
Configured right-axis price modes reach
Chart::with_config,update_configand changes throughconfig_mut. A mode change resets manual scale ranges and zoom history; unchanged settings preserve them. Undo restores manual ranges after a mode edit throughconfig_mut. (#86) -
CI builds the separate native demo on Linux, macOS and Windows, tests its controller and starts its Linux window under X11 with a software Vulkan backend. Startup must leave a visible window and survive the first rendered frames. (#282)
-
The demo restores its selected light or dark theme before building the chart and saves the selection through application storage. The existing full theme switch continues to update active and saved chart layouts. (#283)
-
Series settings Reset to defaults uses the active theme’s candle colours, clears custom borders and wicks and retains the selected chart type. Opening and accepting settings continues to preserve the chart’s current colours. (#578)
-
Pane legends identify each visible output with its plot colour. Values below 4.5:1 contrast use a coloured swatch and normal text, retaining the study name and legend controls. (#580)
-
RSI defaults to a two-pixel blue line, a 20% fill between its two grey 4/4 dashed guides and a 138 px pane when space permits. Other pane presets retain their zone fills. Migration:
IndicatorPaneConfigliterals addfill_between_zonesor use..Default::default(). (#726) -
The top toolbar uses a 38 px strip followed by a 4 px gap, measured menu, settings and screenshot glyphs and a leading symbol-search icon. Its dark strip and separators use #0f0f0f and #4a4a4a. Save, quick search, settings, fullscreen and screenshot form the right group; alerts, replay and layouts remain reachable through overflow. Overflow preserves disabled Undo and Redo and the selected Replay state, including when playback stops outside the menu. The demo feed toggle moves into its menu and unsupported Publish and Trade buttons are hidden. (#287)
-
Save and the layout menu create independent session layout copies; export remains an explicit command. Drawing templates and account-dependent orders and positions controls are hidden until the host supplies them. Persistent layouts and trading accounts remain host-owned. (#118)
-
The widget bar centres Help on the adjacent 38 px bottom row in every preset, keeping the section rule above it. (#583)
-
Opening a chart, series or drawing context menu suppresses the crosshair, axis tags and data tooltip on the opening frame as well as while the menu stays open. (#291)
-
Removed the unused
ContextMenuSizingTokens::char_width: context menus measure their laid-out labels and shortcuts, and elide labels to keep the shortcut column clear when a narrow window reduces their width. Migration: removechar_widthfrom token struct literals. (#457) -
Replay transport keys reach the visible replay bar before chart navigation, while dialogs retain keyboard priority. Hosts can call
FloatingReplayControl::shortcutbefore dispatching chart input. The demo checks quick search through full application frames, including text arriving with its opening command. (#113, #523) -
Shortcut dispatch preserves text queued after an opening command, and quick search focuses its input before processing that text. Drawing toolbars defer to the chart’s bindings even when keys are disabled or removed. Binding precedence also applies while a field has focus. Shortcut help wraps within narrow windows, and interval entry uses the shared dialog footer. (#113, #120)
-
A bound character key also consumes its text event, so a restored F binding fits the chart without opening symbol search. Typing
?in a text field edits the field; command search and F1 help remain available there. Opening a host dialog hands subsequent input to it, and typed symbol and interval entry focus their fields before processing queued editing keys. (#113) -
Drawing tool shortcuts use the shared exact-modifier matcher, including when the toolbar is used without a chart. An extra Shift no longer selects a tool bound only with Alt. (#113)
-
Disabling chart keyboard shortcuts retains native arrow-key focus navigation and does not emit chart-focus commands for Tab. Enabled charts continue to keep repeated arrow pans on the chart. (#113)
-
Keyboard defaults now pan one bar, use Ctrl/Cmd+Left/Right for a page and Ctrl/Cmd+Up/Down for zoom, dispatch drawing undo/redo, quick search, study search, drawing tools and scale toggles, and route date, snapshot, clipboard and chart focus commands to the host. Typing opens symbol search or interval entry instead of selecting fixed intervals; 15 enters fifteen minutes. Help shows the supplied map’s bound actions. Migration: exhaustive
KeyboardActionmatches need the new command andDrawingToolarms, and labels/descriptions borrow the action. Reset is Alt+R, date entry Alt+G, snapshot Alt+S, inversion Alt+I, logarithmic Alt+L, percentage Alt+P and help Ctrl/Cmd+/. Unmodified F now starts symbol entry; bindFitContentexplicitly to retain the former F shortcut. Drawing rectangle, text and pitchfork shortcuts no longer overlap these commands; assign custom bindings through the map. (#113) -
The demo drawing toolbar zoom controls arm box zoom and restore its previous view through
Chart::zoom_back, without consuming drawing undo or redo or editing drawing geometry. (#118) -
Drawing bulk removal, hide/show and lock-all are single undo steps. Ordering changes and new cloned drawings also enter the existing drawing history, and bulk undo restores every drawing and its list order while queuing host synchronization for the affected records. Property edits were already recorded. Migration: exhaustive
DrawingCommandmatches need theSnapshotarm. (#108) -
Quick Search finds and executes drawing tools, built-in studies, chart settings and chart actions. The demo builds its entries from the existing tool and study catalogues; Ctrl/Cmd+K, the search button and menu open the same palette. Migration: handle
TopToolbarAction::OpenQuickSearchby opening the command palette; symbol and compare entries still emit their own requests. (#120) -
The demo gives dialogs keyboard input before the chart and replay controls. Escape closes the shortcuts help without changing the drawing selection, armed tool or replay; an open popup keeps the key even when opened during the same frame. (#523)
-
Drawing Delete, Backspace, Escape and completion keys respect keyboard focus and open popups. Editing a text field leaves the selected drawing and armed tool intact; chart Delete still removes the selection and chart Escape cancels it. (#640)
-
Chart and series settings use the same modal, sidebar and action chrome, with object-specific titles, measured label columns, 8 px swatch gaps and readable section headings. Series colours use the shared picker; unavailable visibility and overlay controls are omitted. Shared dialog titles are 14 px, modal surfaces dim the app, and frame headers and footers handle Escape and primary Enter without taking keys from focused controls or popups. (#294, #278)
-
ChartSettingsState::from_chartandapply_to_chartread and apply the dialog’s display controls in the library, including background gradients, crosshair styling, precision, watermark, navigation, status, scale and margin settings. Invalid timezone, margins or crosshair width leave the chart unchanged. The demo uses this adapter and reads back current values; trading and events remain host-managed; alert visibility, labels and colour control the demo overlay and survive reopening settings. Main-series line settings now apply and read back. (#114) -
Vertical grid lines retain their own colour through
ChartConfig::vertical_grid_color;Nonefollowsgrid_color.show_gridnow gates both grid directions. Migration:ChartConfigliterals addvertical_grid_color: Noneor use..Default::default(); setshow_grid = truebefore selecting individual horizontal and vertical visibility flags. -
Symbol search opens near the top third with 32 px result rows, 13/11 px symbol and description text, trailing exchange/type columns and spaced keyboard hints. Comparison searches the same host catalogue. The demo adds timestamp-aligned close-price overlays from independent synthetic feeds, removes and hides them, and keeps their membership with each chart and saved layout. Add, remove and visibility actions leave the public
compared_symbolslist untouched until the host accepts them. Migration: updatecompared_symbolsafter handling an accepted intent. (#296, #117) -
Vertical-only grid settings edit the visible grid colour. Fractional margins retain their text when settings reopen, and an edited right margin survives live updates. Settings controls inherit the shared checkbox, combo and sidebar styling; series candle colours are paired. Remove the ineffective panel-layout control and unused picker state. Migration: use
SettingsDialog::openinstead of the removedopen_with_layout,set_layout_styleandlayout_stylemethods. (#114, #293, #294) -
Series settings remove the placeholder Alerts, Trading and Events tabs. General settings remove inactive Trading and Events controls; the Alerts controls remain because the demo now applies their visibility, labels and colour to its alert overlay. Migration: remove
SeriesSettingsTab::{Alerts,Trading,Events}andSettingsTab::{Trading,Events}from exhaustive matches. Host-owned trading and event settings data remain available for hosts that implement those surfaces. (#212) -
Active price alerts, including channel boundaries and compound price conditions, have labelled draggable levels through
chart::render_alert_levels; a drag returns a replacement for host submission. The demo applies alert visibility, labels and colour, opens the shared dialog at the latest price and saves hovered-price alerts with Alt+A when the chart owns the hovered point. The existing crosshair add menu remains available. The demo host evaluates its displayed synthetic feed, including consecutive crossings and changed drawing or study outputs while prices are idle, and reports triggers and expiry throughAlerts, so the existing popup and log show them. Evaluation, sound, background watchlists and durable storage remain host-owned. (#210, #211) -
PnlLabel::currencyuses a host-suppliedCurrencyFormatter, retaining sign placement and zero rounding with the instrument currency and decimals. Migration: pass the formatter as the second argument, for examplePnlLabel::currency(value, &CurrencyFormatter::eur()). (#209) -
Crosshairs honour independent line visibility, colours, widths and label visibility, align x with the selected bar, and snap to visible OHLC and study values in magnet mode. The demo magnet menu sets the crosshair mode too. Hovering price, volume or any study pane shares one bar index across all legends and readouts; horizontal cursors use the hovered pane’s scale and precision. Empty-space and synchronized cursors extend through the study panes. Crosshair tags stay inside their axis, including pane edges, with 4 px text padding; clicking the price tag retains the add-at-price intent without a permanent glyph. Pane guides use the theme grid colour, and study legends highlight on hover with visibility, settings and remove controls. Hidden overlay rows retain their show control. Long pane captions leave room for their controls, and floating study readouts fit narrow plots away from the hovered bar. Migration:
Legend::show_with_study_actionsreturnsStudyActioninstead of a settings index;PaneInteractionliterals includevisibility_responseandsettings_response. (#107, #90, #286, #288) -
Button::text_colorchanges a label without tinting its fill or icon. Floating replay uses the shared speed combo, a danger-coloured Exit label on the secondary button and a 28 px hide button. The 32 px bar stays inside an 8 px dock inset and scrolls horizontally when the window is too narrow for its controls. (#302) -
The bottom-bar clock requests a repaint at the next whole second while visible, so it keeps advancing without pointer or feed activity. Hidden clocks schedule no wake-up. (#536)
-
Bottom-bar session and dividend controls show their selected state and describe the current mode. The calendar stays selected while the date picker is open, and range tips use singular interval units in both layouts. Narrow strips shorten the clock to its time, retain the zone in its tooltip and compact the range trigger so session and dividend controls stay visible. (#303)
-
DrawingToolbarDomainStatesnapshots and restores magnet strength, cursor type and eraser state alongside the active drawing tool. The demo synchronises from the chart before every toolbar frame, clearing finished tools and reflecting externally changed modes without retaining a conflicting zoom highlight. Cursor, eraser and drawing picks leave the previous mode immediately. Migration: snapshot literals supplymagnet_type,current_cursor_typeanderaser_mode_enabled; hosts callsync_from_domain_statebefore showing the toolbar. (#519) -
The magnet flyout gives Off, Weak, Strong and OHLC modes action icons alongside their existing current-mode checks. (#290)
-
The floating selection toolbar uses shared icon buttons with accessible action names and the kit’s hover, pressed and focus states. Its frame follows popup fill, border and shadow, and group separators use the full theme stroke. (#468, #587)
-
Synchronized ranges interpolate repeated element timestamps without jumping forward; nearest crosshairs select the first element at a repeated time. (#116)
-
Layout synchronization retains hidden slots, clears stale tab hovers, retries drawings after receiver history loads and repaints mirrored edits. Drawing Delete shortcuts affect only the focused chart. Layout and group inputs stay open while editing, including toolbar overflow, and overlapping popups do not activate the chart underneath. New and copied layouts keep one linked copy of each shared drawing and retain main-series visibility. Layout theme changes use
Chart::set_themefor active and saved charts. The demo preserves custom chart colours when changing slots and applies both endpoints of custom date ranges. (#115) -
Chart::hover_time,set_synced_crosshair_time,visible_time_rangeandapply_synced_time_rangeexchange UTC timestamps instead of local bar indices. Receivers resolve their own bars, sessions, intervals and plot widths; missing crosshair times clear the cursor, and fractional range edges interpolate across gaps. Existing index and spacing methods remain available for local view restoration. (#116) -
Series settings reserve room for their footer and scroll within narrow and short windows. Price-based types omit unsupported border and wick colour controls, and the inactive Template menu is removed. (#562, #633)
-
Baseline dashes keep their spacing across short segments and base crossings. (#562)
-
Renko wicks retain unfinished price moves beyond the last completed brick when the next brick reverses direction. (#633)
-
Resetting series settings keeps the active chart type in the dialog, so its style controls remain visible.
-
Dashed and dotted series retain their pattern when zooming out makes individual segments shorter than one point.
-
The Area chart uses a blue 2 pt line and a vertical fill fading from 45% opacity at the highest visible point to transparent at the plot bottom, behind the volume overlay. Panning and zooming move the gradient with the visible range. (#735)
-
The shared plot insets from #759 now grow the axis column for wide prices, quotes and study tags, retaining an 8 px outer clearance. Pane plots keep the same left and right edges, with no unused left-axis gutter. Width comes from the rendered tags and ticks, including custom price lines, currency headers and panes with hidden value tags, and updates in the same frame. (#579)
-
Price ticks, tags, crosshairs, legends and tooltip readouts derive precision from explicit instrument decimals or its minimum tick, including integer ticks, five-decimal quotes and prices quoted beyond sixteen decimal places. Sub-unit ranges retain their coordinates and axis marks.
instrument_price_precisionexposes the same rule to host readouts.Instrument::with_volume_decimalsapplies volume precision to legends, quote tags and tooltips;DataWindowInfo::with_instrumentapplies both precisions and zero is a price. Prices and absolute change shareDataWindowInfo::price_decimals. Cloned custom formatters retain their closure. Migration:Instrumentliterals needvolume_decimals, or..Instrument::new(symbol);DataWindowInfoliterals needprice_decimalsandvolume_precision, or..Default::default(). (#78) -
Indicator pane ticks use the price axis text colour in every preset, retaining the shared axis font. Their shared tick generator avoids repeated labels at integer precision. (#584)
-
The demo alerts panel shares the panel header and New alert icon button, with a centred empty state and Create alert action. Demo notices use the shared opaque, padded toast component; screenshot completion keeps its saved-path feedback. (#304)
-
Object tree headers use shared icon buttons, the search field and type selector share a 28 px row, and the 11 px footer stays at the panel bottom. The Data Window separates Time and Interval; instrument precision and migration are covered in #78. The demo passes instrument metadata alongside its existing chart-formatted time and previous close. (#301)
-
Object tree rows open native context menus with menu rows, sentence case labels and ellipses. Menus stay within the window and close on Escape or any outside click. Migration:
ObjectTreeStateno longer exposescontext_menu_open,context_menu_pos,context_menu_target,open_context_menuorclose_context_menu; egui owns popup state. (#530) -
Object tree selections use the active theme’s selection fill and text; hover state clears when the pointer leaves a row. Long names end with an ellipsis 4 px before the row buttons, with the full name in the row tooltip. (#529, #532)
-
Object tree shortcuts leave focused widgets and open popups alone, and consume handled keys so a chart cannot also act on them. (#527)
-
The grouped object tree shows data sources above its groups and honours the Data Source filter, so the main series agrees with the flat view and object count. (#526)
-
The demo keeps the right rail selection in step with the open panel, including panels opened from menus and the shortcuts dialog closing.
WidgetBar::active_icondocuments the host synchronisation contract. (#528) -
Chart::set_theme(ctx, theme)updates chart colours and the context theme while retaining data and viewport. Crosshair labels and their add controls use the active theme’s colour pair, rectangle measurements use its axis colour pair, connection and alert statuses follow its semantic colours, and TPO letters retain at least 4.5:1 contrast on both the plot and value-area shading. The settings dialog resolves default background swatches from the theme instead of a fixed dark fill. Explicit crosshair and background colours remain overrides; alert statuses read the active theme directly. Default settings swatches follow runtime theme changes without changing saved values on Cancel. Migration: standalonecrosshair_price_actioncalls pass the resolved label text colour as the final argument. (#275) -
Custom controls draw keyboard focus rings, including object-tree actions, floating controls, layout menus and the Save arrow. Contiguous list rows keep their ring inside the row so neighbouring fills cannot cover it. Toolbars, custom intervals and dialog footers follow visual order under Tab; search and template fields release focus, and Enter activates the focused control. (#277)
-
The colour picker measures its popup bounds after layout, so clicking Hex reaches the custom editor. Custom editing starts from the current colour, Escape is consumed, and closing restores the swatch view. Only selection and hover draw a 2 px ring; swatches close to the popup fill get an inside hairline. Wells, swatches and the custom row show keyboard focus. Migration:
ColorPicker::showreturnsegui::InnerResponse<Option<Color32>>; read.innerfor a picked colour and.responsefor the well. The unusedcolor_picker_btnhelper is removed; useColorPickerwith persistentColorPickerState. (#576, #650, part of #277) -
Autocomplete keeps its popup alive while open and moves selection to the hovered suggestion before drawing any row. Only that row is highlighted, inset with rounded corners, and Enter confirms it. (#592)
-
Auto-height dialogs and modals offer scrolling bodies the current window cap each frame, so they grow with content, shrink again and retain their on-screen header when resized. Dialogs also retain their horizontal margins in narrow windows. The shortcuts dialog uses that cap without its own height workaround. (#641, #652)
-
Egui controls and kit buttons share the 4 px small radius. Focus rings follow each control’s corners and end 2 px outside it; the text cursor uses the theme text colour. Split buttons, sections and
UiExtcombos use the small chevron icons. Migration:styles::focus::draw_focus_ringtakes the control’s radius as its third argument. (#586, #593, #594, #595) -
Command palette highlights are inset from the row edges and use the kit small radius for selected and hovered rows. (#591)
-
Subdued list text and property labels use the weak text colour while values retain the row text colour. Dark weak text reads at 4.5:1 or better on panels and floating windows. (#589)
-
Action list rows are transparent at rest, including disabled rows, with disabled text and icons in the theme colour. Primary and danger rows use the shared opaque hover and pressed shades. (#596)
-
FormRowstarts its controls after the label column with the same horizontal gap and row pitch asFormGrid. (#590) -
Kit filter fields clear on Escape only while focused and consume that key, including immediately after focus moves elsewhere. Autocomplete handles confirmation only from its own field and reports a closed popup after a pick. The clear control uses the kit icon button with hover, pressed and keyboard states. (#588, #592)
-
Selected indicator rows take both their fill and text from
IndicatorDialogConfig, including when the configuration was frozen from another theme. The default follows the active selection pair. Migration: addsel_text_colorto configuration literals or use..Default::default(). (#437) -
Modal dialogs, modal handlers and the command palette read
UiColors::modal_overlayfrom the active theme. Light dialogs dim white panels to 159 rather than 75; high contrast uses its window outline without dimming. Migration: addmodal_overlayto colour literals and saved palettes, or construct colours from a preset. (#585) -
Active widget rail entries use the selection colour pair and show the pressed step when held. Alert counts use
danger_bgwithdanger_textinstead of mixing a status foreground with the badge text. (#387, #531) -
List action buttons and
UiExtprimary, secondary and danger helpers share the kit variants, including opaque themed state shades and their matching text. The dark primary blue now meets 4.5:1 with white. Ghost and Outlined controls use egui’s hover and pressed fills, and neutral button glyphs use the same foreground states across button types. (#435, #582) -
Deserialising incomplete theme colour palettes reports a missing-field error instead of silently filling a light theme with dark colours. Text, spacing and radius scales still default independently. Migration: save the complete
Themevalue; hand-written theme files must includedark,uiandchartwith all colour fields. (#434) -
Links and clickable labels derive a readable colour from the accent on panels and windows.
Theme::with_accentgives black, white and near-endpoint accents distinct opaque hover and pressed shades, a visible selection and a matching light focus ring while retaining text contrast. (#432, #433) -
egui buttons, headers and open combo boxes use the theme’s fills and strokes in every state. Pressed neutral fills differ from hover by at least 1.2:1. Settings controls use control outlines, active settings icons and timeframe labels use readable text, and secondary surfaces retain readable muted and status colours. (#431, #276, #436, #581)
-
The drawing properties dialog in the demo opens with the drawing’s saved style and interval settings, and applies fill, font size and interval visibility through the existing undo and host-update path. The lock-all button derives its state from the current drawings, including locks changed through context menus. Locked drawings reject property and colour edits until unlocked, as well as movement, handle edits, erasing and deletion. (#138, #140, #141)
-
Drawing renderers apply common dash styles, non-default widths and configured fills to their paint primitives, while preserving custom fork levels and position profit/loss colours. Annotation text, tables and icons use the configured font size before sizing their surrounding geometry; the fixed note marker keeps its icon size. Bold adds synthetic weight using the host’s existing font family and fallback glyphs. Line endpoints render all stored marker styles in anchor order, including reversed lines and path tangents. Info lines, angle lines and arrows also honour left/right extensions. Migration: new non-arrow tools default to no endpoint marker; saved endpoint settings now render as stored. Icons use their saved font size instead of a size derived from stroke width. (#141)
-
Drawing selection also follows the clipped shapes emitted by the renderer, including text extents, position zones, data-driven tools, rings and cycle lines. The manager retains the last paint alongside the existing geometric hit tests; standalone interaction hosts can pass paint commands to
DrawingInteraction::hit_test_painted. Moved anchors and edited properties discard stale painted hits. Geometric hits also respect the last paint clip. (#137) -
Strong drawing magnet snaps to the nearest open, high, low or close of the bar under the pointer even outside the weak magnet’s pixel threshold. Weak magnet retains nearby bar, overlay and drawing targets. Both apply during placement and handle drags, and the drawing toolbar passes the selected strength to the chart. Migration:
DrawingManagerOptionsliterals needstrong_magnet, or..Default::default(); set it withmagnet_modefor strong snapping. (#139) -
Drawing bodies, previews, selected handles and eraser highlights are clipped to the price pane and the caller’s clip rectangle. Patterns projected past the pane edge no longer paint across the time axis or other panes. The chart’s separate axis labels keep their own painters. (#653)
-
Selection handles follow the drawing’s visibility on the current interval, so a selected drawing hidden by its interval settings leaves no visible or hittable handles behind. Chart interval synchronization, drawing rendering and hit filtering were already applied. (#140)
-
Selected drawings move from a body grab while retaining the pointer offset. Every anchor follows the same bar and screen-height offset through the price scale, with one undo step and one host update per gesture. Rectangles also have a centre handle, and body grabs suppress chart panning. (#741)
-
The live demo varies execution arrival intensity in clustered bursts and quieter stretches over a daily activity profile, so minute volume varies several-fold. Price steps, tick sizes and trade-size generation retain their seeded sequence; history and streaming use the same timing. (#782)
-
The demo opens at its configured bar spacing even when the first canvas is narrow. Charts defer initial visible-bar and resize calculations while the plot is collapsed, preserving zoom and the right edge when a hidden or tiny canvas becomes visible. Pixel right offsets use the first usable bar spacing, locked resizes retain fractional visible ranges, and explicit visible-bar requests take precedence over a simultaneous resize. (#781)
-
Study selection follows histogram and circle geometry in overlays and panes. The applied-study editor keeps its controls and footer inside narrow and short windows in both themes. (#169)
-
Study output uses
IndicatorValues, one contiguousVec<f64>per output line, with NaN for missing values. Rendering, hit testing, snapping and autoscaling read the columns directly. Migration:Indicator::valuesimplementations return&IndicatorValues; readline(index),columns()orvalue(line, bar)instead of indexing rows.to_rows()explicitly allocates the former owned row format for exports. Custom calculation closures still accept owned rows and their stored results are converted to columns. Numeric definitions and streaming update results are unchanged. (#180) -
KST and RVI use running means of complete windows, STC shares the linear rolling extrema, and RankCorr reuses its sorting buffers and computes Pearson correlation of average ranks for ties. Migration: KST first appears at
max(roc_period + sma_period - 1), with its signalsignal_period - 1bars later; RVI starts at barperiod + 2, its signal atperiod + 5. These indices are zero-based; at default lengths KST starts at 44 and its signal at 52, RVI at 12 and its signal at 15. Incomplete windows no longer produce averages. Callers must handleIndicatorValue::Nonebefore the main line andNaNfor a pending signal, and load enough history before consuming either line. RankCorr values on tied prices follow the rank correlation definition; flat windows have no value. (#179) -
KAMA keeps a running sum of its last
periodabsolute price changes and resumes last-bar updates and appends through the shared study driver. Full calculations are linear in history length and no longer allocate a price window for every bar. Its SMA seed, efficiency ratio, smoothing and handling of non-finite closes are unchanged. (#179) -
Stochastic RSI returns its first value as soon as RSI, stochastic, %K and %D have warmed up, including histories of 32 and 33 bars at the default lengths. (#714)
-
DEMA and TEMA seed each inner exponential average with its own first full window, so constant input stays constant and the warm-up remains
2 * period - 2and3 * period - 3bars. (#713) -
Measurement boxes stay inside the pane when their anchors approach an edge. Gann and trend-time labels omit collisions in small drawings, and harmonic ratio labels move along their comparison chords to avoid anchors.
-
Parallel channel extensions follow chart left and right even when the anchors were placed right to left. Rays retain their direction when panned beyond the pane, and leftward Fibonacci time zones keep their fills. Drawing rail menus use the same available entries as drawing categories.
-
Pitchforks without custom level settings retain the drawing colour and the existing tine width. Fixed Gann grids without custom divisions retain their quarter grid.
-
Three-anchor projections add the first price and bar leg at the third anchor before mapping to screen coordinates, so logarithmic charts preserve the measured move. The target label shows the projected price.
-
Gann grid percentages suppress floating-point tails, the fixed-ratio label sizes to its text, and pitchfan labels sit at the visible ray ends where they have room.
-
Drawing placement collects the construction anchors: three for extensions, trend-based time, wedges, pitchfans, arcs, rotated rectangles, projections and channels; four for triangle patterns; seven for three drives; three and five for double and triple Elliott combinations. Price notes and arrow markers take two points. Positions place entry, target and stop in one click, with independent editable anchors. Extensions project the price leg from the third anchor and trend-based time projects its bar interval there.
-
Rotated rectangles use a sloping base and perpendicular width, Curve has a placed quadratic control, Double curve has two placed cubic controls, arcs pass through a third control, and pitchfan rays pass through Fibonacci fractions of the second-to-third anchor span. Table, Image, X post, Idea and Ghost feed stay loadable but are removed from tool menus until their content is implemented. Migration: new Curve and Double curve placements collect three and four anchors. Older saved placements still load: rotated rectangles gain their axis-aligned corner, double curves gain endpoint controls, wedges and pitchfans gain a boundary at the second time and first price, and one-point notes and markers gain a coincident second anchor. The added controls can be dragged after loading.
-
Fibonacci speed resistance fans include the time fan, ratio grid and quarter arcs in the anchor direction, and selection follows them. A three-anchor Fib wedge draws circular ratio arcs between its two trend rays, using the first trend radius and the signed shorter sweep.
-
Measuring tools count signed ticks and pips from
Instrument::tick_sizeand the new optionalpip_size(with_pip_size). Unknown, non-positive and non-finite sizes are omitted.Chartpasses its host or feed instrument to drawings. Migration:ChartViewliterals setinstrument(Nonewhen unknown);Instrumentliterals setpip_size: Noneor useInstrument::new. -
Gann fans follow the signed anchor direction and retain their steep rays when they leave through the pane’s top or bottom. Fixed Gann squares keep their anchor-defined price-per-bar ratio through zoom.
Drawing::gann(GannConfig) sets independent price and time grid fractions on boxes and squares; levels count from the first anchor. Migration:Drawingstruct literals setgann, or useDrawing::new. Saved grid and pitchfork settings reject non-finite values. -
Inside pitchforks use the first leg midpoint and second anchor as their tines, with the first tine passing through the third anchor and the median halfway between the tines. All fork rays follow their direction, including leftward and vertical forks.
-
ABCD, XABCD and Cypher label every price ratio on its comparison chord, including C’s retracement and D’s placement. Undefined ratios on flat legs are omitted.
-
Session breaks and previous-session closes follow exchange windows and holidays, with chart-zone calendar boundaries when no exchange is supplied.
DailySessionProvidernow honors its configured break time, and its exchange preset follows daylight-saving changes. Migration:DailySessionProviderstruct literals needtime_zoneor..Default::default();newstill takes UTC hours. -
Time-scale clock, seconds and tick visibility flags now reach axis and crosshair rendering, and
ChartBuilder::options_charthides its time axis. Migration:time_visibledefaults totrueto preserve existing labels;falseshows dates alone. -
Floating and tracking tooltip times use the same chart-zone formatter as the crosshair, including daylight-saving changes. Exchange display mode reads the instrument zone when supplied.
Chart::format_timegives host readouts the same format and source-bar precision on every chart type, and the demo Data Window uses it. Floating readouts paint above the legend so their time row remains visible. -
Migration for standalone renderers: pass the chart-zone
TimeFormatterand the bar duration in seconds as the final two arguments torender_tooltip_with_options. Passticks_visiblebeforeslottorender_time_labels;falsepreserves the previous tick-free axis. -
Applying the demo’s time-zone setting updates chart readouts and the bottom clock without resetting pan or zoom. Reopening settings retains the zone selected from either control.
-
Daily axis marks use fixed calendar anchors for two-day and weekly intervals, keeping their dates stable while panning. Month boundaries remain visible between day strides and on the first of the displayed month at medium widths and wide time ranges, including across daylight-saving changes.
-
Horizontal arrow keys keep keyboard focus on the chart and pan on every press. Tab still moves to the next control.
-
Chart::visible_barsnow applies the requested initial bar spacing on the first frame, matchingset_visible_bars. -
Chart settings read back current status and scale controls before opening. Choosing log or percentage scale clears the other mode; legend volume remains independent of the histogram. Custom price-line tags and axis gestures follow left placement, and long session tags stay inside the chart.
-
Enlarged modals fit narrow windows, with scrollable settings content and tabs. Indicator results use a 32 px row pitch.
-
Symbol search gives its category strip and results separate scroll identities, keeps keyboard selection under a stationary pointer and scrolls the selected result into view. (#597)
-
Opening chart settings now reads the chart’s current candle, background and grid colours, so applying display controls preserves its appearance in every preset. (#577)
-
The host Trade and Publish controls now explain their trading-account and chart-export actions on hover, using the shared toolbar tooltip.
-
The interval menu reserves a compact 200 px outer width until the custom form is expanded; the form retains its full input and unit controls.
-
Chart settings opens on Symbol in the shared modal, with a 752 px surface, tab-specific heights, neutral sidebar selection and aligned value columns. Existing tabs retain their controls and template actions; dropdown selection remains readable.
-
The indicator dialog uses an 840 px surface, a 40 px search field, a wider category column and single-line study names. Categories with no provider are omitted from the sidebar; favourite and study configuration actions are retained. Filter fields respect the host interaction height.
-
Quick search uses the shared 480 px modal with a search header and close button. The demo connects its quick-search button and Ctrl/Cmd+K to the existing command palette for symbol search, indicators, settings and export. Shared dialog titles use 20 px text.
-
The compare dialog uses the shared modal frame, a wide search header, a close control and a single list of 56 px symbol rows. Its configured fill remains supported through
Modal::fill. -
Symbol search uses the shared modal frame, a full-width search row with a close button and 56 px result rows. Escape and backdrop dismissal follow the modal; symbol filtering and keyboard selection are preserved. Empty modal titles allow a search row to serve as the header.
-
The Save arrow opens a compact export menu while the label keeps its existing action. Entries requiring hosted layout storage are omitted.
-
Snapshot offers image download in a compact menu beneath its trigger. Opening the menu leaves capture to an explicit download choice.
-
Chart-type menu rows use a single 14 px name beside each icon, neutral selection and separators between type families.
-
The interval menu groups full interval names in 32 px rows with trailing favourite marks and neutral selection, retaining custom interval entry and model selection.
-
Top toolbar tooltips use compact dark surfaces below their controls, with platform-specific shortcut chips for alerts. Symbol, interval and chart-type triggers now identify their actions on hover.
-
The demo opens at one minute in Arrow mode with axis readouts. Synthetic sessions stay continuous, with shorter wicks, varying low ordinary volumes and occasional peaks. Volume peaks use a quarter of the plot height with a flush baseline, and candle bodies use 75% of the bar pitch. Hourly data remains available; session timestamps and adjustment inputs are unchanged.
-
The in-pane legend and held values keep the chart’s configured candle colours. The legend title exposes a flag and copy actions on hover. The Data Window computes change from the preceding displayed element, matching the legend on both time-based and price-based charts.
ChartState::shownexposes the series indexed by hover and selection. -
Time axes use denser calendar marks shared with the vertical grid and semibold day, month and year labels. Round price levels use semibold labels. Minute intervals retain their unit in the toolbar, and interval picks update the trigger and selected row.
-
Dark plot and panels are black, with neutral hover fills quieter than pressed fills. Volume uses muted teal and salmon at the configured theme opacity, and both themes use dotted grids. The demo preserves its rounded chart container.
-
Cursor choices use 40 px rows, larger glyphs, a neutral selected row and a labelled values switch, with visible keyboard focus. Held values use a compact six-row panel. Eraser suppresses the previous cursor’s trail and crosshair strokes.
-
Toolbar controls, including replay, undo and redo, move into overflow before overlapping host actions at narrow widths. Demo Search, Trade and Publish keep their intended order and sizes.
-
Price ticks stay on the supplied decimal precision when zoomed in. Intraday marks survive bars that start between clock boundaries, and daily charts at multi-month zoom use calendar month names and year boundaries. Hover tags remain within narrow viewports.
-
Crosshair price and time tags default to black with white text, use 21 px and 25 px rows, and clamp at both horizontal edges. The price row reserves a 21 px add-action cell for the host to route with
chart::crosshair_price_action. The default crosshair stroke is dotted; explicit colours and line styles remain supported.chart::render_crosshair_fullandRenderContextlet hosts draw the same readout over a combined price and volume viewport. -
Price lines use 4 px dashes with 4 px gaps, and dotted price lines use 1 px dots with 3 px gaps. Drawing line patterns keep their existing lengths. Price tags are about 17 px high at the default axis font size.
-
Intraday time marks use actual session bars and the formatter’s timezone for calendar boundaries, so closed hours and missing weekends take no slots and month labels name the new month. Day labels show the day number.
TimeFormatter::wall_timesupplies calendar fields andformat_crosshairsupplies a hover readout; both have defaults for existing custom formatters. Intraday hover dates include weekday, day, month, short year and time, with fractional seconds preserved through timezone conversion. -
Price ticks, price lines and crosshair price labels use the feed instrument’s
price_decimals, which clears when the feed reloads. Hosts without a feed can setPriceScale::set_price_precision; an unspecified precision keeps at least two decimals on price ticks. Default price marks stay at least 40 px apart. Price tags have square left corners and white text on financial colours, while pale custom fills retain dark text. -
The series legend wraps between whole OHLC fields within its supplied plot bounds, truncates long titles and paints the chart background behind text. The title uses 16 px text and the readout 13 px, with financial colours and 8 px field gaps; wide readouts stay inline.
-
Price and study panes share the available height at a 3 to 1 weight per study, with one 28 point time axis below the lowest pane. A study that would be under 40 points collapses to a 24 point legend row; clicking its title expands or collapses it. Pane plots and selection handles use the main plot’s horizontal bounds and clip to the allocated pane, including after a resize. (#736)
-
The bottom clock converts UTC instants to the named time zone, including daylight-saving offsets, and falls back to UTC digits and a UTC label for unknown names.
-
The bottom bar uses 14 px primary text, measures its labels to align the clock and session controls at the right edge, and keeps range buttons unfilled at rest. Clicking the remembered range requests it again after panning; narrow bars keep all ranges in a menu. The date button has a 24 px icon grid beside a 22 px rule.
-
The top toolbar is 38 px high with larger icons, a filled symbol pill with a semibold ticker, a plain interval and an icon-only chart type trigger. Group rules are 22 px high with compact gaps, and theme and search actions open from the menu.
TopToolbar::show_with_slotsreserves space for a host menu and right-side actions before compacting the built-in controls; alert, indicator and settings actions also move into overflow when a long symbol leaves too little room. -
The demo opens in light with labelled synthetic one-minute candles, volume and one in-pane header; studies remain available on demand. The shell uses 38 px top and 39 px bottom strips, 52 px left and 45 px right rails, 4 px gutters, a 6.1 px opening pitch and a 65 px right margin. Regular and extended sessions and dividend adjustment derive from retained history. Ranges fit displayed timestamps, including replay and narrow windows; date navigation selects an available session. Chart timezone choices update both axis formatting and the bottom clock.
-
The export dialog stays open to show success with the file path or an error, and prevents duplicate requests while an export is pending. The demo reports file write results and offers PNG and CSV downloads in the browser. Image exports capture a frame after closing the dialog and report the result in a notice.
-
Drawing magnet mode snaps placed anchors and dragged handles to nearby OHLC and visible overlay-study values, keeping each value paired with its bar. Targets follow the current pan, zoom and price scale within
DrawingManagerOptions::magnet_distance(15 logical points by default). Hidden overlays and the drawing being dragged are excluded; undo and redo retain the snapped data coordinates. -
Drawing rail icons render on their 24 px grid with simpler Fibonacci, pattern, brush, magnet and keep-drawing details. The cursor family gains a pointer-and-halo icon for demonstration mode.
-
Drawing rail selection uses a neutral fill, distinct from the magnet’s contrasting latched fill. It keeps a 24 px icon grid on a 38 px pitch, with 35 px state fills and primary text ink. Its rules are 36 px wide and light-theme rules use a neutral grey. Drawing templates remain available in the Hide flyout instead of taking a utility row. Keep Drawing shows a pencil and lock, and the visibility menu uses an open eye. The right widget bar defaults to 45 px with 28 px icon grids; hosts should size its outer panel from
WidgetBarConfig::width. Migration:TemplatesButton::showis removed; use the visibility flyout, or renderTemplatesButton::show_submenuin a host menu. -
UiExt::error_label,warning_label,success_labelandinfo_labeluse the active theme’s error, warning, success and info colours instead of fixed colours, so the export dialog’s error message reads at 4.5:1 or better in every preset. -
The interval and chart type menus close on Escape and on a click anywhere outside them, take the theme’s menu frame, and end on a whole row above the window’s edge with a scroll bar shown at rest when they scroll, so every interval and chart type can be reached. Interval codes no longer run into their descriptions, favourite intervals show a star icon instead of an asterisk and the current chart type a check icon instead of a “v”, and every row reports its name, role and selected state to accessibility tools, shows a focus ring and scrolls into view when the arrow keys reach it. (#289)
-
The crosshair of Renko, Kagi, Line Break, Point and Figure and range bar charts writes times to the precision of the bars they are built from, instead of milliseconds for the bricks of one bar or the date alone for elements days apart, and the tooltip and the OHLC header leave out volume on chart types without it. A view of a single bar takes the precision from the bar before it instead of writing seconds.
-
Renko, Kagi, Line Break, Point and Figure and range bar charts are drawn on a time scale of their own. Each brick, line, column or range bar takes one slot at the bar spacing and carries the time of the last bar that built it, so the time axis, the crosshair, the tooltip and the legend describe the element under the pointer. Panning, zooming, following the live edge and fitting the price scale work on the elements, and a few elements sit at the right of the pane as bars do instead of packed against its left edge. A change of chart type keeps the time at the right edge of the view, and a view at the live edge stays there. The time scale starts at the oldest kept element, and a chart with a feed stops asking for older history once older bars would not be drawn.
-
Intraday time axis marks fall on multiples of their interval from midnight UTC, so each midnight shows its date, clock times appear between dates and panning keeps each remaining mark’s time.
-
Cypher labels C as an extension of XA and D as a retracement of XC, both from anchor prices, instead of reusing the XABCD ratios and omitting C. B keeps its retracement of XA.
-
A multi-line study emits
IndicatorValue::Multiplewith one value per line, NaN for a line without a value, on every bar where any line has one, and neverSingle, asIndicatorValuenow documents. TRIX, KST, SMI, RVI, PPO and PVO emittedSinglewith their main line while the signal warmed up, which every renderer drew on all lines, and Fisher Transform, Ehlers Fisher and Center of Gravity did so whenever the trigger or signal was exactly 0, as on a flat series. Their first value has no trigger or signal, since there is no previous value; a later trigger or signal of 0 is drawn. Migration: code matchingSingleon these studies reads the first value ofMultiple; values do not change except the first trigger or signal, which is NaN instead of 0. -
Multi-line studies draw every line they compute.
Indicator::line_cntdefaults to the number ofline_namesinstead of 1, so TRIX, KST, SMI, RVI, Center of Gravity, Fisher Transform and Ehlers Fisher draw their signal or trigger line, Elder Ray its Bear Power, Vortex its VI-, Price Channel its lower and middle lines, Pivot Points its six support and resistance levels and Squeeze Momentum its squeeze flag (1 or 0) in its squeeze-on gray, which becomes its second colour ahead of the negative-momentum red. DMI adds the ADX line of the same length, equal to theADXstudy’s, after +DI and -DI. SuperTrend and Parabolic SAR are drawn as an up and a down trend line in their bullish and bearish colours. The main chart breaks a line at a NaN value as at a bar without one, and draws a run of one point as a dot; pane renderers skip a NaN value. Migration: anIndicatorimplementation that returns moreline_namesthan lines overridesline_cnt.SuperTrendandParabolicSARoutputMultiple(vec![up, down]), with NaN on the line of the other trend, instead ofMultiple(vec![value, direction]), and name their linesUp TrendandDown Trend, without the parameters;DirectionalMovementoutputsMultiple(vec![plus_di, minus_di, adx]), NaN for a line without a value, and reports three lines and colours. -
FloatingSelectionToolbar::showno longer panics when the window is narrower or shorter than the toolbar. On an axis where it does not fit, the toolbar is placed at the window’s left or top edge. -
The indicator dialog starts each study from its own default parameters instead of one length of 14 shared by all, so Bollinger Bands open at 20 and EMA at 12, and it edits the Keltner Channels ATR length and multiplier and the Stochastic %K smoothing, which it fixed at 10, 2.0 and 3.
IndicatorParamsgainskeltner_atr,keltner_multiplierandstoch_smooth; struct literals must set them. -
Price auto-scale fits the visible values of visible overlay studies, every line they draw, together with the visible bars and through the same price transform, and skips values that are not finite. It fitted the bars alone, so a moving average or band outside their range ran off the pane.
Chart::set_indicator_autoscale(id, false)leaves a study out of the fit without hiding it.VolProfileVisibleandVolProfileFixed, whose values are volumes, draw no line. Migration: leave a study out to keep the bars-only range;ChartState::fit_price_scaletakes the studies to fit,std::iter::empty()for the bars alone. -
The time axis does a bounded amount of work for very long time spans and large right offsets, and formats only the labels it shows. Spans of a few hundred years and more show evenly spaced years.
-
TPO profiles add each bar in constant time instead of per row it spans, and a steady frame reuses the profiles of sessions whose bars did not change.
-
A Heikin-Ashi chart no longer recomputes its whole history when the forming bar ticks or a new bar opens: it updates the last bars of the cached transform, and draws the visible bars without copying them.
-
TimeScaleOptions::fix_left_edgeworks: when set, panning, zooming and scrolling stop with the first bar at the left edge of the chart, and when every bar fits the empty space is on the right. It had no effect, so its default is nowfalse, matching how charts already behaved: the view can move up to 100 bars past the first bar. -
Dragging the chart pans the price axis vertically while auto-scale is off, so a range zoomed by hand can be moved to other prices. Dragging used to pan in time only.
-
Price zoom stops at a span of a millionth of the price level on every price scale mode, also for views that cross zero: a percentage view, a logarithmic view of prices near 1, or a spread. It used to take a millionth of the visible bounds, which shrinks with each step across zero, until every price landed on the middle of the pane. Box zoom stops at the same span, and flat data on a logarithmic scale is fitted like flat prices, with margins taken from 1% of the price instead of 1% of its logarithm.
-
Box zoom zooms in time: the bars inside the box fill the chart width, up to
TimeScaleOptions::max_bar_spacing, centred on the box, and a box inside one bar shows that bar across the width. It used to re-centre the view on the box and keep the bar spacing. -
DrawingPropertiesDialogsizes its default frame to its tallest tab and uses the kit footer, with Apply as the only filled button and Delete and Clone as icon buttons, the kit colour picker, and line width swatches with a 1 to 10 px stepper; labels are in sentence case. Escape cancels the dialog and Enter applies it unless an open popup, colour picker or focused field takes the key. -
Percent changes have the sign of the price change when the reference price is negative, as in spreads and some futures: the data window, the symbol header, the floating and tracking tooltips, the OHLC header, the position tools, the forecast tool, the measure tools, the percentage price axis labels and
Bar::change_percentdivide by the magnitude of the reference price, so a rise from -10 to -5 reads +50%. A zero or non-finite reference gives 0%, so the tooltips no longer show an infinite or undefined percentage for an open of 0. Migration:Bar::change_percent,OhlcData::change_percentandDataWindowInfo::change_percentchange sign for a negative reference price. -
Renko, Kagi, Line Break, Point and Figure and range bar charts are built once over the whole history and updated with each new bar, so their bricks, lines and columns no longer change while panning or zooming, and a steady frame no longer recomputes them. Only the newest 10,000 bricks or lines, or 5,000 columns or range bars, are kept.
-
Hollow candles are coloured by the close versus the previous close and filled by the close versus the open; the baseline chart uses a configurable level (a price or a share of the pane height, 50% by default) and splits segments where they cross it; the HLC area fills above the close in the up colour and below it in the down colour; volume candles scale by the largest visible volume whether or not the volume pane is shown.
-
Renko, Kagi, Point and Figure, range bars and Line Break use their own configured size, reversal and line count exactly, at any price level; a size the chart cannot use is reported on the chart instead of being replaced. Point and Figure columns draw each box at its own price instead of a running sum that drifted and stopped after 500 boxes, and a column whose boxes are under 2 px tall is drawn as a line.
-
The time axis no longer panics when a bar is stamped near the end of the representable date range, such as a millisecond timestamp read as seconds or
DateTime::<Utc>::MAX_UTC: times it would extrapolate past the range are left out, andTickMarkGenerator::generate_marksstops at the last mark that fits. -
The alert dialog and the alerts panel accept only a finite price or threshold, a multiplier above 0 and a lookback of at least one bar, keep Create disabled until the form is valid, and the dialog names the field to fix; an indicator alert set to compare with a threshold no longer loses an unreadable one.
-
A magnifier tooltip with a zoom of 0, a NaN or infinite zoom, or a lens larger than the plot no longer freezes or garbles the chart on hover: the zoom is drawn within 0.1 to 100 (NaN as 0.1), the lens is at most as large as the plot’s smaller side, and only the bars on screen are drawn in it.
-
model::to_range_bars_from_ticksandmodel::to_range_bars_from_ohlcleave out a volume that would make a range bar’s volume overflow, so two volumes nearf64::MAXno longer give a range bar an infinite volume that breaks the volume scale. -
The keyboard shortcuts dialog draws each key over its badge instead of under it, sizes itself to its content up to the window height with a scroll bar shown at rest once the list scrolls, lists only the shortcuts the crate handles, adds that the chart keys need the chart focused, and closes on an Escape only when no popup is open and no text field has focus, consuming the key.
-
The go to date picker no longer ignores a date it cannot parse: the field is outlined in the error colour, the line under it gives the expected format, and Go is disabled. In custom range mode Go is disabled until both ends are picked, the line under the field says which end to pick and then shows the range, a range no longer survives switching the mode or reopening the picker, and a typed date and the Today button pick a range end as a click on a day does. (#525)
-
The go to date picker closes when Go or Cancel is pressed. Go moved the chart and left the picker open over it, and Cancel did nothing; only the close button closed it. (#524)
-
IndicatorDialog::with_configkeeps the configuration a caller sets:showno longer replaces it with the theme’s on every frame. Each colour leftColor32::TRANSPARENT, as inIndicatorDialogConfig::default(), follows the theme passed toshow.IndicatorDialogConfig::from_themesets every colour, so a configuration built from it no longer follows a theme change, and it now takesmuted_colorfromtext_secondaryinstead oftext_mutedandsel_colorfromselection_bginstead ofaccent. -
The indicator dialog’s Community category and its Profiles and Patterns tabs list nothing instead of the built-in indicators, since no source supplies those entries yet. Community also hides indicators a host passes to
with_indicators, asIndicatorInfohas no community flag. -
Returning to the live edge (a new bar while following it, tracking mode, the jump-to-latest button and
TimeScale::jump_to_latest) restores the configuredTimeScaleOptions::right_offset, orright_offset_pixelsat the current bar spacing when set, instead of a fixed 2.5 bars; a time axis double-click restores the configured bar spacing before the offset, and a fixed right edge clamps it. -
Overlay study lines walk only the values of the visible bars each frame instead of every value from the first bar, so their drawing cost follows the visible bars, not the length of the history (about 26.3M to 4.3M instructions per frame for SMA and EMA on 1,000,000 bars).
-
Volume bubbles draw as one mesh, each circle with as many sides as its radius needs to stay within a quarter of a pixel of round, instead of a filled circle and an outline shape per bubble, and the mesh reuses its memory from frame to frame. With 100,000 trades over 1,667 one-minute bars at 40 price levels a bar and 200 bars in view on a 1440 by 900 window, a frame tessellates 0.49 million vertices instead of 1.85 million and takes 13 ms instead of 33 ms, tessellation included;
cargo bench --bench frame_time -- bubblesmeasures it. (#694) -
Drawings that paint within a known reach of their anchors, such as shapes, patterns, Elliott waves and lines that are not extended, are skipped when that reach lies outside the pane’s time range, and the manager tracks last frame’s paints in time linear in the drawings instead of quadratic. The sine line draws its wave as one path instead of 200 line segments, and the circles of every drawing, such as anchor dots, wave labels and Fibonacci circles, become polygons with as many sides as their radius needs to stay within a quarter of a pixel of round instead of 32 to 128. With 500 drawings, every tool in turn, on a chart of 10,000 bars, a frame takes 15 to 17 ms instead of 17 to 21 ms when all are in view, at 364,000 vertices instead of 463,000, and 3.6 to 4.2 ms instead of 5.2 to 8.7 ms when they are spread across the history;
cargo bench --bench frame_time -- "500 drawings"measures it. (#155) -
A drawing that paints the same geometry as on the frame before reuses that frame’s tessellation: each run of lines, paths and fills becomes one mesh, tessellated once and kept until the drawing, the view, the scale or the tessellation options change, while its text and small discs are painted as before. Drawings are now also skipped when their reach lies above or below the pane, except tools that paint at prices from the bars or run a leg on past an anchor. Line segments that continue one another become one path for every line style, not only dashed ones, which halves the vertices of arcs drawn as chained segments, and the half circles of time cycles and speed resistance arcs get as many sides as their radius needs to stay within a quarter of a pixel of round instead of 32. A Fibonacci wedge tessellates 2,088 vertices instead of 3,600 and speed resistance arcs 424 instead of 1,652. With 500 drawings, every tool in turn, all in view on a chart of 10,000 bars, a frame tessellates 327,000 vertices instead of 362,000 and takes about 20 ms instead of 26 ms on a loaded machine, tessellation 12 ms instead of 19 ms;
cargo bench --bench frame_time -- "500 drawings"measures it. (#155) -
to_renko_bricks,to_kagi_lines,to_pnf_columnsandto_range_bars_from_ohlcbuild with the size they are given, at any price level, instead of raising it to a share of the price range of the bars (a 200th, a 500th for Kagi and Point and Figure) or to 0.0001, and range bars no longer stop splitting a bar after 100 steps. A size that is not a positive finite number, or a Point and Figure reversal of 0 boxes, gives no elements. Renko and range bars start from a later bar when the bars move by more than two million sizes. Migration: pass the size to draw; the former behaviour wassize.max((max_high - min_low) / 200.0)for Renko and range bars and/ 500.0for Kagi and Point and Figure. -
A Line Break reversal line now starts at the open of the line it reverses, as the construction defines, instead of at its close.
-
ui_kit::Cardis visible: it fills with the theme’s secondary surface, has a 1 px border and pads its content by 8 px. It filled with the panel colour and had no edge. -
ui_kit::section::Sectiondraws its icon 8 px before the title, inside the header row, instead of left of the header where it was clipped. Section titles are 11 px. -
ui_kit::tab_bar::TabBardraws 12 px tabs 16 px apart from the content edge, each on a 28 px hit row, over a full-width rule that carries the active tab’s underline, and leaves 8 px before the content. A hovered tab brightens, tabs report their selected state to accessibility tools and show a focus ring. The alert and drawing properties dialogs no longer draw a second rule under their tabs. -
ui_kit::toolbar::ButtonGrouplays out its content along the parent’s direction, side by side in a horizontal toolbar and stacked in a vertical one, and draws its separators across the group, not down the rest of the parent. -
ui_kit::sidebar_layout::SidebarLayoutinsets its content 16 px from the divider and the top. EverySidebarTabreserves the icon slot, so labels line up whether or not a tab has an icon, and tabs report their selected state to accessibility tools and show a focus ring. -
ui_kit::trading_labels::PnlLabelputs the sign before the currency symbol and groups thousands (”-$98.10”, ”+$1,234.56”), and shows no sign for zero, including-0.0.PnlLabelandSideLabeluse the theme’s success and error colours, which are readable in every preset, instead of fixed chart tokens. Text that shows zero is in the normal text colour, not the gain or loss colour. ThePnlLabel::percentexample takes percent units, as the method does. -
The command palette draws each command’s icon, description and shortcut, fills the selected and hovered rows with the theme’s selection and hover colours, reports rows as selectable buttons to accessibility tools, and takes the theme’s window corner radius and shadow.
-
ui_kit::PanelHeaderuses one title style, the theme’s title size in the strong text colour, on a 36 px row with its actions 4 px apart.PanelHeader::stronghas no effect and is kept for source compatibility. -
CommandPalette::add_commandandremove_command, and the sameCommandPaletteHandlermethods, rebuild the listed commands and keep the highlight on the same command, so changing the commands while the palette is open no longer panics or makes Enter run the command next to the highlighted one. -
AutocompleteEditno longer panics on Enter or Tab after a suggestion was picked from further down the list or the suggestions shrank: the highlighted row stays within the shown suggestions and returns to the first row after a pick. -
Renko, Kagi, Line Break, Point and Figure and range bar charts keep their newest bricks, lines, columns and bars when they reach their element limit, and draw the newest ones, so the chart always ends at the last bar instead of losing the most recent data on a long or volatile history.
-
VWAP restarts at each trading day by default, counted in UTC, instead of accumulating over all loaded history.
VolumeWeightedAvgPrice::with_time_zoneandwith_sessioncount days in the instrument’s zone and trading hours, so a session that crosses midnight in the exchange zone or in UTC stays one period, and a window that spans midnight starts the next trading day at its open. A bar of a day or longer, which a feed stamps inside its UTC period, counts on its UTC date; bars count as a day or longer when no two consecutive bars share a UTC date.with_anchorrestarts at each week or month instead (VwapAnchor), andwith_std_dev_bandsadds upper and lower bands at multiples of the volume-weighted standard deviation of the typical price. Migration:with_session_resetis removed, since restarting at each session is now the default; values ofnew()and the factory’s VWAP that were cumulative now restart each day, and those ofwith_session_resetrestart in the exchange zone once a zone is set. To keep a cumulative VWAP over the whole series, useAnchoredVWAP::new(0). -
The indicators, Go to, compare symbol, symbol search and export dialogs keep their content size under egui 0.37, which counts a window’s frame and title bar in its size, and their title bars span the dialog. The indicators, Go to and compare symbol dialogs keep their titles centred over the dialog, which egui 0.37 centres in the space left of the close button. The date picker centres its calendar in its configured width, which the calendar overflowed because it left out the spacing between days, and the indicator dialog keeps its width when the configuration panel opens.
-
An application that follows the system appearance, as egui does by default, keeps the theme applied with
apply_to_eguiwhen the system switches between light and dark.apply_to_eguiwrote only the egui style in use, so egui switched to its own default style for the other appearance while the crate’s widgets kept the theme’s colours; it now styles both. -
KDJ smooths K and D recursively from 50, weighting the new value by
1 / k_smoothand1 / d_smooth(a third by default), as the formula is published, instead of with simple averages of those lengths, starts on barperiod - 1, and draws its D and J lines. A bar with a non-finite close or window range has no value, and K and D carry over it unchanged. Migration: K, D and J differ on every bar, J most, so thresholds tuned on the old values need retuning. -
Trend Intensity Index follows Pee’s definition: the share of the size of the last
perioddeviations from the2 * periodbar simple moving average that lies above it, with the first value on bar3 * period - 2. It counted the bars above the average of the same window, which reads 50 on any straight trend. Flat closes read 50 at any price level. Migration: values change, and barsperiod - 1to3 * period - 3no longer have a value, so levels tuned on the old output need retuning. -
VW-MACD is the 12-bar minus the 26-bar volume-weighted moving average of the close, with a 9-bar EMA signal, and starts on bar 25. It took exponential averages of one cumulative VWAP from the first bar, which shrank toward zero as history grew. Migration: values differ from those of the cumulative average, and bars before the slow period have no value instead of a line, so thresholds tuned on the old line need retuning.
-
SnapService::snap_pointno longer panics when a snap target or the point is NaN: NaN targets are never chosen and a NaN coordinate is returned unchanged.BarData::min_price,max_price,price_rangeandmax_volumeskip NaN and infinite values, so the result no longer depends on bar order, and they returnNonewhen no finite value remains. -
Logarithmic, percentage, indexed-to-100 and inverted price scales reach the screen. Candles and every other chart type, indicators, markers, drawings, the crosshair, the tooltip, the grid and the price axis render through the chart’s price scale; on an inverted scale High-Low bars are drawn, hollow candles keep their body clear of the wick, above-bar and below-bar markers sit outside the bar on screen, a click on a candle’s body or wick selects the series, and the volume profile drawings draw their rows and box with the VAH and VAL labels outside the value area. The series settings dialog’s scale mode and invert options apply to the main price scale (
Chart::apply_series_settings), as does the mode given toChartBuilder::with_right_price_scale. A new mode returns the scale to auto-scaling and clears the zoom history. Percentage and indexed modes are relative to the first visible close and keep the price order when that close is negative; the axis, the last-price label and the crosshair label show signed percentages or index values, and box zoom fills the pane with the selected prices in every mode. A range scaled by hand keeps its prices while the chart scrolls and when the zoom history restores it. A narrow logarithmic range is labelled in even price steps, and axis labels keep the same decimals at zero. -
Logarithmic, percentage, indexed-to-100 and inverted price scales reach the screen. Candles and every other chart type, indicators, markers, drawings, the crosshair, the tooltip, the grid and the price axis render through the chart’s price scale, and the series settings dialog’s scale mode and invert options apply to the main price scale (
Chart::apply_series_settings), as does the mode given toChartBuilder::with_right_price_scale. A new mode returns the scale to auto-scaling and clears the zoom history. Percentage and indexed modes are relative to the first visible close and keep the price order when that close is negative; the axis, the last-price label and the crosshair label show signed percentages or index values, and box zoom fills the pane with the selected prices in every mode. A range scaled by hand keeps its prices while the chart scrolls and when the zoom history restores it. A narrow logarithmic range is labelled in even price steps, and axis labels keep the same decimals at zero. -
The head and shoulders neckline runs through the two troughs instead of the two shoulders, and the target is projected from it at the last anchor: the head’s distance from the neckline, measured at the head, beyond the neckline on the side away from the head. No neckline or target is drawn while the troughs share a bar, where the neckline would be vertical.
-
XABCD, Cypher and ABCD ratio labels are measured in price, so they no longer change with zoom, pane size or scale mode. The XAB label is B’s retracement of XA (
|B - A| / |A - X|), where it showed|B - X| / |A - X|, and the ABCD label is|D - C| / |B - A|in price, where it compared on-screen leg lengths mixing time and price. A ratio whose base leg is flat is not shown, where it showed 0. -
Dragging the price axis zooms by each frame’s movement around the point where the drag began, so the zoom no longer depends on how many frames the drag spans.
-
The last-price line and label follow the newest bar instead of the last visible one, and are hidden while that price is off the scale.
-
KAMA’s efficiency ratio covers the last
periodbar-to-bar price changes, as Kaufman defines it, instead of the lastperiod - 1, in both the net change and the sum of absolute changes. Migration: KAMA values from barperiodonward differ on most series, so levels and signals tuned on the previous values need checking. -
Chandelier Exit measures its distance from Wilder’s average true range, as the ATR study does, instead of a simple average of true range, and draws the short exit line as well as the long one. Migration: values after the first one change wherever the true range varies, so stops placed on the old values move.
-
On Balance Volume starts at 0 on the first bar instead of at that bar’s volume, which offset every value by that volume. Migration: every OBV value is lower by the first bar’s volume, so thresholds set on the OBV level need the same shift; changes between bars are unaffected.
-
Zig Zag draws its swings: each value between two consecutive pivots lies on the straight line joining them, instead of only the pivot bars having a value, which left nothing to draw. Bars before the first pivot and after the last stay empty, and a series without a reversal of at least the deviation has no values. Migration: pivots are the first and last bars with a value and the bars where the line changes direction, rather than the only bars with a value.
-
Built-in studies clamp float parameters into a documented range at construction, NaN to the bottom of it, as they raise a length of 0 to 1: multipliers, percentages and costs to 0 or more, the Accumulation Swing limit move and the Ease of Movement and Market Facilitation divisors to
f64::EPSILONor more, the ALMA offset to 0 to 1 and sigma to 0.001 to 100, and the Parabolic SAR factors to at most 1, with the maximum no lower than the start.AccumulationSwingIndex::new(0.0), a NaN or negative band multiplier and an infinite ALMA sigma no longer turn every value into NaN or infinity. -
FisherTransformfollows Ehlers’ published construction: the normalised price is weighted by 0.33 instead of 0.66 before smoothing, the clamped value feeds the next bar, values beyond 0.99 are clamped to 0.999, and each Fisher value adds half of the previous one. Its output was off by up to several units in trends. -
Ichimoku plots Senkou Span A and B
displacementbars after the bar they are computed on and the Chikou Spandisplacementbars before its close, instead of all on the same bar, and each line starts once it has a value instead of every line starting at the Senkou B period with 0.0 in place of missing values. Values remain one per bar, so the leading spans computed on the lastdisplacementbars are not drawn. Migration: the value at barinow holds the spans computed on bari - displacementand the close of bari + displacement; a line without a value at a bar is NaN. -
EaseOfMovementdivides volume by 10,000 by default, as Arms defines the box ratio with volume in units of 10,000, instead of 1,000,000, which made every value 100 times too large. Migration: values with the default divisor are 100 times smaller; levels tuned on the old scale need dividing by 100, orwith_divisor(1_000_000.0)keeps the previous scale. -
Light theme text and control outlines are readable: secondary and muted text reach at least 4.5:1 on panels and windows, unchecked checkboxes and radios, text inputs and combo boxes have a 3:1 outline, and egui’s weak text uses the muted colour instead of fading by alpha. Dark theme secondary and muted text are raised to the same bar.
-
apply_to_eguisetserror_fg_colorandwarn_fg_colorfrom the theme, so error text no longer uses egui’s default pure red, and the status colours (success, warning, error, info) are defined per theme with at least 4.5:1 on its panels. -
Hover and pressed fills in the light theme are visible against white (1.2:1 and 1.3:1, from 1.1:1), and the accent hover and pressed shades and the danger button reds keep white text at 4.5:1 or better.
-
The crate builds warning-free on current stable Rust: float literals that relied on the deprecated
f32inference fallback are now explicitly typed. -
The documentation examples across the crate use the current crate name and module paths, and they compile as doctests with all features; those not marked
no_runalso run, and none is ignored. Theicon_from_path!documentation now says its path is relative to theassets/icons/directory of the crate that invokes the macro. -
Cloning a
CustomIndicatororCustomTimeFormatternow keeps its closure instead of replacing it with an empty or default one. Migration:CustomIndicator::newtakes the closure directly (CustomIndicator::new(name, |bars| ...)instead ofBox::new(...)), and the closure must beSync. -
The indicator dialog’s Momentum entry creates a new
Momentumstudy (the close minus the close n bars earlier, in price units) instead of Rate of Change;Momentumis also registered in the indicator factory. -
The export dialog no longer offers actions it cannot perform: the save path is typed into an editable field instead of a Browse button that set a fixed name, the data export text lists only the bar fields, and
ExportDialog::with_formatslimits the offered formats to those the host supports.Exportable::copy_to_clipboard, which discarded the image and reported success, is removed; copy a renderedegui::ColorImagewithegui::Context::copy_imageinstead. The demo copies the chart image to the clipboard and saves PNG exports to the chosen path. -
Dashed lines are clipped to the visible area before they are dashed, so a drawing anchored far off screen no longer hangs the UI thread or exhausts memory. Every dashed line in the crate (drawings, crosshair, price lines, session breaks, indicator pane zones) now shares this routine.
-
Auto-scaling flat price or indicator data now centres the series in a range proportional to the price level instead of collapsing to a near-zero range.
-
The anchored VWAP drawing computes the volume-weighted average of the typical price from its anchor bar, with bands one and two volume-weighted standard deviations away.
-
The fixed range and anchored volume profiles are built from bar volume, spreading each bar’s volume over its high-low range, with the point of control and a 70% value area. The anchored volume profile is placed with a single click and runs to the latest bar.
-
The regression trend fits the closes between its anchors by least squares and shows the resulting R² and the Pearson correlation of the closes.
-
The anchored VWAP, the volume profiles, the regression trend and Heikin-Ashi candles recompute when a bar inside their span is corrected, instead of showing values from the old bars until an anchor moved or the span grew.
ChartState::set_datacompares the new bars with the current ones to tell a correction from an append or a last-bar update, one pass over the bars per call. -
A live volume profile or regression trend no longer recomputes its whole span when the forming bar ticks or a new bar opens, or after another drawing was dragged: it adds that bar to the cached result for the bars before it (a profile only while the bar trades inside the profile’s price range). At 1,000,000 bars a new bar costs about 0.002 ms instead of 20 ms for a profile, and a tick 0.001 ms instead of 5 ms for a regression trend. Heikin-Ashi candles no longer copy the whole transformed series on every frame.
-
Long and short position tools have a stop of their own that moves independently of the target, so risk/reward reflects the levels set; P&L replays the bars after the entry and shows the position as closed once the stop or the target trades. Both read n/a while the stop or the target is on the wrong side of the entry.
-
The forecast drawing shows the predicted change over its bar span and resolves to success once a bar reaches the target by the target bar, or to failure once the target bar has closed without that.
-
The bars pattern projection draws shifted copies of the selected bars.
-
The chart watermark falls back to the chart symbol and is hidden when there is none, instead of showing a placeholder.
-
The OHLC header of a chart without a symbol prints prices with the same magnitude-based decimals as the legend instead of 8 decimals, and labels the last bar’s volume as volume instead of 24h volume. The top toolbar’s symbol pill shows no symbol instead of AAPL when none is set, the chart and series context menus leave out their alert and order items until there is a symbol, and
SymbolHeaderleaves out empty info fields instead of drawing bare separators. -
Zooming the price axis in by hand stops at a span of one millionth of the price level instead of narrowing to a few nanounits, and repeated zooming out can no longer overflow the price range to infinite or NaN bounds.
-
Timeframe::duration_mssaturates ati64::MAXfor custom timeframes too large to represent instead of overflowing into a panic or a negative duration, and parsing a custom timeframe whose second count overflows is rejected. -
Built-in studies raise a length of 0 to 1 and accept any longer length, alone or mixed with short ones, so a zero, huge or swapped period no longer panics, exhausts memory or yields only NaN (for example
KAMA::new(0),SmoothedMA::new(0)andMACross::new(50, 20)). -
SMA, VWMA, LSMA, Bollinger Bands, RSI, MACD and VW-MACD return one
Noneper bar instead of no values when there are fewer bars than their period. -
Stochastic no longer panics when all its periods are 1, Volume Profile Fixed Range no longer panics on a bar with a NaN price, and Rank Correlation no longer panics sorting NaN closes.
-
Rainbow Oscillator keeps a running sum instead of every SMA level, so a huge level count no longer exhausts memory.
-
Rainbow Oscillator divides the close’s distance from the mean of its averages by the close’s range over the last
levelsbars, as published, instead of by the mean itself. A bar whose range is zero has no value. Migration: every value changes scale, from a percentage of the price level to a percentage of the recent range of the close, so levels set on the previous values need to be set again. -
Volume profiles refuse a row count above 10,000 and yield
Nonefor every bar instead of allocating that many rows for each bar. -
to_tpo_profileswidens the tick size to a whole number of ticks when the bars span more than 1,000 ticks and skips bars with a non-finite or inverted range, so one wide or infinite bar no longer hangs the chart or exhausts memory. Migration:TPOProfilehas atick_sizefield holding the row height used, whichTPOProfile::newtakes as a second argument and whichtpo_count_at,price_levels,letters_atandclassify_shapeuse. -
The CVD documentation states that it is estimated from bars and uses no trade or order book data.
-
The keyboard focus ring uses the applied theme’s
ui.focuscolour (egui’s selection stroke when no theme has been applied) instead of the selection fill at reduced alpha, so it reaches 3:1 on panels and windows in every preset, and 4.5:1 in the high-contrast preset (it was 1.2:1 in light themes and 2.0 to 2.3:1 in dark ones). -
Widgets that meant the accent read the theme accent instead of the selection fill, which is pale in light themes: tab underlines, the sync button and its checkboxes, the selected drawing colour swatch, the open colour picker, the layout name input, the date picker range and Primary list item buttons. Text on an accent fill uses the theme’s on-accent colour, and Danger list item buttons fill from the danger button token.
-
Selected sidebar items and active chart control toggles use the selection fill and text colour (the sidebar painted accent text on an accent tint, 2.4:1 in dark themes), active tab labels use the strong text colour, descriptions on selected timeframe, chart type and template rows are no longer faded to 3.7:1, and the success status message uses the theme’s success colour instead of the accent.
-
Selected rows, tabs, menu items and calendar days render readable text on the selection fill instead of an empty accent bar (the selection text colour equalled the fill): white on the accent in dark themes, accent text on a pale accent fill in light themes.
-
Tooltips, popups and menus have padding, a hairline border, an elevated fill, a small radius and a tight shadow; windows get padding and a border.
-
apply_to_eguisets item spacing, window padding and menu padding from the design tokens instead of zero, so labels no longer touch their controls; toolbars, dropdown rows and stacked chart panes keep their own explicit gaps. -
Switching the theme repaints everything: the bottom toolbar, date picker, range switcher, timeframe bar, right panel tabs, symbol header, chart context menus, OHLC tooltip, replay bar and command palette resolve their colours from the active theme instead of keeping the dark theme they were built with. Fields a caller sets on the public
configofTimeframeToolbar,TimeframeBarorRightPanelTabsare kept; only the fields left at their theme-derived value follow the theme. -
Custom-painted buttons (top toolbar, drawing toolbar, widget bar and the
ui_kitbuttons) draw a focus ring when they have keyboard focus. -
The dialog close button no longer draws an accent outline at rest; it looks like an icon button, so only keyboard focus draws a ring around it.
-
The command palette search icon follows the theme instead of staying white, so it is visible in the light theme.
-
The native demo starts on Linux: it enables wgpu’s default backends instead of none.
-
The web demo publishes, next to its page, the licences of the egui default fonts (Hack, Ubuntu Light and the egui icon subset of emoji-icon-font) and the Lucide icons that its WebAssembly module embeds;
THIRD-PARTY-NOTICES.mdlists the fonts. -
The README, package description, crate docs and ROADMAP state what the code does: the number of drawing tool types (counting cursor modes) and of registered indicator names, with a unit test that keeps those counts in step with the code; no unproven icon count; and no claim of magnet snapping, drawings saved by the chart or templates saved to disk, none of which works yet. The crate and module docs describe the modules, presets and data contracts as they are: which builder sets what, where pan and zoom live, that
fetch_historicalneedssupports_historical, and that nothing consumesDatafeedor the services yet. -
ROADMAP ticks an item only when it works end to end: unwired widgets, scale modes the chart does not render, drawing tools with wrong geometry and indicator lines that are computed but not drawn are now unticked or carry their limits.
-
The README’s Rust snippets compile and run as doctests against the current API (including the
Datafeedexample), and the install lines use version0.2. -
The
QuoteSourcedocs describe when it is actually called: nothing in the crate polls quote sources. -
Bar replay no longer panics when a frame is due more bars than remain, and
ReplayState::updatereturns the number of bars actually advanced. -
ListItemallocates its row once: rows are 28 px apart with no gap, hover, pressed and selected fill the whole row, and every content type starts its icon and text 8 px inside the row. CustomListItemContentimplementations paint insideContentContext::rectand return the row response instead of allocating space of their own. Row colours come from the active theme, with a pressed state distinct from hover and on-accent text on selected rows, and rows report their role, label and selection to accessibility tools. -
The
AutocompleteEditpopup is exactly as wide as its input, has the popup border, aligns its suggestions with the input text and draws them in the theme’s text colour. -
FormRowtakes the height of its content instead of the remaining height of the panel, so consecutive rows and a followingFormGridstay visible. The label is centred on the widget’s line, and the description sits below it in the theme’s muted text colour. -
The
FilterWidgetsearch icon and clear button sit inside the field, 8 px from its edges, and the field no longer grows by a pixel when hovered or focused. Clicking the clear button now clears the query. -
The
ColorPickerswatch is 28 px with a border that stays visible on dark colours and brightens on hover. Its popup is as wide as the swatch grid and uses the popup border, and the row below the grid shows the hex value and opacity of the selected colour. -
The compare symbols dialog draws its symbols, labels and background in the theme’s colours when
CompareSymbolsConfigleaves them at the default instead of drawing them transparent. -
The
ui_kitbuttons share one state model. Rest, hover and press are each a visible step: neutral fills move one step further from the surface, and Primary and Danger fills darken, so pressed no longer equals hover or looks paler than it; a selectedButton,IconButtonorSplitButtonis drawn as Primary, filled with the accent;enabled(false)renders exactly like a button insideadd_enabled_ui(false); and a disabled Primary or Danger button is drawn as Secondary, so its faded label stays as readable as other disabled buttons, with an accent outline on a disabled PrimaryButtonso a selected one still reads as selected. -
ButtonVariantcolours follow the active theme: Primary is the theme accent with its hover and pressed shades and on-accent text, Secondary a neutral fill one step above the surface, Outlined a border in the secondary text colour, Ghost the primary text colour, and Danger the danger button reds with on-accent text. -
Buttonis as wide as its laid-out label plus 12 px on each side, instead of an estimate from the byte length, so every label gets the same padding and labels with multi-byte characters fit. -
SplitButtonpoints its chevron down whether or not it is expanded. -
The
ui_kitbuttons report their role, label (the tooltip for icon-only buttons), and enabled and selected state to accessibility tools, and show their tooltip while disabled. -
The kit
Modal,ConfirmDialog,PromptDialogand the command palette draw their dimming backdrop below their window instead of over it, so the dialog is shown at full contrast. Clicking the backdrop closes a closable modal. -
PromptDialogkeeps the text typed into it between frames instead of resetting it to the initial value, so Enter and the submit button return what was typed. -
The data window prints a negative price with the decimals of the positive price of the same magnitude, so -37.63 reads
-37.63instead of-37.63000000. -
Saved drawings round-trip:
stored_to_drawingrestores the anchors (chart_points), so a restored drawing no longer disappears on the next frame, every tool type loads back, and every setting (line style, fill, font, extend, arrows, lock, visibility, per-timeframe visibility, z-order, Fibonacci levels, volume profile, regression trend and position size) is kept. -
Every drawing tool’s display name parses back to that tool with
FromStr, ignoring case; the Fibonacci extension, time zone, speed resistance fan, trend-based time and speed resistance arcs tools and the five Elliott wave tools were not parsed. -
A drawing whose tool type is unknown is skipped with the error
unknown drawing tool "Name"instead of one listing all 95 tool types. -
ColorType::from_hexreturns an error for input that is not six or eight hexadecimal digits, instead of panicking on a multi-byte character such as"aÄÄb"or accepting a sign such as"+F+F+F". -
ColorType::from_hexandColorType::from_rgbaread the alpha as unmultiplied, as CSS andColor32::from_hexdo, so"#FF000000"is fully transparent and"#FF000080"is half transparent red. They stored the unmultiplied channels as premultiplied, which drew a transparent colour as additive red and a translucent one too bright. Migration: code that passed premultiplied channels tofrom_rgbabuildsColorType::Solid(Color32::from_rgba_premultiplied(r, g, b, a))instead. Colours saved by earlier versions keep the values they were saved with; build them again from their hex or RGBA source to get the corrected colour. -
Ease of Movement leaves a bar with zero volume and a nonzero range out of its average instead of counting it as a bar that did not move. A bar with a NaN or infinite high, low or volume has no value, and a window without any bar with a raw value has no value.
-
Zig Zag confirms its first pivot from the first reversal instead of starting at an extreme of the first bars, extends the current leg on an outside bar instead of reading it as a reversal, and skips a bar whose prices are not finite or not positive. The rules are documented on
ZigZag. Migration: values change on most series, since the line now starts at the first confirmed pivot, usually earlier than before, pivots around outside bars move, a series at or below zero, such as a spread, has no values, and a deviation of 0 gives no values instead of a pivot on almost every bar, so swing levels read from the previous values need checking. -
Fibonacci retracement levels are measured back from the second anchor, the end of the move: level 0 is drawn on the second anchor and 100% on the first, with each level’s price label, background band and hit area at the same height, and the Reverse option, which had no effect, now swaps the two anchors. Migration: saved retracements draw with their levels flipped; set
FibonacciConfig::reverseto keep the previous placement. -
The Gann fan draws each angle at its labelled ratio: an NxM line has N/M times the slope of the 1x1 line, so 8x1 is the steepest and 1x8 the flattest. They were drawn the other way round, so the drawn lines did not match the lines a click selects, and 1x3 used 0.333 instead of one third.
-
The sine line passes through both anchors, a peak and a trough half a period apart, with the centre guide midway between them and the amplitude label at half their price distance. It crossed the centre line at the first anchor and returned to it at the second, so it missed the second anchor unless both had the same price. Migration: a saved sine line keeps its anchors, and its first anchor is now a peak or trough instead of a crossing of the centre line.
-
The parallel channel’s second line starts and ends on the bars of the first two anchors, straight above or below them, and passes through the third anchor. It was shifted along the base line by a construction at right angles to it, so its ends sat on other bars and the connecting lines were slanted; the hit test now uses the drawn line.
-
The Gann box draws its 2x1, 3x1 and 4x1 lines and their mirrors from the first anchor to 1/2, 1/3 and 1/4 of the far edges, and counts its 0%, 50% and 100% levels from the first anchor’s price. The lines started at the top-left corner whatever corner the box was drawn from, and ended at a pixel slope that matched the labels only for a square box.
-
Time cycles repeat the interval between their anchors forward in time: each cycle is a half circle as wide as that interval, standing on the first anchor’s price, from the earlier anchor to the right edge of the chart. They drew six concentric half circles around the first anchor, from 0.5 to 3 times the anchor distance.
-
Several Fibonacci tools are corrected: channel levels lie on the side of the base line where the third anchor is, where they were always drawn on one side; speed resistance arcs open towards the first anchor’s price, below the end of a rise and above the end of a fall, where they were always drawn below; the speed resistance fan extends towards the side of its second anchor, where a fan drawn right to left was mirrored to the right; time zones fall on 0, 1, 2, 3, 5, 8 and on along the Fibonacci sequence, where the line at 1 was drawn twice; and the spiral is a golden spiral through the second anchor whose radius grows by the golden ratio every quarter turn, where it grew by that ratio per full turn from a tenth of the anchor distance and ignored the second anchor’s direction.
-
to_renko_bricksreverses only after a two-brick move: a close must move one brick beyond the open of the last brick, and the reversal brick starts at that open. A one-brick move against the trend drew a reversal brick over the last brick. Renko charts now show fewer reversal bricks. -
parse_date_range("MTD")starts at 00:00 UTC on the first day of the current month, asYTDstarts on the first day of the year, instead of 30 days before now.1Mstill covers the last 30 days. -
parse_date_rangerejects a relative count below 1, such as"last -5 days"or"last 0 days", withDateRangeParseError::InvalidNumberinstead of returning a reversed or empty range, and returns the same error for a count too large to represent instead of panicking. -
An absolute range from
parse_date_rangeincludes its end date:"2024-01-01 to 2024-12-31"ends at the start of 1 January 2025, and a range whose two dates are equal covers that day instead of being refused. An end date on the last day chrono can represent returnsInvalidDateFormat. Migration: the end of an absolute range is one day later than before, so code that added a day to include the end date no longer needs to. The end is exclusive: keep a bar when its time is before the end.DateRangeParseError::InvalidDateOrderreads “End date must not be before start date”. -
TPO profiles count each period once at each price row instead of once per bar, and a bar’s period follows the whole minutes elapsed since the session’s first bar instead of advancing by at most one period per bar, so a gap leaves its periods empty and a bar 95 minutes into a profile with 30-minute periods gets letter D instead of B. On bars shorter than the period, a row touched by several bars of one period holds one letter and one TPO, which changes the point of control, the value area, single prints and poor highs and lows. On bars longer than the period, each bar takes the letter of the period it opens in, so letters skip the periods it also spans, for example A, C, E on 1-hour bars with 30-minute periods. Building a profile walks each row once per period instead of once per bar. Migration:
TPOLetter::tsis the open time of the first bar of the letter’s period instead of the bar that placed it; letters and counts differ from earlier versions on series whose bars are shorter than the period or have gaps, and letters differ on bars longer than the period. -
to_tpo_profilesuses the default letters whenTPOConfig::custom_lettersis an empty string, instead of panicking with a remainder by zero. -
Time scale options whose minimum bar spacing exceeds the maximum, or is NaN or infinite, no longer panic when the chart is built, zoomed or box zoomed: a minimum above the maximum counts as the maximum, a NaN or infinite minimum as the default 0.5, a negative minimum as 0, and a NaN or infinite maximum as unlimited.
-
The crosshair price label sits in the price axis, aligned with the tick labels and in their font, shows the price with the decimals of the axis ticks instead of eight, and no longer ends in a ”+”. The time label sits on the time axis instead of over the volume bars, in the axis date format with the year when it is not the current one, and the vertical line runs through the volume pane.
-
The crosshair’s time label and its magnet snap take the bar nearest the pointer, the one the OHLC readout shows; they took the bar to its left when the pointer was past the middle between two bars.
-
The last price tag is aligned with the tick labels and in their font, and its text is black or white, whichever reads better on the candle colour; it was light grey at 2:1 or less. An axis label under the last price tag or a crosshair label is left out instead of showing in part, and the crosshair price label covers the last price tag it overlaps.
-
The crosshair line and labels follow the theme (
chart.crosshair_line,chart.crosshair_label_bgandchart.crosshair_label_text); the light and high contrast themes showed the dark theme’s. TheCrosshairOptionscolours, including the label colours that nothing read, default toColor32::PLACEHOLDER, the theme’s colour, and override it when set. The light theme’s crosshair line is darker, 3.2:1 on white. -
The floating tooltip shows its labels and values in two aligned columns in the proportional font, prices with the legend’s decimals (at most
price_precision), and a 1 px border in the theme’s border colour instead of a 2 px ring in the candle colour. It sits in the top corner of the price pane away from the pointer instead of next to it, so it no longer covers the hovered bar.TooltipOptions::border_color_bullishandborder_color_bearishdefault toColor32::PLACEHOLDER, the theme’s border colour; the tracking bar and the magnifier take the candle, crosshair and text colours from the theme. -
Price and time axis labels use one font size, so month and day labels share a baseline.
-
The selected drawing’s handles are round, an accent ring around the chart background like the selection dots of a series, instead of white squares with a dark outline; the handle being dragged is filled with the accent.
HandleConfig::colorandselected_colordefault toColor32::PLACEHOLDER.to_array(), the theme’s accent. -
A new drawing is pink (
DrawingManagerOptions::default_color), a colour no default study uses, instead of a blue close to the EMA’s. -
The legend’s O, H, L and C labels and the bullet after the symbol use the theme’s secondary axis text colour instead of fixed greys (#459), and its values and change the theme’s success and error colours instead of the candle colours, which read at 3:1 on the light chart.
-
The chart, series and drawing context menus hide the crosshair, its labels and the tooltip while they are open, open 2 px from the pointer (the drawing menu 6 px, clear of the clicked handle) and flip to the other side of it to stay 8 px inside the window, size themselves from the laid-out text and elide labels wider than 300 px, and draw with the theme’s menu frame, hover fill and shadow. Rows show the bound shortcut, formatted for the platform (“Ctrl+R” on Linux and Windows), only for actions with a key binding; the crate handles only Delete, destructive rows (“Remove 5 indicators”, “Delete”) use the danger colour, both menus format the clicked price with thousands separators, and every row reports its label and role to accessibility tools.
-
NotificationPanelstacks its toasts 8 px apart, newest nearest the corner, 16 px from the window corner. Every toast was drawn at the same spot, flush to the corner, so only one was visible. -
Toasts are opaque and follow the theme: the window fill, border and popup shadow, text in the theme’s text colour (a title in the strong text colour, its message in the secondary text colour), and the icon and progress bar in the theme’s colour for the kind. They were translucent fixed-colour slabs, the same in every theme, with error text below 4.5:1. The close button can be clicked, and a timed toast’s progress bar spans the toast’s content instead of stopping 16 px short.
-
Alerttakes its colours from the theme: the icon in the theme’s colour for the kind, the fill and border in that colour at 10 % and 40 %, and the title in the strong text colour with the message under it in the secondary text colour. It used fixed tokens tuned for the dark theme, so several icons fell below 3:1 in the light theme and the high contrast theme showed the dark colours. Every alert fills the available width, the dismiss button can be clicked, and the text starts 8 px after the icon instead of 16 px. -
status_messagedraws Info in the theme’s info colour instead of the plain text colour, starts at the left edge of the content around it instead of 8 px in, and leaves 4 px above instead of 6 px. -
Acceleration Bands average each bar’s widened high and low, as Headley defines them, instead of widening the average high and low by the average range, and draw all three bands.
-
Klinger Oscillator weighs volume by Klinger’s volume force, built from each bar’s range and the cumulative range of the current trend, instead of by the trend sign alone, and draws its signal line. Equal sums of high, low and close keep the current trend, a series too short for the long average has no values instead of values from a partial average, and a bar with a non-finite price has no value without ending the study. Migration: values differ from the signed-volume averages computed before, and every value is
Multiple([oscillator, signal]), the signal NaN until it exists, where it wasSingle(oscillator)until the signal existed. -
BarData::to_csv,to_csv_stringandto_csv_with_indicatorswrite a bar’s fraction of a second, andBarData::from_csvreads it, so bars less than a second apart keep their times through a CSV file. Whole-second times are written as before. -
A replay speed that is not finite plays at 1x and a custom speed is clamped to 0.1x to 100x, so
ReplayAction::SetSpeed(f32::NAN)or a negative speed no longer freezes a replay that still reports playing. -
to_range_bars_from_tickscloses one bar per full range a tick crosses, up to 100, and always returns the bar holding the last trade, so a tick that closes a bar no longer loses the rest of its move and the series ends at the last traded price. It keeps the newest 5,000 bars, liketo_range_bars_from_ohlc. -
Trend Detection Index follows Pee’s definition, the absolute n-bar sum of n-bar momentum minus the excess of the 2n-bar over the n-bar sum of absolute momentum, and starts on bar 3n - 1. It returned the net move minus the path length, which is never positive. Migration: levels tuned on the old values need resetting, and the first value now comes 2n - 1 bars later.
-
The True Strength Index starts its averages at the first price change instead of a made-up zero change on the first bar, which skewed the index for dozens of bars after its warm-up, and draws its signal line.
-
ADX starts from the mean of the first n DX values, as Wilder defines it, instead of n - 1 values divided by n, so it no longer reads low after its warm-up.
-
ATR with length 1 has a value on a single bar, its range, instead of none until a second bar exists.
-
The Commodity Selection Index computes Wilder’s formula, ADXR * ATR(n) * (V / sqrt(M)) * (1 / (150 + C)) * 100, from the ADX and ATR studies, and starts on bar 3n - 1; it used a simple mean of true ranges, an unsmoothed DX and a division by the close. Migration:
CommoditySelectionIndex::new(period, cost)is nownew(period); set the contract withwith_point_value,with_marginandwith_commission. The old cost parameter had no counterpart in Wilder’s formula. -
The release workflow fails when
cargo publishfails; it skips the publish only when crates.io already has the exact version. -
Bars with a non-finite value, a high below the open or close, a low above them or negative volume are dropped and counted instead of drawn; bars out of time order are sorted, and of several bars with one open time, or in one slot of the timeframe for a chart built with a feed, the last is kept. This holds for
Chart::new,set_dataandupdateand for the bars a feed sends. -
A live update no longer copies the history: the chart merges new bars in place and updates its studies once per frame from the first changed bar instead of recomputing them on every update.
-
Removing a study no longer moves the selection to another study, and removing the selected study clears the selection.
-
Loading older bars with
Chart::set_datamoves the drawings with their bars, and so does a bar thatChart::updateor a feed inserts between stored bars. -
The Schiff pitchfork’s median starts at the first anchor’s time, halfway between the first and second anchors, and runs through the midpoint of the second and third anchors with the tines parallel to it. It started at the first anchor and was aimed halfway between that anchor and the midpoint, so the median and both tines had the wrong slope.
-
An Image drawing draws its checkerboard only where it is visible, so a large frame, or a stored anchor far off screen, no longer stalls every frame.
-
Fibonacci retracement and extension levels are drawn, labelled and hit at the price they are labelled with on every price scale, where on a logarithmic scale the line sat at the interpolation of the anchors’ screen positions and its label named another price. The hit test of a retracement and of an extension follows the visible levels of their config, where the extension tested the retracement’s fixed levels.
Drawinggains the fieldlevel_ys, the screen y of each visible level, rebuilt byupdate_screen_coords. Migration: construct aDrawingwithDrawing::newinstead of a struct literal, and callupdate_screen_coordsafter changingfib_configorchart_pointsbefore rendering or a hit test. A retracement or extension with fewer than twochart_points, asDrawing::add_pointleaves it, now draws nothing, where it drew its levels from the screen points. -
A bar with a non-finite price or volume no longer blanks every later value of KAMA, On Balance Volume, ATR, Fisher Transform, Ehlers Fisher, Chandelier Exit and the Commodity Selection Index: that bar has no value and the study continues past it, as the new
Indicatorsection on non-finite bars states. -
The floating replay bar’s shortcuts (Space, Home, End and the arrow keys) no longer act while a text field has focus, a popup is open or a control outside the background layer has focus, and take their key when they act, so a space typed in the symbol search no longer toggles playback and Space on a focused button presses that button. Escape no longer hides the bar: a close button on the bar does,
FloatingReplayControl::show_controlshows it again, and the demo’s Replay button shows a hidden bar instead of stopping replay. The bar is also drawn in the frame a shortcut acts in. -
The floating replay bar draws Go to start and Previous bar disabled on the first bar, and Next bar and Go to end disabled on the last.
FloatingReplayControl::sync_fromdivides the zero-based bar index by the last index instead of the bar count, so the last bar reads 100% instead of 99.7% for 300 bars. -
A bar with a non-finite close no longer blanks every later value of EMA, DEMA, TEMA, SMMA, GMMA, McGinley Dynamic, VIDYA, ZLEMA, EMA Cross, MACD, VW-MACD, PPO, TRIX and Stochastic RSI (VW-MACD also needs a finite volume): that bar has no value and the study continues past it.
-
A bar with a non-finite input no longer blanks every later value of Elder Ray, Force Index, Mass Index, TSI, SMI, STC, DMI, Keltner Channels, Chaikin Volatility, VWAP, Anchored VWAP, A/D, CVD, VPT, PVT Enhanced, PVI, Williams AD, the Accumulation Swing Index, Volume Oscillator and both volume profiles (the high, low, close, open or volume the study reads): that bar has no value and the study continues past it.
-
A bar with a non-finite input no longer leaves finite but wrong values after it in RSI, Connors RSI, Stochastic, KDJ, Double Stochastic, Williams %R, Ultimate Oscillator, Pretty Good Oscillator, Relative Vigor Index, Know Sure Thing, Trend Intensity Index, Elder Impulse, MFI, VWMA, Ease of Movement, Historical, Close-to-Close, Garman-Klass and Parkinson Volatility, rank correlation, ADX, SuperTrend, Parabolic SAR, Aroon, Ichimoku, Donchian Channels, Price Channel, Pivot Points, 52 Week High/Low and Choppiness, True Range, Vortex, Squeeze Momentum, Majority Rule, Chaikin Money Flow and Klinger (the high, low, close, open or volume the study reads): that bar has no value and every later value equals the one for the series without it.
-
“52W HL%” measures its range over the bars within 364 days of the current bar’s timestamp on every interval instead of over 252 bars, so on a 1-minute chart it no longer covers 252 minutes, and has no value before 52 weeks of history. The new “52W High/Low” (
Week52HighLowLevels) draws the highest high and lowest low of the same window as two lines on the price pane. Migration: replaceWeek52HighLow::new(period)withWeek52HighLow::new(); intraday charts with less than a year of bars show no value. The factory category for both 52W studies changes from “Breadth and spread” to “Market structure”. -
Net Volume signs each bar’s volume by its close against the previous close (positive up, negative down, zero when equal) instead of against its own open, so a gap no longer inverts the sign, and the first bar has no value. Migration: the first value is blank and signs differ on bars that open away from the previous close.
-
ZeroTrendVolcomputed the Parkinson high-low estimator; that calculation is nowParkinsonVolinparkinson_vol.rs, still registered as “Parkinson Vol” with unchanged values. “Zero-Trend Vol” (ZeroTrendVol) is the zero-mean close-to-close estimator: the square root of the mean squared log return, annualised bysqrt(252) * 100. Both assume daily bars (#672). Migration: Rust code that builtZeroTrendVolfor the high-low estimator buildsParkinsonVol. -
Balance of Power with smoothing of length
nhas no value on its firstn - 1bars, and none on any bar of a series shorter thann, instead of plotting the unsmoothed ratio there. A bar with a non-finite price has no value and the average is taken without it. Migration: the first 13 bars of the default Balance of Power are blank instead of raw ratios. -
PPO seeds its signal line with the mean of the first
signalvalues of the PPO, as MACD defines it, instead of an EMA over zeros before the PPO exists, and returns the histogram (PPO minus signal) as a third line, soline_cnt,line_namesandcolorsreport three lines. The newPercentageVolumeOscillator, registered as “PVO” with lengths 12, 26 and 9, returns the same three lines computed from volume. Migration: PPO values from bar 33 (for 12, 26 and 9) areMultiple([ppo, signal, histogram])and the signal differs on every bar, since the zero start no longer pulls it down;PriceOscillator::with_colorsandset_colorskeep the colour of a line they are given none for. -
Zig Zag pivots sit on the swing extremes: when a reversal is confirmed, the new leg starts at the lowest low or highest high since the pivot it reverses from, not at the confirming bar, and the bars after that extreme are judged against the new leg, so the line touches every swing extreme.
depthis now the minimum number of bars from a pivot to the bar that confirms the next reversal, and two pivots can be fewer thandepthbars apart. Migration: values change on any series with a swing extreme fewer thandepthbars before its confirming bar, which with the default depth of 10 is most series, so swing levels read from the previous values need checking, and a depth chosen to keep pivots apart no longer does. A bar with a non-finite price has no value and is not counted indepth, as if it were not in the series, instead of being drawn across. -
A replay’s playback state follows seeks and steps:
ReplayState::jump_to_barandstep_forwardmark the replay finished whenever they land on the last bar and paused when they leave it, asstep_backwarddid, andreset,initandenter_replay_modeapply the same rule, so a reset after the end is paused and a one-bar replay starts finished. Playing after seeking back from the end continues from the bar sought to instead of the first bar, and toggling play (ReplayAction::TogglePlayPause, the play button and Space inReplayControls) on a last bar reached by a seek or a step restarts the replay instead of doing nothing;ReplayAction::Playstill does nothing on the last bar. -
ReplayController::load_dataduring an active replay keeps the replay time: the position moves to the last bar that opens at or before it and a playing replay keeps playing, instead of restarting paused on the first bar. On a coarser interval the bar that contains the replay time is shown whole. The demo reloads its replay this way on an interval change, so the next step no longer brings back the old interval’s bars. Migration: to restart a replay on new data, stop it first or sendReplayAction::JumpToStartafterload_data; a series that ends before the replay time resumes finished on its last bar. -
An indicator alert needs an Indicator A and either an Indicator B or a threshold: the alert dialog keeps Create Alert disabled and names the missing field (“Choose Indicator A”, “Choose Indicator B”) until it has them, and
AlertsPanel::get_indicator_alert_formreturnsNonefor a blank indicator, so the panel’s Create stays disabled. Both used to create an alert with nothing to compare against. -
A drawing placed with clicks keeps exactly the anchors that were clicked: the pointer preview between clicks is no longer kept as an anchor, so a parallel channel, a pitchfork or a triangle needs three clicks rather than finishing on the second with its last anchor repeated, the pattern and Elliott tools take one click per anchor, and a trend line or a polyline no longer stores an extra point where the pointer last was.
-
Releasing a drag that has left the price pane, over an axis or outside the chart, finishes the drawing with its last anchor on the pane’s edge, and ends a handle drag, where the drawing stayed in progress until the next drag on the pane or Escape and the handle kept following the next drag.
-
A locked drawing can no longer be moved or reshaped by its handles, or removed by the eraser, the Delete key,
DrawingManager::delete_drawing(which the drawing’s context menu, properties dialog and object tree row call) orDrawingManager::clear_all(Remove all drawings), until it is unlocked, and the eraser no longer highlights it. -
Drawings are drawn in ascending
Drawing::z_orderand hit from the highest down, in list order where it is the same, so a layering set withZOrderServicetakes effect and survives a save and load.DrawingManager::bring_to_frontandsend_to_backsetz_orderinstead of moving the drawing inDrawingManager::drawings, a drawing created with the tools starts on the top layer, and a drawing restored throughDrawingManager::add_synced_drawingkeeps its stored z-order. -
A drawing shown only on some intervals is no longer drawn on the others, and
Chart::set_timeframesets the interval its visibility is checked against, where the check always used 1D and applied only to selection. The Visibility tab of the drawing properties dialog names the minute intervals 1min to 30min, as the chart’s interval label does, where it offered 1m to 30m, which matched no interval. -
The trend line, ray, extended line, horizontal and vertical lines, horizontal ray, cross line and trend angle are drawn in the drawing’s dashed or dotted line style, and a trend line set to extend left or right reaches that edge of the pane and is hit along the extension, where these lines were always solid and the trend line ended at its anchors.
-
A drawing restored with
stored_to_drawingkeeps the id, creation time and notes of its stored record in the newDrawing::stored_id,created_atandnotesfields, anddrawing_to_storedsaves it back under them, where a load and save renamed every drawing to its session id, reset its creation time and dropped its notes.DrawingManagergives a new drawing an id above every id its drawings hold or are stored under, so a drawing created after a restore no longer replaces an older stored one. Deleting a restored drawing queuesDrawingSyncAction::Deletewith its stored id, and a copy of a drawing passed toDrawingManager::add_synced_drawingwhile the original is there is saved as a new drawing rather than over the original. Migration: construct drawings withDrawing::new, or setstored_id,created_atandnotesin a struct literal ofDrawing. -
The measure, info line, price range, date range and date and price range drawings report durations from the bars’ times instead of counting a bar as one minute, the volume traded between their anchors, and the price change with its sign; the info line’s angle is positive for a line that rises on screen. The measure no longer prints a pips figure computed as the price change times 100, nor
Vol --. -
The flat top/bottom and disjoint channel drawings label the price distance between their two lines as drawn on the chart’s price scale, logarithmic included, with its percentage of the lower line, and the rectangle labels its width in bars and its height in price, all from the anchors’ bars and prices instead of screen pixels, so the labels no longer change with zoom and pan. The trend angle prints its price change, bars and duration in place of a pixel length and slope.
-
The Fibonacci channel moves its levels straight up or down from the base line, as the parallel channel moves its second line, so each level is as far in price from the base at every bar; on a sloped base they were moved at right angles to it and slid sideways.
-
Fibonacci retracements, extensions and channels are selected along the level lines they draw and nowhere else: over the extent the lines are drawn, including the part extended to the chart edge, and for the channel along its sloped levels instead of fixed horizontal ones. The undrawn diagonal between the anchors no longer selects them.
-
Rays, extended and cross lines, horizontal rays, price and date ranges, the measure, polylines, paths, brushes, arrows, trend angles, info lines, the harmonic, head and shoulders, triangle and Elliott wave patterns, triangles, circles, ellipses, arcs, curves, every pitchfork and the pitchfan, the Gann fan, box and squares, the flat top/bottom and disjoint channels, and the Fibonacci time zones and speed resistance fan are selected anywhere along the lines they draw, from the same geometry their renderers draw, where they could be selected only near an anchor. The measure, date range, date and price range, Gann box and squares, the two channels, and filled triangles, circles and ellipses are also selected inside the areas they fill; brushes and the highlighter are selected across the width they are drawn at. The Gann fan is hit along its nine lines to the chart edge instead of eight lines that stopped at the second anchor, and an unfilled circle is no longer selected at its centre.
-
A ray whose second anchor is left of its first is drawn, and selected, from its first anchor through its second to the left edge of the pane; it ran from its first anchor to the right edge, away from its second.
-
DrawingStorage::to_jsonrefuses a drawing whose tool is a cursor, such as the eraser, withSaveError::Cursor, instead of saving a drawing thatfrom_jsonskips on the next load. -
DrawingManager::pending_syncreceives oneDrawingSyncActionper drawing for every change to a stored field: drawings finished by a drag, a double-click or Enter, clearing all drawings, hiding or locking them all, bringing to front, sending to back, undo, redo and a copy added withadd_synced_drawingnow queue theirs too. The newDrawingManager::edit_drawingapplies an edit, records it for undo and queues it, andDrawingManager::drag_edit_drawingwithend_drag_handlemakes a continuous edit, such as a colour picker drag, one undo step and one update. The host drains the queue; the chart never does. Migration:clear_allnow queues aDeletefor each drawing it removes, so a host that saves from the queue deletes their stored records; to unload drawings without deleting them, cleardrawings, then callcancel_curr_drawinganddeselect. -
Choosing the eraser in the drawing bar lets a click delete the drawing under the pointer. The chart erased only while a crate-private flag was on that nothing set; it now follows
DrawingManager::eraser_mode, which the newDrawingManager::set_eraser_modeswitches on (leaving the active tool) and off, and which choosing a tool withset_active_toolswitches off. -
In eraser mode a click deletes the drawing under the pointer while another drawing is selected too, instead of selecting it; a locked drawing is still not erased, and Escape switches the eraser off.
-
The drawing bar’s “Save as Template…” opens a template name dialog that stays open until the name is saved or the dialog is cancelled, instead of closing on its first frame because its empty name read as a cancel. The visibility flyout closes when the dialog opens.
TemplatesButton::show_name_dialogreturnsSome(DrawingToolbarAction::None)on Cancel or Escape, where it returnedNone, so a caller can tell a cancel from a name still being typed. -
The drawing bar’s Icons/Emojis button opens a menu of icons and emoji that emits
DrawingToolbarAction::InsertEmoji, drawn with the app’s fonts (the demo enables egui’smonochrome_emoji_fontsand lists Noto Emoji and emoji-icon-font in its font licences), and the next click on the chart places the one picked, as does every later click in keep-drawing mode; the button opened nothing, and a click afterDrawingManager::start_icon_insertionplaced a default*instead of the picked icon. -
The drawing bar scrolls when the window is shorter than its buttons, so Templates, Hide and Remove stay reachable, and its flyouts scroll when they are taller than the window. A flyout opens beside its button, closes on an outside click or Escape without also clearing the chart’s drawing state, and closes after a pick unless keep drawing is on.
-
The drawing bar’s buttons and flyout rows no longer overlap their neighbours by 3 and 5 px, so a click near the lower edge of a button no longer activates the next one. Tooltips open to the right of the bar instead of over the next button.
-
The drawing bar shows the state it was left in: the cursor button shows the chosen cursor or the eraser, the cursor menu checks the current one and the values tooltip option, the magnet menu has an Off row and checks the current mode, and the magnet button is filled while snapping is on. Zoom and the cursor are no longer highlighted at the same time.
-
The selected drawing bar button and flyout row use the accent fill with the accent text colour, readable in every theme; hovered and selected rows differ. Section headers and shortcut hints in the flyouts are 11 px and use the secondary text colour, and a flyout is as wide as its widest row, so “Elliott Triple Combo Wave (WXYXZ)” no longer meets the border.
-
The drawing bar’s menus share one look: rows 28 px high with a 16 px icon column, the theme’s menu fill, border and shadow. The Hide menu reads “Hide drawings”, “Hide indicators”, “Hide positions” and “Hide orders”, the Remove menu shows its two rows in the error colour, and the Text flyout’s sections read “TEXT & NOTES” and “CONTENT” in the order the bar uses.
-
Typing ”/” in a text field no longer opens the drawing bar’s tool search; with no field focused it opens a search field beside the bar, with a close button.
-
Drawing bar buttons and flyout rows have a role, a name and their selected state for assistive technology, and rows show a focus ring.
Changed
Section titled “Changed”-
MAChannel::newtakes the upper and lower lengths, and MA Channel draws the simple average of the highs and of the lows, where it drew a simple average of the closes with percentage bands; the LinReg Channel inputmultiplieris replaced byupper_multiplierandlower_multiplier. Saved templates and layouts keep loading. Migration:MAChannel::new(period, offset_percent)becomesMAChannel::new(upper_length, lower_length), withwith_offsets(upper, lower)for bar offsets, and the former lines areEnvelopes::new(period, offset_percent, EnvelopeAverage::Simple); MA Channel colour lists hold the upper line, the lower line and the fill. Code that sets themultiplierinput of LinReg Channel setsupper_multiplierandlower_multiplier. Envelopes colour lists gain the fill as a fourth entry, and LinReg Channel lists gain the upper and lower band fills as a fourth and fifth. Code that relied onEnvelopes::default()at 2.5% orLinearRegressionChannel::default()at 20 bars passes those values tonew. (#1492) -
Drawinggains the public fieldsposition_target_colorandposition_stop_color, andDrawingPropsgainstick_size. Migration: addposition_target_color: Noneandposition_stop_color: NonetoDrawingliterals andtick_size: NonetoDrawingPropsliterals, or end them with..Default::default().DrawingProps::from_drawingreads the tick size of the chart’s instrument; properties assembled by hand supply a positive finitetick_sizeto enable the tick inputs. Saved drawing files stay compatible. (#1408) -
DrawingProps::timeframe_visibility, aTimeframeVisibility, replacesvisible_all_timeframesandvisible_timeframes,TimeframeVisibilitygains the public fieldranges, andDrawingPropertiesAction::Applycarries its properties as aBox<DrawingProps>. Migration: read and set the dialog’s visibility throughDrawingProps::timeframe_visibility, such asprops.timeframe_visibility.show_on_all; addranges: Default::default()toTimeframeVisibilityliterals; buildApplywithBox::new(props), and read a matched payload as before, since its fields are reached through the box.TimeframeUnitmoves from the interval menu tomodel, so the drawings code builds without theuifeature, and is now ordered;ui::top_toolbar::TimeframeUnitkeeps working. (#1368) -
FibonacciConfiggains the public fieldslevel_widthandlevel_style, andChartViewgainsprice_formatter. Migration: addlevel_widthandlevel_styletoFibonacciConfigliterals, or end them with..Default::default(); addprice_formatter: NonetoChartViewliterals, orSome(&formatter)with the host’sPriceFormatterto format the price labels of drawings as the chart does. New drawings use ratio labels and the updated construction defaults, and saved explicit settings stay intact. (#1380, #1381, #1382) -
Trading::is_connectedis false while the broker reports that it is connecting or disconnected, where it was true whenever a broker was set. Migration: code that used it to tell whether a broker is set, for example to show the account panel or to open the broker picker, calls the newTrading::has_broker. (#1484) -
TPOProfile::tpo_count_at,price_levels,letters_atandclassify_shapeno longer take a tick size and key on the profile’s owntick_size, the row heightto_tpo_profilesused. The configured tick they took gave wrong prices and counts onceto_tpo_profileswidened the rows. Migration: drop the tick size argument, so thatprofile.tpo_count_at(price, tick_size)becomesprofile.tpo_count_at(price). (#1308) -
MagnetType::OHLCis removed; it snapped asMagnetType::Strong, which replaces it, so the magnet menu lists Off, Weak and Strong. Migration: useMagnetType::Strong, and read a stored OHLC choice as Strong. Hosts that handle drawing toolbar actions applyDrawingToolbarAction::HideAllby hiding every supported drawing, indicator, position and order group, andDrawingToolbarAction::RemoveDrawingsAndIndicatorsby removing both groups, each in one undo step; the new menu rows do nothing until the host handles them, and position and order handling stays with the host. Measure is no longer a saved drawing, so a host that needs a persistent measurement adds one withDrawingManager::add_drawing; loaded and explicitly added Measure drawings keep ordinary drawing behaviour. (#1409) -
DrawingPropertiesDialogholds its named templates inDrawingPropertiesDialog::templates, kept in memory unless the host attaches itsStorageservice, and restores an unfinished preview when it closes. Migration: construct the dialog withnew()ordefault()instead of a struct literal, retain the instance, and callshow_and_applyeach frame, including after closing it externally. (#1367) -
The drawing storage format is version 3 (
DrawingStorage::CURRENT_VERSION), which tells editable ray and extended-line extensions from flags earlier renderers ignored.DrawingStorage::from_jsonmigrates versions 1 and 2 with those extensions set to their former reach, including the direction of reversed rays, and later saves keep explicit extension edits. Migration: hosts that read the storage JSON themselves must accept version 3; older releases cannot load it. (#1372) -
Envelopes::newtakes its average as anEnvelopeAverage,SimpleorExponential, instead of a string, for which any value but"EMA"computed a simple average under that name. Values, the middle line namesSMA(20)andEMA(20)and saved inputs are unchanged; the Average input lists Simple and Exponential. Migration: passEnvelopeAverage::Simplefor"SMA"andEnvelopeAverage::Exponentialfor"EMA". (#1333) -
IndicatorFactory::registerandregister_inreturn whether they registered the constructor, and refuse a name that is empty or only whitespace. A constructor already registered under the name, a built-in included, is replaced, as before. Migration: a call used as a value of type(), such as a match arm or the last expression of a closure, ends with a semicolon. (#1335) -
Built-in studies have refined default colours, transparencies, widths and line styles that read on the light and dark themes. Averages and VWAP are blue, oscillators use individual hues with muted dotted or dashed guides, and Bollinger Bands have a red upper boundary, a blue basis, a teal lower boundary and a faint blue fill. Volume columns are teal and red at 50% opacity. MACD, PPO and PVO histograms shade rising and easing columns above and below zero. Study legend backdrops default to 60% opacity and fit their text. Volume profiles draw the point of control as a solid line in the text colour and hide the value area boundaries unless
VolumeProfileConfig::show_value_area_linesis set; TPO profiles hide single prints by default. A pitchfork with edited levels fills each band in the colour of its outer level. Saved explicit study colours and palettes load unchanged. Migration:studies::paletteconstants keep their names with refined values;DEEP_GREEN,DEEP_ORANGE,GOLDandINDIGOare removed, so code that named them uses the values they held (Color32::from_rgb(27, 94, 32),(255, 87, 34),(255, 193, 7)and(63, 81, 181)).VolumeProfileConfigliterals addvalue_area_colorsandshow_value_area_linesor use..Default::default(). (#1298) -
The long and short position tools draw their handles only while selected, from the shared handle painter, and stroke only the entry line. The target and stop labels are sized to their text and centred above and below the box, with the amount gained at the target and lost at the stop; the P&L, quantity, risk/reward and capital sit in one block on the entry line, on the stop side, coloured by the result; and a dashed line runs from the entry to the exit, over the part of the zone the trade covered. Compact labels, muted theme-aware fills, finer hollow handles and a thin light border around the selected stats block keep the chart readable in both themes. Migration:
PositionToolSizingTokensloseslabel_info_width,label_info_height,label_target_width,label_offset_xandtext_offset_x, which no layout uses any more. (#1266) -
TickMarkType::TimeWithMillisecondsmarks fractional-second ticks and subsecond crosshair clocks. Migration: exhaustiveTickMarkTypematches handle the new variant, and customTimeFormatters format it, as the trait default now asks for it instead of appending the fraction to a seconds clock. (#1227, #1228) -
Chart’s per-frame pan, zoom, tracking, focus, keyboard and drawing handlers, includinghandle_drawingsandrender_eraser_highlight, andcalculate_bar_spacingare now crate-private; unusedcalculate_visible_barsis removed. Migration: input is handled byChart::show; dispatch host shortcuts withChart::dispatch_shortcuts, and zoom from code withset_visible_logical_rangeorexecute_box_zoom.execute_box_zoomremains public andzoom_backundoes it. (#1311) -
TPO charts use a smooth period gradient, separated blocks, neutral POC rows and initial balance bars, compact value-area and midpoint labels, and a thin price path. Profiles have clearer session spacing and theme-aware contrast in dark and light views; when sessions are too narrow to hold the labels, as on zoomed-out daily charts, the labels are left out and the profiles keep their full session width. (#1296)
-
Session volume profiles use faint session boxes, blue and violet volume stacks, distinct value-area shading and thin red POC lines in dark and light themes. Default value-area guides, node labels and developing traces are hidden; shared trade-profile rows gain crisp gaps, theme-aware value-area opacity and a thinner POC stroke. (#1297)
-
UserSettingsis#[non_exhaustive], so that fields can be added without a breaking change. Migration: buildUserSettingswithDefaultand assign fields.IndicatorDialogActionimplementsCloneandDebug, andSettingsActionimplementsDebug. -
Migration for scale settings:
ScalesAndLinesSettings,ChartConfigandPriceAxisOptionsliterals add the new display fields or use..Default::default(). Older saved settings take their defaults.chart::render_axis_currencytakes an optional unit before the currency choices; passNonefor the previous header.PriceScale::set_bar_ratioaccepts a positive finite number of scale units per bar, withNoneunlocking it; logarithmic axes measure natural logarithms of prices. -
EventVisibilitystruct literals addshow_earnings_breaks,show_news_notificationsandshow_ideasor end with..Default::default(); saved visibility without them takes the defaults. -
chart::render_alert_levelstakesactive_onlyafterlabels; passtrueto keep drawing only active alerts.AlertsSettingsliterals addshow_active_onlyandnotification_secondsor use..Default::default(); older saved settings take defaults. Hosts apply lifetime throughAlertsPanel::set_notification_seconds; sound playback uses the existing host audio path. -
ChartTypeStyles,CandleColorConfig,StatusLineOptionsandChartSettingsStategain the requested candle, status and dividend fields. Struct literals add the fields or use..Default::default(); older saved settings take defaults.chart::render_candletakes the rising/falling direction after the bar and&CandlesStylelast; passbar.is_bullish()and&CandlesStyle::default()for the previous drawing behaviour. -
Chart settings use seven tab pictograms, a 206 point sidebar with 40 point rows, neutral selection and an undimmed backdrop. Shared dialog titles use semibold 20 point text, and footer actions are at least 44 by 34 points with a primary fill in the theme text colour. (#991)
-
The chart layout menu shows arrangement diagrams grouped by chart count from 1 through 16, including available alternatives, and highlights the active arrangement. Hover labels name each arrangement and explain synchronization effects. Short windows scroll the menu. (#997)
-
The indicator browser lists Profiles and Patterns and searches across built-in pages.
IndicatorFactory::register_inaccepts host categories, includingPERSONALfor My scripts andCOMMUNITYfor shared studies. Destinations without compatible studies stay hidden, host-only catalogues open their populated page, and Favorites retains its explanatory empty state. Migration: exhaustiveIndicatorCategorymatches handleMyScripts; volume and time price profiles now use theProfilesfactory category (IndicatorFactory::PROFILES) instead ofVolume. (#972) -
A click, or Enter or Space, on an indicator browser result adds the study at once with its default inputs, and the browser stays open for the next one; an added study’s inputs are edited through its settings with
IndicatorSettingsDialog. A source the study rejects is reported above the results. Migration: the parameter panel is removed withIndicatorParams,IndicatorDialog::{selected, params, params_mut, input_summary}andIndicatorDialogConfig::{sel_color, sel_text_color}; caption an added study from itsIndicator::inputs, and callIndicatorDialog::closeonIndicatorDialogAction::AddIndicatorto keep adding one study per visit. (#971) -
Symbol details inset the title and price by 10 points inside the host panel and enlarge the main price to 26 points. The supplied
SymbolDetails::categoryappears below the name, key statistics sit on a tinted card, and prices use the watchlist’s thousands grouping. (#990) -
Watchlist rows are 30 points high with an 18 point symbol mark and aligned names.
WatchlistPanel::set_marksupplies a mark; rows without one show an initial on a neutral disc. Prices and changes use thousands grouping, so 43237.45 reads 43,237.45, and changes omit the sign when they round to zero. (#989) -
Chart layout uses the shared dark toolbar tooltip with consistent padding and no shortcut chip when no shortcut is bound. (#1011)
-
Sell and Buy quote buttons use outlines and matching text on the chart background, with a minimum width of 59 points. Bid and Ask axis tags default to hidden while saved choices remain intact; volume shows a compact last-value tag when study values are enabled. (#988)
-
The demo allocates 25% of the price pane to overlay volume, keeping the columns on the plot bottom and the height configurable through
ChartConfig::volume_height_fraction. (#987) -
Light crosshair tags use black fills and white text, with dashed crosshair ink at approximately #9C9C9C on the white plot. (#1007)
-
The light preset draws grid lines in #D1D1D1 instead of #DCDCDC, so the dotted grid stays visible on the white plot. Horizontal and vertical grid lines keep their separate visibility settings. (#1010)
-
Crate and public API documentation now describe host-supplied history and streaming data, current feature boundaries and a populated quick start. Stale capability claims, counts and implementation inventories are removed, and the README and package description use the same scope. (#933)
-
Charts follow active theme changes for inherited background, grid, text, candle, border and wick colours, retaining host edits and per-chart overrides. Chart titles, OHLC and pane legends, secondary series, trading labels and chart controls read the active text, spacing and radius scales. Clearing an override rejoins the current context palette. Migration: a default
ChartBuildernow follows the active theme; callwith_theme(Theme::dark())to retain a fixed dark chart beside a differently themed UI. Settings dialogs readThemedirectly; UI chrome, shared buttons, forms, lists and dialog padding use the applied text, spacing and radius scales. Applying a theme also updates egui’s built-in text sizes while retaining font families. Study defaults now usestudies::palette, preserving their existing colours independently of UI status colours; unused study and extended colour tokens have been removed. Migration: replace the removedtheme::components::{DialogStyle, SettingsDialogStyle, ContextMenuStyle}and their theme re-exports withThemefields or egui visuals; replaceDESIGN_TOKENS.typographyandTypographyTokenswiththeme.text; pass&Uiinstead of&VisualstoStyledPanelFrameconstructors so separate frames also read the applied scales. RemoveSemanticTokens::{buttons, alert, modal, command_palette}and their correspondingButtonSemanticTokens,AlertSemanticTokens,ModalSemanticTokensandCommandPaletteSemanticTokensliterals;UiSemanticTokensretains only the engine fallbackstext_muted_darkandborder_dark.TextSizesliterals addmicro,markeranddialog_titleor use..Default::default(); saved themes default missing roles. See theme integration. (#356) -
The next release is 0.3.0. Public implementation modules are private, extensible options and output records are non-exhaustive, and growing chart, interval, drawing, study and host-intent enums require fallback matches. The timezone formatter wrapper is crate-private; hosts keep using
TimeFormatterBuilder::with_timezone. Main stateful types retain their private fields and accessors. Public configuration and data fields remain intentionally editable. CI compares the API with the latest published crate version and also gates release publication. Before 1.0, an incompatible API or exposed egui upgrade requires a new minor release; from 1.0 it requires a major release. The 0.3 line uses egui 0.37; compatible egui patch upgrades may ship in patch releases. (#253)Old path or construction New path or construction widget::builder::ChartBuilderwidget::ChartBuilderor the crate-rootChartBuilderwidget::indicator_pane::ChartMappingchart::coords::ChartMappingwidget::indicator_pane::{IndicatorCoordParams, IndicatorPane, IndicatorPaneConfig, PaneInteraction}widget::{IndicatorCoordParams, IndicatorPane, IndicatorPaneConfig, PaneInteraction}widget::keyboard::{ShortcutMap, ShortcutRequest}widget::{ShortcutMap, ShortcutRequest}widget::layout::{ChartLayout, ChartLayoutMode, ChartSyncOptions}widget::{ChartLayout, ChartLayoutMode, ChartSyncOptions}widget::export::{ChartImage, ImageExportOptions}widget::{ChartImage, ImageExportOptions}chart::selection::{SeriesId, ChartElementId}widget::{SeriesId, ChartElementId}; useChart::{selected_element, selected_bar, clear_selection}instead of selection state helperschart::selection::{SelectionState, SelectableId}Use Chart::{selected_element, selected_bar, clear_selection}for a chart, or a host-ownedOption<Id>for standalone selectionComplete literals of config::{ChartConfig, ChartOptions, CrosshairOptions, TooltipOptions},widget::ImageExportOptionsStart from constructors or Defaultand assign fields; struct literals, including update syntax, are unavailable. Output geometry and image records are returned by the chartComplete literals of widget::{RenderedIndicatorPane, ChartLayoutRects, PaneInteraction, ChartImage}Obtain output geometry and image records from the chart and pane methods; PaneInteraction::default()remains availableExhaustive matches on growing chart, timeframe, drawing, keyboard, event, study and UI intent enums Add a fallback arm for future variants TimeframeSelectorConfig::{item_height, bg_color, hover_color, sel_color, text_color, muted_color, favorite_color}Removed unused options; rows use the menu layout and colours use the active theme. btn_widthanddropdown_widthremain supportedTimeframeAction::AddCustomRemoved unused intent; custom intervals emit TimeframeAction::Select -
Runtime module dependencies are acyclic. Shared bar interpolation, streaming study inputs, profile calculations and formatting live below rendering; study geometry and timestamp drawing methods live with their chart and widget consumers. Chart settings and study recipes no longer depend on UI modules, localization is shared at the crate root, and UI extension traits live beside the UI kit. CI rejects module cycles and inherent methods defined outside their type’s module. The crate remains one package. (#93)
Old path or member New path or member model::{ChartState, ZoomState}studies::{ChartState, ZoomState}studies::{OrderFlowInput, OrderFlowKind, ProfileDisplay, StudyProfile, VolumeProfile, VolumeProfileConfig}data::{OrderFlowInput, OrderFlowKind, ProfileDisplay, StudyProfile, VolumeProfile, VolumeProfileConfig}drawings::{ProfileDisplay, VolumeProfileConfig},drawings::domain::{ProfileDisplay, VolumeProfileConfig},drawings::domain::options::{ProfileDisplay, VolumeProfileConfig}data::{ProfileDisplay, VolumeProfileConfig}studies::StudyFormatscales::StudyFormatservices::PriceTargetsdata::PriceTargetsui::dialogs::templates::StudyTemplatestudies::StudyTemplatewidget::localizationlocalizationext::{UiExt, ResponseExt, ButtonWidgetExt, TextEditWidgetExt, RoundingExt}ui_kit::ext::{UiExt, ResponseExt, ButtonWidgetExt, TextEditWidgetExt, RoundingExt}Theme::apply_to_config(config)config.with_theme(&theme)ChartSettingsState::{background_color, grid_color, sync_legacy_fields}Use chart_basic_styles.background_colorandgrid_lines.horizontal_colordirectly; the redundant mirrors and synchronization method are removedui::top_toolbar::components::settings_menu::data::EventsSettingsand its settings-menu re-exportmodel::EventVisibilityui::top_toolbar::{CandleColorConfig, StatusLineOptions, ChartSettingsState, PrecisionMode}widget::settings::{CandleColorConfig, StatusLineOptions, ChartSettingsState, PrecisionMode}ui::top_toolbar::components::{CandleColorConfig, StatusLineOptions, ChartSettingsState, PrecisionMode}widget::settings::{CandleColorConfig, StatusLineOptions, ChartSettingsState, PrecisionMode}ui::top_toolbar::components::settings_menu::{CandleColorConfig, StatusLineOptions, ChartBasicStylesSettings, GridLinesSettings, CrosshairSettings, WatermarkSettings, ScalesAppearanceSettings, ButtonsSettings, MarginsSettings, ScalesAndLinesSettings, TradingSettings, TradingNotifications, AlertsSettings, ChartSettingsState, BackgroundType, GridLinesMode, ButtonVisibility, WatermarkMode, PrecisionMode}widget::settings::{CandleColorConfig, StatusLineOptions, ChartBasicStylesSettings, GridLinesSettings, CrosshairSettings, WatermarkSettings, ScalesAppearanceSettings, ButtonsSettings, MarginsSettings, ScalesAndLinesSettings, TradingSettings, TradingNotifications, AlertsSettings, ChartSettingsState, BackgroundType, GridLinesMode, ButtonVisibility, WatermarkMode, PrecisionMode}ui::top_toolbar::components::settings_menu::data::{CandleColorConfig, StatusLineOptions, ChartBasicStylesSettings, GridLinesSettings, CrosshairSettings, WatermarkSettings, ScalesAppearanceSettings, ButtonsSettings, MarginsSettings, ScalesAndLinesSettings, TradingSettings, TradingNotifications, AlertsSettings, ChartSettingsState}widget::settings::{CandleColorConfig, StatusLineOptions, ChartBasicStylesSettings, GridLinesSettings, CrosshairSettings, WatermarkSettings, ScalesAppearanceSettings, ButtonsSettings, MarginsSettings, ScalesAndLinesSettings, TradingSettings, TradingNotifications, AlertsSettings, ChartSettingsState}ui::top_toolbar::components::settings_menu::types::{BackgroundType, GridLinesMode, ButtonVisibility, WatermarkMode, PrecisionMode}widget::settings::{BackgroundType, GridLinesMode, ButtonVisibility, WatermarkMode, PrecisionMode} -
Breaking API cleanup: interval controls, settings, drawings, studies and trading share the domain types below. The small
preludeexports common host types and traits, with widget exports following their feature. There are no compatibility aliases. Symbol search returns the host’sInstrumentwith its metadata intact. (#95)Old path or member New path or member ui::top_toolbar::Timeframe,ui::top_toolbar::components::Timeframe,ui::top_toolbar::components::timeframe_selector::Timeframemodel::Timeframe; use its variants or parse"7min", and pass it directly to the selectordrawings::LineStyle,drawings::domain::LineStyle,drawings::domain::options::LineStylemodel::LineStyleconfig::CrosshairLineStyle,config::SessionBreakStylemodel::LineStyle; crosshair and session defaults remain dotted and dashed respectivelystudies::PlotPatternmodel::LineStyleui::top_toolbar::components::settings_menu::LineStyle,ui::top_toolbar::components::settings_menu::data::LineStylemodel::LineStyleui::widget_bar::LineStyle,ui::widget_bar::panels::LineStyle,ui::widget_bar::panels::object_tree::LineStyle,ui::widget_bar::panels::object_tree::types::LineStylemodel::LineStyle::name()replacesas_str()ui::dialogs::DrawingLineStyle,ui::dialogs::drawing_properties::DrawingLineStyle,ui::dialogs::drawing_properties::actions::DrawingLineStylemodel::LineStyle;name()replaceslabel(),all().iter().copied()yields valuesmodel::TradeSide,model::quote::TradeSidemodel::OrderSide; unknown aggressors remainNonemodel::StrategySide::{Long, Short}model::OrderSide::{Buy, Sell}; migrate saved strategy sides from"Long"/"Short"to"Buy"/"Sell"model::Symbolmodel::Instrument;namebecomessymbol,display_namebecomes optionaldescription,exchangebecomes optional, and subscription state belongs to the host; usewith_exchangeandwith_symbol_typeinstead ofwith_marketui::symbol_header::SymbolInfo,SymbolHeader::symbol_infomodel::Instrument,SymbolHeader::instrument; pass the interval label separately toSymbolHeader::new(instrument, timeframe)ui::top_toolbar::ScaleMode,ui::top_toolbar::components::ScaleMode,ui::top_toolbar::components::settings_menu::ScaleMode,ui::top_toolbar::components::settings_menu::types::ScaleModescales::PriceScaleMode;AutobecomesNormalui::top_toolbar::components::settings_menu::types::{CandleColorConfig, StatusLineOptions}widget::settings::{CandleColorConfig, StatusLineOptions}; use..Default::default()for additional status fieldsIndicator::line_cnt,CustomIndicator::with_line_cnt,LineBreakConfig::line_cntIndicator::line_count,CustomIndicator::with_line_count,LineBreakConfig::line_countui::top_toolbar::components::settings_menu::TradingSettings::show_possTradingSettings::show_positions; migrate the saved JSON key tooThe selector accepts model intervals directly, including subsecond presets, and preserves full nonzero execution counts and custom seconds in its labels.
Interval preferences now serialize
model::Timeframevalues instead of{value, unit}objects. Convert each old entry with its unit (Minuteuses"min",Monthuses"month"), parse it and serialize the resulting value. Presets and arbitrary intervals use the same nonzero model representation. Existing line-pattern JSON variant names are unchanged. -
IANA time zones and daylight-saving rules are behind the
timezonesfeature, enabled by default, so builds withdefault-features = falseomitchrono-tz. UTC, system local time and signed fixed offsets remain available. All time zone APIs now usemodel::TimezoneId, includingTimezoneMode::{Timezone, Exchange},TimezoneMode::to_tz,BarClock::with_timezone,TimeAndSalesConfig::timezoneandSymbolDetailsPanel::set_timezone. Migration: replace achrono_tzconstant with a parsed name such as"America/New_York".parse()?; add"timezones"to an explicit feature list to keep named exchange zones and presets. Without it, Trading Sessions uses fixed standard-time offsets (+09:00, +00:00 and -05:00), configurable throughwith_session. Use offsets such as"+05:45".parse()?orTimezoneId::fixed_offset(seconds); unknown or unavailable names are rejected instead of approximated. Persisted named-zone strings retain their format. Session presets and the settings time zone list also use fixed offsets withouttimezones. CI checks licences and duplicate versions in both the library and demo againstdeny.toml, with pinned exceptions for existing upstream version splits. (#256) -
Ordinary solid study lines draw each uninterrupted run as one joined path instead of a separate shape for every pair of bars, reducing painting and tessellation work on charts with many studies while keeping gaps, colours and stroke widths. Directional colours and gradient fills retain their segment rendering. The README links performance notes with application-owned glibc allocator settings for large native charts. (#472)
-
Replay no longer holds a separate simulated balance or position. Migration: use
services::PaperAccountthroughBrokerinstead ofTradingSimulationState,ReplayState::trading_sim, the simulation actions onReplayAction, or the trading fields onReplayBehavior. (#221) -
WatchlistPanel::set_quoteandSymbolDetailsPanel::set_quotetake amodel::Quote, which carries the update time, extended-hours trade and session volume, andSymbolHeader::quoteis anOption<Quote>whose bid and ask show when both are known.ExtendedHoursQuoteandExtendedSessionmoved fromui::widget_bartomodel. The symbol details panel takes its price decimals from the instrument, or from the size of the price. Migration: buildQuote::new(last, prev_close, time)in place of aWatchlistQuoteand pass its decimals toWatchlistPanel::set_price_decimals; replaceSymbolDetailsPanel::set_extended_hourswithQuote::with_extended, andset_volume(volume, average)withQuote::with_volumeandset_average_volume; setSymbolHeader::quotetoSome(Quote::new(..).with_bid_ask(bid, ask))in place of aQuoteData. (#222) -
The chart’s order book keys levels by the nearest integer tick of the instrument’s tick size, so a feed that computes prices with rounding errors updates and removes the level it means instead of adding a neighbour. A crossed book is kept as the feed sends it, and
Sink::push_quotenow keeps a crossed quote, the top of such a book, instead of rejecting it. (#229) -
Sink::push_depth_deltatakes the delta by reference, so a feed can clear and refill oneOrderBookfor every update instead of allocating its levels per message, and the chart’s book keeps each side in a sorted array that reuses its capacity, so applying a delta allocates nothing once the sides reached their depth. Migration: pass&changes. (#228) -
The web demo builds with the
wasm-releaseprofile, whole-program optimisation atopt-level = "s", which cuts its download by 15%; native builds keeprelease. The library defines the same profile for its own web builds, andscripts/web-size.shbuilds the demo and the bare chart for the web and prints their raw, gzip and brotli sizes.examples/bare_chart.rsnow also runs in the browser, where it applies the dark theme, so its web build carries Roboto alone instead of egui’s default fonts. The demo renders with eframe’sglowbackend instead ofwgpu, which takes another 17% off its download, and exports images through an offscreen framebuffer. The crate documentation lists these steps for an application’s web build, with chrono-tz’sfilter-by-regexto keep only the time zones it needs. (#251) -
Zoomed out until several bars share a physical pixel, a time-based chart draws them merged, about one bar per pixel column, instead of every bar. Candles, bars, columns, HLC area and high-low merge each group into its first open, highest high, lowest low and last close with its highest volume. Line, step, area and baseline charts keep the first, lowest, highest and last value of each group at their own bars, which draws the same line through the column. Groups with whitespace or per-bar colours retain their source bars for drawing, so gaps and individual styles stay visible. Volume, the time axis, sessions and hit testing read the merged groups, which are aligned to multiples of a power of two so panning keeps them, and are rebuilt only when the bars, the zoom step or the price source change. One chart of 1,000,000 bars all in view now paints 3,043 shapes in a 12 ms frame instead of 3,000,104 shapes in 1,864 ms, measured by the new scenario of
benches/frame_time.rs. Heikin-Ashi, price-based and TPO charts, and study plots other than the volume on the main pane, still draw every bar. (#834) -
Bars charts draw their bars and ticks with
ChartConfig::wick_width, one point by default, instead of a fixed 1.5 point stroke, so they stay as crisp as candle wicks. Turn offBarsStyle::thin_barsfor bars that widen with the zoom. (#832) -
Panes keep their proportions when the chart is resized: dragging a separator and a study’s preferred pane height now set stretch factors instead of fixed pixel heights. A double click on a separator still restores the default shares. (#827)
-
PriceScaleMarginsare shares of the pane height rather than of the data range, as the chart settings dialog already presented them: the default 10% above and below keeps the data in the middle 80% of the pane, and margins that leave no room for the data are ignored.PriceMarkGeneratorConfigdefaults to a 20 pixelmin_spacingand 100max_marks, sotarget_densityalone sets the spacing, which stays 40 pixels by default. (#833) -
DetrendedPriceOscillatordefaults to the conventional length 21 in its non-centred form, the close minus the 21-bar SMA of 11 bars earlier, aligned with the current bar. The newcenteredinput, orwith_centered(true), selects the centred form, the close 11 bars back minus the SMA, which is now stored at the bar that completes the average and drawn back throughplot_offset, so it no longer reads later bars and fills the bars a previous rule left blank. Bars with a non-finite close are skipped and the pane draws a zero level. Migration: for the previous series useDetrendedPriceOscillator::new(20).with_centered(true)and read a centred value withplot_value, or at its source bar plusperiod / 2 + 1. (#176) -
PivotPointsis the Pivot Points Standard study: levels for each day, week, month, quarter or year of exchange trading days come from the previous period’s open, high, low and close, counted in the instrument’s time zone and session as VWAP counts them, instead of a rolling window of bars.PivotTimeframe::Auto, the default, picks the period from the chart interval: daily up to 15 minutes, weekly below a day, monthly below a week and yearly above. The Traditional, Fibonacci, Woodie (with the current period’s open), Classic, DM and Camarilla types output P, R1, S1 through R5, S5, NaN where a type has no such level, for the last 15 periods by default (with_pivots_back). Lines are constant within a period and not drawn across the change to the next.AnchorPeriodnames the calendar periods. Migration:PivotPoints::new(period)becomesPivotPoints::new()withwith_method,with_timeframeandwith_pivots_back;PivotMethod::StandardisTraditionalandDeMarkisDM, which now has P, R1 and S1 only; the catalogue name"Pivot Points"is"Pivot Points Standard"; values are eleven lines in the order above instead of[Pivot, S1, S2, S3, R1, R2, R3], andset_colorssets them line by line. Saved study templates of the previous study no longer load. (#176) -
The widget bar’s bottom section keeps host entries at the foot of the bar above its line, with Help below the line, so a lower group of host panels stands apart from Help. Without host entries the bottom section is unchanged. The demo opens with its watchlist and the chart symbol’s details in a 300 point panel, lists the watchlist before Alerts and the Object Tree, and moves Data Window, Time and sales and Session notes to the lower group; compact windows still start with the chart alone.
-
The built-in
Volumestudy starts with its moving average off and draws its columns in the theme’s rising and falling volume colours at reduced opacity; the chart’s volume switch applies the active theme’svolume_upandvolume_down. Its legend row reads Vol and the bar’s volume in the study’s declared volume format (154, 64.55M), coloured like that bar’s column. The study no longer fixes three decimals. Migration: turn the average on withVolume::with_average(Some(VolumeAverage::Simple))or the Moving average input, and set a precision override in the study settings to keep three decimals. (#817) -
KineticScrollOptions::dumping_coeffis renamed todamping_coeff, the share of kinetic scroll velocity kept per frame; its default and effect are unchanged. Migration: replacedumping_coeffwithdamping_coeffin field access and struct literals. (#369) -
Chart menu orders choose sides relative to the last price, use the quantity and capabilities from
ChartMenus::set_order_entries, and open the ticket for confirmation. At the market price they may fill immediately. Migration: replaceContextMenuAction::SellLimitandBuyStopwithOrder(OrderRequest);ChartContextMenuliterals addmarket_price,tick_size,order_quantityandorder_types, or usenew(). (#218) -
Chart navigation buttons default to
NavigationButtons::Never, leaving the plot clear on hover. SetOnHoverorAlwaysto show the existing controls; keyboard navigation stays available. The settings dialog starts with the same hidden choice, and the row hides if it cannot fit in the pane. -
The plot uses the chart interior with a floating legend and the configured axis widths instead of fixed 40 point insets.
ChartConfig::paddingdefaults to 0.ChartConfig::volume_baseline_insetmakes the volume baseline configurable, retaining the 12 point default; set it to 0 andvolume_height_fractionto 0.25 for a flush quarter-height overlay. Axis ticks that would cross the plot edge are omitted. Migration: struct literals ofChartConfigsetvolume_baseline_insetor use..Default::default(). The unusedstyles::sizing::chart::{TOP_PADDING_WITH_OHLC, TOP_PADDING_NO_OHLC, BOTTOM_PADDING_NO_TIME, MIN_CHART_WIDTH, MIN_CHART_HEIGHT}constants are removed; useChart::calculate_layout_rectsfor configured bounds. -
Light chart grids use 1 point dots with 3 point gaps in #dcdcdc, for both price and time lines. Explicit grid colours are kept; dark chart grids use the same dotted strokes.
-
The light preset uses neutral text, separators, control states and panel gaps, white plot and axis surfaces, and #089981 up candles and #f23645 down candles. Semantic success and error colours stay separate from the candle palette.
-
theme::apply_to_eguiinstalls the bundled Roboto Latin subset with tabular digits, at weight 400 with semibold symbols and time-axis years. Toolbar text is 14 px, legend values 13 px with 16 px titles, axes and price tags 12 px, and the bottom bar 14 px, with its right controls reserved at their actual width.TimeframeToolbarSizingTokensandSizingTokens::timeframe_toolbarare removed because the reservation follows the controls. Migration: remove those token fields from struct literals; to replace the bundled face, callegui::Context::set_fontsafter applying the theme. -
Volume bars take #26a69a up and #ef5350 down from the theme at 60% opacity in dark. The library defaults stand 12 points above the price pane bottom, reach 12% of the height above that baseline and span 80% of the bar pitch, with candle bodies defaulting to 60%. Reported layout bounds, hit testing and selection handles follow the overlaid bars.
-
Bollinger Bands default to #2962ff upper and lower bands and a #ffa726 basis, and overlay study lines default to 1 point instead of 2. Study colour overrides and oscillator pane widths stay the same.
-
The dark preset uses #000000 for panels, plot and axes, #2a2a2a separators, #dbdbdb text and toolbar icons, #b8b8b8 secondary text and time labels, #707070 muted text, #575757 disabled text, white price labels, #222222 grid lines, #089981 up candles, #f23645 down candles and #3179f5 active toggles. Light and high contrast preset values stay the same.
-
On Renko, Kagi, Line Break, Point and Figure and range bar charts, the indices the chart reports and accepts count elements instead of bars: the
TimeScaleandvisible_rangeofChartState,ChartState::visible_data(one bar per element),Chart::set_start_idx,get_start_idx,get_visible_bars,get_chart_mapping,selected_bar,get_hover_bar_idx,set_synced_crosshair_bar_idxandRightClickTarget::Element::bar_idx.Chart::set_chart_type, andset_chart_type_paramson these types, clear the zoom history when the value changes. Migration: read the bars fromChart::bars, and find the bars of an element by its time. -
Studies, drawings and markers are not drawn on Renko, Kagi, Line Break, Point and Figure and range bar charts, whose bricks, lines and columns do not map onto the bars they are anchored to. They cannot be selected, edited or hit there, and studies do not count in the price fit. They are kept, studies stay up to date, and they show again on the other chart types; a note in the price pane says what is hidden. These chart types draw no volume and no longer reserve a volume area.
Chart::set_chart_typeclears the selection when the type changes. -
The indicator dialog lists every study of its
IndicatorFactoryinstead of 24 hardcoded entries, each row showing the full name and the explanation from the study’sIndicator::desc(the registered name when the description has no “Full name - ” prefix), sorted by that name and searchable by its registered name and category, and creates the one added through the factory, so a study the host registers is offered too.IndicatorDialog::with_factorysets the factory andIndicatorDialogAction::AddIndicatorcarries the created study. Migration: replacewith_indicatorswithwith_factory, and handleAddIndicator(study)by addingstudyto the chart instead of callingcreate_indicatoronAddConfiguredIndicator;IndicatorType,ConfiguredIndicator,IndicatorInfo::builtin_indicatorsandIndicatorInfo::indicator_typeare removed, andIndicatorInfo::idis the factory name, so favourites andToggleFavoriteids saved under the old ids (“sma”, “bb”, “stoch”) must be mapped to factory names (“SMA”, “BB”, “Stochastic”). -
Volume bubbles are drawn by the chart from the trades its feed sends:
Chart::set_volume_bubblesturns them on with achart::overlays::VolumeBubblesConfig. Trades are summed per bar and price level (price_step, else the instrument’s tick size) as they arrive, and a frame reads only the bubbles of the visible bars, the levels of a bar that fall on one pixel row drawing as one bubble, so its cost follows the bubbles in view instead of growing with the square of the trades held: 16,000 trades that did not merge took 1.6 s per frame before; now 100,000 held trades over 1,667 one-minute bars, 40 levels a bar, draw 200 bars in 45 ms including tessellation, and 100,000 trades at 100,000 prices all in view in 15 ms. The bubbles hold no trade the chart’s bounded trade store has dropped, and Renko, Kagi, line break, point and figure and range charts draw none, since their x axis is not time. Sizes scale over the visible bubbles, a volume more thanclamp_std_devsstandard deviations (3 by default) above their mean draws at the maximum diameter so one large print does not shrink the rest, andcolor_bycolours a bubble by its dominant aggressor side (BubbleColor::Side) or blends the sell and buy colours by its delta (BubbleColor::Delta). Migration:VolumeBubbles,TradeBubble,AggregatedBubble,VolumeBubblesConfig::aggregate_nearbyandVolumeBubblesConfig::aggregate_thresholdare removed: push trades into the feed’sSinkwithpush_tickand pass the configuration toChart::set_volume_bubbles; struct literals ofVolumeBubblesConfigsetcolor_by,clamp_std_devsandprice_stepor use..Default::default(). (#234) -
The last-price line is drawn as a price line: the same width, with the standard dashed pattern (8 points on, 4 off) instead of its shorter dashes.
-
The export dialog uses the kit dialog chrome: a left-aligned title with a close button, one form grid with sentence-case labels, an instruction as the path hint, and a footer with Export as the primary action. Enter exports, and Escape closes it unless a field has the focus, which it leaves instead. An empty path keeps the dialog open, shows the error under the field and focuses it. The file path field is named by its label.
-
config::KeyboardAction::all_by_categoryreturns only the actions whose keys are handled, in five categories, andKeyboardAction::labeluses sentence case (“Zoom in more”, “Jump to latest”). -
The go to date picker is a modal titled “Go to date” in the dialog chrome, over a dimmed backdrop, and Escape closes it. It always shows six weeks, with the days of the previous and next month muted and selectable, so it keeps its height in every month. Chevron buttons at the edges of the grid change the month, the footer has a ghost Today button and Go as the primary action, a range shows both of its ends filled and the days between in a light accent, and today has a ring. When the picker opens, the date field has the focus with its text selected, and Enter applies Go. Each day reports its date and selected state to accessibility tools and shows a focus ring. Today is the current UTC date, the time zone of the chart’s time axis by default. (#299)
-
The indicator dialog is a kit
Modal: the shared title row, frame and scrim, Escape and a click outside close it, and it keeps its configured height, clamped to the window and following it when the window shrinks, with only the result list scrolling. The search field is the kit filter field with a search icon and a clear button, focused on open; Escape clears a search before it closes the dialog. Tabs useTabBarand categoriesSidebarTabwith their own icons. Rows show a star icon with a tooltip, the name at 13 px over an 11 px description in the secondary text colour, cut off before outlined badges that sit inside the row padding clear of the scroll bar, and the theme’s selection colours when selected. ArrowDown in the search field moves to the first row, the arrows move between rows, Enter selects a row and Enter on the selected row adds it. Each empty list has its own empty state. The configuration panel lays out its parameters in aFormGridand ends in aDialogFooterwhose Back button returns to the list instead of closing the dialog. -
Chart::set_renko_brick_size,renko_brick_size,set_kagi_reversal_amountandkagi_reversal_amountare replaced byset_chart_type_paramsandchart_type_params, which hold the sizes of all price-based chart types.ChartTypeParams::baseline_priceis replaced bybaseline: BaselineLevel, and the defaults are now 1.0 for every size (the unused struct said 4.0 and 10.0). Migration:let mut p = chart.chart_type_params().clone(); p.renko_brick_size = 2.0; chart.set_chart_type_params(p);. -
ChartTypehas a new variant,Columns. Migration: an exhaustivematchonChartTypeneeds aChartType::Columnsarm. -
ui_kit::EmptyState::showreturnsbool, whether the action was clicked, instead of(). Migration: anEmptyState::showcall in a place that expects(), such as the last expression of anifwithoutelse, takes a semicolon. -
egui-charts depends on egui, egui_extras and ecolor 0.37 instead of 0.33 and needs Rust 1.95. Migration: move the application to egui and eframe 0.37 and Rust 1.95. An eframe application implements
App::ui, which receives the rootUi, instead ofApp::update, and shows its panels inside thatUiwithshow(ui, ..)onegui::Panel::top,bottom,leftorright(which replaceTopBottomPanelandSidePanel) and onCentralPanel. egui creates the rootUibefore the application runs, so a call toapply_to_eguiinApp::uiis followed byui.set_style(ui.ctx().global_style()). The id and id salt parameters ofUiExt::combo_select,combo_select_width,combo_str_selectandcombo_str_select_width,ColorPicker::new,color_picker_btn,ModalHandler::new,Modal::new,SimpleModal::new,show_modal,PromptDialog::new,prompt,prompt_with_message,ConfirmDialog::new,confirm,confirm_danger,AutocompleteEdit::id_salt,Section::new,ResponsiveToolbar::horizontalandvertical, andRangeSwitcher::with_idrequireHash + Debug, as egui’s ids do, so an id type of the application’s own needsDebug. Code that buildstokens::SizingTokenswith a struct literal sets the newcontrol_height. egui 0.37’sdefault_fontscontain no emoji: enable egui’smonochrome_emoji_fontsfeature or install a font that has them. Panel sizes and other widget state that egui persisted (window sizes, collapsed headers, scroll offsets) reset once, because egui derives panel and child ids differently. An eframe build with default features off enables eframe’sclipboardfeature for copy and paste. -
apply_to_eguisets the button padding (4 x 1), control height (18) and corner radius (2) of egui’s built-in widgets, so they keep the size they had with egui 0.33 instead of egui 0.37’s 8 x 2, 20 and 4 to 6. An application that sets these itself does so afterapply_to_egui. -
egui fills the title bar of the window on top with
widgets.open.weak_bg_fill; since 0.35 it does so also for windows with their own frame, such as the Go to and compare symbol dialogs.apply_to_eguisets it to the theme’sbtn_bg_hoverinstead of egui’s grey, which also fills an open combo box or submenu button. -
SymbolSearchDialogandExportDialogopen centred horizontally in the window, a fifth of the way down, and can still be moved. They grow downwards as their content changes, so the search field stays in place while results appear. Since egui 0.34 a window without a position opens at the top-left corner of the window, over the application’s toolbars, instead of in the space its panels leave. -
The floating selection toolbar’s settings, duplicate, lock, visibility and delete buttons show the crate’s SVG icons instead of emoji, which egui 0.37’s default fonts no longer contain; no bundled font had the duplicate glyph.
-
The chart widget is behind a new feature,
widget, whichiconsanduienable.default-features = falsenow builds the headless engine (model,scales,data,services,tokensand theIndicatortrait layer ofstudies), which depends onecolorinstead of egui and on no windowing or rendering crate. Migration: a build that setsdefault-features = falseto drop the icons addsfeatures = ["widget"]to keep the chart. -
Timeframe::Customholds aNonZeroU64, so no timeframe has a zero duration: deserializing{"Custom":0}fails, as parsing"0s"already did, and the serialized form is unchanged. Migration: build a custom timeframe withTimeframe::Custom(NonZeroU64::new(seconds)?)or by parsing a label such as"45s", and read its length withseconds.get()orduration_ms(). -
egui-charts no longer enables egui’s default features. Applications built on eframe keep the default fonts (eframe enables them). Migration: an application in which no dependency enables egui’s
default_fontsfeature (for example eframe with default features off and no direct egui dependency) must enable it or install its own fonts. -
The chart installs only egui_extras’ SVG image loader, and only with the
iconsfeature, instead of every image loader (file, HTTP, PNG, JPEG, GIF, WebP). Migration: an application that loads other images must callegui_extras::install_image_loaderswith the egui_extras loader features it needs enabled. -
rand,getrandom,wasm-bindgenandweb-sysare no longer dependencies,egui_extrasis needed only by theiconsfeature andthiserroronly byui, which removes theimagecrate, the HTTP crates and the random number crates from a default build. Migration: a wasm32 application that relied on this crate enabling getrandom’swasm_jsbackend must enable it itself. -
Themeholds the colours and scales directly:theme.semantic.uiistheme.uiandtheme.semantic.chartistheme.chart, andtheme::UiSemanticTokensandtheme::ChartSemanticTokensaretheme::UiColorsandtheme::ChartColors.UiColorsgainsfocus, the keyboard focus colour, anddanger_bg,danger_bg_hover,danger_bg_activeanddanger_text, which kit Danger buttons and Danger list items now fill from instead of the danger button tokens. Fields that duplicated another are removed:toolbar_bg,btn_bgandbtn_bg_disabledarepanel_bg;toolbar_separatorandborder_subtleareborder;iconistext_secondaryandicon_hoveristext;icon_active,border_focusandtext_linkareaccent;candle_up_borderandcandle_up_wickarecandle_up, and likewise for down;volume_upandvolume_downare methods usingvolume_alpha. In the dark theme the separators and resting icons that read the removed fields are drawn in the border and secondary text colours, and hovered icons in the text colour; in the light theme the separators are the border colour and the resting icons the secondary text colour. Migration: replace.semantic.ui.with.ui.and.semantic.chart.with.chart.,theme::UiSemanticTokenswiththeme::UiColorsandtheme::ChartSemanticTokenswiththeme::ChartColors, and a removed field with the one it duplicated;theme.is_dark_ui()istheme.dark; the colour accessors such astheme.background()are the fields, such astheme.chart.bg. -
Theme::default()is the dark theme. It was Classic, light UI chrome with the dark chart. -
ContextMenuStyle,DialogStyleandSettingsDialogStyleare built withfrom_theme(&Theme)instead offrom_semantic. -
The bottom toolbar, timeframe bar, date picker, range switcher and right panel tabs follow any change of the applied theme, including an edited preset, instead of only a change of preset.
-
scales::PriceScaleis the chart’s price axis and keeps its visible range in scale units:PriceScale::new(options),autoscale,zoom,set_range,reset,range,is_manual,optionsandoptions_mut, andmap, which returns the frame’sscales::PriceMapfor ascales::PriceTransform(mode and base price).PriceMap::price_to_yandy_to_pricedo not clamp to the pane. Migration:PriceScale::new(options)replacesnew(height)andwith_options;map(transform, top, bottom).price_to_y(price)and.y_to_price(y)replaceprice_to_coordandcoord_to_price;autoscale,set_range,resetandrangereplaceauto_scale,set_manual_range,reset_auto_scale,price_rangeandvisible_price_range;options_mutreplacesset_options; the pane extent andPriceTransform::basepassed tomapreplaceset_heightandset_first_val. -
PriceScaleOptionsno longer hasauto_scale; usePriceScale::is_manualandPriceScale::reset.PriceScaleMarginsfields aref64and default to 0.1 at the top and the bottom, the margins the chart has always drawn. -
ChartMappingholds the frame’sprice: PriceMapinstead ofprice_minandprice_max, andChartMapping::newtakes it as its last argument.pricekeeps its own vertical extent, soChartMapping::with_rectmoves only the x mapping and the bounds checks. Migration: passPriceMap::new(PriceTransform::default(), PriceRange::new(min, max), rect.min.y, rect.max.y, false)for a linear axis. -
ChartStateowns the main price scale:price_scale,price_scale_mutandfit_price_scalereplaceprice_range,set_price_range,set_price_auto_scaleandis_price_auto_scale. Migration:state.price_scale_mut().set_range(min, max),.reset()andstate.price_scale().is_manual(); the fitted range isstate.price_scale().range()afterstate.fit_price_scale().ZoomState::price_rangeholds a manual range in scale units. -
PriceMarkGenerator::generate_markstakes the frame’s&PriceMapinstead of a price range, height, mode and pane bounds. In percentage and indexed modesPriceMark::priceholds the percentage or index value, not a price. -
Chart::handle_drawingstakes the frame’s&PriceMapinstead of the lowest and highest price. -
model::Tickis#[non_exhaustive]and has anidfield. Migration: build it withTick::new(ts, price, size, side), adding.with_id(id)when the feed has trade ids. -
model::SymbolTypeis#[non_exhaustive]. Migration: add a wildcard arm to matches on it. -
tokens::UiSemanticTokensreplaceswarningandsuccesswith per-theme status colours{success,warning,error,info}_{light,dark}, and gainstext_disabled_light,text_disabled_dark,border_control_light,border_control_dark,selection_bg_lightandselection_text_light;theme::UiColorshasborder_control, the outlineapply_to_eguigives inactive and hovered widgets. Migration: readDESIGN_TOKENS.semantic.ui.warning_darkandsuccess_darkfor the old values, or the theme’sui.warningandsuccessto follow the active theme; struct literals must set the new fields. -
The theme’s
accent_active(pressed accent) is a darker accent, (31, 78, 205), instead of the greybuttons.primary_bg_active, andaccent_hoveris (35, 88, 230) instead of the lighterblue_600.tokens::BrandSemanticTokensgainsaccent_active; struct literals must set it. Thebuttons.danger_bg,danger_bg_hoveranddanger_bg_activetokens are darker reds. -
Replaced the bundled icon set with original artwork drawn on a 24 px grid. Toolbar, chart-type and widget-bar icons now render at 24 px, and close buttons, the cross cursor, alert and toast states, move to pane, add to watchlist, the replay next-bar button, the price range tool, the arrow tool and the note, callout, comment, table, image and other annotation tools show their own icons.
-
Drawing::render,Drawing::render_original, andDrawingManager::render_alltake adrawings::rendering::ChartViewholding the chart’s bars and coordinate mapping. Migration: buildChartView { bars, bar_to_x, price_to_y }from the series and the closures passed toupdate_all_screen_coords, and pass it as the last argument. -
drawings::rendering::ChartViewhas arevisionfield, under which results computed from the bars are cached. Migration: set it toChartState::revision()of the state the bars come from, or to a value that changes whenever a bar before the last one changes. -
The regression trend draws one pair of bands at its configured distance (two standard deviations by default) instead of bands at one and two.
-
Long and short position tools size their quantity from
Drawing::position_size; without a setting the quantity is one unit, so P&L reads per unit, instead of a fixed 100. The target and stop labels no longer repeat the quantity, and a quantity that is not whole is shown with up to four decimals, or four significant digits below 0.1. Migration:Drawing::quantityis replaced byDrawing::position_size;quantity: Some(q)becomesposition_size: Some(PositionSize::Quantity(f64::from(q))). -
Chart::handle_drawingsno longer takes the last close price. -
TooltipOptions::default()leavesbackground_color,text_colorandtracking_bar_backgroundasColor32::PLACEHOLDER, which resolves from the active theme; set them explicitly to keep fixed colours. -
SymbolHeaderConfig::default()text, label and separator colours areColor32::PLACEHOLDERand follow the egui style;SymbolHeaderConfig::from_themenow uses the theme it is given. -
apply_to_eguistyles the selection per theme. Dark themes fill it with the accent and setvisuals.selection.stroketo white; light themes fill it with a pale accent, (219, 229, 255), and set the stroke to a darker accent, (31, 78, 205), which also outlines a focused text input. Migration: code that readselection.bg_fillorselection.stroke.coloras the accent colour should read the theme’sui.accent; text painted onselection.bg_fillshould useselection.stroke.color, not white. -
apply_to_eguisetsitem_spacingto 8 x 4,window_marginto 12 andmenu_marginto 8 x 4 instead of zero. Layouts that relied on zero spacing should setui.spacing_mut().item_spacing = Vec2::ZEROlocally. -
apply_to_eguisetsvisuals.window_filltoUiColors::panel_bg_floating, which in dark themes is now (42, 46, 57), one step abovepanel_bg, instead of equal to it. Popups and windows also get a hairline border and a smaller shadow. -
The chart’s context menus follow the theme applied with
theme::apply_to_egui(Theme::dark()until one is applied);ChartBuilder::with_themesets the chart’s colours only. -
ChartBuilderno longer defaults the symbol toBTCUSDT: a chart built withoutwith_symbolhas an empty symbol, shows no symbol and asks its feed for nothing untilChart::set_symbolis called. Migration: callwith_symbolto keep the previous behaviour. -
SymbolInfo::default()(inui::symbol_header) has empty fields instead of AAPL, Apple Inc, NASDAQ and 1D. Migration: set the fields explicitly. -
CompareSymbolsDialog::showtakes the symbols to suggest (show(ctx, &symbols), the same&[model::Symbol]thatSymbolSearchDialog::showtakes) and lists only those, with an empty state when there are none, instead of a built-in list of tickers the data source may not offer. Added symbols have an emptyCompareSymbol::exchange, sinceSymbolcarries no exchange. Migration: pass the symbols your data source offers. -
ButtonVariant::bg_color,fg_colorandborder_colorresolve colours from the theme applied withapply_to_eguiand theUi’s visuals instead of fixed design tokens, andapply_to_stylesets them on aUiinstead of aStyle;fg_colorreturns a real colour for Ghost and Outlined instead ofColor32::PLACEHOLDER. Migration: passuias the first argument (callapply_to_styleinsideui.scope);border_colorno longer takeshovered. -
IconButton,SplitButtonandButtonicons are 16, 20 or 24 px for small, medium and larger buttons (20 px at the default 28 px) instead of 60% of the button size;icon_scalestill overrides this. -
SplitButtonoccupies the same square cell as anIconButtonof its size, with the chevron in the cell’s corner, instead of a cell 10 px wider. -
dialog_close_buttonis anIconButtonshowingicons::CLOSEwith a “Close” tooltip. -
DialogFrame,dialog_header,DialogFooter,Modal,ConfirmDialog,PromptDialogandModalHandlershare one dialog chrome: the theme’s window fill, border, radius and shadow with 16 px padding, a title row with a left-aligned 14 px title and an icon close button centred on it, and a footer whose buttons are 28 px high, 8 px apart, with a filled primary and an outlined secondary. The size passed toDialogFrame::newis the preferred content size inside the padding: the dialog is at least that large, grows with its content and is limited to the application window. ADialogFootershown directly in aDialogFrame::newframe sits at the bottom of the frame, with any free space above its rule. Modals are centred and sized to their content, andModal::widthandModal::min_heightset the outer size including the padding (before, the content size);ConfirmDialogis cancelled by Escape, the close button or a backdrop click, andModalHandlercloses on Escape. -
UiExt::clickable_labeland the alert count badge of the widget bar take their colours from the active theme: the clickable label is drawn inui.accent, and the badge text isui.danger_text. They used fixed token colours, so a custom accent or the high-contrast preset did not reach them. -
tokens::DESIGN_TOKENSis a plainstaticof typeDesignTokensdefined in Rust instead of aonce_cell::sync::Lazythat parsed an embedded RON file on first access, which took 10 to 40 ms and 1,224 allocations in a release build. Theronandonce_celldependencies are removed. Migration: field access is unchanged; code that dereferenced the static (*DESIGN_TOKENS,Lazy::force(&DESIGN_TOKENS)) usesDESIGN_TOKENSor&DESIGN_TOKENS. -
The drawing storage format is version 2: a
StoredDrawingholds its anchors and theDrawing(StoredDrawing::drawing) with the tool type and all settings.DrawingStorage::from_jsonmigrates version 1 files, with defaults for the settings they lacked, and fails on any other version instead of relabelling it. It loads each drawing on its own and returns(DrawingStorage, Vec<drawings::persistence::SkippedDrawing>): a drawing it cannot read (a tool type from a newer release or an unknown version 1 tool name, a cursor tool, a missing field, anullwritten for a non-finite number, a number outside the range of its field, a setting out of bounds) is left out and reported with its id and error, while the file as a whole fails only on invalid JSON, an unknown version or an invalid symbol, timeframe or metadata. Saving the returned storage writes only the drawings that loaded; keep the original file if the skipped ones must be recovered. Migration: build a stored drawing withStoredDrawing::new(id, drawing), read its settings fromstored.drawing, and take the storage from the first element of thefrom_jsonresult, reporting or logging the skipped drawings. -
drawing_to_stored(drawing, bar_to_time)andstored_to_drawing(stored, time_to_bar, next_id)map anchors between bar index and timestamp instead of taking screen-space closures, andstored_to_drawingreturns theDrawinginstead of anOption; screen points follow on the nextupdate_screen_coords. Migration: pass the chart’s bar index to timestamp mapping and its inverse. Both must take fractional bar indices and extrapolate by the bar interval before the first and after the last bar instead of clamping, or anchors outside the loaded bars are moved onto the edge bar and saved there. -
DrawingStorage::to_jsonrefuses a drawing holding NaN or an infinity in its stroke width, font size, an anchor price, its position size or a Fibonacci level value, and returnsdrawings::persistence::SaveError::NonFinitewith the drawing’s id and the field, instead of writingnulland losing the drawing on the next load.from_jsonskips such a drawing too, so every storage it returns can be saved. Migration:to_jsonreturnsResult<String, SaveError>instead ofResult<String, serde_json::Error>; a serialization error isSaveError::Json. -
DrawingStorage::from_jsonskips a drawing whose id an earlier loaded drawing already has and reports it as a duplicate, so the loaded ids are unique and the first one in the file wins.SkippedDrawing::indexis the entry’s position in the file, which tells skipped entries with the same id or no id apart. Migration: struct literals ofSkippedDrawingmust setindex. -
DrawingStorage::from_jsonskips a drawing with fewer anchors than its tool draws with and reports it with the tool and the anchor count, since such a drawing loaded as completed, drew nothing and could not be selected or deleted on its own, and a drawing whose timeframe filter names no timeframe loads as visible on every timeframe.DrawingStorage::to_jsonrefuses the same drawing withSaveError::MissingAnchors, so every storage it accepts loads back whole. -
DrawingStorage::add_drawingreplaces the drawing with the same id, keeping its position andcreated_at, instead of storing a second one that the next load skipped as a duplicate, so saving a drawing again after an edit stores the edited version once.DrawingStorage::to_jsonrefuses duplicate ids that reach the storage another way (the publicdrawingsfield, a struct literal or an id changed throughget_drawing_mut) withSaveError::DuplicateId, instead of saving a drawing the next load skips. Migration: give each drawing its own id to keep both. -
The cross, dot and arrow cursors are named “Cross Cursor”, “Dot Cursor” and “Arrow Cursor” (
DrawingToolType::as_strandDisplay), so “Arrow” names only the arrow drawing and “Cross” no longer names one tool while parsing to another. The floating toolbar’s all-tools menu shows the new names. Migration: code that compares a cursor’sas_str()orto_string()with “Cross”, “Dot” or “Arrow” uses the new names. -
Parsing a
DrawingToolTypefails withdrawings::ParseToolTypeError, whoseinputfield holds the name as given and whose message readsunknown drawing tool "name", instead of aString. The names that parse, and the tools they parse to, are unchanged. Migration: code that used the error as aStringreadserror.inputor callserror.to_string(). -
OrderIdandOrderSidenow live inmodel. -
A last-bar update or an append of
SMAreads the window from the bars instead of keeping a copy of it, so it no longer copies the whole close series when the period is longer than the series. -
DonchianChannels,IchimokuCloud,StochasticandWilliamsRfind the highest high and lowest low of each window in time linear in the number of bars, independent of the period, instead of rescanning the window for every bar; their values are unchanged.IchimokuCloudtakes about 24 ms instead of 52 ms on 100,000 bars. -
The default feature is
ui, socargo add egui-chartsgives the chart with its toolbars, panels, dialogs, icons and built-in studies instead of the chart and its icons. Migration: an application that only shows charts setsdefault-features = false, features = ["widget"], adding"icons"for the icon set and"studies"for the built-in studies. -
The built-in right-click menus are shown by
ui::context_menu::ChartMenus(featureui), which takes the chart’s right-click; a host that handles right-clicks itself readsChart::take_right_clickand does not showChartMenus. -
The built-in studies,
IndicatorFactoryand thestudies::factorymodule need the newstudiesfeature, whichuienables.Indicator,IndicatorValue,IndicatorRegistryandCustomIndicatorremain in every build, so custom studies work in a bare chart. Migration: a build withdefault-features = falsethat uses built-in studies adds"studies"; it needs no egui, so a headless build keeps computing the same studies. -
ext(UiExt,ResponseExt,ButtonWidgetExt,TextEditWidgetExt,RoundingExt) needs theuifeature instead ofwidget. Migration: enableui. -
ui::context_menu::MenuItemis generic over its action,MenuItem<A = ContextMenuAction>, holds its shortcut as anegui::KeyboardShortcutinstead of a string, and gainsdanger. Migration: replacewith_shortcut("Cmd R")withwith_shortcut(KeyboardShortcut::new(Modifiers::COMMAND, Key::R)), which egui formats for the platform; struct literals setdanger. -
The top toolbar is 32 px high, with 28 px buttons, 20 px icons and 13 px labels, except Save, which keeps its look. When the window is too narrow, Indicators, Alert and Replay show only their icons, then the least important controls move into a menu at the right end, so no control overlaps another.
TOOLBAR_HEIGHT,BUTTON_SIZEandICON_SIZEinui::top_toolbar::configare 32, 28 and 20. The keyboard focus ring fills the 2 px around a control instead of sitting 2 to 4 px outside it, so a control that fills its strip keeps all four sides of the ring. -
The symbol pill and the interval and chart type buttons are sized to their laid-out labels and drawn alike: an icon where they have one, the label and a chevron, with an outline at rest, the hover fill on hover and the pressed fill while pressed or open. The pill is visible at rest in the light theme, shows the symbol in the primary text colour and no longer overdraws its last letter, and the interval button no longer shows a missing-glyph box. The three report themselves to accessibility tools as buttons and show the keyboard focus ring.
TimeframeSelectorConfig::btn_widthandChartTypeSelectorConfig::btn_widthare minimum widths, 0 by default. -
The symbol header shows the last close with its change instead of the bar’s open, high, low and close, which the chart legend shows. Its up and down colours default to the theme’s success and error text colours, which read at 4.5:1 or better where the candle colours do not (
Color32::PLACEHOLDERinSymbolHeaderConfig::default, resolved while painting), andSymbolHeaderConfig::from_themesets them. -
Widget bar icons are 20 px, as in the top toolbar, and their tooltips open to the left of the button instead of over the button below. The bottom bar’s date button icon is 16 px.
-
BarData::from_csvrequires the header rowts,open,high,low,close,volume(any case, spaces around names ignored) and returns an error naming it otherwise, instead of taking the first row as a header unchecked and reading the columns by position, which lost the first bar of a file without a header and swapped the columns of a file in another order. An empty file is refused too. Migration: give the file that header, with the columns in that order. -
Every CI job has a
timeout-minuteslimit, so a hung job fails in minutes instead of after the 6 hour default. -
CI runs default, all-feature and headless library tests on stable and Rust 1.95.0 on Linux, macOS and Windows. Headless Chrome also runs the widget’s pan, pointer zoom, drawing selection and degenerate-history tests with all features and with the widget alone. (#254)
-
ChartState::set_datareturns the index of the first bar that differs from the previous bars, the shorter length when one series is a prefix of the other, orNonewhen they are identical. -
Chart::showdraws the chart’s studies, overlays on the main pane and the others in panes below it, and its drawings, and the chart updates its studies once per frame from the first bar changed since the last one. Migration: move the studies in withadd_indicatorand the drawings withdrawings_mut(), replaceshow_with_indicators,show_with_drawingsandshow_with_indicators_plotwithshow, and drop thecalculate_allcalls that followed bar updates. -
The close button in a study pane’s legend removes the study. Migration: drop calls to
Chart::take_indicator_remove, which is removed. -
ChartElementId::OverlayIndicator(usize)andChartElementId::PaneIndicator(usize)are replaced byChartElementId::Indicator(SeriesId), the idadd_indicatorreturned. Migration: find the study withChart::indicators. -
DrawingManager::shift_bar_indices,Drawing::shift_bar_indices,HistoryService::shift_bar_indicesandDrawingCommand::shift_bar_indicestake the first bar index to shift,from, before the shift. Migration: passf32::NEG_INFINITYto shift every point, as before. -
Chartholds its studies asBox<dyn Indicator>, which isSendbut notSync, soChartis no longerSync. Migration: share it behind aMutex;Arc<Mutex<Chart>>still works. -
Chart’s fields are private. Migration:chart.configbecomeschart.config()orchart.config_mut(),chart.chart_optionsbecomeschart.chart_options(),chart.marks = markersbecomeschart.set_markers(SeriesId::MAIN, markers),chart.state.data().barsbecomeschart.bars(SeriesId::MAIN),chart.state.price_scale_mut()becomeschart.price_scale_mut()andchart.last_rendered_price_rectbecomeschart.get_rendered_price_rect(). Other reads of the state, such asrevision,visible_range,visible_data,time_scaleandhas_zoom_history, go throughchart.state();time_scale_mut,fit_price_scaleand the zoom history’spush_zoom_state,pop_zoom_stateandclear_zoom_historyhave no public replacement, since the chart scrolls, fits and zooms itself. -
The floating replay bar opens docked at the bottom of its dock rect instead of at the window’s top left corner over the top toolbar, which it did wherever the platform does not report the window position (the web, Wayland). It uses the kit’s 28 px icon buttons, a 28 px speed control named “Playback speed” and a secondary “Exit replay” button, shows the symbol and progress at 12 px in the theme’s text colours with the progress always shown, keeps its width as the progress and speed change, and casts the popup shadow.
-
ReplayControls,CompactReplayControlsandReplayToolbaruse the kit’s icon buttons instead of text glyphs and egui image buttons.ReplayToolbarshows its progress percentage beside the bar instead of over the fill, and the single-step buttons ofReplayControlsandReplayToolbarshow arrows instead of the skip icons. -
ReplayColors::defaulttakes the dark theme’s colours, and the replay widgets paint with the active theme’s colours while the configured colours are the defaults. -
ReplayStatusIndicatortakes its colours from the active theme, reads “Replay”, “Paused” and “Complete” at the theme’s small text size, and takes no space forReplayStatus::Inactive. -
ChartBuilder::with_initial_barstakes ausize. Migration:Some(n)becomesn; forNone, build without a feed. -
Chart::set_symbolandChart::set_timeframereload a chart built with a feed at its nextshowwhen the value changes: the series and its studies are cleared and the new one is loaded, once however many of the two changed. Without a feed they set the label only.Chart::set_symboltakesimpl Into<String>. Migration:set_timeframe_label(tf.as_str())becomesset_timeframe(tf). -
ChartBuilder::buildreturns aChartand never blocks. Migration:tc.chart.x()andtc.x()becomechart.x(), droptc.update()(showapplies updates),tc.take_context_action()becomesmenus.show(ctx, &mut chart)with aChartMenuskept next to the chart (featureui). -
ChartBuildermoved towidget::builder. Migration: importegui_charts::ChartBuilderoregui_charts::widget::ChartBuilderinstead ofegui_charts::chart::builder::ChartBuilder. -
ChartBuilder::price_charthides the horizontal and vertical grid lines; it used to clear a flag the chart does not read. -
While bars stream, each frame recomputes at most one study in full, the one that has waited longest, and a study then waits 0.25 s, or four times what that recompute took if longer, before its next one. An incremental study follows a new bar or a new close of the last bar on the same frame.
Chart::indicatorscan therefore return values that lag the bars by that wait, and after the bars change from the first one on, as whenset_dataloads other bars or older bars are loaded in front, a study has no values until its turn, one study per frame. Migration: a host that reads study values right afterset_data, for alerts or exports, reads them on a later frame once the study has values again, or callscalculateon a clone of the study (Indicator::clone_box) withChart::bars. -
While the view is scrolled back, new bars no longer move the visible bars.
-
Exportable::export_pngtakes no arguments, since the export has no size or background options. Migration:export_png(w, h, transparent)becomesexport_png(). -
TopToolbarAction::IntervalSelectedcarries amodel::Timeframeinstead of the menu label, so every interval the menu offers, a custom one included, reaches the host: before, 12 of the 21 labels had noTimeframe::from_resolutionmapping, andFromStrread bare minute labels as custom timeframes. Migration: match on the value instead of parsing the label; an interval with no preset of its length arrives asTimeframe::Custom(seconds). -
HideMenu::show_submenutakes whether to show the positions and orders rows. Migration: passtrueto keep them. -
TopToolbarandWidgetBarhave a private field and can no longer be built with a struct literal. Migration: start fromTopToolbar::default()orWidgetBar::default()and set the public fields. -
The drawing bar draws its menus in one flyout.
SubmenuBuilder::newtakes only theUi,SubmenuBuilder::with_category_rectis gone andshowdraws the rows into thatUi;SubmenuItemgainsis_checkedandis_dangerand implementsDefault;SubmenuBuilder::checkedanddangerset them on the item added last.ToolCategory::render_submenu(ui, sel_tool, favorites)andcategories::trend_lines::render_tool_submenu(ui, sections, sel_tool, favorites)draw rows into theUithey are given, take the favourites as&mut Vec<DrawingToolType>and no longer take an anchor rect or an id;ToolCategory::all_tools,sectionsandrender_submenuhave default implementations that readdata::get_category_sections. Migration: show the rows inside your own popup, or useDrawingToolbar. -
MagnetButton::show,HideMenu::showandRemoveMenu::showreturn the button’sResponse, where they returned tuples of flags and a rect.MagnetButton::show_submenu(ui, magnet_on, magnet_type),HideMenu::show_submenu(ui, trading, state),RemoveMenu::show_submenu(ui)andTemplatesButton::show_submenu(ui, templates)draw into theUithey are given.components::render_svg_at_rect_themedno longer moves the layout cursor.
Removed
Section titled “Removed”-
model::Annotationandmodel::MarkerType, which nothing drew, with the unnameableAnnotationPos. Migration: useMarker. (#1310) -
The loose ALMA smoothness check, drawing-tool inventory pins, a duplicate tracking default check and an enum-distinctness tautology. (#258)
-
model::QuoteSourceandQuoteSourceError, a polled quote source nothing consumed,ui::widget_bar::WatchlistQuoteandui::symbol_header::QuoteData. Migration: implementservices::Quotesand attach it withWatchlistPanel::set_service, and usemodel::Quotein place of the two quote types. (#222) -
TradeSide::Unknownandmodel::RangeTickData. A trade of unknown side hasTick::sideset toNone, the one way to say it, andto_range_bars_from_ticksbuilds range bars fromTick, the crate’s one trade type. Migration: replaceSome(TradeSide::Unknown)withNone, and buildTick::new(ts, price, volume, None)in place of aRangeTickData. (#228) -
Unread design token fields:
UiSemanticTokens::{panel_bg_dark, panel_bg_secondary_dark, panel_bg_floating_dark, text_dark, text_secondary_dark, text_disabled_dark, text_disabled_light, border_subtle_dark, border_control_dark, border_control_light, btn_bg_dark, btn_bg_hover_dark, btn_bg_active_dark, selection_bg_light, selection_text_light, error_light, warning_dark, info_dark},ChartSemanticTokens::{bg_selection, bg_selection_light, bg_light, bg_axis_light, grid_line_light, grid_line_major_light, crosshair_line_light},IndicatorSemanticTokens::{bb_fill, rsi_overbought, rsi_oversold, macd_hist_pos, macd_hist_neg},DrawingSemanticTokens::{default_line, handle, handle_hover, handle_active, line_hover, line_selected, label_bg, fib_0, fib_236, fib_382, fib_618},TpoSemanticTokens::opening_range,ToolbarSizingTokens::top_heightandShadowTokens::offset_md. Migration: remove these fields from token struct literals; read applied colours fromThemeExt::active_themeand keep host-specific constants where no theme field applies.UiSemanticTokens::border_darkandDrawingSemanticTokens::fib_50retain their rendering readers, andChartSemanticTokens::watermark_alpharemains available as the documented watermark migration target. (#367) -
Unread layout timestamps, cloud/default flags and the
LayoutInfowrapper, unusedLayoutAction::OpenMenuandSetDefault, and unusedLayoutMenuConfigcolours and item height. Migration: supplyLayoutMenu::layoutsasVec<String>and update that list directly instead of callingadd_layout;LayoutMenuConfigretains onlymenu_width. -
The “Correlation”, “CorrLogRet”, “Ratio”, “Spread” and advance/decline “A/D Line” studies and their Rust types, since one symbol’s bars cannot supply a second series or market breadth, and “Vol Index” (
VolatilityIndex), whose annualised ATR percentage follows no published definition. Accumulation/Distribution keeps its “A/D Line” output. Migration: the two-series and breadth studies return when studies can read another symbol (#175); a host can compute them today as a custom study in Rust. An annualised ATR percentage can also be written as a custom study. -
ui::chart_controls::ChartControlBar,ChartControlBarState,ChartControlBarConfigandChartControlAction, which nothing drew or handled and whose icons did not match their actions. Migration: remove any use of them; the chart draws and handles its navigation buttons itself, andChartConfig::navigation_buttonssets when they show. -
studies::list_builtin_indicators, whose table listed seven names the factory could not create, and the factory names “CVD”, “C2C Vol”, “HL2”, “HLC3” and “Price Channel”, which computed the same studies as “A/D”, “HV”, “MP”, “TP” and “Donchian”, and “Ehlers Fisher”, a variant of the Fisher Transform recursion with length 10 and a clamp on the normalised price.IndicatorFactoryis now the one catalogue:IndicatorFactory::categorygives each built-in’s category, and a study added withregisteris inIndicatorFactory::CUSTOM. Migration: list studies withIndicatorFactory::listand describe each withIndicator::descandIndicatorFactory::category; create the registered twin of a removed name, or buildCVD,CloseToCloseVol,HL2,HLC3,PriceChannelorEhlersFisherdirectly. -
chart::overlays::{OrderLine, OrderLineOverlay, OrderLineAction, OrderLineType}, which nothing in the crate drew, with the re-exportschart::overlays::{OrderId, OrderSide}and the sizing tokensChartsExtSizingTokens::{order_line_label_width, order_line_label_height}. Migration: draw each order’s price as amodel::PriceLinewith its label as the title, for examplePriceLine::new(order.price, color).with_title(label), and pass the lines toChart::set_price_lines(SeriesId::MAIN, lines); the chart places them through its own price scale, so noprice_to_ymapping is needed. Selecting, dragging and cancelling an order line (OrderLineAction) and its cancel button have no replacement: price lines do not respond to the pointer. ImportOrderIdandOrderSidefrommodel. Code that read the two tokens uses the values they held, 120.0 and 20.0, andChartsExtSizingTokensliterals drop the two fields. -
BoxZoomModeandBoxZoomState::mode: no chart could select the measure mode, and a box released in it showed nothing. Migration: remove any use of them; box zoom always zooms, and theMeasuredrawing tool measures the price change, percentage and bar count between two points. -
DatePickerConfig, which no API ever passed to aDatePicker. Migration: remove any use of it; the go to date picker takes its colours from the active theme. -
IndicatorDialogConfig::bg_colorandIndicatorDialogConfig::sidebar_color, which had no effect: the dialog takes its surface from the kit modal and its sidebar fromSidebarTab. Migration: drop both fields from struct literals; the dialog surface isTheme::ui.panel_bg_floating, whichapply_to_eguiapplies as egui’sVisuals::window_fill. -
ChartSettingsState::color_based_on_prev_close, which had no effect. -
Timeframe::total_seconds,Timeframe::as_secondsandTimeframe::to_seconds, which returned 0 forMs100,Ms250andMs500. The demo’s sample bars at those timeframes were one second apart and now follow the timeframe. Migration: useTimeframe::duration_ms(), orduration()for achrono::Duration; time intervals always have a positive duration. -
ThemePreset,ThemeManager,Theme::{classic, midnight, from_preset, name, is_dark_ui, is_dark_chart},Theme::componentswithComponentStylesand the unusedBtnStyle,ToolbarStyle,PanelStyle,MenuStyle,InputStyle,ChartStyle,CandleStyleandVolumeStyle, the colour accessors onTheme(background,grid,text,bullish,tpo_*,footprint_*and the others),theme::all_presets,theme::all_themes, andtheme::SemanticTokenswithIndicatorSemanticTokensandDrawingSemanticTokens, whose fields nothing read. Migration: useTheme::dark(),Theme::light()orTheme::high_contrast(), andtheme::presets()for the list; the Classic look isTheme { chart: Theme::dark().chart, ..Theme::light() }; Midnight was identical to Dark; persist a theme choice in the application (with theserdefeature, serialise theTheme). TPO and footprint colours are inDESIGN_TOKENS.semantic.tpoandDESIGN_TOKENS.semantic.footprint. -
Fields of the old theme colour structs that nothing drew with, and their constructors and alpha helpers. Migration:
UiSemanticTokens::icon_disabledisui.text_disabled;ChartSemanticTokens::bg_legendischart.bg_tooltip;price_lineischart.axis_text;price_label_bgandprice_label_textarechart.crosshair_label_bgandchart.crosshair_label_text;watermarkwas the secondary axis text in dark themes and the muted text in light ones atDESIGN_TOKENS.semantic.chart.watermark_alpha;bg_selectionhas no replacement. Forcandle_up_alpha(a)andcandle_down_alpha(a), build the colour fromchart.candle_uporchart.candle_downwithColor32::from_rgba_unmultiplied. ForUiSemanticTokens::from_design_tokens(dark)andChartSemanticTokens::from_design_tokens(dark), takeuiorchartfromTheme::dark()orTheme::light(); thefrom_design_tokensconstructors ofSemanticTokens,IndicatorSemanticTokensandDrawingSemanticTokenswent with those types. -
Design tokens that nothing read:
tokens::ListItemSemanticTokens,HeatmapSemanticTokens,ToastSemanticTokens,TierSemanticTokens,AuthDialogSizingTokens,BurgerMenuSizingTokens,ChartSizingTokens,CursorSizingTokens,EmojiPickerSizingTokens,FootprintSizingTokens,RightSidebarSizingTokens,WatermarkSizingTokensandWidgetSizingTokenswith theSemanticTokensandSizingTokensfields that held them, and 111 unread fields of the other token structs. Migration: code that named a removed token uses the value it held, listed insrc/tokens/design_tokens.ronof 0.2.0; colour tokens there name a palette entry (for exampleblue_500) whose RGB value is in the file’spalettesection. -
theme::ThemeData,theme::ThemeContextExt,theme::ThemeUiExt,theme::context::{get_icon_color, get_icon_hover_color, get_icon_active_color},ext::DesignTokens,ext::HasDesignTokens,ext::ContextExtand thethemingmodule, which were five ways to read the same colours, andstyles::marginand thestyles::sizingmodulestoolbar,auth_dialog,footprint,indicatorandcandle, which nothing used. Migration:ctx.active_theme()andui.active_theme()(traittheme::ThemeExt) return the theme last applied, or the dark theme, instead of anOption, andctx.theme_data()andDesignTokens::from_context(ctx)arectx.active_theme();set_theme_dataisapply_to_egui; aThemeDataorDesignTokenscolour is theThemefield of the same meaning (ui_textandtext_primary()areui.text,chart_bg_axisandchart_axis_bg()arechart.bg_axis,crosshair()ischart.crosshair_line,volume_bullishischart.volume_up()), andpage_bgwasui.panel_bg_secondaryin dark themes andchart.bgin light ones; colours that egui models are read fromui.visuals(). By replacement:visuals.panel_fillfortheming::toolbar_bg,panel_fill()andtheme_panel_bg();visuals.widgets.hovered.bg_fillfortheming::hover_color,theming::btn_bg_hover,hover_bg()andtheme_hover_bg();visuals.widgets.active.bg_fillfortheming::sel_color,theming::btn_bg_pressed,active_bg()andtheme_active_bg();Color32::TRANSPARENTfortheming::btn_bg_normal;visuals.widgets.noninteractive.fg_stroke.colorfortheming::icon_color,icon_normalandmuted_color,icon_color(),text_secondary(),theme_icon()andtheme_text_secondary();visuals.widgets.hovered.fg_stroke.colorfortheming::icon_hover_colorandtheming::icon_active,icon_hover()andtheme_icon_hover();visuals.strong_text_color()fortheming::active_icon_color,HasDesignTokens::text_color()andtheme_text();visuals.text_color()fortheming::text_color;visuals.widgets.noninteractive.bg_stroke.colorfortheming::separator_color,border_color()andtheme_border();visuals.weak_text_color()forThemeData::ui_text_mutedandtext_muted();visuals.warn_fg_colorforwarning_color()andtheme_warning(); the theme’sui.accentfortheme_accent(),theme_icon_active(),accent_color(),icon_active()andtheming::publish_button_bg, andui.accent_hover,ui.accent_activeandui.accent_textforpublish_button_bg_hover,publish_button_bg_pressedandpublish_button_text;ui.accent_textforThemeData::ui_accent_text;ui.danger_textfortheming::badge_text_color;ui.successforsuccess_color()andtheme_success();chart.bg,chart.grid_line,chart.axis_text,chart.candle_upandchart.candle_downforchart_bg(),chart_grid(),theme_chart_text(),bullish_color()andbearish_color()and theirtheme_forms;DESIGN_TOKENS.semantic.footprintfor the footprint colour getters;theme.darkforis_dark_ui()andContextExt::is_dark_mode(), andtheme.chart.bg.intensity() < 0.5foris_dark_chart().theming::active_hover_color,pill_bg,lighten_coloranddarken_colorhave no replacement; for an opaque colour,lighten_color(c, f)isc.lerp_to_gamma(Color32::WHITE, f)up to rounding. TheContextExtdevice queries returned constants, andis_touch_activeisctx.input(|i| i.any_touches()). Forstyles::margin, use theegui::Marginconstructors. Widgets drawn before anyapply_to_eguicall read the dark theme, not the light colours ofThemeData::default(). -
The unused
panel_bg,panel_borderandheader_bgfields oftokens::ModalSemanticTokens. Migration: use the theme’sui.panel_bg_floatingandui.border. -
scales::{DualPriceScaleManager, PosedPriceScaleOptions, SeriesScaleAssignment, PriceDisplayMode, AutoScaleMode}, which nothing used.scales::PriceScaleIdstays. -
ChartMapping::x_onlyandChartMapping::with_price_range, which nothing called. Migration: build the mapping with thePriceMapit needs. -
widget::apply_price_zoomandwidget::y_to_price, which assumed a linear axis. Migration:PriceScale::zoomandPriceMap::y_to_price. -
Chart::get_rendered_price_range. Migration:Chart::get_chart_mapping().pricemaps prices exactly as the last frame drew them. -
Chart::apply_price_zoom, a step ofChart::show. Migration: zoom the price axis withchart.price_scale_mut().zoom(factor, anchor). -
PriceScaleOptions::{align_labels, border_visible, visible, ticks_visible, entire_text_only}, which nothing read. Migration: remove them from struct literals;ChartConfig::show_right_axisshows or hides the price axis. -
ui_kit::buttons::button_bgandui_kit::buttons::icon_color, which had no pressed state. Migration: useButtonVariant::Ghost.bg_color(ui, hovered, pressed), orButtonVariant::Primaryfor a selected button, andButtonVariant::fg_color. -
The Volume Footprint and Session Volume chart types, which approximated per-price volume from bar totals, with their
icons::icons::CHART_VOLUME_FOOTPRINTandicons::icons::CHART_SESSION_VOLUMEicons, and the unusedmodel::footprintmodule. -
The
chart::series_apimodule (ISeriesApi,IPriceScaleApi,ITimeScaleApi,IStudyApi, their implementations and option types), which nothing constructed. -
The series context menu “Hide” entry (
SeriesContextMenuAction::Hide), which had no effect. -
DrawingManager::update_pos_prices,Drawing::format_timestamp, and theDrawingfieldsis_closed,curr_price,forecast_start_price,forecast_target_price,forecast_start_time, andforecast_target_time; position and forecast results come from the chart’s bars. -
Unused icon constants
AREA_CHART,LINE_CHART,ORDER_BOOK,TIME_AND_SALES,HIDE,RISK_REWARD_SHORT,TREND_BASED_FIB_EXTENSION,ZOOM_TOGGLE,EMOJI_EAGLE,EMOJI_ORNAMENT,WIDGET_BAR_NOTIFICATIONS,WATCHLIST_44,SCREENER_44,PINE_SCRIPT_44,COMMUNITY_44andPRODUCTS_44. Migration: useCHART_AREA,CHART_LINE,WATCHLIST,EYE_HIDE(orEYEfor the visible state),SHORT_POSITIONandFIB_EXTENSION; the others have no replacement. -
The unused series renderers
chart::series::{LineSeries, AreaSeries, BaselineSeries, HistogramSeries, BarSeries}and theSeriestrait withSeriesDataandSeriesType, which the chart never drew through. No replacement; the chart renders its series fromChartType. -
The
model::enumsmodule of wire-format enums, which nothing used, withChartType::to_chart_styleandFrom<ChartStyle> for ChartType. Migration: usescales::PriceScaleModeforPriceScaleMode,ChartTypeforChartStyle, andmodel::LineStyleforLineStyle(it has no large-dashed or sparse-dotted style);CrosshairModeandColorTypeare unrelated toconfig::CrosshairModeandmodel::ColorTypeand, likeChartMode,Timezone,MagnetMode,Orientation,Size,Resolution,ChartTheme,PriceLineSource,ScaleLocation,BackgroundType,OverrideLineStyle,OverridePriceAxisLastValueMode,ChartStyleParameters,ClearMarksMode,MarkLocation,StudyPlotType,StudyDisplayTarget,StudyInputType,StudyTargetPriceScale,LineStudyPlotStyle,OhlcStudyPlotStyleandFilledAreaType, have no replacement. -
ui::top_toolbar::components::symbol_search::popular_symbols, a fixed list of index, crypto, commodity and forex tickers. Migration: pass your own symbols toCompareSymbolsDialog::show. -
The
templatesmodule. Migration: importSettingsTemplateandTemplateManagerfromui::model. -
CVDMode::TickSplit, which computed the same estimate asCVDMode::ClosePositionwhile claiming footprint data; useClosePosition.CVD::with_histogram, which had no effect, with no replacement. -
The Iceberg, Liquidity and Stop Run studies:
IcebergDetector,IcebergDetection,LiquidityTracker,LiquidityLevel,LiquiditySweep,LiquidityZone,LiquidityZoneType,SweepDirection,StopRunIndicator,StopRunDetectionandStopRunType, and the factory names “Iceberg”, “Liquidity” and “Stop Run”. Bars carry no trades and no order book, so these studies guessed hidden orders, swept liquidity and stop runs from bar shapes and from volume spread evenly over each bar’s range. Studies compute fixed aggregations of the data the chart receives; CVD, Net Volume and the volume profiles are unchanged. Migration: detect these events in your application or on your server, from your own trade and order book data.IndicatorFactory::createreturnsNonefor the three names, so code that builds studies from stored names should skip unknown ones. -
The
ui::watermarkmodule (Watermark,WatermarkManager,TextWatermark,TextWatermarkLineOptions,ImageWatermark,ImageScaleMode,HorizontalAlign,VerticalAlignand its ownWatermarkPos), which the chart never drew. Migration:ui::watermarkis removed; the chart’s watermark is configured throughChartConfig(show_watermark,watermark_text,watermark_color,watermark_font_sizeandwatermark_pos, aconfig::WatermarkPos). Image watermarks, custom pixel positions and a font size, colour or weight per line have no replacement;watermark_textmay contain\nfor several lines in one style. -
StoredColor,StoredValue,StoredDrawing::{tool_type, color, line_width, selected, locked, visible, properties},StoredDrawing::{set_property, get_property}andStoredCoord::{from_screen, to_screen}fromdrawings::persistence. Migration: read and set the settings onStoredDrawing::drawing; selection is not stored. -
Deserializefordrawings::persistence::DrawingStorage, which skipped the version check, the migration and per-drawing loading. Migration: load withDrawingStorage::from_json. To keep drawings inside your own serde state, store theto_jsontext and pass it tofrom_json. -
The
scriptingfeature and module, the script editor dialog inui::dialogswith its action enum, and the indicator dialog’s “My scripts” category (IndicatorCategory::MyScripts), which listed the built-in indicators. The interpreter ignored the source argument of mosttafunctions, never reported a crossover and ran one statement per block, and the editor ran scripts on no bars and could not add one to a chart. Migration: write custom studies in Rust withstudies::CustomIndicator; 0.2.0 keeps the module. -
The
backtestfeature and module, and the indicator dialog’s “Strategies” tab (IndicatorTab::Strategies), which listed the built-in indicators. The backtester filled orders at the close of the signal bar, stamped trades with the wall-clock time, dropped orders larger than the cash without notice and left several metrics unset. The dialog is titled “Indicators” and the series context menu entry reads “Add indicator”. Migration: run backtests in the host or on a server against the headless engine with the built-in studies (default-features = false, features = ["studies"]); 0.2.0 keeps the module. -
IndicatorPalette,IndicatorColorSchemesandColorCategory, which no study or component used. Study colours come fromIndicator::colorsand the theme. -
ToastKind::bg_colorandToastKind::text_color, fixed colours that ignored the theme. Migration:ToastKind::color(&theme.ui)gives the kind’s status colour; a toast draws onvisuals.window_fillwiththeme.ui.text. -
AlertKind::bg_color,AlertKind::border_colorandAlertKind::icon_color, fixed colours tuned for the dark theme. Migration:AlertKind::color(&theme.ui)gives the kind’s status colour; an alert fills withcolor.gamma_multiply(0.1)and outlines withcolor.gamma_multiply(0.4). -
Chart::update_dataandChart::data. Migration:chart.update_data(BarData::from_bars(bars))becomeschart.set_data(SeriesId::MAIN, bars), orchart.update(SeriesId::MAIN, bar)for each new or changed bar, andchart.data().barsbecomeschart.bars(SeriesId::MAIN). Theboolthatupdate_datareturned has no replacement: the chart follows the live edge itself whenChartOptions::time_scale.shift_visible_range_on_new_baris set. -
The
validationmodule (DataValidatorand its result types) andChart::{enable_validation, disable_validation, set_validator, is_validation_enabled}, which only logged problems: every bar is validated and invalid ones are dropped. Migration: remove the calls;Chart::feed_state(SeriesId::MAIN).rejected_barscounts the dropped bars. -
ChartBuilder::extendedandChartBuilder::with_drawing_tools: every chart has studies and drawings. Migration: useChartBuilder::new(). -
The consuming
Chart::config(self, config), whose name now reads the configuration. Migration: build withChart::with_config(data, config)or set*chart.config_mut() = config. -
Chart::timescale_marks, which was never drawn. -
examples/tauri_integration.rs, replaced byexamples/live_feed.rs. -
TradingChart: useChart, built withChartBuilder(see Changed). Its studies and drawings live on the chart:tc.indicators.add(s)becomeschart.add_indicator(s),tc.drawing_managerbecomeschart.drawings_mut(),tc.remove_indicator(i)becomeschart.remove_series(id),tc.set_indicator_visible(i, v)becomeschart.set_indicator_visible(id, v)with the study’sSeriesId,tc.remove_drawing(id)becomeschart.drawings_mut().delete_drawing(id),tc.get_last_bar()becomeschart.bars(SeriesId::MAIN).last(),tc.get_symbol()andtc.symbolbecomechart.symbol(),tc.timeframebecomeschart.timeframe()(anOption), andtc.data_srchas no replacement: pass the feed toChartBuilder::with_feed. -
data::DataSource,DataSourceError,DataUpdate,HistoricalDataRequest,SymbolSearchResult,PaginatedSearchResult,BarMarkandTimescaleMark, and theDataSourcere-export at the crate root. Migration: implementdata::Datafeed: answerhistorythrough theReply(HistoryRequest::beforeis an exclusiveDateTime<Utc>,Nonefor the latest bars), and for live data push into theSinkgiven tosubscribe. Errors map toFeedError:ConnError,FetchErrorandIoErrortoNetwork,ParseErrorandInvalidTimeRangetoInvalidData,SymbolNotFoundtoSymbolNotFound,RateLimitedtoRateLimited { retry_after: None }andNotSupportedtoNotSupported. Symbol search is theservices::SymbolSearchservice. -
ChartBuilder::{with_data_src, with_auto_fetch, with_auto_fetch_on_symbol_change, with_auto_fetch_on_timeframe_change}: usewith_feed; a feed always reloads on a change. -
ChartBuilder::{with_left_price_scale, with_left_axis_width, with_right_axis_width}, which set fields the chart never read. -
ui::context_menu::ContextMenuAction::RemoveIndicator, which no menu produced. Remove a study withChart::remove_series. -
model::TickSourceandmodel::OrderBookSource, which the chart never polled: push trades withSink::push_tickand the order book withSink::push_depth_snapshotandSink::push_depth_delta. -
model::LibrarySymbolInfo,SymbolFormat,SubsessionInfoand themodel::symbol_infomodule, which nothing read: describe an instrument withmodel::Instrument.SymbolTypeis unchanged atmodel::SymbolType.model::DataStatusis now the type ofInstrument::data_status, with the variantsRealtime(formerlyStreaming),DelayedandEndOfDay;Pulsedhas no replacement, and the type no longer implementsDefault,Displayor serde’s traits. -
model::bar::{MAX_BARS, MAX_VISIBLE_BARS}andBarData::{trim_to_limit, push_with_limit}, which nothing applied. -
TopToolbarAction::{ChartGridChanged, SetSyncOptions}and theTopToolbar::{chart_grid_selector, sync_button}fields, which the toolbar never drew: no control emits them.ChartGridSelectorandSyncButtonstay intop_toolbar::components. -
DrawingToolbarAction::{ClearSelection, AddFavorite, RemoveFavorite, OpenSettings, DeleteTemplate}, which no control emits. -
TimeframeToolbarAction::{TimeframeChanged, GoToDate, TimezoneChanged, SessionChanged, ZoomFitAll, ZoomToRange, ToggleTradingPanel, TradingPanelFullscreen}, which no control emits, andui::timeframe_toolbar::{TradingPanelRow, TradingPanelRowAction, TradingPanelRowConfig}, which nothing drew, with thePanelSizingTokens::{trading_panel_row_height, trading_panel_row_icon_size, trading_panel_row_btn_size}tokens that sized it andTimeframeToolbarState::{trading_panel_expanded, toggle_trading_panel, set_trading_panel_expanded}, which nothing read. Migration: the date picker emitsDatePickerAction::GoToDate. -
ObjectTreeAction::{ShowSelected, LockSelected, UnlockSelected, UpdateProperties, Reorder, BringSelectedToFront, SendSelectedToBack, PanTo, SaveAsTemplate, LoadTemplate, DeleteTemplate, ToggleDataWindow}, which no control emits. -
ContextMenuAction::{GoToDate, ChangeSymbol, ChangeInterval, SymbolInfo, InsertIndicator, CompareOrAddSymbol, DrawingTools, HideMarksOnBars, PriceScale, TimeScale}, which no menu entry emits. -
SettingsAction::LayoutStyleChangedandSeriesSettingsAction::ResetToDefault, which no control emits. -
The top toolbar’s Menu, Trade and Publish buttons with
TopToolbarAction::{OpenMenu, OpenTradingPanel, Publish}, andtop_toolbar::buttons::{PillButtonFilled, PillButtonOutlined}, whose only users they were. No service backs them: the order ticket brings its own buttons, and a desktop app has its own main menu. -
The chart context menu’s Paste, Add order, Lock vertical cursor line by time and Table view entries with
ContextMenuAction::{Paste, AddOrder, LockVerticalCursor, TableView}, which nothing implemented. -
The series context menu’s Add order, Add financial metric, Security info, Metrics, Paste, Table view, Visual order, Move to, Pin to scale, Add to watchlist and Add text note entries with their
SeriesContextMenuActionvariants, which nothing implemented. The menu offers Add alert, Add indicator, Copy price and Settings. -
The drawing context menu’s Copy entry and
DrawingContextMenuAction::Copy: there is no drawing clipboard. Migration: matchCloneto duplicate a drawing. -
MenuItem::submenuandMenuItem::is_submenu, with theContextMenuSizingTokens::submenu_arrow_font_sizetoken of their arrow: no menu row opens a submenu. -
ExportConfig::{include_title, include_timestamp, include_watermark, width, height, transparent_background}and the export dialog’s checkboxes and size options for them, which no export applied, andExportFormat::SvgwithExportable::export_svg, which nothing rendered. Migration: buildExportConfig { format }; an image export has the size of the chart on screen. -
TimeframeUnit::Tickand the tick intervals of the interval menu: no data contract carries tick bars. -
DrawingToolType::Paintbrush, which drew exactly asBrushand was on no menu. Migration: useDrawingToolType::Brush. Drawings saved in the crate’s JSON format (DrawingStorage, versions 1 and 2) and other formats that store the tool by name, and names parsed withFromStr, loadPaintbrushas a brush. Data that stores the variant index (bincode, postcard) must be re-saved in a name-based format before upgrading. -
The drawing bar’s Favourites button,
utilities::FavoritesButton,DrawingToolbarAction::ToggleFavoritesToolbarandToolbarState::show_favorites_toolbar: the button filled and nothing else changed. The stars in the flyouts keep the favourites list.categories::trend_lines::get_shortcutandcategories::fibonacci::get_shortcutare gone; the flyouts readDrawingToolShortcuts. The Remove menu no longer has a separate “Remove All Studies” row;DrawingToolbarAction::RemoveAllStudiesremains.
0.2.0 - 2026-06-04
Section titled “0.2.0 - 2026-06-04”- Click-to-select for indicators and series on a single unified selection model, with on-chart selection handles.
- Right-click context menus for the chart background, a series, and a drawing, opened directly from the chart.
- Hover tooltip with an OHLC readout, in floating, tracking, and magnifier modes.
- Session-break dividers and optional background shading, with a
ChartBuilder::with_session_breakstoggle (timeframe-aware day, week, and month boundaries). - TPO / Market Profile chart type with point-of-control and a contiguous 70% value-area computation, rendered as letters or blocks.
- Remove an indicator from its pane legend;
Chart::take_indicator_removesurfaces the request to host applications. - Host interaction plumbing:
Chart::take_right_clickandRightClickTarget,TradingChart::take_context_actionandChartContextAction. TradingChartcontroller helpers:config_mut,apply_series_settings,remove_indicator,set_indicator_visible, andremove_drawing.- The bundled demo is now a complete application: every toolbar action, all dialogs, the object-tree and alerts panels, and bar replay are wired, and it is published as a live WebAssembly build.
- Backtest equity now signs short positions correctly, and the Sharpe, Sortino, and Calmar ratios are no longer inflated by a percent-versus-fraction unit mismatch.
- RSI output length now matches the bar count and is no longer misaligned by one bar.
- The indicator factory constructs every built-in indicator by name rather than a small subset.
- Heikin-Ashi candles are computed over the full series, so they no longer change shape on pan and zoom.
- Coordinate and formatter transforms guard against flat price ranges and zero denominators.
- Drawing hit-testing is unified through a single path, and an undone add now survives history pruning so redo still works.
- Selection handles render correctly when the chart is scrolled.
- Embedded SVG icons render because the image loaders are now installed automatically, and notification timing no longer panics on WebAssembly.
- The bundled examples compile again.
- Issue #1: the focus ring appeared when the pointer merely hovered the chart. Issue #2: the examples did not compile.
Changed
Section titled “Changed”- Renamed
ui::stubstoui::model. - Corrected the documented metrics to match the code.
- CI now builds the examples and runs the documentation and feature-gated tests.
Removed
Section titled “Removed”- The unused
egui_plotdependency. - Superseded legacy renderers and the unused render pipeline.
Thanks to @intelligentnet and @sstscrypto for the reports that became issues #2 and #1.