Public Sub McOptV(F As Double, K As Double, T As Double, V As Double, R As Double, _
      Cp As String, CalcType As String, Steps As Integer, _
      Px As Double, Delta As Double, Gamma As Double, Theta As Double, Vega As Double)
      ' Calculates and returns PX (PREMIUM), DELTA, GAMMA, THETA and VEGA from
      ' Binomial calculation fixed as 50 (wSteps)
      '   F         Future price
      '   K         Strike
      '   T         Time in years to expiry
      '   V         Annualised volatility
      '   R         Continuously componded dicount rate
      '   Cp        'C'all or 'P'ut
      '   Calctype  'E'uropean, 'A'merican or 'Z' european binomial
      '   Steps     No. of binomial steps
           
           
      Dim A(0 To 2001) As Double
      Dim FSHIFT As Double, TSHIFT As Double, VSHIFT As Double
      Dim F_PLUS As Double, F_MINUS As Double, T_MINUS As Double, V_PLUS As Double
      Dim PX_NOW As Double, GkPx As Double, GkDelta As Double, PX_PLUS As Double
      Dim BinPx  As Double, DELTA_PLUS  As Double, PX_MINUS As Double
      Dim DELTA_MINUS As Double, BinDelta As Double, FF As Double
      Dim FK As Double, FT  As Double, FV As Double, ONE As Double, Discount As Double
      Dim X1 As Double, X2 As Double, CUMX1 As Double, CUMX2 As Double
      Dim z As Double, X As Double, K1 As Double, Rval As Double, PX_ODD As Double
      Dim DELTA_ODD As Double, PX_EVEN As Double, FN As Double, TN As Double
      Dim U  As Double, D As Double, P As Double, Q As Double, S As Double
      Dim VEG As Double, DELTA_EVEN  As Double
     
      Dim wx As Integer, wi As Integer, wj As Integer, wSteps As Integer
           
      On Error GoTo Errors
      GoSub 5100                                          ' Initialise
      If CalcType = "E" Then GoSub 6000                   ' European style
      If CalcType = "A" Or CalcType = "Z" Then GoSub 6100 ' Binomial
      Exit Sub
    5100    '******************************************
            '   I N I T I A L I S E
            '   -------------------
            '
            Px = 0
            Delta = 0
            Gamma = 0
            Theta = 0
            Vega = 0
            Cp$ = Left$(Cp$, 1)
            CalcType = Left$(CalcType$, 1)
            If InStr(1, "CP", Cp$) = 0 Then Exit Sub
            If InStr(1, "EAZ", CalcType) = 0 Then Exit Sub
            FSHIFT = F * 0.001
            TSHIFT = 1 / 365
            VSHIFT = 0.01
            F_PLUS = F + FSHIFT
            F_MINUS = F - FSHIFT
            T_MINUS = T - TSHIFT
            V_PLUS = V + VSHIFT
            Return
    6000    '******************************************
            '       E U R O P E A N     S T Y L E
            '       -----------------------------
            '
            FF = F: FK = K: FT = T: FV = V
            GoSub EuroStyle                   ' Price/delta
            Px = GkPx
            PX_NOW = GkPx
            Delta = GkDelta
           
            FF = F_PLUS: FK = K: FT = T: FV = V
            GoSub EuroStyle                    ' Price/delta on fut price + .1%
            PX_PLUS = GkPx
            DELTA_PLUS = GkDelta
           
            FF = F_MINUS: FK = K: FT = T: FV = V
            GoSub EuroStyle                     ' Price/delta on fut price - .1%
            PX_MINUS = GkPx
            DELTA_MINUS = GkDelta
            Gamma = (DELTA_PLUS - DELTA_MINUS) / (2 * FSHIFT)
            FF = F: FK = K: FT = T_MINUS: FV = V
            GoSub EuroStyle                   ' Price/delta on time - 1 day
            Theta = GkPx - PX_NOW
            FF = F: FK = K: FT = T: FV = V_PLUS
            GoSub EuroStyle                     ' Price/delta on volatity + .01
            Vega = GkPx - PX_NOW
            Return
    6100    '***************************************************************
            '       B I N O M I A L    S T Y L E
            '       ----------------------------
            '
            FF = F: FK = K: FT = T: FV = V
            GoSub BinOEStyle              ' Price/delta
            Px = BinPx
            PX_NOW = BinPx
            Delta = BinDelta
           
            FF = F_PLUS: FK = K: FT = T: FV = V
            GoSub BinOEStyle            '  Price/delta on fut price + .1%
            PX_PLUS = BinPx
            DELTA_PLUS = BinDelta
           
            FF = F_MINUS: FK = K: FT = T: FV = V
            GoSub BinOEStyle            ' Price/delta on fut price - .1%
            PX_MINUS = BinPx
            DELTA_MINUS = BinDelta
            Gamma = (DELTA_PLUS - DELTA_MINUS) / (2 * FSHIFT)
           
            FF = F: FK = K: FT = T_MINUS: FV = V
            GoSub BinOEStyle            ' Price/delta on time - 1 day
            Theta = BinPx - PX_NOW
            
            FF = F: FK = K: FT = T: FV = V_PLUS
            GoSub BinOEStyle            ' Price/delta on volatity + .01
            Vega = BinPx - PX_NOW
            Return
    EuroStyle:
        ' European style calc (GK), returns GkPx and GkDelta
        If FT <= 0 Then
          GkDelta = 0
          If Cp = "C" Then GkPx = FnMax(FF - FK, 0)
          If Cp = "P" Then GkPx = FnMax(FK - FF, 0)
          Return
        End If
        ONE = 0
        If Cp = "P" Then ONE = 1
        Discount = Exp(-R * FT)
        X1 = (Log(FF / FK) + FV * FV / 2 * FT) / (FV * FT ^ 0.5)
        X2 = X1 - FV * FT ^ 0.5
        CUMX1 = FnCum(X1) - ONE
        CUMX2 = FnCum(X2) - ONE
        GkPx = Discount * (FF * CUMX1 - FK * CUMX2)
        GkDelta = Discount * CUMX1
        Return
    BinOEStyle:
      ' Binomial calc on odd and even. Returns BinPx and BinDelta
      wSteps = Steps
      GoSub BinCalc
      PX_ODD = BinPx
      DELTA_ODD = BinDelta
      wSteps = Steps + 1
      GoSub BinCalc
      PX_EVEN = BinPx
      DELTA_EVEN = BinDelta
      BinPx = (PX_ODD + PX_EVEN) / 2
      BinDelta = (DELTA_ODD + DELTA_EVEN) / 2
      Return
     
    BinCalc:
        ' Binomial calculation, returns BinPx and BinDelta
        If FT <= 0 Then
          BinDelta = 0
          If Cp = "C" Then BinPx = FnMax(FF - FK, 0)
          If Cp = "P" Then BinPx = FnMax(FK - FF, 0)
          Return
        End If
        TN = FT / wSteps
        U = Exp(FV * TN ^ 0.5)
        D = 1 / U
        P = (Exp(R * TN) / Exp(R * TN) - D) / (U - D)
        Q = 1 - P
        Select Case Cp
          Case "C"
            For wi = wSteps To 0 Step -1
              A(wi) = FnMax(0, FF * U ^ wi * D ^ (wSteps - wi) - FK)
            Next wi
          Case "P"
            For wi = wSteps To 0 Step -1
              A(wi) = FnMax(0, FK - FF * U ^ wi * D ^ (wSteps - wi))
            Next wi
         End Select
             
         If CalcType = "Z" Then
           wx = 0
           For wj = 1 To wSteps Step 1
             S = FF * D ^ (wSteps - wj + 1) / U
             For wi = 0 To (wSteps - wj) Step 1
               S = S * U / D
               A(wi) = (P * A(wi + 1) + Q * A(wi)) * Exp(-R * TN)
             Next wi
             If wj = wSteps - 1 Then BinDelta = (A(1) - A(0)) / (FF * U - FF * D)
           Next wj
           BinPx = A(0)
         End If
             
         If CalcType = "A" Then
           wx = 0
           For wj = 1 To wSteps Step 1
             S = FF * D ^ (wSteps - wj + 1) / U
             For wi = 0 To (wSteps - wj) Step 1
               S = S * U / D
               If Cp = "C" Then A(wi) = FnMax(S - FK, (P * A(wi + 1) + Q * A(wi)) * Exp(-R * TN))
               If Cp = "P" Then A(wi) = FnMax(FK - S, (P * A(wi + 1) + Q * A(wi)) * Exp(-R * TN))
              Next wi
              If wj = (wSteps - 1) Then BinDelta = (A(1) - A(0)) / (FF * U - FF * D)
            Next wj
            BinPx = A(0)
          End If
          Return
         
    Errors:
        Resume Errors2
       
    Errors2:
        Px = 0
        Delta = 0
        Gamma = 0
        Theta = 0
        VEG = 0
        Exit Sub
    End Sub
           
    Function FnCum(z As Double) As Double
      ' Used in McOptV
      Dim Rval As Double, K1 As Double, X As Double
      Dim Alpha As Double, Pie As Double, a1 As Double, a2 As Double, a3 As Double
     
      Alpha = 0.33267
      a1 = 0.4361836
      a2 = -0.1201676
      a3 = 0.937298
      Pie = 3.141593
         
      X = Abs(z)
      K1 = 1 / (1 + Alpha * X)
      Rval = 1 - 1 / (2 * Pie) ^ 0.5 * Exp(-X * X / 2) * (a1 * K1 + a2 * K1 * K1 + a3 * K1 * K1 * K1)
      If z < 0 Then Rval = 1 - Rval
      FnCum = Rval
     
    End Function
    Function FnMax(N1 As Double, N2 As Double) As Double
      If N1 > N2 Then
        FnMax = N1
      Else
        FnMax = N2
      End If
    End Function