基于 MiniQMT(xtquant)接口的量化交易工程,支持全天候策略、ETF 轮动策略和 T+0 日内策略, 提供历史回测、HTML 报告生成和定时调仓/信号提醒。MiniQMT 为唯一数据源。
quant/
├── config.yaml # 核心配置(资产、策略、通知等)
├── requirements.txt # Python 依赖
├── position.json # 全天候持仓文件(可替换为实际持仓)
├── rotation_position.json # ETF 轮动持仓文件(可不存在,默认空持仓)
├── run_backtest.py # 统一回测入口(按 active_strategy 分发)
├── run_monitor.py # 统一监控入口(按 active_strategy 分发)
├── data_fetcher.py # 数据获取(xtquant / MiniQMT)
├── strategy.py # 全天候策略类
├── backtest.py # 全天候回测引擎(含命令行入口)
├── report_generator.py # HTML 报告生成
├── rebalance_reminder.py # 全天候调仓提醒脚本
├── etf_rotation_strategy.py # ETF 轮动策略类(多因子评分)
├── etf_rotation_backtest.py # ETF 轮动回测引擎
├── etf_rotation_monitor.py # ETF 轮动调仓监控
├── etf_param_optimizer.py # ETF 轮动参数网格搜索与可视化
├── t0_backtest.py # T+0 策略回测引擎(OHLC 日线模拟)
├── t0_monitor.py # T+0 策略盘中实时监控(tick 驱动)
├── smoke_test.py # 全系统冒烟测试(11 条用例)
├── output/ # 回测报告输出目录(自动创建)
└── logs/ # 日志目录(自动创建)
# 建议使用 Python 3.9+
pip install -r requirements.txtxtquant 安装(必须,MiniQMT 为唯一数据源):
xtquant 随 MiniQMT/QMT 客户端附带,通常在客户端安装目录下:
# 方式一:从客户端目录安装
pip install "C:\国金QMT交易端模拟\bin\pythonlib\xtquant"
# 方式二:若迅投提供 pip 源
pip install xtquant编辑 config.yaml,重点关注以下几项:
# 当前激活的策略:all_weather | etf_rotation | t0_strategy
active_strategy: "all_weather"
# MiniQMT 连接配置
miniqmt:
path: "C:/国金QMT交易端模拟/userdata_mini" # 改为实际路径
account: "your_account_id" # 改为实际账号
enable_realtime: false # 改为 true 启用实时行情
# 回测参数
backtest:
start_date: "2020-01-01"
end_date: "2025-12-31"
initial_capital: 1000000
# 调仓频率:daily / monthly / quarterly / weekly
strategy:
rebalance_freq: "monthly"通过 config.yaml 中的 active_strategy 字段切换策略:
active_strategy: "all_weather" # 全天候策略
# active_strategy: "etf_rotation" # ETF 轮动策略
# active_strategy: "t0_strategy" # T+0 日内策略统一入口脚本会读取该字段并自动分发到对应策略模块。
推荐:使用统一入口
# 使用 config.yaml 中的 active_strategy
python run_backtest.py
# 覆盖日期和资金
python run_backtest.py --start 2022-01-01 --end 2024-12-31 --capital 500000
# 仅输出指标,不生成报告
python run_backtest.py --no-report也可直接使用各策略脚本
# 全天候回测
python backtest.py
python backtest.py --start 2022-01-01 --end 2024-12-31 --capital 500000
python backtest.py --no-report
# ETF 轮动回测
python etf_rotation_backtest.py
python etf_rotation_backtest.py --start 2021-01-01 --capital 500000
# T+0 策略回测
python t0_backtest.py
python t0_backtest.py --start 2023-01-01 --end 2024-12-31
python t0_backtest.py --no-report推荐:使用统一入口
# 测试模式(仅打印,不发送通知)
python run_monitor.py --dry-run
# 强制触发(忽略周期判断)
python run_monitor.py --force --dry-run
# 显示评分排名(ETF 轮动策略有效)
python run_monitor.py --dry-run --show-scores也可直接使用各策略脚本
# 全天候调仓提醒
python rebalance_reminder.py --dry-run
python rebalance_reminder.py --force --dry-run
python rebalance_reminder.py --position-file my_position.json
# ETF 轮动调仓监控
python etf_rotation_monitor.py --dry-run
python etf_rotation_monitor.py --dry-run --force
python etf_rotation_monitor.py --dry-run --show-scores
# T+0 策略盘中监控
python t0_monitor.py --dry-run
python t0_monitor.py --force --dry-run
python t0_monitor.py --force # 执行一次扫描 + 发心跳| 策略 | 文件名格式 | 示例 |
|---|---|---|
| 全天候 | report_YYYYMMDD_HHMMSS.html |
report_20260315_120345.html |
| ETF 轮动 | etf_rotation_report_YYYYMMDD_HHMMSS.html |
etf_rotation_report_20260315_120345.html |
| T+0 策略 | t0_report_YYYYMMDD_HHMMSS.html |
t0_report_20260315_120345.html |
| 策略 | 文件名格式 | 示例 |
|---|---|---|
| 全天候 | rebalance_YYYYMMDD.json |
rebalance_20260315.json |
| ETF 轮动 | rotation_YYYYMMDD.json |
rotation_20260315.json |
| 脚本 | 日志文件 |
|---|---|
backtest.py / run_backtest.py(全天候) |
backtest.log |
rebalance_reminder.py / run_monitor.py(全天候) |
rebalance.log |
etf_rotation_backtest.py / run_backtest.py(轮动) |
etf_rotation_backtest.log |
t0_backtest.py |
t0_backtest.log |
t0_monitor.py / run_monitor.py(T+0) |
t0_monitor.log |
{
"_total_cash": 50000,
"518880.SH": 1000,
"511010.SH": 3000
}- 键为证券代码(格式:
代码.交易所) - 值为持有股数(整数)
_total_cash:账户现金(元,可选)- 以
_开头的字段为元数据,自动忽略
{
"_last_rebalance_date": "2026-03-01",
"_entry_prices": {"159915.SZ": 2.135},
"_entry_dates": {"159915.SZ": "2026-03-01"},
"159915.SZ": 10000
}_last_rebalance_date:最后一次调仓日期,用于周期判断_entry_prices:各持仓建仓均价,用于止损判断_entry_dates:各持仓建仓日期,用于最短持仓天数判断- 文件不存在时默认为空持仓,自动初始化
在 config.yaml 的 notification 部分配置。以钉钉为例:
notification:
channels: ["dingtalk"]
dingtalk:
enabled: true
webhook_url: "https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN"
secret: "YOUR_SECRET" # 若开启加签则填写,否则留空邮件(QQ 邮箱示例):
notification:
channels: ["email"]
email:
enabled: true
smtp_host: "smtp.qq.com"
smtp_port: 465
use_ssl: true
username: "your@qq.com"
password: "your_smtp_authorization_code" # 授权码,非登录密码
from_addr: "your@qq.com"
to_addrs: ["recipient@example.com"]新建任务,操作设置为:
程序:C:\Python\python.exe
参数:C:\Users\zhanghang\OneDrive\Python\quant\run_monitor.py
起始于:C:\Users\zhanghang\OneDrive\Python\quant
触发器设置为每月第一个工作日早上 9:30。
# 每月 1 日 09:30 触发
30 9 1 * * /usr/bin/python3 /path/to/quant/run_monitor.py固定权重资产配置,以风险平价为理念,覆盖四种经济环境(增长/衰退 × 通胀/通缩):
| 大类 | 资产 | 代码 | 目标权重 |
|---|---|---|---|
| 商品 | 黄金ETF | 518880.SH | 8.33% |
| 商品 | 石油基金 | 160416.SZ | 8.33% |
| 商品 | 豆粕ETF | 159985.SZ | 8.34% |
| 股票 | 创业板ETF | 159915.SZ | 8.33% |
| 股票 | 纳指ETF | 513100.SH | 8.33% |
| 股票 | 日经ETF | 513520.SH | 8.34% |
| 长债 | 国债ETF | 511010.SH | 12.5% |
| 长债 | 标普500ETF博时 | 513500.SH | 12.5% |
| 短债 | 短融ETF | 511360.SH | 25% |
调仓规则:
- 固定周期(daily / weekly / monthly / quarterly,默认每月第一个交易日)恢复目标权重
- 可选漂移触发:任一资产偏离目标超过
drift_threshold(默认 5%)时提前触发
多因子动态轮动,每期持有评分最高的 1 只 ETF:
候选池(8 只 ETF):
| 资产 | 代码 |
|---|---|
| 创业板ETF | 159915.SZ |
| 沪深300ETF | 510300.SH |
| 纳指ETF | 513100.SH |
| 黄金ETF | 518880.SH |
| 国债ETF | 511010.SH |
| 短融ETF | 511360.SH |
| 豆粕ETF | 159985.SZ |
| 日经ETF | 513520.SH |
评分因子:
- 动量(40%):近期价格涨幅
- 夏普(40%):近期风险调整收益
- 低波动(20%):近期波动率(越低越好)
各因子均做百分比排名后加权合成总分,每月调仓一次。
止损规则:持仓下跌超过 8% 且持仓满 3 天时,触发换仓至当期最高分资产。
针对指定股票池,盘中实时检测先卖后买的日内交易机会,通过飞书机器人推送信号。
信号逻辑(三路卖出 OR + 两路买回 OR):
卖出信号(任一满足即触发):
- 路径A:当日涨幅 ≥
sell_threshold(默认 2%),无趋势要求 - 路径B:RSI >
rsi_sell_threshold(默认 70)AND 量比 >volume_ratio_threshold(默认 1.8)AND EMA 趋势向上 - 路径C:价格 > 昨收 × (1 +
vwap_threshold,默认 1%) AND EMA 趋势向上(昨收近似 VWAP)
买回信号(任一满足即触发):
- 回落买回:从日内高点回落 ≥
pullback_threshold(默认 0.5%) - RSI 超卖买回:RSI <
rsi_buy_threshold(默认 50)
技术指标(EMA、RSI、量比)在每个交易日开盘前从日线数据计算一次,获取失败时路径B/C自动降级不触发,行为与仅路径A一致。
配置项(config.yaml → t0_strategy):sell_threshold、pullback_threshold、ema_short、ema_long、rsi_period、rsi_sell_threshold、rsi_buy_threshold、volume_ratio_threshold、volume_ratio_window、vwap_threshold
| 图表 / 表格 | 说明 |
|---|---|
| 净值曲线 | 策略净值 vs 沪深300基准 |
| 回撤曲线 | 历史回撤变化 |
| 大类权重变化 | 商品/股票/长债/短债权重历史(全天候) |
| 各资产权重变化 | 各资产的权重堆叠图 |
| 绩效指标 | 年化收益、最大回撤、夏普/索提诺/卡玛比率等 |
| 调仓记录 | 每次调仓的日期、操作、数量、价格、手续费 |
Q:如何在两套策略之间切换?
修改 config.yaml 中的 active_strategy 字段,然后通过统一入口运行:
active_strategy: "etf_rotation" # 切换到 ETF 轮动python run_backtest.py # 自动使用 etf_rotation 策略
python run_monitor.py # 自动使用 etf_rotation 策略Q:xtquant 连接失败?
确认:(1) MiniQMT/QMT 客户端正在运行;(2) config.yaml 中 path 和 account 配置正确;(3) enable_realtime: true。
Q:如何修改全天候资产组合?
直接在 config.yaml 的 assets 列表中修改 code、weight、enabled。权重会自动归一化,无需保证总和精确为 1。
Q:如何生成 PDF 报告?
安装 weasyprint 后,在 backtest.py 中调用:
rg.generate_pdf(result, charts, "output/report.pdf")注意:weasyprint 在 Windows 上依赖 GTK,安装较复杂,建议优先使用 HTML 报告。