HQu-0.0.0.0: src/Q/Greeks.hs
{-# LANGUAGE MonoLocalBinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
module Q.Greeks
(
module Q.Types
, module Q.Options
, Bump (..)
, DiffMethod(..)
, Bumpable(..)
, firstOrder
) where
import Q.Types
import Q.Options
import Data.Coerce
-- | A relative or an absolute bump. Used with numerical Greeks.
data Bump = Abs Double
| Rel Double
data DiffMethod = ForwardDiff
| BackwardDiff
| CenteralDiff
class Bumpable a where
bumpUp :: a -> Bump -> a
bumpDown :: a -> Bump -> a
stepSize :: a -> Bump -> Double
-- | Things we can bump to calculate Greeks such as 'Spot', 'Rate'..etc'
instance (Coercible a Double) => Bumpable a where
bumpUp a (Abs bump) = coerce $ coerce a + bump
bumpUp a (Rel bump) = coerce $ coerce a * (1 + bump)
bumpDown a (Abs bump) = coerce $ coerce a - bump
bumpDown a (Rel bump) = coerce $ coerce a * (1 - bump)
stepSize _ (Abs bump) = bump
stepSize s (Rel bump) = coerce s * bump
firstOrder :: (Bumpable a) => DiffMethod -> Bump -> (a -> Double) -> a -> Double
firstOrder ForwardDiff b f a = df / dx
where df = f a' - f a
a' = bumpUp a b
dx = stepSize a b :: Double
firstOrder BackwardDiff d f a = df / dx
where df = f a - f a'
a' = bumpDown a d
dx = negate (stepSize a d )
firstOrder CenteralDiff b f a = df / dx
where df = f u - f d
u = bumpUp a b
d = bumpDown a b
dx = 2 * stepSize a b