Skip to main content
Sign in
Snippets Groups Projects
Commit 2508eb49 authored by benoit-cty's avatar benoit-cty
Browse files

graph cdhr

parent a61223fa
No related branches found
No related tags found
1 merge request!140Mémo CDHR
Pipeline #17723 passed
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
# CDHR : Contribution Diférentielle temporaire sur les très Hauts Revenus # CDHR : Contribution Diférentielle temporaire sur les très Hauts Revenus
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
Cette nouvelle contribution est introduite page 35 du PLF 2025. Elle vise à atteindre un taux moyen d'imposition minimal de 20% pour les revenus supérieurs à 250 000 euros pour une personne seule et 500 000 euros pour un couple. Elle est calculée en fonction de la différence entre le taux moyen d'imposition et ce que le contribuable aurait eu à payer avec un taux moyen de 20%. Cette nouvelle contribution est introduite page 35 du PLF 2025. Elle vise à atteindre un taux moyen d'imposition minimal de 20% pour les revenus supérieurs à 250 000 euros pour une personne seule et 500 000 euros pour un couple. Elle est calculée en fonction de la différence entre le taux moyen d'imposition et ce que le contribuable aurait eu à payer avec un taux moyen de 20%.
L'assiette prévue est le revenu fiscal de référence plutôt que le revenu net imposable. L'assiette prévue est le revenu fiscal de référence plutôt que le revenu net imposable.
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
```{mermaid} ```{mermaid}
flowchart TD flowchart TD
Assiette_CDHR[RFR retraité = RFR] Assiette_CDHR[RFR retraité = RFR]
X[Début] --> F{"Eligible à la CDHR ?<br/>(rfr > 250 k€ célib ou 500 k€ couple)"} X[Début] --> F{"Eligible à la CDHR ?<br/>(rfr > 250 k€ célib ou 500 k€ couple)"}
F -->|NON| Z[pas de CDHR] F -->|NON| Z[pas de CDHR]
F -->|OUI| decote{"Eligible à décote ?<br/>(rfr < 330 k€ célib, 660 k€ couple)"} F -->|OUI| decote{"Eligible à décote ?<br/>(rfr < 330 k€ célib, 660 k€ couple)"}
impot_cible_sans_decote["impôt cible sans décote = RFR retraité * 20%"] impot_cible_sans_decote["impôt cible sans décote = RFR retraité * 20%"]
decote --> |NON| cdhr_pas_decote["décote = 0"] decote --> |NON| cdhr_pas_decote["décote = 0"]
decote --> |OUI| cdhr_decote["décote = impôt cible sans décote - 82.5% de la différence entre RFR et seuil décote"] decote --> |OUI| cdhr_decote["décote = impôt cible sans décote - 82.5% de la différence entre RFR et seuil décote"]
impot_cible_sans_decote --> cdhr_decote impot_cible_sans_decote --> cdhr_decote
cdhr_pas_decote --> impot_cible["impôt cible = 20% du RFR retraité - décote"] cdhr_pas_decote --> impot_cible["impôt cible = 20% du RFR retraité - décote"]
cdhr_decote --> impot_cible cdhr_decote --> impot_cible
impot_avant_creation_cdhr["impot_avant_creation_cdhr = impôt_net + contribution_exceptionnelle_hauts_revenus + prelevement_forfaitaire_liberatoire"] impot_avant_creation_cdhr["impot_avant_creation_cdhr = impôt_net + contribution_exceptionnelle_hauts_revenus + prelevement_forfaitaire_liberatoire"]
majoration["Majoration de 1 500 € par enfant et de 12 500€ pour un couple"] majoration["Majoration de 1 500 € par enfant et de 12 500€ pour un couple"]
impot_avant_creation_cdhr --> montant_cdhr["CDHR = max(<br/>(impôt cible + majoration) - impot_avant_creation_cdhr<br/>, 0)"] impot_avant_creation_cdhr --> montant_cdhr["CDHR = max(<br/>(impôt cible + majoration) - impot_avant_creation_cdhr<br/>, 0)"]
majoration --> montant_cdhr majoration --> montant_cdhr
impot_cible --> montant_cdhr impot_cible --> montant_cdhr
``` ```
%% Cell type:code id: tags:
``` python
from openfisca_france import FranceTaxBenefitSystem
from openfisca_france_reforms.plf_plfss_2025 import PlfPlfss2025
from openfisca_core.simulations import SimulationBuilder
from openfisca_core import periods
from openfisca_france.model.base import Reform
from openfisca_france.scenarios import init_single_entity
import plotly.graph_objects as go
```
%% Cell type:code id: tags:
``` python
plf_tbs = PlfPlfss2025(FranceTaxBenefitSystem())
```
%% Cell type:code id: tags:
``` python
def plot(
revenus,
irpp_economique_bareme,
irpp_economique_pfu,
contribution_differentielle_hauts_revenus_bareme,
contribution_differentielle_hauts_revenus_pfu,
title="Titre",
):
fig = go.Figure()
fig.add_trace(
go.Scatter(
x=revenus,
y=irpp_economique_bareme,
name="Impôt sur le revenu avec option au barème, avant CDHR",
)
)
fig.add_trace(
go.Scatter(
x=revenus,
y=irpp_economique_pfu,
name="Impôt sur le revenu au PFU, avant CDHR",
)
)
fig.add_trace(
go.Scatter(
x=revenus,
y=contribution_differentielle_hauts_revenus_bareme,
name="Impôt sur le revenu avec option au barème, avec CDHR",
)
)
fig.add_trace(
go.Scatter(
x=revenus,
y=contribution_differentielle_hauts_revenus_pfu,
name="Impôt sur le revenu au PFU, avec CDHR",
)
)
fig.update_layout(
xaxis=dict(
title="Revenus distribués éligibles à l’abattement de 40 % (case 2DC)",
# tickmode="linear",
),
yaxis=dict(
title="Montant du prélèvement hors cotisations sociales"
), # , rangemode="tozero"
title=title,
)
# _ = fig.add_vline(x=250_000, line_dash="dash", line_color="red")
# Make the figure bigge in height
fig.update_layout(
height=800,
width=1000,
)
return fig
```
%% Cell type:code id: tags:
``` python
# @title Graphique de l'évolution { run: "auto" }
# @markdown Utiliser le slider pour faire varier le nombre de pas et le montant du "Taux du prélèvement forfaitaire unique (PFU), Prélèvements libératoires sur les revenus des valeurs mobilières"
nb_step = 500
# current_period = 2010 #@param {type:"slider", min:1980, max:2022, step:1}
date_naissance = "1980-01-01" # #param {type:"date"}
f2dc_max = 600_000
##@param {type:"slider", min:10000, max:1000000, step:50000}
current_period = 2024
sb = SimulationBuilder()
start = (periods.instant(current_period),)
taux_prelevement_pfu = 12.8 # @param {type:"slider", min:12.8, max:20, step:0.1}
def modify_parameters(parameters):
parameters.taxation_capital.prelevement_forfaitaire.partir_2018.taux_prelevement_forfaitaire_rev_capital_eligibles_pfu_interets_dividendes_etc.update(
value=taux_prelevement_pfu / 100, start=start
)
return parameters
class ma_reforme(Reform):
name = "Modif PFU"
def apply(self):
self.modify_parameters(modifier_function=modify_parameters)
reformed_tax_benefit_system = ma_reforme(plf_tbs)
# Avec PFU
scenario_pfu = init_single_entity(
reformed_tax_benefit_system.new_scenario(),
# Axe declaration
axes=[
[
dict( # in a dictionary
count=nb_step, # 'count' indicates the number of steps
min=0,
max=f2dc_max,
name="f2dc", # the variable that will evolve 'count' times between 'min' and 'max' values
),
# dict( # in a dictionary
# count=nb_step, # 'count' indicates the number of steps
# min=0,
# max=f2dc_max,
# name="f2op", # the variable that will evolve 'count' times between 'min' and 'max' values
# ),
]
],
period=current_period,
parent1=dict(
date_naissance=date_naissance,
),
foyer_fiscal=dict(f2op=False),
)
simulation_pfu = scenario_pfu.new_simulation()
# https://simulateur-socio-fiscal.leximpact.dev/?law=true&test_case=21&parameters=csg_revenus_capital&tab=dispositif
f2dc_pfu = simulation_pfu.calculate_add("f2dc", current_period)
prelevement_forfaitaire_unique_ir_pfu = simulation_pfu.calculate_add(
"prelevement_forfaitaire_unique_ir", current_period
)
irpp_economique_pfu = (
simulation_pfu.calculate_add("impot_revenu_restant_a_payer", current_period) * -1
)
contribution_differentielle_hauts_revenus_pfu = simulation_pfu.calculate_add(
"contribution_differentielle_hauts_revenus", current_period
)
# Avec option au barême
scenario_bareme = init_single_entity(
reformed_tax_benefit_system.new_scenario(),
# Axe declaration
axes=[
[
dict( # in a dictionary
count=nb_step, # 'count' indicates the number of steps
min=0,
max=f2dc_max,
name="f2dc", # the variable that will evolve 'count' times between 'min' and 'max' values
),
]
],
period=current_period,
parent1=dict(
date_naissance=date_naissance,
),
foyer_fiscal=dict(f2op=True),
)
simulation_bareme = scenario_bareme.new_simulation()
f2dc_bareme = simulation_bareme.calculate_add("f2dc", current_period)
# prelevements_sociaux_revenus_capital_hors_csg_crds_bareme = simulation_bareme.calculate_add("prelevements_sociaux_revenus_capital_hors_csg_crds", current_period) * -1
irpp_economique_bareme = (
simulation_bareme.calculate_add("impot_revenu_restant_a_payer", current_period) * -1
)
contribution_differentielle_hauts_revenus_bareme = simulation_pfu.calculate_add(
"contribution_differentielle_hauts_revenus", current_period
)
fig = plot(
f2dc_pfu,
irpp_economique_bareme,
irpp_economique_pfu,
irpp_economique_bareme + contribution_differentielle_hauts_revenus_bareme,
irpp_economique_pfu + contribution_differentielle_hauts_revenus_pfu,
"Impact de la Contribution différentielle sur les hauts revenus (CDHR) pour une personne seule percevant uniquement des dividendes",
)
fig.show()
```
%% Output
---------------------------------------------------------------------------
VariableNotFoundError Traceback (most recent call last)
Cell In[4], line 71
69 prelevement_forfaitaire_unique_ir_pfu = simulation_pfu.calculate_add("prelevement_forfaitaire_unique_ir", current_period)
70 irpp_economique_pfu = simulation_pfu.calculate_add("impot_revenu_restant_a_payer", current_period)* -1
---> 71 contribution_differentielle_hauts_revenus_pfu = simulation_pfu.calculate_add("contribution_differentielle_hauts_revenus", current_period)
74 # Avec option au barême
76 scenario_bareme = init_single_entity(
77 reformed_tax_benefit_system.new_scenario(),
78 # Axe declaration
(...)
93 foyer_fiscal=dict(f2op=True)
94 )
File /media/2To-nvme/dev/src/LEXIMPACT/leximpact-prepare-data/.venv/lib/python3.10/site-packages/openfisca_core/simulations/simulation.py:167, in Simulation.calculate_add(self, variable_name, period)
164 def calculate_add(self, variable_name: str, period):
165 variable: Optional[Variable]
--> 167 variable = self.tax_benefit_system.get_variable(
168 variable_name, check_existence=True
169 )
171 if variable is None:
172 raise errors.VariableNotFoundError(variable_name, self.tax_benefit_system)
File /media/2To-nvme/dev/src/LEXIMPACT/leximpact-prepare-data/.venv/lib/python3.10/site-packages/openfisca_core/taxbenefitsystems/tax_benefit_system.py:395, in TaxBenefitSystem.get_variable(self, variable_name, check_existence)
392 if not isinstance(variable, Variable) and not check_existence:
393 return variable
--> 395 raise VariableNotFoundError(variable_name, self)
VariableNotFoundError: You tried to calculate or to set a value for variable 'contribution_differentielle_hauts_revenus', but it was not found in the loaded tax and benefit system (openfisca-france@168.0.9).
Are you sure you spelled 'contribution_differentielle_hauts_revenus' correctly?
If this code used to work and suddenly does not, this is most probably linked to an update of the tax and benefit system.
Look at its changelog to learn about renames and removals and update your code. If it is an official package,
it is probably available on <https://github.com/openfisca/openfisca-france/blob/master/CHANGELOG.md>.
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
Les points à lever sont les suivants : Les points à lever sont les suivants :
- Qu'est-ce qui rentre vraiment dans les abattements de la CDHR ? - Qu'est-ce qui rentre vraiment dans les abattements de la CDHR ?
- Est-ce que c'est vraiment l'impôt sur le revenu restant à payer qui doit être pris en compte ? Faut-il tenir compte des prélèvements sociaux ? - Est-ce que c'est vraiment l'impôt sur le revenu restant à payer qui doit être pris en compte ? Faut-il tenir compte des prélèvements sociaux ?
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
... ...
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment