File size: 2,935 Bytes
d4f8959
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
from backend.red_flags import (
    evaluate_red_flags,
    compute_risk_score,
    overall_confidence,
    get_value,
    FLAG_SEVERITY,
)


class FakeGraph:
    def __init__(self, data):
        self._data = data

    def get_company_metrics(self, company):
        return self._data.get(company, {})


FAKE_DATA = {
    "HDFC Bank": {
        "2023": {
            "deposits": {"value": 1_900_000_00_00_000, "confidence": "high"},
            "gross_npa_pct": 1.3, "net_npa_pct": 0.4,
            "casa_ratio": 44.0, "capital_adequacy": 18.9,
        },
        "2024": {
            "profit_after_tax": {"value": 608_120_00_00_000, "confidence": "high"},
            "deposits": {"value": 1_500_000_00_00_000, "confidence": "high"},
            "gross_npa_pct": 6.2, "net_npa_pct": 0.33,
            "casa_ratio": 28.0, "capital_adequacy": 19.3,
        },
    },
    "Infosys": {
        "2023": {"revenue": {"value": 1_500_000_000_000, "confidence": "high"}},
        "2024": {
            "revenue": {"value": 1_300_000_000_000, "confidence": "high"},
            "net_income": {"value": -50_000_000, "confidence": "medium"},
            "attrition": 27.5,
        },
    },
}


def test_get_value_normalizes_both_shapes():
    assert get_value({"value": 5.0, "confidence": "high"}) == (5.0, "high")
    assert get_value(3.2) == (3.2, "medium")
    assert get_value(None) == (None, None)


def test_bank_flags_trigger():
    result = evaluate_red_flags(FakeGraph(FAKE_DATA), "HDFC Bank", "2024", sector="BANK")
    flag_names = {f["flag"] for f in result["flags_triggered"]}
    assert "HIGH_GROSS_NPA" in flag_names        # 6.2 > 5
    assert "LOW_CASA" in flag_names              # 28 < 30
    assert "DEPOSIT_DECLINE_YOY" in flag_names   # 1.9e15 -> 1.5e15 is >10%
    assert result["risk_score"] > 0


def test_it_flags_trigger():
    result = evaluate_red_flags(FakeGraph(FAKE_DATA), "Infosys", "2024", sector="IT")
    flag_names = {f["flag"] for f in result["flags_triggered"]}
    assert "HIGH_ATTRITION" in flag_names         # 27.5 > 25
    assert "REVENUE_DECLINE_YOY" in flag_names    # >5% decline
    assert "NEGATIVE_NET_INCOME" in flag_names


def test_missing_filing_returns_error_not_crash():
    result = evaluate_red_flags(FakeGraph(FAKE_DATA), "Nobody", "2024", sector="BANK")
    assert result["risk_score"] is None
    assert "error" in result


def test_risk_score_capped_at_100():
    flags = [{"flag": "HIGH_GROSS_NPA"}] * 10
    assert compute_risk_score(flags) == 100


def test_overall_confidence_is_weakest_link():
    flags = [
        {"flag": "A", "confidence": "high"},
        {"flag": "B", "confidence": "low"},
    ]
    assert overall_confidence(flags) == "low"
    assert overall_confidence([]) == "high"


def test_severity_table_has_entries_for_core_flags():
    for flag in ("HIGH_GROSS_NPA", "NEGATIVE_PAT", "HIGH_ATTRITION", "HIGH_DEBT_EQUITY"):
        assert flag in FLAG_SEVERITY