Skip to content
All library documents

Fixing QuantLib American Option Pricing with Discrete Dividends

Article Quant Q&A · Author: JBerstein

Summary

The document diagnoses errors in a Python example for pricing an American option with discrete dividends in QuantLib. The example builds a Black–Scholes process from spot, a flat risk-free rate, and constant volatility, then creates a dividend-paying vanilla option and requests a finite-difference price and Greeks. The response identifies a pricing-engine class that was deprecated and gives its replacement.

It also points out that the sample assigns the valuation date to an attribute name that does not affect QuantLib’s evaluation settings. The response recommends using the valid evaluation-date property or its setter method. It warns that, with the ineffective assignment, the code can return zero values. These are library API and setup corrections, not evidence comparing pricing models or validating the resulting Greeks. The answer may depend on the QuantLib version, and the document does not report outputs after the fixes.

Key ideas

  • The cited finite-difference engine had been deprecated in favor of a replacement engine.
  • The evaluation date must be set through a recognized QuantLib setting.
  • An ineffective evaluation-date assignment can leave pricing outputs at zero.
  • The example addresses implementation setup, not model accuracy or Greek validation.

Tags

Full text
# Constructor error pricing american ops with divs quantlib?


# Constructor error pricing american ops with divs quantlib?












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)
```

## Answer by David Duarte (score 2)

https://quant.stackexchange.com/a/59697

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)
```

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.