0% found this document useful (0 votes)
91 views

Python For Finance: Risk Measurement

The document discusses risk measurement in quantitative finance using Python. It begins with an introduction to common risk measures like value at risk (VaR) and expected shortfall (ES). It then provides Python code to calculate VaR and ES from a sample of returns. The rest of the document covers additional risk measurement techniques in Python like parametric VaR/ES assuming a normal distribution, Monte Carlo simulation, and the historical method. It also discusses testing whether the normality assumption is valid for real market data like S&P 500 returns.

Uploaded by

Sergey Borisov
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
91 views

Python For Finance: Risk Measurement

The document discusses risk measurement in quantitative finance using Python. It begins with an introduction to common risk measures like value at risk (VaR) and expected shortfall (ES). It then provides Python code to calculate VaR and ES from a sample of returns. The rest of the document covers additional risk measurement techniques in Python like parametric VaR/ES assuming a normal distribution, Monte Carlo simulation, and the historical method. It also discusses testing whether the normality assumption is valid for real market data like S&P 500 returns.

Uploaded by

Sergey Borisov
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 36

Python for Finance

Risk Measurement

Andras Niedermayer
Outline

1 Risk Measures

2 Parametric VaR, ES

3 Monte Carlo Simulation

4 Historical method

Wednesday, April, 2019 Python for Finance - Lecture 9


Andras Niedermayer - Université Paris-Dauphine 2/36
Motivation

• In quantitative finance arguably the most important


task/challenge is the financial risk measurement and assessment.
The majority of the financial engineer’s task is connected to this
field.
• Risk Measurement for a financial institution is very data intense
and computational expensive process.
• Using the adequate, state of the art technologies are key to keep
up with the speed of the financial market innovation, and to be
able to meet the regulatory requirements.

Wednesday, April, 2019 Python for Finance - Lecture 9


Andras Niedermayer - Université Paris-Dauphine 3/36
Types of risk measures

There is a wide range of risk measures that spread through the


Market.
• Volatility (σ)
• Value at Risk (VaR)
• Expected Shortfall (ES)
• Conditional Value at Risk (CVaR) - In case of continuous
distributions same as ES
• Average Drawdown, Maximum Drawdown
• etc.

Wednesday, April, 2019 Python for Finance - Lecture 9


Andras Niedermayer - Université Paris-Dauphine 4/36
VaR and ES

Formal definitions:
1 Value at Risk:

VaRα (X ) = − inf{x ∈ R : FX (x) > α} = −FX−1 (α) (1)


2 Expected Shortfall:
ESα (X ) =
1
− [E (X ∗ 1{X ≤−VaRα (X )} ) − VaRα (X )(α − P(X ≤ −VaRα (X )))]
α
(2)
1 α
Z
= VaRp (X )dp (3)
α 0

Wednesday, April, 2019 Python for Finance - Lecture 9


Andras Niedermayer - Université Paris-Dauphine 5/36
Python Implementation

1 def compute_var (x , alpha ):


2 return - np . percentile (x , alpha *100.0)
3 def compute_es (x , alpha ):
4 x_alpha = - compute_var (x , alpha )
5 prct = sum (x <= x_alpha )/ float ( len ( x ))
6 y = x * ( x <= var_alpha )
7 es = -1.0/ alpha *( y . mean ()+
8 x_alpha *( alpha - prct ))
9 return es

Wednesday, April, 2019 Python for Finance - Lecture 9


Andras Niedermayer - Université Paris-Dauphine 6/36
Outline

1 Risk Measures

2 Parametric VaR, ES

3 Monte Carlo Simulation

4 Historical method

Wednesday, April, 2019 Python for Finance - Lecture 9


Andras Niedermayer - Université Paris-Dauphine 7/36
Parametric VaR, ES
1 From historical prices we need to calculate the returns:
1 rets = np . log ( S ) - np . log ( S . shift (1))
2 rets = rets [1:]

2 Assuming Normal distribution (r ∼ N(µ, σ 2 )), we need to


estimate the parameters:
1 mu = rets . mean ()
2 sigma = rets . std ()

3 Use the closed form solution to calculate the VaR and ES:
1 var = - scs . norm . ppf ( alpha , loc = mu ,
2 scale = sigma )
3 es = scs . norm . pdf ( scs . norm . ppf ( alpha ))*
4 1/ alpha * sigma - mu
Wednesday, April, 2019 Python for Finance - Lecture 9
Andras Niedermayer - Université Paris-Dauphine 8/36
Normality assumption

Many influential theories in finance assume the normality of stock


returns:
1 Portfolio theory and CAPM: Normality of returns implies that
only the mean and variance are relevant for portfolio
optimization.
2 Option pricing theory: The Black and Scholes model, and many
other pricing models assume (log-)returns follow a Brownian
motion, i.e., are normally distributed over any given time
interval.
Is normality a realistic assumption? How to test for it?

Wednesday, April, 2019 Python for Finance - Lecture 9


Andras Niedermayer - Université Paris-Dauphine 9/36
Benchmark: Simulated data

Let us simulate 10,000 stock price paths from a Geometric Brownian


motion, and save the log returns.
1 def gen_paths ( S0 ,r , sigma , T ,M , I ):
2 dt = float ( T )/ M
3 paths = np . zeros (( M +1 , I ))
4 paths [0]= S0
5 for t in range (1 , M +1):
6 rand = np . random . randn ( I )
7 paths [ t ]= paths [t -1]*
8 np . exp (( r -0.5* sigma **2)* dt
9 + sigma * np . sqrt ( dt )* rand )
10 return paths
11 paths = gen_paths (100 ,0.05 ,0.2 ,1.0 ,50 ,10000)
12 log_returns = np . log ( paths [1:]/ paths [0: -1])

Wednesday, April, 2019 Python for Finance - Lecture 9


Andras Niedermayer - Université Paris-Dauphine 10/36
Informal tests of normality

Graphically, one can assess (non-)normality of data via two types of


plots:
1 Histograms.
1 plt . hist ( log_returns . flatten () , bins =100 ,
2 normed = True )

2 QQ (quantile-quantile) plots.
1 sm . qqplot ( log_returns . flatten ())

Wednesday, April, 2019 Python for Finance - Lecture 9


Andras Niedermayer - Université Paris-Dauphine 11/36
Wednesday, April, 2019 Python for Finance - Lecture 9
Andras Niedermayer - Université Paris-Dauphine 12/36
Wednesday, April, 2019 Python for Finance - Lecture 9
Andras Niedermayer - Université Paris-Dauphine 13/36
Formal tests
• We need to import the scipy.stats sublibrary.
1 import scipy . stats as scs

• Skewness and skewness test (returns test value and p-value).


1 scs . skew ( log_returns . flatten ())
2 scs . skewtest ( log_returns . flatten ())

• Kurtosis (normalized to 0) and kurtosis test (returns test value


and p-value).
1 scs . kurtosis ( log_returns . flatten ())
2 scs . kurtosistest ( log_returns . flatten ())

• Catch-all normality test (returns test value and p-value), based


on D’Agostino and Pearson (1973).
1 scs . normaltest ( log_returns . flatten ())
Wednesday, April, 2019 Python for Finance - Lecture 9
Andras Niedermayer - Université Paris-Dauphine 14/36
Real-world data: the S&P 500 index

We want to see whether the S&P 500 returns are also normally
distributed.
1 plt . hist ( sp_returns , bins =50 , density = True )
2 sm . qqplot ( sp_returns )

Wednesday, April, 2019 Python for Finance - Lecture 9


Andras Niedermayer - Université Paris-Dauphine 15/36
Wednesday, April, 2019 Python for Finance - Lecture 9
Andras Niedermayer - Université Paris-Dauphine 16/36
Wednesday, April, 2019 Python for Finance - Lecture 9
Andras Niedermayer - Université Paris-Dauphine 17/36
Normality tests on S&P 500 data

The S&P 500 data have negative skewness (i.e., the returns are not
symmetric around the mean), and they also have excess kurtosis (fat
tails: excessive extreme returns). Therefore, it fails the normality test.

Measure Value Test statistic p-value


Skewness -0.943 -7.943 1.96e-15

Kurtosis 5.540 8.673 4.19e-18

Normality 138.3 9.18e-31

Wednesday, April, 2019 Python for Finance - Lecture 9


