Розробка системи transaction monitoring для AML
Transaction monitoring (TM) — безперервний процес аналізу транзакцій для виявлення підозрілої активності. Це не просто перевірка blocklist: TM виявляє паттерни (structuring, швидкий рух, round-trip) які окремо виглядають нормально, але в сукупності — признак відмивання.
Архітектура TM системи
Два підходи: rule-based (детерміновані правила) та ML-based (anomaly detection). У production використовуємо обидва: правила для відомих паттернів, ML для виявлення нових.
Rule Engine
interface MonitoringRule {
id: string;
name: string;
category: "structuring" | "velocity" | "geographic" | "behavioral" | "watchlist";
evaluate: (context: TransactionContext) => Promise<RuleResult>;
alertLevel: AlertLevel;
action: AlertAction;
}
class TransactionMonitoringEngine {
private rules: MonitoringRule[];
async evaluateTransaction(tx: Transaction): Promise<EvaluationResult> {
const context = await this.buildContext(tx);
const results = await Promise.all(
this.rules.map(rule => rule.evaluate(context).catch(err => ({
triggered: false,
error: err.message,
})))
);
const triggered = results.filter(r => r.triggered);
if (triggered.length === 0) return { action: "ALLOW", ruleHits: [] };
const maxLevel = Math.max(...triggered.map(r => r.alertLevel));
const action = this.determineAction(maxLevel, triggered);
if (action !== "ALLOW") {
await this.createAlert(tx, triggered, action);
}
return { action, ruleHits: triggered };
}
private async buildContext(tx: Transaction): Promise<TransactionContext> {
const [history30d, history24h, userProfile, walletRisk] = await Promise.all([
this.db.getTransactionHistory(tx.userId, 30),
this.db.getTransactionHistory(tx.userId, 1),
this.db.getUserProfile(tx.userId),
this.amlProvider.getWalletRisk(tx.address, tx.asset),
]);
return { transaction: tx, history30d, history24h, userProfile, walletRisk };
}
}
Конкретні правила
const STRUCTURING_RULE: MonitoringRule = {
id: "TM-001",
name: "Structuring Detection",
category: "structuring",
alertLevel: AlertLevel.HIGH,
action: AlertAction.FREEZE_AND_REVIEW,
async evaluate(ctx: TransactionContext): Promise<RuleResult> {
const REPORTING_THRESHOLD = 10000;
// Знаходимо транзакції чуть нижче threshold за 3 дні
const nearThreshold = ctx.history30d.filter(t =>
t.usdAmount >= REPORTING_THRESHOLD * 0.7 &&
t.usdAmount < REPORTING_THRESHOLD &&
Date.now() - t.timestamp < 3 * 86400000
);
const currentNearThreshold = ctx.transaction.usdAmount >= REPORTING_THRESHOLD * 0.7 &&
ctx.transaction.usdAmount < REPORTING_THRESHOLD;
if (currentNearThreshold && nearThreshold.length >= 2) {
return {
triggered: true,
alertLevel: AlertLevel.HIGH,
details: `${nearThreshold.length + 1} transactions just below $${REPORTING_THRESHOLD}`,
evidence: nearThreshold.map(t => t.id),
};
}
return { triggered: false };
},
};
ML-based Anomaly Detection
Для продвинутих систем — Isolation Forest або Autoencoder для виявлення аномалій:
from sklearn.ensemble import IsolationForest
import numpy as np
class TransactionAnomalyDetector:
def __init__(self):
self.model = IsolationForest(contamination=0.01, random_state=42)
def extract_features(self, transaction, user_history):
return [
transaction['usd_amount'],
transaction['usd_amount'] / (user_history['avg_30d'] + 1),
len(user_history['transactions_24h']),
transaction['hour_of_day'],
transaction['day_of_week'],
user_history['unique_counterparties_7d'],
transaction['aml_risk_score'],
]
def predict(self, features) -> float:
# Повертає: -1 anomaly, 1 normal
score = self.model.score_samples([features])[0]
return (score + 0.5) * 2 # normalize to [0, 1]
Alert Management та SAR
class AlertManager {
async createAlert(tx: Transaction, rules: RuleResult[], action: AlertAction): Promise<Alert> {
const alert = await this.db.createAlert({
transactionId: tx.id,
userId: tx.userId,
triggeredRules: rules.map(r => r.ruleId),
maxAlertLevel: Math.max(...rules.map(r => r.alertLevel)),
action,
status: AlertStatus.OPEN,
assignedTo: await this.autoAssignCompliance(),
dueDate: this.calculateDueDate(action),
});
if (action === AlertAction.FREEZE_AND_REVIEW) {
await this.freezeUserAccount(tx.userId, alert.id);
}
await this.notifyComplianceTeam(alert);
return alert;
}
}
Стек
| Компонент | Технологія |
|---|---|
| Rule engine | Node.js + TypeScript |
| ML detection | Python + scikit-learn або TensorFlow |
| Streaming | Apache Kafka для real-time |
| Storage | PostgreSQL + TimescaleDB (time-series) |
| Alerting | Custom + PagerDuty |
| Dashboard | React |
Повна TM система з rule engine, ML аномаліями та SAR management: 2-3 місяці.







