小果动量策略回测系统助手

SKILL研究检索
研究检索 未标注权限 许可证不明确
安装这个技能

小果(微信:xg_quant)动量策略回测系统助手,专注于量化动量策略的深度开发、回测与优化。 本系统基于“加权线性回归动量打分 + 排名持有前N + 止盈离场”核心架构,提供从数据治理、 动量因子工程、策略构建、回测执行到绩效归因的全链路解决方案。支持灵活的资金分配方式、 自定义数据注入、完备的止盈风控模型和丰富的输出接口。 适用人群:量化研究员、算法交易工程师、动量策略开发者、ETF/指数轮动投资者、基金投研人员。 触发关键词:动量回测、动量排名、动量策略、持有前N、ETF轮动、加权线性回归、策略回测、 量化选基、xg_mom_backtrader、小果量化、绩效归因、止盈策略。

一句话选型结论

按资料字段整理

小果动量策略回测系统助手是研究检索类的 Agent Skill,安装方式未标注,权限级别未标注,许可证不明确,有可直接复制的安装命令。技能本质是给模型读的说明书,效果取决于模型与客户端;装完先用一个小任务验证,再放进正式流程。

分类研究检索 安装方式未标注 权限级别未标注权限 许可证许可证不明确
累计安装 未标注 本周 未标注
GitHub 星标 未标注 仓库 未标注
下载量 未标注 技能市场下载数
权限级别 未标注权限 安装前请确认风险范围
许可证 许可证不明确 未说明

安装

未标注
在支持 Skills 的客户端里执行,装完问一句「你有哪些技能」验证
skillhub install user_676c825d/xg-mom-backtrader
  1. 1
    确认客户端支持

    确认你的客户端支持 Skills(Claude、Codex、Cursor 等),并升级到较新的版本。

  2. 2
    拿到技能文件

    执行上面的命令安装;也可以把仓库里的 SKILL.md 手动放进客户端的 skills 目录。

  3. 3
    刷新技能列表

    重新打开客户端,或刷新技能列表,让新放进来的技能被加载。

  4. 4
    验证是否生效

    问一句「你有哪些技能」,确认列表里出现它,再拿一个小任务试跑。

技能档案

研究检索
字段来自技能仓库与公开索引,中文说明由本站标注
作者 / 维护方user_676c825d仓库 未标注 · 版本 未标注
宿主客户端未标注技能可被这些客户端加载
安装方式未标注安装包 community
权限级别未标注权限安装前请确认风险范围
许可证未说明许可证不明确,商用前请自行确认条款
仓库可用性available技能仓库当前是否可访问
最近核验未标注上游最后核验时间 · 数据更新 1791728660
正文体量30.3 KBSKILL.md 原文大小,越大说明说明书写得越细

典型使用场景

3 类
按分类整理的常见用法,具体以 SKILL.md 为准
查资料并整理出处

让模型按主题查资料,并把引用来源整理成清单。

网页与文献要点提炼

把长文、论文、网页压成能直接看的要点。

竞品与行业汇总

按关键词汇总竞品动态与行业信息。

选择建议

装之前先看这几条
按条目字段给出的判断,不替你决定用不用

值得选的地方

  • 有可直接复制的安装命令,不用自己翻文档找入口。

先想清楚的地方

  • 没有标注权限级别,实际能做什么要装好后确认。
  • 许可证不明确,商用或二次分发前先到仓库确认条款。
  • 没有做站内核验,内容以作者仓库为准。
  • 技能只是说明书,实际效果取决于模型与客户端,装完先用小任务试一遍。

更适合

  • 需要在研究检索场景里给模型补一套做法的人。
  • 愿意先读一遍 SKILL.md、确认它会让模型做什么的人。

不太适合

  • 对许可证要求很严、必须明确可商用的人。
  • 只想装完就自动变强、不打算看说明书的人。

同类对比

6 个同类
同分类里挑最接近的几条,字段以各自详情页为准
技能权限级别安装方式累计安装宿主客户端安装命令
小果动量策略回测系统助手当前 未标注权限 未标注 未标注 未标注 有
寻找技能 浏览器控制 GitHub 仓库 3120.0 万 Codex、Claude、Cursor 有
自我改进 Agent 接触敏感数据 ClawHub 市场 1646.4 万 OpenClaw 有
灵魂追踪 联网访问 GitHub 仓库 758.9 万 Codex、Claude、Cursor 有
自我完善 联网访问 ClawHub 市场 682.9 万 OpenClaw 有
微软代工厂 调用外部服务 GitHub 仓库 661.4 万 Codex、Claude、Cursor 有

