File size: 2,601 Bytes
942b115
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import pandas as pd
import pytest

from app.config import settings
from app.scoring import build_feature_row, load_model_bundle, risk_tier, score_transaction

EMPTY_HISTORY = pd.DataFrame(
    columns=[
        "step", "type", "amount", "nameOrig", "oldbalanceOrg", "newbalanceOrig",
        "nameDest", "oldbalanceDest", "newbalanceDest",
    ]
)


@pytest.fixture(scope="module")
def bundle():
    return load_model_bundle(settings.MODEL_PATH)


def test_risk_tier_bands():
    assert risk_tier(0.1) == "low"
    assert risk_tier(0.3) == "medium"
    assert risk_tier(0.69) == "medium"
    assert risk_tier(0.7) == "high"
    assert risk_tier(0.99) == "high"


def test_fraud_drain_pattern_scores_high(bundle):
    raw = {
        "step": 5, "type": "TRANSFER", "amount": 181.0,
        "nameOrig": "CFRAUD1", "oldbalanceOrg": 181.0, "newbalanceOrig": 0.0,
        "nameDest": "CFRAUD2", "oldbalanceDest": 0.0, "newbalanceDest": 0.0,
    }
    row = build_feature_row(EMPTY_HISTORY, raw)
    result = score_transaction(bundle, row)
    assert result["risk_tier"] == "high"
    assert result["probability"] > 0.5
    assert len(result["top_features"]) == 5
    assert result["model_version"]


def test_legit_payment_scores_low(bundle):
    raw = {
        "step": 5, "type": "PAYMENT", "amount": 50.0,
        "nameOrig": "CLEGIT1", "oldbalanceOrg": 5000.0, "newbalanceOrig": 4950.0,
        "nameDest": "MMERCHANT1", "oldbalanceDest": 0.0, "newbalanceDest": 0.0,
    }
    row = build_feature_row(EMPTY_HISTORY, raw)
    result = score_transaction(bundle, row)
    assert result["risk_tier"] == "low"
    assert result["probability"] < 0.3


def test_build_feature_row_uses_prior_history_for_velocity(bundle):
    history = pd.DataFrame(
        [
            {
                "step": 1, "type": "PAYMENT", "amount": 10.0,
                "nameOrig": "CVEL1", "oldbalanceOrg": 100.0, "newbalanceOrig": 90.0,
                "nameDest": "MVEL1", "oldbalanceDest": 0.0, "newbalanceDest": 0.0,
            },
            {
                "step": 2, "type": "PAYMENT", "amount": 10.0,
                "nameOrig": "CVEL1", "oldbalanceOrg": 90.0, "newbalanceOrig": 80.0,
                "nameDest": "MVEL1", "oldbalanceDest": 0.0, "newbalanceDest": 0.0,
            },
        ]
    )
    raw = {
        "step": 3, "type": "PAYMENT", "amount": 10.0,
        "nameOrig": "CVEL1", "oldbalanceOrg": 80.0, "newbalanceOrig": 70.0,
        "nameDest": "MVEL1", "oldbalanceDest": 0.0, "newbalanceDest": 0.0,
    }
    row = build_feature_row(history, raw)
    assert row.iloc[0]["orig_prior_txn_count"] == 2