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
|