Erster Commit des Strangs "Optimierte Entscheidungsfindung mit Python" (Version 04). Die Historie der 71 Commits bis zur Trennung bleibt im uebergeordneten Repository OR_mit_Python liegen, das ab jetzt nur noch Version_03 (eingefroren) verwaltet und Version_04/ ignoriert. Bewusst kein "git subtree split": Der Pfad Version_04/ existiert erst seit der Verzeichnistrennung, ein Split braechte daher nur 7 der 41 einschlaegigen Commits - eine Teilhistorie, die vollstaendig aussieht und es nicht ist. Stand: 5 Teile, 23 Kapitel, 5 Anhaenge, 292 Abschnitte, 703 Querverweise, 325 Indexmarken, 73 Beispielprogramme, 32 SVGs, 4 Plotly-Figuren, 25 Notebooks, PDF mit 715 Seiten. Zusaetzlich in diesem Commit: * pyproject.toml mit Abhaengigkeitsgruppen finance, large-scale, api, figures, dev, empfehlungen. Die abgedruckte requirements.txt bleibt unveraendert daneben bestehen. ortools steht in der Grundausstattung, highspy erst in [large-scale] - so kann der HiGHS-Symbolkonflikt bei der schlanken Installation gar nicht erst auftreten. * Dabei zwei Funde: graphviz wird von erzeuge_architektur_diagramme.py importiert, fehlt aber in requirements.txt (jetzt in [figures]); pymoo steht in requirements.txt, wird aber von keinem Programm importiert, sondern nur im Kapitel Metaheuristiken empfohlen (jetzt in [empfehlungen]). * NEUER_TITEL.md nach Kritik_und_Verbesserungsvorschlaege/ verschoben - es ist die Vorlage des Titelblatts, kein Bestandteil des Werks. Die beiden Fundstellen in PROGRESS.md und erzeuge_titelseite.py nachgezogen. * PROGRESS.md nannte noch den Untertitel der ersten Fassung; auf den tatsaechlichen aus erzeuge_titelseite.py korrigiert. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
68 lines
2.9 KiB
Python
Generated
68 lines
2.9 KiB
Python
Generated
#!/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)
|