Skip to content

Commit 75a9dd1

Browse files
committed
added explanations for stochastic volatility
1 parent 0cc925b commit 75a9dd1

File tree

1 file changed

+33
-16
lines changed

1 file changed

+33
-16
lines changed

examples/stochastic_volatility.py

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,28 @@
22
from pymc import *
33

44
from scipy.sparse import csc_matrix
5+
from scipy import optimize
56

6-
#data
7+
"""
8+
1. Data
9+
-------
10+
"""
711
returns = np.genfromtxt("data/SP500.csv")
812

913
n = 400
1014
returns = returns[-n:]
1115

12-
#model
13-
16+
"""
17+
2. Build Model
18+
--------------
19+
Stochastic volatility model described in Hoffman (2011) on p21.
20+
"""
1421
model = Model()
1522
Var = model.Var
1623
Data = model.Data
1724

18-
19-
20-
sd, lsd = model.TransformedVar(
21-
'sd', Exponential(1./.02),
25+
#its easier to sample the scale of the volatility process innovations on a log scale
26+
sd, log_sd = model.TransformedVar('sd', Exponential(1./.02),
2227
transforms.log, testval = -2.5)
2328

2429
nu = Var('nu', Exponential(1./10))
@@ -27,29 +32,41 @@
2732

2833
lreturns = Data(returns, T(nu, lam = exp(-2*lvol)))
2934

30-
31-
32-
#fitting
33-
35+
"""
36+
3. Fit Model
37+
------------
38+
"""
3439
H = model.d2logpc()
3540

36-
def hessian(q, nusd):
37-
h = H(q)
41+
"""
42+
To get a decent scale for the hamiltonaian sampler, we find the hessian at a point. However, the 2nd derivatives for the degrees of freedom are negative and thus not very informative, so we make an educated guess. The interactions between lsd/nu and lvol are also not very useful, so we set them to zero.
43+
44+
The hessian matrix is also very sparse, so we make it a sparse matrix for faster sampling.
45+
"""
46+
def hessian(point, nusd):
47+
h = H(point)
3848
h[1,1] = nusd**-2
3949
h[:2,2:] = h[2:,:2] = 0
4050

4151
return csc_matrix(h)
4252

53+
"""
54+
the full MAP is a degenerate case wrt to sd and nu, so we find the MAP wrt the volatility process, keeping log_sd and nu constant at their default values. we use l_bfgs_b because it is more efficient for high dimensional functions (lvol has n elements)
55+
"""
4356

44-
from scipy import optimize
4557
s = find_MAP(model, vars = [lvol], fmin = optimize.fmin_l_bfgs_b)
46-
s = find_MAP(model, s, vars = [lsd, nu])
4758

59+
#we do a short initial run to get near the right area
4860
step = hmc_step(model, model.vars, hessian(s, 6))
4961
trace, _,t = sample(200, step, s)
5062

63+
#then start again using a new hessian at the new start
5164
s2 = trace.point(-1)
52-
5365
step = hmc_step(model, model.vars, hessian(s2, 6), trajectory_length = 4.)
5466
trace, _,t = sample(4000, step, trace = trace)
5567

68+
"""
69+
4. References
70+
-------------
71+
1. Hoffman & Gelman. (2011). The No-U-Turn Sampler: Adaptively Setting Path Lengths in Hamiltonian Monte Carlo. http://arxiv.org/abs/1111.4246
72+
"""

0 commit comments

Comments
 (0)