Startseite » ETF Portfolio Tools » Krisenindikatoren des ultrastabilen Portfolios

Krisenindikatoren des ultrastabilen Portfolios

Chris

Dipl.-Ingenieur, Developer, #Buy-and-Hold #ETF #Investor, Freelancer, Lerner

Auto Tacho

Während wir im letzten Artikel das ultrastabile Portfolio von Dr. Andreas Beck analysiert haben, schauen wir uns jetzt die Indikatoren für eine Krise genauer an, die zu einer Veränderung des investierten Kapitals führen.

Wie im aktuellen Whitepaper zur Beschreibung des ultrastabilen Portfolios dargestellt, werden 3 verschiedene Zustände des Systems unterschieden (sog. “Regimes”) 1, die zu unterschiedlichen Gewichtungen des investierten Kapitals führen.
Dabei erfolgt die Steuerung, in welchem Regime sich das Portfolio aktuell befindet, über folgende Krisen-Indikatoren:

  1. Aktienmarktverlust zum 3-Jahreshoch
  2. Volatilität am Aktienmarkt
  3. Risikoprämien bei Unternehmensanleihen

Unser Ziel ist jetzt, diese 3 Key Performance Indicators (KPIs) des ultrastabilen Portfolios in R abzubilden, um so in Zukunft selbst schnell und einfach feststellen zu können, in welchem Regime wir uns befinden.

Krisen-Indikatoren in R abbilden

Für den Code verwenden wir diesmal eine RMarkdown-Datei. Damit ist es sehr einfach möglich, alle 3 Indikatoren übersichtlich auf einer Seite abzubilden, ggfs. noch erklärenden Text zu ergänzen und diesen dann z.B. als PDF oder HTML-Datei zu exportieren.

Als Vorbereitung laden wir noch ein paar benötigte Libraries:

library(tidyverse)
library(tidyquant)
library(plotly)

Indikator #1: Aktienmarktverlust zum 3-Jahreshoch

Für diesen Indikator verwenden wir den MSCI All Country World Index (ACWI), der alle Mid Caps und Large Caps der Welt inkl. der Schwellenländer enthält und somit einen guten Gradmesser für den gesamten Aktienmarkt darstellt.
Hierzu laden wir als erstes die historischen Kurse der letzten 3 Jahre. Als Kurslieferant verwenden wir diesmal Ariva, da diese sehr weit zurückreichende historische Daten zur Verfügung stellen.

min_time <- "1.3.2018"
max_time <- "1.3.2021"
tbl_timeseries <- read_csv2(paste("https://www.ariva.de/quote/historic/historic.csv?secu=105686722&boerse_id=8&clean_split=1&clean_payout=1&clean_bezug=1&currency=EUR&min_time=", min_time, "&max_time=", max_time, "&trenner=%3B&go=Download", sep="")) %>%
  select("Datum", "Schlusskurs") %>%
  arrange(Datum)

Der Krisen-Indikator besagt, dass für den Übergang in das Krisen-Regime “Eigenkapitalknappheit” (Regime A -> B) der Aktienmarktverlust im Vergleich zum 3-Jahreshoch mehr als 20% betragen muss. Berechnen wir also das Maximum in diesen 3 Jahren:

all_time_high <- max(tbl_timeseries$Schlusskurs)

Als nächstes müssen wir diese historischen Kursdaten nur noch in eine Form überführen, so dass wir sie schön grafisch darstellen können:

p <- tbl_timeseries %>%
    ggplot(aes(x = Datum, y = Schlusskurs)) +
    geom_line() +
    labs(x = "", y = "Price") +
    theme_tq() +
    scale_color_tq() +
    scale_x_date(date_labels = "%Y-%m-%d") +
    theme(legend.position = "none")

  ggplotly(p + 
             geom_hline(yintercept=all_time_high, color = "red") + 
             geom_hline(yintercept=0.8*all_time_high, color = "green"))

Und so stellt sich das Ergebnis unseres ersten Krisen-Indikators Aktienmarktverlust am 1.3.2021 dar:

Die rote bzw. grüne horizontale Linie markiert jeweils den Höchststand bzw. 20% Verlust davon, d.h. das Signal, dass dieser Indikator erfüllt ist.

Indikator #2: Volatilität am Aktienmarkt

Auch die Volatilität stellen wir wieder anhand der täglichen Schwankungen des MSCI ACWI dar. Hierzu berechnen wir mit der Funktion periodReturn die Renditen auf Tagesbasis:

p2 <- tbl_timeseries %>%
  tq_transmute(select = Schlusskurs, mutate_fun = periodReturn, period = "daily") %>%
    ggplot(aes(x = Datum, y = daily.returns)) +
    geom_bar(stat = "identity", aes(fill = (abs(daily.returns) > 0.05))) +
    scale_fill_manual(guide = FALSE, breaks = c(TRUE, FALSE), values=c(palette_light()[["red"]], "#EFEFEF")) +
    labs(x = "", y = "Daily Returns") +
    theme_tq() +
    scale_color_tq() +
    scale_y_continuous(labels = scales::percent) +
    scale_x_date(date_labels = "%Y-%m-%d") +
    theme(legend.position = "none")

  ggplotly(p2)

Der Krisen-Indikator verlangt eine sprunghafte Erhöhung der Volatilität am Aktienmarkt. Im Ergebnis habe ich daher die täglichen Ausschläge über 5% rot markiert:

Indikator #3: Risikoprämien bei Unternehmensanleihen

Dies ist sicherlich der komplizierteste Krisen-Indikator im Vergleich zu den anderen beiden.
Im Folgenden schaue ich mir für diesen Indikator den Spread zwischen globalen Unternehmensanleihen mit Rating “Investment Grade” (IG) im Vergleich zu High Yield Unternehmensanleihen an, d.h. Hoch-Risiko-Anleihen. Für den Vergleich verwende ich 2 ETFs von iShares auf entsprechende Indizes, weil sich diese Daten gut auswerten lassen.

Hierfür laden wir als erstes die Kurse der beiden iShares-ETF mit den WKNs A0RGEP und A1C3NE wieder von der Ariva-Website:

tbl_timeseries_ig <- read_csv2(paste("https://www.ariva.de/quote/historic/historic.csv?secu=101756953&boerse_id=8&clean_split=1&clean_payout=1&clean_bezug=1&currency=EUR&min_time=", min_time, "&max_time=", max_time, "&trenner=%3B&go=Download", sep="")) %>%
  select("Datum", "Schlusskurs") %>%
  arrange(Datum)

tbl_timeseries_high_yield <- read_csv2(paste("https://www.ariva.de/quote/historic/historic.csv?secu=103419256&boerse_id=8&clean_split=1&clean_payout=1&clean_bezug=1&currency=EUR&min_time=", min_time, "&max_time=", max_time, "&trenner=%3B&go=Download", sep="")) %>%
  select("Datum", "Schlusskurs") %>%
  arrange(Datum)

Als nächstes berechnen wir die Kursdifferenz der beiden ETFs und stellen diese grafisch dar:

p <- left_join(tbl_timeseries_ig, tbl_timeseries_high_yield, by="Datum") %>%
    mutate(Schlusskurs = Schlusskurs.x - Schlusskurs.y) %>%
    ggplot(aes(x = Datum, y = Schlusskurs)) +
    geom_line() +
    labs(x = "", y = "Spread") +
    theme_tq() +
    scale_color_tq() +
    scale_x_date(date_labels = "%Y-%m-%d") +
    theme(legend.position = "none")

  ggplotly(p)

Der Indikator verlangt laut dem Whitepaper eine Ausweitung der Risikoprämien, wie sich in unserer generierten Grafik zeigt:

Zeitliche Abfolge am Beispiel des Corona-Crashes

Insbesondere bei den Indikatoren #2 und #3 besteht natürlich eine gewisse Flexibilität zur Bestimmung des exakten Zeitpunkts für den Wechsel von Regime “Normal” zu “Eigenkapitalknappheit”. Während sich der erste Indikator Aktienmarktverlust größer 20% sehr genau bestimmen lässt und knüpft Andreas Beck die Volatilität und den Spread in seinem veröffentlichten Whitepaper nicht an harte Zahlen.

Schauen wir uns daher abschließend am Beispiel des Spreads noch kurz die zeitliche Abfolge an und vergleichen diese mit unseren generierten Grafiken.

Als erstes schlägt der Volatilitäts-Indikator an: ab 9.3.2020 ist hier ein sprunghafter Anstieg zu sehen – erkennbar an den roten Balken im Graphen. Am selben Tag greift auch der erste Indikator, weil der Aktienmarktverlust gegenüber dem Dreijahreshoch vom 19.2.2020 mehr als 20% beträgt, wie der Schnittpunkt der grünen Linie im Diagramm deutlich zeigt.
Trotzdem wurde der Wechsel von Regime A nach B noch nicht vollzogen, da der dritte Indikator, die Anleihe-Spreads, noch nicht auffällig war (siehe Whitepaper Seite 31). In unserem interaktiven Plot zu den Spreads (Indikator #3) in RStudio kann man sehr schön ablesen, dass der Spread am 9.3.2020 mit 38,41 nur leicht über dem Durchschnitt lag. Laut dem Whitepaper wurde dann einige Tage später am 15.3. auch dieser Indikator gerissen, so dass der Regime-Wechsel im Portfolio am 20.3.2020 vollzogen wurde.

Ergebnis

Im Ergebnis sieht man sehr schön, dass für die letzten 3 Jahre die Corona-Krise im März 2020 eine Krise im Sinne des Regimes “Eigenkapitalknappheit” (Regime A -> B) des ultrastabilen Portfolios von Dr. Andreas Beck ist.
Dies zeigen alle 3 Krisen-Indikatoren in den grafischen Auswertungen sehr deutlich. Mit dieser Anleitung lassen sich die Indikatoren sehr gut in R nachvollziehen und für zukünftige Krisen nutzen.


  1. siehe PDF-Whitepaper “Erfolgreich wissenschaftlich investieren” von Dr. Andreas Beck, Seite 27.

Weitere interessante Artikel

Disclaimer: Meine kostenlosen und freien Recherchen stellen meine persönliche Meinung dar und sind in keinster Weise eine Anlageempfehlung. Sie werden mit größtmöglicher Sorgfalt erstellt, aber sie können trotzdem ganz oder teilweise falsch sein. Daher übernehme ich keinerlei Haftung für Anlageentscheidungen, die auf Basis der hier vermittelten Informationen getroffen werden. Des Weiteren erhebt diese Website keinen Anspruch auf Vollständigkeit, Richtigkeit und Aktualität.

10 Gedanken zu „Krisenindikatoren des ultrastabilen Portfolios“

  1. Pingback: Analyse des ultrastabilen Portfolio von Andreas Beck | Finanzen für Techies | /dev/investor

  2. Hi, sehr guter Artikel, danke dafür.

    Deine Ermittlung für die Volatilität ist natürlich sehr viel genauer, aber einfacher geht es mit dem VIX index auf den S&P 500. Nach Marktkapitalisierung ist dies eh der "größte" Markt.

    Den Indikator für B zu C habe ich allerdings anders, bzw. weniger komplex verstanden nachdem ich die Fußnote durchgelesen habe, Zitat: "Ausgehend vom Dreijahreshoch befindet sich das Aktienportfolio somit nach den Regimewechseln A->B und B->C zu 40% im Verlust(0,80×0,75=0,60).
    Somit würde ein das Dreijahreshoch * 0,6 mit dem aktuellen Wert des ACWI oder FTSE All-World (Symbol VGWL.DE) vergleichen (hat eine etwas größere Abdeckung). Hier mal ein Beispiel in Python, allerdings ohne Plot. Benutze das lediglich um mich via Telegram zu alarmieren:

    import time
    import pandas as pd
    import datetime
    import yahoo_fin.stock_info as si
    import requests
    
    today = datetime.datetime.today()-datetime.timedelta(days=1096)
    
    # dd/mm/YY
    d1 = today.strftime("%d/%m/%Y")
    
    def telegram_bot_sendtext(bot_message):
        
        bot_token = ''
        bot_chatID = ''
        send_text = 'https://api.telegram.org/bot ' + bot_token + '/sendMessage?chat_id=' + bot_chatID + '&parse_mode=Markdown&text=' + bot_message
        response = requests.get(send_text)
        return response.json()
    
    
    def executeSomething():
        vix = si.get_live_price('^vix')
        vgwl = si.get_live_price('VGWL.DE')
        if vix < 40:
          print("--- calc VIX ---")
          d = si.get_data("VGWL.DE" , start_date = d1 , interval = "1d")
          df = pd.DataFrame(d,columns=['high'])
          highs = df['high'].max()
          if vgwl <= highs*0.8:
            print("--- VGWL value ---")
            message = "ALERT VGWL at 80% of 3 year high:" + str(vgwl)
            telegram_bot_sendtext(message)
            print(message)
            elif vgwl <= highs*0.8:
              print("--- VGWL value ---")
              message = "ALERT VGWL at 60% of 3 year high:" + str(vgwl)
              telegram_bot_sendtext(message)
              print(message)
    
    
    while True:
        executeSomething()
        time.sleep(60)
    1. Servus Andre,

      wow, vielen Dank für Deinen Kommentar und das Script!
      Werde ich auf jeden Fall mal testen.

      Du hast Recht, ich würde auch sagen, das ist eine valide Vereinfachung mit dem VIX.

      Viele Grüße,
      Chris

  3. Sehr guter Artikel!
    Natürlich ist perfektes Timing unmöglich. Es wäre aber dennoch interessant zu untersuchen, wann genau man kaufen sollte, d.h. sollte man kaufen wenn der Spread maximal ist, oder wenn er sich wieder verringert hat? Gibt es hierzu Erfahrungswerte?
    Grüsse,
    Dirk

    1. Hi Dirk,

      vielen Dank für Dein Feedback! Freut mich sehr, dass Dir der Artikel gefällt.

      Andreas Beck spricht in seinem Whitepaper (https://globalportfolio-one.com/ ) von einer "Ausweitung der Risikoprämien" (siehe Seite 27) und konkretisiert dies dann später in der zeitlichen Abfolge noch. D.h. ich verstehe es so, dass der Spread möglichst maximal sein sollte.

      Ich habe im Blog-Post noch einen Abschnitt ergänzt, der die zeitliche Abfolge genauer beschreibt und mit meinen generierten Plots aus R vergleicht. Ich hoffe, es wird so auch nochmal verständlicher.

      Viele Grüße,
      Chris

      1. Hi Chris,
        ja, ich denke auch, dass der Spread maximal sein sollte. D.h. man weiss natürlich nicht, wann das Maximum erreicht sein wird. Daher sollte man den Spread eine Zeit lang beobachten. Ich werde so verfahren: Wenn der Spread nach seinem sprunghaften Anstieg 7 Tage in Folge wieder gefallen ist, so werde ich kaufen. Ich hoffe und bete dann, dass das bisher beobachtete Maximum wirklich das absolute Maxiumum war und es nicht noch zu einem weiteren Anstieg des Spreads kommt. Eine Garantie gibts natürlich nicht.
        Grüsse,
        Dirk

    2. Herzlichen Dank für diese nützlichen Werkzeuge, finde ich großartig. Leider kenne ich mich mit diesem "R" überhaupt nicht aus und habe etwas Zeit benötigt, um diese Code-Zeilen zum Leben zu erwecken. Letzten Endes ist es gelungen und ich konnte die hier abgebildeten Plots dann erzeugen. Ich musste dafür allerdings an zwei Stellen Änderungen vornehmen: Beim Indikator "Aktienmarktverlust" habe ich in der Zeile
      labs(, x = "", y = "Price") +
      das Komma hinter der öffnenden Klammer entfernt. Im letzten Code-Block für den Indikator Risikoprämien habe ich "tbl_timeseries_aaa" durch "tbl_timeseries_ig" ersetzt.
      Nochmals vielen Dank jedenfalls, finde es super, dass du dir die Mühe machst und das hier veröffentlichst.

      1. Hi cs,

        vielen herzlichen Dank für Deinen Input!

        Du hast absolut Recht, da haben sich tatsächlich 2 kleine Fehler eingeschlichen (so ist das, wenn man nachträglich noch optimiert ;-).
        Ich habe beide Stellen korrigiert.

        Viele Grüße & schöne Ostertage,
        Chris

    3. Hallo – Super Beitrag, bin ebenfalls großer Fan vom A Beck ! Ich habe es in Excel 2017 Nachgebaut!
      Ich habe für secu=105686722 / ACWI / A1JMDF am
      2/12/2020 eine Kurs von 56,6032

      1. Hi,

        vielen Dank für Deinen Kommentar!

        Magst Du Dein Excel vielleicht zur Verfügung stellen, damit wir die Ergebnisse vergleichen können?

        Viele Grüße,
        Chris

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.