fixato problema interno di CVXPY/ARPACK durante ccertificazione matrice PSD
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Ottimizzatore Lite
|
||||
Ottimizzatore ITA
|
||||
"""
|
||||
|
||||
# =========================
|
||||
@@ -22,6 +22,26 @@ from pypfopt import risk_models
|
||||
from pypfopt.efficient_frontier import EfficientFrontier
|
||||
from pypfopt.exceptions import OptimizationError
|
||||
|
||||
# ---------------------------------------------------
|
||||
# Patch PyPortfolioOpt: usa cp.psd_wrap sulla covarianza
|
||||
# ---------------------------------------------------
|
||||
import cvxpy as cp
|
||||
from pypfopt import objective_functions as _obj
|
||||
|
||||
def portfolio_variance_psdwrap(w, cov_matrix):
|
||||
"""
|
||||
Versione patchata di portfolio_variance:
|
||||
usa cp.psd_wrap(cov_matrix) per evitare che CVXPY
|
||||
faccia il controllo spettrale con ARPACK.
|
||||
Comportamento identico all'originale, ma più robusto.
|
||||
"""
|
||||
variance = cp.quad_form(w, cp.psd_wrap(cov_matrix))
|
||||
return _obj._objective_value(w, variance)
|
||||
|
||||
# Monkey patch globale: da qui in poi EfficientFrontier usa questa versione
|
||||
_obj.portfolio_variance = portfolio_variance_psdwrap
|
||||
|
||||
|
||||
# Cartelle di input/output/plot
|
||||
OUTPUT_DIR = "Output"
|
||||
INPUT_DIR = "Input"
|
||||
@@ -256,6 +276,37 @@ def h_min_100(returns: pd.Series, month_len: int = 21):
|
||||
|
||||
return np.nan, np.nan
|
||||
|
||||
# ---------------------------------
|
||||
# Utility per rendere PSD/robusta la covarianza
|
||||
# ---------------------------------
|
||||
def regularize_covariance(cov_df: pd.DataFrame, ridge_factor: float = 1e-6) -> pd.DataFrame:
|
||||
"""
|
||||
Rende la matrice di covarianza numericamente piu' robusta:
|
||||
- la simmetrizza
|
||||
- aggiunge un piccolo termine di ridge sulla diagonale
|
||||
Ritorna un nuovo DataFrame con stessa index/columns.
|
||||
"""
|
||||
if cov_df.empty:
|
||||
return cov_df
|
||||
|
||||
Sigma = cov_df.values.astype(float)
|
||||
|
||||
# simmetrizza (elimina piccole asimmetrie numeriche)
|
||||
Sigma = 0.5 * (Sigma + Sigma.T)
|
||||
|
||||
# piccolo ridge proporzionato alla scala media delle varianze
|
||||
n = Sigma.shape[0]
|
||||
trace = np.trace(Sigma)
|
||||
if np.isfinite(trace) and n > 0:
|
||||
eps = ridge_factor * (trace / n)
|
||||
else:
|
||||
eps = ridge_factor
|
||||
|
||||
Sigma_reg = Sigma + eps * np.eye(n)
|
||||
|
||||
return pd.DataFrame(Sigma_reg, index=cov_df.index, columns=cov_df.columns)
|
||||
|
||||
|
||||
# --- Lettura parametri dal file connection.txt ---
|
||||
params = {}
|
||||
with open("connection.txt", "r") as f:
|
||||
@@ -359,6 +410,9 @@ for (years, target_vol), name in volatility_targets.items():
|
||||
daily_returns_mean = period_df.mean()
|
||||
annual_returns_mean = daily_returns_mean * days_per_year
|
||||
annual_covariance_matrix = risk_models.sample_cov(period_df, returns_data=True)
|
||||
# --- Regularizzazione covarianza per l'ottimizzatore ---
|
||||
annual_covariance_matrix = regularize_covariance(annual_covariance_matrix)
|
||||
|
||||
|
||||
# ---------- PER-ASSET METRICS ----------
|
||||
n_days = int(period_df.shape[0])
|
||||
@@ -519,6 +573,9 @@ for (years, target_vol), name in volatility_targets.items():
|
||||
annual_returns_mean = daily_returns_mean * days_per_year
|
||||
annual_covariance_matrix = risk_models.sample_cov(period_df, returns_data=True)
|
||||
|
||||
# --- Regularizzazione covarianza per l'ottimizzatore ---
|
||||
annual_covariance_matrix = regularize_covariance(annual_covariance_matrix)
|
||||
|
||||
w_series = optimized_weights[name].reindex(period_df.columns).fillna(0.0)
|
||||
w_vec = w_series.values
|
||||
|
||||
|
||||
Reference in New Issue
Block a user