Spaces:
Running
Running
| import pandas as pd | |
| import numpy as np | |
| from sklearn.covariance import LedoitWolf | |
| import logging | |
| logger = logging.getLogger(__name__) | |
| class RiskModel: | |
| """ | |
| Computes the covariance matrix of asset returns using Ledoit-Wolf Shrinkage. | |
| This is essential for high-dimensional portfolios (N > 500) where the | |
| sample covariance matrix is often ill-conditioned or noisy. | |
| """ | |
| def __init__(self): | |
| pass | |
| def compute_covariance_matrix(self, returns: pd.DataFrame) -> pd.DataFrame: | |
| """ | |
| Calculates the shrunk covariance matrix. | |
| Args: | |
| returns (pd.DataFrame): Historical daily returns (Date index, Ticker columns). | |
| Returns: | |
| pd.DataFrame: Covariance matrix (Ticker index, Ticker columns). | |
| """ | |
| if returns.empty: | |
| logger.error("Returns dataframe is empty. Cannot compute covariance.") | |
| raise ValueError("Empty returns dataframe.") | |
| logger.info(f"Computing Ledoit-Wolf shrinkage covariance for {returns.shape[1]} assets...") | |
| # Use scikit-learn's LedoitWolf estimator | |
| lw = LedoitWolf() | |
| # Fit logic | |
| # Note: scikit-learn expects (n_samples, n_features). | |
| # Our returns df is already (n_days, n_tickers), which matches. | |
| try: | |
| X = returns.values | |
| lw.fit(X) | |
| # The estimated covariance matrix | |
| cov_matrix = lw.covariance_ | |
| # Reconstruct DataFrame | |
| cov_df = pd.DataFrame( | |
| cov_matrix, | |
| index=returns.columns, | |
| columns=returns.columns | |
| ) | |
| logger.info("Covariance matrix computation successful.") | |
| return cov_df | |
| except Exception as e: | |
| logger.error(f"Failed to compute covariance matrix: {e}") | |
| raise e | |