packages feed

HQu-0.0.0.0: test/normalimpliedvol/Spec.hs

module Main where
import           Control.Monad           (guard, unless, when)
import           Data.List               (intercalate)
import           Q.Options.Bachelier
import           Q.Options.ImpliedVol.Normal
import           Q.Options
import           Q.Types
import           Test.Hspec              hiding (shouldBe)
import           Test.Hspec.Expectations

closeTo x y =  compareWith (\x y -> (abs $ (x - y)) / (max x y) <= 1e-2) errorMessage x y where
  errorMessage = "Is not close to"
  compareWith :: (HasCallStack, Show a) => (a -> a -> Bool) -> String -> a -> a -> Expectation
  compareWith comparator errorDesc result expected  = expectTrue errorMsg (comparator expected result)
    where errorMsg = show result ++ " " ++ errorDesc ++ " " ++ show expected
  expectTrue msg b = unless b (expectationFailure msg)

test cp t (k, b@(Bachelier f r sigma))= do
  let v = euOption b t cp k
      p      = vPremium v
      sigma' = euImpliedVolWith Jackel cp f k t r p
      df     = discountFactor t r
  when (hasTimeValue cp f k p df) $
    it (intercalate ", " [show t, show f, show df, show cp, show k, show p, show sigma]) $ do
        sigma' `closeTo` sigma


runTests f r strikes vols t = do
  let bs        = [Bachelier f r sigma | sigma <- vols]
      testCases = [(k, b)              | k <-  strikes, b <- bs]
  context "Call Option" $ do
    mapM_ (test Call t) testCases
  context "Put Option" $ do
    mapM_ (test Put t) testCases

main = hspec $ do
  describe "bachelier european implied vol" $ do
    context "When asset price is positive ($100)" $ do
      let strikes   = [Strike k            | k <- [80,81..120]]
          vols      = [Vol sigma           | sigma <- [1,2..200]]
      let f = Forward 100
      context "1Y option" $ do
        let t = YearFrac 1
        context "When interest rate is zero (0%)" $ do
          let r         = Rate 0
          runTests f r strikes vols t
        context "When interest rate is slightly positive (1%)" $ do
          let r         = Rate 0.01
          runTests f r strikes vols t
        context "When interest rate is slightly negative (-1%)" $ do
          let r         = Rate (-0.01)
          runTests f r strikes vols t