Content
# BackTest_MCP
Stock backtesting engine MCP server (QuantForge MCP): A quantitative backtesting and data service for Cursor/Agent.
Supports executing the full process of "dynamic strategy code verification → pulling/caching market data → sub-process backtesting → product/report generation → result query" through MCP tools.
**Main Tech Stack**: Python 3.10+, `mcp` (FastMCP, stdio/SSE), SQLite (task/market data/product indexing), pandas/numpy (data and indicator calculation), akshare/yfinance (market data source, routed by A-share/US stock), uvx/pyproject (packaging and distribution), uvicorn (SSE hosting compatibility).
## Reference
The core backtesting engine code of this project is referenced from the open-source repository [theNeuralHorizon/quantforge](https://github.com/theNeuralHorizon/quantforge).
On this basis, combined with the MCP scenario, tool encapsulation, service layer, and operation process are supplemented.
## Function Overview
- Provides stock data pulling/caching capability (default `auto` US stock + A-share, `yfinance` US stock, `akshare` A-share).
- Provides dynamic strategy code verification and backtesting execution.
- Provides backtesting result query, artifact download, and Markdown report generation.
- Exposes strategy generation auxiliary directory (indicator/statistic/risk management/combination function and strategy examples).
- Supports multi-symbol (multi-target) strategy backtesting.
- To be developed: ML capability improvement and Docker deployment (e.g., worker/server containerization).
## Documentation
- `docs/quantforge_mcp.md`: MCP server layer architecture and module description
- `docs/quantforge_stock.md`: Backtesting/research library architecture and module description
## Directory Structure
```text
BackTest_MCP/
├─ pyproject.toml # Packaging configuration (for uvx to run from git)
├─ requirements.txt # Python dependencies (for development/compatibility)
├─ docs/ # Architecture and usage documents
├─ quantforge_mcp/ # MCP service package (server, tools, services, db, resources, etc.)
├─ quantforge_stock/ # Quantitative calculation and strategy library
└─ storage/
├─ db/ # SQLite database directory (including .db/.db-wal/.db-shm)
└─ artifacts/ # Backtesting artifact directory (divided by job_id)
> Note: By default, `storage/` will be resolved **relative to the current working directory (cwd)** (e.g., if you start the service in `C:\Users\username`, it will default to `C:\Users\username\storage\...`).
> If started in a non-writable directory like `C:\Windows\System32`, it will automatically fall back to the user directory (e.g., `%LOCALAPPDATA%\quantforge-mcp\...`).
> To fix the location, it is recommended to explicitly set `QUANTFORGE_DB_PATH` / `QUANTFORGE_ARTIFACTS_DIR` to an absolute path.
```
## Environment Requirements
- Python 3.10+
## Start Service
### Method 1: Cursor/Agent Access via uvx (Recommended)
Add the following configuration to your Cursor MCP configuration (the example only shows the structure, adjust according to your actual path):
```json
{
"mcpServers": {
"quantforge": {
"command": "uvx",
"args": [
"--from",
"git+https://github.com/Dor1Toes/BackTest_MCP.git@v0.1.0",
"quantforge-mcp"
]
}
}
}
```
(Not yet released) If released to PyPI in the future, you can use the following form (example):
```json
{
"mcpServers": {
"quantforge": {
"command": "uvx",
"args": ["quantforge-mcp==0.1.0"],
"env": { "QUANTFORGE_TRANSPORT": "stdio" }
}
}
}
```
### Method 2: Local Operation (Development/Debugging)
First, install dependencies:
```bash
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
```
Then, start stdio:
```bash
python -m quantforge_mcp
```
### Method 3: SSE
```bash
set QUANTFORGE_TRANSPORT=sse # Linux/macOS use export
set QUANTFORGE_SSE_PORT=8001
python -m quantforge_mcp
```
## MCP Tool List
### Data
- `get_stock_data(symbol, start, end, interval)`: Obtain and aggregate OHLCV data.
- `list_cached_symbols()`: View locally cached stock symbols.
- `prefetch_stock_data(symbols, start, end, interval)`: Batch pre-fetch data.
### Backtest
- `validate_strategy_code(code)`: Strategy code AST security verification.
- `validate_backtest_config(config_json)`: Backtest configuration verification.
- `run_backtest_dynamic(code, config_json)`: Run dynamic strategy backtest.
- `list_backtest_jobs(limit, status)`: List historical backtest jobs in SQLite.
- `get_backtest_result(job_id)`: Query backtest result.
- `generate_backtest_report(job_id, title)`: Generate Markdown report.
- `get_backtest_artifacts(job_id, kind)`: Obtain backtest artifacts.
## Strategy Example
The following is an example of a "momentum strategy" code and corresponding configuration generated by Agent after accessing MCP:
> Multi-target description: Pass multiple targets to `config_json.symbols`; the engine will call `on_bar(symbol, bar, history)` once for each symbol on each bar (where `history` is the single-target history).
### Example Strategy Code (MomentumStrategy)
```python
"""Momentum strategy: 60-day return momentum, positive return long, negative return close position."""
from dataclasses import dataclass
import pandas as pd
from quantforge_stock.strategies.base import Strategy
@dataclass
class MomentumStrategy(Strategy):
lookback: int = 60
threshold: float = 0.0
allow_short: bool = False
name: str = "momentum"
def warmup(self) -> int:
return self.lookback + 1
def on_bar(self, symbol: str, bar: pd.Series, history: pd.DataFrame) -> list:
if len(history) < self.lookback + 1:
return []
past = history["close"].iloc[-(self.lookback + 1)]
now = history["close"].iloc[-1]
ret = now / past - 1.0
direction = 0
if ret > self.threshold:
direction = 1
elif ret < -self.threshold and self.allow_short:
direction = -1
strength = min(1.0, abs(ret) / max(self.threshold + 1e-6, 0.05))
return [self._signal(bar.name, symbol, direction, strength, self.name)]
```
### Example Configuration (config_json)
```json
{
"name": "ashare_momentum_real",
"symbols": ["600519"],
"start": "2025-07-23",
"end": "2026-07-23",
"initial_capital": 100000.0,
"commission": 0.0003,
"slippage": 0.001
}
```
## MCP Resource List
- `quantforge://codegen/spec`: Strategy code generation specification.
- `quantforge://data/symbol-guide`: Symbol usage guide.
- `quantforge://examples/nvda_dynamic_config`: Dynamic backtest configuration example.
- `quantforge://compute/modules`: Computing modules and function directory for strategy generation.
- `quantforge://compute/{module}`: View details of a single computing module (e.g., `quantforge://compute/indicators`).
- `quantforge://strategies/index`: Built-in strategy example index.
- `quantforge://strategies/{name}`: Single strategy source code and description (e.g., `quantforge://strategies/ma_crossover`).
## Key Environment Variables
All configuration items are prefixed with `QUANTFORGE_`:
- `QUANTFORGE_DB_PATH` (default `storage/db/quantforge.db`, relative to cwd)
- `QUANTFORGE_ARTIFACTS_DIR` (default `storage/artifacts`, relative to cwd)
- `QUANTFORGE_DATA_SOURCE` (default `auto`)
- `QUANTFORGE_AKSHARE_ADJUST` (default `qfq`)
- `QUANTFORGE_ALLOW_SYNTHETIC_FALLBACK` (default `true`)
- `QUANTFORGE_SANDBOX_TIMEOUT_SEC` (default `120`)
- `QUANTFORGE_TRANSPORT` (`stdio` / `sse`, default `stdio`)
- `QUANTFORGE_SSE_PORT` (default `8001`)
Windows example (fix data/artifacts to your directory):
```bash
set QUANTFORGE_DB_PATH=C:\Users\24161\storage\db\quantforge.db
set QUANTFORGE_ARTIFACTS_DIR=C:\Users\24161\storage\artifacts
```
## About `quantforge_stock/ml`
`quantforge_stock/ml` is currently under development.
- Disabled by default; if you need to enable experimental capabilities, manually set `QUANTFORGE_ENABLE_EXPERIMENTAL_ML=1`.
```bash
set QUANTFORGE_ENABLE_EXPERIMENTAL_ML=1 # Linux/macOS use export
```
## About Sandbox Execution
Dynamic backtesting runs through `sandbox/worker/backtest_worker.py` as a **local subprocess** (not Docker).
Timeout is controlled by `QUANTFORGE_SANDBOX_TIMEOUT_SEC`; the first market data fetch/database initialization may be slightly slower.
## FAQ
- **`ModuleNotFoundError: quantforge_mcp`**
Currently, it is recommended to directly execute `python server.py` in the repository root directory; if using module startup, please execute in the parent directory and ensure `quantforge_mcp` is in `PYTHONPATH`.
- **Cursor log prompt: `'uvx' is not an internal or external command`**
This indicates that `uvx` is not found in the environment where Cursor starts MCP (PATH not included). Please change `mcpServers.quantforge.command` to the **absolute path** of `uvx.exe` (e.g., `C:\\Users\\username\\.local\\bin\\uvx.exe`), or ensure the directory where `uvx` is located is added to the system PATH.
- **`uvx` started from a directory like `C:\\Windows\\System32` reports `...\\storage\\db` creation failure**
This is because by default, `storage/` will be resolved **relative to the current working directory (cwd)**, causing an attempt to create `storage/db` in a system directory. Solution:
- Explicitly set `QUANTFORGE_DB_PATH` / `QUANTFORGE_ARTIFACTS_DIR` to an absolute path
- Or set `QUANTFORGE_STORAGE_ROOT` to a writable directory (as the base for relative paths)
- **Still hitting old cache after updating version**
When using `uvx`, you can add `--reinstall` before parameters to force refresh cache (e.g., `["--reinstall", "--from", "...", "quantforge-mcp"]`).
- **First backtest is slower**
The first market data fetch and database initialization will have cold start overhead, which is a normal phenomenon.