module Quant.Models.Dupire (
Dupire (..)
) where
import Data.Random
import Control.Monad.State
import Quant.ContingentClaim
import Quant.MonteCarlo
import Quant.YieldCurve
import qualified Data.Vector.Unboxed as U
data Dupire = forall a b . (YieldCurve a, YieldCurve b) => Dupire {
dupireInitial :: Double
, dupireFunc :: Double -> Double -> Double
, mertonForwardGen :: a
, mertonDiscounter :: b }
instance Discretize Dupire where
initialize (Dupire s _ _ _) trials = put (Observables [U.replicate trials s], 0)
evolve' d@(Dupire _ f _ _) t2 anti = do
(Observables (stateVec:_), t1) <- get
fwd <- forwardGen d t2
let vols = U.map (f t1) stateVec
grwth = U.map (\(fwdVal, v) -> (fwdVal v * v / 2) / (t2t1)) $ U.zip fwd vols
postVal <- U.forM (U.zip3 grwth stateVec vols) $ \ ( g,x,v ) -> do
normResid <- lift stdNormal
if anti then
return $ x * exp (g normResid*v)
else
return $ x * exp (g + normResid*v)
put (Observables [postVal], t2)
discounter (Dupire _ _ _ dsc) t = do
size <- getTrials
return $ U.replicate size $ disc dsc t
forwardGen (Dupire _ _ fg _) t2 = do
t1 <- gets snd
size <- getTrials
return $ U.replicate size $ forward fg t1 t2