mirror of
https://github.com/elisspace/own_vs_buy.git
synced 2026-08-29 15:44:04 +00:00
start web app
This commit is contained in:
161
app.py
Normal file
161
app.py
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
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)
|
||||||
|
|
||||||
|
# We’ll 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)
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ def main():
|
|||||||
total_months = total_years * 12
|
total_months = total_years * 12
|
||||||
|
|
||||||
# --- Income & Growth ---
|
# --- Income & Growth ---
|
||||||
MONTHLY_SALARY = 5000.0 # Initial monthly salary
|
MONTHLY_SALARY = 10000.0 # Initial monthly salary
|
||||||
ANNUAL_SALARY_GROWTH = 0.02 # 2% annual salary increase
|
ANNUAL_SALARY_GROWTH = 0.02 # 2% annual salary increase
|
||||||
|
|
||||||
# --- Inflation for Monthly Expenses ---
|
# --- Inflation for Monthly Expenses ---
|
||||||
@@ -34,13 +34,13 @@ def main():
|
|||||||
BASE_TRAVEL = 200.0
|
BASE_TRAVEL = 200.0
|
||||||
BASE_SCHOOLING = 300.0
|
BASE_SCHOOLING = 300.0
|
||||||
BASE_HEALTHCARE = 400.0
|
BASE_HEALTHCARE = 400.0
|
||||||
BASE_INCIDENTALS = 2500 # "catch-all" category
|
BASE_INCIDENTALS = 2500.0 # "catch-all" category
|
||||||
|
|
||||||
# --- Investment Growth ---
|
# --- Investment Growth ---
|
||||||
ANNUAL_INVESTMENT_RETURN = 0.06 # 6% annual
|
ANNUAL_INVESTMENT_RETURN = 0.07 # 7% annual
|
||||||
|
|
||||||
# --- Renting Details ---
|
# --- Renting Details ---
|
||||||
RENT_PER_MONTH = 1500.0
|
RENT_PER_MONTH = 2000.0
|
||||||
ANNUAL_RENT_GROWTH = 0.025 # 2.5% annual
|
ANNUAL_RENT_GROWTH = 0.025 # 2.5% annual
|
||||||
|
|
||||||
# --- Buying Details ---
|
# --- Buying Details ---
|
||||||
@@ -55,7 +55,7 @@ def main():
|
|||||||
AVERAGE_YEARLY_MAINTENANCE = 5000.0
|
AVERAGE_YEARLY_MAINTENANCE = 5000.0
|
||||||
|
|
||||||
# Home appreciation (positive or negative)
|
# Home appreciation (positive or negative)
|
||||||
ANNUAL_HOME_APPRECIATION = 0.02 # 2% per year
|
ANNUAL_HOME_APPRECIATION = 0.05 # 5% per year
|
||||||
|
|
||||||
# ================
|
# ================
|
||||||
# Display Assumptions
|
# Display Assumptions
|
||||||
@@ -118,9 +118,11 @@ def main():
|
|||||||
else:
|
else:
|
||||||
monthly_mortgage_payment = 0.0
|
monthly_mortgage_payment = 0.0
|
||||||
|
|
||||||
monthly_property_tax = (HOME_COST * PROPERTY_TAX_RATE) / 12
|
# Convert your annual property tax, insurance, and maintenance to percentage rates relative to HOME_COST:
|
||||||
monthly_insurance = HOME_INSURANCE_PER_YEAR / 12
|
# We'll do this so we can recalculate them each month based on the new house_value.
|
||||||
monthly_maintenance = AVERAGE_YEARLY_MAINTENANCE / 12
|
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
|
# Part 3: Tracking & Simulation
|
||||||
@@ -155,31 +157,36 @@ def main():
|
|||||||
rent_investment_balance += leftover_rent
|
rent_investment_balance += leftover_rent
|
||||||
rent_investment_balance *= (1 + monthly_investment_growth)
|
rent_investment_balance *= (1 + monthly_investment_growth)
|
||||||
|
|
||||||
# --- Buying: Pay Mortgage/Costs, Invest Leftover
|
# --- 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:
|
if month <= number_of_payments:
|
||||||
monthly_ownership_cost = (
|
monthly_ownership_cost = (
|
||||||
monthly_mortgage_payment +
|
monthly_mortgage_payment +
|
||||||
monthly_property_tax +
|
dynamic_monthly_property_tax +
|
||||||
monthly_insurance +
|
dynamic_monthly_insurance +
|
||||||
monthly_maintenance
|
dynamic_monthly_maintenance
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
monthly_ownership_cost = (
|
monthly_ownership_cost = (
|
||||||
monthly_property_tax +
|
dynamic_monthly_property_tax +
|
||||||
monthly_insurance +
|
dynamic_monthly_insurance +
|
||||||
monthly_maintenance
|
dynamic_monthly_maintenance
|
||||||
)
|
)
|
||||||
|
|
||||||
total_buy_cost += monthly_ownership_cost
|
total_buy_cost += monthly_ownership_cost
|
||||||
|
|
||||||
leftover_buy = current_monthly_salary - current_standard_expenses - monthly_ownership_cost
|
leftover_buy = current_monthly_salary - current_standard_expenses - monthly_ownership_cost
|
||||||
if leftover_buy > 0:
|
if leftover_buy > 0:
|
||||||
buy_investment_balance += leftover_buy
|
buy_investment_balance += leftover_buy
|
||||||
buy_investment_balance *= (1 + monthly_investment_growth)
|
buy_investment_balance *= (1 + monthly_investment_growth)
|
||||||
|
|
||||||
# House Appreciation
|
# --- Increase Salary, Rent, Standard Expenses (monthly growth)
|
||||||
house_value *= (1 + monthly_home_appreciation)
|
|
||||||
|
|
||||||
# Increase Salary, Rent, Standard Expenses (monthly growth)
|
|
||||||
current_monthly_salary *= (1 + monthly_salary_growth)
|
current_monthly_salary *= (1 + monthly_salary_growth)
|
||||||
current_rent *= (1 + monthly_rent_growth)
|
current_rent *= (1 + monthly_rent_growth)
|
||||||
current_standard_expenses *= (1 + monthly_inflation)
|
current_standard_expenses *= (1 + monthly_inflation)
|
||||||
|
|||||||
Reference in New Issue
Block a user