Synthack-SyntaxSquad / src /frontend /loan_prediction.py
WickedFaith's picture
Upload 77 files
3efedb0 verified
raw
history blame contribute delete
12.3 kB
import streamlit as st
import requests
import pandas as pd
import plotly.express as px
import traceback
# API endpoint
API_URL = "http://127.0.0.1:8000/predict"
def show_loan_prediction():
st.title("Loan Approval Prediction System")
# Create sidebar for inputs
with st.sidebar:
st.header("Loan Application Details")
# Personal information
st.subheader("Personal Information")
no_of_dependents = st.slider("Number of Dependents", 0, 10, 2)
education = st.selectbox("Education", ["Graduate", "Not Graduate"])
self_employed = st.selectbox("Self Employed", ["Yes", "No"])
# Financial information
st.subheader("Financial Information")
income_annum = st.number_input("Annual Income (₹)", min_value=100000, max_value=20000000, value=5000000, step=100000)
loan_amount = st.number_input("Loan Amount (₹)", min_value=100000, max_value=50000000, value=10000000, step=100000)
loan_term = st.slider("Loan Term (years)", 2, 30, 15)
cibil_score = st.slider("CIBIL Score", 300, 900, 650)
# Assets information
st.subheader("Assets Information")
residential_assets_value = st.number_input("Residential Assets Value (₹)", min_value=0, max_value=50000000, value=5000000, step=100000)
commercial_assets_value = st.number_input("Commercial Assets Value (₹)", min_value=0, max_value=50000000, value=2000000, step=100000)
luxury_assets_value = st.number_input("Luxury Assets Value (₹)", min_value=0, max_value=50000000, value=1000000, step=100000)
bank_asset_value = st.number_input("Bank Assets Value (₹)", min_value=0, max_value=50000000, value=3000000, step=100000)
# Submit button
predict_button = st.button("Predict Loan Approval")
# Main content area
if predict_button or ('prediction_result' in st.session_state and st.session_state.prediction_result):
# If button was just pressed, API call happens
if predict_button:
# Prepare data for API
data = {
"no_of_dependents": no_of_dependents,
"education": education,
"self_employed": self_employed,
"income_annum": income_annum,
"loan_amount": loan_amount,
"loan_term": loan_term,
"cibil_score": cibil_score,
"residential_assets_value": residential_assets_value,
"commercial_assets_value": commercial_assets_value,
"luxury_assets_value": luxury_assets_value,
"bank_asset_value": bank_asset_value
}
# Call API
with st.spinner("Predicting..."):
try:
# Update the API endpoint to use the specific loan endpoint
response = requests.post(
"http://127.0.0.1:8000/predict/loan",
json={"features": data}
)
if response.status_code == 200:
result = response.json()
# Store result in session state
st.session_state.prediction_result = result
st.session_state.loan_data = data
except Exception as e:
st.error(f"Error connecting to API: {str(e)}")
st.error(traceback.format_exc())
st.info("Make sure the FastAPI backend is running with: python -m uvicorn src.api.main:app --reload")
return
# Use stored result if available
if 'prediction_result' in st.session_state:
result = st.session_state.prediction_result
data = st.session_state.loan_data
# Display prediction result
if result["prediction"]:
st.success("### Loan Approved! ✅")
else:
st.error("### Loan Rejected ❌")
# Display approval probability
col1, col2 = st.columns(2)
with col1:
st.subheader("Explanation")
st.write("Based on your financial profile and application details, here's why your loan was approved/rejected.")
# Display factors affecting application
st.subheader("Factors Affecting Your Application")
# Create feature importance dataframe
feature_names = [
"CIBIL Score",
"Annual Income",
"Loan Amount",
"Loan Term",
"Residential Assets",
"Commercial Assets",
"Luxury Assets",
"Bank Assets",
"Dependents",
"Education",
"Self Employed"
]
# Make sure we have the right number of feature names
importance_values = result.get("feature_importance", [])
# If no feature importance is returned, create dummy values
if not importance_values:
importance_values = [0.2, 0.15, 0.15, 0.1, 0.1, 0.08, 0.07, 0.05, 0.05, 0.03, 0.02]
# Adjust lengths if needed
if len(importance_values) != len(feature_names):
if len(importance_values) > len(feature_names):
feature_names = feature_names + [f"Feature {i+1}" for i in range(len(feature_names), len(importance_values))]
else:
importance_values = importance_values + [0] * (len(feature_names) - len(importance_values))
# Create and sort the dataframe
importance_df = pd.DataFrame({
"Feature": feature_names[:len(importance_values)],
"Importance": importance_values
})
importance_df = importance_df.sort_values("Importance", ascending=False)
# Create the bar chart
fig = px.bar(
importance_df,
x="Importance",
y="Feature",
orientation='h',
color="Importance",
color_continuous_scale=px.colors.sequential.Blues
)
fig.update_layout(
margin=dict(l=20, r=20, t=30, b=20),
height=400
)
st.plotly_chart(fig, use_container_width=True)
with col2:
# Display approval probability
st.subheader("Approval Probability")
st.markdown("### Confidence")
probability = result["probability"] * 100
st.markdown(f"### {probability:.2f}%")
# Display financial metrics
st.subheader("Application Summary")
st.subheader("Detailed Financial Metrics")
metrics_col1, metrics_col2, metrics_col3 = st.columns(3)
with metrics_col1:
st.markdown("**CIBIL Score**")
st.markdown(f"### {data['cibil_score']}")
if data['cibil_score'] >= 700:
st.markdown("Good - Favorable credit history")
elif data['cibil_score'] >= 600:
st.markdown("Fair - Average credit history")
else:
st.markdown("Poor - Unfavorable credit history")
with metrics_col2:
# Calculate debt-to-income ratio
monthly_income = data['income_annum'] / 12
loan_amount = data['loan_amount']
interest_rate = 0.08 # Assuming 8% interest rate
loan_term_months = data['loan_term'] * 12
# Calculate monthly payment using the formula: P = L[i(1+i)^n]/[(1+i)^n-1]
monthly_interest = interest_rate / 12
monthly_payment = loan_amount * (monthly_interest * (1 + monthly_interest) ** loan_term_months) / ((1 + monthly_interest) ** loan_term_months - 1)
debt_to_income = monthly_payment / monthly_income
st.markdown("**Debt-to-Income**")
st.markdown(f"### {debt_to_income:.2f}")
if debt_to_income <= 0.36:
st.markdown("Low - Manageable debt burden")
elif debt_to_income <= 0.43:
st.markdown("Medium - Moderate debt burden")
else:
st.markdown("High - Significant debt burden")
with metrics_col3:
# Calculate assets-to-loan ratio
total_assets = data['residential_assets_value'] + data['commercial_assets_value'] + data['luxury_assets_value'] + data['bank_asset_value']
assets_to_loan = total_assets / loan_amount
st.markdown("**Assets-to-Loan**")
st.markdown(f"### {assets_to_loan:.2f}")
if assets_to_loan >= 2:
st.markdown("Strong - Excellent asset coverage")
elif assets_to_loan >= 1:
st.markdown("Fair - Minimal asset coverage")
else:
st.markdown("Weak - Insufficient asset coverage")
# Monthly payment analysis
st.subheader("Monthly Payment Analysis")
payment_col1, payment_col2 = st.columns(2)
with payment_col1:
st.markdown("**Monthly Payment**")
st.markdown(f"### ₹{monthly_payment:,.2f}")
payment_ratio = monthly_payment / monthly_income
payment_percentage = payment_ratio * 100
st.markdown(f"This represents {payment_percentage:.2f}% of your monthly income (₹{monthly_income:,.2f}).")
if payment_ratio <= 0.28:
st.markdown("Excellent - Very affordable payment")
elif payment_ratio <= 0.36:
st.markdown("Good - Affordable payment")
elif payment_ratio <= 0.43:
st.markdown("Fair - Manageable payment")
else:
st.markdown("Poor - High payment burden")
with payment_col2:
# Create pie chart for income allocation
remaining_income = monthly_income - monthly_payment
income_allocation = pd.DataFrame({
'Category': ['Loan Payment', 'Remaining Income'],
'Amount': [monthly_payment, remaining_income]
})
fig = px.pie(
income_allocation,
values='Amount',
names='Category',
color_discrete_sequence=['#FF9900', '#0066CC'],
hole=0.4
)
fig.update_layout(
margin=dict(l=20, r=20, t=20, b=20),
height=200
)
st.plotly_chart(fig, use_container_width=True)