Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R Optimize issues

Tags:

optimization

r

I have written a function bs.pp that calculates the Black Scholes value of a Put Option.

    bs.pp <- function (Price, Strike, sigma, texp, int) {
  d1=(1 / (sigma*sqrt(texp)))*(log(Price/Strike)+(int+(sigma^2)/2)*texp)
  d2=d1-sigma*sqrt(texp)
  Strike*pnorm(-d2)*exp(-int*texp)-Price*pnorm(-d1)}

Which seems to work well

> bs.pp(1000,1000,.2,1,.02)
[1] 69.35905
> bs.pp(1000,900,.25,1,.02)
[1] 46.15609

I am now trying to utilize the R optimize function to calculate the inverse of the function when we know (Price, Strike, texp, int) and the result of the function but not sigma.

I tried to do this as follows

gg <- function(Price, Strike, sigma, texp, int, PutPrice){(bs.pp(Price, Strike, sigma, texp, int) - PutPrice)^2}
xmin <- optimize(gg, c(0,1), tol = 0.0001, Price = 1000, Strike = 1000, texp = 1, int = 0.02, PutPrice = 69.4)
xmin$minimum

Which returns the error

Error in optimize(gg, c(0, 1), tol = 1e-04, Price = 1000, Strike = 1000,  : 
  'xmin' not less than 'xmax'

Interestingly if I run the following (NOTE "int = 0.02" replaced with just "0.02" in the optimize line)

gg <- function(Price, Strike, sigma, texp, int, PutPrice){(bs.pp(Price, Strike, sigma, texp, int) - PutPrice)^2}
xmin <- optimize(gg, c(0,1), tol = 0.0001, Price = 1000, Strike = 900, texp = 1, 0.02, PutPrice = 46.2)
xmin$minimum

I get the correct answer

[1] 0.2501474

And to prove that wasn't just a fluke

gg <- function(Price, Strike, sigma, texp, int, PutPrice){(bs.pp(Price, Strike, sigma, texp, int) - PutPrice)^2}
xmin <- optimize(gg, c(0,1), tol = 0.0001, Price = 1000, Strike = 1000, texp = 1, 0.02, PutPrice = 69.4)
xmin$minimum

returns the correct answer also

[1] 0.2001055

Any ideas? I've tried moving the arguments of the function around so that sigma is first but that doesn't seem to make any difference.

Just FYI my end function was going to be the following, which I'm sure can be written more elegantly

bs.piv <- function(Price, Strike, texp, intr, PutPrice){
  optfunc <- function(P, S, sigma, t, i, PP){(bs.pp(Price, Strike, sigma, texp, intr) - PutPrice)^2}
  xmin <- optimize(optfunc, c(0,1), tol = 0.0001, P=Price, S=Strike, t=texp, i=intr, PP=PutPrice)
  xmin$minimum}
like image 981
SC. Avatar asked Dec 20 '22 04:12

SC.


2 Answers

Naming all your arguments is usually a good idea, especially when working with the ... argument. It fixes the problem in this case:

xmin <- optimize(f = gg, interval = c(0,1), tol = 0.0001, Price = 1000, Strike = 1000, texp = 1, int = 0.02, PutPrice = 69.4)

EDIT: as @Roland explained, interval is matched by int, so this is one example for the dangers of partial matching of arguments in R.

like image 154
David Heckmann Avatar answered Jan 03 '23 05:01

David Heckmann


In addition to @David H's answer, which provides the solution of naming the interval argument, here is an explanation:

This is a consequence of partial matching of arguments. See the language definition section 4.3.2 for details. In brief, the matching works in three steps:

1.) Exact name matches are searched for between the supplied arguments and optimize' arguments. E.g., interval would be matched to interval here.

2.) Partial name matches are searched for between the supplied arguments and optimize' arguments. E.g., int would be matched to interval here.

3.) Positional matching occurs. "If there is a ‘...’ argument, it will take up the remaining arguments, tagged or not." And ... is used by optimize to pass arguments to the function specified in f.

So, step 2 takes away your int argument because partial matching occurs before positional matching.

like image 24
Roland Avatar answered Jan 03 '23 07:01

Roland