0

I am trying to solve a quite straight forward non linear least squares problem where the formulation takes 'so to say' a vector of zeroes as dependent variable because I am only interested in the parameters of the minimization for a prediction exercise. However, whatever I do with this algorithm, the code keeps giving me the following error: Error in str2lang(x) : <text>:2:0: unexpected end of input 1: ~ ^

EDIT: The suggestion to replace the LHS of the equation with a specified variable seems to resolve the parser issue. However, I now get the following error:

Error in nlsLM(formula = y ~ fit(params, T_k_IV_matrix), start = x0, lower = lb,  : 
  parameters without starting value in 'data': params

Does anyone know where I should be looking to solve this problem?

Here is the important part of the code I use:

fit <- function(params, T_k_IV_matrix) {
  T <- T_k_IV_matrix[, "tenor"]
  k <- T_k_IV_matrix[, "k"]
  IV <- T_k_IV_matrix[, "impl_volatility"]
  vt <- params[1]
  mt <- params[2]
  wt <- params[3]
  nt <- params[4]
  rhot <- params[5]

  (1/4) * exp(-2 * nt * T) * (wt^2) * (T^2) * (IV^4) +
    (1 - 2 * exp(-nt * T) * mt * T - exp(-nt * T) * wt * rhot * 
sqrt(vt) * T) * (IV^2) -(vt + 2 * exp(-nt * T) * wt * rhot * 
sqrt(vt) * k + exp(-2 * nt * T) * (wt^2) * (k^2))
}

for (i in 1:length(grouped_data)) {
  T_k_IV_matrix <- data.table(
    tenor = c(110, 110, 82, 138, 82, 173, 138, 173, 173, 47),
    k = c(0.1629164648, 0.4307829161, -0.3811180797, 0.0009384402, 
-0.1823215568, -0.0219789067, -0.0988005847, -0.4187103349, 
-0.0737730947, -0.0527505654),
    impl_volatility = c(0.950298, 1.106709, 0.732060, 0.740338, 
0.638142, 0.525060, 0.689398, 0.652785, 0.955989, 0.962296)
  )
  y = rep(0, nrow(T_k_IV_matrix))

  x0  = c(0.04, 0.1, 0.5, 0.3,-0.8)
  lb = c(0.001,-Inf,0.001,0.001,-.999)
  ub = c(Inf,Inf,Inf,Inf,.999)

  result <- nlsLM(
    formula = y ~  fit(params, T_k_IV_matrix),
    start = x0, 
    lower = lb,
    upper = ub
  )
  params[[i]] <- coef(result)
}
Wolfie
  • 27,562
  • 7
  • 28
  • 55
LuSm
  • 31
  • 3
  • I appreciate the desire to keep things simple for us but we really need a [mcve] to help with this. Two thoughts: (1) provide the output of `traceback()` so we can see where in the underlying code the error occurred? (2) you might try saving `rep(0, nrow(T_k_IV_matrix))` as a variable and using the symbol on the LHS of the equation, in case `nlsLM` is doing something fragile in parsing the formula ... – Ben Bolker May 22 '23 at 15:54
  • Thank you very much for your response. The suggestion seems to solve the parser issue, but this brings a new error message. I have edited the code above to be reproducible and I have added the new error as well. The traceback shows: 2: stop("parameters without starting value in 'data': ", paste(nnn, collapse = ", ")) 1: nlsLM(formula = y ~ fit(params, T_k_IV_matrix), start = x0, lower = lb, upper = ub) – LuSm May 22 '23 at 16:17
  • I think `nlsLM` is typically expecting an expression written in terms of scalar parameters. You might try `fit <- function(vt,mt,nt,wt, rhot, T_k_IV_matrix) { ...} ` and then make `start` a list of the starting values ... – Ben Bolker May 22 '23 at 16:20
  • This does indeed make the error go away, thank you very much! It still leaves me with an error message stating non-sensible return values, but I think I need to figure this out by looking at the functional form and/or input data. Thanks again for the help, it is much appreciated! – LuSm May 22 '23 at 16:34
  • Please write up the solutions as an answer to your own question when you get a chance. – Ben Bolker May 22 '23 at 17:21

1 Answers1

3

The solution to the above problem consists of three parts. Firstly, the LHS of the nlsLM statement needed to be written as a variable itself to avoid the parsing problem. Secondly, the fit function required the parameter vector to be written out instead of being a list of parameters. Thirdly, to get the wished-for results, the allocation of the variables in the fit function needed to be accessed by '$x' instead of [,"x"].

fit <- function(vt,mt,nt,wt, rhot, T_k_IV_matrix) { 
  T <- T_k_IV_matrix$tenor
  k <- T_k_IV_matrix$k
  IV <- T_k_IV_matrix$impl_volatility
  
  (1/4) * exp(-2 * nt * T) * (wt^2) * (T^2) * (IV^4) +
    (1 - 2 * exp(-nt * T) * mt * T - exp(-nt * T) * wt * rhot * sqrt(vt) * T) * (IV^2) -
    (vt + 2 * exp(-nt * T) * wt * rhot * sqrt(vt) * k + exp(-2 * nt * T) * (wt^2) * (k^2))
}

params <- list()

for (i in 1:length(grouped_data)) {
  group <- grouped_data[[i]]
    T_k_IV_matrix <- data.table(
    tenor = c(110, 110, 82, 138, 82, 173, 138, 173, 173, 47),
    k = c(0.1629164648, 0.4307829161, -0.3811180797, 0.0009384402, 
    -0.1823215568, -0.0219789067, -0.0988005847, -0.4187103349, 
    -0.0737730947, -0.0527505654),
    impl_volatility = c(0.950298, 1.106709, 0.732060, 0.740338, 
    0.638142, 0.525060, 0.689398, 0.652785, 0.955989, 0.962296)
  )
  y = rep(0, nrow(T_k_IV_matrix))
  
  x0  = c(vt = 0.04, mt=0.1, nt=0.01, wt=0.3, rhot=-0.8)
  lb = c(0.001,-Inf,0.001,0.001,-.999)
  ub = c(Inf,Inf,Inf,Inf,.999)
  
  result <- nlsLM(
    formula = y ~ fit(vt,mt,nt,wt, rhot, T_k_IV_matrix),
    start = x0, 
    lower = lb,
    upper = ub
  )
  
  params[[i]] <- coef(result)
}
LuSm
  • 31
  • 3