1
0
mirror of https://github.com/elisspace/own_vs_buy.git synced 2026-08-29 15:44:04 +00:00

First commit

This commit is contained in:
Eli
2025-02-11 15:34:38 -05:00
commit 0d3e0dda5f
2 changed files with 384 additions and 0 deletions

151
own_vs_buy.py Normal file
View File

@@ -0,0 +1,151 @@
def main():
"""
Compare lifetime cost of home ownership vs. renting+investing.
Incorporates:
- House appreciation/depreciation
- Down payment and closing costs
- Monthly leftover investment if renting is cheaper
- Monthly compounding for investment returns
"""
# 1. Define Constants
CURRENT_AGE = 35
AGE_AT_DEATH = 90
# Mortgage details
MORTGAGE_RATE = 0.04 # 4% annual
MORTGAGE_TERM_YEARS = 30
HOME_COST = 350_000
DOWN_PAYMENT = 50_000
BUYER_CLOSING_COSTS = 10_000 # e.g., typical closing fees
# Home-related costs
PROPERTY_TAX_RATE = 0.083 # 1% per year
HOME_INSURANCE_PER_YEAR = 1200
AVERAGE_YEARLY_MAINTENANCE = 5000
# House appreciation/depreciation
# e.g. 0.02 => +2% per year, -0.02 => -2% per year
HOME_APPRECIATION_PERCENT = 0.05
# Rent details
RENT_PER_MONTH = 1500
RENT_ANNUAL_GROWTH_RATE = 0.10 # 2.5% per year
# Investment details
INVESTMENT_RETURN_PERCENT = 0.07 # 10% annual
# 2. Calculate total months for the simulation
total_years = AGE_AT_DEATH - CURRENT_AGE
total_months = total_years * 12
# 3. Mortgage Payment Calculation (Monthly)
# Formula: M = P * (r(1+r)^n) / ((1+r)^n - 1)
# where:
# P = (HOME_COST - DOWN_PAYMENT)
# r = MORTGAGE_RATE / 12
# n = MORTGAGE_TERM_YEARS * 12
principal = HOME_COST - DOWN_PAYMENT
monthly_interest_rate = MORTGAGE_RATE / 12
number_of_payments = MORTGAGE_TERM_YEARS * 12
if principal > 0:
monthly_mortgage_payment = (
principal *
(monthly_interest_rate * (1 + monthly_interest_rate) ** number_of_payments) /
((1 + monthly_interest_rate) ** number_of_payments - 1)
)
else:
# If DOWN_PAYMENT >= HOME_COST, no mortgage needed
monthly_mortgage_payment = 0
# 4. Break down monthly home costs
monthly_property_tax = (HOME_COST * PROPERTY_TAX_RATE) / 12
monthly_insurance = HOME_INSURANCE_PER_YEAR / 12
monthly_maintenance = AVERAGE_YEARLY_MAINTENANCE / 12
# 5. Initialize tracking variables
# For the homeowner:
# Start with the homes initial value; it will appreciate monthly
house_value = HOME_COST
total_ownership_cost = DOWN_PAYMENT + BUYER_CLOSING_COSTS # upfront out-of-pocket
# For the renter:
# Lump sum investment is the down payment + closing costs that aren't spent on buying.
investment_balance = DOWN_PAYMENT + BUYER_CLOSING_COSTS
total_renting_cost = 0.0
# Convert annual appreciation to a monthly factor
monthly_appreciation_rate = (1 + HOME_APPRECIATION_PERCENT) ** (1/12) - 1
# Convert annual investment return to monthly
monthly_investment_return_rate = INVESTMENT_RETURN_PERCENT / 12
current_rent = RENT_PER_MONTH
# 6. Iterate month by month
for month in range(1, total_months + 1):
# House appreciates each month (can be negative if it's depreciation)
house_value *= (1 + monthly_appreciation_rate)
# Calculate monthly ownership cost
if month <= number_of_payments:
# Mortgage not fully paid yet
monthly_owner_cost = (monthly_mortgage_payment +
monthly_property_tax +
monthly_insurance +
monthly_maintenance)
else:
# After the mortgage is paid off, only taxes, insurance, and maintenance remain
monthly_owner_cost = (monthly_property_tax +
monthly_insurance +
monthly_maintenance)
# Add to total ownership cost
total_ownership_cost += monthly_owner_cost
# Renter pays this months rent
total_renting_cost += current_rent
# Determine leftover that the renter invests if renting is cheaper
# difference > 0 => owning is more expensive => that difference can be invested by the renter
difference = monthly_owner_cost - current_rent
if difference > 0:
# This means renting is cheaper by 'difference'
investment_balance += difference # invest that difference immediately
# Grow the investment balance by the monthly return
investment_balance *= (1 + monthly_investment_return_rate)
# Increase rent once a year
if month % 12 == 0:
current_rent *= (1 + RENT_ANNUAL_GROWTH_RATE)
# 7. Final net worth calculations
# Homeowner's final net worth (simplified):
# They own the house, which is now worth house_value.
# total_ownership_cost is how much cash was spent over the period (plus the upfront).
# You can show them both or compute net_worth as (house_value - total_ownership_cost)
net_worth_owning = house_value - total_ownership_cost
# Renter's final net worth is simply the investment balance
net_worth_renting = investment_balance
# 8. Results
print("----- Results -----")
print(f"Total Ownership Cost (cash outlay): ${total_ownership_cost:,.2f}")
print(f"Final House Value: ${house_value:,.2f}")
print(f"Net Worth (Owning) = House Value - Outlays = ${net_worth_owning:,.2f}")
print()
print(f"Total Rent Paid Over {total_years} Years: ${total_renting_cost:,.2f}")
print(f"Final Investment Balance (Renting): ${investment_balance:,.2f}")
print(f"Net Worth (Renting) = ${net_worth_renting:,.2f}")
print()
difference = net_worth_renting - net_worth_owning
print(f"Difference (Renting Net Worth - Owning Net Worth): ${difference:,.2f}")
if __name__ == "__main__":
main()

233
own_vs_buy2.py Normal file
View File

@@ -0,0 +1,233 @@
def main():
"""
1. Prints assumption values.
2. Calculates monthly living expenses (inflation-adjusted) for groceries, travel, schooling, healthcare, incidentals.
3. Calculates renting vs buying costs each month (both in terms of cash flow and net worth).
4. Compares the final net worth of renting vs buying, color-codes the final statement to indicate which is better.
"""
# ANSI color codes for terminal output
COLOR_GREEN = "\033[92m"
COLOR_RED = "\033[91m"
COLOR_RESET = "\033[0m"
COLOR_YELLOW = "\033[93m" # optional for neutral or headings
# ================
# Part 1: Constants
# ================
# Time horizon
CURRENT_AGE = 35
AGE_AT_DEATH = 90
total_years = AGE_AT_DEATH - CURRENT_AGE
total_months = total_years * 12
# --- Income & Growth ---
MONTHLY_SALARY = 5000.0 # Initial monthly salary
ANNUAL_SALARY_GROWTH = 0.02 # 2% annual salary increase
# --- Inflation for Monthly Expenses ---
ANNUAL_INFLATION = 0.03 # 3% annual
# --- Base Monthly Expenses (excluding accommodation) ---
BASE_GROCERIES = 500.0
BASE_TRAVEL = 200.0
BASE_SCHOOLING = 300.0
BASE_HEALTHCARE = 400.0
BASE_INCIDENTALS = 2500 # "catch-all" category
# --- Investment Growth ---
ANNUAL_INVESTMENT_RETURN = 0.06 # 6% annual
# --- Renting Details ---
RENT_PER_MONTH = 1500.0
ANNUAL_RENT_GROWTH = 0.025 # 2.5% annual
# --- Buying Details ---
HOME_COST = 350_000.0
DOWN_PAYMENT = 80_000.0
BUYER_CLOSING_COSTS = 5_000.0
MORTGAGE_RATE = 0.04 # 4% annual
MORTGAGE_TERM_YEARS = 30
PROPERTY_TAX_RATE = 0.01 # 1% of home value per year
HOME_INSURANCE_PER_YEAR = 1200.0
AVERAGE_YEARLY_MAINTENANCE = 5000.0
# Home appreciation (positive or negative)
ANNUAL_HOME_APPRECIATION = 0.02 # 2% per year
# ================
# Display Assumptions
# ================
print(f"{COLOR_YELLOW}----- Assumptions -----{COLOR_RESET}")
print(f"Time Span: {CURRENT_AGE} to {AGE_AT_DEATH} (Total {total_years} years)")
print(f"Initial Monthly Salary: ${MONTHLY_SALARY:,.2f}")
print(f"Annual Salary Growth: {ANNUAL_SALARY_GROWTH*100:.2f}%")
print(f"Annual Inflation (non-housing expenses): {ANNUAL_INFLATION*100:.2f}%")
print(f"Base Monthly Expenses (Groceries + Travel + Schooling + Healthcare + Incidentals): "
f"${(BASE_GROCERIES + BASE_TRAVEL + BASE_SCHOOLING + BASE_HEALTHCARE + BASE_INCIDENTALS):,.2f}")
print(f"Annual Investment Return: {ANNUAL_INVESTMENT_RETURN*100:.2f}%\n")
print("Renting Assumptions:")
print(f" - Initial Monthly Rent: ${RENT_PER_MONTH:,.2f}")
print(f" - Annual Rent Growth: {ANNUAL_RENT_GROWTH*100:.2f}%\n")
print("Buying Assumptions:")
print(f" - Home Cost: ${HOME_COST:,.2f}")
print(f" - Down Payment: ${DOWN_PAYMENT:,.2f}")
print(f" - Buyer Closing Costs: ${BUYER_CLOSING_COSTS:,.2f}")
print(f" - Mortgage Rate (Annual): {MORTGAGE_RATE*100:.2f}%")
print(f" - Mortgage Term: {MORTGAGE_TERM_YEARS} years")
print(f" - Property Tax Rate: {PROPERTY_TAX_RATE*100:.2f}% of home value/year")
print(f" - Home Insurance/Year: ${HOME_INSURANCE_PER_YEAR:,.2f}")
print(f" - Avg Yearly Maintenance: ${AVERAGE_YEARLY_MAINTENANCE:,.2f}")
print(f" - Annual Home Appreciation: {ANNUAL_HOME_APPRECIATION*100:.2f}%")
print(f"{'-'*50}\n")
# ================
# Part 2: Derive Monthly Rates and Setup
# ================
monthly_salary_growth = (1 + ANNUAL_SALARY_GROWTH) ** (1/12) - 1
monthly_inflation = (1 + ANNUAL_INFLATION) ** (1/12) - 1
monthly_investment_growth = ANNUAL_INVESTMENT_RETURN / 12
monthly_rent_growth = (1 + ANNUAL_RENT_GROWTH) ** (1/12) - 1
monthly_home_appreciation = (1 + ANNUAL_HOME_APPRECIATION) ** (1/12) - 1
# Base standard expenses total
base_standard_expenses = (
BASE_GROCERIES +
BASE_TRAVEL +
BASE_SCHOOLING +
BASE_HEALTHCARE +
BASE_INCIDENTALS
)
current_standard_expenses = base_standard_expenses
# Mortgage payment
principal = HOME_COST - DOWN_PAYMENT
monthly_mortgage_rate = MORTGAGE_RATE / 12
number_of_payments = MORTGAGE_TERM_YEARS * 12
if principal > 0:
monthly_mortgage_payment = (
principal *
(monthly_mortgage_rate * (1 + monthly_mortgage_rate) ** number_of_payments) /
((1 + monthly_mortgage_rate) ** number_of_payments - 1)
)
else:
monthly_mortgage_payment = 0.0
monthly_property_tax = (HOME_COST * PROPERTY_TAX_RATE) / 12
monthly_insurance = HOME_INSURANCE_PER_YEAR / 12
monthly_maintenance = AVERAGE_YEARLY_MAINTENANCE / 12
# ================
# Part 3: Tracking & Simulation
# ================
total_income = 0.0
total_standard_expenses_accum = 0.0
# Renting scenario
total_rent_cost = 0.0
rent_investment_balance = DOWN_PAYMENT + BUYER_CLOSING_COSTS # Freed up capital if you don't buy
current_rent = RENT_PER_MONTH
# Buying scenario
total_buy_cost = DOWN_PAYMENT + BUYER_CLOSING_COSTS # upfront cost
buy_investment_balance = 0.0
house_value = HOME_COST
# Starting salary
current_monthly_salary = MONTHLY_SALARY
for month in range(1, total_months + 1):
# --- Income
total_income += current_monthly_salary
# --- Standard Expenses (inflation-adjusted)
total_standard_expenses_accum += current_standard_expenses
# --- Renting: Pay Rent, Invest Leftover
total_rent_cost += current_rent
leftover_rent = current_monthly_salary - current_standard_expenses - current_rent
if leftover_rent > 0:
rent_investment_balance += leftover_rent
rent_investment_balance *= (1 + monthly_investment_growth)
# --- Buying: Pay Mortgage/Costs, Invest Leftover
if month <= number_of_payments:
monthly_ownership_cost = (
monthly_mortgage_payment +
monthly_property_tax +
monthly_insurance +
monthly_maintenance
)
else:
monthly_ownership_cost = (
monthly_property_tax +
monthly_insurance +
monthly_maintenance
)
total_buy_cost += monthly_ownership_cost
leftover_buy = current_monthly_salary - current_standard_expenses - monthly_ownership_cost
if leftover_buy > 0:
buy_investment_balance += leftover_buy
buy_investment_balance *= (1 + monthly_investment_growth)
# House Appreciation
house_value *= (1 + monthly_home_appreciation)
# Increase Salary, Rent, Standard Expenses (monthly growth)
current_monthly_salary *= (1 + monthly_salary_growth)
current_rent *= (1 + monthly_rent_growth)
current_standard_expenses *= (1 + monthly_inflation)
# ================
# Part 4: Final Output & Comparison
# ================
print(f"{COLOR_YELLOW}----- Final Results -----{COLOR_RESET}")
print(f"Total Income (All Sources): ${total_income:,.2f}")
print(f"Total Standard Expenses (Excl. Accommodation): ${total_standard_expenses_accum:,.2f}")
# Costs including renting
total_rent_incl_expenses = total_standard_expenses_accum + total_rent_cost
print(f"Total Costs (Incl. Rent): ${total_rent_incl_expenses:,.2f}")
# Costs including buying
total_buy_incl_expenses = total_standard_expenses_accum + total_buy_cost
print(f"Total Costs (Incl. Buy): ${total_buy_incl_expenses:,.2f}\n")
# Compute a simplified 'final net worth' approach
# - Renter's net worth: final investment balance
# - Owner's net worth: final investment balance + house value
rent_net_worth = rent_investment_balance
buy_net_worth = buy_investment_balance + house_value
print(f"Renter's Final Investment Balance: ${rent_net_worth:,.2f}")
print(f"Homeowner's Investment Balance: ${buy_investment_balance:,.2f}")
print(f"Final House Value: ${house_value:,.2f}")
print()
difference = buy_net_worth - rent_net_worth
if difference > 0:
# Buying scenario is ahead
print(
f"{COLOR_GREEN}Buying is ahead by ${difference:,.2f} "
f"({buy_net_worth:,.2f} vs. {rent_net_worth:,.2f}){COLOR_RESET}"
)
elif difference < 0:
# Renting scenario is ahead
print(
f"{COLOR_GREEN}Renting is ahead by ${abs(difference):,.2f} "
f"({rent_net_worth:,.2f} vs. {buy_net_worth:,.2f}){COLOR_RESET}"
)
else:
# Exactly the same (unlikely in real life)
print(f"{COLOR_YELLOW}Both scenarios come out exactly the same!{COLOR_RESET}")
if __name__ == "__main__":
main()