I need some guidance on valuing American style FX options (spots and forwards) using quantlib in Python. Given the following parameters:
- Domestic and foreign risk-free rates
- Current market spot and forward points for the underlying asset (maturity at option exercise date plus tenor) - as an aside, does the maturity move forward for an early exercise of the option?
- Approximate volatility of the underlying (by using historical prices)
- Strike price
- Expiration date
- Maturity date
Here is what I have tried so far:
# QuantLib date settings
todayDate = ql.Date().todaysDate()
ql.Settings.instance().evaluationDate = todayDate
dayCount = ql.ActualActual()
volatilityHandle = ql.BlackVolTermStructureHandle(
ql.BlackConstantVol(todayDate, ql.NullCalendar(), ql.QuoteHandle(ql.SimpleQuote(req.Volatility)), dayCount)
)
# define the option
option = ql.VanillaOption(
ql.PlainVanillaPayoff(ql.Option.Call, req.StrikePrice), ql.AmericanExercise(req.ExpirationDate)
)
# build the process
localInterestRateHandle = ql.YieldTermStructureHandle(
ql.FlatForward(todayDate, req.LocalInterestRate / 100, dayCount)
)
# this is the one big issue - for FX options, both the domestic and
# foreign risk-free rates have to be considered, but the
# BlackScholesProcess does not cater for this.
# foreignInterestRateHandle = ql.YieldTermStructureHandle(
# ql.FlatForward(todayDate, req.ForeignInterestRate / 100, dayCount)
# )
process = ql.BlackScholesProcess(
ql.QuoteHandle(ql.SimpleQuote(req.SpotPrice + req.ForwardPoints)),
localInterestRateHandle,
volatilityHandle,
)
# set the pricing engine
option.setPricingEngine(ql.MCAmericanEngine(process, "pseudorandom", timeSteps=100, requiredSamples=1000))
return GetOptionValueResponse(OptionValue=option.NPV())
The biggest issue is that (as commented), the BlackScholesProcess
does not cater for domestic and foreign RFRs. The GarmanKohlagenProcess
does work for European options, but I have not seen a similar process for American options.
For more clarity, this is the request class passed to the function:
@dataclass
class GetOptionValueRequest:
"""The request parameters of the GetEuropeanOptionValue service."""
SpotPrice: float
"""The latest spot price of the underlying asset."""
ForwardPoints: float
"""The latest forward points of the underlying asset."""
StrikePrice: float
"""The strike price of the option."""
ExpirationDate: date
"""The expiration date of the option in days."""
LocalInterestRate: float
"""The risk-free interest rate of the local currency as a percentage"""
ForeignInterestRate: float
"""The risk-free interest rate of the foreign currency as a percentage"""
Volatility: float
"""The volatility of the underlying asset"""