diff --git a/notebooks/Micro-and-Macro-Implications-of-Very-Impatient-HHs-Problems.ipynb b/notebooks/Micro-and-Macro-Implications-of-Very-Impatient-HHs-Problems.ipynb index 5836c6e..ed73e48 100644 --- a/notebooks/Micro-and-Macro-Implications-of-Very-Impatient-HHs-Problems.ipynb +++ b/notebooks/Micro-and-Macro-Implications-of-Very-Impatient-HHs-Problems.ipynb @@ -161,8 +161,7 @@ "execution_count": 2, "metadata": { "code_folding": [ - 0, - 4 + 0 ] }, "outputs": [], @@ -488,6 +487,7 @@ "metadata": { "jupytext": { "cell_metadata_filter": "collapsed,code_folding", + "cell_metadata_json": true, "formats": "ipynb,py:percent" }, "kernelspec": { @@ -505,7 +505,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.9" + "version": "3.7.4" }, "latex_envs": { "LaTeX_envs_menu_present": true, @@ -525,6 +525,19 @@ "report_style_numbering": false, "user_envs_cfg": false }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": false + }, "varInspector": { "cols": { "lenName": 16, diff --git a/notebooks/Micro-and-Macro-Implications-of-Very-Impatient-HHs-Problems.py b/notebooks/Micro-and-Macro-Implications-of-Very-Impatient-HHs-Problems.py index 8a46a2b..6ff1125 100644 --- a/notebooks/Micro-and-Macro-Implications-of-Very-Impatient-HHs-Problems.py +++ b/notebooks/Micro-and-Macro-Implications-of-Very-Impatient-HHs-Problems.py @@ -2,12 +2,13 @@ # jupyter: # jupytext: # cell_metadata_filter: collapsed,code_folding +# cell_metadata_json: true # formats: ipynb,py:percent # text_representation: # extension: .py # format_name: percent -# format_version: '1.2' -# jupytext_version: 1.2.1 +# format_version: '1.3' +# jupytext_version: 1.4.0 # kernelspec: # display_name: Python 3 # language: python @@ -145,7 +146,7 @@ def in_ipynb(): # # To reproduce their basic results, we must import an $\texttt{AgentType}$ subclass and define a dictionary with calibrated parameters identical to those in the paper. -# %% {"code_folding": [0, 4]} +# %% {"code_folding": [0]} # Import IndShockConsumerType from HARK.ConsumptionSaving.ConsIndShockModel import IndShockConsumerType diff --git a/notebooks/Structural-Estimates-From-Empirical-MPCs-Fagereng-et-al-Problems-And-Solutions-HakonsNewVersion.ipynb b/notebooks/Structural-Estimates-From-Empirical-MPCs-Fagereng-et-al-Problems-And-Solutions-HakonsNewVersion.ipynb new file mode 100644 index 0000000..d22b195 --- /dev/null +++ b/notebooks/Structural-Estimates-From-Empirical-MPCs-Fagereng-et-al-Problems-And-Solutions-HakonsNewVersion.ipynb @@ -0,0 +1,715 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Making Structural Estimates From Empirical Results\n", + "\n", + "This notebook conducts a quick and dirty structural estimation based on Table 9 of \"MPC Heterogeneity and Household Balance Sheets\" by Fagereng, Holm, and Natvik , who use Norweigian administrative data on income, household assets, and lottery winnings to examine the MPC from transitory income shocks (lottery prizes). Their Table 9 reports an estimated MPC broken down by quartiles of bank deposits and\n", + "prize size; this table is reproduced here as $\\texttt{MPC_target_base}$. In this demo, we use the Table 9 estimates as targets in a simple structural estimation, seeking to minimize the sum of squared differences between simulated and estimated MPCs by changing the (uniform) distribution of discount factors. The essential question is how well their results be rationalized by a simple one-asset consumption-saving model. \n", + "\n", + "\n", + "The function that estimates discount factors includes several options for estimating different specifications:\n", + "\n", + "1. TypeCount : Integer number of discount factors in discrete distribution; can be set to 1 to turn off _ex ante_ heterogeneity (and to discover that the model has no chance to fit the data well without such heterogeneity).\n", + "2. AdjFactor : Scaling factor for the target MPCs; user can try to fit estimated MPCs scaled down by (e.g.) 50%.\n", + "3. T_kill : Maximum number of years the (perpetually young) agents are allowed to live. Because this is quick and dirty, it's also the number of periods to simulate.\n", + "4. Splurge : Amount of lottery prize that an individual will automatically spend in a moment of excitement (perhaps ancient tradition in Norway requires a big party when you win the lottery), before beginning to behave according to the optimal consumption function. The patterns in Table 9 can be fit much better when this is set around \\$700 --> 0.7. That doesn't seem like an unreasonable amount of money to spend on a memorable party.\n", + "5. do_secant : Boolean indicator for whether to use \"secant MPC\", which is average MPC over the range of the prize. MNW believes authors' regressions are estimating this rather than point MPC. When False, structural estimation uses point MPC after receiving prize. NB: This is incompatible with Splurge > 0.\n", + "6. drop_corner : Boolean for whether to include target MPC in the top left corner, which is greater than 1. Authors discuss reasons why the MPC from a transitory shock *could* exceed 1. Option is included here because this target tends to push the estimate around a bit." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "code_folding": [] + }, + "outputs": [], + "source": [ + "# Import python tools\n", + "\n", + "import sys\n", + "import os\n", + "\n", + "import numpy as np\n", + "from copy import deepcopy" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "code_folding": [] + }, + "outputs": [], + "source": [ + "# Import needed tools from HARK\n", + "\n", + "from HARK.utilities import approxUniform, getPercentiles\n", + "from HARK.parallel import multiThreadCommands\n", + "from HARK.estimation import minimizeNelderMead\n", + "from HARK.ConsumptionSaving.ConsIndShockModel import *\n", + "from HARK.cstwMPC.SetupParamsCSTW import init_infinite" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "code_folding": [] + }, + "outputs": [], + "source": [ + "# Set key problem-specific parameters\n", + "\n", + "TypeCount = 8 # Number of consumer types with heterogeneous discount factors\n", + "AdjFactor = 1.0 # Factor by which to scale all of MPCs in Table 9\n", + "T_kill = 100 # Don't let agents live past this age\n", + "Splurge = 0.7 # Consumers automatically spend this amount of any lottery prize\n", + "do_secant = True # If True, calculate MPC by secant, else point MPC\n", + "drop_corner = True # If True, ignore upper left corner when calculating distance" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "code_folding": [] + }, + "outputs": [], + "source": [ + "# Set standard HARK parameter values\n", + "\n", + "base_params = deepcopy(init_infinite)\n", + "base_params['LivPrb'] = [0.975]\n", + "base_params['Rfree'] = 1.04/base_params['LivPrb'][0]\n", + "base_params['PermShkStd'] = [0.1]\n", + "base_params['TranShkStd'] = [0.1]\n", + "base_params['T_age'] = T_kill # Kill off agents if they manage to achieve T_kill working years\n", + "base_params['AgentCount'] = 10000\n", + "base_params['pLvlInitMean'] = np.log(23.72) # From Table 1, in thousands of USD\n", + "base_params['T_sim'] = T_kill # No point simulating past when agents would be killed off" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "code_folding": [] + }, + "outputs": [], + "source": [ + "# Define the MPC targets from Fagereng et al Table 9; element i,j is lottery quartile i, deposit quartile j\n", + "\n", + "MPC_target_base = np.array([[1.047, 0.745, 0.720, 0.490],\n", + " [0.762, 0.640, 0.559, 0.437],\n", + " [0.663, 0.546, 0.390, 0.386],\n", + " [0.354, 0.325, 0.242, 0.216]])\n", + "MPC_target = AdjFactor*MPC_target_base" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "code_folding": [] + }, + "outputs": [], + "source": [ + "# Define the four lottery sizes, in thousands of USD; these are eyeballed centers/averages\n", + "\n", + "lottery_size = np.array([1.625, 3.3741, 7.129, 40.0])" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "code_folding": [], + "lines_to_next_cell": 1 + }, + "outputs": [], + "source": [ + "# Make several consumer types to be used during estimation\n", + "\n", + "BaseType = IndShockConsumerType(**base_params)\n", + "EstTypeList = []\n", + "for j in range(TypeCount):\n", + " EstTypeList.append(deepcopy(BaseType))\n", + " EstTypeList[-1](seed = j)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "code_folding": [] + }, + "outputs": [], + "source": [ + "# Define the objective function\n", + "\n", + "def FagerengObjFunc(center,spread,verbose=False):\n", + " '''\n", + " Objective function for the quick and dirty structural estimation to fit\n", + " Fagereng, Holm, and Natvik's Table 9 results with a basic infinite horizon\n", + " consumption-saving model (with permanent and transitory income shocks).\n", + "\n", + " Parameters\n", + " ----------\n", + " center : float\n", + " Center of the uniform distribution of discount factors.\n", + " spread : float\n", + " Width of the uniform distribution of discount factors.\n", + " verbose : bool\n", + " When True, print to screen MPC table for these parameters. When False,\n", + " print (center, spread, distance).\n", + "\n", + " Returns\n", + " -------\n", + " distance : float\n", + " Euclidean distance between simulated MPCs and (adjusted) Table 9 MPCs.\n", + " '''\n", + " # Give our consumer types the requested discount factor distribution\n", + " beta_set = approxUniform(N=TypeCount,bot=center-spread,top=center+spread)[1]\n", + " for j in range(TypeCount):\n", + " EstTypeList[j](DiscFac = beta_set[j])\n", + "\n", + " # Solve and simulate all consumer types, then gather their wealth levels\n", + " multiThreadCommands(EstTypeList,['solve()','initializeSim()','simulate(95)','unpackcFunc()'])\n", + " WealthNow = np.concatenate([ThisType.aLvlNow for ThisType in EstTypeList])\n", + "\n", + " # Get wealth quartile cutoffs and distribute them to each consumer type\n", + " quartile_cuts = getPercentiles(WealthNow,percentiles=[0.25,0.50,0.75])\n", + " for ThisType in EstTypeList:\n", + " WealthQ = np.zeros(ThisType.AgentCount,dtype=int)\n", + " for n in range(3):\n", + " WealthQ[ThisType.aLvlNow > quartile_cuts[n]] += 1\n", + " ThisType(WealthQ = WealthQ)\n", + "\n", + " # Keep track of MPC sets in lists of lists of arrays\n", + " MPC_set_list = [ [[],[],[],[]],\n", + " [[],[],[],[]],\n", + " [[],[],[],[]],\n", + " [[],[],[],[]] ]\n", + "\n", + " # Calculate the MPC for each of the four lottery sizes for all agents\n", + " for ThisType in EstTypeList:\n", + " ThisType.simulate(1)\n", + " c_base = ThisType.cNrmNow\n", + " MPC_this_type = np.zeros((ThisType.AgentCount,4))\n", + " for k in range(4): # Get MPC for all agents of this type\n", + " Llvl = lottery_size[k]\n", + " Lnrm = Llvl/ThisType.pLvlNow\n", + " if do_secant:\n", + " SplurgeNrm = Splurge/ThisType.pLvlNow\n", + " mAdj = ThisType.mNrmNow + Lnrm - SplurgeNrm\n", + " cAdj = ThisType.cFunc[0](mAdj) + SplurgeNrm\n", + " MPC_this_type[:,k] = (cAdj - c_base)/Lnrm\n", + " else:\n", + " mAdj = ThisType.mNrmNow + Lnrm\n", + " MPC_this_type[:,k] = cAdj = ThisType.cFunc[0].derivative(mAdj)\n", + "\n", + " # Sort the MPCs into the proper MPC sets\n", + " for q in range(4):\n", + " these = ThisType.WealthQ == q\n", + " for k in range(4):\n", + " MPC_set_list[k][q].append(MPC_this_type[these,k])\n", + "\n", + " # Calculate average within each MPC set\n", + " simulated_MPC_means = np.zeros((4,4))\n", + " for k in range(4):\n", + " for q in range(4):\n", + " MPC_array = np.concatenate(MPC_set_list[k][q])\n", + " simulated_MPC_means[k,q] = np.mean(MPC_array)\n", + "\n", + " # Calculate Euclidean distance between simulated MPC averages and Table 9 targets\n", + " diff = simulated_MPC_means - MPC_target\n", + " if drop_corner:\n", + " diff[0,0] = 0.0\n", + " distance = np.sqrt(np.sum((diff)**2))\n", + " if verbose:\n", + " print(simulated_MPC_means)\n", + " else:\n", + " print (center, spread, distance)\n", + " return distance" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "code_folding": [], + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.85 0.1 0.27883408895212314\n", + "0.8925 0.1 0.35390998260541334\n", + "0.85 0.10500000000000001 0.26530798881461\n", + "0.8075 0.10500000000000001 0.4828691242118494\n", + "0.87125 0.10125 0.24781113982995787\n", + "0.87125 0.10625000000000001 0.25345270114240204\n", + "0.8925 0.10250000000000001 0.36118246270165194\n", + "0.860625 0.10437500000000001 0.23718447511093388\n", + "0.8606250000000001 0.09937499999999999 0.24045925226231343\n", + "0.85 0.10249999999999998 0.2719428828293148\n", + "0.8659375 0.1015625 0.23839175723952177\n", + "0.8659374999999999 0.1065625 0.24353360989230485\n", + "0.8619531250000001 0.101171875 0.23680890871777144\n", + "0.856640625 0.10398437500000002 0.24314617851292902\n", + "0.86361328125 0.10216796875 0.23668478648914162\n", + "0.86494140625 0.09896484374999999 0.23608009325426257\n", + "0.8670996093750003 0.09625976562499997 0.23673771218313686\n", + "0.8666015624999999 0.09996093749999999 0.23778868289006297\n", + "0.863115234375 0.10086914062499999 0.23623538987333287\n", + "0.8644433593750002 0.09766601562499999 0.23665686788297197\n", + "0.86423583984375 0.09879150390625 0.23632419873536445\n", + "0.8638208007812502 0.10104248046875 0.236453875659263\n", + "0.864132080078125 0.099354248046875 0.2361458789493217\n", + "0.8659582519531249 0.097449951171875 0.23627833280090677\n", + "0.8638259887695312 0.10001434326171874 0.23600405679010458\n", + "0.8646353149414062 0.09962493896484374 0.2361332692808619\n", + "0.8645095062255859 0.09955726623535155 0.23609442182217139\n", + "0.8642578887939454 0.09942192077636719 0.23612018803036852\n", + "0.8644466018676757 0.09952342987060546 0.23600623870482612\n", + "0.8633311843872069 0.10057292938232419 0.2361255111620774\n", + "0.8645388507843017 0.09936686515808105 0.23606568371352615\n", + "0.8637337398529052 0.10017090797424313 0.23600829840255386\n", + "0.8639350175857543 0.0999698972702026 0.23603588396919856\n", + "0.8641362953186035 0.09976888656616209 0.23598479183125098\n", + "0.8641824197769165 0.09969060420989989 0.23600954438940197\n", + "0.8637798643112181 0.10009262561798093 0.23601754015774298\n", + "0.8640817809104919 0.09979110956192015 0.2360160378094304\n", + "0.8639811420440673 0.09989161491394041 0.23603241058830587\n", + "0.86415935754776 0.09972974538803099 0.23601876461504\n", + "0.864314510822296 0.09960701704025268 0.2360110301525716\n", + "0.8642914485931394 0.09964615821838378 0.23601679233832187\n", + "0.8642584258317946 0.09966705501079559 0.2360143418777654\n", + "0.8641923803091048 0.09970884859561918 0.23598896945161313\n", + "0.8640141648054123 0.09987071812152859 0.23603291159120565\n", + "0.8642394243180751 0.09967294231057167 0.2359993229033908\n", + "0.8640892513096332 0.0998047928512096 0.23602384526864414\n", + "0.8642018810659646 0.09970590494573114 0.235982691548442\n", + "Optimization terminated successfully.\n", + " Current function value: 0.235983\n", + " Iterations: 23\n", + " Function evaluations: 47\n", + "Time to estimate is 192.3493173122406 seconds.\n", + "Finished estimating for scaling factor of 1.0 and \"splurge amount\" of $700.0\n", + "Optimal (beta,nabla) is [0.86420188 0.0997059 ], simulated MPCs are:\n", + "[[0.76319463 0.73520229 0.68946622 0.58239921]\n", + " [0.65543163 0.62175622 0.55992585 0.41440615]\n", + " [0.57804563 0.54806506 0.48115428 0.32465235]\n", + " [0.40226637 0.38649713 0.33427427 0.21517005]]\n", + "Distance from Fagereng et al Table 9 is 0.235982691548442\n" + ] + } + ], + "source": [ + "# Conduct the estimation\n", + "\n", + "guess = [0.85,0.1]\n", + "f_temp = lambda x : FagerengObjFunc(x[0],x[1])\n", + "opt_params = minimizeNelderMead(f_temp, guess, verbose=True)\n", + "print('Finished estimating for scaling factor of ' + str(AdjFactor) + ' and \"splurge amount\" of $' + str(1000*Splurge))\n", + "print('Optimal (beta,nabla) is ' + str(opt_params) + ', simulated MPCs are:')\n", + "dist = FagerengObjFunc(opt_params[0],opt_params[1],True)\n", + "print('Distance from Fagereng et al Table 9 is ' + str(dist))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### PROBLEM\n", + "\n", + "See what happens if you do not allow a splurge amount at all. Hint: Think about how this question relates to the `drop_corner` option.\n", + "\n", + "Explain why you get the results you do, and comment on possible interpretations of the \"splurge\" that might be consistent with economic theory. \n", + "Hint: What the authors are able to measure is actually the marginal propensity to EXPEND, not the marginal propensity to CONSUME as it is defined in our benchmark model." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Put your solution here\n", + "\n", + "\n", + "\n", + "1. No splurge drop_corner=False: Gives optimal $\\beta=0.7874$ and $\\nabla=0.1602$. Simulated MPCs are:\n", + "\n", + " \n", + " \n", + " \n", + " \n", + "
0.77300.68170.56290.4085
0.74410.66290.55120.4003
0.70310.63220.52860.3838
0.55890.50110.41170.2994
\n", + "Distance from Fagereng et al Table 9 is 0.4997.\n", + "\n", + "\n", + "\n", + "2. No splurge, drop_corner=True: Gives optimal $\\beta=0.8111$ and $\\nabla=0.1266$. Simulated MPCs are:\n", + "\n", + " \n", + " \n", + " \n", + " \n", + "
0.68420.62570.54080.4214
0.66230.61120.52990.4130
0.62850.58490.50840.3963
0.48970.45840.39440.3105
\n", + "Distance from Fagereng et al Table 9 is 0.3853.\n", + "\n", + "\n", + "\n", + "3. Splurge=0.7, drop_corner=False: Gives optimal $\\beta=0.8532$ and $\\nabla=0.1138$. Simulated MPCs are:\n", + "\n", + " \n", + " \n", + " \n", + " \n", + "
0.78090.75030.69930.5808
0.67990.64240.57350.4120
0.60620.57130.49640.3220
0.43290.41060.34810.2128
\n", + "Distance from Fagereng et al Table 9 is 0.3622.\n", + "\n", + "\n", + "\n", + "4. Splurge=0.7, drop_corner=True: Gives optimal $\\beta=0.8642$ and $\\nabla=0.0997$. Simulated MPCs are:\n", + "\n", + " \n", + " \n", + " \n", + " \n", + "
0.76320.73520.68950.5824
0.65540.62180.55990.4144
0.57800.54810.48120.3247
0.40230.38650.33430.2152
\n", + "Distance from Fagereng et al Table 9 is 0.2360.\n", + "\n", + "## Discussion\n", + "\n", + "The first thing to note about these results is the large drop in the distance from Table 9 in Fagereng et al when setting drop_corner=True (compare results 1 vs 2 and results 3 vs 4). In the table the MPC for the lowest lottery size and lowest wealth quartile is 1.047. Even with splurge=0.7 the model cannot generate an MPC close to (and certainly not above) 1. The deviation between the model MPC and the value in the data will therefore be considerable, contributing to a larger distance. Given that the model cannot generate an MPC > 1, it makes sense to drop that value, but the improvement in the distance is to some extent mechanical. Ignoring that value yields higher estimates of $\\beta$ however, since lowering $\\beta$ is the model's best attempt at increasing the MPC. \n", + "\n", + "Focusing rather on the splurge component, we compare results 2 (without a splurge) vs 4 (with a splurge included). Setting splurge=0.7 gives an automatic increase in spending after the lottery which is not generated by the model. In the real world such an increase in spending makes sense if, for example, the lottery win enables a purchase of a durable good that a consumer was saving for. Such a mechanism is not included in the model. \n", + "\n", + "With the splurge fixed and independent of wealth and lottery sizes, the inclusion of the splurge increases MPCs for the smallest lottery wins and reduces it for the larger wins. This enables the model to generate a larger difference in MPCs for different lottery sizes, and improves the fit with the data. The improved fit is achieved with $\\beta$ centered around $0.86$ rather than $0.81$ since the splurge enables the model to imply high MPCs for the smallest lottery wins without needing to reduce $\\beta$. The higher $\\beta$ then enables lower MPCs for the larger lottery wins. \n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### PROBLEM\n", + "\n", + "Call the _Marginal Propensity to Continue Consuming_ (MPCC) in year `t+n` the proportion of lottery winnings that get spent in year `t+n`. That is, if consumption is higher in year `t+2` by an amount corresponding to 14 percent of lottery winnings, we would say _the MPCC in t+2 is 14 percent.\n", + "\n", + "For the baseline version of the model with the \"splurge\" component, calculate the MPCC's for years `t+1` through `t+3` and plot them together with the MPC in the first year (including the splurge component)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Done assigning wealth quartiles\n" + ] + } + ], + "source": [ + "# Put your solution here\n", + "\n", + "# Use estimated beta range from case 4 above (splurge + drop_corner=True)\n", + "center = opt_params[0]\n", + "spread = opt_params[1]\n", + "\n", + "# Give our consumer types the estimated discount factor distribution\n", + "beta_set = approxUniform(N=TypeCount,bot=center-spread,top=center+spread)[1]\n", + "for j in range(TypeCount):\n", + " EstTypeList[j](DiscFac = beta_set[j])\n", + " #EstTypeList[j].track_vars = ['mNrmNow', 'cNrmNow', 'pLvlNow']\n", + "\n", + "# Solve and simulate all consumer types, then gather their wealth levels\n", + "multiThreadCommands(EstTypeList,['solve()','initializeSim()','simulate(95)','unpackcFunc()'])\n", + "WealthNow = np.concatenate([ThisType.aLvlNow for ThisType in EstTypeList])\n", + "\n", + "# Get wealth quartile cutoffs and distribute them to each consumer type\n", + "quartile_cuts = getPercentiles(WealthNow,percentiles=[0.25,0.50,0.75])\n", + "for ThisType in EstTypeList:\n", + " WealthQ = np.zeros(ThisType.AgentCount,dtype=int)\n", + " for n in range(3):\n", + " WealthQ[ThisType.aLvlNow > quartile_cuts[n]] += 1\n", + " ThisType(WealthQ = WealthQ)\n", + "\n", + "print('Done assigning wealth quartiles')" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "# Now for each type we want to simulate 4 periods and calculate MPCCs \n", + "# from consumptions with and without lottery winnings\n", + "numPeriods = 4\n", + "\n", + "simulated_MPC_means = np.zeros((4,4,numPeriods)) # 3d array to store MPC matrices for t to t+n\n", + "\n", + "# Need a structure to keep track of how wealth evolves after the lottery win\n", + "lotteryWealthMat = np.zeros((base_params['AgentCount'],4,numPeriods))\n", + "lotteryWealthList = []\n", + "for j in range(TypeCount):\n", + " lotteryWealthList.append(deepcopy(lotteryWealthMat))\n", + "\n", + "for n in range(numPeriods):\n", + " # Keep track of MPC sets in lists of lists of arrays\n", + " MPC_set_list = [ [[],[],[],[]],\n", + " [[],[],[],[]],\n", + " [[],[],[],[]],\n", + " [[],[],[],[]] ]\n", + "\n", + " for ThisType in EstTypeList:\n", + " ThisType.simulate(1)\n", + " c_base = ThisType.cNrmNow\n", + " MPC_this_type = np.zeros((ThisType.AgentCount,4))\n", + " for k in range(4): \n", + " if n == 0: # Calculate the initial period MPCs \n", + " Llvl = lottery_size[k]*0\n", + " Lnrm = Llvl/ThisType.pLvlNow\n", + " SplurgeNrm = Splurge/ThisType.pLvlNow\n", + " mAdj = ThisType.mNrmNow + Lnrm - SplurgeNrm\n", + " cAdj = ThisType.cFunc[0](mAdj) + SplurgeNrm\n", + " MPC_this_type[:,k] = (cAdj - c_base)#/Lnrm\n", + " # Store the resulting wealth after the lottery win\n", + " lotteryWealthList[ThisType.seed][:,k,n] = ThisType.mNrmNow + Lnrm - cAdj\n", + " else: # Calculate MPCC after initial lottery win\n", + " # by iterating last period's lottery wealth one period forward\n", + " Llvl = lottery_size[k]*0\n", + " Lnrm = Llvl/ThisType.pLvlNow\n", + " mAdjPrev = lotteryWealthList[ThisType.seed][:,k,n-1]\n", + " mAdjNew = mAdjPrev*base_params['Rfree']/ThisType.PermShkNow + ThisType.TranShkNow\n", + " cAdj = ThisType.cFunc[0](mAdjNew)\n", + " MPC_this_type[:,k] = (cAdj - c_base)#/Lnrm \n", + " lotteryWealthList[ThisType.seed][:,k,n] = mAdjNew-cAdj\n", + " \n", + " # Sort the MPCs into the proper MPC sets\n", + " for q in range(4):\n", + " these = ThisType.WealthQ == q\n", + " for k in range(4):\n", + " MPC_set_list[k][q].append(MPC_this_type[these,k])\n", + "\n", + " # Calculate average within each MPC set\n", + " for k in range(4):\n", + " for q in range(4):\n", + " MPC_array = np.concatenate(MPC_set_list[k][q])\n", + " simulated_MPC_means[k,q, n] = np.mean(MPC_array)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[ nan 0.019 0.0195 0.0244]\n", + " [ nan 0.019 0.0195 0.0244]\n", + " [ nan 0.019 0.0195 0.0244]\n", + " [ nan 0.019 0.0195 0.0244]]\n", + "[[ nan -0.0072 -0.0043 -0. ]\n", + " [ nan -0.0072 -0.0043 -0. ]\n", + " [ nan -0.0072 -0.0043 -0. ]\n", + " [ nan -0.0072 -0.0043 -0. ]]\n", + "[[ nan -0.0007 0.0012 0.0063]\n", + " [ nan -0.0007 0.0012 0.0063]\n", + " [ nan -0.0007 0.0012 0.0063]\n", + " [ nan -0.0007 0.0012 0.0063]]\n", + "[[ nan 0.0025 0.0042 0.01 ]\n", + " [ nan 0.0025 0.0042 0.01 ]\n", + " [ nan 0.0025 0.0042 0.01 ]\n", + " [ nan 0.0025 0.0042 0.01 ]]\n" + ] + } + ], + "source": [ + "print(np.round(simulated_MPC_means[:,:,0],4))\n", + "print(np.round(simulated_MPC_means[:,:,1],4))\n", + "print(np.round(simulated_MPC_means[:,:,2],4))\n", + "print(np.round(simulated_MPC_means[:,:,3],4))\n" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "for lottSize in range(4):\n", + " plt.subplot(2,2,lottSize+1)\n", + " for q in range(4):\n", + " labStr = \"Wealth Q=\" + str(q)\n", + " plt.plot(simulated_MPC_means[lottSize,q,:], label=labStr)\n", + " plt.xticks(ticks=range(4))\n", + " plt.title('Lottery size = %d' %lottSize)\n", + "plt.subplots_adjust(hspace=0.6, wspace=0.4)\n", + "# plt.legend(loc='best')\n", + "plt.show()" + ] + } + ], + "metadata": { + "cite2c": { + "citations": { + "6202365/SUE56C4B": { + "author": [ + { + "family": "Fagereng", + "given": "Andreas" + }, + { + "family": "Holm", + "given": "Martin B." + }, + { + "family": "Natvik", + "given": "Gisle J." + } + ], + "genre": "discussion paper", + "id": "6202365/SUE56C4B", + "issued": { + "year": 2017 + }, + "publisher": "Statistics Norway", + "title": "MPC Heterogeneity and Household Balance Sheets", + "type": "report" + } + } + }, + "jupytext": { + "cell_metadata_filter": "collapsed,code_folding", + "formats": "ipynb,py:percent" + }, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.4" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": false + }, + "varInspector": { + "cols": { + "lenName": 16, + "lenType": 16, + "lenVar": 40 + }, + "kernels_config": { + "python": { + "delete_cmd_postfix": "", + "delete_cmd_prefix": "del ", + "library": "var_list.py", + "varRefreshCmd": "print(var_dic_list())" + }, + "r": { + "delete_cmd_postfix": ") ", + "delete_cmd_prefix": "rm(", + "library": "var_list.r", + "varRefreshCmd": "cat(var_dic_list()) " + } + }, + "types_to_exclude": [ + "module", + "function", + "builtin_function_or_method", + "instance", + "_Feature" + ], + "window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/notebooks/Structural-Estimates-From-Empirical-MPCs-Fagereng-et-al-Problems-And-Solutions-HakonsNewVersion.py b/notebooks/Structural-Estimates-From-Empirical-MPCs-Fagereng-et-al-Problems-And-Solutions-HakonsNewVersion.py new file mode 100644 index 0000000..eff80e4 --- /dev/null +++ b/notebooks/Structural-Estimates-From-Empirical-MPCs-Fagereng-et-al-Problems-And-Solutions-HakonsNewVersion.py @@ -0,0 +1,407 @@ +# --- +# jupyter: +# jupytext: +# cell_metadata_filter: collapsed,code_folding +# formats: ipynb,py:percent +# text_representation: +# extension: .py +# format_name: percent +# format_version: '1.3' +# jupytext_version: 1.4.0 +# kernelspec: +# display_name: Python 3 +# language: python +# name: python3 +# --- + +# %% [markdown] +# # Making Structural Estimates From Empirical Results +# +# This notebook conducts a quick and dirty structural estimation based on Table 9 of "MPC Heterogeneity and Household Balance Sheets" by Fagereng, Holm, and Natvik , who use Norweigian administrative data on income, household assets, and lottery winnings to examine the MPC from transitory income shocks (lottery prizes). Their Table 9 reports an estimated MPC broken down by quartiles of bank deposits and +# prize size; this table is reproduced here as $\texttt{MPC_target_base}$. In this demo, we use the Table 9 estimates as targets in a simple structural estimation, seeking to minimize the sum of squared differences between simulated and estimated MPCs by changing the (uniform) distribution of discount factors. The essential question is how well their results be rationalized by a simple one-asset consumption-saving model. +# +# +# The function that estimates discount factors includes several options for estimating different specifications: +# +# 1. TypeCount : Integer number of discount factors in discrete distribution; can be set to 1 to turn off _ex ante_ heterogeneity (and to discover that the model has no chance to fit the data well without such heterogeneity). +# 2. AdjFactor : Scaling factor for the target MPCs; user can try to fit estimated MPCs scaled down by (e.g.) 50%. +# 3. T_kill : Maximum number of years the (perpetually young) agents are allowed to live. Because this is quick and dirty, it's also the number of periods to simulate. +# 4. Splurge : Amount of lottery prize that an individual will automatically spend in a moment of excitement (perhaps ancient tradition in Norway requires a big party when you win the lottery), before beginning to behave according to the optimal consumption function. The patterns in Table 9 can be fit much better when this is set around \$700 --> 0.7. That doesn't seem like an unreasonable amount of money to spend on a memorable party. +# 5. do_secant : Boolean indicator for whether to use "secant MPC", which is average MPC over the range of the prize. MNW believes authors' regressions are estimating this rather than point MPC. When False, structural estimation uses point MPC after receiving prize. NB: This is incompatible with Splurge > 0. +# 6. drop_corner : Boolean for whether to include target MPC in the top left corner, which is greater than 1. Authors discuss reasons why the MPC from a transitory shock *could* exceed 1. Option is included here because this target tends to push the estimate around a bit. + +# %% code_folding=[] +# Import python tools + +import sys +import os + +import numpy as np +from copy import deepcopy + +# %% code_folding=[] +# Import needed tools from HARK + +from HARK.utilities import approxUniform, getPercentiles +from HARK.parallel import multiThreadCommands +from HARK.estimation import minimizeNelderMead +from HARK.ConsumptionSaving.ConsIndShockModel import * +from HARK.cstwMPC.SetupParamsCSTW import init_infinite + +# %% code_folding=[] +# Set key problem-specific parameters + +TypeCount = 8 # Number of consumer types with heterogeneous discount factors +AdjFactor = 1.0 # Factor by which to scale all of MPCs in Table 9 +T_kill = 100 # Don't let agents live past this age +Splurge = 0.7 # Consumers automatically spend this amount of any lottery prize +do_secant = True # If True, calculate MPC by secant, else point MPC +drop_corner = True # If True, ignore upper left corner when calculating distance + +# %% code_folding=[] +# Set standard HARK parameter values + +base_params = deepcopy(init_infinite) +base_params['LivPrb'] = [0.975] +base_params['Rfree'] = 1.04/base_params['LivPrb'][0] +base_params['PermShkStd'] = [0.1] +base_params['TranShkStd'] = [0.1] +base_params['T_age'] = T_kill # Kill off agents if they manage to achieve T_kill working years +base_params['AgentCount'] = 10000 +base_params['pLvlInitMean'] = np.log(23.72) # From Table 1, in thousands of USD +base_params['T_sim'] = T_kill # No point simulating past when agents would be killed off + +# %% code_folding=[] +# Define the MPC targets from Fagereng et al Table 9; element i,j is lottery quartile i, deposit quartile j + +MPC_target_base = np.array([[1.047, 0.745, 0.720, 0.490], + [0.762, 0.640, 0.559, 0.437], + [0.663, 0.546, 0.390, 0.386], + [0.354, 0.325, 0.242, 0.216]]) +MPC_target = AdjFactor*MPC_target_base + +# %% code_folding=[] +# Define the four lottery sizes, in thousands of USD; these are eyeballed centers/averages + +lottery_size = np.array([1.625, 3.3741, 7.129, 40.0]) + +# %% code_folding=[] +# Make several consumer types to be used during estimation + +BaseType = IndShockConsumerType(**base_params) +EstTypeList = [] +for j in range(TypeCount): + EstTypeList.append(deepcopy(BaseType)) + EstTypeList[-1](seed = j) + +# %% code_folding=[] +# Define the objective function + +def FagerengObjFunc(center,spread,verbose=False): + ''' + Objective function for the quick and dirty structural estimation to fit + Fagereng, Holm, and Natvik's Table 9 results with a basic infinite horizon + consumption-saving model (with permanent and transitory income shocks). + + Parameters + ---------- + center : float + Center of the uniform distribution of discount factors. + spread : float + Width of the uniform distribution of discount factors. + verbose : bool + When True, print to screen MPC table for these parameters. When False, + print (center, spread, distance). + + Returns + ------- + distance : float + Euclidean distance between simulated MPCs and (adjusted) Table 9 MPCs. + ''' + # Give our consumer types the requested discount factor distribution + beta_set = approxUniform(N=TypeCount,bot=center-spread,top=center+spread)[1] + for j in range(TypeCount): + EstTypeList[j](DiscFac = beta_set[j]) + + # Solve and simulate all consumer types, then gather their wealth levels + multiThreadCommands(EstTypeList,['solve()','initializeSim()','simulate(95)','unpackcFunc()']) + WealthNow = np.concatenate([ThisType.aLvlNow for ThisType in EstTypeList]) + + # Get wealth quartile cutoffs and distribute them to each consumer type + quartile_cuts = getPercentiles(WealthNow,percentiles=[0.25,0.50,0.75]) + for ThisType in EstTypeList: + WealthQ = np.zeros(ThisType.AgentCount,dtype=int) + for n in range(3): + WealthQ[ThisType.aLvlNow > quartile_cuts[n]] += 1 + ThisType(WealthQ = WealthQ) + + # Keep track of MPC sets in lists of lists of arrays + MPC_set_list = [ [[],[],[],[]], + [[],[],[],[]], + [[],[],[],[]], + [[],[],[],[]] ] + + # Calculate the MPC for each of the four lottery sizes for all agents + for ThisType in EstTypeList: + ThisType.simulate(1) + c_base = ThisType.cNrmNow + MPC_this_type = np.zeros((ThisType.AgentCount,4)) + for k in range(4): # Get MPC for all agents of this type + Llvl = lottery_size[k] + Lnrm = Llvl/ThisType.pLvlNow + if do_secant: + SplurgeNrm = Splurge/ThisType.pLvlNow + mAdj = ThisType.mNrmNow + Lnrm - SplurgeNrm + cAdj = ThisType.cFunc[0](mAdj) + SplurgeNrm + MPC_this_type[:,k] = (cAdj - c_base)/Lnrm + else: + mAdj = ThisType.mNrmNow + Lnrm + MPC_this_type[:,k] = cAdj = ThisType.cFunc[0].derivative(mAdj) + + # Sort the MPCs into the proper MPC sets + for q in range(4): + these = ThisType.WealthQ == q + for k in range(4): + MPC_set_list[k][q].append(MPC_this_type[these,k]) + + # Calculate average within each MPC set + simulated_MPC_means = np.zeros((4,4)) + for k in range(4): + for q in range(4): + MPC_array = np.concatenate(MPC_set_list[k][q]) + simulated_MPC_means[k,q] = np.mean(MPC_array) + + # Calculate Euclidean distance between simulated MPC averages and Table 9 targets + diff = simulated_MPC_means - MPC_target + if drop_corner: + diff[0,0] = 0.0 + distance = np.sqrt(np.sum((diff)**2)) + if verbose: + print(simulated_MPC_means) + else: + print (center, spread, distance) + return distance + + +# %% code_folding=[] +# Conduct the estimation + +guess = [0.85,0.1] +f_temp = lambda x : FagerengObjFunc(x[0],x[1]) +opt_params = minimizeNelderMead(f_temp, guess, verbose=True) +print('Finished estimating for scaling factor of ' + str(AdjFactor) + ' and "splurge amount" of $' + str(1000*Splurge)) +print('Optimal (beta,nabla) is ' + str(opt_params) + ', simulated MPCs are:') +dist = FagerengObjFunc(opt_params[0],opt_params[1],True) +print('Distance from Fagereng et al Table 9 is ' + str(dist)) + +# %% [markdown] +# ### PROBLEM +# +# See what happens if you do not allow a splurge amount at all. Hint: Think about how this question relates to the `drop_corner` option. +# +# Explain why you get the results you do, and comment on possible interpretations of the "splurge" that might be consistent with economic theory. +# Hint: What the authors are able to measure is actually the marginal propensity to EXPEND, not the marginal propensity to CONSUME as it is defined in our benchmark model. + +# %% [markdown] +# ## Put your solution here +# +# +# +# 1. No splurge drop_corner=False: Gives optimal $\beta=0.7874$ and $\nabla=0.1602$. Simulated MPCs are: +# +# +# +# +# +#
0.77300.68170.56290.4085
0.74410.66290.55120.4003
0.70310.63220.52860.3838
0.55890.50110.41170.2994
+# Distance from Fagereng et al Table 9 is 0.4997. +# +# +# +# 2. No splurge, drop_corner=True: Gives optimal $\beta=0.8111$ and $\nabla=0.1266$. Simulated MPCs are: +# +# +# +# +# +#
0.68420.62570.54080.4214
0.66230.61120.52990.4130
0.62850.58490.50840.3963
0.48970.45840.39440.3105
+# Distance from Fagereng et al Table 9 is 0.3853. +# +# +# +# 3. Splurge=0.7, drop_corner=False: Gives optimal $\beta=0.8532$ and $\nabla=0.1138$. Simulated MPCs are: +# +# +# +# +# +#
0.78090.75030.69930.5808
0.67990.64240.57350.4120
0.60620.57130.49640.3220
0.43290.41060.34810.2128
+# Distance from Fagereng et al Table 9 is 0.3622. +# +# +# +# 4. Splurge=0.7, drop_corner=True: Gives optimal $\beta=0.8642$ and $\nabla=0.0997$. Simulated MPCs are: +# +# +# +# +# +#
0.76320.73520.68950.5824
0.65540.62180.55990.4144
0.57800.54810.48120.3247
0.40230.38650.33430.2152
+# Distance from Fagereng et al Table 9 is 0.2360. +# +# ## Discussion +# +# The first thing to note about these results is the large drop in the distance from Table 9 in Fagereng et al when setting drop_corner=True (compare results 1 vs 2 and results 3 vs 4). In the table the MPC for the lowest lottery size and lowest wealth quartile is 1.047. Even with splurge=0.7 the model cannot generate an MPC close to (and certainly not above) 1. The deviation between the model MPC and the value in the data will therefore be considerable, contributing to a larger distance. Given that the model cannot generate an MPC > 1, it makes sense to drop that value, but the improvement in the distance is to some extent mechanical. Ignoring that value yields higher estimates of $\beta$ however, since lowering $\beta$ is the model's best attempt at increasing the MPC. +# +# Focusing rather on the splurge component, we compare results 2 (without a splurge) vs 4 (with a splurge included). Setting splurge=0.7 gives an automatic increase in spending after the lottery which is not generated by the model. In the real world such an increase in spending makes sense if, for example, the lottery win enables a purchase of a durable good that a consumer was saving for. Such a mechanism is not included in the model. +# +# With the splurge fixed and independent of wealth and lottery sizes, the inclusion of the splurge increases MPCs for the smallest lottery wins and reduces it for the larger wins. This enables the model to generate a larger difference in MPCs for different lottery sizes, and improves the fit with the data. The improved fit is achieved with $\beta$ centered around $0.86$ rather than $0.81$ since the splurge enables the model to imply high MPCs for the smallest lottery wins without needing to reduce $\beta$. The higher $\beta$ then enables lower MPCs for the larger lottery wins. +# + +# %% [markdown] +# ### PROBLEM +# +# Call the _Marginal Propensity to Continue Consuming_ (MPCC) in year `t+n` the proportion of lottery winnings that get spent in year `t+n`. That is, if consumption is higher in year `t+2` by an amount corresponding to 14 percent of lottery winnings, we would say _the MPCC in t+2 is 14 percent. +# +# For the baseline version of the model with the "splurge" component, calculate the MPCC's for years `t+1` through `t+3` and plot them together with the MPC in the first year (including the splurge component) +# + +# %% +# Put your solution here + +# Use estimated beta range from case 4 above (splurge + drop_corner=True) +center = opt_params[0] +spread = opt_params[1] + +# Give our consumer types the estimated discount factor distribution +beta_set = approxUniform(N=TypeCount,bot=center-spread,top=center+spread)[1] +for j in range(TypeCount): + EstTypeList[j](DiscFac = beta_set[j]) + #EstTypeList[j].track_vars = ['mNrmNow', 'cNrmNow', 'pLvlNow'] + +# Solve and simulate all consumer types, then gather their wealth levels +multiThreadCommands(EstTypeList,['solve()','initializeSim()','simulate(95)','unpackcFunc()']) +WealthNow = np.concatenate([ThisType.aLvlNow for ThisType in EstTypeList]) + +# Get wealth quartile cutoffs and distribute them to each consumer type +quartile_cuts = getPercentiles(WealthNow,percentiles=[0.25,0.50,0.75]) +for ThisType in EstTypeList: + WealthQ = np.zeros(ThisType.AgentCount,dtype=int) + for n in range(3): + WealthQ[ThisType.aLvlNow > quartile_cuts[n]] += 1 + ThisType(WealthQ = WealthQ) + +print('Done assigning wealth quartiles') + +# %% +# Now for each type we want to simulate 4 periods and calculate MPCCs +# from consumptions with and without lottery winnings +numPeriods = 4 + +simulated_MPC_means = np.zeros((4,4,numPeriods)) # 3d array to store MPC matrices for t to t+n + +# Need a structure to keep track of how wealth evolves after the lottery win +lotteryWealthMat = np.zeros((base_params['AgentCount'],4,numPeriods)) +lotteryWealthList = [] +for j in range(TypeCount): + lotteryWealthList.append(deepcopy(lotteryWealthMat)) + +for n in range(numPeriods): + # Keep track of MPC sets in lists of lists of arrays + MPC_set_list = [ [[],[],[],[]], + [[],[],[],[]], + [[],[],[],[]], + [[],[],[],[]] ] + + for ThisType in EstTypeList: + ThisType.simulate(1) + c_base = ThisType.cNrmNow + MPC_this_type = np.zeros((ThisType.AgentCount,4)) + for k in range(4): + if n == 0: # Calculate the initial period MPCs + Llvl = lottery_size[k]*0 + Lnrm = Llvl/ThisType.pLvlNow + SplurgeNrm = Splurge/ThisType.pLvlNow + mAdj = ThisType.mNrmNow + Lnrm - SplurgeNrm + cAdj = ThisType.cFunc[0](mAdj) + SplurgeNrm + MPC_this_type[:,k] = (cAdj - c_base)#/Lnrm + # Store the resulting wealth after the lottery win + lotteryWealthList[ThisType.seed][:,k,n] = ThisType.mNrmNow + Lnrm - cAdj + else: # Calculate MPCC after initial lottery win + # by iterating last period's lottery wealth one period forward + Llvl = lottery_size[k]*0 + Lnrm = Llvl/ThisType.pLvlNow + mAdjPrev = lotteryWealthList[ThisType.seed][:,k,n-1] + mAdjNew = mAdjPrev*base_params['Rfree']/ThisType.PermShkNow + ThisType.TranShkNow + cAdj = ThisType.cFunc[0](mAdjNew) + MPC_this_type[:,k] = (cAdj - c_base)#/Lnrm + lotteryWealthList[ThisType.seed][:,k,n] = mAdjNew-cAdj + + # Sort the MPCs into the proper MPC sets + for q in range(4): + these = ThisType.WealthQ == q + for k in range(4): + MPC_set_list[k][q].append(MPC_this_type[these,k]) + + # Calculate average within each MPC set + for k in range(4): + for q in range(4): + MPC_array = np.concatenate(MPC_set_list[k][q]) + simulated_MPC_means[k,q, n] = np.mean(MPC_array) + +# %% +print(np.round(simulated_MPC_means[:,:,0],4)) +print(np.round(simulated_MPC_means[:,:,1],4)) +print(np.round(simulated_MPC_means[:,:,2],4)) +print(np.round(simulated_MPC_means[:,:,3],4)) + + +# %% +import matplotlib.pyplot as plt + +for lottSize in range(4): + plt.subplot(2,2,lottSize+1) + for q in range(4): + labStr = "Wealth Q=" + str(q) + plt.plot(simulated_MPC_means[lottSize,q,:], label=labStr) + plt.xticks(ticks=range(4)) + plt.title('Lottery size = %d' %lottSize) +plt.subplots_adjust(hspace=0.6, wspace=0.4) +# plt.legend(loc='best') +plt.show() diff --git a/notebooks/Structural-Estimates-From-Empirical-MPCs-Fagereng-et-al-Problems-And-Solutions-HakonsVersion.ipynb b/notebooks/Structural-Estimates-From-Empirical-MPCs-Fagereng-et-al-Problems-And-Solutions-HakonsVersion.ipynb new file mode 100644 index 0000000..7295ac2 --- /dev/null +++ b/notebooks/Structural-Estimates-From-Empirical-MPCs-Fagereng-et-al-Problems-And-Solutions-HakonsVersion.ipynb @@ -0,0 +1,679 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Making Structural Estimates From Empirical Results\n", + "\n", + "This notebook conducts a quick and dirty structural estimation based on Table 9 of \"MPC Heterogeneity and Household Balance Sheets\" by Fagereng, Holm, and Natvik , who use Norweigian administrative data on income, household assets, and lottery winnings to examine the MPC from transitory income shocks (lottery prizes). Their Table 9 reports an estimated MPC broken down by quartiles of bank deposits and\n", + "prize size; this table is reproduced here as $\\texttt{MPC_target_base}$. In this demo, we use the Table 9 estimates as targets in a simple structural estimation, seeking to minimize the sum of squared differences between simulated and estimated MPCs by changing the (uniform) distribution of discount factors. The essential question is how well their results be rationalized by a simple one-asset consumption-saving model. \n", + "\n", + "\n", + "The function that estimates discount factors includes several options for estimating different specifications:\n", + "\n", + "1. TypeCount : Integer number of discount factors in discrete distribution; can be set to 1 to turn off _ex ante_ heterogeneity (and to discover that the model has no chance to fit the data well without such heterogeneity).\n", + "2. AdjFactor : Scaling factor for the target MPCs; user can try to fit estimated MPCs scaled down by (e.g.) 50%.\n", + "3. T_kill : Maximum number of years the (perpetually young) agents are allowed to live. Because this is quick and dirty, it's also the number of periods to simulate.\n", + "4. Splurge : Amount of lottery prize that an individual will automatically spend in a moment of excitement (perhaps ancient tradition in Norway requires a big party when you win the lottery), before beginning to behave according to the optimal consumption function. The patterns in Table 9 can be fit much better when this is set around \\$700 --> 0.7. That doesn't seem like an unreasonable amount of money to spend on a memorable party.\n", + "5. do_secant : Boolean indicator for whether to use \"secant MPC\", which is average MPC over the range of the prize. MNW believes authors' regressions are estimating this rather than point MPC. When False, structural estimation uses point MPC after receiving prize. NB: This is incompatible with Splurge > 0.\n", + "6. drop_corner : Boolean for whether to include target MPC in the top left corner, which is greater than 1. Authors discuss reasons why the MPC from a transitory shock *could* exceed 1. Option is included here because this target tends to push the estimate around a bit." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "code_folding": [] + }, + "outputs": [], + "source": [ + "# Import python tools\n", + "\n", + "import sys\n", + "import os\n", + "\n", + "import numpy as np\n", + "from copy import deepcopy" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "code_folding": [] + }, + "outputs": [], + "source": [ + "# Import needed tools from HARK\n", + "\n", + "from HARK.utilities import approxUniform, getPercentiles\n", + "from HARK.parallel import multiThreadCommands\n", + "from HARK.estimation import minimizeNelderMead\n", + "from HARK.ConsumptionSaving.ConsIndShockModel import *\n", + "from HARK.cstwMPC.SetupParamsCSTW import init_infinite" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "code_folding": [] + }, + "outputs": [], + "source": [ + "# Set key problem-specific parameters\n", + "\n", + "TypeCount = 8 # Number of consumer types with heterogeneous discount factors\n", + "AdjFactor = 1.0 # Factor by which to scale all of MPCs in Table 9\n", + "T_kill = 100 # Don't let agents live past this age\n", + "Splurge = 0.7 # Consumers automatically spend this amount of any lottery prize\n", + "do_secant = True # If True, calculate MPC by secant, else point MPC\n", + "drop_corner = True # If True, ignore upper left corner when calculating distance" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "code_folding": [] + }, + "outputs": [], + "source": [ + "# Set standard HARK parameter values\n", + "\n", + "base_params = deepcopy(init_infinite)\n", + "base_params['LivPrb'] = [0.975]\n", + "base_params['Rfree'] = 1.04/base_params['LivPrb'][0]\n", + "base_params['PermShkStd'] = [0.1]\n", + "base_params['TranShkStd'] = [0.1]\n", + "base_params['T_age'] = T_kill # Kill off agents if they manage to achieve T_kill working years\n", + "base_params['AgentCount'] = 10000\n", + "base_params['pLvlInitMean'] = np.log(23.72) # From Table 1, in thousands of USD\n", + "base_params['T_sim'] = T_kill # No point simulating past when agents would be killed off" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "code_folding": [] + }, + "outputs": [], + "source": [ + "# Define the MPC targets from Fagereng et al Table 9; element i,j is lottery quartile i, deposit quartile j\n", + "\n", + "MPC_target_base = np.array([[1.047, 0.745, 0.720, 0.490],\n", + " [0.762, 0.640, 0.559, 0.437],\n", + " [0.663, 0.546, 0.390, 0.386],\n", + " [0.354, 0.325, 0.242, 0.216]])\n", + "MPC_target = AdjFactor*MPC_target_base" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "code_folding": [] + }, + "outputs": [], + "source": [ + "# Define the four lottery sizes, in thousands of USD; these are eyeballed centers/averages\n", + "\n", + "lottery_size = np.array([1.625, 3.3741, 7.129, 40.0])" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "code_folding": [], + "lines_to_next_cell": 1 + }, + "outputs": [], + "source": [ + "# Make several consumer types to be used during estimation\n", + "\n", + "BaseType = IndShockConsumerType(**base_params)\n", + "EstTypeList = []\n", + "for j in range(TypeCount):\n", + " EstTypeList.append(deepcopy(BaseType))\n", + " EstTypeList[-1](seed = j)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "code_folding": [] + }, + "outputs": [], + "source": [ + "# Define the objective function\n", + "\n", + "def FagerengObjFunc(center,spread,verbose=False):\n", + " '''\n", + " Objective function for the quick and dirty structural estimation to fit\n", + " Fagereng, Holm, and Natvik's Table 9 results with a basic infinite horizon\n", + " consumption-saving model (with permanent and transitory income shocks).\n", + "\n", + " Parameters\n", + " ----------\n", + " center : float\n", + " Center of the uniform distribution of discount factors.\n", + " spread : float\n", + " Width of the uniform distribution of discount factors.\n", + " verbose : bool\n", + " When True, print to screen MPC table for these parameters. When False,\n", + " print (center, spread, distance).\n", + "\n", + " Returns\n", + " -------\n", + " distance : float\n", + " Euclidean distance between simulated MPCs and (adjusted) Table 9 MPCs.\n", + " '''\n", + " # Give our consumer types the requested discount factor distribution\n", + " beta_set = approxUniform(N=TypeCount,bot=center-spread,top=center+spread)[1]\n", + " for j in range(TypeCount):\n", + " EstTypeList[j](DiscFac = beta_set[j])\n", + "\n", + " # Solve and simulate all consumer types, then gather their wealth levels\n", + " multiThreadCommands(EstTypeList,['solve()','initializeSim()','simulate()','unpackcFunc()'])\n", + " WealthNow = np.concatenate([ThisType.aLvlNow for ThisType in EstTypeList])\n", + "\n", + " # Get wealth quartile cutoffs and distribute them to each consumer type\n", + " quartile_cuts = getPercentiles(WealthNow,percentiles=[0.25,0.50,0.75])\n", + " for ThisType in EstTypeList:\n", + " WealthQ = np.zeros(ThisType.AgentCount,dtype=int)\n", + " for n in range(3):\n", + " WealthQ[ThisType.aLvlNow > quartile_cuts[n]] += 1\n", + " ThisType(WealthQ = WealthQ)\n", + "\n", + " # Keep track of MPC sets in lists of lists of arrays\n", + " MPC_set_list = [ [[],[],[],[]],\n", + " [[],[],[],[]],\n", + " [[],[],[],[]],\n", + " [[],[],[],[]] ]\n", + "\n", + " # Calculate the MPC for each of the four lottery sizes for all agents\n", + " for ThisType in EstTypeList:\n", + " ThisType.simulate(1)\n", + " c_base = ThisType.cNrmNow\n", + " MPC_this_type = np.zeros((ThisType.AgentCount,4))\n", + " for k in range(4): # Get MPC for all agents of this type\n", + " Llvl = lottery_size[k]\n", + " Lnrm = Llvl/ThisType.pLvlNow\n", + " if do_secant:\n", + " SplurgeNrm = Splurge/ThisType.pLvlNow\n", + " mAdj = ThisType.mNrmNow + Lnrm - SplurgeNrm\n", + " cAdj = ThisType.cFunc[0](mAdj) + SplurgeNrm\n", + " MPC_this_type[:,k] = (cAdj - c_base)/Lnrm\n", + " else:\n", + " mAdj = ThisType.mNrmNow + Lnrm\n", + " MPC_this_type[:,k] = cAdj = ThisType.cFunc[0].derivative(mAdj)\n", + "\n", + " # Sort the MPCs into the proper MPC sets\n", + " for q in range(4):\n", + " these = ThisType.WealthQ == q\n", + " for k in range(4):\n", + " MPC_set_list[k][q].append(MPC_this_type[these,k])\n", + "\n", + " # Calculate average within each MPC set\n", + " simulated_MPC_means = np.zeros((4,4))\n", + " for k in range(4):\n", + " for q in range(4):\n", + " MPC_array = np.concatenate(MPC_set_list[k][q])\n", + " simulated_MPC_means[k,q] = np.mean(MPC_array)\n", + "\n", + " # Calculate Euclidean distance between simulated MPC averages and Table 9 targets\n", + " diff = simulated_MPC_means - MPC_target\n", + " if drop_corner:\n", + " diff[0,0] = 0.0\n", + " distance = np.sqrt(np.sum((diff)**2))\n", + " if verbose:\n", + " print(simulated_MPC_means)\n", + " else:\n", + " print (center, spread, distance)\n", + " return distance" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "code_folding": [], + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.86 0.09 0.27241259579700133\n", + "0.903 0.09 0.38194704269423835\n", + "0.86 0.0945 0.2595896473492727\n", + "0.817 0.0945 0.4693136169405813\n", + "0.8815 0.091125 0.25455911357070304\n", + "0.8814999999999998 0.09562499999999999 0.25980354599503014\n", + "0.8761249999999998 0.09421875 0.2429598008152171\n", + "0.8976249999999998 0.09084375 0.3449412070243577\n", + "0.8694062499999999 0.0935859375 0.23745756257727538\n", + "0.8640312499999998 0.09667968750000001 0.24169333798807494\n", + "0.8573124999999999 0.09604687499999999 0.2664561666780328\n", + "0.8714218749999998 0.09467578125000001 0.23711149626461797\n", + "0.8767968749999999 0.09158203124999999 0.24290091628520527\n", + "0.8672226562499998 0.09540527343750001 0.2379206737502208\n", + "0.8736054687499999 0.0928564453125 0.23862171108100785\n", + "0.8688183593749998 0.09476806640625 0.23700687498348497\n", + "0.8708339843749997 0.09585791015625 0.2369064481020436\n", + "0.8715478515624997 0.09699389648437501 0.23759509176499125\n", + "0.8682304687499998 0.09595019531250001 0.2366352068138906\n", + "0.8666347656249997 0.09658740234375002 0.23739394759879984\n", + "0.8702460937499996 0.09704003906250001 0.2367027219922535\n", + "0.8676425781249997 0.09713232421875001 0.23651159282325868\n", + "0.8660468749999999 0.09776953124999999 0.23705044494205021\n", + "0.8656269531249998 0.09604248046875001 0.23960973176025058\n", + "0.8690913085937497 0.09679064941406251 0.23633625586147677\n", + "0.8685034179687496 0.09797277832031251 0.23599523654927274\n", + "0.8686398925781247 0.09898406982421876 0.23636341150349835\n", + "0.8699521484374997 0.09763110351562501 0.2364761691743695\n", + "0.8693747558593746 0.09750640869140625 0.23634717183868773\n", + "0.8682199707031247 0.09725701904296877 0.23624720042849792\n", + "0.8676320800781245 0.09843914794921876 0.2359910665337985\n", + "0.8669024658203117 0.09926339721679689 0.2362521354445832\n", + "0.8679155273437494 0.0991549072265625 0.23611602326763723\n", + "0.8679916381835933 0.09868043518066406 0.23599666944369402\n", + "0.8681438598632809 0.09773149108886721 0.23604556016043673\n", + "0.8680296936035152 0.09844319915771485 0.23597313593865624\n", + "0.8671583557128901 0.0989095687866211 0.23607054772021147\n", + "0.8681671524047847 0.09820697593688965 0.23592989429741668\n", + "0.8685647659301754 0.09821102714538574 0.23600188316899104\n", + "0.8678652515411373 0.0983821177482605 0.23598600749712895\n", + "0.8683315944671627 0.098268057346344 0.23591052446375343\n", + "0.8685647659301756 0.09821102714538577 0.23600188316899093\n", + "0.8684690532684323 0.0980318341255188 0.23599819140384437\n", + "0.8681395335197445 0.09834035789966583 0.23595311729234256\n", + "0.868359213352203 0.09813467538356782 0.23596938839914966\n", + "0.8681944534778592 0.09828893727064134 0.2359284475558041\n", + "0.868358895540237 0.09835001868009569 0.2358890026280835\n", + "0.8684547671079632 0.09842154005169867 0.23601908322182721\n", + "0.8684960365295407 0.09832913875579835 0.23599018397834334\n", + "0.8682698492407795 0.0982989876419306 0.2358994962767861\n", + "Optimization terminated successfully.\n", + " Current function value: 0.235889\n", + " Iterations: 26\n", + " Function evaluations: 50\n", + "Time to estimate is 214.11683011054993 seconds.\n", + "Finished estimating for scaling factor of 1.0 and \"splurge amount\" of $700.0\n", + "Optimal (beta,nabla) is [0.8683589 0.09835002], simulated MPCs are:\n", + "[[0.76151999 0.73298046 0.68864956 0.58006627]\n", + " [0.65413467 0.61885419 0.55851358 0.41024209]\n", + " [0.57849521 0.5453823 0.47929304 0.31907809]\n", + " [0.40379988 0.38415114 0.33102358 0.20557137]]\n", + "Distance from Fagereng et al Table 9 is 0.2358890026280835\n" + ] + } + ], + "source": [ + "# Conduct the estimation\n", + "\n", + "guess = [0.86,0.09]\n", + "f_temp = lambda x : FagerengObjFunc(x[0],x[1])\n", + "opt_params = minimizeNelderMead(f_temp, guess, verbose=True)\n", + "print('Finished estimating for scaling factor of ' + str(AdjFactor) + ' and \"splurge amount\" of $' + str(1000*Splurge))\n", + "print('Optimal (beta,nabla) is ' + str(opt_params) + ', simulated MPCs are:')\n", + "dist = FagerengObjFunc(opt_params[0],opt_params[1],True)\n", + "print('Distance from Fagereng et al Table 9 is ' + str(dist))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### PROBLEM\n", + "\n", + "See what happens if you do not allow a splurge amount at all. Hint: Think about how this question relates to the `drop_corner` option.\n", + "\n", + "Explain why you get the results you do, and comment on possible interpretations of the \"splurge\" that might be consistent with economic theory. \n", + "Hint: What the authors are able to measure is actually the marginal propensity to EXPEND, not the marginal propensity to CONSUME as it is defined in our benchmark model." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Put your solution here\n", + "\n", + "1. No splurge drop_corner=False: Gives optimal $\\beta=0.7898$ and $\\nabla=0.1610$. Simulated MPCs are:\n", + "\n", + " \n", + " \n", + " \n", + " \n", + "
0.77360.68320.56460.4048
0.74350.66480.55300.3963
0.70350.63510.53050.3793
0.56130.50430.41260.2926
\n", + "Distance from Fagereng et al Table 9 is 0.5021.\n", + "\n", + "2. No splurge, drop_corner=True: Gives optimal $\\beta=0.8144$ and $\\nabla=0.1254$. Simulated MPCs are:\n", + "\n", + " \n", + " \n", + " \n", + " \n", + "
0.67840.62360.54110.4202
0.65900.60970.53040.4116
0.62750.58430.50880.3944
0.49120.45830.39350.3058
\n", + "Distance from Fagereng et al Table 9 is 0.3862.\n", + "\n", + "3. Splurge=0.7, drop_corner=False: Gives optimal $\\beta=0.8572$ and $\\nabla=0.1163$. Simulated MPCs are:\n", + "\n", + " \n", + " \n", + " \n", + " \n", + "
0.78130.74900.69770.5700
0.68170.64090.57100.3973
0.61000.57030.49330.3049
0.43830.41060.34400.1940
\n", + "Distance from Fagereng et al Table 9 is 0.3629.\n", + "\n", + "4. Splurge=0.7, drop_corner=True: Gives optimal $\\beta=0.8683$ and $\\nabla=0.0983$. Simulated MPCs are:\n", + "\n", + " \n", + " \n", + " \n", + " \n", + "
0.76150.73300.68880.5805
0.65410.61890.55870.4108
0.57850.54550.47950.3197
0.40380.38420.33120.2061
\n", + "Distance from Fagereng et al Table 9 is 0.2359.\n", + "\n", + "## Discussion\n", + "\n", + "The first thing to note about these results is the large drop in the distance from Table 9 in Fagereng et al when setting drop_corner=True (compare results 1 vs 2 and results 3 vs 4). In the table the MPC for the lowest lottery size and lowest wealth quartile is 1.047. Even with splurge=0.7 the model cannot generate an MPC close to (and certainly not above) 1. The deviation between the model MPC and the value in the data will therefore be considerable, contributing to a larger distance. Given that the model cannot generate an MPC > 1, it makes sense to drop that value, but the improvement in the distance is to some extent mechanical. Ignoring that value yields higher estimates of $\\beta$ however, since lowering $\\beta$ is the model's best attempt at increasing the MPC. \n", + "\n", + "Focusing rather on the splurge component, we compare results 2 (without a splurge) vs 4 (with a splurge included). Setting splurge=0.7 gives an automatic increase in spending after the lottery which is not generated by the model. In the real world such an increase in spending makes sense if, for example, the lottery win enables a purchase of a durable good that a consumer was saving for. Such a mechanism is not included in the model. \n", + "\n", + "With the splurge fixed and independent of wealth and lottery sizes, the inclusion of the splurge increases MPCs for the smallest lottery wins and reduces it for the larger wins. This enables the model to generate a larger difference in MPCs for different lottery sizes, and improves the fit with the data. The improved fit is achieved with $\\beta$ centered around $0.87$ rather than $0.81$ since the splurge enables the model to imply high MPCs for the smallest lottery wins without needing to reduce $\\beta$. The higher $\\beta$ then enables lower MPCs for the larger lottery wins. \n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### PROBLEM\n", + "\n", + "Call the _Marginal Propensity to Continue Consuming_ (MPCC) in year `t+n` the proportion of lottery winnings that get spent in year `t+n`. That is, if consumption is higher in year `t+2` by an amount corresponding to 14 percent of lottery winnings, we would say _the MPCC in t+2 is 14 percent.\n", + "\n", + "For the baseline version of the model with the \"splurge\" component, calculate the MPCC's for years `t+1` through `t+3` and plot them together with the MPC in the first year (including the splurge component)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Done assigning wealth quartiles\n" + ] + } + ], + "source": [ + "# Put your solution here\n", + "\n", + "# Use estimated beta range from case 4 above (splurge + drop_corner=True)\n", + "center = opt_params[0]\n", + "spread = opt_params[1]\n", + "\n", + "# Give our consumer types the estimated discount factor distribution\n", + "beta_set = approxUniform(N=TypeCount,bot=center-spread,top=center+spread)[1]\n", + "for j in range(TypeCount):\n", + " EstTypeList[j](DiscFac = beta_set[j])\n", + " #EstTypeList[j].track_vars = ['mNrmNow', 'cNrmNow', 'pLvlNow']\n", + "\n", + "# Solve and simulate all consumer types, then gather their wealth levels\n", + "multiThreadCommands(EstTypeList,['solve()','initializeSim()','simulate()','unpackcFunc()'])\n", + "WealthNow = np.concatenate([ThisType.aLvlNow for ThisType in EstTypeList])\n", + "\n", + "# Get wealth quartile cutoffs and distribute them to each consumer type\n", + "quartile_cuts = getPercentiles(WealthNow,percentiles=[0.25,0.50,0.75])\n", + "for ThisType in EstTypeList:\n", + " WealthQ = np.zeros(ThisType.AgentCount,dtype=int)\n", + " for n in range(3):\n", + " WealthQ[ThisType.aLvlNow > quartile_cuts[n]] += 1\n", + " ThisType(WealthQ = WealthQ)\n", + "\n", + "print('Done assigning wealth quartiles')" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The MPC for t+0 is \n", + " [[0.74833991 0.73064054 0.68780729 0.58372576]\n", + " [0.63722291 0.61559769 0.5574549 0.41568309]\n", + " [0.56163735 0.54158694 0.47854467 0.32477331]\n", + " [0.39545884 0.38236334 0.33061264 0.20751553]]\n", + "\n", + "\n", + "The MPCC for t+1 is \n", + " [[0.18530711 0.18706143 0.19655785 0.20235439]\n", + " [0.2279251 0.22491684 0.22394888 0.18887014]\n", + " [0.25323252 0.2465847 0.2378824 0.18074179]\n", + " [0.26801595 0.25791383 0.23329237 0.15793976]]\n", + "\n", + "\n", + "The MPCC for t+2 is \n", + " [[0.1288356 0.13855847 0.17127878 0.24380637]\n", + " [0.13260479 0.13742298 0.15890968 0.18393275]\n", + " [0.14214544 0.14253161 0.15662819 0.15541036]\n", + " [0.18144763 0.17442858 0.17041619 0.13331058]]\n", + "\n", + "\n", + "The MPCC for t+3 is \n", + " [[0.10295604 0.11424483 0.15915858 0.26918345]\n", + " [0.0861973 0.09315381 0.12354401 0.18041371]\n", + " [0.08413233 0.08735972 0.10993616 0.13837196]\n", + " [0.11848662 0.1145507 0.12281311 0.11307857]]\n" + ] + } + ], + "source": [ + "# Now for each type we want to simulate 4 periods and calculate MPCCs \n", + "# from consumptions with and without lottery winnings\n", + "numPeriods = 4\n", + "\n", + "simulated_MPC_means = np.zeros((4,4,numPeriods)) # 3d array to store MPC matrices for t to t+n\n", + "\n", + "# Need a structure to keep track of how wealth evolves after the lottery win\n", + "lotteryWealthMat = np.zeros((base_params['AgentCount'],4,numPeriods))\n", + "lotteryWealthList = []\n", + "for j in range(TypeCount):\n", + " lotteryWealthList.append(deepcopy(lotteryWealthMat))\n", + "\n", + "for n in range(numPeriods):\n", + " # Keep track of MPC sets in lists of lists of arrays\n", + " MPC_set_list = [ [[],[],[],[]],\n", + " [[],[],[],[]],\n", + " [[],[],[],[]],\n", + " [[],[],[],[]] ]\n", + "\n", + " for ThisType in EstTypeList:\n", + " ThisType.simulate(1)\n", + " c_base = ThisType.cNrmNow\n", + " MPC_this_type = np.zeros((ThisType.AgentCount,4))\n", + " for k in range(4): \n", + " if n == 0: # Calculate the initial period MPCs \n", + " Llvl = lottery_size[k]\n", + " Lnrm = Llvl/ThisType.pLvlNow\n", + " SplurgeNrm = Splurge/ThisType.pLvlNow\n", + " mAdj = ThisType.mNrmNow + Lnrm - SplurgeNrm\n", + " cAdj = ThisType.cFunc[0](mAdj) + SplurgeNrm\n", + " MPC_this_type[:,k] = (cAdj - c_base)/Lnrm\n", + " # Store the resulting wealth after the lottery win\n", + " lotteryWealthList[ThisType.seed][:,k,n] = ThisType.mNrmNow + Lnrm - cAdj\n", + " else: # Calculate MPCC after initial lottery win\n", + " # by iterating last period's lottery wealth one period forward\n", + " Llvl = lottery_size[k]\n", + " Lnrm = Llvl/ThisType.pLvlNow\n", + " mAdjPrev = lotteryWealthList[ThisType.seed][:,k,n-1]\n", + " mAdjNew = mAdjPrev*base_params['Rfree']/ThisType.PermShkNow + ThisType.TranShkNow\n", + " cAdj = ThisType.cFunc[0](mAdjNew)\n", + " MPC_this_type[:,k] = (cAdj - c_base)/Lnrm \n", + " lotteryWealthList[ThisType.seed][:,k,n] = mAdjNew-cAdj\n", + " \n", + " # Sort the MPCs into the proper MPC sets\n", + " for q in range(4):\n", + " these = ThisType.WealthQ == q\n", + " for k in range(4):\n", + " MPC_set_list[k][q].append(MPC_this_type[these,k])\n", + "\n", + " # Calculate average within each MPC set\n", + " for k in range(4):\n", + " for q in range(4):\n", + " MPC_array = np.concatenate(MPC_set_list[k][q])\n", + " simulated_MPC_means[k,q, n] = np.mean(MPC_array)\n", + " \n", + "\n", + "print('The MPC for t+0 is \\n', simulated_MPC_means[:,:,0])\n", + "print('\\n')\n", + "print('The MPCC for t+1 is \\n', simulated_MPC_means[:,:,1])\n", + "print('\\n')\n", + "print('The MPCC for t+2 is \\n', simulated_MPC_means[:,:,2])\n", + "print('\\n')\n", + "print('The MPCC for t+3 is \\n', simulated_MPC_means[:,:,3])" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXQAAAEICAYAAABPgw/pAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjMsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+AADFEAAAgAElEQVR4nOydd3hURduH72dLsuk9EBJCgFBeuoIdBAQRbMArFhTFAtiwvOpnQRQrKoKFpoCACCJgA2wIioqgKL33nkB6722+P3aBlE0hJOwmmfu6zrV7zpmZ8+zueX47Z8ozopRCo9FoNHUfg6MN0Gg0Gk3NoAVdo9Fo6gla0DUajaaeoAVdo9Fo6gla0DUajaaeoAVdo9Fo6gla0OsIIvKTiAx3tB0ajaPRvlA+9VLQReSoiPStRj4lIpHF9nuJSFTNWlc9lFIDlFLzHG0HgIhEiMhvIpIlInur811rLgzaF2oXEXldRHaISIGIvOJoe+qloDsLImJytA21xBfAFiAAeBH4SkSCHGuSxpmpx75wEHgW+MHRhkADFHQRGSkiB0UkSUSWi0gT2/E1tiTbRCTD9kj3E9DEtp8hIk1ExCAiz4vIIRFJFJElIuJvKyPCVrN5QESOA6tF5AcReayUDdtFZJAd2ywissBWboqIbBCRRrZzv4vICNv7bcVsyrBds5ft3OUi8pct/7bTx2vw+2sNXAyMU0plK6W+BnYAt9TkdTS1j/aF80cpNU8p9ROQXtNlVwulVL3bgKNAXzvHrwESsAqSKzAFWFPsvAIii+33AqJKlfEksB4Is5UxA/jCdi7CVsZngAfgBtwG/FMsf2cgEXCxY9+DwHeAO2AEugLetnO/AyPs5BkF7AW8gVBb2ddj/bO+1rYfVM739D2QUs72fTl5BgN7Sh2bCkxx9O+uN+0LF9IXSuVfALzi8N/b0QZc4Jt4NjCh2L4nkA9EnMNNvAfoU2w/xFaGqdhN3KLYeVcgCWhl258ITC/H7vuBv4BOds6VuYmB7kAc0Nq2/xwwv1San4HhNfjd3g2sL3XsTeBTR//uerP7e2lfOJumRn2hVNlOIegNrcmlCXDs9I5SKgPrv3boOZTRDPjW9hiXgvWmLgQaFUtzotg1coElwDARMQBDgfnllD0f6023SEROisgEETHbSygiTW3lDldK7S9m262nbbPZ1x2ro9UUGVhrQMXxxlkeOTVVRftCPaShCfpJrD80ACLigbVjL7qc9PZCUZ4ABiilfIttFqVUdAX55gF3AX2ALKXU33YvplS+UupVpVQ74ErgRuCe0ulExA1YCnygrO13xW2bX8o2D6XU2/auJ9bhXxnlbD/ZywPsAlqIiFexY51txzV1B+0LJcupji84HfVZ0M22jpXTmwlYCNwnIl1ExBUYj7VN76gtTyzQolgZsUCAiPgUO/Yx8KaINAMQkSARGViRIbabtgiYRPk1EkSkt4h0FBEjkIb18bXQTtI5wF6l1IRSxxcAN4nIdSJitH3uXiISVo5dA5RSnuVsA8rJsx/YCoyzlT8Y6AR8XdF3oHEo2hdqwRdsdppFxIJVS0226xgr+g5qFUe3+dTGhrXdUJXa3rCdewg4hLUt73sgrFi+h4BTWDtCbrMdm4P1UTQF62OqAXgK2Ie1meEQMN6WNsJ2LZMdm8ZSqk3RTpqhtnIzsTrQ5NNlUazd0FZOFtbmj9NbD9u5y4A/bJ8vHutwqvAa/n4jbPZk2+wt00arN+fYtC/Uui98auf7vddRv7fYjNLUMiJyDzBKKdXd0bZoNI5E+0LtUZ+bXJwGEXEHHgFmOtoWjcaRaF+oXbSg1zIich3Wx71YrO2WGk2DRPtC7aObXDQajaaeoGvoGo1GU09wWMCcwMBAFRER4ajLa+oYmzZtSlBK1csAYNoXNOdCRb7gMEGPiIhg48aNjrq8po4hIscqT1U30b6gORcq8gXd5KLRaDT1BKcS9AOx6TyxaAs5+fYmhGk0DYesvAJe+GYHO6NTHW2Kpg7hVIIel57Lsq0nmbr6oKNN0WgcSk5+Eb/tjeOxL7aQkVvgaHM0dQSnEvSrIgO55eIwPv7jEPtidPA+TcPF38OFD+/owrHETMZ+uwM9vFhTFZxK0MnP5rWwjXhbTDz/zXaKivRNrGm4XNYigCf6tGbp1pN8uckplvPUODnOJeg7vsJj5VN80mkPW46n8Pk/9XZgg0ZTOTlpjO7dkitaBDBu2S4OxumnVk3FOJegd7kLInpw0e4JDG5ewDsr9nEqNdvRVmk0ZxCR/iKyT6xrcT5fTprbRGS3iOwSkepNcU+NgulXYNw0mw/u6IK7i5FHP9cDBjQV41yCbjDAoOkIwluGjygsKmDcMr1ugsY5sMW5ngYMANoBQ0WkXak0rYAXgKuUUu2xrrt57ng1gcYdYMXzNErcwKTbOrMvNp3Xvt99fh9CU69xLkEH8A2H/m9hif6bT9psYuXuWFbsjHG0VRoNwKXAQaXUYaVUHrAIKL2gw0hgmlIqGUApFVetKxkM8N9Z4N8SltxDr+AsHuzZgoX/HOeH7afO5zNo6jFOJej5Rfn8ePhHVJe7oHV/rjw6jWuDUxm3fCdpOfmONk+jCaXYGplAFGXX4GwNtBaRdSKyXkT62ytIREaJyEYR2RgfH2//ahZvGPoFqEL44k6e6RXKReG+PP/1do4nZtXAx9HUN5xK0JcdXMZzfz7Ht4eWwk2TEbM7H7p8TGJ6Fu+u2Odo8zQasXOs9FAsE9AK6IV11Z1PRMS3TCalZiqluimlugUFVRCiJqAlDJkL8XswL3uYybd3RgRGf7GZvIKian8QTf3EqQR9cORgLg+5nPH/jGdffgrc+B7uCduY1XwNC/45xqZjSY42UdOwiQKaFtsPw7rYcuk0y5R1keMjWJdRa3VeV43sA/3egL3f03T7FCYM6cT2qFQmrNh7XsVq6h9OJehGg5G3e7yNt4s3z/zxDJmt+0GHIfSKmUtPz2he+GaHrpVoHMkGoJWINBcRF+AOYHmpNEuB3gAiEoi1CebweV/58keso8D+eJv+hn+554pmfLL2CKv3xp530Zr6g1MJOkCAWwDvXP0Ox9OP8+pfr6IGTEDcA5nqNpNjsUnMXHPI0SZqGihKqQJgNPAzsAdYopTaJSKvicjNtmQ/A4kishv4Dfg/pVRida6Xlpd2dkcEbnwfwi6Bbx/ixa5FtAvx5ukl2/TQXs0ZnE7QAS5pfAmPXfQYPx39iS+jfoWBU/FMO8DUkJ+YvPogh+MzHG2ipoGilPpRKdVaKdVSKfWm7djLSqnltvdKKfWUUqqdUqqjUmpRda4TkxnD4GWDmbtz7tmDJle4fQFYfHH98i6mDw4nt6CIJxZtpaBQP7lqnFTQAe7vcD/dQ7vz9r9vs9s/FLreS9/kJVxu2s8YHdtCU88Jcgvi4uCLeW/Te3yx94uzJ7wawx0LICOWiF8f4c2b2/DvkSQm64B2GpxY0A1iYHz38fhb/Hn696dJ7/U84hvONPeZbD+sY1to6jdGg5HxPcbTu2lvxv8znm8PfHv2ZGhXGDgVjq1lcMwUbrk4jCmrD/DXwQTHGaxxCqok6BdsunMp/Cx+TOw5kZjMGMZtehc16CM8s6L5wO9r3vxhDwkZuTVxGY3GKTEbzEzsOZErm1zJuL/G8ePhH8+e7HQbXPk4bJzN+PANtAj04InFW7VPNHAqFfQLOt3ZDl2Cu/DExU+w6tgqFmYfRa54lH7ZP9A1fzOv62nQmnqOi9GFD3p/QNdGXRmzdgy/Hvv17Mm+r0DktbiufI7ZvfJIzc7nqSXbdJTSBkxVaugXbrpzOQxvP5xeYb2YuHEiOzr9F4LaMtn9E37bup/f99XopTQap8PN5MbUPlNpH9ieZ9Y8w9rotdYTBiMMmQ1+zYn49SHe6ePLmv3xzPzz/EdJauomVRH0GpvuXF1EhDe6v0GwWzDPrBtD6o2T8ChI5j3Pzxm7dCdZeXpFF039xsPswUd9P6KVbyue/O1J/j31r/WExQeGLoLCAgbtfYZB7X2Y+PM+Nh9PdqzBGodQFUGvsenOVYlfUZhuP+azj6sPE3tOJC47jrGHFkOPZ+hb8AcdUv/gg18OVOFjaDR1G28Xb2ZcO4MwzzBGrx7N1rit1hOBkTBkDhK3m3dNM2js7cpjC7eQmqXjHzU0qiLoNTbdubL4Fem//sqhvteSvWOnXUM6BnXk6a5P8/uJ3/kssBGEdGGS21yW/rlFL6araRD4WfyY1W8Wwe7BPPzLw+xKtIWXbtUX+r6Ked9yvmy3lti0HJ79epse3tvAqIqgX7DpzpZ27TB4enJ8xAhy9tkPxnXXf+6ib3hfPtgyha29n8adHN61zOGFr7fryRWaBkGQexCf9PsEbxdvHlz1IAeSbU+oVz4GnW4nZPN7TO96ip93xTJ/vV71qyFRqaBfyOnO5pAQwud9isFi4fh995N7qOw0fxHhtateo7FHY57ZNpmU3s/SU22gTex3fPrX0XO9pEZTJ2ns0ZhPrvsEV4MrI1eO5EjqEWt4gJsmQ2hXrt33MsOaZ/DG93vYdVI/vTYUqjQO/UJNdwZwCQsj/NO5YDBw/N77yDtWtobh5eLFpF6TSMpJYkz2IQqbXclrLvNZuPIvTiTpONGahkFTr6bMum4WCsWIlSOISo8CswVu/xxx8eTVrDdp5p7DYwu3kJmrBw40BJxypqhr8+aEz5mNys/n2H33kR8dXSZNu4B2PHfJc6w9uZa57a/BYhLGGz7i5aXbdbuhpsHQwqcFM6+dSU5BDiNWjiAmMwa8Q+COzzFmxPBVwAyiElMZu3Sn9osGgFMKOoCldWvC58ymKCOTY/fdT35s2TCht7W5jf4R/Zm693M293iEy2UnzQ59zvd6iS5NA6KNfxtmXjuT1NxURq4cSUJ2AoR1g5s+xCfmb5ZEfM+3W6L5SofLqPc4raCDtZM0fNZMChMSOH7f/RQklmyWFxHGXTGOMK8wno1ZTUJkH14wL+LT5StJycpzkNUazYWnfWB7pvedTmxWLCNXjiQlJwW6DIUrRtPl1BJeaPQPLy/bxcE4+8OCNfUDpxZ0ALfOnWk642PyT560inpyyQkTni6eTOo5ibS8NMYEeIGrOy/lT+adH+wPfdRo6isXBV/ElGumcDztOKNWjbLGU+/7KrS8hlHp07nSvJ/RC7eQk1/oaFM1tYTTCzqA+yWX0HT6NPKOHuXEiJFlJh+18W/DC5e+wN9xm5nbbSBdDIfw3/oRfx+q1roCGk2d5bKQy3i/9/scSDnAI788QlZRnnXSkW84H5k/IC3miI6BVI+pE4IO4HHllYRO/pCc/fs5MepBijIzS5z/b6v/cmOLG5l+8nf+at2HJ83fMOerZbo2omlwXB12NROunsDOhJ08tvoxcsxuMHQRLuTzjf9Uvv7nAD/ofqZ6SZ0RdACvXr0InTiR7O3bOfHwIxRln116S0R46fKXiPCJYIwhkTh3P57OfI8Zv+raiKbhcW2za3mj+xtsiNnAk78/SZ5/BNwym0ZZB5jlM5fnv97G8UQ9xLe+UacEHcD7un40efttsjZsIGr0YxTlne38dDe7817P98gsyOKlVh1oZTiBZd0E9sfqjiBNzVCVtQFs6YaIiBKRbtW9VuoPP5Qb26gq3NjiRl658hXWRa/j2TXPkh/ZG+k7jh65axgh3/LYF5v1ouv1jDon6AA+N91IyBuvk7luHdFP/g+VfzYIUaRfJGMvH8uGtENMbt2dEcbv+HTRYh0jWnPeVGVtAFs6L+Bx4J/qXiv/5ElOPv8ChwcOJGvDhuoWw39b/ZfnL32eX4//yotrX6Twiseg4608zmICT67m3Z/3VrtsjfNRJwUdwPeWW2j00lgyVq8m+tlnUQVnZ8INjBzIoMhBzM0/wR8+TRiVOIHFf+kbV3PeVGVtAIDXgQlATnUvZG7ShIgF8xGzmWP3DCdu0iRUXvWG4t71n7t48uIn+enIT7yy/lWKbvoQCenMNMtH/Lb2T1bvLTvHQ1M3qbOCDuB/110EP/ss6T+t4NSLL6KKzj4+jrlsDC19W/JKIx9czYnIqpeJTau2f2k0UIW1AUTkIqCpUur7igqqSihpt86dafHNN/jeeiuJsz7hyO13kHuweotBP9DxAR7q/BBLDy7lrc0foG7/HFc3Tz5ze59XF68lJlX7Rn2gTgs6QMD99xH4+GOkLltOzCuvnpne7GZyY1KvSeSoQp5p3p4hspJFi+Y52FpNHafCtQFExAC8DzxdWUGVhZI+jcHDg5DXXiVs+jQKYmM5cssQkuYvqNY0/kc6P8K97e9l0b5FvH9wCdy+gBASeavoff73xUYKdbNknafOCzpA4MMPEzBqFClLlhA7/q0zN3sLnxaMu2Ic2wuTeTe4GbdFv83qLfsdbK2mDlPZ2gBeQAfgdxE5ClwOLD+fjtEzBV9zDS2WL8Pj8suJffNNTowcRX7suS2/KCI81fUpbm9zO3N3zeXjpM3ITe9zpezg2qgpTP5VLxRT16kXgi4iBP3vSfyH30Py/PnEv/feGVG/ocUN3Nr6VhZ6KPa655Dz3TOk5+iVXDTVosK1AZRSqUqpQKVUhFIqAlgP3KyU2lgTFzcFBhL28Uc0fmUcWRs3cmTgQNJWrjynMkSEMZeNYVDkIKZvm84ccx5c9jD3m1Zw8vdZ/HUooSZM1TiIKgn6hRyqVV1EhODnn8f3jttJnPUJCdOnnzn33KXP0da/LS+GhHCRrOWHJbMutHmaekAV1waoVUQEvzvuoPk332AOCyP68Sc4OeZFCjMyK89swyAGXrniFQZEDOD9Te+zsFkHCiN68qZ5DrMXLiYhI7cWP4GmNqlU0C/kUK3zRURo/PLL+AwaRMKUqSTOng2Aq9GVST0nUWRy4YnGYfQ89BY79unHS825U9naAKXS9qqp2nlpXFs0J+KLhQQ8/BCpS5dyZPBgsjZvqXJ+o8HImz3epHfT3ry14R2WX3IreIfydsE7vLHwFz3Mt45SlRr6BRuqVROIwUDIm2/gff0A4t6dSNL8BQCEe4fz6pWvssdFMS/ARNpXo8kv0GEBNHUXMZsJfuIJmi1YAEpxbNgw4j78sMS8jIowG8xM7DmRq5pcxbiN7/LLNY/hYyrg/qgXmfO7nmFdF6mKoF/QoVo1gRiNNHnnHTz79iH2zTdJ/vJLAK6LuI6hbYfyuY8nOeZtrPlqSq3ZoNFcKNwvvojmS7/FZ9AgEj/6mKND7yT3yJEq5XUxuvB+7/fp1rgbY7ZPY02fJ+lgOErwb8+w+VhSLVuuqWmqIugXfKhWTSBmM6HvvYdHjx7EvDyO1OXWJ+Jnuj1D+4B2jAkKIuzABE4c0aNeNHUfo6cnTca/SejkD8k/cYIj/72F5EWLqjS80c3kxpRrptAhsAP/d+gLfrtkODcb/2L9/JdJzdIDCOoSVRF0hw3VOl8MLi6ETZmM+6WXcvL5F0hb8TMuRhcm9pyEuLjzUrA38YtGoop004umfuDdrx/Nly/HvWtXYl55laiHHqYgofKRKx5mD6b3nU4r31Y8l7yOX5r34qH8Bcz/bKZeuq4OURVBd+hQrfPFYLHQdPo03Lp0IfqZZ0hf/RthXmG82WM8eyxmVngcY+s3kxxtpkZTY5gbBdN01kwavfgimevXc/jmgaSv/q3SfN4u3sy4dgZNvZoyxnSKNX6R3HPqdZb/UnlejXNQqaA7w1Ct88Xg4UHTGR9jaduW6CeeIGPtOvqE92FY22F84eNF1OHJJJ/Y42gzNZoaQ0Twv3sYzb/+ClOjRkQ98ginXh5HUVbFIXP9LH7M6jeLYPdgXggyssfNjU5rH2bPkWMXyHLN+VClcejOMlTrfDB6eRH+ySxcWrYkavRoMv/9l6e6PUUbr9a8EeTD7sX3gW560dQzXCMjab54EQEjR5Dy5ZccGfxfsrdvrzBPoFsgn/T7BB+LH081DSbbJYX0BcPJzNbxXpydejFTtKoYfX0Jn/0J5tBQoh56mPztO5nSbyoY3PjAO5l9S193tIkaTY0jLi4EP/00zT6bR1F+HkeH3kn8tGklIpSWprFHY2b1m4XFxZNR4c0IMuxgw6zHLqDVmurQoAQdwBQQQPicORgDAzkx6kF8jyXx5tXvstfVhS+iPyMnquLai0ZTV3G/5BJaLFuG9w3XkzBlKsfuGkbe8ePlpm/q1ZRP+n2C0cWN4aERtEz7mn+XTruAFmvOlQYn6GDtNGr26VyMXl6cuP8BuueFcn3jwXzt7cE339wDBXrqs6Z+YvTyInTCBELfm0TukSMcHjSYlK++KnckS3Of5szqN4siVzeGhzSl0fZXObFjzQW2WlNVGqSgg3UBgfBP5yKurhy//37GRd5NqArhA698Ni17xtHmaTS1ivf119Ni+TLcOnXi1NiXiHrsMQqS7E8kau3XmhnXziDLYuHBkCCyl91LTlLUBbZYUxUarKADuISHE/7pXACi7x/J5IvfRJSJN5JWkXFY10I09Rtz48aEz5lN8PPPkfnHGg7fPJCMNfbv+/aB7fn42hkkuLrxbCMXDs2+BfKz7abVOI4GLegAri1aED5nDionB8OTz3Of76McMpt4feWjkFf1CHYaTV1EDAYC7r2XiK++xOTvz4lRDxLz2usUZZcV6y7BXZh27TSOuVh41SeFffPvBz3pyKlo8IIOYGnTmqazZ1OYnk7fj7/mspQu/OgGi7+939GmaTQXBEubNkR8uQT/e+8leeFCjtwyhOxdu8qkuyzkMt7rNZl9Lq68nr+Jk6vecYC1mvLQgm7DrUN7ms6cQUFCAk+vSOI/iRYmZu1k//aFjjat3qKUojAtjdzDR8jasIH01asdbVKDxuDqSqPnnyN87hyKMjM5evsdJMyYiSosOT+jd7OrGdPtLXa4uvLi4dmk7/nBQRZrSiOOitPQrVs3tXGj080/IvPffzkxchRpgcG8NDgaFzdh8W2rcPcKcbRpdQKlFEWpqRQkJlKQkEhhYgIFCYkUJCRQkJhAYUKi9VxiIoWJiSVXsjcaabtjO2IoW88QkU1KKYfHB6oNnNEXClNTOfXKK6T/tAK3rl1p8s47uISVCLLK26vnsvD4e1yek8fUgV/hEtLRQdY2LCryBS3odshYu46ohx8m2s+LF+9MoadnI96+61dE7AWerP+ooiIKU1MpTEioXKiTksBePG6TCZO/P8bAAEwBgZgCAjAFBmAMCMQUGIApwPretVWkFnQnQSlF2nffEfPa66AUjV4ai8/AgSX84MGFb/BX/mKa5efTzeBJp6DOdIq8keatbsBocnGg9fUXLejVIH31b5x47DGiA428MKyQF9rcwi1Xv+pos2oMVVhIYUrKWXG2K9SJVhFPTgZ7swrNZqswBwRULNSBgRh9fOwKdVVxFkEXkf7Ah4AR+EQp9Xap808BI4ACIB64XylVYSAUZ/eF/OhoTj73PFkbN+LVvz8hr4zD6OsLQE5+IXfMfI1s+ZVUSyqZRmsejyJFB5M3nQI70LFFfzqGX02gW6ADP0X9QQt6NUlbsYKo/z3F0VB47XZh3vWzaRN6uaPNqpTCjAzyo6KsW3Q0+bFxZYU6KQmKisrkFReXEuJcrlAHBmLw9r5gTy3OIOi25Rj3A9diDSu9ARiqlNpdLE1v4B+lVJaIPAz0UkrdXlG5dcEXVGEhSXPnEvfhZEx+foS8NR7Pq64CrKK+Zn88q3afYv2BDTQyrMPb/QCplhQOuxgosN0joUZ3Ovq3o2P41XQKvoj/BPwHV6OrIz9WnUQL+nkQ9823JIwZw+7m8Nmtbiy86w88Xb0calNRbq5VqKOiyIuKIj8q+sx+flQUhampJdKLxVJGnM+8L9bcYQoKxODp6ZRNS04i6FcAryilrrPtvwCglHqrnPQXAVOVUldVVG5d8QWAnN27if6/Z8k7dAj/4fcQ9NRTGFzPinJhkWLL8WRW7Y5l1a4YzMnb6eC2niDvA8SZk9nh6kKMyQSASQy09YmkY+OudAzsSOegzjT1auqU958zoQX9PPlnymy8p03k31aw676OvDN4ca3edCo/n/yYmLKiHRVFXnQUhfElFywQFxfMoaGYw8Iwh4XiEhaGOTTMdiwUo69vnXcSJxH0IUB/pdQI2/7dwGVKqdHlpJ8KxCil3rBzbhQwCiA8PLzrsWN1JzxtUU4OcRMnkbxgAa6tImny7rtY2ra1m/ZgXAardsfyy55Y9h+P5krZRXePbfha9nDQlMUOV1d2Wixk225PX1cfOgR2pFNQJzoFdqJDYAd8XH0u4Kdzfs5b0Btiu2FpZj05nu4r5rPuP4Ln2NHc0fWRapelioooiI8/U6POi44+I9j5UVHkx8ZC8aFiRiPmxo1LCvZp0Q4LxRQYeF7t03UBJxH0W4HrSgn6pUqpMmEIRWQY1nUEeiqlKgwOVNd84TQZf67l1JgxFKak4NmnD+JitlYcxAAGAxik2L6Qk19EVGoOx5NziE7NwVNlEG5KpIU5ASGJeCPEm12IdXElUQpQgBLBx+JLI8/GNPJoTGOvEAI9gjAaTGfKtd77cvaaZ/Zt78UAImftgbOxa07L35n9MwdK7KvS50vnq2r6c7iWV99ry4wsgop9wWTvYKnMRmAaxdoNRWR58XZDYAvQrVi74QSgwnbDusbgN55m7qkT3Ljtd9a8PZVd03rQPtj+MC2lFIUpKWcFu3SzyMmTJYfrAabgYMyhobh17Yp38Vp2WBjmxo0QU6U/lab2qWw5RgBEpC/wIlUQ87qMZ4/uNF++jNi33iJ72zarLhUVQVGRVZSUsr0vgiLrfqOiIoKVomtREYWFRRQWFJJbWIQoT/woIhBFO5VvEzfBWmiSbbNKTqLDPvGFxbVlS7uCXhFVUYlLgYNKqcMAIrIIGMjpbxdQShVfo2o9MOycrKgDBHq60uz/xrB5/FGu3nGUdf+7m6yHx+KTmINbfDqmmEQKok+e6YgsvTKM0dcXc1gYrm3b4tnnmpK17NAmJdohNU7LmeUYgWisyzHeWTyBrd18BtammbgLb+KFxeTnR+iECedVRmGRYvPxZH7cHcuq3bEcScikmcRwp98+rnXZQbO0zUhBDifNbuwMbc9OryB2qVz2p06+Rj0AACAASURBVB0jvzAPg4IgSyDtA9rRzq8t7fz+Q2vf1riZLHb/YDjd/Fj6FSm1W066UunPvFSW3k6zZ0V5DBZLlb/DM+VV1uSi2w3PopRi6Iy/GPXLo4TsLFnxynaBRD8jaQFuZAd5kd/ID0KCMYU2wa1pBL7+Ifhb/PG3+ONn8cPb5cKNEKkPOEOTi82O64EPsDY/zlFKvSkirwEblVLLReQXoCNwypbluFKqwqUa62qTS21xut191e4YtpxIwUXlcb33EW7z3Uvn3E24px4EIN8nnH0Rl7DdL4Qd5LI9aQ/H063x3Q1iINI38kxna8fAjrTwbYFB6n7T5Hm1oet2w5Icjs9g+AffMivpdbJUFineEO8D8R5Gkt29SXJ1J8lkJkkgqSiPtEL7EelMBhP+rlZx97f44+/mf0bwiwu/v8WfAEsAbia3Bv0H4CyCXhvUVV+4EMSn5/LrHmvNfe3BBHILimhrSeL+Roe52rCdRol/I3mZYDBD+OUkN+/ODv9QdhSksiNhJ9sTtpOelw6Ah9mDtv5tCfEIobFHYxq7N6aRR6Mz731cfeqEj51XGzq63bAELYI8ub3P5QxYOYnBkSa6eqXQ2iWBnsQQkBeNOfUYxByB7GQA8oFko5FkzwASvUNI8gwgyeJNsouFJKOBJApJys/kRPoJknKSyCqwv4ivxWg5K/42sQ+wBJQQfn83q/j7Wfz0+F5NvSDIy5U7Lg3njkvDycor4M8DCazaHcvbexvzbGY3PIz3cldoDDd77KZN+nr8fnuLq4GrvUIgsg9FHZ/mWFArdmQcZXv8dvYn72dT7CbisuIoVCVj1FiMFqvA24S+kbtN7D0an3nv7E/WVamhm7BOpuiDtd1wA3CnUmpXsTQXAV9hbZo5UJUL1+VaSV5BEa9+t4t/jyRxNDGT/MKz32Ejb1cigz3p4Kfo5JFMpDmeUBWDR+YJJPkoJB2BtGhKdHu7eIJfBPhFkOMXTrJXMEnufiS6epBsNJKUl0pSTlLZLTuJvKK80uYB1trIabH3MnvhanTF1eiKi9GlxOvp9xaTpeQ5Q9n0FpOlzDGTmC7IDa5r6JriFBYpNh1L5pc9Z9vdAXqFFDAs8CCXFm7G6+SfSE4qiBHCLoHIvtD8agiIpNDiQ2JuEjGZMcRmxRKTGVPmfXx2PEWq5OQ7N5PbGXG3J/iNPRrjaa7duRw1MWxRtxuWQ35hEceTsjgYl8HBuAwOxWVwMN76mpl3tgbgbTERGexJZLAnbQLMtPdIoYUhgcD8aAwpR61Cn3wEko9CYTGRNpjApyn4Nwe/5iVelW8zsgxCUnYSSblWgU/KSSI5N5nE7MQzwp+Vn0VuYW6JLa8wj9zCXPKL7MRdOQcMYij5J2Cq5I/DaCn3nKvRlcGRg+06gxZ0TXkopTgUn8FKW6fq1hMpKAURfi7cHZ5IP5fthCX8hZzacjaTq7e1EuXfoqxveYeCwUBBUQEJ2Ql2BT82M5aYrBgSshPKiL67yd2u0Bd/72H2qPbn1ROLHIBSipi0nDNCf0bw4zNIyDgr2K4mA80DPc6IfWSQO209MggnFpe0Y2eF/vRrTslZoHg2KiP0Z17dA+z2rBenSBWdEffSYl/6eHnn8grzyCnIIa+ognPF8xWdPa6KPamYxMSWe7bYtVMLuqaqxKXnsHpPHKt2x/LnwQTyCorwcTNzc6SZ6/1OEC5xBOZF45p+3OpXKcegqFisIqML+Daz41MtwK8ZmM42Z+YX5ZOYnWi3hn/6fUJ2Qon7HMDT7GkV+WJNPKXb9N3N7nY/nxZ0JyMlK6+k0MdbX6NTss/MNTAIhPu7ExnsSctgTyKDrILf0isf76wTxYT+KCQdtr5PP1XyQq7e1hvQqwlYfEpubr5lj1l8rXmMF2bMu1KKAlVAbkHumaeFxh6N7abVgq6pDll5BazZb213X703luSss0+k3hYTEYEeRPi50sEzndYuCYRLLMH5J882kSYfgbyMYiWKtQbv39xWwy8l+m6+ZWzIL8wnPju+bC2/mPgn5pQdXT/lmin0atqrzHEt6HWE7LxCDsVba/GHign9kQT77fSRQSXFPshShKQcszbbFK/ZZ8ZBdoq1dp+bBqpsUK4SuHieFfgyol/Jn4KrNxiMNf7daEHXnC+FRYqDcRkcS8zkeFIWxxKzOGp7H52cTUHRWR9zNRkI93enmb8bbb3zaGdJJMIQS0jhKbyzozCmHLX6V2Z8yYu4+dlq8naemr0al/vEnF+YX0boBzQfQBPPJmXSakGv4xQUb6ePP9tWfyg+k4zcs4+K3hZTCYE/vYX4uOFiso2/LSqy1jhyUsvZUio5lgZUcs+4epes9Z/Ln4Krd3kTMLSga2qNgsIiTqbkcCwpk2OJWRxLtL6eFv7s/LP9YQaBJr5uNAtwJ9JH6OCeREtjHE1UDAF5JzGn2CpTqVElK08mt7O1ev8WJWv4vuFgNFfJVi3o9ZTi7fTFa/QH4zJJyCg5ctTVZMDLYsbbYsLLYsLLYra9mvC2mEvsn01X8piLyWD7Q0g/W+OvdCuVLjetgk8k8HKSNSZH6TNa0DUOQilFfEauTeizOJ6YyTGb0B9PyiIps+RIs0BPF8L93Wnh70J791Rau8TTlFiC8k9iyTiOJB21PkUXFJujIkbwCStZq2830Cr6pTjfcegaJ0VECPFxI8THjR6tgkqcS83K52B8OgfjMohLyyU9t4D0nHzScgpIz7G+j0nLIT0nn/ScArLyCsu5yllK/Cm4nRZ9d7xcfUr+SXhV8KdgUFZRtyf+eVl2xVyjcSQiQrCXhWAvC5dE+Jc5n5aTz3Gb2B9Lyjzz/q8jaXydlotS3oA30AoPFyPhAR5EhFto551FW9cEmkk8jQpP4pUVhSH5COxeap3H0riTXUGvCC3o9RQfdzNdm/nTtVnZG9AeBYVFZORaxT41O/+M6Jd4tfOncCr13P4ULGZDMZE3421xxcvSBC/XZnhZTIwpUhgMzjtxQ6MpjbfFTIdQHzqElg3zm5NfSFRyNsfPNOVYm3P2xWfy675s8gotWOdtNsVsvJwwP3fCg9xp41PIrW6taHWOtmhB1wBgMhrwdXfB192lxLTgc+H0n0JadgFppf8MqvCnkFdQxNgb29Xo59JoHInFbDzTl1WawiJrk+mxRGut/mhi1hnh33wsi95dRAu6xnEU/1PQaDQVYzQIob5uhPq6cWXLkueq27epBV2j0WicjOqGDtA9UBqNRlNPcNiwRRGJB+wFRA8EEuwcd0bqiq31wc5mSqmgcs7VaSrwBagfv50zUVfshPJtLdcXHCbo5SEiG+vKeOO6Yqu2s+5SV74TbWfNUx1bdZOLRqPR1BO0oGs0Gk09wRkFfaajDTgH6oqt2s66S135TrSdNc852+p0begajUajqR7OWEPXaDQaTTXQgq7RaDT1BKcSdBHpLyL7ROSgiDzvaHvKQ0TmiEiciOx0tC0VISJNReQ3EdkjIrtE5AlH22QPEbGIyL8iss1m56uOtsnRaF+oWRqKLzhNG7qIGIH9wLVAFLABGKqU2u1Qw+wgIlcDGcBnSqkOjranPEQkBAhRSm0WES9gEzDI2b5Tsc5z9lBKZYiIGVgLPKGUWu9g0xyC9oWap6H4gjPV0C8FDiqlDiul8oBFwEAH22QXpdQaIMnRdlSGUuqUUmqz7X06sAcIdaxVZVFWTi/caLZtzlHTcAzaF2qYhuILziToocCJYvtROOEXXlcRkQjgIuAfx1piHxExishWIA5YpZRySjsvENoXapH67AvOJOj2wos15FpajSEinsDXwJNKqYrWgHMYSqlCpVQXIAy4VESc9vH9AqB9oZao777gTIIeBSXWVggDTjrIlnqDrR3ua+BzpdQ3jranMpRSKcDvQH8Hm+JItC/UAg3BF5xJ0DcArUSkuYi4AHcAyx1sU53G1sEyG9ijlHrP0faUh4gEiYiv7b0b0BfY61irHIr2hRqmofiC0wi6UqoAGA38jLXDYolSapdjrbKPiHwB/A20EZEoEXnA0TaVw1XA3cA1IrLVtl3vaKPsEAL8JiLbsYrZKqXU9w62yWFoX6gVGoQvOM2wRY1Go9GcH05TQ9doNBrN+aEFXaPRaOoJWtA1Go2mnqAFXaPRaOoJWtA1Go2mnqAFXaPRaOoJWtA1Go2mnqAFXaPRaOoJWtA1Go2mnqAFXaPRaOoJWtA1Go2mnqAFXaPRaOoJWtA1Go2mnqAFXaPRaOoJWtA1Go2mnqAFXaPRaOoJWtA1Go2mnqAFXaPRaOoJWtDrCCLyk4gMd7QdGo2j0b5QPvVS0EXkqIj0rUY+JSKRxfZ7iUhUzVpXPZRSA5RS8xxth4gEi8gXInJSRFJFZJ2IXOZouzT20b5Qu4jIbyISLyJpIrJNRAY60p56KejOgoiYHG1DLeCJdTXyroA/MA/4QUQ8HWqVxqmpp74A8AQQopTyBkYBC0QkxFHGNDhBF5GRInJQRJJEZLmINLEdX2NLsk1EMmyPdD8BTWz7GSLSREQMIvK8iBwSkUQRWSIi/rYyImw1mwdE5DiwWkR+EJHHStmwXUQG2bHNIiILbOWmiMgGEWlkO/e7iIywvd9WzKYM2zV72c5dLiJ/2fJvO328plBKHVZKvaeUOqWUKlRKzQRcgDY1eR1N7aN94fxRSm1XShWc3gXMQNOavs65GFTvNuAo0NfO8WuABOBiwBWYAqwpdl4BkcX2ewFRpcp4ElgPhNnKmAF8YTsXYSvjM8ADcANuA/4plr8zkAi42LHvQeA7wB0wYq0Fe9vO/Q6MsJNnFLAX8AZCbWVfj/XP+lrbflA539P3QEo52/dV/K67ADmAj6N/d71pX3CEL9jy5tg+7wrA4LDf29E33AW+iWcDE4rtewL5QMQ53MR7gD7F9kNsZZiK3cQtip13BZKAVrb9icD0cuy+H/gL6GTnXJmbGOgOxAGtbfvPAfNLpfkZGF5L37M3sAN4wdG/ud7K/Y20L5xNU5u+YAYGAP9z5O/d0JpcmgDHTu8opTKw/muHnkMZzYBvbY9xKVhv6kKgUbE0J4pdIxdYAgwTEQMwFJhfTtnzsd50i2ydjhNExGwvoYg0tZU7XCm1v5htt562zWZfd6yOVqOIiBvWGtR6pdRbNV2+ptbRvlCDKKXylVI/AdeJyM21cY2q0NAE/STWHxoAEfEAAoDoctIrO8dOAAOUUr7FNotSKrqCfPOAu4A+QJZS6m+7F7PeFK8qpdoBVwI3AveUTmcT06XAB7abqLht80vZ5qGUetve9cQ6/CujnO0ne3ls+Vxt14/G+misqXtoXyhZTrV8wQ4moOU5pK9R6rOgm20dK6c3E7AQuE9EuthEaTzWNr2jtjyxQItiZcQCASLiU+zYx8CbItIMQESCpJKhSrabtgiYRPk1EkSkt4h0FBEjkIb18bXQTtI5wF6l1IRSxxcAN4nIdSJitH3uXiISVo5dA5RSnuVsA8qx0Qx8BWQD9yiliir67BqnQPtC7fhCWxEZICJuImIWkWHA1cAfFX0HtYoj23tqa8PabqhKbW/Yzj0EHMLalvc9EFYs30PAKawdIbfZjs3B+iiagvUx1QA8BewD0m1ljbeljbBdy2THprGUalO0k2aordxMrA40+XRZFGs3tJWTBWQU23rYzl2G9YZKAuKBH4DwGvxue1Z0fb0516Z9oVZ94T/AP7bPnoJ1OO9gR/7eYjNMU8uIyD3AKKVUd0fbotE4Eu0LtUd9bnJxGkTEHXgEmOloWzQaR6J9oXbRgl7LiMh1WB/3YrG2W2o0DRLtC7VPlZpcRKQ/8CHWAf6fKDs9xSJyG/AK1jatbUqpO2vWVI1Go9FURKWCbutl3o91plUU1ob/oUqp3cXStMI6DvQapVSyiAQrpeJqz2yNRqPRlKYqAXMuBQ4qpQ4DiMgiYCCwu1iakcA0pVQyQFXEPDAwUEVERJyzwZqGyaZNmxKUUkGOtqM20L6gORcq8oWqCHooxWZ7Ya2llw6X2hpARNZhbZZ5RSm1onRBIjIKa7wFwsPD2bhxYxUur9GAiByrPFXdJCIiQvuCpspU5AtV6RQVO8dKt9OYgFZY4z0MBT4REd8ymZSaqZTqppTqFhRkv7JVVKSHUWqcFxHpLyL7xBql8PkK0g2xRf7rVt1raV/QnCtVEfQoSoaDDMM6bbh0mmXKOl33CNYJAa3O1Zj1hxPp/+EaYlJzzjWrRlPr2PqTpmENwtQOGCoi7eyk8wIexzrppFpk5BYwePo6lm4pbya+RlOWqgj6BqCViDQXERfgDmB5qTRLgd4AIhKItQnm8Lka4+tu5mRKDg/M20BWXkHlGTSaC8uZ/iSlVB5wuj+pNK8DE7CGVK0WBYVFWMxGnly8lXd/3qtr65oqUamgK2vw9tFYI5/tAZYopXaJyGvFoor9DCSKyG7gN+D/lFKJ52pM28beTBl6EXtOpfHkoq36JtY4G/b6k0pEJxSRi4CmSqnvKypIREaJyEYR2RgfH1/mvK+7C/MfuIyhlzZl2m+HePjzTbqSo6mUKk0sUkr9qJRqrZRqqZR603bsZaXUctt7pZR6SinVTinVUSm1qLoG9W4bzEs3tmPl7ljeWbG3usVoNLVBhf1JtpCw7wNPV1ZQVfqTXEwGxg/uyEs3tmPV7liGfPQ3J1Oyq2u7pgHgfDNFleLeKyO4+/JmzFhzmMUbjjvaIo3mNJX1J3kBHYDfReQocDmw/Hw6RkWEB7o3Z/a9l3A8KYubp65jy/Hk6hanqec4l6BHbYRZvZH0GMbd1I4erQJ58dud/HUowdGWaTRQSX+SUipVKRWolIpQSkVgXZ7tZqXUuY9JLCyArx6Ao+sA6N0mmG8euRI3FwO3z1zPsq26s1RTFucSdAQSDsD8QZhyU5h218U0D/Tg4QWbORyf4WjjNA2cKvYn1QyZcXBqK8y7CdZNBqVo3ciLZY92p0uYL08s2sqklft0P5OmBM4l6GFdYegXkHQEFvwXb7KZc+8lGA3C/Z9uIDkzz9EWaho4lfUnlUrbq1q1cwDvJjDyN2h7A6x6CRYPg5xU/D1cWDDiMm7rFsaU1Qd5dOFm3VmqOYNzCTpA86vhtnlwajt8MZSmXsLMu7tyMiWHhxZsIq9AL5CjaSBYvOG2z+C68bDvJ5jZC2J24mIy8M4tnRh7w39YsSuG22b8zalU3VmqcUZBB2gzAAbPgGPr4Mt76dbUiwlDOvHPkSRe/HbH6dVCNJr6jwhc8Sjc+wPkZcEnfWHrQkSEET1aMHt4N47EZzJw6jq2nkhxtLUaB+Ocgg7Q6Va4YSLsXwHfPsSgzo15vE8rvtwUxYw15zxnSaOp2zS7Ah76E8K6wdKH4bsnID+Ha9o24ptHrsLFZOD2GX+zfFvpSdyahoTzCjrAJSOgzzjY+RX8+Az/6xPJjZ1CeGfFXlbsjHG0dRrNhcUzGO5eCt2fgk2fwpx+kHyUNo29WPboVXQK8+HxL7bw3qr9urO0geLcgg7Q4ym46knYOAdZ/RoTb+1Ml6a+PLl4CzuiUh1tnUZzYTGaoO84GLoIko7CjJ6w/2cCPF1ZMOIyhnQNY/KvB3jsiy1k5xU62lrNBcb5BR2g7yvQ9T5Y+z6W9R8y8+5uBHi4MuKzDTqQl6Zh0mYAPPgH+IbDwtvg19dxNcC7QzrxwoC2/LjzFLfN+Fv7RwOjbgi6CNwwCTreCr++StDeBcy+txuZuYU8MG8Dmbl62JamAeLfHB5YCRfdDX9OhPmDkaxEHuzZkll3d+NwfAY3T13L9ijdWdpQcCpBP5x6mBErRxCXZWfBI4MRBn0ErfvDD0/TNu5nptxpC+S1eCuFus1Q0xAxu8HAqTBwGpz4Bz7uASf+pW+7Rnz9yJWYjQZum/E332/XnaUNAacS9NjMWHbE7+DOH+5kX9K+sgmMZrj1U4joDt8+SG828bItcNEEHchL05C5aBg8sApMLjB3AKz/mLaNvFg2+iraN/Fh9MItfPDLfj3kt57jVIJ+RZMr+GzAZygU9/x0D2uj15ZNZHazziYN6QxLhjO8yYkzgbwW/asDeWkaMCGdYNQf0KofrHgOvrqPQHMeC0dexn8vDuWDX6ydpTn5urO0vuJUgg7Qxr8NC69fSLh3OKN/Hc2SfUvKJnL1gmFfg39z5IuhjOuaw9Wtgxi7dCd/HdSBvDQNGDdfuP1z60CC3ctg1jW4Jh1g0q2deX5AW37YcYrbZ/xNbJruLK2POJ2gAzTyaMS8/vO4KvQqXl//OhM3TKRIlZry7+5vHZPrHoBp4RCmX+tG80APHlqwSQfy0tR58ovyGbFyBMsOLit771eGwQDd/wf3LIfsFJh1DbLzax7q2ZIZw7pyIC6DgVPXsTNaD/utbziloAO4m935sPeHDG07lHm75/H070+TXVAqXoV3CNyzDIyueC4ewrzBwZiNBh3IS1PnSclJIbsgm7HrxnL3T3ezK3HXuRfSvAc8uMbaFPP1A/DDM/Rr48dXD12J0SAM+fgvftxxquaN1zgMpxV0AJPBxJjLxvDcJc/x6/FfeeDnB0jILtWk4t8c7lkKhbk0WXY7c4eEcTJVB/LS1G2C3IOYP2A+b1z1BlHpUQz9fiiv/f0aKTnnOATROwSGfwdXjIYNs2DuANq5p7L00atoF+LNI59vZsqvB3RnaT3BqQX9NMPaDeOD3h9wMOUgd/1wF4dSDpVMEPwfa5t6ViKdVt/Lhzc11YG8NHUegxgYGDmQ7wd/z7B2w/jmwDfc8O0NLN67mMKic+jYNJrhujetkRvj98OMqwmKXcvCkZcz+KJQJq3azxOLturO0npAnRB0gGvCr2HudXPJK8rj7h/vZv2p9SUThHa1TYc+woBto3mmZwhfbori4z90IC9N3cbLxYtnL3mWr276irb+bXnjnze444c72BK35dwKajcQRv0OXiGw4BYs6yby3q0d+b/r2rB820lun7meON1ZWqepM4IO0D6wPQuvX0gjj0Y8vOphvj3wbckEzXtYayExO3g0Ziz/7RhgC+Sl2wk1dZ9Iv0g+6fcJ7/Z8l+ScZO756R7G/DmG+Kz4qhcSGAkjfoHOd8Dv45GFt/HoZf58PKwr+2PSGThNd5bWZaok6CLSX0T2ichBEXm+gnRDRESdz6K4lRHiGcJnAz7j0pBLefmvl5m8eXLJUQBt+sPgGcixv3hXTaJbU0+eXLxVB/LS1AiV+YKIPCQiO0Rkq4isFZF2NXx9+kf0Z/mg5YzsOJIVR1dw09KbmLdrHvlF+VUrxMXdOuv6xg/gyBqYcTX9/aL56uErALj14791JaiOUqmgi4gRmAYMANoBQ+3dpCLiBTwO/FPTRpbGy8WLqX2mckurW5i1YxbPrXmO3MLcswk6DoEbJmE8uJIF/nMJcjfxwLwNelUXzXlRRV9YqJTqqJTqAkwA3qsNW9zN7jx+8eMsHbiUi4MvZuLGiQxZPoS/T/5dtQJEoNt9cP/PgMCc/rSP/pJlj15Jm8ZePLRgM1NX687SukZVauiXAgeVUoeVUnnAImCgnXSvY72BL0gjnNlgZtwV43iq61OsOLqCET+PICkn6WyCSx6Avq9g2fct37VcSlZeAQ98ulEH8tKcD5X6glIqrdiuB1CrihjuHc70vtOZes1U8grzGLVqFE/9/hSnMqpYww692Bq1sXlP+OFpgn95gkX3dmRglyZMXLmf/y3WnaV1iaoIeihwoth+lO3YGUTkIqCpUur7igoSkVEislFENsbHn0O7X/nlcV+H+5jUcxJ7kvYw7MdhHEk9cjZB9/9B9//hu3sBP7T7lb0xaTyxSAfy0lSbSn0BQEQeFZFDWCs4j9srqKZ9oWfTniwdtJTRXUbzZ9Sf3Lz0ZmZsm1HyybU83P3hziXQeyxsX4Ll03580MeDZ/q1ZunWk9wxcz1x6bqztC5QFUEXO8fOKKKIGID3gacrK0gpNVMp1U0p1S0oKKjqVlZCv4h+zL5uNpn5mQz7cRgbY4ottN5nHHS7n2Z7ZvJl+/X8sieWd3QgL031qNAXzhxQappSqiXwHDDWXkG14QuuRlce7Pwgywctp0dYD6ZuncqgpYP448QflWc2GKDn/8Hd30BmHDLrGkY32sVHd13Mvph0Bk1dx66Tuh/K2amKoEcBTYvthwHFY3F6AR2A30XkKHA5sLw2O0bt0TmoM59f/zkBbgGMXDWS7w59Zz0hAtdbY6l3PTiZKZGbmakDeWmqR2W+UJpFwKBatcgOIZ4hvNfrPWb1m4WL0YXRq0fzyC+PcCztWOWZW15jnV0a3Ba+HM6A6Cl8OaobRQqGfPQ3P+/SSz86M1UR9A1AKxFpLiIuwB3A8tMnlVKpSqlApVSEUioCWA/crJTaaL+42iPMK4z5A+ZzcfDFjFk7ho+2fmTt1DEYzsRSvzFqEs+FbteBvDTVoUJfABCRVsV2bwAOXED7SnB5yOV8dfNXPNPtGTbHbWbwssFM3jyZrPysijP6hMG9P8KlD8L6aXRYeRffD29B68ZePDh/E9N/P6g7S52USgVdKVUAjAZ+BvYAS5RSu0TkNRG5ubYNPFd8XH34uO/HDGw5kOnbpvPi2hfJK8w7E0tdIrrzUNK7DPXZxUMLNnFIB/LSVJEq+sJoEdklIluBp4DhDjIXsA4eGN5+ON8N+o4BzQcwa8csbl56MyuOrqhYlE0ucP0EuGU2xOwgcOG1fNkvn5s6N2HCin08vWSb7ix1QsRR/7TdunVTGzfWXiVeKcXM7TOZunUq3Rp144PeH+Dj6gO56TDvZlTsLh5SL7DXrQtLH7kKPw+XWrNFc/6IyCal1AVtxrtQ1LYvFGdL3BbG/zOevUl7ubTxpbxw6QtE+kVWnCl+Hyy+GxIPoHqPZUrejbz3y0EuDvdlxt3dCPJyvSC2a6xU5At1aqbouSAiPNj5Qd7u8Tbb4rcx7MdhnEg7cSaWuvg3Z7rhUnLsugAAHFBJREFUXYJSd/KgDuSlaSBcFHwRi25YxNjLxrI3aS9DvhvCO/++Q3peevmZgtrAyNXQfjCy+jUej3uZmbe2ZPepNAZNW/f/7Z15dFRVvqi/XVMqqUoIJAEykxBmCCCCApIEBQTEVkCC8+u2++nTtvW2w211vdXL7va2XPW22rNenm33ldY2OOPUqJCATAINYYbMI2QeqpJKDWe/P6oSCIZJKqlKsr+1apE6derU74Tsr/b5nb1/myPVLed+r6JPGbBC7+SG1BtYu2gtjR2N3PHJHeyr2ddVS11vjebvoc/TVLKfp1QhL8UgQa/Ts3r8ajYs38CKMStYd2Qdy95bdv7a6yFWb/plyXNQ8CWLtmTz0coI3JrGyj9t44N9lar9BAEDXugAV4y4gnVL1xFuCueHn/+Qz4o/66qlbjKH8a71eXbt3cOfcgsvfDCFYoAw1DyUn8/+OW8ue5OE8IQL114XAq66D37wKWhuxny0nH9mljJmRDgPv7WPW/68nb1ljX17EopuDAqhAyRHJLNu6TomR0/m8bzHWXtgLXLoKLjrfSwGjXetz/HXz1QNC8XgY1LUpEurvZ440zu0MXkOQzY+wntx63jupjGUNbSx4o/b+PG6vZTW2/v2JBTAIBI6QKQ5kv9e9N8sTVnKy3tf5untT+OKHo248x2iRCs5lud4+h955Fdc4iICCkU/55Jrr1uivWsQZP4M3f51ZO/KZsuSeh6+djRfHa1hwW9y+eVHh9XKYX1MUAlda2+n5ZNPkJ7eGw5l0ptYM28N96Xfx7sn3uX+L+6nJSYNcfs/SBQ1/MXwHA+/nqcKeSkGJZdUe12nh/lPedf2NVkwf3gvPy38EdtWulg5PZ7XtxWT+fwmXs0rVEMc+4igEnrzhg1UPvIoRTd+j+YNH/ea2IUQPDj9QX4191fsObmHuz+5m8roFET23xgvSnjO9Sz3/+VrVchLMWi5pNrro+fDfVtgxVpwtjL0/TtZ0/IzNmeHcEXyUH79yVEW/CaXD/ZVoqk6Sr1KUAk9cuVK4l96EaHXUfXYY70u9pvTbubPC/9MTXsNd3x8BweHxSOWv8KV4ggP1T/DI2/uVoW8FIOWS6q9rtNB+ip4cDfc8BtoKCbpg5W8bnyO95aHE2428vBb+1j+x6/ZWVQfmBMaBATlxCKpabT+85/U/eEPdJwowJSaSvQDDxCxZDFCr/d7LEVNRTzw5QPUt9ezZt4arqsthQ0/5UPPbA5e9TxPLZvi989UXBpqYlHgKWspY82uNWyp3ELqkFSemPUEs+Nm97yzsw12vQpbXwRHE9qkFfxz+I94+msHJ1scLJw4gieWjGd0jLVvT2IAcL62EJRC76QvxV7fXs9Dmx7iQO0BHr3yUe5uaEB8+TTr3Nehu/FFbrsq2a+fp7g0lNCDh9zyXNbsWkOFrYKFyQt5/MrHibXG9rxzexNs+x3s+CO4O3BPvYM3zLfywnYb7S4Pt89K4uEFY4i2qtmmF0u/FXonfSV2h9vBU1ufYmPpRlaPW82/tzgxbXuZVzw3MvnuF5k7xn8lfxWXhhJ6cNHh6eD1g6+z9sBaAG6fcDvZ47KJt36rPLwXWw3kvQC7XwOho236PbzsWMbavS2EGvXcnzWae+amEGry/xX4QKPfC72TvhC7JjVe3vsyrx18jWvir+HXNj1D9/0PL3MbNzzwAmnD1SViIFBCD06qbdX8157/YmPpRqSUzI2fS/bYbOYlzMOgM3z7DY2lsHkN5L8FRgsN0+7j5zWZbDjaSuwQM48uGseK6fHodD2VnlfAABJ6J30h9vXH1/PMjmcYHTmaF2whpBz/mBdN9/L9h/9DFfIKAErowU21rZp3TrzDuyfepba9luFhw1k5ZiUrxqxgpGXkt99QcxS++hUc3QBhUZRO/D88WnwluyvbmRgbwVNLJ3DNmOi+P5F+wIATeie9LfZtldt4JPcRLIYwnm0NZVb5Vn435HHu/cmThBjUpWFfooTeP3BpLvLK88g5nsO2qm0IIchIyCB7bDZz4uag153Vbir2wJe/gOJcZEQC+0ffx8NHJlDa5CRrXAxPLpnAuJHhgTmZIGXACr2T3hT78cbj/PjLH9Pc0cz/bTGz9OQB/pb0DD+45wGEUJeFfYUSev+jvLWcd46/w3sF79HgaCDOEsctY29h+ZjlRIee1fsu2gxf/hIq96BFjeGr2P/NoweTaO3QyL4ykUcWjmV4hDkg5xFsDHihd9JbYq9tq+XBrx7kaMNR7m8x8IPaUj6b9ltuWn67H6NXnA8l9P6Ly+Piy/IvWX9sPTtP7sQgDMxPmk/2uGxmjZyFTvimw0jpTcF89QzUHsU9Ip1/RPyApw+PwKDTc29GKvdmpGIJ6SE3P4gYNELvpDfE3uZq44ktT7CpfBM32+DxmlPkJT3EpOvvISUhzs9noDgbJfSBQUlzCeuPr+f9wvdp7mgmKTyJW8bewk1pNzHMPMy7k+aB/Ldh06+huQxH/Gx+r7uD358YRkx4CI8sHMuqGQkY9EE1L7LPGHRC78TfYvdoHl7Y/QJvHHmDqxw61tSUYXEb2G3JwDTzbmbMW4ZB5dZ7hWARuhBiMfAyoAfWSinXnPX6I8CPADdQC9wjpTzv6sznagtSygGb1uvwdLCxdCM5x3LYW7MXo87IguQFZI/NZsaIGd7zdnfAnr9C3vNgr6EpcQG/sK/gvapIxo6w8uSSCWSNixmwv6NzMWiF3om/xf73I3/nP7/5TzSpMVqzsKCphkVtLZhdUVQkr2DsonuJjk/phTMZvASD0IUQeuA4sBCowLto9G1SysNn7DMf2CmlbBNC3A9kSSlXn++4PbUF6XJRuHgJ5vQphGdlYZk3D8OwYf4+paCgoLGAnOM5fFT4Ea2uVlKHpLJq7CpuHH2jd9lIpx12/Am+/i2yo4XqpGU8VruUbY1DmJsWxZNLJjA5fkigT6PPGPRC78SfYi9qKuKLsi/ILc8lvy4fgBi3joX2ZjLa2rHo0jHP/D7j5t2CMKhZcJdLkAh9NvC0lPJ63/MnAaSUz55j/+nA76WUc8933J7agqepiVPPPY8tLw9PXR0IQWh6OtasTKyZmYRMmDDgeqbt7nY+L/mcnGM55NflE6IP4fpR17Nq7CqmxkxFtDfC1y/DzleQmotjccv5SeVCChxWlk+P57FF44iLDA30afQ6Suhn4e8ee21bLXkVeWyu2Mz2ym10aE7CNMm8tjZmtguShy1g8qKfYE2Y3AtnMzgIEqHfAiyWUv7I9/wu4Cop5YPn2P/3wEkp5TM9vHYvcC9AUlLSjNLSnrMyUtNwHDqMLTcXW24ujgMHADAMH441MxNrViaWq69GZ7H44xSDhqMNR8k5lsOGog20udsYO3Qsq8auYlnqMqyOVm8aZu9fkTojO2JW8VB5Bi1YueeaFO7PGk2E2RjoU+g1LlvofZk37Et64+Zpu7udndU7+aLkSzYVb6RF2tFLyXRHB9PcEcxJu4WZWT8Gc4Sfz2ZgEyRCXwVcf5bQZ0kpf9LDvncCDwKZUsqO8x33UtqCu7YWW94WbLm52L/+Gs1uRxiNhM2a1SV4U1LSJZ9bsGJ32fmk+BNyjuVwpOEIoYZQlqYsZdW4VUwSobDpWTiQg2YK59Mh2TxePgezJYJ/WzCG22YlYRyAN04vS+h9mTcMFL013FGTGofqDpGT/x7byz7npM67Ovoop5sZhjiWTL2TK6fehV4/uIdhXQxBIvSLSrkIIRYAv8Mr85oLHfe7tgXpdNK2dy+2zbnYNm/GWVICgCklBWtWFtbMTMJmXIEw9v/eqpSSQ/WHyDmew6fFn9Lubmdi1ESyx2azJCyZsLwX4PinuMzRvGFaxbM1V5MQHcnPloxn0cQRAyo9dblC77O8YaDp7ZmnR2tK+GveKxyt30RJiA23EAzxSGZbR7Noyh3MSbsBi3FgXTr7iyARugFv5+Y6oBJv5+Z2KeWhM/aZDqzHm5o5cTHH9VdbcJaWelMzm3Np++YbpMuFzmrFMneut/eemYEhKuqyPyfQtDpb2VC0gbePvU1BUwEWo4VlqctYFTGecTv/AqVbabck8FvPSl5pmsmMUVE8tXQC05OGBjp0v3C5Qvdb3vBMglHonfS22DVNsunQUTZue4l6104Ohzlp0esxSpgVOZb541aSmXRtzzUwBinBIHRfHEuBl/CmH1+TUv6HEOKXwG4p5YdCiC+AKUDnauNlUsrvne+YvdEWNLsd+/bttG7ejD03D3dtLQiBecoUrJkZWDOzME+cgND135SElJL9tft5+9jbfF7yOU7NydSYqayKnMj1Bz7FXJ1Pk3U0z7StYH3bNJalx/Hv148nKSos0KFfFpcrdL/lDS/2RlCw0BdFwKqb2/l4cx7VR19Fmg+w06KjzHeJPCEihayUxWQmZjJx2MQBddl4qQSL0HuD3u7cSClxHD7jxmr+AZASfUw01owMrFlZWGbPQW/tv1eHzR3NfFDwATnHcyhpKSHcFM5NkZNYVbSH1NpCqq2TeLL5ZvLck7h2/HBWz0xi/riYfjk5qU9SLn2VNwwEPYr9/vsJu2oWhqFD/ZKjdHk0Nh6o5EDeeuKa3qfDWswWSwj7QsxoAoaHxpCVOJ/MxEyuir2KEP3gGgqphO4/3PX12LZswbY5F/vWrWg2GxiNWGZe6UvNZGIaNarP4vEnUkp2n9pNzrEcNpZtxK25mWFJIPtkGQvqKjgZfgWvtGWw3j6NIeHh3DIjgdUzE0mO6j9fZpcr9KDOG/YlZ4u9E31kJProKAxR0RiihqGPisYQFYU+aph3W3QU+mFRGKKj0JkvXGDoxKlW3t+6D5H/FvPFV1RYm9lksbAtLIx2NEINocyJm0NmQiYZCRlEhfb/vOiFUELvHaTLRdvef3X13p2FhQCYkpO9N1azMgmbMQNh6n8lo+vb6/mg8APWH19PeWs5Q/VmltnbubaxhkkeI7tCMvhdwyx2a2OYMzqa1TMTuX7SSMzG4J7t7Y9hi/0ib9hXSE3Dvm07zrJSPPUNuOvr8NTX4+78ua4ezW7v8b06iwV9VBSGqKjToo+K8n4h+KTf+Xq7KZSP9lexa+vnzGr8hOsN2zkcCl9FjiDPEsYpjx2BYGrMVDITM5mfOJ/UIakDMjWjhN43OCsqvKNmcnNp27kT6XSis1iwzJnjndSUkYEhpn+t3KVJjR3VO8g5lsPmis24NTfh6LmmzU6mzcYUGc1nrmt4vfVq7KGxLJ8ez62zEhk/MjiHFquJRQFAczh8kvc+PPX1uOvqcTfU46nzbWvwbvM0NXkrzZ2FMJm8ch82DLslgiKnDkf7KcaYy0kJPUlluJ7do1LJjTKzW1YjdYLE8EQyE7xynz5iOkZd/x+yBkrogUBra8O+Y0eX4N2nTgFgnjy5a8y7edKkfnVj1e6ys71qO7kVueSV59LQ0YhOwrQOBxltDpK0FD5rnMvH7pmMSxzBbTMTWTY1DmsQVXhUQg9ypNuNp7HxW/LvFH7XNt8Dt/vbBxESl8VIc7iRkyEdNIZJ2iNMDItNIS5uHDHRycQOT8USGY3OYkFntXqvFiyWfnE5rYQeWKSUdBw71jXmvX3/fu+N1ehorPPmETZzJiGpKZhSUtAP6R91VTrnieRW5JJXspEjLUUAxLvcXONwYXWMIa8hi6OGdG5Mj2f1rESmJ0YG/ApYCX0AIaVEa2nBWVvHnn2FbP/mKGElu5jhPEaSswaPQ+DUImhzmZCtDowdngsf1GRC7xO8V/Rh6C3WLunrrFZ0Vq/8u7ZZvNt0Fov3vb7t/ly0+0yU0IMLd2Mjdt+NVdvWrWgtLV2v6aOiCEnxyt2UmoopZRQhqakY4+N77e/DH5yyn2JLRR65J95nR/1BHGiEahozOgSidTT/al5IRFQ6q2cmsnx6fMCWolRCH+CUN7Tx911lfLkrn/kdX3GHKY8kWYk0huEZ8z0qY6ZTpumobD7FyZoiGuoraWk8icnhweyEMCfEaBaipYWhnhCsbgOhHWBsd6G1taHZbEiH46JiEaGhXT3/s78QuuTf9YXg+/I44wvBlNrzPQAl9OBFut24KiroKCrGWVxER3ExzqJinEVF3nSiD2E0YhqVjCklFVNqilf6qaneXr01uBZfd7gdfFO+hdxDb5BXt59q4e0YpTj1iJYUiu3XkZE2m9tmJTM7NapPF7VWQh8kdLg9fHbwJP+zrQRZvpPbjbksM+wkRGv37hAeC7HTIHYq7tgplIVHU+hqoaCpkIKmAgqaCihtKcUjvX+8BmEgKSKJtMg0xkSkkmZKINUwghFEINo60Ow2NJsNzW7H4/tXs9lPb7PbvM/tvm02Gx67HVyunk9Ap2P8oYNK6AMId2MjzuJinMXFdBQVeUVfXIyzvBw8p68eDTEx3XrzppQUTCmpGONiA56jl1JyoiyPvH1ryavbx369RBMCq1uP3paKR85j9ZQF3DZzDCP6YJk8JfRByOGqFt7YWcrn/ypktKuAKbpiZpnLSdeXMNJZhsD3/24ZDrFTIc4reufwSZQIVzfJFzQVUNFagfS9x6QzkTIkhbShaaRFnn7EWeNOLyd2HjSns5vkO78QpMNBxOLFPb5HCX1gIZ1OnOXlPtH7JF/k7d2fmb4RISGYRo063aPv7N2PGhWYCpNS0liwka37XiWvLp+vQ4y06nXoNIGuLYl461zuTF/CLenpvTZpSQl9EGPvcLO/vIn8ymYOVDSTX9lEfUMjE0QpU3TFXB1aQbq+mJEdpejQvG8Ki/JKPnZqV4++PXwERS3FFDQWdBP9SfvJrs8KNYQyesjob4l+eNjwy76RpIQ+OJBS4mlo6JK7s6iYjuIinMUluCoqQNO69jWMHOnt0aekduvdG0aO7Jsbl047rsMfsG//X9jcfJy80FBKTN5RZXrXcMZHzuau9CVcn3YVBp3/RskooSu60Wh3+gTfRH5FMwcqm2lsbmaCKGOKroQ5YeVM0ZcS21GMTvpG1JgjT0s+bppX9ENTaHXbKfT15gubCjnRdIKCxgLqHfVdnxduCu8m+LTINNKGpp1eQ/IiUEJXaE4nrtLSrlz9mb17zWbr2k+EhWEalewVfUqKd/RNaiqm5GR0ob20AEZTOeS/RUn+OrY469gcZmG32YQmQC/DmDT0KrInLiIraZ53FabLQAldcUFqWh0crGxmf7lX8PkVTbTabIwVFUzVFzMnrJJ0fTGxjiL00pcDD4mAkeld6Rpip0HUaNDpaXQ0dvXiC5sKOdF4goKmAlqcpy+nh5mHdRN8WmQa6dHp6HXfHgmhhK44F1JK3LW13vx8SfdcvauqqtscD0NsLMb4OIxxZz7iff/GXtRM7gsEA+U7Yd86Wg69y069h8/ChpIXasZhcAOCCUPTWZx6LZkJmd9pIqASuuKSkVJyssXh7cFXNLO/ookDlc3Y29p9ki/hGmsFU3QlxDoKMWi+WmxGC8Smd0vXED0W9AaklNS113Gi6URXr74zhdPmbsOgM7Drjl09ToZSQld8FzSHA2dpqTeFU1SEs7QUV1UVrqoq3CdPdUvhAOijo7vLPv4M6cfHXdpoHGcbHP0YuW8dWtFmDoUYedOcQG5YKK3mVgDiLPFkJWaSmZDJlSOvxKS/8FBIJXSFX5BSUtHYTr4vF3/AJ/v2DgdpoorpxhLmWSqZrCshzlGAweMbXWMIhZGTvYLv7M3HjAe9seu41fZqKm2VzBw5s8fPVkJX+BvpduM+dQpXVRXOysrToq+qwlVZhau6Gul0dnuPLiICY3z8WT183yMhHn3kOSYeNVdA/j/w7F2HvrGQEn0or5jHsdUSRoulBg1ntxpN8xLmER0a3WPcSuiKXkPTJCX1dl+axiv4g1XNOJwuUkUVVxpLmRdexRRRTJzjOAZ3m/eN+hAYMal7umb4RDD03ENRQlf0NVLTcNfVeQV/5qOyCldVJa7KKrS2tm7vEaGh3xZ95xdAfByG6GhE1R7kv9bhOfgOBmcrxUTzB9MU9g4bgiO8jFZ3HQAvzX+J65Ku+1Zc52sLwVOgQNEv0ekEqTFWUmOs3DQtHgCPJimstfkE38TaymYOV7XgdLtJESeZGVJGRmgVk23FxO3Pwbj7Ne/BDGb4WQkYB/7K7YrgR+h0GIcPxzh8OKHTpn3rdSklWnPzWbKv7JK+48CBbhOrADAaMY4c6ZX8yDswmloZYj/C023bMTW42GdO4W8hc6lOjiKCtEuOWQld4Xf0OsHYEeGMHeGtNw3eeu8nTtnIr/AOofxzRTNHT7bg9nhIFLXMNpdzhbWFmzDR+1MzFIrLRwjhLZ0dGYl54sQe99HsdlzV1adF39XDr8K+bQfums6lI7wjvsJFGw+bv0Jv0dBkNPyvn15STEroij7BqNcxMS6CiXER3Orb1uH2cOxkK/t9PfkPm9pZHfy1qBcDL+MtJb1WSrnmrNcz8JaaTgdulVKu7/soFcGCzmIhJC2NkLSee9ua04m7urp7D7/gAM6CQ8ROmHHJn6eErggYIQY96QmRpCdEAsmBDueCCCH0wB+AhUAF8I0Q4kMp5eEzdisDvg881vcRKvobOpMJU3IypmT//P0roSsUF88soEBKWQQghHgLuAnoErqUssT3mtbTARSK3qT/VKZXKAJPPFB+xvMK3zaFIigIWA99z549dUKI0h5eigbq+jqe70h/iXUgxBkMOZmepvR9p3G/Qoh7gXt9T21CiGPn2HUg/N8FE/0lTjh3rOdsCwETupSyx4UJhRC7+8t44/4Sq4rTb1QAiWc8TwCqvsuBpJSvAq9eaL9+8DsBVJy9wXeJVaVcFIqL5xtgjBAiRQhhAm4FPgxwTApFF0roCsVFIqV0Aw8CnwNHgLellIeEEL8UQnwPQAgxUwhRAawCXhFCHApcxIrBRjCOcrngZWgQ0V9iVXH6CSnlJ8AnZ237+Rk/f4M3FeMvgv534kPF6X8uOdaA1XJRKBQKhX9RKReFQqEYICihKxQKxQAhqIQuhFgshDgmhCgQQjwR6HjOhRDiNSFEjRDiYKBjOR9CiEQhxCYhxBEhxCEhxMOBjqknhBBmIcQuIcR+X5y/CHRMgUa1Bf8yWNpC0OTQfXUyjnNGnQzgtrPqZAQFvgJMNuBvUsrJgY7nXAghYoFYKeVeIUQ4sAe4Odh+p8K7IoBFSmkTQhiBrcDDUsodAQ4tIKi24H8GS1sIph56V50MKaUT6KyTEXRIKfOAhkDHcSGklNVSyr2+n1vxDrULuqnq0kvnKr9G3yM4ehqBQbUFPzNY2kIwCV3VyehFhBCjgOnAzsBG0jNCCL0QYh9QA2yUUgZlnH2Eagu9yEBuC8EkdL/VyVB0RwhhBd4B/k1K2RLoeHpCSumRUk7DO4Z7lhAiaC/f+wDVFnqJgd4WgknofquToTiNLw/3DrBOSvluoOO5EFLKJmAzsDjAoQQS1RZ6gcHQFoJJ6KpOhp/x3WD5f8ARKeVvAh3PuRBCxAghIn0/hwILgKOBjSqgqLbgZwZLWwgaoZ+rTkZgo+oZIcSbwHZgnBCiQgjxw0DHdA7mAncB1woh9vkeSwMdVA/EApuEEPl4ZbZRSrkhwDEFDNUWeoVB0RaCZtiiQqFQKC6PoOmhKxQKheLyUEJXKBSKAYISukKhUAwQlNAVCoVigKCErlAoFAMEJXSFQqEYICihKxQKxQDh/wMBFWpHqFsXXQAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "for lottSize in range(4):\n", + " plt.subplot(2,2,lottSize+1)\n", + " for q in range(4):\n", + " labStr = \"Wealth Q=\" + str(q)\n", + " plt.plot(simulated_MPC_means[lottSize,q,:], label=labStr)\n", + " plt.xticks(ticks=range(4))\n", + " plt.title('Lottery size = %d' %lottSize)\n", + "plt.subplots_adjust(hspace=0.6, wspace=0.4)\n", + "# plt.legend(loc='best')\n", + "plt.show()" + ] + } + ], + "metadata": { + "cite2c": { + "citations": { + "6202365/SUE56C4B": { + "author": [ + { + "family": "Fagereng", + "given": "Andreas" + }, + { + "family": "Holm", + "given": "Martin B." + }, + { + "family": "Natvik", + "given": "Gisle J." + } + ], + "genre": "discussion paper", + "id": "6202365/SUE56C4B", + "issued": { + "year": 2017 + }, + "publisher": "Statistics Norway", + "title": "MPC Heterogeneity and Household Balance Sheets", + "type": "report" + } + } + }, + "jupytext": { + "cell_metadata_filter": "collapsed,code_folding", + "formats": "ipynb,py:percent" + }, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.4" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": false + }, + "varInspector": { + "cols": { + "lenName": 16, + "lenType": 16, + "lenVar": 40 + }, + "kernels_config": { + "python": { + "delete_cmd_postfix": "", + "delete_cmd_prefix": "del ", + "library": "var_list.py", + "varRefreshCmd": "print(var_dic_list())" + }, + "r": { + "delete_cmd_postfix": ") ", + "delete_cmd_prefix": "rm(", + "library": "var_list.r", + "varRefreshCmd": "cat(var_dic_list()) " + } + }, + "types_to_exclude": [ + "module", + "function", + "builtin_function_or_method", + "instance", + "_Feature" + ], + "window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/notebooks/Structural-Estimates-From-Empirical-MPCs-Fagereng-et-al-Problems-And-Solutions-HakonsVersion.py b/notebooks/Structural-Estimates-From-Empirical-MPCs-Fagereng-et-al-Problems-And-Solutions-HakonsVersion.py new file mode 100644 index 0000000..d7a9d8c --- /dev/null +++ b/notebooks/Structural-Estimates-From-Empirical-MPCs-Fagereng-et-al-Problems-And-Solutions-HakonsVersion.py @@ -0,0 +1,365 @@ +# --- +# jupyter: +# jupytext: +# cell_metadata_filter: collapsed,code_folding +# formats: ipynb,py:percent +# text_representation: +# extension: .py +# format_name: percent +# format_version: '1.3' +# jupytext_version: 1.4.0 +# kernelspec: +# display_name: Python 3 +# language: python +# name: python3 +# --- + +# %% [markdown] +# # Making Structural Estimates From Empirical Results +# +# This notebook conducts a quick and dirty structural estimation based on Table 9 of "MPC Heterogeneity and Household Balance Sheets" by Fagereng, Holm, and Natvik , who use Norweigian administrative data on income, household assets, and lottery winnings to examine the MPC from transitory income shocks (lottery prizes). Their Table 9 reports an estimated MPC broken down by quartiles of bank deposits and +# prize size; this table is reproduced here as $\texttt{MPC_target_base}$. In this demo, we use the Table 9 estimates as targets in a simple structural estimation, seeking to minimize the sum of squared differences between simulated and estimated MPCs by changing the (uniform) distribution of discount factors. The essential question is how well their results be rationalized by a simple one-asset consumption-saving model. +# +# +# The function that estimates discount factors includes several options for estimating different specifications: +# +# 1. TypeCount : Integer number of discount factors in discrete distribution; can be set to 1 to turn off _ex ante_ heterogeneity (and to discover that the model has no chance to fit the data well without such heterogeneity). +# 2. AdjFactor : Scaling factor for the target MPCs; user can try to fit estimated MPCs scaled down by (e.g.) 50%. +# 3. T_kill : Maximum number of years the (perpetually young) agents are allowed to live. Because this is quick and dirty, it's also the number of periods to simulate. +# 4. Splurge : Amount of lottery prize that an individual will automatically spend in a moment of excitement (perhaps ancient tradition in Norway requires a big party when you win the lottery), before beginning to behave according to the optimal consumption function. The patterns in Table 9 can be fit much better when this is set around \$700 --> 0.7. That doesn't seem like an unreasonable amount of money to spend on a memorable party. +# 5. do_secant : Boolean indicator for whether to use "secant MPC", which is average MPC over the range of the prize. MNW believes authors' regressions are estimating this rather than point MPC. When False, structural estimation uses point MPC after receiving prize. NB: This is incompatible with Splurge > 0. +# 6. drop_corner : Boolean for whether to include target MPC in the top left corner, which is greater than 1. Authors discuss reasons why the MPC from a transitory shock *could* exceed 1. Option is included here because this target tends to push the estimate around a bit. + +# %% code_folding=[] +# Import python tools + +import sys +import os + +import numpy as np +from copy import deepcopy + +# %% code_folding=[] +# Import needed tools from HARK + +from HARK.utilities import approxUniform, getPercentiles +from HARK.parallel import multiThreadCommands +from HARK.estimation import minimizeNelderMead +from HARK.ConsumptionSaving.ConsIndShockModel import * +from HARK.cstwMPC.SetupParamsCSTW import init_infinite + +# %% code_folding=[] +# Set key problem-specific parameters + +TypeCount = 8 # Number of consumer types with heterogeneous discount factors +AdjFactor = 1.0 # Factor by which to scale all of MPCs in Table 9 +T_kill = 100 # Don't let agents live past this age +Splurge = 0.7 # Consumers automatically spend this amount of any lottery prize +do_secant = True # If True, calculate MPC by secant, else point MPC +drop_corner = True # If True, ignore upper left corner when calculating distance + +# %% code_folding=[] +# Set standard HARK parameter values + +base_params = deepcopy(init_infinite) +base_params['LivPrb'] = [0.975] +base_params['Rfree'] = 1.04/base_params['LivPrb'][0] +base_params['PermShkStd'] = [0.1] +base_params['TranShkStd'] = [0.1] +base_params['T_age'] = T_kill # Kill off agents if they manage to achieve T_kill working years +base_params['AgentCount'] = 10000 +base_params['pLvlInitMean'] = np.log(23.72) # From Table 1, in thousands of USD +base_params['T_sim'] = T_kill # No point simulating past when agents would be killed off + +# %% code_folding=[] +# Define the MPC targets from Fagereng et al Table 9; element i,j is lottery quartile i, deposit quartile j + +MPC_target_base = np.array([[1.047, 0.745, 0.720, 0.490], + [0.762, 0.640, 0.559, 0.437], + [0.663, 0.546, 0.390, 0.386], + [0.354, 0.325, 0.242, 0.216]]) +MPC_target = AdjFactor*MPC_target_base + +# %% code_folding=[] +# Define the four lottery sizes, in thousands of USD; these are eyeballed centers/averages + +lottery_size = np.array([1.625, 3.3741, 7.129, 40.0]) + +# %% code_folding=[] +# Make several consumer types to be used during estimation + +BaseType = IndShockConsumerType(**base_params) +EstTypeList = [] +for j in range(TypeCount): + EstTypeList.append(deepcopy(BaseType)) + EstTypeList[-1](seed = j) + +# %% code_folding=[] +# Define the objective function + +def FagerengObjFunc(center,spread,verbose=False): + ''' + Objective function for the quick and dirty structural estimation to fit + Fagereng, Holm, and Natvik's Table 9 results with a basic infinite horizon + consumption-saving model (with permanent and transitory income shocks). + + Parameters + ---------- + center : float + Center of the uniform distribution of discount factors. + spread : float + Width of the uniform distribution of discount factors. + verbose : bool + When True, print to screen MPC table for these parameters. When False, + print (center, spread, distance). + + Returns + ------- + distance : float + Euclidean distance between simulated MPCs and (adjusted) Table 9 MPCs. + ''' + # Give our consumer types the requested discount factor distribution + beta_set = approxUniform(N=TypeCount,bot=center-spread,top=center+spread)[1] + for j in range(TypeCount): + EstTypeList[j](DiscFac = beta_set[j]) + + # Solve and simulate all consumer types, then gather their wealth levels + multiThreadCommands(EstTypeList,['solve()','initializeSim()','simulate()','unpackcFunc()']) + WealthNow = np.concatenate([ThisType.aLvlNow for ThisType in EstTypeList]) + + # Get wealth quartile cutoffs and distribute them to each consumer type + quartile_cuts = getPercentiles(WealthNow,percentiles=[0.25,0.50,0.75]) + for ThisType in EstTypeList: + WealthQ = np.zeros(ThisType.AgentCount,dtype=int) + for n in range(3): + WealthQ[ThisType.aLvlNow > quartile_cuts[n]] += 1 + ThisType(WealthQ = WealthQ) + + # Keep track of MPC sets in lists of lists of arrays + MPC_set_list = [ [[],[],[],[]], + [[],[],[],[]], + [[],[],[],[]], + [[],[],[],[]] ] + + # Calculate the MPC for each of the four lottery sizes for all agents + for ThisType in EstTypeList: + ThisType.simulate(1) + c_base = ThisType.cNrmNow + MPC_this_type = np.zeros((ThisType.AgentCount,4)) + for k in range(4): # Get MPC for all agents of this type + Llvl = lottery_size[k] + Lnrm = Llvl/ThisType.pLvlNow + if do_secant: + SplurgeNrm = Splurge/ThisType.pLvlNow + mAdj = ThisType.mNrmNow + Lnrm - SplurgeNrm + cAdj = ThisType.cFunc[0](mAdj) + SplurgeNrm + MPC_this_type[:,k] = (cAdj - c_base)/Lnrm + else: + mAdj = ThisType.mNrmNow + Lnrm + MPC_this_type[:,k] = cAdj = ThisType.cFunc[0].derivative(mAdj) + + # Sort the MPCs into the proper MPC sets + for q in range(4): + these = ThisType.WealthQ == q + for k in range(4): + MPC_set_list[k][q].append(MPC_this_type[these,k]) + + # Calculate average within each MPC set + simulated_MPC_means = np.zeros((4,4)) + for k in range(4): + for q in range(4): + MPC_array = np.concatenate(MPC_set_list[k][q]) + simulated_MPC_means[k,q] = np.mean(MPC_array) + + # Calculate Euclidean distance between simulated MPC averages and Table 9 targets + diff = simulated_MPC_means - MPC_target + if drop_corner: + diff[0,0] = 0.0 + distance = np.sqrt(np.sum((diff)**2)) + if verbose: + print(simulated_MPC_means) + else: + print (center, spread, distance) + return distance + + +# %% code_folding=[] +# Conduct the estimation + +guess = [0.86,0.09] +f_temp = lambda x : FagerengObjFunc(x[0],x[1]) +opt_params = minimizeNelderMead(f_temp, guess, verbose=True) +print('Finished estimating for scaling factor of ' + str(AdjFactor) + ' and "splurge amount" of $' + str(1000*Splurge)) +print('Optimal (beta,nabla) is ' + str(opt_params) + ', simulated MPCs are:') +dist = FagerengObjFunc(opt_params[0],opt_params[1],True) +print('Distance from Fagereng et al Table 9 is ' + str(dist)) + +# %% [markdown] +# ### PROBLEM +# +# See what happens if you do not allow a splurge amount at all. Hint: Think about how this question relates to the `drop_corner` option. +# +# Explain why you get the results you do, and comment on possible interpretations of the "splurge" that might be consistent with economic theory. +# Hint: What the authors are able to measure is actually the marginal propensity to EXPEND, not the marginal propensity to CONSUME as it is defined in our benchmark model. + +# %% [markdown] +# ## Put your solution here +# +# 1. No splurge drop_corner=False: Gives optimal $\beta=0.7898$ and $\nabla=0.1610$. Simulated MPCs are: +# +# +# +# +# +#
0.77360.68320.56460.4048
0.74350.66480.55300.3963
0.70350.63510.53050.3793
0.56130.50430.41260.2926
+# Distance from Fagereng et al Table 9 is 0.5021. +# +# 2. No splurge, drop_corner=True: Gives optimal $\beta=0.8144$ and $\nabla=0.1254$. Simulated MPCs are: +# +# +# +# +# +#
0.67840.62360.54110.4202
0.65900.60970.53040.4116
0.62750.58430.50880.3944
0.49120.45830.39350.3058
+# Distance from Fagereng et al Table 9 is 0.3862. +# +# 3. Splurge=0.7, drop_corner=False: Gives optimal $\beta=0.8572$ and $\nabla=0.1163$. Simulated MPCs are: +# +# +# +# +# +#
0.78130.74900.69770.5700
0.68170.64090.57100.3973
0.61000.57030.49330.3049
0.43830.41060.34400.1940
+# Distance from Fagereng et al Table 9 is 0.3629. +# +# 4. Splurge=0.7, drop_corner=True: Gives optimal $\beta=0.8683$ and $\nabla=0.0983$. Simulated MPCs are: +# +# +# +# +# +#
0.76150.73300.68880.5805
0.65410.61890.55870.4108
0.57850.54550.47950.3197
0.40380.38420.33120.2061
+# Distance from Fagereng et al Table 9 is 0.2359. +# +# ## Discussion +# +# The first thing to note about these results is the large drop in the distance from Table 9 in Fagereng et al when setting drop_corner=True (compare results 1 vs 2 and results 3 vs 4). In the table the MPC for the lowest lottery size and lowest wealth quartile is 1.047. Even with splurge=0.7 the model cannot generate an MPC close to (and certainly not above) 1. The deviation between the model MPC and the value in the data will therefore be considerable, contributing to a larger distance. Given that the model cannot generate an MPC > 1, it makes sense to drop that value, but the improvement in the distance is to some extent mechanical. Ignoring that value yields higher estimates of $\beta$ however, since lowering $\beta$ is the model's best attempt at increasing the MPC. +# +# Focusing rather on the splurge component, we compare results 2 (without a splurge) vs 4 (with a splurge included). Setting splurge=0.7 gives an automatic increase in spending after the lottery which is not generated by the model. In the real world such an increase in spending makes sense if, for example, the lottery win enables a purchase of a durable good that a consumer was saving for. Such a mechanism is not included in the model. +# +# With the splurge fixed and independent of wealth and lottery sizes, the inclusion of the splurge increases MPCs for the smallest lottery wins and reduces it for the larger wins. This enables the model to generate a larger difference in MPCs for different lottery sizes, and improves the fit with the data. The improved fit is achieved with $\beta$ centered around $0.87$ rather than $0.81$ since the splurge enables the model to imply high MPCs for the smallest lottery wins without needing to reduce $\beta$. The higher $\beta$ then enables lower MPCs for the larger lottery wins. +# + +# %% [markdown] +# ### PROBLEM +# +# Call the _Marginal Propensity to Continue Consuming_ (MPCC) in year `t+n` the proportion of lottery winnings that get spent in year `t+n`. That is, if consumption is higher in year `t+2` by an amount corresponding to 14 percent of lottery winnings, we would say _the MPCC in t+2 is 14 percent. +# +# For the baseline version of the model with the "splurge" component, calculate the MPCC's for years `t+1` through `t+3` and plot them together with the MPC in the first year (including the splurge component) +# + +# %% +# Put your solution here + +# Use estimated beta range from case 4 above (splurge + drop_corner=True) +center = opt_params[0] +spread = opt_params[1] + +# Give our consumer types the estimated discount factor distribution +beta_set = approxUniform(N=TypeCount,bot=center-spread,top=center+spread)[1] +for j in range(TypeCount): + EstTypeList[j](DiscFac = beta_set[j]) + #EstTypeList[j].track_vars = ['mNrmNow', 'cNrmNow', 'pLvlNow'] + +# Solve and simulate all consumer types, then gather their wealth levels +multiThreadCommands(EstTypeList,['solve()','initializeSim()','simulate()','unpackcFunc()']) +WealthNow = np.concatenate([ThisType.aLvlNow for ThisType in EstTypeList]) + +# Get wealth quartile cutoffs and distribute them to each consumer type +quartile_cuts = getPercentiles(WealthNow,percentiles=[0.25,0.50,0.75]) +for ThisType in EstTypeList: + WealthQ = np.zeros(ThisType.AgentCount,dtype=int) + for n in range(3): + WealthQ[ThisType.aLvlNow > quartile_cuts[n]] += 1 + ThisType(WealthQ = WealthQ) + +print('Done assigning wealth quartiles') + +# %% +# Now for each type we want to simulate 4 periods and calculate MPCCs +# from consumptions with and without lottery winnings +numPeriods = 4 + +simulated_MPC_means = np.zeros((4,4,numPeriods)) # 3d array to store MPC matrices for t to t+n + +# Need a structure to keep track of how wealth evolves after the lottery win +lotteryWealthMat = np.zeros((base_params['AgentCount'],4,numPeriods)) +lotteryWealthList = [] +for j in range(TypeCount): + lotteryWealthList.append(deepcopy(lotteryWealthMat)) + +for n in range(numPeriods): + # Keep track of MPC sets in lists of lists of arrays + MPC_set_list = [ [[],[],[],[]], + [[],[],[],[]], + [[],[],[],[]], + [[],[],[],[]] ] + + for ThisType in EstTypeList: + ThisType.simulate(1) + c_base = ThisType.cNrmNow + MPC_this_type = np.zeros((ThisType.AgentCount,4)) + for k in range(4): + if n == 0: # Calculate the initial period MPCs + Llvl = lottery_size[k] + Lnrm = Llvl/ThisType.pLvlNow + SplurgeNrm = Splurge/ThisType.pLvlNow + mAdj = ThisType.mNrmNow + Lnrm - SplurgeNrm + cAdj = ThisType.cFunc[0](mAdj) + SplurgeNrm + MPC_this_type[:,k] = (cAdj - c_base)/Lnrm + # Store the resulting wealth after the lottery win + lotteryWealthList[ThisType.seed][:,k,n] = ThisType.mNrmNow + Lnrm - cAdj + else: # Calculate MPCC after initial lottery win + # by iterating last period's lottery wealth one period forward + Llvl = lottery_size[k] + Lnrm = Llvl/ThisType.pLvlNow + mAdjPrev = lotteryWealthList[ThisType.seed][:,k,n-1] + mAdjNew = mAdjPrev*base_params['Rfree']/ThisType.PermShkNow + ThisType.TranShkNow + cAdj = ThisType.cFunc[0](mAdjNew) + MPC_this_type[:,k] = (cAdj - c_base)/Lnrm + lotteryWealthList[ThisType.seed][:,k,n] = mAdjNew-cAdj + + # Sort the MPCs into the proper MPC sets + for q in range(4): + these = ThisType.WealthQ == q + for k in range(4): + MPC_set_list[k][q].append(MPC_this_type[these,k]) + + # Calculate average within each MPC set + for k in range(4): + for q in range(4): + MPC_array = np.concatenate(MPC_set_list[k][q]) + simulated_MPC_means[k,q, n] = np.mean(MPC_array) + + +print('The MPC for t+0 is \n', simulated_MPC_means[:,:,0]) +print('\n') +print('The MPCC for t+1 is \n', simulated_MPC_means[:,:,1]) +print('\n') +print('The MPCC for t+2 is \n', simulated_MPC_means[:,:,2]) +print('\n') +print('The MPCC for t+3 is \n', simulated_MPC_means[:,:,3]) + +# %% +import matplotlib.pyplot as plt + +for lottSize in range(4): + plt.subplot(2,2,lottSize+1) + for q in range(4): + labStr = "Wealth Q=" + str(q) + plt.plot(simulated_MPC_means[lottSize,q,:], label=labStr) + plt.xticks(ticks=range(4)) + plt.title('Lottery size = %d' %lottSize) +plt.subplots_adjust(hspace=0.6, wspace=0.4) +# plt.legend(loc='best') +plt.show() diff --git a/notebooks/Structural-Estimates-From-Empirical-MPCs-Fagereng-et-al-Problems-And-Solutions.ipynb b/notebooks/Structural-Estimates-From-Empirical-MPCs-Fagereng-et-al-Problems-And-Solutions.ipynb new file mode 100644 index 0000000..d1d11dd --- /dev/null +++ b/notebooks/Structural-Estimates-From-Empirical-MPCs-Fagereng-et-al-Problems-And-Solutions.ipynb @@ -0,0 +1,681 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Making Structural Estimates From Empirical Results\n", + "\n", + "This notebook conducts a quick and dirty structural estimation based on Table 9 of \"MPC Heterogeneity and Household Balance Sheets\" by Fagereng, Holm, and Natvik , who use Norweigian administrative data on income, household assets, and lottery winnings to examine the MPC from transitory income shocks (lottery prizes). Their Table 9 reports an estimated MPC broken down by quartiles of bank deposits and\n", + "prize size; this table is reproduced here as $\\texttt{MPC_target_base}$. In this demo, we use the Table 9 estimates as targets in a simple structural estimation, seeking to minimize the sum of squared differences between simulated and estimated MPCs by changing the (uniform) distribution of discount factors. The essential question is how well their results be rationalized by a simple one-asset consumption-saving model. \n", + "\n", + "\n", + "The function that estimates discount factors includes several options for estimating different specifications:\n", + "\n", + "1. TypeCount : Integer number of discount factors in discrete distribution; can be set to 1 to turn off _ex ante_ heterogeneity (and to discover that the model has no chance to fit the data well without such heterogeneity).\n", + "2. AdjFactor : Scaling factor for the target MPCs; user can try to fit estimated MPCs scaled down by (e.g.) 50%.\n", + "3. T_kill : Maximum number of years the (perpetually young) agents are allowed to live. Because this is quick and dirty, it's also the number of periods to simulate.\n", + "4. Splurge : Amount of lottery prize that an individual will automatically spend in a moment of excitement (perhaps ancient tradition in Norway requires a big party when you win the lottery), before beginning to behave according to the optimal consumption function. The patterns in Table 9 can be fit much better when this is set around \\$700 --> 0.7. That doesn't seem like an unreasonable amount of money to spend on a memorable party.\n", + "5. do_secant : Boolean indicator for whether to use \"secant MPC\", which is average MPC over the range of the prize. MNW believes authors' regressions are estimating this rather than point MPC. When False, structural estimation uses point MPC after receiving prize. NB: This is incompatible with Splurge > 0.\n", + "6. drop_corner : Boolean for whether to include target MPC in the top left corner, which is greater than 1. Authors discuss reasons why the MPC from a transitory shock *could* exceed 1. Option is included here because this target tends to push the estimate around a bit." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "code_folding": [] + }, + "outputs": [], + "source": [ + "# Import python tools\n", + "\n", + "import sys\n", + "import os\n", + "\n", + "import numpy as np\n", + "from copy import deepcopy" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "code_folding": [] + }, + "outputs": [], + "source": [ + "# Import needed tools from HARK\n", + "\n", + "from HARK.utilities import approxUniform, getPercentiles\n", + "from HARK.parallel import multiThreadCommands\n", + "from HARK.estimation import minimizeNelderMead\n", + "from HARK.ConsumptionSaving.ConsIndShockModel import *\n", + "from HARK.cstwMPC.SetupParamsCSTW import init_infinite" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "code_folding": [] + }, + "outputs": [], + "source": [ + "# Set key problem-specific parameters\n", + "\n", + "TypeCount = 8 # Number of consumer types with heterogeneous discount factors\n", + "AdjFactor = 1.0 # Factor by which to scale all of MPCs in Table 9\n", + "T_kill = 100 # Don't let agents live past this age\n", + "Splurge = 0.7 # Consumers automatically spend this amount of any lottery prize\n", + "do_secant = True # If True, calculate MPC by secant, else point MPC\n", + "drop_corner = True # If True, ignore upper left corner when calculating distance" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "code_folding": [] + }, + "outputs": [], + "source": [ + "# Set standard HARK parameter values\n", + "\n", + "base_params = deepcopy(init_infinite)\n", + "base_params['LivPrb'] = [0.975]\n", + "base_params['Rfree'] = 1.04/base_params['LivPrb'][0]\n", + "base_params['PermShkStd'] = [0.1]\n", + "base_params['TranShkStd'] = [0.1]\n", + "base_params['T_age'] = T_kill # Kill off agents if they manage to achieve T_kill working years\n", + "base_params['AgentCount'] = 10000\n", + "base_params['pLvlInitMean'] = np.log(23.72) # From Table 1, in thousands of USD\n", + "base_params['T_sim'] = T_kill # No point simulating past when agents would be killed off" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "code_folding": [] + }, + "outputs": [], + "source": [ + "# Define the MPC targets from Fagereng et al Table 9; element i,j is lottery quartile i, deposit quartile j\n", + "\n", + "MPC_target_base = np.array([[1.047, 0.745, 0.720, 0.490],\n", + " [0.762, 0.640, 0.559, 0.437],\n", + " [0.663, 0.546, 0.390, 0.386],\n", + " [0.354, 0.325, 0.242, 0.216]])\n", + "MPC_target = AdjFactor*MPC_target_base" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "code_folding": [] + }, + "outputs": [], + "source": [ + "# Define the four lottery sizes, in thousands of USD; these are eyeballed centers/averages\n", + "\n", + "lottery_size = np.array([1.625, 3.3741, 7.129, 40.0])" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "code_folding": [], + "lines_to_next_cell": 1 + }, + "outputs": [], + "source": [ + "# Make several consumer types to be used during estimation\n", + "\n", + "BaseType = IndShockConsumerType(**base_params)\n", + "EstTypeList = []\n", + "for j in range(TypeCount):\n", + " EstTypeList.append(deepcopy(BaseType))\n", + " EstTypeList[-1](seed = j)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "code_folding": [] + }, + "outputs": [], + "source": [ + "# Define the objective function\n", + "\n", + "def FagerengObjFunc(center,spread,verbose=False):\n", + " '''\n", + " Objective function for the quick and dirty structural estimation to fit\n", + " Fagereng, Holm, and Natvik's Table 9 results with a basic infinite horizon\n", + " consumption-saving model (with permanent and transitory income shocks).\n", + "\n", + " Parameters\n", + " ----------\n", + " center : float\n", + " Center of the uniform distribution of discount factors.\n", + " spread : float\n", + " Width of the uniform distribution of discount factors.\n", + " verbose : bool\n", + " When True, print to screen MPC table for these parameters. When False,\n", + " print (center, spread, distance).\n", + "\n", + " Returns\n", + " -------\n", + " distance : float\n", + " Euclidean distance between simulated MPCs and (adjusted) Table 9 MPCs.\n", + " '''\n", + " # Give our consumer types the requested discount factor distribution\n", + " beta_set = approxUniform(N=TypeCount,bot=center-spread,top=center+spread)[1]\n", + " for j in range(TypeCount):\n", + " EstTypeList[j](DiscFac = beta_set[j])\n", + "\n", + " # Solve and simulate all consumer types, then gather their wealth levels\n", + " multiThreadCommands(EstTypeList,['solve()','initializeSim()','simulate(95)','unpackcFunc()'])\n", + " WealthNow = np.concatenate([ThisType.aLvlNow for ThisType in EstTypeList])\n", + "\n", + " # Get wealth quartile cutoffs and distribute them to each consumer type\n", + " quartile_cuts = getPercentiles(WealthNow,percentiles=[0.25,0.50,0.75])\n", + " for ThisType in EstTypeList:\n", + " WealthQ = np.zeros(ThisType.AgentCount,dtype=int)\n", + " for n in range(3):\n", + " WealthQ[ThisType.aLvlNow > quartile_cuts[n]] += 1\n", + " ThisType(WealthQ = WealthQ)\n", + "\n", + " # Keep track of MPC sets in lists of lists of arrays\n", + " MPC_set_list = [ [[],[],[],[]],\n", + " [[],[],[],[]],\n", + " [[],[],[],[]],\n", + " [[],[],[],[]] ]\n", + "\n", + " # Calculate the MPC for each of the four lottery sizes for all agents\n", + " for ThisType in EstTypeList:\n", + " ThisType.simulate(1)\n", + " c_base = ThisType.cNrmNow\n", + " MPC_this_type = np.zeros((ThisType.AgentCount,4))\n", + " for k in range(4): # Get MPC for all agents of this type\n", + " Llvl = lottery_size[k]\n", + " Lnrm = Llvl/ThisType.pLvlNow\n", + " if do_secant:\n", + " SplurgeNrm = Splurge/ThisType.pLvlNow\n", + " mAdj = ThisType.mNrmNow + Lnrm - SplurgeNrm\n", + " cAdj = ThisType.cFunc[0](mAdj) + SplurgeNrm\n", + " MPC_this_type[:,k] = (cAdj - c_base)/Lnrm\n", + " else:\n", + " mAdj = ThisType.mNrmNow + Lnrm\n", + " MPC_this_type[:,k] = cAdj = ThisType.cFunc[0].derivative(mAdj)\n", + "\n", + " # Sort the MPCs into the proper MPC sets\n", + " for q in range(4):\n", + " these = ThisType.WealthQ == q\n", + " for k in range(4):\n", + " MPC_set_list[k][q].append(MPC_this_type[these,k])\n", + "\n", + " # Calculate average within each MPC set\n", + " simulated_MPC_means = np.zeros((4,4))\n", + " for k in range(4):\n", + " for q in range(4):\n", + " MPC_array = np.concatenate(MPC_set_list[k][q])\n", + " simulated_MPC_means[k,q] = np.mean(MPC_array)\n", + "\n", + " # Calculate Euclidean distance between simulated MPC averages and Table 9 targets\n", + " diff = simulated_MPC_means - MPC_target\n", + " if drop_corner:\n", + " diff[0,0] = 0.0\n", + " distance = np.sqrt(np.sum((diff)**2))\n", + " if verbose:\n", + " print(simulated_MPC_means)\n", + " else:\n", + " print (center, spread, distance)\n", + " return distance" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "code_folding": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.78981881 0.16098057 0.48580048893979316\n", + "0.8293097505 0.16098057 0.3313405262934448\n", + "0.78981881 0.1690295985 0.47856230067166305\n", + "0.8293097505000001 0.1690295985 0.34477770781230793\n", + "0.868800691 0.16098057 0.3919051119568574\n", + "0.84905522075 0.162992827125 0.34766503675642896\n", + "0.80956428025 0.167017341375 0.39059276121654307\n", + "0.839182485625 0.1639989556875 0.33006777250767005\n", + "0.839182485625 0.1559499271875 0.3114573947400921\n", + "0.8441188531874999 0.14941009153125 0.29759656997602174\n", + "0.8539915883125 0.15242847721875002 0.32272265417221446\n", + "0.8589279558749999 0.13783961306250003 0.2896970383427969\n", + "0.8688006909999999 0.12475994175000005 0.28538450938568033\n", + "0.8589279558749998 0.12174155606250003 0.2552805685429768\n", + "0.8613961396562497 0.10639809548437507 0.23895645235891916\n", + "0.8860779774687497 0.0817479457031251 0.27842013631444334\n", + "0.8786734261249995 0.06338609943750012 0.29913161682865297\n", + "0.8712688747812498 0.10941648117187507 0.25837997054375333\n", + "0.8465870369687498 0.13406663095312504 0.27232460581536816\n", + "0.8564597720937499 0.12098695964062506 0.2530032694577953\n", + "0.8465870369687498 0.11796857395312506 0.2581379647895402\n", + "0.8527574964218747 0.11583055075781257 0.24802360888570885\n", + "0.8576938639843745 0.10124168660156257 0.24492008434188262\n", + "0.8663325072187495 0.09180923132812507 0.24227823900906223\n", + "0.8700347828906247 0.09696564021093756 0.24069501318279268\n", + "0.8650984153281249 0.11155450436718756 0.24798204480204597\n", + "0.8660239842460934 0.0967455495878907 0.23665788491545425\n", + "0.8573853410117183 0.1061780048613282 0.23973677455150047\n", + "0.8605477014814449 0.10387491369873053 0.23712336948335208\n", + "0.8651755460712884 0.09422236780224616 0.2399321914129636\n", + "0.8623409912600094 0.10335416356384283 0.23660541031596866\n", + "0.8678172740246579 0.096224799453003 0.23726139845247388\n", + "0.8623650946172481 0.10196238513729865 0.23644409794820342\n", + "0.8586821016311642 0.10857099911325077 0.2398009838962758\n", + "0.864188513592361 0.09970191196923071 0.23600718133937149\n", + "0.8642126169495997 0.09831013354268653 0.23647344408371473\n", + "0.8637447105272023 0.09957114104797561 0.2362159666394759\n", + "0.8655681295023152 0.09731066787990768 0.23635060272711664\n", + "0.8647673707810485 0.09847359719425541 0.23618797168172395\n", + "0.8652111738462074 0.09860436811551053 0.23613292071033748\n", + "0.8646323166575199 0.09983268289048583 0.23618206079428505\n", + "0.8646660801884021 0.09949291146642822 0.23620399454819865\n", + "0.8646998437192842 0.09915314004237062 0.23609202691925957\n", + "0.8644779421867048 0.09908775458174307 0.23611825832893543\n", + "0.8644104151249403 0.09976729742985826 0.23610281801095978\n", + "0.8644272968903816 0.09959741171782946 0.2360431660507953\n", + "0.8639159667634585 0.10014618364468954 0.2360757180701442\n", + "0.864111936002415 0.0998979227441098 0.2359780723857939\n", + "0.8638731527043945 0.10000242299551107 0.2360513272623322\n", + "0.8642887608438847 0.09969866453724986 0.23599762994353402\n", + "0.8642121832539387 0.09989467531212894 0.23606105519823586\n", + "0.8641944310077554 0.09975010280495528 0.23600045075797765\n", + "0.8642062658385443 0.09984648447640437 0.23603399455793697\n", + "0.8641973897154527 0.09977419822281755 0.2360033380459037\n", + "0.8642003484231499 0.09979829364067982 0.23599103479707295\n", + "0.8641531835050852 0.09982401277453254 0.23602489132053955\n", + "Optimization terminated successfully.\n", + " Current function value: 0.235978\n", + " Iterations: 29\n", + " Function evaluations: 56\n", + "Time to estimate is 219.28957509994507 seconds.\n", + "Finished estimating for scaling factor of 1.0 and \"splurge amount\" of $700.0\n", + "Optimal (beta,nabla) is [0.86411194 0.09989792], simulated MPCs are:\n", + "[[0.76337822 0.73536628 0.68953168 0.58213285]\n", + " [0.65569708 0.62198032 0.56001686 0.41404097]\n", + " [0.57835292 0.54831948 0.48126189 0.32426049]\n", + " [0.40259267 0.38677506 0.33437532 0.21486836]]\n", + "Distance from Fagereng et al Table 9 is 0.2359780723857939\n" + ] + } + ], + "source": [ + "# Conduct the estimation\n", + "\n", + "guess = [0.92,0.03]\n", + "guess = [0.78981881,0.16098057]\n", + "f_temp = lambda x : FagerengObjFunc(x[0],x[1])\n", + "opt_params = minimizeNelderMead(f_temp, guess, verbose=True)\n", + "print('Finished estimating for scaling factor of ' + str(AdjFactor) + ' and \"splurge amount\" of $' + str(1000*Splurge))\n", + "print('Optimal (beta,nabla) is ' + str(opt_params) + ', simulated MPCs are:')\n", + "dist = FagerengObjFunc(opt_params[0],opt_params[1],True)\n", + "print('Distance from Fagereng et al Table 9 is ' + str(dist))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### PROBLEM\n", + "\n", + "See what happens if you do not allow a splurge amount at all. Hint: Think about how this question relates to the `drop_corner` option.\n", + "\n", + "Explain why you get the results you do, and comment on possible interpretations of the \"splurge\" that might be consistent with economic theory. \n", + "Hint: What the authors are able to measure is actually the marginal propensity to EXPEND, not the marginal propensity to CONSUME as it is defined in our benchmark model." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "MPC distribution for `splurge=0.7` and `drop_corner=0` is \n", + "0.78058645 0.74852543 0.69758672 0.57062401 \n", + "0.68077668 0.64027802 0.57082729 0.39800477 \n", + "0.60892177 0.5696061 0.4929874 0.30577941 \n", + "0.43708697 0.40971915 0.34376774 0.1947101 \n", + "Estimation: beta-point =0.86, nabla =12 \n", + "The distance is 0.36 \n", + "The estimator choses a relatively low beta and high nabla when `drop_corner` is set to zero. This is because it puts high importance on matching the MPC value in the upper left corner of the target matrix as the distance to the target is large. The low beta, however, deteriorates matches with the MPC target in other lottery / wealth quartiles. \n", + "\n", + "\n", + "MPC distribution for `splurge=0.7` and `drop_corner=1` is \n", + "0.76146837 0.73294988 0.68867587 0.58023753 \n", + "0.65406631 0.61881131 0.55855225 0.41047637 \n", + "0.5784164 0.54533118 0.47933813 0.31933032 \n", + "0.4037176 0.38408734 0.33105934 0.20577312 \n", + "Estimation: beta-point = 0.87, nabla = 0.10 \n", + "The distance is 0.24 \n", + "With `drop_corner` switched on, the distance is lower. This happens (i) mechanically since one difference is excluded from the euclidean distance, but also (ii) because the now higher beta-point value, allows to match other MPC targets of lower values much easier. The point estimate of beta-point is higher, the nabla becomes smaller, another indicator that the model does a better job to replicate the data as it needs less ex-ante heterogeneity. \n", + "\n", + "\n", + "MPC distribution for `splurge=0.0` and `drop_corner=0` is \n", + "0.77363444 0.68301477 0.56440589 0.40411035 \n", + "0.74357098 0.66467557 0.55281926 0.39561326 \n", + "0.70355573 0.6349713 0.53035817 0.37868694 \n", + "0.56134351 0.5041643 0.41242587 0.29210923 \n", + "Estimation: beta-point = 0.79, nabla = 0.16 \n", + "The distance is 0.50. \n", + "With both options set to zero, we obtain the worst fit. This indicates that removing the splurge makes it more difficult for the model to match the relative high MPC for lower wealth quartiles. This is compensated by a lower beta-point estimate. However, this goes at the cost of other, lower values of the MPC targets. \n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### PROBLEM\n", + "\n", + "Call the _Marginal Propensity to Continue Consuming_ (MPCC) in year `t+n` the proportion of lottery winnings that get spent in year `t+n`. That is, if consumption is higher in year `t+2` by an amount corresponding to 14 percent of lottery winnings, we would say _the MPCC in t+2 is 14 percent.\n", + "\n", + "For the baseline version of the model with the \"splurge\" component, calculate the MPCC's for years `t+1` through `t+3` and plot them together with the MPC in the first year (including the splurge component)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The MPC for t+0 is \n", + " [[0.7634 0.7354 0.6895 0.5821]\n", + " [0.6557 0.622 0.56 0.414 ]\n", + " [0.5784 0.5483 0.4813 0.3243]\n", + " [0.4026 0.3868 0.3344 0.2149]]\n", + "\n", + "\n", + "The MPCC for t+1 is \n", + " [[0.1612 0.18 0.2003 0.2072]\n", + " [0.2115 0.2229 0.2292 0.1974]\n", + " [0.2413 0.2464 0.2431 0.1906]\n", + " [0.2601 0.2583 0.2373 0.1682]]\n", + "\n", + "\n", + "The MPCC for t+2 is \n", + " [[0.0928 0.1189 0.1637 0.2392]\n", + " [0.1083 0.1269 0.157 0.1879]\n", + " [0.1242 0.1367 0.1576 0.1631]\n", + " [0.17 0.1722 0.1721 0.1409]]\n", + "\n", + "\n", + "The MPCC for t+3 is \n", + " [[0.0656 0.0891 0.1396 0.2666]\n", + " [0.0627 0.0793 0.1144 0.184 ]\n", + " [0.0674 0.0792 0.1061 0.1446]\n", + " [0.1069 0.1107 0.1225 0.119 ]]\n", + "\n", + " I plot as an example the evolution of the MPC in the 2nd quartile of wealth and lottery win.\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "def FagerengFutureObjFunc(center,spread,verbose=False):\n", + "\n", + " # Give our consumer types the requested discount factor distribution\n", + " beta_set = approxUniform(N=TypeCount,bot=center-spread,top=center+spread)[1]\n", + " for j in range(TypeCount):\n", + " EstTypeList[j](DiscFac = beta_set[j])\n", + " # add tracking vars to each Type\n", + " EstTypeList[j].track_vars = ['aNrmNow','mNrmNow','cNrmNow','pLvlNow','PermShkNow','TranShkNow']\n", + "\n", + " # Solve and simulate all consumer types, then gather their wealth levels\n", + " StartPeriod = 95;\n", + " multiThreadCommands(EstTypeList,['solve()','initializeSim()','simulate(95)','unpackcFunc()'])\n", + " WealthNow = np.concatenate([ThisType.aLvlNow for ThisType in EstTypeList])\n", + "\n", + " # Get wealth quartile cutoffs and distribute them to each consumer type\n", + " quartile_cuts = getPercentiles(WealthNow,percentiles=[0.25,0.50,0.75])\n", + " for ThisType in EstTypeList:\n", + " WealthQ = np.zeros(ThisType.AgentCount,dtype=int)\n", + " for n in range(3):\n", + " WealthQ[ThisType.aLvlNow > quartile_cuts[n]] += 1\n", + " ThisType(WealthQ = WealthQ)\n", + "\n", + " # Keep track of MPC sets in lists of lists of arrays\n", + " MPC_set_list = [ [[],[],[],[]],\n", + " [[],[],[],[]],\n", + " [[],[],[],[]],\n", + " [[],[],[],[]] ]\n", + " MPC_set_list_t1 = deepcopy(MPC_set_list)\n", + " MPC_set_list_t2 = deepcopy(MPC_set_list)\n", + " MPC_set_list_t3 = deepcopy(MPC_set_list)\n", + "\n", + " Rfree = base_params['Rfree']\n", + " # Calculate the MPC for each of the four lottery sizes for all agents\n", + " for ThisType in EstTypeList:\n", + " ThisType.simulate(4)\n", + " c_base_0 = ThisType.cNrmNow_hist[StartPeriod]\n", + " c_base_t1 = ThisType.cNrmNow_hist[StartPeriod+1]\n", + " c_base_t2 = ThisType.cNrmNow_hist[StartPeriod+2]\n", + " c_base_t3 = ThisType.cNrmNow_hist[StartPeriod+3]\n", + " \n", + " MPC_this_type = np.zeros((ThisType.AgentCount,4))\n", + " MPC_this_type_t1 = np.zeros((ThisType.AgentCount,4))\n", + " MPC_this_type_t2 = np.zeros((ThisType.AgentCount,4))\n", + " MPC_this_type_t3 = np.zeros((ThisType.AgentCount,4))\n", + " \n", + " for k in range(4): # Get MPC for all agents of this type \n", + " Llvl = lottery_size[k]\n", + " Lnrm = Llvl/ThisType.pLvlNow_hist[StartPeriod] \n", + " SplurgeNrm = Splurge/ThisType.pLvlNow_hist[StartPeriod]\n", + " mAdj = ThisType.mNrmNow_hist[StartPeriod] + Lnrm - SplurgeNrm\n", + " cAdj = ThisType.cFunc[0](mAdj) + SplurgeNrm\n", + " MPC_this_type[:,k] = (cAdj - c_base_0) /Lnrm\n", + " \n", + " # Calculate normalized market resources in t+1 (varnames t1)\n", + " #Llvl = lottery_size[k]\n", + " Lnrm = Llvl/ThisType.pLvlNow_hist[StartPeriod+1]\n", + " aNrm_t0 = ThisType.mNrmNow_hist[StartPeriod] + Lnrm - cAdj\n", + " aLvl_t0 = aNrm_t0*ThisType.pLvlNow_hist[StartPeriod]\n", + " mLvl_t1 = aLvl_t0*Rfree + ThisType.TranShkNow_hist[StartPeriod+1]*ThisType.pLvlNow_hist[StartPeriod+1]\n", + " mNrm_t1 = mLvl_t1/ThisType.pLvlNow_hist[StartPeriod+1]\n", + " cNrm_t1 = ThisType.cFunc[0](mNrm_t1)\n", + " MPC_this_type_t1[:,k] = (cNrm_t1 - c_base_t1) /Lnrm\n", + "\n", + " # Calculate normalized market resources in t+2 (varnames t2)\n", + " Llvl = lottery_size[k]\n", + " Lnrm = Llvl/ThisType.pLvlNow_hist[StartPeriod+2]\n", + " aNrm_t1 = mNrm_t1 - cNrm_t1;\n", + " aLvl_t1 = aNrm_t1*ThisType.pLvlNow_hist[StartPeriod+1]\n", + " mLvl_t2 = aLvl_t1*Rfree + ThisType.TranShkNow_hist[StartPeriod+2]*ThisType.pLvlNow_hist[StartPeriod+2]\n", + " mNrm_t2 = mLvl_t2/ThisType.pLvlNow_hist[StartPeriod+2]\n", + " cNrm_t2 = ThisType.cFunc[0](mNrm_t2)\n", + " MPC_this_type_t2[:,k] = (cNrm_t2 - c_base_t2) /Lnrm\n", + "\n", + " # Calculate normalized market resources in t+3 (varnames t3)\n", + " Llvl = lottery_size[k]\n", + " Lnrm = Llvl/ThisType.pLvlNow_hist[StartPeriod+3]\n", + " aNrm_t2 = mNrm_t2 - cNrm_t2;\n", + " aLvl_t2 = aNrm_t2*ThisType.pLvlNow_hist[StartPeriod+2]\n", + " mLvl_t3 = aLvl_t2*Rfree + ThisType.TranShkNow_hist[StartPeriod+3]*ThisType.pLvlNow_hist[StartPeriod+3]\n", + " mNrm_t3 = mLvl_t3/ThisType.pLvlNow_hist[StartPeriod+3]\n", + " cNrm_t3 = ThisType.cFunc[0](mNrm_t3)\n", + " MPC_this_type_t3[:,k] = (cNrm_t3 - c_base_t3) /Lnrm\n", + " \n", + "\n", + " # Sort the MPCs into the proper MPC sets\n", + " for q in range(4):\n", + " these = ThisType.WealthQ == q\n", + " for k in range(4):\n", + " MPC_set_list[k][q].append(MPC_this_type[these,k])\n", + " MPC_set_list_t1[k][q].append(MPC_this_type_t1[these,k])\n", + " MPC_set_list_t2[k][q].append(MPC_this_type_t2[these,k])\n", + " MPC_set_list_t3[k][q].append(MPC_this_type_t3[these,k])\n", + "\n", + " # Calculate average within each MPC set\n", + " simulated_MPC_means = np.zeros((4,4))\n", + " simulated_MPC_means_t1 = np.zeros((4,4))\n", + " simulated_MPC_means_t2 = np.zeros((4,4))\n", + " simulated_MPC_means_t3 = np.zeros((4,4))\n", + " for k in range(4):\n", + " for q in range(4):\n", + " MPC_array = np.concatenate(MPC_set_list[k][q])\n", + " simulated_MPC_means[k,q] = np.mean(MPC_array)\n", + " simulated_MPC_means_t1[k,q] = np.mean(np.concatenate(MPC_set_list_t1[k][q]))\n", + " simulated_MPC_means_t2[k,q] = np.mean(np.concatenate(MPC_set_list_t2[k][q]))\n", + " simulated_MPC_means_t3[k,q] = np.mean(np.concatenate(MPC_set_list_t3[k][q]))\n", + " \n", + " print('The MPC for t+0 is \\n', np.round(simulated_MPC_means,4))\n", + " print('\\n')\n", + " print('The MPCC for t+1 is \\n', np.round(simulated_MPC_means_t1,4))\n", + " print('\\n')\n", + " print('The MPCC for t+2 is \\n', np.round(simulated_MPC_means_t2,4))\n", + " print('\\n')\n", + " print('The MPCC for t+3 is \\n', np.round(simulated_MPC_means_t3,4))\n", + " \n", + " \n", + " import matplotlib.pyplot as plt\n", + " print('\\n I plot as an example the evolution of the MPC in the 2nd quartile of wealth and lottery win.')\n", + " plt.plot([0, 1, 2, 3],[simulated_MPC_means[1,1],simulated_MPC_means_t1[1,1],simulated_MPC_means_t2[1,1],simulated_MPC_means_t3[1,1]])\n", + " plt.xlabel('Year')\n", + " plt.ylabel('MPCC')\n", + " plt.show(block=False)\n", + "\n", + " # Calculate Euclidean distance between simulated MPC averages and Table 9 targets\n", + " diff = simulated_MPC_means - MPC_target\n", + " if drop_corner:\n", + " diff[0,0] = 0.0\n", + " distance = np.sqrt(np.sum((diff)**2))\n", + " return distance\n", + "\n", + "dist = FagerengFutureObjFunc(opt_params[0],opt_params[1],True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "cite2c": { + "citations": { + "6202365/SUE56C4B": { + "author": [ + { + "family": "Fagereng", + "given": "Andreas" + }, + { + "family": "Holm", + "given": "Martin B." + }, + { + "family": "Natvik", + "given": "Gisle J." + } + ], + "genre": "discussion paper", + "id": "6202365/SUE56C4B", + "issued": { + "year": 2017 + }, + "publisher": "Statistics Norway", + "title": "MPC Heterogeneity and Household Balance Sheets", + "type": "report" + } + } + }, + "jupytext": { + "cell_metadata_filter": "collapsed,code_folding", + "formats": "ipynb,py:percent" + }, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.4" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": false + }, + "varInspector": { + "cols": { + "lenName": 16, + "lenType": 16, + "lenVar": 40 + }, + "kernels_config": { + "python": { + "delete_cmd_postfix": "", + "delete_cmd_prefix": "del ", + "library": "var_list.py", + "varRefreshCmd": "print(var_dic_list())" + }, + "r": { + "delete_cmd_postfix": ") ", + "delete_cmd_prefix": "rm(", + "library": "var_list.r", + "varRefreshCmd": "cat(var_dic_list()) " + } + }, + "types_to_exclude": [ + "module", + "function", + "builtin_function_or_method", + "instance", + "_Feature" + ], + "window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/notebooks/Structural-Estimates-From-Empirical-MPCs-Fagereng-et-al-Problems-And-Solutions.py b/notebooks/Structural-Estimates-From-Empirical-MPCs-Fagereng-et-al-Problems-And-Solutions.py new file mode 100644 index 0000000..27d0ca7 --- /dev/null +++ b/notebooks/Structural-Estimates-From-Empirical-MPCs-Fagereng-et-al-Problems-And-Solutions.py @@ -0,0 +1,379 @@ +# --- +# jupyter: +# jupytext: +# cell_metadata_filter: collapsed,code_folding +# formats: ipynb,py:percent +# text_representation: +# extension: .py +# format_name: percent +# format_version: '1.3' +# jupytext_version: 1.4.0 +# kernelspec: +# display_name: Python 3 +# language: python +# name: python3 +# --- + +# %% [markdown] +# # Making Structural Estimates From Empirical Results +# +# This notebook conducts a quick and dirty structural estimation based on Table 9 of "MPC Heterogeneity and Household Balance Sheets" by Fagereng, Holm, and Natvik , who use Norweigian administrative data on income, household assets, and lottery winnings to examine the MPC from transitory income shocks (lottery prizes). Their Table 9 reports an estimated MPC broken down by quartiles of bank deposits and +# prize size; this table is reproduced here as $\texttt{MPC_target_base}$. In this demo, we use the Table 9 estimates as targets in a simple structural estimation, seeking to minimize the sum of squared differences between simulated and estimated MPCs by changing the (uniform) distribution of discount factors. The essential question is how well their results be rationalized by a simple one-asset consumption-saving model. +# +# +# The function that estimates discount factors includes several options for estimating different specifications: +# +# 1. TypeCount : Integer number of discount factors in discrete distribution; can be set to 1 to turn off _ex ante_ heterogeneity (and to discover that the model has no chance to fit the data well without such heterogeneity). +# 2. AdjFactor : Scaling factor for the target MPCs; user can try to fit estimated MPCs scaled down by (e.g.) 50%. +# 3. T_kill : Maximum number of years the (perpetually young) agents are allowed to live. Because this is quick and dirty, it's also the number of periods to simulate. +# 4. Splurge : Amount of lottery prize that an individual will automatically spend in a moment of excitement (perhaps ancient tradition in Norway requires a big party when you win the lottery), before beginning to behave according to the optimal consumption function. The patterns in Table 9 can be fit much better when this is set around \$700 --> 0.7. That doesn't seem like an unreasonable amount of money to spend on a memorable party. +# 5. do_secant : Boolean indicator for whether to use "secant MPC", which is average MPC over the range of the prize. MNW believes authors' regressions are estimating this rather than point MPC. When False, structural estimation uses point MPC after receiving prize. NB: This is incompatible with Splurge > 0. +# 6. drop_corner : Boolean for whether to include target MPC in the top left corner, which is greater than 1. Authors discuss reasons why the MPC from a transitory shock *could* exceed 1. Option is included here because this target tends to push the estimate around a bit. + +# %% code_folding=[] +# Import python tools + +import sys +import os + +import numpy as np +from copy import deepcopy + +# %% code_folding=[] +# Import needed tools from HARK + +from HARK.utilities import approxUniform, getPercentiles +from HARK.parallel import multiThreadCommands +from HARK.estimation import minimizeNelderMead +from HARK.ConsumptionSaving.ConsIndShockModel import * +from HARK.cstwMPC.SetupParamsCSTW import init_infinite + +# %% code_folding=[] +# Set key problem-specific parameters + +TypeCount = 8 # Number of consumer types with heterogeneous discount factors +AdjFactor = 1.0 # Factor by which to scale all of MPCs in Table 9 +T_kill = 100 # Don't let agents live past this age +Splurge = 0.7 # Consumers automatically spend this amount of any lottery prize +do_secant = True # If True, calculate MPC by secant, else point MPC +drop_corner = True # If True, ignore upper left corner when calculating distance + +# %% code_folding=[] +# Set standard HARK parameter values + +base_params = deepcopy(init_infinite) +base_params['LivPrb'] = [0.975] +base_params['Rfree'] = 1.04/base_params['LivPrb'][0] +base_params['PermShkStd'] = [0.1] +base_params['TranShkStd'] = [0.1] +base_params['T_age'] = T_kill # Kill off agents if they manage to achieve T_kill working years +base_params['AgentCount'] = 10000 +base_params['pLvlInitMean'] = np.log(23.72) # From Table 1, in thousands of USD +base_params['T_sim'] = T_kill # No point simulating past when agents would be killed off + +# %% code_folding=[] +# Define the MPC targets from Fagereng et al Table 9; element i,j is lottery quartile i, deposit quartile j + +MPC_target_base = np.array([[1.047, 0.745, 0.720, 0.490], + [0.762, 0.640, 0.559, 0.437], + [0.663, 0.546, 0.390, 0.386], + [0.354, 0.325, 0.242, 0.216]]) +MPC_target = AdjFactor*MPC_target_base + +# %% code_folding=[] +# Define the four lottery sizes, in thousands of USD; these are eyeballed centers/averages + +lottery_size = np.array([1.625, 3.3741, 7.129, 40.0]) + +# %% code_folding=[] +# Make several consumer types to be used during estimation + +BaseType = IndShockConsumerType(**base_params) +EstTypeList = [] +for j in range(TypeCount): + EstTypeList.append(deepcopy(BaseType)) + EstTypeList[-1](seed = j) + +# %% code_folding=[] +# Define the objective function + +def FagerengObjFunc(center,spread,verbose=False): + ''' + Objective function for the quick and dirty structural estimation to fit + Fagereng, Holm, and Natvik's Table 9 results with a basic infinite horizon + consumption-saving model (with permanent and transitory income shocks). + + Parameters + ---------- + center : float + Center of the uniform distribution of discount factors. + spread : float + Width of the uniform distribution of discount factors. + verbose : bool + When True, print to screen MPC table for these parameters. When False, + print (center, spread, distance). + + Returns + ------- + distance : float + Euclidean distance between simulated MPCs and (adjusted) Table 9 MPCs. + ''' + # Give our consumer types the requested discount factor distribution + beta_set = approxUniform(N=TypeCount,bot=center-spread,top=center+spread)[1] + for j in range(TypeCount): + EstTypeList[j](DiscFac = beta_set[j]) + + # Solve and simulate all consumer types, then gather their wealth levels + multiThreadCommands(EstTypeList,['solve()','initializeSim()','simulate(95)','unpackcFunc()']) + WealthNow = np.concatenate([ThisType.aLvlNow for ThisType in EstTypeList]) + + # Get wealth quartile cutoffs and distribute them to each consumer type + quartile_cuts = getPercentiles(WealthNow,percentiles=[0.25,0.50,0.75]) + for ThisType in EstTypeList: + WealthQ = np.zeros(ThisType.AgentCount,dtype=int) + for n in range(3): + WealthQ[ThisType.aLvlNow > quartile_cuts[n]] += 1 + ThisType(WealthQ = WealthQ) + + # Keep track of MPC sets in lists of lists of arrays + MPC_set_list = [ [[],[],[],[]], + [[],[],[],[]], + [[],[],[],[]], + [[],[],[],[]] ] + + # Calculate the MPC for each of the four lottery sizes for all agents + for ThisType in EstTypeList: + ThisType.simulate(1) + c_base = ThisType.cNrmNow + MPC_this_type = np.zeros((ThisType.AgentCount,4)) + for k in range(4): # Get MPC for all agents of this type + Llvl = lottery_size[k] + Lnrm = Llvl/ThisType.pLvlNow + if do_secant: + SplurgeNrm = Splurge/ThisType.pLvlNow + mAdj = ThisType.mNrmNow + Lnrm - SplurgeNrm + cAdj = ThisType.cFunc[0](mAdj) + SplurgeNrm + MPC_this_type[:,k] = (cAdj - c_base)/Lnrm + else: + mAdj = ThisType.mNrmNow + Lnrm + MPC_this_type[:,k] = cAdj = ThisType.cFunc[0].derivative(mAdj) + + # Sort the MPCs into the proper MPC sets + for q in range(4): + these = ThisType.WealthQ == q + for k in range(4): + MPC_set_list[k][q].append(MPC_this_type[these,k]) + + # Calculate average within each MPC set + simulated_MPC_means = np.zeros((4,4)) + for k in range(4): + for q in range(4): + MPC_array = np.concatenate(MPC_set_list[k][q]) + simulated_MPC_means[k,q] = np.mean(MPC_array) + + # Calculate Euclidean distance between simulated MPC averages and Table 9 targets + diff = simulated_MPC_means - MPC_target + if drop_corner: + diff[0,0] = 0.0 + distance = np.sqrt(np.sum((diff)**2)) + if verbose: + print(simulated_MPC_means) + else: + print (center, spread, distance) + return distance + + +# %% code_folding=[] +# Conduct the estimation + +guess = [0.92,0.03] +guess = [0.78981881,0.16098057] +f_temp = lambda x : FagerengObjFunc(x[0],x[1]) +opt_params = minimizeNelderMead(f_temp, guess, verbose=True) +print('Finished estimating for scaling factor of ' + str(AdjFactor) + ' and "splurge amount" of $' + str(1000*Splurge)) +print('Optimal (beta,nabla) is ' + str(opt_params) + ', simulated MPCs are:') +dist = FagerengObjFunc(opt_params[0],opt_params[1],True) +print('Distance from Fagereng et al Table 9 is ' + str(dist)) + + +# %% [markdown] +# ### PROBLEM +# +# See what happens if you do not allow a splurge amount at all. Hint: Think about how this question relates to the `drop_corner` option. +# +# Explain why you get the results you do, and comment on possible interpretations of the "splurge" that might be consistent with economic theory. +# Hint: What the authors are able to measure is actually the marginal propensity to EXPEND, not the marginal propensity to CONSUME as it is defined in our benchmark model. + +# %% [markdown] +# MPC distribution for `splurge=0.7` and `drop_corner=0` is +# 0.78058645 0.74852543 0.69758672 0.57062401 +# 0.68077668 0.64027802 0.57082729 0.39800477 +# 0.60892177 0.5696061 0.4929874 0.30577941 +# 0.43708697 0.40971915 0.34376774 0.1947101 +# Estimation: beta-point =0.86, nabla =12 +# The distance is 0.36 +# The estimator choses a relatively low beta and high nabla when `drop_corner` is set to zero. This is because it puts high importance on matching the MPC value in the upper left corner of the target matrix as the distance to the target is large. The low beta, however, deteriorates matches with the MPC target in other lottery / wealth quartiles. +# +# +# MPC distribution for `splurge=0.7` and `drop_corner=1` is +# 0.76146837 0.73294988 0.68867587 0.58023753 +# 0.65406631 0.61881131 0.55855225 0.41047637 +# 0.5784164 0.54533118 0.47933813 0.31933032 +# 0.4037176 0.38408734 0.33105934 0.20577312 +# Estimation: beta-point = 0.87, nabla = 0.10 +# The distance is 0.24 +# With `drop_corner` switched on, the distance is lower. This happens (i) mechanically since one difference is excluded from the euclidean distance, but also (ii) because the now higher beta-point value, allows to match other MPC targets of lower values much easier. The point estimate of beta-point is higher, the nabla becomes smaller, another indicator that the model does a better job to replicate the data as it needs less ex-ante heterogeneity. +# +# +# MPC distribution for `splurge=0.0` and `drop_corner=0` is +# 0.77363444 0.68301477 0.56440589 0.40411035 +# 0.74357098 0.66467557 0.55281926 0.39561326 +# 0.70355573 0.6349713 0.53035817 0.37868694 +# 0.56134351 0.5041643 0.41242587 0.29210923 +# Estimation: beta-point = 0.79, nabla = 0.16 +# The distance is 0.50. +# With both options set to zero, we obtain the worst fit. This indicates that removing the splurge makes it more difficult for the model to match the relative high MPC for lower wealth quartiles. This is compensated by a lower beta-point estimate. However, this goes at the cost of other, lower values of the MPC targets. +# +# + +# %% [markdown] +# ### PROBLEM +# +# Call the _Marginal Propensity to Continue Consuming_ (MPCC) in year `t+n` the proportion of lottery winnings that get spent in year `t+n`. That is, if consumption is higher in year `t+2` by an amount corresponding to 14 percent of lottery winnings, we would say _the MPCC in t+2 is 14 percent. +# +# For the baseline version of the model with the "splurge" component, calculate the MPCC's for years `t+1` through `t+3` and plot them together with the MPC in the first year (including the splurge component) +# + +# %% +def FagerengFutureObjFunc(center,spread,verbose=False): + + # Give our consumer types the requested discount factor distribution + beta_set = approxUniform(N=TypeCount,bot=center-spread,top=center+spread)[1] + for j in range(TypeCount): + EstTypeList[j](DiscFac = beta_set[j]) + # add tracking vars to each Type + EstTypeList[j].track_vars = ['aNrmNow','mNrmNow','cNrmNow','pLvlNow','PermShkNow','TranShkNow'] + + # Solve and simulate all consumer types, then gather their wealth levels + StartPeriod = 95; + multiThreadCommands(EstTypeList,['solve()','initializeSim()','simulate(95)','unpackcFunc()']) + WealthNow = np.concatenate([ThisType.aLvlNow for ThisType in EstTypeList]) + + # Get wealth quartile cutoffs and distribute them to each consumer type + quartile_cuts = getPercentiles(WealthNow,percentiles=[0.25,0.50,0.75]) + for ThisType in EstTypeList: + WealthQ = np.zeros(ThisType.AgentCount,dtype=int) + for n in range(3): + WealthQ[ThisType.aLvlNow > quartile_cuts[n]] += 1 + ThisType(WealthQ = WealthQ) + + # Keep track of MPC sets in lists of lists of arrays + MPC_set_list = [ [[],[],[],[]], + [[],[],[],[]], + [[],[],[],[]], + [[],[],[],[]] ] + MPC_set_list_t1 = deepcopy(MPC_set_list) + MPC_set_list_t2 = deepcopy(MPC_set_list) + MPC_set_list_t3 = deepcopy(MPC_set_list) + + Rfree = base_params['Rfree'] + # Calculate the MPC for each of the four lottery sizes for all agents + for ThisType in EstTypeList: + ThisType.simulate(4) + c_base_0 = ThisType.cNrmNow_hist[StartPeriod] + c_base_t1 = ThisType.cNrmNow_hist[StartPeriod+1] + c_base_t2 = ThisType.cNrmNow_hist[StartPeriod+2] + c_base_t3 = ThisType.cNrmNow_hist[StartPeriod+3] + + MPC_this_type = np.zeros((ThisType.AgentCount,4)) + MPC_this_type_t1 = np.zeros((ThisType.AgentCount,4)) + MPC_this_type_t2 = np.zeros((ThisType.AgentCount,4)) + MPC_this_type_t3 = np.zeros((ThisType.AgentCount,4)) + + for k in range(4): # Get MPC for all agents of this type + Llvl = lottery_size[k] + Lnrm = Llvl/ThisType.pLvlNow_hist[StartPeriod] + SplurgeNrm = Splurge/ThisType.pLvlNow_hist[StartPeriod] + mAdj = ThisType.mNrmNow_hist[StartPeriod] + Lnrm - SplurgeNrm + cAdj = ThisType.cFunc[0](mAdj) + SplurgeNrm + MPC_this_type[:,k] = (cAdj - c_base_0) /Lnrm + + # Calculate normalized market resources in t+1 (varnames t1) + #Llvl = lottery_size[k] + Lnrm = Llvl/ThisType.pLvlNow_hist[StartPeriod+1] + aNrm_t0 = ThisType.mNrmNow_hist[StartPeriod] + Lnrm - cAdj + aLvl_t0 = aNrm_t0*ThisType.pLvlNow_hist[StartPeriod] + mLvl_t1 = aLvl_t0*Rfree + ThisType.TranShkNow_hist[StartPeriod+1]*ThisType.pLvlNow_hist[StartPeriod+1] + mNrm_t1 = mLvl_t1/ThisType.pLvlNow_hist[StartPeriod+1] + cNrm_t1 = ThisType.cFunc[0](mNrm_t1) + MPC_this_type_t1[:,k] = (cNrm_t1 - c_base_t1) /Lnrm + + # Calculate normalized market resources in t+2 (varnames t2) + Llvl = lottery_size[k] + Lnrm = Llvl/ThisType.pLvlNow_hist[StartPeriod+2] + aNrm_t1 = mNrm_t1 - cNrm_t1; + aLvl_t1 = aNrm_t1*ThisType.pLvlNow_hist[StartPeriod+1] + mLvl_t2 = aLvl_t1*Rfree + ThisType.TranShkNow_hist[StartPeriod+2]*ThisType.pLvlNow_hist[StartPeriod+2] + mNrm_t2 = mLvl_t2/ThisType.pLvlNow_hist[StartPeriod+2] + cNrm_t2 = ThisType.cFunc[0](mNrm_t2) + MPC_this_type_t2[:,k] = (cNrm_t2 - c_base_t2) /Lnrm + + # Calculate normalized market resources in t+3 (varnames t3) + Llvl = lottery_size[k] + Lnrm = Llvl/ThisType.pLvlNow_hist[StartPeriod+3] + aNrm_t2 = mNrm_t2 - cNrm_t2; + aLvl_t2 = aNrm_t2*ThisType.pLvlNow_hist[StartPeriod+2] + mLvl_t3 = aLvl_t2*Rfree + ThisType.TranShkNow_hist[StartPeriod+3]*ThisType.pLvlNow_hist[StartPeriod+3] + mNrm_t3 = mLvl_t3/ThisType.pLvlNow_hist[StartPeriod+3] + cNrm_t3 = ThisType.cFunc[0](mNrm_t3) + MPC_this_type_t3[:,k] = (cNrm_t3 - c_base_t3) /Lnrm + + + # Sort the MPCs into the proper MPC sets + for q in range(4): + these = ThisType.WealthQ == q + for k in range(4): + MPC_set_list[k][q].append(MPC_this_type[these,k]) + MPC_set_list_t1[k][q].append(MPC_this_type_t1[these,k]) + MPC_set_list_t2[k][q].append(MPC_this_type_t2[these,k]) + MPC_set_list_t3[k][q].append(MPC_this_type_t3[these,k]) + + # Calculate average within each MPC set + simulated_MPC_means = np.zeros((4,4)) + simulated_MPC_means_t1 = np.zeros((4,4)) + simulated_MPC_means_t2 = np.zeros((4,4)) + simulated_MPC_means_t3 = np.zeros((4,4)) + for k in range(4): + for q in range(4): + MPC_array = np.concatenate(MPC_set_list[k][q]) + simulated_MPC_means[k,q] = np.mean(MPC_array) + simulated_MPC_means_t1[k,q] = np.mean(np.concatenate(MPC_set_list_t1[k][q])) + simulated_MPC_means_t2[k,q] = np.mean(np.concatenate(MPC_set_list_t2[k][q])) + simulated_MPC_means_t3[k,q] = np.mean(np.concatenate(MPC_set_list_t3[k][q])) + + print('The MPC for t+0 is \n', np.round(simulated_MPC_means,4)) + print('\n') + print('The MPCC for t+1 is \n', np.round(simulated_MPC_means_t1,4)) + print('\n') + print('The MPCC for t+2 is \n', np.round(simulated_MPC_means_t2,4)) + print('\n') + print('The MPCC for t+3 is \n', np.round(simulated_MPC_means_t3,4)) + + + import matplotlib.pyplot as plt + print('\n I plot as an example the evolution of the MPC in the 2nd quartile of wealth and lottery win.') + plt.plot([0, 1, 2, 3],[simulated_MPC_means[1,1],simulated_MPC_means_t1[1,1],simulated_MPC_means_t2[1,1],simulated_MPC_means_t3[1,1]]) + plt.xlabel('Year') + plt.ylabel('MPCC') + plt.show(block=False) + + # Calculate Euclidean distance between simulated MPC averages and Table 9 targets + diff = simulated_MPC_means - MPC_target + if drop_corner: + diff[0,0] = 0.0 + distance = np.sqrt(np.sum((diff)**2)) + return distance + +dist = FagerengFutureObjFunc(opt_params[0],opt_params[1],True) + +# %%