小果网格策略回测系统助手

SKILL效率
效率 未标注权限 许可证不明确
安装这个技能

小果(微信:xg_quant)网格策略回测系统助手,专注于网格交易策略的深度开发、回测与优化。 本系统基于“初始建仓 + 价格网格买卖 + 做T止盈止损”核心架构,提供从数据治理、网格参数工程、 策略构建、回测执行到绩效归因的全链路解决方案。支持百分比/差值/ATR三种网格步长类型、 金额/百分比/数量三种下单类型、多标的独立网格参数配置、标的与指数双重自定义数据注入、 完备的做T风控规则和丰富的输出接口。 适用人群:量化研究员、网格交易策略开发者、ETF网格投资者、资管机构投研人员。 触发关键词:网格回测、网格策略、网格交易、高抛低吸、ATR网格、百分比网格、做T、止盈止损、 xg_gd_backtrader、小果量化、绩效归因、网格参数、多标的网格。

一句话选型结论

按资料字段整理

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

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

安装

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

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

  2. 2
    拿到技能文件

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

  3. 3
    刷新技能列表

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

  4. 4
    验证是否生效

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

技能档案

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

典型使用场景

3 类
按分类整理的常见用法,具体以 SKILL.md 为准
整理待办与日程

把零散任务收进清单,排出优先级。

批量处理重复任务

把固定动作做成模板,重复执行。

把流程写成清单

把口头流程整理成可复用的步骤。

选择建议

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

值得选的地方

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

先想清楚的地方

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

更适合

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

不太适合

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

同类对比

6 个同类
同分类里挑最接近的几条,字段以各自详情页为准
技能权限级别安装方式累计安装宿主客户端安装命令
小果网格策略回测系统助手当前 未标注权限 未标注 未标注 未标注 有
Nano PDF 文档 联网访问 ClawHub 市场 424.9 万 OpenClaw 有
自动更新程序 浏览器控制 ClawHub 市场 296.4 万 OpenClaw 有
Gemini 助手 联网访问 ClawHub 市场 254.7 万 OpenClaw 有
word DOCX 文档 联网访问 ClawHub 市场 239.6 万 OpenClaw 有
Excel XLSX 前端 联网访问 ClawHub 市场 227.0 万 OpenClaw 有

SKILL.md 全文

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

小果网格策略回测系统专家

一、系统概述

使用教程:https://gitcode.com/qq_50882340/xg_gd_backtrader

1.1 系统定位

小果网格策略回测系统(xg_gd_backtrader)是一套专为网格交易(Grid Trading)+ 做T增厚收益设计的专业级量化回测框架。它以「按比例初始建仓」建立底仓,随后「价格每触及一个网格档位就低买高卖」在震荡行情中反复收割价差,并叠加「当日大涨止盈卖出 / 当日大跌止损买入」的做T规则在盘中降低成本。它以每只标的独立网格参数逐日撮合,输出完整绩效。

与其它策略系统最大的不同在于:网格参数是按标的逐一下发的一组列表(gd_*_list 与 stock_list 一一对应),且支持百分比、差值、ATR 三种步长口径与金额、百分比、数量三种下单口径,可高度定制每只标的的网格形态。

1.2 核心策略逻辑(每个交易日)

系统按每只标的独立账户逐日决策,每标资金池 = 总资金 ÷ 标的数:

① 初始建仓:首个交易日按 init_position_ratio 比例 × 总资金 买入底仓(占总资金 X%)
② 网格卖出:当前价 ≥ 卖出触发价 sell_trigger 且该标的卖出步长已启用 → 卖出一档 gd_value 金额(高抛)
③ 网格买入:当前价 ≤ 买入触发价 buy_trigger 且该标的买入步长已启用 → 买入一档 gd_value 金额(低吸)
④ 做T止盈:当前价 ≥ 上次做T价 × (1 + sell_zdf) → 卖出 trade_value 金额(当日涨幅止盈)
⑤ 做T止损:当前价 ≤ 上次做T价 × (1 + buy_zdf) → 买入 trade_value 金额(当日跌幅吸筹)
⑥ 全部成交按 100 份整手、先扣手续费;随后记录现金/持仓/网格中枢/触发价/累计成本/浮盈亏
⑦ 组合级汇总:把各标的在共同交易日的现金、持仓、市值相加,叠加基准曲线输出净值

> 网格买卖与做T互不冲突:网格按「与中枢价相差一个步长」触发,做T按「与上次做T成交价相差止盈/止损阈值」触发;每笔触发后都把中枢价/上次做T价重置为当前成交价。

1.3 网格触发机制(关键概念)

概念 含义 说明
grid_price 网格中枢 最近一次网格成交价 每触发一笔买卖即重置为当前成交价
buy_trigger 买入触发价 grid_price − 买入步长 价格跌至此触发网格买入
sell_trigger 卖出触发价 grid_price + 卖出步长 价格涨至此触发网格卖出
步长类型 gd_bc_type 百分比 / 差值 / ATR 决定网格档位间距口径
下单类型 gd_type 金额 / 百分比 / 数量 决定每档买入/卖出的金额口径

> ⚠️ 参数符号约定(源码关键):gd_buy_bc_list 存的是卖出步长的正数(触发条件 ≥ 0,价格涨超卖出触发价就卖出);gd_sell_bc_list 存的是买入步长的负数(触发条件 < 0,价格跌破买入触发价就买入)。calculate_grid_step 内部:buy_step = abs(sell_bc)、sell_step = buy_bc。

1.4 三种步长类型对照

步长类型 档位间距口径 网格价格计算 适用
百分比 按价格比例 买=中枢×(1−步长)、卖=中枢×(1+步长) 价格波动剧烈、用比例定档
差值 按绝对价格差 买=中枢−步长、卖=中枢+步长 价格稳定、用固定价差定档
ATR 按 ATR 波动倍数 买=中枢−倍×ATR、卖=中枢+倍×ATR 波动率自适应、动态定档

1.5 设计哲学

  • 解耦与复用:数据加载、网格中枢、买卖触发、交易撮合、绩效评估各环节解耦,可独立替换。
  • 透明可解释:每日记录的 grid_price/buy_trigger/sell_trigger 与每笔 action(触发原因)可完整还原决策过程。
  • 灵活可扩展:逐标的网格参数列表、三种步长/下单口径、标的与指数双重自定义数据源、可继承重写做个性化网格。

二、安装与运行环境

2.1 安装包

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

2.2 依赖

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

2.3 包结构

推荐以「包」方式导入:

xg_gd_backtrader/
├── __init__.py                  # 空文件即可
└── xg_gd_backtrader.py          # 主模块(网格回测类)

2.4 导入方式

from xg_gd_backtrader.xg_gd_backtrader import xg_gd_backtrader

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

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

data/
├── 历史数据/
│   ├── 513100.SH.parquet       # 标的日线数据
│   └── ...
└── 指数数据/
    ├── 000300.SH.parquet       # 指数数据(parquet 优先)
    └── ...

> 若不想准备本地数据,可用自定义数据注入(标的 + 指数各自独立注入,见「十、自定义数据详解」),系统自动切换到内存数据源。

2.6 数据字段要求

必须字段:

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

推荐字段:

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

三、初始化参数完整参考

> 以下为 __init__ 方法全部参数详细说明。网格列表参数(gd_*_list)与 stock_list 逐一一对应。

3.1 时间与标的 (Time & Universe)

参数 类型 默认值 说明
start_date str '20250701' 回测起始日期,格式 YYYYMMDD
end_date str '20500101' 回测结束日期,格式 YYYYMMDD
stock_list list ['513100.SH','513500.SH'] 候选标的池,元素需带交易所后缀(.SZ/.SH)
index_stock str '000300.SH' 对比指数代码(仅用于输出指数数据;注入自定义指数后以注入数据为准)

3.2 资金与费用 (Capital & Cost)

参数 类型 默认值 说明
cash float 100000 初始总资金(元),回测中每只标的资金池 = cash ÷ 标的数
comm float 0.0001 手续费率(万1 = 0.0001),买卖双向收取

3.3 网格节奏与做T风控(全局配置)

参数 类型 默认值 说明
gd_interval int 1 网格检查间隔(交易日数),源码当前以日频为粒度,默认每个交易日都检查
sell_zdf float 0.03 做T止盈阈值:当前价 ≥ 上次做T价 ×(1+sell_zdf) 触发卖出 trade_value 金额(0.03=涨3%)
buy_zdf float -0.03 做T止损阈值:当前价 ≤ 上次做T价 ×(1+buy_zdf) 触发买入 trade_value 金额(-0.03=跌3%)
trade_value float 1000 做T单次交易金额(元):每次做T止盈/止损动用多少钱

3.4 网格列表参数(与 stock_list 一一对应)

> 下列 *_list 列表长度必须与 stock_list 完全一致,否则构造时 _validate_list_params() 会抛 ValueError。每个列表的第 i 个元素对应 stock_list[i]。

