Troubleshooting Unbracketed Implied Volatility in American Options
Summary
The document describes a numerical failure when calculating implied volatility for American options with RQuantLib: the solver reports that it cannot bracket a root, even though the user obtains values by entering observations manually. The suggested diagnostic is to compare the exact manual call with the loop inputs, which may reveal a data or argument mismatch.
The response also proposes using a narrower volatility search interval in an alternative R function. An example prices an American option, finds an implied volatility, and checks that volatility by repricing the option. This illustrates how solver bounds and input consistency can affect numerical inversion. The example is not a general fix for every failure: the appropriate interval depends on the option data, and the discussion does not identify the cause in the original dataset or verify the behavior of the specific RQuantLib call.
Key ideas
- An unbracketed-root error means the solver did not find a sign change over its search interval.
- Compare loop inputs with the exact values used in a manual calculation to find discrepancies.
- A narrower volatility interval may help an alternative solver converge.
- Repricing with the inferred volatility can check whether it reproduces the observed option price.
- The example does not establish a universal interval or diagnose the original data issue.
Tags
Full text
# Quantlib: AmericanOption implied volatility / root not bracketed
# Quantlib: AmericanOption implied volatility / root not bracketed
When I apply the americanoptionimpliedvolatility function in the following format:
```
impliedvol_test_v1$IV <- NA
impliedvol_test_v1$`risk free rate` <- as.numeric(impliedvol_test_v1$`risk
free rate`)
for(iRow in seq(1,nrow(impliedvol_test_v1),1)){
typeTMP <- impliedvol_test_v1$type[iRow]
valueTMP <- impliedvol_test_v1$value[iRow]
strikeTMP <- impliedvol_test_v1$strike[iRow]
underlyingTMP <- impliedvol_test_v1$underlying[iRow]
dividendyieldTMP <- impliedvol_test_v1$`Dividend yield`[iRow]
riskfreerateTMP <- impliedvol_test_v1$`risk free rate`[iRow]
maturityTMP <- impliedvol_test_v1$maturity[iRow]
volatilityTMP <- impliedvol_test_v1$volatility[iRow]
impliedvol_test_v1$IV[iRow] <- AmericanOptionImpliedVolatility(typeTMP,
valueTMP,strikeTMP, underlyingTMP, dividendyieldTMP, riskfreerateTMP,
maturityTMP, volatilityTMP)
}
```
I receive the following error: Error in americanOptionImpliedVolatilityEngine(type, value, underlying, :
../../../QuantLib-1.6.2/ql/math/solver1d.hpp:202: In function `QuantLib::Real QuantLib::Solver1D::solve(const F&, QuantLib::Real, QuantLib::Real, QuantLib::Real, QuantLib::Real) const [with F = QuantLib::{anonymous}::PriceError; Impl = QuantLib::Brent; QuantLib::Real = double]': root not bracketed: f[1e-007,4] -> [2.230734e+000,2.306800e+001]
Which is weird since I receive IV values when I plug them in manually.
The dataset looks like:
When I plug in the values manually, I receive values for each row.
Thanks for your help! Ben
## Answer by Enrico Schumann (score 1)
https://quant.stackexchange.com/a/37294
Could you show the exact call that you use when you "plug them in manually"?
Anyway, can you override the bracketing interval in RQuantLib with a tighter range, say 1% to 100%?
```
library("NMOF")
vanillaOptionImpliedVol("american", price = 3.7,
S = 37.39, X = 35,
tau = .1698, q = 0.0654, r = 0.17,
uniroot.control = list(interval = c(0.01, 1)))
## [1] 0.3172167
vanillaOptionAmerican(S = 37.39, X = 35,
tau = .1698, q = 0.0654, r = 0.17,
v = .3173^2)$value
## [1] 3.700333
```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.