#!/usr/bin/env python3 # Renditen_Vergleich.py """ Kapitel Finanzdaten: Diskrete vs. logarithmische Renditen. Zeigt an einem simulierten Kursverlauf, welche Eigenschaft wo gilt - und warum das arithmetische Mittel diskreter Renditen in die Irre fuehrt. """ import numpy as np import pandas as pd if __name__ == "__main__": kurse = np.array([100.0, 150.0, 100.0, 120.0, 90.0, 135.0]) tage = [f"t{i}" for i in range(len(kurse))] diskret = kurse[1:] / kurse[:-1] - 1.0 logarithmisch = np.log(kurse[1:] / kurse[:-1]) print("=" * 74) print(" DISKRETE UND LOGARITHMISCHE RENDITEN IM VERGLEICH") print("=" * 74) tabelle = pd.DataFrame({ "Periode": [f"{tage[i]} -> {tage[i+1]}" for i in range(len(diskret))], "Kurs von": kurse[:-1], "Kurs bis": kurse[1:], "diskret R": [f"{r*100:+7.2f} %" for r in diskret], "log r": [f"{r:+8.4f}" for r in logarithmisch], }) print(tabelle.to_string(index=False)) # --- Zeitliche Aggregation ------------------------------------------ gesamt_wahr = kurse[-1] / kurse[0] - 1.0 summe_log = logarithmisch.sum() aus_log_zurueck = np.exp(summe_log) - 1.0 summe_diskret = diskret.sum() print("\n--- Aggregation ueber die Zeit ---") print(f" Tatsaechliche Gesamtrendite: {gesamt_wahr*100:+8.2f} %") print(f" Summe der Log-Renditen -> exp()-1: {aus_log_zurueck*100:+8.2f} % " f"{'KORREKT' if abs(aus_log_zurueck - gesamt_wahr) < 1e-9 else 'falsch'}") print(f" Summe der diskreten Renditen: {summe_diskret*100:+8.2f} % FALSCH") # --- Mittelwerte ------------------------------------------------------ arithmetisch = diskret.mean() geometrisch = np.prod(1 + diskret) ** (1 / len(diskret)) - 1 aus_log = np.exp(logarithmisch.mean()) - 1 print("\n--- Welcher Mittelwert ist der richtige? ---") print(f" Arithmetisches Mittel (diskret): {arithmetisch*100:+8.2f} % " f"-> ueberschaetzt") print(f" Geometrisches Mittel: {geometrisch*100:+8.2f} % -> korrekt") print(f" exp(Mittel der Log-Renditen) - 1: {aus_log*100:+8.2f} % " f"-> identisch zum geometrischen") # Probe: Endkapital mit dem jeweiligen Mittelwert hochgerechnet n = len(diskret) print(f"\n Probe - Startkapital 100 EUR ueber {n} Perioden:") print(f" tatsaechlich: {kurse[-1]:8.2f} EUR") print(f" mit arithm. Mittel hochgerechnet: {100*(1+arithmetisch)**n:8.2f} EUR") print(f" mit geom. Mittel hochgerechnet: {100*(1+geometrisch)**n:8.2f} EUR") print("\n--- Annualisierung (252 Handelstage) ---") print(f" Volatilitaet aus Log-Renditen: " f"{logarithmisch.std(ddof=1)*np.sqrt(252)*100:.2f} % p.a.") print(" (Die Wurzel-Zeit-Regel gilt nur bei unabhaengigen Renditen -") print(" fuer reale Maerkte ist sie eine Naeherung.)") print("=" * 74)