在跑回测的过程中,我发现了一个比较容易被忽视的一个坑:均线在回测的时间段是不全的。
如图所示,图中红色的线是90日均线,回测的时间范围是2020-01-01 08:00:00 至 2024-01-01 16:00:00,可以看到图中最开始的一段走势中都没有红线,直到2020-05-18 那天才出现红线。

均线在2020年5月18日才出现,这会导致我们的策略在2020年5月18号前都失效!下图是运行回测时的买卖结果,可以看到最早的买单是在2020年6月1日创建的:

那怎样才能解决这个问题呢?
首先来看看为什么会出现这个问题。在单均线策略中,我们采用的指标是90日均线,它需要90根日k线才能计算出来,因此,在回测开始的前90个交易日里没有足够的数据计算出90日均线。
知道了问题的原因,那也就好解决了,我们人为地加上90天k线的数据不就可以了,
接下来我来说一下我的解决方法:
以 量化交易学习(三)backtrader使用掘金量化实时数据源 这篇文章中的代码为基础,首先在初始化函数中,加上获取历史数据的代码,获取完历史数据后把它们直接通过管道传给backtrader,为了简单起见,我直接加上了前一年的k线数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| def init(context): parent_conn, child_conn = Pipe() context.parent_conn = parent_conn p = Process(target=backtrader, args=(child_conn,)) p.start() gmdata = history(symbol='SHSE.510300', frequency='1d', start_time='2019-01-01 09:00:00', end_time='2020-01-01 16:00:00', adjust=ADJUST_PREV, adjust_end_time='2024-01-01', df=True) for idx,row in gmdata.iterrows(): bar = { 'symbol': row['symbol'], 'frequency': row['frequency'], 'open': row['open'], 'high': row['high'], 'low': row['low'], 'close': row['close'], 'volume': row['volume'], 'amount': row['amount'], 'pre_close': row['pre_close'], 'position': row['position'], 'bob': row['bob'], 'eob': row['eob'] } context.parent_conn.send(bar) subscribe(symbols='SHSE.510300', frequency='1d')
|
策略也要相应进行修改:
因为k线添加了回测开始时间前一年的数据,如果直接跑回测的话会把这段时间也算作回测时间,应该让策略跳过这段时间,给策略添加一个新的参数start_date,用于标记策略开始运行的时间,在next函数中,如果当前k线的结束时间小于start_date则跳过执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| class SingleMAStrategy(bt.Strategy): params = ( ('period', 15), ('start_date',None), ) def __init__(self): ... self.start_date=datetime.strptime(self.p.start_date, '%Y-%m-%d %H:%M:%S') if self.p.start_date is not None else None def next(self): if self.start_date is not None and self.start_date>bt.utils.num2date( self.data.datetime[0]): return ... ``` 在backtrader函数中,修改添加策略相关的代码: ```py def backtrader(conn): cerebro = bt.Cerebro() cerebro.addstrategy(SingleMAStrategy, period=90, start_date='2020-01-01 09:00:00') ...
|
跑完后的图像如下:

可以看到回测开始前多了一段股价图,下方的CrossOver是股价与均线交叉信号。回测开始前虽然有信号,但没有触发交易,回测开始后,交易正常触发,说明均线已经被补齐,回测结果正确了。

这一篇就到这里啦。欢迎大家点赞、转发、私信。
