operations_research/OR_HTML_04/programme/Diversifikation_Demo.py
dschlueter b7af2f1d9a Version 04 als eigenes Repository
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>
2026-09-08 01:20:09 +02:00

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.")