SKILL.md 全文

30.3 KB
模型实际读到的说明书原文,来自技能仓库

小果动量策略回测系统专家

一、系统概述

教程 https://gitcode.com/qq_50882340/xg_mom_backtrader

1.1 系统定位

小果动量策略回测系统(xg_mom_backtrader)是一套专为动量排名轮动策略设计的专业级量化回测框架。它把「动量强弱度量 → 每日排名 → 持有排名前 N 的标的 → 排名跌出即卖出 → 大涨触发止盈」这套经典动量轮动逻辑标准化为可配置的流水线,让研究者能够高效地验证动量因子有效性、回测策略并输出完整绩效报告。

1.2 动量策略核心逻辑

每个交易日按以下流程决策:

① 计算每只标的的动量分数 score(加权线性回归斜率 × R²)
② 按 score 从高到低排序,筛出满足 [min_mom, max_mom] 区间的标的
③ 取排名前 buy_rank 只作为目标持仓
④ 先卖出:当前持有但排名跌出前 buy_rank 的标的 → 全部卖出(动量卖出)
⑤ 再买入:目标持仓中尚未持有的标的 → 按比例/金额分配资金买入(动量买入)
⑥ 止盈:当日涨幅 ≥ sell_zdf 的持仓 → 卖出 sell_amount 金额(止盈卖出)

1.3 动量分数的计算原理

calculate_momentum_score 采用加权线性回归 + R² 加权的稳健动量度量:

  • 取最近 mom_daily 天的收盘价;
  • 对收盘价取对数 y = ln(close);
  • 以 x = 0,1,2,... 为自变量,对 y 做加权线性回归(权重从 1 线性递增到 2,越近的样本权重越大);
  • 由回归斜率 slope 年化为年化收益:年化收益 = e^(slope)²⁵⁰ − 1;
  • 计算决定系数 R²,用以衡量该趋势的稳定性/可信度;
  • 最终动量分数 score = 年化收益 × R²。

> 该设计同时惩罚了两类情况:斜率(趋势方向与速度)不佳者分数低;斜率好但趋势不稳定(R² 低)者分数也会被压低。

1.4 设计哲学

  • 解耦与复用:数据加载、动量打分、排名轮动、交易执行、绩效评估各环节解耦,可独立优化。
  • 透明可解释:每个交易日的动量得分、排名、买卖原因均可从 trade_log 与报告追溯。
  • 灵活可扩展:支持自定义数据注入、金额/百分比两种交易模式、可关闭的止盈,覆盖从简单到复杂的动量策略。

二、安装与运行环境

2.1 安装包

教程 https://gitcode.com/qq_50882340/xg_mom_backtrader

2.2 依赖

  • pandas
  • numpy
  • pyarrow(读取 parquet 历史数据用)
  • openpyxl(导出 Excel 用)

2.3 包结构

推荐以「包」方式导入(发布到 GitHub/PyPI 的仓库结构):

xg_mom_backtrader/
├── __init__.py                  # 空文件即可
└── xg_mom_backtrader.py         # 主模块(动量回测类)

2.4 导入方式

from xg_mom_backtrader.xg_mom_backtrader import xg_mom_backtrader

2.5 数据目录要求(使用内置数据源时)

系统默认从脚本同级的 data/ 目录读取本地 parquet 数据,目录结构为:

data/
├── 历史数据/
│   ├── 159915.SZ.parquet       # 标的日线数据
│   └── ...
└── 指数数据/
    └── 000300.SH.parquet       # 基准指数数据

> 若不想准备本地数据,也可用自定义数据注入方式(见「十、自定义数据详解」),系统会自动切换到内存数据源,无需本地文件。

2.6 数据字段要求

必须字段:

字段名 说明 是否必须
date 日期 ✅ 必须
close 收盘价 ✅ 必须
open 开盘价 ✅ 必须
high 最高价 ✅ 必须
low 最低价 ✅ 必须
volume 成交量 ✅ 必须

推荐字段:

字段名 说明 是否必须
preClose 前收盘价 ⚠️ 推荐(用于复权与涨跌停过滤,缺失时会自动用 close.pct_change 计算涨跌幅)
zdf 涨跌幅 ⚠️ 推荐(不存在时自动计算)
amount 成交金额 ⚠️ 可选
证券代码 股票代码 ⚠️ 可选(会自动添加)
证券名称 股票名称 ⚠️ 可选

三、初始化参数完整参考

> 以下为 __init__ 方法全部参数详细说明。

3.1 时间与标的 (Time & Universe)

