backtrader量化回测----基础使用1,附完整代码

今天我们体测完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 btif __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.00Final Portfolio Value: 10000.00

在此示例中:反向交易者被导入,Cerebro 引擎已实例化,生成的 cerebro 实例被告知运行(循环数据),结果被打印出来,虽然看起来不多,但让我们指出一些明确显示的内容:,Cerebro 引擎已在后台创建了一个代理实例,该实例已开始有一些现金,这种幕后经纪人实例化是平台中简化用户生活的一个不变特征。如果用户未设置任何代理,那么将放置一个缺省代理。10K货币单位是一些经纪人的常用值。

下面为生长现金代码,cerebro.set_cash(1000000)​​​​​​​

import backtrader as btif __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 objectsimport os.path  # To manage pathsimport sys  # To find out the script name (in argv[0])# Import the backtrader platformimport backtrader as btif __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 objectsimport os.path  # To manage pathsimport sys  # To find out the script name (in argv[0])# Import the backtrader platformimport backtrader as bt# Create a Strateyclass 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 objectsimport os.path  # To manage pathsimport sys  # To find out the script name (in argv[0])# Import the backtrader platformimport backtrader as bt# Create a Strateyclass 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.002000-01-03, Close, 27.852000-01-04, Close, 25.392000-01-05, Close, 24.052000-01-05, BUY CREATE, 24.052000-01-06, Close, 22.632000-01-06, BUY CREATE, 22.632000-01-07, Close, 24.37......2000-12-20, BUY CREATE, 26.882000-12-21, Close, 27.822000-12-22, Close, 30.062000-12-26, Close, 29.172000-12-27, Close, 28.942000-12-27, BUY CREATE, 28.942000-12-28, Close, 29.292000-12-29, Close, 27.41Final 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 pdimport matplotlib.pyplot as pltimport backtrader as btimport backtrader.feeds as btfeedimport backtrader.indicators as btindfrom backtrader import analyzersimport pyalgotradeimport  PySimpleGUI as sgimport akshare as akimport pandas as pdimport datetimestock=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()
股票回测量化交易中非常重要的一环,它可以通过历史数据对交易策略进行模拟和评估,从而评估策略的可行性和优劣性。在Python中,有很多开源的量化交易框架可以用来进行股票回测,如zipline、backtrader等。 下面是一个使用zipline框架进行简单交易策略回测的例子: 1. 安装zipline ```python pip install zipline ``` 2. 编写交易策略代码 ```python from zipline.api import order_target_percent, record, symbol def initialize(context): context.asset = symbol('AAPL') def handle_data(context, data): # 获取过去10天的收盘价 prices = data.history(context.asset, 'price', 10, '1d') # 计算平均价 mean_price = prices.mean() # 如果当前价格低于平均价,则买入 if data.current(context.asset, 'price') < mean_price: # 调整持仓比例至100% order_target_percent(context.asset, 1.0) # 否则卖出 else: # 调整持仓比例至0% order_target_percent(context.asset, 0.0) # 记录当前持仓比例 record(position=context.portfolio.positions[context.asset].amount) ``` 3. 运行回测 ```python from zipline import run_algorithm from zipline.api import symbol from datetime import datetime start = datetime(2016, 1, 1) end = datetime(2017, 1, 1) result = run_algorithm( start=start, end=end, initialize=initialize, capital_base=10000, handle_data=handle_data, bundle='quandl' ) ``` 在上述代码中,我们定义了一个简单的交易策略,即如果当前价格低于过去10天的平均价,则买入,否则卖出。然后我们使用zipline框架进行回测,设定回测开始和结束时间、初始资本、数据来源等参数,最终得到回测结果。 需要注意的是,这只是一个简单的例子,实际的交易策略可能会更加复杂,需要考虑更多的因素。另外,在进行股票回测时,也需要注意避免过度拟合或过度优化,以免出现回测虚高的情况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_50882340

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值