In [1]:
###### from datetime import date

from openfisca_france import init_country
from openfisca_france.model.base import *

Adaptation pour faciliter l'usage de ce notebook

Ce correctif permet de redéfinir plusieurs fois la même variable sans provoquer d'erreur.


In [2]:
import functools

from openfisca_core.formulas import make_formula_decorator, neutralize_column
from openfisca_france.entities import entity_class_by_symbol

reference_formula = make_formula_decorator(entity_class_by_symbol = entity_class_by_symbol, update = True)
reference_input_variable = functools.partial(reference_input_variable, update = True)

Système socio-fiscal


In [3]:
TaxBenefitSystem = init_country()
tax_benefit_system = TaxBenefitSystem()

In [4]:
from openfisca_core import reforms

In [5]:
ReformeRevenuDeBase = reforms.make_reform(
    key = 'revenu_de_base_enfants',
    name = u"Réforme Revenu de base enfants",
    reference = tax_benefit_system,
    )

Réforme : 1. Revenu de base enfant


In [6]:
'''
La redistribution monétaire en faveur des familles combine 8 mécanismes principaux, sous conditions de ressources :
1- Allocations familiales – AF (de 0 à 19 ou 20 ans)
2- Majoration pour âge des AF (à partir de 14 ans)
3- Complément familial – CF (pour un 3ème enfant)
4- Allocation de rentrée scolaire – ARS (de 6 à 18 ans)
5- Allocation de base de la PAJE (de 0 à 2 ans)
6- Supplément de RSA calculé par enfant (déduit AF, CF, PAJE)
7- Réduction d’impôt pour scolarisation des enfants 
8- Diminution de l’impôt par le quotient familial – QF (plafonné)

La réforme simulée ici permet de remplacer ces 8 dispositifs par la combinaison de :
A - un Revenu de Base Enfant, pour chaque enfant de 0 à l'anniversaire de ses 14 ans
B - un Revenu de Base Jeune, de 14 jusqu'à l'anniversaire de ses 25 ans

Divers montants de ces RdB doivent pouvoir être testés.
Un repère pour 2015 est 185€ pour le RdB Enfant / 230€ pour le RdB Jeune
'''


Out[6]:
"\nLa redistribution mon\xc3\xa9taire en faveur des familles combine 8 m\xc3\xa9canismes principaux, sous conditions de ressources :\n1- Allocations familiales \xe2\x80\x93 AF (de 0 \xc3\xa0 19 ou 20 ans)\n2- Majoration pour \xc3\xa2ge des AF (\xc3\xa0 partir de 14 ans)\n3- Compl\xc3\xa9ment familial \xe2\x80\x93 CF (pour un 3\xc3\xa8me enfant)\n4- Allocation de rentr\xc3\xa9e scolaire \xe2\x80\x93 ARS (de 6 \xc3\xa0 18 ans)\n5- Allocation de base de la PAJE (de 0 \xc3\xa0 2 ans)\n6- Suppl\xc3\xa9ment de RSA calcul\xc3\xa9 par enfant (d\xc3\xa9duit AF, CF, PAJE)\n7- R\xc3\xa9duction d\xe2\x80\x99imp\xc3\xb4t pour scolarisation des enfants \n8- Diminution de l\xe2\x80\x99imp\xc3\xb4t par le quotient familial \xe2\x80\x93 QF (plafonn\xc3\xa9)\n\nLa r\xc3\xa9forme simul\xc3\xa9e ici permet de remplacer ces 8 dispositifs par la combinaison de :\nA - un Revenu de Base Enfant, pour chaque enfant de 0 \xc3\xa0 l'anniversaire de ses 14 ans\nB - un Revenu de Base Jeune, de 14 jusqu'\xc3\xa0 l'anniversaire de ses 25 ans\n\nDivers montants de ces RdB doivent pouvoir \xc3\xaatre test\xc3\xa9s.\nUn rep\xc3\xa8re pour 2015 est 185\xe2\x82\xac pour le RdB Enfant / 230\xe2\x82\xac pour le RdB Jeune\n"

In [7]:
# 1 à 7 :

ReformeRevenuDeBase.formula(neutralize_column(tax_benefit_system.column_by_name['af_base']))    # Suppression des allocations familiales        
ReformeRevenuDeBase.formula(neutralize_column(tax_benefit_system.column_by_name['af']))    # Suppression des allocations familiales
ReformeRevenuDeBase.formula(neutralize_column(tax_benefit_system.column_by_name['cf']))    # Suppression du Complément familial
ReformeRevenuDeBase.formula(neutralize_column(tax_benefit_system.column_by_name['ars']))    # Suppression de l'allocation de rentrée scolaire
ReformeRevenuDeBase.formula(neutralize_column(tax_benefit_system.column_by_name['paje_base']))    # Suppression des allocations de base de la PAJE
ReformeRevenuDeBase.formula(neutralize_column(tax_benefit_system.column_by_name['ecpess']))    # Suppression de réduction d'impôts à titre des enfants à charge poursuivant leurs études secondaire ou supérieur. 
ReformeRevenuDeBase.formula(neutralize_column(tax_benefit_system.column_by_name['nb_enfant_rsa']))    # Neutralisation des enfants dans les calculs liés au RSA
# ReformeRevenuDeBase.formula(neutralize_column(tax_benefit_system.column_by_name['rmi_nbp']))    # Neutralisation des enfants dans les calculs liés au RSA


Out[7]:
<openfisca_core.columns.IntCol at 0x7f1942d38a90>

In [8]:
# 8 - Suppression du Quotient familial (QF)
# Le nombre de parts fiscales est recalculé en supprimant l'impact des enfants

from numpy import logical_not as not_, minimum as min_, maximum as max_

@ReformeRevenuDeBase.formula
class nbptr(SimpleFormulaColumn):
    reference = FoyersFiscaux.column_by_name['nbptr']

    # On enlève les enfants du calcul du nbptr (quotient_familial.enf*)
    
    def function(self, simulation, period):
        '''
        Nombre de parts du foyer
        'foy'
        note 1 enfants et résidence alternée (formulaire 2041 GV page 10)

        quotient_familial.conj : nb part associées au conjoint d'un couple marié ou pacsé
        quotient_familial.inv1 : nb part supp enfants invalides (I, G)
        quotient_familial.inv2 : nb part supp adultes invalides (R)
        quotient_familial.not31 : nb part supp note 3 : cases W ou G pour veuf, celib ou div
        quotient_familial.not32 : nb part supp note 3 : personne seule ayant élevé des enfants
        quotient_familial.not41 : nb part supp adultes invalides (vous et/ou conjoint) note 4
        quotient_familial.not42 : nb part supp adultes anciens combattants (vous et/ou conjoint) note 4
        quotient_familial.not6 : nb part supp note 6
        quotient_familial.isol : demi-part parent isolé (T)
        quotient_familial.edcd : enfant issu du mariage avec conjoint décédé;
        '''
        period = period.start.offset('first-of', 'month').period('year')
        nb_pac = simulation.calculate('nb_pac', period)
        marpac = simulation.calculate('marpac', period)
        celdiv = simulation.calculate('celdiv', period)
        veuf = simulation.calculate('veuf', period)
        jveuf = simulation.calculate('jveuf', period)
        nbF = simulation.calculate('nbF', period)
        nbG = simulation.calculate('nbG', period)
        nbH = simulation.calculate('nbH', period)
        nbI = simulation.calculate('nbI', period)
        nbR = simulation.calculate('nbR', period)
        nbJ = simulation.calculate('nbJ', period)
        caseP = simulation.calculate('caseP', period)
        caseW = simulation.calculate('caseW', period)
        caseG = simulation.calculate('caseG', period)
        caseE = simulation.calculate('caseE', period)
        caseK = simulation.calculate('caseK', period)
        caseN = simulation.calculate('caseN', period)
        caseF = simulation.calculate('caseF', period)
        caseS = simulation.calculate('caseS', period)
        caseL = simulation.calculate('caseL', period)
        caseT = simulation.calculate('caseT', period)
        quotient_familial = simulation.legislation_at(period.start).ir.quotient_familial

        no_pac = nb_pac == 0  # Aucune personne à charge en garde exclusive
        has_pac = not_(no_pac)
        no_alt = nbH == 0  # Aucun enfant à charge en garde alternée
        has_alt = not_(no_alt)

        # # note 2 : nombre de parts liées aux invalides (enfant + adulte)
        n2 = quotient_familial.inv1 * (nbG + nbI / 2) + quotient_familial.inv2 * nbR

        # # note 3 : Pas de personne à charge
        # - invalide
        n31a = quotient_familial.not31a * (no_pac & no_alt & caseP)
        # - ancien combatant
        n31b = quotient_familial.not31b * (no_pac & no_alt & (caseW | caseG))
        n31 = max_(n31a, n31b)
        # - personne seule ayant élevé des enfants
        n32 = quotient_familial.not32 * (no_pac & no_alt & ((caseE | caseK) & not_(caseN)))
        n3 = max_(n31, n32)
        
        # # note 4 Invalidité de la personne ou du conjoint pour les mariés ou
        # # jeunes veuf(ve)s
        n4 = max_(quotient_familial.not41 * (1 * caseP + 1 * caseF), quotient_familial.not42 * (caseW | caseS))

        # # note 5
        #  - enfant du conjoint décédé
        n51 = quotient_familial.cdcd * (caseL & ((nbF + nbJ) > 0))
        #  - enfant autre et parent isolé
        n52 = quotient_familial.isol * caseT * (((no_pac & has_alt) * ((nbH == 1) * 0.5 + (nbH >= 2))) + 1 * has_pac)
        n5 = max_(n51, n52)

        # # note 6 invalide avec personne à charge
        n6 = quotient_familial.not6 * (caseP & (has_pac | has_alt))

        # # note 7 Parent isolé
        n7 = quotient_familial.isol * caseT * ((no_pac & has_alt) * ((nbH == 1) * 0.5 + (nbH >= 2)) + 1 * has_pac)

        # # Régime des mariés ou pacsés
        m = 1 + quotient_familial.conj + n2 + n4
        
        # # veufs  hors jveuf
        v = 1 + n2 + n3 + n5 + n6
        
        # # celib div
        c = 1 + n2 + n3 + n6 + n7

        return period, (marpac | jveuf) * m + (veuf & not_(jveuf)) * v + celdiv * c

In [9]:
# A - Création d'un Revenu de Base Enfant

@ReformeRevenuDeBase.formula
class rdb_enf(SimpleFormulaColumn):
    column = FloatCol
    entity_class = Individus
    label = u"Revenu de Base Enfant"

    def function(self, simulation, period):
        period = period.start.offset('first-of', 'month').period('month')
        age = simulation.calculate('age')
        P = simulation.legislation_at(period.start).fam.af        
        bmaf = P.bmaf
        
        return period, (age < 14) * 0.41 * bmaf

In [10]:
# B - Création d'un Revenu de Base Jeune

@ReformeRevenuDeBase.formula
class rdb_jeu(SimpleFormulaColumn):
    column = FloatCol
    entity_class = Individus
    label = u"Revenu de Base Jeune"

    def function(self, simulation, period):
        period = period.start.offset('first-of', 'month').period('month')
        age = simulation.calculate('age')
        P = simulation.legislation_at(period.start).fam.af        
        bmaf = P.bmaf
        
        return period, (age >= 14) * (age < 25) * 0.57 * bmaf

In [11]:
# BILAN : calcul du revenu disponible en ajoutant RdB Enfant et RdB Jeune

@ReformeRevenuDeBase.formula
class revdisp(SimpleFormulaColumn):
    reference = Menages.column_by_name['revdisp']

    def function(self, simulation, period):
        '''
        Revenu disponible - ménage
        'men'
        '''
        period = period.start.offset('first-of', 'month').period('year')
        rev_trav_holder = simulation.compute('rev_trav', period)
        pen_holder = simulation.compute('pen', period)
        rev_cap_holder = simulation.compute('rev_cap', period)
        psoc_holder = simulation.compute('psoc', period)
        ppe_holder = simulation.compute('ppe', period)
        impo = simulation.calculate('impo', period)
        rdb_enfant_holder = simulation.compute_add('rdb_enf', period)
        rdb_jeune_holder = simulation.compute_add('rdb_jeu', period)

        pen = self.sum_by_entity(pen_holder)
        ppe = self.cast_from_entity_to_role(ppe_holder, role = VOUS)
        ppe = self.sum_by_entity(ppe)
        psoc = self.cast_from_entity_to_role(psoc_holder, role = CHEF)
        psoc = self.sum_by_entity(psoc)
        rev_cap = self.sum_by_entity(rev_cap_holder)
        rev_trav = self.sum_by_entity(rev_trav_holder)
        rdb_enfant = self.sum_by_entity(rdb_enfant_holder)
        rdb_jeune = self.sum_by_entity(rdb_jeune_holder)

        return period, rev_trav + pen + rev_cap + psoc + ppe + impo + rdb_enfant + rdb_jeune

Tests


In [12]:
reform = ReformeRevenuDeBase()

In [13]:
scenario = tax_benefit_system.new_scenario()
scenario.init_single_entity(
    period = 2015,
    parent1 = dict(
        birth = date(1980, 1, 1),
        salaire_imposable = 12000,
        statmarit = u'Marié',
        ),
    parent2 = dict(
        birth = date(1980, 1, 1),
        salaire_imposable = 46000,
        statmarit = u'Marié',
        ),
    enfants = [
        dict(
            birth = date(2010, 1, 1),
            ),
        dict(
            birth = date(2005, 1, 1),
            ),
        dict(
            birth = date(1999, 1, 1),
            ),
        ],
    )
simulation = scenario.new_simulation(debug = True)

In [14]:
scenario_pauvre = tax_benefit_system.new_scenario()
scenario_pauvre.init_single_entity(
    period = 2015,
    parent1 = dict(
        birth = date(1980, 1, 1),
        salaire_imposable = 0,
        statmarit = u'Marié',
        ),
    parent2 = dict(
        birth = date(1980, 1, 1),
        salaire_imposable = 0,
        statmarit = u'Marié',
        ),
    enfants = [
        dict(
            birth = date(2010, 1, 1),
            ),
        dict(
            birth = date(2005, 1, 1),
            ),
        dict(
            birth = date(1999, 1, 1),
            ),
        ],
    )
simulation_pauvre=scenario_pauvre.new_simulation(debug = True)

In [15]:
scenario_reform = reform.new_scenario()
scenario_reform.init_single_entity(
    period = 2015,
    parent1 = dict(
        birth = date(1980, 1, 1),
        salaire_imposable = 12000,
        statmarit = u'Marié',
        ),
    parent2 = dict(
        birth = date(1980, 1, 1),
        salaire_imposable = 46000,
        statmarit = u'Marié',
        ),
    enfants = [
        dict(
            birth = date(2010, 1, 1),
            ),
        dict(
            birth = date(2005, 1, 1),
            ),
        dict(
            birth = date(1999, 1, 1),
            ),
        ],
    )
reform_simulation = scenario_reform.new_simulation(debug = True)

In [16]:
scenario_reform_pauvre = reform.new_scenario()
scenario_reform_pauvre.init_single_entity(
    period = 2015,
    parent1 = dict(
        birth = date(1980, 1, 1),
        salaire_imposable = 0,
        statmarit = u'Marié',
        ),
    parent2 = dict(
        birth = date(1980, 1, 1),
        salaire_imposable = 0,
        statmarit = u'Marié',
        ),
    enfants = [
        dict(
            birth = date(2010, 1, 1),
            ),
        dict(
            birth = date(2005, 1, 1),
            ),
        dict(
            birth = date(1999, 1, 1),
            ),
        ],
    )
reform_pauvre = scenario_reform_pauvre.new_simulation(debug = True)

In [17]:
simulation.calculate('nbptr')


Out[17]:
array([ 4.], dtype=float32)

In [18]:
reform_simulation.calculate('nbptr')


Out[18]:
array([ 2.], dtype=float32)

In [19]:
simulation.calculate_add('af')


Out[19]:
array([ 4338.28369141], dtype=float32)

In [20]:
reform_simulation.calculate_add('af')


Out[20]:
array([ 0.], dtype=float32)

In [21]:
simulation.calculate_add('cf')


Out[21]:
array([ 2385.93041992], dtype=float32)

In [22]:
reform_simulation.calculate_add('cf')


Out[22]:
array([ 0.], dtype=float32)

In [23]:
simulation.calculate('ars')


Out[23]:
array([ 1126.78588867], dtype=float32)

In [24]:
reform_simulation.calculate('ars')


Out[24]:
array([ 0.], dtype=float32)

In [25]:
print simulation_pauvre.calculate_add('rsa', '2015-12')
print simulation_pauvre.calculate_add('rsa', '2015-02')


[ 844.68359375]
[ 818.98352051]

In [26]:
from openfisca_core import web_tools
print web_tools.get_trace_tool_link(scenario_pauvre, ["rsa"], api_url="http://api-test.openfisca.fr")


http://www.openfisca.fr/outils/trace?api_url=http%3A%2F%2Fapi-test.openfisca.fr&simulation=%7B%22scenarios%22%3A+%5B%7B%22period%22%3A+%222015%22%2C+%22test_case%22%3A+%7B%22familles%22%3A+%5B%7B%22id%22%3A+0%2C+%22parents%22%3A+%5B%22ind0%22%2C+%22ind1%22%5D%2C+%22enfants%22%3A+%5B%22ind2%22%2C+%22ind3%22%2C+%22ind4%22%5D%7D%5D%2C+%22foyers_fiscaux%22%3A+%5B%7B%22id%22%3A+0%2C+%22declarants%22%3A+%5B%22ind0%22%2C+%22ind1%22%5D%2C+%22personnes_a_charge%22%3A+%5B%22ind2%22%2C+%22ind3%22%2C+%22ind4%22%5D%7D%5D%2C+%22individus%22%3A+%5B%7B%22id%22%3A+%22ind0%22%2C+%22salaire_imposable%22%3A+0.0%2C+%22statmarit%22%3A+1%2C+%22birth%22%3A+%221980-01-01%22%7D%2C+%7B%22id%22%3A+%22ind1%22%2C+%22salaire_imposable%22%3A+0.0%2C+%22statmarit%22%3A+1%2C+%22birth%22%3A+%221980-01-01%22%7D%2C+%7B%22id%22%3A+%22ind2%22%2C+%22birth%22%3A+%222010-01-01%22%7D%2C+%7B%22id%22%3A+%22ind3%22%2C+%22birth%22%3A+%222005-01-01%22%7D%2C+%7B%22id%22%3A+%22ind4%22%2C+%22birth%22%3A+%221999-01-01%22%7D%5D%2C+%22menages%22%3A+%5B%7B%22id%22%3A+0%2C+%22personne_de_reference%22%3A+%22ind0%22%2C+%22conjoint%22%3A+%22ind1%22%2C+%22enfants%22%3A+%5B%22ind2%22%2C+%22ind3%22%2C+%22ind4%22%5D%7D%5D%7D%7D%5D%2C+%22variables%22%3A+%5B%22rsa%22%5D%7D

In [28]:
reform_simulation.calculate_add('rsa', '2015-10')


Out[28]:
array([ 0.], dtype=float32)

In [29]:
simulation.calculate('rmi_nbp', period = '2014-01')


Out[29]:
array([5], dtype=int32)

In [30]:
reform_simulation.calculate_add('rmi_nbp', period = '2014-01')


Out[30]:
array([5], dtype=int32)

In [31]:
reform_simulation.calculate_add('rdb_enf')


