For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See:

Problem with plotting buy sell arrows

  • Hi guys, I've just started using backtrader and I am struggling with plotting.
    Buy sell arrows don't seem in the correct place. There is some kind of scaling issue. I have a csv data with 5m frames. As you can see in my script I'm using


    Any help is appreciated.


    You can see my config below:

    from __future__ import (absolute_import, division, print_function,
    import backtrader as bt
    import backtrader.feeds as btfeeds
    import datetime
    import os.path  # To manage paths
    import sys  # To find out the script name (in argv[0])
    import numpy
    # Create a Stratey
    class TestStrategy(bt.Strategy):
        def log(self, txt, dt=None):
            ''' Logging function fot this strategy'''
            dt = dt or self.datas[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
            self.datahigh = self.datas[0].high
            # To keep track of pending orders and buy price/commission
            self.order = None
            self.buyprice = None
            self.buycomm = None
            # Add a MovingAverageSimple indicator
            self.ma7 = bt.indicators.SimpleMovingAverage(self.datas[0], period=7)
            self.ma25 = bt.indicators.SimpleMovingAverage(self.datas[0], period=25)
        def notify_order(self, order):
            if order.status in [order.Submitted, order.Accepted]:
                # Buy/Sell order submitted/accepted to/by broker - Nothing to do
            # 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():
                        'BUY EXECUTED, Price: %.8f, Cost: %.8f, Comm %.8f' %
                    self.buyprice = order.executed.price
                    self.buycomm = order.executed.comm
                else:  # Sell
                    self.log('SELL EXECUTED, Price: %.8f, Cost: %.8f, Comm %.8f' %
                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:
            self.log('OPERATION PROFIT, GROSS %.8f, NET %.8f' %
                     (trade.pnl, trade.pnlcomm))
        def next(self):
            # Simply log the closing price of the series from the reference
            self.log('Close, %.8f' % self.dataclose[0])
            # Check if an order is pending ... if yes, we cannot send a 2nd one
            if self.order:
            # Check if we are in the market
            if not self.position:
                # Not yet ... we MIGHT BUY if ...
                if self.ma7[0] > self.ma25[0]:
                    # BUY, BUY, BUY!!! (with all possible default parameters)
                    self.log('BUY CREATE, %.8f' % self.dataclose[0])
                    # Keep track of the created order to avoid a 2nd order
                    self.order =
                if self.ma7[0] < self.ma25[0]:
                    # SELL, SELL, SELL!!! (with all possible default parameters)
                    self.log('SELL CREATE, %.8f' % 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
        # 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, 'ohlcv1.csv')
        data = btfeeds.GenericCSVData(
            dtformat='%Y-%m-%d %H:%M:%S',
            timeframe = bt.TimeFrame.Minutes,
        # Add the Data Feed to Cerebro
        # Set our desired cash start
        # Add a FixedSize sizer according to the stake
        cerebro.addsizer(bt.sizers.FixedSize, stake=0.2)
        # Set the commission
        # Print out the starting conditions
        print('Starting Portfolio Value: %.8f' %
        # Run over everything
        # Print out the final result
        print('Final Portfolio Value: %.8f' %
        # Plot the result
        cerebro.plot(style='candlestick', barup='green', bardown='red')

  • administrators

    @zblp said in Problem with plotting buy sell arrows:

    Buy sell arrows don't seem in the correct place

    They are

    @zblp said in Problem with plotting buy sell arrows:

    There is some kind of scaling issue

    No, there isn't. Your data doesn't have enough price difference from the highest high to the lowest low for the default configuration. See:

    Disable the standard observers in cerebro using stdstats and add the observers you may wish with the configuration of your choice. See:

  • Hi, thank you very much for help. I'm creating the cerebro entity with stdstats=False right now, but as you can see in the figure, arrows placed in the middle of the candles. Is there a way to add some kind of margin space between arrows and candles?


  • administrators

    In the "Observers Reference* pasted above you have the parameters which can be given to the BuySell observer which do that (it is part of the standard configuration), namely barplot to activate the plotting away from the price and bardist to control the distance.

Log in to reply