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

Buy and Sell arrows not showing in Plot

  • Hello,

    I'm new with backtrader and was testing out some machine learning strategy. I cannot seem to get the buy and sell arrows to show in the plot. Tried adding some observers as well to the plot but still they do not show.

    When I try and add a simple strategy using csv data and 'bt.feeds.YahooFinanceCSVData' the buy and sell arrows on the plot show normally.

    Can you kindly assist me please? Also, how can I add a simple observer to the plot such as SMA?


    import numpy as np
    from matplotlib import pyplot as plt
    import pandas as pd
    import seaborn as sns
    import yfinance as yf
    import warnings
    from sklearn.svm import SVC
    import datetime
    import pyfolio as pf
    import backtrader as bt
    from backtrader.feeds import PandasData
    import warnings'seaborn-colorblind')
    warnings.simplefilter(action='ignore', category=FutureWarning)

    ticker = '^NSEI' # Nifty 50 benchmark
    start = datetime.datetime(2010, 1, 1)
    end = datetime.datetime(2020, 7, 31)

    stock =, progress=True, actions=True,start=start, end=end)['Adj Close']
    stock = pd.DataFrame(stock)
    stock.rename(columns = {'Adj Close':ticker}, inplace=True)

    stock['returns'] = np.log(stock / stock.shift(1))
    stock['direction'] = np.sign(stock['returns']).astype(int)

    lags = [1, 2, 3, 4, 5]

    cols = []
    for lag in lags:
    col = f'rtn_lag{lag}'
    stock[col] = stock['returns'].shift(lag)


    def create_bins(data, bins=[0]):
    global cols_bin
    cols_bin = []
    for col in cols:
    col_bin = col + '_bin'
    data[col_bin] = np.digitize(data[col], bins=bins)


    models = {
    'svm': SVC()

    def fit_models(data):
    mfit = {model: models[model].fit(data[cols_bin], data['direction']) for model in models.keys()}

    def derive_positions(data):
    for model in models.keys():
    data['pos_' + model] = models[model].predict(data[cols_bin])

    def evaluate_strats(data):
    global strategy_rtn
    strategy_rtn = []
    for model in models.keys():
    col = 'strategy_' + model
    data[col] = data['pos_' + model] * data['returns']
    strategy_rtn.insert(0, 'returns')


    prices =, progress=True, actions=True, start=start, end=end)
    prices.drop(['Close','Dividends','Stock Splits'], inplace=True, axis=1)
    prices.rename(columns = {'Open':'open','High':'high','Low':'low','Adj Close':'close','Volume':'volume',
    }, inplace=True)

    predictions = stock['strategy_svm']
    predictions = pd.DataFrame(predictions)
    predictions.rename(columns = {'strategy_svm':'predicted'}, inplace=True)
    prices = predictions.join(prices, how='right').dropna()

    OHLCV = ['open', 'high', 'low', 'close', 'volume']

    class SignalData(PandasData):
    Define pandas DataFrame structure
    cols = OHLCV + ['predicted']

    # create lines
    lines = tuple(cols)
    params = {c: -1 for c in cols}
    params.update({'datetime': None})
    params = tuple(params.items())

    class MLStrategy(bt.Strategy):
    params = dict(

    def __init__(self):
        # keep track of open, close prices and predicted value in the series
        self.data_predicted = self.datas[0].predicted
        self.data_open = self.datas[0].open
        self.data_close = self.datas[0].close
        self.order = None
        self.price = None
        self.comm = None
    def log(self, txt):
        '''Logging function'''
        dt = self.datas[0]
        print(f'{dt}, {txt}')
    def notify_order(self, order):
        if order.status in [order.Submitted, order.Accepted]:
            # order already submitted/accepted - no action required
        # report executed order
        if order.status in [order.Completed]:
            if order.isbuy():
                self.log(f'BUY EXECUTED --- Price: {order.executed.price:.2f}, Cost: {order.executed.value:.2f},Commission: {order.executed.comm:.2f}'
                self.price = order.executed.price
                self.comm = order.executed.comm
                self.log(f'SELL EXECUTED --- Price: {order.executed.price:.2f}, Cost: {order.executed.value:.2f},Commission: {order.executed.comm:.2f}'
        # report failed order
        elif order.status in [order.Canceled, order.Margin, 
            self.log('Order Failed')
        # set no pending order
        self.order = None
    def notify_trade(self, trade):
        if not trade.isclosed:
        self.log(f'OPERATION RESULT --- Gross: {trade.pnl:.2f}, Net: {trade.pnlcomm:.2f}')
    # We have set cheat_on_open = True.This means that we calculated the signals on day t's close price, 
    # but calculated the number of shares we wanted to buy based on day t+1's open price.
    def next_open(self):
        if not self.position:
            if self.data_predicted > 0:
                # calculate the max number of shares ('all-in')
                size = int( / self.datas[0].open)
                # buy order
                self.log(f'BUY CREATED --- Size: {size}, Cash: {}, Open: {self.data_open[0]}, Close: {self.data_close[0]}')
            if self.data_predicted < 0:
                # sell order
                self.log(f'SELL CREATED --- Size: {self.position.size}')

    data = SignalData(dataname=prices)

    cerebro = bt.Cerebro()

Log in to reply