vike
Desktop appStudio

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.

On this page