10 KiB
This notebook simulates portfolio returns using Monte Carlo methods to estimate Value at Risk (VaR) and Conditional Value at Risk (CVaR). It begins by importing historical price data for various sectors, calculating daily returns, and determining portfolio statistics. The notebook then simulates portfolio returns over a specified number of days and simulations, using these to calculate VaR and CVaR. Finally, it visualizes the simulated portfolio paths and highlights the calculated risk metrics. This is useful for risk management and financial forecasting.
import numpy as np import pandas as pd from openbb import obb
Define a list of sector symbols to analyze
sectors = [ "XLE", "XLF", "XLU", "XLI", "GDX", "XLK", "XLV", "XLY", "XLP", "XLB", "XOP", "IYR", "XHB", "ITB", "VNQ", "GDXJ", "IYE", "OIH", "XME", "XRT", "SMH", "IBB", "KBE", "KRE", "XTL", ]
Fetch historical price data for the defined sectors from 2022-01-01 using yfinance
data = obb.equity.price.historical( sectors, start_date="2022-01-01", provider="yfinance" ).to_df()
Calculate daily returns for each sector
data["returns"] = data.groupby("symbol").close.pct_change()
Calculate mean daily returns and equal weights for each sector
portfolio_stats = data.groupby("symbol").agg( daily_returns=("returns", "mean"), )
portfolio_stats["weights"] = 1 / len(sectors)
Compute the covariance matrix of the sector returns
covariance_matrix = ( data .pivot( columns="symbol", values="returns" ) .dropna() .cov() )
Set up simulation parameters including number of simulations, days, and initial capital
simulations = 1000 days = len(data.index.unique()) initial_capital = 100_000
Initialize an array to store portfolio values for each simulation
portfolio = np.zeros((days, simulations))
Create an array filled with historical daily returns for each sector
historical_returns = np.full( shape=(days, len(sectors)), fill_value=portfolio_stats.daily_returns )
Perform Cholesky decomposition on the covariance matrix to generate correlated random variables
L = np.linalg.cholesky(covariance_matrix)
Run simulations to generate daily returns and simulate portfolio paths
for i in range(0, simulations): Z = np.random.normal(size=(days, len(sectors))) daily_returns = historical_returns + np.dot(L, Z.T).T portfolio[:, i] = ( np.cumprod(np.dot(daily_returns, portfolio_stats.weights) + 1) * initial_capital )
Convert simulated portfolio values into a DataFrame
simulated_portfolio = pd.DataFrame(portfolio)
Set alpha level for VaR and CVaR calculations
alpha = 5
Define function to calculate Monte Carlo VaR
def montecarlo_var(alpha): """Calculate Monte Carlo Value at Risk (VaR). Parameters ---------- alpha : float The confidence level for the VaR calculation. Returns ------- float The VaR value at the given confidence level. """ # Calculate the percentile of the simulated portfolio values at alpha level sim_val = simulated_portfolio.iloc[-1, :] return np.percentile(sim_val, alpha)
Define function to calculate Conditional VaR
def conditional_var(alpha): """Calculate Conditional Value at Risk (CVaR). Parameters ---------- alpha : float The confidence level for the CVaR calculation. Returns ------- float The CVaR value at the given confidence level. """ # Calculate the mean of the simulated portfolio values below the VaR threshold sim_val = simulated_portfolio.iloc[-1, :] return sim_val[sim_val <= montecarlo_var(alpha)].mean()
Calculate Monte Carlo VaR and Conditional VaR
mc_var = montecarlo_var(alpha) cond_var = conditional_var(alpha)
Plot the simulated portfolio paths and highlight VaR and CVaR
ax = simulated_portfolio.plot(lw=0.25, legend=False) ax.axhline(mc_var, lw=0.5, c="r") ax.axhline(cond_var, lw=0.5, c="g")
PyQuant News is where finance practitioners level up with Python for quant finance, algorithmic trading, and market data analysis. Looking to get started? Check out the fastest growing, top-selling course to get started with Python for quant finance. For educational purposes. Not investment advise. Use at your own risk.
