简体   繁体   中英

plot_ly won't generate the 3D surface in RStudio

I have this function that won't generate a 3D surface:

black_scholes <- function(S, X, r, sigma, t, optionType, greekType, graphics) {
  # Compute d1 and d2
  d1 <- (log(S/X) + (r + (sigma^2)/2)*t) / (sigma*sqrt(t))
  d2 <- d1 - sigma*sqrt(t)
  
  # Compute greek value
  if (optionType == "call") {
    greek <- switch(greekType,
                    delta = pnorm(d1),
                    gamma = (dnorm(d1))/(S*sigma*sqrt(t)),
                    vega = (S*dnorm(d1)*sqrt(t))/100,
                    theta = (-S*sigma*dnorm(d1))/(2*sqrt(t)) - r*X*exp(-r*t)*pnorm(d2),
                    rho = X*t*exp(-r*t)*pnorm(d2))
  } else if (optionType == "put") {
    greek <- switch(greekType,
                    delta = pnorm(-d1),
                    gamma = (dnorm(d1))/(S*sigma*sqrt(t)),
                    vega = (S*dnorm(d1)*sqrt(t))/100,
                    theta = (-S*sigma*dnorm(d1))/(2*sqrt(t)) + r*X*exp(-r*t)*pnorm(-d2),
                    rho = -X*t*exp(-r*t)*pnorm(-d2))
  }
  
  # Import required library
  library(plotly)
  
  # Plot surface if graphics is TRUE
  if (graphics) {
    Sarray <- seq(from = S-round(0.20*S), to = S + round(0.20*S), by = 0.1)
    Tarray <- seq(from = t*360-round(0.20*t*360), to = t*360 + round(0.20*t*360), by = 1)/360
    
    # Allocate greek_array as a matrix
    greek_array <- matrix(0, nrow = length(Sarray), ncol = length(Tarray))
    
    for (i in (1:length(Sarray))) {
      for(j in (1:length(Tarray))) {
        greek_array[i,j] <- black_scholes(Sarray[i], X, r, sigma, Tarray[j]/365, optionType, greekType, graphics = FALSE)
      }
    }
    
    # Create df using expand.grid
    df <- expand.grid(Sarray = Sarray, Tarray = Tarray)
    df$greek_array <- as.vector(greek_array)
    
    # Use plotly to create an interactive 3D surface plot
    plot_ly(df, x = Sarray, y = Tarray, z = greek_array, type = "surface", colorscale = "Viridis") %>%
      layout(scene = list(xaxis = list(title = "Stock Price"),
                          yaxis = list(title = "Time to expiration"),
                          zaxis = list(title = greekType)))
  }
  return(greek)
}

print(black_scholes(S <- 60, X <- 65, r <- 0.08, sigma <- 0.3, t <- 0.25, optionType = "call", greekType = "delta", graphics = FALSE))

out <- black_scholes(S <- 60, X <- 65, r <- 0.08, sigma <- 0.3, t <- 0.25, optionType = "call", greekType = "delta", graphics = TRUE)


I'm trying to generate a surface only when graphics=TRUE , but despite the code doesn't give me any error, the surface won't appear. Can anyone help me understand what I'm doing wrong?

You need to save your plot and return it as the output of your UDF.

black_scholes <- function(S, X, r, sigma, t, optionType, greekType, graphics) {
  # Compute d1 and d2
  d1 <- (log(S/X) + (r + (sigma^2)/2)*t) / (sigma*sqrt(t))
  d2 <- d1 - sigma*sqrt(t)
  
  # Compute greek value
  if (optionType == "call") {
    greek <- switch(greekType,
                    delta = pnorm(d1),
                    gamma = (dnorm(d1))/(S*sigma*sqrt(t)),
                    vega = (S*dnorm(d1)*sqrt(t))/100,
                    theta = (-S*sigma*dnorm(d1))/(2*sqrt(t)) - r*X*exp(-r*t)*pnorm(d2),
                    rho = X*t*exp(-r*t)*pnorm(d2))
  } else if (optionType == "put") {
    greek <- switch(greekType,
                    delta = pnorm(-d1),
                    gamma = (dnorm(d1))/(S*sigma*sqrt(t)),
                    vega = (S*dnorm(d1)*sqrt(t))/100,
                    theta = (-S*sigma*dnorm(d1))/(2*sqrt(t)) + r*X*exp(-r*t)*pnorm(-d2),
                    rho = -X*t*exp(-r*t)*pnorm(-d2))
  }
  
  # Import required library
  library(plotly)
  
  # Plot surface if graphics is TRUE
  if (graphics) {
    Sarray <- seq(from = S-round(0.20*S), to = S + round(0.20*S), by = 0.1)
    Tarray <- seq(from = t*360-round(0.20*t*360), to = t*360 + round(0.20*t*360), by = 1)/360
    
    # Allocate greek_array as a matrix
    greek_array <- matrix(0, nrow = length(Sarray), ncol = length(Tarray))
    
    for (i in (1:length(Sarray))) {
      for(j in (1:length(Tarray))) {
        greek_array[i,j] <- black_scholes(Sarray[i], X, r, sigma, Tarray[j]/365, optionType, greekType, graphics = FALSE)
      }
    }
    
    # Create df using expand.grid
    df <- expand.grid(Sarray = Sarray, Tarray = Tarray)
    df$greek_array <- as.vector(greek_array)
    
    # Use plotly to create an interactive 3D surface plot
    plot_ly(df, x = Sarray, y = Tarray, z = greek_array, type = "surface", colorscale = "Viridis") %>%
      layout(scene = list(xaxis = list(title = "Stock Price"),
                          yaxis = list(title = "Time to expiration"),
                          zaxis = list(title = greekType))) -> plt
  }
  ifelse(graphics, return(plt), return(greek)) 
  
}
black_scholes(S <- 60, X <- 65, r <- 0.08, sigma <- 0.3, t <- 0.25, 
              optionType = "call", greekType = "delta", graphics = FALSE)

#> [1] 0.3724828
black_scholes(S <- 60, X <- 65, r <- 0.08, sigma <- 0.3, t <- 0.25, 
              optionType = "call", greekType = "delta", graphics = TRUE)

Created on 2022-12-22 by the reprex package (v2.0.1)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM