citrusquant engine
The open-source Rust backtest + strategy engine behind citrusquant — the
yuzu backtest core, the pomelo data-engineering layer, and the lemon
strategy DSL. Pure, I/O-free math: (strategy spec JSON, data panels) -> Report.
It compiles to both native (batch backtests via Rayon) and WASM (browser/Worker).
Top-level entry (in the yuzu-core crate):
run_backtest // ctx: &EvalContext (numeric panels keyed by series name + a symbol→industry map)
Architecture, DSL vocabulary, NAV model, metric conventions, and the Report JSON
contract live in docs/backtest-engine.md.
Bring-your-own data (on-disk tree, CSV columns, series names):
docs/data-layout.md.
FMP Starter-tier gaps (which features need which panels):
docs/fmp-data-source.md.
Crate families
The workspace is organized into three crate families:
- yuzu — the backtest engine and the product apps around it (CLI/server/wasm/py).
- pomelo — data engineering: native I/O, storage backends, data sync, quality audit.
- lemon — the strategy language and its tooling.
The library crates are published so you can link them from your own service — e.g.
pomelo-fmp::sync_into + pomelo-s3 for a data-sync service, or yuzu-core +
pomelo-data for a backtest service (yuzu-server is the reference implementation).
It's a layered stack — pomelo-* → yuzu-core → lemon — not parallel silos.
Published crates
| Crate | Description |
|---|---|
yuzu-core |
Pure, I/O-free backtest engine core. |
pomelo-data |
Native I/O: gzip CSV price/fundamental files → panels. |
pomelo-s3 |
S3-compatible ObjectSource/ObjectSink for pomelo-data. |
pomelo-audit |
Read-only data-quality audit of a data-layout tree (yuzu-cli data-audit). |
pomelo-fmp |
Bring-your-own-key FMP data sync + snapshot-factor formulas; writes to local disk or S3/R2. |
lemon-lang |
The lemon strategy DSL (imported as lemon). |
Python: crates/yuzu-py binds the engine + DSL for Python (pip install ./crates/yuzu-py,
module yuzu) — see crates/yuzu-py/README.md.
The wasm/cli/server crates are not published.
Build
WASM
The two wasm crates build to a repo-local dist/ by default:
Override the output directory with OUT:
OUT=/path/to/pkg
(Requires wasm-pack.)
Editor tooling
The lemon DSL ships with editor support driven by the same op catalog as the parser and JSON schema, so highlighting, hover, and completions never drift from the language:
-
Language server —
lemon-lsp, a tower-lsp server over stdio providing hover (op signatures + descriptions), completion (op names, keyword arguments,let-bound names, known series), and live diagnostics sourced from the DSL linter (parse errors, unusedlets, and — when the engine's series list is supplied viainitializationOptions.series— unknown-series warnings with did-you-mean suggestions). The intelligence is a pure, I/O-freelemon::servicesmodule; the binary is a thin shim. -
VS Code extension — a TextMate grammar plus a client for
lemon-lsp, undereditors/vscode. -
In-browser editor — the same
lemon::servicescore is exported throughlemon-wasm(diagnostics/hover/completions) for the web editor.
Test
Coverage
# one-time: rustup component add llvm-tools-preview && cargo install cargo-llvm-cov
The cargo llvm-cov run also executes the test suite, so it doubles as the test step.
Contributing
See CONTRIBUTING.md.
License
MIT — see LICENSE.