3
$\begingroup$

Trying to learn Quantlib with Python, please have a look at below code:

# option data
# AAPL US
maturity_date = ql.Date(26, 1, 2019)
spot_price = 180
strike_price = 180
volatility = 0.2198 # the historical vols or implied vols
option_type = ql.Option.Call
risk_free_rate = 0.025
day_count = ql.Actual365Fixed()
calendar = ql.UnitedStates()
calculation_date = ql.Date(1, 8, 2018)
ql.Settings.instance().evaluationDate = calculation_date
dividenddates = [ql.Date(10,8,2018), ql.Date(8, 11, 2018)]
dividends = [0.73,0.73]
spot_handle = ql.QuoteHandle(ql.SimpleQuote(spot_price))
flat_ts = ql.YieldTermStructureHandle(ql.FlatForward(calculation_date, risk_free_rate, day_count))
# dividend_yield = ql.YieldTermStructureHandle(ql.FlatForward(calculation_date, dividend_rate, day_count))
flat_vol_ts = ql.BlackVolTermStructureHandle(ql.BlackConstantVol(calculation_date, calendar, volatility, day_count))
bs_process = ql.BlackScholesProcess(spot_handle,flat_ts, flat_vol_ts)
payoff = ql.PlainVanillaPayoff(option_type, strike_price)
settlement = calculation_date
am_exercise = ql.AmericanExercise(settlement, maturity_date)
american_option = ql.DividendVanillaOption(payoff, am_exercise, dividenddates, dividends)
engine = ql.FDDividendAmericanEngine(bs_process)
# engine = ql.FDDividendAmericanEngine(bs_process, timeSteps=500, gridPoints=500)
american_option.setPricingEngine(engine)

print(american_option.NPV())

I got 11.273456 as option value. However, when I try to change the spot price, or calculation_date and reprice the option, the NPV doesn't seem to change.

I tried:

spot_handle.setValue = 179
print(american_option.NPV())

or

ql.Settings.instance().evaluationDate = calculation_date + 1
print(american_option.NPV())

NPV still gives same value, unless I re-run through the first section code to re-create instrument with new inputs. I thought Quantlib is designed to allow us use the existing instrument to reprice with simply changing one or more inputs, anything I miss here?

Thanks for your help.

$\endgroup$
2
$\begingroup$

Hello fan and welcome to SE! You were very close, there are two small issues with your code:

setValue()

This is a method and not an attribute which value you can updated, so you have to call object.setValue(new_value) instead of object.setValue = new_value

Handles and quotes

The handle is roughly a smart pointer on a pointer, it points on a quote that can change.

As a result, it's not the handle's value that you need to change (and by the way, it doesn't have a setValue() method, you can see it if you call spot_handle.setValue(179)).

What you can change instead is the value of the underlying quote, in this way:

(...)
spot = ql.SimpleQuote(spot_price)
spot_handle = ql.QuoteHandle(spot)
(...)
print(american_option.NPV())
# Returns 11.273456139007127

spot.setValue(179.)
print(american_option.NPV())
# Returns 10.747540028959339

For more on handles:

$\endgroup$
  • $\begingroup$ Thank you very much, it did the trick. I also found this about changing valuation date: stackoverflow.com/questions/41471675/… $\endgroup$ – fan Jan 24 at 0:28
  • $\begingroup$ another issue here, if I have: dividenddates = [ql.Date(2,8,2018), ql.Date(8, 11, 2018)] in the above example, means going ex tomorrow. When I move evaluation date 1 day forward, NPV() gives error "first date (....) cannot be negative" , any hints on this? Is there a better way to handle dividend block as input? Thanks. $\endgroup$ – fan Jan 24 at 2:43
  • $\begingroup$ Hello fan. If it worked for you, then please accept the answer. For your last question, the problem is that the first date in your curve is in the past. You have to set your curve using a reference date that is relative to the calculation date and not a fixed date, e.g: flat_ts = ql.YieldTermStructureHandle(ql.FlatForward(0, calendar, risk_free_rate, day_count)) see here: stackoverflow.com/a/41473711/2699660 $\endgroup$ – byouness Jan 24 at 9:37
  • $\begingroup$ Hi byouness, thanks for your help on this. I have tried to change the curve to the relative date, but still having the same issue, which I think is related to the ex-div date is same as the calculate date, where probably it should not be passed into dividend block as ex-div already happened. $\endgroup$ – fan Jan 29 at 2:17
  • $\begingroup$ In this case, please accept the answer of the first question and open a new one for this point as it is indpendant of the first. Cheers. $\endgroup$ – byouness Jan 29 at 9:18

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.