本文使用均线交叉策略,对平安银行自2018年1月1日至2020年2月28日的日线数据进行回测分析。
策略会用到短期移动均线及长期移动均线两个技术指标,在backtrader自定义策略init方法中,添加如下代码计算均线指标并判断交叉情况:
sma1 = bt.ind.SMA(period=self.p.pfast) # 短期均线
sma2 = bt.ind.SMA(period=self.p.pslow) # 长期均线
self.crossover = bt.ind.CrossOver(sma1, sma2) # 交叉信号
当短期均线向上金叉长期均线后进行买入,当长期均线向下死叉短期均线后卖出,在策略的next方法下添加如下代码如:
if not self.position: # 不在场内,则可以买入
if self.crossover > 0: # 如果金叉
self.buy() # 买入
elif self.crossover < 0: # 在场内,且死叉
self.close() # 卖出
回测初始资金100000,单笔操作单位5000股,佣金千分之一。
对短期均线及长期均线周期进行不同选择,通过绘图的方式查看回测结果。
回测最终资产:97850.83
回测最终资产:99096.03
回测最终资产:116776.70
回测最终资产:110485.50
回测最终资产:101424.75
均线交叉策略代码:
from __future__ import (absolute_import, division, print_function,
unicode_literals)
import datetime # 用于datetime对象操作
import os.path # 用于管理路径
import sys # 用于在argvTo[0]中找到脚本名称
import backtrader as bt # 引入backtrader框架
# 创建策略
class SmaCross(bt.Strategy):
# 可配置策略参数
params = dict(
pfast=5, # 短期均线周期
pslow=10 # 长期均线周期
)
def __init__(self):
sma1 = bt.ind.SMA(period=self.p.pfast) # 短期均线
sma2 = bt.ind.SMA(period=self.p.pslow) # 长期均线
self.crossover = bt.ind.CrossOver(sma1, sma2) # 交叉信号
def next(self):
if not self.position: # 不在场内,则可以买入
if self.crossover > 0: # 如果金叉
self.buy() # 买入
elif self.crossover < 0: # 在场内,且死叉
self.close() # 卖出
cerebro = bt.Cerebro() # 创建cerebro
# 先找到脚本的位置,然后根据脚本与数据的相对路径关系找到数据位置
# 这样脚本从任意地方被调用,都可以正确地访问到数据
modpath = os.path.dirname(os.path.abspath(sys.argv[0]))
datapath = os.path.join(modpath, '../TQDat/day/stk/000001.csv')
# 创建价格数据
data = bt.feeds.GenericCSVData(
dataname = datapath,
fromdate = datetime.datetime(2018, 1, 1),
todate = datetime.datetime(2020, 2, 29),
nullvalue = 0.0,
dtformat = ('%Y-%m-%d'),
datetime = 0,
open = 1,
high = 2,
low = 3,
close = 4,
volume = 5,
openinterest = -1
)
# 在Cerebro中添加价格数据
cerebro.adddata(data)
# 设置启动资金
cerebro.broker.setcash(100000.0)
# 设置交易单位大小
cerebro.addsizer(bt.sizers.FixedSize, stake = 5000)
# 设置佣金为千分之一
cerebro.broker.setcommission(commission=0.001)
cerebro.addstrategy(SmaCross) # 添加策略
cerebro.run() # 遍历所有数据
cerebro.plot() # 绘图
为了便于相互交流学习,新建了微信群,感兴趣的读者请加微信。