I have the following code and I get the following error:
Compile error, variable not found (it is not able to find j)
Also, even though I provide MktVol as a vector of length 4, the message box returns N=0
Can you please help me fix my mistake.
Public Function EstimateAllParameters(params, MktStrike, MktVol, F, T, b)
Dim R As Double, a As Double, V As Double, N As Integer
Dim j as integer 'stops the compile error but the function returns #VALUE!
Dim ModelVol() As Double, sqdError() As Double
R = params(1)
V = params(2)
a = params(3)
N = MktVol.Length
MsgBox ("N= " & N)
For j = 1 To N
ModelVol(j) = Svol(a, b, R, V, F, MktStrike(j), T)
sqdError(j) = (ModelVol(j) - MktVol(j)) ^ 2
Next j
EstimateAllParameters = Sum(sqdError)
End Function
MktStrike has the following values in cells E5:E8
12
13
14
15
and MktVol has the following values in cells F5:F8
0.234
0.236
0.242
0.249
Obvious issue is J hasn't been Dim'd
I would change:
Dim R As Double, a As Double, V As Double, N As Integer
To
Dim R As Double, a As Double, V As Double, N As Integer, J as Integer
Related
I'm still new with the vba. I have an database that with the help of others peoples I've finally able to do validation check when importing. However, I can get check done with numbers as text, but if I need alpha character or if the cell is blank I'm stuck. This is what I have for numbers as text. I need two checks: 1) accept alphanumeric or blank (null) and 2)numeric or blank (null).
Function chk2(A As String) As Boolean
Dim i As Integer, l As Integer, c As String
l = Len(A)
If l = 4 Then
chk2 = True
For i = 1 To l
c = Mid(A, i, 1)
If Not (c >= "0" And c <= "9") Then
chk2 = False
Exit Function
End If
Next i
End If
End Function
This one works fine as long as there are characters to fill in each row/cell.
Thanks in advance for your help.
If you're returning a boolean value, you should only return a true value if everything has executed correctly, that way you aren't getting a false positive if something fails.
You could use a check if the cell has 0 length for a blank cell, i.e. If Len = 0
What you are doing in your If Not statement is checking if the ascii value of c is between the ascii values of 0 and 9 so you can use or statements to check if it is between a and z or A and Z or if there is a space which is character 32 - Chr(32) :
Function chk2(A As String) As Boolean
Dim i As Integer, l As Integer, c As String
chk2 = false
l = Len(A)
If l = 0 then
'do something if the cell is blank
chk2 = true
ElseIf l = 4 Then
For i = 1 To l
c = Mid(A, i, 1)
If Not ((c >= "0" And c <= "9") Or (c >= "a" And c <= "z") Or (c >= "A" And C <= "Z") Or c = Chr(32)) Then
Exit Function
End If
Next i
chk2=true
End If
End Function
I wrote the GNU Fortran code in two separate files on Code::Blocks: main.f95, example.f95. main.f95 content:
program testing
use example
implicit none
integer :: a, b
write(*,"(a)", advance="no") "Enter first number: "
read(*,*) a
write(*,"(a)", advance="no") "Enter second number: "
read(*,*) b
write(*,*) factorial(a)
write(*,*) permutation(a, b)
write(*,*) combination(a, b)
end program testing
example.f95 content:
module example
contains
integer function factorial(x)
implicit none
integer, intent(in) :: x
integer :: product_ = 1, i
if (x < 1) then
factorial = -1
else if (x == 0 .or. x == 1) then
factorial = 1
else
do i = 2, x
product_ = product_ * i
end do
factorial = product_
end if
end function factorial
real function permutation(x, y)
implicit none
integer, intent(in) :: x, y
permutation = factorial(x) / factorial(x - y)
end function permutation
real function combination(x, y)
implicit none
integer, intent(in) :: x, y
combination = permutation(x, y) / factorial(y)
end function combination
end module example
When I run this code, the output is:
Enter first number: 5
Enter second number: 3
120
0.00000000
0.00000000
The permutation and combination functions don't work properly. Thanks for answers.
I think you've fallen foul of one of Fortran's well-known (to those who know it) gotchas. But before revealing that I have to ask how much testing you did ? I ran your code, got the odd result and thought for a minute ...
then I tested the factorial function for a few small values of x which produced
factorial 1 = 1
factorial 2 = 2
factorial 3 = 12
factorial 4 = 288
factorial 5 = 34560
factorial 6 = 24883200
factorial 7 = 857276416
factorial 8 = -511705088
factorial 9 = 1073741824
factorial 10 = 0
which is obviously wrong. So it seems that you didn't test your code properly, if at all, before asking for help. (I didn't test your combination and permutation functions.)
O tempora, o mores
You've initialised the variable product_ in the line
integer :: product_ = 1, i
and this automatically means that product_ acquires the attribute save so its value is stored from invocation to invocation (gotcha !). At the start of each call (other than the first) product_ has the value it had at the end of the previous call.
The remedy is simple, don't initialise product_. Change
integer :: product_ = 1, i
to
integer :: product_ , i
...
product_ = 1
Simpler still would be to not write your own factorial function but to use the intrinsic product function but that's another story.
Here is the Main Program:
PROGRAM integration
EXTERNAL funct
DOUBLE PRECISION funct, a , b, sum, h
INTEGER n, i
REAL s
PARAMETER (a = 0, b = 10, n = 200)
h = (b-a)/n
sum = 0.0
DO i = 1, n
sum = sum+funct(i*h+a)
END DO
sum = h*(sum-0.5*(funct(a)+funct(b)))
PRINT *,sum
CONTAINS
END
And below is the Function funct(x)
DOUBLE PRECISION FUNCTION funct(x)
IMPLICIT NONE
DOUBLE PRECISION x
INTEGER K
Do k = 1,10
funct = x ** 2 * k
End Do
PRINT *, 'Value of funct is', funct
RETURN
END
I would like the 'Sum' in the Main Program to print 10 different sums over 10 different values of k in Function funct(x).
I have tried the above program but it just compiles the last value of Funct() instead of 10 different values in sum.
Array results require an explicit interface. You would also need to adjust funct and sum to actually be arrays using the dimension statement. Using an explicit interface requires Fortran 90+ (thanks for the hints by #francescalus and #VladimirF) and is quite tedious:
PROGRAM integration
INTERFACE funct
FUNCTION funct(x) result(r)
IMPLICIT NONE
DOUBLE PRECISION r
DIMENSION r( 10 )
DOUBLE PRECISION x
END FUNCTION
END INTERFACE
DOUBLE PRECISION a , b, sum, h
DIMENSION sum( 10)
INTEGER n, i
PARAMETER (a = 0, b = 10, n = 200)
h = (b-a)/n
sum = 0.0
DO i = 1, n
sum = sum+funct(i*h+a)
END DO
sum = h*(sum-0.5*(funct(a)+funct(b)))
PRINT *,sum
END
FUNCTION funct(x)
IMPLICIT NONE
DOUBLE PRECISION funct
DIMENSION funct( 10)
DOUBLE PRECISION x
INTEGER K
Do k = 1,10
funct(k) = x ** 2 * k
End Do
PRINT *, 'Value of funct is', funct
RETURN
END
If you can, you should switch to a more modern Standard such as Fortran 90+, and use modules. These provide interfaces automatically, which makes the code much simpler.
Alternatively, you could take the loop over k out of the function, and perform the sum element-wise. This would be valid FORTRAN 77:
PROGRAM integration
c ...
DIMENSION sum( 10)
c ...
INTEGER K
c ...
DO i = 1, n
Do k = 1,10
sum(k)= sum(k)+funct(i*h+a, k)
End Do
END DO
c ...
Notice that I pass k to the function. It needs to be adjusted accordingly:
DOUBLE PRECISION FUNCTION funct(x,k)
IMPLICIT NONE
DOUBLE PRECISION x
INTEGER K
funct = x ** 2 * k
PRINT *, 'Value of funct is', funct
RETURN
END
This version just returns a scalar and fills the array in the main program.
Apart from that I'm not sure it is wise to use a variable called sum. There is an intrinsic function with the same name. This could lead to some confusion...
The Haskell compiler throws an error on the following function:
balancedMax :: Int -> Int -> Int
balancedMax -1 _ = -1
balancedMax _ -1 = -1
balancedMax a b = max a b
Flipping the sign solves the problem:
balancedMax :: Int -> Int -> Int
balancedMax 1 _ = -1
balancedMax _ 1 = -1
balancedMax a b = max a b
Why does pattern matching fail on the negatives, and what is a clean workaround?
It fails because it thinks you're trying to re-define the minus operator, because f -1 = ... gets parsed as f - 1 = ....
To fix this you just have to add parentheses:
balancedMax :: Int -> Int -> Int
balancedMax (-1) _ = -1
balancedMax _ (-1) = -1
balancedMax a b = max a b
The same thing happens in expressions. To call balancedMax with a negative literal, you would need parentheses as well.
because f -1 = ... gets parsed as f - 1 = ....
Which if you don't know, means the same thing as:
(-) f 1 = ....
which is similar to defining a function like this:
somefunc x 1 = x + 1
Which happens to be equivalent to defining somefunc() like this:
x `somefunc` 1 = x + 1
It's just that with (-) you don't have to write the backticks when using it in infix position, i.e. positioned between its two arguments.
The two beginning haskell books I've looked at both warn you early on that the unary - needs to be used with parentheses, e.g. (-3).
I have the below function that I am using to enter 2 initial parameters, rho and V, and based on minimized sum of squared errors, I want it to return the estimated parameters, rho and V.
Public Function RhoAndV(params, MktStrike, MktVol, Vol, Fwd, Tau, Beta)
Dim rho, V, Alpha As Double
Dim i As Integer, L As Integer
Dim sqdError() As Double, ModelVol() As Double
rho = params(1)
V = params(2)
Alpha = AFn(Fwd, Fwd, Tau, Vol, Beta, rho, V)
'MsgBox ("Alpha=" & Alpha)
L = MktVol.Cells.Count
ReDim ModelVol(L) As Double, sqdError(L) As Double
For i = 1 To L
ModelVol(i) = Vfn(Alpha, Beta, rho, V, Fwd, MktStrike(i), Tau)
'MsgBox ("ModelVol(i)=" & ModelVol(i))
sqdError(i) = (ModelVol(i) - MktVol(i)) ^ 2
Next i
RhoAndV = Application.SUM(sqdError)
End Function
I have rho and V in cells A1:A2 with values 0.1 and 0.1, so I select A1:A2 as params.
In cells C3:C6, I have MktStrike with values
30
31
32
33
In cells D3:D6, I have MktVol with values
0.23
0.24
0.25
0.26
This function now returns the sumof squared errors (I run it in Excel as =RhoAndV(A1:A3,C3:C6,D3:D6,0.25,10,1,0.5) and it returns .003. However, I want it to return the estimated parameters, rho and V. Can anyone please tell me how to fix this function to do so?
You'd modify your original function to something like the example below. How you return the values depends on whether you want to return them to a row (eg D3:E3) or column (eg. D3:D4)
Function RhoAndV(params, MktStrike, MktVol, Vol, Fwd, Tau, Beta)
'rest of your code
'RhoAndV = Array(rho, V) 'returning to a row
RhoAndV = Application.Transpose(Array(rho, V)) 'returning to a column
End Function