Binomial European Options Pricing Model - vba

I created a program, using VBA, to calculate the European Call option price, as follows:
Private Sub CallPrice_Click()
Dim K As Single
Dim So As Single
Dim r As Single
Dim T As Single
Dim sigma As Single
Dim u As Single
Dim d As Single
Dim p As Single
Dim CP As Single
Dim M As Single
Dim S As Single
Dim CB As Double
Dim n As Integer
Dim i As Integer
K = Cells(2, 2)
So = Cells(3, 2)
r = Cells(4, 2)
T = Cells(5, 2)
sigma = Cells(6, 2)
n = Cells(7, 2)
u = Exp(sigma * Sqr(T / n))
d = 1 / u
p = (Exp(r * T / n) - d) / (u - d)
CP = 0
For i = 0 To n Step 1
M = WorksheetFunction.Max(So * (u ^ i) * d ^ (n - i) - K, 0)
CB = WorksheetFunction.Combin(n, i)
S = M * CB * (p ^ n) * (1 - p) ^ (n - i)
CP = CP + S
Next i
Cells(9, 2) = CP / (1 + r) ^ n
End Sub
Here is the layout of the spreadsheet:
When I ran the program, the error occurred.
Could someone here explain what is wrong in my program and how to fix it?

Is your equation for S correct? It seems like it should be:
S = M * CB * (p ^ i) ...
instead of
S = M * CB * (p ^ n) ...
If your equation is indeed wrong, then you can use BINOMDIST instead of COMBIN, because by definition:
Binom_Dist(i, n, p, False) = (p ^ i) * (1 - p) ^ (n - i) * Combin(n, i)
So your code would be:
S = M * WorksheetFunction.Binom_Dist(i, n, p, False)
instead of
CB = WorksheetFunction.Combin(n, i)
S = M * CB * (p ^ n) * (1 - p) ^ (n - i)
BINOMDIST is not as sensitive to large n, i.

You are getting an overflow error. If you check on a work sheet:
COMBIN(5000, 161) = 3.3E+307
COMBIN(5000, 162) = #NUM!
COMBIN(5000, 4838) = #NUM!
COMBIN(5000, 4839) = 3.3E+307
Remember that the number of combinations increases exponentially up until the halfway point in which it will start to go down at an inverse rate.

Related

I need to solve an implicit equation in VBA

I want to give the other parameters that are mentioned in the function, and get a solution for a (the angle), but I get error: "invalid procedure call or argument" Run-time error 5.
I need to call the function in excel worksheet. It is a pretty long equation. Also, it could be that I enter a infinite loop but I don't know how to avoid that.
Function calculateangle(r, h, C, g, d, m, t, x, y As Single) As Single
Dim a As Single
a = 0
While y <> (d + r - r * Cos(a) + (x - (t - r + r * Sin(a))) * Tan(a) - (g
/ (2 * ((((C * m * (2 * g * (h - (d + r - r * Cos(a)))) ^
(1 / 2)) + m * (2 * g * (h - (d + r - r * Cos(a)))) ^ (1 / 2)) / (m +
0.04593)) ^ 2) * (Cos(a)) ^ 2)) * (x - (t - r + r * Sin(a))) ^ 2)
a = a + 0.01
Wend
MsgBox Round(a, 2)
End Function
One obvious issue is that you are using a Function but not returning a value.
This really is a complex piece of spaghetti! However, I suggest an approach like below which will help separate out various bits and thus make it easier to do debugging
Function calculateangle(<...all the bits ...>) As Double
Dim a As Double
Dim tTolerance as Double
dim f1 as Double ' sub sections to help untangle the spaghetti
Dim f2 as Double
Dim f3 as Double
Dim fFinal as Double
Dim tWithinTolerance as Boolean
tWithinTolerance = false
a = 0
tTolerance = 0.01
While not tWithinTolerance
f1 = d + r - r * Cos(a)
f2 = m*2*g*(h - f1)
f3 = x - (t - r + r * Sin(a))
fFinal = (f1 + f3 * Tan(a) - (g / (2 * ((((C * f2) ^
(1 / 2)) + f2 ^ (1 / 2)) / (m + 0.04593)) ^ 2) * (Cos(a)) ^ 2)) * f3 ^ 2)
tWithinTolerance = (Abs(y - fFinal) < tTolerance)
a = a + 0.01
Wend
Calculateangle = a ' note how this sets a return value for the function
End Function
I have left the rounding (which is a presentation issue) to the code that calls this function - this way you can display the answer to whatever level of detail you want!
(apologies if I have mangled any of the calculation on the way through - but you get the concept!)
For the author and those who want to deal with his solitaire. I hope I did not confuse anything in parentheses and simplifications.
Do
vCosA = Cos(a)
vCosADR = d + r * (1 - vCosA) ' d + r - r * vCosA '
vCosMGHADR = m * (2 * g * (h - vCosADR))
vSinAXTR = (x - (t - r * (1 - Sin(a)))) ' - r + r * Sin(a)
'((C * vCosMGHADR) + vCosMGHADR) == ((C + 1) * vCosMGHADR)
If (y = _
(vCosADR + vSinAXTR * Tan(a) - _
(g / _
(2 * _
( _
( _
((C + 1) * vCosMGHADR) / _
(m + 0.04593) _
) ^ 2 _
) * (vCosA ^ 2) _
) _
) * vSinAXTR ^ 2 _
)) Then Exit Do ' *** EXIT DO ***
a = a + 0.01
Loop

VBA root finding trough bisection

My vba code keeps returning a value of 0 when I know the roots of my function are not 0.
It's pretty simple code but I can't seem to debug it. Any idea where this error might be coming from??
Option Explicit
Public Function Bisect(ByVal xlow As Double, ByVal xhigh As Double) As Double
Dim i As Integer
Dim xmid As Double
xmid = (xlow + xhigh) / 2
For i = 1 To 100
If f(xlow) * f(xmid) < 0 Then
xhigh = xmid
xmid = (xlow + xhigh) / 2
Else
xlow = xmid
xmid = (xlow + xhigh) / 2
End If
Next i
Bisect = xmid
End Function
Function f(ByVal x As Double, Optional ByRef inputArray As Range) As Variant
Dim ca0 As Double
Dim v0 As Double
Dim k As Double
Dim e As Double
Dim ac As Double
Dim L As Double
inputArray(2, 2) = ca0
inputArray(3, 2) = v0
inputArray(4, 2) = k
inputArray(5, 2) = e
inputArray(6, 2) = ac
inputArray(7, 2) = L
f(x) = (v0 / (k * ca0 * ac)) * ((2 * e * (1 + e) * Log(1 - x)) + (e ^ 2 * x) + (((1 + e) ^ 2 * x) / (1 - x))) - L
End Function
' i Think you want to take those constant values from cells presentin the sheet
Function f(ByVal x As Double) As Variant
Dim inputArray As Range
Dim ca0 As Double
Dim v0 As Double
Dim k As Double
Dim e As Double
Dim ac As Double
Dim L As Double
' i Think you want to take values from cells in the sheet
ca0 = ActiveSheet.Cells(2, 2).Value
v0 = ActiveSheet.Cells(3, 2).Value
k = ActiveSheet.Cells(4, 2).Value
e = ActiveSheet.Cells(5, 2).Value
ac = ActiveSheet.Cells(6, 2).Value
L = ActiveSheet.Cells(7, 2).Value
Could it be that you try to assign the inputarray with empty variables?
In my mind it should be:
ca0 = inputArray(2, 2)
v0 = inputArray(3, 2)
And so on.
I'm guessing
f(x) = (v0 / (k * ca0 * ac)) * ((2 * e * (1 + e) * Log(1 - x)) + (e ^ 2 * x) + (((1 + e) ^ 2 * x) / (1 - x))) - L
Should be
f = (v0 / (k * ca0 * ac)) * ((2 * e * (1 + e) * Log(1 - x)) + (e ^ 2 * x) + (((1 + e) ^ 2 * x) / (1 - x))) - L

Formula error after file save from network to local

