Setting QuantLib’s Evaluation Date for American Option Pricing
Summary
The document presents a Python and QuantLib problem: a dividend-paying American option returns zero for its net present value and Greeks despite inputs that should produce nonzero values. The code builds an American exercise option, supplies discrete dividend dates and amounts, and calculates prices using a finite-difference engine. The reported issue is traced to QuantLib’s global evaluation date, which was not set in the script running the calculation.
QuantLib therefore used its default current date, which was later than the option’s expiry, and treated the contract as expired. Setting the global evaluation date to the intended valuation date before pricing resolves the date mismatch. The example illustrates that pricing results depend on library-wide date state as well as the option, process, and engine inputs. The answer focuses on this configuration error; it does not analyze the numerical method, dividend modeling, or the accuracy of the expected price and Greeks.
Key ideas
- QuantLib pricing depends on its global evaluation date.
- If the evaluation date is later than expiry, an option may be treated as expired.
- Set the evaluation date to the intended valuation date before calculating the price and Greeks.
- The example concerns American options with discrete dividends and a finite-difference pricing engine.
- The fix addresses a date configuration issue, not the numerical accuracy of the model.
Tags
Full text
# Issue Using QuantLib and Python to Calculate Price and Greeks for American Option With Discrete Dividends
# Issue Using QuantLib and Python to Calculate Price and Greeks for American Option With Discrete Dividends
I am having trouble using QuantLib with Python to calculate American options with discrete dividends. I am using Anaconda, Spyder, Python 3.6, and the most recent version of QuantLib. I created functions in pricingfunctions.py, which streamline the building process for pricing options and the greeks based on the code on this webpage - http://www.bnikolic.co.uk/blog/ql-american-disc-dividend.html:
```
import QuantLib as ql
#%%
def create_american_process(valuation_date, rf_rate, spot, ivol):
#set calendar & day count
calendar = ql.UnitedStates()
day_counter = ql.ActualActual()
#set evaluation date
ql.Settings.instance().evaluation_date = valuation_date
#set rate & vol curves
rate_ts = ql.FlatForward(valuation_date, ql.QuoteHandle(rf_rate),
day_counter)
vol_ts = ql.BlackConstantVol(valuation_date, calendar,
ql.QuoteHandle(ivol), day_counter)
#create process
process = ql.BlackScholesProcess(ql.QuoteHandle(spot),
ql.YieldTermStructureHandle(rate_ts),
ql.BlackVolTermStructureHandle(vol_ts))
return process
#%%
def american_px_greeks(valuation_date, expiry, call_or_put, strike, div_dates,
div_values, time_steps, process):
#create instance as call or put
if call_or_put.lower() == 'call':
option_type = ql.Option.Call
elif call_or_put.lower() == 'put':
option_type = ql.Option.Put
else:
raise ValueError("The call_or_put value must be call or put.")
#set exercise and payoff
exercise = ql.AmericanExercise(valuation_date, expiry)
payoff = ql.PlainVanillaPayoff(option_type, strike)
#create option instance
option = ql.DividendVanillaOption(payoff, exercise, div_dates, div_values)
#set mesh size for finite difference engine
grid_points = time_steps - 1
#create engine
engine = ql.FDDividendAmericanEngine(process, time_steps, grid_points)
option.setPricingEngine(engine)
return option
#%%
def print_option_results(option):
print("NPV: ", option.NPV())
print("Delta: ", option.delta())
print("Gamma: ", option.gamma())
return None
```
Then I run the below script, but the outputs for NPV, Delta and Gamma are all 0.0, which is wrong. The NPV should be in the 12 to 13 range, and the Delta close to 0.50, while Gamma is negligible. I am not sure what is wrong. Any insights are much appreciated. Thanks
```
import QuantLib as ql
from pricingfunctions import create_american_process
from pricingfunctions import american_px_greeks
from pricingfunctions import print_option_results
#%%
#parameters
vol = 0.25
strike = 100
spot = ql.SimpleQuote(100)
rf_rate = ql.SimpleQuote(0.01)
ivol = ql.SimpleQuote(vol)
call_or_put = 'call'
div_dates = [ql.Date(14, 5, 2014), ql.Date(14, 8, 2014), ql.Date(14, 11, 2014)]
div_values = [1.0, 1.0, 1.0]
expiry = ql.Date(15, 1, 2016)
valuation_date = ql.Date(17, 4, 2014)
time_steps = 456
process_test = create_american_process(valuation_date, rf_rate, spot, ivol)
option_test = american_px_greeks(valuation_date, expiry, call_or_put, strike, div_dates, div_values, time_steps, process_test)
print_option_results(option_test)
```
## Answer by Luigi Ballabio (score 8, accepted)
https://quant.stackexchange.com/a/37245
You're not setting the global evaluation date. If you don't, you're in December 2017 and your option has expired a good while ago.
Adding
```
ql.Settings.instance().evaluationDate = valuation_date
```
before the calculations will give you the expected results.Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)
This summary was written by Stratmill's research agent from the original; it is not a copy of the source.