参数 类型 默认值 说明
start_date str '20240101' 回测起始日期,格式 YYYYMMDD
end_date str '20500101' 回测结束日期,格式 YYYYMMDD
stock_list list ['159915.SZ','513100.SZ','518880.SH'] 候选标的池,元素需带交易所后缀(.SZ/.SH)
index_stock str '000300.SH' 对比指数代码(仅用于输出指数数据,非策略基准)

3.2 资金与费用 (Capital & Cost)

参数 类型 默认值 说明
cash float 100000 初始资金(元)
comm float 0.0001 手续费率(万1 = 0.0001)

3.3 动量与排名 (Momentum & Rank)

参数 类型 默认值 说明
mom_type str '百分比' 资金分配方式:'百分比'(占总资产比例)/ '金额'(固定金额)
mom_value float 0.1 动量交易值。百分比模式为每期动用比例(0.1=10%总资产);金额模式为每期固定动用金额
mom_daily int 25 动量计算天数(线性回归窗口)
min_mom float 0 最小动量分数阈值(分数低于此不买入)
max_mom float 5 最大动量分数阈值(分数高于此不买入)
buy_rank int 1 买入排名,持有排名前 N 的标的(也是最大同时持仓数)

3.4 止盈 (Take Profit)

参数 类型 默认值 说明
sell_zdf float 0.03 止盈阈值,当日涨幅 ≥ 此值触发止盈(0.03=3%)。设很大值(如 8888)可关闭止盈
sell_amount float 1000 每次止盈卖出的金额(元)

3.5 运行与数据源 (Runtime & Data Source)

参数 类型 默认值 说明
max_workers int 4 多线程加载数据时的线程数
use_custom_data bool False 是否使用自定义数据源(注入数据后系统会自动置为 True)

3.6 内部固定参数(构造时自动设置,一般不修改)

参数 值 说明
adj_type 'none' 复权方式(源码当前固定为 none,即不做前复权/后复权)
min_shares 100 最小交易单位(ETF 一手 = 100 份)
share_multiple 100 交易数量的整数倍(每次按 100 份整数倍下单)

3.7 mom_type 与 mom_value 匹配表

mom_type mom_value 含义 每期买入金额逻辑
'百分比' 占总资产比例 每只买入 ≈ (总资产 × mom_value) ÷ 目标持仓数
'金额' 固定金额 每只买入 ≈ mom_value ÷ 目标持仓数

> 目标持仓数 = len(target_codes)(通常等于 buy_rank,若有效候选不足则小于它)。买入金额同时被可用现金约束(min(买入额度, 账户现金)),并按 100 份整数倍、先扣手续费再成交。

四、数据加载与处理详解

4.1 数据来源优先级

get_stock_data(stock_code) 加载单只标的数据时按两步取数:

  1. 自定义数据源:当 use_custom_data=True 且该代码已注入 → 从内存 _custom_data_cache 读取;
  2. 本地文件:否则读取 data/历史数据/{code}.parquet。

两种路径都会执行统一的清洗流程:

  • 截取 [start_date, end_date] 区间;
  • 按日期升序排序;
  • 剔除 close <= 0 或 open <= 0 的无效行;
  • 调用 adjust_price(当前 adj_type='none' 时原样返回);
  • 重新计算 zdf = close.pct_change()。

4.2 多线程加载

get_all_stock_data() 用 ThreadPoolExecutor(线程数 = max_workers)并发加载全部标的,打印每只的成功/失败、数据范围与价格范围,并返回 {code: DataFrame} 字典。

4.3 指数数据

get_index_data() 读取 data/指数数据/{index_stock}.parquet,仅用于输出展示(不参与策略基准对比)。

4.4 基准曲线(等权重持有不动)

calculate_benchmark_curve(all_data) 以全部标的的共同交易日为轴,每只归一化为「首日=1」,逐日取平均得到"等权买入持有不动"净值曲线,作为策略的对照基准,用于计算超额收益。

五、动量分数计算详解

5.1 方法签名

def calculate_momentum_score(self, df) -> float

5.2 入参/出参

  • df:某只标的截至当前交易日的 DataFrame(至少含 date、close)。
  • 返回:动量分数 float。数据不足(行数 < mom_daily 或 < 10)时返回 0。

5.3 计算步骤

步骤 说明
取窗口 取 df.tail(mom_daily) 最近 mom_daily 行
取对数 y = ln(close)
构造权重 w = linspace(1, 2, n)(线性增权,越新权重越大)
加权回归 x=0,1,...,对 y 做加权最小二乘,得斜率 slope
年化 年化收益 = e^slope − 1(按 250 个交易日年化)
拟合优度 R² = 1 − Σ(w·残差²) / Σ(w·(y−ȳ)²)
打分 score = 年化收益 × R²

