Source code for timewave.stochasticprocess.multifactor

# -*- coding: utf-8 -*-

# timewave
# --------
# timewave, a stochastic process evolution simulation engine in python.
# 
# Author:   sonntagsgesicht, based on a fork of Deutsche Postbank [pbrisk]
# Version:  0.6, copyright Wednesday, 18 September 2019
# Website:  https://github.com/sonntagsgesicht/timewave
# License:  Apache License 2.0 (see LICENSE file)


from math import sqrt, exp, log
from scipy.linalg import cholesky

from .base import MultivariateStochasticProcess
from .gauss import WienerProcess, GeometricBrownianMotion


[docs]class SABR(MultivariateStochasticProcess): """ class implementing the Hagan et al SABR model """ def __init__(self, alpha=.1, beta=.2, nu=.3, rho=-.2, start=.05): super(SABR, self).__init__((start, alpha)) self._blend_process = GeometricBrownianMotion(0.0) self._vol_process = GeometricBrownianMotion(0.0, nu, alpha) self._beta = beta self._rho = rho self._diffusion_driver = self._blend_process.diffusion_driver + self._vol_process.diffusion_driver def __str__(self): alpha = self._vol_process.start beta = self._beta nu = self._vol_process._sigma rho = self._rho return 'SABR(alpha=%0.4f, beta=%0.4f, nu=%0.4f, rho=%0.4f)' % (alpha, beta, nu, rho)
[docs] def evolve(self, x, s, e, q): f, a = x if e - s > 0: q1, q2 = q q2 = self._rho * q1 + sqrt(1. - self._rho ** 2) * q2 a = self._vol_process.evolve(a, s, e, q2) sgn = -1. if f < 0. else 1. f += sgn * abs(f) ** self._beta * sqrt(e - s) * a * q1 return f, a
[docs] def mean(self, t): return self.start[0]
[docs] def variance(self, t): return self._vol_process.variance(t) * t # todo give better sabr variance proxy
[docs]class MultiGauss(MultivariateStochasticProcess): """ class implementing multi dimensional brownian motion """ def __init__(self, mu=list([0.]), covar=list([[1.]]), start=list([0.])): super(MultiGauss, self).__init__(start) self._mu = mu self._dim = len(start) self._cholesky = None if covar is None else cholesky(covar).T self._variance = [1.] * self._dim if covar is None else [covar[i][i] for i in range(self._dim)] self._diffusion_driver = [WienerProcess(m, sqrt(s)) for m, s in zip(self._mu, self._variance)] def __str__(self): cov = self._cholesky.T * self._cholesky return '%d-MultiGauss(mu=%s, cov=%s)' % (len(self), str(self._mu), str(cov)) def _drift(self, x, s, e): return [m * (e - s) for m in self._mu]
[docs] def evolve(self, x, s, e, q): dt = sqrt(e - s) q = [qq * dt for qq in q] q = list(self._cholesky.dot(q)) d = self._drift(x, s, e) return [xx + dd + qq for xx, dd, qq in zip(x, d, q)]
[docs] def mean(self, t): return [s + m * t for s, m in zip(self.start, self._mu)]
[docs] def variance(self, t): return [v * t for v in self._variance]