I have issue with an Excel worksheet that contains the formula:
=Spline($D$9:$D$34,$J$9:$J$34,$D43)
Sheet works fine until I open this sheet on network drive and save it on local drive. Then this formula throws #NAME? error. Strange is, that error is gone when I click on line with formula to edit it and press enter (nothing changes in formula).
Have someone met similar issue?
I just found another information. Formula spline is defined in VBA module, not internal in Excel. It looks like. But issue is still here.
Function spline(periodcol As Range, ratecol As Range, x As Range)
Dim period_count As Integer
Dim rate_count As Integer
period_count = periodcol.Rows.Count
rate_count = ratecol.Rows.Count
If period_count <> rate_count Then
spline = "Error: Range count does not match"
GoTo endnow
End If
ReDim xin(period_count) As Single
ReDim yin(period_count) As Single
Dim c As Integer
For c = 1 To period_count
xin(c) = periodcol(c)
yin(c) = ratecol(c)
Next c
Dim n As Integer
Dim i, k As Integer
Dim p, qn, sig, un As Single
ReDim u(period_count - 1) As Single
ReDim yt(period_count) As Single
n = period_count
yt(1) = 0
u(1) = 0
For i = 2 To n - 1
sig = (xin(i) - xin(i - 1)) / (xin(i + 1) - xin(i - 1))
p = sig * yt(i - 1) + 2
yt(i) = (sig - 1) / p
u(i) = (yin(i + 1) - yin(i)) / (xin(i + 1) - xin(i)) - (yin(i) - yin(i - 1)) / (xin(i) - xin(i - 1))
u(i) = (6 * u(i) / (xin(i + 1) - xin(i - 1)) - sig * u(i - 1)) / p
Next i
qn = 0
un = 0
yt(n) = (un - qn * u(n - 1)) / (qn * yt(n - 1) + 1)
For k = n - 1 To 1 Step -1
yt(k) = yt(k) * yt(k + 1) + u(k)
Next k
Dim klo, khi As Integer
Dim h, b, a As Single
klo = 1
khi = n
Do
k = khi - klo
If xin(k) > x Then
khi = k
Else
klo = k
End If
k = khi - klo
Loop While k > 1
h = xin(khi) - xin(klo)
a = (xin(khi) - x) / h
b = (x - xin(klo)) / h
y = a * yin(klo) + b * yin(khi) + ((a ^ 3 - a) * yt(klo) + (b ^ 3 - b) * yt(khi)) * (h ^ 2) / 6
spline = y
endnow:
End Function
Try to add:
Application.Volatile
to your VBA code. Add this just below the Function statement to force a renewed calculation as soon as anything changes.

run time error 5 in VBA excel when working with array

I use vba on excel 2007, OS: windows vista, to make calculation using kinematic wave equation in finite difference scheme. But, when it runs the run-time 5 (invalid procedure call or arguments) message appears. I really don't what is going wrong. Anyone can help?
Sub kwave()
Dim u(500, 500), yy(500, 500), alpha, dt, dx, m, n, so, r, f, X, L, K As Single
Dim i, j As Integer
dx = 0.1
dt = 0.01
L = 10
m = 5 / 3
r = 1
f = 0.5
n = 0.025
so = 0.1 'this is slope
alpha = 1 / n * so ^ 0.5
X = 0
For i = 0 To 100
Cells(i + 1, 1) = X
u(i, 1) = L - so * X
X = X + dx
Cells(i + 1, 2) = u(i, 1)
Next i
For j = 0 To 100
For i = 1 To 100
'predictor step
u(i, j + 1) = u(i, j) - alpha * dt / dx * (u(i + 1, j) ^ m - u(i, j) ^ m) + (r - f) * dt
'corrector step
K = u(i, j + 1) ^ m - u(i - 1, j + 1) ^ m '<<<<----- RUNTIME ERROR 5 HAPPENS AT THIS LINE
yy(i, j + 1) = 0.5 * ((yy(i, j) + u(i, j + 1)) - alpha * dt / dx * K + (r - f) * dt)
Next i
Next j
End Sub
You are declaring the variables wrong- the array should store a double/single but it is defaulting to a variant. See this article.
http://www.cpearson.com/excel/declaringvariables.aspx -
"Pay Attention To Variables Declared With One Dim Statement
VBA allows declaring more than one variable with a single Dim
statement. I don't like this for stylistic reasons, but others do
prefer it. However, it is important to remember how variables will be
typed. Consider the following code:
Dim J, K, L As Long You may think that all three variables are
declared as Long types. This is not the case. Only L is typed as a
Long. The variables J and K are typed as Variant. This declaration is
functionally equivalent to the following:
Dim J As Variant, K As Variant, L As Long You should use the As Type
modifier for each variable declared with the Dim statement:
Dim J As Long, K As Long, L As Long "
Additionally, when i = 99 and j = 10, u(99,11), which is j+1, produces a negative number. Note that this does not fully cause the problem though, because you can raise negative numbers to exponents. Ex, -5^3 = -125

The results of my functions when I call a spline function gives wrong values

I have a function that only call the spline function when something happens..in this case when a division is less than zero..the inputs for the function is the same that for the spline function(called CUBIC), the spline was tested and works well when I call it direct! someone can help me?...follows a party of the code
Function NDF6(T As Variant, dias As Variant, taxas As Variant)
If T <= dias(1) Then
NDF6 = taxas(1)
Exit Function
End If
If T >= dias(tam) Then
NDF6 = taxas(tam)
Exit Function
End If
For i = 1 To tam
If T <= dias(i) Then
If taxas(i) / taxas(i - 1) < 0 Then
Call CUBIC(T, dias, taxas)
Else
i0 = ((taxas(i - 1) * dias(i - 1)) / 360) + 1
i1 = ((taxas(i - 1) * dias(i - 1)) / 360) + 1
irel = i1 / i0
i2 = irel ^ ((T - dias(i - 1)) / (dias(i) - dias(i - 1)))
i2rel = i2 * i0
i2real = i2rel - 1
NDF6 = i2real * (360 / T)
End If
Public Function CUBIC(x As Variant, input_column As Variant, output_column As Variant)
The function returns a zero value when I call the cubic function. The inputs are a cell with a value with a value equivalent a day and two arrays(DUONOFF and ONOFF) equivalent a days and rates, I call the function like:
NDF6(512,DUONOFF,ONOFF)
follows the CUBIC function
Public Function CUBIC(x As Variant, input_column As Variant, output_column As Variant)
'Purpose: Given a data set consisting of a list of x values
' and y values, this function will smoothly interpolate
' a resulting output (y) value from a given input (x) value
' This counts how many points are in "input" and "output" set of data
Dim input_count As Integer
Dim output_count As Integer
input_count = input_column.Rows.Count
output_count = output_column.Rows.Count
Next check to be sure that "input" # points = "output" # points
If input_count <> output_count Then
CUBIC = "Something's messed up! The number of indeces number of output_columnues don't match!"
GoTo out
End If
ReDim xin(input_count) As Single
ReDim yin(input_count) As Single
Dim c As Integer
For c = 1 To input_count
xin(c) = input_column(c)
yin(c) = output_column(c)
Next c
values are populated
Dim N As Integer 'n=input_count
Dim i, k As Integer 'these are loop counting integers
Dim p, qn, sig, un As Single
ReDim u(input_count - 1) As Single
ReDim yt(input_count) As Single 'these are the 2nd deriv values
N = input_count
yt(1) = 0
u(1) = 0
For i = 2 To N - 1
sig = (xin(i) - xin(i - 1)) / (xin(i + 1) - xin(i - 1))
p = sig * yt(i - 1) + 2
yt(i) = (sig - 1) / p
u(i) = (yin(i + 1) - yin(i)) / (xin(i + 1) - xin(i)) - (yin(i) - yin(i - 1)) / (xin(i) - xin(i - _1))
u(i) = (6 * u(i) / (xin(i + 1) - xin(i - 1)) - sig * u(i - 1)) / p
Next i
qn = 0
un = 0
yt(N) = (un - qn * u(N - 1)) / (qn * yt(N - 1) + 1)
For k = N - 1 To 1 Step -1
yt(k) = yt(k) * yt(k + 1) + u(k)
Next k
now eval spline at one point
Dim klo, khi As Integer
Dim h, b, a As Single
first find correct interval
klo = 1
khi = N
Do
k = khi - klo
If xin(k) > x Then
khi = k
Else
klo = k
End If
k = khi - klo
Loop While k > 1
h = xin(khi) - xin(klo)
a = (xin(khi) - x) / h
b = (x - xin(klo)) / h
y = a * yin(klo) + b * yin(khi) + ((a ^ 3 - a) * yt(klo) + (b ^ 3 - b) * yt(khi)) * (h ^ 2) _/ 6
CUBIC = y
out:
End Function