Created
January 25, 2019 14:15
-
-
Save saxbophone/3302b3ae7a880dc3679a259944cf213a to your computer and use it in GitHub Desktop.
I'm not quite as good as calculating income tax as I thought I was...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from decimal import Decimal | |
DEFAULT_PERSONAL_ALLOWANCE = Decimal(11_850) | |
PERSONAL_ALLOWANCE_ADJUSTMENT_BEGIN = Decimal(100_000) | |
BASIC_RATE_BEGIN = DEFAULT_PERSONAL_ALLOWANCE | |
HIGHER_RATE_BEGIN = Decimal(46_350) | |
ADDITIONAL_RATE_BEGIN = Decimal(150_000) | |
BASIC_RATE = Decimal(0.20) | |
HIGHER_RATE = Decimal(0.40) | |
ADDITIONAL_RATE = Decimal(0.45) | |
def income_tax(s): | |
# make sure salary is stored as Decimal type | |
salary = Decimal(s) | |
# everyone gets the default personal allowance to start with | |
personal_allowance = DEFAULT_PERSONAL_ALLOWANCE | |
# calculate any personal allowance adjustments | |
if salary > PERSONAL_ALLOWANCE_ADJUSTMENT_BEGIN: | |
# personal allowance goes down by GBP1 for every GBP2 over 100k | |
personal_allowance -= ( | |
(salary - PERSONAL_ALLOWANCE_ADJUSTMENT_BEGIN) / 2 | |
) | |
# this guards against ending up with a negative personal allowance | |
personal_allowance = max(personal_allowance, Decimal(0)) | |
# take_home tracks take-home pay, taxable tracks tax to pay | |
take_home = min(personal_allowance, salary) | |
taxable = Decimal(0) | |
salary -= take_home | |
# now that the personal allowance is out of the way, calculate up tax bands | |
if salary > 0: | |
# basic rate | |
basic_rate_taxable = min(HIGHER_RATE_BEGIN - BASIC_RATE_BEGIN, salary) | |
take_home += basic_rate_taxable * (1 - BASIC_RATE) | |
taxable += basic_rate_taxable * BASIC_RATE | |
salary -= basic_rate_taxable | |
if salary > 0: | |
# higher rate | |
higher_rate_taxable = min(ADDITIONAL_RATE_BEGIN - HIGHER_RATE_BEGIN, salary) | |
take_home += higher_rate_taxable * (1 - HIGHER_RATE) | |
taxable += higher_rate_taxable * HIGHER_RATE | |
salary -= higher_rate_taxable | |
if salary > 0: | |
# additional rate -this is calculated on any remaining income | |
additional_rate_taxable = salary | |
take_home += additional_rate_taxable * (1 - ADDITIONAL_RATE) | |
taxable += additional_rate_taxable * ADDITIONAL_RATE | |
salary -= additional_rate_taxable | |
# these post-conditional assertions perform basic sanity checks | |
assert salary == 0. # we should have accounted for all income | |
# take-home + taxable = original salary | |
# FIXME: below assertion doesn't always work. maybe being too picky | |
# assert (take_home + taxable) == Decimal(s) | |
return (take_home, taxable) | |
for i in range(0, 201_000, 1_000): | |
take_home, taxable = income_tax(i) | |
print(i, take_home, taxable) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment