Skip to content
All library documents

Diagnosing NA Values in an Implied Volatility Bisection Loop

Article Quant Q&A · Author: Edgar S Martinez

Summary

The document presents an R routine that estimates SPX option implied volatility by repeatedly applying the Black–Scholes formula and narrowing a volatility bracket. Its failure occurs when the while-loop condition evaluates to a missing value rather than TRUE or FALSE. The replies recommend inspecting the error and loop variables, and point to a numerical source: a zero volatility input can make the Black–Scholes calculation produce NaN through division by zero, which then propagates into the loop condition.

The discussion also suggests using QuantLib’s built-in implied-volatility function instead of a custom solver. It offers practical debugging clues, but does not establish which value in the supplied dataset triggers the failure or fully validate the bisection implementation. In particular, a robust solver needs valid option prices and a bracket that actually contains a solution; merely adjusting condition parentheses will not resolve missing or non-finite inputs.

Key ideas

  • A while-loop condition must evaluate to TRUE or FALSE, so NA or NaN values cause this error.
  • A zero volatility input can make the Black–Scholes calculation divide by zero and return a non-finite value.
  • Inspecting intermediate error and iteration values can help locate where invalid results enter the solver.
  • A library-provided implied-volatility routine may be an alternative to custom bisection code.
  • The replies do not identify the exact problematic row or confirm that the bisection bounds are valid.

Tags

Full text
# Error message in calculation Implied Volatility


# Error message in calculation Implied Volatility












I am unsuccessfully trying to find the Implied Volatilities for the SPX on a given date using information of the CBOE, as well as Open Interest, but as I run the code I am getting and error message that I cannot resolve.

```
> ## library(RQuantLib)
> library(RQuantLib)
Loading required package: Rcpp
> ## library(Rcpp)
> library(Rcpp)
> ## Black-Scholes Function
> BS <-
+ function(S, K, T, r, sig, type="C"){
+    d1 <- (log(S/K) + (r + sig^2/2)*T) / (sig*sqrt(T))
+    d2 <- d1 - sig*sqrt(T)
+    if(type=="C"){
+      value <- S*pnorm(d1) - K*exp(-r*T)*pnorm(d2)
+    }
+    if(type=="P"){
+      value <- K*exp(-r*T)*pnorm(-d2) - S*pnorm(-d1)
+    }
+    return(value)
+  }
> ## Function to find BS Implied Vol using Bisection Method
> implied.vol <-
+  function(S, K, T, r, market, type){
+    sig <- 0.20
+    sig.up <- 1
+    sig.down <- 0.001
+    count <- 0
+    err <- BS(S, K, T, r, sig, type) - market   
+    ## repeat until error is sufficiently small or counter hits 1000
+    while(abs(err) > 0.00001 && count<1000){
+      if(err < 0){
+        sig.down <- sig
+        sig <- (sig.up + sig)/2
+      }else{
+        sig.up <- sig
+        sig <- (sig.down + sig)/2
+      }
+      err <- BS(S, K, T, r, sig, type) - market
+      count <- count + 1
+    }  
+    ## return NA if counter hit 1000
+    if(count==1000){
+      return(NA)
+    }else{
+      return(sig)
+    }
+  }
> ## read in data
> dat <- read.csv('C:/Users/Edgar Martinez/Downloads/SPX_data.csv')
> ## read in data
> dat <- read.csv('C:/Users/Edgar Martinez/Downloads/SPX_data.csv')
> ## calculate implied vol for Call
>  S <- 1841.36
>  T <- 20/365
>  r <- 0.01  
>  n <- dim(dat)[1]
>  c.vol.Ask <- rep(0,n)
>  c.vol.Bid <- rep(0,n)
>  p.vol.Ask <- rep(0,n)
> p.vol.Bid <- rep(0,n)
> for(i in 1:n){
+    c.vol.Ask[i] <- implied.vol(S, dat$K[i], T, r, dat$C.Ask[i], "C")
+    c.vol.Bid[i] <- implied.vol(S, dat$K[i], T, r, dat$C.Bid[i], "C")
+    p.vol.Ask[i] <- implied.vol(S, dat$K[i], T, r, dat$P.Ask[i], "P")
+    p.vol.Bid[i] <- implied.vol(S, dat$K[i], T, r, dat$P.Bid[i], "P")
+  }

**Error in while (abs(err) > 1e-05 && count < 1000) { : 
  missing value where TRUE/FALSE needed**
```

## Answer by Enrico Schumann (score 1)

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

In a while loop, the condition expression is evaluated and, if TRUE, the block is executed. The error tells you that the condition in the loop did not evaluate to TRUE or FALSE, but to NA. So check how you define/compute 'count' and 'err'.

## Answer by aajajim (score 1)

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

Try to put some parenthesis to your condition, i experienced many issues liked to this in the past.

```
+    while( (abs(err) > 0.00001) && (count < 1000) ){
```

## Answer by Richi Wa (score 0)

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

I see two ways:

- Could you use ` EuropeanOptionImpliedVolatility ` which is contained in RQuantLib ?

- use the `print ` command and look at the values for count and err in each iteration. For a simple example look at this ` c = 1; print(paste("Hallo:",c)); `

## Answer by Joshua Ulrich (score 0)

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

If `sig==0`, then `BS` returns `NaN` because of dividing by zero on this line:

```
d1 <- (log(S/K) + (r + sig^2/2)*T) / (sig*sqrt(T))
```

That then causes `err` to be `NaN`.

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.