jessegrabowski / gEconpy

A collection of tools for working with DSGE models in python, inspired by the R package gEcon
https://geconpy.readthedocs.io/en/latest/index.html
GNU General Public License v3.0
21 stars 4 forks source link

Parameters defined as equations of other parameters are interpreted as calibrating constraints #27

Closed lukasgrahl closed 1 year ago

lukasgrahl commented 1 year ago

Hi Jesse,

I was trying to load an already log-linear model and when reading in my GCN file I came across this error message below. I was wondering whether this is due to the GCN specification or possibly something else. The GCN can be found under: https://github.com/lukasgrahl/memoire1/blob/b3e2901e96936badc71a61cee8b097f2b3de85cc/model_files/log_lin2.gcn

Thanks for your help!

KeyError

Traceback (most recent call last) ----> 1 mod.solve_model(model_is_linear=True)

gEconpy\classes\model.py:451, in gEconModel.solve_model(self, solver, not_loglin_variable, order, model_is_linear, tol, max_iter, verbose, on_failure) 448 steady_state_dict = self.steady_state_dict 450 if self.build_perturbation_matrices is None: --> 451 self._perturbation_setup(not_loglin_variable, order, model_is_linear, verbose, bool) 453 A, B, C, D = self.build_perturbation_matrices( 454 param_dict.to_string(), steady_state_dict.tostring() 455 ) 456 , variables, _ = self.perturbation_solver.make_all_variable_time_combinations()

gEconpy\classes\model.py:595, in `gEconModel._perturbation_setup(self, not_loglin_variables, order, model_is_linear, verbose, return_F_matrices, tol) 592 if variable.base_name in not_loglin_variables: 593 continue --> 595 if abs(steady_state_dict[variable.to_ss().name]) < tol: 596 not_loglin_variables.append(variable.base_name) 597 close_to_zero_warnings.append(variable)

KeyError: 'Y_ss'

PS: adding it as code would have ruined the indents
jessegrabowski commented 1 year ago

Just to rule out the obvious -- you called mod.steady_state() before mod.solve_model() yea?

lukasgrahl commented 1 year ago

I did, but I restarted the notebook once more, just to make sure. Now it actually throws an error on the .steady_state() method, that previously wasn't shown. I get a non-zero residual in the steady state, it seems there must have been an error in the GCN all along. I'll try fix that one first then.

jessegrabowski commented 1 year ago

Since the model isn't that complicated, it would be good to include a steady_state block and provide the analytical steady states. I recommend always doing that, if possible. The automatic solver isn't bad, but it isn't great either, and can systematically fail for certain parameter boundaries (see the last 2 plots here)

jessegrabowski commented 1 year ago

Also, for linear systems, you can get the steady state super fast using Sympy by making an augmented matrix and putting it into reduced row-echelon form:

Y, pi, r, v, a = sp.symbols('Y \pi, r, v, a')
omega, sigma, beta, phi_pi, kappa, rho, psi_y, phi_y = sp.symbols('omega sigma beta, \phi_{\pi} kappa rho \psi_{ya} \phi_{y}')

a = 0
v = 0

eq_1 = Y - (omega * (sigma * Y + (1 - beta) * phi_pi * pi) + omega * (r - v))
eq_2 = pi - (omega * (sigma * kappa * Y + (kappa + beta * ( sigma + phi_y ) ) * pi ) + omega * kappa * (r - v))
eq_3 = r - (rho + sigma * psi_ya * (a - a))

A, y = sp.linear_eq_to_matrix([eq_1, eq_2, eq_3], [Y, pi, r])
sp.Matrix([[A, y]]).rref()[0]

$$ \displaystyle \left[\begin{matrix}1 & 0 & 0 & \frac{- \phi{\pi} \beta \kappa \omega^{2} \rho + \phi{\pi} \kappa \omega^{2} \rho - \phi{y} \beta \omega^{2} \rho - \beta \omega^{2} \rho \sigma - \kappa \omega^{2} \rho + \omega \rho}{\phi{\pi} \beta \kappa \omega^{2} \sigma - \phi{\pi} \kappa \omega^{2} \sigma + \phi{y} \beta \omega^{2} \sigma - \phi{y} \beta \omega + \beta \omega^{2} \sigma^{2} - \beta \omega \sigma + \kappa \omega^{2} \sigma - \kappa \omega - \omega \sigma + 1} \\ 0 & 1 & 0 & \frac{\kappa \omega \rho}{\phi{\pi} \beta \kappa \omega^{2} \sigma - \phi{\pi} \kappa \omega^{2} \sigma + \phi{y} \beta \omega^{2} \sigma - \phi_{y} \beta \omega + \beta \omega^{2} \sigma^{2} - \beta \omega \sigma + \kappa \omega^{2} \sigma - \kappa \omega - \omega \sigma + 1} \\ 0 & 0 & 1 & \rho\end{matrix}\right] $$

A quick check that these in fact satisfy the steady state:

ss_vals = sp.Matrix([[A, y]]).rref()[0][:, 3]
y_ss, pi_ss, r_ss = [x[0] for x in ss_vals.tolist()]

for eq in [eq_1, eq_2, eq_3]:
    assert eq.subs({Y:y_ss, pi:pi_ss, r:r_ss}).simplify() == 0
jessegrabowski commented 1 year ago

Ok I found the bug, it's related to the definition of parameters in the calibration block. The system thinks these are calibrating restrictions, and is trying to add them to the model system as variables. The correct behavior should be to ignore these equations unless there is an arrow syntax, so it's definitely a bug.