Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

186 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Evolution — Evolutionary Multi-Wallet Trading Platform

A self-evolving BTCUSDT paper-trading research platform. Twenty-five isolated wallets compete every week. Losers are eliminated and permanently banned. A local LLM writes their replacements. The platform live-trades every closed 5-minute candle, refreshes its market awareness hourly from real cited sources, and survives restarts via atomic snapshots. Nothing is trusted — not the model, not the market data, not the generated code.

Paper trading only. No real exchange orders are ever placed and no funds are held. Nothing here is a profitability claim or investment advice.

Portfolio dashboard


What it is

12 active wallets Twelve structurally distinct strategies, 10,000 USDT each
12 shadow wallets Virtual evaluation capital, never mixed into active totals
1 Dark Horse Permanent wallet, never reset, exempt from elimination
140,000 USDT Active baseline (12 × 10k + Dark Horse + Darkhorse - Daily)
Local Qwen Writes and mutates strategies autonomously via llama.cpp
Continuous live loop Polls Binance every 15s; every newly closed 5m candle is traded by all wallets
Hourly awareness CoinGecko + mempool.space + news RSS, synthesized into a cited brief by the local LLM
Restart persistence Versioned atomic snapshots; startup restores and gap-replays instead of resetting

Every week: rank by profit → eliminate every loser and every zero-trade strategy → permanently ban their code and structure → generate ceil(n/2) novel + floor(n/2) mutation replacements → promote atomically.

Screenshots

Active portfolio Shadow (virtual capital)
Active Shadow
Dark Horse All 25 wallets
Dark Horse All

Active, shadow and Dark Horse capital are rendered in visually distinct panels so virtual money can never be misread as real equity.

The twelve strategies

Not twelve presets of one grid — twelve materially different signal engines, each with its own signal() and conceptual family. This is proven by test: all twelve score pairwise below the 0.65 structural-similarity threshold under the same novelty policy that governs new candidates.

# Strategy Distinctive characteristic
1 Volatility-Adaptive Inventory Grid Multi-level inventory-managed range
2 Bollinger Z-Score Reversion Statistical deviation, with falling-knife veto
3 Rolling VWAP Deviation Volume-weighted fair-value reversion
4 RSI/Stochastic Exhaustion Oscillator exhaustion + recovery trigger
5 Donchian Breakout Price-channel break, volume-confirmed
6 EMA Trend Pullback Trend continuation after a controlled dip
7 MACD Histogram Momentum Momentum acceleration/deceleration
8 Bollinger–Keltner Squeeze Volatility compression → expansion
9 Chandelier Trend Follower Long-horizon ATR trailing
10 Multi-Timeframe Momentum Return momentum across 4 horizons, inverse-vol sized
11 OBV / Relative-Volume Breakout Volume-flow-confirmed accumulation
12 Regime-Switching Ensemble Deterministic regime → independent subpolicies

Engineering guarantees

