This script below pulls yahoo data via a function in quantmod, then massages the data around to forumalate a 3D graph with RGL library, attached is a ggplot to show the data i'm trying to create a surface with in separate line geoms . the issue is that the 3D graph looks very ugly and cut up because of the limited quantities of points on the front month expirations.. can anyone tell me whats going on here , what i can do to fix this.. do i need to smooth each expiration's line then interpolate.... ?? library(RQuantLib) library(quantmod) library(rgl) library(akima) library(ggplot2) library(plyr) GetIV <- function(type, value, underlying, strike,dividendYield, riskFreeRate, maturity, volatility, timeSteps=150, gridPoints=151) { AmericanOptionImpliedVolatility(type, value, underlying, strike,dividendYield, riskFreeRate, maturity, volatility, timeSteps=150, gridPoints=151)$impliedVol } GetDelta <- function(type, underlying, strike, dividendYield, riskFreeRate, maturity, volatility, timeSteps=150, gridPoints=149, engine="CrankNicolson") { AmericanOption(type,underlying, strike, dividendYield, riskFreeRate, maturity, volatility, timeSteps=150, gridPoints=149, engine="CrankNicolson")$delta } # set what symbol you want vol surface for underlying <- 'GOOG' # set what your volatility forcast or assumption is volforcast <- .25 # Get symbols current price underlying.price <- getQuote(underlying,what=yahooQF("Last Trade (Price Only)"))$Last OC <- getOptionChain(underlying, NULL) #check data head(OC) lputs <- lapply(OC, FUN = function(x) x$puts[grep("[A-Z]\\d{6}[CP]\\d{8}$", rownames(x$puts)), ]) head(lputs) #check for NA values, yahoo returns all NA values sometimes puts <- do.call('rbind', lputs ) #check data head(puts,5) symbols <- as.vector(unlist(lapply(lputs, rownames))) expiries <- unlist(lapply(symbols, FUN = function(x) regmatches(x=x, regexpr('[0-9]{6}', x) ))) puts$maturity <- as.numeric((as.Date(expiries, "%y%m%d") - Sys.Date())/365) puts$IV <- mapply(GetIV, value = puts$Ask, strike = puts$Strike, maturity puts$maturity, MoreArgs= list(type='put', underlying= underlying.price, dividendYield=0, riskFreeRate = 0.01, volatility = volforcast), SIMPLIFY=TRUE) puts$delta <- mapply(GetDelta, strike = puts$Strike, volatility = puts$IV, maturity = puts$maturity, MoreArgs= list(type='put', underlying=underlying.price, dividendYield=0, riskFreeRate = 0.01 ), SIMPLIFY=TRUE) # subset out itm puts puts <- subset(puts, delta < -.09 & delta > -.5 ) expiries.formated <- format(as.Date(levels(factor(expiries)), format '%y%m%d'), "%B %d, %Y") fractionofyear.levels <- levels(factor(puts$maturity)) xyz <- with(puts, interp(x=maturity, y=delta*100, z=IV*100, xo=sort(unique(maturity)), extrap=FALSE )) with(xyz, persp3d(x,y,z, col=heat.colors(length(z))[rank(z)], xlab='maturity', ylab='delta', zlab='IV', main='IV Surface')) putsplot <- ggplot(puts, aes(delta, IV, group = factor(maturity), color factor(maturity))) + labs(x = "Delta", y = "Implied Volatilty", title="Volatility Smile", color = "GooG \nExpiration") + scale_colour_discrete( breaks=c(fractionofyear.levels), labels=c(expiries.formated)) + geom_line() + geom_point() putsplot [[alternative HTML version deleted]]