【问题标题】:How to loop optim over a dataframe in R如何在R中的数据帧上循环优化
【发布时间】:2021-12-07 10:12:27
【问题描述】:

我正在努力将优化函数 optim 循环到我的整个数据帧。 下面你可以找到我的代码的一部分,当我使用标量作为 Strike09 = 1142.757 时,我的优化问题有效,但现在我想在我的整个数据集上解决这个优化问题,其中 Strike09、Strike095、...、blackscholesc11 是数据集,我想为数据集的每一行(对应于日期)优化我的函数的 5 个参数。

下面要优化的函数和使用标量作为硬参数时的工作优化问题示例

error_vector_price <- function(Strike09, Strike095, Strike1, Strike105, Strike11, Liborrate, par_x, TimetoMaturity, SPX, blackscholesc09, blackscholesc095, blackscholesc1, blackscholesc105, blackscholesc11){
  
MixtureCall <- function(Strike, Liborrate, par_x, TimetoMaturity, SPX){
  
  alpha1 = log(SPX) + (par_x[2]-0.5*(par_x[4]^2)*(par_x[4]^2))*TimetoMaturity
  alpha2 = log(SPX) + (par_x[3]-0.5*(par_x[5]^2)*(par_x[5]^2))*TimetoMaturity
  beta1 = (par_x[4]^2)*(TimetoMaturity^0.5)
  beta2 = (par_x[5]^2)*(TimetoMaturity^0.5)
  theta = (par_x[1]^2)/(1+par_x[1]^2)
  
  D1 = (-log(Strike) + alpha1 + (beta1 ^ 2)) / beta1
  D2 = D1 - beta1
  D3 = (-log(Strike) + alpha2 + (beta2 ^ 2)) / beta2
  D4 = D3 - beta2
  nD1 = sapply(D1,  function(x) pnorm(x))
  nD2 = sapply(D2,  function(x) pnorm(x))
  nD3 = sapply(D3,  function(x) pnorm(x))
  nD4 = sapply(D4,  function(x) pnorm(x))
  
  call1 = exp(alpha1 + beta1 * beta1 / 2) * nD1 - Strike * nD2
  call2 = exp(alpha2 + beta2 * beta2 / 2) * nD3 - Strike * nD4
    
  InstRate = (log(1 + Liborrate * TimetoMaturity)) / TimetoMaturity
    
  Mixturecall = exp(-InstRate * TimetoMaturity) * (theta * call1 + (1 - theta) * call2)
  
  return(Mixturecall)
}

MixturePut <- function(Strike, Liborrate, par_x, TimetoMaturity, SPX){
  
  alpha1 = log(SPX) + (par_x[2]-0.5*(par_x[4]^2)*(par_x[4]^2))*TimetoMaturity
  alpha2 = log(SPX) + (par_x[3]-0.5*(par_x[5]^2)*(par_x[5]^2))*TimetoMaturity
  beta1 = (par_x[4]^2)*(TimetoMaturity^0.5)
  beta2 = (par_x[5]^2)*(TimetoMaturity^0.5)
  theta = (par_x[1]^2)/(1+par_x[1]^2)
  
  D1 = (-log(Strike) + alpha1 + (beta1 ^ 2)) / beta1
  D2 = D1 - beta1
  D3 = (-log(Strike) + alpha2 + (beta2 ^ 2)) / beta2
  D4 = D3 - beta2
  nD1 = sapply(D1, function(x) pnorm(x))
  nD2 = sapply(D2, function(x) pnorm(x))
  nD3 = sapply(D3, function(x) pnorm(x))
  nD4 = sapply(D4, function(x) pnorm(x))
  
  call1 = exp(alpha1 + beta1 * beta1 / 2) * nD1 - Strike * nD2
  call2 = exp(alpha2 + beta2 * beta2 / 2) * nD3 - Strike * nD4
    
  InstRate = (log(1 + Liborrate * TimetoMaturity)) / TimetoMaturity
    
  Mixturecall = exp(-InstRate * TimetoMaturity) * (theta * call1 + (1 - theta) * call2)
  
  fwdprice = theta * exp(alpha1 + beta1 * beta1 / 2) + (1 - theta) * exp(alpha2 + beta2 * beta2 / 2)
  
  Mixtureput = Mixturecall + (Strike - fwdprice) / (1 + Liborrate * TimetoMaturity)
  
  return(Mixtureput)
}

model_price_vector09 <- MixturePut(Strike09, Liborrate, par_x, TimetoMaturity, SPX)
model_price_vector095 <- MixturePut(Strike095, Liborrate, par_x, TimetoMaturity, SPX)
model_price_vector1 <- MixturePut(Strike1, Liborrate, par_x, TimetoMaturity, SPX)
model_price_vector105 <- MixtureCall(Strike105, Liborrate, par_x, TimetoMaturity, SPX)
model_price_vector11 <- MixtureCall(Strike11, Liborrate, par_x, TimetoMaturity, SPX)

error_vector_price <- (((blackscholesc09 - model_price_vector09)^2+(blackscholesc095 - model_price_vector095)^2+(blackscholesc1 - model_price_vector1)^2+(blackscholesc105 - model_price_vector105)^2+(blackscholesc11 - model_price_vector11)^2))

return(error_vector_price)
}

x_seed <- c(0.64,-0.57,0.25,0.53,0.36)

results <- optim( x_seed , fn = error_vector_price, gr = NULL,  Strike09 = 1142.757, Strike095 = 1206.2435, Strike1 = 1269.73, Strike105 = 1333.216, Strike11 = 1396.703, Liborrate = 0.0505750, TimetoMaturity = 0.25, SPX = 1269.73, blackscholesc09=24.995126, blackscholesc095=37.78425, blackscholesc1=57.87691, blackscholesc105=33.47135, blackscholesc11=12.671979, method = "L-BFGS-B", upper = (1))

x_star <- results$par
x_star

我现在想在我的数据集上循环这个优化问题,并为每一行获取 5 个参数来最小化我的函数。 我的数据集由 13 个变量的 152 个 obs 组成,这 13 个变量是我的优化问题的硬参数(Strike09、Strike095、Strike1、Strike105、Strike11、Liborrate、TimetoMaturity、SPX、blackscholesc09、blackscholesc095、blackscholesc1、blackscholesc105、blackscholesc11)。 这个想法如下所示,但随后的循环不起作用,我不确定循环是否是最好的方法

MIN_DATA1 =data.frame(Strike09 <-  c (1142.757, 1090.971, 1111.644, 1138.833), Strike095 <- c (1206.2435, 1151.5805,1173.4020, 1202.1015), Strike1 <- c (1269.73, 1212.19, 1235.16, 1265.37),Strike105 <- c (1333.216, 1272.800, 1296.918, 1328.639), Strike11 <- c (1396.703,1333.409, 1358.676, 1391.907), Liborrate <- c (0.0505750, 0.0500500, 0.0497078, 0.0496969), TimetoMaturity <- c (0.25, 0.25, 0.25, 0.25), SPX <- c (1269.73, 1212.19, 1235.16, 1265.37), blackscholesc09 <- c(24.995126, 34.905765, 32.103535, 29.686353), blackscholesc095 <- c(37.78425, 50.31239, 45.41761, 43.50957), blackscholesc1 <- c(57.87691, 69.78892, 65.36423, 64.41497), blackscholesc105 <- c(33.47135, 44.10261, 44.12110, 41.11879), blackscholesc11<- c(12.671979, 21.055396, 21.175705, 18.883918))
for (i in 1:length(MIN_DATA)){
results[i] <- optim( x_seed , fn = error_vector_price, gr = NULL,  Strike09[i], Strike095[i], Strike1[i], Strike105[i], Strike11[i], Liborrate[i], TimetoMaturity[h], SPX[i], blackscholesc09[i], blackscholesc095[i], blackscholesc1[i], blackscholesc105[i], blackscholesc11[i], method = "L-BFGS-B", upper = (0.9))
}

results

我希望我的问题足够清楚。

【问题讨论】:

  • 请提供一个可重复的示例,以便您最大限度地获得帮助:How to make a great R reproducible example
  • 您可以通过嵌套来完成此操作,然后使用purrr::map2mapply(以一种简单的方式)。我们无能为力,因为您没有为我们提供最小的可重现示例。但是请查看tidyr::nest
  • @Mossa,感谢您的评论。我试图添加一个可重现的示例,因为您的建议的最终实施对我来说不是 100% 清楚。再次感谢您。

标签: r loops optimization


【解决方案1】:

好的,所以答案是:

results <- vector("list", length = nrow(MIN_DATA1))
with(MIN_DATA1,
     for (i in seq_len(nrow(MIN_DATA1))) {
       results[[i]] <<-
         optim(
           x_seed,
           fn = error_vector_price,
           gr = NULL,
           Strike09 = Strike09[i],
           Strike095 = Strike095[i],
           Strike1 = Strike1[i],
           Strike105 = Strike105[i],
           Strike11 = Strike11[i],
           Liborrate = Liborrate[i],
           TimetoMaturity = TimetoMaturity[i],
           SPX = SPX[i],
           blackscholesc09 = blackscholesc09[i],
           blackscholesc095 = blackscholesc095[i],
           blackscholesc1 = blackscholesc1[i],
           blackscholesc105 = blackscholesc105[i],
           blackscholesc11 = blackscholesc11[i],
           method = "L-BFGS-B",
           upper = (0.9)
         )
     }
)

但是有很多东西可以用你的脚本来调整。我做了一些更改,并将它们粘贴在这里

#' This comes from [SO](https://stackoverflow.com/questions/69648537/how-to-loop-optim-over-a-dataframe-in-r?noredirect=1#comment123111774_69648537)
#'
#'
#'

x_seed <- c(0.64,-0.57,0.25,0.53,0.36)


MIN_DATA1 <-  data.frame(
  Strike09 =
    c(1142.757, 1090.971, 1111.644, 1138.833),
  Strike095 =
    c(1206.2435, 1151.5805, 1173.4020, 1202.1015),
  Strike1 =
    c(1269.73, 1212.19, 1235.16, 1265.37),
  Strike105 =
    c(1333.216, 1272.800, 1296.918, 1328.639),
  Strike11 =
    c(1396.703, 1333.409, 1358.676, 1391.907),
  Liborrate =
    c(0.0505750, 0.0500500, 0.0497078, 0.0496969),
  TimetoMaturity =
    c(0.25, 0.25, 0.25, 0.25),
  SPX =
    c(1269.73, 1212.19, 1235.16, 1265.37),
  blackscholesc09 =
    c(24.995126, 34.905765, 32.103535, 29.686353),
  blackscholesc095 =
    c(37.78425, 50.31239, 45.41761, 43.50957),
  blackscholesc1 =
    c(57.87691, 69.78892, 65.36423, 64.41497),
  blackscholesc105 =
    c(33.47135, 44.10261, 44.12110, 41.11879),
  blackscholesc11 = c(12.671979, 21.055396, 21.175705, 18.883918)
)




MixtureCall <- function(Strike, Liborrate, par_x, TimetoMaturity, SPX) {

  alpha1 <- log(SPX) + (par_x[2]-0.5*(par_x[4]^2)*(par_x[4]^2))*TimetoMaturity
  alpha2 <- log(SPX) + (par_x[3]-0.5*(par_x[5]^2)*(par_x[5]^2))*TimetoMaturity
  beta1  <- (par_x[4]^2)*(TimetoMaturity^0.5)
  beta2  <- (par_x[5]^2)*(TimetoMaturity^0.5)
  theta  <- (par_x[1]^2)/(1+par_x[1]^2)

  D1 <- (-log(Strike) + alpha1 + (beta1 ^ 2)) / beta1
  D2 <- D1 - beta1
  D3 <- (-log(Strike) + alpha2 + (beta2 ^ 2)) / beta2
  D4 <- D3 - beta2
  nD1 <- sapply(D1,  function(x) pnorm(x))
  nD2 <- sapply(D2,  function(x) pnorm(x))
  nD3 <- sapply(D3,  function(x) pnorm(x))
  nD4 <- sapply(D4,  function(x) pnorm(x))

  call1 <- exp(alpha1 + beta1 * beta1 / 2) * nD1 - Strike * nD2
  call2 <- exp(alpha2 + beta2 * beta2 / 2) * nD3 - Strike * nD4

  InstRate <- (log(1 + Liborrate * TimetoMaturity)) / TimetoMaturity

  Mixturecall <- exp(-InstRate * TimetoMaturity) * (theta * call1 + (1 - theta) * call2)

  return(Mixturecall)
}

# MixtureCall(Strike105, Liborrate, par_x, TimetoMaturity, SPX)
# MixtureCall(Strike11, Liborrate, par_x, TimetoMaturity, SPX)

# MixtureCall(Strike = MIN_DATA1$Strike105[1],
#             Liborrate = MIN_DATA1$Liborrate[1],
#             par_x = x_seed,
#             TimetoMaturity = MIN_DATA1$TimetoMaturity[1],
#             SPX = MIN_DATA1$SPX[1])
# MixtureCall(Strike = MIN_DATA1$Strike11[1],
#             Liborrate = MIN_DATA1$Liborrate[1],
#             par_x = x_seed,
#             TimetoMaturity = MIN_DATA1$TimetoMaturity[1],
#             SPX = MIN_DATA1$SPX[1])


MixturePut <- function(Strike, Liborrate, par_x, TimetoMaturity, SPX){

  alpha1 = log(SPX) + (par_x[2]-0.5*(par_x[4]^2)*(par_x[4]^2))*TimetoMaturity
  alpha2 = log(SPX) + (par_x[3]-0.5*(par_x[5]^2)*(par_x[5]^2))*TimetoMaturity
  beta1 = (par_x[4]^2)*(TimetoMaturity^0.5)
  beta2 = (par_x[5]^2)*(TimetoMaturity^0.5)
  theta = (par_x[1]^2)/(1+par_x[1]^2)

  D1 = (-log(Strike) + alpha1 + (beta1 ^ 2)) / beta1
  D2 = D1 - beta1
  D3 = (-log(Strike) + alpha2 + (beta2 ^ 2)) / beta2
  D4 = D3 - beta2
  nD1 = sapply(D1, function(x) pnorm(x))
  nD2 = sapply(D2, function(x) pnorm(x))
  nD3 = sapply(D3, function(x) pnorm(x))
  nD4 = sapply(D4, function(x) pnorm(x))

  call1 = exp(alpha1 + beta1 * beta1 / 2) * nD1 - Strike * nD2
  call2 = exp(alpha2 + beta2 * beta2 / 2) * nD3 - Strike * nD4

  InstRate = (log(1 + Liborrate * TimetoMaturity)) / TimetoMaturity

  Mixturecall = exp(-InstRate * TimetoMaturity) * (theta * call1 + (1 - theta) * call2)

  fwdprice = theta * exp(alpha1 + beta1 * beta1 / 2) + (1 - theta) * exp(alpha2 + beta2 * beta2 / 2)

  Mixtureput = Mixturecall + (Strike - fwdprice) / (1 + Liborrate * TimetoMaturity)

  return(Mixtureput)
}


# MixturePut(Strike09, Liborrate, par_x, TimetoMaturity, SPX)
# MixturePut(Strike095, Liborrate, par_x, TimetoMaturity, SPX)
# MixturePut(Strike1, Liborrate, par_x, TimetoMaturity, SPX)
#
# debug(MixturePut)

# MixturePut(Strike = MIN_DATA1$Strike09[1],
#            Liborrate = MIN_DATA1$Liborrate[1],
#            par_x = x_seed,
#            TimetoMaturity = MIN_DATA1[1],
#            SPX = MIN_DATA1$SPX[1])
# MixturePut(Strike = MIN_DATA1$Strike095[1],
#            Liborrate = MIN_DATA1$Liborrate[1],
#            par_x = x_seed,
#            TimetoMaturity = MIN_DATA1[1],
#            SPX = MIN_DATA1$SPX[1])
# MixturePut(Strike = MIN_DATA1$Strike1[1],
#            Liborrate = MIN_DATA1$Liborrate[1],
#            par_x = x_seed,
#            TimetoMaturity = MIN_DATA1[1],
#            SPX = MIN_DATA1$SPX[1])


error_vector_price <- function(Strike09, Strike095,
                               Strike1, Strike105, Strike11,
                               Liborrate, par_x,
                               TimetoMaturity, SPX,
                               blackscholesc09, blackscholesc095,
                               blackscholesc1, blackscholesc105, blackscholesc11){

  model_price_vector09  <- MixturePut(Strike09, Liborrate, par_x, TimetoMaturity, SPX)
  model_price_vector095 <- MixturePut(Strike095, Liborrate, par_x, TimetoMaturity, SPX)
  model_price_vector1   <- MixturePut(Strike1, Liborrate, par_x, TimetoMaturity, SPX)
  model_price_vector105 <- MixtureCall(Strike105, Liborrate, par_x, TimetoMaturity, SPX)
  model_price_vector11  <- MixtureCall(Strike11, Liborrate, par_x, TimetoMaturity, SPX)

  error_vector_price <-
    (((blackscholesc09 - model_price_vector09) ^ 2 + (blackscholesc095 - model_price_vector095) ^
        2 + (blackscholesc1 - model_price_vector1) ^ 2 + (blackscholesc105 - model_price_vector105) ^
        2 + (blackscholesc11 - model_price_vector11) ^ 2
    ))

  return(error_vector_price)
}



results <-
  optim(
    x_seed ,
    fn = error_vector_price,
    gr = NULL,
    Strike09 = 1142.757,
    Strike095 = 1206.2435,
    Strike1 = 1269.73,
    Strike105 = 1333.216,
    Strike11 = 1396.703,
    Liborrate = 0.0505750,
    TimetoMaturity = 0.25,
    SPX = 1269.73,
    blackscholesc09 = 24.995126,
    blackscholesc095 = 37.78425,
    blackscholesc1 = 57.87691,
    blackscholesc105 = 33.47135,
    blackscholesc11 = 12.671979,
    method = "L-BFGS-B",
    upper = (1)
  )

x_star <- results$par
x_star

results <- vector("list", length = nrow(MIN_DATA1))
with(MIN_DATA1,
     for (i in seq_len(nrow(MIN_DATA1))) {
       results[[i]] <<-
         optim(
           x_seed,
           fn = error_vector_price,
           gr = NULL,
           Strike09 = Strike09[i],
           Strike095 = Strike095[i],
           Strike1 = Strike1[i],
           Strike105 = Strike105[i],
           Strike11 = Strike11[i],
           Liborrate = Liborrate[i],
           TimetoMaturity = TimetoMaturity[i],
           SPX = SPX[i],
           blackscholesc09 = blackscholesc09[i],
           blackscholesc095 = blackscholesc095[i],
           blackscholesc1 = blackscholesc1[i],
           blackscholesc105 = blackscholesc105[i],
           blackscholesc11 = blackscholesc11[i],
           method = "L-BFGS-B",
           upper = (0.9)
         )
     }
)

library(tidyverse)
results %>%
  enframe() %>%
  unnest_wider(value) %>%
  unnest_wider(par)

【讨论】:

    猜你喜欢
    • 2015-02-17
    • 1970-01-01
    • 1970-01-01
    • 2021-04-16
    • 2013-07-12
    • 2019-07-29
    • 2012-07-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多