今天我们体测完1000米感觉人都要废了,目前在学习天勤量化,但是我还是打算仔细将这个量化框架介绍完,我们开始下面介绍来自官网,因为有时候官网打不开,我将仔细介绍,我们开始。
需要程序关注微信公众号,数据分析与运用,回复backtrader量化回测基础使用1就可以
因为文章比较长,我们自己看效果,我结合了金融数据库akshare,所以可以回测A股全部的股票,我们只需要输入股票代码,开始时间,开始资金就可以了。
下面为全部买卖点输出,收益率还是不错的
下面为绘制分析图,非常的好
下面我们介绍重要的概念线,可以同时开9条线,0代表目前的数据,-1代表昨天数据,-2代表前天数据。让我们来看看一系列的例子(从几乎空的到一个成熟的策略),但在粗略解释使用反向交易者时的2个基本概念之前,并非没有
线数据馈送、指标和策略都有线条。线是连接在一起形成此线的一系列点。在谈论市场时,数据馈送通常每天有以下几组点:打开”系列沿时间是一条线。因此,数据馈送通常有6行。如果我们还考虑“DateTime”(这是单个点的实际参考),我们可以数出7行。开盘, 高, 低, 收盘, 成交量, OpenInterest索引 0 方法访问行中的值时,将使用 index: 0 访问当前值并且使用-1访问“最后一个”输出值。这符合Python对可迭代的约定(一行可以被迭代,因此是可迭代的),其中索引-1用于访问迭代/数组的“最后一个”项。在我们的例子中,是最后一个被访问的输出值。因此,在 -1 之后是索引 0,它用于按行访问当前时刻。下面为一个简单的程序,获取账户值。
import backtrader as bt
if __name__ == '__main__':
cerebro = bt.Cerebro()
print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
cerebro.run()
print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
执行后输出的结果
Starting Portfolio Value: 10000.00
Final Portfolio Value: 10000.00
在此示例中:反向交易者被导入,Cerebro 引擎已实例化,生成的 cerebro 实例被告知运行(循环数据),结果被打印出来,虽然看起来不多,但让我们指出一些明确显示的内容:,Cerebro 引擎已在后台创建了一个代理实例,该实例已开始有一些现金,这种幕后经纪人实例化是平台中简化用户生活的一个不变特征。如果用户未设置任何代理,那么将放置一个缺省代理。10K货币单位是一些经纪人的常用值。
下面为生长现金代码,cerebro.set_cash(1000000)
import backtrader as bt
if __name__ == '__main__':
cerebro = bt.Cerebro()
cerebro.broker.setcash(100000.0)
print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
cerebro.run()
print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
下面为数据输入,官网的代码,也可以参考我的程序,数据怎么样输入以后会介绍,因为塔提供数据输入方式很多,代码如下
import datetime # For datetime objects
import os.path # To manage paths
import sys # To find out the script name (in argv[0])
# Import the backtrader platform
import backtrader as bt
if __name__ == '__main__':
# Create a cerebro entity
cerebro = bt.Cerebro()
# Datas are in a subfolder of the samples. Need to find where the script is
# because it could have been called from anywhere
modpath = os.path.dirname(os.path.abspath(sys.argv[0]))
datapath = os.path.join(modpath, '../../datas/orcl-1995-2014.txt')
# Create a Data Feed
data = bt.feeds.YahooFinanceCSVData(
dataname=datapath,
# Do not pass values before this date
fromdate=datetime.datetime(2000, 1, 1),
# Do not pass values after this date
todate=datetime.datetime(2000, 12, 31),
reverse=False)
# Add the Data Feed to Cerebro
cerebro.adddata(data)
# Set our desired cash start
cerebro.broker.setcash(100000.0)
# Print out the starting conditions
print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
# Run over everything
cerebro.run()
# Print out the final result
print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
我们已经有数据输入了,但是没有数据输出,我们定义数据输出函数,self.log(),我们选择输出收盘价。代码
import datetime # For datetime objects
import os.path # To manage paths
import sys # To find out the script name (in argv[0])
# Import the backtrader platform
import backtrader as bt
# Create a Stratey
class TestStrategy(bt.Strategy):
def log(self, txt, dt=None):
''' Logging function for this strategy'''
dt = dt or self.datas[0].datetime.date(0)
print('%s, %s' % (dt.isoformat(), txt))
def __init__(self):
# Keep a reference to the "close" line in the data[0] dataseries
self.dataclose = self.datas[0].close
def next(self):
# Simply log the closing price of the series from the reference
self.log('Close, %.2f' % self.dataclose[0])
if __name__ == '__main__':
# Create a cerebro entity
cerebro = bt.Cerebro()
# Add a strategy
cerebro.addstrategy(TestStrategy)
# Datas are in a subfolder of the samples. Need to find where the script is
# because it could have been called from anywhere
modpath = os.path.dirname(os.path.abspath(sys.argv[0]))
datapath = os.path.join(modpath, '../../datas/orcl-1995-2014.txt')
# Create a Data Feed
data = bt.feeds.YahooFinanceCSVData(
dataname=datapath,
# Do not pass values before this date
fromdate=datetime.datetime(2000, 1, 1),
# Do not pass values before this date
todate=datetime.datetime(2000, 12, 31),
# Do not pass values after this date
reverse=False)
# Add the Data Feed to Cerebro
cerebro.adddata(data)
# Set our desired cash start
cerebro.broker.setcash(100000.0)
# Print out the starting conditions
print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
# Run over everything
cerebro.run()
# Print out the final result
print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
我们已经有数据的输入了,但是我们没有交易策略运行数据下面我们看交易策略编写,我们在函数next下面写交易策略,我们的交易策略为上涨3天卖出,连续下跌3天买入。下面为官网的代码,也可以参考我的代码
import datetime # For datetime objects
import os.path # To manage paths
import sys # To find out the script name (in argv[0])
# Import the backtrader platform
import backtrader as bt
# Create a Stratey
class TestStrategy(bt.Strategy):
def log(self, txt, dt=None):
''' Logging function fot this strategy'''
dt = dt or self.datas[0].datetime.date(0)
print('%s, %s' % (dt.isoformat(), txt))
def __init__(self):
# Keep a reference to the "close" line in the data[0] dataseries
self.dataclose = self.datas[0].close
def next(self):
# Simply log the closing price of the series from the reference
self.log('Close, %.2f' % self.dataclose[0])
if self.dataclose[0] < self.dataclose[-1]:
# current close less than previous close
if self.dataclose[-1] < self.dataclose[-2]:
# previous close less than the previous close
# BUY, BUY, BUY!!! (with all possible default parameters)
self.log('BUY CREATE, %.2f' % self.dataclose[0])
self.buy()
if __name__ == '__main__':
# Create a cerebro entity
cerebro = bt.Cerebro()
# Add a strategy
cerebro.addstrategy(TestStrategy)
# Datas are in a subfolder of the samples. Need to find where the script is
# because it could have been called from anywhere
modpath = os.path.dirname(os.path.abspath(sys.argv[0]))
datapath = os.path.join(modpath, '../../datas/orcl-1995-2014.txt')
# Create a Data Feed
data = bt.feeds.YahooFinanceCSVData(
dataname=datapath,
# Do not pass values before this date
fromdate=datetime.datetime(2000, 1, 1),
# Do not pass values before this date
todate=datetime.datetime(2000, 12, 31),
# Do not pass values after this date
reverse=False)
# Add the Data Feed to Cerebro
cerebro.adddata(data)
# Set our desired cash start
cerebro.broker.setcash(100000.0)
# Print out the starting conditions
print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
# Run over everything
cerebro.run()
# Print out the final result
print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
下面为输出的结果
Starting Portfolio Value: 100000.00
2000-01-03, Close, 27.85
2000-01-04, Close, 25.39
2000-01-05, Close, 24.05
2000-01-05, BUY CREATE, 24.05
2000-01-06, Close, 22.63
2000-01-06, BUY CREATE, 22.63
2000-01-07, Close, 24.37
...
...
2000-12-20, BUY CREATE, 26.88
2000-12-21, Close, 27.82
2000-12-22, Close, 30.06
2000-12-26, Close, 29.17
2000-12-27, Close, 28.94
2000-12-27, BUY CREATE, 28.94
2000-12-28, Close, 29.29
2000-12-29, Close, 27.41
Final Portfolio Value: 99725.08
我们知道交易策略,但是我们不知道买卖点,什么时候买的所以我们需要定义交易状态检测函数如下
def notify_order(self, order):
if order.status in [order.Submitted, order.Accepted]:
# Buy/Sell order submitted/accepted to/by broker - Nothing to do
return
# Check if an order has been completed
# Attention: broker could reject order if not enough cash
if order.status in [order.Completed]:
if order.isbuy():
self.log('BUY EXECUTED, %.2f' % order.executed.price)
elif order.issell():
self.log('SELL EXECUTED, %.2f' % order.executed.price)
self.bar_executed = len(self)
elif order.status in [order.Canceled, order.Margin, order.Rejected]:
self.log('Order Canceled/Margin/Rejected')
# Write down: no pending order
self.order = None
下面为我写的基础使用完整的代码,供参考学习
#交易策略为连续下跌3天买入,连续上涨3天卖出
import pandas as pd
import matplotlib.pyplot as plt
import backtrader as bt
import backtrader.feeds as btfeed
import backtrader.indicators as btind
from backtrader import analyzers
import pyalgotrade
import PySimpleGUI as sg
import akshare as ak
import pandas as pd
import datetime
stock=sg.popup_get_file('输入股票代码比如sz002466')
start_date=sg.popup_get_file('输入数据开始时间比如20200101')
start_cash=sg.popup_get_file('输入开始资金比如1000000')
#定义测试类
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
#定义交易状态检测函数,交易前
def notify_order(self,order):
#如果交易提交/接受
if order.status in [order.Submitted,order.Accepted]:
print('交易提交,交易接受')
#如果交易完成
if order.status in [order.Completed]:
#如果交易类型是买
if order.isbuy():
self.log('买的价格, %.2f' % order.executed.price)
#如果交易类型是卖
elif order.issell():
self.log('卖的价格, %.2f' % order.executed.price)
self.bar_executed=len(self)
#如果交易交易取消,保证金不足,交易拒绝
elif order.status in [order.Canceled,order.Margin,order.Rejected]:
self.log('交易取消/保证金不足/交易拒绝')
self.order=None
#主交易函数
def next(self):
self.log('收盘价,%.2f' % self.dataclose[0])
#写交易函数,连续下跌3天买入,连续上涨3天卖出
#如果今天的价格小于昨天的价格
if self.dataclose[0]<self.dataclose[-1]:
#如果昨天的价格小于前天的价格
if self.dataclose[-1]<self.dataclose[-2]:
#记录买卖的价格
self.log('买的价格 %.2f' % self.dataclose[0])
self.buy(size=200)#单位为股,代表1手
elif self.dataclose[0]>self.dataclose[-1]:
if self.dataclose[-1]>self.dataclose[-2]:
self.log('卖出的价格 %.2f' %self.dataclose[0])
self.sell(size=100)
#简单例子
if __name__ == "__main__":
#将大脑实例化
cerebro=bt.Cerebro()
cerebro.addstrategy(testStrategy)
#加入数据
df=ak.stock_zh_a_daily(symbol=stock,start_date=start_date)
df.index=pd.to_datetime(df['date'])
data=btfeed.PandasData(dataname=df)
cerebro.adddata(data=data)
#设置开始资金
cerebro.broker.set_cash(int(start_cash))
#设置交易费用
cerebro.broker.setcommission(0.003)
print('开始值{}'.format(cerebro.broker.getvalue()))
cerebro.run()
print('最终值{}'.format(cerebro.broker.getvalue()))
cerebro.plot(style='candle')
plt.show()