A Gymnasium-compatible, microstructure-aware backtest environment with O(1)
steps for fast RL rollouts over 497 streaming indicators. The whole dataset is
precomputed once into a fixed feature tensor, so step() is a pure array index —
and the same seed produces a byte-identical trajectory in every language.
▶ Live demos: the backtester compiled to WebAssembly, an equity curve building bar by bar — backtest-live.wickra.org; one StrategySpec side by side in Python, Rust, JS and Go — playground.wickra.org; all 514 indicators of the core over a real Binance feed — live.wickra.org. Zero backend, all of them.
Part of the Wickra ecosystem. Built on the same deterministic engine and ten-language binding surface as wickra-backtest, wickra-benchmark and the rest.
wickra-gym turns a candle dataset plus an observation/action/reward
specification into a reinforcement-learning environment. It precomputes every
bar's features (indicators, and optionally orderbook / funding / open-interest
microstructure) in one O(1)-per-bar pass into a fixed FeatureTensor; from then
on each step() is a constant-time index into that tensor, so rollouts are fast.
The reward draws on the wickra-backtest
fill/PnL model, and the only source of randomness is an explicitly-seeded episode
RNG — so a (seed, policy) pair fully determines a trajectory.
The core (wickra-gym-core) is a JSON-over-C-ABI data API usable in ten languages, and
Python additionally ships a real gymnasium.Env subclass as its primary
consumer.
=
, =
, , , , =
Every step is a pure array index into a tensor precomputed once, so a
(seed, policy) pair fully determines the trajectory — in any of the ten
languages, byte for byte.
Status
0.2.0 — the current release. The core, the CLI, all ten language bindings, the golden trajectory corpus, the property + fuzz suites, the benchmarks and one runnable example per language are built and green across Linux, macOS and Windows. Track progress in ROADMAP.md and CHANGELOG.md.
Documentation
ARCHITECTURE.md— the workspace, the feature tensor, and the environment lifecycle.docs/OBSERVATIONS.md— theObsSpec, the feature families, and the exact observation-vector order.docs/ACTIONS_REWARDS.md— discrete/continuous action spaces, the position model, and the reward kinds.docs/GYMNASIUM.md— thegymnasium.Envsubclass, how theBox/Discretespaces are derived, andmake/register.docs/MICROSTRUCTURE.md— orderbook levels, funding and open-interest observations.THREAT_MODEL.md— assets, actors, and what determinism buys.
Determinism is the product
- O(1) steps — the dataset is precomputed once to a fixed feature tensor;
step()is a pure array index, never a recompute. - Seed-determined trajectories — the only RNG is the seeded episode RNG
(never
thread_rng); the same(seed, policy)yields a byte-identical trajectory in every language and between the parallel (rayon) and sequential (WASM) tensor precompute. - Fixed observation layout — an observation is an
f64vector of fixed length and canonical order (theObsSpecorder), so it is comparable across languages bit for bit.
Quickstart
Drive a fixed deterministic policy through an environment from the command line:
# A discrete "always long" rollout on the bundled example data, seed 42.
# Golden-format JSON ({reset, trajectory}) instead of the human-readable table.
A spec names the observation features, the action space, the reward kind and the episode bounds; the CLI loads the candle CSV, resets with the seed and prints each step's reward and equity. The same spec, data and seed produce the same trajectory here as in every language binding.
Gymnasium usage
The Python binding ships a real gymnasium.Env subclass — the environment plugs
straight into the RL ecosystem (Stable-Baselines3, CleanRL, RLlib, …):
# registers "WickraGym-v0"
=
=
=
, =
, , , , =
observation_space is a Box derived from the spec (finite bounds where the
core knows them, ±inf otherwise); action_space is Discrete(n) or a 1-D
Box. Without Gymnasium installed, the lower-level RawEnv (the JSON command
surface) still works — see docs/GYMNASIUM.md and
examples/python/.
Observations, actions and rewards
- Observation — an
ObsSpeclistsFeatures in declaration order, and the observation vector concatenates them in exactly that order: the features, then4 × include_book_levelsorderbook columns, then2funding/OI columns if requested. A feature is an indicator ({"kind":"indicator","name":"Rsi", "params":[14]}, optionally a sub-output"field"), a price field, or a microstructure field. Beforewarmupthe indicators are not ready, so the firstwarmupbars are skipped rather than emitted asNaN. - Action —
Discrete{n}mapsnbuckets onto a target position;Continuous{low,high}sets the target position directly (clamped). The position feeds thewickra-backtestfill/PnL model. - Reward —
Pnl,SharpeorLogReturn, computed from the realised position path.
Full semantics (with the exact ordering and formulas) are in
docs/OBSERVATIONS.md and
docs/ACTIONS_REWARDS.md.
Microstructure observations
Beyond price and indicators, the observation can include exchange
microstructure: set include_book_levels: N to append bid_px, bid_sz, ask_px, ask_sz for each of N orderbook levels, and include_funding_oi: true to
append funding rate and open interest. When a dataset lacks a requested column
the value is a defined 0.0 (never NaN), so the observation length stays
fixed. See docs/MICROSTRUCTURE.md.
Use in any language
The core drives a single command_json envelope (load, reset, step,
spec, version); every binding passes the same string through verbatim, so a
trajectory is byte-identical everywhere. The golden/ fixtures pin one
blessed response per case and the cross-language golden tests assert byte-for-byte
equality — the same observations, rewards and termination flags in all ten
bindings and between the parallel (rayon) and sequential (WASM) tensor
precompute. One runnable example per language lives under
examples/; per-binding quickstarts are in each
bindings/<lang>/README.md.
| Language | Binding | Package |
|---|---|---|
| Rust | wickra-gym-core (native) |
crates.io |
| Python | PyO3 (native) + gymnasium.Env |
PyPI |
| Node.js | napi (native) | npm |
| WASM | wasm-bindgen (native) | npm |
| C / C++ | C ABI | header + library |
| C# | C ABI (P/Invoke) | NuGet |
| Go | C ABI (cgo) | Go module |
| Java | C ABI (FFM/Panama) | Maven |
| R | C ABI (.Call) |
R-universe |
Project layout
crates/gym-core the library: feature tensor + env + reward + command
crates/gym-cli reference CLI, binary `wickra-gym`
crates/gym-bench Criterion benchmarks
bindings/{c,python,node,wasm,go,csharp,java,r} ten-language surface
golden/ spec + policy + seed -> byte-exact trajectories
examples/ runnable per-language rollouts + shared data
fuzz/ cargo-fuzz targets (spec/command/tensor/step)
docs/ observations, actions/rewards, gymnasium, microstructure
Building everything from source
( && ) # Python
( && && ) # Node
( && ) # WASM
( && ) # C#
( && ) # Go
( && ) # Java
The C-ABI consumers (C/C++, C#, Go, Java, R) need the C ABI library first —
cargo build --release -p wickra-gym-c — on the loader path.
Testing
Every binding replays the same golden rollouts from golden/ and
must produce the identical bytes; that corpus is the cross-language contract,
not a per-language approximation. python scripts/check_binding_surface.py
asserts the ten surfaces stayed in step.
Requirements
- Rust 1.86+ — the workspace MSRV; the Node binding needs Rust 1.88.
- Python 3.9+ — the Python binding (the
gymnasium.Envsubclass needs 3.10+). - Node 22+ — the Node binding.
- Go 1.23+ — the Go binding.
- Java 22+ — the Java binding.
- R 4.1+ — the R package.
- .NET 8+ — the C# binding.
- A C11 / C++17 compiler with CMake for the C and C++ examples.
Benchmarks
Criterion benchmarks for reset + N × step throughput (at observation
dimensions 5/20/50) and build_tensor (at 1k/10k/100k bars, parallel vs
sequential) live in crates/gym-bench; numbers and methodology are in
BENCHMARKS.md.
Ecosystem
Part of the Wickra family — each one a data-driven core with a CLI and the same ten-language binding surface:
- wickra — main library (Rust core + Python / Node.js / WASM bindings + a C ABI for C / C++ / C# / Go / Java / R)
- wickra-playground — a polyglot strategy playground: one StrategySpec live side by side in Python, Rust, JS and Go, entirely in the browser
- wickra-exchange — unified market-data + execution across ten crypto exchanges
- wickra-backtest — event-driven backtester over the Wickra core
- wickra-terminal — the trading terminal: a TUI and a browser renderer over the stack
- wickra-xray — market-microstructure explorer: footprint, order-book heatmap, liquidation map, funding/OI divergence
- wickra-radar — perp-universe alert radar: OI delta, funding flip, book imbalance, liquidation clusters, OI/price divergence
- wickra-copilot — local market copilot grounded in real order-book, liquidation and funding microstructure
- wickra-shazam — match an asset's current microstructure fingerprint against its entire history
- wickra-benchmark — reproducible, golden-verified benchmark suite — recompute any (strategy, dataset, report) in ten languages and confirm it byte-for-byte
- wickra-strategy-ci — Jest for trading strategies: golden-pin the report, catch regressions in CI, property-test against fuzzed data
- wickra-verify — confirm or refute a claimed backtest report against its strategy and data, in ten languages
- wickra-proof — Proof-of-Backtest: deterministic (spec, data) → report + blake3 hash, recomputable byte-for-byte in ten languages
- wickra-zk — prove a backtest zero-knowledge — on-chain-verifiable performance without revealing the data or the strategy
- wickra-impact — the backtester that knows you would have moved the market: agent-based fills on the real historical L2 order book
- wickra-darwin — evolutionary strategy search at hundreds of thousands of backtests per second, mutating and crossing JSON specs across the whole indicator registry
- wickra-feature-store — OHLCV and microstructure streams into ML-ready feature matrices over 497 O(1) streaming indicators
- wickra-genome — a vector database of the whole market: every asset a live vector over the indicator registry, for similarity search, clustering and anomaly detection
- wickra-timemachine — scrub the whole market like a video — every symbol, full order book, rewound to any moment via deterministic re-fold
- wickra-synth — deterministic synthetic market microstructure: OHLCV, order book, trades and funding from a single seed
- wickra-compile — compile a strategy spec into a standalone deployable: a WASM module, a self-contained binary, or a
no_stdartifact - wickra-embed — allocation-free,
no_stdstreaming indicators for bare-metal and HFT, byte-for-byte identical to the core - wickra-pico — the O(1) indicator core running bare-metal on a $5 Raspberry Pi Pico — the LED blinks on the EMA cross
The screener's own guides live in docs/ beside the code; its site,
with the in-browser demo and the benchmark figures, is at
screener.wickra.org. The indicator library's
reference is at docs.wickra.org and the org landing
page at wickra.org.
Contributing
See CONTRIBUTING.md and the Code of Conduct. Every change runs the full CI matrix (all ten languages × three OSes) plus CodeQL, Scorecard, zizmor and the metadata audit.
Security
Report vulnerabilities per SECURITY.md. The threat model is in THREAT_MODEL.md.
License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option. Use it, fork it, modify it, redistribute it — commercially or not — file issues, send pull requests; all welcome.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Disclaimer
wickra-gym is research and engineering tooling, not financial advice. A trained
agent's backtested performance says nothing about future returns; markets carry
risk and you are responsible for your own decisions. wickra-gym is free
software you run yourself: no hosted service, no data collection, no warranty.