Trader changelog
Every released version of the Vike trading platform, newest first — what changed for a user, what breaks on upgrade, and what was measured.
Seventeen versions have shipped, from 0.1.0 on 2026-07-08 to 0.1.16 on 2026-09-02. This page is the user-facing record: per version, what a user of the platform gets, what changes behaviour on an existing install, and the numbers behind a fix where a number exists.
Versioning is SemVer, and the platform is pre-1.0 — a patch bump may
include a breaking change. Two of the seventeen change behaviour on a box that is already
running, and one moves a directory: 0.1.1 (settings, credentials and state
move into one project folder), 0.1.9 (credential presence stops arming a
venue) and 0.1.15 (<project>/data becomes <project>/market_data). Read
those three before upgrading across them.
Each version is a git tag. The release pipeline builds every binary from that tagged commit on a
Linux runner, embeds an SBOM into each one with cargo auditable, and publishes a SHA256SUMS
manifest covering every asset — binaries, the Dukascopy sidecar jar and the pinned LightGBM tool
alike. Since 0.1.15 the container images are built from those published assets, verified against
that same manifest before anything is copied in, so "the image is the release" is checked rather
than assumed. Install with Docker is the current install
path.
Where these entries come from
The platform's source repository is private, so there are no public release-note pages to link to. Each entry below was written from the project's own curated changelog and from the merged pull requests in each tag's span — the same two sources a maintainer would re-check. Measurements quoted here are taken from those records rather than restated from memory.
0.1.16 — 2026-09-02
The platform got a licence. Until this version the tree carried none at all — signed trading
binaries were shipping to end users under no terms. It is now FSL-1.1-ALv2 (LICENSE.md):
source-available today, with each version irrevocably becoming Apache-2.0 on the second
anniversary of its own release, and paid support and consulting explicitly permitted — the reason
it was chosen over Commons Clause, which bans exactly that.
One executable instead of seven. The new vike binary carries every headless tool —
vike-cli, vike-tradehub, backtest, vike-datahub, vike-recorder, vike-study,
tearsheet — dispatched by argv[0] (an installed symlink) or by vike <tool>. Measured: the
three DataFusion-linked binaries were 128 + 106 + 107 MB,
each carrying its own static copy of the same query engine; the multicall is 128 MB, the size
of the largest tool it replaces. Every old binary name is kept as a thin shim, so an existing
ExecStart= or installed path still resolves.
The container image became a channel people can actually pull. It now carries the whole
headless product — one binary and seven symlinks, 128 MB against roughly 500 — and is pushed to
Docker Hub (vikeio/vike-tradehub) and GHCR (ghcr.io/vike-io/vike-tradehub). There is no
floating latest: each image is tagged with its release version alone.
vike-cli secrets template prints a starter credential grid — every roster venue × SIM/DEMO/LIVE ×
the credential suffixes plus that venue's attribution keys, the legacy MAINNET tier and the
bespoke per-venue shapes deliberately absent — with empty values, derived from the venue roster so
a new venue appears the day its bridge lands. It prints to stdout only; a --out flag was
deliberately not added, because the moment the command owns a path it can truncate a live store.
⚠ FXCM still does not trade from the published image. The ForexConnect runtime libraries are
in the image, but the multicall's release build never enables fxcm: enabling it links
libForexConnect, and the resulting executable dies at exec wherever that SDK is absent — which
would break every non-FXCM user of the same binary. The separate vike-tradehub-fxcm release
asset remains the FXCM path.
Also fixed: three of the eight binaries the image roster named had never built at all, because the roster named a library package and a file name rather than real cargo bin targets — and every text check agreed with it.
0.1.15 — 2026-08-31
⚠ The Linux desktop GUI had never actually run. The GUI loaded every font face from a
C:\Windows\Fonts\… path, so off Windows the named families were never bound and the app panicked
on the title bar in frame one — while the release had been publishing a Linux GUI asset since
0.1.14. Compilation checks and the PNG-export lane could not see it: they render the chart and
Studio examples, not this binary. Found by running it in a container.
Windows GUI assets. vike-app.exe and vike-app-thin.exe are now cross-built on the Linux
release runner and published. ⚠ They are x86_64-pc-windows-gnu, not -msvc — the msvc target
needs the MSVC linker and Windows SDK, which no Linux runner has. vike-app-thin (Linux,
observe-only) also joined, at 51 MB against the fat build's 152 MB.
Two container images, vike-tradehub (the daemon) and vike-thin (the observe-only GUI), both
built from the assets the release already published and verified against its own SHA256SUMS.
⚠ <project>/data is now <project>/market_data. It sat beside <project>/user_data and the
pair read as one concept split in half. The one configuration that moves is a deployment naming no
store root — and a store does not merge: the old one is simply no longer read, and a run
reports zero rows rather than failing, so check where your store resolved before assuming.
vike-tradehub gained the ibkr feature. Before this the GUI could mount IBKR live while the
headless daemon fell through to paper in silence — the daemon crate had never carried the
feature the GUI forwarded.
Fixed: an absent observe key was signed with "" and the node answered bad mac, so "no key"
reached the operator as "wrong key". And a --observe build warned that "this chart will stay
empty" while the chart filled from the node protocol — measured while it logged on repeat against
five hours of live candles.
0.1.14 — 2026-08-29
⚠ A limit price sitting exactly on the venue's tick grid could reach the wire a whole tick low.
Rounding a price to n steps computes n · fl(step); where a step's f64 image sits below its
decimal value, that product lands one ULP under the grid point and the wire quantizer's truncation
then drops a whole step — 5 · fl(1e-6) reached the venue as "0.000004". Measured against live
public instrument
grids: 477 order-placing markets carry an exposed tick (binance spot 96, binance perp 124,
bybit linear 124, okx swap 47, aster 85, deribit 1), and across the 96 exposed binance-spot symbols
one tick is worth a mean of 8.45 bps and a max of 51.8 bps (ATOMBTC), on about 30% of prices.
Truncation biases every limit price toward zero: a sell gives up value and can cross into a taker
fee, a buy loses queue position. The paper exchange never truncated, so live and backtest diverged
by a full tick on exactly those markets. The quantity axis was nearly harmless — the first loss is
at n = 5, so at least four steps always reached the wire.
⚠ The market maker quoted different prices on Windows and Linux. Seven of nine measured rows in
vike-mm differed bit-for-bit between Windows/MSVC and Linux/glibc, including the
Avellaneda-Stoikov optimal half-spread and the LMSR reservation price; the two rows that agreed are
the control that makes it a finding rather than a broken harness. Cause: the platform's own libm
for exp, ln and powf. Cure: the libm crate at those sites, so a quote is the same number on
both boxes. The geometric order ladder had the same divergence in ratio.powi(k) and was converted
with it.
The desktop GUI became a release asset — vike-app-fat for Linux x86-64, with its SBOM
embedded and its line in SHA256SUMS. Obtaining the GUI used to mean compiling the workspace.
Thirteen of the fourteen venues can now express a second account, and the credential editor can
create one. Also fixed: 44,840 leaked temporary directories, and four venues whose credential dots
and forms read key names no bridge reads.
0.1.13 — 2026-08-25
Two fixes, both found on a live box after the previous deploy. A reconcile pass that changed nothing logged anyway, once per pass carrying alerts — about 1,440 lines a day per venue, and wholly redundant when nothing moved. A pass that folds events still logs every time, and a venue with nothing held stays silent exactly as before.
Deribit's post-reconnect history replay stopped forever on the first socket close, in silence. The resync transport connected once and nothing re-dialled it, so a venue-side close ended the replay of order and trade history across reconnect gaps for the life of the process, with every error swallowed. It was the last of three never-heals sockets in that bridge; the other two were fixed in 0.1.11. An outage is now bracketed by one warning naming the consequence and one recovery line, and the latch re-arms — a latch that fires only once makes a broken lane look healthier the longer it stays broken.
0.1.12 — 2026-08-25
A venue can mount several accounts. The mount now creates one engine per active account — its per-account ceiling permits it, its credentials load, the venue's arm can address an account at all, and no symbol collision refuses it. Account selection and the Data Manager's Effective column are one function, so the screen cannot disagree with the mount, and a default-account box is byte-identical (measured: one engine per roster venue, an empty live-venue set, and a ledger record with no account key at all).
⚠ Only binance, bybit, okx and deribit consume the account-aware credential loader. A labelled account is refused elsewhere rather than half-supported — arming one would otherwise have built a live client on the first account's credentials.
Also: the live journal's p99.9 tail is gone rather than reduced — 37,150 → 3,342 ns, an 11× improvement over interleaved medians of eight repetitions, landing where the journal-less baseline already sat.
0.1.11 — 2026-08-25
Security — a Rhai strategy, and a user indicator, could read any file on disk. Fixed.
⚠ IG's fill lane had never worked, for any account, demo or live. The trade stream sent
LS_cid: "vike-trader-rust" where Lightstreamer's client-type licensing field must carry the
TLCP-2.1.0 mandated value, and IG answered CONERR,71 License not valid for this Client type on
every dial since the day it was written. The market-data lane always sent the correct value, which
is why feeds worked while fills did not — and why the split read as an account-permissions problem
for weeks. Proven on the wire against the demo gateway with one login and two client ids,
everything else held constant.
A Deribit socket closing mid-submit reported an order rejected that the venue may have accepted. Only a response timeout was treated as ambiguous, so a mid-request close — the common first error on a dying socket — synthesized a terminal reject for a possibly-live order, stranding a phantom position. Resolution is now re-dial then re-query, never re-send. Separately, a Deribit reconcile lane died on its first socket close and never recovered: 795 identical failures in a day while the daemon reported healthy.
Two log floods that could hide a real event. A permanently refused IG stream wrote an error line every second forever — 53,160 lines and 23 MB in one day from one loop, 99.5% of that box's entire error volume. And a held reconcile divergence re-announced itself every interval with an unbounded alert store: 396 warnings in a day for one bybit divergence, with a genuinely new one indistinguishable among them. A held divergence is now a state — announced on entering and on clearing, with a slow backlog summary and one stored row per distinct identity.
Added: perpetual funding premium is no longer discarded, and is recorded as kind=perp_metrics;
and a study can be run from the Studio GUI, either tier, with one results surface.
0.1.10 — 2026-08-24
Small, and both entries are consequences of watching the previous release run. A held reconcile
divergence now reaches the log, not only an in-memory ring: the shipped daemon's control channel
is off, so reconcile pass folded venue=bybit events=0 alerts=2 repeated every 60 seconds for
hours with nothing at WARN or above, and no way for anyone reading logs to learn which two
divergences were being held. The raise path now emits a warning carrying the divergence kind, venue
and detail; the refresh path stays silent on purpose, because a divergence held for a day would
otherwise re-raise 1,440 times. The second fix is a release-blocking test flake, not a product
change.
0.1.9 — 2026-08-24
⚠ Breaking behaviour: credential presence stops arming a venue. Per-venue arming is now a
setting — policy.toml's [venues] table, paper / demo / live, defaulting to paper — and
it is read above the credential read, so a disarmed venue loads no credential, fetches no
instrument grid and opens no socket. The ceiling can only ever refuse; a live line arms nothing
by itself. Measured on a live box beforehand: a daemon profile that mounted one venue printed
nine live authenticated exec sessions, aster among them — a venue with no testnet, whose keys
reach the real account.
A box with no [venues] table therefore mounts everything on paper, whatever its credential
store holds. That is loud rather than silent: the daemon warns once at startup naming the file, the
key and every venue it refused, rather than refusing to start. The GUI's Data Manager gained the
matching screen — what is live, and why not.
Also in this version: the live change journal records what each venue was asked to be and what it became; Polymarket answers its own geoblock before the mount instead of one 403 at a time, and a cancel batch survives to the venue so the flatten reserve's bulk arm is no longer dead code; the REST rate gate became FIFO, so a heavy caller is no longer starved by light ones inside quota; and the first (additive, locally built) backend container image landed, with the project folder mounted rather than baked in.
0.1.8 — 2026-08-22
⚠ The two runtime tools became obtainable. A release now attaches the Dukascopy JForex sidecar
jar and the pinned LightGBM binary — with the PROVENANCE file vike refuses to run without —
covered by the same SHA256SUMS as the binaries, and they are downloaded, verified and installed
into <project>/bin/<tool>/. Before this, a research run hard-failed on a fresh install because
nothing shipped LightGBM, and Dukascopy worked only because a 43 MB jar was committed into the
source tree.
⚠ The jar is no longer committed, so an offline clone no longer gets one. JFOREX_BRIDGE_JAR
names one outright, and the provisioning script's --rebuild still builds one from source. Its CI
gate became a reproducibility gate instead: the jar is built twice from a cleaned directory and
the two must be byte-identical, which is what lets anyone re-derive a published digest from the
tag.
Fixed: the startup preflight's clock budget was a flat constant sized against six venue reads, and the roster outgrew it — 5,973 ms needed against 5,000 available, so eight venues reported their clock "not read". It is now derived from how many venues are actually read, sized to absorb one dead venue and still read the rest.
0.1.7 — 2026-08-22
⚠ The startup preflight's clock budget was being spent by credential probes. The two legs interleave per venue, and a credential probe is a blocking authenticated read — so one unreachable venue sat about 20 s on a TCP connect and cost alpaca, aster and hyperliquid their clock checks, while the log blamed "an earlier venue's clock read" and sent operators to inspect rows that were all fast and healthy. Each probe is now measured and the deadline pushed out by its cost, so the budget bounds the clock leg and only the clock leg.
OKX options were never in the catalog. The listing was fetched as a bare instType=OPTION,
which the venue refuses with 400/50015, while okx's advertised asset classes included options
and the picker received zero. Now fetched once per underlying: okx 2,004 → 5,162 instruments.
Alpaca reported a transport failure as HTTP 401 — answering a network condition with a
credential rotation. A token mint that answered and refused is now separated from one that was
never reached. And the GUI can now be launched with no credentials in scope, so every venue stays
paper by construction: on a populated box the obvious "just look at a chart" run could not start at
all, because a live mount refuses without an operator risk budget.
0.1.6 — 2026-08-19
Five more venues joined the daemon's live-wired set — alpaca, ctrader, oanda, deribit and ig — each mounting a credentialed market-data lane the way binance and friends already did. Deribit, oanda and ig also gained their first live market-data adapters: oanda's chunked-HTTP pricing stream, and ig's Lightstreamer TLCP spoken raw over the shared transport stack. ⚠ IG serves no depth, which its adapter says outright rather than reporting an empty book.
The datahub authenticates. It had served history reads, backtest compute over client-supplied Rhai and — in a backfill-serve build — writes into the store, to anything that could reach the socket. It now speaks the node handshake with scoped reads and writes; keys absent serves exactly as before, so an existing single-user install is unchanged.
Settings hot-reload for the classified-safe subset: the console and file log levels apply on a
running daemon, every other key answers restart_required, and policy.toml is structurally
excluded, so no future key can make a risk ceiling hot-appliable. Runtime strategy mounts now
survive a restart — a mount is remembered as daemon state, and only an explicit unmount forgets
one. vike-cli strategy-status asks a running node what it is running (human table, or the wire
payload verbatim under --json); asking used to mean compiling a throwaway probe.
A cluster of fixes with one shape — a capability gap was answering as data: a history store that cannot serve depth now refuses instead of returning an empty read, a failed Studio scan stopped rendering as an empty store, oanda's live tier refuses instead of vanishing, and an FXCM login that failed reddens its smoke test instead of being reported green.
0.1.5 — 2026-08-19
Aster joins the daemon's live-wired venues — ⚠ capability only, and the mainnet warning travels with it: no aster testnet credentials exist, so an armed aster lane reaches the real account.
Backends are managed from the GUI — add, edit and delete backend records in place, with
key-name hygiene on the credential names each record points at. Settings became writable over the
wire, behind the control scope and a typed confirmation: the would-be file is validated with the
same loader that will read it back, edited comment-preservingly (untouched lines stay untouched
bytes) and landed atomically. policy.toml is special-cased — a risk ceiling is not a remote edit.
0.1.4 — 2026-08-18
One daemon, N strategies, N venues. Strategies mount and unmount at runtime off the fold, and
two new wire verbs — a read-only StrategyStatus and a control-scoped UpdateParams — let you
inspect and retune a mounted strategy without restarting the daemon.
A third GUI mode: observe a backend while taking venue market data directly rather than through that backend. Backfill-on-demand over the datahub wire — the backend fetches a bounded kline range once, writes it through to the store, and replies only after the served handle reads it back; it is capability-negotiated, so a client refuses locally against a server that does not advertise it, and remote-mode chart gaps backfill through the same path.
Reconciliation gained EXTERNAL-tagged divergences and an opt-in hold-first policy
(external-quarantine), so a foreign account's activity needs an operator claim instead of being
folded blind. Hyperliquid and aster grew feeds-only builds: the market-data plane compiles
without the order signer.
0.1.3 — 2026-08-18
Rhai strategies mount live. [strategy] rhai = "<path>" in a daemon profile compiles the
script through the same engine builder the backtest arm uses and mounts it on the same paper or
live core, with the script's audit hash logged at mount.
The GUI gained a persisted backend registry (records, key resolution, and the control arming
gate) and runtime backend switching — one active backend, total state clear on switch — with
both status surfaces naming the connected daemon and whether it is LIVE or paper. Studio moved onto
the HistStore trait, so it can browse a served store rather than only a local one.
0.1.2 — 2026-08-18
The split-plane safety trio. LiveLock — one live process per venue account, so two live
traders can no longer silently rewrite each other's positions through reconciliation. A Windows
console-ctrl graceful stop: Ctrl-C and window-close now run the same bounded teardown as the unix
SIGTERM arm. And the observe snapshot names its daemon — profile name, mounted strategy,
paper-vs-live and build identity — so a client can tell which node it is looking at.
0.1.1 — 2026-08-18
The largest release by a wide margin: 1,062 merged pull requests over six weeks, and the one that reshapes an existing install.
⚠ Breaking — settings unification. Every setting the typed settings model reads from a file, every credential and the state the program writes for itself now live in one project-owned directory:
<project>/settings/policy.toml config.toml preferences.toml flags.toml
<project>/settings/secrets.env every API key, every venue
<project>/settings/state/… program-written filesCredentials moved from <repo>/.env. Absent credentials are the live gate, so a leftover
.env used to mean every venue silently on paper with nothing in any log; an absent store with a
.env beside it now warns on every credential read, naming both paths — a finding, never a
refusal, because .env is also a legitimate systemd EnvironmentFile, and nothing reads, prints
or moves its contents. <project> is resolved at runtime by walking up for a project marker;
VIKE_SETTINGS_DIR names it outright and skips the walk, which is what a deployment should set.
⚠ Three environment variables are refused at startup, not ignored. VIKE_MAX_ORDER_NOTIONAL
and VIKE_TRADEHUB_MAX_ORDER_NOTIONAL became policy.toml's max_notional_per_order, because a
ceiling any exported variable can raise is not a ceiling; VIKE_SECRETS_PASSPHRASE is refused
because nothing consumes it. A set, non-empty value is a hard startup failure naming the file, the
key and a paste-ready replacement line — an operator who set one believes a ceiling is armed, and a
build that quietly ignored it would trade uncapped.
What else is in it. Five venue bridges — hyperliquid, aster, ibkr, alpaca and ctrader —
taking the roster to fourteen. The headless daemon vike-tradehub, with an authenticated
observe/control wire and a thin --observe GUI client for it. The unified vike-cli: backtest,
sweep, walkforward, a human trade REPL, config show (every setting, its value, and where it
came from), and mcp — the agent surface. The live reconciliation engine behind
VIKE_RECONCILE, off by default. vike-datahub, the compute-to-data backtest server, and a Studio
that can drive it locally or remotely. An alerting engine inside the daemon, and an optional
confirm-gated Telegram control channel.
If you are upgrading an install made before this version, start the binary and read what it prints: every leftover from the old layout is handled explicitly — silently, with a warning, with a refusal naming the replacement, or by migrating itself — and the startup output names which.
0.1.0 — 2026-07-08
The first tagged release, at 389 commits. One execution core behind a unified Strategy/Broker
seam, so a strategy written once runs in backtest and live. Nine venue bridges — binance,
bybit, okx, deribit, oanda, ig, fxcm, dukascopy and polymarket — each speaking one
ExecutionClient contract, with live market data on the tick and L2 lanes. The DataFusion +
Parquet history store, with date partitioning, background compaction and retention, WAL crash
recovery and bounded-memory streaming scans. The accounting upgrade: a buying-power gate, margin
call, order_target, and multi-symbol, cross-venue mounts. A chart with log and percent scales,
panes and persisted workspaces. Tracing-native structured logging across the workspace.
The error-lane closure the venue contract still rests on landed here: no order may silently vanish, a submit timeout re-queries rather than assuming an outcome, and post-reconnect history replay recovers terminals and fills that landed inside a gap — across binance spot and perp, bybit, okx, deribit and polymarket.
And the machinery that makes every later entry on this page checkable: the tag-triggered release
pipeline, a cargo-deny supply-chain gate, SHA-pinned CI actions with least-privilege tokens, a
pinned toolchain, and a workspace-wide unsafe_code = "forbid" lint.