def dag(): # Combine Blocks household = hh.add_hetinputs([income, make_grids]) production = combine([labor, investment]) production_solved = production.solved(unknowns={'Q': 1., 'K': 10.}, targets=['inv', 'val'], solver='broyden_custom') blocks = [household, pricing_solved, arbitrage_solved, production_solved, dividend, taylor, fiscal, share_value, finance, wage, union, mkt_clearing] two_asset_model = create_model(blocks, name='Two-Asset HANK') # Steadt state DAG blocks_ss = [household, partial_ss, dividend, taylor, fiscal, share_value, finance, union_ss, mkt_clearing] two_asset_model_ss = create_model(blocks_ss, name='Two-Asset HANK SS') # Steady State calibration = {'Y': 1., 'N': 1.0, 'K': 10., 'r': 0.0125, 'rstar': 0.0125, 'tot_wealth': 14, 'delta': 0.02, 'pi': 0., 'kappap': 0.1, 'muw': 1.1, 'Bh': 1.04, 'Bg': 2.8, 'G': 0.2, 'eis': 0.5, 'frisch': 1, 'chi0': 0.25, 'chi2': 2, 'epsI': 4, 'omega': 0.005, 'kappaw': 0.1, 'phi': 1.5, 'nZ': 3, 'nB': 10, 'nA': 16, 'nK': 4, 'bmax': 50, 'amax': 4000, 'kmax': 1, 'rho_z': 0.966, 'sigma_z': 0.92} unknowns_ss = {'beta': 0.976, 'chi1': 6.5} targets_ss = {'asset_mkt': 0., 'B': 'Bh'} cali = two_asset_model_ss.solve_steady_state(calibration, unknowns_ss, targets_ss, solver='broyden_custom') ss = two_asset_model.steady_state(cali) # Transitional Dynamics/Jacobian Calculation unknowns = ['r', 'w', 'Y'] targets = ['asset_mkt', 'fisher', 'wnkpc'] exogenous = ['rstar', 'Z', 'G'] return two_asset_model_ss, ss, two_asset_model, unknowns, targets, exogenous
def test_all(): # Assemble HA block (want to test nesting) household_ha = hh.add_hetinputs([make_grids, income]) household_ha = household_ha.add_hetoutputs([mpcs, weighted_uc]).rename('household_ha') # Assemble DAG (for transition dynamics) dag = {} common_blocks = [firm, union, fiscal, mkt_clearing] dag['ha'] = create_model([household_ha] + common_blocks, name='HANK') dag['ra'] = create_model([household_ra] + common_blocks, name='RANK') unknowns = ['N', 'pi'] targets = ['asset_mkt', 'wnkpc'] # Solve steady state calibration = {'N': 1.0, 'Z': 1.0, 'r': 0.005, 'pi': 0.0, 'eis': 0.5, 'nu': 0.5, 'rho_e': 0.91, 'sd_e': 0.92, 'nE': 3, 'amin': 0.0, 'amax': 200, 'nA': 100, 'kappaw': 0.1, 'muw': 1.2, 'transfer': 0.143, 'rho_B': 0.9} ss = {} # Constructing ss-dag manually works just fine dag_ss = {} dag_ss['ha'] = create_model([household_ha, union_ss, firm, fiscal, mkt_clearing]) ss['ha'] = dag_ss['ha'].solve_steady_state(calibration, dissolve=['fiscal'], solver='hybr', unknowns={'beta': 0.96, 'B': 3.0, 'G': 0.2}, targets={'asset_mkt': 0.0, 'MPC': 0.25, 'tau': 0.334}) assert np.isclose(ss['ha']['goods_mkt'], 0.0) assert np.isclose(ss['ha']['asset_mkt'], 0.0) assert np.isclose(ss['ha']['wnkpc'], 0.0) dag_ss['ra'] = create_model([household_ra_ss, union_ss, firm, fiscal, mkt_clearing]) ss['ra'] = dag_ss['ra'].steady_state(ss['ha'], dissolve=['fiscal']) assert np.isclose(ss['ra']['goods_mkt'], 0.0) assert np.isclose(ss['ra']['asset_mkt'], 0.0) assert np.isclose(ss['ra']['wnkpc'], 0.0) # Precompute HA Jacobian Js = {'ra': {}, 'ha': {}} Js['ha']['household_ha'] = household_ha.jacobian(ss['ha'], inputs=['N', 'atw', 'r', 'transfer'], outputs=['C', 'A', 'UCE'], T=300) # Linear impulse responses from Jacobian vs directly shock = ImpulseDict({'G': 0.9 ** np.arange(300)}) G, td_lin1, td_lin2 = dict(), dict(), dict() for k in ['ra', 'ha']: G[k] = dag[k].solve_jacobian(ss[k], unknowns, targets, inputs=['G'], T=300, Js=Js[k]) td_lin1[k] = G[k] @ shock td_lin2[k] = dag[k].solve_impulse_linear(ss[k], unknowns, targets, shock, Js=Js[k]) assert all(np.allclose(td_lin1[k][i], td_lin2[k][i]) for i in td_lin1[k]) # Nonlinear vs linear impulses (sneak in test of ss_initial here too) td_nonlin = dag['ha'].solve_impulse_nonlinear(ss['ha'], unknowns, targets, inputs=shock*1E-2, Js=Js, internals=['household_ha'], ss_initial=ss['ha']) assert np.max(np.abs(td_nonlin['goods_mkt'])) < 1E-8 # See if D change matches up with aggregate assets td_nonlin_lvl = td_nonlin + ss['ha'] td_A = np.sum(td_nonlin_lvl.internals['household_ha']['a'] * td_nonlin_lvl.internals['household_ha']['D'], axis=(1, 2)) assert np.allclose(td_A - ss['ha']['A'], td_nonlin['A'])
def test_jacobian_accumulation(): # Define two blocks. Notice: Second one does not use output from the first! @sj.solved(unknowns={'p': (-10, 1000)}, targets=['valuation'], solver="brentq") def equity(r1, p, Y): valuation = Y + p(+1) / (1 + r1) - p return valuation @sj.simple def mkt_clearing(r0, r1, A0, A1, Y, B): asset_mkt_0 = A0 + (r0 + Y - 0.5 * r1) - B asset_mkt_1 = A1 + (r1 + Y - 0.5 * r0) - B return asset_mkt_0, asset_mkt_1 both_blocks = sj.create_model([equity, mkt_clearing]) only_second = sj.create_model([mkt_clearing]) calibration = { 'B': 0, 'Y': 0, 'r0': 0.01 / 4, 'r1': 0.01 / 4, 'A0': 1, 'A1': 1 } ss_both = both_blocks.steady_state(calibration) ss_second = only_second.steady_state(calibration) # Second block alone gives us Jacobian without issues. unknowns_td = ['Y', 'r1'] targets_td = ['asset_mkt_0', 'asset_mkt_1'] T = 300 shock = {'r0': 0.95**np.arange(T)} irf = only_second.solve_impulse_linear(ss_second, unknowns_td, targets_td, shock) G = only_second.solve_jacobian(ss_second, unknowns_td, targets_td, ['r0'], T=T) # Both blocks give us trouble. Even though solve_impulse_linear runs through... unknowns_td = ['Y', 'r1'] targets_td = ['asset_mkt_0', 'asset_mkt_1'] T = 300 shock = {'r0': 0.95**np.arange(T)} irf = both_blocks.solve_impulse_linear(ss_both, unknowns_td, targets_td, shock) G = both_blocks.solve_jacobian(ss_both, unknowns_td, targets_td, ['r0'], T=T)
def dag(): # Combine blocks household = hh.add_hetinputs([income, make_grids]) ks_model = create_model([household, firm, mkt_clearing], name="Krusell-Smith") ks_model_ss = create_model([household, firm_ss, mkt_clearing], name="Krusell-Smith SS") # Steady state calibration = {'eis': 1.0, 'delta': 0.025, 'alpha': 0.11, 'rho': 0.966, 'sigma': 0.5, 'Y': 1.0, 'L': 1.0, 'nS': 2, 'nA': 10, 'amax': 200, 'r': 0.01} unknowns_ss = {'beta': (0.98 / 1.01, 0.999 / 1.01)} targets_ss = {'asset_mkt': 0.} ss = ks_model_ss.solve_steady_state(calibration, unknowns_ss, targets_ss, solver='brentq') # Transitional dynamics inputs = ['Z'] unknowns = ['K'] targets = ['asset_mkt'] return ks_model_ss, ss, ks_model, unknowns, targets, inputs
def dag(): # Combine blocks household = hh.add_hetinputs([transfers, wages, make_grids]) household = household.add_hetoutputs([labor_supply]) blocks = [household, firm, monetary, fiscal, mkt_clearing, nkpc] blocks_ss = [household, firm, monetary, fiscal, mkt_clearing, nkpc_ss] hank_model = create_model(blocks, name="One-Asset HANK") hank_model_ss = create_model(blocks_ss, name="One-Asset HANK SS") # Steady state calibration = { 'r': 0.005, 'rstar': 0.005, 'eis': 0.5, 'frisch': 0.5, 'B': 5.6, 'mu': 1.2, 'rho_s': 0.966, 'sigma_s': 0.5, 'kappa': 0.1, 'phi': 1.5, 'Y': 1., 'Z': 1., 'pi': 0., 'nS': 2, 'amax': 150, 'nA': 10 } unknowns_ss = {'beta': 0.986, 'vphi': 0.8} targets_ss = {'asset_mkt': 0., 'NE': 1.} cali = hank_model_ss.solve_steady_state(calibration, unknowns_ss, targets_ss, solver='broyden_custom') ss = hank_model.steady_state(cali) # Transitional dynamics unknowns = ['w', 'Y', 'pi'] targets = ['asset_mkt', 'goods_mkt', 'nkpc_res'] exogenous = ['rstar', 'Z'] return hank_model_ss, ss, hank_model, unknowns, targets, exogenous
def remapped_dag(): # Create 2 versions of the household block using `remap` household = hh.household.add_hetinputs([income, make_grids]) to_map = ['beta', *household.outputs] hh_patient = household.remap({k: k + '_patient' for k in to_map}).rename('hh_patient') hh_impatient = household.remap({k: k + '_impatient' for k in to_map}).rename('hh_impatient') blocks = [hh_patient, hh_impatient, firm, mkt_clearing, aggregate] blocks_ss = [hh_patient, hh_impatient, firm_ss, mkt_clearing, aggregate] ks_remapped = create_model(blocks, name='KS-beta-het') ks_remapped_ss = create_model(blocks_ss, name='KS-beta-het') # Steady State calibration = {'eis': 1., 'delta': 0.025, 'alpha': 0.3, 'rho': 0.966, 'sigma': 0.5, 'Y': 1.0, 'L': 1.0, 'nS': 3, 'nA': 100, 'amax': 1000, 'beta_impatient': 0.985, 'mass_patient': 0.5} unknowns_ss = {'beta_patient': (0.98 / 1.01, 0.999 / 1.01)} targets_ss = {'asset_mkt': 0.} ss = ks_remapped_ss.solve_steady_state(calibration, unknowns_ss, targets_ss, solver='brentq') # Transitional Dynamics/Jacobian Calculation unknowns = ['K'] targets = ['asset_mkt'] exogenous = ['Z'] return ks_remapped_ss, ss, ks_remapped, unknowns, targets, ss, exogenous
def dag(): # Combine blocks blocks = [household, firm, mkt_clearing] rbc_model = create_model(blocks, name="RBC") # Steady state calibration = {'eis': 1., 'frisch': 1., 'delta': 0.025, 'alpha': 0.11, 'L': 1.} unknowns_ss = {'vphi': 0.92, 'beta': 1 / (1 + 0.01), 'K': 2., 'Z': 1.} targets_ss = {'goods_mkt': 0., 'r': 0.01, 'euler': 0., 'Y': 1.} ss = rbc_model.solve_steady_state(calibration, unknowns_ss, targets_ss, solver='hybr') # Transitional dynamics unknowns = ['K', 'L'] targets = ['goods_mkt', 'euler'] exogenous = ['Z'] return rbc_model, ss, unknowns, targets, exogenous