Parametric Method: Value at Risk (VaR) In Python
In this blog article, we will demonstrate how to calculate the Value at Risk (VaR) for a portfolio of stocks using the parametric method, also known as the variance-covariance method. This implementation models daily portfolio log returns as normal, then converts the modeled horizon quantile to a compounded simple-return dollar loss. We will use Python and the yfinance library to download historical stock data and perform the calculations.
Set Timeframe and Define Tickers
First, we will define the time range for our analysis and create a list of tickers we want to include in our portfolio:
import numpy as np
import pandas as pd
import datetime as dt
import yfinance as yf
import matplotlib.pyplot as plt
years = 15
endDate = dt.datetime.now()
startDate = endDate - dt.timedelta(days=365*years)
tickers = ['SPY', 'BND', 'GLD', 'QQQ', 'VTI']
Download Adjusted Close Prices and Calculate Log Returns
The code explicitly requests auto_adjust=False to retain Adj Close and multi_level_index=False for a flat single-ticker result. Use a current yfinance version supporting those arguments. Check that downloads contain the expected tickers and enough common trading dates; a failed or missing download should be corrected before interpreting VaR.
Next, we will download the daily adjusted close prices for each ticker and calculate the daily log returns:
adj_close_df = pd.DataFrame()
for ticker in tickers:
data = yf.download(ticker, start=startDate, end=endDate,
auto_adjust=False, multi_level_index=False, progress=False)
adj_close_df[ticker] = data['Adj Close']
log_returns = np.log(adj_close_df / adj_close_df.shift(1))
log_returns = log_returns.dropna()
Create Equally Weighted Portfolio and Calculate Historical Returns
We assume costless daily rebalancing to equal weights. Convert each asset log return to a simple return, weight those simple returns, and then take log1p to obtain the portfolio log return. Weighted asset log returns would only approximate this aggregation:
portfolio_value = 1000000
weights = np.array([1/len(tickers)] * len(tickers))
daily_portfolio_simple = np.expm1(log_returns).dot(weights)
historical_returns = np.log1p(daily_portfolio_simple)
Find X-Day Historical Returns
We will find the rolling sum of historical returns for a specified number of days:
days = 5
historical_x_day_returns = historical_returns.rolling(window=days).sum()
Create Covariance Matrix and Calculate Portfolio Standard Deviation
The asset simple-return covariance matrix gives the weighted portfolio’s simple-return volatility. For the lognormal VaR model below, estimate volatility directly from the portfolio log-return series, keeping its mean and volatility in consistent units:
cov_matrix = np.expm1(log_returns).cov() * 252
# Covariance gives annualized daily simple-return volatility.
portfolio_simple_std_dev = np.sqrt(weights.T @ cov_matrix @ weights)
# The lognormal VaR model below uses actual portfolio log-return volatility.
portfolio_std_dev = historical_returns.std(ddof=1) * np.sqrt(252)
Calculate VaR at Different Confidence Levels
Assume independent normal daily portfolio log returns with stable mean and volatility. Scale the mean by days and volatility by the square root of days, then convert the lower log-return quantile with expm1. VaR is the negative of that dollar-return quantile, so a loss threshold is positive; a negative VaR would indicate that the selected quantile is a gain, not a sign error:
from scipy.stats import norm
confidence_levels = [0.90, 0.95, 0.99]
VaRs = []
for cl in confidence_levels:
log_return_quantile = (historical_returns.mean() * days
+ norm.ppf(1 - cl) * portfolio_std_dev * np.sqrt(days / 252))
VaR = -portfolio_value * np.expm1(log_return_quantile)
VaRs.append(VaR)
Print VaR Results
Let’s print the VaR results for each confidence level:
print(f'{"Confidence Level":<20} {"Value at Risk":<20}')
print('-' * 40)
for cl, VaR in zip(confidence_levels, VaRs):
print(f'{cl * 100:>6.0f}%: {"":<8} ${VaR:>10,.2f}')
Plot the Distribution of Portfolio Returns and Parametric VaR Estimates
Finally, we will plot the distribution of the X-day portfolio returns and the parametric VaR estimates:
# Convert returns to dollar values for the histogram
historical_x_day_returns_dollar = np.expm1(historical_x_day_returns.dropna()) * portfolio_value
# Plot the histogram
plt.hist(historical_x_day_returns_dollar, bins=50, density=True, alpha=0.5, label=f'{days}-Day Returns')
# Add vertical lines representing VaR at each confidence level
for cl, VaR in zip(confidence_levels, VaRs):
plt.axvline(x=-VaR, linestyle='--', color='r', label='VaR at {}% Confidence'.format(int(cl * 100)))
plt.xlabel(f'{days}-Day Portfolio Return ($)')
plt.ylabel('Frequency')
plt.title(f'Distribution of Portfolio {days}-Day Returns and Parametric VaR Estimates')
plt.legend()
plt.show()
By following these steps, you can create a Python script that calculates the Value at Risk (VaR) using the parametric method for your investment portfolio. Keep in mind that this implementation assumes independent normal daily portfolio log returns, which may not always hold true. Continuously refining your analysis and considering other factors will help you develop a more accurate understanding of the risks associated with your investments, enabling you to make more informed decisions.
In conclusion, calculating Value at Risk (VaR) using the parametric method can provide you with a useful metric for understanding and managing the potential risks associated with your investment portfolio. By incorporating this approach into your analysis, you can better anticipate potential losses and make more informed decisions about your investments. However, always remember that the underlying assumptions of this method, such as independent normal daily portfolio log returns with stable parameters, may not always be valid. As an investor, it’s essential to keep refining your analysis, stay informed about market conditions, and explore other risk management techniques to ensure that you’re effectively managing the potential risks and rewards of your investments.
Find discounts on finance certificates, courses and products here.
