在量化策略开发的过程中,很多新手习惯用简单的 for 循环遍历 Pandas 的 DataFrame 甚至是 List 来做回测。这种做法虽然直观,但在处理复杂的资金管理、交易滑点、手续费以及限价单/市价单时,很容易因为逻辑不严谨而引入“未来函数”(Lookahead Bias),导致回测表现优秀、实盘却一败涂地。
为了提高回测的严谨性,使用成熟的事件驱动型回测引擎是更推荐的方案。在 Python 生态中,Backtrader 是目前个人开发者使用最广泛、生态最活跃的开源框架之一。
然而,使用 Backtrader 的第一个痛点往往不是编写策略本身,而是数据源的适配。Backtrader 对输入的数据格式有着较为严苛的要求(需要包含特定的开盘、最高、最低、收盘、成交量等字段,且时间戳必须对齐),同时对于跨市场策略,除权除息带来的价格跳空也会严重干扰均线等技术指标。
本文将演示如何利用 QuantDash的前复权历史 K 线数据,快速清洗并适配至 Backtrader 数据管道,搭建一个标准的双均线策略回测框架。
下面我们来编写一个完整的、可运行的策略回测脚本。该策略使用经典的双均线交叉逻辑:当短期均线上穿长期均线时买入,下穿时卖出。
首先需要安装相关的依赖:
pip install backtrader pandas quantdash复制
import datetime
import backtrader as bt
import pandas as pd
from quantdash import QuantDash
# 定义策略
class SmaCrossStrategy(bt.Strategy):
params = (
('fast_period', 20),
('slow_period', 50),
)
def __init__(self):
# 定义快速和慢速简单移动平均线
self.sma_fast = bt.indicators.SimpleMovingAverage(
self.data.close, period=self.p.fast_period
)
self.sma_slow = bt.indicators.SimpleMovingAverage(
self.data.close, period=self.p.slow_period
)
# 交叉信号:1 代表上穿,-1 代表下穿
self.crossover = bt.indicators.CrossOver(self.sma_fast, self.sma_slow)
def next(self):
# 如果当前无持仓,且发生金叉,则买入
if not self.position:
if self.crossover > 0:
self.buy(size=100) # 买入100股
# 如果已有持仓,且发生死叉,则卖出(清仓)
else:
if self.crossover < 0:
self.close()
# 数据获取与格式适配函数
def get_backtrader_data(api_key, symbol, start_date, end_date):
# 1. 使用 QuantDash 获取前复权历史K线
qd = QuantDash(api_key=api_key)
df = qd.stock.get_kline(
symbol=symbol,
start_date=start_date,
end_date=end_date,
adjust="forward" # 开启前复权,确保技术指标不因分红送股而变形
)
# 2. 格式转换:Backtrader 要求 DatetimeIndex 且字段类型为 float
df['date'] = pd.to_datetime(df['date'])
df.set_index('date', inplace=True)
# 保证数据列格式正确
for col in ['open', 'high', 'low', 'close', 'volume']:
df[col] = df[col].astype(float)
# Backtrader 默认需要 openinterest 列,我们填充为 0
df['openinterest'] = 0
# 3. 将 Pandas DataFrame 转换为 Backtrader 接受的 Feed 格式
data_feed = bt.feeds.PandasData(
dataname=df,
datetime=None, # None 表示使用 index 作为时间戳
open='open',
high='high',
low='low',
close='close',
volume='volume',
openinterest='openinterest'
)
return data_feed
if __name__ == '__main__':
# 请在此处替换为你的 QuantDash API Key
API_KEY = "your_quantdash_api_key_here"
# 回测标的与时间范围(支持 A股、港股、美股,这里以腾讯控股为例)
SYMBOL = "00700.HK"
START_DATE = "2024-01-01"
END_DATE = "2025-12-31"
# 初始化 Backtrader 引擎
cerebro = bt.Cerebro()
# 获取并添加数据
try:
data = get_backtrader_data(API_KEY, SYMBOL, START_DATE, END_DATE)
cerebro.adddata(data)
except Exception as e:
print(f"获取数据失败,请检查 API Key 或代码格式: {e}")
exit()
# 添加自定义策略
cerebro.addstrategy(SmaCrossStrategy)
# 设置初始资金与佣金率(万分之三)
cerebro.broker.setcash(100000.0)
cerebro.broker.setcommission(commission=0.0003)
# 运行回测
print(f"初始资产: {cerebro.broker.getvalue():.2f}")
cerebro.run()
print(f"最终资产: {cerebro.broker.getvalue():.2f}")复制
通过在本地组合 Backtrader 与 QuantDash,开发者不需要再去维护复杂的底层爬虫或承受不稳定的清洗过程,能将更多精力放在策略设计、滑点测试以及仓位管理等核心问题上。对于多资产配置研究而言,这提供了一个相对低成本、逻辑清晰且扩展性良好的基建方案。
参考文档:
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。