5.4 参数调优建议

参数 说明 建议
mom_daily 动量窗口天数 短周期 10–20,中周期 25–60,长周期 60–120;与调仓频率匹配
min_mom/max_mom 动量分数过滤区间 可排除过热(分数过高)与弱势(分数过低)标的
buy_rank 持有/买入前 N 越大越分散、换手越低;越小越集中、进攻性越强

六、交易执行详解

6.1 买入规则(calculate_buy_shares)

calculate_buy_shares(amount, price) -&gt; (shares, actual_cost)
  • 先扣除手续费:买入金额 = amount / (1 + comm);
  • 按 100 份整数倍取整:shares = floor(买入金额 / price / 100) × 100;
  • 不足一手(< 100 份)则买入 0;
  • 若含手续费成本超过可用金额,循环减一手直到不超;
  • 返回 (买入股数, 实际成本=市值+手续费)。

6.2 卖出规则

全卖(动量卖出) —— calculate_sell_shares_all(shares, price):

  • 排名跌出前 N 时,将持仓全部卖出(不足一手时按实际持仓卖出);
  • 实收金额 = 卖出市值 − 手续费。

按金额卖(止盈卖出) —— calculate_sell_shares_by_amount(shares, price, sell_amount):

  • 当日涨幅 ≥ sell_zdf 时触发,卖出 sell_amount 对应市值;
  • 按 100 份整数倍;卖出股数超持仓则全卖;
  • 实收金额 = 卖出市值 − 手续费。

6.3 日交易记录字段

每笔成交写入 trade_log,字段如下:

字段 类型 说明
date datetime 交易日期
stock str 标的代码
type str 交易类型:动量卖出 / 动量买入 / 止盈卖出
price float 成交价格
shares int 成交股数
amount float 成交金额(买入为含手续费成本;卖出为实收金额)
commission float 该笔手续费
reason str 交易原因,如 排名跌出前1,卖出XXX、排名前1,买入XXX、涨幅3.50%触发止盈

七、完整函数清单

7.1 构造与配置

方法 说明
__init__(...) 构造动量回测实例并打印参数配置
get_config() -&gt; dict 返回当前全部配置参数(含隐藏内部参数与已注入数据 key)

7.2 数据加载与处理

