crypto-quant-platform MCP server
by FETKlOkAn2
README.md
# Crypto Quant Platform
Backtesting, walk-forward validation and paper trading for crypto strategies —
self-hosted, and drivable by an AI agent through MCP.
**It is built to tell you when a strategy does not work.** Take 200 strategies
with provably zero edge and keep the luckiest one:
| | |
|---|---|
| Conventional significance test | **99.5%** — accepted |
| Deflated Sharpe *(this platform)* | **43.7%** — rejected |
Same data. One of those answers is wrong, and it is the one most backtesting
tools give you.
[**See a real report**](docs/examples/walk-forward-report.html) —
RSI on BTC-USD, 18 windows, one self-contained HTML file
([download and open it](https://raw.githubusercontent.com/FETKlOkAn2/crypto-quant-platform/main/docs/examples/walk-forward-report.html)).
```bash
git clone <repo> && cd backend
make setup # deps, generated secrets, real market data
make demo # health → strategies → backtest → walk-forward → paper trading
```
No API keys. No cloud account. The demo runs against real BTC-USD and ETH-USD
candles committed to the repository, so it works offline on a clean clone.
---
## What this is
Infrastructure for testing whether a trading strategy actually works, and for
running it once you believe it does.
- **Backtesting** — vectorbt engine with transaction costs and slippage taken
from your risk configuration, not hardcoded
- **Walk-forward validation** — parameters chosen per training window with a
purge gap, scored once on unseen data, reported with in-sample/out-of-sample
degradation, parameter stability and a deflated-Sharpe correction for
the size of the parameter search
- **Paper trading** — order book, fills, fees and slippage simulation
- **Live execution** — Kraken (verified) and Coinbase Advanced (implemented,
not yet exercised against the live venue), with risk-based position sizing
and stop-loss enforcement
- **Position reconciliation** — compares what the platform thinks it holds
against what the exchange reports, and halts on a material mismatch
- **Strategy plug-ins** — 18 reference implementations; add your own by
subclassing `Strategy`
- **REST + WebSocket API** — Flask, with a local auth provider that needs no
cloud account
- **MCP server** — drive all of the above from Claude Desktop or Cursor in
plain English
## What this is not
- **Not a source of alpha.** The included strategies are reference
implementations. Run the walk-forward before believing any of them; it is
built to tell you when a strategy does not work, and it usually does.
- **Not high-frequency.** Intraday to multi-day holding periods.
- **Not a managed service.** You run it.
---
## Ask an agent to do the work
The MCP server exposes the research surface as tools, so an agent can run the
analysis and interpret it:
> *"List the strategies, run a 90-day RSI backtest on BTC-USD, then a
> walk-forward with rsi_window between 10 and 30, and tell me whether it's
> overfitted."*
```bash
make mcp # stdio server; see core/mcp/README.md for Claude Desktop wiring
```
Tools: `list_strategies`, `run_backtest`, `run_walk_forward`,
`run_combined_backtest`, `start_paper_trading`, `stop_paper_trading`,
`get_trading_status`, `get_risk_state`, `get_reconciliation`.
The MCP server is paper-only by design. There is no tool that can place a real
order.
---
## Walk-forward: the part that matters
A backtest tells you what a strategy would have returned on data you fitted it
to. That number is nearly always good and nearly always meaningless.
```bash
curl -X POST localhost:5000/api/backtest/walk-forward \
-H 'Content-Type: application/json' \
-d '{"strategy":"RSI","symbol":"BTC-USD","granularity":"ONE_HOUR",
"num_days":365,"param_ranges":{"rsi_window":[10,14,20,30]}}'
```
Returns per-window in-sample and out-of-sample metrics, a buy-and-hold
benchmark for each window, the degradation between in and out of sample,
how much the selected parameters moved between windows, and a verdict:
```json
{
"summary": {
"mean_oos_return": -1.52,
"mean_benchmark_return": -3.32,
"mean_excess_return": 1.80,
"windows_beating_benchmark": 13,
"degradation": 0.31
},
"verdict": {
"rating": "inconclusive",
"summary": "No disqualifying signal, but the evidence is not strong
enough to call this an edge."
}
}
```
Or as a self-contained HTML report you can send to someone:
```bash
make report STRATEGY=RSI SYMBOL=BTC-USD
```
One file, no network, no scripts — per-window in-sample against
out-of-sample, a benchmark bar per window, parameter stability, and the
verdict. It opens from disk and survives an email attachment.
It also answers the question a good backtest number cannot: **how much of
this is just the best of N tries?**
```
combinations tried 16
best-by-chance SR 0.0527 <- what 16 zero-edge attempts produce
deflated Sharpe 0.0% <- probability this reflects skill
```
Search a parameter grid, report the best result, and that result is biased
upward whether or not the strategy has an edge. The deflated Sharpe (Bailey &
López de Prado) corrects for how many combinations were tried and for the skew
and fat tails of the actual returns. Below 95%, the result does not survive.
Methodology: parameters are selected in memory from each training window and
never read back from a shared table; a purge gap separates train from test;
out-of-sample windows do not overlap; selection defaults to Sharpe rather than
total return, because selecting on raw return reliably picks the most
over-fitted corner of the grid.
---
## Configuration
`make setup` writes a `.env` with generated secrets. Only two values are
required:
| Variable | Purpose |
|----------|---------|
| `SECRET_KEY` | Signs session tokens |
| `ENCRYPTION_KEY` | Encrypts stored exchange API keys. **Back this up** — losing it makes stored credentials unreadable |
Everything else has a working default. The ones worth knowing:
| Variable | Default | Notes |
|----------|---------|-------|
| `TRADING_MODE` | `paper` | `paper`, `backtest` or `live` |
| `AUTH_PROVIDER` | `local` | `local` (no cloud account), `cognito`, or `none` |
| `DATABASE_PATH` | `database` | Where SQLite files live |
| `EXCHANGE` | `kraken` | Live venue: `kraken` or `coinbase` |
`AUTH_PROVIDER=none` disables authentication and refuses to start unless
`TRADING_MODE` is explicitly `paper` or `backtest`, so an unauthenticated API
can never front a live-money deployment.
Check any deployment with:
```bash
curl -s localhost:5000/api/health | jq .data.checks
```
Every check reports `ok`, `warn` or `error` plus what to do about it.
---
## Market data
```bash
python -m scripts.seed_data # fetch from Coinbase's public API
python -m scripts.seed_data --offline # committed fixtures only
python -m scripts.seed_data --symbols ETH-USD --granularities ONE_HOUR --days 730
```
Fixtures under `scripts/fixtures/` are gzipped CSV — text, so they diff and
review like code rather than sitting in the repository as opaque binaries.
---
## Adding a strategy
```python
from core.strategies.strategy import Strategy, MarketCondition, register_strategy
@register_strategy
class MyStrategy(Strategy):
market_condition = MarketCondition.TRENDING
strategy_name = "My Strategy"
def custom_indicator(self, close=None, window=14):
...
return self.generate_signals(buy_signal, sell_signal)
```
Drop it in `core/strategies/`. It is discovered automatically and becomes
available to backtesting, walk-forward, the API and the MCP server with no
registration step.
## Adding an exchange
Implement [`ExchangeClient`](core/wrappers/base.py) — nine methods — and pass
it in:
```python
LiveTrader(socketio, client=MyVenueClient())
```
The contract states the units explicitly, because the trading path does not
convert between them: volume is base-asset units, never dollars. An
incomplete client is rejected at construction with a list of what is missing,
rather than failing part-way through a trading cycle. `core/paper_trading/
client.py` is a complete reference implementation, and the conformance tests
in `tests/test_exchange_clients.py` run against every registered venue.
---
## Development
```bash
make test # 730 tests with coverage
make lint # ruff
make check # both, as CI runs them
```
CI runs lint, the suite, an end-to-end smoke test that boots the API and
drives it, and a Docker build that fails if the container does not report
healthy.
## Tech stack
Python 3.10 · Flask + Socket.IO · pandas / NumPy / TA-Lib · vectorbt ·
Optuna · SQLite (PostgreSQL optional) · Docker
The numeric stack is pinned to Python 3.10 by vectorbt 0.26.2's numba
requirement. See [docs/ROADMAP.md](docs/ROADMAP.md).
## Documentation
- **[docs/OVERVIEW.md](docs/OVERVIEW.md) — start here: what this solves, in plain language**
- [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) — how it fits together
- [docs/DEMO.md](docs/DEMO.md) — annotated walkthrough
- [docs/SECURITY.md](docs/SECURITY.md) — threat model and key handling
- [docs/ROADMAP.md](docs/ROADMAP.md) — known limitations and what's next
- [core/mcp/README.md](core/mcp/README.md) — MCP client wiring
- [docs/COMMERCIAL.md](docs/COMMERCIAL.md) — what is free, what is paid
## License
[Apache-2.0](LICENSE). Use it commercially, modify it, fork it — no fee and
no per-seat licence. See [NOTICE](NOTICE) for the trading-risk disclaimer and
third-party components.
Paid work (audits, integrations, retainers) is described in
[docs/COMMERCIAL.md](docs/COMMERCIAL.md). The software itself is not for
sale — expertise is.
---
*Cryptocurrency trading involves substantial risk of loss. Nothing here is
financial advice.*
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues