Exemple de calcul de l'impôt fédéral ------------------------------------ Importation du package ^^^^^^^^^^^^^^^^^^^^^^  .. code:: ipython3 import srd Initialisation d’un ménage ^^^^^^^^^^^^^^^^^^^^^^^^^^ On doit d’abord initialiser un ménage. Ici nous supposerons un couple avec deux membres ayant tous les deux 45 ans et des revenus de travail de 50 000$ et 25 000$, respectivement. .. code:: ipython3 jean = srd.Person(age=45,earn=50e3) pauline = srd.Person(age=45,earn=25e3) On les insère dans un ménage vivant au Québec. .. code:: ipython3 hh = srd.Hhold(jean,pauline,prov='qc') On peut voir le profil de chacun des membres du ménage en utilisant *vars()*: .. code:: ipython3 vars(jean) .. parsed-literal:: {'age': 45, 'male': True, 'inc_earn': 50000.0, 'inc_self_earn': 0, 'inc_work_month': [4166.666666666667, 4166.666666666667, 4166.666666666667, 4166.666666666667, 4166.666666666667, 4166.666666666667, 4166.666666666667, 4166.666666666667, 4166.666666666667, 4166.666666666667, 4166.666666666667, 4166.666666666667], 'prev_inc_work': 50000.0, 'inc_rpp': 0, 'inc_cpp': 0, 'net_cap_gains': 0, 'prev_cap_losses': 0, 'cap_gains_exempt': 0, 'inc_othtax': 0, 'inc_othntax': 0, 'div_elig': 0, 'div_other_can': 0, 'inc_rrsp': 0, 'con_rrsp': 0, 'con_non_rrsp': 0, 'con_rpp': 0, 'union_dues': 0, 'donation': 0, 'gift': 0, 'years_can': 27, 'disabled': False, 'widow': False, 'med_exp': 0, 'ndays_chcare_k1': 0, 'ndays_chcare_k2': 0, 'asset': 0, 'months_crb': 0, 'months_ei': 0, 'oas_years_post': 0, 'months_cesb': 0, 'months_cerb': 0, 'pub_drug_insurance': False, 'tax_shield': False, 'student': False, 'essential_worker': False, 'emp_temp_constraints': False, 'hours_month': None, 'dep_senior': False, 'home_support_cost': 0, 'pension_split': 0, 'pension_split_qc': 0, 'pension_deduction': 0, 'pension_deduction_qc': 0, 'inc_oas': 0, 'inc_gis': 0, 'rent': 0, 'prop_tax': 0, 'inc_ei': 0, 'inc_sa': 0, 'allow_couple': 0, 'allow_surv': 0, 'inc_cerb': 0, 'inc_cesb': 0, 'inc_crb': 0, 'inc_iprew': 0, 'covid': None, 'after_tax_inc': None, 'disp_inc': None, 'fed_return': None, 'prov_return': None, 'payroll': None, 'prov_contrib': None, 'max_split': 0.0} Calcul de l’impôt fédéral ^^^^^^^^^^^^^^^^^^^^^^^^^ On doit d’abord créer un formulaire d’impôt pour une année en particulier. .. code:: ipython3 from srd import federal fed_form = federal.form(2022) On peut voir les différents paramètres du système fiscal en utilisant encore *vars()*: .. code:: ipython3 vars(fed_form) .. parsed-literal:: {'div_elig_factor': 1.38, 'div_other_can_factor': 1.15, 'div_elig_cred_rate': 0.150198, 'div_other_can_cred_rate': 0.090313, 'cap_gains_rate': 0.5, 'qpip_deduc_rate': 0.43786, 'basic_amount_poor': 14398.0, 'basic_amount_rich': 12719.0, 'age_cred_amount': 7898.0, 'min_age_cred': 65, 'age_cred_exempt': 39826.0, 'age_cred_claw_rate': 0.15, 'empl_cred_max': 1287.0, 'pension_cred_amount': 2000.0, 'pension_cred_min_age_split': 65, 'disability_cred_amount': 8870.0, 'med_exp_nr_cred_max_age': 18, 'med_exp_nr_cred_max_claw': 2479.0, 'med_exp_nr_cred_rate': 0.03, 'donation_frac_net': 0.75, 'donation_low_cut': 200.0, 'donation_high_cut': 216511.0, 'donation_low_rate': 0.15, 'donation_med_rate': 0.29, 'donation_high_rate': 0.33, 'rate_non_ref_tax_cred': 0.15, 'rate_abatment_qc': 0.165, 'ccb_young': 6997.0, 'ccb_old': 5903.0, 'ccb_max_num_ch': 4, 'ccb_cutoff_1': 32797.0, 'ccb_cutoff_2': 71060.0, 'ccb_rate_1_1ch': 0.07, 'ccb_rate_1_2ch': 0.135, 'ccb_rate_1_3ch': 0.19, 'ccb_rate_1_4ch': 0.23, 'ccb_rate_2_1ch': 0.032, 'ccb_rate_2_2ch': 0.057, 'ccb_rate_2_3ch': 0.08, 'ccb_rate_2_4ch': 0.095, 'med_exp_rate': 0.25, 'med_exp_claw_rate': 0.05, 'med_exp_claw_cutoff': 29129.0, 'med_exp_max': 1316.0, 'med_exp_min_work_inc': 3841.0, 'gst_cred_claw_rate': 0.05, 'gst_cred_claw_cutoff': 39826.0, 'gst_cred_base': 459.0, 'gst_cred_other': 241.5, 'gst_cred_rate': 0.02, 'gst_cred_base_amount': 9919.0, 'gst_covid_single': 400.0, 'gst_covid_couple': 600.0, 'chcare_young': 8000.0, 'chcare_old': 5000.0, 'chcare_rate_inc': 0.66666, 'ei_max_net_inc': 70375.0, 'ei_rate_repay': 0.3, 'ded_qpp_rate': 0.052632, 'ded_qpp_exempt': 3500, 'ded_qpp_claw_rate': 0.03, 'nrtc_spouse_dis': 2357, 'dep_disa_amount': 2985, 'base_single': 2400, 'base_couple': 3600, 'rate_single_dep': 0.2, 'rate': 0.373, 'rate_couple_dep': 0.239, 'max_single': 3277.92, 'max_single_dep': 1757.59, 'max_couple': 5120.45, 'max_couple_dep': 3280.93, 'exempt_single': 12683.06, 'exempt_single_dep': 12700.5, 'exempt_couple': 19457.77, 'exempt_couple_dep': 19508.32, 'exempt_second_earner': 14000, 'claw_rate': 0.2, 'dis_base': 1200, 'dis_max': 738.31, 'dis_rate_single': 0.4, 'dis_rate_couple': 0.2, 'dis_exempt_single': 29072.64, 'dis_exempt_single_dep': 21488.47, 'dis_exempt_couple': 45060.02, 'dis_exempt_couple_dep': 35912.95, 'dis_claw_rate': 0.2, 'dis_couple_claw_rate': 0.1, 'l_brackets': [0.0, 50197.0, 100392.0, 155625.0, 221708.0], 'l_rates': [0.15, 0.205, 0.26, 0.29, 0.33], 'l_constant': [0.0, 7530.0, 17820.0, 32180.0, 51344.0], 'witb_params': {'on': {'base_single': 3000, 'base_couple': 3000, 'rate_single_dep': 0.27, 'rate': 0.27, 'rate_couple_dep': 0.27, 'max_single': 1428.48, 'max_single_dep': 1428.48, 'max_couple': 2460.67, 'max_couple_dep': 2460.67, 'exempt_single': 23494.66, 'exempt_single_dep': 26805.25, 'exempt_couple': 26805.25, 'exempt_couple_dep': 26805.25, 'claw_rate': 0.12, 'dis_base': 1150, 'dis_max': 737.28, 'dis_rate_single': 0.27, 'dis_rate_couple': 0.27, 'dis_exempt_single': 33017.86, 'dis_exempt_single_dep': 43209.73, 'dis_exempt_couple': 43209.73, 'dis_exempt_couple_dep': 43209.73, 'dis_claw_rate': 0.15, 'dis_couple_claw_rate': 0.075}, 'qc': {'base_single': 2400, 'base_couple': 3600, 'rate_single_dep': 0.2, 'rate': 0.373, 'rate_couple_dep': 0.239, 'max_single': 3277.92, 'max_single_dep': 1757.59, 'max_couple': 5120.45, 'max_couple_dep': 3280.93, 'exempt_single': 12683.06, 'exempt_single_dep': 12700.5, 'exempt_couple': 19457.77, 'exempt_couple_dep': 19508.32, 'exempt_second_earner': 14000, 'claw_rate': 0.2, 'dis_base': 1200, 'dis_max': 738.31, 'dis_rate_single': 0.4, 'dis_rate_couple': 0.2, 'dis_exempt_single': 29072.64, 'dis_exempt_single_dep': 21488.47, 'dis_exempt_couple': 45060.02, 'dis_exempt_couple_dep': 35912.95, 'dis_claw_rate': 0.2, 'dis_couple_claw_rate': 0.1}}} On remplit le formulaire d’impôt à l’aide de la fonction *tax()*. .. code:: ipython3 from srd import tax tax_form = tax(2022) tax_form.compute(hh) On peut visualiser un formulaire d’impôt sommaire qui est rattaché à chaque personne: .. code:: ipython3 jean.fed_return .. parsed-literal:: {'gross_income': 50000.0, 'deductions_gross_inc': 348.75, 'net_income': 49651.25, 'deductions_net_inc': 0.0, 'taxable_income': 49651.25, 'gross_tax_liability': 7447.6875, 'non_refund_credits': 2856.45, 'refund_credits': 757.5541875, 'net_tax_liability': 3833.6833125000003} .. code:: ipython3 pauline.fed_return .. parsed-literal:: {'gross_income': 25000.0, 'deductions_gross_inc': 161.25, 'net_income': 24838.75, 'deductions_net_inc': 0.0, 'taxable_income': 24838.75, 'gross_tax_liability': 3725.8125, 'non_refund_credits': 2590.4249999999997, 'refund_credits': 187.33893750000004, 'net_tax_liability': 948.0485625000002} On peut ajouter des enfants au ménage à l'aide de la fonction *add_dependent()*. .. code:: ipython3 emma = srd.Dependent(age=4, child_care=2000, med_exp=500) alex = srd.Dependent(age=14, school=4000) hh.add_dependent(emma,alex) On peut ensuite calculer le nouveau formulaire d’impôt pour les deux adultes de la famille. .. code:: ipython3 tax_form.compute(hh) jean.fed_return .. parsed-literal:: {'gross_income': 50000.0, 'deductions_gross_inc': 348.75, 'net_income': 49651.25, 'deductions_net_inc': 0.0, 'taxable_income': 49651.25, 'gross_tax_liability': 7447.6875, 'non_refund_credits': 2856.45, 'refund_credits': 4584.0466875, 'net_tax_liability': 7.190812499999993} .. code:: ipython3 pauline.fed_return .. parsed-literal:: {'gross_income': 25000.0, 'deductions_gross_inc': 2161.25, 'net_income': 22838.75, 'deductions_net_inc': 0.0, 'taxable_income': 22838.75, 'gross_tax_liability': 3425.8125, 'non_refund_credits': 2590.4249999999997, 'refund_credits': 3964.3314375, 'net_tax_liability': -3128.9439374999997} On peut voir les différents attributs du ménage en utilisant encore *vars()*: .. code:: ipython3 vars(hh) .. parsed-literal:: {'sp': [, ], 'couple': True, 'prev_fam_net_inc_prov': None, 'prov': 'qc', 'dep': [, ], 'nkids_0_6': 1, 'nkids_7_16': 1, 'nkids_0_17': 2, 'nkids_0_18': 2, 'n_adults_in_hh': 2, 'elig_split': False, 'sa_elig_asset': True, 'nkids_0_5': 1, 'nkids_6_17': 1} Expériences ^^^^^^^^^^^ On peut faire des expériences assez complexes. Une première consisterait par exemple à regarder l’impôt fédéral payé si on augmente les revenus de travail par petites tranches. .. code:: ipython3 import numpy as np from matplotlib import pyplot as plt earns = np.linspace(10e3,200e3,100) atrs = [] for earn in earns: jean = srd.Person(age=45,earn=earn) hh = srd.Hhold(jean, prov='qc') tax_form.compute(hh) atrs.append(jean.fed_return['net_tax_liability']/jean.fed_return['gross_income']) plt.figure() plt.plot(earns,atrs) plt.xlabel('niveau de revenu de travail') plt.ylabel('taux moyen imposition effectif') plt.show() .. image:: output_ex1.png On peut aussi faire une expérience dans laquelle on change un paramètre du système d’imposition. Supposons par exemple qu’on augmente le montant de base: .. code:: ipython3 base = np.linspace(1.0,1.5,10) atrs = [] bases = [] jean.inc_earn = 50e3 base_amount = tax_form.federal.basic_amount_poor for b in base: tax_form.federal.basic_amount_poor = base_amount * b bases.append(tax_form.federal.basic_amount_poor) tax_form.compute(hh) atrs.append(jean.fed_return['net_tax_liability']/jean.fed_return['gross_income']) plt.figure() plt.plot(bases,atrs) plt.xlabel('montant de base') plt.ylabel('taux moyen imposition effectif') plt.show() .. image:: output_ex2.png