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?