战雄电竞决赛

Backtrader  is an open-source python framework for trading and backtesting. Backtrader allows you to focus on writing reusable trading strategies, indicators, and analyzers instead of having to spend time building infrastructure.

I think of Backtrader as a Swiss Army Knife for backtesting. It supports live trading and quick analysis of trading strategies. I used to use Backtrader for my live trading and backtesting.

Backtrader also has  great documentation  and an  active trading community . You can download the code from this post at the  Analyzing Alpha Github .

Backtrader Installation

You’ll want to create a conda or pip environment, and then install the packages you’ll be using. I’m adding Pandas and SQLAlchemy as I’ll be using data from my local securities database .

If you’re interested in building from source, check out the  Backtrader installation guide .

													
													conda create --name backtrader conda activate backtrader conda install pandas matplotlib conda install -c anaconda sqlalchemy pip install backtrader
												
											

Using Backtrader: A Quick Overview

Let’s understand how to use Backtrader. If you run into any questions, read the  Backtrader quickstart . Most of what I’ve written about here can be found there.

Developing and testing a trading strategy in Backtrader generally follows five steps:

  1. Initialize the engine
  2. Configure the broker
  3. Add the data
  4. Create the strategy
  5. Analyze the performance

Initialize the Engine

Below we import backtrader and then instantiate an instance of it using backtrader.Cerebro(). We then check to see if our program backtrader_initialize.py is the main programming running. If it isn’t and our program was imported into another program, the name wouldn’t be main, it would be __name__ == backtrader_initialize.

Configure the Broker

Instantiating backtrader using backtrader.Cerebro() creates a broker instance in the background for convenience. We set the starting balance to $1,337.00. If we didn’t set the cash, the default balance is 10k. While we only set the cash on our broker instance, the  Backtrader broker  is robust and supports different order types,  slippage  models, and commission schemes.

												
												import backtrader as bt if __name__ == '__main__': cerebro = bt.Cerebro() cerebro.broker.setcash(1337.0) print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue()) cerebro.run() print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
											
										

Add the Data

Backtrader provides a bunch of built-in data feed options and the ability to create your own. For instance, we can easily add Yahoo Finance data by adding feeds.YahooFinanceData.

Adding Data from Yahoo

											
											data = bt.feeds.YahooFinanceData(dataname='AAPL', fromdate=datetime(2017, 1, 1), todate=datetime(2017, 12, 31))
										
									

Adding Yahoo CSV Data

We could have also added the Yahoo data from a CSV file.

										
										data = btfeeds.YahooFinanceCSVData(dataname='yahoo_finance_aapl.csv')
									
								

Adding Data from Pandas

For those of you that follow my blog, you know that I enjoy using Python & Pandas . We can  create a Pandas Datafeed in Backtrader  by inheriting it from the base class feed.DataBase.

An example using data from PostgreSQL and Pandas is shown in the Connors RSI indicator :

									
									class PandasData(feed.DataBase): ''' The ``dataname`` parameter inherited from ``feed.DataBase`` is the pandas DataFrame ''' params = ( # Possible values for datetime (must always be present) # None : datetime is the "index" in the Pandas Dataframe # -1 : autodetect position or case-wise equal name # >= 0 : numeric index to the colum in the pandas dataframe # string : column name (as index) in the pandas dataframe ('datetime', None), # Possible values below: # None : column not present # -1 : autodetect position or case-wise equal name # >= 0 : numeric index to the colum in the pandas dataframe # string : column name (as index) in the pandas dataframe ('open', -1), ('high', -1), ('low', -1), ('close', -1), ('volume', -1), ('openinterest', -1), )
								
							

Backtrader Strategy Examples

Now that Cerebro has data let’s create a few strategies. Strategies generally follow a four-step process:

  1. Initiation
  2. Pre-processing
  3. Processing
  4. Post-processing

Pre-processing occurs because we need to process 15 bars (period=15) before we can use our simple moving average indicator . Once the pre-processing has been completed, processing will start and will call next.

								
								class MyStrategy(bt.Strategy): def __init__(self): # Initiation self.sma = btind.SimpleMovingAverage(period=15) # Processing def next(self): # Processing if self.sma > self.data.close: # Do something pass elif self.sma < self.data.close: # Post-processing # Do something else pass
							
						

Dual Moving Average (DMA) Strategy

If you’re going to follow along with me, you’ll need to install the requests module to grab data from Yahoo Finance.

							
							conda install requests
						
					

The first strategy is a simple dual moving average (DMA) strategy trading Apple (AAPL) for 2017. We start with $1,337.00 and end with $1,354.77. As you can see, the code to create a DMA strategy in Backtrader is more simple than in the Zipline DMA strategy , but as stated previously, the return analysis is more simplistic, too.

						
						from datetime import datetime import backtrader as bt class SmaCross(bt.SignalStrategy): def __init__(self): sma1, sma2 = bt.ind.SMA(period=10), bt.ind.SMA(period=20) crossover = bt.ind.CrossOver(sma1, sma2) self.signal_add(bt.SIGNAL_LONG, crossover) if __name__ == '__main__': cerebro = bt.Cerebro() cerebro.addstrategy(SmaCross) cerebro.broker.setcash(1337.0) cerebro.broker.setcommission(commission=0.001) data = bt.feeds.YahooFinanceData(dataname='AAPL', fromdate=datetime(2017, 1, 1), todate=datetime(2017, 12, 31)) cerebro.adddata(data) print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue()) cerebro.run() print('Ending Portfolio Value: %.2f' % cerebro.broker.getvalue()) cerebro.plot()
					
				

Donchain Channels Strategy

Donchian channels are not implemented in Backtrader, so we need to create an indicator by inheriting from backtrader.Indicator.  Donchain channels  are named after Richard Donchain and can be used in a variety of ways, but are most often used to buy breakouts. We inherit bt.Indicator to create the DonchainChannels class, and code up the logic. We buy when the price breaks through the 20-period high and sell when the price drops below the 20-period low. We can also add graphing through plotlines as seen below.

					
					from datetime import datetime import backtrader as bt class DonchianChannels(bt.Indicator): ''' Params Note: - `lookback` (default: -1) If `-1`, the bars to consider will start 1 bar in the past and the current high/low may break through the channel. If `0`, the current prices will be considered for the Donchian Channel. This means that the price will **NEVER** break through the upper/lower channel bands. ''' alias = ('DCH', 'DonchianChannel',) lines = ('dcm', 'dch', 'dcl',) # dc middle, dc high, dc low params = dict( period=20, lookback=-1, # consider current bar or not ) plotinfo = dict(subplot=False) # plot along with data plotlines = dict( dcm=dict(ls='--'), # dashed line dch=dict(_samecolor=True), # use same color as prev line (dcm) dcl=dict(_samecolor=True), # use same color as prev line (dch) ) def __init__(self): hi, lo = self.data.high, self.data.low if self.p.lookback: # move backwards as needed hi, lo = hi(self.p.lookback), lo(self.p.lookback) self.l.dch = bt.ind.Highest(hi, period=self.p.period) self.l.dcl = bt.ind.Lowest(lo, period=self.p.period) self.l.dcm = (self.l.dch + self.l.dcl) / 2.0 # avg of the above class MyStrategy(bt.Strategy): def __init__(self): self.myind = DonchianChannels() def next(self): if self.data[0] > self.myind.dch[0]: self.buy() elif self.data[0] < self.myind.dcl[0]: self.sell() if __name__ == '__main__': cerebro = bt.Cerebro() cerebro.addstrategy(MyStrategy) cerebro.broker.setcash(1337.0) cerebro.broker.setcommission(commission=0.001) data = bt.feeds.YahooFinanceData(dataname='AAPL', fromdate=datetime(2017, 1, 1), todate=datetime(2017, 12, 31)) cerebro.adddata(data) print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue()) cerebro.run() print('Ending Portfolio Value: %.2f' % cerebro.broker.getvalue()) cerebro.plot()
				
			

Connors RSI Strategy Using Pandas

Created by Larry Connors,  Connors RSI Strategy  three different indicators together. We will sell if the Connors RSI hits 90 and buy if it reaches 10. If you want to follow this strategy, you’ll need to create an equity database and import the stock data using Python .

				
				from datetime import datetime import backtrader as bt import pandas as pd import sqlalchemy import setup_psql_environment from models import Security, SecurityPrice class Streak(bt.ind.PeriodN): ''' Keeps a counter of the current upwards/downwards/neutral streak ''' lines = ('streak',) params = dict(period=2) # need prev/cur days (2) for comparisons curstreak = 0 def next(self): d0, d1 = self.data[0], self.data[-1] if d0 > d1: self.l.streak[0] = self.curstreak = max(1, self.curstreak + 1) elif d0 < d1: self.l.streak[0] = self.curstreak = min(-1, self.curstreak - 1) else: self.l.streak[0] = self.curstreak = 0 class ConnorsRSI(bt.Indicator): ''' Calculates the ConnorsRSI as: - (RSI(per_rsi) + RSI(Streak, per_streak) + PctRank(per_rank)) / 3 ''' lines = ('crsi',) params = dict(prsi=3, pstreak=2, prank=100) def __init__(self): # Calculate the components rsi = bt.ind.RSI(self.data, period=self.p.prsi) streak = Streak(self.data) rsi_streak = bt.ind.RSI(streak.data, period=self.p.pstreak) prank = bt.ind.PercentRank(self.data, period=self.p.prank) # Apply the formula self.l.crsi = (rsi + rsi_streak + prank) / 3.0 class MyStrategy(bt.Strategy): def __init__(self): self.myind = ConnorsRSI() def next(self): if self.myind.crsi[0] <= 10: self.buy() elif self.myind.crsi[0] >= 90: self.sell() if __name__ == '__main__': cerebro = bt.Cerebro() cerebro.broker.setcash(1337.0) cerebro.broker.setcommission(commission=0.001) db = setup_psql_environment.get_database() session = setup_psql_environment.get_session() query = session.query(SecurityPrice).join(Security). \ filter(Security.ticker == 'AAPL'). \ filter(SecurityPrice.date >= '2017-01-01'). \ filter(SecurityPrice.date <= '2017-12-31').statement dataframe = pd.read_sql(query, db, index_col='date', parse_dates=['date']) dataframe = dataframe[['adj_open', 'adj_high', 'adj_low', 'adj_close', 'adj_volume']] dataframe.columns = columns = ['open', 'high', 'low', 'close', 'volume'] dataframe['openinterest'] = 0 dataframe.sort_index(inplace=True) data = bt.feeds.PandasData(dataname=dataframe) cerebro.adddata(data) cerebro.addstrategy(MyStrategy) print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue()) cerebro.run() print('Ending Portfolio Value: %.2f' % cerebro.broker.getvalue()) cerebro.plot()
			
		

Backtrader enables visual strategy analysis by using matplotlib to visualize the results . It’s easy to craft a strategy and quickly plot it using cerebro.plot() before putting the strategy through further analysis in Zipline. There are multiple options when  plotting in Backtrader .

Backtrader Alternatives

While I’m not an expert on the following tools, I’ve heard good things about QuantConnect and QuantRocket from the community.

You can see how I reviewed them and more in the best python trading tools .

Leave a Comment

CCG电子竞技比赛竞猜app下载 365电竞观看全球 英雄联盟竞猜比分入口 fifa电竞(长春)手游外围1.4.10 英雄联盟竞猜数据抽注 电竞体育(武汉)观看全球网址