Как использовать uniroot для решения пользовательской функции (UDF) во фрейме данных?

#r #dataframe #user-defined-functions

#r #фрейм данных #определяемые пользователем функции

Вопрос:

У меня есть фрейм данных, и я хочу использовать uniroot в каждой строке для решения подразумеваемой волатильности на основе формулы Блэка-Шоулза. Как правильно использовать uniroot.все, что нужно решить для каждой строки? Это должно привести к созданию нового векторного столбца результатов.

Приведенный ниже код содержит эту ошибку

«Ошибка в S / K: нечисловой аргумент двоичного оператора»

. Я подозреваю, что проблема возникает, когда uniroot пытается решить несколько строк вместо каждой строки по одной.

Я пытался изменить векторизованную версию функции bscall, но, похоже, это не лучший способ сделать это.

 df <- data.frame( strike = c(80,120,100,100), 
                  type = c("C", "C", "C","C"),
                  optionPrice = c(22,3,7,9),
                  futurePrice = c(100, 100,100,100),
                  time_to_expiry = c(0.1, 0.1,1,1.2))

bscall <-
  function (S,K,r,T,sig) {
    d1 <- (log(S/K) (r 0.5*sig^2)*T) / (sig*sqrt(T)) 
    d2 <- d1 - sig*sqrt(T)
    price <- S*pnorm(d1) - K*exp(-r*T)*pnorm(d2)
    return(price)
  }


apply(df, 1,
      function(z) uniroot.all( function(x) bscall(z[4],z[1],r,z[5],x) - z[3], interval = c(0,1) ))
  

Ответ №1:

Первая строка df является 80, "C", 22, 100, 0.1 . Он содержит символьную строку. Поэтому, когда вы это делаете apply(df, 1, ....) , строки преобразуются в символьные векторы:

 df <- data.frame( strike = c(80,120,100,100), 
                  type = c("C", "C", "C","C"),
                  optionPrice = c(22,3,7,9),
                  futurePrice = c(100, 100,100,100),
                  time_to_expiry = c(0.1, 0.1,1,1.2))

apply(df, 1, function(z) z)
#                [,1]  [,2]  [,3]  [,4] 
# strike         " 80" "120" "100" "100"
# type           "C"   "C"   "C"   "C"  
# optionPrice    "22"  " 3"  " 7"  " 9" 
# futurePrice    "100" "100" "100" "100"
# time_to_expiry "0.1" "0.1" "1.0" "1.2"
  

Ответ №2:

Во-первых: вы должны включить library инструкцию, которую вы использовали для package rootSolve . Где определены переменные r и sig ?

В этом нет необходимости, uniroot.all как вы можете видеть, проверив функцию bscall . Нет необходимости в итерации; price вычисляется непосредственно из входных данных.

Определите df следующим образом, принимая во внимание первый ответ.

 df <- data.frame( strike = c(80,120,100,100), 
                  # type = c("C", "C", "C","C"),
                  optionPrice = c(22,3,7,9),
                  futurePrice = c(100, 100,100,100),
                  time_to_expiry = c(0.1, 0.1,1,1.2))
  

Столбец type был закомментирован.

Определите свою функцию bscall как

 bscall <-
  function (S,K,r,T,sig) {
  d1 <- (log(S/K) (r 0.5*sig^2)*T) / (sig*sqrt(T)) 
  d2 <- d1 - sig*sqrt(T)
  price <- S*pnorm(d1) - K*exp(-r*T)*pnorm(d2)
  return(price)
}
  

Укажите r и sig значение

 r <- .05
sig <- 1
  

Примените вашу функцию к строкам df (индексы в z изменены из-за изменения в df )

 apply(df, 1,
   function(z) bscall(z[3],z[1],r,z[4],sig) - z[2])
  

предоставление

 [1]  2.258107  3.168623 32.840162 34.366636
  

в качестве ответа.

Остальное зависит от вас.