Bollinger Bänder im Backtest mit Python

In diesem Artikel werde ich die Strategie der Bollinger Bänder zunächst etwas genauer erläutern, um anschließend aufzuzeigen, wie eine Variante der Strategie in Python getestet werden kann. Dieser Artikel ist ähnlich zum kürzlich veröffentlichten Artikel über gleitende Durchschnitte. Dieses Mal wird die Strategie jedoch anhand einer eigens programmierten Funktion getestet.

Was sind Bollinger Bänder?

Die Bollinger Bänder sind grundsätzlich den gleitenden Durchschnitten sehr ähnlich. Bei diesem Indikator werden drei Bänder betrachtet. Das mittlere Band stellt einen gleitenden Durchschnitt dar und wird oft mit einem Horizont von 20 Tagen berechnet. Das obere Band ergibt sich, indem man die Standardabweichung mit einem festgelegten, konstanten Faktor multipliziert und anschließend auf den gleitenden Durchschnitt addiert. Das untere Band ergibt sich, respektive, indem man die Standardabweichung mit dem gleichen festgelegten, konstanten Faktor multipliziert und anschließend vom mittleren Durchschnitt subtrahiert. Der konstante Faktor kann variieren (dazu später mehr).

Am Beispiel des Aktienkurses von Apple sind die Bollinger Bänder im folgenden Diagramm veranschaulicht.

Wie sieht die Strategie aus?

Ziel der Strategie ist es, zum Mittel zurückzugehen. Sobald der Kurs das untere Band trifft, gehen wir Long und sobald der Kurs das obere Band trifft, gehen wir Short. Ziemlich simpel. Die Strategie in diesem Artikel soll zudem ohne einen Take Profit getestet werden. Das wird in einem Folgeartikel dann nachgeholt und geschaut, welchen Effekt ein Take Profit hätte.

Let's start Coding

Die Strategie wird mittels einer programmierten Funktion umgesetzt. Die Erläuterungen dazu sind direkt im Code zu finden. Das sollte alles etwas besser verständlich und übersichtlicher machen.

#Alle notwendigen libraries importieren
import pandas as pd
import numpy as np
import quandl
import matplotlib.pyplot as plt  
import seaborn as sns

#Zeitreihe von Apple über die API von Quandl herunterladen
df = quandl.get("EOD/AAPL",start_date ='2000-01-01', 
end_date='2021-01-01',column_index =11)
#Eine Funktion wird durch die Kürzel 'def' definiert
#Innerhalb der Funktion Bollinger_Bands werden alle notwendigen Variablen definiert
def Bollinger_Bands(data,window,no_of_std):

#Es werden zuerst alle Bänder berechnet
    df['Mean'] = df.Adj_Close.rolling(window).mean() #Mittleres Band
    df['SD'] = df.Adj_Close.rolling(window).std() #Standardabweichung
    df['BB Oben'] = df.Mean + (data.SD * no_of_std) # Oberes Band
    df['BB Unten'] = df.Mean - (data.SD * no_of_std) #Unteres Band
    
    df['Short'] = None
    df['Long'] = None
    df['Position'] = None
    
#Hier wird ein for loop verwendet um über alle Reihen des Datensatzes zu loopen
    for row in range(len(df)):
    #Checken, wo ein Signal für eine Short Position auftritt
        if (df['Adj_Close'].iloc[row] > df['BB Oben'].iloc[row]) and (df['Adj_Close'].iloc[row-1] < df['BB Oben'].iloc[row-1]):
            df['Position'].iloc[row] = -1
    #Checken, wo ein Signal für eine Long Position auftritt
        if (df['Adj_Close'].iloc[row] < df['BB Unten'].iloc[row]) and (df['Adj_Close'].iloc[row-1] > df['BB Unten'].iloc[row-1]):
            df['Position'].iloc[row] = 1
            
    #Die gefundenen Signale werden ganz simple fortgeführt, da es keinen Take Profit gibt!
    df['Position'].fillna(method='ffill',inplace=True)
    
    #Berechnen der Renditen von Apple
    df['Market Return'] = np.log(df['Adj_Close'] / df['Adj_Close'].shift(1))
    #Berechnen der Renditen der Strategie
    df['Strategy Return'] = df['Market Return'] * df['Position'].shift(1)
    #Kumulierte Performance + Plot
    df['Strategy Return'].cumsum().plot(linewidth = 3)
    plt.xticks(fontsize=18)
    plt.yticks(fontsize=18)

So, das war’s auch schon! Die Funktion ist programmiert und kann durch Aufrufen von Bollinger_Bands jederzeit verwendet werden. Lediglich die notwendigen Parameter müssen eingetragen werden.

#Beispiel
Bollinger_Bands(df,20,2)
#df definiert den Datensatz
#20 steht für unseren Zeithorizont
#2 ist der zu wählende Faktor, mit dem die Standardabweichung multipliziert wird

Das folgende Diagramm zeigt die kumulierte Performance des in der Funktion betrachteten Portfolios.

Die Strategie der Bollinger Bänder eignet sich also scheinbar nicht, um eine positive Rendite zu erzielen. Zumindest nicht mit den Parametern, die oben gewählt wurden.

Wir können nun jedoch eine gewisse Bandbreite definieren, für die unsere Funktion die Performance der Bollinger Bänder Strategie berechnen soll. Dabei werden die beiden Inputparameter innerhalb eines von uns definierten Intervalls variiert. Im nachfolgenden Diagramm sind die Performance Ergebnisse mit unterschiedlichen Parameterwerten abgetragen.

#Wir definieren mit windows und stds zwei Vektoren, innerhalb derer die Funktion die Performance berechnen soll
windows = np.linspace(10,100,10,dtype=int)
stds = np.linspace(1,3,10)
#Wir loopen durch beide Vektoren und lassen die Funktion den Rest erledigen
for window in windows:
    for std in stds:
        Bollinger_Bands(df,window,std)

Ehrlicherweise sind die Ergebnisse auch bei Variation der Parameter nicht sehr überzeugend. Dies liegt unter anderem an der sehr einfachen Strategie, die verfolgt wurde. So wurde bspw. kein Take Profit definiert, sodass man ständig im Markt investiert war. Des Weiteren wurde die Strategie nur anhand von Kursdaten der Apple Aktie getestet, was nicht optimal ist. Besser ist es, eine Strategie an mehreren Aktien zu testen, da so ein Portfolio aus Short und Long Position erstellt werden kann. All das wird aber in Folgeartikeln nachgeholt.

Viele Grüße

Felix von Portfolio-Architekt

Inhalte werden geladen

Schreibe einen Kommentar