2. 2 | P a g e
Note: The Program has been written in Visual Basic Version 6.5.1024
Salient Features of the Code
• Consists of an ‘error trapping’ mechanism which prevents the user from entering negative or zero strike prices.
• Includes a ‘For Next Loop’ which enables the user to input a range, along with a desired tick size. Also uses ‘Clear
contents’ to clear the cells before a range is specified to run.
• The main ‘sub’ of the code reads in the values from the frontend and calculates the Call Value of an option using
the Black‐Scholes method, calculates the Price of the Warrant using the Call Value and finally calculates the
number of Warrants, based on the given data.
• The program uses the ‘If’ function to replace negative values of the Call values with zero, since a call value may
only be positive or zero.
• Calculations are carried out in the code at the backend, based on the data given, and the range of the strikes
specified by the user.
• All the above activities occur with the single click of a ‘Calculate’ button at the frontend.
Benchmarking the Program using a different approach
While the program follows the Black Scholes method to value warrants, in order to test for possible errors, I have
benchmarked it against the Binomial valuation method, performing the calculations in the front end.
The above table are the results from running Black Scholes in Visual Basic.
While the table above displays the results from using the same data and range of strike prices, to calculate through the
Binomial method. Clearly, there is little difference in the Call Value between the 2 methods, attributable to the Binomial
method being an approximation, while the Black Scholes being the more robust method. This indicates that the code in the
backend is acceptable.
4. 4 | P a g e
The Program Code
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
'XX
'XX Code to calculate Number of warrants to issue based on a range of
'XX Strike prices
'XX
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Option Explicit
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
'XX
'XX Global Type declaration
'XX
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Private Type Kartik_data
S As Double 'stock price
sig As Double 'volatility
r As Double 'risk free rate
X As Double 'strike price
T As Double 'time to maturity
lx As Double 'lower limit of range
ux As Double 'upper limit of range
dx As Double 'tick size of range
End Type
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
'XX
'XX Main sub which reads in the data from the frontend
'XX
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Private Sub main()
Dim ws As Worksheet, sheet As Worksheet 'Code to clear previous
contents each time the sub is run
Set sheet = ActiveSheet
ActiveSheet.Range("b13:e113").ClearContents
Dim Kartik As Kartik_data: Call ReadInData(Kartik)
Dim N As Integer: N = (Kartik.ux-Kartik.lx)/Kartik.dx 'Index loop will
will run from 0 to N
Kartik.X = Kartik.lx
If Kartik.X <= 0 Then 'Error trapping to ensure negative strike
price is not entered
GoTo error_label
Else: Kartik.X = Kartik.lx 'if error does not occur, function will run
normally
End If
Dim i As Long
Dim X As Double
5. 5 | P a g e
For X = Kartik.lx To Kartik.ux Step Kartik.dx 'initiating a loop, enables the
user to enter a range
i = (X - Kartik.lx) / Kartik.dx
'Cells(13 + i, 1).Value = i
Cells(13 + i, 2).Value = Kartik.X 'displays the strike price
following the range
Kartik.X = X
Cells(13 + i, 3).Value = Blck_Schls(Kartik) 'displays the call price
Cells(13 + i, 4).Value = Val_Warrant(Kartik) 'displays the price of the
warrant
Cells(13 + i, 5).Value = Num_Warr(Kartik) 'displays the number of
warrants needed to issue
Kartik.X = Kartik.X + Kartik.dx
Next X
Dim Call_Price As Double: Call_Price = Blck_Schls(Kartik)
Dim Price_Warrant As Double: Price_Warrant = Val_Warrant(Kartik)
Exit Sub
error_label: 'function to be performed when negative strike price is entered
Beep
MsgBox prompt:="Strike price cannot be zero or negative"
Exit Sub
End Sub
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
'XX
'XX Main Sub reads in the following data from the frontend references
'XX
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Private Sub ReadInData(ByRef Kartik As Kartik_data) 'data is referenced from the
frontend
Kartik.X = Kartik.lx
Kartik.lx = Cells(5, 3).Value
Kartik.ux = Cells(6, 3).Value
Kartik.dx = Cells(7, 3).Value
Kartik.S = Cells(5, 5).Value
Kartik.sig = Cells(6, 5).Value
Kartik.r = Cells(7, 5).Value
Kartik.T = Cells(8, 5).Value
Dim P As Long: P = (Kartik.ux - Kartik.lx) / Kartik.dx 'Index loop will
will run from 0 to N
End Sub
6. 6 | P a g e
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
'XX
'XX The Black Scholes function, using defined type and referencing
'XX
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Private Function Blck_Schls(Kartik As Kartik_data) As Double
Dim Pres_Val As Double: Pres_Val = Kartik.X * Exp(-Kartik.r * Kartik.T)
'present value of the strike
Dim Vol_Root As Double: Vol_Root = Kartik.sig * Sqr(Kartik.T)
'sqaureroot of volatility
Dim d1 As Double: d1 = Log(Kartik.S/Pres_Val)/Vol_Root + 0.5 * Vol_Root
'defines d1
Blck_Schls = Kartik.S * Application.NormSDist(d1) - Pres_Val *
Application.NormSDist(d1 - Vol_Root)
End Function
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
'XX
'XX Calculating the value of the warrants
'XX
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Private Function Val_Warrant(Kartik As Kartik_data) As Double
Dim Pres_Val As Double: Pres_Val = Kartik.X * Exp(-Kartik.r * Kartik.T)
Dim Vol_Root As Double: Vol_Root = Kartik.sig * Sqr(Kartik.T)
Dim d1 As Double: d1 = Log(Kartik.S / Pres_Val) / Vol_Root + 0.5 * Vol_Root
Val_Warrant = (Kartik.S * Application.NormSDist(d1) - Pres_Val *
Application.NormSDist(d1 - Vol_Root)) - 0.1
If Val_Warrant < 0 Then 'Using If function to ensure that the value is
positive or 0
GoTo error_label
End If
Exit Function
error_label:
Val_Warrant = 0
End Function
7. 7 | P a g e
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
'XX
'XX Calculating the number of warrants to be issued
'XX
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Private Function Num_Warr(Kartik As Kartik_data) As Double
Dim Pres_Val As Double: Pres_Val = Kartik.X * Exp(-Kartik.r * Kartik.T)
Dim Vol_Root As Double: Vol_Root = Kartik.sig * Sqr(Kartik.T)
Dim d1 As Double: d1 = Log(Kartik.S / Pres_Val) / Vol_Root + 0.5 * Vol_Root
Num_Warr = 20/((Kartik.S*Application.NormSDist(d1)-Pres_Val*
Application.NormSDist(d1 - Vol_Root)) - 0.1)
If Num_Warr < 0 Then 'Again using If function to ensure that the number of
the warrants is positive
GoTo error_label
End If
Exit Function
error_label:
Num_Warr = 0
End Function
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
'XX
'XX end of file
'XX
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
8. 8 | P a g e
Inferring the results
This program enables the user to understand how the value of the warrants and the corresponding number of warrants to
be issued changes across a range of strike prices. If we set the strike price range between £2 and £6, with a tick size of
£0.25, we get the following plots
As we observe, the number of warrants to be issued by the company increases at an exponential rate as strike price
increases, while the value of the warrant falls correspondingly and approaches zero simultaneously.