quantfin-0.1.0.0: src/Quant/Models/Dupire.hs
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ExistentialQuantification #-}
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
-- | 'Dupire' represents a Dupire-style local vol model.
data Dupire = forall a b . (YieldCurve a, YieldCurve b) => Dupire {
dupireInitial :: Double -- ^ Initial asset level
, dupireFunc :: Double -> Double -> Double -- ^ Local vol function taking a time to maturity and a level
, mertonForwardGen :: a -- ^ 'YieldCurve' to generate forwards
, mertonDiscounter :: b } -- ^ 'YieldCurve' to generate discount rates
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) / (t2-t1)) $ 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