The stochastic volatility model \(r_t = \exp(h_t/2) z_t\) with
\(z_t\) standard normal and \(h_t\) a Gaussian AR(1) is not a
linear Gaussian state space model, so the exact likelihood needs
simulation. Squaring and taking logs linearises it,
$$\log r_t^2 = h_t + \log z_t^2,$$
at the price of a measurement error \(\log z_t^2\) that is the log
of a chi-square with one degree of freedom, and so is very far from
normal: it is sharply left-skewed. Treating it as normal anyway, with
its true first two moments
\(E[\log z^2] = \psi(1/2) + \log 2 = -\gamma - \log 2 = -1.2703628\)
and \(Var[\log z^2] = \psi'(1/2) = \pi^2/2 = 4.9348022\), turns the
model into a linear Gaussian one whose Kalman filter prediction errors
give a quasi likelihood. Maximising it is consistent and
asymptotically normal but not efficient, and the reported ll is
a quasi log-likelihood, not a log-likelihood: it is not comparable
with the likelihood of a model estimated exactly.
Details
The filter runs on the state \(h^*_t = h_t - \mu\), with stationary prior \(Var(h^*_0) = \sigma_\eta^2/(1 - \phi^2)\) and measurement intercept \(\mu + E[\log z^2]\).
Maximisation is a deterministic coordinate ascent: golden-section line
search on each of \(\mu\), \(\phi\) and \(\log \sigma_\eta\) in
turn, for a fixed number of sweeps. There is no random restart and no
convergence tolerance, so the result is a deterministic function of
the data and of init.
Zero returns make \(\log r_t^2\) infinite. offset is added to
\(r_t^2\) before the log to keep the filter finite; it is the usual
remedy and it biases the estimate slightly, so it is reported.
Mirrors morie.fn.volsv on the Python side.
