[R] How to vectorize this function

Lynette Chang momtoom@x @end|ng |rom gm@||@com
Thu Sep 20 23:46:01 CEST 2018


Here are the code and data file. I’m not sure if I put too much unrelated information here. 

My goal is to factor out volatilities from the data. I hope I can get sigV <- impVolC(callM, K, T, F, r), which has five vectors as input, and one vector as output. The length of all those six vectors are the same. However, I got stuck in the nested if-else sentence, as if-condition cannot handle vectors. I rewrite it as you guys suggestions, however, I still have one layer of if-condition. Any thoughts to improve it? Thanks.

Lynette

-------------- next part --------------


df <- read.csv(file = "/S&P500_ETF_Option_0917.csv", header = TRUE, 
               colClasses = c("integer", "character", "numeric", "numeric", "numeric",
                              "character", "numeric", "numeric", "numeric"))

call <- (df$callBid + df$callAsk)/2
put <- (df$putBid + df$putAsk)/2

y <- call - put
A <- cbind(rep(1, dim(df)[1]), -df$Strike)

x <- solve(t(A)%*%A)%*%t(A)%*%y
PVF <- x[1]
disc <- x[2]

S <- 2381



library(timeDate)
# Lets work in your environment:
getRmetricsOptions("myFinCenter")
setRmetricsOptions(myFinCenter = "America/New_York")

# define a sequence of days with  timeSequence 
t1 <- timeSequence(from = "2017-03-16", to = "2017-09-29")

# Define a calendar for your exchange (use an available one as a template, e.g. holidayNYSE) 
# subindex the sequence with isBizday using your calendar as an argument 
holidayNYSE(2017)
isBizday(t1, holidayNYSE())
t2 <- t1[isBizday(t1, holidayNYSE(2017))]

T <- length(t2)/252
q_m <- -log(PVF/S)/T
r_m <- log(disc)/(-T)


polya <- function(x){
  1/2 + sign(x)/2* sqrt(1- exp(-2*x^2/pi))
}
impVolC <- function(callM, K, T, F, r){
  
  y <- log(F/K)
  alpha <- callM/(K*exp(-r*T))
  R <- 2*alpha - exp(y) + 1
  
  A <- (exp((1 - 2/pi)*y) - exp(-(1 - 2/pi)*y))^2
  B <- 4*(exp(2/pi*y) + exp(-2/pi*y)) - 2*exp(-y)*(exp((1-2/pi)*y)+exp(-(1-2/pi)*y))*(exp(2*y) + 1 - R^2)
  C <- exp(-2*y)*(R^2 - (exp(y) -1)^2)*((exp(y) + 1)^2 - R^2)                                                
  
  beta <- (2*C)/(B + sqrt(B^2 + 4*A*C))
  gamma <- -pi/2*log(beta)
  
  if(y >= 0){
    call0 <- K*exp(-r*T)*(exp(y)*polya(sqrt(2*y)) - 0.5)
    sig <- (sqrt(gamma + y)  + ifelse(callM <= call0, -1, 1) * sqrt(gamma - y))/sqrt(T)
  }else{
    call0 <- K*exp(-r*T)*(exp(y)/2 - polya(-sqrt(-2*y)))
    sig <-  (ifelse(callM <= call0, -1, 1)*sqrt(gamma + y)  +  sqrt(gamma - y))/sqrt(T)
  }
  sig
}

F <- PVF*exp(r_m*T)
sigV <- rep(0, length(call))

for(i in 1:length(call)){
  sigV[i] <- impVolC(callM = call[i], K = df$Strike[i], T = T, F = F, r = r_m)  
}


> On Sep 20, 2018, at 1:56 PM, MacQueen, Don <macqueen1 using llnl.gov> wrote:
> 
> In addition to what the other said, if callM is a vector then an expression of the form
>   if (callM <= call0)
> is inappropriate. Objects inside the parentheses of   if()  should have length one. For example,
> 
>> if (1:5 < 3) 'a' else 'b'
> [1] "a"
> Warning message:
> In if (1:5 < 3) "a" else "b" :
>  the condition has length > 1 and only the first element will be used
> 
> 
> instead of what you have:
>         if(callM <= call0){
>           sig <- 1/sqrt(T)*(sqrt(gamma + y) - sqrt(gamma - y))
>         }else{
>           sig <- 1/sqrt(T)*(sqrt(gamma + y) + sqrt(gamma - y))
>        }
> 
> Here are a couple of (untested) possibilities:
> 
>  M.gt.0 <- callM > call0
>  sig <- 1/sqrt(T)*(sqrt(gamma + y) - sqrt(gamma - y))
>  sig[M.gt.0] <- (1/sqrt(T)*(sqrt(gamma + y) + sqrt(gamma - y)))[M.gt.0]
> 
> or
> 
>    sig <- 1/sqrt(T)*(sqrt(gamma + y)  + ifelse(callM <= call0, -1, 1) * sqrt(gamma - y))
> 
> incidentally, I would write
>   sig <- (sqrt(gamma + y) - sqrt(gamma - y))/sqrt(T)
> instead of
>   sig <- 1/sqrt(T)*(sqrt(gamma + y) - sqrt(gamma - y))
> 
> --
> Don MacQueen
> Lawrence Livermore National Laboratory
> 7000 East Ave., L-627
> Livermore, CA 94550
> 925-423-1062
> Lab cell 925-724-7509
> 
> 
> 
> On 9/20/18, 8:08 AM, "R-help on behalf of Lynette Chang" <r-help-bounces using r-project.org on behalf of momtoomax using gmail.com> wrote:
> 
>    Hello everyone,
> 
>         I’ve a function with five input argument and one output number. 
>    	  impVolC <- function(callM, K, T, F, r)
> 
>         I hope this function can take five vectors as input, then return one vector as output. My vectorization ran into problems with the nested if-else operation. As a result, I have to write another for loop to call this function. Can anyone suggest some methods to overcome it? I put my code below, thanks.
> 
>    impVolC <- function(callM, K, T, F, r){
> 
> 
>     if(y >= 0){
>         call0 <- K*exp(-r*T)*(exp(y)*polya(sqrt(2*y)) - 0.5)
>         if(callM <= call0){
>           sig <- 1/sqrt(T)*(sqrt(gamma + y) - sqrt(gamma - y))
>         }else{
>           sig <- 1/sqrt(T)*(sqrt(gamma + y) + sqrt(gamma - y))
>         }
>     }else{
>         call0 <- K*exp(-r*T)*(exp(y)/2 - polya(-sqrt(-2*y)))
>         if(callM <= call0){
>           sig <- 1/sqrt(T)*(-sqrt(gamma + y) + sqrt(gamma - y))
>         }else{
>           sig <- 1/sqrt(T)*(sqrt(gamma + y) + sqrt(gamma - y))
>         }
>     }
>     sig
>    } 
> 
>    for(i in 1:length(call)){
>     sigV[i] <- impVolC(callM = call[i], K = df$Strike[i], T = T, F = F, r = r_m)  
>    }
> 
>    ______________________________________________
>    R-help using r-project.org mailing list -- To UNSUBSCRIBE and more, see
>    https://stat.ethz.ch/mailman/listinfo/r-help
>    PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
>    and provide commented, minimal, self-contained, reproducible code.
> 
> 



More information about the R-help mailing list