Rust Core PR-1 Layout (Scaffold + Parity Harness)¶
Date: 2026-02-19
Status: Draft for approval
Branch: feat/rust-core-pr1-scaffold
Related guide:
docs/plans/rust_migration_guide.md
Progress Snapshot (2026-02-19)¶
- Implemented:
- backend selection helpers (
python/rust) rust_bridge.build_core(...)and Rust availability checks- runtime wiring in
CerebroEngineRuntimefor backend selection - Rust workspace/crate scaffold (
rust/cracktrader_engine) with PyO3 module shape - unit tests for backend selection/bridge behavior
- contract parity harness scaffold and first fixture (auto-skips when Rust module is unavailable)
- Pending:
- install/load compiled Rust extension in local dev + CI so parity contracts run unskipped
- expand golden fixture matrix for broader parity coverage
PR-1 Objective¶
Create the minimum Rust integration scaffold so Cracktrader can run with:
engine_backend="python"(current default behavior)engine_backend="rust"(delegates deterministic core transitions to Rust)
without changing user-facing APIs (ct.CracktraderEngine, factories/sessions).
ct.Cerebro remains a supported compatibility surface in PR-1, but it is not
the primary migration target.
This PR should not port full strategy runtime, feeds, or broker adapters. It only introduces the Rust core boundary and parity harness.
Why This Slice First¶
It targets the most stable seam already present in the repo:
src/cracktrader/engine/core.pysrc/cracktrader/engine/sequencer.pysrc/cracktrader/engine/events.pysrc/cracktrader/engine/intents.pysrc/cracktrader/engine/results.pysrc/cracktrader/engine/invariants.py
These modules are already explicitly decoupled and exercised by engine unit/contracts tests.
Non-Goals (PR-1)¶
- No rewrite of
engine_runtime.pyadapters. - No migration of Backtrader classes to Rust.
- No direct behavior changes to
ct.Cerebrocompatibility mode. - No packaging/release changes beyond local/dev build hooks required for CI.
- No performance optimization pass yet.
Exact File Layout¶
New Rust workspace files¶
rust/Cargo.tomlrust/cracktrader_engine/Cargo.tomlrust/cracktrader_engine/src/lib.rsrust/cracktrader_engine/src/domain.rsrust/cracktrader_engine/src/events.rsrust/cracktrader_engine/src/intents.rsrust/cracktrader_engine/src/results.rsrust/cracktrader_engine/src/core.rsrust/cracktrader_engine/src/error.rsrust/cracktrader_engine/src/python.rs(PyO3 binding surface)
New Python bridge files¶
src/cracktrader/engine/rust_bridge.pysrc/cracktrader/engine/backends.py
Existing files to change¶
src/cracktrader/engine/runner.pysrc/cracktrader/engine/__init__.pysrc/cracktrader/engine/replay.pysrc/cracktrader/engine_runtime.pypyproject.toml(dev/build config only; no API changes)
New tests¶
tests/unit/engine/test_rust_bridge_smoke.pytests/unit/engine/test_runner_backend_selection.pytests/contracts/engine/test_python_rust_core_parity.pytests/contracts/engine/fixtures/(golden event fixtures for parity)
Proposed Public/Internal Interfaces¶
Python: backend selection¶
- Add optional runtime kwarg:
engine_backend: Literal["python", "rust"] = "python"- Thread this into runtime internals only.
- Keep all existing run signatures backward-compatible (additive only).
Python: bridge contract (rust_bridge.py)¶
is_rust_available() -> boolbuild_core(initial_cash: float, backend: str) -> CoreProtocolCoreProtocolmethods:apply_event(event: EngineEvent) -> TransitionResultprocess_intent(intent: EngineIntent) -> TransitionResultget_cash() -> floatget_positions() -> dict[str, float]snapshot() -> dict[str, Any]reset() -> None
Rust: PyO3 module¶
- Expose class
RustDeterministicCoremirroring PythonDeterministicCore. - All ingress/egress remains JSON/dict compatible for PR-1 simplicity.
- Error conversion: Rust domain errors -> Python
ValueError/RuntimeError.
Implementation Steps (Atomic)¶
- Add Rust crate skeleton + compile gate.
- Implement Rust domain enums and result structs equivalent to Python engine types.
- Implement Rust
DeterministicCorewith: - order lifecycle transitions
- fill handling
- cash/position mutation
- Add PyO3 bindings exposing
RustDeterministicCore. - Add Python bridge selecting Python or Rust core backend.
- Update
EngineRunnerto accept injected core protocol unchanged. - Add backend toggle path in
CerebroEngineRuntime(engine_backendkwarg). - Add parity contract fixtures comparing:
- transition trace
- final cash
- final positions
- order terminal states
- Add replay parity check path using existing
engine/replay.py.
Test and Gate Plan¶
Required green checks for PR-1:
python -m pytest -q tests/unit/enginepython -m pytest -q tests/contracts/enginepython -m pytest -q tests/contracts/test_fees.py tests/contracts/test_order_lifecycle.py tests/contracts/test_order_scenarios.pypython examples/basics/hello_engine.pypython examples/basics/session_quickstart.pypython examples/basics/shared_store.py
Parity assertions must include:
- Python core and Rust core generate equivalent
TransitionResultsequences for shared fixtures. - No invariant regression in strict mode for either backend on same fixture stream.
Risk Controls¶
- Backend fallback:
- If Rust module is unavailable,
engine_backend="rust"raises clear error. engine_backend="python"remains unaffected.- Isolation:
- Runtime adapters stay Python-owned in PR-1.
- Determinism:
- Golden fixtures include duplicate order reports and partial fill flows.
Review Checklist¶
- No breaking API changes to public entry points.
- Rust backend is strictly opt-in.
- Parity suite exists and fails loudly on divergence.
- Existing example gates still pass.
- Documentation updated:
- this plan file
- short note in
docs/plans/rust_engine_architecture.mdpointing to PR-1 scope.
Explicit Approval Request¶
Before implementation, approve:
- Branch name and PR title:
- Branch:
feat/rust-core-pr1-scaffold - PR:
engine: add rust deterministic-core scaffold with python parity harness - Backend flag name:
engine_backend(python/rust)- PR-1 scope freeze:
- no adapter rewrite, no strategy API rewrite, no packaging change beyond build hooks