From 6b8e88ea5bbb1a06082f692be253698e371cfe14 Mon Sep 17 00:00:00 2001 From: alanlujan91 Date: Thu, 15 Feb 2024 12:04:08 -0500 Subject: [PATCH] update to allow subjective beliefs --- code/Portfolio.ipynb | 3 +- code/do_all.py | 20 ++++++ .../calibration/estimation_parameters.py | 28 ++++++++ code/estimark/calibration/options.py | 8 +++ code/estimark/estimation.py | 69 ++++++++++++------- ...b(Stock)(Labor)Market_estimate_results.csv | 2 + code/tables/IndShock_estimate_results.csv | 4 +- ...b(Stock)(Labor)Market_estimate_results.csv | 2 + ...b(Stock)(Labor)Market_estimate_results.csv | 2 + ...b(Stock)(Labor)Market_estimate_results.csv | 2 + ...b(Stock)(Labor)Market_estimate_results.csv | 2 + environment.yml | 4 -- 12 files changed, 112 insertions(+), 34 deletions(-) create mode 100644 code/tables/IndShockSub(Stock)(Labor)Market_estimate_results.csv create mode 100644 code/tables/PortfolioSub(Stock)(Labor)Market_estimate_results.csv create mode 100644 code/tables/WarmGlowPortfolioSub(Stock)(Labor)Market_estimate_results.csv create mode 100644 code/tables/WarmGlowSub(Stock)(Labor)Market_estimate_results.csv create mode 100644 code/tables/WealthPortfolioSub(Stock)(Labor)Market_estimate_results.csv diff --git a/code/Portfolio.ipynb b/code/Portfolio.ipynb index 38a915e..93f3f40 100644 --- a/code/Portfolio.ipynb +++ b/code/Portfolio.ipynb @@ -39,8 +39,7 @@ "metadata": {}, "outputs": [], "source": [ - "portfolio_agent = PortfolioLifeCycleConsumerType(\n", - " **parameters.init_consumer_objects)\n", + "portfolio_agent = PortfolioLifeCycleConsumerType(**parameters.init_consumer_objects)\n", "\n", "\n", "portfolio_agent.CRRA = CRRA\n", diff --git a/code/do_all.py b/code/do_all.py index ff98b62..b46e999 100644 --- a/code/do_all.py +++ b/code/do_all.py @@ -85,6 +85,18 @@ def run_replication(): q quit: exit without executing.\n\n""" ) + subjective_markets = input( + """Would you like to add subjective stock or labor market beliefs to the model?: + + [1] No + + [2] Subjective Stock Market Beliefs + + [3] Subjective Labor Market Beliefs + + [4] Both\n\n""" + ) + replication_specs = {} if which_model == "1" or which_model == "": @@ -124,6 +136,14 @@ def run_replication(): print("Invalid replication choice.") return + if subjective_markets == "2" or subjective_markets == "4": + replication_specs["subjective_stock_market"] = True + print("Adding subjective stock market beliefs...") + + if subjective_markets == "3" or subjective_markets == "4": + replication_specs["subjective_labor_market"] = True + print("Adding subjective labor market beliefs...") + estimate(**replication_specs) diff --git a/code/estimark/calibration/estimation_parameters.py b/code/estimark/calibration/estimation_parameters.py index c6e20e3..a7c3976 100644 --- a/code/estimark/calibration/estimation_parameters.py +++ b/code/estimark/calibration/estimation_parameters.py @@ -103,6 +103,19 @@ bootstrap_size = 50 # Number of re-estimations to do during bootstrap seed = 31382 # Just an integer to seed the estimation +options = { + "initial_wealth_income_ratio_vals": initial_wealth_income_ratio_vals, + "initial_wealth_income_ratio_probs": initial_wealth_income_ratio_probs, + "num_agents": num_agents, + "bootstrap_size": bootstrap_size, + "seed": seed, + "DiscFacAdj_start": DiscFacAdj_start, + "CRRA_start": CRRA_start, + "DiscFacAdj_bound": DiscFacAdj_bound, + "CRRA_bound": CRRA_bound, + "DiscFac_timevary": DiscFac_timevary, +} + # ----------------------------------------------------------------------------- # -- Set up the dictionary "container" for making a basic lifecycle type ------ # ----------------------------------------------------------------------------- @@ -141,6 +154,21 @@ }, } +# from Mateo's JMP for College Educated +ElnR = 0.020 +VlnR = 0.424**2 + +init_subjective_stock_market = { + "Rfree": 1.019, # from Mateo's JMP + "RiskyAvg": np.exp(ElnR + 0.5 * VlnR), + "RiskyStd": np.sqrt(np.exp(2 * ElnR + VlnR) * (np.exp(VlnR) - 1)), +} + +init_subjective_labor_market = { # from Tao's JMP + "TranShkStd": [0.03] * len(inc_calib["TranShkStd"]), + "PermShkStd": [0.03] * len(inc_calib["PermShkStd"]), +} + if show_PermGroFacAgg_error: pass # do nothing else: diff --git a/code/estimark/calibration/options.py b/code/estimark/calibration/options.py index f018cce..c2378a4 100644 --- a/code/estimark/calibration/options.py +++ b/code/estimark/calibration/options.py @@ -6,6 +6,8 @@ "make_contour_plot": False, "compute_standard_errors": False, "compute_sensitivity": False, + "subjective_stock_market": False, + "subjective_labor_market": False, } # Author note: # This takes approximately 90 seconds on a laptop with the following specs: @@ -16,6 +18,8 @@ "make_contour_plot": True, "compute_standard_errors": False, "compute_sensitivity": True, + "subjective_stock_market": False, + "subjective_labor_market": False, } # Author note: # This takes approximately 7 minutes on a laptop with the following specs: @@ -26,6 +30,8 @@ "make_contour_plot": False, "compute_standard_errors": True, "compute_sensitivity": True, + "subjective_stock_market": False, + "subjective_labor_market": False, } # Author note: # This takes approximately 30 minutes on a laptop with the following specs: @@ -36,6 +42,8 @@ "make_contour_plot": True, "compute_standard_errors": True, "compute_sensitivity": True, + "subjective_stock_market": False, + "subjective_labor_market": False, } # Author note: # This takes approximately 40 minutes on a laptop with the following specs: diff --git a/code/estimark/estimation.py b/code/estimark/estimation.py index c4d360c..b48ff76 100644 --- a/code/estimark/estimation.py +++ b/code/estimark/estimation.py @@ -10,7 +10,12 @@ """ # Parameters for the consumer type and the estimation -import estimark.calibration.estimation_parameters as parameters +from estimark.calibration.estimation_parameters import ( + init_consumer_objects, + init_subjective_labor_market, + init_subjective_stock_market, + options, +) import estimark.calibration.setup_scf_data as scf_data # SCF 2004 data on household wealth import csv from estimark.agents import ( @@ -103,8 +108,8 @@ def simulate_moments( DiscFacAdj, CRRA, agent, - DiscFacAdj_bound=parameters.DiscFacAdj_bound, - CRRA_bound=parameters.CRRA_bound, + DiscFacAdj_bound=options["DiscFacAdj_bound"], + CRRA_bound=options["CRRA_bound"], map_simulated_to_empirical_cohorts=scf_data.simulation_map_cohorts_to_age_indices, ): """ @@ -121,7 +126,7 @@ def simulate_moments( return 1e30 * np.ones(len(map_simulated_to_empirical_cohorts)) # Update the agent with a new path of DiscFac based on this DiscFacAdj (and a new CRRA) - agent.DiscFac = [b * DiscFacAdj for b in parameters.DiscFac_timevary] + agent.DiscFac = [b * DiscFacAdj for b in options["DiscFac_timevary"]] agent.CRRA = CRRA # Solve the model for these parameters, then simulate wealth data agent.solve() # Solve the microeconomic model @@ -153,8 +158,8 @@ def smm_obj_func( CRRA, agent, tgt_moments, - DiscFacAdj_bound=parameters.DiscFacAdj_bound, - CRRA_bound=parameters.CRRA_bound, + DiscFacAdj_bound=options["DiscFacAdj_bound"], + CRRA_bound=options["CRRA_bound"], map_simulated_to_empirical_cohorts=scf_data.simulation_map_cohorts_to_age_indices, ): """ @@ -358,20 +363,20 @@ def compute_std_err_bootstrap( # Estimate the model: print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~") print( - f"Computing standard errors using {parameters.bootstrap_size} bootstrap replications." + f"Computing standard errors using {options['bootstrap_size']} bootstrap replications." ) print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~") - t_bootstrap_guess = time_to_estimate * parameters.bootstrap_size + t_bootstrap_guess = time_to_estimate * options["bootstrap_size"] minutes, seconds = divmod(t_bootstrap_guess, 60) print(f"This will take approximately {int(minutes)} min, {int(seconds)} sec.") t_start_bootstrap = time() std_errors = calculate_std_err_bootstrap( model_estimate, - N=parameters.bootstrap_size, + N=options["bootstrap_size"], agent=EstimationAgent, - seed=parameters.seed, + seed=options["seed"], verbose=True, ) t_end_bootstrap = time() @@ -416,8 +421,8 @@ def simulate_moments_redux(x): x[0], x[1], agent=EstimationAgent, - DiscFacAdj_bound=parameters.DiscFacAdj_bound, - CRRA_bound=parameters.CRRA_bound, + DiscFacAdj_bound=options["DiscFacAdj_bound"], + CRRA_bound=options["CRRA_bound"], map_simulated_to_empirical_cohorts=scf_data.simulation_map_cohorts_to_age_indices, ) @@ -515,6 +520,8 @@ def estimate( compute_standard_errors=local_compute_standard_errors, compute_sensitivity=local_compute_sensitivity, make_contour_plot=local_make_contour_plot, + subjective_stock_market=False, + subjective_labor_market=False, ): """ Run the main estimation procedure for SolvingMicroDSOP. @@ -546,20 +553,30 @@ def estimate( elif estimation_agent == "WealthPortfolio": agent_type = WealthPortfolioLifeCycleConsumerType + if subjective_stock_market or subjective_labor_market: + estimation_agent += "Sub" + if subjective_stock_market: + estimation_agent += "(Stock)" + init_consumer_objects.update(init_subjective_stock_market) + if subjective_labor_market: + estimation_agent += "(Labor)" + init_consumer_objects.update(init_subjective_labor_market) + estimation_agent += "Market" + # Make a lifecycle consumer to be used for estimation, including simulated # shocks (plus an initial distribution of wealth) # Make a TempConsumerType for estimation - EstimationAgent = agent_type(**parameters.init_consumer_objects) + EstimationAgent = agent_type(**init_consumer_objects) # Set the number of periods to simulate EstimationAgent.T_sim = EstimationAgent.T_cycle + 1 # Choose to track bank balances as wealth EstimationAgent.track_vars = ["bNrm"] # Draw initial assets for each consumer EstimationAgent.aNrmInit = DiscreteDistribution( - parameters.initial_wealth_income_ratio_probs, - parameters.initial_wealth_income_ratio_vals, - seed=parameters.seed, - ).draw(N=parameters.num_agents) + options["initial_wealth_income_ratio_probs"], + options["initial_wealth_income_ratio_vals"], + seed=options["seed"], + ).draw(N=options["num_agents"]) EstimationAgent.make_shock_history() targeted_moments = get_targeted_moments() @@ -575,7 +592,7 @@ def estimate( initial_guess = np.genfromtxt(csv_file_path, skip_header=1, delimiter=",") except: - initial_guess = [parameters.DiscFacAdj_start, parameters.CRRA_start] + initial_guess = [options["DiscFacAdj_start"], options["CRRA_start"]] # Estimate the model using Nelder-Mead if estimate_model: @@ -631,24 +648,24 @@ def estimate_all(): # Make a lifecycle consumer to be used for estimation, including simulated # shocks (plus an initial distribution of wealth) # Make a TempConsumerType for estimation - EstimationAgent = agent_type(**parameters.init_consumer_objects) + EstimationAgent = agent_type(**init_consumer_objects) # Set the number of periods to simulate EstimationAgent.T_sim = EstimationAgent.T_cycle + 1 # Choose to track bank balances as wealth EstimationAgent.track_vars = ["bNrm"] # Draw initial assets for each consumer EstimationAgent.aNrmInit = DiscreteDistribution( - parameters.initial_wealth_income_ratio_probs, - parameters.initial_wealth_income_ratio_vals, - seed=parameters.seed, - ).draw(N=parameters.num_agents) + options["initial_wealth_income_ratio_probs"], + options["initial_wealth_income_ratio_vals"], + seed=options["seed"], + ).draw(N=options["num_agents"]) EstimationAgent.make_shock_history() targeted_moments = get_targeted_moments() idx = np.unravel_index(count, (2, 2)) - initial_guess = [parameters.DiscFacAdj_start, parameters.CRRA_start] + initial_guess = [options["DiscFacAdj_start"], options["CRRA_start"]] print("----------------------------------------------------------------------") print( f"Now estimating the model using Nelder-Mead from an initial guess of {initial_guess}..." @@ -695,8 +712,8 @@ def simulate_moments_redux(x): x[0], x[1], agent=EstimationAgent, - DiscFacAdj_bound=parameters.DiscFacAdj_bound, - CRRA_bound=parameters.CRRA_bound, + DiscFacAdj_bound=options["DiscFacAdj_bound"], + CRRA_bound=options["CRRA_bound"], map_simulated_to_empirical_cohorts=scf_data.simulation_map_cohorts_to_age_indices, ) diff --git a/code/tables/IndShockSub(Stock)(Labor)Market_estimate_results.csv b/code/tables/IndShockSub(Stock)(Labor)Market_estimate_results.csv new file mode 100644 index 0000000..59a4fe8 --- /dev/null +++ b/code/tables/IndShockSub(Stock)(Labor)Market_estimate_results.csv @@ -0,0 +1,2 @@ +DiscFacAdj,CRRA +0.9900216884662436,4.1368574835978205 diff --git a/code/tables/IndShock_estimate_results.csv b/code/tables/IndShock_estimate_results.csv index 216074a..195b41d 100644 --- a/code/tables/IndShock_estimate_results.csv +++ b/code/tables/IndShock_estimate_results.csv @@ -1,2 +1,2 @@ -DiscFacAdj,CRRA -0.9552205116274122,1.3759978446748666 +DiscFacAdj,CRRA +0.9552205116274122,1.3759978446748666 diff --git a/code/tables/PortfolioSub(Stock)(Labor)Market_estimate_results.csv b/code/tables/PortfolioSub(Stock)(Labor)Market_estimate_results.csv new file mode 100644 index 0000000..7db3b61 --- /dev/null +++ b/code/tables/PortfolioSub(Stock)(Labor)Market_estimate_results.csv @@ -0,0 +1,2 @@ +DiscFacAdj,CRRA +0.9911742480356607,6.034052128020187 diff --git a/code/tables/WarmGlowPortfolioSub(Stock)(Labor)Market_estimate_results.csv b/code/tables/WarmGlowPortfolioSub(Stock)(Labor)Market_estimate_results.csv new file mode 100644 index 0000000..787de44 --- /dev/null +++ b/code/tables/WarmGlowPortfolioSub(Stock)(Labor)Market_estimate_results.csv @@ -0,0 +1,2 @@ +DiscFacAdj,CRRA +0.9756577076244863,8.846001517130244 diff --git a/code/tables/WarmGlowSub(Stock)(Labor)Market_estimate_results.csv b/code/tables/WarmGlowSub(Stock)(Labor)Market_estimate_results.csv new file mode 100644 index 0000000..ff0568f --- /dev/null +++ b/code/tables/WarmGlowSub(Stock)(Labor)Market_estimate_results.csv @@ -0,0 +1,2 @@ +DiscFacAdj,CRRA +0.9861730357696492,4.425749877454312 diff --git a/code/tables/WealthPortfolioSub(Stock)(Labor)Market_estimate_results.csv b/code/tables/WealthPortfolioSub(Stock)(Labor)Market_estimate_results.csv new file mode 100644 index 0000000..72a1484 --- /dev/null +++ b/code/tables/WealthPortfolioSub(Stock)(Labor)Market_estimate_results.csv @@ -0,0 +1,2 @@ +DiscFacAdj,CRRA +0.8623504474809875,7.657921805596357 diff --git a/environment.yml b/environment.yml index e3b20a5..2bfbef5 100644 --- a/environment.yml +++ b/environment.yml @@ -3,10 +3,6 @@ channels: - conda-forge dependencies: - python=3.10 - - matplotlib - - numpy - - scipy - - pandas - pip - pip: - git+https://github.com/econ-ark/HARK@master