Quantitative Finance Stack Exchange is a question and answer site for finance professionals and academics. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I Calculated facebook option(expired in 12/4/13) Implied Volatility with the Bisection Method. The program will be attached at the end. The results for different strike prices are so different:

                call    put     call    put     put
Stock Price     26.55   26.55   26.55   26.55   26.55
Strike Price    26.5    26.5    27      27      28
Time to maturity    0.06301
Risk Free Rate      1.88E-02
Dividend Yield  0       0       0       0
Option Price    0.87    0.86    0.63    1.08    1.65

Implied Volatility  0.312236566 0.308462006 0.306893589     0.477272194

Can any tell me what's wrong with the program?

  Public TargetColume As Integer

  Function BlackScholesCall( _ 
    ByVal S As Double, _ 
    ByVal X As Double, _ 
    ByVal T As Double, _ 
    ByVal r As Double, _ 
    ByVal d As Double, _ 
    ByVal v As Double) As Double 
    Dim d1 As Double 
    Dim d2 As Double 
    d1 = (Log(S / X) + (r - d + v ^ 2 / 2) * T) / v / Sqr(T)
    d2 = d1 - v * Sqr(T) 
    BlackScholesCall = Exp(-d * T) * S * Application.NormSDist(d1) - X * Exp(-r * T) * Application.NormSDist(d2)
  End Function 

  Function ImpliedVolatility( _ 
    ByVal S As Double, _ 
    ByVal X As Double, _ 
    ByVal T As Double, _ 
    ByVal r As Double, _ 
    ByVal d As Double, _ 
    ByVal Price As Double) As Double 

    Dim epsilonABS As Double 
    Dim epsilonSTEP As Double 
    Dim volMid As Double
    Dim niter As Integer 
    Dim volLower As Double 
    Dim volUpper As Double 

    epsilonABS = 0.0000001 
    epsilonSTEP = 0.0000001 
    niter = 0 
    volLower = 0.001 
    volUpper = 1 

    Do While volUpper - volLower >= epsilonSTEP Or Abs(BlackScholesCall(S, X, T, r, d, volLower) - Price) >= epsilonABS And epsilonABS <= Abs(BlackScholesCall(S, X, T, r, d, volUpper) - Price) >= epsilonABS 
      volMid = (volLower + volUpper) / 2 
      If Abs(BlackScholesCall(S, X, T, r, d, volMid) - Price) <= epsilonABS Then 
        Exit Do 
      ElseIf ((BlackScholesCall(S, X, T, r, d, volLower) - Price) * (BlackScholesCall(S, X, T, r, d, volMid) - Price) < 0) Then 
        volUpper = volMid
        volLower = volMid 
      End If
      niter = niter + 1

    ImpliedVolatility = volLower 

  End Function

  Function CalcImpliedVolatility()

  Dim S, X, T, r, d, Price As Double 
  Dim volatility As Double 

  S = ActiveSheet.Cells(6, TargetColume).Value 
  X = ActiveSheet.Cells(7, TargetColume).Value 
  T = ActiveSheet.Cells(8, "B").Value 
  r = ActiveSheet.Cells(9, "B").Value 
  d = ActiveSheet.Cells(10, TargetColume).Value
  Price = ActiveSheet.Cells(11, TargetColume).Value 

  volatility = ImpliedVolatility(S, X, T, r, d, Price)

  ActiveSheet.Cells(14, TargetColume).Value = volatility

  End Function

Private Sub CommandButton1_Click()


End Sub

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    TargetColume = Target.Column
End Sub
share|improve this question
Implied vols for equities show skew. There is nothing wrong with IV being so different for different strikes. Having said that there might be something definitely wrong with your code. Hence my comment instead of answer – Chinmay Patil Mar 20 '13 at 3:17
You can format code on Stack Exchange simply by highlighting it and clicking Ctrl-K. We support Markdown for formatting here. – chrisaycock Mar 20 '13 at 3:28
becareful for rounding errors.. and no options series will have all the same implieds across the strike space.. – cdcaveman Mar 20 '13 at 4:33
I vote to close it as long as the table on top isn't cleaned up. A clear table will allow simple answering by anyone with a implied vol calculator – Bob Jansen Mar 20 '13 at 13:17
I know and often do but these dumps without coming back are quite irritating. Despite heavy editing by other editors there still was an error. This doesn't help anyone :( – Bob Jansen Mar 23 '13 at 19:42

The line

Dim S, X, T, r, d, Price As Double 

is better written as

Dim S As Double, X As Double, T As Double, r As Double, d As Double, Price As Double

because 'as' only applies to the variable directly before it.

The bisection algorithm seems to work as advertised. You could check with an online calculator such as this one. I've rewritten the function to be more efficient and shorter although I believe the initial output was also correct but the column header are wrong, some puts are calls and the code for puts is not included. Anyway here is the code.

Private Const maxIter As Long = 100000#
Private Const epsilonABS As Double = 0.0000001
Private Const epsilonSTEP As Double = 0.0000001

Public Function ImpliedVolatility( _
  S As Double, X As Double, T As Double, r As Double, d As Double, _
  Price As Double _
) As Double

  Dim volMid As Double, valMid As Double, diff As Double
  Dim niter As Integer

  volLower = 0.001
  volUpper = 1
  niter = 0       
    volMid = (volLower + volUpper) / 2
    valMid = BlackScholesCall(S, X, T, r, d, volMid)
    diff = Abs(valMid - Price)

    If valMid > Price Then
      volUpper = volMid
      volLower = volMid
    End If

    niter = niter + 1
  Loop While volUpper - volLower >= epsilonSTEP And diff > epsilonABS And _
      niter < maxIter

  ImpliedVolatility = volMid

End Function
share|improve this answer

you can use this code from Uwe Wystup FX Options and Structured Products. you can find it online. it uses vega and taylor expansion (just to 1st derivative which is vega) to find vol. you have to have code for european call price, but you have it already

Function VanillaVolRetriever(spot As Double, rd As Double,rf As Double, strike As Double, T As Double, type As Integer, GivenValue As Double) As Double
Dim func As Double
Dim dfunc As Double
Dim maxit As Integer ’maximum number of iterations
Dim j As Integer
Dim s As Double
’first check if a volatility exists, otherwise set result to zero
If GivenValue<Application.Max(0,type*(spot*Exp(-rf*T)-strike*Exp(-rd * T)))Or(type = 1 And GivenValue > spot*Exp(-rf * T)) Or (type = -1 And GivenValue > strike * Exp(-rd * T)) Then VanillaVolRetriever = 0
’ there exists a volatility yielding the given value,
’ now use Newton’s method:
’ the mapping vol to value has a saddle point.
’ First compute this saddle point:
saddle = Sqr(2/T * Abs(Log(spot / strike) + (rd - rf) * T))
If saddle > 0 Then
   VanillaVolRetriever = saddle * 0.9
   VanillaVolRetriever = 0.1
End If
  maxit = 100
For j = 1 To maxit Step 1
   func = Vanilla(spot, strike, VanillaVolRetriever, rd, rf, T, type, value) - GivenValue
   dfunc = Vanilla(spot, strike, VanillaVolRetriever,rd, rf, T, type, vega)
   VanillaVolRetriever = VanillaVolRetriever - func / dfunc
   If VanillaVolRetriever <= 0 Then
      VanillaVolRetriever = 0.01
   If Abs(func / dfunc) <= 0.0000001 Then j = maxit
Next j
End If
End Function

you can find it also here

it is absolutely OK that they are different dependent on strike, you would suspect there's bug in your function otherwise. this is reality: we use BS model with const vol assumption and we quote different vol for different strike/delta

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.