参数 类型 默认值 说明
gd_bc_type_list list[str] ['百分比','百分比'] 每只标的网格步长类型:'百分比' / '差值' / 'ATR'
gd_buy_bc_list list[float] [0.03,0.02] 每只标的卖出步长(正数,价格涨超该档触发卖出)
gd_sell_bc_list list[float] [-0.02,-0.015] 每只标的买入步长(负数,价格跌破该档触发买入)
gd_atr_ratio_list list[float] [2.0,2.0] 每只标的 ATR 倍数(gd_bc_type='ATR' 时生效)
gd_atr_period_list list[int] [14,14] 每只标的 ATR 周期(gd_bc_type='ATR' 时生效)
gd_type_list list[str] ['金额','金额'] 每只标的下单类型:'金额' / '百分比' / '数量'
gd_value_list list[float] [1000,1500] 每只标的下单值,含义随 gd_type 变化
init_position_ratio_list list[float] [0.1,0.15] 每只标的初始建仓比例(占总资金比例),和为 1 时满仓,超过 1 会告警

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

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

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

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

3.7 网格步长/下单类型匹配表

步长类型与网格价格:

gd_bc_type gd_buy_bc/gd_sell_bc 含义 网格触发价计算
'百分比' 价格比例(如卖 0.03=3%、买 -0.02=跌2%) 买=中枢×(1−abs(sell_bc))、卖=中枢×(1+buy_bc)
'差值' 绝对价格差 买=中枢−abs(sell_bc)、卖=中枢+buy_bc
'ATR' 步长 = ATR倍数 × ATR值 买=中枢−步长、卖=中枢+步长

下单类型与每档金额:

gd_type gd_value 含义 每档买卖金额逻辑
'金额' 固定金额(元) 每档投入 = gd_value
'百分比' 资金池的比例(%数) 每档投入 = (cash÷标的数) × gd_value ÷ 100
'数量' 固定份额(份) 每档投入 = gd_value 份 × 当前价(自动按 100 份整手)

> 例:gd_buy_bc_list=[0.03](卖出档 3%)、gd_sell_bc_list=[-0.02](买入档 2%)、gd_type='金额', gd_value=1000 → 中枢价 1.5 时,价格涨到 1.5×1.03 卖出 1000 元、跌到 1.5×0.98 买入 1000 元,成交后中枢价重置为新价格,依次递推滚动。

四、数据加载与处理详解

4.1 标的(股票/ETF)数据来源优先级

get_stock_data(stock_code) 取数顺序:

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

两种路径均执行统一清洗:截取 [start_date, end_date] 区间 → 日期升序 → 剔除 close<=0 或 open<=0 行 → adjust_price(当前为 none 原样返回)→ 重算 zdf = close.pct_change() → 按该标的 gd_atr_period 计算 atr/tr/atr_pct 列。

4.2 多线程加载

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

4.3 指数数据来源

get_index_data() 依次尝试以下来源,命中即返回:

优先级 来源 说明
① 自定义指数数据 use_custom_index_data=True 且有注入数据时优先使用
② data/指数数据/{index_stock}.parquet 本地 parquet

> 指数数据只用于输出展示/留档(导出目录的「指数数据」),不参与策略基准对比;策略对照基准是「等权持有不动」曲线(calculate_benchmark_curve,取各标的共同交易日等权归一化平均)。

五、网格与做T信号生成详解

5.1 ATR 计算(calculate_atr)

每个标的在数据加载时自动追加 tr(真实波幅)、atr(Wilder 平滑平均真实波幅)、atr_pct(ATR÷close×100)三列,供 gd_bc_type='ATR' 的动态网格档位使用。

5.2 网格档位(calculate_grid_prices)

calculate_grid_prices(current_price, grid_price, atr_value, stock) 依据步长类型计算买入/卖出触发价:

步长类型 返回 (buy_price, sell_price)
百分比 grid_price×(1−buy_step)、grid_price×(1+sell_step)
差值 grid_price−buy_step、grid_price+sell_step
ATR grid_price−buy_step、grid_price+sell_step,其中步长 = atr_ratio×atr

5.3 触发与重置

每日循环内(每只标的):

网格卖出:若卖出步长已启用(gd_buy_bc>0) 且 current_price ≥ sell_trigger 且持仓>0 → 卖出一档
网格买入:若买入步长已启用(gd_sell_bc<0) 且 current_price ≤ buy_trigger 且现金足够 → 买入一档
   (非ATR:卖出档位用 gd_buy_bc、买入档位用 gd_sell_bc 判断;ATR:两端用同一步长)
做T止盈:若 sell_zdf>0 且 current_price ≥ dt_last_price×(1+sell_zdf) → 卖出 trade_value
做T止损:若 buy_zdf<0 且 current_price ≤ dt_last_price×(1+buy_zdf) → 买入 trade_value

每笔成交后重置:grid_price = 当前价(网格)或 dt_last_price = 当前价(做T),并重算下一档触发价。买入需现金 ≥ 应投金额,卖出需持仓 > 0,最终以「实际能成交」为准。

六、交易执行详解

6.1 买入撮合(calculate_buy_shares)

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

6.2 卖出撮合(calculate_sell_shares)

