GenAICoder commited on
Commit
e89ed92
ยท
verified ยท
1 Parent(s): 9366f7a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +430 -58
app.py CHANGED
@@ -32,6 +32,27 @@ from analytics.performance_analysis import (
32
  generate_metric_view
33
  )
34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  # ---------------------------------------------------
36
  # LOAD DATA
37
  # ---------------------------------------------------
@@ -259,6 +280,108 @@ def run_performance_analysis(
259
 
260
  return final_result
261
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
  # ---------------------------------------------------
263
  # DYNAMIC DROPDOWNS
264
  # ---------------------------------------------------
@@ -291,7 +414,7 @@ def update_analysis_dropdown(
291
  choices=[
292
  "30+@3",
293
  "30+@6",
294
- "30+@9",
295
  "Yr1 NCL"
296
  ],
297
  value="30+@6"
@@ -378,74 +501,323 @@ def run_analysis(
378
  with gr.Blocks() as app:
379
 
380
  gr.Markdown(
381
- "# Risk Analytics Manager Agent"
382
  )
383
 
384
- with gr.Row():
385
 
386
- dataset_dropdown = gr.Dropdown(
387
- choices=[
388
- "Acquisition",
389
- "Performance"
390
- ],
391
- value="Acquisition",
392
- label="Dataset"
393
- )
394
 
395
- analysis_dropdown = gr.Dropdown(
396
- choices=[
397
- "Portfolio Mix",
398
- "Credit Line Concentration"
399
- ],
400
- value="Portfolio Mix",
401
- label="Analysis"
402
- )
403
 
404
- category_dropdown = gr.Dropdown(
405
- choices=[
406
- "fico_band",
407
- "sourcing_channel",
408
- "city_tier",
409
- "occupation_type"
410
- ],
411
- value="fico_band",
412
- label="Category / View"
413
- )
414
 
415
- # -----------------------------------------
416
- # DYNAMIC DROPDOWNS
417
- # -----------------------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
418
 
419
- dataset_dropdown.change(
420
- fn=update_analysis_dropdown,
421
- inputs=dataset_dropdown,
422
- outputs=analysis_dropdown
423
- )
424
 
425
- dataset_dropdown.change(
426
- fn=update_category_dropdown,
427
- inputs=dataset_dropdown,
428
- outputs=category_dropdown
429
- )
430
 
431
- # -----------------------------------------
432
- # RUN BUTTON
433
- # -----------------------------------------
 
434
 
435
- run_button = gr.Button(
436
- "Run Analysis"
437
- )
438
 
439
- output_table = gr.Dataframe()
 
 
 
 
 
 
 
 
440
 
441
- run_button.click(
442
- fn=run_analysis,
443
- inputs=[
444
- dataset_dropdown,
445
- analysis_dropdown,
446
- category_dropdown
447
- ],
448
- outputs=output_table
449
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
450
 
451
  app.launch()
 
32
  generate_metric_view
33
  )
34
 
35
+ # ---------------------------------------------------
36
+ # VISUALIZATIONS - VINTAGE CURVES
37
+ # ---------------------------------------------------
38
+
39
+ from visualizations.vintage_curves import (
40
+ generate_delinquency_metric_chart,
41
+ generate_multi_metric_comparison,
42
+ generate_segment_delinquency_curve
43
+ )
44
+
45
+ # ---------------------------------------------------
46
+ # VISUALIZATIONS - SEGMENT RANKING
47
+ # ---------------------------------------------------
48
+
49
+ from visualizations.segment_ranking import (
50
+ generate_segment_risk_heatmap,
51
+ generate_segment_risk_ranking,
52
+ generate_multi_category_risk_comparison,
53
+ calculate_portfolio_risk_summary
54
+ )
55
+
56
  # ---------------------------------------------------
57
  # LOAD DATA
58
  # ---------------------------------------------------
 
280
 
281
  return final_result
282
 
283
+ # ---------------------------------------------------
284
+ # VINTAGE CURVES ANALYSIS
285
+ # ---------------------------------------------------
286
+
287
+ def generate_vintage_curve_single(
288
+ metric_name
289
+ ):
290
+ """Generate single vintage curve for a metric."""
291
+ try:
292
+ fig = generate_delinquency_metric_chart(
293
+ df=master_df,
294
+ metric_name=metric_name,
295
+ chart_type="line"
296
+ )
297
+ return fig
298
+ except Exception as e:
299
+ return f"Error generating vintage curve: {str(e)}"
300
+
301
+
302
+ def generate_vintage_curves_comparison():
303
+ """Generate comparison of all vintage curves."""
304
+ try:
305
+ fig = generate_multi_metric_comparison(
306
+ df=master_df,
307
+ metrics=["30+@3", "30+@6", "60+@6", "Yr1 NCL"]
308
+ )
309
+ return fig
310
+ except Exception as e:
311
+ return f"Error generating comparison: {str(e)}"
312
+
313
+
314
+ def generate_segmented_vintage_curve(
315
+ metric_name,
316
+ category
317
+ ):
318
+ """Generate vintage curve segmented by category."""
319
+ try:
320
+ fig = generate_segment_delinquency_curve(
321
+ df=master_df,
322
+ metric_name=metric_name,
323
+ category=category
324
+ )
325
+ return fig
326
+ except Exception as e:
327
+ return f"Error generating segmented curve: {str(e)}"
328
+
329
+ # ---------------------------------------------------
330
+ # SEGMENT RANKING ANALYSIS
331
+ # ---------------------------------------------------
332
+
333
+ def generate_segment_risk_heatmap_chart():
334
+ """Generate risk heatmap across all segments and metrics."""
335
+ try:
336
+ fig = generate_segment_risk_heatmap(
337
+ df=master_df
338
+ )
339
+ return fig
340
+ except Exception as e:
341
+ return f"Error generating heatmap: {str(e)}"
342
+
343
+
344
+ def generate_high_risk_segments_ranking(
345
+ metric_name,
346
+ category
347
+ ):
348
+ """Generate ranking of high-risk segments."""
349
+ try:
350
+ fig = generate_segment_risk_ranking(
351
+ df=master_df,
352
+ metric_name=metric_name,
353
+ category=category,
354
+ top_n=10
355
+ )
356
+ return fig
357
+ except Exception as e:
358
+ return f"Error generating ranking: {str(e)}"
359
+
360
+
361
+ def generate_multi_category_comparison(
362
+ metric_name
363
+ ):
364
+ """Generate risk comparison across all categories."""
365
+ try:
366
+ fig = generate_multi_category_risk_comparison(
367
+ df=master_df,
368
+ metric_name=metric_name
369
+ )
370
+ return fig
371
+ except Exception as e:
372
+ return f"Error generating comparison: {str(e)}"
373
+
374
+
375
+ def generate_portfolio_summary():
376
+ """Generate portfolio risk summary."""
377
+ try:
378
+ summary_df = calculate_portfolio_risk_summary(
379
+ df=master_df
380
+ )
381
+ return summary_df
382
+ except Exception as e:
383
+ return f"Error generating summary: {str(e)}"
384
+
385
  # ---------------------------------------------------
386
  # DYNAMIC DROPDOWNS
387
  # ---------------------------------------------------
 
414
  choices=[
415
  "30+@3",
416
  "30+@6",
417
+ "60+@6",
418
  "Yr1 NCL"
419
  ],
420
  value="30+@6"
 
501
  with gr.Blocks() as app:
502
 
503
  gr.Markdown(
504
+ "# Risk Analytics Manager Agent - Phase 2"
505
  )
506
 
507
+ with gr.Tabs():
508
 
509
+ # =================================================
510
+ # TAB 1: BASIC ANALYSIS (Phase 1)
511
+ # =================================================
 
 
 
 
 
512
 
513
+ with gr.TabItem("๐Ÿ“Š Basic Analysis"):
 
 
 
 
 
 
 
514
 
515
+ gr.Markdown(
516
+ "## Phase 1: Acquisition & Performance Analysis"
517
+ )
 
 
 
 
 
 
 
518
 
519
+ with gr.Row():
520
+
521
+ dataset_dropdown = gr.Dropdown(
522
+ choices=[
523
+ "Acquisition",
524
+ "Performance"
525
+ ],
526
+ value="Acquisition",
527
+ label="Dataset"
528
+ )
529
+
530
+ analysis_dropdown = gr.Dropdown(
531
+ choices=[
532
+ "Portfolio Mix",
533
+ "Credit Line Concentration"
534
+ ],
535
+ value="Portfolio Mix",
536
+ label="Analysis"
537
+ )
538
+
539
+ category_dropdown = gr.Dropdown(
540
+ choices=[
541
+ "fico_band",
542
+ "sourcing_channel",
543
+ "city_tier",
544
+ "occupation_type"
545
+ ],
546
+ value="fico_band",
547
+ label="Category / View"
548
+ )
549
+
550
+ # -----------------------------------------
551
+ # DYNAMIC DROPDOWNS
552
+ # -----------------------------------------
553
+
554
+ dataset_dropdown.change(
555
+ fn=update_analysis_dropdown,
556
+ inputs=dataset_dropdown,
557
+ outputs=analysis_dropdown
558
+ )
559
 
560
+ dataset_dropdown.change(
561
+ fn=update_category_dropdown,
562
+ inputs=dataset_dropdown,
563
+ outputs=category_dropdown
564
+ )
565
 
566
+ # -----------------------------------------
567
+ # RUN BUTTON
568
+ # -----------------------------------------
 
 
569
 
570
+ run_button = gr.Button(
571
+ "Run Analysis",
572
+ variant="primary"
573
+ )
574
 
575
+ output_table = gr.Dataframe()
 
 
576
 
577
+ run_button.click(
578
+ fn=run_analysis,
579
+ inputs=[
580
+ dataset_dropdown,
581
+ analysis_dropdown,
582
+ category_dropdown
583
+ ],
584
+ outputs=output_table
585
+ )
586
 
587
+ # =================================================
588
+ # TAB 2: VINTAGE CURVES (Phase 2)
589
+ # =================================================
590
+
591
+ with gr.TabItem("๐Ÿ“ˆ Vintage Curves"):
592
+
593
+ gr.Markdown(
594
+ "## Phase 2: Vintage Delinquency Curves Analysis"
595
+ )
596
+
597
+ with gr.Row():
598
+
599
+ metric_dropdown = gr.Dropdown(
600
+ choices=[
601
+ "30+@3",
602
+ "30+@6",
603
+ "60+@6",
604
+ "Yr1 NCL"
605
+ ],
606
+ value="30+@6",
607
+ label="Delinquency Metric"
608
+ )
609
+
610
+ vintage_chart_type = gr.Radio(
611
+ choices=["Single Metric", "All Metrics Comparison"],
612
+ value="Single Metric",
613
+ label="Chart Type"
614
+ )
615
+
616
+ def update_vintage_view(metric, chart_type):
617
+ if chart_type == "Single Metric":
618
+ return generate_vintage_curve_single(metric)
619
+ else:
620
+ return generate_vintage_curves_comparison()
621
+
622
+ vintage_chart = gr.Plot(
623
+ label="Vintage Curve"
624
+ )
625
+
626
+ gen_vintage_btn = gr.Button(
627
+ "Generate Vintage Curve",
628
+ variant="primary"
629
+ )
630
+
631
+ gen_vintage_btn.click(
632
+ fn=update_vintage_view,
633
+ inputs=[metric_dropdown, vintage_chart_type],
634
+ outputs=vintage_chart
635
+ )
636
+
637
+ gr.Markdown(
638
+ "### Segmented Vintage Curves"
639
+ )
640
+
641
+ with gr.Row():
642
+
643
+ segment_metric = gr.Dropdown(
644
+ choices=[
645
+ "30+@3",
646
+ "30+@6",
647
+ "60+@6",
648
+ "Yr1 NCL"
649
+ ],
650
+ value="30+@6",
651
+ label="Metric"
652
+ )
653
+
654
+ segment_category = gr.Dropdown(
655
+ choices=[
656
+ "fico_band",
657
+ "sourcing_channel",
658
+ "city_tier",
659
+ "occupation_type"
660
+ ],
661
+ value="fico_band",
662
+ label="Category"
663
+ )
664
+
665
+ segmented_chart = gr.Plot(
666
+ label="Segmented Vintage Curve"
667
+ )
668
+
669
+ gen_segment_btn = gr.Button(
670
+ "Generate Segmented Curve",
671
+ variant="primary"
672
+ )
673
+
674
+ gen_segment_btn.click(
675
+ fn=generate_segmented_vintage_curve,
676
+ inputs=[segment_metric, segment_category],
677
+ outputs=segmented_chart
678
+ )
679
+
680
+ # =================================================
681
+ # TAB 3: SEGMENT RANKING (Phase 2)
682
+ # =================================================
683
+
684
+ with gr.TabItem("โš ๏ธ Segment Ranking"):
685
+
686
+ gr.Markdown(
687
+ "## Phase 2: High-Risk Segment Analysis"
688
+ )
689
+
690
+ # --------- HEATMAP SECTION ---------
691
+
692
+ gr.Markdown(
693
+ "### ๐Ÿ”ฅ Overall Risk Heatmap"
694
+ )
695
+
696
+ gr.Markdown(
697
+ "Risk scores across all delinquency metrics and segments"
698
+ )
699
+
700
+ heatmap_chart = gr.Plot(
701
+ label="Risk Heatmap"
702
+ )
703
+
704
+ gen_heatmap_btn = gr.Button(
705
+ "Generate Risk Heatmap",
706
+ variant="primary"
707
+ )
708
+
709
+ gen_heatmap_btn.click(
710
+ fn=generate_segment_risk_heatmap_chart,
711
+ outputs=heatmap_chart
712
+ )
713
+
714
+ gr.Markdown(
715
+ "---"
716
+ )
717
+
718
+ # --------- HIGH-RISK RANKING SECTION ---------
719
+
720
+ gr.Markdown(
721
+ "### ๐Ÿ“Š High-Risk Segments Ranking"
722
+ )
723
+
724
+ with gr.Row():
725
+
726
+ ranking_metric = gr.Dropdown(
727
+ choices=[
728
+ "30+@3",
729
+ "30+@6",
730
+ "60+@6",
731
+ "Yr1 NCL"
732
+ ],
733
+ value="30+@6",
734
+ label="Metric"
735
+ )
736
+
737
+ ranking_category = gr.Dropdown(
738
+ choices=[
739
+ "fico_band",
740
+ "sourcing_channel",
741
+ "city_tier",
742
+ "occupation_type"
743
+ ],
744
+ value="fico_band",
745
+ label="Category"
746
+ )
747
+
748
+ ranking_chart = gr.Plot(
749
+ label="High-Risk Segments"
750
+ )
751
+
752
+ gen_ranking_btn = gr.Button(
753
+ "Generate Risk Ranking",
754
+ variant="primary"
755
+ )
756
+
757
+ gen_ranking_btn.click(
758
+ fn=generate_high_risk_segments_ranking,
759
+ inputs=[ranking_metric, ranking_category],
760
+ outputs=ranking_chart
761
+ )
762
+
763
+ gr.Markdown(
764
+ "---"
765
+ )
766
+
767
+ # --------- MULTI-CATEGORY COMPARISON ---------
768
+
769
+ gr.Markdown(
770
+ "### ๐Ÿ”€ Cross-Category Risk Comparison"
771
+ )
772
+
773
+ comparison_metric = gr.Dropdown(
774
+ choices=[
775
+ "30+@3",
776
+ "30+@6",
777
+ "60+@6",
778
+ "Yr1 NCL"
779
+ ],
780
+ value="30+@6",
781
+ label="Metric"
782
+ )
783
+
784
+ comparison_chart = gr.Plot(
785
+ label="Multi-Category Comparison"
786
+ )
787
+
788
+ gen_comparison_btn = gr.Button(
789
+ "Generate Comparison",
790
+ variant="primary"
791
+ )
792
+
793
+ gen_comparison_btn.click(
794
+ fn=generate_multi_category_comparison,
795
+ inputs=comparison_metric,
796
+ outputs=comparison_chart
797
+ )
798
+
799
+ gr.Markdown(
800
+ "---"
801
+ )
802
+
803
+ # --------- PORTFOLIO SUMMARY ---------
804
+
805
+ gr.Markdown(
806
+ "### ๐Ÿ“‹ Portfolio Risk Summary"
807
+ )
808
+
809
+ summary_table = gr.Dataframe(
810
+ label="Risk Summary"
811
+ )
812
+
813
+ gen_summary_btn = gr.Button(
814
+ "Generate Summary",
815
+ variant="primary"
816
+ )
817
+
818
+ gen_summary_btn.click(
819
+ fn=generate_portfolio_summary,
820
+ outputs=summary_table
821
+ )
822
 
823
  app.launch()