hasquant-0.7.0.0: test/example/QuantLib/Example/AsianOption.hs
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.PricingEngine
import QuantLib.Process hiding(fixingDates)
import QuantLib.Quote
import QuantLib.Context
import QuantLib.Time.Calendar
import QuantLib.Time.Date
import QuantLib.Time.Schedule
import QuantLib.TermStructure.Volatility
import QuantLib.TermStructure.Yield
-- | 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 evalDate
dc <- dayCounter (Actual360 False)
underQ <- simpleQuote 90
divQ <- simpleQuote 0.06
riskFreeQ <- simpleQuote 0.025
ts <- flatForward (ReferenceDate evalDate) riskFreeQ dc Continuous Annual
divTS <- flatForward (ReferenceDate evalDate) divQ dc Continuous Annual
volQ <- simpleQuote 0.13
volTS <- calendar TARGET >>= \cal -> blackConstantVol (CalendarReferenceDate evalDate) cal 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 Statistics 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
evalDate = 1 `january` 2020
strike = 87
fixings = 26 :: Int
len = 11 / 12 :: Double
dt = len / fromIntegral (fixings - 1)
-- matches upstream's `timeEvalDates(t, 360) = lround(t * 360)`
timeEvalDates t = round (t * 360 :: Double)
fixingDates = [addDays (timeEvalDates (fromIntegral i * dt)) evalDate | i <- [0 .. fixings - 1]]
maturity = last fixingDates
-- vim: set ft=haskell ff=unix ts=8 sts=2 sw=2 et: