@@ -26,6 +26,8 @@ def sharpe_ratio(returns: pd.Series, risk_free: float = RISK_FREE_RATE) -> float
2626
2727
2828def max_drawdown (prices : pd .Series ) -> float :
29+ if prices is None or len (prices ) == 0 :
30+ return 0.0
2931 cumulative = prices / prices .iloc [0 ]
3032 running_max = cumulative .cummax ()
3133 drawdown = (cumulative - running_max ) / running_max
@@ -47,6 +49,9 @@ def compute_per_asset_risk(processed: Dict[str, pd.DataFrame]) -> Dict[str, Dict
4749 """Risk metrics for each symbol."""
4850 metrics : Dict [str , Dict [str , float ]] = {}
4951 for symbol , df in processed .items ():
52+ if df .empty or len (df ) == 0 or "daily_return" not in df .columns :
53+ metrics [symbol ] = {"volatility" : 0.0 , "sharpe_ratio" : 0.0 , "max_drawdown" : 0.0 }
54+ continue
5055 returns = df ["daily_return" ].dropna ()
5156 metrics [symbol ] = {
5257 "volatility" : round (annualized_volatility (returns ), 4 ),
@@ -58,8 +63,9 @@ def compute_per_asset_risk(processed: Dict[str, pd.DataFrame]) -> Dict[str, Dict
5863
5964def correlation_matrix (processed : Dict [str , pd .DataFrame ]) -> Dict [str , Dict [str , float ]]:
6065 """Pairwise return correlations across assets."""
66+ cleaned = {s : df for s , df in processed .items () if not df .empty and len (df ) > 0 }
6167 returns_df = pd .DataFrame (
62- {symbol : df .set_index ("date" )["daily_return" ] for symbol , df in processed .items ()}
68+ {symbol : df .set_index ("date" )["daily_return" ] for symbol , df in cleaned .items ()}
6369 ).dropna ()
6470
6571 if returns_df .empty or returns_df .shape [1 ] < 2 :
0 commit comments