The Black-Scholes method is another common way of pricing options. However, instead of using an interest rate based model, Fischer Black and Myron Scholes modeled the stock price directly and assumed that its price can be adequately described as a geometric Brownian motion (equation 4.38)
Equation 4.38 by itself, along with the basic solution to S, has no sense of arbitrage or what a “fair” price is. We will not go into the details here, but the pricing equations we will mention a little later depend on the assumptions made on how an option should be priced, and those assumptions necessarily take arbitrage into account. Another thing to note here is that a geometric Brownian motion process is very different from a regular Brownian motion, which is shown in equation 4.4. Equation 4.38 can be rewritten to into equation 4.39:
If you recall from calculus that the integral of 1/x is the natural log of x, ln(x), then you can see that the natural log of S is normally distributed (since the right side of the equation is normally distributed). In summary regular Brownian motion produces normally distributed numbers while geometric Brownian motion produces lognormally distributed numbers. We will discuss this effect in more detail in the next chapter when we use the Merton-KMV model to predict corporate default probabilities.
The Black-Scholes method when applied to pricing European call and put options, C and P, respectively, yields the following results (equations 4.40 through 4.43),
where K is the strike price, r is the risk free rate, T is the time to maturity, t is the time at valuation, σ is the volatility of the underlying asset, S, and N(d) denotes the value of the cumulative standard normal distribution at position d with mean of zero and variance of one.
The advantage of the Black-Scholes model over the Hull-White model is in its simplicity. All the terms in the Black-Scholes equations are market observable quantities, independent of time, and unlike the Hull-White interest rate model, there is only one constant stochastic variable that the final result is dependent on. It is quite common in financial applications to extract the market-implied volatility of various asset classes from observations of market prices of its put and call options. If the call or put price is known in addition to the asset value under consideration, then we have one equation, either 4.40 or 4.41, and one unknown, the volatility. The system is therefore uniquely solvable. Unfortunately equations 4.40 and 4.41 are rather convoluted and as such, the volatility cannot be analytically extracted and must be solved for in an iterative fashion. The methodology we chose to use here is the Newton-Raphson method for finding the root of a function. There is a brief explanation of this formalism in Appendix B if you are not already familiar this concept.
The Model Builder we will work through next is solving for the volatility for one asset given all its observables for a call option. Since we are solving for the volatility that produces a given call price, we must first determine the derivative of C with respect to the volatility. Fortunately, this quantity is already predetermined and is one of the greeks, a table of equations (equations 4.44 through 4.47) describing the derivative of C or P with respect to S, r, σ, and t.
For our current problem, we will use vega since we will be trying to recover the volatility. One particular thing to note is that N'(d1) is the derivative of the cumulative distribution function. We know from statistics that the derivative of the cumulative distribution function is simply the probability distribution function, which in our case is the Normal function with mean of zero and standard deviation of one.
B3: “Inputs: Option & Stock Data” B8: “Today's Date”
B4: “Variable” B9: “Option Expiry Date:”
B5: “Stock Price” B10: “Vega Threshold Guess”
B6: “Strike Price” B11: “Call Price:”
B7: “Risk-Free Interest Rate” C4: “Value”
C5: 12 C9: 10/16/2010
C6: 4 C10: .4
C7: 5.00% C11: 9
C8: 7/6/2010
D4: “Common Calculation Method” D8: “Current Date”
D5: “Current Value in Market” D9: “Give in Option Contract”
D6: “Given in Option Contract” D11: “Current Value in Market, Mid”
D7: “Appropriate T-bill/T-bond rate”
C5: stockPrice C11: callPrice
C6: strike C15: maturity
C7: riskFreeRate C16: CallPriceSolution
C10: Threshold C17: ImpVol
Function computeD1(ByVal vol As Double) As Double computeD1 = (Log(stockPrice / strike) + (riskFreeRate + 0.5 * (vol ^ 2)) * maturity) / (vol * Sqr(maturity)) End Function}]]>
Function myNormDistPDF(ByVal x As Double) myNormDistPDF = Exp(-x ^ 2 / 2) / Sqr(2 * WorksheetFunction.Pi) End Function}]]>
If we plot this function, we will get a curve that will look like the curve shown in Figure 4.8. You will notice that the function asymptotically approaches +/– 2 where the slope in that region, our vega, will be essentially zero. If our starting point happens to lie within this region, our iterative solver will fail to converge since dividing by zero will produce infinity. Therefore, before the start of each solve, we must do an initial scan to make sure we are not starting within this region.
Function volatilityInitialGuess() As Double Dim threshold As Double Dim i As Integer
Dim d1 As Double Dim vol As Double Dim vega As Double Dim vegaConstTerm As Double ' threshold on vega because we want the derivative, ie slope, relative to sigma threshold = Range(“Threshold”).Value vol = 0.02 vegaConstTerm = stockPrice * Sqr(maturity)
For i = 1 To 500 d1 = computeD1(vol) vega = vegaConstTerm * myNormDistPDF(d1) If (vega >= threshold) Then Exit For End If vol = vol + 0.02 Next i volatilityInitialGuess = vol End Function
Option Explicit Dim stockPrice, strike As Double Dim riskFreeRate, maturity As Double Dim callPrice As Double Dim vegaConstTerm As Double Sub BlackScholesSolve() 'Error Term is known as epsilon in most texts Dim errorTerm As Double Dim impVol As Double Dim d1, d2 As Double Dim calcPrice As Double Dim vega As Double Dim counter As Integer Dim vegaConstTerm As Double 'Take inputs from spreadsheet stockPrice = Range(“stockPrice”).Value strike = Range(“strike”).Value riskFreeRate = Range(“riskFreeRate”).Value maturity = Range(“maturity”).Value callPrice = Range(“callPrice”).Value
If (strike >= stockPrice) Then MsgBox (“Strike cannot be greater than or equal to the stock price”) Exit Sub End If
If (callPrice < stockPrice-strike) Then MsgBox (“Call price cannot be less than stockPrice minus strike”) Exit Sub End If
'Initialize variables before start of loop calcPrice = 0 impVol = volatilityInitialGuess() errorTerm = 0.0001 counter = 0 vegaConstTerm = stockPrice * Sqr(maturity)
'Use Newton-Raphson Method to Converge on Correct Value On Error GoTo ErrorHandler While counter < 100 And Abs(callPrice-calcPrice) > errorTerm d1 = (Log(stockPrice / strike) + (riskFreeRate + 0.5 * (impVol ^ 2)) * maturity) / (impVol * Sqr(maturity)) d2 = d1-(impVol * Sqr(maturity)) 'N'(d1) = normdist(d1, 0, 1, false) but this is faster vega = vegaConstTerm * myNormDistPDF(d1) calcPrice = stockPrice * Application.NormSDist(d1)-strike * Exp(-riskFreeRate * maturity) * Application.NormSDist(d2) impVol = impVol-(calcPrice-callPrice) / vega counter = counter + 1 Wend
'insert values onto spreadsheet Range(“ImpVol”) = impVol Range(“CallPriceSolution”) = calcPrice Exit Sub ErrorHandler: MsgBox (“Converge failed. Try another initial guess threshold”) End Sub
One final step that we might want to consider, but that is not absolutely necessary, is to create a button to run the subroutine from the sheet.