I'm writing a code that should calculate the Fair Values of sevaral different financial securities. The securities come from different issuers, so they are grouped by country and then evaluated.
In order to do so, I need to fit 6 parameters for each group/country, unfortunately these parameters aren't fixed, but they will change every day. I need to recalculated them every time I run my model, so I wrote a subroutine to optimize this problem with the Solver.
So far it works most of the time, but sometimes before lunching the solver the vba code steps into other function of the same spreadsheet and changes the starting values ( read as previous day parameters) of my problem. These function are not mentioned in the Solver subroutine, they are not even in the same module or sheet.
Any idea of why this is happening? Any Idea of how to prevent VBA stepping inside unwanted function?
here is my Solver code
Sub NSCoeff()
Dim current_wb As String
current_wb = ThisWorkbook.Name
Workbooks(current_wb).Sheets("Nelson_Siegel").Calculate
Workbooks(current_wb).Sheets("Nelson_Siegel").Activate
SolverReset
SolverOptions Precision:=0.01, Convergence:=0.1, AssumeNonNeg:=False
SolverOk SetCell:="$N$9", MaxMinVal:=2, ValueOf:=0, ByChange:="$N$4:$S$4", _
Engine:=1, EngineDesc:="GRG Nonlinear"
SolverAdd CellRef:="$N$4", Relation:=3, FormulaText:="0.001"
SolverAdd CellRef:="$S$4", Relation:=3, FormulaText:="0.001"
SolverOk SetCell:="$N$9", MaxMinVal:=2, ValueOf:=0, ByChange:="$N$4:$S$4", _
Engine:=1, EngineDesc:="GRG Nonlinear"
SolverOk SetCell:="$N$9", MaxMinVal:=2, ValueOf:=0, ByChange:="$N$4:$S$4", _
Engine:=1, EngineDesc:="GRG Nonlinear"
SolverSolve userFinish:=True
End Sub
Immediately after the last line the code steps into this function
Function Discount_Quartic(a As Double, b As Double, c As Double, d As Double, t As Double) As Double
Dim dr, r As Double
Application.Volatile
r = Worksheets("ImpBond").Cells(4, 26).Value
dr = Worksheets("ImpBond").Cells(4, 27).Value
Discount_Quartic = a * Exp(-r * t) + b * Exp(-r * t * dr) + c * Exp(-r * t * dr ^ 2) + d * Exp(-r * t * dr ^ 3) + (1 - a - b - c - d) * Exp(-r * dr ^ 4 * t)
End Function
Thanks for the help!
It depends on this:
Application.Volatile
This method tells the application that the function is Volatile
. In other words, every time something changes into the spreadsheet, the function must be recalculated.
Hence:
NSCoeff
; Application
sees what was Volatile
and recalculates everything it was so. In your case, Discount_Quartic
. Voilà voilà Find more about the Application.Volatile
method here .
And as for Any Idea of how to prevent VBA stepping inside unwanted function? , you have two solutions (probably more, but these are the ones coming to my mind now):
Application.Volatile
from the Function. This will, though, not prompt the recalculation of the function anymore (unless you don't explicitly recalculate it). Doing a small trick that I will show you with a simple example:
Dim dontCall As Boolean '<-- default: False Sub dontCallTheFunction() Range("A1") = 1 '<-- recalculation prompted, we will get into the function dontCall= True'<-- we don't want the function to be recalculated End Sub Function myFunction() Application.Volatile If dontCall= False Then myFunction = 3 Else dontCall = False '<-- reset the value to False, so next time we'll calculate it normally End If End Function
If the parameters for Solver are meant to be static values based on yesterday's data then you should make a static copy of the values for using with Solver. I suspect that your parameters are the results of calculations which include dates, etc for discounting (and rates, coupons). So when you open the workbook these calcs get updated (your function above was marked as volatile as explained by @ Matteo NNZ) and so Solver starts using the new values.
From your code, Solver is trying to minimise cell N9 by changing cells N4:S4 but keeping both N4 and S4 >= 0.001.
I had exactly the same problem of you and found your ask trying to answer mine. I agreed with ChipsLetten then I took a look on my spreadsheet and discovery that I have cells with the function. So, check if your spreadsheet isn't using the Discount_Quadratic in some cells
(like cell A1 with the formula "=Discount_Quadratic(a,b,c,d,t)")
If you have this function in cells of your spreadsheet, Excel will run this function equal to no cells with this function there is. So, when Excel update the formulas of all the spreadsheet, at any time your code will be interrupted by this update and running the code inside this function, even without you really had called it.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.