vba excel: do something every time a certain variable is changed - vba

I'm doing a bunch of stuff to the variable St
For i = 1 To 30000
Randomize
e1 = Rnd
e2 = Rnd
z1 = Sqr(-2 * Log(e1)) * Cos(2 * 3.14 * e2)
z2 = Sqr(-2 * Log(e1)) * Sin(2 * 3.14 * e2)
St = So * Exp((r - (sigma ^ 2) / 2) * T + sigma * Sqr(T) * z1)
C = C + Application.WorksheetFunction.Max(St - K, 0)
St = So * Exp((r - (sigma ^ 2) / 2) * T - sigma * Sqr(T) * z1)
C = C + Application.WorksheetFunction.Max(St - K, 0)
St = So * Exp((r - (sigma ^ 2) / 2) * T + sigma * Sqr(T) * z2)
C = C + Application.WorksheetFunction.Max(St - K, 0)
St = So * Exp((r - (sigma ^ 2) / 2) * T - sigma * Sqr(T) * z2)
C = C + Application.WorksheetFunction.Max(St - K, 0)
Next i
how do I get notified every time the variable changes?

In the Excel VBE, you can add a "watch" to each variable. Select your variable, go to the Debug menu, click Add Watch... and then under Watch Type, click Break When Value Changes.

maybe this a very naive answer but if you make a function that calls the sub then everytime a variable is changed then the function will be reevaluated.

you can use breakpoints or dump St's value after every evaluation to a column on your excel file.
a very annoying solution would be to add message boxes all over the place
yet another clever solution would be to add logic to your code by declarin a variable that would store the previous value of St and then compare against it after the evaluation of the new St

Related

Block If without End If during the barrier option calculation

I am not able to compute the Barrier Option, because it shows me an error in the first line (where I wrote function). The code is as following. Thank you in advance.
Function UOBarrierOption(S As Double, q As Double, T As Double, X As Double, r As Double, _
sigma As Double, CallPutFlag As String, H As Double, K As Double, phi As Double, eta As Double)
Dim x1 As Double, x2 As Double
Dim y1 As Double, y2 As Double
Dim z As Double, mu As Double, lambda As Double
Dim AA As Double, BB As Double, CC As Double, DD As Double, EE As Double, FF As Double
mu = (r - q - sigma ^ 2 / 2) / (sigma ^ 2)
lambda = Sqr(mu ^ 2 + 2 * r / sigma ^ 2)
x1 = Log(S / X) / (sigma * Sqr(T)) + (1 + mu) * sigma * Sqr(T)
x2 = Log(S / H) / (sigma * Sqr(T)) + (1 + mu) * sigma * Sqr(T)
y1 = (Log(H ^ 2) / S / S) / (sigma * Sqr(T)) + (1 + mu) * sigma * Sqr(T)
y2 = (Log(H / S)) / (sigma * Sqr(T)) + (1 + mu) * sigma * Sqr(T)
z = Log(H / S) / (sigma * Sqr(T)) + lambda * sigma * Sqr(T)
AA = phi * S * Exp(-q * T) * Application.NormSDist(phi * x1) - phi * X * Exp(-r * T) * Application.NormSDist(phi * x1 - phi * sigma * Sqr(T))
BB = phi * S * Exp(-q * T) * Application.NormSDist(phi * x2) - phi * X * Exp(-r * T) * Application.NormSDist(phi * x2 - phi * sigma * Sqr(T))
CC = phi * S * Exp(-q * T) * (H / S) ^ (2 * (mu + 1)) * Application.NormSDist(eta * y1) - phi * X * Exp(-r * T) * (H / S) ^ (2 * mu) * Application.NormSDist(eta * y1 - eta * sigma * Sqr(T))
DD = phi * S * Exp(-q * T) * (H / S) ^ (2 * (mu + 1)) * Application.NormSDist(eta * y2) - phi * X * Exp(-r * T) * (H / S) ^ (2 * mu) * Application.NormSDist(eta * y2 - eta * sigma * Sqr(T))
EE = K * Exp(-r * T) * (Application.NormSDist(eta * x2 - eta * sigma * Sqr(T)) - (H / S) ^ (2 * mu) * Application.NormSDist(eta * y2 - eta * sigma * Sqr(T)))
FF = K * Exp(-r * T) * (Application.NormSDist(-eta * x2 + eta * sigma * Sqr(T)) + (H / S) ^ (2 * mu) * Application.NormSDist(eta * y2 - eta * sigma * Sqr(T)))
If CallPutFlag = "Cdi" Then
If X > H Then
UOBarrierOption = CC + EE
ElseIf X < H Then
UOBarrierOption = AA - BB + DD + EE
End Function
ElseIf CallPutFlag = "Cui" Then
If X > H Then
UOBarrierOption = AA + EE
ElseIf X < H Then
UOBarrierOption = BB - CC + DD + EE
End Function
ElseIf CallPutFlag = "Pdi" Then
If X > H Then
UOBarrierOption = BB - CC + DD + EE
ElseIf X < H Then
UOBarrierOption = AA + EE
End Function
ElseIf CallPutFlag = "Pui" Then
If X > H Then
UOBarrierOption = AA - BB + DD + EE
ElseIf X < H Then
UOBarrierOption = CC + EE
End Function
ElseIf CallPutFlag = "Cdo" Then
If X > H Then
UOBarrierOption = AA - CC + FF
ElseIf X < H Then
UOBarrierOption = BB - DD + FF
End Function
ElseIf CallPutFlag = "Cuo" Then
If X > H Then
UOBarrierOption = F
ElseIf X < H Then
UOBarrierOption = AA - BB + CC - DD + FF
End Function
ElseIf CallPutFlag = "Pdo" Then
If X > H Then
UOBarrierOption = AA - BB + CC - DD + FF
ElseIf X < H Then
UOBarrierOption = F
End Function
ElseIf CallPutFlag = "Puo" Then
If X > H Then
UOBarrierOption = BB - DD + FF
ElseIf X < H Then
UOBarrierOption = AA - CC + FF
End Function
End If
End Function
P.S. I have different "phi"s and "eta"s for different types of option barriers (cdi, pdi and etc.). Right now I am trying different combinations, but it also gives "end if function missing" type of error
If your function returns something you must declare the type returned in the function, and assign the returned value to the function, for exmaple:
Function CalculateSquareRoot(NumberArg As Double) As Double
If NumberArg < 0 Then ' Evaluate argument.
Exit Function ' Exit to calling procedure.
Else
CalculateSquareRoot = Sqr(NumberArg) ' Return square root.
End If
End Function
See the As Double and the CalculateSquareRoot = Sqr(NumberArg). That is what the function returns.
If it does not return anything, and its just a method, you should declare it with Sub().
Sub()
'your method
End Sub

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

Binomial European Options Pricing Model

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.

I Keep getting a #value error in Excel VBA

So I wrote a quick function in VBA for Excel, but every time I call it, it gives me a #value error. I don't know what I am doing wrong. Can anyone help?
Function h(UA, k, A, Af_At, Delta, l)
h1 = 0
m = (2 * h1 / k / Delta) ^ 0.5
ml = m * l
Nf = WorksheetFunction.Tanh(ml)
No = 1 - Af_At * (1 - Nf / ml)
UA1 = h1 * A * No / 2
While UA > UA1
UA_old = UA1
h_old = h1
h1 = h1 + 0.5
m = (2 * h1 / k / Delta) ^ 0.5
ml = m * l
Nf = WorksheetFunction.Tanh(ml)
No = 1 - Af_At * (1 - Nf / ml)
UA1 = h1 * A * No / 2
Wend
h = h_old + (UA - UA_old) * (h1 - h_old) / (UA1 - UA_old)
End Function
I call it using: =h(10,1,1,1,1,1) in the insert function bar.
Division by zero at
No = 1 - Af_At * (1 - Nf / ml)
m1 is zero because h1 is zero.
You should change:
h1 = 0

Algorithm For Finding Greenwich Mean Sidereal Time Having Problems

I have currently gotten an algorithm to work for finding the Julian Day for my current location, but when using this value to proceed in finding the Greenwich Mean Sidereal Time, I get some very funky numbers. Can anyone run this script and maybe determine where my calculations go wrong? Thanks.
#1/user/bin/python
import math
from time import gmtime, strftime
#Sidereal Time Program
#Julien Date Converter
seconds = (int(strftime("%S")) * .01)
JD1 = ((367 * (int(strftime("%Y")))) - ((7 * ((int(strftime("%Y")))
+ (((int(strftime("%m"))) + 9) / 12))) / 4)
+ ((275 * (int(strftime("%m")))) / 9) + (int(strftime("%d"))) + 1721013.5
+ ((int(strftime("%I")) + (seconds) + 4) / 24) - 0.5 + 0.5 + 1.46)
JD2 = ((367 * (int(strftime("%Y")))) - ((7 * ((int(strftime("%Y")))
+ (((int(strftime("%m"))) + 9) / 12))) / 4)
+ ((275 * (int(strftime("%m")))) / 9) + (int(strftime("%d"))) + 1721013.5
+ ((int(12) + 4) / 24) - 0.5 + 0.5 - 0.192361555)
H = JD1 - JD2
JD = JD2 + (H / 24)
D1 = JD1 - 2451545.0
D2 = JD2 - 2451545.0
T = D1 / 36525
GMST1 = 6.697374558 + (0.06570982441908 * D2) + (1.00273790935 * H) + (0.000026 * (T * T))
GMST2 = 18.697374558 + (24.06570982441908 * D1)
o = 125.04 - (0.052954 * D1)
L = 280.47 + (0.98565 * D1)
e = 23.4393 - (0.0000004 * D1)
x = 2 * L
sym = (-0.000319 * (math.sin (o))) - (0.000024 * (math.sin (x)))
eqeq = (sym * (math.cos (e)))
GAST1 = GMST1 + eqeq
GAST2 = GMST2 +eqeq
print (JD1)
print (T)
print (GAST1)
print (GAST2)
Edit: Here is the formula I am using: http://aa.usno.navy.mil/faq/docs/GAST.php
It appears that this is a package that will do what you want. See, e.g., here.