FastAPI + Backtrader + AKShare/pytdx + React 18 + lightweight-charts 真实行情 · 真实回测 · 真实撮合 · 零 Mock 数据
QuantSys 是一套面向 A 股市场的量化交易研究与实践平台,提供:
- 实时行情:pytdx 通达信协议直连交易所行情服务器(境内免代理),AKShare 东方财富实时接口作为 fallback;WebSocket 推送 3 秒刷新
- 历史 K 线:AKShare 全量历史数据(日/周/1m/5m/15m/30m/60m),SQLite 本地缓存,自动增量更新
- 6 大策略回测:双均线 / MACD / RSI / 布林带 / KDJ / 海龟,Backtrader 引擎,A 股佣金模型(双向万三 + 卖出千一印花税 + 最低 5 元/笔)
- 模拟交易:T+1 结算、100 股最小手数、市价/限价单、自动策略信号交易
- 现代前端:Apple 风格深色主题、lightweight-charts 金融 K 线、TanStack Query 数据缓存、Zustand 状态管理
| 依赖 | 最低版本 | 推荐版本 | 备注 |
|---|---|---|---|
| Python | 3.11 | 3.11.x | 必须 ≥ 3.11(使用了 tomllib / match 等新特性) |
| Node.js | 18 | 20 LTS | Vite 5 要求 ≥ 18 |
| pnpm | 8 | 9.x | 包管理器(也可用 npm,但 pnpm 更快) |
| SQLite | 3.35+ | 系统自带 | 用于 upsert(ON CONFLICT) |
操作系统:macOS / Linux 优先;Windows 需 WSL2(pytdx TCP 直连在 Windows 原生也可用)
网络:境内网络直连即可,无需任何代理。pytdx 直连通达信行情服务器,AKShare 走东方财富公开接口。
# 1. 克隆项目
cd quantitative-trading-system
# 2. 复制环境配置
cp .env.example .env
# 3. 一键启动(自动创建 venv、安装依赖、初始化 DB、启动前后端)
bash scripts/start.sh启动完成后:
- 前端:http://127.0.0.1:5173
- 后端 API 文档(FastAPI 自动生成):http://127.0.0.1:8000/docs
- 后端 ReDoc 文档:http://127.0.0.1:8000/redoc
按 Ctrl+C 优雅关闭所有服务。
如不使用 start.sh,可分步安装:
# 推荐使用 uv(更快)
uv sync
# 或使用标准 venv
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
# 初始化数据库 + 默认账户
python scripts/init_db.py
# 预拉股票列表(首次启动建议执行,约 30-60 秒)
python scripts/seed_stocks.py
# 启动后端
uvicorn backend.main:app --reload --host 127.0.0.1 --port 8000cd frontend
pnpm install
pnpm run devcd frontend
pnpm run build # 产物 → frontend/dist
pnpm run preview # 本地预览生产构建source .venv/bin/activate
# 全量测试(含集成测试,需要网络)
pytest
# 仅单元测试(跳过外部 API 调用)
pytest -m "not integration"
# 带覆盖率报告
pytest --cov=backend --cov-report=term-missing测试覆盖:
| 测试文件 | 覆盖范围 |
|---|---|
test_data_fetcher.py |
AKShare 股票列表、日 K、实时行情、股票信息(标记 integration) |
test_cache.py |
K 线落库、upsert 幂等、按 symbol/时间过滤 |
test_backtest.py |
6 大策略回测、佣金扣除、equity_curve 长度、确定性验证 |
test_trader.py |
下单撮合、T+1 结算、佣金/印花税计算、资金/持仓校验、限价单触发 |
test_api.py |
所有 REST 端点、参数校验、错误处理 |
cd frontend
pnpm test # 单次运行
pnpm test:watch # watch 模式测试覆盖:KlineChart 渲染、BacktestPanel 表单与策略切换、TraderPanel 下单验证、useRealtimeQuote WebSocket hook。
| 策略标识 | 中文名 | 核心参数 | 信号规则 |
|---|---|---|---|
ma_cross |
双均线交叉 | fast_period=5, slow_period=20 |
快线上穿慢线买入,下穿卖出 |
macd |
MACD | fast=12, slow=26, signal=9 |
MACD 柱由负转正买入,由正转负卖出 |
rsi |
RSI 反转 | period=14, oversold=30, overbought=70 |
RSI<30 买入,RSI>70 卖出 |
bollinger |
布林带突破 | period=20, devfactor=2.0 |
价格跌破下轨买入,突破上轨卖出 |
kdj |
KDJ 超买超卖 | k_period=9, d_period=3, j_period=3 |
J<20 买入,J>80 卖出 |
turtle |
海龟交易 | entry_period=20, exit_period=10 |
突破 N 日最高买入,跌破 M 日最低卖出 |
所有策略均继承 backtrader.Strategy,参数可通过 /api/backtest/run 的 strategy_params 字段动态传入。
A 股佣金模型(所有策略共用):
- 佣金:买卖双向万三(0.0003),最低 5 元/笔
- 印花税:卖出千一(0.001)
- 滑点:默认 0(可在
BacktestParams中扩展)
启动后端后访问 http://127.0.0.1:8000/docs 查看完整 OpenAPI 文档。核心端点:
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/market/stocks?q= |
搜索股票(代码/名称模糊匹配) |
| GET | /api/market/quote/{symbol} |
单只实时行情 |
| GET | /api/market/quotes?symbols=000001,600519 |
批量实时行情 |
| GET | /api/market/info/{symbol} |
股票基本信息 |
| GET | /api/kline/{symbol}?timeframe=1d&start=&end= |
K 线数据(自动缓存) |
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/backtest/strategies |
6 大策略列表及参数定义 |
| POST | /api/backtest/run |
执行回测,返回完整 BacktestResult |
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /api/trader/order |
下单(市价/限价) |
| DELETE | /api/trader/order/{id} |
撤单 |
| GET | /api/trader/positions |
当前持仓 |
| GET | /api/trader/orders |
历史订单 |
| GET | /api/trader/account |
账户快照 |
| POST | /api/trader/reset |
重置账户 |
| POST | /api/trader/auto |
启用策略自动交易 |
| DELETE | /api/trader/auto/{symbol} |
停止自动交易 |
| GET | /api/trader/auto/list |
列出运行中的自动策略 |
| 路径 | 说明 |
|---|---|
ws://127.0.0.1:8000/ws/realtime |
实时行情推送,3 秒间隔 |
客户端消息:
{"action": "subscribe", "symbols": ["000001", "600519"]}
{"action": "unsubscribe", "symbols": ["000001"]}
{"action": "ping"}启动后访问 http://127.0.0.1:5173 即可看到以下页面:
- 仪表盘(Dashboard):自选股实时看板、市场总览、快捷入口
- 行情页(/market):股票搜索、自选股列表、实时报价卡片
- K 线页(/market/:symbol):lightweight-charts K 线图 + 成交量副图、7 种时间周期、6 种技术指标、右侧实时报价面板
- 回测页(/backtest):左侧策略配置表单(动态参数)、右侧指标卡片 + 收益曲线 + 交易记录表
- 交易页(/trader):账户摘要 + 下单面板 + 持仓表 + 订单历史 + 自动策略面板
K 线图遵循 A 股配色:涨红跌绿(红色 #ef4444 = 上涨,绿色 #10b981 = 下跌)。
| 约束 | 说明 |
|---|---|
| 零 Mock 数据 | 除测试 fixture 外,所有行情/回测数据必须来自 AKShare/pytdx 真实接口 |
| A 股佣金模型 | 双向万三 + 卖出千一印花税 + 最低 5 元/笔,不可省略 |
| T+1 结算 | 买入当日不可卖出,available 字段次日才更新 |
| 100 股最小手数 | 买入数量必须为 100 整数倍 |
| 涨红跌绿 | 前端所有涨跌配色遵循 A 股习惯,不得使用西方涨绿跌红 |
| WebSocket 推送 | 实时行情必须用 WebSocket,禁止轮询(fallback 除外) |
| lightweight-charts | K 线图必须用 lightweight-charts,禁止 ECharts/Highcharts |
| 境内直连 | 所有数据接口境内无需代理,禁止境外金融 API |
quantitative-trading-system/
├── backend/
│ ├── api/ # FastAPI 路由(market/kline/backtest/trader/ws)
│ ├── backtest/ # Backtrader 引擎 + 6 大策略 + 自定义分析器
│ ├── trader/ # 模拟交易引擎 + 账户管理
│ ├── models/ # SQLAlchemy ORM(Stock/KlineBar/Account/Position/Order)
│ ├── data/ # AKShare/pytdx 数据层 + SQLite 缓存 + APScheduler
│ ├── tests/ # pytest 测试套件
│ ├── config.py # 配置读取
│ ├── database.py # 异步 SQLAlchemy 引擎
│ └── main.py # FastAPI 入口 + lifespan
├── frontend/
│ ├── src/
│ │ ├── api/ # TypeScript API 封装
│ │ ├── components/ # Backtest/Chart/Market/Trader/layout 组件
│ │ ├── hooks/ # useRealtimeQuote / useKline
│ │ ├── pages/ # Dashboard/MarketPage/BacktestPage/TraderPage
│ │ ├── store/ # Zustand stores
│ │ └── test/ # Vitest setup
│ └── vite.config.ts
├── scripts/
│ ├── init_db.py # 初始化数据库 + 创建默认账户
│ ├── seed_stocks.py # 预拉股票列表
│ └── start.sh # 一键启动
├── pyproject.toml # uv 管理 Python 依赖
├── .env.example # 环境变量示例
└── quant-system-plan.md # 完整构建计划
- 在
backend/backtest/strategies/创建新文件,继承backtrader.Strategy - 在
backend/backtest/registry.py注册策略元数据(名称、参数、描述) - 在
backend/tests/test_backtest.py添加测试用例 - 前端策略选择器会自动从
/api/backtest/strategies加载
在 backend/backtest/analyzers.py 实现 backtrader.Analyzer 子类,并在 engine.py 的 run_backtest 中添加到 Cerebro。
本项目使用 SQLite 单文件,Schema 变更时:
- 修改
backend/models/下的 ORM 模型 - 删除
quantsys.db(开发环境)或执行drop_db()+init_db() - 重新运行
python scripts/init_db.py
Q: 启动后实时行情不动? A: 检查当前是否为 A 股交易时间(工作日 9:30-11:30 / 13:00-15:00)。非交易时间 pytdx 仍可返回最新收盘数据,但不会变化。
Q: AKShare 接口偶发超时?
A: 已实现 max_retries=3, backoff=1s 重试逻辑。如持续失败,检查网络是否在境内。
Q: 前端 K 线图空白?
A: 检查浏览器控制台是否有 WebSocket 连接错误。后端必须在 8000 端口运行,前端 Vite 代理已配置 /api 和 /ws 转发。
Q: 回测结果在不同运行不一致? A: 不应发生。所有回测使用相同参数应产生相同结果(确定性验证已写入测试)。如发现不一致,请提交 issue。
MIT License — 仅供学习研究使用,不构成任何投资建议。A股有风险,量化需谨慎。
构建依据:quant-system-plan.md v1.0 · 17 工作日计划