Indicatore On Balance Volume in Backtrader

L’indicatore On Balance Volume con backtrader

In questo articolo descriviamo come implementare l’indicatore On Balance Volume con Backtrader che può essere copiato ed esteso in molte progetti e strategie di trading algoritmico e quantitativo.

On Balance Volume

L’On Balance Volume, o OBV in breve, è un indicatore basato sul volume che considera anche i prezzi close per  calcolare un valore finale. Investopedia fornisce un bel riassunto e uno cenno storico sull’indicatore.

L’On Balance Volume (OBV) è un indicatore di momentum che usa il flusso di volume per prevedere le variazioni del prezzo delle azioni. Joseph Granville ha sviluppato per la prima volta l’indica tore OBV negli anni ’60. Credeva che quando il volume aumenta bruscamente senza una variazione significativa del prezzo del titolo, il prezzo alla fine salterà verso l’alto e viceversa.

L’on balance volume si basa sempre sul proprio valore precedente. In altre parole, è un indicatore cumulativo. Se il prezzo close aumenta, il volume è aggiunto al valore  precedente dell’indicatore. Se il prezzo close diminuisce il volume è sottratto dal valore precedente dell’indicatore. Inoltre l’indicatore confronta il valore close corrente con il valore close[-1] (chiusura precedente) e non  confronta il valore open corrente rispetto al valore  close corrente. In altre parole possiamo avere un giorno con una candela verde ma sottrarre comunque il volume, ad esempio quando si verifica un gap al ribasso e si ha una chiusura positiva.

Se cerchiamo idee dove applicare l’indicatore OBV, possiamo consultare stockcharts.com. Hanno un articolo OBV che fornisce alcuni ottimi consigli su come interpretare l’indicatore, individuare le divergenze e confermare i trend.

Ulteriori letture

  1. Wikipedia:  https://en.wikipedia.org/wiki/On-balance_volume
  2. Investopedia:  https://www.investopedia.com/terms/o/onbalancevolume.asp
  3. Grafici azionari:  https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:on_balance_volume_obv

L’indicatore On Balance Volume con Backtrader

				
					
import backtrader as bt
from datetime import datetime

class OnBalanceVolume(bt.Indicator):
    '''
    ----------------------------------------------------------------------
    Investopedia:
    ----------------------------------------------------------------------
    https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:on_balance_volume_obv

    1. Se il prezzo di chiusura di ogge è maggiore del prezzo di chiusura di ieri,
       allora: OBV attuale = OBV precedente + il volume di oggi

    2. Se il prezzo di chiusura di ogge è maggiore del prezzo di chiusura di ieri,
       allora: OBV attuale = OBV precedente - il volume di oggi

    3. Se il prezzo di chiusura di ogge è uguale al prezzo di chiusura di ieri,
       allora: OBV attuale = OBV precedente
    ----------------------------------------------------------------------
    '''

    alias = 'OBV'
    lines = ('obv',)

    plotlines = dict(
        obv=dict(
            _name='OBV',
            color='purple',
            alpha=0.50
        )
    )

    def __init__(self):

        # Grafico di una linea orizzontale
        self.plotinfo.plotyhlines = [0]

    def nextstart(self):
        # Dobbiamo usare nextstart per fornire il valore iniziale perché non
        # abbiamo un valore precedente per il primo calcolo.
        # Questi sono noti come valori seed.

        # Creare gli alias
        c = self.data.close
        v = self.data.volume
        obv = self.lines.obv

        if c[0] > c[-1]:
            obv[0] = v[0]
        elif c[0] < c[-1]:
            obv[0] = -v[0]
        else:
            obv[0] = 0

    def next(self):
        # Alias
        c = self.data.close
        v = self.data.volume
        obv = self.lines.obv

        if c[0] > c[-1]:
            obv[0] = obv[-1] + v[0]
        elif c[0] < c[-1]:
            obv[0] = obv[-1] - v[0]
        else:
            obv[0] = obv[-1]


class testStrategy(bt.Strategy):

    def __init__(self):
        self.obv = OnBalanceVolume(self.data)

    def next(self):
        print("{}: Prev: {}: Close: {}, Volume: {} OBV: {}".format(
            self.data.datetime.date(),
            self.data.close[-1],
            self.data.close[0],
            self.data.volume[0],
            self.obv.lines.obv[0]))

# Creao un istanza di cerebro
cerebro = bt.Cerebro()

# Aggiungere la strategia
cerebro.addstrategy(testStrategy)

# Download i dati di Apple da Quandl.
data = bt.feeds.Quandl(
    dataname='AAPL',
    fromdate = datetime(2016,1,1),
    todate = datetime(2017,1,1),
    buffered= True,
    )

# Aggiungere i dati a cerebro
cerebro.adddata(data)

# Esecuzione del backtest
cerebro.run()

# Grafico dei risultati
cerebro.plot(style='candlestick')
				
			

Commento

I requisiti dell’indicatore sono molto semplici. Tuttavia, questo indicatore un po’ complicato da implementare perchè è un indicatore cumulativo, cioè la lines OBV si basa sul suo valore precedente. Per questo motivo non possiamo costruire la lines OBV all’interno del metodo __init__(), ma dobbiamo costruire la lines ad ogni chiamata del metodo next(). Inoltre, durante il primo calcolo, non abbiamo un valore precedente da aggiungere o sottrarre il volume della prima candela. Quindi dobbiamo  usare il metodo (funzione) nextstart() per fornire un valore iniziale. Un valore seed è solo un altro modo per dire primo valore. Questo ci consente di avviare l’indicatore. La documentazione ufficiale descrive il metodo nextstart() come:

Questo metodo è chiamato una sola volta, esattamente quando il periodo minimo per tutti i dati/indicatori è stato raggiunto. Il comportamento di default è richiamare next

Nel nostro indicatore, quando si richiama nextstart(), usiamo un calcolo leggermente diverso. Assegniamo semplicemente il volume come valore positivo o negativo senza aggiungerlo al valore precedente.

Per ulteriori informazioni sulla creazione degli indicatori comulativi si può leggere il seguente articoli:  https://www.backtrader.com/blog/posts/2018-01-27-recursive-indicators/recursive-indicator.html

Per ulteriori informazioni relativi all’implementazione di backtest con questo framework si può leggere i precedenti articoli su Backtrader.

Dati Quandl: in questo  codice usiamo i dati scaricati con l’API di Quandl. Se usiamo questa API senza una chiave abbiamo un limite al numero di chiamate che  possiamo fare al giorno. Per avere accesso illimitato ai dati gratuiti di Quandl, dobbiamo registrarci, ottenere una chiave API e aggiungere il parametro  apikey alla chiamata ai dati Quandl, come segue:

				
					
data = bt.feeds.Quandl( 
    dataname='AAPL', 
    fromdate = datetime(2016,1,1), 
    todate = datetime(2017,1,1),
    apikey="INSERT YOUR API KEY"
    )
				
			

Valori diversi nella altre piattaforme

Se confrontiamo i valori questo indicatore in un’altra piattaforma come Tradingview, è improbabile che i valori dell’indicatore corrispondano. Questo può accadere perché

  1. I dati OHLC potrebbero non essere esattamente gli stessi. Ad esempio, in casi limite, una piattaforma potrebbe mostrare un asset chiuso leggermente al rialzo mentre in un altra ha chiuso leggermente al ribasso o è rimasto flat.
  2. Ancora più importante, i valori sono cumulativi. Si basano sul valore precedente. Quindi essere uguali i dati sulle due piattaforme devono iniziare esattamente lo stesso giorno.

Tuttavia, detto questo, possiamo avere un’idea generale del comportamento dell’indicatore tramite i grafici. Vediamo il seguente confronto tra l’indicatore in Backtrader e Tradingview.

Backtrader Indicatore On Balance Volume - Grafici

Nell’immagine possiamo vedere che sebbene i valori riportati siano diversi, la forma delle curva dell’indicatore corrisponde abbastanza bene.

Codice completo

In questo articolo abbiamo descritto come costruire ed usare l’indicatore On Balance Volume con Backtrader per creare strategie di trading algoritmico e quantitativo. Per il codice completo riportato in questo articolo, si può consultare il seguente repository di github:
https://github.com/datatrading-info/BackTrader

Torna in alto
Scroll to Top