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(""" """, 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"""
{title}
{value}
""", 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) @staticmethod 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') @staticmethod def get_metric_risk_color(metric, value): # Add logic to determine color based on metric type and value return 'risk-moderate' @staticmethod def format_metric_name(metric): return metric.replace('_', ' ').title() @staticmethod 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 @staticmethod 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()