backtrader由德国工程师开发,拥有股票的回测,检测交易策略,支持期货实时交易,对于股票交易还在完善,我尝试了pylagotrade,vn.py,发现backtrader功能强大,交易策略全面,一直想用zipline写交易策略,但是一直安装不上,很多地方需要改,目前在研究,但是我们也很幸运,很多量化平台都是建立在zipline上的比如聚宽,掘金等,还有一个微软开发的机器学习量化库qlib,我有空去研究研究,分享给大家。
我们看一下如何安装backtrader,我们wind安装按win+r,输入cmd,进入命令节目,输入py -m pip install backtrader,但是安装会比较慢,我们通过清华大学的镜像来加速安装,安装如下,输入
后面我会边学习边介绍每个模块,以前学习过,但是现在有一些忘了,大三了,也快去实习了,打算仔细学习一下,后面我会结合量化平台聚宽进行量化分析,我在聚宽也写了一下文章。
需要回测程序关注微信公众号,数据分析与运用,回复macd量化回测就可以了
这里要重点提一下matplotlib安装版本最好为3.2.2,不然绘图会报错
py -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple matplotlib==3.2.2
我们看一下官网,主要包括,数据输入,大脑,优化指标,订单,经纪人等
下面我们看一下回测策略,我们交易策略为MACD主要交易点。
我结合了金融数据库,所以可以回测全部的股票,我们只要输入股票代码和数据开始时间就可以了,股票代码sz002466,天齐锂业,开始资金100万,交易费用0.003,也可以用于期货回测
我们输入回测开始时间比如20200601
我们就会看到数据回测,交易买卖的过程。
下面我们看到绘制的分析图片,结果还是很不错的,在股票下降的情况下,收益曲线平稳。
下面为程序代码。
量化回测
#北方稀土为例
#开始时间20210101
#结束时间20220217
#MACD交易策略,光头光脚阳线,光头光脚阴线交易策略
#测试资金100万,交易费用0.003
import pandas as pd
import akshare as ak
import matplotlib.pyplot as plt
import backtrader as bt
import datetime
import akshare as ak
import PySimpleGUI as sg
stock=sg.popup_get_file('输入股票代码比如sz002466')
start_date=sg.popup_get_file('输入开始时间比如20210101')
df=ak.stock_zh_a_daily(symbol=stock,start_date=start_date)
df.to_excel(r'C:\Users\Administrator\Desktop\天齐锂业.xlsx')
#写策略
class teststrategy(bt.Strategy):
#记录函数
def log(self,txt,dt=None):
dt=dt or self.datas[0].datetime.date(0)
print('%s, %s' % (dt.isoformat(), txt))
#初始化数据,私有类
def __init__(self):
self.dataclose=self.datas[0].close
self.dataopen=self.datas[0].open
self.datalow=self.datas[0].low
self.datahigh=self.datas[0].high
self.ma5=bt.indicators.MovingAverageSimple(self.dataclose,period=5)
self.ma10=bt.indicators.MovingAverageSimple(self.dataclose,period=10)
self.ma20=bt.indicators.MovingAverageSimple(self.dataclose,period=20)
self.MACD=bt.indicators.MACD(self.datas[0])
self.macd=self.MACD.macd
self.signal=self.MACD.signal
self.rsi=bt.indicators.RSI(self.datas[0])
self.boll=bt.indicators.BollingerBands(self.datas[0])
self.atr=bt.indicators.ATR(self.datas[0])
self.order=None
self.buyprice=None
self.comm=None
#交易状态检测
def notify_order(self,order):
if order.status in [order.Submitted,order.Accepted]:
return
if order.status in [order.Completed]:
if order.isbuy():
self.log('买进的价格 %.2f,账户值;%.2f,交易费用:%.2f' % (order.executed.price,order.executed.value,order.executed.comm))
self.buyprice = order.executed.price
self.buycomm = order.executed.comm
if order.issell():
self.log('卖出的价格 %.2f,账户值;%.2f,交易费用:%.2f' % (order.executed.price,order.executed.value,order.executed.comm))
elif order.status in [order.Canceled, order.Margin, order.Rejected]:
self.log('交易取消,资金不足,交易拒接')
#交易完统计
def notify_trade(self,trade):
if not trade.isclosed:
return
self.log('利润:%.2f,总利润: %.2f' %(trade.pnl,trade.pnlcomm))
#交易函数
def next(self):
#低位金叉买入
if self.macd[-1]
if self.macd[0]>self.signal[0]:
if self.macd[0]<0:
self.buy(size=500)
self.log('MACD低位金叉买入价格:%.2f' % self.dataclose[0])
#正常金叉买价
if self.macd[-1]
if self.macd[0]>self.signal[0]:
if self.macd[0]==0:
self.buy(size=500)
self.log('MACD正常金叉买入价格:%.2f' % self.dataclose[0])
#高位金叉买价,高位金叉有加速上升的作用
if self.macd[-1]
if self.macd[0]>self.signal[0]:
if self.macd[0]>0:
self.buy(size=500)
self.log('MACD高位金叉买入价格:%.2f' % self.dataclose[0])
#高位死叉卖出
if self .macd[-1]>self.signal[-1]:
if self.macd[0]
if self.macd[0]>=0:
self.sell(size=200)
self.log('MACD高位死叉卖出价格:%.2f' % self.dataclose[0])
#低位死叉卖出,和死叉减创
if self.macd[-1]
if self.macd[0]>self.signal[0]:
if self.macd[0]<0:
self.buy(size=500)
self.log('MACD低位金叉卖出价格:%.2f' % self.dataclose[0])
#低位死叉,加速下降卖出
if self .macd[-1]>self.signal[-1]:
if self.macd[0]
if self.macd[0]<0:
self.sell(size=200)
self.log('MACD低位死叉卖出价格:%.2f' % self.dataclose[0])
#macd下降趋势卖出
if (self.macd[-1]-self.signal[-1])>(self.macd[0]-self.signal[0]):
if self.signal[0]>self.macd[0]:
self.buy(size=100)
self.log('MACD下降趋势卖出价格:%.2f' % self.dataclose[0])
#macd上涨趋势买入
if (self.macd[-1]-self.signal[-1])<(self.macd[0]-self.signal[0]):
if self.signal[0]
self.buy(size=100)
self.log('MACD上升趋势买入价格:%.2f' % self.dataclose[0])
#光头光脚大阳线买入
if self.dataopen[0]==self.datalow[0] and self.dataclose[0]==self.datahigh[0] and self.dataclose[0]>self.dataopen[0]:
self.buy(size=500)
self.log('光头光脚阳线买入,价格 %.2f' % self.dataclose[0])
#光头光脚大阴线卖出
if self.dataopen[0]==self.datahigh[0] and self.dataclose[0]==self.datalow[0] and self.dataopen[0]>self.dataclose[0]:
self.sell(size=100)
self.log('光头光脚大阴线卖出,价格 %.2f' % self.dataclose[0])
#底背离
#顶背离有空写
if __name__ == "__main__":
cerebro=bt.Cerebro()
cerebro.broker.set_cash(1000000)
cerebro.broker.setcommission(0.003)
#添加数据
df.index=pd.to_datetime(df['date'])
#,fromdate=datetime.datetime(2021,10,1),todate=datetime.datetime(2022,2,17)
data=bt.feeds.PandasData(dataname=df)
cerebro.adddata(data)
cerebro.addstrategy(teststrategy)
cerebro.run(runonce=False)
print('最终的值',cerebro.broker.getvalue())
cerebro.plot(style='candle')
plt.show()