packages feed

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