calculate_sell_shares(shares, price, amount) -&gt; (sell_shares, actual_amount)
  • 按卖出金额折算股数(手续费从卖出金额中扣):sell_shares = floor(amount ÷ price ÷ 100) × 100;
  • 折算不足 100 但按金额够一手时补足 100;卖出份额超过持仓则全部卖出;
  • 返回 (卖出份数, 实收金额=市值−手续费)。

6.3 全部卖出(calculate_sell_shares_all)

calculate_sell_shares_all(shares, price) -&gt; (sell_shares, actual_amount)
  • 全部持仓按 100 份整手卖出;取整为 0 但有持仓时按实际持仓卖出;实收金额=市值−手续费。

6.4 日交易记录字段(trade_log)

字段 类型 说明
date datetime 交易日期
stock str 标的代码
type str 交易类型:初始建仓 / 网格买入 / 网格卖出 / ATR网格买入 / ATR网格卖出 / 做T止盈卖出 / 做T止损买入
price float 成交价格
amount float 成交金额(买入为含手续费成本;卖出为实收金额)
shares int 成交份额
cash_after float 成交后现金
holdings_after float 成交后持仓
reason str 交易原因,如 上涨触发网格卖出、下跌触发网格买入、止盈卖出、初始建仓
zdf float 当日涨跌幅
commission float 该笔手续费

七、完整函数清单

> 框架类 xg_gd_backtrader 共 65 个方法,以下按功能模块列出,便于二次开发和深度集成。

7.1 构造与配置

方法 说明
__init__(...) 构造网格回测实例(含逐标的网格参数列表与做T规则)
_validate_list_params() 校验各 *_list 长度与 stock_list 一致,并生成 self.stock_params、打印各标的网格配置与初始建仓资金
get_config() -&gt; dict 返回当前全部配置参数(含网格列表参数、已注入标的 key、指数注入状态)

7.2 数据加载与处理

