Skip to content

Instantly share code, notes, and snippets.

@hamidzr
Created October 11, 2022 04:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hamidzr/09725baff31938ad4b4684dd11da5783 to your computer and use it in GitHub Desktop.
Save hamidzr/09725baff31938ad4b4684dd11da5783 to your computer and use it in GitHub Desktop.
car cost calculator. Why you neeeed that sweet new ride, numbers edition.
#!/usr/bin/env python3
import numpy_financial as npf
import numpy as np
import typing as t
import json
"""
TODO:
- opportunity cost calc
"""
# utilities start
# number type union of int or float
Number = t.Union[int, float]
def serialize_number(n: Number):
if isinstance(n, float):
if n % 1 == 0:
return str(int(n))
else:
return str(round(n, 3))
else:
return str(n)
# print as formatted json
def print_as_json(d: dict):
print(json.dumps(d, indent=4, sort_keys=True))
# utilities end
fixed_vars = {
'interest_rate': 0.03, # 0.025,
'loan_term': 3 * 12, # months
'sales_tax_rate': 0.095,
'registration_rate': 0.01,
'keep_for': 5, # years
'usage': 5000, # miles per year. 20000/4 = 5000
'fuel_cost': 5.3, # dollars per gallon
'down_payment': 15000,
}
vars = { # car A
**fixed_vars,
'car_value': 87000,
'residual_value_rate': {
1: 0.96,
2: 0.92,
3: 0.87,
4: 0.85,
5: 0.84,
},
'maintenance_cost': 400, # per year
'insurance_yearly': 2400,
'mpg': 18, # miles per gallon
}
# vars = { # miata. base case
# **fixed_vars,
# 'car_value': 30000,
# # 'down_payment': 0,
# 'residual_value_rate': {
# 1: 0.94,
# 2: 0.91,
# 3: 0.91,
# 4: 0.87,
# 5: 0.82,
# },
# 'maintenance_cost': 200, # per year
# 'insurance_yearly': 1200,
# 'mpg': 27, # miles per gallon
# }
def monthly_loan_payment(loan_value, interest_rate, loan_term): # CHECK
return (interest_rate/12) * (1/(1-(1+interest_rate/12)**(-loan_term)))*loan_value
def principal_schedule(month, loan_value, interest_rate, loan_term):
return npf.ppmt(interest_rate/12, np.arange(1*month)+1, loan_term, loan_value)
# principal amount paid by month `month`
def principal_at(month, loan_value, interest_rate, loan_term):
if month >= loan_term:
month = loan_term
return -1 * float(np.sum(principal_schedule(month, loan_value, interest_rate, loan_term)))
def interest_schedule(month, loan_value, interest_rate, loan_term):
return npf.ipmt(interest_rate/12, np.arange(1*month)+1, loan_term, loan_value)
# interest amount paid by month `month`
def interest_at(month, loan_value, interest_rate, loan_term):
if month >= loan_term:
month = loan_term
interests = interest_schedule(month, loan_value, interest_rate, loan_term)
return -1 * float(np.sum(interests))
tax = vars['car_value'] * vars['sales_tax_rate']
loan_value = vars['car_value'] + tax - vars['down_payment']
monthly_payment = monthly_loan_payment(loan_value, vars['interest_rate'], vars['loan_term'])
# compute vars after a keeping the car for `keep_for` years
# how much we can sell the car for
sale_price = vars['car_value'] * vars['residual_value_rate'][vars['keep_for']]
# how much of the original loan we've paid off that's applied to the principal
principal_paid = principal_at(vars['keep_for'] * 12, loan_value, vars['interest_rate'], vars['loan_term'])
# the amount of payments that has gone to interest
interest_paid = interest_at(vars['keep_for'] * 12, loan_value, vars['interest_rate'], vars['loan_term'])
# the cost of registering the car
registration_paid = vars['car_value'] * vars['registration_rate'] * vars['keep_for']
# insurance cost
insurance_paid = vars['insurance_yearly'] * vars['keep_for']
# gas cost
gas_cost = (vars['usage'] / vars['mpg']) * vars['fuel_cost'] * vars['keep_for']
# maintenance cost
maintenance_cost = vars['maintenance_cost'] * vars['keep_for']
loan_payments = monthly_payment * min(vars['keep_for'] * 12, vars['loan_term'])
# effective loan rate. at the end of the 'keep_for' period what percentage of the principal did you
# pas as interest.
effective_rate = interest_paid / principal_paid
remaining_principal = loan_value - principal_paid
loan_termination_cost = loan_value-principal_paid
overall_cost = vars['down_payment'] + loan_termination_cost + loan_payments + registration_paid + insurance_paid + gas_cost + maintenance_cost
# overall financial change after the car is sold
net_balance = sale_price - overall_cost
computed_vars = {
'loan_value': loan_value,
'monthly_payment': monthly_payment,
'expected_sale_price': sale_price,
'effective_rate': effective_rate,
'sale_price': sale_price,
'overall_paid': overall_cost,
'costs': {
'total_tax': tax,
'insurance_paid': insurance_paid,
'registration_paid': registration_paid,
'interest_paid': interest_paid,
'depreciation': vars['car_value'] - sale_price,
'gas_cost': gas_cost,
'maintenance_cost': maintenance_cost,
'net_balance': net_balance,
'monthly_change': net_balance / (vars['keep_for'] * 12),
'monthly_state_tax': tax / (vars['keep_for'] * 12),
},
# other
'loan_payments': loan_payments,
'principal_paid': principal_paid,
'loan_termination_cost': loan_termination_cost,
}
output = {'inputs': vars, 'computed': computed_vars}
# check if yaml is installed
try:
import yaml
def float_representer(dumper, value):
text = '{0:.2f}'.format(value)
return dumper.represent_scalar(u'tag:yaml.org,2002:float', text)
yaml.add_representer(float, float_representer)
print(yaml.dump(output))
except ImportError:
print_as_json(output)
# print('diff', 930-370)
@hamidzr
Copy link
Author

hamidzr commented Oct 11, 2022

sample output:

computed:
  costs:
    depreciation: 13920.00
    gas_cost: 7361.11
    insurance_paid: 12000
    interest_paid: 3766.32
    maintenance_cost: 2000
    monthly_change: -861.04
    monthly_state_tax: 137.75
    net_balance: -51662.43
    registration_paid: 4350.00
    total_tax: 8265.00
  effective_rate: 0.05
  expected_sale_price: 73080.00
  loan_payments: 84031.32
  loan_termination_cost: -0.00
  loan_value: 80265.00
  monthly_payment: 2334.20
  overall_paid: 124742.43
  principal_paid: 80265.00
  sale_price: 73080.00
inputs:
  car_value: 87000
  down_payment: 15000
  fuel_cost: 5.30
  insurance_yearly: 2400
  interest_rate: 0.03
  keep_for: 5
  loan_term: 36
  maintenance_cost: 400
  mpg: 18
  registration_rate: 0.01
  residual_value_rate:
    1: 0.96
    2: 0.92
    3: 0.87
    4: 0.85
    5: 0.84
  sales_tax_rate: 0.10
  usage: 5000

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment