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

new branch building on lessons learned

This commit is contained in:
Eli
2025-02-15 15:20:21 -05:00
parent 33a19ee313
commit a1ade4dc32
7 changed files with 324 additions and 712 deletions

161
app.py
View File

@@ -1,161 +0,0 @@
from flask import Flask, render_template, request, redirect, url_for, session, jsonify
app = Flask(__name__)
app.secret_key = 'SUPER-SECRET-KEY' # Replace with something more secure in production
# Demo user dictionary (store hashed credentials in a real system)
USERS = {
"testuser": "testpass"
}
@app.route('/', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
if USERS.get(username) == password:
session['logged_in'] = True
return redirect(url_for('calculator'))
else:
return render_template('login.html', error="Invalid username/password.")
else:
if session.get('logged_in'):
return redirect(url_for('calculator'))
return render_template('login.html')
@app.route('/logout')
def logout():
session.clear()
return redirect(url_for('login'))
@app.route('/calculator')
def calculator():
if not session.get('logged_in'):
return redirect(url_for('login'))
return render_template('calculator.html')
@app.route('/compute', methods=['POST'])
def compute():
"""
AJAX endpoint that receives user inputs (via JSON),
then calculates renting vs. buying outcomes.
This version dynamically updates taxes, insurance,
and maintenance based on the house's changing value.
"""
data = request.json
# User inputs
current_age = float(data.get('current_age', 30))
age_at_death = float(data.get('age_at_death', 90))
monthly_salary = float(data.get('monthly_salary', 5000))
monthly_rent = float(data.get('monthly_rent', 1500))
home_cost = float(data.get('home_cost', 400000))
down_payment = float(data.get('down_payment', 80000))
monthly_expenses = float(data.get('monthly_expenses', 1500))
investment_return = float(data.get('investment_return', 6)) / 100.0
# Time horizon
years = age_at_death - current_age
months = int(years * 12)
# Simple monthly investment rate
monthly_investment_rate = investment_return / 12
# ------------------
# Renter Scenario
# ------------------
# Start with a lump sum (down payment) in investments
renter_investment_balance = down_payment
current_monthly_salary = monthly_salary
# We won't change rent monthly here in detail,
# but you could add rent growth if desired.
# For now, keep it fixed for simplicity.
for _ in range(months):
leftover_rent = current_monthly_salary - (monthly_rent + monthly_expenses)
if leftover_rent > 0:
renter_investment_balance += leftover_rent
# Grow investment
renter_investment_balance *= (1 + monthly_investment_rate)
# Well skip monthly salary growth to keep it straightforward
# but you could easily incorporate that as well.
renter_net_worth = renter_investment_balance
# ------------------
# Buyer Scenario
# ------------------
# Mortgage logic: Very simplified example
principal = home_cost - down_payment
mortgage_rate_annual = 0.04 # 4% annual, for demonstration
monthly_mortgage_rate = mortgage_rate_annual / 12
mortgage_term_years = 30
num_payments = mortgage_term_years * 12
if principal > 0:
# Standard formula
monthly_mortgage_payment = (
principal *
(monthly_mortgage_rate * (1 + monthly_mortgage_rate) ** num_payments) /
((1 + monthly_mortgage_rate) ** num_payments - 1)
)
else:
monthly_mortgage_payment = 0
# Let's assume a 1% property tax and 0.3% insurance, 0.2% maintenance, all annual,
# but it will scale with changing house value
property_tax_annual_rate = 0.01
insurance_annual_rate = 0.003
maintenance_annual_rate = 0.002
# House appreciation
annual_appreciation_rate = 0.02 # 2% annual
monthly_appreciation_rate = annual_appreciation_rate / 12
house_value = home_cost
buyer_investment_balance = 0
total_upfront = down_payment # ignoring closing costs for simplicity here
for month_index in range(months):
# Each month, update the house value first
house_value *= (1 + monthly_appreciation_rate)
# Recalc these costs based on the updated house value
monthly_taxes = (house_value * property_tax_annual_rate) / 12
monthly_insurance = (house_value * insurance_annual_rate) / 12
monthly_maintenance = (house_value * maintenance_annual_rate) / 12
# If mortgage is still active
if month_index < num_payments:
monthly_costs = monthly_mortgage_payment + monthly_taxes + monthly_insurance + monthly_maintenance
else:
monthly_costs = monthly_taxes + monthly_insurance + monthly_maintenance
leftover_buy = monthly_salary - (monthly_expenses + monthly_costs)
if leftover_buy > 0:
buyer_investment_balance += leftover_buy
# Grow leftover investment
buyer_investment_balance *= (1 + monthly_investment_rate)
homeowner_net_worth = buyer_investment_balance + house_value
# Compare
difference = homeowner_net_worth - renter_net_worth
results = {
"renter_investment_balance": f"${renter_investment_balance:,.2f}",
"homeowner_investment_balance": f"${buyer_investment_balance:,.2f}",
"final_house_value": f"${house_value:,.2f}",
"homeowner_net_worth": f"${homeowner_net_worth:,.2f}",
"renter_net_worth": f"${renter_net_worth:,.2f}",
"difference": difference
}
return jsonify(results)
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0')

160
calculator.py Normal file
View File

@@ -0,0 +1,160 @@
import math
def calculate_mortgage_payment(principal, annual_interest_rate, term_years):
"""Calculates the fixed monthly mortgage payment."""
monthly_rate = annual_interest_rate / 12
n = term_years * 12
if monthly_rate == 0:
return principal / n
payment = principal * monthly_rate / (1 - (1 + monthly_rate) ** (-n))
return payment
def simulate_own_vs_rent(params):
# Extract parameters with defaults (as provided)
start_age = params.get("start_age", 30)
end_age = params.get("end_age", 65)
total_months = (end_age - start_age) * 12
annual_income = params.get("annual_income", 60000)
annual_salary_growth = params.get("annual_salary_growth", 0.02)
home_price = params.get("home_price", 300000)
down_payment = params.get("down_payment", 60000)
mortgage_rate = params.get("mortgage_rate", 0.04)
mortgage_term = params.get("mortgage_term", 30)
property_tax_rate = params.get("property_tax_rate", 0.012)
homeowner_insurance = params.get("homeowner_insurance", 1200)
maintenance_rate = params.get("maintenance_rate", 0.01)
rent = params.get("rent", 1500)
rent_escalation_rate = params.get("rent_escalation_rate", 0.03)
renters_insurance_annual = params.get("renters_insurance_annual", 240) # ~$20/month
home_appreciation = params.get("home_appreciation", 0.03)
investment_return = params.get("investment_return", 0.05)
marginal_tax_rate = params.get("marginal_tax_rate", 0.25)
inflation_rate = params.get("inflation_rate", 0.02)
# Monthly conversion factors (using monthly compounding approximations)
monthly_salary_growth = (1 + annual_salary_growth) ** (1/12) - 1
monthly_investment_return = (1 + investment_return) ** (1/12) - 1
monthly_home_appreciation = (1 + home_appreciation) ** (1/12) - 1
monthly_rent_escalation = (1 + rent_escalation_rate) ** (1/12) - 1
# Initialize simulation variables
salary = annual_income
current_home_value = home_price
mortgage_balance = home_price - down_payment
mortgage_payment = calculate_mortgage_payment(mortgage_balance, mortgage_rate, mortgage_term)
mortgage_term_months = mortgage_term * 12
homeowner_investment = 0.0
renter_investment = down_payment # down payment is invested in the renting scenario
homeowner_debt = 0.0
renter_debt = 0.0
lifetime_income = 0.0
# For rent, we will update the current monthly rent over time
current_rent = rent
# Simulation loop (month by month)
for month in range(1, total_months + 1):
# Update lifetime income (monthly)
monthly_income = salary / 12
lifetime_income += monthly_income
# --- Homeowner Scenario ---
if month <= mortgage_term_months:
# Calculate current month's mortgage payment details
monthly_interest = mortgage_balance * (mortgage_rate / 12)
principal_payment = mortgage_payment - monthly_interest
# Adjust final payment if necessary
if principal_payment > mortgage_balance:
principal_payment = mortgage_balance
mortgage_payment = monthly_interest + principal_payment
mortgage_balance -= principal_payment
else:
mortgage_payment = 0
monthly_interest = 0
monthly_property_tax = (current_home_value * property_tax_rate) / 12
monthly_insurance = homeowner_insurance / 12
monthly_maintenance = (current_home_value * maintenance_rate) / 12
# Tax benefit applies only when mortgage (and its interest) is active.
tax_benefit = 0
if month <= mortgage_term_months:
tax_benefit = (monthly_interest + monthly_property_tax) * marginal_tax_rate
homeowner_cost = mortgage_payment + monthly_property_tax + monthly_insurance + monthly_maintenance - tax_benefit
# --- Renting Scenario ---
monthly_rent = current_rent
renters_insurance = renters_insurance_annual / 12
renting_cost = monthly_rent + renters_insurance
# --- Surplus Cash Flow ---
homeowner_surplus = monthly_income - homeowner_cost
renter_surplus = monthly_income - renting_cost
# Update investment balances (if surplus positive) or accumulate debt (if negative)
if homeowner_surplus >= 0:
homeowner_investment = homeowner_investment * (1 + monthly_investment_return) + homeowner_surplus
else:
# Debt grows with the effective investment rate
homeowner_debt = homeowner_debt * (1 + monthly_investment_return) - homeowner_surplus
if renter_surplus >= 0:
renter_investment = renter_investment * (1 + monthly_investment_return) + renter_surplus
else:
renter_debt = renter_debt * (1 + monthly_investment_return) - renter_surplus
# Update home value (appreciation)
current_home_value *= (1 + monthly_home_appreciation)
# Update salary for next month
salary *= (1 + monthly_salary_growth)
# Update rent for next month
current_rent *= (1 + monthly_rent_escalation)
final_house_value = current_home_value
# Net worth calculations: include investment balance, property value, subtract remaining mortgage and any accumulated debt.
homeowner_net_worth = final_house_value + homeowner_investment - mortgage_balance - homeowner_debt
renter_net_worth = renter_investment - renter_debt
results = {
"lifetime_income": lifetime_income,
"renter_final_investment": renter_investment,
"homeowner_final_investment": homeowner_investment,
"final_house_value": final_house_value,
"homeowner_net_worth": homeowner_net_worth,
"renter_net_worth": renter_net_worth,
"mortgage_balance": mortgage_balance, # for reference if needed
}
return results
if __name__ == "__main__":
# Run simulation with default values for testing
defaults = {
"start_age": 30,
"end_age": 65,
"annual_income": 60000,
"annual_salary_growth": 0.02,
"home_price": 300000,
"down_payment": 60000,
"mortgage_rate": 0.04,
"mortgage_term": 30,
"property_tax_rate": 0.012,
"homeowner_insurance": 1200,
"maintenance_rate": 0.01,
"rent": 1500,
"rent_escalation_rate": 0.03,
"renters_insurance_annual": 240,
"home_appreciation": 0.03,
"investment_return": 0.05,
"marginal_tax_rate": 0.25,
"inflation_rate": 0.02,
}
results = simulate_own_vs_rent(defaults)
for key, value in results.items():
print(f"{key}: {value:.2f}")

View File

@@ -1,151 +0,0 @@
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()

View File

@@ -1,240 +0,0 @@
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 = 10000.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.0 # "catch-all" category
# --- Investment Growth ---
ANNUAL_INVESTMENT_RETURN = 0.07 # 7% annual
# --- Renting Details ---
RENT_PER_MONTH = 2000.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.05 # 5% 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
# Convert your annual property tax, insurance, and maintenance to percentage rates relative to HOME_COST:
# We'll do this so we can recalculate them each month based on the new house_value.
property_tax_annual_rate = PROPERTY_TAX_RATE # e.g., 0.01
insurance_annual_rate = HOME_INSURANCE_PER_YEAR / HOME_COST # e.g., 1200 / 350000
maintenance_annual_rate = AVERAGE_YEARLY_MAINTENANCE / HOME_COST # e.g., 5000 / 350000
# ================
# 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: Update House Value, then compute monthly taxes, insurance, maintenance
house_value *= (1 + monthly_home_appreciation)
# Recalc monthly property tax, insurance, maintenance based on current house_value
dynamic_monthly_property_tax = (house_value * property_tax_annual_rate) / 12
dynamic_monthly_insurance = (house_value * insurance_annual_rate) / 12
dynamic_monthly_maintenance = (house_value * maintenance_annual_rate) / 12
if month <= number_of_payments:
monthly_ownership_cost = (
monthly_mortgage_payment +
dynamic_monthly_property_tax +
dynamic_monthly_insurance +
dynamic_monthly_maintenance
)
else:
monthly_ownership_cost = (
dynamic_monthly_property_tax +
dynamic_monthly_insurance +
dynamic_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)
# --- 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()

View File

@@ -1,142 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>Rent vs. Buy Calculator</title>
<style>
body {
font-family: Arial, sans-serif;
}
.input-section, .output-section {
margin: 20px;
}
.slider-label {
margin-right: 10px;
}
</style>
</head>
<body>
<h2>Rent vs. Buy Calculator</h2>
<p><a href="/logout">Logout</a></p>
<div class="input-section">
<h3>Input Values</h3>
<div>
<label for="currentAge">Current Age</label>
<input type="range" id="currentAge" min="20" max="70" step="1" value="30" oninput="updateDisplay('currentAgeDisplay', this.value)">
<span id="currentAgeDisplay">30</span>
</div>
<div>
<label for="ageAtDeath">Age at Death</label>
<input type="range" id="ageAtDeath" min="70" max="120" step="1" value="90" oninput="updateDisplay('ageAtDeathDisplay', this.value)">
<span id="ageAtDeathDisplay">90</span>
</div>
<div>
<label for="monthlySalary">Monthly Salary</label>
<input type="range" id="monthlySalary" min="1000" max="20000" step="500" value="5000" oninput="updateDisplay('monthlySalaryDisplay', this.value)">
<span id="monthlySalaryDisplay">5000</span>
</div>
<div>
<label for="monthlyRent">Monthly Rent</label>
<input type="range" id="monthlyRent" min="500" max="4000" step="100" value="1500" oninput="updateDisplay('monthlyRentDisplay', this.value)">
<span id="monthlyRentDisplay">1500</span>
</div>
<div>
<label for="homeCost">Home Cost</label>
<input type="range" id="homeCost" min="100000" max="1000000" step="50000" value="400000" oninput="updateDisplay('homeCostDisplay', this.value)">
<span id="homeCostDisplay">400000</span>
</div>
<div>
<label for="downPayment">Down Payment</label>
<input type="range" id="downPayment" min="0" max="400000" step="10000" value="80000" oninput="updateDisplay('downPaymentDisplay', this.value)">
<span id="downPaymentDisplay">80000</span>
</div>
<div>
<label for="monthlyExpenses">Monthly Expenses (non-housing)</label>
<input type="range" id="monthlyExpenses" min="500" max="5000" step="100" value="1500" oninput="updateDisplay('monthlyExpensesDisplay', this.value)">
<span id="monthlyExpensesDisplay">1500</span>
</div>
<div>
<label for="investmentReturn">Investment Return (%)</label>
<input type="range" id="investmentReturn" min="0" max="15" step="0.5" value="6" oninput="updateDisplay('investmentReturnDisplay', this.value)">
<span id="investmentReturnDisplay">6</span>%
</div>
<button onclick="calculate()">Calculate</button>
</div>
<div class="output-section">
<h3>Results</h3>
<p>Renter's Final Investment Balance: <span id="renterInvestment"></span></p>
<p>Homeowner's Investment Balance: <span id="homeownerInvestment"></span></p>
<p>Final House Value: <span id="houseValue"></span></p>
<p>Homeowner Net Worth: <span id="homeownerNetWorth"></span></p>
<p>Renter Net Worth: <span id="renterNetWorth"></span></p>
<h4 id="comparisonResult"></h4>
</div>
<script>
// Simple helper to update the text next to sliders
function updateDisplay(spanId, val) {
document.getElementById(spanId).innerText = val;
}
function calculate() {
// Collect the current slider/input values
let data = {
current_age: document.getElementById('currentAge').value,
age_at_death: document.getElementById('ageAtDeath').value,
monthly_salary: document.getElementById('monthlySalary').value,
monthly_rent: document.getElementById('monthlyRent').value,
home_cost: document.getElementById('homeCost').value,
down_payment: document.getElementById('downPayment').value,
monthly_expenses: document.getElementById('monthlyExpenses').value,
investment_return: document.getElementById('investmentReturn').value
};
// Send data to the server via POST /compute
fetch('/compute', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
})
.then(response => response.json())
.then(result => {
// Update the page with the returned results
document.getElementById('renterInvestment').innerText = result.renter_investment_balance;
document.getElementById('homeownerInvestment').innerText = result.homeowner_investment_balance;
document.getElementById('houseValue').innerText = result.final_house_value;
document.getElementById('homeownerNetWorth').innerText = result.homeowner_net_worth;
document.getElementById('renterNetWorth').innerText = result.renter_net_worth;
// Compare difference
let difference = result.difference;
let comparison = "";
if (difference > 0) {
comparison = `Buying is ahead by $${Math.abs(difference).toLocaleString()}.`;
// color it green
document.getElementById('comparisonResult').style.color = 'green';
} else if (difference < 0) {
comparison = `Renting is ahead by $${Math.abs(difference).toLocaleString()}.`;
// color it green
document.getElementById('comparisonResult').style.color = 'green';
} else {
comparison = "Both scenarios come out exactly the same!";
document.getElementById('comparisonResult').style.color = 'orange';
}
document.getElementById('comparisonResult').innerText = comparison;
})
.catch(err => {
console.error(err);
});
}
</script>
</body>
</html>

164
templates/index.html Normal file
View File

@@ -0,0 +1,164 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Own vs Rent Analyzer</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.slider-container { margin-bottom: 15px; }
label { display: inline-block; width: 250px; }
input[type=range] { width: 300px; }
</style>
</head>
<body>
<h1>Own vs Rent Analyzer</h1>
<div>
<div class="slider-container">
<label for="annual_income">Annual Income ($):</label>
<input type="range" id="annual_income" min="30000" max="200000" step="1000" value="60000" oninput="updateValue('annual_income')">
<span id="annual_income_val">60000</span>
</div>
<div class="slider-container">
<label for="home_price">Home Price ($):</label>
<input type="range" id="home_price" min="100000" max="1000000" step="10000" value="300000" oninput="updateValue('home_price')">
<span id="home_price_val">300000</span>
</div>
<div class="slider-container">
<label for="down_payment">Down Payment ($):</label>
<input type="range" id="down_payment" min="10000" max="500000" step="5000" value="60000" oninput="updateValue('down_payment')">
<span id="down_payment_val">60000</span>
</div>
<div class="slider-container">
<label for="mortgage_rate">Mortgage Rate (%):</label>
<input type="range" id="mortgage_rate" min="1" max="10" step="0.1" value="4" oninput="updateValue('mortgage_rate')">
<span id="mortgage_rate_val">4</span>
</div>
<div class="slider-container">
<label for="mortgage_term">Mortgage Term (years):</label>
<input type="range" id="mortgage_term" min="10" max="40" step="1" value="30" oninput="updateValue('mortgage_term')">
<span id="mortgage_term_val">30</span>
</div>
<div class="slider-container">
<label for="property_tax_rate">Property Tax Rate (%):</label>
<input type="range" id="property_tax_rate" min="0" max="5" step="0.1" value="1.2" oninput="updateValue('property_tax_rate')">
<span id="property_tax_rate_val">1.2</span>
</div>
<div class="slider-container">
<label for="homeowner_insurance">Homeowner Insurance ($/year):</label>
<input type="range" id="homeowner_insurance" min="500" max="5000" step="100" value="1200" oninput="updateValue('homeowner_insurance')">
<span id="homeowner_insurance_val">1200</span>
</div>
<div class="slider-container">
<label for="maintenance_rate">Maintenance Rate (%):</label>
<input type="range" id="maintenance_rate" min="0" max="5" step="0.1" value="1" oninput="updateValue('maintenance_rate')">
<span id="maintenance_rate_val">1</span>
</div>
<div class="slider-container">
<label for="rent">Rent ($/month):</label>
<input type="range" id="rent" min="500" max="5000" step="50" value="1500" oninput="updateValue('rent')">
<span id="rent_val">1500</span>
</div>
<div class="slider-container">
<label for="rent_escalation_rate">Rent Escalation Rate (%):</label>
<input type="range" id="rent_escalation_rate" min="0" max="10" step="0.1" value="3" oninput="updateValue('rent_escalation_rate')">
<span id="rent_escalation_rate_val">3</span>
</div>
<div class="slider-container">
<label for="home_appreciation">Home Appreciation Rate (%):</label>
<input type="range" id="home_appreciation" min="0" max="10" step="0.1" value="3" oninput="updateValue('home_appreciation')">
<span id="home_appreciation_val">3</span>
</div>
<div class="slider-container">
<label for="investment_return">Investment Return (%):</label>
<input type="range" id="investment_return" min="0" max="15" step="0.1" value="5" oninput="updateValue('investment_return')">
<span id="investment_return_val">5</span>
</div>
<div class="slider-container">
<label for="marginal_tax_rate">Marginal Tax Rate (%):</label>
<input type="range" id="marginal_tax_rate" min="0" max="50" step="1" value="25" oninput="updateValue('marginal_tax_rate')">
<span id="marginal_tax_rate_val">25</span>
</div>
<div class="slider-container">
<label for="inflation_rate">Inflation Rate (%):</label>
<input type="range" id="inflation_rate" min="0" max="10" step="0.1" value="2" oninput="updateValue('inflation_rate')">
<span id="inflation_rate_val">2</span>
</div>
<div class="slider-container">
<label for="start_age">Start Age:</label>
<input type="range" id="start_age" min="18" max="70" step="1" value="30" oninput="updateValue('start_age')">
<span id="start_age_val">30</span>
</div>
<div class="slider-container">
<label for="end_age">End Age:</label>
<input type="range" id="end_age" min="30" max="100" step="1" value="65" oninput="updateValue('end_age')">
<span id="end_age_val">65</span>
</div>
<button onclick="runSimulation()">Run Simulation</button>
</div>
<h2>Results</h2>
<div id="results">
<p id="renter_investment"></p>
<p id="homeowner_investment"></p>
<p id="final_house_value"></p>
<p id="homeowner_net_worth"></p>
<p id="renter_net_worth"></p>
<p id="lifetime_income"></p>
<p id="comparison"></p>
</div>
<script>
function updateValue(id) {
var val = document.getElementById(id).value;
document.getElementById(id + '_val').innerText = val;
}
function runSimulation() {
// Gather parameters from the sliders
var params = {
annual_income: parseFloat(document.getElementById('annual_income').value),
home_price: parseFloat(document.getElementById('home_price').value),
down_payment: parseFloat(document.getElementById('down_payment').value),
mortgage_rate: parseFloat(document.getElementById('mortgage_rate').value) / 100,
mortgage_term: parseFloat(document.getElementById('mortgage_term').value),
property_tax_rate: parseFloat(document.getElementById('property_tax_rate').value) / 100,
homeowner_insurance: parseFloat(document.getElementById('homeowner_insurance').value),
maintenance_rate: parseFloat(document.getElementById('maintenance_rate').value) / 100,
rent: parseFloat(document.getElementById('rent').value),
rent_escalation_rate: parseFloat(document.getElementById('rent_escalation_rate').value) / 100,
home_appreciation: parseFloat(document.getElementById('home_appreciation').value) / 100,
investment_return: parseFloat(document.getElementById('investment_return').value) / 100,
marginal_tax_rate: parseFloat(document.getElementById('marginal_tax_rate').value) / 100,
inflation_rate: parseFloat(document.getElementById('inflation_rate').value) / 100,
start_age: parseFloat(document.getElementById('start_age').value),
end_age: parseFloat(document.getElementById('end_age').value),
annual_salary_growth: 0.02, // fixed for now
renters_insurance_annual: 240
};
// Send the parameters to the backend /calculate endpoint via POST
fetch('/calculate', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(params)
})
.then(response => response.json())
.then(data => {
document.getElementById('renter_investment').innerText = "Renter's Final Investment Balance: $" + data.renter_final_investment.toFixed(2);
document.getElementById('homeowner_investment').innerText = "Homeowner's Final Investment Balance: $" + data.homeowner_final_investment.toFixed(2);
document.getElementById('final_house_value').innerText = "Final House Value: $" + data.final_house_value.toFixed(2);
document.getElementById('homeowner_net_worth').innerText = "Homeowner Net Worth: $" + data.homeowner_net_worth.toFixed(2);
document.getElementById('renter_net_worth').innerText = "Renter Net Worth: $" + data.renter_net_worth.toFixed(2);
document.getElementById('lifetime_income').innerText = "Lifetime Income: $" + data.lifetime_income.toFixed(2);
var comparison = data.homeowner_net_worth > data.renter_net_worth ?
"Home ownership is better over the set duration." :
"Renting is better over the set duration.";
document.getElementById('comparison').innerText = comparison;
});
}
</script>
</body>
</html>

View File

@@ -1,18 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
</head>
<body>
<h2>Login</h2>
{% if error %}
<p style="color: red;">{{ error }}</p>
{% endif %}
<form method="POST">
<label>Username: <input type="text" name="username"></label><br><br>
<label>Password: <input type="password" name="password"></label><br><br>
<input type="submit" value="Login">
</form>
</body>
</html>