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}
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With