3

Solution Found

I am trying to plot a volatility surface using "persp" in R. To do so I need to fill a matrix, z, with implied volatilities.

I have a data frame of the strike prices, time and market prices. Data only contains call options.

    AAPL <- #data
    df <- data.frame(AAPL$Strike.Price,AAPL$Time.Left,AAPL$Market.Price)

I currently have a matrix, zz, that has stock prices in the first column, times as the headers and the respective market prices in columns 2, 3 and 4. It is important to note that some values of the market prices are missing (NA).

    zz <- cast(df, df.Strike.Price ~ df.Time.Left)

For my x, y axis, I define the vectors:

    x0 <- zz$df.Strike.Price  #Strike prices for calculation of imp. vol.
    x <- zz$df.Strike.Price / 153.06  #Axis for plotting
    y <- c(time1, time2, time3) 

Now the z matrix for plotting implied volatility. I start with an empty matrix

    z = matrix(data=NA,nrow=length(x0),ncol=length(y))

Then I attempt to fill the matrix, leaving NA for values that cannot be calculated

    for(i in 1:length(x0)){
        for(j in 1:length(y)){
            #Formula for Black-Scholes call option price (no dividends)
            BS = function(X,T,sigma){
                #Parameters
                S=153.06; r=0.05 #Stock value is same for all options, r is arbitrarily selected to be some constant.

                d1 = (log(S/X) + (r + sigma^2/2)*T) / (sigma*sqrt(T))
                d2 = d1 - sigma*sqrt(T)

                #Price for call options
                price = S*pnorm(d1) - X*exp(-r*T)*pnorm(d2)
                return(price)
            }

            #To address NA entries in zz
            if(is.na(zz[i,j+1] == TRUE)){  
                z[i,j] = NA
            }

            #This is the part of the code that causes issues
            else{
                #Function for fsolve, the Black-Scholes price minus the market price.
                A = function(sigma){
                    a = BS(x0[i], y[j], sigma) - zz[i,j+1]
                    return(a)
                }

            V = fsolve(A, 0.5) #Should give me the implied volatility from market data.
            z[i,j] = V
            }
        }
    }

Upon executing this piece of code I get the error message:

Error in if (norm(s, "F") < tol || norm(as.matrix(ynew), "F") < tol) break : missing value where TRUE/FALSE needed

I'm not sure what the error is about. Is there a way to overcome this problem or an alternative method to getting the implied volatilities instead of using fsolve?

R. Lad
  • 73
  • 1
  • 5

1 Answers1

1

The error is to do with the changes in sigma becoming too small for the function fsolve. I was able to find another function that could solve non-linear equations and used that instead.

The function was nleqslv from a package of the same name nleqslv.

R. Lad
  • 73
  • 1
  • 5