Tax scales#
The policyengine_core.taxscales module contains classes used to represent tax scales (parameters that are numeric functions of a variable).
TaxScaleLike#
RateTaxScaleLike#
- class policyengine_core.taxscales.rate_tax_scale_like.RateTaxScaleLike(name: Optional[str] = None, option: Any = None, unit: Any = None)#
Bases:
TaxScaleLike,ABCBase class for various types of rate-based tax scales: marginal rate, linear average rate…
- bracket_indices(tax_base: NumericalArray, factor: float = 1.0, round_decimals: Optional[int] = None) numpy.int_#
Compute the relevant bracket indices for the given tax bases.
- Parameters:
tax_base (ndarray) – Array of the tax bases.
factor (float) – Factor to apply to the thresholds.
round_decimals (int) – Decimals to keep when rounding thresholds.
- Returns:
Integer array with relevant bracket indices for the given tax bases.
For instance:
>>> tax_scale = LinearAverageRateTaxScale() >>> tax_scale.add_bracket(0, 0) >>> tax_scale.add_bracket(100, 0.1) >>> tax_base = array([0, 150]) >>> tax_scale.bracket_indices(tax_base) [0, 1]
- threshold_from_tax_base(tax_base: NumericalArray) NumericalArray#
Compute the relevant thresholds for the given tax bases.
- Param:
ndarray tax_base: Array of the tax bases.
- Returns:
Floating array with relevant thresholds for the given tax bases.
For instance:
>>> import numpy >>> from policyengine_core import taxscales >>> tax_scale = taxscales.MarginalRateTaxScale() >>> tax_scale.add_bracket(0, 0) >>> tax_scale.add_bracket(200, 0.1) >>> tax_scale.add_bracket(500, 0.25) >>> tax_base = numpy.array([450, 1_150, 10]) >>> tax_scale.threshold_from_tax_base(tax_base) array([200, 500, 0])
AbstractTaxScale#
- class policyengine_core.taxscales.abstract_tax_scale.AbstractTaxScale(name: Optional[str] = None, option: Any = None, unit: numpy.int_ = None)#
Bases:
TaxScaleLikeBase class for various types of tax scales: amount-based tax scales, rate-based tax scales…
AbstractRateTaxScale#
- class policyengine_core.taxscales.abstract_rate_tax_scale.AbstractRateTaxScale(name: Optional[str] = None, option: Any = None, unit: Any = None)#
Bases:
RateTaxScaleLikeBase class for various types of rate-based tax scales: marginal rate, linear average rate…
- bracket_indices(tax_base: NumericalArray, factor: float = 1.0, round_decimals: Optional[int] = None) numpy.int_#
Compute the relevant bracket indices for the given tax bases.
- Parameters:
tax_base (ndarray) – Array of the tax bases.
factor (float) – Factor to apply to the thresholds.
round_decimals (int) – Decimals to keep when rounding thresholds.
- Returns:
Integer array with relevant bracket indices for the given tax bases.
For instance:
>>> tax_scale = LinearAverageRateTaxScale() >>> tax_scale.add_bracket(0, 0) >>> tax_scale.add_bracket(100, 0.1) >>> tax_base = array([0, 150]) >>> tax_scale.bracket_indices(tax_base) [0, 1]
- threshold_from_tax_base(tax_base: NumericalArray) NumericalArray#
Compute the relevant thresholds for the given tax bases.
- Param:
ndarray tax_base: Array of the tax bases.
- Returns:
Floating array with relevant thresholds for the given tax bases.
For instance:
>>> import numpy >>> from policyengine_core import taxscales >>> tax_scale = taxscales.MarginalRateTaxScale() >>> tax_scale.add_bracket(0, 0) >>> tax_scale.add_bracket(200, 0.1) >>> tax_scale.add_bracket(500, 0.25) >>> tax_base = numpy.array([450, 1_150, 10]) >>> tax_scale.threshold_from_tax_base(tax_base) array([200, 500, 0])
AmountTaxScaleLike#
- class policyengine_core.taxscales.amount_tax_scale_like.AmountTaxScaleLike(name: Optional[str] = None, option: Any = None, unit: Any = None)#
Bases:
TaxScaleLike,ABCBase class for various types of amount-based tax scales: single amount, marginal amount…
SingleAmountTaxScale#
- class policyengine_core.taxscales.single_amount_tax_scale.SingleAmountTaxScale(name: Optional[str] = None, option: Any = None, unit: Any = None)[source]#
Bases:
AmountTaxScaleLike- calc(tax_base: NumericalArray, right: bool = False) numpy.float_[source]#
Matches the input amount to a set of brackets and returns the single cell value that fits within that bracket.
The returned array preserves the dtype of the bracket amounts. In particular, a scale whose amounts are booleans (
amount_unit: boolwithamount: true/false) returns a boolean array rather than the int640/1array that naive sentinel padding would produce. This keeps logical NOT (~) working on the result:~on an int array is a bitwise negation (~1 == -2and~0 == -1, both truthy), whereas~on a bool array is the intended element-wise logical negation.
MarginalRateTaxScale#
- class policyengine_core.taxscales.marginal_rate_tax_scale.MarginalRateTaxScale(name: Optional[str] = None, option: Any = None, unit: Any = None)#
Bases:
RateTaxScaleLike- bracket_indices(tax_base: NumericalArray, factor: float = 1.0, round_decimals: Optional[int] = None) numpy.int_#
Compute the relevant bracket indices for the given tax bases.
- Parameters:
tax_base (ndarray) – Array of the tax bases.
factor (float) – Factor to apply to the thresholds.
round_decimals (int) – Decimals to keep when rounding thresholds.
- Returns:
Integer array with relevant bracket indices for the given tax bases.
For instance:
>>> tax_scale = LinearAverageRateTaxScale() >>> tax_scale.add_bracket(0, 0) >>> tax_scale.add_bracket(100, 0.1) >>> tax_base = array([0, 150]) >>> tax_scale.bracket_indices(tax_base) [0, 1]
- calc(tax_base: NumericalArray, factor: float = 1.0, round_base_decimals: Optional[int] = None) numpy.float_#
Compute the tax amount for the given tax bases by applying a taxscale.
- Parameters:
tax_base (ndarray) – Array of the tax bases.
factor (float) – Factor to apply to the thresholds of the taxscale.
round_base_decimals (int) – Decimals to keep when rounding thresholds.
- Returns:
Float array with tax amount for the given tax bases.
For instance:
>>> tax_scale = MarginalRateTaxScale() >>> tax_scale.add_bracket(0, 0) >>> tax_scale.add_bracket(100, 0.1) >>> tax_base = array([0, 150]) >>> tax_scale.calc(tax_base) [0.0, 5.0]
- inverse() MarginalRateTaxScale#
Returns a new instance of MarginalRateTaxScale.
Invert a taxscale:
Assume tax_scale composed of bracket whose thresholds are expressed in terms of gross revenue.
The inverse is another MarginalRateTaxScale whose thresholds are expressed in terms of net revenue.
If net = gross_revenue - tax_scale.calc(gross_revenue) Then gross = tax_scale.inverse().calc(net)
- marginal_rates(tax_base: NumericalArray, factor: float = 1.0, round_base_decimals: Optional[int] = None) numpy.float_#
Compute the marginal tax rates relevant for the given tax bases.
- Parameters:
tax_base (ndarray) – Array of the tax bases.
factor (float) – Factor to apply to the thresholds of a tax scale.
round_base_decimals (int) – Decimals to keep when rounding thresholds.
- Returns:
Float array with relevant marginal tax rate for the given tax bases.
For instance:
>>> tax_scale = MarginalRateTaxScale() >>> tax_scale.add_bracket(0, 0) >>> tax_scale.add_bracket(100, 0.1) >>> tax_base = array([0, 150]) >>> tax_scale.marginal_rates(tax_base) [0.0, 0.1]
- rate_from_bracket_indice(bracket_indice: numpy.int_) numpy.float_#
Compute the relevant tax rates for the given bracket indices.
- Param:
ndarray bracket_indice: Array of the bracket indices.
- Returns:
Floating array with relevant tax rates for the given bracket indices.
For instance:
>>> import numpy >>> tax_scale = MarginalRateTaxScale() >>> tax_scale.add_bracket(0, 0) >>> tax_scale.add_bracket(200, 0.1) >>> tax_scale.add_bracket(500, 0.25) >>> tax_base = numpy.array([50, 1_000, 250]) >>> bracket_indice = tax_scale.bracket_indices(tax_base) >>> tax_scale.rate_from_bracket_indice(bracket_indice) array([0. , 0.25, 0.1 ])
- rate_from_tax_base(tax_base: NumericalArray) numpy.float_#
Compute the relevant tax rates for the given tax bases.
- Param:
ndarray tax_base: Array of the tax bases.
- Returns:
Floating array with relevant tax rates for the given tax bases.
For instance:
>>> import numpy >>> tax_scale = MarginalRateTaxScale() >>> tax_scale.add_bracket(0, 0) >>> tax_scale.add_bracket(200, 0.1) >>> tax_scale.add_bracket(500, 0.25) >>> tax_base = numpy.array([1_000, 50, 450]) >>> tax_scale.rate_from_tax_base(tax_base) array([0.25, 0. , 0.1 ])
- scale_tax_scales(factor: float) MarginalRateTaxScale#
Scale all the MarginalRateTaxScales in the node.
- threshold_from_tax_base(tax_base: NumericalArray) NumericalArray#
Compute the relevant thresholds for the given tax bases.
- Param:
ndarray tax_base: Array of the tax bases.
- Returns:
Floating array with relevant thresholds for the given tax bases.
For instance:
>>> import numpy >>> from policyengine_core import taxscales >>> tax_scale = taxscales.MarginalRateTaxScale() >>> tax_scale.add_bracket(0, 0) >>> tax_scale.add_bracket(200, 0.1) >>> tax_scale.add_bracket(500, 0.25) >>> tax_base = numpy.array([450, 1_150, 10]) >>> tax_scale.threshold_from_tax_base(tax_base) array([200, 500, 0])
- to_average() LinearAverageRateTaxScale#
Convert the scale to a LinearAverageRateTaxScale.
The average scale has the same thresholds, then a last threshold of infinity that carries the top rate, so
to_marginalgives this scale back. Its rate at each threshold is the tax there divided by the threshold, or 0 where both are 0. So the two scales levy the same tax at every threshold.One bracket from 0 instead gets its rate at both thresholds. Its average rate is the same at every base, so the two scales levy the same tax at every base. With two or more brackets,
LinearAverageRateTaxScale.calckeeps the average rate of the last finite threshold above it. That matches this scale’s tax only when the top rate is that average rate.- Raises:
ValueError – if no average rate scale levies the tax at every threshold or, for one bracket, at every base. This is so for one bracket with a nonzero rate whose threshold is not 0, and for a threshold of 0 at which the tax is not 0.
MarginalAmountTaxScale#
- class policyengine_core.taxscales.marginal_amount_tax_scale.MarginalAmountTaxScale(name: Optional[str] = None, option: Any = None, unit: Any = None)[source]#
Bases:
AmountTaxScaleLike
LinearAverageRateTaxScale#
- class policyengine_core.taxscales.linear_average_rate_tax_scale.LinearAverageRateTaxScale(name: Optional[str] = None, option: Any = None, unit: Any = None)#
Bases:
RateTaxScaleLike- bracket_indices(tax_base: NumericalArray, factor: float = 1.0, round_decimals: Optional[int] = None) numpy.int_#
Compute the relevant bracket indices for the given tax bases.
- Parameters:
tax_base (ndarray) – Array of the tax bases.
factor (float) – Factor to apply to the thresholds.
round_decimals (int) – Decimals to keep when rounding thresholds.
- Returns:
Integer array with relevant bracket indices for the given tax bases.
For instance:
>>> tax_scale = LinearAverageRateTaxScale() >>> tax_scale.add_bracket(0, 0) >>> tax_scale.add_bracket(100, 0.1) >>> tax_base = array([0, 150]) >>> tax_scale.bracket_indices(tax_base) [0, 1]
- calc(tax_base: NumericalArray, right: bool = False) numpy.float_#
Compute the tax amount for the given tax bases by applying a taxscale.
Each bracket’s rate is the average rate at its threshold. Between two thresholds the average rate moves linearly from one rate to the next. From the last threshold up it stays at the last rate. Below the first threshold the tax is 0, except that a scale with a single bracket applies its rate to every tax base.
- Parameters:
tax_base (ndarray) – Array of the tax bases.
- Returns:
Float array with tax amount for the given tax bases.
For instance:
>>> tax_scale = LinearAverageRateTaxScale() >>> tax_scale.add_bracket(0, 0) >>> tax_scale.add_bracket(100, 0.1) >>> tax_base = array([50, 100, 150]) >>> tax_scale.calc(tax_base) [2.5, 10.0, 15.0]
- threshold_from_tax_base(tax_base: NumericalArray) NumericalArray#
Compute the relevant thresholds for the given tax bases.
- Param:
ndarray tax_base: Array of the tax bases.
- Returns:
Floating array with relevant thresholds for the given tax bases.
For instance:
>>> import numpy >>> from policyengine_core import taxscales >>> tax_scale = taxscales.MarginalRateTaxScale() >>> tax_scale.add_bracket(0, 0) >>> tax_scale.add_bracket(200, 0.1) >>> tax_scale.add_bracket(500, 0.25) >>> tax_base = numpy.array([450, 1_150, 10]) >>> tax_scale.threshold_from_tax_base(tax_base) array([200, 500, 0])