Skip to content

Instantly share code, notes, and snippets.

@architectureman
Created April 28, 2025 03:44
def calculate_portfolio_performance(
stock_data: pd.DataFrame,
tickers: List[str],
allocations: Dict[str, float],
risk_free_rate: float = 0.02,
target_return: float = 0.0,
annualization_factor: float = 252
) -> Dict[str, float]:
"""
Calculate comprehensive portfolio performance metrics.
Args:
stock_data: DataFrame with price data for each ticker
tickers: List of stock tickers
allocations: Dictionary mapping tickers to their weight allocations
risk_free_rate: Risk-free rate (annualized)
target_return: Minimum acceptable return for Sortino ratio (default: 0)
annualization_factor: Number of trading days in a year
Returns:
Dictionary with portfolio performance metrics
"""
# Ensure allocations are provided for all tickers
weights_dict = {ticker: allocations.get(ticker, 0) for ticker in tickers}
# Convert weights to numpy array
weights_array = weights_to_array(tickers, weights_dict)
# Calculate expected returns and covariance matrix
mu, S = calculate_returns_and_covariance(stock_data)
# Calculate basic portfolio metrics (expected return, std dev, Sharpe)
basic_metrics = calculate_portfolio_metrics(weights_array, mu, S, risk_free_rate)
# Calculate Sortino ratio
sortino_ratio = calculate_sortino_ratio(
weights_array,
stock_data,
risk_free_rate,
target_return,
annualization_factor
)
# Calculate max drawdown
daily_returns = stock_data.pct_change().dropna()
portfolio_returns = pd.Series(0, index=daily_returns.index)
for ticker, weight in weights_dict.items():
if ticker in daily_returns.columns:
portfolio_returns += daily_returns[ticker] * weight
# Calculate cumulative returns
cumulative_returns = (1 + portfolio_returns).cumprod()
max_drawdown = (cumulative_returns / cumulative_returns.cummax() - 1).min()
# Combine all metrics
return {
"expected_return": basic_metrics["expected_return"],
"standard_deviation": basic_metrics["standard_deviation"],
"sharpe_ratio": basic_metrics["sharpe_ratio"],
"sortino_ratio": sortino_ratio,
"max_drawdown": float(max_drawdown),
"risk_free_rate": basic_metrics["risk_free_rate"]
}
##########################################################################################
# Example usage
tickers = ["AAPL", "MSFT", "GOOG"]
allocations = {"AAPL": 0.4, "MSFT": 0.3, "GOOG": 0.3}
# Fetch data
stock_data, _, _ = fetch_stock_data(tickers, "2020-01-01", "2023-01-01")
# Calculate metrics
performance = calculate_portfolio_performance(stock_data, tickers, allocations, risk_free_rate=0.02)
print(f"Expected Return: {performance['expected_return']:.2%}")
print(f"Standard Deviation: {performance['standard_deviation']:.2%}")
print(f"Sharpe Ratio: {performance['sharpe_ratio']:.2f}")
print(f"Sortino Ratio: {performance['sortino_ratio']:.2f}")
print(f"Maximum Drawdown: {performance['max_drawdown']:.2%}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment