How to calculate implied volatility in R
Asked Answered
E

3

6

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

Ensoul answered 21/4, 2019 at 1:45 Comment(0)
K
3

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.

Keratin answered 21/4, 2019 at 12:21 Comment(0)
M
2

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.

Meiosis answered 21/4, 2019 at 11:43 Comment(0)
K
1

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.

Keratin answered 23/4, 2019 at 6:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.