module Quant.Models.Merton (
Merton (..)
) where
import Data.Random
import Data.Random.Distribution.Poisson
import Control.Monad.State
import Quant.MonteCarlo
import Quant.ContingentClaim
import Quant.YieldCurve
import qualified Data.Vector.Unboxed as U
data Merton = forall a b . (YieldCurve a, YieldCurve b) => Merton {
mertonInitial :: Double
, mertonVol :: Double
, mertonIntensity :: Double
, mertonJumpMean :: Double
, mertonJumpVol :: Double
, mertonForwardGen :: a
, mertonDiscounter :: b }
instance Discretize Merton where
initialize (Merton s _ _ _ _ _ _) trials = put (Observables [U.replicate trials s], 0)
evolve' m@(Merton _ vol intensity mu sig _ _) t2 anti = do
(Observables (stateVec:_), t1) <- get
fwd <- forwardGen m t2
let correction = exp (mu + sig*sig /2.0) 1
grwth = U.map (\x -> (x vol*vol/2 intensity * correction) * (t2t1)) fwd
postVal <- U.forM (U.zip grwth stateVec) $ \ ( g,x ) -> do
normResid1 <- lift stdNormal
normResid2 <- lift stdNormal
poissonResid <- lift $ integralPoisson (intensity * (t2t1)) :: MonteCarlo (Observables, Double) Int
let poisson' = fromIntegral poissonResid
jumpterm = mu*poisson'+sig*sqrt poisson' * normResid2
if anti then
return $ x * exp (g normResid1*vol + jumpterm)
else
return $ x * exp (g + normResid1*vol + jumpterm)
put (Observables [postVal], t2)
discounter (Merton _ _ _ _ _ _ dsc) t = do
size <- getTrials
return $ U.replicate size $ disc dsc t
forwardGen (Merton _ _ _ _ _ fg _) t2 = do
size <- getTrials
t1 <- gets snd
return $ U.replicate size $ forward fg t1 t2