# coding=utf-8
"""
module containing stochastic process model producer
"""
from math import sqrt
from scipy.linalg import cholesky
from engine import Producer, State
from producers import MultiProducer
from indexedmatrix import IndexMatrix
# producer
[docs]class GaussEvolutionFunctionProducer(Producer):
"""
class implementing general Gauss process between grid dates
"""
def __init__(self, func=None, initial_state=None, length=None):
"""
:param callable func: evolve function, e.g. `lambda x, s, e, q: x + sqrt(e - s) * q` by default
with `x` current state value, `s` current point in time, i.e. start point of next evolution step,
`e` next point in time, i.e. end point of evolution step, `q` standard normal random number to do step
:param initial_state: initial state (value) of evolution,
:param int or None length: length of `q` as a list of Gauss random numbers,
if `None` or `0` the evolution function `func` will be invoked with `q`
not as a list but a float random number.
class implementing general Gauss process between grid dates and provides state to any evolve style function
`foo(x, s, e, q)` with `x` last state, `s` last state time, `e` current point in time and
`q` current Gauss process state
"""
if func is None:
func = (lambda x, s, e, q: x + sqrt(e - s) * q)
self._len = length
super(GaussEvolutionFunctionProducer, self).__init__(func, initial_state)
def __len__(self):
return 0 if self._len is None else self._len
[docs] def evolve(self, new_date):
"""
evolve to the new process state at the next date
:param date new_date: date or point in time of the new state
:return State:
"""
if self.state.date == new_date and not self.initial_state.date == new_date:
return self.state
if self._len:
q = [self.random.gauss(0., 1.) for _ in range(int(self._len))]
else:
q = self.random.gauss(0., 1.)
self.state.value = self.func(self.state.value, self.state.date, new_date, q)
self.state.date = new_date
return self.state
[docs]class GaussEvolutionProducer(GaussEvolutionFunctionProducer):
"""
producer to bring diffusion process to life
"""
def __init__(self, process):
"""
:param StochasticProcess process: diffusion process to evolve
"""
self.process = process
self.diffusion_driver = process.diffusion_driver
length = len(process) if len(process) > 1 else None
super(GaussEvolutionProducer, self).__init__(process.evolve, State(process.start), length)
[docs]class MultiGaussEvolutionProducer(CorrelatedGaussEvolutionProducer):
"""
class implementing multi variant GaussEvolutionProducer
"""
def __init__(self, process_list, correlation=None, diffusion_driver=None):
producers = [GaussEvolutionProducer(p) for p in process_list]
super(MultiGaussEvolutionProducer, self).__init__(producers, correlation, diffusion_driver)