[PYTHON] How to make a Backtrader custom indicator

__ How can I create the indicator myself? __

Indicator creation -Create a class that inherits the bt.indicator class -Set the Lines object to plot ・ Set parameters such as the period of the moving average line -Add plot display settings if necessary ・ Write an expression I will create it in the flow.

As an example, let's create a stochastic oscillator and take a look at its contents.

sto1.py



import backtrader as bt


class MyStochastic1(bt.Indicator):  #bt.Inherit Indicator
    
    lines = ('k', 'd', )  #Lines object to display on the plot
    params = (
        ('k_period', 14), #Specify parameters with tuples of tuples
        ('d_period', 3),  #Comma at the end of the tuple(、)Put in
    )
    plotinfo = dict(plot   =True,
                    subplot=True,
                    plotname='',
               )   

    def __init__(self):
        
        highest = bt.indicators.Highest(self.datas[0], period=self.params.k_period)
        lowest = bt.indicators.Lowest(self.datas[0], period=self.params.k_period)        
        self.lines.k = k = (self.datas[0] - lowest) / (highest - lowest)    
        self.lines.d = bt.ind.SimpleMovingAverage(k, period=self.params.d_period)

    def next(self):
        pass

This is the big picture of the indicator class. A 14-day high / low price is required to calculate the stochastic oscillator. The amount of change is calculated by combining them with the closing price and smoothed by a 3-day simple moving average.

Class declaration

class MyStochastic1(bt.Indicator): First, declare the "MyStochastic1" class that inherits the Backtrader Indicator class.

Lines object settings

lines=('k','d')

There are two lines in Stochastic Oscillator, K and D. So I'm setting up two Lines objects to display on the plot. This Lines object is like "Index buffer" in MQL4, and is a ** iterable array ** in which a numerical value and a time axis are connected. Cerebro will plot this Lines object on the chart.

Lines object index and slice

In MQL4, the latest bar is represented by [0]. Counting from the latest Bar, the number increases as it gets older, 1, 2, 3, .... Even in backtrader, the latest Bar / Lines object is represented by [0]. This is the same as MQL4. However, as the bar becomes older with 0 as the standard, minus signs such as -1, -2, -3 ... are added.

In this regard, Lines objects cannot perform Python's native slicing operations. If you want to use slices, use the get () method.

myslice = self.lines.my_sma.get (ago = 0, size = 1) [-1] Only one array except [0] myslice = self.lines.my_sma.get (ago = 0, size = 10) 10 arrays from [-1] to [-10] except [0] myslice = self.lines.my_sma.get (ago = -1, size = 5) Arrays from [-2] to [-6] except [-1]

** * The [] operator can be used for Lines objects only in the next method. I will summarize the next method at a later date. ** **

Parameter setting (params)

params = ( ('k_period', 14), ('d_period', 3), * # Add a comma at the end * ) Stochastic oscillators perform calculations over a 14-day period and smooth the results with a 3-day simple moving average. (K_period, d_period) It is this parameter that sets it. Specify by tuple of tuple or dict (). (Reference 1) It is expressed by writing "self.params.name" like self.params.k_period. For tuples, be careful not to forget to put the last comma.

Plot settings (plotinfo)

plotinfo = dict(plot =True, subplot=True, plotname='', ) You can change the settings when plotting.

plot: Plot display On / Off subplot: Subplot display switching plotname: Footnote display name (class name is displayed if blank)

There are other setting items.

Write an expression in the Init method

Formula creation # 1 Calling a built-in indicator for calculation

highest = bt.indicators.Highest(self.datas[0],period=self.params.k_period) lowest = bt.indicators.Lowest(self.datas[0],period=self.params.k_period) Describe the stochastic calculation in the init method. First, calculate the high and low prices for 14 days. Fortunately, backtrader has an indicator that calculates the high and low prices for a specific period. Built-in indicators can be called with bt.indicators.XXXX (). (Note s at the end!) Here we call Highest and Lowest to find the highest and lowest values during the k_period period. I put the result in the Lines objects highest and lowest.

Creating an expression Part 2 Put a value in the Lines object

self.lines.k = k = (self.datas[0] - lowest) / (highest - lowest) self.lines.d = bt.ind.SimpleMovingAverage(k,period=self.params.d_period)

The Lines object to plot is represented by "self.lines.name". k is self.lines.k and d is self.lines.d. The resulting Lines object can also be used for calculations. Here, in order to simplify the notation of the calculation on the next line, it is assigned to "k" and passed to the simple moving average indicator.

Data feed (datas)

self.datas[0] Self.datas [0] in the formula represents the "first CSV data". Unless otherwise specified, the closing price is used. Since multiple data can be passed, for example, when passing two CSV data such as daily and weekly, the smaller time frame must be specified first and the larger time frame must be specified later. In other words, datas [0] must be daily data and datas [1] must be weekly data. This time, only daily data is passed.

Abbreviation

--- Official abridgement
lines self.lines.XXX self.l.XXX
params self.params.XXX self.p.XXX
datas self.datas[0].close self.data.close or self.data
indicators bt.indicators.XXX bt.ind.XXX
Alias SimpleMovingAverage SMA

Backtrader can be abbreviated. It's convenient, but it can be confusing until you get used to it. And in fact, you can omit all plotinfo this time. If plot, subplot, plotname are omitted, the default settings will be used.

next method

I haven't used it this time, but if you want to judge the condition or perform processing for each Bar, describe the contents in the next method.

Completion Call in strategy class

__ How do I display the indicator? __

All settings are complete. If you instantiate this indicator class inside the init method of the strategy class, Cerebro will plot it on the chart. You can freely name the instance.

self.myind1 = MyStochastic1(self.data)

(Explanatory comments have been added to various places and omitted as much as possible.)

sto12.py


%matplotlib notebook
from __future__ import (absolute_import, division, print_function,
                        unicode_literals)

import datetime  
import os.path  
import sys  


import backtrader as bt


class MyStochastic1(bt.Indicator):
    
    lines = ('k', 'd', )  #Lines object to display on the plot
    params = (
        ('k_period', 14), #Specify parameters with tuples of tuples
        ('d_period', 3),  #Comma at the end of the tuple(、)Put in
    )
    
    #abridgement
    #plotinfo = dict()

    def __init__(self):
        #To be exact, self.datas[0]Can be omitted
        # self.params.k_omit period and self.p.k_period 
        highest = bt.ind.Highest(self.data, period=self.p.k_period)
        lowest = bt.ind.Lowest(self.data, period=self.p.k_period)        
       
        self.lines.k = k = (self.data - lowest) / (highest - lowest)    
        self.lines.d = bt.ind.SMA(k, period=self.p.d_period)

        

class TestStrategy(bt.Strategy):
    def __init__(self):
        #The instance name myind1 can be any name
        self.myind1 = MyStochastic1(self.data)    
        
        
if __name__ == '__main__':
    cerebro = bt.Cerebro()
    cerebro.addstrategy(TestStrategy)

    datapath = 'C:\\Users\\XXXX\\orcl-1995-2014.txt'

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

    cerebro.adddata(data)
    cerebro.run(stdstats=False)
    cerebro.plot(style='candle')

1sto.png

The stochastic oscillator is displayed safely.

Rough flow until Cerebro starts

__ What is Cerebro? __

This is the core function of Backtrader. If you start this Cerebro after making various settings, it will automatically buy and sell, analyze and optimize, and plot the results automatically. I will review the flow up to the start of Cerebro in the previous script.

  1. Describe the contents of automatic trading and the indicator to be called for it in the strategy class (TestStrategy).
  2. Instantiate Cerebro cerebro = bt. Cerebro ()
  3. Pass CSV data to cerebro cerebro.adddata (data)
  4. Load the strategy into cerebro cerebro.addstrategy (TestStrategy)
  5. Start cerebro cerebro.run ()
  6. Display the chart cerebro.plot ()

If you create a strategy class "TestStrategy" that you think of yourself, specify CSV data, and then execute Cerebro, the contents of this "TestStrategy" class will be executed automatically. This time we are not doing automatic trading, but since Stochastic Oscillator is used in "Test Strategy", Cerebro will plot it.

Summary

What did you think? To use a custom indicator with Backtrader, create your own class of custom indicators and instantiate it inside the strategy class.

References

Reference 1

Reference 2 2.Gold vs SP500 https://www.backtrader.com/blog/posts/2016-12-13-gold-vs-sp500/gold-vs-sp500/

Recommended Posts

How to make a Backtrader custom indicator
How to make a Japanese-English translation
How to make a crawler --Advanced
How to make a recursive function
How to make a deadman's switch
[Blender] How to make a Blender plugin
How to make a crawler --Basic
[Python] How to make a class iterable
How to make a Pelican site map
How to make a dialogue system dedicated to beginners
How to make a dictionary with a hierarchical structure.
How to make a QGIS plugin (package generation)
I read "How to make a hacking lab"
How to call a function
[Go] How to create a custom error for Sentry
How to hack a terminal
How to make a Python package using VS Code
How to make a Cisco Webex Teams BOT with Flask
[Python] How to make a list of character strings character by character
How to make a multiplayer online action game on Slack
How to make a hacking lab-Kali Linux (2020.1) VirtualBox 64-bit Part 2-
How to make a hacking lab-Kali Linux (2020.1) VirtualBox 64-bit edition-
How to make a Python package (written for an intern)
How to make a simple Flappy Bird game with pygame
How to write a Python class
How to put a symbolic link
How to create a Conda package
How to create a virtual bridge
How to create a Dockerfile (basic)
[Blender] How to make Blender scripts multilingual
How to delete a Docker container
How to create a config file
How to make a string into an array or an array into a string in Python
How to make a command to read the configuration file with pyramid
How to make a surveillance camera (Security Camera) with Opencv and Python
How to customize U-Boot with OSD335X on a custom board (memo)
[C language] How to create, avoid, and make a zombie process
Spigot (Paper) Introduction to how to make a plug-in for 2020 # 01 (Environment construction)
Slack --APIGateway --Lambda (Python) --How to make a RedShift interactive app
How to make a unit test Part.1 Design pattern for introduction
[Python] How to make a matrix of repeating patterns (repmat / tile)
How to make Word Cloud characters monochromatic
How to split and save a DataFrame
How to build a sphinx translation environment
How to create a git clone folder
How to add a package with PyCharm
How to draw a graph using Matplotlib
Try to make a kernel of Jupyter
[Colab] How to copy a huge dataset
[Python] How to invert a character string
How to install a package using a repository
[Ubuntu] How to execute a shell script
[Cocos2d-x] How to make Script Binding (Part 2)
How to make multi-boot USB (Windows 10 compatible)
How to create a repository from media
I tried to make a Web API
To make a dict type property read-only
How to choose a Seaborn color palette
How to test on a Django-authenticated page
[Cocos2d-x] How to make Script Binding (Part 1)
How to run a Maya Python script