Spaces:
Paused
Paused
| import gradio as gr | |
| import pandas as pd | |
| # Format currency values | |
| def format_currency(value): | |
| return f"${value:,.2f}" if isinstance(value, (int, float)) else value | |
| # Mortgage Loan Calculation with Amortization Schedule | |
| def mortgage_simulation(home_price, interest_rate, down_payment_pct, closing_costs, annual_home_price_rate, term_years): | |
| down_payment_pct /= 100 # Convert percentage to decimal | |
| annual_home_price_rate /= 100 # Convert percentage to decimal | |
| interest_rate /= 100 # Convert percentage to decimal | |
| loan_amount = home_price * (1 - down_payment_pct) # Loan after down payment | |
| monthly_interest_rate = interest_rate / 12 | |
| total_months = term_years * 12 | |
| # Calculate fixed monthly mortgage payment (P&I) | |
| monthly_payment = (loan_amount * monthly_interest_rate) / (1 - (1 + monthly_interest_rate) ** -total_months) | |
| outstanding_balance = loan_amount | |
| cumulative_principal = 0 | |
| cumulative_interest = 0 | |
| cumulative_total_paid = 0 | |
| cumulative_home_value = home_price | |
| amortization_schedule = [] | |
| for month in range(1, total_months + 1): | |
| interest_payment = outstanding_balance * monthly_interest_rate | |
| principal_payment = monthly_payment - interest_payment | |
| outstanding_balance -= principal_payment | |
| cumulative_principal += principal_payment | |
| cumulative_interest += interest_payment | |
| cumulative_total_paid += monthly_payment | |
| # Annual home price appreciation | |
| if month % 12 == 1 and month > 1: | |
| cumulative_home_value *= (1 + annual_home_price_rate) | |
| # Ensure outstanding balance reaches exactly 0 at the last month | |
| if month == total_months: | |
| outstanding_balance = 0 | |
| amortization_schedule.append([ | |
| month, monthly_payment, principal_payment, interest_payment, outstanding_balance, | |
| cumulative_principal, cumulative_interest, cumulative_total_paid, cumulative_home_value | |
| ]) | |
| df = pd.DataFrame(amortization_schedule, columns=[ | |
| "Month", "Monthly Payment", "Principal Payment", "Interest Payment", "Outstanding Balance", | |
| "Cumulative Principal", "Cumulative Interest", "Cumulative Total Paid", "Home Value" | |
| ]) | |
| # β Extract numerical values BEFORE formatting | |
| down_payment_amount = home_price * down_payment_pct | |
| final_home_value = df["Home Value"].astype(float).max() | |
| total_paid = df["Cumulative Total Paid"].astype(float).max() | |
| # Final row with total amounts (before formatting) | |
| total_row = pd.DataFrame([[ | |
| "TOTAL", monthly_payment, df["Principal Payment"].sum(), df["Interest Payment"].sum(), "", | |
| df["Cumulative Principal"].max(), df["Cumulative Interest"].max(), df["Cumulative Total Paid"].max(), | |
| final_home_value | |
| ]], columns=df.columns) | |
| df = pd.concat([df, total_row], ignore_index=True) | |
| # β Apply currency formatting **AFTER** extracting numerical values | |
| currency_columns = [ | |
| "Monthly Payment", "Principal Payment", "Interest Payment", "Outstanding Balance", | |
| "Cumulative Principal", "Cumulative Interest", "Cumulative Total Paid", "Home Value" | |
| ] | |
| for col in currency_columns: | |
| df[col] = df[col].apply(format_currency) | |
| # β Increased Font Size for Highlights | |
| highlights = f""" | |
| <div style="font-size:20px; "> | |
| π‘ <b>Mortgage Summary</b><br> | |
| π° <b>Down Payment:</b> {format_currency(down_payment_amount)}<br> | |
| π° <b>Monthly Payment:</b> {format_currency(monthly_payment)}<br> | |
| π° <b>Closing Costs:</b> {format_currency(closing_costs)}<br><br> | |
| π <b>Term:</b> {term_years} years<br> | |
| π΅ <b>Total Paid Over Loan:</b> {format_currency(total_paid)}<br> | |
| π <b>Final Home Value:</b> {format_currency(final_home_value)} | |
| </div> | |
| """ | |
| return df, highlights | |
| def calculate_installments(total_credit, total_months, annual_adjustment_rate, admin_fee, reserve_fund_fee, | |
| month_selected=None): | |
| annual_adjustment_rate /= 100 | |
| admin_fee /= 100 | |
| reserve_fund_fee /= 100 | |
| total_years = int(total_months / 12) | |
| total_fees = admin_fee + reserve_fund_fee | |
| total_debt = total_credit * (1 + total_fees) | |
| monthly_group_installment = total_credit / total_months | |
| monthly_admin_fee = (total_credit * admin_fee) / total_months | |
| monthly_reserve_fund_fee = (total_credit * reserve_fund_fee) / total_months | |
| installments = [] | |
| outstanding_balance_group = total_credit | |
| outstanding_balance_admin = total_credit * admin_fee | |
| outstanding_balance_reserve = total_credit * reserve_fund_fee | |
| cumulative_group_fund = 0 | |
| cumulative_admin_fee = 0 | |
| cumulative_reserve_fund = 0 | |
| cumulative_total_installment = 0 | |
| for month in range(1, total_months + 1): | |
| if month_selected and month < month_selected: | |
| monthly_group_installment = (total_credit / total_months) / 2 # Half before the selected month | |
| elif month_selected and month == month_selected: | |
| remaining_months = total_months - month + 1 | |
| monthly_group_installment = outstanding_balance_group / remaining_months | |
| if month % 12 == 1 and month > 1: # Apply annual adjustment | |
| outstanding_balance_group *= (1 + annual_adjustment_rate) | |
| outstanding_balance_admin *= (1 + annual_adjustment_rate) | |
| outstanding_balance_reserve *= (1 + annual_adjustment_rate) | |
| monthly_group_installment *= (1 + annual_adjustment_rate) | |
| monthly_admin_fee *= (1 + annual_adjustment_rate) | |
| monthly_reserve_fund_fee *= (1 + annual_adjustment_rate) | |
| total_credit *= (1 + annual_adjustment_rate) | |
| total_installment = monthly_group_installment + monthly_admin_fee + monthly_reserve_fund_fee | |
| outstanding_balance_group -= monthly_group_installment | |
| outstanding_balance_admin -= monthly_admin_fee | |
| outstanding_balance_reserve -= monthly_reserve_fund_fee | |
| # Update cumulative values | |
| cumulative_group_fund += monthly_group_installment | |
| cumulative_admin_fee += monthly_admin_fee | |
| cumulative_reserve_fund += monthly_reserve_fund_fee | |
| cumulative_total_installment += total_installment | |
| # Ensure the outstanding balances are exactly 0 at the last month | |
| if month == total_months: | |
| outstanding_balance_group = 0 | |
| outstanding_balance_admin = 0 | |
| outstanding_balance_reserve = 0 | |
| installments.append([ | |
| total_credit, month, monthly_group_installment, monthly_admin_fee, | |
| monthly_reserve_fund_fee, total_installment, outstanding_balance_group, | |
| outstanding_balance_admin, outstanding_balance_reserve, | |
| cumulative_group_fund, cumulative_admin_fee, cumulative_reserve_fund, cumulative_total_installment | |
| ]) | |
| df = pd.DataFrame(installments, columns=[ | |
| "Credit Amount", "Month", "Group Fund", "Admin Fee", "Reserve Fund", | |
| "Total Installment", "Outstanding Balance (Group Fund)", | |
| "Outstanding Balance (Admin Fee)", "Outstanding Balance (Reserve Fund)", | |
| "Cumulative Group Fund", "Cumulative Admin Fee", "Cumulative Reserve Fund", | |
| "Cumulative Total Installment" | |
| ]) | |
| # Calculate totals | |
| total_group_fund = df["Group Fund"].sum() | |
| total_admin_fee = df["Admin Fee"].sum() | |
| total_reserve_fund = df["Reserve Fund"].sum() | |
| total_installments = df["Total Installment"].sum() | |
| total_cumulative_group_fund = df["Cumulative Group Fund"].max() | |
| total_cumulative_admin_fee = df["Cumulative Admin Fee"].max() | |
| total_cumulative_reserve_fund = df["Cumulative Reserve Fund"].max() | |
| total_cumulative_total_installment = df["Cumulative Total Installment"].max() | |
| # Append total row | |
| total_row = pd.DataFrame([[ | |
| "TOTAL", "", total_group_fund, total_admin_fee, total_reserve_fund, | |
| total_installments, "", "", "", | |
| total_cumulative_group_fund, total_cumulative_admin_fee, total_cumulative_reserve_fund, | |
| total_cumulative_total_installment | |
| ]], columns=df.columns) | |
| df = pd.concat([df, total_row], ignore_index=True) | |
| # Format columns as currency except for "Month" and empty total row values | |
| currency_columns = [ | |
| "Credit Amount", "Group Fund", "Admin Fee", "Reserve Fund", "Total Installment", | |
| "Outstanding Balance (Group Fund)", "Outstanding Balance (Admin Fee)", "Outstanding Balance (Reserve Fund)", | |
| "Cumulative Group Fund", "Cumulative Admin Fee", "Cumulative Reserve Fund", "Cumulative Total Installment" | |
| ] | |
| df[currency_columns] = df[currency_columns].applymap(lambda x: f"${x:,.2f}" if isinstance(x, (int, float)) else x) | |
| # Extract summary values | |
| first_group_fund_payment = df.iloc[0]["Group Fund"] | |
| admin_fee_payment = df.iloc[0]["Admin Fee"] | |
| reserve_fund_payment = df.iloc[0]["Reserve Fund"] | |
| # Convert from formatted currency (string) to float | |
| first_group_fund_payment = float(str(first_group_fund_payment).replace("$", "").replace(",", "")) | |
| admin_fee_payment = float(str(admin_fee_payment).replace("$", "").replace(",", "")) | |
| reserve_fund_payment = float(str(reserve_fund_payment).replace("$", "").replace(",", "")) | |
| # Calculate the correct Monthly Payment | |
| if month_selected: | |
| monthly_payment = first_group_fund_payment + admin_fee_payment + reserve_fund_payment | |
| else: | |
| monthly_payment = (first_group_fund_payment / 2) + admin_fee_payment + reserve_fund_payment | |
| total_paid = total_cumulative_total_installment | |
| final_home_value = df.iloc[-2]["Credit Amount"] # Last adjusted credit amount | |
| # Format summary | |
| summary = f""" | |
| <div style="font-size:20px; "> | |
| π‘ <b>Consortium Summary</b><br> | |
| π° <b>Down Payment:</b> $0.00<br> | |
| π° <b>Monthly Payment:</b> {format_currency(monthly_payment)}<br> | |
| π° <b>Closing Costs:</b> $0.00<br><br> | |
| π <b>Term:</b> {total_years} years<br> | |
| π΅ <b>Total Paid at the End:</b> {format_currency(total_paid)}<br> | |
| π <b>Final Home Value:</b> {format_currency(final_home_value)} | |
| </div> | |
| """ | |
| return df, summary | |
| def gradio_interface(total_credit, total_months, annual_adjustment_rate, admin_fee, reserve_fund_fee, month_selected): | |
| df, summary = calculate_installments(total_credit, total_months, annual_adjustment_rate, admin_fee, | |
| reserve_fund_fee, | |
| month_selected) | |
| return df, summary | |
| # Gradio UI for Mortgage Loan Simulator | |
| with gr.Blocks() as mortgage_ui: | |
| gr.Markdown("# π‘ Mortgage Loan Calculator") | |
| gr.Markdown( | |
| "Simulates a traditional mortgage loan, calculating monthly payments, principal and interest breakdown, " | |
| "and tracking home value appreciation over time.") | |
| with gr.Row(): | |
| home_price = gr.Number(value=600000, label="Home Price ($)", precision=2) | |
| interest_rate = gr.Number(value=6.5, label="Annual Interest Rate (%)", precision=2) # Use whole number | |
| down_payment_pct = gr.Number(value=20, label="Down Payment (%)", precision=2) # Use whole number | |
| closing_costs = gr.Number(value=10000, label="Closing Costs ($)", precision=2) | |
| annual_home_price_rate = gr.Number(value=1.5, label="Annual Home Price Increase (%)", precision=2) # Use whole number | |
| term_years = gr.Number(value=30, label="Loan Term (Years)", precision=0) | |
| output_df = gr.Dataframe() | |
| output_highlights = gr.HTML() # β Change to HTML to apply font-size styles | |
| btn = gr.Button("Calculate") | |
| btn.click(mortgage_simulation, | |
| inputs=[home_price, interest_rate, down_payment_pct, closing_costs, annual_home_price_rate, term_years], | |
| outputs=[output_df, output_highlights]) | |
| with gr.Blocks() as consortium_ui: | |
| gr.Markdown("# π‘ Consortium Installment Calculator") | |
| gr.Markdown( | |
| "Generates a financial projection for a consortium with annual adjustments. Optionally adjust group fund calculations from a selected month.") | |
| with gr.Row(): | |
| total_credit = gr.Number(value=600000, label="Total Credit Amount") | |
| total_months = gr.Number(value=240, label="Total Months") | |
| annual_adjustment_rate = gr.Number(value=1.5, label="Annual Adjustment Rate (%)") | |
| admin_fee = gr.Number(value=19.0, label="Admin Fee (%)") | |
| reserve_fund_fee = gr.Number(value=1.0, label="Reserve Fund Fee (%)") | |
| month_selected = gr.Number(label="Month Participant Got Selected (Optional)") | |
| output_df = gr.Dataframe() | |
| highlights_output = gr.HTML(label="Consortium Summary") | |
| btn = gr.Button("Calculate") | |
| btn.click(gradio_interface, | |
| inputs=[total_credit, total_months, annual_adjustment_rate, admin_fee, reserve_fund_fee, month_selected], | |
| outputs=[output_df, highlights_output]) | |
| # β Integrate this into a Tabbed Interface | |
| app = gr.TabbedInterface([mortgage_ui, consortium_ui], ["Mortgage Loan Simulator", "Consortium Installment Calculator"]) | |
| app.launch(share=True) | |