From da043bf95245fbbe52ec9cb83ebf53fa9d53c135 Mon Sep 17 00:00:00 2001 From: Eli Date: Thu, 13 Feb 2025 18:07:05 -0500 Subject: [PATCH] start web app --- app.py | 161 +++++++++++++++++++++++++++++++++++++++++++++++++ own_vs_buy2.py | 45 ++++++++------ 2 files changed, 187 insertions(+), 19 deletions(-) create mode 100644 app.py diff --git a/app.py b/app.py new file mode 100644 index 0000000..f7ba96a --- /dev/null +++ b/app.py @@ -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) + diff --git a/own_vs_buy2.py b/own_vs_buy2.py index f1cb7ca..aa034c7 100644 --- a/own_vs_buy2.py +++ b/own_vs_buy2.py @@ -23,7 +23,7 @@ def main(): total_months = total_years * 12 # --- 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 # --- Inflation for Monthly Expenses --- @@ -34,13 +34,13 @@ def main(): BASE_TRAVEL = 200.0 BASE_SCHOOLING = 300.0 BASE_HEALTHCARE = 400.0 - BASE_INCIDENTALS = 2500 # "catch-all" category + BASE_INCIDENTALS = 2500.0 # "catch-all" category # --- Investment Growth --- - ANNUAL_INVESTMENT_RETURN = 0.06 # 6% annual + ANNUAL_INVESTMENT_RETURN = 0.07 # 7% annual # --- Renting Details --- - RENT_PER_MONTH = 1500.0 + RENT_PER_MONTH = 2000.0 ANNUAL_RENT_GROWTH = 0.025 # 2.5% annual # --- Buying Details --- @@ -55,7 +55,7 @@ def main(): AVERAGE_YEARLY_MAINTENANCE = 5000.0 # Home appreciation (positive or negative) - ANNUAL_HOME_APPRECIATION = 0.02 # 2% per year + ANNUAL_HOME_APPRECIATION = 0.05 # 5% per year # ================ # Display Assumptions @@ -118,9 +118,11 @@ def main(): 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 + # 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 @@ -155,31 +157,36 @@ def main(): rent_investment_balance += leftover_rent 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: monthly_ownership_cost = ( monthly_mortgage_payment + - monthly_property_tax + - monthly_insurance + - monthly_maintenance + dynamic_monthly_property_tax + + dynamic_monthly_insurance + + dynamic_monthly_maintenance ) else: monthly_ownership_cost = ( - monthly_property_tax + - monthly_insurance + - monthly_maintenance + 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) - # House Appreciation - house_value *= (1 + monthly_home_appreciation) - - # Increase Salary, Rent, Standard Expenses (monthly 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)