Fraud detection
Checks: sender ID, genuine format, spelling, scam phrases, disguised (accented) letters, transaction ID length, balance consistency, and an optional ML model. Signals combine with a noisy-OR: score = 1 - (1 - s1)(1 - s2).... LOW < 0.35 <= MEDIUM <= 0.70 < HIGH.
Warning
Results are risk indicators, not guarantees. Always confirm payments in the official app.
cedikit.fraud
Detect likely fake Mobile Money payment alerts and explain why.
Results are risk indicators, not guarantees. Always confirm a payment in the official Mobile Money app before releasing goods.
Example
from cedikit import fraud report = fraud.check(message_text, sender="0551234567") # doctest: +SKIP print(report) # doctest: +SKIP Risk: HIGH (score 0.97) Reasons: - Sent from a personal phone number ...
FraudReport
dataclass
The result of :func:check.
Attributes:
| Name | Type | Description |
|---|---|---|
risk |
Risk
|
|
score |
float
|
Combined score from 0 to 1. |
reasons |
list[str]
|
Human-readable explanations, strongest first. |
checks |
dict[str, bool]
|
Each check that could run, mapped to True if it passed. |
signals |
list[Signal]
|
The raw evidence behind |
parsed |
ParseResult | None
|
The SMS parser's reading of the message. |
advice |
str
|
What the user should do before trusting any alert. |
Signal
dataclass
One piece of evidence from one check.
check(message, sender=None, history=(), *, parser=None, classifier=None)
Assess how likely a payment SMS is to be fake.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
message
|
str
|
The SMS text. |
required |
sender
|
str | None
|
Who sent it (sender ID or phone number). Strongly recommended: fake alerts almost always come from personal numbers. |
None
|
history
|
Iterable[Transaction | ParseResult]
|
Earlier genuine transactions from the same wallet, oldest first, used to check that the claimed balance adds up. |
()
|
parser
|
Parser | None
|
A custom SMS parser, if you use extra templates. |
None
|
classifier
|
ScamClassifier | None
|
An optional trained :class: |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
A |
FraudReport
|
class: |
FraudReport
|
always confirm payments in the official app before releasing goods. |
Example
report = check( ... "SORRY YOU HAVE BEING BLOCKED BY TOO MANY AGENT REPORT, DO NOT TRY YOUR PIN", ... sender="0241234567", ... ) report.risk 'HIGH'
risk_level(score)
Map a 0-1 score to a risk level.
cedikit.fraud.classifier
Optional machine-learning scam classifier (needs pip install 'cedikit[ml]').
The model is an extra signal for :func:cedikit.fraud.check, never the only
one. cedikit does not ship a trained model: train one on your own labelled,
anonymised messages (hundreds of each class, ideally) and keep a held-out set
for evaluation.
Example::
from cedikit.fraud.classifier import ScamClassifier
model = ScamClassifier.train(genuine_texts, scam_texts)
model.save("scam_model.joblib")
report = fraud.check(text, sender=sender, classifier=model)
Security: :meth:ScamClassifier.load uses joblib (pickle), which can run code.
Only load model files you created yourself.
ScamClassifier
Character n-gram TF-IDF + logistic regression.
Character n-grams cope with typos and odd spacing ("Avaliable", "balan"), which word-based models would treat as unknown words.
train(genuine, scam)
classmethod
Fit a new model. Needs at least two examples of each class.
probability(text)
Estimated probability (0-1) that text is a scam.
load(path)
classmethod
Load a model saved with :meth:save. Only load files you trust.
prepare(text)
Normalise text so the model learns wording, not specific amounts or IDs.