Andras Niedermayer - Université Paris-Dauphine 18/36
Outline

1 Risk Measures

2 Parametric VaR, ES

3 Monte Carlo Simulation

4 Historical method

Wednesday, April, 2019 Python for Finance - Lecture 9


Andras Niedermayer - Université Paris-Dauphine 19/36
Monte Carlo Simulation

1 Similarly to Parametric calculation the Monte Carlo simulations


are also driven by an assumed distribution. In case of Normality
assumption we can estimate the parameters similarly to the
Parametric case.
2 Generating random numbers based on the given distribution
3 Generating return paths
4 Calculate Risk Measures

Wednesday, April, 2019 Python for Finance - Lecture 9


Andras Niedermayer - Université Paris-Dauphine 20/36
Built in random number Generators

1 import numpy . random as npr


2 # Normal distribution
3 r = npr . normal ( loc = mu , scale = sigma , size =( T , N ))
4 R = npr . multivari a t e_ n o rm a l ( mean , cov , size )
5 # Log - Normal distribution :
6 r = npr . lognormal ([ mean , sigma , size ])
7 # Student - t distribution
8 r = npr . standard_t ( dof , N )

Full list: https://docs.scipy.org/doc/numpy-1.14.0/


reference/routines.random.html

Wednesday, April, 2019 Python for Finance - Lecture 9


Andras Niedermayer - Université Paris-Dauphine 21/36
Path generation with pre-generated returns

1 def make_path (R , S0 =1 , b_return_path = True ):


2 # R . shape = [T , N ]
3 R_with_0 = np . zeros (( R . shape [0]+1 , R . shape [1]))
4 R_with_0 [1: ,:] = R
5 c umulative_r et ur ns = R_with_0 . cumsum ( axis =0)
6 if b_return_path :
7 return np . exp ( c um ul at iv e_ re tu rn s )* S0
8 else :
9 return c um ul at iv e_ re tu rn s

Wednesday, April, 2019 Python for Finance - Lecture 9


Andras Niedermayer - Université Paris-Dauphine 22/36
Standardizing variables – mean
Let us generate 100 standard normal variables:
1 X = npr . randn (100)

Especially in small samples, the sample mean and variance will not be
zero and one!
1 X . mean ()= -0.128
2 X . std ()=1.015

Mean adjustment
First, we can normalize the mean by subtracting it from each element:
1 X1 =X - X . mean ()
2 X1 . mean ()=5.16 e -17
3 X1 . std ()=1.015

This solves the mean issue, not the standard deviation!


Wednesday, April, 2019 Python for Finance - Lecture 9
Andras Niedermayer - Université Paris-Dauphine 23/36
Standardizing variables – variance

Variance adjustment
Second, we can normalize the variance by dividing each element with
the standard deviation:
1 X2 = X1 / X . std ()
2 X2 . mean ()=5.16 e -17
3 X2 . std ()=1.000

Or, directly:
1 X3 =( X - X . mean ())/ X . std ()

Wednesday, April, 2019 Python for Finance - Lecture 9


Andras Niedermayer - Université Paris-Dauphine 24/36
Antithetic variables

Exploiting the feature of a distribution where the transformation of


the variable leads to a similar distribution, we can
• significantly speed up the simulation procedure
• reduce the error of the Monte Carlo Simulation
In case of normal distribution:
X ∼ N(0, σ 2 ), Y := −X ⇒ Y ∼ N(0, σ 2 )

VaR with Antithetic variate


1 rets = npr . randn ( n )
2 [ pct_up , pct_down ] =
3 np . percentile ( rets , [ alpha , 100.0 - alpha ])
4 var = -( sigma *( pct_up - pct_down )/2+ mu )

Wednesday, April, 2019 Python for Finance - Lecture 9


Andras Niedermayer - Université Paris-Dauphine 25/36
GARCH model

The Generalised Autoregressive Conditional Heteroskedasticity


model, or GARCH:
1 Allows the volatility of returns to be time-dependent, following a
AR process.
2 Therefore, it is a suitable model to account for the empirical
observation of volatility clustering
3 Clustering: Periods of high volatility are likely to be followed also
by periods of high volatility.
4 An important note is that the volatility is non-stochastic!
5 Estimation of GARCH is done by maximum likelihood.

