Compile error of erfc function - excel

I tried to use erfc but it says argument not optional.
An example is given below
For j = 0 To 150
f = 1
For m = 1 To j
f = f * m
Next
Application.WorksheetFunction.Erf = (Application.WorksheetFunction.Erf) + (-1) ^ j * b ^ (2 * j + 1) / ((2 * j + 1) * f)
Next
Application.WorksheetFunction.ErfC = 1 - 2 / Sqr(3.14) * Application.WorksheetFunction.Erf
MsgBox (Application.WorksheetFunction.ErfC)
xf1 = (wa + 2 * sp) * q / (4 * cl ^ 2 * 3.14 * hf)
xf2 = Exp(b ^ 2) * Application.WorksheetFunction.ErfC
xf3 = 2 * b / Sqr(3.14) - 1
xf = xf1 * (xf2 + xf3)

According to the MSDN documentation at least one parameter needs to be passed to the Erf method:
Name Required/Optional Data Type Description
Arg1 Required Variant Lower_limit - the lower bound for integrating ERF.
Arg2 Optional Variant Upper_limit - the upper bound for integrating ERF.
If omitted, ERF integrates between zero and
lower_limit.
Therefore, calling it with zero parameters (e.g. Application.WorksheetFunction.Erf) will give you an "argument not optional" error.
You also won't be able to set Erf to a value, i.e.
Application.WorksheetFunction.Erf = ...
is invalid.

Related

Rearrange equation to solve for a different variable

I am looking at VBA code (function) written by someone else.
Here is the code:
Function EuropeanDelta(StrikePrice, MarketPrice, Volatility, InterestRate As Double, PC As String, ValueDate, ExpiryDate As Date, Optional PriceOrYield As String = "P") As Double
Rem Declare our working variables
Dim r As Double
Dim d1 As Double
Dim d2 As Double
Dim t As Double
Dim SqT As Double
Rem End of variable declaration
If PriceOrYield = "Y" Then
MarketPrice = 100 - MarketPrice
StrikePrice = 100 - StrikePrice
If PC = "C" Then
PC = "P"
Else
PC = "C"
End If
End If
Rem Initiase our working variables
t = (ExpiryDate - ValueDate) / 365
SqT = Sqr(t)
r = Application.WorksheetFunction.Ln(1 + InterestRate)
d1 = (Application.WorksheetFunction.Ln(MarketPrice / StrikePrice) + (Volatility * Volatility * 0.5) * t) / (Volatility * SqT)
Rem Quick logic to deal with Calls or Puts
If PC = "C" Then
EuropeanDelta = Exp(-r * t) * Application.WorksheetFunction.NormSDist(d1)
Else
EuropeanDelta = -Exp(-r * t) * Application.WorksheetFunction.NormSDist(-d1)
End If
If PriceOrYield = "Y" Then
EuropeanDelta = EuropeanDelta * -1
End If
End Function
The whole problem is based around the line for "d1". I would like to re-organise to solve for "StrikePrice". I have tried writing it out mathematically and then re-arranging, then swapping back to VBA.
#duffymo is correct, but am giving the answer directly in terms of VBA code
' d1 = (Log(MarketPrice / StrikePrice) + (Volatility * Volatility * 0.5) * t) / (Volatility * Sqr(t))
'
' Volatility * Sqr(t) * d1 = Log(MarketPrice / StrikePrice) + Volatility^2 * t/2
'
' Log(MarketPrice / StrikePrice) = Volatility * Sqr(t) * d1 - Volatility^2 * t/2
'
' MarketPrice / StrikePrice = Exp(Volatility * Sqr(t) * d1 - Volatility^2 * t/2)
'
StrikePrice = MarketPrice / Exp(Volatility * Sqr(t) * d1 - Volatility^2 * t/2)
Other Notes :
For brevity replace Application.WorksheetFunction.Ln() with Log()
There is no need cache SqT = Sqr(t) since it is only used once.
For clarity replace Volatility*Volatility with Volatility^2 as internally it does the same thing.
This is just algebra - high school math.
Take it in steps. Make sure you do the same operation to both sides to make sure that equality still holds.
Here's your starting equation:
d = {ln(m/s) + v*v*t/2}/(v*sqrt(t))
Multiply both sides by the denominator of the RHS:
d*v*sqrt(t) = ln(m/s) + v*v*t/2
Subtract v*v*t/2 from both sides:
(d*v*sqrt(t) - v*v*t/2) = ln(m/s)
Apply the exponential function to both sides, noting that exp(ln(x)) = x:
exp(d*v*sqrt(t) - v*v*t/2) = m/s
Multiply both sides by s:
s*exp(d*v*sqrt(t) - v*v*t/2) = m
Divide both sides by exp(d*v*sqrt(t) - v*v*t/2) to get the desired result:
s = m/exp(d*v*sqrt(t) - v*v*t/2)
Let's see if this function makes sense.
At t = 0 the denominator exp(0) = 1, so the strike price is equal to the market price.
As t -> infinity, we hope that the denominator gets large so s -> zero. L'Hospital's Rule will help here.

How to update an old vba code to work on excel?

I have this code from an old book that does not work in my Excel. It is supposed to calculate the slope and intercept of a Deming regression from a range of numbers, x and y
Function Deming(XValues, YValues)
Dim MeanX(), MeanY()
Ncells = XValues.Count
ReDim MeanX(Ncells / 2), MeanY(Ncells / 2)
For x = 2 To Ncells Step 2
MeanX(x / 2) = (XValues(x - 1) + XValues(x)) / 2
MeanY(x / 2) = (YValues(x - 1) + YValues(x)) / 2
SumX = SumX + MeanX(x / 2): SumY = SumY + MeanY(x / 2)
SumX2 = SumX2 + (MeanX(x / 2)) ^ 2
SumY2 = SumY2 + (MeanY(x / 2)) ^ 2
SumXY = SumXY + MeanX(x / 2) * MeanY(x / 2)
SumDeltaX2 = SumDeltaX2 + (XValues(x - 1) - XValues(x)) ^ 2
SumDeltaY2 = SumDeltaY2 + (YValues(x - 1) - YValues(x)) ^ 2
Next
XBar = SumX / N: YBar = SumY / N
Sx2 = (N * SumX2 - SumX ^ 2) / (N * (N - 1))
Sy2 = (N * SumY2 - SumY ^ 2) / (N * (N - 1))
Sdx2 = SumDeltaX2 / (2 * N)
Sdy2 = SumDeltaY2 / (2 * N)
rPearson = (N * SumXY - SumX * SumY) / Sqr((N * SumX2 - SumX ^ 2) * (N *
SumY2 - SumY ^ 2))
lambda = Sdx2 / Sdy2
U = (Sy2 - Sx2 / lambda) / (2 * rPearson * Sqr(Sx2) * Sqr(Sy2))
Slope = U + Sqr(U ^ 2 + 1 / lambda)
Intercept = YBar - Slope * XBar
Deming = Array(Slope, Intercept)
End Function
Does this have a bad syntax or not?
First this is not old code, this is simply bad code.
Anything in VBA, which does not compile, when someone writes Option Explicit on the top of the Module/Worksheet is a bad syntax. This is a rule of a thumb. And in the case of the code, if this one is pasted to the editor the following line is red:
rPearson = (N * SumXY - SumX * SumY) / Sqr((N * SumX2 - SumX ^ 2) * (N *
SumY2 - SumY ^ 2))
This is because it should be in 1 line, and not in 2.
So, concerning the question - how to update it - as a first step, make sure the code compiles with Option Explicit on top (Option Explicit statement). So, write Option Explicit and then go to Debug>Compile on the VBEditor's ribbon. VBeditor will highlight the problem. The first one is that Ncell is not defined:
Then find a way to define it, e.g. write Dim Ncells as Variant or as anything else you may consider useful on the top of the highligted line. It could be that just declaring a variable is not enough, as there is a calculation XBar = SumX / N in the code. There, N should be declared and assigned to a value. If it is only declared, it will be 0, and then a division by 0 will be an error. Thus, probably something like this should be written, depending on the logic: Dim N as Double: N = 1

Mathematics - Distribute a list of numbers over an interval

My problem is simple.
I am searching a mathematical function to distribute number over an interval.
For example I have this list :
[2; 4; 9; 14]
And in my case I wish
2 -> 1 = f(2)
14 -> 20 = f(14)
4 -> f(4) = ?
9 -> f(9) = ?
This is just an example I am searching for f(x).
Someone would have any idea ?
Thanks for advance ! :)
If you want a linear function, then:
f(x) = lowerFunc + (x - lowerX) * (upperFunc - lowerFunc) / (upperX - lowerX),
where:
lowerFunc: function value at the lower end
upperFunc: function value at the upper end
lowerX: x parameter at the lower end
upperX: x parameter at the upper end.
For your example:
f(x) = 1 + (x - 2) * (20 - 1) / (14 - 2)
= 1 + (x - 2) * 19/12
f(2) = 1
f(4) = 4.1666
f(9) = 12.08333
f(14) = 20

How to return value in Excel UDF Function?

I got some code written in a function in VBA, but I'm stuck on how to return the output values areaAnswer1 & areaAnswer2 inside the if - else statments. I'm still new to this. Any help & suggestions are very much appreciated.
Function dateArea(inputDate1 As Date, t1 As Date, t2 As Date, duration As Integer, output As Integer) As Integer
endOfYear = Workbook.Date(Year(inputDate1), 12, 31)
inputDate2 = Workbook.Date(Year(inputDate1) + 1, Month(inputDate1), Day(inputDate1))
endOfDate1 = Workbook.Date(Year(inputDate1) + duration, Month(inputDate1), Day(inputDate1))
endOfDate2 = Workbook.Date(Year(inputDate2) + duration, Month(inputDate2), Day(inputDate2))
areaBase1 = endOfYear - inputDate1
areaBase2 = inputDate2 - endOfYear
totalArea1 = areaBase1 * 365
totalArea2 = areaBase2 * 365
triangleBase1 = endOfDate1 - inputDate1
triangleHypo1 = Workbook.Sqrt((365 * 365) + (triangleBase1 * triangleBase1))
triangleBase2 = t1 - inputDate2
triangleHypo2 = triangleHypo1 * triangleBase2 / triangleBase1
triangleHeight2 = Workbook.Sqrt((triangleHypo2 * triangleHypo2) - (triangleBase2 * triangleBase2))
triangleArea2 = (triangleBase2 * triangleHeight2) / 2
triangleBase3 = (inputDate2 - endOfYear) + (t1 - inputDate2)
triangleHypo3 = triangleBase3 * triangleHypo2 / (t1 - inputDate2)
triangleHeight3 = Workbook.Sqrt((triangleHypo3 * triangleHypo3) - (triangleBase3 * triangleBase3))
triangleArea3 = (triangleBase3 * triangleBaseHeight3) / 2
areaDiffBot2 = triangleArea3 - triangleArea2
triangleBase4 = 365 + (t1 - inputDate2)
triangleHypo4 = triangleBase4 * triangleHeight2 / (t1 - inputDate2)
triangleHeight4 = Workbook.Sqrt((triangleHypo4 * triangleHypo4) - (triangleBase4 * triangleBase4))
triangleArea4 = (triangleBase4 * triangleHeight4) / 2
areaDiffBot1 = triangleArea4 - triangleArea3
triangleHeight5 = 365 * (endOfDate1 - t2) / triangleBase1
triangleHypo5 = Workbook.Sqrt((triangleHeight5 * triangleHeight5) + ((endOfDate1 - t2) * (endOfDate1 - t2)))
triangleArea5 = (endOfDate1 - t2) * triangleHeight5 / 2
triangleBase6 = (endOfDate1 - t2) + areaBase1
triangleHeight6 = (triangleBase6) * 365 / (endOfDate1 - t2)
triangleHypo6 = Workbook.Sqrt((triangleBase6 * triangleBase6) + (triangleHeight6 * triangleHeight6))
triangleArea6 = (triangleBase6 * triangleHeight6) / 2
areaDiffTop1 = triangleArea6 - triangleArea5
triangleBase7 = triangleBase6 + areaBase2
triangleHeight7 = triangleBase7 * triangleHeight6 / triangleBase6
triangleHypo7 = Workbook.Sqrt((triangleBase7 * triangleBase7) + (triangleHeight7 * triangleHeight7))
triangleArea7 = (triangleBase7 * triangleHeight7) / 2
areaDiffTop2 = triangleArea7 - triangleArea6
totalUsedArea1 = areaDiffTop1 + areaDiffBot1
totalUsedArea2 = areaDiffTop2 + areaDiffBot2
areaAnswer1 = totalArea1 - totalUsedArea1
areaAnswer2 = totalArea2 - totalUsedArea2
If output = 1 Then
ElseIf output = 2 Then
ElseIf output = 3 Then
Else
End If
End Function
In VBA you set the return value by assigning it to the function like this:
areaAnswer1 = totalArea1 - totalUsedArea1
areaAnswer2 = totalArea2 - totalUsedArea2
If output = 1 Then
dateArea = areaAnswer1
ElseIf output = 2 Then
dateArea = areaAnswer2
ElseIf output = 3 Then
' ...etc
Note that the assignment to the function does not exit the function. In this case you don't need that immediate exit, as you are already at the end of it. But in some cases you'll want to exit the function as soon as you have assigned the return value:
Exit Function
Just have the function equal a typed value or one of the variables at the end.
select case output
case 1
dateArea = totalUsedArea1
case 2
dateArea = totalUsedArea2
case 3
dateArea = totalUsedArea3
case else
'do something or nothing
end select
Note that you have specified returning an integer which cannot contain a decimal and must be smaller than 32667 (or there abouts).

Recursion code in VBA

I am trying to run this code to calculate Q(n) at different Tn in the Equation 16.4 in the attached picture.But its not giving me the correct output. I would appreciate any help. Note: delta1=delta2 =...deltan = dt=1 ( I have taken here ) and further divided S term by 10000 just because in the Equation it is in basis point i.e. 100th part of 1 %.
Function Bootstrap(S As Range, Z As Range, L As Double) As Double
Dim j As Integer
Dim a As Variant
Dim b As Variant
Dim n As Integer
Dim Q() As Double
Dim sum As Double
Dim P As Double
Dim dt As Double
n = Application.WorksheetFunction.Max(S.Columns.Count, Z.Columns.Count)
a = S.Value
b = Z.Value
dt = 1
sum = 0
ReDim Q(0 To n)
Q(0) = 1
For j = 1 To n - 1
P = (b(1, j) * (L * Q(j - 1) - (L + dt * a(1, n) / 10000) * Q(j))) / (b(1, n) * (L + a(1, n) * dt / 10000)) + Q(n - 1) * L / (L + a(1, n) * dt / 10000)
sum = sum + P
Q(n) = sum
Next j
Bootstrap = sum
End Function
To solve a recursive function you can write it this way, for example
Function Factorial(n as long) as long
If n = 1 Then
Factorial = 1
Else
Factorial = n * Factorial(n-1)
End If
End function
Yes, you can see For...Loop can also do the Factorial calculation, but in your case, its much easier to use recursive solution.
Besides Eq 16.4 is intentionally written as a recursive function. It is not written as a summation function because it is harder to do so. If given to you is a summation function, then you can apply the For...Loop solution.
Hope this helps.
EDIT
Function Q(n as long) as double
If n = 1 Then
Q = 5
Else
Q = Z * ( L * Q_t - (L + d * S) * Q(n-1) ) / ( Z * ( L + d * S ) )
End If
End Function
Notice that the function Q keep calling itself in Q(n-1) when n>1. That is called recursive solution.
(Check the formula. I might copy it wrong)

Resources