导包

#引入技术指标数据
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框架
%matplotlib inline

策略

#创建策略
class TestStrategy(bt.Strategy):params = (('maperiod1',5),('maperiod2',13),('maperiod3',21),('maperiod4',34),('maperiod5',55),('printlog',True),('poneplot' , False),#是否打印到同一张图('pstake' , 100000) #单笔交易股票数据)def log(self,txt,dt=None,doprint = False):dt = dt or self.datas[0].datetime.date(0)#print('%s,%s' % (dt.isoformat(),txt))"""策略的日志函数"""if self.params.printlog or doprint:dt = dt or self.datas[0].datetime.date(0)print('%s,%s' % (dt.isoformat(),txt))def __init__(self):self.inds = dict()for i, d in enumerate(self.datas):self.inds[d] = dict()self.inds[d]['ma1'] = bt.indicators.SimpleMovingAverage( d.close,period = self.params.maperiod1)self.inds[d]['ma2'] = bt.indicators.SimpleMovingAverage( d.close,period = self.params.maperiod2)self.inds[d]['ma3'] = bt.indicators.SimpleMovingAverage( d.close,period = self.params.maperiod3)self.inds[d]['ma4'] = bt.indicators.SimpleMovingAverage( d.close,period = self.params.maperiod4)self.inds[d]['ma5'] = bt.indicators.SimpleMovingAverage( d.close,period = self.params.maperiod5)self.inds[d]['D1'] = bt.ind.CrossOver(self.inds[d]['ma5'],self.inds[d]['ma4']) #交叉信号self.inds[d]['A1'] = bt.ind.CrossOver(self.inds[d]['ma1'],self.inds[d]['ma2']) #交叉信号   self.inds[d]['C1'] = bt.ind.CrossOver(self.inds[d]['ma2'],self.inds[d]['ma3'])#跳过第一只股票data,第一只股票data作为主图数据if i > 0:if self.p.poneplot:d.plotinfo.plotmaster = self.datas[0]def notify_trade(self,trade):if not trade.isclosed:returnself.log('OPERATION PROFIT,GROSS %.2F,NET %.2F' %(trade.pnl,trade.pnlcomm))#多股回测时使用,数据读取。 def prenext(self):self.next()def next(self):# 获取当天日期date = self.datas[0].datetime.date(0)# 获取当天valuevalue = self.broker.getvalue()for i , d in enumerate(self.datas):            dt,dn = self.datetime.date(),d._name             #获取时间及股票代码        pos = self.getposition(d).size sig1 = ((self.inds[d]['D1'][-1]>0) and (self.inds[d]['A1'][0]>0)) and (self.inds[d]['ma2'][0] >self.inds[d]['ma4'][0])and (self.inds[d]['ma4'][0] >self.inds[d]['ma4'][-1])sig2 = ((self.inds[d]['D1'][-1]>0)  or (self.inds[d]['A1'][0]>0 ))and(self.inds[d]['ma2'][0] >self.inds[d]['ma2'][-1])and(d.close[0]/d.open[0]>1.05)and(d.volume[0] /d.volume[-1]>2)sig3 = ((self.inds[d]['D1'][-1]>0)  or (self.inds[d]['A1'][0]>0 ))and(self.inds[d]['ma2'][0] >self.inds[d]['ma3'][0] )and(self.inds[d]['ma3'][0] >self.inds[d]['ma4'][0] )and(self.inds[d]['ma4'][0] >self.inds[d]['ma4'][-1] )sig4 = self.inds[d]['C1'][0]<0#print('sig1',sig1)if not pos:                                      # 不在场内,则可以买入  vol成交量, ref日前if sig1 or sig2 and sig3: #如果金叉self.buy(data =d,size =self.p.pstake)    #买self.log('%s,BUY CREATE, %.2f ,%s' % (dt, d.close[0] ,d._name))#self.order = self.buy()elif sig4:              #在场内。且死叉self.close(data = d)                     #卖self.log('%s,SELL CREATE,%.2f,%s' % (dt, d.close[0] ,d._name))#self.order = self.sell()

印花税

class stampDutyCommissionScheme(bt.CommInfoBase):params = (('stamp_duty',0.005),#印花税率('percabs',True),)def _gotcommission(self,size,price,pseudoexec):if size >0:#买入,不考虑印花税return size*price * self.p.commissionelif size<0:#卖出,考虑印花税return -size*price*(self.p.stamp_duty + self.p.commission)else:return 0

开始回测

#创建cerebro实体
cerebro = bt.Cerebro()
#添加策略
cerebro.addstrategy(TestStrategy)

添加数据

#创建价格数据
import akshare as ak
import baostock as bs
import pandas as pd
import datetime#获取股票池数据
from os import listdir
filename = listdir('D:/stock_data')
stk_pools = filenamefor i in stk_pools[:]:try:datapath = 'D:/stock_data/'+idf = pd.read_csv('D:/stock_data/'+i)#将数据长度不足的股票删去if len(df)<55:passelse:try:data = bt.feeds.GenericCSVData(dataname = datapath,fromdate = datetime.datetime(2010,4,1),todate = datetime.datetime(2021,7,8),nullvalue = 0.0,dtformat = ('%Y-%m-%d'),datetime = 1,open =2,high = 3,low = 4,close = 5,volume = 6,openinterest = -1)cerebro.adddata(data,name = i)except:continue except:continue

设置参数

#设置启动资金
cerebro.broker.setcash(len(stk_pools[:50])*10000)
#设置交易单位大小
cerebro.addsizer(bt.sizers.FixedSize,stake = 100)
#设置佣金为千分之一
comminfo = stampDutyCommissionScheme(stamp_duty=0.005,commission=0.001)
cerebro.broker.addcommissioninfo(comminfo)
#不显示曲线
for d in cerebro.datas:d.plotinfo.plot = False
#打印开始信息
print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())

回测数据分析

#查看策略效果
cerebro.addanalyzer(bt.analyzers.PyFolio, _name='pyfolio')
back  = cerebro.run(maxcpus=12,exactbars=True,stdstats=False)import warnings
warnings.filterwarnings('ignore')
strat = back[0]
portfolio_stats = strat.analyzers.getbyname('pyfolio')
returns, positions, transactions, gross_lev = portfolio_stats.get_pf_items()
returns.index = returns.index.tz_convert(None)import quantstats
quantstats.reports.html(returns, output='stats.html', title='Stock Sentiment')import webbrowser
f = webbrowser.open('stats.html')
#打印最后结果
print('Final Profolio Value : %.2f' %cerebro.broker.getvalue())

多股回测(backtrader+quantstats+akshare)相关推荐

  1. Python 量化投资原来这么简单(5) — A股回测KDJ策略

    许多技术投资方面的教材,经常会用几幅上涨的图来表明某些指标的用处,实际上那些上涨的图很可能只是假象.作者为了证明他所强调的指标的作用,选定了符合该指标策略的股票上升趋势图,但实际上这些策略并不一定适合 ...

  2. Python 量化投资实战教程(3) —A股回测MACD策略

    量化投资系列文章: Backtrader 教程 - Python 量化投资实战教程(1) Python 量化投资实战教程(2) -MACD策略(+26.9%) Python 量化投资实战教程(3) - ...

  3. Python量化交易学习笔记(36)——backtrader多股回测避坑3

    本文继续记录多股回测时可能遇到的异常情况. 坑描述 多股回测时,当日期达到所有股票的技术指标都能够计算出有效值后,backtrader才开始进行回测.由于这种逻辑的存在,如果某些股票在回测周期的最后几 ...

  4. A股回测“孕线”策略 — Python 量化投资实战教程(8)

    上一篇系列文章<Python 量化投资实战教程(7)-孕线真的有用吗?>中我们讲到了孕线的形态和其基本的量化规则. 不过,当时只是基于一支股票对这个策略进行回测,数据量过少,其结果并不具有 ...

  5. Quantopian 做多大市值科技和消费周期股,做空小市值和消费周期股回测

    源码 from quantopian.pipeline import Pipeline from quantopian.algorithm import attach_pipeline, pipeli ...

  6. Backtrader 策略回测初探

    Backtrader 策略回测初探 这篇介绍简单的回测流程,主要的内容如下: 回测函数介绍 单股回测 多股回测 回测函数 回测策略类很简洁,直接继承 bt.Strategy ,复写父类的方法,最后把回 ...

  7. 自己做量化交易软件(35)小白量化实战8--事件型回测程序

    自己做量化交易软件(35)小白量化实战8–事件型回测程序 小白量化第二代程序也提供了一个简单的事件型回测程序,我们前面的博客文章有介绍这方面的知识.当时用MT5 做的回测演示,见文章:自己做量化交易软 ...

  8. 【手把手教你】基于均线排列的价格动量策略回测

    01 引言 动量策略是通过利用市场波动从现有趋势的延续中获利.简单来说,高买高卖,反之亦然("低买高卖"是均值回归策略思想,与动量策略相反).价值投资通常基于均值的长期回归,而动量 ...

  9. 量化策略——准备3 数据、Backtrader回测框架与quantstats评价指标

    我们一般使用AKShare这个库来获取股票数据或策略中用得到的数据: AKShare github主页:https://github.com/akfamily/akshare 使用Backtrader ...

最新文章

  1. 如何实现对ELK各组件的监控?试试Metricbeat
  2. 物种丰度排序堆积柱形图及处理间各物种差异分析
  3. Debian/Ubuntu/Raspbian 时间同步
  4. Gartner对于建设「数据中台」的建议
  5. python手机版安卓-当python遇到Android手机 那么,万物皆可盘
  6. 字符串的第n个排列的算法
  7. Dubbo的Zookeeper版本
  8. [Qt教程] 第38篇 网络(八)TCP(二)
  9. mysql 8.0.19 winx64安装及修改初始密码
  10. linux下c语言scanf,C语言输入scanf
  11. Pytorch class 中 的__call__方法
  12. python网易云_python 网易云音乐
  13. GoLang的安装和使用
  14. 【NOI2011】 阿狸的打字机(AC自动机+树状数组)
  15. 长期不上班,人会废掉吗?
  16. Python学习Day01
  17. 海洋CMS采集-内置接口的海洋CMS采集
  18. 微信小程序接入环信客服
  19. day01血字的研究
  20. 香蕉皮的妙用(想歪的去面壁)(不管有没有用,先记下再说)

热门文章

  1. 《Python Cookbook 3rd》笔记(1.2):拆分任意长可迭代对象后赋值给多个变量
  2. python用pip安装pillow_cent 6.5使用pip安装pillow总是失败
  3. google浏览器 隐藏功能开启
  4. 开源是如何让Android成为移动市场大佬的?
  5. 八个实用的CMD命令及开始→运行→命令集锦
  6. linux :Docker 方式 安装 zookeeper、阿里服务器上 Docker 运行 zookeeper
  7. JNA—JNI终结者
  8. PHP环境搭建和Apache HTTP服务器配置
  9. equals和==的区别(转)
  10. 设计模式--23、访问者模式