示例#1
0
    def growmodel_analysis(input_data, tax_year,
                           baseline, reform, assump,
                           aging_input_data, exact_calculations,
                           writing_output_file=False,
                           output_tables=False,
                           output_graphs=False,
                           dump_varset=None,
                           output_dump=False,
                           output_sqldb=False):
        """
        High-level logic for dynamic analysis using GrowModel class.

        Parameters
        ----------
        First five parameters are same as the first five parameters of
        the TaxCalcIO.init method.

        Last seven parameters are same as the first seven parameters of
        the TaxCalcIO.analyze method.

        Returns
        -------
        Nothing
        """
        # pylint: disable=too-many-arguments,too-many-locals
        progress = 'STARTING ANALYSIS FOR YEAR {}'
        gdiff_dict = {Policy.JSON_START_YEAR: {}}
        for year in range(Policy.JSON_START_YEAR, tax_year + 1):
            print(progress.format(year))
            # specify growdiff_growmodel using gdiff_dict
            growdiff_growmodel = GrowDiff()
            growdiff_growmodel.update_growdiff(gdiff_dict)
            gd_dict = TaxCalcIO.annual_analysis(input_data, tax_year,
                                                baseline, reform, assump,
                                                aging_input_data,
                                                exact_calculations,
                                                growdiff_growmodel, year,
                                                writing_output_file,
                                                output_tables,
                                                output_graphs,
                                                dump_varset,
                                                output_dump,
                                                output_sqldb)
            gdiff_dict[year + 1] = gd_dict
示例#2
0
 def with_suffix(gdict, growdiff_baseline_dict, growdiff_response_dict):
     """
     Return param_base:year dictionary having only suffix parameters.
     """
     if bool(growdiff_baseline_dict) or bool(growdiff_response_dict):
         gdiff_baseline = GrowDiff()
         gdiff_baseline.update_growdiff(growdiff_baseline_dict)
         gdiff_response = GrowDiff()
         gdiff_response.update_growdiff(growdiff_response_dict)
         growfactors = GrowFactors()
         gdiff_baseline.apply_to(growfactors)
         gdiff_response.apply_to(growfactors)
     else:
         gdiff_baseline = None
         gdiff_response = None
         growfactors = None
     pol = Policy(gfactors=growfactors)
     pol.ignore_reform_errors()
     odict = dict()
     for param in gdict.keys():
         odict[param] = dict()
         for year in sorted(gdict[param].keys()):
             odict[param][year] = dict()
             for suffix in gdict[param][year].keys():
                 plist = getattr(pol, param).tolist()
                 dvals = plist[int(year) - Policy.JSON_START_YEAR]
                 odict[param][year] = [dvals]
                 idx = Policy.JSON_REFORM_SUFFIXES[suffix]
                 odict[param][year][0][idx] = gdict[param][year][suffix]
                 udict = {int(year): {param: odict[param][year]}}
                 pol.implement_reform(udict,
                                      print_warnings=False,
                                      raise_errors=False)
     del gdiff_baseline
     del gdiff_response
     del growfactors
     del pol
     return odict
示例#3
0
 def with_suffix(gdict, growdiff_baseline_dict, growdiff_response_dict):
     """
     Return param_base:year dictionary having only suffix parameters.
     """
     if bool(growdiff_baseline_dict) or bool(growdiff_response_dict):
         gdiff_baseline = GrowDiff()
         gdiff_baseline.update_growdiff(growdiff_baseline_dict)
         gdiff_response = GrowDiff()
         gdiff_response.update_growdiff(growdiff_response_dict)
         growfactors = GrowFactors()
         gdiff_baseline.apply_to(growfactors)
         gdiff_response.apply_to(growfactors)
     else:
         gdiff_baseline = None
         gdiff_response = None
         growfactors = None
     pol = Policy(gfactors=growfactors)
     pol.ignore_reform_errors()
     odict = dict()
     for param in gdict.keys():
         odict[param] = dict()
         for year in sorted(gdict[param].keys()):
             odict[param][year] = dict()
             for suffix in gdict[param][year].keys():
                 plist = getattr(pol, param).tolist()
                 dvals = plist[int(year) - Policy.JSON_START_YEAR]
                 odict[param][year] = [dvals]
                 idx = Policy.JSON_REFORM_SUFFIXES[suffix]
                 odict[param][year][0][idx] = gdict[param][year][suffix]
                 udict = {int(year): {param: odict[param][year]}}
                 pol.implement_reform(udict,
                                      print_warnings=False,
                                      raise_errors=False)
     del gdiff_baseline
     del gdiff_response
     del growfactors
     del pol
     return odict
def test_json_file_contents(tests_path, fname):
    """
    Check contents of JSON parameter files in Tax-Calculator/taxcalc directory.
    """
    first_year = Policy.JSON_START_YEAR
    last_known_year = Policy.LAST_KNOWN_YEAR  # for indexed parameter values
    known_years = set(range(first_year, last_known_year + 1))
    long_params = [
        'II_brk1', 'II_brk2', 'II_brk3', 'II_brk4', 'II_brk5', 'II_brk6',
        'II_brk7', 'PT_brk1', 'PT_brk2', 'PT_brk3', 'PT_brk4', 'PT_brk5',
        'PT_brk6', 'PT_brk7', 'PT_qbid_taxinc_thd', 'ALD_BusinessLosses_c',
        'STD', 'II_em', 'II_em_ps', 'AMT_em', 'AMT_em_ps', 'AMT_em_pe',
        'ID_ps', 'ID_AllTaxes_c'
    ]
    # for TCJA-reverting long_params
    long_known_years = set(range(first_year, last_known_year + 1))
    long_known_years.add(2026)
    # check elements in each parameter sub-dictionary
    failures = ''
    with open(os.path.join(tests_path, "..", fname)) as f:
        allparams = json.loads(f.read())
    for pname in allparams:
        if pname == "schema":
            continue
        # check that param contains required keys
        param = allparams[pname]
        # check that indexable and indexed are False in many files
        if fname != 'policy_current_law.json':
            assert param.get('indexable', False) is False
            assert param.get('indexed', False) is False
        # check that indexable is True when indexed is True
        if param.get('indexed', False) and not param.get('indexable', False):
            msg = 'param:<{}>; indexed={}; indexable={}'
            fail = msg.format(pname, param.get('indexed', False),
                              param.get('indexable', False))
            failures += fail + '\n'
        # check that indexable param has value_type float
        if param.get('indexable', False) and param['type'] != 'float':
            msg = 'param:<{}>; type={}; indexable={}'
            fail = msg.format(pname, param['type'],
                              param.get('indexable', False))
            failures += fail + '\n'
        # ensure that indexable is False when value_type is not real
        if param.get('indexable', False) and param['type'] != 'float':
            msg = 'param:<{}>; indexable={}; type={}'
            fail = msg.format(pname, param.get('indexable', False),
                              param['value_type'])
            failures += fail + '\n'
    if fname == "consumption.json":
        o = Consumption()
    elif fname == "policy_current_law.json":
        o = Policy()
    elif fname == "growdiff.json":
        o = GrowDiff()
    param_list = []
    for k in o:
        if k[0].isupper():  # find parameters by case of first letter
            param_list.append(k)
    for param in param_list:
        for y in known_years:
            o.set_year(y)
            if np.isnan(getattr(o, param)).any():
                msg = 'param:<{}>; not found in year={}'
                fail = msg.format(param, y)
                failures += fail + '\n'
    if failures:
        raise ValueError(failures)
示例#5
0
    def init(self, input_data, tax_year, baseline, reform, assump,
             growdiff_growmodel, aging_input_data, exact_calculations):
        """
        TaxCalcIO class post-constructor method that completes initialization.

        Parameters
        ----------
        First five are same as the first five of the TaxCalcIO constructor:
            input_data, tax_year, baseline, reform, assump.

        growdiff_growmodel: GrowDiff object or None
            growdiff_growmodel GrowDiff object is used only in the
            TaxCalcIO.growmodel_analysis method.

        aging_input_data: boolean
            whether or not to extrapolate Records data from data year to
            tax_year.

        exact_calculations: boolean
            specifies whether or not exact tax calculations are done without
            any smoothing of "stair-step" provisions in the tax law.
        """
        # pylint: disable=too-many-arguments,too-many-locals
        # pylint: disable=too-many-statements,too-many-branches
        self.errmsg = ''
        # get policy parameter dictionary from --baseline file
        basedict = Calculator.read_json_param_objects(baseline, None)
        # get assumption sub-dictionaries
        paramdict = Calculator.read_json_param_objects(None, assump)
        # get policy parameter dictionaries from --reform file(s)
        policydicts = list()
        if self.specified_reform:
            reforms = reform.split('+')
            for ref in reforms:
                pdict = Calculator.read_json_param_objects(ref, None)
                policydicts.append(pdict['policy'])
            paramdict['policy'] = policydicts[0]
        # remember parameters for reform documentation
        self.param_dict = paramdict
        self.policy_dicts = policydicts
        # create Behavior object
        beh = Behavior()
        try:
            beh.update_behavior(paramdict['behavior'])
        except ValueError as valerr_msg:
            self.errmsg += valerr_msg.__str__()
        self.behavior_has_any_response = beh.has_any_response()
        # create gdiff_baseline object
        gdiff_baseline = GrowDiff()
        try:
            gdiff_baseline.update_growdiff(paramdict['growdiff_baseline'])
        except ValueError as valerr_msg:
            self.errmsg += valerr_msg.__str__()
        # create GrowFactors base object that incorporates gdiff_baseline
        gfactors_base = GrowFactors()
        gdiff_baseline.apply_to(gfactors_base)
        # specify gdiff_response object
        gdiff_response = GrowDiff()
        try:
            gdiff_response.update_growdiff(paramdict['growdiff_response'])
        except ValueError as valerr_msg:
            self.errmsg += valerr_msg.__str__()
        # create GrowFactors ref object that has all gdiff objects applied
        gfactors_ref = GrowFactors()
        gdiff_baseline.apply_to(gfactors_ref)
        gdiff_response.apply_to(gfactors_ref)
        if growdiff_growmodel:
            growdiff_growmodel.apply_to(gfactors_ref)
        # create Policy objects:
        # ... the baseline Policy object
        base = Policy(gfactors=gfactors_base)
        try:
            base.implement_reform(basedict['policy'],
                                  print_warnings=False,
                                  raise_errors=False)
            self.errmsg += base.parameter_errors
        except ValueError as valerr_msg:
            self.errmsg += valerr_msg.__str__()
        # ... the reform Policy object
        if self.specified_reform:
            pol = Policy(gfactors=gfactors_ref)
            for poldict in policydicts:
                try:
                    pol.implement_reform(poldict,
                                         print_warnings=False,
                                         raise_errors=False)
                    self.errmsg += pol.parameter_errors
                except ValueError as valerr_msg:
                    self.errmsg += valerr_msg.__str__()
        else:
            pol = Policy(gfactors=gfactors_base)
        # create Consumption object
        con = Consumption()
        try:
            con.update_consumption(paramdict['consumption'])
        except ValueError as valerr_msg:
            self.errmsg += valerr_msg.__str__()
        # create GrowModel object
        self.growmodel = GrowModel()
        try:
            self.growmodel.update_growmodel(paramdict['growmodel'])
        except ValueError as valerr_msg:
            self.errmsg += valerr_msg.__str__()
        # check for valid tax_year value
        if tax_year < pol.start_year:
            msg = 'tax_year {} less than policy.start_year {}'
            msg = msg.format(tax_year, pol.start_year)
            self.errmsg += 'ERROR: {}\n'.format(msg)
        if tax_year > pol.end_year:
            msg = 'tax_year {} greater than policy.end_year {}'
            msg = msg.format(tax_year, pol.end_year)
            self.errmsg += 'ERROR: {}\n'.format(msg)
        # any errors imply cannot proceed with calculations
        if self.errmsg:
            return
        # set policy to tax_year
        pol.set_year(tax_year)
        base.set_year(tax_year)
        # read input file contents into Records objects
        if aging_input_data:
            if self.cps_input_data:
                recs = Records.cps_constructor(
                    gfactors=gfactors_ref,
                    exact_calculations=exact_calculations)
                recs_base = Records.cps_constructor(
                    gfactors=gfactors_base,
                    exact_calculations=exact_calculations)
            else:  # if not cps_input_data but aging_input_data
                recs = Records(data=input_data,
                               gfactors=gfactors_ref,
                               exact_calculations=exact_calculations)
                recs_base = Records(data=input_data,
                                    gfactors=gfactors_base,
                                    exact_calculations=exact_calculations)
        else:  # input_data are raw data that are not being aged
            recs = Records(data=input_data,
                           gfactors=None,
                           exact_calculations=exact_calculations,
                           weights=None,
                           adjust_ratios=None,
                           start_year=tax_year)
            recs_base = copy.deepcopy(recs)
        if tax_year < recs.data_year:
            msg = 'tax_year {} less than records.data_year {}'
            msg = msg.format(tax_year, recs.data_year)
            self.errmsg += 'ERROR: {}\n'.format(msg)
        # create Calculator objects
        self.calc = Calculator(policy=pol,
                               records=recs,
                               verbose=True,
                               consumption=con,
                               behavior=beh,
                               sync_years=aging_input_data)
        self.calc_base = Calculator(policy=base,
                                    records=recs_base,
                                    verbose=False,
                                    consumption=con,
                                    sync_years=aging_input_data)
    def init(self, input_data, tax_year, baseline, reform, assump,
             aging_input_data, exact_calculations):
        """
        TaxCalcIO class post-constructor method that completes initialization.

        Parameters
        ----------
        First five are same as the first five of the TaxCalcIO constructor:
            input_data, tax_year, baseline, reform, assump.

        aging_input_data: boolean
            whether or not to extrapolate Records data from data year to
            tax_year.

        exact_calculations: boolean
            specifies whether or not exact tax calculations are done without
            any smoothing of "stair-step" provisions in the tax law.
        """
        # pylint: disable=too-many-arguments,too-many-locals
        # pylint: disable=too-many-statements,too-many-branches
        self.errmsg = ''
        # get policy parameter dictionary from --baseline file
        basedict = Calculator.read_json_param_objects(baseline, None)
        # get assumption sub-dictionaries
        paramdict = Calculator.read_json_param_objects(None, assump)
        # get policy parameter dictionaries from --reform file(s)
        policydicts = list()
        if self.specified_reform:
            reforms = reform.split('+')
            for ref in reforms:
                pdict = Calculator.read_json_param_objects(ref, None)
                policydicts.append(pdict['policy'])
            paramdict['policy'] = policydicts[0]
        # remember parameters for reform documentation
        self.param_dict = paramdict
        self.policy_dicts = policydicts
        # create gdiff_baseline object
        gdiff_baseline = GrowDiff()
        try:
            gdiff_baseline.update_growdiff(paramdict['growdiff_baseline'])
        except ValueError as valerr_msg:
            self.errmsg += valerr_msg.__str__()
        # create GrowFactors base object that incorporates gdiff_baseline
        gfactors_base = GrowFactors()
        gdiff_baseline.apply_to(gfactors_base)
        # specify gdiff_response object
        gdiff_response = GrowDiff()
        try:
            gdiff_response.update_growdiff(paramdict['growdiff_response'])
        except ValueError as valerr_msg:
            self.errmsg += valerr_msg.__str__()
        # create GrowFactors ref object that has all gdiff objects applied
        gfactors_ref = GrowFactors()
        gdiff_baseline.apply_to(gfactors_ref)
        gdiff_response.apply_to(gfactors_ref)
        # create Policy objects:
        # ... the baseline Policy object
        base = Policy(gfactors=gfactors_base)
        try:
            base.implement_reform(basedict['policy'],
                                  print_warnings=False,
                                  raise_errors=False)
            self.errmsg += base.parameter_errors
        except ValueError as valerr_msg:
            self.errmsg += valerr_msg.__str__()
        # ... the reform Policy object
        if self.specified_reform:
            pol = Policy(gfactors=gfactors_ref)
            for poldict in policydicts:
                try:
                    pol.implement_reform(poldict,
                                         print_warnings=False,
                                         raise_errors=False)
                    self.errmsg += pol.parameter_errors
                except ValueError as valerr_msg:
                    self.errmsg += valerr_msg.__str__()
        else:
            pol = Policy(gfactors=gfactors_base)
        # create Consumption object
        con = Consumption()
        try:
            con.update_consumption(paramdict['consumption'])
        except ValueError as valerr_msg:
            self.errmsg += valerr_msg.__str__()
        # check for valid tax_year value
        if tax_year < pol.start_year:
            msg = 'tax_year {} less than policy.start_year {}'
            msg = msg.format(tax_year, pol.start_year)
            self.errmsg += 'ERROR: {}\n'.format(msg)
        if tax_year > pol.end_year:
            msg = 'tax_year {} greater than policy.end_year {}'
            msg = msg.format(tax_year, pol.end_year)
            self.errmsg += 'ERROR: {}\n'.format(msg)
        # any errors imply cannot proceed with calculations
        if self.errmsg:
            return
        # set policy to tax_year
        pol.set_year(tax_year)
        base.set_year(tax_year)
        # read input file contents into Records objects
        if aging_input_data:
            if self.cps_input_data:
                recs = Records.cps_constructor(
                    gfactors=gfactors_ref,
                    exact_calculations=exact_calculations
                )
                recs_base = Records.cps_constructor(
                    gfactors=gfactors_base,
                    exact_calculations=exact_calculations
                )
            else:  # if not cps_input_data but aging_input_data
                recs = Records(
                    data=input_data,
                    gfactors=gfactors_ref,
                    exact_calculations=exact_calculations
                )
                recs_base = Records(
                    data=input_data,
                    gfactors=gfactors_base,
                    exact_calculations=exact_calculations
                )
        else:  # input_data are raw data that are not being aged
            recs = Records(data=input_data,
                           gfactors=None,
                           exact_calculations=exact_calculations,
                           weights=None,
                           adjust_ratios=None,
                           start_year=tax_year)
            recs_base = copy.deepcopy(recs)
        if tax_year < recs.data_year:
            msg = 'tax_year {} less than records.data_year {}'
            msg = msg.format(tax_year, recs.data_year)
            self.errmsg += 'ERROR: {}\n'.format(msg)
        # create Calculator objects
        self.calc = Calculator(policy=pol, records=recs,
                               verbose=True,
                               consumption=con,
                               sync_years=aging_input_data)
        self.calc_base = Calculator(policy=base, records=recs_base,
                                    verbose=False,
                                    consumption=con,
                                    sync_years=aging_input_data)