|
Example - Black-Scholes
* The "\" symbol has been used at the end of lines to indicate that the line was too long for the display and has been
wrapped to the line below in order to fit within the width of the web page. These lines would need to be joined in the normal
program editor.
I. Introduction
The Black-Scholes model is a famous example of mathematics that is applicable to “real life”. It concerns the relationship between the premium on a European call (or put) option and the price of the underlying stock. The model is based on the assumption that the logarithm of the stock price follows a Brownian motion (random, like particles in a gas).

II. Mathematics Involved
1) Background
A European-style option is a financial product: a contract giving the holder the right to buy (in the case of a call) or sell (in the case of a put) an underlying asset at the strike price, a pre-agreed price, at a fixed point in the future (the expiry date of the option). Obviously the option holder benefits if the strike price is higher or lower, depending on the type of option, than the value of the asset on the expiry date.
2) Formulae
The formulae are as follows:


where C and P are the premiums on the call and put options and S 0 is the stock price.
F(X) is the cumulative n ormal distribution function.
3) Parameters
c is the strike price of the option
ρ is the risk-free interest rate
t0 is the time to the expiry of the option
s is the volatility – the sensitivity of the system to random fluctuations.
All the above parameters can be varied and the option premium graphed as a function of the stock price for any values of the parameters.
III. How the Program Works
1) Functionalities
The Black-Scholes calculator allows the user to set the following parameters:
- The initial stock price
- The volatility
- The interest rate
- The time to expiry
- The strike price
After having set those parameters, you can ask the program to calculate the call and put prices, and display the graph.

2) The BSInit() Function
The main() procedure calls the BSInit() function to perform the initialisation. It initialises the form, the labels, the text boxes (which will contain the parameters set by the user), and the command buttons.
3) The calculate() Function
The calculate() function is called when the users clicks the ‘calculate' button.
SUB calculate()
superbase.processclear()
Superbase.StatusText = "Calculating..."
c% = VAL (myform.strbox.Text)
s0% = VAL (myform.ispbox.Text)
r% = VAL (myform.intbox.Text) / 100
t0% = VAL (myform.expbox.Text) / 12
sigma% = VAL (myform.volbox.Text)
myform.callbox.Text = LTRIM$ ( STR$ (callprice%(c%,s0%,r%,t0%,sigma%)\ ,"99999.00"))
myform.putbox.Text = LTRIM$ ( STR$ (putprice%(c%,s0%,r%,t0%,sigma%)\ ,"99999.00"))
'myform.Page.SetDirtyRect(250,225,330,270)
myform.Refresh()
END SUB
It displays the call and put prices, respectively calling the callprice () and putprice () functions, giving them the parameters set by the user in the text boxes.
4) The callprice% () and putprice% () Functions
The callprice%() and putprice%() functions simply apply the formulae seen in part I:

FUNCTION callprice%(cb%,s0b%,rb%,t0b%,sigmab%)
'calculates the Black-Scholes price for a call option
DIM d1%,d2%
d1% = ( LOG (s0b% / cb%) + (rb% + (sigmab% ^ 2) / 2) * t0b%) / \ (sigmab% * SQR (t0b%))
d2% = ( LOG (s0b% / cb%) + (rb% - (sigmab% ^ 2) / 2) * t0b%) / \ (sigmab% * SQR (t0b%))
callprice% = s0b% * DistNormal(d1%) - cb% * EXP ( - rb% * t0b%)\ * DistNormal(d2%)
END FUNCTION

The DistNormal () function is used to give convenient and rapid access to the cumulative standardised normal distribution function F .
FUNCTION putprice%(cb%,s0b%,rb%,t0b%,sigmab%)
'calculates the Black-Scholes price for a put option
DIM d1%,d2%
d1% = ( LOG (s0b% / cb%) + (rb% + (sigmab% ^ 2) / 2) * t0b%) /\ (sigmab% * SQR (t0b%))
d2% = ( LOG (s0b% / cb%) + (rb% - (sigmab% ^ 2) / 2) * t0b%) /\
(sigmab% * SQR (t0b%))
putprice% = cb% * EXP ( - rb% * t0b%) * DistNormal( - d2%) - \ s0b% * DistNormal( - d1%)
END FUNCTION
5) The graph () Function
This function plots a graph of the call and put prices over a range of stock price values.
SUB graph()
DIM x1%%,y1%%,x2%%,y2%%
'plot a graph of premiums against stock price
'want x range to be zero to (2*strike price)
myform.Tag = ""
CALL calculate()
CALL gclear()
After calling the calculate () function, it calls the gclear () function, which clears the previous (if existing) graph:
SUB gclear()
'Delete the lines from the graph
'NB leave axes and keys in place
Superbase.StatusText = "Clearing graph..."
i%% = 1:flag%% = 0
WHILE flag%% = 0
IF myform.Exists("cline" + STR$ (i%%)) THEN
myform("cline" + STR$ (i%%)).Delete()
myform("pline" + STR$ (i%%)).Delete()
ELSE
flag%% = - 1
END IF
i%% = i%% + 1
WEND
myform.Refresh()
END SUB
Then we draw the axis and scale units:
Superbase.StatusText = "Drawing graph..."
myform.axis1.Visible = - 1
myform.axis2.Visible = - 1
xrange% = 2 * c%
yrange% = callprice%(c%,2 * c%,r%,t0%,sigma%)
xscale% = 450 / xrange%
yscale% = 200 / yrange%
'now put in axis marks at every 10 (on x axis) and 20 (on y axis)
FOR i%% = 1 TO 20
IF myform.Exists("xmk" + STR$ (i%%)) THEN
myform("xmk" + STR$ (i%%)).Delete()
myform("xlb" + STR$ (i%%)).Delete()
END IF
IF myform.Exists("ymk" + STR$ (i%%)) THEN
myform("ymk" + STR$ (i%%)).Delete()
myform("ylb" + STR$ (i%%)).Delete()
END IF
NEXT i%%
nummksx%% = INT (xrange% / 10)
FOR i%% = 1 TO nummksx%%
SET mycontrol = myform.Add("xmk" + STR$ (i%%),"Line")
mycontrol.Move(127 + i%% * 10 * xscale%,500,127 + i%% * 10 *\ xscale%,496)
mycontrol.ForeColor = 1
SET mycontrol = myform.Add("xlb" + STR$ (i%%),"Label")
mycontrol.Move(112 + i%% * 10 * xscale%,501,30,20)
mycontrol.Caption = LTRIM$ ( STR$ (10 * i%%,"999"))
mycontrol.Alignment = 2
mycontrol.BackVisible = 0
NEXT i%%
nummksy%% = INT (yrange% / 20)
FOR i%% = 1 TO nummksy%%
SET mycontrol = myform.Add("ymk" + STR$ (i%%),"Line")
mycontrol.Move(117,496 - 20 * i%% * yscale%,127,496 - 20 * i%%\ * yscale%)
mycontrol.ForeColor = 1
SET mycontrol = myform.Add("ylb" + STR$ (i%%),"Label")
mycontrol.Move(97,486 - 20 * i%% * yscale%,20,20)
mycontrol.Caption = LTRIM$ ( STR$ (20 * i%%,"999"))
mycontrol.BackVisible = 0
NEXT i%%
And now the call and put prices are drawn:
oldx% = 2 / xscale%:oldyc% = callprice%(c%,oldx%,r%,t0%,sigma%)
oldyp% = putprice%(c%,oldx%,r%,t0%,sigma%)
i%% = 1
FOR x% = (2 / xscale%) TO xrange% STEP (2 / xscale%)
SET mycontrol = myform.Add("cline" + STR$ (i%%),"Line")
y% = callprice%(c%,x%,r%,t0%,sigma%)
x1%% = 127 + oldx% * xscale%:y1%% = 496 - oldyc% * yscale%
x2%% = 127 + x% * xscale%:y2%% = 496 - y% * yscale%
mycontrol.Move(x1%%,y1%%,x2%%,y2%%)
mycontrol.ForeColor = 2
oldyc% = y%
SET mycontrol = myform.Add("pline" + STR$ (i%%),"Line")
y% = putprice%(c%,x%,r%,t0%,sigma%)
x1%% = 127 + oldx% * xscale%:y1%% = 496 - oldyp% * yscale%
x2%% = 127 + x% * xscale%:y2%% = 496 - y% * yscale%
mycontrol.Move(x1%%,y1%%,x2%%,y2%%)
mycontrol.ForeColor = 4
oldx% = x%:oldyp% = y%
i%% = i%% + 1
NEXT x%
'Make graph labels and keys visible
myform.axislab.Visible = - 1
myform.yaxislab.Visible = - 1
myform.callkeyline.Visible = - 1
myform.callkeylab.Visible = - 1
myform.putkeyline.Visible = - 1
myform.putkeylab.Visible = - 1
myform.Refresh()
END SUB
|