|
1 | 1 | import theano.tensor as T
|
| 2 | +from theano import scan |
2 | 3 |
|
3 | 4 | from .continuous import Normal, Flat
|
4 | 5 | from .distribution import Continuous
|
5 | 6 |
|
6 |
| -__all__ = ['AR1', 'GaussianRandomWalk'] |
| 7 | +__all__ = ['AR1', 'GaussianRandomWalk', 'GARCH11'] |
7 | 8 |
|
8 | 9 |
|
9 | 10 | class AR1(Continuous):
|
@@ -71,3 +72,52 @@ def logp(self, x):
|
71 | 72 |
|
72 | 73 | innov_like = Normal.dist(mu=x_im1 + mu, tau=tau, sd=sd).logp(x_i)
|
73 | 74 | return init.logp(x[0]) + T.sum(innov_like)
|
| 75 | + |
| 76 | + |
| 77 | +class GARCH11(Continuous): |
| 78 | + """ |
| 79 | + GARCH(1,1) with Normal innovations. The model is specified by |
| 80 | +
|
| 81 | + y_t = sigma_t * z_t |
| 82 | + sigma_t^2 = omega + alpha_1 * y_{t-1}^2 + beta_1 * sigma_{t-1}^2 |
| 83 | +
|
| 84 | + with z_t iid and Normal with mean zero and unit standard deviation. |
| 85 | +
|
| 86 | + Parameters |
| 87 | + ---------- |
| 88 | + omega : distribution |
| 89 | + omega > 0, distribution for mean variance |
| 90 | + alpha_1 : distribution |
| 91 | + alpha_1 >= 0, distribution for autoregressive term |
| 92 | + beta_1 : distribution |
| 93 | + beta_1 >= 0, alpha_1 + beta_1 < 1, distribution for moving |
| 94 | + average term |
| 95 | + initial_vol : distribution |
| 96 | + initial_vol >= 0, distribution for initial volatility, sigma_0 |
| 97 | + """ |
| 98 | + def __init__(self, omega=None, alpha_1=None, beta_1=None, |
| 99 | + initial_vol=None, *args, **kwargs): |
| 100 | + super(GARCH11, self).__init__(*args, **kwargs) |
| 101 | + |
| 102 | + self.omega = omega |
| 103 | + self.alpha_1 = alpha_1 |
| 104 | + self.beta_1 = beta_1 |
| 105 | + self.initial_vol = initial_vol |
| 106 | + self.mean = 0 |
| 107 | + |
| 108 | + def _get_volatility(self, x): |
| 109 | + |
| 110 | + def volatility_update(x, vol, w, a, b): |
| 111 | + return T.sqrt(w + a * T.square(x) + b * T.square(vol)) |
| 112 | + |
| 113 | + vol, _ = scan(fn=volatility_update, |
| 114 | + sequences=[x], |
| 115 | + outputs_info=[self.initial_vol], |
| 116 | + non_sequences=[self.omega, self.alpha_1, |
| 117 | + self.beta_1]) |
| 118 | + return vol |
| 119 | + |
| 120 | + def logp(self, x): |
| 121 | + vol = self._get_volatility(x[:-1]) |
| 122 | + return (Normal.dist(0., sd=self.initial_vol).logp(x[0]) + |
| 123 | + T.sum(Normal.dist(0, sd=vol).logp(x[1:]))) |
0 commit comments