Reputation:
I am trying to create my own function in R based on black scholes variables and solve "backwards" i suppose for sigma.
I have created a function to find the call price; however, now I have to find the sigma (implied volatility) estimates in R and then test my function to see if it works... I have tried different functions but I can not seem to figure out what I am doing wrong, part of me thinks I need to know sigma to find sigma but I am not sure if that even makes sense.
Here is the function I created for the price of a European call option in the Black Scholes model:
call <- function(s0, K, r, T, sigma) {
d1 <- (log(s0/K) + (r + sigma^2/2)*T) / (sigma*sqrt(T))
d2 <- d1 - sigma*sqrt(T
c <- s0*pnorm(d1) - K*exp(-r*T)*pnorm(d2)
c
}
I tested my function to see if it works properly with different code which it does:
call(100, 70, 0.05, 1, 0.16)
[1] 33.43686
call(300, 280, 0.03, 3, 0.18)
[1] 60.81694
call(400, 350, 0.04, 5, 0.20)
[1] 133.1626
Now I need to use the following function to find sigma:
sigma <- function(call, s0, K, r, T) {
???
}
After creating the function I need to test it using the following:
sigma(33.43686, 100, 70, 0.05, 1)
sigma(60.81694, 300, 280, 0.03, 3)
sigma(133.1626, 400, 350, 0.04, 5)
Same format but I cannot figure it out. I need to include a range or sequence to find sigma?
I have tried this but I don't believe we are supposed to include 'v' in the function
sigma <- function(call, s0, K, r, T, v) {
d1 <- (log(s0/K) + (r + v^2/2)*T) / (v*sqrt(T))
d2 <- d1 - v*sqrt(T)
c <- s0*pnorm(d1) - K*exp(-r*T)*pnorm(d2)
sigma_value <- d1 - d2 / sqrt(T)
sigma_value
}
sigma(33.43686, 100, 70, 0.05, 1, 0.16)
[1] 0.16
sigma(60.81694, 300, 280, 0.03, 3, 0.18)
[1] 0.4614232
sigma(133.1626, 400, 350, 0.04, 5, 0.20)
[1] 0.7358743
0.16 is "sigma" I am trying to find an estimate close to this by creating my own function.
I also feel my sigmas are way off then they are supposed to be
I also tried :
sigma <- function(call, s0, K, r, T) {
v = seq(from = 0.1, to = .2, by = .01)
k.range = floor(seq(from = 100, to = 400, length.out = length(v)))
for (i in 1:length(v)) {
d1 <- (log(s0/K[i]) + (r + (v^2)/2) * T) / (v * sqrt(T))
d2 <- d1 - v * sqrt(T)
C <- s0 * pnorm(d1) - K[i] * exp(-r*T) * pnorm(d2) - call[i]
}
v
}
Any help on the function aspect would be great. Thank you
Upvotes: 6
Views: 8024
Reputation: 11981
you can use the uniroot
function to find the implied volatility. uniroot
finds the roots of a function.
Here is how to use it.
call_fun <- function(s0, K, r, TT, sig) {
d1 <- (log(s0/K) + (r + sig^2/2)*TT) / (sig*sqrt(TT))
d2 <- d1 - sig*sqrt(TT)
s0*pnorm(d1) - K*exp(-r*TT)*pnorm(d2)
}
sig_impl <- function(s0, K, r, TT, .c) {
root_fun <- function(sig){
call_fun(s0, K, r, TT, sig) - .c
}
uniroot(root_fun, c(0, 1))$root
}
call_fun(100, 70, 0.05, 1, 0.16)
[1] 33.43686
sig_impl(100, 70, 0.05, 1, 33.43686)
[1] 0.1599868
Note that I changed some of the variable names: T
is usually reserved for TRUE
so you should not name a variable T
. Also, there is a function called sigma
so better not name your variables sigma.
Upvotes: 2
Reputation: 153
Uniroot is one possibility the traditional method of solving the equation is with either newtons gradient method or the simpler bi-section search, this is industry standard I will post psuedocode for the standard approach
function ImpliedCallVolatility(UnderlyingPrice, ExercisePrice, Time, Interest, Target, Dividend)
High = 5
LOW = 0
Do While (High - LOW) > 0.0001
If CallOption(UnderlyingPrice, ExercisePrice, Time, Interest, (High + LOW) / 2, Dividend) > Target Then
High = (High + LOW) / 2
Else: LOW = (High + LOW) / 2
End If
Loop
ImpliedCallVolatility = (High + LOW) / 2
End Function
Function ImpliedPutVolatility(UnderlyingPrice, ExercisePrice, Time, Interest, Target, Dividend)
High = 5
LOW = 0
Do While (High - LOW) > 0.0001
If PutOption(UnderlyingPrice, ExercisePrice, Time, Interest, (High + LOW) / 2, Dividend) > Target Then
High = (High + LOW) / 2
Else: LOW = (High + LOW) / 2
End If
Loop
ImpliedPutVolatility = (High + LOW) / 2
End Function
Based on Simon Beninga's Financial Modelling with Excel, similar to Paul Willmot and Espen Haugs methods in their respective books, but they do not rely on Excel's normal curve functions, but use highly efficient and accurate normal distribution approximation functions. Otherwise much the same. Espen Haug The Complete guide to option Pricing formulas 2007 Paul Willmot Introduction to Quantitative Finance. All three books implement the formulas in excel, I believe in the attached disk to Haug he has a c++ implementation also. It really is a simple task to convert to R, sorry I have not done it, I use the built in methods mentioned above, fOptions or Rquantlib, you should test your implementation against the output from these for accuracy and correctness.
Upvotes: 1
Reputation: 153
There is a built in implied volatility function in the RQuant library eg.
AmericanOptionImpliedVolatility(type="call", value=11.10, underlying=100,
strike=100, dividendYield=0.01, riskFreeRate=0.03,
maturity=0.5, volatility=0.4)
It is also a function in fOptions package, GBSVolatility returns the GBS option implied volatility for a given price. GBS = Generalised Black Scholes model
GBSVolatility(price, TypeFlag, S, X, Time, r, b, tol, maxiter)
BlackScholesOption(...)
See Espen Haug book 1997,2007 Complete option pricing; for algorithms in MS excel VBA.
Upvotes: 3