feat(ml): re-enable hyperopt action counting (fixes 62% Sharpe degradation)

This commit is contained in:
jgrusewski
2026-02-21 21:20:45 +01:00
parent 4a8513f813
commit ece9ae11d2
10 changed files with 792 additions and 72 deletions

View File

@@ -453,6 +453,12 @@ impl ComplianceEngine {
}
/// Assess `MAR` compliance
///
/// Performs basic market surveillance checks including:
/// - Unusual volume detection (large order quantities)
/// - Price deviation analysis (limit price vs market volatility)
/// - Suspicious pattern detection (off-hours trading, stressed market activity)
#[allow(clippy::float_arithmetic)]
async fn assess_mar_compliance(
&self,
context: &ComplianceContext,
@@ -462,23 +468,200 @@ impl ComplianceEngine {
return Ok(ComplianceStatus::NotApplicable);
}
// TODO: Market surveillance analysis (when module is implemented)
// Market surveillance analysis
if let Some(_order) = &context.order_info {
// Placeholder - market surveillance module not yet implemented
findings.push(ComplianceFinding {
id: format!("MAR-TODO-{}", Uuid::new_v4()),
regulation: "Market Abuse Regulation".to_owned(),
severity: ComplianceSeverity::Info,
description: "Market surveillance module not yet implemented".to_owned(),
remediation: "Implement market surveillance analysis".to_owned(),
due_date: Some(Utc::now() + Duration::days(30)),
status: FindingStatus::Open,
});
let mut warnings: Vec<String> = Vec::new();
let mut has_violation = false;
// --- Check 1: Unusual volume detection ---
if let Some(order) = &context.order_info {
let qty = order.quantity.to_f64();
// Flag extraordinarily large orders as potential market manipulation
// (layering/spoofing indicator). In production this threshold would be
// instrument-specific and derived from historical ADV; here we use a
// conservative static bound as a baseline surveillance heuristic.
const LARGE_ORDER_THRESHOLD: f64 = 100_000.0;
const VERY_LARGE_ORDER_THRESHOLD: f64 = 500_000.0;
if qty > VERY_LARGE_ORDER_THRESHOLD {
findings.push(ComplianceFinding {
id: format!("MAR-VOL-CRIT-{}", Uuid::new_v4()),
regulation: "MAR Article 16 - Suspicious Order Detection".to_owned(),
severity: ComplianceSeverity::High,
description: format!(
"Exceptionally large order detected: {qty:.2} units on {} ({}). \
Order size exceeds critical threshold ({VERY_LARGE_ORDER_THRESHOLD:.0}) \
and may indicate market manipulation or erroneous order entry.",
order.symbol, order.side
),
remediation: "Investigate order origin. Verify client intent and \
review for potential layering or spoofing activity."
.to_owned(),
due_date: Some(Utc::now() + Duration::hours(4)),
status: FindingStatus::Open,
});
has_violation = true;
} else if qty > LARGE_ORDER_THRESHOLD {
findings.push(ComplianceFinding {
id: format!("MAR-VOL-{}", Uuid::new_v4()),
regulation: "MAR Article 16 - Unusual Volume".to_owned(),
severity: ComplianceSeverity::Medium,
description: format!(
"Large order detected: {qty:.2} units on {} ({}). \
Exceeds surveillance threshold ({LARGE_ORDER_THRESHOLD:.0}).",
order.symbol, order.side
),
remediation:
"Monitor subsequent order flow for this symbol and client."
.to_owned(),
due_date: Some(Utc::now() + Duration::hours(24)),
status: FindingStatus::Open,
});
warnings.push(format!("Large order volume on {}", order.symbol));
}
// --- Check 2: Price deviation analysis ---
// When a limit price is set, check for anomalies. A price of zero
// is treated as potentially erroneous. With market context we also
// flag large limit orders during high volatility.
if let Some(limit_price) = &order.price {
let price_val = limit_price.to_f64();
// Zero or near-zero limit price is suspicious
if price_val < f64::EPSILON {
findings.push(ComplianceFinding {
id: format!("MAR-PRC-ZERO-{}", Uuid::new_v4()),
regulation: "MAR Article 12 - Price Manipulation".to_owned(),
severity: ComplianceSeverity::High,
description: format!(
"Order on {} has a zero or near-zero limit price ({price_val:.8}). \
This may indicate an erroneous order or attempted price manipulation.",
order.symbol
),
remediation:
"Reject or hold order pending manual review of price validity."
.to_owned(),
due_date: Some(Utc::now() + Duration::hours(1)),
status: FindingStatus::Open,
});
has_violation = true;
}
// In high-volatility markets, large limit orders carry
// elevated manipulation risk
if let Some(mkt) = &context.market_context {
if mkt.volatility > 0.05 && qty > LARGE_ORDER_THRESHOLD {
findings.push(ComplianceFinding {
id: format!("MAR-PRC-HVOL-{}", Uuid::new_v4()),
regulation: "MAR Article 12 - Price Manipulation Risk".to_owned(),
severity: ComplianceSeverity::Medium,
description: format!(
"Large limit order ({qty:.2} units @ {price_val:.4}) on {} \
during high volatility (vol={:.4}). Elevated manipulation risk.",
order.symbol, mkt.volatility
),
remediation: "Cross-reference with recent price movements. \
Verify order is not part of a layering pattern."
.to_owned(),
due_date: Some(Utc::now() + Duration::hours(8)),
status: FindingStatus::Open,
});
warnings.push("High-vol limit order".to_owned());
}
}
}
}
// Ok variant
Ok(ComplianceStatus::Compliant)
// --- Check 3: Suspicious pattern detection ---
// Trading during off-hours or market stress can indicate insider
// knowledge or manipulative intent.
if let Some(mkt) = &context.market_context {
match mkt.session {
TradingSession::PreMarket | TradingSession::AfterHours => {
if let Some(order) = &context.order_info {
let qty = order.quantity.to_f64();
// Large off-hours orders are more suspicious
if qty > 10_000.0 {
findings.push(ComplianceFinding {
id: format!("MAR-PAT-OOH-{}", Uuid::new_v4()),
regulation: "MAR Article 16 - Off-Hours Surveillance".to_owned(),
severity: ComplianceSeverity::Medium,
description: format!(
"Significant order ({qty:.2} units) on {} placed during \
{:?} session. Off-hours large orders warrant additional \
scrutiny for potential insider trading.",
order.symbol, mkt.session
),
remediation: "Review client trading history for pattern of \
off-hours activity preceding material events."
.to_owned(),
due_date: Some(Utc::now() + Duration::hours(24)),
status: FindingStatus::Open,
});
warnings.push("Off-hours large order".to_owned());
}
}
}
TradingSession::Closed => {
// Orders submitted while market is closed are abnormal
if context.order_info.is_some() {
findings.push(ComplianceFinding {
id: format!("MAR-PAT-CLOSED-{}", Uuid::new_v4()),
regulation: "MAR Article 16 - Closed Market Order".to_owned(),
severity: ComplianceSeverity::High,
description:
"Order submitted during closed market session. \
This is abnormal and may indicate system error or \
attempted manipulation."
.to_owned(),
remediation:
"Verify order source and system clock synchronization."
.to_owned(),
due_date: Some(Utc::now() + Duration::hours(1)),
status: FindingStatus::Open,
});
has_violation = true;
}
}
TradingSession::Regular => {}
}
// Stressed market conditions warrant heightened surveillance
if matches!(mkt.conditions, MarketConditions::Stress) {
if let Some(order) = &context.order_info {
findings.push(ComplianceFinding {
id: format!("MAR-PAT-STRESS-{}", Uuid::new_v4()),
regulation: "MAR Article 12 - Stressed Market Activity".to_owned(),
severity: ComplianceSeverity::Medium,
description: format!(
"Order on {} submitted during market stress conditions. \
Enhanced surveillance required per MAR guidelines.",
order.symbol
),
remediation:
"Apply enhanced monitoring. Review for potential exploitation \
of stressed conditions."
.to_owned(),
due_date: Some(Utc::now() + Duration::hours(12)),
status: FindingStatus::Open,
});
warnings.push("Stressed market order".to_owned());
}
}
}
// --- Determine MAR status ---
if has_violation {
Ok(ComplianceStatus::Violation(
warnings
.into_iter()
.chain(std::iter::once("MAR violation detected".to_owned()))
.collect(),
))
} else if !warnings.is_empty() {
Ok(ComplianceStatus::Warning(warnings))
} else {
Ok(ComplianceStatus::Compliant)
}
}
/// Assess data protection compliance

View File

@@ -1584,14 +1584,16 @@ pub enum ReviewStatus {
}
/// `SOX` Audit Logger
#[derive(Debug)]
/// `SOXAuditLogger`
///
/// Auto-generated documentation placeholder - enhance with specifics
/// Maintains an in-memory audit trail and asynchronously persists events
/// to a JSONL file via a background tokio task for durable SOX compliance.
#[derive(Debug)]
#[allow(dead_code)]
pub struct SOXAuditLogger {
audit_trail: Vec<SOXAuditEvent>,
retention_policy: AuditRetentionPolicy,
/// Async channel sender for persisting audit events to disk
audit_writer: Option<tokio::sync::mpsc::UnboundedSender<SOXAuditEvent>>,
}
/// `SOX` audit event
@@ -2108,6 +2110,45 @@ impl AccessControlMatrix {
impl SOXAuditLogger {
pub fn new(retention_days: &u32) -> Self {
let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel::<SOXAuditEvent>();
tokio::spawn(async move {
use tokio::io::AsyncWriteExt;
// Ensure the audit directory exists
if let Err(e) = tokio::fs::create_dir_all("audit").await {
tracing::error!("Failed to create audit directory: {e}");
return;
}
let file = tokio::fs::OpenOptions::new()
.create(true)
.append(true)
.open("audit/sox_audit_trail.jsonl")
.await;
let mut file = match file {
Ok(f) => f,
Err(e) => {
tracing::error!("Failed to open SOX audit trail file: {e}");
return;
}
};
while let Some(event) = rx.recv().await {
let line = match serde_json::to_string(&event) {
Ok(json) => format!("{json}\n"),
Err(e) => {
tracing::error!("Failed to serialize SOX audit event: {e}");
continue;
}
};
if let Err(e) = file.write_all(line.as_bytes()).await {
tracing::error!("Failed to write SOX audit event: {e}");
}
}
});
Self {
audit_trail: Vec::new(),
retention_policy: AuditRetentionPolicy {
@@ -2116,6 +2157,7 @@ impl SOXAuditLogger {
compression_enabled: true,
encryption_required: true,
},
audit_writer: Some(tx),
}
}
@@ -2124,10 +2166,12 @@ impl SOXAuditLogger {
// Add to in-memory trail for immediate access
self.audit_trail.push(event.clone());
// TODO: Implement high-performance async persistence
// - Use lock-free ring buffer for HFT compatibility
// - Batch events for efficient disk writes
// - Compress and encrypt per retention policy
// Persist asynchronously via background writer task
if let Some(ref tx) = self.audit_writer {
if let Err(e) = tx.send(event) {
tracing::error!("SOX audit persistence channel closed: {e}");
}
}
Ok(())
}