0

Im trying to create my very own first project in R but have hit a roadblock.

I have a data frame such as below where every row represents dataset of a financial option.

type <- c("C", "C")
marketV <- c(1.1166, 1.911)
S <- c(20, 60)
K <- c(20, 56)
T <- c(0.333, 0.5)
df <- data.frame(type, marketV, S, K, T)

I made a user defined function to take this data frame as an input and works great when the data frame is one row long. However, I'm not sure how to have my function iterate through all the data frame rows and produce a result for all of them.

I'm new to R so I'm unsure whether I should be running a 'for' loop around or playing around with lapply, or if theres a simple syntax answer. I simply want the function to take the df as input, but repeat its calculation for n row, and produce n results. Thank you for the help in advance.

My current function code for a df with 1 row below as reference:

3
  • lapply(df,IV) ? Commented Jan 26, 2017 at 13:14
  • You are not defining your arguments in the right way. You need to think about what you input in your function (atm it looks like you want to input the whole dataset) and how this input should be used inside the function. R does not know that the S, K and T inside your function are variables of the input. I did not look over the whole function, but maybe try to insert attach(df) at the beginning of your function and then call IV(yourdf). Commented Jan 26, 2017 at 13:26
  • Thanks @jogo, you are right. This won't work. Commented Jan 26, 2017 at 13:33

1 Answer 1

2

This is a corrected version of your program:

df <- data.frame(type=c("C", "C"), marketV=c(1.1166, 1.911), S=c(20, 60), K=c(20, 56), T=c(0.333, 0.5))

IV <- function(df) {
  # check if df has more then 1 row:
  if (nrow(df)>1) { message("!! nrow(df)>1 !!");  return(NA) }

  # Initializing of variables
  r <- 0
  sigma <- 0.3
  sigma_down <- 0.001
  sigma_up <- 1
  count <- 0

  type <- df$type; marketV <- df$marketV; S <- df$S; K <- df$K; T <- df$T

  d1 <- (log(S/K) + (sigma^2/2)*T)/(sigma*sqrt(T))
  d2 <- (log(S/K) - (sigma^2/2)*T)/(sigma*sqrt(T))

  if(type=="C") {
    V <- exp(-r*T)*(S*pnorm(d1) - K*pnorm(d2))
  } else {
    V <- exp(-r*T)*(K*pnorm(-d2) - S*pnorm(-d1)) }

  difference <- V - marketV

  # Root finding of sigma by Bisection method
  while(abs(difference)>0.001 && count<1000) {
    if(difference < 0) {
      sigma_down <- sigma
      sigma <- (sigma_up + sigma)/2 
    } else {
      sigma_up <- sigma
      sigma <- (sigma_down + sigma)/2
    }

    d1 <- (log(S/K) + (sigma^2/2)*T)/(sigma*sqrt(T))
    d2 <- d1 - sigma*sqrt(T)

    if(type=="C") {
      V <- exp(-r*T)*(S*pnorm(d1) - K*pnorm(d2))
    } else {
      V <- exp(-r*T)*(K*pnorm(-d2) - S*pnorm(-d1)) }

    difference <- V - marketV
    count <- count + 1
  }
  if(count == 1000){
    return(NA)          # If sigma to satisfy Black76 price cannot be found
  } else{
    return(sigma)
  }
}

sapply(split(df, seq(nrow(df))), IV)

The main thing is to run row by row through the dataframe. This is done by

sapply(split(df, seq(nrow(df))), IV)

In your original function are many errors: the biggest is accessing to S, K and so on. You might thinking taking the values from the dataframe df. But in fact you were taking the values from the workspace! I corrected this by redefining:

type <- df$type; marketV <- df$marketV; S <- df$S; K <- df$K; T <- df$T

I inserted a test for the number of rows in df, so you will get:

> IV(df)
!! nrow(df)>1 !!
[1] NA

Here is a cleaned up version of your program:

df <- data.frame(type=c("C", "C"), marketV=c(1.1166, 1.911), S=c(20, 60), K=c(20, 56), T=c(0.333, 0.5))

IV2 <- function(type, marketV, S, K, T) {
  r <- 0; sigma <- 0.3
  sigma_down <- 0.001; sigma_up <- 1
  count <- 0

  if(type=="C") {
    f.sig <- function(sigma)  {
      d1 <- (log(S/K) + (sigma^2/2)*T)/(sigma*sqrt(T))
      d2 <- d1 - sigma*sqrt(T)
      exp(-r*T)*(S*pnorm(d1) - K*pnorm(d2)) - marketV
    } 
  } else {
    f.sig <- function(sigma)  {
      d1 <- (log(S/K) + (sigma^2/2)*T)/(sigma*sqrt(T))
      d2 <- d1 - sigma*sqrt(T)
      exp(-r*T)*(K*pnorm(-d2) - S*pnorm(-d1)) - marketV
    }
  }
  ifelse(f.sig(sigma_down)*f.sig(sigma_up) < 0, uniroot(f.sig, c(sigma_down,sigma_up))$root, NA) # sigma
}

sapply(split(df, seq(nrow(df))), do.call, what="IV2")
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

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