System Module¶
Constraints in PyMacroFin
can be used in different ways depending on the solver selected [1]. First, with the 'newton-raphson'
option (macro_model.options.inner_solver
= 'newton-raphson'
), when a constraint is binding while solving the
core system [2] of endogenous equations using the Newton-Raphson method for a grid point,
the binding value is given to the variable and the corresponding endogenous equation is removed to solve a system of n-1 equations and n-1
unknowns (starting originally with n endogenous equations and n endogenous variables). For example, consider a system with
m.endog = ['a','b','c]
and endogenous equations 1, 2, and 3. If we set m.constraint('b','<',10)
,
then if in the process of solving for the endogenous variables we reach b >= 10
, then we set
b = 10
and remove equation 2 from the endogenous equations and continue to solve with 2 equations
and 2 unknowns.
When using the least_squares
solver options, a constrained least squares method is used to solve the endogenous system of equations at each grid point.
You may also specify systems to use with the least_squares
solver. A system consists of another set of endogenous equations, separate
from the core set of endogenous equations, and a set of constraints. When the set of constraints corresponding to a system is binding, the
solver will switch from the core (or current) set of endogenous equations to the set specified by the system activated by the
constraints. This module documents how to use systems of equations [3].
Consider the following over-simplified expository example:
from PyMacroFin.model import macro_model
from PyMacroFin.system import system
m = macro_model(name='simple-example')
m.set_endog(['x','y'],init=[5,5])
m.endog_equation('y - (x - 10)')
m.endog_equation('y - (-2*x + 20)')
m.constraint('x','<',9,label='upper')
s = system(['upper'],m)
s.endog_equation('y - x')
s.endog_equation('y - 9')
m.systems.append(s)
In the example, the obvious solution to the core system of equations is x = 10
and y = 0
. However,
the constraint for x < 9
creates an infeasible system. However, when the constraint becomes binding in the
course of solving the core system, the system defined as s
becomes active and the solution is found
at y = x = 9
. Although this example is far from what an example would look like in an actual model, it illustrates
the functionality and flexibility provided by system
. To see an example of systems used to replicate published results,
see the one-dimensional example.
It is important to note that in the current release, switching more than once is not supported. The active system will only switch at most once for each grid point. After switching to a system, the constraints will not be checked again. This lends to simplicity and avoids the possibility of infinite loops alternating between systems at a given grid point. Further support for switching may be added in a future release.
-
class
PyMacroFin.system.
system
(constraint_trigger, m)¶ A system of equations to solve when a set of constraints is binding.
Parameters: - constraint_trigger: list(str)
List of labels corresponding to constraints which, when all binding, will trigger this system to become active when solving for endogenous variable values.
- m: macro_model
Model object to which the system will be attached.
Methods
endog_equation
(eq)Add an equation to the system to solve for endogenous variable values. equation
(eq)Define a new intermediate variable with an equation (specific to this system). -
endog_equation
(eq)¶ Add an equation to the system to solve for endogenous variable values. This equation will be solved to be equal to zero to find the values of the endogenous variables at each grid point where the constraints corresonding to this system are binding.
Parameters: - eq: str
This string should be of the form
f(<previously defined variables>)
. For example, ifb
andc
are already defined as parameters, endogenous variables, value variables, or defined in previous equations, theneq='b + c'
is acceptable. At equilibrium, the expression given byeq
should be equal to zero.
Notes
- There should be as many
endog_equation
calls as there are endogenous equations. For a variable (i.e.x
) that is set to a known value (i.e.c
) in this system, simply writesystem.endog_equation('c - x')
.
-
equation
(eq)¶ Define a new intermediate variable with an equation (specific to this system).
Parameters: - eq: str
This string should be of the form
newvar = f(<previously defined variables>)
. For example, ifb
andc
are already defined as parameters, endogenous variables, value variables, or defined in previous equations, theneq='a = b + c'
is acceptable.
Notes
- It is important to note that you may re-define intermediate variables from the core set of equations in the system.
- See the derivatives section for using derivatives in equations.
- As of the current release, system specific intermediate variables may not be plotted. However, if the equation re-defines a core equation variable then it will be plotted based on the plot input in the core system.
- To re-define HJB variables such as the drift and volatility of state variables in a constraint system, simply define intermediates that are referenced in the
macro_model.hjb_equation
calls, then re-define those intermediates in the constraint system.
Footnotes
[1] | The solver is used to solve the system of endogeonus equations provided by the user. This occurs in the inner static loop. For descriptions of loops used in the solution procedure, please see the notes in the options documentation and the solution method paper. |
[2] | The core system of endogenous equations is the system defined at the base level of the macro_model class. In other words,
any endogenous equation defined by macro_model.endog_equation rather than by macro_model.system.endog_equation is
considered to be part of the core system. |
[3] | Systems are not supported for the macro_model.options.inner_solver = 'fsolve' solver option. |