Estimating Exercise Probability from an Option’s Strike Sensitivity
Summary
This discussion asks how to estimate the exercise probability of the embedded American call in a convertible bond using QuantLib, and distinguishes that probability from delta. It describes approximating the option’s sensitivity to strike, also called dual delta, by repricing at nearby strikes. For a call, the strike derivative is negative; in the European Black–Scholes case, it equals the negative discounted risk-neutral probability of finishing in the money.
The answer proposes reversing the derivative’s sign and multiplying by the discount factor’s inverse to recover an undiscounted probability measure. This relies on the stated European call relationship and is offered as a suggested approach, not a verified QuantLib method for American exercise. The question’s American option and binomial engine add modeling details that the answer does not resolve, and exercise probability depends on model assumptions and the definition of probability being used. The suggested measure should not be treated as interchangeable with delta or as a universal classification rule for convertible bonds.
Key ideas
- Option delta measures sensitivity to the underlying price, while dual delta measures sensitivity to strike.
- A call’s value generally decreases as its strike rises, so its strike derivative is negative.
- For a European Black–Scholes call, the strike derivative relates to a discounted risk-neutral exercise probability.
- Removing the discount factor yields the probability measure proposed in the answer.
- The discussion does not establish that this relationship directly gives an American option’s exercise probability.
Tags
Full text
# Quantlib - exercise probability function?
# Quantlib - exercise probability function?
I am using Quantlib to obtain the option value embedded in a convertible bond. I create an american option as follows:
```
strike_price = redemption / conversion_ratio
option_type = ql.Option.Call
payoff = ql.PlainVanillaPayoff(option_type, strike_price)
settlement = calculation_date
am_exercise = ql.AmericanExercise(settlement, maturity_date)
american_option = ql.VanillaOption(payoff, am_exercise)
flat_vol_ts = ql.BlackVolTermStructureHandle(ql.BlackConstantVol(calculation_date, calendar, volatility, day_count))
bsm_process = ql.BlackScholesMertonProcess(spot_price_handle,
dividend_ts_handle,
yield_ts_handle,
volatility_ts_handle)
binomial_engine = ql.BinomialVanillaEngine(bsm_process, "crr", time_steps)
american_option.setPricingEngine(binomial_engine)
option_position1 = round(american_option.NPV(),4)
delta_position1 = round(american_option.delta(),4)
gamma_position1 = round(american_option.gamma(),4)
```
I want to obtain the exercise probability as this is a measure of how equity or debt like a convertible bond is. (e.g. >60% exercise probability is labelled as equity-like). Is there function within quantlib that will provide me the exercise probability (exercise probability is not the same as the delta)?
Edit 1: Approach of obtaining the equity or debtness of the convertible bond:
Edit 2: I have tried to incorporate a dual delta in code. I calculate the dual delta by retrieving two seperate option values with a slightly different strike price. However, first results show a huge difference between the delta and the dual delta, delta being 2-3x as high, so I must be doing something wrong. Does my code as it currently is makes sense to manually calculate the dual delta?
```
strike_price_up = strike_price + 0.0001
strike_price_down = strike_price - 0.0001
payoff_up = ql.PlainVanillaPayoff(option_type, strike_price_up)
payoff_down = ql.PlainVanillaPayoff(option_type, strike_price_down)
american_option_up = ql.VanillaOption(payoff_up, am_exercise)
flat_vol_ts = ql.BlackVolTermStructureHandle(ql.BlackConstantVol(calculation_date, calendar, volatility, day_count))
bsm_process = ql.BlackScholesMertonProcess(spot_price_handle,
dividend_ts_handle,
yield_ts_handle,
flat_vol_ts)
binomial_engine = ql.BinomialVanillaEngine(bsm_process, "crr", time_steps)
american_option_up.setPricingEngine(binomial_engine)
dd_u = american_option_up.NPV()
american_option_down = ql.VanillaOption(payoff_down, am_exercise)
flat_vol_ts = ql.BlackVolTermStructureHandle(ql.BlackConstantVol(calculation_date, calendar, volatility, day_count))
bsm_process = ql.BlackScholesMertonProcess(spot_price_handle,
dividend_ts_handle,
yield_ts_handle,
flat_vol_ts)
binomial_engine = ql.BinomialVanillaEngine(bsm_process, "crr", time_steps)
american_option_down.setPricingEngine(binomial_engine)
dd_d = american_option_down.NPV()
dualdelta = (dd_d - dd_u)/(2*0.0001)
dualdelta_position1 = round(dualdelta,4)
```
Edit 3: I believe the correct formula should be: `dualdelta = (dd_u - dd_d)/(2*0.0001)`. This returns a negative dual delta..?
## Answer by nbbo2 (score 1)
https://quant.stackexchange.com/a/51663
OK, here is what I think. (But you should ask for advice from others in this forum or elsewhere).
You computed $\frac{dC}{dK}$ (the dual delta) by a discrete approximation. The result is negative and this is correct (it is negative for a Call and Positive for a Put). In the case of a European Call it is given by the formula $-e^{-r T}N(d_2)$. (See here for source).
In the article you cited they are using $N(d_2)$ as the probability of exercise, so it is a different value. We are discounting the probability to the present time, while the article is using the probability itself (without time discounting). Since these convertible bonds are quite long term (eg. 10 years) it makes a difference. (In my work I usually deal with options of about 1 year, so I have not noticed or thought about this problem before. But from now on I will).
What is the solution? After computing the Dual Delta I would (1) change the sign to positive (2) Multiply by $e^{rT}$ to find the future value, i.e. to remove the discount factor $e^{-rT}$ mentioned earlier. So the probability you want is
$$p=-e^{rT}\frac{dC}{dK}$$
(With an interest rate of 2.8% the exp(rT) factor for 10 years is about 1.323).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.