Initial extraction from monorepo
This commit is contained in:
commit
f7ef7ca4ab
56 changed files with 6163 additions and 0 deletions
49
fire_planner/tax/cyprus.py
Normal file
49
fire_planner/tax/cyprus.py
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
"""Cyprus regime — non-dom 17-year exemption on foreign dividends +
|
||||
interest, plus 2.65% GeSY healthcare levy capped at €180k.
|
||||
|
||||
The non-dom regime (Art 8(20)/(20A) Income Tax Law 118(I)/2002) gives
|
||||
17 years of full exemption from SDC (Special Defence Contribution) on
|
||||
foreign dividends and interest. Capital gains on shares are exempt
|
||||
under standard CGT rules (only Cypriot real estate is taxed). Earned
|
||||
income from employment is taxed under standard PIT bands — irrelevant
|
||||
for our retirement scenarios.
|
||||
|
||||
GeSY (Γε.Σ.Υ. — General Healthcare System) levies 2.65% on worldwide
|
||||
income with an annual cap of €180,000 of contributing income. We
|
||||
convert the €180k cap to GBP via the FX rate at scenario time;
|
||||
default = 0.86 GBP/EUR ≈ £154,800.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from decimal import Decimal
|
||||
|
||||
from fire_planner.tax.base import TaxBreakdown, TaxInputs, TaxRegime
|
||||
|
||||
DEFAULT_GESY_RATE = Decimal("0.0265")
|
||||
DEFAULT_GESY_CAP_EUR = Decimal("180000")
|
||||
|
||||
|
||||
class CyprusTaxRegime(TaxRegime):
|
||||
name = "cyprus"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
gesy_rate: Decimal = DEFAULT_GESY_RATE,
|
||||
gesy_cap_gbp: Decimal | None = None,
|
||||
gbp_per_eur: Decimal = Decimal("0.86"),
|
||||
) -> None:
|
||||
self.gesy_rate = gesy_rate
|
||||
self.gesy_cap_gbp = (gesy_cap_gbp if gesy_cap_gbp is not None else DEFAULT_GESY_CAP_EUR *
|
||||
gbp_per_eur)
|
||||
|
||||
def compute_tax(self, inputs: TaxInputs) -> TaxBreakdown:
|
||||
# Foreign divs/interest exempt under non-dom (assumed within 17y window).
|
||||
# Foreign capital gains exempt unless the underlying is Cypriot real estate.
|
||||
chargeable = (inputs.earned_income + inputs.pension_withdrawal + inputs.capital_gains +
|
||||
inputs.dividends + inputs.interest)
|
||||
capped = min(chargeable, self.gesy_cap_gbp)
|
||||
return TaxBreakdown(
|
||||
healthcare_levy=capped * self.gesy_rate,
|
||||
notes=("cyprus-non-dom", f"gesy_rate={self.gesy_rate}",
|
||||
f"gesy_cap_gbp={self.gesy_cap_gbp}"),
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue