Skip to content

Instantly share code, notes, and snippets.

@budhash
Created November 10, 2023 06:16
Show Gist options
  • Select an option

  • Save budhash/fddde911292a8fba6fd5a0933b65f3d6 to your computer and use it in GitHub Desktop.

Select an option

Save budhash/fddde911292a8fba6fd5a0933b65f3d6 to your computer and use it in GitHub Desktop.
NapkinTax
import json
class Income:
def __init__(self):
self.income_sources = {}
def add(self, source, amount):
"""Add income to the total, categorizing by source."""
self.income_sources[source] = self.income_sources.get(source, 0) + amount
def wages(self, amount):
self.add('wages', amount)
def interest(self, amount):
self.add('interest', amount)
def rental(self, amount):
self.add('rental', amount)
def business(self, amount):
self.add('business', amount)
def misc(self, amount):
self.add('misc', amount)
def total(self):
"""Calculate the total income from all sources."""
return sum(self.income_sources.values())
class RetirementContributions:
def __init__(self):
self.contributions = {}
def add(self, contribution_type, amount):
"""Add contributions to the total, categorizing by type."""
self.contributions[contribution_type] = self.contributions.get(contribution_type, 0) + amount
def traditional_401k(self, amount):
self.add('traditional_401k', amount)
def traditional_ira(self, amount):
self.add('traditional_ira', amount)
def misc(self, amount):
self.add('misc', amount)
def total(self):
"""Calculate the total contributions from all types."""
return sum(self.contributions.values())
class TaxInfo:
def __init__(self, calculated_tax_amount, tax_rate, blended_tax_rate, standard_deduction):
self.calculated_tax_amount = calculated_tax_amount
self.tax_rate = tax_rate
self.blended_tax_rate = blended_tax_rate
self.standard_deduction = standard_deduction
def print_table(self):
print("+---------------------------+------------------+")
print("| Description | Amount |")
print("+---------------------------+------------------+")
print(f"| Calculated Tax Amount | $ {self.calculated_tax_amount:,.2f} ")
print(f"| Tax Rate | {self.tax_rate:.2f}% ")
print(f"| Blended Tax Rate | {self.blended_tax_rate:.2f}% ")
print(f"| Standard Deduction | $ {self.standard_deduction:,.2f} ")
print("+---------------------------+------------------+")
def print(self):
print(f"Calculated Tax Amount: ${self.calculated_tax_amount}")
print(f"Tax Rate: {self.tax_rate:.2f}%")
print(f"Blended Tax Rate: {self.blended_tax_rate:.2f}%")
print(f"Standard Deduction: ${self.standard_deduction}")
class TaxCalculator:
def __init__(self, tax_metadata):
self.metadata = tax_metadata
def get_standard_deduction(self, filing_type):
return self.metadata['standard_deduction'][filing_type]
def get_brackets(self, filing_type):
return self.metadata['tax_brackets'][filing_type]
def calculate(self, filing_type, income, retirement_contributions):
total_income = income.total()
total_retirement_contributions = retirement_contributions.total()
adjusted_gross_income = total_income - total_retirement_contributions
# Get the standard deduction for the given filing type
standard_deduction = self.get_standard_deduction(filing_type)
# Apply the standard deduction
taxable_income = max(0, adjusted_gross_income - standard_deduction)
# Get the tax brackets for the given filing type
tax_brackets = self.get_brackets(filing_type)
# Calculate the tax liability
tax_liability = 0.0
tax_rate = 0
for lower_bound, upper_bound, rate in tax_brackets:
if taxable_income > lower_bound:
tax_rate = float(rate)
# Calculate tax for this bracket
income_in_bracket = min(taxable_income, upper_bound) - lower_bound
tax_liability += income_in_bracket * (rate / 100.0)
else:
# No more income to tax
break
# Calculate the effective tax rate and the blended tax rate
blended_tax_rate = (tax_liability / total_income * 100) if total_income > 0 else 0
# Return a TaxInfo object with the calculated values
return TaxInfo(calculated_tax_amount=tax_liability, tax_rate=tax_rate, blended_tax_rate=blended_tax_rate, standard_deduction=standard_deduction)
class TaxMetadataHandler:
def load_metadata_from_file(self, year):
try:
with open(f"{year}_tax_data.json", 'r') as file:
return json.load(file)
except FileNotFoundError:
return None
def load_metadata(self, year):
# Hardcoded metadata for 2024 with tax rates included
hardcoded_data = {
'2024': {
'standard_deduction': {'s': 14600, 'h': 21900, 'j': 29200, 'm': 14600},
'tax_brackets': {
's': [(0, 11600, 10), (11600, 47150, 12), (47150, 100525, 22), (100525, 191950, 24), (191950, 243725, 32), (243725, 609350, 35), (609350, float('inf'), 37)],
'h': [(0, 16550, 10), (16550, 63100, 12), (63100, 100500, 22), (100500, 191950, 24), (191950, 243700, 32), (243700, 609350, 35), (609350, float('inf'), 37)],
'j': [(0, 23200, 10), (23200, 94300, 12), (94300, 201050, 22), (201050, 383900, 24), (383900, 487450, 32), (487450, 731200, 35), (731200, float('inf'), 37)],
'm': [(0, 11600, 10), (11600, 47150, 12), (47150, 100525, 22), (100525, 191950, 24), (191950, 243725, 32), (243725, 365600, 35), (365600, float('inf'), 37)]
}
},
'2023': {
'standard_deduction': {'s': 13850, 'h': 20800, 'j': 27700, 'm': 13850},
'tax_brackets': {
's': [(0, 11000, 10), (11000, 44725, 12), (44725, 95375, 22), (95375, 182100, 24), (182100, 231250, 32), (231250, 578125, 35), (578125, float('inf'), 37)],
'h': [(0, 15700, 10), (15700, 59850, 12), (59850, 95350, 22), (95350, 182100, 24), (182100, 231250, 32), (231250, 578100, 35), (578100, float('inf'), 37)],
'j': [(0, 22000, 10), (22000, 89450, 12), (89450, 190750, 22), (190750, 364200, 24), (364200, 462500, 32), (462500, 693750, 35), (693750, float('inf'), 37)],
'm': [(0, 11000, 10), (11000, 44725, 12), (44725, 95375, 22), (95375, 182100, 24), (182100, 231250, 32), (231250, 346875, 35), (346875, float('inf'), 37)]
}
}
}
return hardcoded_data.get(year)
def load_metadata_from_web(self, year):
# Placeholder for future implementation
return None
def get_metadata(self, year):
data = self.load_metadata(year)
if not data:
data = self.load_metadata_from_web(year)
if not data:
data = self.load_metadata_from_file(year)
if not data:
raise Exception(f"No tax metadata found for year {year}")
return data
class NapkinTax:
def __init__(self):
self.metadata_handler = TaxMetadataHandler()
def run(self, year, filing_type, income, retirement_contributions):
try:
metadata = self.metadata_handler.get_metadata(year)
calculator = TaxCalculator(metadata)
tax_info = calculator.calculate(filing_type, income, retirement_contributions)
tax_info.print_table()
except Exception as e:
print(e)
# Handle the exception accordingly
# Example CLI usage (to be integrated with argparse or similar)
income = Income()
income.add('wages', 500000)
retirement_contributions = RetirementContributions()
retirement_contributions.traditional_401k(19000)
napkin_tax = NapkinTax()
napkin_tax.run('2023', 's', income, retirement_contributions)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment