3

I have a data.frame that I am currently applying a for loop to in order to get my desired outcome. However, I am not happy with using a for loop and seem to run into weird errors every once in awhile. I am looping over each row and calculating the greeks of an option given the values in each row. There is also an "if else" statement that decides if i use the put option formula or call option formula

Here is what I am currently using to get the desired output. I was hoping there would be a cleaner way to do this using map() or some other function. Thanks

library(tidyverse)
library(derivmkts)


df = structure(list(pc = c("C", "P", "C", "P", "C", "P", "C", "P", 
"C", "P"), spot = c(100, 100, 100, 100, 100, 100, 100, 100, 100, 
100), Strike = c(98, 98, 98, 98, 98, 98, 98, 98, 98, 98), iv = c(0.3, 
0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3), dte = c(10, 10, 
10, 10, 10, 10, 10, 10, 10, 10)), class = "data.frame", row.names = c(NA, 
-10L))

head(df)
 pc spot Strike  iv dte
1   C  100     98 0.3  10
2   P  100     98 0.3  10
3   C  100     98 0.3  10
4   P  100     98 0.3  10
5   C  100     98 0.3  10

#if the pc value is "P" use bsput() otherwise use bscall()
#create list

l = list()
for(i in 1:nrow(df)){
  
  if(df$pc[i] == "P"){
    l[[i]] = greeks(bsput(df$spot[i], df$Strike[i], df$iv[i], 0, df$dte[1]/252, 0), complete = T)
  } else {
    l[[i]] = greeks(bscall(df$spot[i], df$Strike[i], df$iv[i], 0, df$dte[1]/252, 0), complete = T)
  }
  
  
}

l = do.call(rbind, l)
head(l)
 s  k   v r         tt d funcname  Premium      Delta       Vega         Rho      Theta         Psi     Elast      Gamma
1 100 98 0.3 0 0.03968254 0   bscall 3.493478  0.6435398 0.07426992  0.02415099 -0.0769152 -0.02553729  18.42118 0.06238675
2 100 98 0.3 0 0.03968254 0    bsput 1.493478 -0.3564602 0.07426992 -0.01473790 -0.0769152  0.01414525 -23.86780 0.06238672
3 100 98 0.3 0 0.03968254 0   bscall 3.493478  0.6435398 0.07426992  0.02415099 -0.0769152 -0.02553729  18.42118 0.06238675
4 100 98 0.3 0 0.03968254 0    bsput 1.493478 -0.3564602 0.07426992 -0.01473790 -0.0769152  0.01414525 -23.86780 0.06238672
5 100 98 0.3 0 0.03968254 0   bscall 3.493478  0.6435398 0.07426992  0.02415099 -0.0769152 -0.02553729  18.42118 0.06238675
6 100 98 0.3 0 0.03968254 0    bsput 1.493478 -0.3564602 0.07426992 -0.01473790 -0.0769152  0.01414525 -23.86780 0.06238672

I am having a hard time breaking away from a for loop in this situation and would appreciate some help. Thank you kindly

2
  • Do you know why greeks(bsput(100, 98, 0.3, 0, 0.03968, 0), complete = T) works but greeks(1.493406, complete = TRUE) doesn't? Where 1.493406 is output of bsput(100, 98, 0.3, 0, 0.03968, 0) Commented Feb 9, 2021 at 7:37
  • 2
    @RonakShah It looks like greeks() doesn't actually use the value of f, it uses non-standard evaluation on the function call itself. This does make it harder to use within a functional. Commented Feb 9, 2021 at 7:46

1 Answer 1

2

In R, when you need repeat a calculation on each row in a data.frame - and the calculation does not depend on the preceding/succeeding row, you should do it with vectorization. Looking up greeks, it tells us that is supports vectorization.

But, with your if-else setup, you need to do a bit of subsetting. The biggest issue is preserving order:

df$i <- 1:nrow(df)

dte1 <- df$dte[1]/252
df <- df[order(df$pc),]
rows <- df$pc == 'C'

greeks.C <- greeks(bsput(df$spot[rows], df$Strike[rows], df$iv[rows], 0, dte1, 0), complete=T)
greeks.C$i <- df$i[rows]
rows <- df$pc == 'P'
greeks.P <- greeks(bscall(df$spot[rows], df$Strike[rows], df$iv[rows], 0, dte1, 0), complete=T)
greeks.P$i <- df$i[rows]

result <- rbind(greeks.C, greeks.P)
result[order(result$i),]

     s  k   v r         tt d funcname  Premium      Delta       Vega         Rho      Theta         Psi     Elast      Gamma  i
1  100 98 0.3 0 0.03968254 0    bsput 1.493478 -0.3564602 0.07426992 -0.01473790 -0.0769152  0.01414525 -23.86780 0.06238672  1
6  100 98 0.3 0 0.03968254 0   bscall 3.493478  0.6435398 0.07426992  0.02415099 -0.0769152 -0.02553729  18.42118 0.06238675  2
2  100 98 0.3 0 0.03968254 0    bsput 1.493478 -0.3564602 0.07426992 -0.01473790 -0.0769152  0.01414525 -23.86780 0.06238672  3
7  100 98 0.3 0 0.03968254 0   bscall 3.493478  0.6435398 0.07426992  0.02415099 -0.0769152 -0.02553729  18.42118 0.06238675  4
3  100 98 0.3 0 0.03968254 0    bsput 1.493478 -0.3564602 0.07426992 -0.01473790 -0.0769152  0.01414525 -23.86780 0.06238672  5
8  100 98 0.3 0 0.03968254 0   bscall 3.493478  0.6435398 0.07426992  0.02415099 -0.0769152 -0.02553729  18.42118 0.06238675  6
4  100 98 0.3 0 0.03968254 0    bsput 1.493478 -0.3564602 0.07426992 -0.01473790 -0.0769152  0.01414525 -23.86780 0.06238672  7
9  100 98 0.3 0 0.03968254 0   bscall 3.493478  0.6435398 0.07426992  0.02415099 -0.0769152 -0.02553729  18.42118 0.06238675  8
5  100 98 0.3 0 0.03968254 0    bsput 1.493478 -0.3564602 0.07426992 -0.01473790 -0.0769152  0.01414525 -23.86780 0.06238672  9
10 100 98 0.3 0 0.03968254 0   bscall 3.493478  0.6435398 0.07426992  0.02415099 -0.0769152 -0.02553729  18.42118 0.06238675 10
Sign up to request clarification or add additional context in comments.

1 Comment

brilliant! Thanks @MrGumble

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.