module QuantLib.Stochastic.Process
( module QuantLib.Stochastic.Process )
where
import Control.Monad (foldM)
import Data.List (foldl')
import QuantLib.Stochastic.Random (NormalGenerator (..))
class Discretize b where
dDrift :: StochasticProcess a => a->b->Dot->Double
dDiff :: StochasticProcess a => a->b->Dot->Double
dDt :: StochasticProcess a => a->b->Dot->Double
class StochasticProcess a where
drift :: a->Dot->Double
diff :: a->Dot->Double
evolve :: Discretize b=> b->a->Dot->Double->Dot
evolve discr p dot dw = Dot newT newX
where !newT = getT dot + dDt p discr dot
!newX = getX dot + dDrift p discr dot + dDiff p discr dot * dw
data Dot = Dot { getT :: !Double, getX :: !Double }
deriving (Show, Eq)
type Path = [Dot]
generatePath :: (StochasticProcess a, NormalGenerator b, Discretize c) => b->c->a->Int->Dot->IO Path
generatePath rnd discr sp steps x0 = do
(!list, _) <- foldM generator ([], rnd) [1..steps]
let !path = foldl' evolver [x0] list
return $! reverse path
where evolver p dw = evolve discr sp (head p) dw : p
generator (list, r) _ = do
(!p, newRnd) <- ngGetNext r
return (p:list, newRnd)
data GeometricBrownian = GeometricBrownian {
gbDrift :: Double,
gbDiff :: Double
} deriving (Show)
instance StochasticProcess GeometricBrownian where
drift p (Dot _ x) = gbDrift p * x
diff p (Dot _ x) = gbDiff p * x
data ItoProcess = ItoProcess {
ipDrift :: Dot->Double,
ipDiff :: Dot->Double
}
instance StochasticProcess ItoProcess where
drift = ipDrift
diff = ipDiff
data SquareRootProcess = SquareRootProcess {
srpSpeed :: Double,
srpMean :: Double,
srpSigma :: Double
} deriving (Show)
instance StochasticProcess SquareRootProcess where
drift p (Dot _ x) = srpSpeed p * (srpMean p x)
diff p (Dot _ x) = srpSigma p * sqrt x
data OrnsteinUhlenbeckProcess = OrnsteinUhlenbeckProcess {
oupSpeed :: Double,
oupLevel :: Double,
oupSigma :: Double
} deriving (Show)
instance StochasticProcess OrnsteinUhlenbeckProcess where
drift p (Dot _ x) = oupSpeed p * (oupLevel p x)
diff p _ = oupSigma p
data BlackScholesProcess = BlackScholesProcess {
bspRiskFree :: Double->Double,
bspDividend :: Double->Double,
bspBlackVol :: Dot->Double
}
instance StochasticProcess BlackScholesProcess where
drift (BlackScholesProcess r q v) dot = r (getT dot) q ( getT dot) 0.5 * v dot ** 2
diff = bspBlackVol