Mercury is an early-stage, event-driven system for ingesting crypto market data, generating typed strategy signals, archiving events, and experimenting with execution controls.
Project status: research alpha. The default configuration is observation-only: it creates no exchange client, makes no private exchange calls, and submits no orders. Mercury has no demonstrated trading edge and is not ready for unattended or live-capital use. Nothing in this repository is financial, legal, or investment advice.
Mercury is the sister project to Nephtys, the generic real-time connector layer. Nephtys connects to upstream feeds and publishes durable events to NATS JetStream; Mercury owns the trading-domain schemas, strategies, risk controls, archive, and execution experiments. Their supported wire and restart boundary is defined in the NME/1 compatibility contract.
| Mode | Exchange client | Orders | Intended use |
|---|---|---|---|
observe (default) |
No | No | Public alpha, feed and signal verification |
sandbox |
Yes, explicitly named | Test venue only | Integration experiments where the venue has a genuine CCXT sandbox |
live |
No | No | Recognized only to fail at startup; outside the supported release |
Live execution is deliberately disabled because open blockers include execution idempotency, atomic risk accounting, ambiguous order-state reconciliation, and operational kill-switch drills. See ROADMAP.md and docs/ASSESSMENT.md.
MiCA's remaining transitional periods ended by July 2026. An execution venue must be checked against the current ESMA MiCA register and its authorisation must cover the required services and jurisdiction. Italy's transition and cross-border rules are summarized by Banca d'Italia.
Mercury therefore does not treat “supported by CCXT” as “legally available.” Venue authorisation can change and is deliberately an operator decision. The default public market-data profile uses an unauthenticated Coinbase BTC/EUR ticker; the old Binance BTC/USDT trade and depth feeds remain available only as an explicitly selected legacy research profile.
upstream feed
│
▼
Nephtys ──► NATS JetStream ──► Brain ──► trade.signals ──► Executor
│ │
└────────────► Plutarch archive └─ observe by default
│
▼
Backtester
- Brain consumes normalized
MarketEventenvelopes and emitsTradeSignalintent. The default moving-average strategy is illustrative, not profitable evidence. - Executor checks HALT and risk state before handling signals. Observation mode records the outcome without constructing a CCXT exchange. Sandbox mode requires explicit configuration; live mode is rejected.
- Plutarch archives raw event envelopes to Lance with ack-after-write behavior and an NDJSON quarantine fallback. Archive schema v2 stores the JetStream stream sequence so replay can identify write-success/ack-failure duplicates.
- Backtesting replays Lance rows through the same strategy interface used by the Brain. Its cash-backed, long-only MARKET fill model applies configurable fees and adverse slippage. It remains intentionally basic and is not suitable for validating an edge.
The services communicate through NATS rather than sharing API keys or process memory. Exchange credentials belong only in the Executor environment.
Requirements:
-
Install the locked environment:
uv sync --locked
-
Create local configuration:
cp .env.example .env
On PowerShell, use
Copy-Item .env.example .env.Keep
EXECUTION_MODE=observe. No exchange credentials are needed. -
Start NATS if you do not already have one:
docker compose up -d nats
The Compose file uses pinned images, unprivileged users, read-only filesystems, health-based startup, and loopback-only host ports. Its NATS broker has no authentication or TLS: it is a local development profile and must not be exposed to another host.
Existing pre-candidate installations should read the stream-migration note under Market-data profiles before starting Nephtys.
-
Start Nephtys against
nats://localhost:4222, then register Mercury's default public feed:uv run python -m scripts.provision_nephtys
-
Run the services in separate terminals:
uv run python -m brain.main uv run python -m executor.main uv run python -m plutarch.archiver
-
Inspect health and metrics:
- Brain:
http://127.0.0.1:9108/healthand/metrics - Executor:
http://127.0.0.1:9109/healthand/metrics - Plutarch:
http://127.0.0.1:9110/healthzand/metrics
- Brain:
Application health fails readiness while its NATS client is disconnected. Brain also reports whether the selected strategy requires a ready L2 order book.
The first moving-average signal appears only after its rolling window is populated. In observation
mode that signal is risk-checked and marked observed; it is never sent to an exchange.
Plutarch writes new archives to data/history/market_history_v2.lance. The backtester can still
read legacy v1 rows, but only v2 rows retain the broker identity needed for exact redelivery
deduplication.
Set MERCURY_MARKET_DATA_PROFILE before running the provisioning script.
| Profile | Default | Feed | Purpose |
|---|---|---|---|
coinbase_btc_eur |
Yes | Public BTC/EUR ticker | EU-oriented L1 observation path |
binance_btc_usdt |
No | Public trade + depthUpdate |
Legacy L1/L2 research and regression path |
Provisioning is idempotent by stream ID. A 409 means the existing Nephtys stream is retained;
it does not prove that its configuration matches the current profile. Remove or rename stale
streams deliberately when migrating profiles.
Nephtys owns the broad NEPHTYS stream on nephtys.stream.>; Mercury's consumers apply narrower
filters within it. Pre-candidate Mercury deployments may contain the old, overlapping
nephtys_crypto stream. Preserve any needed data and migrate that stream deliberately before
starting current Nephtys—NATS rejects overlapping stream subjects, and Mercury never deletes
broker data automatically. Persisted durable-consumer settings are also validated at startup;
change a durable name or perform an explicit migration when changing its filter or ACK policy.
Observation mode needs only:
EXECUTION_MODE=observeSandbox mode additionally requires:
EXECUTION_EXCHANGE_ID=<ccxt-id>
EXCHANGE_API_KEY=...
EXCHANGE_SECRET=...
EXCHANGE_PASSWORD=... # only when required by the venuesandbox fails closed if CCXT cannot enable a sandbox for that venue. Some exchange “sandboxes”
return static mock responses rather than simulated matching, so a successful API response is not
equivalent to a realistic test.
EXECUTION_MODE=live always raises a configuration error before constructing an exchange client.
The repository still lacks the safeguards listed in the roadmap.
uv run python -m scripts.checkThis is the cross-platform canonical gate; make check is a convenience alias where GNU Make is
installed. CI enforces the same checks:
- Ruff lint and formatting
- mypy across all runtime packages
- the full pytest suite
- source and wheel builds
- a vulnerability audit of locked runtime dependencies
- a real NATS JetStream smoke test covering observation, archival, and NAK redelivery
Useful individual commands:
uv run pytest
uv run ruff check .
uv run ruff format --check .
uv run mypy .
uv run pip-audit
uv build- Strategy output has no demonstrated positive expectancy.
- Backtests use generic fee/slippage assumptions but still omit latency, order-book liquidity, partial fills, venue rejects, and venue-specific rules.
- A signal redelivered after a partially completed live order can still create an ambiguous or duplicate execution; this is why live mode is disabled.
- Portfolio cost basis still depends on the venue retaining complete trade history and does not fully account for external asset transfers or every venue-specific fee representation.
- The optional Bytewax path acknowledges input before checkpointed processing and does not await signal publication; it is experimental.
- The local Compose profile has been exercised as a hardened local development deployment, but it is not secured for remote use.
- The exact real-Nephtys/Coinbase quickstart and connector restart passed on 2026-07-26; see the alpha release record. Nephtys connector registration persists, but runtime pipeline updates remain transient across restart.
Mercury is licensed under the Apache License 2.0. Contributions are accepted under the same terms; see CONTRIBUTING.md.
Public reporting and conduct expectations are documented in SECURITY.md, SUPPORT.md, and CODE_OF_CONDUCT.md.
