DHF_Calculator / main.py
llatos's picture
Upload folder using huggingface_hub
b7d3211 verified
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)