Spaces:
Sleeping
Sleeping
import streamlit as st | |
import pandas as pd | |
import numpy as np | |
import plotly.graph_objects as go | |
import plotly.express as px | |
from datetime import datetime, timedelta | |
import json | |
# Custom CSS with Tailwind-like utilities | |
def load_css(): | |
st.markdown(""" | |
<style> | |
/* Tailwind-inspired utilities */ | |
.dashboard-card { | |
background-color: white; | |
border-radius: 0.5rem; | |
padding: 1.5rem; | |
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1); | |
margin-bottom: 1rem; | |
} | |
.metric-card { | |
background-color: #f8fafc; | |
border-radius: 0.375rem; | |
padding: 1rem; | |
margin: 0.5rem 0; | |
border: 1px solid #e2e8f0; | |
} | |
.metric-title { | |
color: #64748b; | |
font-size: 0.875rem; | |
font-weight: 500; | |
margin-bottom: 0.5rem; | |
} | |
.metric-value { | |
color: #1e293b; | |
font-size: 1.5rem; | |
font-weight: 600; | |
} | |
.risk-high { | |
color: #dc2626; | |
} | |
.risk-moderate { | |
color: #d97706; | |
} | |
.risk-low { | |
color: #059669; | |
} | |
/* Custom Streamlit modifications */ | |
.stApp { | |
background-color: #f1f5f9; | |
} | |
.css-1d391kg { | |
padding: 1rem 1rem; | |
} | |
</style> | |
""", unsafe_allow_html=True) | |
class FinancialDashboard: | |
def __init__(self): | |
self.risk_analyzer = FinancialRiskAnalyzer() | |
load_css() | |
def run(self): | |
st.set_page_config( | |
page_title="Financial Risk Analysis Dashboard", | |
page_icon="π", | |
layout="wide" | |
) | |
# Sidebar | |
self.create_sidebar() | |
# Main dashboard | |
st.title("π Financial Risk Analysis Dashboard") | |
# Load sample or uploaded data | |
financial_data = self.load_financial_data() | |
if financial_data: | |
# Generate risk report | |
risk_report = self.risk_analyzer.generate_risk_report(financial_data) | |
# Display dashboard components | |
self.display_risk_summary(risk_report) | |
self.display_detailed_metrics(risk_report) | |
self.display_risk_charts(financial_data, risk_report) | |
self.display_recommendations(risk_report) | |
def create_sidebar(self): | |
with st.sidebar: | |
st.title("Controls & Filters") | |
# Date range selector | |
st.subheader("Date Range") | |
start_date = st.date_input( | |
"Start Date", | |
datetime.now() - timedelta(days=30) | |
) | |
end_date = st.date_input( | |
"End Date", | |
datetime.now() | |
) | |
# Risk threshold adjustments | |
st.subheader("Risk Thresholds") | |
leverage_threshold = st.slider( | |
"Leverage Ratio Threshold", | |
min_value=10.0, | |
max_value=50.0, | |
value=30.0 | |
) | |
npl_threshold = st.slider( | |
"NPL Ratio Threshold (%)", | |
min_value=1.0, | |
max_value=10.0, | |
value=5.0 | |
) / 100 | |
# Export options | |
st.subheader("Export Options") | |
if st.button("Export Report (PDF)"): | |
st.info("Generating PDF report...") | |
# Add PDF export functionality | |
if st.button("Export Data (Excel)"): | |
st.info("Generating Excel file...") | |
# Add Excel export functionality | |
def load_financial_data(self): | |
# File upload option | |
uploaded_file = st.file_uploader( | |
"Upload financial data (JSON/CSV)", | |
type=["json", "csv"] | |
) | |
if uploaded_file: | |
try: | |
if uploaded_file.type == "application/json": | |
return json.load(uploaded_file) | |
else: | |
df = pd.read_csv(uploaded_file) | |
return df.to_dict() | |
except Exception as e: | |
st.error(f"Error loading file: {str(e)}") | |
return None | |
# Use sample data if no file uploaded | |
return self.get_sample_data() | |
def display_risk_summary(self, risk_report): | |
st.subheader("Risk Summary") | |
# Create three columns for key metrics | |
col1, col2, col3 = st.columns(3) | |
with col1: | |
self.metric_card( | |
"Overall Risk Level", | |
risk_report['risk_level'], | |
self.get_risk_color(risk_report['risk_level']) | |
) | |
with col2: | |
self.metric_card( | |
"Risk Score", | |
f"{risk_report['risk_score']:.2f}", | |
self.get_risk_color(risk_report['risk_level']) | |
) | |
with col3: | |
self.metric_card( | |
"Total Alerts", | |
len(risk_report['risk_alerts']), | |
"risk-moderate" if len(risk_report['risk_alerts']) > 0 else "risk-low" | |
) | |
# Risk Alerts | |
if risk_report['risk_alerts']: | |
st.markdown("### β οΈ Risk Alerts") | |
for alert in risk_report['risk_alerts']: | |
st.warning(alert) | |
def display_detailed_metrics(self, risk_report): | |
st.subheader("Detailed Metrics") | |
# Create tabs for different metric categories | |
tabs = st.tabs([ | |
"Basic Ratios", | |
"Funding Risk", | |
"Asset Quality", | |
"Market Risk", | |
"Operational Risk" | |
]) | |
# Basic Ratios Tab | |
with tabs[0]: | |
metrics = risk_report['detailed_metrics']['basic_ratios'] | |
self.create_metrics_grid(metrics) | |
# Funding Risk Tab | |
with tabs[1]: | |
metrics = risk_report['detailed_metrics']['funding_risks'] | |
self.create_metrics_grid(metrics) | |
# Asset Quality Tab | |
with tabs[2]: | |
metrics = risk_report['detailed_metrics']['asset_risks'] | |
self.create_metrics_grid(metrics) | |
# Market Risk Tab | |
with tabs[3]: | |
metrics = risk_report['detailed_metrics']['market_risks'] | |
self.create_metrics_grid(metrics) | |
# Operational Risk Tab | |
with tabs[4]: | |
metrics = risk_report['detailed_metrics']['operational_risks'] | |
self.create_metrics_grid(metrics) | |
def display_risk_charts(self, financial_data, risk_report): | |
st.subheader("Risk Analysis Charts") | |
# Create two columns for charts | |
col1, col2 = st.columns(2) | |
with col1: | |
# Radar chart for key risk indicators | |
self.create_radar_chart(risk_report) | |
with col2: | |
# Time series chart for trending metrics | |
self.create_trend_chart(financial_data) | |
# Additional charts in new row | |
col3, col4 = st.columns(2) | |
with col3: | |
# Asset composition pie chart | |
self.create_asset_composition_chart(financial_data) | |
with col4: | |
# Funding structure chart | |
self.create_funding_structure_chart(financial_data) | |
def display_recommendations(self, risk_report): | |
st.subheader("Recommendations & Actions") | |
# Generate recommendations based on risk levels | |
recommendations = self.generate_recommendations(risk_report) | |
for category, rec_list in recommendations.items(): | |
with st.expander(f"π {category}"): | |
for rec in rec_list: | |
st.markdown(f"- {rec}") | |
def metric_card(self, title, value, risk_class): | |
st.markdown(f""" | |
<div class="metric-card"> | |
<div class="metric-title">{title}</div> | |
<div class="metric-value {risk_class}">{value}</div> | |
</div> | |
""", unsafe_allow_html=True) | |
def create_metrics_grid(self, metrics): | |
cols = st.columns(2) | |
for idx, (metric, value) in enumerate(metrics.items()): | |
with cols[idx % 2]: | |
self.metric_card( | |
self.format_metric_name(metric), | |
f"{value:.2%}" if isinstance(value, float) else value, | |
self.get_metric_risk_color(metric, value) | |
) | |
def create_radar_chart(self, risk_report): | |
# Extract key risk indicators | |
metrics = risk_report['detailed_metrics']['basic_ratios'] | |
fig = go.Figure() | |
categories = list(metrics.keys()) | |
values = list(metrics.values()) | |
fig.add_trace(go.Scatterpolar( | |
r=values, | |
theta=categories, | |
fill='toself', | |
name='Current' | |
)) | |
fig.update_layout( | |
polar=dict( | |
radialaxis=dict( | |
visible=True, | |
range=[0, 1] | |
) | |
), | |
showlegend=False | |
) | |
st.plotly_chart(fig, use_container_width=True) | |
def create_trend_chart(self, financial_data): | |
# Create sample trend data | |
dates = pd.date_range(end=datetime.now(), periods=30, freq='D') | |
trend_data = pd.DataFrame({ | |
'Date': dates, | |
'Risk Score': np.random.uniform(2, 6, 30) | |
}) | |
fig = px.line( | |
trend_data, | |
x='Date', | |
y='Risk Score', | |
title='Risk Score Trend' | |
) | |
st.plotly_chart(fig, use_container_width=True) | |
def create_asset_composition_chart(self, financial_data): | |
# Extract asset composition | |
assets = { | |
'Corporate Loans': financial_data.get('corporate_loans', 0), | |
'Retail Loans': financial_data.get('retail_loans', 0), | |
'Securities': financial_data.get('securities', 0), | |
'Interbank Assets': financial_data.get('interbank_assets', 0) | |
} | |
fig = px.pie( | |
values=list(assets.values()), | |
names=list(assets.keys()), | |
title='Asset Composition' | |
) | |
st.plotly_chart(fig, use_container_width=True) | |
def create_funding_structure_chart(self, financial_data): | |
# Extract funding structure | |
funding = { | |
'Retail Deposits': financial_data.get('retail_deposits', 0), | |
'Corporate Deposits': financial_data.get('corporate_deposits', 0), | |
'Wholesale Funding': financial_data.get('wholesale_funding', 0), | |
'Interbank Borrowing': financial_data.get('interbank_borrowing', 0) | |
} | |
fig = px.bar( | |
x=list(funding.keys()), | |
y=list(funding.values()), | |
title='Funding Structure' | |
) | |
st.plotly_chart(fig, use_container_width=True) | |
def get_risk_color(risk_level): | |
colors = { | |
'CRITICAL': 'risk-high', | |
'HIGH': 'risk-high', | |
'MODERATE': 'risk-moderate', | |
'LOW': 'risk-low' | |
} | |
return colors.get(risk_level, 'risk-low') | |
def get_metric_risk_color(metric, value): | |
# Add logic to determine color based on metric type and value | |
return 'risk-moderate' | |
def format_metric_name(metric): | |
return metric.replace('_', ' ').title() | |
def generate_recommendations(risk_report): | |
recommendations = { | |
'Immediate Actions': [ | |
'Review and adjust leverage levels', | |
'Strengthen liquidity buffers', | |
'Enhance risk monitoring systems' | |
], | |
'Medium-term Improvements': [ | |
'Develop comprehensive risk management framework', | |
'Implement stress testing scenarios', | |
'Review counterparty exposure limits' | |
], | |
'Long-term Strategy': [ | |
'Diversify funding sources', | |
'Strengthen capital adequacy', | |
'Enhance risk reporting systems' | |
] | |
} | |
return recommendations | |
def get_sample_data(): | |
return { | |
'total_debt': 500000000, | |
'equity': 150000000, | |
'non_performing_loans': 25000000, | |
'total_loans': 400000000, | |
'loan_loss_provisions': 15000000, | |
'total_assets': 700000000, | |
'current_assets': 200000000, | |
'current_liabilities': 180000000, | |
'total_capital': 120000000, | |
'risk_weighted_assets': 500000000, | |
'short_term_funding': 300000000, | |
'total_funding': 600000000, | |
'wholesale_funding': 200000000, | |
'retail_deposits': 250000000, | |
'corporate_deposits': 150000000, | |
'interbank_borrowing': 100000000, | |
'long_term_funding': 200000000, | |
'level_3_assets': 50000000, | |
'derivative_notional': 400000000, | |
'contingent_liabilities': 80000000, | |
'undrawn_commitments': 120000000, | |
'var_99': 10000000, | |
'interest_rate_gap': 30000000, | |
'net_forex_position': 15000000, | |
'market_correlation': 0.6, | |
'process_risk_score': 0.04, | |
'system_risk_score': 0.03, | |
'compliance_risk_score': 0.02, | |
'fraud_risk_score': 0.03, | |
'collateral_coverage': 0.85, | |
'current_npl': 25000000, | |
'previous_npl': 20000000, | |
'corporate_loans': 200000000, | |
'retail_loans': 150000000, | |
'securities': 100000000, | |
'interbank_assets': 50000000 | |
} | |
# Main app file (app.py) | |
def main(): | |
dashboard = FinancialDashboard() | |
dashboard.run() | |
if __name__ == "__main__": | |
main() |