Backtrader Quantification & Backtesting 2 – Read Pandas data in the strategy and add more custom data columns to the strategy

Backtrader reads data official documentation:https://www.backtrader.com/docu/dataautoref/

Backtrader reads Pandas data set basics

Using Backtrader’s built-in classesbacktrader.feeds.PandasDataAfter reading the dataframe data, the existing data column names will be mapped tobacktraderThe PandasData class will only contain the following data by default:

* close
* low
* high
* open
* volume
* openinterest
* datetime

If you want to obtain more data, you need to add it manually. For details, please refer to the custom data set section.

Get data information in the strategy

import backtrader
import efinance
import pandas as pd
from datetime import datetime


def get_k_data(stock_code, begin: datetime, end: datetime) -> pd.DataFrame:
    """
    Get stock data based on efinance toolkit
    :param stock_code:stock code
    :param begin: start date
    :param end: end date
    :return:
    """
    # stock_code = '600519' # Stock code, Moutai
    k_dataframe: pd.DataFrame = efinance.stock.get_quote_history(
        stock_code, beg=begin.strftime("%Y%m%d"), end=end.strftime("%Y%m%d"))
    k_dataframe = k_dataframe.iloc[:, :9]
    k_dataframe.columns = ['name', 'code', 'date', 'open', 'close', 'high', 'low', 'volume', 'turnover']
    k_dataframe.index = pd.to_datetime(k_dataframe.date)
    k_dataframe.drop(['name', 'code', "date"], axis=1, inplace=True)
    return k_dataframe


class MyStrategy1(backtrader.Strategy): # Strategy
    def __init__(self):
        # Initialize trading instructions, buying and selling prices and handling fees
        self.close_price = self.datas[0].close #Add a data reference here to facilitate subsequent operations
        this_data = self.getdatabyname("stock_600519") # Get the data of the incoming name = stock_600519
        print("All column names:", this_data.getlinealiases()) # All column names
        print("Total trading days:", self.datas[0].buflen()) # How many rows are there in the data set?

    def next(self): # During the execution of the framework, next() will be continuously looped, passing a K line, and executing next() once.
        print('==========================')
        print("Today {}, is the {}th trading day, closing price: {}".format(self.datetime.date(), len(self.datas[0]), self.datas[0].close [0]))
        print("The closing price of the day before yesterday, yesterday, and today:", list(self.datas[0].close.get(ago=0, size=3))) # Use get() to get data forward
        if len(self.datas[0]) <= self.datas[0].buflen() - 2:
            print("The closing price tomorrow and the day after tomorrow:", self.datas[0].close[1], self.datas[0].close[2])


if __name__ == '__main__':
    # retrieve data
    start_time = datetime(2015, 1, 1)
    end_time = datetime(2015, 1, 10)
    dataframe = get_k_data('600519', begin=start_time, end=end_time)
    # =============== Inject data into the system =================
    # Download Data
    data = backtrader.feeds.PandasData(dataname=dataframe, fromdate=start_time, todate=end_time)
    # Initialize cerebro backtesting system
    cerebral_system = backtrader.Cerebro() # The Cerebro engine creates a broker instance in the background. The system defaults the initial capital amount of each broker to 10,000.
    #Transfer data into the backtesting system
    cerebral_system.adddata(data, name="stock_600519") #Import data and use self.datas in the strategy to obtain the data source
    # Load the trading strategy into the backtesting system
    cerebral_system.addstrategy(MyStrategy1)
    # =============== System Settings==================
    #Run the backtest system
    cerebral_system.run()

You can see the printed results:

All column names: ('close', 'low', 'high', 'open', 'volume', 'openinterest', 'datetime')
Total trading days: 5
==========================
Today, 2015-01-05, is the first trading day, closing price: 105.32
The closing price the day before yesterday, yesterday, and today: []
The closing price tomorrow and the day after tomorrow: 101.06 96.61
==========================
Today, 2015-01-06, is the second trading day, closing price: 101.06
The closing price the day before yesterday, yesterday, and today: []
The closing price tomorrow and the day after tomorrow: 96.61 95.54
==========================
Today, 2015-01-07, is the third trading day, closing price: 96.61
The closing prices the day before yesterday, yesterday, and today: [105.32, 101.06, 96.61]
The closing price tomorrow and the day after tomorrow: 95.54 94.22
==========================
Today, 2015-01-08, is the 4th trading day, closing price: 95.54
The closing prices the day before yesterday, yesterday, and today: [101.06, 96.61, 95.54]
==========================
Today, 2015-01-09, is the fifth trading day, closing price: 94.22
The closing prices the day before yesterday, yesterday, and today: [96.61, 95.54, 94.22]

Customize the data set to expand more columns of data

If you look at the original data, you can find that the original data set column names are: ‘open’, ‘close’, ‘high’, ‘low’, ‘volume’, ‘turnover’

But in the policy the column names become: (‘close’, ‘low’, ‘high’, ‘open’, ‘volume’, ‘openinterest’, ‘datetime’)

This is because backtrader encapsulates the original data. Check the source code.class PandasData(feed.DataBase):can be seen,PandasDataThe inputs accepted by the class are: (‘nocase’, ‘close’, ‘low’, ‘high’, ‘open’, ‘volume’, ‘openinterest’, ‘datetime’). If you want to expand, you need to inherit from this class and then rewriteparamsThis parameter:

Adding custom columns only requires two steps:

  1. Modify lines
  2. Modify params
import backtrader
import efinance
import pandas as pd
from datetime import datetime


def get_k_data(stock_code, begin: datetime, end: datetime) -> pd.DataFrame:
    """
    Get stock data based on efinance toolkit
    :param stock_code:stock code
    :param begin: start date
    :param end: end date
    :return:
    """
    # stock_code = '600519' # Stock code, Moutai
    k_dataframe: pd.DataFrame = efinance.stock.get_quote_history(
        stock_code, beg=begin.strftime("%Y%m%d"), end=end.strftime("%Y%m%d"))
    k_dataframe = k_dataframe.iloc[:, :9]
    k_dataframe.columns = ['name', 'code', 'date', 'open', 'close', 'high', 'low', 'volume', 'turnover']
    k_dataframe.index = pd.to_datetime(k_dataframe.date)
    k_dataframe.drop(['name', 'code', "date"], axis=1, inplace=True)
    return k_dataframe


class PandasDataPlus(backtrader.feeds.PandasData):
    lines = ('turnover',) # Column names to be added
    # Set the new position of line on the data source
    params = (
        ('turnover', -1), #turnover corresponds to the column name of the incoming data. This -1 will automatically match the backtrader data class and the column name of the original pandas file.
        # If it is a number greater than or equal to 0, such as 8, then backtrader will consider the original data subscript 8 (column 9, subscript starting from 0) as the turnover column.
    )


class MyStrategy1(backtrader.Strategy): # Strategy
    def __init__(self):
        # Initialize trading instructions, buying and selling prices and handling fees
        self.close_price = self.datas[0].close #Add a data reference here to facilitate subsequent operations
        this_data = self.getdatabyname("stock_600519") # Get the data of the incoming name = stock_600519
        print("All column names:", this_data.getlinealiases()) # All column names

    def next(self): # During the execution of the framework, next() will be continuously looped, passing a K line, and executing next() once.
        pass


if __name__ == '__main__':
    # retrieve data
    start_time = datetime(2015, 1, 1)
    end_time = datetime(2015, 1, 10)
    dataframe = get_k_data('600519', begin=start_time, end=end_time)
    # =============== Inject data into the system =================
    # Download Data
    data = PandasDataPlus(dataname=dataframe, fromdate=start_time, todate=end_time)
    # Initialize cerebro backtesting system
    cerebral_system = backtrader.Cerebro() # The Cerebro engine creates a broker instance in the background. The system defaults the initial capital amount of each broker to 10,000.
    #Transfer data into the backtesting system
    cerebral_system.adddata(data, name="stock_600519") #Import data and use self.datas in the strategy to obtain the data source
    # Load the trading strategy into the backtesting system
    cerebral_system.addstrategy(MyStrategy1)
    # =============== System Settings==================
    #Run the backtest system
    cerebral_system.run()

You can see that the data in the turnover column has been added, and you can select it in the strategy:

All column names: ('close', 'low', 'high', 'open', 'volume', 'openinterest', 'datetime', 'turnover')

Related Posts

I want to simply write nce and infonce

python: Some problems and solutions when starting to use tensorflow

It’s actually very simple and will teach you how to easily create cool data visualization on a large screen.

graphviz.backend.execute.ExecutableNotFound: failed to execute WindowsPath(‘dot‘), make sure the Gra

Solve the problem of sorting after SQLite auto-increment ID modification:

The simplest Anaconda+Python3.7 installation tutorial on the Internet for Win10 (100% successful)

Anaconda environment cloning and migration

Pandas merge csv files

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*