Skip to main content

ringkernel_accnet/analytics/
mod.rs

1//! Analytics engine for real-time analysis of the accounting network.
2//!
3//! Provides high-level analysis combining outputs from GPU kernels.
4
5use crate::models::AccountingNetwork;
6use std::collections::HashMap;
7
8/// The main analytics engine.
9pub struct AnalyticsEngine {
10    /// Risk thresholds
11    pub thresholds: RiskThresholds,
12}
13
14/// Configuration thresholds for risk assessment.
15#[derive(Debug, Clone)]
16pub struct RiskThresholds {
17    /// Suspense score threshold
18    pub suspense_threshold: f32,
19    /// Confidence threshold for low-confidence alerts
20    pub confidence_threshold: f32,
21    /// Benford chi-squared threshold
22    pub benford_chi_sq_threshold: f64,
23    /// Z-score threshold for anomaly detection
24    pub z_score_threshold: f64,
25}
26
27impl Default for RiskThresholds {
28    fn default() -> Self {
29        Self {
30            suspense_threshold: 0.7,
31            confidence_threshold: 0.5,
32            benford_chi_sq_threshold: 15.507,
33            z_score_threshold: 3.0,
34        }
35    }
36}
37
38impl AnalyticsEngine {
39    /// Create a new analytics engine.
40    pub fn new() -> Self {
41        Self {
42            thresholds: RiskThresholds::default(),
43        }
44    }
45
46    /// Create with custom thresholds.
47    pub fn with_thresholds(thresholds: RiskThresholds) -> Self {
48        Self { thresholds }
49    }
50
51    /// Analyze the network and return a snapshot.
52    pub fn analyze(&self, network: &AccountingNetwork) -> AnalyticsSnapshot {
53        let mut snapshot = AnalyticsSnapshot {
54            overall_risk: self.calculate_overall_risk(network),
55            suspense_accounts: network.statistics.suspense_account_count,
56            gaap_violations: network.statistics.gaap_violation_count,
57            fraud_patterns: network.statistics.fraud_pattern_count,
58            ..Default::default()
59        };
60
61        // Account risks
62        for account in &network.accounts {
63            snapshot.account_risks.insert(
64                account.index,
65                RiskScore {
66                    total: account.risk_score,
67                    suspense_component: account.suspense_score * 0.3,
68                    fraud_component: if account
69                        .flags
70                        .has(crate::models::AccountFlags::HAS_FRAUD_PATTERN)
71                    {
72                        0.5
73                    } else {
74                        0.0
75                    },
76                    confidence_component: 0.0, // Would be calculated from flows
77                },
78            );
79        }
80
81        // Network health
82        snapshot.network_health = NetworkHealth {
83            balance_check: true, // Simplified
84            coverage: network.statistics.avg_confidence,
85            connectivity: network.statistics.density,
86        };
87
88        snapshot
89    }
90
91    /// Calculate overall risk score for the network.
92    fn calculate_overall_risk(&self, network: &AccountingNetwork) -> f32 {
93        let n = network.accounts.len().max(1) as f32;
94
95        // Weighted combination of risk factors
96        let suspense_ratio = network.statistics.suspense_account_count as f32 / n;
97        let violation_ratio = network.statistics.gaap_violation_count as f32 / n;
98        let fraud_ratio = network.statistics.fraud_pattern_count as f32 / n;
99        let confidence_factor = 1.0 - network.statistics.avg_confidence as f32;
100
101        (0.25 * suspense_ratio
102            + 0.30 * violation_ratio
103            + 0.35 * fraud_ratio
104            + 0.10 * confidence_factor)
105            .min(1.0)
106    }
107}
108
109impl Default for AnalyticsEngine {
110    fn default() -> Self {
111        Self::new()
112    }
113}
114
115/// Snapshot of analytics results.
116#[derive(Debug, Clone, Default)]
117pub struct AnalyticsSnapshot {
118    /// Overall network risk score (0.0 - 1.0)
119    pub overall_risk: f32,
120    /// Number of suspected suspense accounts
121    pub suspense_accounts: usize,
122    /// Number of GAAP violations detected
123    pub gaap_violations: usize,
124    /// Number of fraud patterns detected
125    pub fraud_patterns: usize,
126    /// Risk scores by account
127    pub account_risks: HashMap<u16, RiskScore>,
128    /// Network health metrics
129    pub network_health: NetworkHealth,
130}
131
132/// Risk score breakdown for an account.
133#[derive(Debug, Clone, Default)]
134pub struct RiskScore {
135    /// Total risk score
136    pub total: f32,
137    /// Contribution from suspense detection
138    pub suspense_component: f32,
139    /// Contribution from fraud patterns
140    pub fraud_component: f32,
141    /// Contribution from low confidence
142    pub confidence_component: f32,
143}
144
145/// Network health metrics.
146#[derive(Debug, Clone, Default)]
147pub struct NetworkHealth {
148    /// Whether all entries balance
149    pub balance_check: bool,
150    /// Average transformation confidence
151    pub coverage: f64,
152    /// Network connectivity (density)
153    pub connectivity: f64,
154}
155
156#[cfg(test)]
157mod tests {
158    use super::*;
159    use uuid::Uuid;
160
161    #[test]
162    fn test_analytics_engine() {
163        let engine = AnalyticsEngine::new();
164        let network = AccountingNetwork::new(Uuid::new_v4(), 2024, 1);
165        let snapshot = engine.analyze(&network);
166
167        assert!(snapshot.overall_risk >= 0.0 && snapshot.overall_risk <= 1.0);
168    }
169}