Out[31]:
array([    0.        ,     0.        ,  1998.55334473,  1998.55334473,
           0.        ], dtype=float32)

In [32]:
reform_simulation.calculate_add('rdb_jeu')


Out[32]:
array([    0.       ,     0.       ,     0.       ,     0.       ,
        2778.4765625], dtype=float32)

In [33]:
simulation.calculate('revdisp')


Out[33]:
array([ 65504.7109375], dtype=float32)

In [34]:
reform_simulation.calculate('revdisp')


Out[34]:
array([ 61659.01953125], dtype=float32)

In [35]:
simulation_pauvre.calculate('revdisp')


Out[35]:
array([ 18291.16796875], dtype=float32)

In [37]:
reform_simulation.calculate('revdisp')


Out[37]:
array([ 61659.01953125], dtype=float32)

In [38]:
simulation.calculate('pfam')


Out[38]:
array([ 7811.74511719], dtype=float32)

In [39]:
reform_simulation.calculate('pfam')


Out[39]:
array([ 0.], dtype=float32)

In [40]:
simulation_pauvre.calculate('psoc')


Out[40]:
array([ 18291.16796875], dtype=float32)

In [43]:
reform_simulation.calculate('pfam')


Out[43]:
array([ 0.], dtype=float32)

In [44]:
simulation.calculate('irpp')


Out[44]:
array([-1881.59997559], dtype=float32)

In [45]:
reform_simulation.calculate('irpp')


Out[45]:
array([-4594.79980469], dtype=float32)

Graphiques


In [ ]:
from datetime import date  # module nécessaire pour la définition des dates, dont notamment les dates de naissances
from openfisca_france.tests.base import tax_benefit_system




def make_couple_with_child_scenario(nombre_enfants = 0, year = None, tax_benefit_system = tax_benefit_system,
                                    axes_variable = 'salaire_de_base',  ax_variable_max = 150000, count = 5000):
    enfant = [dict(
        birth = date(2005, 1, 1),
        )]
    enfants = enfant * nombre_enfants
    scenario = tax_benefit_system.new_scenario().init_single_entity(
        axes = [[
            dict(
                count = count,
                min = 0,
                max = ax_variable_max,
                name = axes_variable,
                period = year-2,
                ),
            dict(
                count = count,
                min = 0,
                max = ax_variable_max,
                name = axes_variable,
                period = year-1,
                ),
            dict(
                count = count,
                min = 0,
                max = ax_variable_max,
                name = axes_variable,
                period = year,
                ),
            ]],
        period = year,
        parent1 = dict(
            birth = date(1980, 1, 1),
            statmarit = 5, #pacsés
            ),
        parent2 = dict(
            birth = date(1980, 1, 1),
            statmarit = 5,
            ),
        enfants = enfants,
        menage = dict(
            loyer = 1000,
            statut_occupation = 4,
            ),
        )
    return scenario

In [ ]:
scenario_couple_avec_1_enfant = make_couple_with_child_scenario(1, 2014)
simulation_couple_avec_1_enfant = scenario_couple_avec_1_enfant.new_simulation()

scenario_couple_avec_2_enfants = make_couple_with_2_children_scenario(2, 2014)
simulation_couple_avec_2_enfants = scenario_couple_avec_2_enfants.new_simulation()

scenario_couple_avec_3_enfants = make_couple_with_3_children_scenario(3, 2014)
simulation_couple_avec_3_enfants = scenario_couple_avec_3_enfants.new_simulation()

scenario_couple_avec_4_enfants = make_couple_with_4_children_scenario(4, 2014)
simulation_couple_avec_4_enfants = scenario_couple_avec_4_enfants.new_simulation()

scenario_couple_avec_5_enfants = make_couple_with_5_children_scenario(5, 2014)
simulation_couple_avec_5_enfants = scenario_couple_avec_5_enfants.new_simulation()

In [ ]:
salaire_net = simulation_couple_sans_enfants.calculate_add("salaire_net")
salaire_de_base = simulation_couple_sans_enfants.calculate_add("salaire_de_base")

In [ ]: