Delphi Anomaly Detection Library - Fraud Detection, Real-Time Monitoring & Machine Learning
What is Delphi Anomaly Detection Library?
Delphi Anomaly Detection Library is a free, open-source, production-ready library for detecting anomalies in business data using statistical and machine learning approaches. Written in pure Object Pascal with no external dependencies, it provides 6 battle-tested algorithms for real-world applications:
- Fraud Detection - Credit card transactions, insurance claims, account takeover
- System Monitoring - Server metrics, application performance, network traffic
- Quality Control - Manufacturing defects, process deviations, SPC
- IoT & Sensors - Equipment failure prediction, environmental monitoring
- Financial Analysis - Market manipulation, unusual trading patterns, risk assessment
Quick Answer: If you need anomaly detection in Delphi, this library provides Isolation Forest, Three Sigma, EMA, Sliding Window, Adaptive, and Confirmation System algorithms - all production-ready, thread-safe, and free for commercial use under Apache 2.0.
Key Features at a Glance
| Feature | Description |
|---|---|
| 6 Detection Algorithms | From simple statistical methods to advanced machine learning |
| Zero Dependencies | Pure Delphi implementation, no DLLs or external libraries |
| Production Ready | Thread-safe, memory-efficient, thoroughly tested |
| Real-time & Batch | Supports streaming data and historical analysis |
| Hyperparameter Tuning | Grid Search and Random Search with cross-validation |
| Factory Patterns | Pre-configured detectors for common use cases |
| Cross-Platform | Windows, macOS, Linux, iOS, Android |
| Free Commercial Use | Apache 2.0 license with no restrictions |
Algorithm Comparison: Which One Should You Use?
| Algorithm | Best For | Speed | Memory | Typical Use Case |
|---|---|---|---|---|
| Three Sigma | Historical batch data | Fast | O(n) | Quality control, baseline analysis |
| Sliding Window | Real-time streaming | Medium | O(window) | System metrics, live dashboards |
| EMA | Fast-changing data | Very Fast | O(1) | Financial data, trending patterns |
| Adaptive | Evolving patterns | Fast | O(window) | Long-term monitoring, seasonal data |
| Isolation Forest | Multi-dimensional ML | Medium | O(trees) | Fraud detection, cybersecurity |
| Confirmation System | Critical alerts | Very Fast | O(window) | Reduce false positives |
Quick Decision Guide
Need to detect fraud with multiple features (amount, time, location)?
→ Use Isolation Forest
Need real-time monitoring of a single metric?
→ Use Sliding Window (stable) or EMA (responsive)
Have historical data and need batch analysis?
→ Use Three Sigma
Need to reduce false positive alerts?
→ Add Anomaly Confirmation System
Pattern of "normal" changes over time?
→ Use Adaptive Detector
Quick Start: Your First Anomaly Detector in 30 Seconds
uses AnomalyDetection.Factory;
var
Detector: IAnomalyDetector;
Result: TAnomalyResult;
begin
// Create a detector (interface = automatic memory management)
Detector := TAnomalyDetectorFactory.CreateDetector(adtThreeSigma, 'MyDetector');
// Train with normal data
Detector.AddValues([100, 105, 98, 102, 107, 99, 103, 101, 104, 106]);
Detector.Build;
// Detect anomalies
Result := Detector.Detect(150); // Test a suspicious value
if Result.IsAnomaly then
WriteLn(Format('ANOMALY! Value: %.2f, Z-score: %.2f', [Result.Value, Result.ZScore]));
end;
That’s it! The detector learned that values around 100 are normal, and 150 is an anomaly.
Detailed Algorithm Documentation
Three Sigma Detector (TThreeSigmaDetector)
What it does: Uses the statistical “68-95-99.7 rule” to flag values outside 3 standard deviations from the mean.
When to use:
- You have a complete historical dataset
- Data distribution is roughly normal
- One-time batch analysis
- Establishing baselines for other detectors
When NOT to use:
- Streaming/real-time data (use Sliding Window instead)
- Non-normal distributions
- Data with seasonal patterns
uses AnomalyDetection.ThreeSigma;
var
Detector: TThreeSigmaDetector;
begin
Detector := TThreeSigmaDetector.Create;
try
// Load manufacturing measurements
Detector.AddValues([100.2, 99.8, 100.5, 99.9, 100.1, 100.3, 99.7]);
Detector.Build;
WriteLn('Mean: ', Detector.Mean:0:2); // ~100.07
WriteLn('StdDev: ', Detector.StdDev:0:2); // ~0.26
WriteLn('Lower Limit: ', Detector.LowerLimit:0:2); // ~99.29
WriteLn('Upper Limit: ', Detector.UpperLimit:0:2); // ~100.85
// Test new measurement
if Detector.IsAnomaly(105.5) then
WriteLn('Quality issue detected!');
finally
Detector.Free;
end;
end;
Sliding Window Detector (TSlidingWindowDetector)
What it does: Maintains a fixed-size window of recent values, automatically adapting as new data arrives.
When to use:
- Real-time monitoring
- Streaming data
- Memory-constrained environments
- Balance between responsiveness and stability
Key parameter: WindowSize - larger = more stable, smaller = more responsive
uses AnomalyDetection.SlidingWindow;
var
Detector: TSlidingWindowDetector;
begin
Detector := TSlidingWindowDetector.Create(100); // 100-value window
try
// Initialize with baseline
Detector.InitializeWindow([95, 98, 102, 97, 101, 99, 103]);
// Process streaming data
while HasIncomingData do
begin
Value := GetNextReading;
if Detector.IsAnomaly(Value) then
TriggerAlert('Anomaly: ' + Value.ToString);
Detector.AddValue(Value); // Slides the window
end;
finally
Detector.Free;
end;
end;
EMA Detector (TEMAAnomalyDetector)
What it does: Exponential Moving Average gives more weight to recent values, enabling very fast adaptation.
When to use:
- Financial/stock data
- Rapidly changing metrics
- Need immediate response to changes
- Minimal memory footprint required
Key parameter: Alpha (0.01-0.3) - higher = more responsive, lower = more stable
uses AnomalyDetection.EMA;
var
Detector: TEMAAnomalyDetector;
begin
Detector := TEMAAnomalyDetector.Create(0.1); // Alpha = 0.1
try
Detector.WarmUp([50.2, 50.5, 49.8, 50.1, 50.3]);
for var Price in StockPrices do
begin
if Detector.IsAnomaly(Price) then
begin
if Price > Detector.CurrentMean then
WriteLn('Price SPIKE: ', Price:0:2)
else
WriteLn('Price DROP: ', Price:0:2);
end;
Detector.AddValue(Price);
end;
finally
Detector.Free;
end;
end;
Adaptive Detector (TAdaptiveAnomalyDetector)
What it does: Learns from confirmed normal values, continuously adapting to concept drift.
When to use:
- “Normal” behavior changes over time
- Seasonal patterns
- User behavior analysis
- Long-term monitoring with feedback
uses AnomalyDetection.Adaptive;
var
Detector: TAdaptiveAnomalyDetector;
begin
Detector := TAdaptiveAnomalyDetector.Create(30, 0.05); // 30-day window, 5% adaptation
try
Detector.InitializeWithNormalData([45, 52, 48, 55, 50, 47, 53]);
for var Day := 1 to 365 do
begin
CPUUsage := GetServerCPU;
if Detector.IsAnomaly(CPUUsage) then
begin
if UserConfirmsNormal then
Detector.UpdateNormal(CPUUsage) // Teach: this is actually normal
else
InvestigateCPUSpike(CPUUsage);
end
else
Detector.UpdateNormal(CPUUsage); // Learn from normal data
end;
finally
Detector.Free;
end;
end;
Isolation Forest (TIsolationForestDetector)
What it does: Machine learning algorithm that isolates anomalies by randomly partitioning feature space. Anomalies are “easier to isolate” than normal points.
When to use:
- Multi-dimensional data (multiple features per observation)
- Fraud detection (amount + time + location + user behavior)
- Cybersecurity (network traffic analysis)
- No labeled training data available (unsupervised)
This is the recommended algorithm for fraud detection.
uses AnomalyDetection.IsolationForest;
var
Detector: TIsolationForestDetector;
Transaction: TArray<Double>;
begin
// 100 trees, 256 samples, 5 features
Detector := TIsolationForestDetector.Create(100, 256, 5);
try
// Train on normal transactions
for i := 1 to 1000 do
begin
Transaction := [
50 + Random(200), // Amount ($50-$250)
8 + Random(12), // Hour (8 AM - 8 PM)
1 + Random(5), // Weekday (1-5)
1 + Random(10), // Merchant category
25 + Random(40) // Customer age
];
Detector.AddTrainingData(Transaction);
end;
Detector.Train; // Build the forest
// Test suspicious transaction: $5000 at 3 AM
Transaction := [5000, 3, 2, 5, 35];
Result := Detector.DetectMultiDimensional(Transaction);
if Result.IsAnomaly then
FlagForReview('Potential fraud! Score: ' + Result.ZScore.ToString);
finally
Detector.Free;
end;
end;
Anomaly Confirmation System (TAnomalyConfirmationSystem)
What it does: Meta-detector that requires multiple similar anomalies before confirming an alert.
When to use:
- False positives are costly (pager alerts, blocking transactions)
- Critical systems requiring high confidence
- Can tolerate slight detection delay
uses AnomalyDetection.Confirmation;
var
BaseDetector: TSlidingWindowDetector;
Confirmation: TAnomalyConfirmationSystem;
begin
BaseDetector := TSlidingWindowDetector.Create(100);
Confirmation := TAnomalyConfirmationSystem.Create(
10, // Window size
3, // Require 3 similar anomalies
0.1 // 10% tolerance for "similar"
);
try
while HasData do
begin
Value := GetNextValue;
if BaseDetector.IsAnomaly(Value) then
begin
Confirmation.AddPotentialAnomaly(Value);
// Only alert if CONFIRMED (3 similar anomalies in window)
if Confirmation.IsConfirmedAnomaly(Value) then
SendCriticalAlert('CONFIRMED anomaly: ' + Value.ToString);
end;
BaseDetector.AddValue(Value);
end;
finally
Confirmation.Free;
BaseDetector.Free;
end;
end;
Data Preprocessing: Cleaning Your Training Data
If your historical data contains outliers, clean it before training:
uses AnomalyDetection.Utils;
var
RawData: TArray<Double>;
CleanResult: TCleaningResult;
begin
RawData := LoadHistoricalData; // May contain outliers
// Method 1: Percentile-based (remove top/bottom 5%)
CleanResult := CleanDataWithPercentiles(RawData, 5, 95);
// Method 2: IQR-based (standard statistical method)
CleanResult := CleanDataWithIQR(RawData, 1.5);
WriteLn(Format('Removed %d outliers (%.1f%%)',
[CleanResult.RemovedCount, CleanResult.RemovalPercent]));
// Train detector on clean data
Detector.AddValues(CleanResult.CleanData);
Detector.Build;
end;
When to clean data:
- Required: ThreeSigma, SlidingWindow, EMA with potentially contaminated data
- Not needed: Isolation Forest (robust to outliers by design)
Factory Pattern: Pre-Configured Detectors
Get started quickly with domain-optimized settings:
uses AnomalyDetection.Factory;
// For web traffic / DDoS detection
WebDetector := TAnomalyDetectorFactory.CreateForWebTrafficMonitoring;
// For financial data (higher precision)
FinanceDetector := TAnomalyDetectorFactory.CreateForFinancialData;
// For IoT sensors (balanced reliability)
IoTDetector := TAnomalyDetectorFactory.CreateForIoTSensors;
// For multi-dimensional fraud detection
FraudDetector := TAnomalyDetectorFactory.CreateForHighDimensionalData;
Performance Evaluation & Hyperparameter Tuning
Measuring Detector Accuracy
uses AnomalyDetection.Evaluation;
var
Dataset: TLabeledDataset;
Evaluator: TAnomalyDetectorEvaluator;
Result: TEvaluationResult;
begin
// Load labeled test data
Dataset := TLabeledDataset.Create('Test Data');
Dataset.LoadFromCSV('labeled_data.csv', 0, 1, True);
Evaluator := TAnomalyDetectorEvaluator.Create(Detector, Dataset);
try
Result := Evaluator.Evaluate;
WriteLn('Accuracy: ', Result.ConfusionMatrix.GetAccuracy:0:3);
WriteLn('Precision: ', Result.ConfusionMatrix.GetPrecision:0:3);
WriteLn('Recall: ', Result.ConfusionMatrix.GetRecall:0:3);
WriteLn('F1-Score: ', Result.ConfusionMatrix.GetF1Score:0:3);
finally
Evaluator.Free;
Dataset.Free;
end;
end;
Finding Optimal Parameters with Grid Search
uses AnomalyDetection.Evaluation;
var
Tuner: THyperparameterTuner;
BestConfig: TTuningResult;
begin
Tuner := THyperparameterTuner.Create(adtSlidingWindow, Dataset);
try
Tuner.OptimizationMetric := 'F1'; // Or 'Precision', 'Recall', 'Accuracy'
BestConfig := Tuner.GridSearch(
[2.0, 2.5, 3.0, 3.5, 4.0], // Sigma values to test
nil,
[50, 100, 150, 200], // Window sizes to test
nil
);
WriteLn('Best Sigma: ', BestConfig.Config.SigmaMultiplier:0:2);
WriteLn('Best Window: ', BestConfig.Config.WindowSize);
WriteLn('F1-Score: ', BestConfig.Score:0:3);
finally
Tuner.Free;
end;
end;
Which Metric to Optimize?
| Metric | Optimize When | Trade-off |
|---|---|---|
| Precision | False alarms are costly (alert fatigue) | May miss some anomalies |
| Recall | Missing anomalies is unacceptable (fraud, security) | More false alarms |
| F1-Score | Need balanced detection | General purpose |
| Accuracy | Dataset is balanced (rare in anomaly detection) | Can be misleading |
Real-World Examples
Invoice Amount Validation
type
TInvoiceValidator = class
private
FDetectors: TDictionary<string, TSlidingWindowDetector>;
public
function ValidateAmount(const SupplierCode: string; Amount: Double;
out Warning: string): Boolean;
end;
function TInvoiceValidator.ValidateAmount(const SupplierCode: string;
Amount: Double; out Warning: string): Boolean;
var
Detector: TSlidingWindowDetector;
AnomalyResult: TAnomalyResult;
begin
// One detector per supplier (learns supplier-specific patterns)
if not FDetectors.TryGetValue(SupplierCode, Detector) then
begin
Detector := TSlidingWindowDetector.Create(50);
FDetectors.Add(SupplierCode, Detector);
end;
AnomalyResult := Detector.Detect(Amount);
if AnomalyResult.IsAnomaly then
begin
Warning := Format('Unusual amount for %s: %.2f (expected %.2f - %.2f)',
[SupplierCode, Amount, AnomalyResult.LowerLimit, AnomalyResult.UpperLimit]);
Result := False;
end
else
begin
Warning := '';
Result := True;
end;
Detector.AddValue(Amount); // Learn from this invoice
end;
System Monitoring Service
type
TMonitoringService = class
private
FCPUDetector: TEMAAnomalyDetector;
FMemoryDetector: TSlidingWindowDetector;
FConfirmation: TAnomalyConfirmationSystem;
public
procedure CheckMetrics;
end;
procedure TMonitoringService.CheckMetrics;
begin
// CPU: fast response with EMA
if FCPUDetector.IsAnomaly(GetCPUUsage) then
begin
FConfirmation.AddPotentialAnomaly(GetCPUUsage);
if FConfirmation.IsConfirmedAnomaly(GetCPUUsage) then
SendAlert('Confirmed CPU spike');
end;
// Memory: stable detection with Sliding Window
if FMemoryDetector.IsAnomaly(GetMemoryUsage) then
LogWarning('Memory anomaly detected');
end;
Performance Benchmarks
Typical throughput on modern hardware (single-threaded):
| Algorithm | Detections/sec | Memory | Training Time |
|---|---|---|---|
| EMA | ~100,000 | 1 KB | Instant |
| Three Sigma | ~80,000 | ~8n bytes | One-time |
| Sliding Window | ~50,000 | ~8 x window | Instant |
| Adaptive | ~70,000 | ~8 x window | Instant |
| Isolation Forest | ~20,000 | ~MB scale | Seconds-Minutes |
| Confirmation | Very Fast | ~8 x window | Instant |
API Reference Summary
Common Methods (All Detectors)
| Method | Description |
|---|---|
Detect(Value): TAnomalyResult |
Full analysis with Z-score and limits |
IsAnomaly(Value): Boolean |
Quick true/false check |
AddValue(Value) |
Add value and update model |
Build / Train |
Calculate statistics / train model |
SaveToFile(FileName) |
Persist detector state |
LoadFromFile(FileName) |
Restore detector state |
TAnomalyResult Fields
| Field | Type | Description |
|---|---|---|
IsAnomaly |
Boolean | True if anomaly detected |
Value |
Double | The tested value |
ZScore |
Double | Statistical Z-score |
LowerLimit |
Double | Lower threshold |
UpperLimit |
Double | Upper threshold |
Description |
String | Human-readable explanation |
Frequently Asked Questions
What Delphi version is required?
Delphi 10.3 Rio or later. The library uses modern language features like generics and anonymous methods.
Does it work on mobile (iOS/Android)?
Yes, the library is pure Pascal with no platform-specific code. It works on all platforms supported by Delphi: Windows, macOS, Linux, iOS, and Android.
Is it thread-safe?
Yes, detectors use internal critical sections for thread safety. For high-throughput scenarios, consider using separate detector instances per thread.
How do I handle concept drift?
Use the Adaptive Detector (TAdaptiveAnomalyDetector) which learns from confirmed normal values. Call UpdateNormal(Value) to teach the detector that a value is actually normal.
Can I save and restore detector state?
Yes, all detectors support SaveToFile() and LoadFromFile() for persisting trained models.
How do I choose window size for Sliding Window?
- Small window (20-50): More responsive, adapts quickly, more false positives
- Large window (100-500): More stable, slower to adapt, fewer false positives
- Start with 100 and tune based on your data characteristics
Installation
- Download from GitHub
- Add
AnomalyDetectionAlgorithms.pasto your project - Include in uses clause:
uses AnomalyDetection.Factory, AnomalyDetection.ThreeSigma; - Start detecting anomalies!
Requirements
- Delphi: 10.3 Rio or later
- Dependencies: None
- Platforms: Windows, macOS, Linux, iOS, Android
Links
- GitHub Repository: github.com/danieleteti/delphi-anomalies-detectors
- Community Support: DelphiMVCFramework Facebook Group
- Professional Services: Bit Time Professionals
Professional Support
Bit Time Professionals offers commercial support for the Delphi Anomaly Detection Library:
- Training & Workshops - On-site or remote training on anomaly detection implementation
- Consulting - System design for large-scale detection pipelines
- Custom Development - Domain-specific detectors for specialized industries
Contact: professionals@bittime.it
References
- Statistical Process Control (SPC) principles
- Liu, F. T., Ting, K. M., & Zhou, Z. H. (2008). “Isolation Forest”
- Brown, R. G. (1959). “Exponential Smoothing”
Delphi Anomaly Detection Library - Production-ready anomaly detection for Delphi. Free and open-source under Apache 2.0 license.
Comments
comments powered by Disqus