方法 说明
get_stock_data(stock_code) 加载单只标的(自定义源优先,其次本地 parquet),返回含 atr/tr/atr_pct 的清洗后 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、算复权因子
_normalize_index_dataframe(df) 标准化注入的指数 DataFrame(含 date+close,自动识别日期列/索引)
calculate_atr(df, period) 计算 ATR:追加 tr / atr(Wilder 平滑)/ atr_pct 三列
adjust_price(df) 价格复权处理(当前 adj_type=&#x27;none&#x27; 时原样返回)
calculate_benchmark_curve(all_data) 计算等权持有不动基准净值曲线

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 注入(自动尝试多编码)
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 自定义指数注入(7 种接口)

方法 说明
add_index_data_from_dataframe(df) -&gt; bool 从 DataFrame 加载指数数据
add_index_data_from_excel(file_path, sheet_name=0, **kwargs) -&gt; bool 从 Excel 加载指数数据
add_index_data_from_csv(file_path, **kwargs) -&gt; bool 从 CSV 加载指数数据(自动尝试多编码)
add_index_data_from_json(file_path, orient=&#x27;records&#x27;, **kwargs) -&gt; bool 从 JSON 加载指数数据
add_index_data_from_dict(data) -&gt; bool 从字典加载指数数据(格式 {&#x27;date&#x27;: [...], &#x27;close&#x27;: [...]})
add_index_data_from_parquet(file_path, columns=None, **kwargs) -&gt; bool 从 Parquet 加载指数数据
add_index_data_from_bytes(file_bytes, file_type=&#x27;csv&#x27;, **kwargs) -&gt; bool 从字节数据加载指数数据(csv/excel/json,适合上传场景)

7.6 指数数据管理

方法 说明
clear_index_data() 清空自定义指数数据(恢复读取本地指数文件)
has_index_data() -&gt; bool 检查是否已有自定义指数数据
get_index_data_info() -&gt; dict 获取指数数据信息:{&#x27;has_data&#x27;: bool, &#x27;rows&#x27;: int, &#x27;start_date&#x27;: str, &#x27;end_date&#x27;: str, &#x27;columns&#x27;: list}(无数据时返回 {&#x27;has_data&#x27;: False})

7.7 网格核心计算

方法 说明
calculate_grid_step(current_price, atr_value, stock) 按该标的步长类型计算买入/卖出步长 {&#x27;buy_step&#x27;, &#x27;sell_step&#x27;}
calculate_grid_prices(current_price, grid_price, atr_value, stock) 计算买入/卖出触发价 (buy_price, sell_price)
calculate_order_amount(total_cash, current_price, current_holdings, stock) 按该标的下单类型计算每档应投金额

7.8 交易撮合计算

方法 说明
calculate_buy_shares(amount, price) 买入份额与成本计算(100 份整数倍、先扣佣金)
calculate_sell_shares(shares, price, amount) 按金额卖出份额与实收计算(超持仓则全卖)
calculate_sell_shares_all(shares, price) 全部卖出计算(含尾仓处理)

7.9 回测执行

方法 说明
vectorized_backtest() 向量化回测主引擎(多标的独立跑通 + 组合汇总)
run_backtest() 回测主入口,等价于 vectorized_backtest()

7.10 绩效与数据生成

方法 说明
calculate_performance_metrics(df, df_index) -&gt; dict 计算核心绩效指标
calculate_annual_performance(portfolio_df) -&gt; dict 计算逐年收益统计
generate_equity_curve_data() 生成净值曲线 dict
generate_trade_data() 生成成交数据 dict
generate_position_data() 生成持仓数据 dict
generate_account_data() 生成账户数据 dict

7.11 数据获取接口

方法 说明
get_performance_metrics() 获取绩效指标(未回测则自动回测)
get_equity_curve_data() 获取净值曲线数据
get_annual_performance() 获取年度收益统计(dict)
get_annual_performance_df() 获取年度收益统计(DataFrame,带 year 列)
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.12 结果保存

方法 说明
save_backtrader_data(user=&#x27;test&#x27;) 分类保存为 Excel + JSON 到 策略模型/网格策略/{user}/
save_to_json(filename=None, include_raw_data=False) 保存结果为单个 JSON 文件(默认文件名含 wangge_backtest_ 前缀;include_raw_data=True 时含指数原始数据)

7.13 报告生成

方法 说明
generate_report() -&gt; str 生成格式化文本回测报告

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

方法 说明
_convert_to_serializable(obj) 把 numpy/pandas/Timestamp/datetime 等递归转为 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_invested 网格买入累计投入额 元(仅统计 网格买入)
t_trades 网格交易次数 int(含网格买入+卖出,含 ATR 网格)
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 超额收益百分比 数值

8.2 年度收益统计字段(annual_performance)

字段 说明
start_date / end_date / total_days 当年统计区间与交易日数
total_cash / final_value / total_pnl 当年末总资产与区间盈亏
total_invested 当年网格买入投入额(当年新增成本口径)
t_trades 当年网格交易次数
total_commission / remaining_cash / final_holdings 当年手续费 / 期末现金 / 期末持仓
total_return / annual_return 当年收益率(区间口径)
max_drawdown / max_drawdown_date 当年最大回撤
sharpe_ratio / sortino_ratio / calmar_ratio 当年风险调整收益
win_rate / volatility 当年日胜率 / 波动率
benchmark_* 当年基准起止净值、总收益、最大回撤
excess_return / excess_return_pct 相对基准超额收益

8.3 净值曲线字段(equity_curve_data)

字段 说明
dates 日期字符串列表
total_value 每日总资产
cumulative_pnl 每日累计盈亏
cash 每日现金
holdings 每日持仓份额
investment_cost 每日累计投入成本(含手续费)
net_value 策略净值(总资产/初始资金)
drawdown 回撤百分比(%)
position_ratio 持仓占比(近似,份数口径)
total_return 每日累计收益率
daily_return 每日收益率
benchmark_net_value / benchmark_return 基准净值 / 基准日收益
statistics 起点/终点/总天数/初始资金/期末总资产/最高最低资产/总收益/最大回撤及日期摘要
benchmark_statistics 基准起止净值、总收益、最大回撤摘要

8.4 成交统计(trade_data['statistics'])

total_trades、buy_trades、sell_trades、total_buy_amount、total_sell_amount、net_invested(净投入=买-卖)、total_commission、first_trade_date、last_trade_date。

8.5 持仓统计(position_data['statistics'])

total_days、max_holdings、min_holdings、final_holdings、avg_holdings、first_date、last_date、final_return。每日明细还含 investment_cost、daily_pnl、cumulative_pnl、total_return(百分数口径)、stock_details(逐标的现值/现金/持仓/网格中枢/收益率)。

8.6 账户统计(account_data['statistics'])

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

8.7 各标的独立结果(get_stock_results)

每只标的含完整数组:cash/holdings/total_value/daily_pnl/cumulative_pnl/investment_cost/grid_price/buy_trigger/sell_trigger/dt_last_price/is_grid_triggered(每日序列)、trade_*(成交序列)、daily_records(每日明细含 action 触发原因)、final_holdings/final_cash/final_value/final_price/final_return/init_position_ratio/init_cash。

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

策略参数(标的/指数/复权/区间/资金/网格间隔/手续费/数据源)→ 做T参数(止盈/止损/金额)→ 各标的盈亏明细 → 汇总持仓 → 收益指标(总/年化/盈亏/波动/手续费)→ 基准对比(含超额)→ 风险指标(回撤/夏普/索提诺/卡尔玛)→ 交易统计(总次数/网格次数/做T次数/胜率)→ 年度收益统计表。

8.9 导出目录结构

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

九、完整实战示例

9.1 示例1:经典百分比网格 + 做T(本地数据)

from xg_gd_backtrader.xg_gd_backtrader import xg_gd_backtrader

bt = xg_gd_backtrader(
    start_date=&#x27;20250701&#x27;,
    end_date=&#x27;20261201&#x27;,
    stock_list=[&#x27;513100.SH&#x27;, &#x27;513500.SH&#x27;],   # 纳指ETF / 标普500ETF
    index_stock=&#x27;000300.SH&#x27;,
    cash=100000,
    comm=0.0001,
    gd_interval=1,
    gd_bc_type_list=[&#x27;百分比&#x27;, &#x27;百分比&#x27;],
    gd_buy_bc_list=[0.03, 0.02],       # 卖出档 3% / 2%
    gd_sell_bc_list=[-0.02, -0.015],   # 买入档 2% / 1.5%
    gd_type_list=[&#x27;金额&#x27;, &#x27;金额&#x27;],
    gd_value_list=[1000, 1500],        # 每档网格投入
    init_position_ratio_list=[0.1, 0.1],  # 初始建仓 10% / 10%
    sell_zdf=0.03,       # 涨 3% 做T止盈卖出
    buy_zdf=-0.02,       # 跌 2% 做T止损买入
    trade_value=1000,    # 每次做T 1000 元
    max_workers=8,
)

bt.run_backtest()
print(bt.generate_report())
bt.save_backtrader_data(user=&#x27;经典网格&#x27;)

9.2 示例2:纯网格 + 关闭做T

bt = xg_gd_backtrader(
    start_date=&#x27;20240101&#x27;,
    end_date=&#x27;20261201&#x27;,
    stock_list=[&#x27;159915.SZ&#x27;, &#x27;510300.SH&#x27;],
    cash=200000,
    comm=0.0001,
    gd_bc_type_list=[&#x27;百分比&#x27;, &#x27;百分比&#x27;],
    gd_buy_bc_list=[0.04, 0.04],        # 卖出档 4%
    gd_sell_bc_list=[-0.03, -0.03],     # 买入档 3%
    gd_type_list=[&#x27;金额&#x27;, &#x27;金额&#x27;],
    gd_value_list=[2000, 2000],
    init_position_ratio_list=[0.2, 0.2],
    sell_zdf=0.99,       # 极大值 → 关闭做T止盈
    buy_zdf=-0.99,       # 极大值 → 关闭做T止损
    trade_value=1000,
    max_workers=4,
)

bt.run_backtest()
print(bt.generate_report())
# 网格交易次数(做T已关闭,仅网格)
print(&quot;网格交易次数:&quot;, bt.get_performance_metrics().get(&#x27;t_trades&#x27;, 0))

9.3 示例3:ATR 动态网格 + 注入自定义标的数据

bt = xg_gd_backtrader(
    start_date=&#x27;20230101&#x27;,
    end_date=&#x27;20261201&#x27;,
    stock_list=[&#x27;513100.SH&#x27;, &#x27;513500.SH&#x27;],
    cash=200000,
    comm=0.0001,
    gd_interval=1,
    gd_bc_type_list=[&#x27;ATR&#x27;, &#x27;ATR&#x27;],       # 用 ATR 动态定档
    gd_atr_ratio_list=[2.0, 2.0],         # 2 倍 ATR 为步长
    gd_atr_period_list=[14, 14],          # 14 日 ATR
    gd_buy_bc_list=[0.03, 0.03],          # 非 ATR 时用,ATR 模式下忽略
    gd_sell_bc_list=[-0.02, -0.02],       # 非 ATR 时用,ATR 模式下忽略
    gd_type_list=[&#x27;金额&#x27;, &#x27;金额&#x27;],
    gd_value_list=[2000, 2000],
    init_position_ratio_list=[0.15, 0.15],
    use_custom_data=True,   # 显式声明使用自定义数据
)

# 不同格式注入
bt.add_stock_data_from_csv(&#x27;513100.SH&#x27;, &#x27;data/513100.csv&#x27;)
bt.add_stock_data_from_dataframe(&#x27;513500.SH&#x27;, df_513500)  # 内存 DataFrame

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

9.4 示例4:注入自定义指数数据(自定义对比指数)

import pandas as pd

# 构造或读取指数 DataFrame(含 date/close 即可)
index_df = pd.read_csv(&#x27;data/index_000300.csv&#x27;)

bt = xg_gd_backtrader(
    start_date=&#x27;20250701&#x27;,
    end_date=&#x27;20261201&#x27;,
    stock_list=[&#x27;513100.SH&#x27;, &#x27;513500.SH&#x27;],
    index_stock=&#x27;CUSTOM_INDEX&#x27;,   # 占位代码(不影响,指数以注入为准)
    cash=100000,
    use_custom_index_data=True,   # 关键:启用自定义指数
)

bt.add_index_data_from_dataframe(index_df)      # 或 add_index_data_from_csv(&#x27;xxx.csv&#x27;)
print(&quot;指数已注入:&quot;, bt.has_index_data())
print(bt.get_index_data_info())   # {&#x27;has_data&#x27;: True, &#x27;rows&#x27;: N, &#x27;start_date&#x27;:..., &#x27;columns&#x27;: [...]}

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

9.5 示例5:提取结果做二次分析 + 画净值/回撤曲线

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;total_invested&#x27;]:,.2f}&quot;)
print(f&quot;网格交易次数: {metrics[&#x27;t_trades&#x27;]}&quot;)
print(f&quot;总手续费: ¥{metrics[&#x27;total_commission&#x27;]:,.2f}&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;网格+做T 策略净值曲线&#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.6 示例6:按标的查看网格中枢与回测明细

bt.run_backtest()

# 各标的独立结果(含每日网格触发价)
for stock, res in bt.get_stock_results().items():
    print(f&quot;{stock}: 最终资产¥{res[&#x27;final_value&#x27;]:,.2f}, &quot;
          f&quot;最终持仓{res[&#x27;final_holdings&#x27;]:.0f}份, 末档网格中枢{res[&#x27;grid_price&#x27;][-1]:.4f}&quot;)

# 查看某标的最后一个交易日的网格中枢与买/卖触发价
res = bt.get_stock_results()[&#x27;513100.SH&#x27;]
print(&quot;最后一日:&quot;, res[&#x27;daily_records&#x27;][-1][&#x27;date&#x27;])
print(&quot;  中枢价:&quot;, res[&#x27;daily_records&#x27;][-1][&#x27;grid_price&#x27;])
print(&quot;  买入触发:&quot;, res[&#x27;daily_records&#x27;][-1][&#x27;buy_trigger&#x27;])
print(&quot;  卖出触发:&quot;, res[&#x27;daily_records&#x27;][-1][&#x27;sell_trigger&#x27;])
print(&quot;  动作:&quot;, res[&#x27;daily_records&#x27;][-1][&#x27;action&#x27;])

# 年度绩效
annual_df = bt.get_annual_performance_df()
print(annual_df[[&#x27;year&#x27;, &#x27;total_return&#x27;, &#x27;max_drawdown&#x27;, &#x27;sharpe_ratio&#x27;, &#x27;t_trades&#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 指数注入说明

  • 指数注入走独立的一套 _normalize_index_dataframe,只要求含 date 与 close(close&gt;0);
  • 注入成功后 use_custom_index_data 自动置 True,get_index_data() 优先返回注入数据;
  • get_index_data_info() 返回 has_data/rows/start_date/end_date/columns。

10.3 注入成功判定与验证

数据种类 注入方法 验证方法
标的 add_stock_data_from_* 返回 True;get_custom_data_keys() / has_custom_data(code)
指数 add_index_data_from_* 返回 True;has_index_data() / get_index_data_info()

> 建议:构造时把 use_custom_data=True / use_custom_index_data=True 传入,可避免中途依赖本地文件。

十一、常见问题与 FAQ

问题 解决方案
提示数据/文件不存在 检查 data/历史数据/{code}.parquet;或改用 add_*_data_from_* 注入;指数支持 parquet 及注入多格式
报错 "xxx 长度必须与 stock_list 长度一致" 网格列表参数(gd_bc_type_list 等 8 个列表)长度必须与 stock_list 完全一致,逐一对齐
一直没有网格成交 检查步长与行情波动:价格需先涨/跌破中枢一个档位才触发;gd_buy_bc_list 需为正数、gd_sell_bc_list 需为负数;可减小步长(如 0.01)或增大初始建仓
网格方向反了(该买却卖) 确认符号:gd_buy_bc_list 存卖出档正数、gd_sell_bc_list 存买入档负数;不要写反
做T几乎不触发 默认需当日价格相对上次做T价涨 ≥ sell_zdf(如 3%)或跌 ≤ buy_zdf;做T买入还需现金 ≥ trade_value,卖出需已有持仓
某标的现金先用完 每标资金池 = cash ÷ 标的数,独立封顶;调小 gd_value/init_position_ratio 或调大 cash
初始建仓占总资金比例之和超 100% 构造时会打印 ⚠️ 告警;应保证 sum(init_position_ratio_list) ≤ 1
自定义标的注入了但没生效 用 get_custom_data_keys() 验证;确认 use_custom_data=True;代码(含后缀 .SZ/.SH)须与 stock_list 完全一致
自定义指数注入了但没生效 用 has_index_data() 验证,确认 use_custom_index_data=True(或注入成功后自动置位)
手续费偏高 网格/做T越频繁手续费越高:放宽网格步长与 ±sell_zdf/buy_zdf 阈值、加大 gd_value/trade_value 或调小 comm
收益率/份额如何看 比率字段多为小数(如 total_return=0.25 表示 25%);position_data/account_data 里的 total_return 是百分数口径,注意区分
如何只做网格、关闭做T 把 sell_zdf、buy_zdf 设成极大值(如 0.99 / -0.99),做T信号永不触发

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

12.1 参数调优建议

参数 建议范围 说明
gd_buy_bc_list 0.01–0.05 网格卖出档间距,越小网格越密、交易越频繁
gd_sell_bc_list −0.05 ~ −0.01 网格买入档间距,与卖出档可不对称(买入档可略大于卖出档赚价差)
gd_atr_ratio_list 1.5–3.0 ATR 倍数,越大档位越宽、触发越少
gd_atr_period_list 10–30 ATR 平滑周期
gd_value / trade_value 与资金池匹配 每档网格/做T投入金额,越大单次价差收益越高但占用现金越多
init_position_ratio_list 0.05–0.30 初始建仓比例,总和 ≤ 1;比例越高越早进入网格状态
comm 0.0001–0.0005 网格是高频策略,对手续费高度敏感,务必按真实费率设置

12.2 网格设计经验

  • 震荡市网格最优:网格天生适合"箱体震荡",单边大涨易过早卖光、单边大跌易满仓被套,建议结合做T止盈止损对冲单边风险;
  • 买入档宽于卖出档:让每次低吸赚到的价差能覆盖手续费并留出利润,通常 |卖出档| &lt; |买入档|;
  • 留足现金:初始建仓建议 ≤ 60%,保证下跌时有充足弹药逐档补仓;
  • ATR 自适应:用 ATR 动态档位可避免在波动放大时档位过密、波动萎缩时长期不触发。

12.3 自定义网格/做T规则

继承 xg_gd_backtrader 后重写信号/撮合方法,即可换成任意网格加仓逻辑:

from xg_gd_backtrader.xg_gd_backtrader import xg_gd_backtrader

class MyGrid(xg_gd_backtrader):
    def calculate_order_amount(self, total_cash, current_price, current_holdings, stock):
        # 例:越跌买越多(金字塔加仓)
        params = self.stock_params[stock]
        drop = (params[&#x27;gd_buy_bc&#x27;] * 2)  # 示意,可按当前价距中枢的跌幅放大下单
        return super().calculate_order_amount(total_cash, current_price, current_holdings, stock) * 2

    def calculate_grid_prices(self, current_price, grid_price, atr_value, stock):
        # 例:自定义档位(如双倍距离触发的变体)
        return super().calculate_grid_prices(current_price, grid_price, atr_value, stock)

bt = MyGrid(start_date=&#x27;20240101&#x27;, end_date=&#x27;20261201&#x27;,
            stock_list=[&#x27;513100.SH&#x27;], gd_value_list=[1000],
            init_position_ratio_list=[0.1])
bt.run_backtest()
print(bt.generate_report())

12.4 自定义交易/成本规则

重写 calculate_buy_shares() / calculate_sell_shares() / calculate_sell_shares_all() 可自定义整手规则、印花税、最低佣金等;重写 vectorized_backtest() 可在不改变数据层的前提下整体替换交易引擎。

十三、技术说明与提示

  • performance_metrics 中的比率多为小数(如 total_return=0.25 表示 25%);报告打印时已 ×100;position_data/account_data 里的 total_return 是百分数口径,直接从 dict 取值时注意区分。
  • 年化按 365.25 天折算;夏普/索提诺/波动率按 250 个交易日年化;无风险利率固定 0.02。
  • total_invested 只统计 网格买入 金额(含 ATR 网格买入;不含初始建仓与做T买入),t_trades 为网格总笔数(含网格买+卖、ATR 网格,不含做T)。
  • 网格参数以每只标的独立列表下发;组合净值按标的间共同交易日汇总,每标资金池 = cash ÷ 标的数。
  • 符号约定:gd_buy_bc_list 为卖出步长正数、gd_sell_bc_list 为买入步长负数;初始建仓比例之和建议 ≤ 1。
  • 指数数据仅用于输出留档,策略对照基准为「等权持有不动」曲线。
  • 源码当前固定 adj_type=&#x27;none&#x27;,若需前复权/后复权可在 adjust_price 中扩展。
  • 做T参数 sell_zdf/buy_zdf 是全局的(所有标的共用),与逐标的网格参数独立。

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

常见问题

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

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

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

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

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

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

小果网格策略回测系统助手收费吗?

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

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

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

热门专题

按场景挑技能
全部专题 →

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