def VCV_moments(scf, n, bin_weights, J): """ Compute variance-covariance matrix for wealth moments by bootstrapping data. Args: scf (Pandas DataFrame): raw data from SCF n (int): number of bootstrap iterations to run bin_weights (array-like): ability weights (Jx1 array) J (int): number of ability groups Returns: VCV (Numpy array): variance-covariance matrix of wealth moments, (J+2xJ+2) array """ wealth_moments_boot = np.zeros((n, J + 2)) for i in range(n): sample = scf[np.random.randint(2, size=len(scf.index)).astype(bool)] # note that wealth moments from data are in array in same order # as model moments are computed in this module wealth_moments_boot[i, :] = wealth.compute_wealth_moments( sample, bin_weights) VCV = np.cov(wealth_moments_boot.T) return VCV
def wealth_moments_table(base_ss, base_params, table_format=None, path=None): ''' Creates table with moments of the wealth distribution from the model and SCF data. Args: base_ss (dictionary): SS output from baseline run base_params (OG-Core Specifications class): baseline parameters object table_format (string): format to return table in: 'csv', 'tex', 'excel', 'json', if None, a DataFrame is returned path (string): path to save table to Returns: table (various): table in DataFrame or string format or `None` if saved to disk ''' table_dict = { 'Moment': [ 'Share 0-25%', 'Share 25-50%', 'Share 50-70%', 'Share 70-80%', 'Share 80-90%', 'Share 90-99%', 'Share 99-100%', 'Gini Coefficient', 'var(ln(Wealth))' ], 'Data': [], 'Model': [] } base_ineq = Inequality(base_ss['bssmat_splus1'], base_params.omega_SS, base_params.lambdas, base_params.S, base_params.J) base_values = [ 1 - base_ineq.top_share(0.75), base_ineq.top_share(0.75) - base_ineq.top_share(0.5), base_ineq.top_share(0.5) - base_ineq.top_share(0.3), base_ineq.top_share(0.3) - base_ineq.top_share(0.2), base_ineq.top_share(0.2) - base_ineq.top_share(0.1), base_ineq.top_share(0.1) - base_ineq.top_share(0.01), base_ineq.top_share(0.01), base_ineq.gini(), base_ineq.var_of_logs() ] table_dict['Model'].extend(base_values) # get moments from Survey of Consumer Finances data scf = wealth.get_wealth_data() table_dict['Data'] = wealth.compute_wealth_moments( scf, np.array([0.25, 0.25, 0.2, 0.1, 0.1, 0.09, 0.01])) # Make df with dict so can use pandas functions table_df = pd.DataFrame.from_dict(table_dict) table = save_return_table(table_df, table_format, path, precision=3) return table
def test_compute_wealth_moments(): ''' Test of computation of wealth moments. Need SCF data which is too large to check into repo so this will be flagged so as to not run on TravisCI. ''' expected_moments = np.array([ -4.42248572e-03, 1.87200063e-02, 5.78230550e-02, 5.94466440e-02, 1.15413004e-01, 3.88100712e-01, 3.64919063e-01, 8.47639595e-01, 5.04231901e+00]) df = wealth.get_wealth_data() test_moments = wealth.compute_wealth_moments( df, np.array([0.25, 0.25, 0.2, 0.1, 0.1, 0.09, 0.01])) assert(np.allclose(expected_moments, test_moments, rtol=0.001))
def beta_estimate(beta_initial_guesses, og_spec={}, two_step=False, client=None): """ This function estimates the beta_j parameters using a simulated method of moments estimator that targets moments of the wealth distribution. Args: beta_initial_guesses (array-like): array of initial guesses for the beta_j parameters og_spec (dict): any updates to default model parameters two_step (boolean): whether to use a two-step estimator client (Dask Client object): dask client for multiprocessing Returns: beta_hat (array-like): estimates of the beta_j beta_se (array-like): standard errors on the beta_j estimates """ # initialize parametes object tax_func_path = os.path.join( "..", "..", "dynamic", "ogusa", "data", "tax_functions", "TxFuncEst_baseline_PUF.pkl", ) p = Specifications(baseline=True) p.update_specifications(og_spec) p.get_tax_function_parameters(client, False, tax_func_path) # Compute wealth moments from the data scf = wealth.get_wealth_data(scf_yrs_list=[2019], web=True, directory=None) data_moments = wealth.compute_wealth_moments(scf, p.lambdas) # Get weighting matrix W = compute_weighting_matrix(p, optimal_weight=False) # call minimizer # set bounds on beta estimates (need to be between 0 and 1) bnds = np.tile(np.array([1e-12, 1]), (p.J, 1)) # Need (1e-12, 1) J times # pack arguments in a tuple min_args = (data_moments, W, p, client) # NOTE: may want to try some global optimization routing like # simulated annealing (aka basin hopping) or differential # evolution est_output = opt.minimize( minstat, beta_initial_guesses, args=(min_args), method="L-BFGS-B", bounds=bnds, tol=1e-15, options={ "maxfun": 1, "maxiter": 1, "maxls": 1 }, ) beta_hat = est_output["x"] # calculate std errors K = len(data_moments) beta_se, VCV_params = compute_se(beta_hat, W, K, p, h=0.01, client=client) if two_step: W = VCV_params min_args = (data_moments, W, p, client) est_output = opt.minimize( minstat, beta_initial_guesses, args=(min_args), method="L-BFGS-B", bounds=bnds, tol=1e-15, options={ "maxfun": 1, "maxiter": 1, "maxls": 1 }, ) beta_hat = est_output["x"] beta_se, VCV_params = compute_se(beta_hat, W, K, p, h=0.01, client=client) return beta_hat, beta_se