Forex & Multi-Asset Trading 6.0.0
28 July 2026
This release has upgrade notes. Read them before updating — they describe behaviour changes that need your attention.
Forex & Multi-Asset Trading v6.0.0
Release Date: July 28, 2026 Tags: CHARTS, MARKET DATA, PROVIDERS, POLYGON, INSTRUMENTS, CATALOG, SECURITY, ADMIN, UI
Overview
Version 6.0.0 fixes the two things that made the terminal untrustworthy: higher-timeframe charts were built from invented candles, and closed markets showed no price at all. Chart history is now real, closed markets quote a last price, and the terminal shows the spread you can actually deal on.
Live quotes and historical candles can now come from different providers, so an operator is no longer forced to choose between a vendor that streams in real time and one that sells deep history.
Requires Core v6.5.8.
Update Instructions
pnpm updatorThe chart cache key is versioned in this release, so previously cached series are retired automatically. No operator action is required.
Upgrade Notes
None.
Added
Closed markets showed a dash instead of a price
Every instrument whose market is shut — all US stocks for ~17 hours a day and the whole weekend — rendered a bare dash in the markets rail, even though the provider serves a last price over REST.
- Added display-only snapshots of the last traded price, TTL-cached with negative caching, fetched in small batches on subscribe. Used by the markets rail, the single-symbol ticker endpoint and the ticker stream.
Providers
- Added an asset-class coverage column to the provider list, visible before switching. Switching to a provider that lacks an asset class silently strands every instrument in it — a stocks-only provider takes an FX-heavy catalog dark — so the coverage has to be visible in advance. It renders without an API key.
Polygon adapter
- Added coverage for US stocks and ETFs plus currencies and precious metals, with aggregate history and dividend/split calendars.
- Added graceful degradation for plan entitlements: no WebSocket entitlement falls back to REST snapshots (display only — a REST-only plan cannot quote a tradable price, so the terminal shows a last price and cannot trade), no real-time FX snapshot falls back to previous close, and entry plans serving daily bars only return empty intraday results instead of errors.
Admin
- Added lifecycle status back to the instrument edit form. It previously said status changes had to go through the table's bulk actions.
Changed
History and live quotes can now use different providers
- Changed the chart to fall back across providers for history. Live quoting stays strictly single-provider — one feed owns the marks that fills are priced against. Historical candles have no such constraint, so the chart now tries the active provider first, then falls back to any other configured provider holding an API key, up to three in total.
- Fixed duplicate fetching — the back-fill re-checks after each provider, so a fallback only fetches what is still missing.
- Why: keeping the two coupled forced an all-or-nothing choice between vendors that stream live but sell no history and vendors with deep history but no live feed, which is why charts ended up either flat or hours stale.
Admin
- Changed the edit form and the table's bulk actions to share one transition table and one set of guards, including the provider-symbol requirement for activation and the open-position guard for deactivation and delisting.
Terminal
- Changed the terminal header to match the Pro trading header: a 40px bar of full-height square segments separated by hairline borders, carrying the back link, FX brand link, selected symbol with asset-class chip, session dot and status badges, and a live Bid / Ask / Spread / 24h strip.
Fixed
Higher-timeframe candles were fabricated from ticks
Daily, weekly and 4-hour candles were built from the live tick stream — a "1w" bar whose open, high, low and close described four minutes of quotes. Because those bars were written to the cache, the chart considered the slot filled and permanently suppressed the real provider back-fill for it.
- Fixed the tick engine writing coarse bars at all: it now persists only the 1-minute series it can honestly observe, and every coarser interval is rolled up from it on read. Buckets with no underlying data stay empty instead of being carried forward as flat bars.
- Fixed an in-progress coarse candle the engine joined part-way through, which is now rebuilt from the recorded minute bars, so the live frame agrees with the history the chart just loaded.
- Changed the Redis cache prefix, which is now versioned so existing fabricated series are retired without an operator flush. Gzip files on disk only ever received provider candles and stay valid.
Tick history did not survive a restart
The only copy lived in Redis under a 24-hour expiry, which is why the on-disk chart folder was still empty after the plugin had been running for days. Every restart or key expiry threw away all accumulated candles.
- Fixed the loss on restart — the live series is now flushed to disk on a one-minute cadence.
Candles were being silently dropped
Overlapping writes to the same series each re-read and rewrote the whole array, so a later read starting before an earlier write landed threw candles away. Observed live as 29 surviving 1-minute candles across a 73-minute span.
- Fixed the dropped candles — writes per series are now serialized.
Provider bars did not line up with the chart grid
Vendors anchor bars to the trading session, not the epoch — a US-equity hourly bar stamped 13:30 UTC, daily bars at exchange midnight, weekly bars starting Sunday or Monday. Stored unsnapped, those bars never satisfied the "do I already have this?" test, so the same range was re-fetched on every load and pan, and the derived roll-up stacked a second offset copy of the series on top.
- Fixed the misalignment — provider bars are snapped onto the same time grid, folding collisions with OHLC semantics (first open, max high, min low, last close, summed volume) rather than last-wins.
Other chart fixes
- Fixed the back-fill budget being shared across ranges. A session calendar that fragments a window into many small gaps spent the entire budget on the oldest gaps and never reached the recent ones the user is looking at. Each range now has its own budget alongside the global one.
- Fixed out-of-order provider timestamps rolling a candle backwards, which persisted an unfinished newer bar as complete and then overwrote the finished older one with a single-tick bar.
- Added a cap on persisted series length, so the tick engine no longer grows the cached array indefinitely and re-serializes the whole thing on every upsert.
The terminal quoted prices nobody could trade at
The ticker published the raw feed quote. Feeds that carry no order book give an identical bid and ask, so the terminal showed a 0.0 spread and a bid/ask that could not be dealt on.
- Fixed the untradable quote — the ticker now applies the instrument group's spread markup using the same calculation the order path fills at.
Feed reliability
- Fixed a dead feed staying dead until a process restart. When the stream's circuit breaker opened after repeated failures it latched shut and nothing would re-arm it, ending the price feed for every symbol until a client happened to open a brand-new instrument. The breaker now stays half-open, probing at the slowest backoff, so the status still reads "failed" for alerting while the feed heals itself.
- Fixed a stream that never opened at all (provider rate-limited, no active provider row, database blip) never being retried. It is now re-attempted on the periodic staleness sweep.
- Fixed halted and closed symbols rendering as live indefinitely. The only message carrying a symbol's state was the ticker, which by definition stops arriving exactly when the feed dies. State transitions are now published on the channels the client actually listens to.
- Fixed subscribe-time snapshots being broadcast to every connected client instead of the subscriber. Because the chart merges incoming frames rather than replacing them, every new subscriber or React remount regressed the close and double-counted the volume on every other open chart.
- Fixed the subscribe snapshot serving a stale cached bar for the current bucket. The engine's in-progress candle is now preferred when it is at least as recent.
Security
- Fixed the public single-symbol ticker endpoint pushing a REST snapshot into the price engine. On a closed market this let an unauthenticated request promote a stale last trade into the tradable mark, the persisted chart bar, and a full stop-loss / take-profit / stop-out sweep. The endpoint now pins the symbol for streaming but returns the snapshot for display only.
Instruments were matched to the wrong asset
Import matched purely on the currency pair, ignoring asset class. WTI/USD (crude oil) was linked to the "WTI" stock ticker — W&T Offshore, around $3.66 — and quoted a penny stock as oil indefinitely.
- Fixed the cross-asset match — matching is now asset-class aware, and a class mismatch leaves the row unmatched. A wrong feed is worse than no feed. Index rows are the deliberate exception, since they are priced through ETF proxies and legitimately resolve against the stock universe.
- Added alternative vendor codes, tried when a catalog row's own symbol is absent from the provider's list. OANDA-derived feeds publish crude oil as
WTICO/BCO, for example. - Fixed the classification of OANDA's "forex" list, which is a mixed CFD universe carrying metals, energy, softs and cash indices alongside currency pairs. These are now classified correctly instead of all being treated as foreign exchange.
Other import fixes
- Added a report of stranded instruments: rows still live that the selected provider cannot quote. Import never removes another provider's mapping or changes a status, since an active instrument may hold open client positions, so switching providers could previously leave live markets silently on a feed that no longer runs.
- Fixed ETF index proxies (SPY, QQQ, DIA, IWM) being dropped during import. Without them, activating any row in the "Indices (ETF)" group failed with "no provider symbol mapping" immediately after running the import. Their listing venues had to be allowed too.
Providers
- Fixed provider descriptions only being written at creation, so an install kept showing stale claims. One provider's saved text still advertised foreign exchange it has never supported. Operator config (status, proxy URL) is untouched.
- Fixed credential verification showing an empty green banner on success, because adapters only attach a message on failure.
Polygon adapter
- Fixed FX symbols being silently dropped from the live feed. Polygon serves stocks and currencies on separate sockets with different subscription grammars and event shapes; routing everything at one socket looked exactly like a dead feed, since the vendor ignores unknown subscriptions. The adapter now runs both clusters as independent lanes, and one cluster being down or unentitled never silences the other.
- Fixed gold being mapped to the equity ticker "XAU". Membership in a known currency/metal list — not "the quote happens to be USD" — now decides FX versus equity.
Admin
- Fixed resubmitting an instrument's current status being rejected as an illegal transition, which made saving the form without touching status fail.
Terminal
- Fixed a spurious "Instrument not found" error on load. The chart now mounts only once a visible instrument is selected.