Wednesday, April, 2019 Python for Finance - Lecture 9


Andras Niedermayer - Université Paris-Dauphine 26/36
GARCH specification

Let stock (index) returns be given by:

rt = µ + t , where t ∼ N 0, σt2

(4)

The variance dynamics is:

σt2 = ω + α2t−1 + βσt−1


2
(5)

For the model to remain stationary (variance does not explode) we


require:
α + β < 1. (6)
There are four parameters to estimate: µ, ω, α, β.

Wednesday, April, 2019 Python for Finance - Lecture 9


Andras Niedermayer - Université Paris-Dauphine 27/36
GARCH in Python
The arch package contains the tools for GARCH analysis. It can be
downloaded by pip install (available for Python 2 and 3 as well).
1 from arch import arch . model

First we need to define the model that we would like to estimate.


Default is GARCH(1,1).
1 am = arch_model ( returns )

Then we can estimate the model parameters. The default estimation


methodology is Maximum Likelihood.
1 res = am . fit ()
2 res . summary ()

Then using the forecast method we can generate log-returns:


1 fcast = res . forecast ( method = ’ simulation ’ ,
2 simulations =N , horizon = days )
Wednesday, April, 2019 Python for Finance - Lecture 9
Andras Niedermayer - Université Paris-Dauphine 28/36
Conditional Volatility of Facebook

Wednesday, April, 2019 Python for Finance - Lecture 9


Andras Niedermayer - Université Paris-Dauphine 29/36
Effect of ”GARCH” on Facebook

Comparing Facebook VaR and ES with and without GARCH(1,1)

GARCH Normal
VaR95 0.0387 0.0248

ES95 0.0474 0.0313

VaR99 0.0514 0.0354

ES99 0.0605 0.0407

Wednesday, April, 2019 Python for Finance - Lecture 9


Andras Niedermayer - Université Paris-Dauphine 30/36
Outline

1 Risk Measures

2 Parametric VaR, ES

3 Monte Carlo Simulation

4 Historical method

Wednesday, April, 2019 Python for Finance - Lecture 9


Andras Niedermayer - Université Paris-Dauphine 31/36
Bootstrap Method

1 There is no assumption on the return distribution, so no


parameter estimation is required. It will use the historical
distribution.
2 Random sampling on the historical returns. NOTE: Keep the
Correlation structure!
3 Generate return path
4 Calculate Risk Measures

Wednesday, April, 2019 Python for Finance - Lecture 9


Andras Niedermayer - Université Paris-Dauphine 32/36
Random sampling

The fastest way to generate random sample of historical returns, we


can assign an integer for each observation time, and using a random
sampling algorithm we can generate a the set of simulated returns.
1 df2 = df . reset_index ()
2 nr_of_rets = len ( df2 )
3 return_indexes =
4 npr . choice ( range ( nr_of_rets ) , N )
5 retruns = df2 . loc [ return_indexes ]

Wednesday, April, 2019 Python for Finance - Lecture 9


Andras Niedermayer - Université Paris-Dauphine 33/36
Backtesting VaR

The Basel Committee introduced a VaR Backtest Methodology in the


Basel regulation, which is called the BIS Traffic Light System. Their
approach is based on how many breach would happen in the 1 day
99% VaR value today, if the last 250 days return scenario would
repeat.

Wednesday, April, 2019 Python for Finance - Lecture 9


Andras Niedermayer - Université Paris-Dauphine 34/36
BIS Traffic Light System

Zone Breach Value Cummulative Probability


Green 0 8.11%
Green 1 28.58%
Green 2 54.32%
Green 3 75.81%
Green 4 89.22%
Yellow 5 95.88%
Yellow 6 98.63%
Yellow 7 99.60%
Yellow 8 99.89%
Yellow 9 99.97%
Red 10+ 99.99%

Wednesday, April, 2019 Python for Finance - Lecture 9


Andras Niedermayer - Université Paris-Dauphine 35/36
Thank you for you attention!

Wednesday, April, 2019 Python for Finance - Lecture 9


Andras Niedermayer - Université Paris-Dauphine 36/36

You might also like