Pure-Rust, zero-allocation, zero-copy, single-writer, lock-free HFT engine that executes systematic strategies across a multivenue universe — Binance spot/USDM, OKX, Deribit, Hyperliquid, Bybit, MEXC (data-only), Polymarket's CLOB and Polygon RPC, plus a boot-selected options ladder.
Strategies are composed at boot from a slot set (AI-executed intents, the ruleset VM, the intrabar candle member) and are free to trade any subset of that universe. Polymarket is one venue among several, not the target: a strategy may use it, ignore it, or trade purely between the crypto venues. The original Polymarket latency-arbitrage strategy still exists in-tree but is disabled at boot.
v1 runs locally on a MacBook Pro M4 on free-tier external APIs only. Phase 7 migrates to a plain Linux EC2 box — no cloud services, no observability stack, no IaC, at any phase.
Claude (via the claude-worker Python process) is an offline strategy
researcher — it proposes rulesets, backtests them and stages them
through an HMAC'd UDS command plane. It is never in the hot path.
| Lane | State |
|---|---|
| Engine + capture (Stage 1–2, M1–M6, VM2, venue-time v3) | CLOSED — MVP complete 2026-09-02 |
| Regime + dashboard, S3 cold archive, ICDP, XSD, VRP, BIN15 lanes | CLOSED / live in paper |
| Real execution E1–E6 (per-slot routing, HL signer + arm, risk gate, kill switches) | LANDED, reviewed + re-tested in E7 (2026-09-19) |
| E7 — the ramp | TESTNET first (operator-gated R0); mainnet is a later ruling |
| Stage 3 — AI-promoted members live | GATED on the Stage-3 entry gate (waived for BIN15 only) |
MEXC — the seventh market-data venue (MX0–MX9, docs/mexc-ingress-plan.md) |
LANDED 2026-09-23, data-only — captured once [mexc] is in the boot universe |
Gates at HEAD: 2585 nextest · 62/62 alloc assertions at 0 B/op ·
clippy clean · make copy-audit new=0 · 1153 worker pytest.
CLAUDE.md carries the authoritative CURRENT STATE and the standing laws.
- CLAUDE.md — current state, standing laws, hard rules. Read this first.
- docs/risk-policy.md — caps, kill switches, LAWS E-1..E-9, the execution lane's record.
- PLAN.md — the architecture deep-dive and doctrine (its roadmap section is historical).
- The three sheets: docs/phase-8-architecture-v2.svg (live architecture), docs/engine-memory-cpu.svg (memory, cores, the copy ledger), docs/ai-strategy-pipeline.svg (+ .md).
- AGENTS.md — tool-agnostic brief for any AI coding agent.
- docs/ — wire format, migration notes, local setup, venue latency. History lives in
docs/arch/ and research in the git-excluded
docs/research/— both read only on request.
# 1. Secrets (.env only — chmod 600, git-ignored, never printed)
cp .env.example .env && chmod 600 .env
$EDITOR .env
# 2. Universe (M1: the boot universe is a file, not flags)
cp universe.toml.example ~/multivenue/universe.toml
$EDITOR ~/multivenue/universe.toml
# 3. Build (G0 law: test gates never relink the release binary —
# always build -p cli before a live boot)
cargo build --release -p cli
# 4. Tests
cargo nextest run --workspace
cargo test -p bench --test alloc_assertions --release -- --test-threads=1 # MUST show 0 B/op
cd claude-worker && uv run pytest
# 5. Paper-mode run — zero flags, universe comes from the file
cargo run --release -p cli -- run --paper --strategy aiPolymarket crypto up/down dailies expire 16:00Z — refresh
universe.toml via the Gamma lane before a manual boot (the M3 launchd
fleet automates this). After a restart, run claude-worker fetch once;
unresolved=0 is the done-tell.
Legacy fallback (no universe.toml): per-venue flags are required —
--polymarket-asset-id <token id> --okx-symbols … --deribit-symbols … --hl-coins ….
Boot refuses to start venue-blind.
multivenue-engine run --paper --strategy ai # spawn ingress + engine, drain until SIGINT
multivenue-engine run --strategy ai+vrp+xsd+bin15 --exec ~/multivenue/exec.toml --arm-live 3 # E7: arm ONE slot (testnet first)
multivenue-engine print-config --env-file ./.env # resolved non-secret config; smoke-tests the loader
multivenue-engine audit-replay --dir <run dir> # per-symbol rates, cadence bands, integrity, venue×channel matrix
multivenue-engine capture-catalog --dir <log root> # per-run spans, UTC-day continuity, gap map, backtest/monitor views
multivenue-engine backtest --ruleset R --replay-dir D --split 70/30 # deterministic VM replay; schema-1 JSON on stdout
multivenue-engine audit-pnl --dir <log root> # shadow P&L: logged intents through the strict-cross fill model
multivenue-engine exec-smoke [--lifecycle] # the TESTNET-only signing gate (never mainnet, by construction)Every ingress thread writes PMLR replay capture (per-venue tick /
event / signal logs, the engine-orders.pmlr intent log, plus an optional
--raw-tap payload tap) into a per-run directory under
MULTIVENUE_LOG_DIR. Each run also drops instrument-manifest.tsv (and
options-manifest.tsv when an options ladder is live) — options ordinals
reshuffle per boot by design, so every offline consumer resolves
symbols through the manifest, never a bare SymbolId across runs.
backtest's argv and schema-1 JSON are a frozen contract with
claude-worker. The harness conforms to the worker, never vice versa.
Venue time + staleness (VT, 2026-09-03 — docs/arch/venue-time-capture-plan.md).
Tick v3 carries venue_time_ms + flags; every ingress judges each tick
against the venue's own fastest message (core_time::FeedClock) and
flags it STALE past the per-venue stale_after_ms (pm 1000 / bn 1000 /
okx 400 / deribit 600 / hl 700 / bybit 500 / mexc 400; run --stale-after-ms <venue>:<ms> overrides, :0 = measure only). A stale tick is captured
but never a signal (Mid/Bid/Ask ABSENT in the VM), never a fill and
never a mark. backtest and audit-pnl RE-JUDGE v3 captures from the
stamp (--stale-after-ms on both — a threshold change is a replay), print
stale: bn=59149/2639478 (12bps) … per run and stale-blind(v2) on a
v2 root; --emit-detail is detail_version 2 with a stale block;
capture-catalog reports stale_captured per lane. Any number from
a v2 root is an upper bound. Metrics:
engine_ingress_<venue>_stale_ticks_total, _feed_delay_ema_ms.
Engine-side delay per venue: docs/venue-latency.md §5. Capture windows
for research are ≤ 2 h by law (VT plan §6.1).
Slot 6 — strategy-xmm (XMM XH1–XH3, 2026-09-26; paper only). The
Binance-led post-only market maker on Hyperliquid perps (plan
xmm-hl-maker-plan-2026-09-26.md, rulings O-XH1…O-XH15). Parameters come
from ~/multivenue/xmm.toml (--xmm <path>; xmm.toml.example is the
probe); a requested xmm bit with no artifact refuses the boot. Since XH2
the member runs the LEAD θ policy (post-only at the touch, the LEAD
cancel, the 500 ms gate, hard caps, stale-feed pulls), judged on paper by
the queue law (core_fill::queue: queue ahead, prints, post-only
rejects) in both the engine's paper matcher and backtest --member xmm;
multivenue-engine xmm-parity replays one window on the XMM simulator's
clock for the parity gate. Since XH3 it reports on /state (the xmm
block: counters and one row per perp) and /metrics
(engine_xmm_*_total, engine_xmm_perps, engine_xmm_p{k}_pos_1e6),
audit-pnl fills its orders from the prints, and [labels.xmm] carries a
regime label it never consults. A live slot 6 refuses the boot until XH4.
strategy-icdp (ICDP I1–I7, 2026-09-03) — unlinked at XMM XH1. Its
crate, tests and backtest --member icdp --icdp <path> stay; no engine
path composes it and --strategy ai+icdp refuses the boot. The
intrabar candle-direction member: a UTC bar grid (core_time::BarClock),
L1 features from every tick, an offline-fitted linear composite, IoC
taker intents (Order.kind = 1, ttl_ns = the bar's remaining life) —
entry at open + δ, exit at the roll, one position per instrument per
bar. Parameters come from ~/multivenue/icdp.toml (--icdp <path>), a
generated integer artifact (sha256 logged at boot); descriptors must
resolve against the boot universe or the boot refuses. It was enabled
with --strategy ai+icdp until XH1 (that name now refuses the boot). The
offline fill model
scores its intents under the I1 IoC law and prints the fee ladder.
Its engine_icdp_*_total metrics and /state block were retired at XMM
XH3.
The backtest / audit-pnl fill model activates an order Δ_venue after
emit and matches it against ticks in local receive time, so
Δ_venue = feed one-way + order one-way as seen from the host and
network the engine runs on. Those are location facts, not constants:
moving the engine (a new box, a new region, a new ISP, a VPN) changes
every number in the table and silently mis-prices every P&L the harness
reports. The defaults in crates/cli/src/backtest.rs (ModelParams)
are the values measured for the current deployment and carry their
measurement date + location in the doc comment.
cd claude-worker && uv run python -m claude_worker.latency_probe --out ~/multivenue/research/latency-<date> --minutes 25Run it on the deployment host before the first backtest there and
after every move, then update ModelParams::default() and the table
in docs/venue-latency.md (procedure,
derivation, and the current measurement). The probe is stdlib-only,
touches no engine path, and leaves per-message NDJSON so lead-lag can be
re-derived in venue time.
Python 3.14 package under claude-worker/. One serve
daemon plus the frozen operator verb surface:
serve fetch backtest push positions stage-ruleset commit-ruleset pnl
Frame-sending verbs (push, stage-ruleset, commit-ruleset) open the
HMAC'd UDS; read-only verbs never touch the socket — a data pull must not
signal AI liveness to the engine. The Anthropic SDK is constructed inside
serve only; the strategist model is claude-fable-5. Verbs are
globally serialized (one SQLite sequence namespace) — pgrep -f claude-worker before invoking one.
./scripts/install-launchd.sh # idempotent: renders launchd/*.plist, seeds state, bootstraps the agentsInstalls the standing engine (com.multivenue.engine), the 00:00Z
SIGTERM restart + universe refresh (com.multivenue.daily-restart), the
hourly candles agent (com.multivenue.candles) and caffeinate.
One engine ever — port 9191 and ai.sock are singletons; any smoke
boot must stop the standing instance first and restart it after.
crates/
core-*/ OS-agnostic primitives (alloc, config, crypto, io, latency,
metrics, net, parse, ring, simd, time, types)
ingress-*/ External sources: polymarket, binance, okx, deribit,
hyperliquid, rpc + ingress-ai (UDS/HMAC command plane)
options-select/ Boot-only options-chain selection law (shared by venues)
book-builder/ Order-book construction
strategy-*/ core, latency-arb, vrp, rule-tree, vm (ruleset VM), icdp,
set (the composed set), ai-exec; cross-arb + ev stay in
the workspace but are unlinked from the set
research-artifacts/ Ruleset artifacts + validation
signer-eip712/ EIP-712 signer (secp256k1 + tiny-keccak, no ethers/alloy)
clob-dispatcher/ Persistent HTTP/2 client, preallocated buffers
engine/ Engine<S: Strategy>
cli/ Main binary (multivenue-engine)
tui/ ratatui dashboard (read-only)
bench/ criterion + dhat + allocation assertions
fuzz/ cargo-fuzz targets (integration tests are per-crate under tests/)
claude-worker/ Python 3.14 offline Claude researcher (never in the hot path)
launchd/ scripts/ M3 launchd plists + install / restart / candles / retention
docs/ Live docs (arch/ = closed historical plans and logs)
.claude/ Subagents, slash commands, settings
make help lists the full developer target set.
config.example.toml is operator reference only — the binary is driven
by env vars + CLI flags + universe.toml.
- Zero runtime allocations in hot paths. Enforced by
alloc_assertions(0 B/op). - No
tokio,serde_json,ethers,alloy,reqwest,async-stdon hot paths. Handwritten byte scanners over&[u8];mio+ state machines. - No
dyn Traitin hot paths. Monomorphization only (Engine<S: Strategy>). - No panics in release hot paths.
debug_assert!+panic = "abort"; fail fast. - Every POD hot-path struct is
#[repr(C)] + Copy; every ring is#[repr(align(64))]. - Every ingress parser has a property test + a fuzz target.
- No
from x import yin Python. Fullimport xonly. - Secrets = a single
.envfile (chmod 600, git-ignored). No Keychain, no KMS, no Vault. - No cloud services at any phase. Plain VMs only.
- No observability stack. TUI + log files + loopback
/metricsonly. - No git operations without the operator's explicit ask. No push, rebase, history rewrite or new branches.
- Venue latency is measured, never assumed. Every deployment and every location re-runs
claude_worker.latency_probeand re-derives the harness Δ table (docs/venue-latency.md).
See CLAUDE.md for the complete list plus the "stop if you're about to do this" pitfalls.
Licensed under the Apache License, Version 2.0 — see LICENSE and NOTICE.
Copyright 2026 Anton (darkcite)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Every source file carries SPDX-License-Identifier: Apache-2.0; make license-check fails the build if one does not. The license covers
documentation source and diagrams (docs/, PLAN.md, *.svg) on the same
terms — Apache-2.0's definition of "Source" is explicit that it includes
documentation source.
Contributions are accepted under Apache-2.0 §5 — a submitted contribution is licensed under the same terms, without additional conditions. See CONTRIBUTING.md.
No third-party source is vendored in this tree; dependencies are resolved
at build time from crates.io and PyPI and carry their own licenses. A
compiled binary does link them, so attribution for the binary is generated
by make license-deps (cargo-about) into THIRD-PARTY-NOTICES.md. No
distributed binary may ship without LICENSE, NOTICE and
THIRD-PARTY-NOTICES.md alongside it. make license-deps also runs
cargo deny check licenses against the allowlist in
deny.toml.
Polymarket, Binance, OKX, Deribit and Hyperliquid are trademarks of their respective owners. This project is not affiliated with, endorsed by, or sponsored by any of them, and names them only to describe interoperability. Per Apache-2.0 §6, this license grants no trademark rights.
This software trades real money on live venues. It is provided as is, without warranty of any kind, and nothing here is financial advice. Running it in non-paper mode is entirely at your own risk. See docs/risk-policy.md for the kill-switch and cap rules.