#!/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.")
