Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pricing options with holidays #2035

Open
bgladwyn-pm opened this issue Jul 25, 2024 · 1 comment
Open

Pricing options with holidays #2035

bgladwyn-pm opened this issue Jul 25, 2024 · 1 comment

Comments

@bgladwyn-pm
Copy link

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, f
365/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! :)

image
image

Copy link

boring-cyborg bot commented Jul 25, 2024

Thanks for posting! It might take a while before we look at your issue, so don't worry if there seems to be no feedback. We'll get to it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant