Value at Risk (VaR)

Ioannis Paraskevopoulos, PhD

What is VaR?

VaR is defined as the lowest quantile of the potential losses that can occur within a given portfolio during a specific time period.

VaR characteristics

The time period $T$ and the confidence level are the two major parameters, which are chosen carefully and are dependent upon the goal of the risk management (regulatory reporting, corporate risk management, etc.).

-Provides just one number that summarizes the total risk of a portfolio.

-Indicates the maximum potencial loss that can generate a given position for a given statistical confidence level and a given time horizon.

Once calculated we can state “ there is a probability $p$% that we will not loose more than $V$ monetary units in the next $T$ days -It tells us “how wrong things can go” -If $T=10$ and $p=99$% we will be calculating the losses over a 10 day period that that will only occur 1 out of 100 times

Regulation capital requirement

-The required by regualation capital for market risk operations is 12.5 times the 10 day with 99.9%

$$12.5xVaR_{99.9}$$

.

VaR Definition:

Formally defined, VaR estimates the likelihood that a given portfolio’s losses (L) will exceed a certain amount l.

$$VaR_{\alpha}(L) = Pr(L > l) ≤ 1 − \alpha$$

, where $l \in \mathbb{R}$. L is the loss of the portfolio and $\alpha \in [0, 1]$ is the confidence level.

Examples of Calculating VaR

-Imagine that during the last year the daily benefits of a firm are on average 8M euros, but that 5% of the days losses equal or greater than 10M euros were observed. If this is stable the maximum loss that we can observe 5 out of 100 days is 10M euros, thus VaR in absolute terms is 10M euros.

-We can also talk about relative VaR, in terms of relative loss with respect to expected average. In our example relative VaR will be 18M euros.

Assume that our portfolio consists only of one asset. Further we suppose percentiles can be expressed as a function of a dispersion parameters so that the returns of this asset have a bell-shaped normal distribution with annual mean return 10% and standard deviation 30%. If the value of our portfolio is( $V_t$ ) now Eur100m, we would like to answer:

-What’s the value of the portfolio in one year?

In [1]:
import matplotlib.pyplot as plt
%matplotlib inline
from scipy import stats
import numpy as np


# Plot the PDF of our Portfolio V
xmin, xmax = plt.xlim()
x = np.linspace(10, 230, 100)
p = stats.norm.pdf(x, 110, 30)
plt.plot(x, p, 'k', linewidth=2)
title = "Portfolio Value, $V_t$ in a years time"
plt.title(title)

plt.show()

-What is the probability that we suffer a loss?

Since returns are normally distributed around their mean of 10% with volatility 30% we can use the statistical theory and form a normal random variable Z:

$Z=\frac{X-\mu}{\sigma}\Leftrightarrow Z*\sigma+\mu \Rightarrow Pr(X\leq 0)=Pr(Z*\sigma+\mu \leq 0)=Pr(Z\leq -\frac{0.1}{0.3})=Pr(Z \leq -0.333)=N(-0.333)$

In [2]:
import scipy.stats
scipy.stats.norm(0.1, 0.3).pdf(-0.333)
Out[2]:
0.46927267427666119
In [2]:
import numpy
import scipy.stats
import datetime
import matplotlib.pyplot as plt
from pandas.io.data import DataReader, DataFrame
%matplotlib inline

We get yahoo data to play with

In [3]:
start = datetime.datetime(2005, 1, 1)
end   = datetime.datetime(2015, 11, 2)
AAPL = DataReader("AAPL", "yahoo", start, end)
SP = DataReader("^GSPC", "yahoo", start, end)


df = DataFrame({ 'AAPL': AAPL["Adj Close"].pct_change(),
                 'SP': SP["Close"].pct_change()})
dfna = df.dropna()

Lets do some plotting on levels

In [4]:
AAPL.plot(y="Adj Close")
plt.title(u"Apple 2015", weight='bold');

We plot the returns

In [5]:
plt.plot(dfna["AAPL"],'b.',alpha=0.5) #chose the color of line: 'b.'=blue, for red is 'r.'
plt.title(u"Apple daily returns period 2005-2015", weight='bold');
In [6]:
# plotting (figure #1)
#  return-series for Apple and S&P index
#
plt.figure(num=2, figsize=(10, 6))
plt.subplot(211)
plt.grid(True)
plt.plot(dfna["AAPL"], '-r', label="Apple")
plt.axis("tight")
plt.ylim([-0.25,0.3])
plt.legend(loc="upper right")
plt.ylabel("Apple daily returns")
plt.subplot(212)
plt.grid(True)
plt.plot(dfna["SP"], '-', label="S&P")
plt.legend(loc="upper right")
plt.axis("tight")
plt.ylim([-0.10,0.15])
plt.ylabel("S&P daily returns")
plt.xlabel("Trading days 13/05/2005-12/11/2015")
plt.show()

we can get immediattely the quantile we want from Apple returns

In [7]:
dfna["AAPL"].quantile(0.05) #see the returns in 0.05 empirical quantile
Out[7]:
-0.032959698907465515

Lets see the histogram of Apple returns

In [8]:
returns = dfna["AAPL"]
returns.hist(bins=30, normed=True, histtype='stepfilled', alpha=0.5)
support = numpy.linspace(returns.min(), returns.max(), 100)
tdf, tmean, tsigma = scipy.stats.t.fit(returns.as_matrix())
print("Apple t fit: mean={}, scale={}, df={}".format(tmean, tsigma, tdf))
plt.plot(support, scipy.stats.t.pdf(support, loc=tmean, scale=tsigma, df=tdf), "r-")
plt.figtext(0.6, 0.7, u"t$\mu$ = {:.3}".format(tmean))
plt.figtext(0.6, 0.65, u"t$\sigma$ = %3f" % tsigma)
plt.figtext(0.6, 0.6, u"df = %3f" % tdf)
plt.title(u"Histogram of Apple daily returns over 2005–2015", weight='bold');
Apple t fit: mean=0.00139714131679, scale=0.0153600071028, df=3.68016002902
In [11]:
#Variance Covariance of Dailly VaR

import datetime
import numpy as np
import pandas.io.data as web
from scipy.stats import norm


def var_cov_var(P, c, mu, sigma):
    """
    Variance-Covariance calculation of daily Value-at-Risk
    using confidence level c, with mean of returns mu
    and standard deviation of returns sigma, on a portfolio
    of value P.
    """
    phiInv = norm.ppf(1-c, mu, sigma)
    return P - P*(phiInv + 1)  #daily VaR

if __name__ == "__main__":
    start = datetime.datetime(2010, 1, 1)
    end = datetime.datetime(2015, 11,2 )

    citi = web.DataReader("AAL", 'yahoo', start, end) #get yahoo data
    citi["rets"] = citi["Adj Close"].pct_change() #Create Returns of citi

    P = 1e6   # 1,000,000 USD
    c = 0.99  # 99% confidence interval
    mu = np.mean(citi["rets"]) #mean returns
    sigma = np.std(citi["rets"]) #volatility

    var = var_cov_var(P, c, mu, sigma)
    print "Value-at-Risk: $%0.2f" % var

    
    
    print "Value at Risk for dailly movement in Apple and with 99 percent confidence is: $%0.2f" % var
Value-at-Risk: $72560.64
Value at Risk for dailly movement in Apple and with 99 percent confidence is: $72560.64

Value at Risk using the historical bootstrap method Method: we calculate empirical quantiles from a histogram of daily returns.

Historical Bootstrap for the 21 days Apple VaR

In [12]:
import numpy as np

#returns = np.random.randn(1000)
#Assuming returns are independently and identically distributed (i.i.d.), then the volatility of T days equals to the product of sqrt(T) times one-day-volatility.

# one-way 5% quantile or 95% confidense, critical value is 1.64
VaR_21 = sigma * np.sqrt(21) * 1.645
VaR_21

#Alternatively, you can do bootstraps. 
#That's randomly select 21 days from historical dataset, 
#calculate the return over this randomly drawed 21 days. Plot the histogram and get the 5% quantile.

def generate_random_index(n=21):
    # could set replace to False as well
    return np.random.choice(np.arange(1000), size=n, replace=False)  

VaR_simulated_21 = []
n_bootstrap = 10000
for _ in range(n_bootstrap):
    VaR = dfna["AAPL"][generate_random_index(21)].sum()
    VaR_simulated_21.append(VaR)

plt.hist(VaR_simulated_21)
np.percentile(VaR_simulated_21, q=5)
Out[12]:
-0.17919784335156427

we move on to plot a histogram

Value at Risk using the historical bootstrap method Method: we calculate empirical quantiles from a histogram of daily returns.

In [13]:
returns.quantile(0.05) #see the returns in 0.05 empirical quantile
Out[13]:
-0.032959698907465515

The 0.05 empirical quantile of daily returns is at -0.019. That means that with 95% confidence, our worst daily loss will not exceed 1.9%. If we have a 1Meuros investment, our one-day 5% VaR is 1.9 * 1M€ = 19 k€.

In [ ]:
 
In [ ]:
returns = dfna["SP"]
returns.hist(bins=30, normed=True, histtype='stepfilled', alpha=0.5)
support = numpy.linspace(returns.min(), returns.max(), 100)
tdf, tmean, tsigma = scipy.stats.t.fit(returns.as_matrix())
print("SP t fit: mean={}, scale={}, df={}".format(tmean, tsigma, tdf))
plt.plot(support, scipy.stats.t.pdf(support, loc=tmean, scale=tsigma, df=tdf), "r-")
plt.figtext(0.6, 0.7, u"t$\mu$ = %3f" % tmean)
plt.figtext(0.6, 0.65, u"t$\sigma$ = %3f" % tsigma)
plt.figtext(0.6, 0.6, u"df = %3f" % tdf)
plt.title(u"Histogram of SP daily returns over 2005–2015", weight='bold');

Let's simulate random joint stock returns from a joint distribution of Apple hat and SP hat according to the distribution parameters estimated above, and plot the results. We need these simulated joint returns to do a Monte Carlo VaR analysis of a stock portfolio composed of Apple and SP stock.

In [ ]:
runs = 5000
fittedAPL = numpy.zeros(runs, float)
fittedSP = numpy.zeros(runs, float)
for i in range(runs):
    fittedAPL[i] = scipy.stats.t.rvs(loc=0.00139714130016, scale=0.0153600071028, df=3.68016002902)
    fittedSP[i] = scipy.stats.t.rvs(loc=0.00074328426861, scale=0.00656089369387, df=2.29005123591)
plt.plot(fittedAPL, fittedSP, 'r.', alpha=0.5)
plt.title(u"Apple vs SP returns (simulated, no correlation)", weight='bold');

Monte Carlo Simualation VaR

Method: run many trials with random market conditions, calculating portfolio loss for each trial. Use the aggregated trial data to establish a profile of the porfolio's risk characteristics.

Hypothesis: stock market evolution can be simulated by geometric Brownian motion. Start by defining some parameters of the geometric Brownian motion.

The mathematical formula for the price evololution in future is $\frac{\Delta S}{S}=\mu \Delta t + \sigma*N(0,1)$

In [46]:
days = 300   # time horizon
dt = 1/float(days)
sigma = 0.0152 # volatility
mu = 0.01  # drift (average growth rate)

#BS world...generates a path

def random_walk(startprice):
    price = numpy.zeros(days)
    shock = numpy.zeros(days)
    price[0] = startprice
    for i in range(1, days):
        shock[i] = numpy.random.normal(loc=mu * dt, scale=sigma * numpy.sqrt(dt))
        price[i] = max(0, price[i-1] + shock[i] * price[i-1])
    return price

for run in range(10):
    plt.plot(random_walk(121.18))

    plt.xlabel("Time")
plt.ylabel("Price");

Now let's run a big Monte Carlo simulation of random walks of this type, to obtain the probability distribution of the final price, and obtain quantile measures for the Value at Risk estimation.

Price Distribution in 300 days

In [45]:
runs = 10000
simulations = numpy.zeros(runs)
for run in range(runs):
    simulations[run] = random_walk(121.18)[days-1] #Apple price @ 02/11/2015 is 121.18 is the staring price
q = numpy.percentile(simulations, 1)
plt.hist(simulations, normed=True, bins=30, histtype='stepfilled', alpha=0.5)
plt.figtext(0.6, 0.8, u"Start price: 121.18€")
plt.figtext(0.6, 0.7, u"Mean final price: %.3f€" % simulations.mean())
plt.figtext(0.6, 0.6, u"VaR(0.99): %.3f€" % (121.18 - q,))
plt.figtext(0.15, 0.6, u"q(0.99): %.3f€" % q)
plt.axvline(x=q, linewidth=4, color='r')
plt.title(u"Final price distribution after %s days" % days, weight='bold');
In [ ]: