Studio
The in-app IDE for a strategy over recorded history — a Rhai editor, a store-backed slice picker, worker-thread Run, Sweep and Walk-Forward, and a tabbed results pane, in one window of the desktop app.
Studio is one tool window of the desktop app, opened from the launcher row's studio icon
(crates/vike-desktop/src/main.rs's LAUNCHERS), titled "Studio" and painted in the violet that
crates/vike-app-core/src/workspace/state.rs's WinKind::Studio assigns. What it holds is stated
by crates/vike-studio/src/lib.rs's header: a Rhai editor, a store-backed slice picker, a
worker-thread Run over the history store, and tabbed backtest results — egui without a window
system of its own, so the crate is CI-testable and vike-desktop mounts it.
The shell
crates/vike-studio/src/studio.rs's StudioState is the shell: a Run toolbar across the top, the
editor on the left, a tools panel on the right, the results in the centre.
The toolbar carries, left to right, the data-slice picker, a chip naming which strategy ▶ Run will
execute (🧩 rhai for the editor buffer, or the native registry name — clicking it jumps to the
Strategy tool), ▶ Run, and ⟳ Refresh, which re-scans the store. Everything transient — the spinner,
✖ Cancel, and the "running backtest…", "running sweep…", "running walk-forward…", "running study…"
or "comparing saved…" label — is right-aligned so the left half never jumps mid-run. A second line
selects the backend: Local, in-process over the store, or Remote, which offloads a Run, Sweep or
Walk-Forward to a vike-datahub server (Remote runs).
The right-hand side is two sibling panels in the activity-bar shape of a code editor: a 40 px icon
rail and a 340 px tools panel. Seven tools share the one tabbed panel — RightTab's doc records
why: simultaneous side panels crushed the editor and results to a sliver. In rail order: Sweep &
Validate, Strategy, Data, Indicators, Saved, Research, AI Chat. Clicking the active tool's icon
collapses the panel; clicking any other selects it and expands. Each page in this tree covers one:
the editor, data and slices,
the indicators pane,
the templates gallery,
the research pane, results,
saved strategies and the workspace, and
the AI copilot.
Three shortcuts are checked once per frame, Ctrl on Windows and Linux and Cmd on macOS:
Ctrl+Enter runs the backtest, Ctrl+S saves the editor buffer to the Saved list, Ctrl+/
cycles the tool tab and expands the panel, so the shortcut always shows its effect.
What Run executes
StudioState::current_spec is the one place the choice becomes a runnable StrategySpec. The
Strategy tool's "Rhai script" runs the editor buffer; "Native (Rust)" runs a compiled strategy
from the backtest harness registry, with its parameters
typed as free-form key/value rows. The rows are free-form on purpose —
crates/vike-studio-core/src/spec.rs's header: the harness has no parameter spec to generate a
form from, so a typed form would be a second source of truth no strategy is obliged to honour.
params_from_rows types each cell (3 an integer, 2.5 a float, true a bool, bare text a
string), and the pane echoes the resolved table so the fallback is visible rather than surprising.
Sweep & Validate holds the parameter grid. "Seed from params" fills it from the script's param()
declarations — or, for a native strategy, from the numeric rows you typed, since no
discover_params twin exists for the registry. ▶ Run Sweep backtests every grid combination and
ranks by Sharpe; Walk-Forward is a four-split anchored out-of-sample validation
(StudioState::start_walkforward fixes n_splits at 4, and
crates/vike-studio-core/src/run.rs's run_walkforward_slice_with_params runs
WalkMode::Anchored). The templates dropdown and gallery live in the same pane.
Nothing runs on the update loop
Run, Sweep, Walk-Forward, Compare all and a study each spawn a worker thread and hand back a
receiver; StudioState::poll, called once per frame, folds whatever arrived. A worker that panics
or drops its sender is a terminal failure surfaced as "run failed (worker terminated)" rather than
a spinner that never stops.
Cancel abandons; it does not kill
StudioState::cancel drops the receivers and resets the running state so the UI is usable the
next frame, but there is no cooperative-cancellation hook into the engine: the spawned thread keeps
executing the backtest to completion in the background, and its result is discarded on arrival.
The CPU time is not reclaimed. A true kill would need a cancellation token threaded through the
engine and the script strategy, which that method's doc names as out of scope.
Two result surfaces
The centre panel shows one of two producers, and CenterView's doc is explicit that the split is
deliberate: a backtest's numbers come from the event-driven simulator and a study's do not, so
results_ui renders a BacktestResult and study_result_ui renders a StudyRun, each naming its
own producer. Every dispatch claims the panel for its own surface, so you see the result of the
thing you last asked for rather than the winner of a precedence rule. Before any result exists the
panel reads "1 Pick a data slice · 2 Write or load a strategy · 3 Run" and offers ▶ Run backtest
and Load a template directly — and it asks the picker whether its scan failed before it asks
whether the list is empty, because an unreadable store leaves the list empty too, and the old
emptiness test sent an operator whose datahub had gone away off to backfill history.
The store, and where it comes from
The Studio holds its history store as a trait handle — StudioState::store's doc: a local
DataFusionHist or an RPC-backed RemoteHistStore, every pane reading through HistStore verbs
only. vike-desktop opens it lazily, once, the first time the window is shown; success and failure
both stick, so a broken store never retries the open on every frame. With a resolved datahub
address the app dials a remote store, probes it with one list_series, and — since the same server
serves the store verbs and the run verbs — seeds the backend to Remote and arms the tick rule.
Without one there is no local arm to fall back to — the binary links no store engine — so the open
is an error naming both fixes — set config.datahub_addr, or connect a
backend that advertises its datahub. crates/vike-desktop/src/main.rs's open_studio_store is the
authority; see the history store and
observe mode.
The library reads no credential store, and the constructor takes its configuration as parameters —
StudioState::new's doc: the per-store state directory, the AI-provider keys, and the two
headless-capture hooks are values the binary resolves and passes in. What the crate still reads
from the environment is where the workspace snapshot lives, and the constructor reaches it through
load_workspace: crates/vike-studio/src/workspace.rs's state_root_override reads
$VIKE_STATE_ROOT, and its project_state_dir walks up from the working directory —
saved strategies and the workspace covers where the file
lands.
The options chain
The Options window is a mirrored calls–strike–puts ladder over Deribit's public book, kept live between polls and painted with the trader's own orders and positions; the Greeks window prices those positions off the same chains.
The editor
A code editor bound to the strategy source, compiled on every change through the same path Run uses, with the verdict as a chip, an inline banner naming the line, and an amber dot while the buffer has drifted from its last save.