Adding indicators to your trading strategy

In this post, we show how to add indicators in to your strategy.

  1. We add a simple indicator such as the Simple Moving Average (SMA)
  2. We apply a strategy that buys (sells) when the closing price of the bar is above (below) the SMA.
  3. We print the size of each position when a trade is executed.
  4. We add a x6 indicators to be added to the cerebro.plot() output.

The code additions here are in the following cells:

  1. Strategy Class

Import modules

In [1]:
import datetime
import os.path
import sys
import backtrader as bt
import matplotlib.pyplot as plt

Data

In [2]:
homepath = os.getenv('HOME')
datapath = os.path.join(homepath, 'github/backtrader/datas/orcl-1995-2014.txt')

data = bt.feeds.YahooFinanceCSVData(
    dataname=datapath,
    fromdate=datetime.datetime(2000,1,1),
    todate = datetime.datetime(2000,12,31),
    reverse=False)

Strategy Class

In the __init__ function, we add a Simple Moving Average (SMA) indicator. We inform the strategy that the SMA indicator should be based off the most current datapoint (i.e., self.datas[0]), and that the length of the moving average is based off the parameters maperiod which is set at 15. We also add a whole set of indicators using bt.indicators to be added to the backtest result plot function (i.e., cerebro.plot()).

In the next function, our strategy is such that when the current closing price is greater (less) than the SMA, we buy (sell).

In the notify function, we also print out the size of the order based on order.executed.size.

In [3]:
class Strat2_BGTMA_SLSMA(bt.Strategy):
    
    params = (
        ('maperiod',15), # Tuple of tuples containing any variable settings required by the strategy.
    )
    
    def __init__(self):
        self.dataclose= self.datas[0].close    # Keep a reference to the "close" line in the data[0] dataseries
        self.order = None # Property to keep track of pending orders.  There are no orders when the strategy is initialized.
        self.buyprice = None
        self.buycomm = None
        
        # Add SimpleMovingAverage indicator for use in the trading strategy
        self.sma = bt.indicators.SimpleMovingAverage( 
            self.datas[0], period=self.params.maperiod)
        
        # Add ExpMA, WtgMA, StocSlow, MACD, ATR, RSI indicators for plotting.
        bt.indicators.ExponentialMovingAverage(self.datas[0], period=25)
        bt.indicators.WeightedMovingAverage(self.datas[0], period=25,subplot = True)
        bt.indicators.StochasticSlow(self.datas[0])
        bt.indicators.MACDHisto(self.datas[0])
        rsi = bt.indicators.RSI(self.datas[0])
        bt.indicators.SmoothedMovingAverage(rsi, period=10)
        bt.indicators.ATR(self.datas[0], plot = False)
    
    def log(self, txt, dt=None):
        # Logging function for the strategy.  'txt' is the statement and 'dt' can be used to specify a specific datetime
        dt = dt or self.datas[0].datetime.date(0)
        print('{0},{1}'.format(dt.isoformat(),txt))
    
    def notify_order(self, order):
        # 1. If order is submitted/accepted, do nothing 
        if order.status in [order.Submitted, order.Accepted]:
            return
        # 2. If order is buy/sell executed, report price executed
        if order.status in [order.Completed]: 
            if order.isbuy():
                self.log('BUY EXECUTED, Price: {0:8.2f}, Size: {1:8.2f} Cost: {2:8.2f}, Comm: {3:8.2f}'.format(
                    order.executed.price,
                    order.executed.size,
                    order.executed.value,
                    order.executed.comm))
                
                self.buyprice = order.executed.price
                self.buycomm = order.executed.comm
            else:
                self.log('SELL EXECUTED, {0:8.2f}, Size: {1:8.2f} Cost: {2:8.2f}, Comm{3:8.2f}'.format(
                    order.executed.price, 
                    order.executed.size, 
                    order.executed.value,
                    order.executed.comm))
            
            self.bar_executed = len(self) #when was trade executed
        # 3. If order is canceled/margin/rejected, report order canceled
        elif order.status in [order.Canceled, order.Margin, order.Rejected]:
            self.log('Order Canceled/Margin/Rejected')
            
        self.order = None
    
    def notify_trade(self,trade):
        if not trade.isclosed:
            return
        
        self.log('OPERATION PROFIT, GROSS {0:8.2f}, NET {1:8.2f}'.format(
            trade.pnl, trade.pnlcomm))
    
    def next(self):
        # Log the closing prices of the series from the reference
        self.log('Close, {0:8.2f}'.format(self.dataclose[0]))

        if self.order: # check if order is pending, if so, then break out
            return
                
        # since there is no order pending, are we in the market?    
        if not self.position: # not in the market
            if self.dataclose[0] > self.sma[0]:
                self.log('BUY CREATE {0:8.2f}'.format(self.dataclose[0]))
                self.order = self.buy()           
        else: # in the market
            if self.dataclose[0] < self.sma[0]:
                self.log('SELL CREATE, {0:8.2f}'.format(self.dataclose[0]))
                self.order = self.sell()

