Architecture
July 3, 2026 · View on GitHub
wickra-copilot is one data-driven core with many thin consumers, plus a
separate, swappable LLM adapter. The core turns a serde ContextSpec folded over
serialized microstructure feeds into a MarketContext — a list of hard facts.
Because the context is data, not instructions, the exact same result is produced
natively, across the C ABI and in WASM, byte-for-byte identical — and stays
identical between the parallel (rayon) and sequential builds. The LLM call that
turns that context into an answer is a distinct, non-deterministic layer, kept
strictly out of the deterministic core.
The layers
CONSUMERS CLI: crates/copilot-cli (context | ask) · desktop: crates/copilot-desktop · any language via its binding (command JSON)
▲ MarketContext JSON (deterministic) │ Answer (LLM, non-deterministic — only via `ask` / the adapter)
CORE crates/copilot-core: ContextSpec (JSON) + FeedSnapshot (JSON)
→ FactBuilder (O(1), deterministic) → MarketContext { Vec<Fact> }
+ ToolCatalog (function-calling interface) ← deterministic, golden-tested
▼ data-driven JSON API in ten languages (like screener command_json / backtest run_json)
ADAPTER crates/copilot-llm: provider abstraction + prompt renderer (MarketContext → messages)
→ calls the user's own LLM endpoint, key from the environment *** separate, non-deterministic, never golden ***
BINDINGS python · node · wasm · c (C-ABI hub) → c / c++ / c# / go / java / r
CORES wickra-core (indicators grounding facts) · wickra-exchange (microstructure feeds = fact inputs) · wickra-data (Candle, optional)
Each binding ships the same surface — a Copilot handle plus
command(json) -> json and version — with its own README, tests, a runnable
example, and a completeness guard.
The core is data-driven
A Fact is a serde data-model, not a list of instructions, and the spec that
selects and thresholds the facts is data too: a ContextSpec never carries a
Rust closure. Closures cannot cross the C ABI or a WASM boundary; a serde
data-model can, so a Python, Go or browser consumer builds the identical
MarketContext a Rust consumer would.
The six facts
Each fact is a hard, attributable observation derived from the feeds — a
kind + symbol + value + magnitude + ts + a human-readable string:
price_move— a significant move in price over a window.orderbook_imbalance— resting bid/ask volume skew at the top of book.liquidation_cluster— a burst of liquidation notional in a short window.funding_flip— the funding rate crossing zero or reaching an extreme.oi_change— a relative change in open interest.volatility_spike— a jump in realised volatility.
The facts are the grounding: an answer is built from the real order book, liquidations and funding, not from the model's priors.
Determinism is the moat
The MarketContext is byte-identical across all ten languages and between the
parallel and sequential builds: BTreeMap in every output path, the fact vector
stably sorted (severity then symbol key), no RNG, and reductions run serially in
key order rather than rayon order. That determinism is what lets the golden corpus
pin the context byte-for-byte. The LLM call is never part of it — it is
non-deterministic by nature and lives entirely in the separate copilot-llm
adapter.
The command boundary
Every consumer talks to the core through a single JSON-in / JSON-out function,
Copilot::command. The binding does no logic of its own — it forwards the command
string and returns the core's response verbatim. That verbatim pass-through is
what makes the golden corpus a cross-language parity corpus: the same command
produces a byte-identical MarketContext in every language, with no per-language
JSON reformatting.
The LLM adapter
copilot-llm renders a MarketContext into a prompt and calls the user's chosen
LLM over the OpenAI-compatible chat/completions interface. Four providers are
selectable (ollama / openai / claude / gemini, plus custom); each preset
only sets the base_url (overridable via the environment), so one HTTP
implementation targets four endpoints. Ollama is local and needs no key; the cloud
providers use the user's own key, read from the environment. It is not a hosted
service and places no orders — it reads market data and asks questions.
Indicators come from the Wickra core
No indicator mathematics lives in this repository. Where a fact needs a derived
series (realised volatility, OI deltas), IndicatorSet resolves each building
block from the wickra-core registry by name and parameters (the same resolver
the backtester uses), so wickra-copilot inherits all 514 indicators and any
future additions for free.
Integration with the rest of Wickra
wickra-copilot sits beside the other Wickra consumers — the terminal, the
screener, the X-ray, the radar and the backtester — over the same core. It depends
on wickra-core (indicators) and on wickra-exchange, whose order-book, trade,
funding, open-interest and liquidation streams define the shapes of the copilot's
input feeds; wickra-data (Candle + CSV) is optional. It only reads and
analyses market data — it never places orders and holds no order-secret material.