Enforced in code and locked by tests — not aspirations.

  • Fixed-point money everywhere. float is rejected at the boundary in both the domain (money.py) and the database (money is stored as exact decimal text, because SQLite's Numeric silently round-trips through binary float).
  • Wallet isolation. Cross-wallet postings are structurally impossible; each wallet only mutates itself.
  • Fees counted exactly once — acquisition into cost basis, disposal from proceeds. A flat round trip yields exactly -(fees).
  • No same-candle churn. A per-wallet candle watermark makes repeated fills against one open candle impossible.
  • Deterministic + bit-reproducible. The same seed replays to identical ledgers, and active/shadow wallets running the same strategy evolve identically.
  • Profit is the only ranking value. No Sharpe, drawdown, or committee vote can alter rank — enforced by schema validators, not convention.

Security posture

Generated strategy code is treated as hostile.

  • Never imported into any core process. Each tick runs in a python -I subprocess: sanitized environment, temp cwd, hard timeout, POSIX rlimits.
  • AST deny-by-default, hardened after an independent verifier proved the original was escapable: getattr + string dunders reached object.__subclasses__() (299 classes, incl. os gadgets). Now all dunder access and every reflection builtin are rejected.
  • SSRF-resistant DataBroker. Deny-by-default allowlist; DNS-resolved private/ link-local/metadata IPs blocked; every redirect revalidated; the model cannot add hosts.
  • Fail-closed API. Mutations require a token (401/403/400/422); errors are redacted to a correlation ID; zero unsafe DOM sinks in the frontend.
  • Identity-verified process control. A recycled PID receives no signal at all.

See docs/threat-model.md and docs/audits/phase13-verification.md — the latter records every defect independent verifiers found, including two severe ones.

Quick start

python -m venv .venv
.venv/Scripts/python -m pip install -r requirements-dev.txt

# LIVE: real BTCUSDT candles from Binance public. No API key required.
.venv/Scripts/python -m tradebot.api.devserver --port 5555 --live

# Offline: seeded synthetic market, touches no network.
.venv/Scripts/python -m tradebot.api.devserver --port 5555
# -> http://127.0.0.1:5555/

Going live

Market data — live, and no API key needed

--live is wired and working. Public BTCUSDT data requires no credentials — deliberately: requiring exchange keys for paper trading was audit finding A10. Every request goes through the DataBroker allowlist (data-api.binance.vision, GET only).

What live mode actually does:

  • backfills 1000 real 5m candles and replays them through the real execution engine;
  • then keeps trading: a LiveLoop polls Binance every 15s and runs every wallet plus the permanent committee on each newly closed 5m candle — replay, live trading, and outage catch-up all share one idempotent TickEngine code path;
  • replays any gap (downtime, network outage) in order on reconnect — parity-tested against an uninterrupted run;
  • fetches the real exchange filters — Binance's actual LOT_SIZE step is 0.00001, not the 1-satoshi default, so fills obey true venue rules;
  • excludes the in-progress candle — only completed bars ever drive a decision or a mark;
  • re-marks equity every 15s from the newest closed candle;
  • fails loudly if live data can't be fetched, rather than silently serving synthetic prices; a refresh failure keeps the last good mark and flags the source degraded.

Prices are never parsed through a binary float — decimal strings go straight to Decimal.

If you later add private endpoints (not required, and not recommended for a paper platform), credentials go in .env — never in the dashboard, never in git:

# .env  (gitignored; CI Gate 1 fails the build if it is ever tracked)
BINANCE_API_KEY=...
BINANCE_API_SECRET=...

Local LLM

TRADEBOT_LLM_PROVIDER=llama_cpp
TRADEBOT_LLM_BASE_URL=http://172.29.72.68:18081/v1
TRADEBOT_LLM_HEALTH_URL=http://172.29.72.68:18081/health
TRADEBOT_LLM_EXPECTED_MODEL_ARTIFACT=Qwen3VL-30B-A3B-Instruct-Q4_K_M.gguf

The served model ID is discovered via /v1/models — never assumed to equal the GGUF filename. (It currently resolves to Qwen3-VL-30B-A3B-Instruct.) If the model is down the platform reports degraded and keeps trading; it never fabricates analysis.

Market awareness

Every hour an AwarenessService pulls CoinGecko market stats, mempool.space on-chain data, and news RSS — all through the same deny-by-default DataBroker — and has the local model synthesize a structured, cited brief. It replaces the old synthetic macro/fundamental/on-chain placeholders and degrades honestly: a stale brief is capped and falls back to the placeholder rather than pretending to be fresh. Exposed at /system/awareness and on the dashboard's market-awareness panel; /system/live reports the trading heartbeat.

Quality

Gate Result
Tests 947 passing (full suite)
Coverage (tradebot/*) 97% (ratchet; see docs/testing.md)
Ruff / Mypy clean (63 files)
Bandit / pip-audit 0 issues / no known vulnerabilities
Tick performance 0.62 ms for 24 wallets (10 ms budget)

CI runs 8 gates: hygiene, correctness, security, database, frontend, deterministic replay, performance, release candidate.

Documentation

Architecture · Accounting · Execution · Plugin SDK · Evolution policy · Dark Horse · DataBroker · Threat model · Testing · Release checklist

Honest status

The new tradebot package is a release candidate, not a finished replacement:

  • Legacy event import is not implemented — the platform starts fresh.
  • Coverage is 97%, not 100%.
  • Frontend has static safety analysis; no jsdom/Playwright suite yet.
  • The legacy flat modules still exist and still carry their original findings.

Full detail in docs/release-checklist.md.

About

Self-evolving BTCUSDT paper-trading research platform: 25 competing wallets, weekly elimination + permanent bans, strategies written by a local LLM and run in sandboxes, continuous live trading, hourly cited market briefs, restart-safe snapshots. Paper trading only.

Topics

Resources

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages