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>
47 lines
1.8 KiB
Python
Generated
47 lines
1.8 KiB
Python
Generated
#!/usr/bin/env python3
|
|
|
|
# Diversifikation_Demo.py
|
|
"""
|
|
Kapitel Markowitz: Portfoliorisiko in Abhaengigkeit von der Korrelation - die
|
|
Handrechnung zum Gratis-Mittagessen, geprueft ueber die analytische Formel und
|
|
ueber simulierte, korrelierte Renditen.
|
|
"""
|
|
|
|
import numpy as np
|
|
|
|
MU = 0.08
|
|
SIGMA = 0.20
|
|
|
|
|
|
def sigma_portfolio(rho: float, w1: float = 0.5) -> float:
|
|
"""Analytische Formel: sigma_p^2 = w1^2 s1^2 + w2^2 s2^2 + 2 w1 w2 rho s1 s2."""
|
|
w2 = 1 - w1
|
|
varianz = w1**2 * SIGMA**2 + w2**2 * SIGMA**2 + 2 * w1 * w2 * rho * SIGMA**2
|
|
return float(np.sqrt(varianz))
|
|
|
|
|
|
def simuliere(rho: float, n: int = 500_000, seed: int = 7) -> float:
|
|
"""Erzeugt n korrelierte Renditepaare und misst die Portfolio-Volatilitaet empirisch."""
|
|
rng = np.random.default_rng(seed)
|
|
kovarianz = np.array([[SIGMA**2, rho * SIGMA**2],
|
|
[rho * SIGMA**2, SIGMA**2]])
|
|
renditen = rng.multivariate_normal([MU, MU], kovarianz, size=n)
|
|
portfolio = 0.5 * renditen[:, 0] + 0.5 * renditen[:, 1]
|
|
return float(portfolio.std(ddof=1))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print("=" * 78)
|
|
print(" PORTFOLIORISIKO IN ABHAENGIGKEIT VON DER KORRELATION")
|
|
print("=" * 78)
|
|
print(f"{'rho':>6} | {'sigma_p (Formel)':>18} | {'sigma_p (Simulation)':>20} | {'Risikoreduktion':>16}")
|
|
print("-" * 78)
|
|
for rho in [1.0, 0.5, 0.0, -0.5, -1.0]:
|
|
formel = sigma_portfolio(rho)
|
|
sim = simuliere(rho)
|
|
reduktion = (1 - formel / SIGMA) * 100
|
|
print(f"{rho:6.1f} | {formel*100:16.2f} % | {sim*100:18.2f} % | {reduktion:14.0f} %")
|
|
|
|
print("\nDie simulierten Werte (500.000 gezogene Renditepaare je rho) bestaetigen")
|
|
print("die Formel aus der Handrechnung bis auf statistisches Rauschen - und das,")
|
|
print("obwohl Formel und Simulation nichts voneinander wissen.")
|