Skip to main content

一个灵活高效的量化策略回测框架,支持多资产组合、任意调仓频率、向量化计算和丰富的性能分析

Project description

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+ 可视化图表
  • ✨ 支持基准对比
  • ✨ 真实交易细节模拟

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

generalbacktest-1.1.0.tar.gz (38.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

generalbacktest-1.1.0-py3-none-any.whl (33.0 kB view details)

Uploaded Python 3

File details

Details for the file generalbacktest-1.1.0.tar.gz.

File metadata

  • Download URL: generalbacktest-1.1.0.tar.gz
  • Upload date:
  • Size: 38.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.11

File hashes

Hashes for generalbacktest-1.1.0.tar.gz
Algorithm Hash digest
SHA256 31190ad08b88a17585a3d4f2cdc35c0c5bb6a6ff74ec48078a93d51af18d4296
MD5 2ae13c889b40994214b03945b792d43e
BLAKE2b-256 bf9e264692fa09f64b6e1c6540aeeb72b48a07c78850d30e8495dca1112e2d64

See more details on using hashes here.

File details

Details for the file generalbacktest-1.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for generalbacktest-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5bc6c97efe2be5254da93cb08af7e29bb2517e97908c558bafa2338ea10c2654
MD5 b5ab3237a3fe7748ac489405f97ec680
BLAKE2b-256 2cfeb1162cf6233323daa7613367bcd19c731d0f91d52cf29e4b5f0d020cc4e1

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page