%pylab inline
import pandas as pd
import numpy as np
import fmt
Populating the interactive namespace from numpy and matplotlib
This homework is to price synthetic CDO using the one factor Gaussian Copula model.
A synthetic CDO consists of $n$ CDS, the total loss of the portfolio is defned as:
$$ l(t) = \sum_i^n w_i \tilde {\mathbb{1}}_i(t) (1-r_i(t)) $$where $w_i$ and $r_i(t)$ are the notional weights and recovery rate of the i-th name in the portfolio. The notional weighs sum up to 1: $\sum_i w_i = 1 $. The $ \tilde {\mathbb{1}}_i(t) $ is the default indicator of the i-th name defaulted before time $t$, the default probability is therefore $p_i(t) = \mathbb E[\tilde {\mathbb{1}}_i(t) ]$
For the purpose of this homework, we consider a simplified synthetic CDO that has no coupon payments, therefore the PV of a $1 notional synthetic CDO tranche with maturity $t$, attachment $a$ and detachment $d$ is:
$$ v(a, d) = \frac{d(t)}{d-a} \min\left((l(t) - a)^+, d-a\right) $$where $d(t)$ is the discount factor.
The following are the parameters to the synthetic CDO, and a straight forward Monte Carlo pricer:
n = 125
t = 5.
defProbs = 1 - exp(-(np.random.uniform(size=n)*.03)*t)
recovery = 0.4*np.ones(n)
w = 1./n*np.ones(n)
rho = 0.5
discf = .9
npath = 1000
# a list of attachements and detachements, they pair up by elements
attachements = np.array([0, .03, .07, .1, .15, .3])
detachements = np.array([.03, .07, .1, .15, .3, .6])
#portfolio expected loss
el = np.sum(w*defProbs*(1-recovery))
print("portfolio expected loss is ", el)
portfolio expected loss is 0.043182264890472034
from scipy.stats import norm
class CDO(object) :
def __init__(self, w, defProbs, recovery, a, d) :
self.w = w/np.sum(w)
self.p = defProbs
self.rec = recovery
self.rho = rho
self.a = a
self.d = d
def drawDefaultIndicator(self, z, rho) :
'''return a list of default indicators given common factor z, using one factor Gaussian Copula
'''
e = np.random.normal(size=np.shape(self.p))
x = z*np.sqrt(self.rho) + np.sqrt(1-self.rho)*e
return np.less(norm.cdf(x), self.p)
def portfolioLoss(self, defIndicator) :
'''compute portfolio loss given default indicators'''
return np.sum(defIndicator*self.w*(1-self.rec))
def tranchePV(self, portfLoss, discf) :
'''compute tranche PV from portfolio loss
Args:
portfLoss: the total portfolio loss
discf: discount factor
Returns:
tranche PVs'''
sz = self.d - self.a
return discf/sz*np.minimum(np.maximum(portfLoss - self.a, 0), sz)
def drawPV(self, z, rho, discf) :
''' compute PV and portfolio Loss conditioned on a common factor z'''
di = self.drawDefaultIndicator(z, rho)
pfLoss = self.portfolioLoss(di)
return self.tranchePV(pfLoss, discf), pfLoss
cdo = CDO(w, defProbs, recovery, attachements, detachements)
## price the tranches using simulation
def simCDO(cdo, rho, disc, paths) :
zs = np.random.normal(size=[paths])
pv = np.zeros(np.shape(cdo.a))
pv2 = np.zeros(np.shape(cdo.d))
for z in zs:
thisPV, _ = cdo.drawPV(z, rho, discf)
pv += thisPV
pv2 += thisPV*thisPV
v = pv/paths
var = pv2/paths - v**2
return pv/paths, np.sqrt(var/paths)
pv_0, err_0 = simCDO(cdo, rho, discf, npath)
df = pd.DataFrame(np.array([cdo.a, cdo.d, pv_0, err_0]), index=['Attach', 'Detach', 'PV', 'MC err'])
fmt.displayDF(df, fmt='4g')
0 | 1 | 2 | 3 | 4 | 5 | |
---|---|---|---|---|---|---|
Attach | 0 | 0.03 | 0.07 | 0.1 | 0.15 | 0.3 |
Detach | 0.03 | 0.07 | 0.1 | 0.15 | 0.3 | 0.6 |
PV | 0.4695 | 0.249 | 0.1519 | 0.09073 | 0.03766 | 0.003708 |
MC err | 0.01227 | 0.01184 | 0.01021 | 0.008128 | 0.004988 | 0.001249 |
Modify the simCDO function to implement the following variance reduction techniques, and show whether the technique is effective:
For this homework, we only apply the variance reduction in the common market factor $z$, you should not change the random number $e$ that were drew with in the drawDefaultIndicator function, i.e., only modify the simCDO code, re-use but do not modify the CDO class. Unless explicitly mentioned, keep the simulation path the same as the base case above.
Compute the variance reduction factor for each technique, and comment on the effectiveness of these variance reduction techniques.