hasquant-0.6.0.0: test/example/QuantLib/Example/AsianOption.hs
{-# LANGUAGE TemplateHaskell #-}
module QuantLib.Example.AsianOption
(
Result(..)
, run
) where
import Data.Time.Calendar
import QuantLib.Instrument
import QuantLib.InterestRate
import QuantLib.Instrument.Option
import QuantLib.Math
import QuantLib.Model()
import QuantLib.PricingEngine
import QuantLib.Process
import QuantLib.Quote
import QuantLib.Settings
import QuantLib.Time.Calendar
import QuantLib.Time.Date hiding(today)
import QuantLib.Time.Schedule
import QuantLib.TermStructure.Volatility
import QuantLib.TermStructure.Yield
import QuantLib.Syntax
-- | Discrete arithmetic average-price Asian put, reproducing the 26-fixing
-- case from QuantLib's own @asianoptions.cpp@ (@testMCDiscreteArithmeticAveragePrice@,
-- data from Levy 1997 as reproduced by Haug): spot 90, strike 87, dividend
-- yield 6%, risk-free rate 2.5%, 11\/12y to maturity, 13% vol, expected NPV
-- 1.7255070456. Cross-checks 'turnbullWakemanAsianEngine' and
-- 'fdBlackScholesAsianEngine' (this module's two new engines) against the
-- already-bound 'mcDiscreteArithmeticAPEngine' on the same instrument.
data Result = Result
{ twR :: Double
, fdR :: Double
, mcR :: Double
}
run :: IO Result
run = do
setEvaluationDate $ Just today
dc <- dayCounter (Actual360 False)
underQ <- simpleQuote 90
divQ <- simpleQuote 0.06
riskFreeQ <- simpleQuote 0.025
ts <- flatForward today riskFreeQ dc Continuous Annual
divTS <- flatForward today divQ dc Continuous Annual
volQ <- simpleQuote 0.13
volTS <- calendar TARGET >>= $(free2nd 'blackConstantVol) today volQ dc
bsmProc <- blackScholesMertonProcess underQ divTS ts volTS EulerDiscretization False
let payoff = PlainVanilla $ PlainVanillaPayoff Put strike
exercise = European $ EuropeanExercise maturity
option <- discreteAveragingAsianOption Arithmetic 0.0 0 fixingDates payoff exercise
twEng <- turnbullWakemanAsianEngine bsmProc
QuantLib.Instrument.setPricingEngine option twEng
tw <- npv option
fdEng <- fdBlackScholesAsianEngine bsmProc 100 100 100 Douglas
QuantLib.Instrument.setPricingEngine option fdEng
fd <- npv option
mcEng <- mcDiscreteArithmeticAPEngine LowDiscrepancy bsmProc False False True (Just 2047) Nothing Nothing 0
QuantLib.Instrument.setPricingEngine option mcEng
mc <- npv option
return Result { twR = tw, fdR = fd, mcR = mc }
where
today = 1 `january` 2020
strike = 87
fixings = 26 :: Int
len = 11 / 12 :: Double
dt = len / fromIntegral (fixings - 1)
-- matches upstream's `timeToDays(t, 360) = lround(t * 360)`
timeToDays t = round (t * 360 :: Double)
fixingDates = [addDays (timeToDays (fromIntegral i * dt)) today | i <- [0 .. fixings - 1]]
maturity = last fixingDates
-- vim: set ft=haskell ff=unix ts=8 sts=2 sw=2 et: