8
$\begingroup$

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)
$\endgroup$
4
  • 1
    $\begingroup$ You might want to delete stackoverflow.com/questions/47660745/python-quantlib if you're asking the question here. $\endgroup$ Commented Dec 6, 2017 at 9:40
  • 2
    $\begingroup$ "I am using Anaconda, Spyder, Python" I'm sure the Viper and the Tarantula are around the corner! $\endgroup$
    – Yian Pap
    Commented Dec 6, 2017 at 13:26
  • $\begingroup$ I get an error when using this AttributeError: No constructor defined I can't call ql.FDDividendAmericanEngine $\endgroup$
    – pyCthon
    Commented Aug 26, 2020 at 17:03
  • $\begingroup$ I get the same Constructor Error. Would love to know the cause of this so it can be usuable. @fmc100 told us it is fine, and was a typo, but this is not working at all. Any ideas ? $\endgroup$
    – JBerstein
    Commented Dec 1, 2020 at 20:37

1 Answer 1

8
$\begingroup$

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.

$\endgroup$
1
  • $\begingroup$ thanks very much. i realized the error. instead of using evaluationDate, i used evaluation_date. subtle but bad mistake. appreciate the response Luigi. cheers $\endgroup$
    – fmc100
    Commented Dec 6, 2017 at 17:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.