Backtest settings

In [4]:
cerebro = bt.Cerebro()  
cerebro.adddata(data) 
cerebro.addstrategy(Strat2_BGTMA_SLSMA, maperiod=15) 
cerebro.addsizer(bt.sizers.FixedSize,stake=10)
cerebro.broker.setcash(1000.0) 
cerebro.broker.setcommission(commission=0.0) 

Run backtest

We see that the Ending Portfolio Value is about $975 showing that the strategy is losing money.

In [5]:
print('Starting Portfolio Value: {0:8.2f}'.format(cerebro.broker.getvalue()))
cerebro.run()
print('Final Portfolio Value: {0:8.2f}'.format(cerebro.broker.getvalue()))
Starting Portfolio Value:  1000.00
2000-02-18,Close,    26.05
2000-02-22,Close,    26.38
2000-02-22,BUY CREATE    26.38
2000-02-23,BUY EXECUTED, Price:    26.77, Size:    10.00 Cost:   267.70, Comm:     0.00
2000-02-23,Close,    28.05
2000-02-24,Close,    27.55
2000-02-25,Close,    31.41
2000-02-28,Close,    30.52
2000-02-29,Close,    33.02
2000-03-01,Close,    31.80
2000-03-02,Close,    30.47
2000-03-03,Close,    33.36
2000-03-06,Close,    33.69
2000-03-07,Close,    33.33
2000-03-08,Close,    36.97
2000-03-09,Close,    37.36
2000-03-10,Close,    36.30
2000-03-13,Close,    35.02
2000-03-14,Close,    34.25
2000-03-15,Close,    34.97
2000-03-16,Close,    36.44
2000-03-17,Close,    35.50
2000-03-20,Close,    34.75
2000-03-21,Close,    35.89
2000-03-22,Close,    37.39
2000-03-23,Close,    38.64
2000-03-24,Close,    38.69
2000-03-27,Close,    39.33
2000-03-28,Close,    38.50
2000-03-29,Close,    36.69
2000-03-30,Close,    34.88
2000-03-30,SELL CREATE,    34.88
2000-03-31,SELL EXECUTED,    35.66, Size:   -10.00 Cost:   267.70, Comm    0.00
2000-03-31,OPERATION PROFIT, GROSS    88.90, NET    88.90
2000-03-31,Close,    34.72
2000-04-03,Close,    34.19
2000-04-04,Close,    33.77
2000-04-05,Close,    34.80
2000-04-06,Close,    36.55
2000-04-06,BUY CREATE    36.55
2000-04-07,BUY EXECUTED, Price:    37.22, Size:    10.00 Cost:   372.20, Comm:     0.00
2000-04-07,Close,    38.75
2000-04-10,Close,    36.69
2000-04-11,Close,    34.41
2000-04-11,SELL CREATE,    34.41
2000-04-12,SELL EXECUTED,    34.66, Size:   -10.00 Cost:   372.20, Comm    0.00
2000-04-12,OPERATION PROFIT, GROSS   -25.60, NET   -25.60
2000-04-12,Close,    32.52
2000-04-13,Close,    31.99
2000-04-14,Close,    27.80
2000-04-17,Close,    33.27
2000-04-18,Close,    35.11
2000-04-18,BUY CREATE    35.11
2000-04-19,BUY EXECUTED, Price:    34.97, Size:    10.00 Cost:   349.70, Comm:     0.00
2000-04-19,Close,    33.16
2000-04-19,SELL CREATE,    33.16
2000-04-20,SELL EXECUTED,    32.83, Size:   -10.00 Cost:   349.70, Comm    0.00
2000-04-20,OPERATION PROFIT, GROSS   -21.40, NET   -21.40
2000-04-20,Close,    31.49
2000-04-24,Close,    32.22
2000-04-25,Close,    33.61
2000-04-26,Close,    32.11
2000-04-27,Close,    34.38
2000-04-27,BUY CREATE    34.38
2000-04-28,BUY EXECUTED, Price:    34.91, Size:    10.00 Cost:   349.10, Comm:     0.00
2000-04-28,Close,    35.55
2000-05-01,Close,    35.44
2000-05-02,Close,    34.61
2000-05-03,Close,    33.72
2000-05-04,Close,    33.02
2000-05-04,SELL CREATE,    33.02
2000-05-05,SELL EXECUTED,    32.91, Size:   -10.00 Cost:   349.10, Comm    0.00
2000-05-05,OPERATION PROFIT, GROSS   -20.00, NET   -20.00
2000-05-05,Close,    34.16
2000-05-05,BUY CREATE    34.16
2000-05-08,BUY EXECUTED, Price:    33.49, Size:    10.00 Cost:   334.90, Comm:     0.00
2000-05-08,Close,    32.16
2000-05-08,SELL CREATE,    32.16
2000-05-09,SELL EXECUTED,    32.77, Size:   -10.00 Cost:   334.90, Comm    0.00
2000-05-09,OPERATION PROFIT, GROSS    -7.20, NET    -7.20
2000-05-09,Close,    32.02
2000-05-10,Close,    30.08
2000-05-11,Close,    32.19
2000-05-12,Close,    32.99
2000-05-15,Close,    34.25
2000-05-15,BUY CREATE    34.25
2000-05-16,BUY EXECUTED, Price:    34.52, Size:    10.00 Cost:   345.20, Comm:     0.00
2000-05-16,Close,    35.22
2000-05-17,Close,    34.77
2000-05-18,Close,    32.49
2000-05-18,SELL CREATE,    32.49
2000-05-19,SELL EXECUTED,    32.02, Size:   -10.00 Cost:   345.20, Comm    0.00
2000-05-19,OPERATION PROFIT, GROSS   -25.00, NET   -25.00
2000-05-19,Close,    31.16
2000-05-22,Close,    30.16
2000-05-23,Close,    27.85
2000-05-24,Close,    28.57
2000-05-25,Close,    29.55
2000-05-26,Close,    29.80
2000-05-30,Close,    32.99
2000-05-30,BUY CREATE    32.99
2000-05-31,BUY EXECUTED, Price:    32.58, Size:    10.00 Cost:   325.80, Comm:     0.00
2000-05-31,Close,    31.97
2000-06-01,Close,    34.63
2000-06-02,Close,    35.66
2000-06-05,Close,    36.00
2000-06-06,Close,    34.27
2000-06-07,Close,    35.58
2000-06-08,Close,    36.64
2000-06-09,Close,    36.77
2000-06-12,Close,    35.83
2000-06-13,Close,    36.33
2000-06-14,Close,    35.13
2000-06-15,Close,    36.69
2000-06-16,Close,    36.41
2000-06-19,Close,    38.25
2000-06-20,Close,    38.27
2000-06-21,Close,    38.33
2000-06-22,Close,    36.25
2000-06-22,SELL CREATE,    36.25
2000-06-23,SELL EXECUTED,    35.94, Size:   -10.00 Cost:   325.80, Comm    0.00
2000-06-23,OPERATION PROFIT, GROSS    33.60, NET    33.60
2000-06-23,Close,    35.36
2000-06-26,Close,    36.77
2000-06-26,BUY CREATE    36.77
2000-06-27,BUY EXECUTED, Price:    36.64, Size:    10.00 Cost:   366.40, Comm:     0.00
2000-06-27,Close,    36.58
2000-06-27,SELL CREATE,    36.58
2000-06-28,SELL EXECUTED,    36.50, Size:   -10.00 Cost:   366.40, Comm    0.00
2000-06-28,OPERATION PROFIT, GROSS    -1.40, NET    -1.40
2000-06-28,Close,    36.89
2000-06-28,BUY CREATE    36.89
2000-06-29,BUY EXECUTED, Price:    36.50, Size:    10.00 Cost:   365.00, Comm:     0.00
2000-06-29,Close,    35.97
2000-06-29,SELL CREATE,    35.97
2000-06-30,SELL EXECUTED,    35.75, Size:   -10.00 Cost:   365.00, Comm    0.00
2000-06-30,OPERATION PROFIT, GROSS    -7.50, NET    -7.50
2000-06-30,Close,    37.39
2000-06-30,BUY CREATE    37.39
2000-07-03,BUY EXECUTED, Price:    36.08, Size:    10.00 Cost:   360.80, Comm:     0.00
2000-07-03,Close,    35.66
2000-07-03,SELL CREATE,    35.66
2000-07-05,SELL EXECUTED,    34.16, Size:   -10.00 Cost:   360.80, Comm    0.00
2000-07-05,OPERATION PROFIT, GROSS   -19.20, NET   -19.20
2000-07-05,Close,    32.16
2000-07-06,Close,    33.63
2000-07-07,Close,    33.75
2000-07-10,Close,    32.97
2000-07-11,Close,    32.16
2000-07-12,Close,    33.22
2000-07-13,Close,    33.69
2000-07-14,Close,    33.86
2000-07-17,Close,    33.86
2000-07-18,Close,    32.99
2000-07-19,Close,    32.80
2000-07-20,Close,    34.75
2000-07-20,BUY CREATE    34.75
2000-07-21,BUY EXECUTED, Price:    34.44, Size:    10.00 Cost:   344.40, Comm:     0.00
2000-07-21,Close,    33.55
2000-07-21,SELL CREATE,    33.55
2000-07-24,SELL EXECUTED,    34.30, Size:   -10.00 Cost:   344.40, Comm    0.00
2000-07-24,OPERATION PROFIT, GROSS    -1.40, NET    -1.40
2000-07-24,Close,    33.36
2000-07-25,Close,    33.80
2000-07-25,BUY CREATE    33.80
2000-07-26,BUY EXECUTED, Price:    33.27, Size:    10.00 Cost:   332.70, Comm:     0.00
2000-07-26,Close,    34.13
2000-07-27,Close,    33.38
2000-07-27,SELL CREATE,    33.38
2000-07-28,SELL EXECUTED,    33.41, Size:   -10.00 Cost:   332.70, Comm    0.00
2000-07-28,OPERATION PROFIT, GROSS     1.40, NET     1.40
2000-07-28,Close,    32.19
2000-07-31,Close,    33.44
2000-07-31,BUY CREATE    33.44
2000-08-01,BUY EXECUTED, Price:    33.44, Size:    10.00 Cost:   334.40, Comm:     0.00
2000-08-01,Close,    32.52
2000-08-01,SELL CREATE,    32.52
2000-08-02,SELL EXECUTED,    32.47, Size:   -10.00 Cost:   334.40, Comm    0.00
2000-08-02,OPERATION PROFIT, GROSS    -9.70, NET    -9.70
2000-08-02,Close,    32.52
2000-08-03,Close,    34.44
2000-08-03,BUY CREATE    34.44
2000-08-04,BUY EXECUTED, Price:    34.83, Size:    10.00 Cost:   348.30, Comm:     0.00
2000-08-04,Close,    36.27
2000-08-07,Close,    36.41
2000-08-08,Close,    36.91
2000-08-09,Close,    36.19
2000-08-10,Close,    35.61
2000-08-11,Close,    36.08
2000-08-14,Close,    36.64
2000-08-15,Close,    36.14
2000-08-16,Close,    36.11
2000-08-17,Close,    37.33
2000-08-18,Close,    36.16
2000-08-21,Close,    37.00
2000-08-22,Close,    37.16
2000-08-23,Close,    36.86
2000-08-24,Close,    37.66
2000-08-25,Close,    37.64
2000-08-28,Close,    38.58
2000-08-29,Close,    39.03
2000-08-30,Close,    39.25
2000-08-31,Close,    40.44
2000-09-01,Close,    41.19
2000-09-05,Close,    40.50
2000-09-06,Close,    39.69
2000-09-07,Close,    40.56
2000-09-08,Close,    38.50
2000-09-08,SELL CREATE,    38.50
2000-09-11,SELL EXECUTED,    38.28, Size:   -10.00 Cost:   348.30, Comm    0.00
2000-09-11,OPERATION PROFIT, GROSS    34.50, NET    34.50
2000-09-11,Close,    37.11
2000-09-12,Close,    35.30
2000-09-13,Close,    36.39
2000-09-14,Close,    37.78
2000-09-15,Close,    34.83
2000-09-18,Close,    34.01
2000-09-19,Close,    35.27
2000-09-20,Close,    35.55
2000-09-21,Close,    35.11
2000-09-22,Close,    35.91
2000-09-25,Close,    35.02
2000-09-26,Close,    35.33
2000-09-27,Close,    35.52
2000-09-28,Close,    36.24
2000-09-28,BUY CREATE    36.24
2000-09-29,BUY EXECUTED, Price:    36.18, Size:    10.00 Cost:   361.80, Comm:     0.00
2000-09-29,Close,    35.02
2000-09-29,SELL CREATE,    35.02
2000-10-02,SELL EXECUTED,    35.47, Size:   -10.00 Cost:   361.80, Comm    0.00
2000-10-02,OPERATION PROFIT, GROSS    -7.10, NET    -7.10
2000-10-02,Close,    35.02
2000-10-03,Close,    30.91
2000-10-04,Close,    30.30
2000-10-05,Close,    30.38
2000-10-06,Close,    30.08
2000-10-09,Close,    29.69
2000-10-10,Close,    28.74
2000-10-11,Close,    27.69
2000-10-12,Close,    28.02
2000-10-13,Close,    31.69
2000-10-16,Close,    30.74
2000-10-17,Close,    29.96
2000-10-18,Close,    29.85
2000-10-19,Close,    32.36
2000-10-19,BUY CREATE    32.36
2000-10-20,BUY EXECUTED, Price:    32.13, Size:    10.00 Cost:   321.30, Comm:     0.00
2000-10-20,Close,    31.35
2000-10-23,Close,    30.30
2000-10-24,Close,    31.85
2000-10-25,Close,    30.58
2000-10-26,Close,    30.30
2000-10-27,Close,    30.41
2000-10-30,Close,    28.13
2000-10-30,SELL CREATE,    28.13
2000-10-31,SELL EXECUTED,    29.02, Size:   -10.00 Cost:   321.30, Comm    0.00
2000-10-31,OPERATION PROFIT, GROSS   -31.10, NET   -31.10
2000-10-31,Close,    29.35
2000-11-01,Close,    27.91
2000-11-02,Close,    26.30
2000-11-03,Close,    26.96
2000-11-06,Close,    24.85
2000-11-07,Close,    23.63
2000-11-08,Close,    22.07
2000-11-09,Close,    24.18
2000-11-10,Close,    22.63
2000-11-13,Close,    22.01
2000-11-14,Close,    25.24
2000-11-15,Close,    25.68
2000-11-16,Close,    24.35
2000-11-17,Close,    25.63
2000-11-17,BUY CREATE    25.63
2000-11-20,BUY EXECUTED, Price:    21.63, Size:    10.00 Cost:   216.30, Comm:     0.00
2000-11-20,Close,    22.01
2000-11-20,SELL CREATE,    22.01
2000-11-21,SELL EXECUTED,    22.07, Size:   -10.00 Cost:   216.30, Comm    0.00
2000-11-21,OPERATION PROFIT, GROSS     4.40, NET     4.40
2000-11-21,Close,    21.24
2000-11-22,Close,    19.85
2000-11-24,Close,    21.46
2000-11-27,Close,    20.57
2000-11-28,Close,    20.15
2000-11-29,Close,    20.35
2000-11-30,Close,    23.57
2000-11-30,BUY CREATE    23.57
2000-12-01,BUY EXECUTED, Price:    23.46, Size:    10.00 Cost:   234.60, Comm:     0.00
2000-12-01,Close,    23.52
2000-12-04,Close,    25.07
2000-12-05,Close,    28.02
2000-12-06,Close,    26.85
2000-12-07,Close,    25.18
2000-12-08,Close,    26.74
2000-12-11,Close,    28.41
2000-12-12,Close,    27.35
2000-12-13,Close,    25.24
2000-12-14,Close,    24.46
2000-12-14,SELL CREATE,    24.46
2000-12-15,SELL EXECUTED,    26.18, Size:   -10.00 Cost:   234.60, Comm    0.00
2000-12-15,OPERATION PROFIT, GROSS    27.20, NET    27.20
2000-12-15,Close,    25.41
2000-12-15,BUY CREATE    25.41
2000-12-18,BUY EXECUTED, Price:    26.68, Size:    10.00 Cost:   266.80, Comm:     0.00
2000-12-18,Close,    28.46
2000-12-19,Close,    27.24
2000-12-20,Close,    25.35
2000-12-20,SELL CREATE,    25.35
2000-12-21,SELL EXECUTED,    24.74, Size:   -10.00 Cost:   266.80, Comm    0.00
2000-12-21,OPERATION PROFIT, GROSS   -19.40, NET   -19.40
2000-12-21,Close,    26.24
2000-12-21,BUY CREATE    26.24
2000-12-22,BUY EXECUTED, Price:    27.02, Size:    10.00 Cost:   270.20, Comm:     0.00
2000-12-22,Close,    28.35
2000-12-26,Close,    27.52
2000-12-27,Close,    27.30
2000-12-28,Close,    27.63
2000-12-29,Close,    25.85
2000-12-29,SELL CREATE,    25.85
Final Portfolio Value:   982.30

Plot backtest results

We can see that the below plot now has x7 charts

  1. Accumulation of wealth. Shows the equity and cash value of your account.
  2. Profitability of each trade. Shows net profit/loss of each trade.
  3. Price chart. Shows the prices, buy/sell signals, the SimpleMA and the ExpMA, and the volume of trades.
  4. Weighted Moving Average
  5. Stochastic Slow
  6. MACD
  7. RSI
In [7]:
%matplotlib inline
cerebro.plot()
Out[7]:
[[<Figure size 432x288 with 8 Axes>]]

Conclusion

In this post, we learnt how to add indicators to the trading strategy as follows:

  1. We learnt how to add indicators by using the bt.indicators.
  2. We learnt how to include additional indicators in the the cerebro.plot() function.

In the next post, we will look at optimizing the parameters of the strategy.

The below code needs to be run to execute cerebro.plot() successfullly

In [6]:
import numpy as np
import pandas as pd

df = pd.DataFrame(np.random.randint(0,100,size=(100,4)),columns = list('ABCD'))
df.head()
df.plot()
Out[6]:
<matplotlib.axes._subplots.AxesSubplot at 0x783a2d5ee780>
In [ ]:
 

Comments

Comments powered by Disqus