QuantLib
QuantLib copied to clipboard
Pricing options with holidays
Hi, I'm trying to use Quant lib to price FX options. For some dates, when the settlement date is 2 days after the evaluation, and delivery two days after the expiry I get perfect agreement between bloomberg OVML and quant lib. However, if there is a weekened/holiday between expiry/delivery or evaluation/settlement then there is no longer agreement. How do I get this behavior in quantlib so I can accurately price options?
`import QuantLib as ql import numpy as np
evaluationDate = ql.Date(13, 2, 2018) settlementDate = evaluationDate + ql.Period(2, ql.Days) # T+2 = Date(15, Feb, 2018) expirationDate = ql.Date(13, 2, 2019) # Date(15, Feb, 2019) deliveryDate = expirationDate + ql.Period(2, ql.Days) # Date(19, Feb, 2019) numberofdays=expirationDate-settlementDate print(numberofdays)
Parameters
S = 100 K = 105 f = 0.05 # Foreign rate (EUR in EURUSD) r = 0.02 # Domestic rate (USD in EURUSD) vol = 0.2
calendar = ql.UnitedStates(ql.UnitedStates.NYSE) dayCounter = ql.Actual365Fixed() exerciseType = ql.Exercise.European result = 4.6205 tol = 1e-3 # tolerance optionType = ql.Option.Call compounding = ql.Compounded compoundingFrequency = ql.Annual
Set the evaluation date
ql.Settings.instance().evaluationDate = evaluationDate
Option data
exercise = ql.EuropeanExercise(expirationDate) underlyingH = ql.QuoteHandle(ql.SimpleQuote(S))
rTS = ql.YieldTermStructureHandle(ql.FlatForward(evaluationDate, r365/360, dayCounter, compounding, compoundingFrequency)) fTS = ql.YieldTermStructureHandle(ql.FlatForward(evaluationDate, f365/360, dayCounter, compounding, compoundingFrequency)) flatVolTS = ql.BlackVolTermStructureHandle(ql.BlackConstantVol(evaluationDate, calendar, vol, dayCounter))
print(f'Fwd matching bloomberg {1.30*(1+r365/360)/(1+f365/360)}') print(f'Forward rate {1.30*(1+r)/(1+f)}')
payoff = ql.PlainVanillaPayoff(optionType, K) process = ql.GarmanKohlagenProcess(underlyingH, fTS, rTS, flatVolTS)
option = ql.VanillaOption(payoff, exercise) engine = ql.AnalyticEuropeanEngine(process) option.setPricingEngine(engine)
Calculate option price
calculated = option.NPV()
Print results
expected = 4.613072 error=(calculated-expected)/expected print(f"Calculated value = {calculated:.5f}, Expected value = {expected:.5f}, Error = {error*100:.8f}%")`
The output matches Bloomberg:
363 Fwd matching bloomberg 1.2623661599471252 Forward rate 1.262857142857143 Calculated value = 4.61307, Expected value = 4.61307, Error = 0.00000739%
But shifting the expiry to 02/15/19 gives:
365 Fwd matching bloomberg 1.2623661599471252 Forward rate 1.262857142857143 Calculated value = 4.62657, Expected value = 4.62016, Error = 0.13883435%
which no longer matches.
Is there a way to consider the correct dates in this calculation? Thanks for the help! :)