Estimate VaR for Equity Portfolio Using Parametric Methods
This example shows how to estimate the value-at-risk (VaR) for a portfolio of equity positions using two parametric methods, normal VaR and exponentially weighted moving average (EWMA) VaR. Parametric VaR methods, also known as variance-covariance methods when the returns are normally distributed, assume a closed form for the return distribution of the portfolio. Using a parametric model simplifies the problem of VaR calculation to that of estimating the parameters of the distribution. Parametric methods are often contrasted with nonparametric approaches, such as Monte Carlo VaR or historical VaR, that do not assume an analytic formula for the return distribution of the portfolio. For a similar example of VaR calculation on a single index, see Value-at-Risk Estimation and Backtesting.
Normal VaR Calculation
The VaR of a portfolio is the maximum loss that the portfolio can incur over a given time window and still fall within the designated confidence bound. For example, if a portfolio has a one-day 95% VaR of 1,000,000 USD, then 95% of the time the portfolio should lose less than 1,000,000 USD over the course of the following day. That is, the portfolio should lose more than 1,000,000 USD only about once every 20 business days.
This example focuses on the one day 95% VaR for a portfolio of stocks. With the assumption that the one day returns of the portfolio are normally distributed, the problem of calculating a VaR value reduces to finding the parameters of the normal distribution. That is, VaR = [1,2], where is the mean return of the portfolio, is the standard deviation of the portfolio returns, and is the z-score for the confidence level. This example assumes , which is a common assumption and is approximately true for a one-day time period. The most common confidence intervals are the 95% and 99% values, with z-scores of 1.6449
and 2.3263
, respectively. In general, you can compute z-scores using the norminv
function.
Computing is the primary task in Normal VaR computation. Suppose the portfolio contains a set of financial assets, and let be the covariance matrix for the returns of those assets. Then , where is the vector of dollar values invested in each financial asset. In practice, correlations are often easier to work with [2], and so is decomposed into correlations and standard deviations . This yields , where In addition, some workflows use weights rather than dollar values [2]. In this case, is replaced by where is the total portfolio value. This yields .
To calculate the one day 95% VaR for a single trading day, begin by loading the data. The data set SharePrices.mat
contains share prices for 87 stocks over 782 trading days. The following VaR calculations use the last 250 data points, which correspond to a year of data.
% Load equity prices equityPrices = load("SharePrices.mat","data"); equityPrices = equityPrices.data;
Calculate the arithmetic returns for the share prices, then load the number of shares the portfolio holds for each stock from SimulatedRiskParityPortfolio.mat
. This data set contains the shares for a simulated portfolio generated using a risk parity approach, as demonstrated in Estimate Expected Shortfall for Asset Portfolios.
% Calculate the arithmetic returns returns = tick2ret(equityPrices); % Load simulated portfolio numShares = load("SimulatedRiskParityPortfolio.mat","RiskParityPortfolio"); numShares = numShares.RiskParityPortfolio;
The three VaR formulas previously discussed in Normal VaR Calculation use zScore
, v
, covarianceMatrix
, R
, sigmas
, sigma_v
, vTotal
, and w
.
% Calculate the zscore for 95% VaR pVaR = 0.95; zScore = norminv(pVaR); % Calculate dollar values for the assets V = equityPrices(end,:).*numShares(end,:); % Calculate covariance matrix covarianceMatrix = cov(returns); % Calculate correlation matrix and standard deviations R = corr(returns); sigmas = std(returns); % Calculate sigma weighted asset values (v vector) sigma_v = V.*sigmas; % Total portfolio value vTotal = sum(V,2); % Portfolio weights w = sigma_v./vTotal;
To calculate the one day 95% VaR, use these variables in the relevant formulas. Each formula yields an identical result.
% Calculate VaR with asset values and covariance
portfolioSigma = sqrt(V*covarianceMatrix*V')
portfolioSigma = 7.0417e+03
covarianceVaR = portfolioSigma*zScore
covarianceVaR = 1.1583e+04
% Calculate VaR with correlations and sigma weighted asset values
portfolioSigma = sqrt(sigma_v*R*sigma_v')
portfolioSigma = 7.0417e+03
correlationsVaR = portfolioSigma*zScore
correlationsVaR = 1.1583e+04
% Calculate VaR with weights
portfolioSigma = vTotal*sqrt(w*R*w')
portfolioSigma = 7.0417e+03
weightsVaR = portfolioSigma*zScore
weightsVaR = 1.1583e+04
Exponentially Weighted Moving Average (EWMA) VaR Calculation
Moving averages are common in time series algorithms. A typical example of a moving average is the covariance formula:
.
In Normal VaR Calculation, you calculate asset covariances using this formula, which weights each day in the time series identically. However, newer observations are often considered more relevant than older observations. In these situations, an alternative covariance calculation method is preferable. The EWMA method weights newer (i is closer to 1
) data points more heavily in the covariance estimate
= ,
where and the new denominatoris equal to the sum of the n weights and is derived using the formula for the partial sum of a geometric series.
Like Normal VaR, EWMA VaR assumes the portfolio returns are normally distributed. Therefore, EWMA VaR uses the same data, and values as in the Normal VaR case. However, for EWMA VaR you calculate the covariance matrix , and therefore using ewstats
. ewstats
implements this alternative covariance formula, which requires the returns data and a value for . In this example, , which is a commonly used exponential weight in Risk Management [2].
% Calculate covariance matrix lambda = 0.94; [~,ewmaCovMatrix] = ewstats(returns,lambda); % Calculate EWMAVaR portfolioSigma = sqrt(V*ewmaCovMatrix*V')
portfolioSigma = 7.9269e+03
ewmaVaR = portfolioSigma*zScore
ewmaVaR = 1.3039e+04
The calculated ewmaVaR
is larger than the calculated Normal VaR. This is because EWMA places greater emphasis on newer data in the covariance calculations and the observed equity variances are greater towards the end of the data window. You can see this behavior in the following plot. Compared to Normal VaR, EWMA generally leads to a higher VaR estimate immediately after periods of high market volatility and a lower VaR estimate immediately after periods of low market volatility.
h = plot(returns(end-250:end,:)); ax = h.Parent; xlabel(ax,'Trading Day'); ylabel(ax,'Asset Return'); title(ax,'Asset Returns over Time');
Calculate EWMA and Normal VaR with Rolling Data Window
VaR values are usually recalculated for a portfolio each day to account for changing market dynamics and changes to the portfolio composition. Additionally, backtesting a VaR model requires tracking the model performance over a period of time. Therefore, you can calculate a sequence of VaR estimates using a rolling data window.
Calculate the arithmetic returns using tick2ret
and the price data in the variable equityPrices
.
returns = tick2ret(equityPrices);
Set the window variables for windowSize
(the size of the rolling data window), testSize
(the number of days to calculate a VaR value), and sampleSize
(the total number of observed returns in the data set).
sampleSize = length(returns); windowSize = 250; testWindowSize = sampleSize-windowSize;
Calculate the dollar amount invested in each stock on each day by extracting the number of shares the portfolio is holding for each stock on each day, then multiplying by the share price. Note that the portfolio composition changes from one day to the next.
% Dollar value of exposure to each stock
V = equityPrices(windowSize+1:end-1,:).*numShares;
Calculate the z-scores and initialize the VaR, , and profit and loss (P&L) vectors.
% VaR confidence level pVaR = 0.95; % Get Zscores for alpha value zScore = norminv(pVaR); % Initialize VaR vectors ewma95 = zeros(testWindowSize,1); normalVaR95 = zeros(testWindowSize,1); % Initialize portfolioSigmas vectors ewmaPortfolioSigmas = zeros(testWindowSize,1); normalPortfolioSigmas = zeros(testWindowSize,1); % Initialize P&L values for backtesting portfolioPandL = zeros(testWindowSize,1);
For each trading day in the estimation window, calculate the regular and EWMA VaR in the estimation window by passing the returns for the previous 250 trading days to cov
and ewstats
, respectively. Then, calculate using the prices on that day and scale by the z-score to get the VaR. Finally, save P&L values.
% t is the index number within the estimation window, % k is the index number within the entire data set. for t = 1:testWindowSize k = windowSize + t; % Calculate covariance Matrix returnsData = returns(t:k-1,:); % Using ewstats to compute exponentially weighted covariance matrix. covMatrix = cov(returnsData); [~,ewmaCovMatrix] = ewstats(returnsData,lambda,windowSize); % Calculate the standard deviation of the portfolio returns. v = V(t,:); normalPortfolioSigmas(t) = sqrt(v*covMatrix*v'); ewmaPortfolioSigmas(t) = sqrt(v*ewmaCovMatrix*v'); % Save VaR values normalVaR95(t) = zScore*normalPortfolioSigmas(t); ewma95(t) = zScore*ewmaPortfolioSigmas(t); % Save P&L values portfolioPandL(t) = sum(returns(k,:).*v); end % Plot normal and EWMA VaRs by day h = plot(1:testWindowSize,[ewma95, normalVaR95]); ax = h.Parent; xlabel(ax,'Trading Day'); ylabel(ax,'VaR Estimate'); title(ax,'Normal 95% VaR Versus EWMA 95% VaR'); legend(ax,{'EWMA Var','NormalVar'},'Location','Best');
The EWMA VaR is more sensitive to changes in recent volatility data and is more likely to have larger increases (or decreases) in estimated VaR levels relative to Normal VaR. This sensitivity is because the Normal VaR uses a simple moving average that does not emphasize recent data over older data in the relevant window. You can see this at the beginning of the plot where the Normal VaR begins much higher than EWMA, which is due to a period of high volatility that occurs approximately 100–200 days before the first VaR estimate. This period of instability is old enough to have a limited impact on the exponentially weighted average used in EWMA, but it is still relevant to the simple moving average used in Normal VaR. You can see this behavior in the following plot.
h = plot(-249:531,returns); ax = h.Parent; xlabel(ax,'Trading Day'); ylabel(ax,'Asset Return'); title(ax,'Asset Returns over Time');
VaR Backtesting Using Both VaR Types
The validation process for a VaR model requires comparing a large number of computed VaR values to the corresponding realized profit and loss values. That is, if the 95% VaR is accurate, then the realized profit and loss for the portfolio is less than the computed VaR 95% of the time and greater than the VaR only 5% of the time. This process is called VaR backtesting.
You can use varbacktest
for VaR backtesting. varbacktest
requires at least two input arguments: a vector of VaR values and a vector of realized profit and loss values.
vbt = varbacktest(portfolioPandL,[ewma95,normalVaR95],'VaRID',{'EWMA','Normal'});
Use the summary
and runtests
functions to validate the VaR estimates.
summaryResults = summary(vbt)
summaryResults=2×10 table
PortfolioID VaRID VaRLevel ObservedLevel Observations Failures Expected Ratio FirstFailure Missing
___________ ________ ________ _____________ ____________ ________ ________ ______ ____________ _______
"Portfolio" "EWMA" 0.95 0.9096 531 48 26.55 1.8079 20 0
"Portfolio" "Normal" 0.95 0.9096 531 48 26.55 1.8079 115 0
testResults = runtests(vbt)
testResults=2×11 table
PortfolioID VaRID VaRLevel TL Bin POF TUFF CC CCI TBF TBFI
___________ ________ ________ ___ ______ ______ ______ ______ ______ ______ ______
"Portfolio" "EWMA" 0.95 red reject reject accept reject accept reject reject
"Portfolio" "Normal" 0.95 red reject reject reject reject accept reject reject
Most of the tests performed by the varbacktest
object have failed. The summaryResults
table shows that the 95%
VaR
is greater than the realized profit and loss only about 90% of the time.
You can use plot
to visualize the results.
h = plot(vbt)
h = 4x1 Line array: Line (Portfolio) Line (EWMA) Line (Normal) Line (Exceptions)
ax = h.Parent;
ylabel(ax,'Daily P&L');
The failures here are shown as black dots. Although the two VaRs have the same number of failures the EWMA VaR (red) and Normal VaR (yellow) are not failing on identical days. This suggests a trade-off between emphasizing new data and losing info from older data. One option is to set a VaR value equal to the maximum value of ewma95
and normalVaR95
.
varMax = max(ewma95,normalVaR95); vbtMax = varbacktest(portfolioPandL,varMax); summaryResultsMax = summary(vbtMax)
summaryResultsMax=1×10 table
PortfolioID VaRID VaRLevel ObservedLevel Observations Failures Expected Ratio FirstFailure Missing
___________ _____ ________ _____________ ____________ ________ ________ ______ ____________ _______
"Portfolio" "VaR" 0.95 0.93409 531 35 26.55 1.3183 115 0
testResultsMax = runtests(vbtMax)
testResultsMax=1×11 table
PortfolioID VaRID VaRLevel TL Bin POF TUFF CC CCI TBF TBFI
___________ _____ ________ ______ ______ ______ ______ ______ ______ ______ ______
"Portfolio" "VaR" 0.95 yellow accept accept reject accept accept reject reject
The resulting VaR value when the VaR value is equal to the maximum value of ewma95
and normalVaR95
does perform better than the two alternatives (EWMA VaR and Normal VaR), although the observed VaR level is still below the 95% target.
This example assumes the portfolio returns are normally distributed. Actual financial data, however, has fatter tails than a normal distribution, so assuming a normal distribution can lead to an underestimate of the VaR values. Two potential solutions to this problem are:
Use a different distribution. For example, a t-distribution has fatter tails than the normal distribution. The
zscores
are calculated usingtinv
instead ofnorminv
and the standard deviation is replaced with a scale parameter, but otherwise the process is identical. However, you do need to estimate the degrees of freedom for the t-distribution. For an example of a VaR calculation with a t-distribution, see Expected Shortfall Estimation and Backtesting.Use a nonparametric method to calculate the portfolio VaR using a historical VaR method. For an example of calculating a historical VaR, see Value-at-Risk Estimation and Backtesting.
References
[1] Dowd, Kevin. Measuring Market Risk. 1st ed. Wiley, 2005.
[2] J.P. Morgan, Reuters. "RiskMetrics-Technical Document." Morgan Guaranty Trust Company of New York, 1996.
See Also
esbacktestbyde
| esbacktest
| esbacktestbysim
| varbacktest
Related Topics
- VaR Backtesting Workflow
- Value-at-Risk Estimation and Backtesting
- Expected Shortfall (ES) Backtesting Workflow with No Model Distribution Information
- Expected Shortfall (ES) Backtesting Workflow Using Simulation
- Expected Shortfall Estimation and Backtesting
- Workflow for Expected Shortfall (ES) Backtesting by Du and Escanciano