packages feed

hasquant-0.7.0.0: test/hspec/QuantLib/Spec/Instrument/Forward.hs

-- | Coverage for the two new getters bound onto 'QuantLib.Instrument.Forward': the FRA's
-- settlement payoff ('amount') and the nominal-ratio FX forward rate ('fxForwardRate'). Both
-- are self-consistency checks against upstream's own closed-form definitions
-- (forwardrateagreement.cpp's @calculateAmount@, fxforward.hpp's inline @forwardRate@) rather
-- than golden values ported from QuantLib's test-suite, which has no dedicated fixture for
-- either.
module QuantLib.Spec.Instrument.Forward (spec) where

import Test.Hspec

import qualified QuantLib.Context as Context
import QuantLib.Time.Date
import QuantLib.Time.Calendar
import QuantLib.Time.Schedule
import QuantLib.InterestRate(Compounding(..))
import qualified QuantLib.InterestRate as IR
import QuantLib.Currency
import qualified QuantLib.Index.InterestRate as I
import QuantLib.Index(fixingCalendar)
import QuantLib.Quote
import QuantLib.TermStructure.Yield hiding(forwardRate)
import QuantLib.Instrument(PositionType(..))
import QuantLib.Instrument.Forward

import QuantLib.Spec.Helpers(closePrec)

spec :: Spec
spec = do
  describe "ForwardRateAgreement" $
    it "amount matches upstream's closed form: notional*sign*(F-K)*T/(1+F*T)" $
      Context.keepingSettingsGc $ do
        let today' = 23 `may` 2006
        Context.setEvaluationDate (Just today')
        q <- simpleQuote 0.035
        dc <- dayCounter (Actual360 False)
        ts <- flatForward (ReferenceDate today') q dc Continuous Annual
        eu3m <- I.iborIndex I.Euribor3M (Just ts)
        cal <- fixingCalendar eu3m
        idxDC <- I.dayCounter eu3m
        valueDate <- advance cal today' (3, Months) Following False
        maturityDate <- advance cal valueDate (3, Months) Following False
        let strike = 0.03
            notional = 100.0
        fra <- forwardRateAgreement eu3m valueDate maturityDate Long strike notional (Just ts)
        fwdRate <- forwardRate fra
        let f = IR.rate fwdRate
        t <- yearFraction idxDC valueDate maturityDate Nothing Nothing
        let expected = notional * (f - strike) * t / (1 + f * t)
        actual <- amount fra
        actual `shouldSatisfy` closePrec expected 1e-8

  describe "FxForward" $
    it "fxForwardRate equals targetNominal/sourceNominal for the nominal-based constructor" $
      Context.keepingSettingsGc $ do
        let today' = 23 `may` 2006
        Context.setEvaluationDate (Just today')
        usd <- currency USD
        eur <- currency EUR
        cal <- calendar TARGET
        maturity <- advance cal today' (6, Months) Following False
        let sourceNominal = 100.0
            targetNominal = 112.34
        fwd <- fxForward sourceNominal usd targetNominal eur maturity True 2 cal
        let r = fxForwardRate fwd
        r `shouldSatisfy` closePrec (targetNominal / sourceNominal) 1e-12

-- vim: set ft=haskell ff=unix ts=8 sts=2 sw=2 et: