[PYTHON] Prepare Backtrader CSV data and try running the sample script

How to use Backtrader

If the sample script is used as it is, an error will occur.

backtrader Document_Quickstart https://www.backtrader.com/docu/quickstart/quickstart/

After the installation, when I run the sample script on this page, I get an error saying "The CSV file does not exist in the specified path".

I tried searching, but the corresponding folder itself was not found locally. Apparently, when I download backtrader with PIP, the data folder used to run the sample script and the sample folder itself are not included.

Prepare CSV data

https://github.com/mementum/backtrader/blob/master/datas/orcl-1995-2014.txt Therefore, copy the contents of Oracle's stock price "orcl-1995-2014.txt" from this Git page and make it a text file. Save this in the same directory as the sample script and rewrite the file path specification part in the script. (For Jupyter notebook, the directory where the ipynb file is saved: C: \ Users \ user name by default)

datapath.py



datapath = os.path.join(modpath, '../../datas/orcl-1995-2014.txt')

#Rewrite this as follows

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

Try running it with Jupyter notebook

Start Jupyter notebook from the virtual environment of Anaconda and execute the following sample script with the file path rewritten.

quickstart.py



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

import datetime  # For datetime objects
import os.path  # To manage paths
import sys  # To find out the script name (in argv[0])

# Import the backtrader platform
import backtrader as bt


# Create a Stratey
class TestStrategy(bt.Strategy):
    params = (
        ('maperiod', 15),
    )

    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

        # To keep track of pending orders and buy price/commission
        self.order = None
        self.buyprice = None
        self.buycomm = None

        # Add a MovingAverageSimple indicator
        self.sma = bt.indicators.SimpleMovingAverage(
            self.datas[0], period=self.params.maperiod)

        # Indicators for the plotting show
        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 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, Price: %.2f, Cost: %.2f, Comm %.2f' %
                    (order.executed.price,
                     order.executed.value,
                     order.executed.comm))

                self.buyprice = order.executed.price
                self.buycomm = order.executed.comm
            else:  # Sell
                self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                         (order.executed.price,
                          order.executed.value,
                          order.executed.comm))

            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

    def notify_trade(self, trade):
        if not trade.isclosed:
            return

        self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' %
                 (trade.pnl, trade.pnlcomm))

    def next(self):
        # Simply log the closing price of the series from the reference
        self.log('Close, %.2f' % self.dataclose[0])

        # Check if an order is pending ... if yes, we cannot send a 2nd one
        if self.order:
            return

        # Check if we are in the market
        if not self.position:

            # Not yet ... we MIGHT BUY if ...
            if self.dataclose[0] > self.sma[0]:

                # BUY, BUY, BUY!!! (with all possible default parameters)
                self.log('BUY CREATE, %.2f' % self.dataclose[0])

                # Keep track of the created order to avoid a 2nd order
                self.order = self.buy()

        else:

            if self.dataclose[0] < self.sma[0]:
                # SELL, SELL, SELL!!! (with all possible default parameters)
                self.log('SELL CREATE, %.2f' % self.dataclose[0])

                # Keep track of the created order to avoid a 2nd order
                self.order = self.sell()


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')
    datapath = 'C:\\Users\\xxxx\\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(1000.0)

    # Add a FixedSize sizer according to the stake
    cerebro.addsizer(bt.sizers.FixedSize, stake=10)

    # Set the commission
    cerebro.broker.setcommission(commission=0.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())

    # Plot the result
    cerebro.plot()

quickstart2.JPG

When executed in Jupyter notebook, the trading result (omitted) of the strategy and the plot of the indicator are displayed.

In the case of Jupyter notebook, if you write % matplotlib notebook at the beginning of the sample script, a scaling button and chart scroll button will be added to the plot screen. By pressing this, you can enlarge the part of the price movement that you are interested in. You can also move the place you want to see at the same magnification. It is not displayed this time, but it is convenient when you want to analyze candlesticks in detail.

quickstart3.JPG

(Added 2020.0207) It's different from the above script, but when you zoom in on the candlestick, it looks like this. Switch to cerebro.plot (style ='candle') at the end of the script. index.png

Recommended Posts

Prepare Backtrader CSV data and try running the sample script
Extract csv data and calculate
Quickly install OpenCV 2.4 (+ python) on OS X and try the sample
Try running the basic information Python sample problem only in the browser
Download sample data before running Bokeh
I saved the scraped data in CSV!
A Python script that reads a SQL file, executes BigQuery and saves the csv