fraud_detection_model / decision.py
Samyak000's picture
Upload 2 files
d88df03 verified
Raw
History Blame Contribute Delete
2.24 kB
"""Phase 12: Decision engine.
Apply deterministic action thresholds to produce final actions.
"""
from __future__ import annotations
from typing import Any
HIGH_RISK_THRESHOLD = 66.6666
MEDIUM_RISK_THRESHOLD = 33.3333
def risk_band(risk_score: float) -> str:
if risk_score >= HIGH_RISK_THRESHOLD:
return "HIGH"
if risk_score >= MEDIUM_RISK_THRESHOLD:
return "MEDIUM"
return "LOW"
def decide_action(risk_score: float) -> str:
band = risk_band(risk_score)
if band == "HIGH":
return "BLOCK"
if band == "MEDIUM":
return "MFA"
return "APPROVE"
def build_decision_output(
*,
transaction_id: str | None,
classification: str,
fraud_probability: float,
risk_score: float,
fraud_threshold: float,
suspicious_threshold: float,
explainability: dict[str, Any],
) -> dict[str, Any]:
band = risk_band(risk_score)
action = decide_action(risk_score)
top_positive = explainability.get("top_positive_signals", [])
top_signal = top_positive[0] if top_positive else None
rationale = f"Risk band {band} maps deterministically to action {action}."
if top_signal is not None:
label = str(top_signal.get("label", top_signal.get("feature", "top signal")))
rationale = f"Risk band {band} maps to {action}; strongest risk driver: {label}."
return {
"transaction_id": transaction_id,
"action": action,
"risk_band": band,
"risk_score": round(float(risk_score), 2),
"classification": classification,
"fraud_probability": round(float(fraud_probability), 6),
"policy": {
"name": "phase12_deterministic_thresholds",
"high_risk_threshold": HIGH_RISK_THRESHOLD,
"medium_risk_threshold": MEDIUM_RISK_THRESHOLD,
"fraud_threshold": round(float(fraud_threshold), 6),
"suspicious_threshold": round(float(suspicious_threshold), 6),
},
"rationale": rationale,
"recommended_next_step": "manual_review" if action == "MFA" else "finalize",
}
def phase_status() -> str:
return "phase 12 decision engine implemented"