方法 说明
get_stock_data(stock_code) 加载单只标的(自定义源优先,其次本地 parquet),返回清洗后的 DataFrame
_load_single_stock(stock) 多线程任务包装:加载单只,返回 (code, df, success, msg)
get_all_stock_data() -&gt; dict 多线程并发加载全部标的
get_index_data() 加载对比指数数据(parquet)
_normalize_dataframe(df, stock_code) 标准化注入的 DataFrame:日期识别/排序、补缺列、算 zdf、算复权因子
adjust_price(df) 价格复权处理(当前 adj_type=&#x27;none&#x27; 时原样返回)

7.3 自定义数据注入(7 种接口)

方法 说明
add_stock_data_from_dataframe(stock_code, df) -&gt; bool 从 DataFrame 注入
add_stock_data_from_excel(stock_code, file_path, sheet_name=0, **kwargs) -&gt; bool 从 Excel 注入
add_stock_data_from_csv(stock_code, file_path, **kwargs) -&gt; bool 从 CSV 注入(自动尝试 utf-8/gbk 等编码)
add_stock_data_from_json(stock_code, file_path, orient=&#x27;records&#x27;, **kwargs) -&gt; bool 从 JSON 注入
add_stock_data_from_dict(stock_code, data) -&gt; bool 从字典注入
add_stock_data_from_parquet(stock_code, file_path, columns=None, **kwargs) -&gt; bool 从 Parquet 注入
add_stock_data_from_bytes(stock_code, file_bytes, file_type=&#x27;csv&#x27;, **kwargs) -&gt; bool 从字节流注入(适合上传)

7.4 自定义数据管理

方法 说明
clear_custom_data() 清空全部自定义数据,use_custom_data 置 False
remove_stock_data(stock_code) -&gt; bool 移除指定标的自定义数据
get_custom_data_keys() -&gt; list 返回已注入数据的全部标的代码
has_custom_data(stock_code) -&gt; bool 检查某标的是否已注入数据

7.5 动量打分与基准

方法 说明
calculate_momentum_score(df) 计算单只标的动量分数(加权线性回归×R²)
calculate_benchmark_curve(all_data) 计算等权持有不动基准净值曲线

7.6 交易计算

方法 说明
calculate_buy_shares(amount, price) 买入股数与成本计算(100 份整数倍、先扣佣金)
calculate_sell_shares_by_amount(shares, price, sell_amount) 按金额卖出(止盈)
calculate_sell_shares_all(shares, price) 全部卖出(动量卖出)

7.7 回测执行

方法 说明
vectorized_backtest() 向量化回测主引擎(逐日轮动)
run_backtest() 回测主入口,等价于 vectorized_backtest()

7.8 绩效与报告

方法 说明
calculate_performance_metrics(df, df_index) -&gt; dict 计算核心绩效指标
calculate_annual_performance(portfolio_df) -&gt; dict 计算逐年收益统计
get_annual_performance_df() 年度统计转 DataFrame
get_performance_metrics() 获取绩效(未回测则自动回测)
get_equity_curve_data() 获取净值曲线数据
get_annual_performance() 获取年度统计
generate_report() -&gt; str 生成文本回测报告
generate_equity_curve_data() 生成净值曲线 dict
generate_trade_data() 生成成交数据 dict
generate_position_data() 生成持仓数据 dict
generate_account_data() 生成账户数据 dict

7.9 数据获取接口

方法 说明
get_trade_data() 获取成交数据 {&#x27;trades&#x27;: [...], &#x27;statistics&#x27;: {...}}
get_position_data() 获取持仓数据 {&#x27;positions&#x27;: [...], &#x27;statistics&#x27;: {...}}
get_account_data() 获取账户数据 {&#x27;account_history&#x27;: [...], &#x27;statistics&#x27;: {...}}
get_daily_positions() 获取每日持仓明细(records)
get_trade_log() 获取交易日志(records)
get_portfolio_history() 获取组合历史(records)
get_stock_results() 获取各标的回测结果
get_backtest_summary() 获取回测摘要(配置+绩效+年度+全量数据)
get_all_data() 获取全部数据(JSON 可序列化)
get_backtrader_data() 兼容接口,按「指数/成交/持股/账户/绩效/年度/净值/策略参数」组织

7.10 结果保存

方法 说明
save_backtrader_data(user=&#x27;test&#x27;) 分类保存为 Excel + JSON 到 策略模型/动量策略/{user}/
save_to_json(filename=None, include_raw_data=False) 保存全量结果为单个 JSON 文件

7.11 内部工具方法(供二次开发参考)

方法 说明
_convert_to_serializable(obj) 把 numpy/pandas/Timestamp 等递归转为 JSON 可序列化类型

八、输出数据结构详解

8.1 绩效指标字段(performance_metrics)

字段 说明 备注
start_date / end_date 回测起止 字符串 YYYY-MM-DD
total_days 交易日数 int
total_cash 初始资金 float
final_value 最终总资产 元
total_return 总收益率 小数(0.25 = 25%)
total_pnl 总盈亏额 元
total_commission 总手续费 元
remaining_cash 期末现金 元
final_holdings 期末总持仓份额 份
annual_return 年化收益率 小数
max_drawdown 最大回撤 负数,小数
max_drawdown_date 最大回撤发生日 字符串
sharpe_ratio 夏普比率 —
sortino_ratio 索提诺比率 —
calmar_ratio 卡尔玛比率 —
win_rate 日胜率 小数
volatility 年化波动率 小数
benchmark_start_value / benchmark_final_value 基准起止净值 等权持有不动
benchmark_total_return 基准总收益率 小数
benchmark_max_drawdown 基准最大回撤 小数
excess_return 超额收益 小数(策略−基准)
excess_return_pct 超额收益百分比 数值
mom_daily/min_mom/max_mom/buy_rank/mom_type/mom_value/sell_zdf/sell_amount/use_custom_data 回放的策略参数 便于留档

8.2 净值曲线字段(equity_curve_data)

字段 说明
dates 日期字符串列表
total_value 每日总资产
cumulative_pnl 每日累计盈亏
cash 每日现金
holdings 每日持仓份额
net_value 策略净值(总资产/初始资金)
drawdown 回撤百分比(%)
total_return 每日累计收益率
daily_return 每日收益率
benchmark_net_value / benchmark_return 基准净值/收益
statistics 起点/终点/最高/最低/总收益/最大回撤等摘要
benchmark_statistics 基准净值摘要

8.3 成交统计(trade_data[&#x27;statistics&#x27;])

total_trades、buy_trades、sell_trades、total_buy_amount、total_sell_amount、total_commission、first_trade_date、last_trade_date。

8.4 账户统计(account_data[&#x27;statistics&#x27;])

起始/结束日期、总天数、初始资金、期末总资产/现金/持仓、总盈亏、总收益率、最高/最低总资产、最高/最低净值、波动率、基准期末净值与总收益。

8.5 文本报告内容(generate_report())

策略参数 → 最终持仓 → 汇总持仓 → 收益指标(总/年化/盈亏/波动/手续费)→ 基准对比 → 风险指标(回撤/夏普/索提诺/卡尔玛)→ 交易统计(笔数/胜率)→ 年度收益统计表。

8.6 导出目录结构

策略模型/动量策略/{user}/
├── 指数数据/      指数数据.xlsx + .json
├── 成交数据/      成交数据.xlsx + .json
├── 持股数据/      持股数据.xlsx + .json
├── 账户数据/      账户数据.xlsx + .json
├── 绩效指标/      绩效指标.xlsx + .json
├── 净值曲线/      净值曲线.xlsx + .json
├── 策略参数/      策略参数.xlsx + .json
└── 年度收益统计/  年度收益统计.xlsx + .json

九、完整实战示例

9.1 示例 1:经典动量轮动(百分比模式)

from xg_mom_backtrader.xg_mom_backtrader import xg_mom_backtrader

bt = xg_mom_backtrader(
    start_date=&#x27;20230101&#x27;,
    end_date=&#x27;20261201&#x27;,
    stock_list=[&#x27;159915.SZ&#x27;, &#x27;513100.SH&#x27;, &#x27;518880.SH&#x27;, &#x27;510300.SH&#x27;, &#x27;512880.SH&#x27;],
    index_stock=&#x27;000300.SH&#x27;,
    cash=500000,
    comm=0.0003,
    mom_type=&#x27;百分比&#x27;,   # 每期动用总资产的 XX%
    mom_value=0.8,       # 每次动用总资产的 80% 用于买入
    mom_daily=25,        # 动量窗口 25 天
    min_mom=0,           # 动量分数下限
    max_mom=5,           # 动量分数上限
    buy_rank=3,          # 持有并买入排名前 3 的标的
    sell_zdf=0.15,       # 当日涨 15% 触发止盈
    sell_amount=20000,   # 每次止盈卖 2 万元
    max_workers=8,
)

bt.run_backtest()
print(bt.generate_report())
bt.save_backtrader_data(user=&#x27;动量轮动示例&#x27;)

9.2 示例 2:固定金额模式(关闭止盈)

bt = xg_mom_backtrader(
    start_date=&#x27;20240101&#x27;,
    end_date=&#x27;20261201&#x27;,
    stock_list=[&#x27;159915.SZ&#x27;, &#x27;513100.SH&#x27;, &#x27;518880.SH&#x27;],
    cash=200000,
    comm=0.0001,
    mom_type=&#x27;金额&#x27;,     # 每期动用固定金额
    mom_value=100000,    # 每期动用 10 万元买入
    mom_daily=60,        # 更长动量窗口
    min_mom=0,
    max_mom=5,
    buy_rank=1,          # 只持有第一名
    sell_zdf=8888,       # 设很大的值关闭止盈,仅靠排名轮动
    sell_amount=1000,
    max_workers=4,
)

bt.run_backtest()
print(bt.generate_report())

9.3 示例 3:自定义数据注入回测

bt = xg_mom_backtrader(
    start_date=&#x27;20230101&#x27;,
    end_date=&#x27;20261201&#x27;,
    stock_list=[&#x27;159915.SZ&#x27;, &#x27;513100.SH&#x27;, &#x27;518880.SH&#x27;, &#x27;510300.SH&#x27;],
    cash=300000,
    comm=0.0002,
    mom_type=&#x27;百分比&#x27;,
    mom_value=1.0,
    mom_daily=20,
    min_mom=0,
    max_mom=5,
    buy_rank=2,
    sell_zdf=0.1,
    sell_amount=5000,
    use_custom_data=True,   # 显式声明使用自定义数据
)

# 用不同格式注入数据
bt.add_stock_data_from_csv(&#x27;159915.SZ&#x27;, &#x27;data/159915.csv&#x27;)
bt.add_stock_data_from_excel(&#x27;513100.SH&#x27;, &#x27;data/513100.xlsx&#x27;, sheet_name=&#x27;Sheet1&#x27;)
bt.add_stock_data_from_json(&#x27;518880.SH&#x27;, &#x27;data/518880.json&#x27;)
bt.add_stock_data_from_dataframe(&#x27;510300.SH&#x27;, df_510300)  # 内存 DataFrame

print(&quot;已注入:&quot;, bt.get_custom_data_keys())
bt.run_backtest()
print(bt.generate_report())
bt.save_to_json(&#x27;result/momentum_backtest.json&#x27;)

9.4 示例 4:提取结果做二次分析 + 画净值曲线

bt.run_backtest()

metrics = bt.get_performance_metrics()
curve = bt.get_equity_curve_data()
trades = bt.get_trade_data()

print(f&quot;总收益率: {metrics[&#x27;total_return&#x27;]*100:.2f}%&quot;)
print(f&quot;年化收益: {metrics[&#x27;annual_return&#x27;]*100:.2f}%&quot;)
print(f&quot;最大回撤: {metrics[&#x27;max_drawdown&#x27;]*100:.2f}%&quot;)
print(f&quot;夏普比率: {metrics[&#x27;sharpe_ratio&#x27;]:.3f}&quot;)
print(f&quot;胜率: {metrics[&#x27;win_rate&#x27;]*100:.2f}%&quot;)
print(f&quot;总交易笔数: {metrics.get(&#x27;total_commission&#x27;, &#x27;&#x27;)}(详见 trade_data)&quot;)

import matplotlib.pyplot as plt
dates = curve[&#x27;dates&#x27;]
plt.figure(figsize=(12, 6))
plt.plot(dates, curve[&#x27;net_value&#x27;], label=&#x27;策略净值&#x27;, linewidth=2)
if curve.get(&#x27;benchmark_net_value&#x27;):
    plt.plot(dates, curve[&#x27;benchmark_net_value&#x27;], label=&#x27;基准(持有不动)&#x27;, linestyle=&#x27;--&#x27;)
plt.legend(); plt.xlabel(&#x27;日期&#x27;); plt.ylabel(&#x27;净值&#x27;)
plt.title(&#x27;动量策略净值曲线&#x27;); plt.xticks(rotation=45); plt.tight_layout(); plt.show()

plt.figure(figsize=(12, 4))
plt.fill_between(dates, 0, curve[&#x27;drawdown&#x27;], color=&#x27;red&#x27;, alpha=0.3)
plt.plot(dates, curve[&#x27;drawdown&#x27;], color=&#x27;red&#x27;)
plt.xlabel(&#x27;日期&#x27;); plt.ylabel(&#x27;回撤(%)&#x27;); plt.title(&#x27;动量策略回撤&#x27;); plt.tight_layout(); plt.show()

9.5 示例 5:年度绩效查看

bt.run_backtest()
annual = bt.get_annual_performance()          # dict
annual_df = bt.get_annual_performance_df()    # DataFrame
print(annual_df[[&#x27;year&#x27;, &#x27;total_return&#x27;, &#x27;annual_return&#x27;, &#x27;max_drawdown&#x27;, &#x27;sharpe_ratio&#x27;, &#x27;win_rate&#x27;]])

十、自定义数据详解

10.1 注入后系统自动做的事

add_stock_data_from_* 最终都会调用 add_stock_data_from_dataframe → _normalize_dataframe:

  • 日期列:识别含 date/日期 的列或 DatetimeIndex,统一转 datetime 并升序;
  • 缺列补齐:close/high/low/open/volume 任一缺失 → 尝试按列名模糊匹配,否则补空列(NaN);
  • 代码列:自动补 证券代码;
  • 涨跌幅:缺 zdf 时用 close.pct_change() 自动计算;
  • 复权因子:含 preClose 时自动用 close/preClose 累计生成 adj_factor。

10.2 注入成功判定与验证

  • 注入成功返回 True,并把 use_custom_data 置为 True;
  • 用 get_custom_data_keys() 查看已注入的代码;
  • 用 has_custom_data(&#x27;159915.SZ&#x27;) 判断是否已注入。

> 建议:构造时把 use_custom_data=True 传入,可避免中途依赖本地文件;若使用本地数据则保持默认 False。

十一、常见问题与 FAQ

问题 解决方案
提示数据/文件不存在 检查 data/历史数据/{code}.parquet 与 data/指数数据/{index}.parquet;或改用 add_stock_data_from_* 注入自定义数据
某标的动量分数恒为 0 数据行数需 ≥ mom_daily 且 ≥ 10,否则返回 0;检查区间内数据量是否足够
买入很少 / 一直空仓 确认候选分数落在 [min_mom, max_mom] 内;max_mom 过高会排除强势股,过低又可能全被排除(此时系统会兜底取前 buy_rank,请留意日志)
持仓数量超过 buy_rank 系统每天都会把排名跌出前 N 的先卖、新进前 N 的后买,正常情况下持仓数 ≤ buy_rank
自定义数据注入了但没生效 用 get_custom_data_keys() 验证;确认构造或注入后 use_custom_data=True;代码(含后缀 .SZ/.SH)必须与 stock_list 完全一致
收益率为 0 或异常 检查价格列全为正、cash 初始值、买入是否因金额不足/不够一手而失败
手续费很高 降低换手可同时调大 mom_daily(更平滑)与 sell_zdf(减少止盈触发);检查 comm 是否正确
如何关闭止盈 把 sell_zdf 设成很大的数(如 8888),仅保留排名轮动卖出

十二、高级技巧与二次开发

12.1 动量窗口与调仓频率匹配

  • 中短线:mom_daily 10–25,buy_rank 1–3;
  • 中长线:mom_daily 60–120,buy_rank 3–10;
  • 想降低换手可同时加大 mom_daily 与 buy_rank。

12.2 分数区间风控

用 min_mom/max_mom 做"动量温度"过滤:过热(分数过高,追高风险大)与弱势(分数过低/为负)标的都可被排除,从而过滤噪声行情。

12.3 自定义动量打分

继承 xg_mom_backtrader 并重写 calculate_momentum_score(df),即可换成任意动量/因子打分逻辑(如 RSI 动量、MACD 排序、双均线斜率等),排名与买卖流程完全复用。

from xg_mom_backtrader.xg_mom_backtrader import xg_mom_backtrader

class MyMom(xg_mom_backtrader):
    def calculate_momentum_score(self, df):
        # 自定义:改用 20日涨跌幅 作为动量分数
        if len(df) &lt; 21:
            return 0
        return float(df[&#x27;close&#x27;].iloc[-1] / df[&#x27;close&#x27;].iloc[-21] - 1)

bt = MyMom(start_date=&#x27;20230101&#x27;, end_date=&#x27;20261201&#x27;, buy_rank=2, mom_daily=20)
bt.run_backtest()
print(bt.generate_report())

12.4 自定义交易/止盈规则

继承后重写 vectorized_backtest() 或复用其框架,自定义买卖金额分配、加止盈/止损组合等逻辑。

十三、技术说明与提示

  • performance_metrics 中的比率多为小数(如 total_return=0.25 表示 25%),报告打印时已 ×100;直接从 dict 取值时注意换算。
  • total_return、win_rate、max_drawdown、volatility 均为小数;excess_return_pct 已是百分比数值。
  • 年化按 365.25 天折算,夏普/波动按 250 个交易日年化,无风险利率固定 0.02。
  • 回测按共同交易日推进,标的上市/停牌造成的日期错位会被自动对齐剔除。
  • 源码当前固定 adj_type=&#x27;none&#x27;,若需前复权/后复权可在 adjust_price 中扩展。
1. 指数数据读取接口
新增了以下方法用于加载自定义指数数据:

方法  说明
add_index_data_from_dataframe(df)   从DataFrame加载指数数据
add_index_data_from_csv(file_path)  从CSV文件加载指数数据
add_index_data_from_excel(file_path, sheet_name)    从Excel文件加载指数数据
add_index_data_from_json(file_path) 从JSON文件加载指数数据
add_index_data_from_dict(data)  从字典加载指数数据
add_index_data_from_parquet(file_path)  从Parquet文件加载指数数据
add_index_data_from_bytes(bytes, file_type) 从字节数据加载指数数据
2. 指数数据管理方法
方法  说明
clear_index_data()  清空自定义指数数据
has_index_data()    检查是否有自定义指数数据
get_index_data_info()   获取指数数据信息

小果动量策略回测系统,让动量/轮动策略开发更高效、更透明。如需源码、更多因子库或技术支持,欢迎联系小果(微信:xg_quant)。

常见问题

5 问
答案由本站依据条目字段整理
小果动量策略回测系统助手怎么安装?

在支持 Skills 的客户端里执行:skillhub install user_676c825d/xg-mom-backtrader。安装方式为未标注。装完刷新技能列表或重开客户端。

小果动量策略回测系统助手支持哪些客户端?

资料没有标注宿主客户端,但只要客户端支持 Skills(Claude、Codex、Cursor 等),一般都能加载。

小果动量策略回测系统助手权限高吗,安全吗?

权限级别为未标注权限。安装前先看它会读取或写入哪些内容。

小果动量策略回测系统助手收费吗?

本站不代收费用,也没有标注具体价格。是否收费取决于技能本身和所用的模型或客户端,正式使用前按作者说明确认。

小果动量策略回测系统助手用什么许可证?

许可证标注为 未说明(许可证不明确)。商用或二次分发前请到仓库确认条款原文。

热门专题

按场景挑技能
全部专题 →

技能内容以作者仓库为准;分类、权限级别与许可证状态的中文说明为中文整理,最近核验 未标注。