vincentiusyoshuac commited on
Commit
5ae4604
·
verified ·
1 Parent(s): d3f64a5

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +440 -0
app.py ADDED
@@ -0,0 +1,440 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import numpy as np
4
+ import plotly.graph_objects as go
5
+ import plotly.express as px
6
+ from datetime import datetime, timedelta
7
+ import json
8
+
9
+ # Custom CSS with Tailwind-like utilities
10
+ def load_css():
11
+ st.markdown("""
12
+ <style>
13
+ /* Tailwind-inspired utilities */
14
+ .dashboard-card {
15
+ background-color: white;
16
+ border-radius: 0.5rem;
17
+ padding: 1.5rem;
18
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
19
+ margin-bottom: 1rem;
20
+ }
21
+ .metric-card {
22
+ background-color: #f8fafc;
23
+ border-radius: 0.375rem;
24
+ padding: 1rem;
25
+ margin: 0.5rem 0;
26
+ border: 1px solid #e2e8f0;
27
+ }
28
+ .metric-title {
29
+ color: #64748b;
30
+ font-size: 0.875rem;
31
+ font-weight: 500;
32
+ margin-bottom: 0.5rem;
33
+ }
34
+ .metric-value {
35
+ color: #1e293b;
36
+ font-size: 1.5rem;
37
+ font-weight: 600;
38
+ }
39
+ .risk-high {
40
+ color: #dc2626;
41
+ }
42
+ .risk-moderate {
43
+ color: #d97706;
44
+ }
45
+ .risk-low {
46
+ color: #059669;
47
+ }
48
+ /* Custom Streamlit modifications */
49
+ .stApp {
50
+ background-color: #f1f5f9;
51
+ }
52
+ .css-1d391kg {
53
+ padding: 1rem 1rem;
54
+ }
55
+ </style>
56
+ """, unsafe_allow_html=True)
57
+
58
+ class FinancialDashboard:
59
+ def __init__(self):
60
+ self.risk_analyzer = FinancialRiskAnalyzer()
61
+ load_css()
62
+
63
+ def run(self):
64
+ st.set_page_config(
65
+ page_title="Financial Risk Analysis Dashboard",
66
+ page_icon="📊",
67
+ layout="wide"
68
+ )
69
+
70
+ # Sidebar
71
+ self.create_sidebar()
72
+
73
+ # Main dashboard
74
+ st.title("📊 Financial Risk Analysis Dashboard")
75
+
76
+ # Load sample or uploaded data
77
+ financial_data = self.load_financial_data()
78
+
79
+ if financial_data:
80
+ # Generate risk report
81
+ risk_report = self.risk_analyzer.generate_risk_report(financial_data)
82
+
83
+ # Display dashboard components
84
+ self.display_risk_summary(risk_report)
85
+ self.display_detailed_metrics(risk_report)
86
+ self.display_risk_charts(financial_data, risk_report)
87
+ self.display_recommendations(risk_report)
88
+
89
+ def create_sidebar(self):
90
+ with st.sidebar:
91
+ st.title("Controls & Filters")
92
+
93
+ # Date range selector
94
+ st.subheader("Date Range")
95
+ start_date = st.date_input(
96
+ "Start Date",
97
+ datetime.now() - timedelta(days=30)
98
+ )
99
+ end_date = st.date_input(
100
+ "End Date",
101
+ datetime.now()
102
+ )
103
+
104
+ # Risk threshold adjustments
105
+ st.subheader("Risk Thresholds")
106
+ leverage_threshold = st.slider(
107
+ "Leverage Ratio Threshold",
108
+ min_value=10.0,
109
+ max_value=50.0,
110
+ value=30.0
111
+ )
112
+ npl_threshold = st.slider(
113
+ "NPL Ratio Threshold (%)",
114
+ min_value=1.0,
115
+ max_value=10.0,
116
+ value=5.0
117
+ ) / 100
118
+
119
+ # Export options
120
+ st.subheader("Export Options")
121
+ if st.button("Export Report (PDF)"):
122
+ st.info("Generating PDF report...")
123
+ # Add PDF export functionality
124
+
125
+ if st.button("Export Data (Excel)"):
126
+ st.info("Generating Excel file...")
127
+ # Add Excel export functionality
128
+
129
+ def load_financial_data(self):
130
+ # File upload option
131
+ uploaded_file = st.file_uploader(
132
+ "Upload financial data (JSON/CSV)",
133
+ type=["json", "csv"]
134
+ )
135
+
136
+ if uploaded_file:
137
+ try:
138
+ if uploaded_file.type == "application/json":
139
+ return json.load(uploaded_file)
140
+ else:
141
+ df = pd.read_csv(uploaded_file)
142
+ return df.to_dict()
143
+ except Exception as e:
144
+ st.error(f"Error loading file: {str(e)}")
145
+ return None
146
+
147
+ # Use sample data if no file uploaded
148
+ return self.get_sample_data()
149
+
150
+ def display_risk_summary(self, risk_report):
151
+ st.subheader("Risk Summary")
152
+
153
+ # Create three columns for key metrics
154
+ col1, col2, col3 = st.columns(3)
155
+
156
+ with col1:
157
+ self.metric_card(
158
+ "Overall Risk Level",
159
+ risk_report['risk_level'],
160
+ self.get_risk_color(risk_report['risk_level'])
161
+ )
162
+
163
+ with col2:
164
+ self.metric_card(
165
+ "Risk Score",
166
+ f"{risk_report['risk_score']:.2f}",
167
+ self.get_risk_color(risk_report['risk_level'])
168
+ )
169
+
170
+ with col3:
171
+ self.metric_card(
172
+ "Total Alerts",
173
+ len(risk_report['risk_alerts']),
174
+ "risk-moderate" if len(risk_report['risk_alerts']) > 0 else "risk-low"
175
+ )
176
+
177
+ # Risk Alerts
178
+ if risk_report['risk_alerts']:
179
+ st.markdown("### ⚠️ Risk Alerts")
180
+ for alert in risk_report['risk_alerts']:
181
+ st.warning(alert)
182
+
183
+ def display_detailed_metrics(self, risk_report):
184
+ st.subheader("Detailed Metrics")
185
+
186
+ # Create tabs for different metric categories
187
+ tabs = st.tabs([
188
+ "Basic Ratios",
189
+ "Funding Risk",
190
+ "Asset Quality",
191
+ "Market Risk",
192
+ "Operational Risk"
193
+ ])
194
+
195
+ # Basic Ratios Tab
196
+ with tabs[0]:
197
+ metrics = risk_report['detailed_metrics']['basic_ratios']
198
+ self.create_metrics_grid(metrics)
199
+
200
+ # Funding Risk Tab
201
+ with tabs[1]:
202
+ metrics = risk_report['detailed_metrics']['funding_risks']
203
+ self.create_metrics_grid(metrics)
204
+
205
+ # Asset Quality Tab
206
+ with tabs[2]:
207
+ metrics = risk_report['detailed_metrics']['asset_risks']
208
+ self.create_metrics_grid(metrics)
209
+
210
+ # Market Risk Tab
211
+ with tabs[3]:
212
+ metrics = risk_report['detailed_metrics']['market_risks']
213
+ self.create_metrics_grid(metrics)
214
+
215
+ # Operational Risk Tab
216
+ with tabs[4]:
217
+ metrics = risk_report['detailed_metrics']['operational_risks']
218
+ self.create_metrics_grid(metrics)
219
+
220
+ def display_risk_charts(self, financial_data, risk_report):
221
+ st.subheader("Risk Analysis Charts")
222
+
223
+ # Create two columns for charts
224
+ col1, col2 = st.columns(2)
225
+
226
+ with col1:
227
+ # Radar chart for key risk indicators
228
+ self.create_radar_chart(risk_report)
229
+
230
+ with col2:
231
+ # Time series chart for trending metrics
232
+ self.create_trend_chart(financial_data)
233
+
234
+ # Additional charts in new row
235
+ col3, col4 = st.columns(2)
236
+
237
+ with col3:
238
+ # Asset composition pie chart
239
+ self.create_asset_composition_chart(financial_data)
240
+
241
+ with col4:
242
+ # Funding structure chart
243
+ self.create_funding_structure_chart(financial_data)
244
+
245
+ def display_recommendations(self, risk_report):
246
+ st.subheader("Recommendations & Actions")
247
+
248
+ # Generate recommendations based on risk levels
249
+ recommendations = self.generate_recommendations(risk_report)
250
+
251
+ for category, rec_list in recommendations.items():
252
+ with st.expander(f"📋 {category}"):
253
+ for rec in rec_list:
254
+ st.markdown(f"- {rec}")
255
+
256
+ def metric_card(self, title, value, risk_class):
257
+ st.markdown(f"""
258
+ <div class="metric-card">
259
+ <div class="metric-title">{title}</div>
260
+ <div class="metric-value {risk_class}">{value}</div>
261
+ </div>
262
+ """, unsafe_allow_html=True)
263
+
264
+ def create_metrics_grid(self, metrics):
265
+ cols = st.columns(2)
266
+ for idx, (metric, value) in enumerate(metrics.items()):
267
+ with cols[idx % 2]:
268
+ self.metric_card(
269
+ self.format_metric_name(metric),
270
+ f"{value:.2%}" if isinstance(value, float) else value,
271
+ self.get_metric_risk_color(metric, value)
272
+ )
273
+
274
+ def create_radar_chart(self, risk_report):
275
+ # Extract key risk indicators
276
+ metrics = risk_report['detailed_metrics']['basic_ratios']
277
+
278
+ fig = go.Figure()
279
+
280
+ categories = list(metrics.keys())
281
+ values = list(metrics.values())
282
+
283
+ fig.add_trace(go.Scatterpolar(
284
+ r=values,
285
+ theta=categories,
286
+ fill='toself',
287
+ name='Current'
288
+ ))
289
+
290
+ fig.update_layout(
291
+ polar=dict(
292
+ radialaxis=dict(
293
+ visible=True,
294
+ range=[0, 1]
295
+ )
296
+ ),
297
+ showlegend=False
298
+ )
299
+
300
+ st.plotly_chart(fig, use_container_width=True)
301
+
302
+ def create_trend_chart(self, financial_data):
303
+ # Create sample trend data
304
+ dates = pd.date_range(end=datetime.now(), periods=30, freq='D')
305
+ trend_data = pd.DataFrame({
306
+ 'Date': dates,
307
+ 'Risk Score': np.random.uniform(2, 6, 30)
308
+ })
309
+
310
+ fig = px.line(
311
+ trend_data,
312
+ x='Date',
313
+ y='Risk Score',
314
+ title='Risk Score Trend'
315
+ )
316
+
317
+ st.plotly_chart(fig, use_container_width=True)
318
+
319
+ def create_asset_composition_chart(self, financial_data):
320
+ # Extract asset composition
321
+ assets = {
322
+ 'Corporate Loans': financial_data.get('corporate_loans', 0),
323
+ 'Retail Loans': financial_data.get('retail_loans', 0),
324
+ 'Securities': financial_data.get('securities', 0),
325
+ 'Interbank Assets': financial_data.get('interbank_assets', 0)
326
+ }
327
+
328
+ fig = px.pie(
329
+ values=list(assets.values()),
330
+ names=list(assets.keys()),
331
+ title='Asset Composition'
332
+ )
333
+
334
+ st.plotly_chart(fig, use_container_width=True)
335
+
336
+ def create_funding_structure_chart(self, financial_data):
337
+ # Extract funding structure
338
+ funding = {
339
+ 'Retail Deposits': financial_data.get('retail_deposits', 0),
340
+ 'Corporate Deposits': financial_data.get('corporate_deposits', 0),
341
+ 'Wholesale Funding': financial_data.get('wholesale_funding', 0),
342
+ 'Interbank Borrowing': financial_data.get('interbank_borrowing', 0)
343
+ }
344
+
345
+ fig = px.bar(
346
+ x=list(funding.keys()),
347
+ y=list(funding.values()),
348
+ title='Funding Structure'
349
+ )
350
+
351
+ st.plotly_chart(fig, use_container_width=True)
352
+
353
+ @staticmethod
354
+ def get_risk_color(risk_level):
355
+ colors = {
356
+ 'CRITICAL': 'risk-high',
357
+ 'HIGH': 'risk-high',
358
+ 'MODERATE': 'risk-moderate',
359
+ 'LOW': 'risk-low'
360
+ }
361
+ return colors.get(risk_level, 'risk-low')
362
+
363
+ @staticmethod
364
+ def get_metric_risk_color(metric, value):
365
+ # Add logic to determine color based on metric type and value
366
+ return 'risk-moderate'
367
+
368
+ @staticmethod
369
+ def format_metric_name(metric):
370
+ return metric.replace('_', ' ').title()
371
+
372
+ @staticmethod
373
+ def generate_recommendations(risk_report):
374
+ recommendations = {
375
+ 'Immediate Actions': [
376
+ 'Review and adjust leverage levels',
377
+ 'Strengthen liquidity buffers',
378
+ 'Enhance risk monitoring systems'
379
+ ],
380
+ 'Medium-term Improvements': [
381
+ 'Develop comprehensive risk management framework',
382
+ 'Implement stress testing scenarios',
383
+ 'Review counterparty exposure limits'
384
+ ],
385
+ 'Long-term Strategy': [
386
+ 'Diversify funding sources',
387
+ 'Strengthen capital adequacy',
388
+ 'Enhance risk reporting systems'
389
+ ]
390
+ }
391
+ return recommendations
392
+
393
+ @staticmethod
394
+ def get_sample_data():
395
+ return {
396
+ 'total_debt': 500000000,
397
+ 'equity': 150000000,
398
+ 'non_performing_loans': 25000000,
399
+ 'total_loans': 400000000,
400
+ 'loan_loss_provisions': 15000000,
401
+ 'total_assets': 700000000,
402
+ 'current_assets': 200000000,
403
+ 'current_liabilities': 180000000,
404
+ 'total_capital': 120000000,
405
+ 'risk_weighted_assets': 500000000,
406
+ 'short_term_funding': 300000000,
407
+ 'total_funding': 600000000,
408
+ 'wholesale_funding': 200000000,
409
+ 'retail_deposits': 250000000,
410
+ 'corporate_deposits': 150000000,
411
+ 'interbank_borrowing': 100000000,
412
+ 'long_term_funding': 200000000,
413
+ 'level_3_assets': 50000000,
414
+ 'derivative_notional': 400000000,
415
+ 'contingent_liabilities': 80000000,
416
+ 'undrawn_commitments': 120000000,
417
+ 'var_99': 10000000,
418
+ 'interest_rate_gap': 30000000,
419
+ 'net_forex_position': 15000000,
420
+ 'market_correlation': 0.6,
421
+ 'process_risk_score': 0.04,
422
+ 'system_risk_score': 0.03,
423
+ 'compliance_risk_score': 0.02,
424
+ 'fraud_risk_score': 0.03,
425
+ 'collateral_coverage': 0.85,
426
+ 'current_npl': 25000000,
427
+ 'previous_npl': 20000000,
428
+ 'corporate_loans': 200000000,
429
+ 'retail_loans': 150000000,
430
+ 'securities': 100000000,
431
+ 'interbank_assets': 50000000
432
+ }
433
+
434
+ # Main app file (app.py)
435
+ def main():
436
+ dashboard = FinancialDashboard()
437
+ dashboard.run()
438
+
439
+ if __name__ == "__main__":
440
+ main()