In [0]:
import pandas as pd
import numpy as np
import plotly.express as pe
import matplotlib.pyplot as plt
plt.style.use('ggplot')
In [0]:
'''https://www.pwc.com.au/taxtalk/tax-rates.html'''
def income_tax(x):
'''https://www.ato.gov.au/rates/individual-income-tax-rates/'''
if x <= 18200:
return 0
elif x <= 37000:
return 0.19 * (x - 18200)
elif x <= 90000:
return 3572 + 0.325 * (x - 37000)
elif x <= 180000:
return 20797 + 0.37 * (x - 90000)
else:
return 54097 + 0.45 * (x - 180000)
def medicare_levy(x):
'''
https://www.ato.gov.au/Individuals/Medicare-levy/
https://www.ato.gov.au/individuals/medicare-levy/medicare-levy-reduction-for-low-income-earners/ <-- Last year's figures
'''
if x <= 22398:
return 0
if x <= 27997:
# (27997 * 0.02) / (27997 - 22398) = 0.1
return 0.1 * (x - 22398)
else:
return 0.02 * x
def hecs_debt(x):
'''https://www.ato.gov.au/Rates/HELP,-TSL-and-SFSS-repayment-thresholds-and-rates/'''
thresholds = [
(45880, 0),
(52973, 0.01),
(56151, 0.02),
(59521, 0.025),
(63092, 0.03),
(66877, 0.035),
(70890, 0.04),
(75144, 0.045),
(79652, 0.05),
(84432, 0.055),
(89498, 0.06),
(94868, 0.065),
(100560, 0.07),
(106593, 0.075),
(112989, 0.08),
(119769, 0.085),
(126955, 0.09),
(134572, 0.095),
]
for threshold, multiplier in thresholds:
if x <= threshold:
return x * multiplier
# You rich
return 0.1 * x
def mls(x):
'''https://www.ato.gov.au/Individuals/Medicare-levy/Medicare-levy-surcharge/Income-thresholds-and-rates-for-the-Medicare-levy-surcharge/'''
if x <= 90000:
return 0
elif x <= 105000:
return 0.01 * x
elif x <= 140000:
return 0.0125 * x
else:
return 0.015 * x
def lmito(x):
'''https://www.ato.gov.au/Individuals/Income-and-deductions/Offsets-and-rebates/Low-and-middle-income-earners/'''
if x <= 37000:
return -255
elif x <= 48000:
return -(255 + (x - 37000) * 0.075)
elif x <= 90000:
return -1080
elif x <= 126000:
return -1080 + (x - 90000) * 0.03
else:
return 0
In [0]:
df = pd.DataFrame({
'Income': [i for i in range(200000)]
})
In [0]:
df['INCOME_TAX'] = df.Income.apply(income_tax)
df['MEDICARE_LEVY'] = df.Income.apply(medicare_levy)
df['HECS'] = df.Income.apply(hecs_debt)
df['MLS'] = df.Income.apply(mls)
df['LIMTO'] = df.Income.apply(lmito)
In [0]:
df
Out[0]:
In [0]:
df['NORMAL'] = np.maximum(df.INCOME_TAX + df.MEDICARE_LEVY + df.LIMTO, 0)
df['MRGL_NORMAL'] = df.NORMAL.diff().fillna(0)
In [0]:
df.MRGL_NORMAL
Out[0]:
In [0]:
df['W_HECS'] = np.maximum(df.INCOME_TAX + df.MEDICARE_LEVY + df.LIMTO + df.HECS, 0)
df['MRGL_W_HECS'] = df.W_HECS.diff().fillna(0)
df['MRGL_W_HECS_NRM'] = np.where(df.MRGL_W_HECS > 1.0, df.MRGL_W_HECS.shift(), df.MRGL_W_HECS)
In [0]:
df.MRGL_W_HECS[df.MRGL_W_HECS > 1.0]
Out[0]:
In [0]:
df['W_MLS'] = np.maximum(df.INCOME_TAX + df.MEDICARE_LEVY + df.LIMTO + df.MLS, 0)
df['MRGL_W_MLS'] = df.W_MLS.diff().fillna(0)
df['MRGL_W_MLS_NRM'] = np.where(df.MRGL_W_MLS > 1.0, df.MRGL_W_MLS.shift(), df.MRGL_W_MLS)
In [0]:
df.MRGL_W_MLS
Out[0]:
In [0]:
ax = df.plot('Income', ['MRGL_NORMAL', 'MRGL_W_HECS', 'MRGL_W_MLS'], ylim=(0, 0.6), figsize=(20,10), title="Australian Marginal Income Tax")
ax.annotate('Medicare Levy Phasing', xy=(22398, 0.3), xytext=(10000, 0.35), arrowprops=dict(facecolor='black', shrink=0.01))
ax.annotate('End of LMITO', xy=(126000, 0.39), xytext=(126000, 0.33), arrowprops=dict(facecolor='black', shrink=0.01))
ax.set_xlabel("Taxable Income ($)")
ax.set_ylabel("Marginal Tax Rate per Dollar (%)")
plt.show()
In [0]:
ax = df.plot('Income', ['MRGL_NORMAL', 'MRGL_W_HECS_NRM', 'MRGL_W_MLS_NRM'], ylim=(0, 0.6), figsize=(20,10), title="Australian Marginal Income Tax")
ax.annotate('Medicare Levy Phasing', xy=(22398, 0.3), xytext=(10000, 0.35), arrowprops=dict(facecolor='black', shrink=0.01))
ax.annotate('End of LMITO', xy=(126000, 0.39), xytext=(126000, 0.33), arrowprops=dict(facecolor='black', shrink=0.01))
ax.set_xlabel("Taxable Income ($)")
ax.set_ylabel("Marginal Tax Rate per Dollar (%)")
plt.show()
In [0]:
ax = df.plot('Income', ['NORMAL', 'W_HECS', 'W_MLS'], figsize=(20,10), title="Australian Income Tax")
ax.set_xlabel("Taxable Income ($)")
ax.set_ylabel("Tax Liability ($)")
plt.show()
In [0]: