Skip to content

ElenYoung/GeneralBacktest

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GeneralBacktest

PyPI version Python 3.8+ License: MIT

GeneralBacktest 是一个灵活高效的量化策略回测框架,专为多资产组合策略设计。核心理念是"权重→交易→净值",支持任意调仓频率、真实交易细节模拟、向量化高性能计算和丰富的性能分析。

✨ 主要特性

  • 🎯 灵活的调仓策略:支持任意调仓频率和时间点,无需固定周期
  • 🚀 高性能计算:向量化实现,支持数千标的、数年数据的快速回测
  • 💰 真实交易模拟
    • 调仓阈值控制(避免微小调整)
    • 买卖分开计费
    • 滑点模拟
    • 调仓日盈亏拆分(持仓/卖出/买入)
  • 📊 总仓位控制:支持动态调整每个调仓日的总仓位比例(v1.1.0 新增)
  • 💵 现金仓位回测:基于实际资金和交易单位的精确回测(v1.1.0 新增)
  • 📈 增强可视化:支持对数坐标净值曲线和双坐标对比(v1.1.0 新增)
  • 📊 丰富的性能指标:15+ 常用指标
    • 收益率指标:累计收益、年化收益
    • 风险指标:波动率、最大回撤
    • 风险调整指标:夏普比率、索提诺比率、卡玛比率
    • 尾部风险:VaR、CVaR
    • 相对指标:信息比率、超额收益
    • 交易指标:换手率
  • 📈 专业的可视化:10+ 图表类型
    • 净值曲线(支持普通/对数坐标)
    • 策略对比
    • 超额收益分析
    • 月度收益热力图
    • 换手率分析
    • 持仓变化
    • 综合 Dashboard

📦 安装

基础安装

pip install GeneralBacktest

完整安装(包含数据库支持)

如果需要使用 run_backtest_ETF()run_backtest_stock() 方法连接数据库:

pip install GeneralBacktest[database]

或安装所有可选依赖:

pip install GeneralBacktest[full]

依赖说明

  • 必需依赖numpy, pandas, matplotlib
  • 可选依赖
    • quantchdb:用于数据库连接(ETF/股票数据)
    • openpyxl:用于导出 Excel 报告

🚀 快速开始

基础用法 - 本地数据回测

from GeneralBacktest import GeneralBacktest
import pandas as pd

# 准备权重数据(调仓信号)
weights_data = pd.DataFrame({
    'date': ['2023-01-01', '2023-01-01', '2023-06-01', '2023-06-01'],
    'code': ['stock_A', 'stock_B', 'stock_A', 'stock_B'],
    'weight': [0.6, 0.4, 0.3, 0.7]
})

# 准备价格数据(日线行情)
price_data = pd.DataFrame({
    'date': pd.date_range('2023-01-01', '2023-12-31', freq='D'),
    'code': 'stock_A',
    'open': [...],
    'close': [...],
    'adj_factor': [...]  # 复权因子
})
# ... 更多股票数据

# 创建回测实例
bt = GeneralBacktest(start_date="2023-01-01", end_date="2023-12-31")

# 运行回测
results = bt.run_backtest(
    weights_data=weights_data,
    price_data=price_data,
    buy_price="open",              # 买入价格字段
    sell_price="close",            # 卖出价格字段
    adj_factor_col="adj_factor",   # 复权因子字段
    close_price_col="close",       # 收盘价字段
    rebalance_threshold=0.005,     # 调仓阈值:0.5%
    transaction_cost=[0.001, 0.001],  # 买卖成本各 0.1%
    slippage=0.0005,               # 滑点:0.05%
    initial_capital=1.0
)

# 查看性能指标
bt.print_metrics()

# 生成可视化报告
bt.plot_all()  # 综合 Dashboard
bt.plot_nav_curve()  # 净值曲线
bt.plot_monthly_returns()  # 月度收益热力图

高级功能 - 总仓位控制与现金仓位回测

总仓位控制

支持动态调整每个调仓日的总仓位比例,例如保持 80% 股票仓位,20% 现金:

# 在 weights_data 中增加 position_ratio 列
weights_data = pd.DataFrame({
    'date': ['2023-01-01', '2023-01-01', '2023-06-01', '2023-06-01'],
    'code': ['stock_A', 'stock_B', 'stock_A', 'stock_B'],
    'weight': [0.6, 0.4, 0.3, 0.7],
    'position_ratio': [0.8, 0.8, 0.9, 0.9]  # 每个调仓日的目标仓位比例
})

results = bt.run_backtest(
    weights_data=weights_data,
    price_data=price_data,
    position_ratio_col='position_ratio',  # 指定仓位比例列名
    ...
)

现金仓位回测(精确模拟)

使用 run_backtest_with_cash() 方法进行基于实际资金和交易单位的精确回测,适用于需要考虑以下因素的实盘模拟:

  • 最小交易单位(每手 100 股)
  • 实际资金约束(现金不足时无法买入)
  • 交易优先级策略
# 运行现金仓位回测
results = bt.run_backtest_with_cash(
    weights_data=weights_data,
    price_data=price_data,
    initial_capital=1_000_000,  # 初始资金 100 万
    buy_price='open',
    sell_price='close',
    close_price_col='close',
    lot_size=100,  # 每手股数(A 股=100)
    trade_critic='weight_desc',  # 按权重从大到小交易
    transaction_cost=[0.001, 0.001],
    slippage=0.001
)

# 查看回测结果
print(f"最终净值: {results['nav_series'].iloc[-1]:,.2f}")
print(f"最终现金: {results['cash_series'].iloc[-1]:,.2f}")
print(f"最终现金占比: {results['metrics']['Cash Ratio']:.2%}")

高级用法 - ETF 数据库回测(需要数据库配置)

注意run_backtest_ETF()run_backtest_stock() 方法需要特定的数据库配置(db_config),这些方法需要有特定数据库支持。一般建议使用 run_backtest() 方法。

from GeneralBacktest import GeneralBacktest
import pandas as pd

# 准备权重数据
weights_data = pd.DataFrame({
    'date': ['2023-01-01', '2023-01-01'],
    'code': ['510300', '510500'],  # ETF 代码
    'weight': [0.6, 0.4]
})

# 数据库配置(需要有效的数据库访问权限)
db_config = {
    'host': 'your_host',
    'port': 9000,
    'user': 'your_user',
    'password': 'your_password',
    'database': 'etf'
}

# 创建回测实例
bt = GeneralBacktest(start_date="2023-01-01", end_date="2023-12-31")

# 运行 ETF 回测(自动从数据库获取价格数据)
results = bt.run_backtest_ETF(
    etf_db_config=db_config,
    weights_data=weights_data,
    buy_price='open',
    sell_price='open',
    transaction_cost=[0.001, 0.001],
    rebalance_threshold=0.005
)

bt.print_metrics()
bt.plot_all()

📚 核心概念

总仓位控制(v1.1.0)

支持在 run_backtest() 中通过 position_ratio_col 参数动态控制每个调仓日的总仓位比例:

计算逻辑:

  1. 首先将同一天所有标的的权重归一化到 1(各标的权重之和为 1)
  2. 然后乘以当天的 position_ratio 值,得到最终权重
  3. 最终权重之和 = position_ratio,剩余部分视为现金(不产生收益)

示例:

  • 原始权重:A=0.6, B=0.4(和为 1.0)
  • position_ratio = 0.8
  • 最终权重:A=0.48, B=0.32(和为 0.8)
  • 现金仓位 = 0.2(20%)

向后兼容性:

  • position_ratio_col=None 时(默认值),行为与之前版本完全一致(满仓)

现金仓位回测 vs 标准回测

特性 run_backtest() run_backtest_with_cash()
资金单位 相对权重(0-1) 绝对金额(如 1,000,000)
持仓追踪 权重比例 实际股数
最小交易单位 无限制 每手 lot_size 股(默认 100)
现金约束 有(现金不足时无法买入)
复权因子 需要提供 不需要(使用原始价格)

run_backtest_with_cash() 特有指标:

  • Final Cash: 最终现金余额
  • Cash Ratio: 最终现金占比
  • Avg Cash Ratio: 平均现金占比

权重数据格式

权重数据表示组合在各个调仓日的目标仓位:

标准回测(run_backtest):

date code weight position_ratio*
2023-01-01 stock_A 0.6 0.8
2023-01-01 stock_B 0.4 0.8
2023-06-01 stock_A 0.3 1.0
2023-06-01 stock_B 0.7 1.0
  • weight:各标的的相对权重,系统会自动归一化
  • position_ratio(可选):该调仓日的总仓位比例(0-1),剩余部分为现金
  • 若不提供 position_ratio,系统默认满仓(position_ratio=1.0)

现金回测(run_backtest_with_cash):

date code weight
2023-01-01 stock_A 0.6
2023-01-01 stock_B 0.4
2023-06-01 stock_A 0.3
2023-06-01 stock_B 0.7
  • 每个调仓日的权重和应为 1.0
  • 不同调仓日可以有不同的持仓数量

价格数据格式

价格数据包含资产的日线行情:

date code open high low close adj_factor
2023-01-01 stock_A 10.0 10.5 9.8 10.2 1.0
2023-01-02 stock_A 10.2 10.8 10.1 10.5 1.0
  • adj_factor:复权因子,用于计算真实收益
  • 买卖价格可以灵活指定(开盘价、收盘价等)

调仓机制

  1. 调仓阈值:只有当目标权重与当前权重差异超过阈值时才交易
  2. 买卖拆分:先卖出不需要的仓位,再买入新仓位
  3. 成本计算:买卖分开计费,可设置不同费率
  4. 滑点模拟:买入价格上浮、卖出价格下压

📊 性能指标说明

指标类别 指标名称 说明 适用方法
收益指标 累计收益率 期末/期初 - 1 所有
年化收益率 按交易日年化 所有
风险指标 年化波动率 日收益率标准差年化 所有
最大回撤 从峰值到谷底的最大损失 所有
最大回撤持续期 最长回撤时间(天) 所有
风险调整 夏普比率 年化收益/年化波动率 所有
索提诺比率 年化收益/下行波动率 所有
卡玛比率 年化收益/最大回撤 所有
尾部风险 VaR (95%) 5%分位数损失 所有
CVaR (95%) 超过VaR的平均损失 所有
相对指标 信息比率 超额收益/跟踪误差 所有
超额年化收益 相对基准的年化超额 所有
交易指标 换手率 调仓时的买卖金额 所有
现金指标 最终现金余额 回测结束时的现金金额 run_backtest_with_cash
最终现金占比 最终现金 / 最终净值 run_backtest_with_cash
平均现金占比 每日(现金 / 净值)的均值 run_backtest_with_cash
换手率 调仓时的买卖金额 run_backtest_with_cash

🎨 可视化示例

框架提供多种可视化方法:

# 1. 综合 Dashboard(推荐)
bt.plot_all()

# 2. 净值曲线和回撤
bt.plot_nav_curve()  # 普通坐标
bt.plot_nav_curve(log_scale=True)  # 对数坐标(v1.1.0 新增)

# 3. 双坐标净值曲线对比(v1.1.0 新增)
bt.plot_nav_curve_dual(
    figsize=(14, 12),
    title="Strategy Performance",
    save_path="dual_nav.png"
)

# 4. 策略与基准对比
bt.plot_comparison()

# 5. 超额收益分析
bt.plot_excess_returns()

# 6. 月度收益热力图
bt.plot_monthly_returns()

# 7. 换手率分析
bt.plot_turnover()

# 8. 持仓变化热力图
bt.plot_positions()

# 9. 收益分布直方图
bt.plot_return_distribution()

可视化增强(v1.1.0):

  • plot_nav_curve() 新增 log_scale 参数,支持对数坐标显示
  • 新增 plot_nav_curve_dual() 方法,同时显示普通坐标和对数坐标
  • plot_all() Dashboard 根据回测类型自动调整显示:
    • run_backtest(): 显示归一化净值(从 1 开始)
    • run_backtest_with_cash(): 显示实际资金净值(带千位分隔符)

🔧 高级配置

自定义基准

# 提供基准权重数据
benchmark_weights = pd.DataFrame({
    'date': ['2023-01-01'],
    'code': ['index_300'],
    'weight': [1.0]
})

results = bt.run_backtest(
    weights_data=weights_data,
    price_data=price_data,
    benchmark_weights=benchmark_weights,
    benchmark_name="HS300",
    ...
)

导出结果

# 获取回测结果
nav_series = bt.daily_nav  # 日度净值序列
positions = bt.daily_positions  # 持仓明细
trade_records = bt.trade_records  # 交易记录
metrics = bt.metrics  # 性能指标字典

# 导出为 DataFrame
import pandas as pd
pd.DataFrame(metrics, index=[0]).to_excel('metrics.xlsx')

📖 API 文档

GeneralBacktest 类

初始化

GeneralBacktest(start_date: str, end_date: str)

主要方法

标准回测方法:

  • run_backtest(weights_data, price_data, buy_price, sell_price, close_price_col, adj_factor_col=None, position_ratio_col=None, ...): 通用回测方法(推荐)
    • position_ratio_col (str, optional): 总仓位比例列名(v1.1.0 新增),用于动态控制现金仓位
  • run_backtest_ETF(...): ETF 回测(需数据库配置)
  • run_backtest_stock(...): 股票回测(需数据库配置)

现金仓位回测方法(v1.1.0 新增):

  • run_backtest_with_cash(weights_data, price_data, initial_capital, buy_price='open', sell_price='close', close_price_col='close', lot_size=100, trade_critic='weight_desc', ...): 现金仓位回测
    • 基于实际资金和交易单位的精确回测
    • 自动计算换手率、现金占比等指标
    • lot_size: 每手股数(A股=100)
    • trade_critic: 交易优先级策略('weight_desc', 'weight_asc', 'amount_max')

可视化方法:

  • print_metrics(): 打印性能指标
  • plot_all(): 生成综合报告
  • plot_nav_curve(log_scale=False): 绘制净值曲线(v1.1.0 新增 log_scale 参数)
  • plot_nav_curve_dual(figsize=(14, 12), title=None, save_path=None): 双坐标净值曲线对比(v1.1.0 新增)
  • plot_comparison(): 策略对比图
  • plot_excess_returns(): 超额收益图
  • plot_monthly_returns(): 月度收益热力图
  • plot_turnover(): 换手率图
  • plot_positions(): 持仓热力图
  • plot_return_distribution(): 收益分布图

🤝 贡献

欢迎提交 Issue 和 Pull Request!

📄 许可证

本项目采用 MIT 许可证 - 详见 LICENSE 文件

👨‍💻 作者

Elen Young - yang13515360252@163.com

🔗 相关链接

⚠️ 免责声明

本框架仅供学习和研究使用,不构成任何投资建议。使用本框架进行的任何投资决策,风险自负。

🔙 向后兼容性

所有 v1.1.0 的更新均为增量更新,100% 向后兼容

  • run_backtest() 新增 position_ratio_col 参数,默认值为 None(满仓),不传此参数时行为与 v1.0.0 完全一致
  • plot_nav_curve() 新增 log_scale 参数,默认值为 False,不传此参数时行为与 v1.0.0 一致
  • run_backtest_with_cash()全新方法,不影响现有代码
  • plot_nav_curve_dual()全新方法,不影响现有代码

您可以在不修改现有代码的情况下安全升级到新版本,并根据需要选择使用新功能。

📝 更新日志

v1.1.0 (2026-02-06)

  • 新增总仓位控制 (position_ratio_col 参数):支持动态调整每个调仓日的总仓位比例
  • 💵 新增现金仓位回测 (run_backtest_with_cash):基于实际资金和交易单位的精确回测
  • 📈 增强可视化功能
    • plot_nav_curve() 新增 log_scale 参数,支持对数坐标
    • 新增 plot_nav_curve_dual() 方法,同时显示普通/对数坐标
    • Dashboard 根据回测类型自动调整显示(归一化净值 vs 实际资金)
  • 📊 新增性能指标:换手率、最终现金、现金占比等
  • 🔧 向后兼容:所有新功能均为增量更新,不影响现有代码

v1.0.0 (2026-01-24)

  • 🎉 首次发布
  • ✨ 支持灵活调仓频率
  • ✨ 向量化高性能计算
  • ✨ 15+ 性能指标
  • ✨ 8+ 可视化图表
  • ✨ 支持基准对比
  • ✨ 真实交易细节模拟

About

A General Backtest Framework for Quantative Research.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages