0
$\begingroup$

Looking at post from Issue Using QuantLib and Python to Calculate Price and Greeks for American Option With Discrete Dividends

and trying to recreate the result; but getting a constructor error I cannot debug.

Anyone know what the cause of this is?

import QuantLib as ql


#%%
#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 




#%%
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   


#%%
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$
2
$\begingroup$

Not sure what version you have, but if you check the QuantLib documentation (link), that class was deprecated in version 1.17:

Use FdBlackScholesVanillaEngine instead. Deprecated in version 1.17.

To get it working you just have to replace the this line:

engine = ql.FDDividendAmericanEngine(process, time_steps, grid_points)

with:

engine = ql.FdBlackScholesVanillaEngine(process, time_steps, grid_points)

On another note, the code will produce zeros for all the values and the reason is because there is an error on the way to are setting the evaluation date.

The code has:

ql.Settings.instance().evaluation_date = valuation_date 

But evaluation_date is not a valid attribute of that class. In fact, you can set whatever attributes you want but that doesn't mean they have any effect: ql.Settings.instance().bananas = 5

The correct attribute would be evaluationDate, and so:

ql.Settings.instance().evaluationDate = valuation_date 

Although it's considered best practice to use a setter method instead of changing class atributes directly, and in this case that would be:

ql.Settings.instance().setEvaluationDate(valuation_date)
$\endgroup$
1
  • $\begingroup$ Thanks fully working now ! $\endgroup$ – JBerstein Dec 2 '20 at 10:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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