>- 根据策略描述、研报 PDF 或截图,解读因子/选股逻辑,基于 scripts/daily-factors-backtest.py 框架生成 QMT 内置日频因子回测脚本。用户提到 QMT 内置回测、因子选股回测、截面因子、 研报复现、handlebar 回测、after_init 预计算信号时使用。
npx skills add https://github.com/dfkai/xtquantai --skill qmt-inner-backtest
基于 scripts/daily-factors-backtest.py 生成 QMT 策略编辑器内置回测 脚本。
核心模式:after_init 预计算全区间因子与买卖信号 → handlebar 按调仓日执行交易。
母版路径:本 skill 目录下的 scripts/daily-factors-backtest.py(相对 SKILL.md 所在目录)
| 适合 | 不适合 |
|------|--------|
| 日频截面因子选股(Barra 风格处理) | Tick/分钟高频 |
| 固定持仓数 Top-N 等权调仓 | 期货开平仓(qmt-future-trade,规划中) |
| 研报因子复现、上下影线/价值/动量等 | 目标持仓型期货实盘(qmt-live-strategy-template,规划中) |
| 申万行业 + 市值中性化 | 仅要信号推送(qmt-live-signal-feishu,规划中) |
daily-factors-backtest.py
├── 文件头 # coding:gbk + 策略说明 docstring
├── 因子函数库 ← 【主要替换区】factor_xxx + 中性化/去极值
├── init(C) ← 【配置区】回测区间、股票池、资金、因子参数
├── after_init(C) ← 【信号区】拉数据 → 算因子 → 过滤 → 生成 g.buy/sell_signals
├── handlebar(C) ← 【执行区】调仓日卖出/买入(通常保留)
├── 交易执行函数 ← 通常原样保留
└── 辅助工具函数 ← 通常原样保留(IPO/ST/涨跌停/财务宽表)
| 段 | 函数/变量 | 做什么 |
|----|-----------|--------|
| 全局状态 | g = G() | 跨函数共享参数、信号矩阵、持仓 |
| 因子库 | factor_ubl(...) | 输入 OHLCV/市值等宽表,输出因子 DataFrame(index=日期, columns=股票) |
| 因子后处理 | filter_extreme_mad_df / neutralize_by_market_cap / neutralize_by_industry_zscore / cross_section_zscore | Barra 风格流水线,按研报需求保留或删减 |
| 初始化 | init(C) | 设 g.start_date/g.end_date、g.stock_pool、g.max_positions、g.rebalance_days 等;预定义 g.buy_signals/g.sell_signals 防空矩阵 |
| 预计算 | after_init(C) | 一次性拉全区间行情+财务 → 算因子 → IPO/ST/停牌过滤 → 截面排名 → shift(1) 生成 T+1 信号 |
| 执行 | handlebar(C) | 每 g.rebalance_days 个交易日调仓:先卖后买,开盘价成交 |
| 交易 | execute_sell/buy_signals | 涨停不买、跌停不卖;科创板 200 股、其余 100 股整数倍 |
| 辅助 | get_ipo_mask / get_st_mask / get_financial_wide_table | 上市满 120 天、ST 区间、财务字段宽表 |
df_rank = df_factor_filtered.rank(axis=1, ascending=g.rank_ascending)
df_is_top_n = df_rank <= g.max_positions
g.buy_signals = df_is_top_n.shift(1).fillna(False) # T 日因子 → T+1 日买入
g.sell_signals = ~g.buy_signals
禁止去掉 .shift(1),除非用户明确要求当日收盘调仓且接受前视偏差。
用户可能提供:文字描述、研报 PDF、截图、已有因子公式。提取并输出 策略规格表(生成前给用户确认):
## 策略规格(待确认)
| 项 | 内容 |
|----|------|
| 策略名称 | |
| 因子公式 | 逐行写明计算步骤 |
| 所需行情字段 | open/high/low/close/volume/... |
| 所需财务字段 | 如 CAPITALSTRUCTURE.free_float_capital |
| 因子窗口 | std_period / factor_period 等 |
| 排序方向 | ascending=True(值越小越好)或 False |
| 中性化 | 市值 OLS / 申万行业 Z-score / 无 |
| 股票池 | 如 中证1000、沪深300、全 A |
| 持仓数 | max_positions |
| 调仓频率 | rebalance_days(交易日) |
| 回测区间 | start_date ~ end_date |
| 初始资金 | initial_capital |
研报/PDF 解读要点:
截图解读要点:
scripts/daily-factors-backtest.py 全文作模板strategies/<策略名>-backtest/backtest.py必改清单:
| 位置 | 改什么 |
|------|--------|
| 文件头 docstring | 策略名、研报来源、因子逻辑、参数说明 |
| logger 名称 | 与策略一致,便于日志过滤 |
| factor_xxx() | 新因子计算;函数名与 g.factor_name 对应 |
| init() | 回测区间、股票池、资金、因子参数、rank_ascending |
| after_init() | 数据字段获取、调用新因子函数;中性化步骤按研报增删 |
| init 日志文案 | 策略名称与参数摘要 |
通常不改: handlebar、execute_*、get_ipo_mask、get_st_mask、涨跌停判断、get_df_ex。
模式 A — 单因子 Top-N(母版默认)
def factor_xxx(daily_open, daily_high, daily_low, daily_close, daily_market_cap,
stock_industry_map=None, **kwargs):
# 1. 原始特征
# 2. 滚动统计
# 3. 去极值 → 市值中性 → 行业中性(可选)
# 4. 截面 Z-score(单因子可跳过第 4 步)
return factor_df
模式 B — 多子因子合成
每个子因子独立走 MAD + 中性化,最后 zscore(A) + zscore(B) 或加权求和。
模式 C — 无需中性化
跳过 neutralize_by_*,仅 filter_extreme_mad_df + cross_section_zscore。
模式 D — 需额外财务因子
在 after_init 用 get_financial_wide_table(C, g.stock_pool, 'TABLE.field', ...) 拉宽表,传入 factor_xxx。
常用财务字段示例:
CAPITALSTRUCTURE.free_float_capital — 自由流通股本(母版用于市值)PERSHAREINDEX.eps — 每股收益ASHAREINCOME.net_profit_incl_min_int_inc — 净利润# coding:gbkinit 中预定义 g.buy_signals / g.sell_signals 空 DataFrameafter_init 行情为空时 return,不抛未捕获异常.shift(1)g.start_date 与 g.backtest_start_time 区间一致C.get_stock_list_in_sector(...) 名称在 QMT 中存在daily_close 对齐(index=日期, columns=股票代码)rank_ascending 与研报「因子越大越好/越小越好」一致生成脚本后,必须提醒用户在 QMT 中核对以下配置(Agent 不代替用户在 QMT GUI 操作):
init() 参数| 参数 | 格式 | 说明 |
|------|------|------|
| g.start_date / g.end_date | 'YYYYMMDD' | after_init 拉行情/财务的起止 |
| g.backtest_start_time / g.backtest_end_time | 'YYYY-MM-DD HH:MM:SS' | 与上面区间一致 |
| g.stock_pool | 板块名或代码列表 | C.get_stock_list_in_sector("中证1000") |
| g.initial_capital | 整数 | 初始资金 |
| g.max_positions | 整数 | 持仓只数 = Top N |
| g.cash_usage_ratio | 0~1 | 调仓日可用资金比例,默认 0.95 |
| g.rebalance_days | 整数 | 每 N 个交易日调仓一次 |
| g.accid | 'test' | 回测账号,保持 test |
用户需在 QMT 模型交易 / 策略研究 中手动设置:
g.backtest_* 一致g.initial_capital 一致dividend_type='front_ratio'(前复权),面板需一致| 用户说法 | QMT sector 名 |
|----------|---------------|
| 中证1000 | "中证1000" |
| 沪深300 | "沪深300" |
| 中证500 | "中证500" |
| 全 A | "沪深A股" |
| 创业板 | "创业板" |
| 科创板 | "科创板" |
| 申万一级行业 | get_sector_list('申万一级行业板块') 下各行业 |
板块名因 QMT 版本可能略有差异;若 get_stock_list_in_sector 失败,提示用户在本机 QMT 板块列表中确认准确名称。
after_init 越慢(中证1000 约 1000 只,属正常)QMT 内置回测 不在 conda 命令行运行,流程如下:
.py 复制到 QMT 策略目录,或在策略编辑器新建策略粘贴代码[数据检查]、[因子] 步骤统计、【最新调仓建议】若用户需要在项目内留存:
strategies/<name>-backtest/
└── backtest.py # 生成的策略文件
策略生成前:
> 请确认策略规格表中的:股票池、回测区间、持仓数、调仓频率、因子方向。
> 若有研报未写明的参数(如 MAD 倍数、中性化顺序),我将按母版默认处理并标注。
交付脚本后:
> 脚本已生成。请在 QMT 中:
> 1. 核对回测起止日期与脚本 init() 一致
> 2. 确认股票池板块名在本机 QMT 可用
> 3. 下载对应区间的日线与财务数据
> 4. 设置手续费/滑点(研报有要求请按研报)
> 5. 编译运行回测
>
> 默认 T 日收盘算因子、T+1 日开盘调仓。如需改调仓逻辑请说明。
母版 factor_ubl 实现的是东吴证券上下影线因子:
蜡烛上影线 = High - max(Open, Close)
威廉下影线 = Close - Low
→ 标准化 → 20日 std/mean → MAD去极值 → 市值OLS中性 → 申万行业Z-score → 截面Z-score → 相加
→ 值越小越好 → Top 10 → 每5日调仓
替换其他因子时,保持相同「宽表进、宽表出」接口,其余流水线按研报裁剪。
# coding:gbkinit 中对信号变量的预定义shift(1) 或等价滞后)用户需求: 复现 20 日动量因子,沪深300成分,Top 20,每月调仓。
Agent 动作:
factor_momentum(daily_close, lookback=20):daily_close / daily_close.shift(20) - 1g.rank_ascending = False(动量越大越好)g.stock_pool = C.get_stock_list_in_sector("沪深300")g.max_positions = 20,g.rebalance_days = 20(约月度)Comprehensive document creation, editing, and analysis with support for tracked changes, comments, formatting preservation, and text extraction. When Claude needs to work with professional documents (.docx files) for: (1) Creating new documents, (2) Modifying or editing content, (3) Working with tracked changes, (4) Adding comments, or any other document tasks
Comprehensive PDF manipulation toolkit for extracting text and tables, creating new PDFs, merging/splitting documents, and handling forms. When Claude needs to fill in a PDF form or programmatically process, generate, or analyze PDF documents at scale.
Presentation creation, editing, and analysis. When Claude needs to work with presentations (.pptx files) for: (1) Creating new presentations, (2) Modifying or editing content, (3) Working with layouts, (4) Adding comments or speaker notes, or any other presentation tasks
Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.
Use this skill whenever the user wants to do anything with PDF files. This includes reading or extracting text/tables from PDFs, combining or merging multiple PDFs into one, splitting PDFs apart, rotating pages, adding watermarks, creating new PDFs, filling PDF forms, encrypting/decrypting PDFs, extracting images, and OCR on scanned PDFs to make them searchable. If the user mentions a .pdf file or asks to produce one, use this skill.
Use this skill whenever the user wants to create, read, edit, or manipulate Word documents (.docx files). Triggers include: any mention of 'Word doc', 'word document', '.docx', or requests to produce professional documents with formatting like tables of contents, headings, page numbers, or letterheads. Also use when extracting or reorganizing content from .docx files, inserting or replacing images in documents, performing find-and-replace in Word files, working with tracked changes or comments, or converting content into a polished Word document. If the user asks for a 'report', 'memo', 'letter', 'template', or similar deliverable as a Word or .docx file, use this skill. Do NOT use for PDFs, spreadsheets, Google Docs, or general coding tasks unrelated to document generation.
Use this skill any time a .pptx file is involved in any way — as input, output, or both. This includes: creating slide decks, pitch decks, or presentations; reading, parsing, or extracting text from any .pptx file (even if the extracted content will be used elsewhere, like in an email or summary); editing, modifying, or updating existing presentations; combining or splitting slide files; working with templates, layouts, speaker notes, or comments. Trigger whenever the user mentions \"deck,\" \"slides,\" \"presentation,\" or references a .pptx filename, regardless of what they plan to do with the content afterward. If a .pptx file needs to be opened, created, or touched, use this skill.
Create and edit Obsidian Flavored Markdown with wikilinks, embeds, callouts, properties, and other Obsidian-specific syntax. Use when working with .md files in Obsidian, or when the user mentions wikilinks, callouts, frontmatter, tags, embeds, or Obsidian notes.
Take dfkai/qmt-inner-backtest from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.