Move 17 library crates into crates/, CLI binary into bin/fxt, consolidate 10 test crates into testing/, split config crate from deployment config files. Root directory reduced from 38+ to ~17 directories. All Cargo.toml paths and build.rs proto refs updated. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
674 lines
21 KiB
Rust
674 lines
21 KiB
Rust
//! Comprehensive Compliance Validation Test Suite
|
|
//!
|
|
//! This module provides extensive tests for all compliance functionality,
|
|
//! ensuring regulatory adherence for SOX, MiFID II, and other requirements.
|
|
//! Includes property-based testing and regulatory scenario validation.
|
|
#![allow(unused_crate_dependencies)]
|
|
|
|
use chrono::{Duration, Utc};
|
|
use proptest::prelude::*;
|
|
use std::collections::HashMap;
|
|
|
|
// Import common types
|
|
use common::{OrderId, OrderSide, OrderType, Price, Quantity};
|
|
use rust_decimal::Decimal;
|
|
|
|
// Import compliance modules
|
|
use trading_engine::compliance::{
|
|
audit_trails::{
|
|
AuditEventType, AuditTrailConfig, AuditTrailEngine, ExecutionDetails, OrderDetails,
|
|
},
|
|
automated_reporting::AutomatedReportingConfig,
|
|
best_execution::BestExecutionAnalyzer,
|
|
regulatory_api::{RegulatoryApiConfig, RegulatoryApiServer},
|
|
sox_compliance::{EventOutcome, SOXAuditEvent, SOXComplianceManager, SOXConfig, SOXEventType},
|
|
transaction_reporting::{OrderExecution, TransactionReporter},
|
|
ComplianceConfig, ComplianceEngine, ComplianceStatus, OrderInfo,
|
|
};
|
|
|
|
/// Compliance test suite
|
|
#[derive(Debug)]
|
|
pub struct ComplianceTestSuite {
|
|
compliance_engine: ComplianceEngine,
|
|
sox_manager: SOXComplianceManager,
|
|
transaction_reporter: TransactionReporter,
|
|
audit_trail_engine: AuditTrailEngine,
|
|
}
|
|
|
|
impl ComplianceTestSuite {
|
|
/// Create new test suite with default configuration
|
|
pub fn new() -> Self {
|
|
let compliance_config = ComplianceConfig::default();
|
|
let sox_config = SOXConfig::default();
|
|
let audit_config = AuditTrailConfig::default();
|
|
|
|
Self {
|
|
compliance_engine: ComplianceEngine::new(compliance_config.clone()),
|
|
sox_manager: SOXComplianceManager::new(&sox_config),
|
|
transaction_reporter: TransactionReporter::new(&compliance_config.mifid2),
|
|
audit_trail_engine: AuditTrailEngine::new(audit_config),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Test basic compliance engine functionality
|
|
#[tokio::test]
|
|
async fn test_compliance_engine_basic_functionality() {
|
|
let test_suite = ComplianceTestSuite::new();
|
|
|
|
// Create test context
|
|
let context = create_test_compliance_context();
|
|
|
|
// Assess compliance
|
|
let result = test_suite
|
|
.compliance_engine
|
|
.assess_compliance(&context)
|
|
.await;
|
|
assert!(result.is_ok(), "Compliance assessment should succeed");
|
|
|
|
let compliance_result = result.unwrap();
|
|
assert!(
|
|
compliance_result.compliance_score >= 0.0 && compliance_result.compliance_score <= 100.0,
|
|
"Compliance score should be between 0 and 100"
|
|
);
|
|
}
|
|
|
|
/// Test SOX compliance manager
|
|
#[tokio::test]
|
|
async fn test_sox_compliance_manager() {
|
|
let test_suite = ComplianceTestSuite::new();
|
|
|
|
// Test SOX compliance assessment
|
|
let assessment = test_suite.sox_manager.assess_sox_compliance().await;
|
|
assert!(assessment.is_ok(), "SOX assessment should succeed");
|
|
|
|
let sox_result = assessment.unwrap();
|
|
assert!(
|
|
sox_result.overall_score >= 0.0,
|
|
"SOX score should be non-negative"
|
|
);
|
|
}
|
|
|
|
/// Test SOX audit logging
|
|
#[tokio::test]
|
|
async fn test_sox_audit_logging() {
|
|
let test_suite = ComplianceTestSuite::new();
|
|
let sox_manager = test_suite.sox_manager;
|
|
|
|
// Create test audit event
|
|
let _audit_event = SOXAuditEvent {
|
|
event_id: "TEST-001".to_string(),
|
|
event_type: SOXEventType::ControlTesting,
|
|
timestamp: Utc::now(),
|
|
actor: "test_user".to_string(),
|
|
resource: "test_control".to_string(),
|
|
details: HashMap::new(),
|
|
outcome: EventOutcome::Success,
|
|
ip_address: Some("127.0.0.1".to_string()),
|
|
session_id: Some("session_123".to_string()),
|
|
};
|
|
|
|
// Test audit logging (note: this would need access to the audit_logger field)
|
|
// For now, just verify the manager exists
|
|
assert!(format!("{:?}", sox_manager).contains("SOXComplianceManager"));
|
|
}
|
|
|
|
/// Test MiFID II transaction reporting
|
|
#[tokio::test]
|
|
async fn test_mifid2_transaction_reporting() {
|
|
let test_suite = ComplianceTestSuite::new();
|
|
|
|
// Create test execution
|
|
let execution = create_test_order_execution();
|
|
|
|
// Generate transaction report
|
|
let report = test_suite
|
|
.transaction_reporter
|
|
.generate_transaction_report(&execution)
|
|
.await;
|
|
assert!(
|
|
report.is_ok(),
|
|
"Transaction report generation should succeed"
|
|
);
|
|
|
|
let transaction_report = report.unwrap();
|
|
assert!(
|
|
!transaction_report.header.report_id.is_empty(),
|
|
"Report should have an ID"
|
|
);
|
|
assert_eq!(
|
|
transaction_report.transaction.transaction_reference,
|
|
execution.execution_id
|
|
);
|
|
}
|
|
|
|
/// Test transaction audit trails
|
|
#[tokio::test]
|
|
async fn test_transaction_audit_trails() {
|
|
let test_suite = ComplianceTestSuite::new();
|
|
|
|
// Test order creation logging
|
|
let order_details = create_test_order_details();
|
|
let result = test_suite
|
|
.audit_trail_engine
|
|
.log_order_created("ORDER-123", &order_details);
|
|
assert!(result.is_ok(), "Order creation logging should succeed");
|
|
|
|
// Test execution logging
|
|
let execution_details = create_test_execution_details();
|
|
let result = test_suite
|
|
.audit_trail_engine
|
|
.log_order_executed(&execution_details);
|
|
assert!(result.is_ok(), "Execution logging should succeed");
|
|
}
|
|
|
|
/// Test best execution analysis
|
|
#[tokio::test]
|
|
async fn test_best_execution_analysis() {
|
|
let compliance_config = ComplianceConfig::default();
|
|
let analyzer = BestExecutionAnalyzer::new(&compliance_config.mifid2);
|
|
|
|
let order = create_test_order_info();
|
|
|
|
// Analyze best execution
|
|
let analysis = analyzer.analyze_best_execution(&order).await;
|
|
assert!(analysis.is_ok(), "Best execution analysis should succeed");
|
|
|
|
let execution_report = analysis.unwrap();
|
|
assert!(
|
|
execution_report.execution_quality_score >= 0.0
|
|
&& execution_report.execution_quality_score <= 100.0,
|
|
"Execution quality score should be between 0 and 100"
|
|
);
|
|
}
|
|
|
|
// Property-based test for compliance scores
|
|
proptest! {
|
|
#[test]
|
|
fn prop_test_compliance_scores(
|
|
score in 0.0f64..=100.0f64
|
|
) {
|
|
// Test that compliance scores are always in valid range
|
|
prop_assert!(score >= 0.0 && score <= 100.0);
|
|
}
|
|
}
|
|
|
|
// Property-based test for order quantities
|
|
proptest! {
|
|
#[test]
|
|
fn prop_test_order_quantities(
|
|
quantity in 1u64..=1_000_000u64
|
|
) {
|
|
let decimal_quantity = Decimal::from(quantity);
|
|
|
|
// Test that order quantities are positive
|
|
prop_assert!(decimal_quantity > Decimal::ZERO);
|
|
|
|
// Test audit trail logging with various quantities
|
|
let order_details = OrderDetails {
|
|
transaction_id: "PROP-TEST".to_string(),
|
|
user_id: "test_user".to_string(),
|
|
session_id: Some("session_123".to_string()),
|
|
client_ip: Some("127.0.0.1".to_string()),
|
|
symbol: "AAPL".to_string(),
|
|
quantity: decimal_quantity,
|
|
price: Some(Decimal::from(150)),
|
|
side: "BUY".to_string(),
|
|
order_type: "LIMIT".to_string(),
|
|
venue: Some("NYSE".to_string()),
|
|
account_id: "ACC-123".to_string(),
|
|
strategy_id: Some("STRAT-001".to_string()),
|
|
metadata: HashMap::new(),
|
|
};
|
|
|
|
let audit_config = AuditTrailConfig::default();
|
|
let audit_engine = AuditTrailEngine::new(audit_config);
|
|
let result = audit_engine.log_order_created("PROP-ORDER", &order_details);
|
|
prop_assert!(result.is_ok());
|
|
}
|
|
}
|
|
|
|
/// Test regulatory API endpoints
|
|
#[tokio::test]
|
|
async fn test_regulatory_api_configuration() {
|
|
let api_config = RegulatoryApiConfig::default();
|
|
let compliance_config = ComplianceConfig::default();
|
|
|
|
// Test API server creation
|
|
let _api_server = RegulatoryApiServer::new(api_config.clone(), compliance_config);
|
|
|
|
// Verify configuration
|
|
assert_eq!(api_config.http_port, 8080);
|
|
assert_eq!(api_config.grpc_port, 9090);
|
|
assert!(
|
|
!api_config.api_keys.is_empty(),
|
|
"Should have default API keys"
|
|
);
|
|
}
|
|
|
|
/// Test automated reporting system
|
|
#[tokio::test]
|
|
async fn test_automated_reporting_system() {
|
|
let reporting_config = AutomatedReportingConfig::default();
|
|
|
|
// Verify default schedules exist
|
|
assert!(
|
|
!reporting_config.schedules.is_empty(),
|
|
"Should have default schedules"
|
|
);
|
|
|
|
// Verify MiFID II daily reports schedule exists
|
|
let mifid_schedule = reporting_config
|
|
.schedules
|
|
.iter()
|
|
.find(|s| s.schedule_id == "daily_mifid_reports");
|
|
assert!(
|
|
mifid_schedule.is_some(),
|
|
"Should have MiFID II daily reports schedule"
|
|
);
|
|
|
|
// Verify SOX quarterly assessment schedule exists
|
|
let sox_schedule = reporting_config
|
|
.schedules
|
|
.iter()
|
|
.find(|s| s.schedule_id == "quarterly_sox_assessment");
|
|
assert!(
|
|
sox_schedule.is_some(),
|
|
"Should have SOX quarterly assessment schedule"
|
|
);
|
|
}
|
|
|
|
/// Test compliance configuration validation
|
|
#[test]
|
|
fn test_compliance_configuration_validation() {
|
|
let config = ComplianceConfig::default();
|
|
|
|
// Test MiFID II configuration
|
|
assert!(
|
|
config.mifid2.best_execution_enabled,
|
|
"Best execution should be enabled by default"
|
|
);
|
|
assert!(
|
|
config.mifid2.client_categorization_enabled,
|
|
"Client categorization should be enabled"
|
|
);
|
|
|
|
// Test SOX configuration
|
|
assert!(
|
|
config.sox.management_certification_required,
|
|
"Management certification should be required"
|
|
);
|
|
assert!(
|
|
config.sox.audit_trail_required,
|
|
"Audit trail should be required"
|
|
);
|
|
|
|
// Test retention period
|
|
assert_eq!(
|
|
config.audit_retention_days, 2555,
|
|
"Audit retention should be 7 years"
|
|
);
|
|
}
|
|
|
|
/// Test compliance error handling
|
|
#[tokio::test]
|
|
async fn test_compliance_error_handling() {
|
|
let test_suite = ComplianceTestSuite::new();
|
|
|
|
// Test with invalid context
|
|
let invalid_context = create_invalid_compliance_context();
|
|
|
|
// Should handle invalid context gracefully
|
|
let result = test_suite
|
|
.compliance_engine
|
|
.assess_compliance(&invalid_context)
|
|
.await;
|
|
// Note: The actual behavior depends on implementation - could be Ok with warnings or Err
|
|
match result {
|
|
Ok(compliance_result) => {
|
|
// If it succeeds, it should flag issues
|
|
assert!(
|
|
!compliance_result.findings.is_empty()
|
|
|| matches!(compliance_result.status, ComplianceStatus::Warning(_))
|
|
|| matches!(compliance_result.status, ComplianceStatus::Violation(_)),
|
|
"Invalid context should result in findings or non-compliant status"
|
|
);
|
|
},
|
|
Err(_) => {
|
|
// Error is also acceptable for invalid context
|
|
},
|
|
}
|
|
}
|
|
|
|
/// Test audit trail query functionality
|
|
#[tokio::test]
|
|
async fn test_audit_trail_queries() {
|
|
let test_suite = ComplianceTestSuite::new();
|
|
|
|
// Create test query
|
|
let query = trading_engine::compliance::audit_trails::AuditTrailQuery {
|
|
start_time: Utc::now() - Duration::hours(24),
|
|
end_time: Utc::now(),
|
|
event_types: Some(vec![
|
|
AuditEventType::OrderCreated,
|
|
AuditEventType::OrderExecuted,
|
|
]),
|
|
transaction_id: None,
|
|
order_id: None,
|
|
actor: None,
|
|
symbol: Some("AAPL".to_string()),
|
|
account_id: None,
|
|
risk_level: None,
|
|
compliance_tags: None,
|
|
limit: Some(100),
|
|
offset: None,
|
|
sort_order: trading_engine::compliance::audit_trails::SortOrder::TimestampDesc,
|
|
};
|
|
|
|
// Execute query
|
|
let result = test_suite.audit_trail_engine.query(query).await;
|
|
assert!(result.is_ok(), "Audit trail query should succeed");
|
|
|
|
let query_result = result.unwrap();
|
|
assert!(
|
|
query_result.execution_time_ms < 5000,
|
|
"Query should complete within 5 seconds"
|
|
);
|
|
}
|
|
|
|
/// Test compliance metrics and monitoring
|
|
#[tokio::test]
|
|
async fn test_compliance_metrics() {
|
|
let reporting_config = AutomatedReportingConfig::default();
|
|
|
|
// Test performance thresholds
|
|
let thresholds = &reporting_config.monitoring_settings.performance_thresholds;
|
|
assert!(
|
|
thresholds.max_generation_time_seconds > 0,
|
|
"Generation time threshold should be positive"
|
|
);
|
|
assert!(
|
|
thresholds.min_success_rate_percentage > 0.0,
|
|
"Success rate threshold should be positive"
|
|
);
|
|
assert!(
|
|
thresholds.min_success_rate_percentage <= 100.0,
|
|
"Success rate threshold should be <= 100%"
|
|
);
|
|
}
|
|
|
|
/// Test regulatory data validation
|
|
#[test]
|
|
fn test_regulatory_data_validation() {
|
|
let order_execution = create_test_order_execution();
|
|
|
|
// Validate required fields
|
|
assert!(
|
|
!order_execution.execution_id.is_empty(),
|
|
"Execution ID is required"
|
|
);
|
|
assert!(!order_execution.symbol.is_empty(), "Symbol is required");
|
|
assert!(
|
|
order_execution.filled_quantity > Decimal::ZERO,
|
|
"Filled quantity must be positive"
|
|
);
|
|
assert!(
|
|
order_execution.execution_price > Decimal::ZERO,
|
|
"Execution price must be positive"
|
|
);
|
|
assert!(!order_execution.currency.is_empty(), "Currency is required");
|
|
}
|
|
|
|
/// Stress test compliance system with high load
|
|
#[tokio::test]
|
|
async fn test_compliance_high_load() {
|
|
let test_suite = ComplianceTestSuite::new();
|
|
|
|
// Generate multiple concurrent compliance assessments
|
|
// Note: We assess sequentially since ComplianceEngine doesn't implement Clone
|
|
// This still tests the engine under repeated load
|
|
let mut success_count = 0;
|
|
|
|
for i in 0..100 {
|
|
let context = create_test_compliance_context_with_id(&format!("STRESS-{}", i));
|
|
let result = test_suite
|
|
.compliance_engine
|
|
.assess_compliance(&context)
|
|
.await;
|
|
|
|
if result.is_ok() {
|
|
success_count += 1;
|
|
}
|
|
}
|
|
|
|
assert!(
|
|
success_count >= 95,
|
|
"At least 95% of assessments should succeed under load"
|
|
);
|
|
}
|
|
|
|
/// Test compliance data encryption and security
|
|
#[test]
|
|
fn test_compliance_data_security() {
|
|
let audit_config = AuditTrailConfig::default();
|
|
|
|
// Verify security settings
|
|
assert!(
|
|
audit_config.encryption_enabled,
|
|
"Encryption should be enabled"
|
|
);
|
|
assert!(
|
|
audit_config.compliance_requirements.immutable_required,
|
|
"Immutability should be required"
|
|
);
|
|
assert!(
|
|
audit_config.compliance_requirements.tamper_detection,
|
|
"Tamper detection should be enabled"
|
|
);
|
|
}
|
|
|
|
// Helper functions for creating test data
|
|
|
|
fn create_test_compliance_context() -> trading_engine::compliance::ComplianceContext {
|
|
trading_engine::compliance::ComplianceContext {
|
|
order_info: Some(create_test_order_info()),
|
|
client_info: Some(create_test_client_info()),
|
|
market_context: Some(create_test_market_context()),
|
|
timestamp: Utc::now(),
|
|
}
|
|
}
|
|
|
|
fn create_test_compliance_context_with_id(
|
|
id: &str,
|
|
) -> trading_engine::compliance::ComplianceContext {
|
|
let mut context = create_test_compliance_context();
|
|
if let Some(order_info) = &mut context.order_info {
|
|
order_info.order_id = OrderId::from(id);
|
|
}
|
|
context
|
|
}
|
|
|
|
fn create_invalid_compliance_context() -> trading_engine::compliance::ComplianceContext {
|
|
trading_engine::compliance::ComplianceContext {
|
|
order_info: None, // Missing required order info
|
|
client_info: None,
|
|
market_context: None,
|
|
timestamp: Utc::now(),
|
|
}
|
|
}
|
|
|
|
fn create_test_order_info() -> OrderInfo {
|
|
OrderInfo {
|
|
order_id: OrderId::from("ORDER-123"),
|
|
side: OrderSide::Buy,
|
|
order_type: OrderType::Limit,
|
|
quantity: Quantity::from_decimal(Decimal::from(100)).unwrap(),
|
|
price: Some(Price::from_decimal(Decimal::from(150))),
|
|
symbol: "AAPL".to_string(),
|
|
client_id: "CLIENT-001".to_string(),
|
|
timestamp: Utc::now(),
|
|
}
|
|
}
|
|
|
|
fn create_test_client_info() -> trading_engine::compliance::ClientInfo {
|
|
trading_engine::compliance::ClientInfo {
|
|
client_id: "CLIENT-001".to_string(),
|
|
classification: trading_engine::compliance::ClientType::Professional,
|
|
risk_tolerance: trading_engine::compliance::RiskTolerance::Moderate,
|
|
jurisdiction: "US".to_string(),
|
|
}
|
|
}
|
|
|
|
fn create_test_market_context() -> trading_engine::compliance::MarketContext {
|
|
trading_engine::compliance::MarketContext {
|
|
conditions: trading_engine::compliance::MarketConditions::Normal,
|
|
session: trading_engine::compliance::TradingSession::Regular,
|
|
volatility: 0.15,
|
|
}
|
|
}
|
|
|
|
fn create_test_order_execution() -> OrderExecution {
|
|
OrderExecution {
|
|
execution_id: "EXEC-123".to_string(),
|
|
order_id: "ORDER-123".to_string(),
|
|
symbol: "AAPL".to_string(),
|
|
isin: Some("US0378331005".to_string()),
|
|
venue: "NYSE".to_string(),
|
|
execution_time: Utc::now(),
|
|
execution_price: Decimal::from(150),
|
|
filled_quantity: Decimal::from(100),
|
|
currency: "USD".to_string(),
|
|
order_type: "LIMIT".to_string(),
|
|
side: "BUY".to_string(),
|
|
}
|
|
}
|
|
|
|
fn create_test_order_details() -> OrderDetails {
|
|
OrderDetails {
|
|
transaction_id: "TXN-123".to_string(),
|
|
user_id: "user_123".to_string(),
|
|
session_id: Some("session_456".to_string()),
|
|
client_ip: Some("192.168.1.100".to_string()),
|
|
symbol: "AAPL".to_string(),
|
|
quantity: Decimal::from(100),
|
|
price: Some(Decimal::from(150)),
|
|
side: "BUY".to_string(),
|
|
order_type: "LIMIT".to_string(),
|
|
venue: Some("NYSE".to_string()),
|
|
account_id: "ACC-123".to_string(),
|
|
strategy_id: Some("STRAT-001".to_string()),
|
|
metadata: HashMap::new(),
|
|
}
|
|
}
|
|
|
|
fn create_test_execution_details() -> ExecutionDetails {
|
|
ExecutionDetails {
|
|
transaction_id: "TXN-123".to_string(),
|
|
order_id: "ORDER-123".to_string(),
|
|
symbol: "AAPL".to_string(),
|
|
executed_quantity: Decimal::from(100),
|
|
execution_price: Decimal::from(150),
|
|
side: "BUY".to_string(),
|
|
venue: "NYSE".to_string(),
|
|
account_id: "ACC-123".to_string(),
|
|
strategy_id: Some("STRAT-001".to_string()),
|
|
metadata: HashMap::new(),
|
|
processing_latency_ns: 50_000, // 50 microseconds
|
|
queue_time_ns: 10_000, // 10 microseconds
|
|
system_load: 0.75,
|
|
memory_usage_bytes: 1_048_576, // 1 MB
|
|
}
|
|
}
|
|
|
|
/// Integration test that combines all compliance components
|
|
#[tokio::test]
|
|
async fn test_full_compliance_integration() {
|
|
let test_suite = ComplianceTestSuite::new();
|
|
|
|
// 1. Log order creation
|
|
let order_details = create_test_order_details();
|
|
let audit_result = test_suite
|
|
.audit_trail_engine
|
|
.log_order_created("ORDER-INTEGRATION", &order_details);
|
|
assert!(audit_result.is_ok(), "Order audit logging should succeed");
|
|
|
|
// 2. Assess compliance
|
|
let context = create_test_compliance_context();
|
|
let compliance_result = test_suite
|
|
.compliance_engine
|
|
.assess_compliance(&context)
|
|
.await;
|
|
assert!(
|
|
compliance_result.is_ok(),
|
|
"Compliance assessment should succeed"
|
|
);
|
|
|
|
// 3. Generate transaction report
|
|
let execution = create_test_order_execution();
|
|
let report_result = test_suite
|
|
.transaction_reporter
|
|
.generate_transaction_report(&execution)
|
|
.await;
|
|
assert!(
|
|
report_result.is_ok(),
|
|
"Transaction report generation should succeed"
|
|
);
|
|
|
|
// 4. Log execution
|
|
let execution_details = create_test_execution_details();
|
|
let execution_audit_result = test_suite
|
|
.audit_trail_engine
|
|
.log_order_executed(&execution_details);
|
|
assert!(
|
|
execution_audit_result.is_ok(),
|
|
"Execution audit logging should succeed"
|
|
);
|
|
|
|
// 5. Verify overall compliance
|
|
let final_compliance = compliance_result.unwrap();
|
|
assert!(
|
|
final_compliance.compliance_score > 80.0,
|
|
"Overall compliance score should be high after successful operations"
|
|
);
|
|
}
|
|
|
|
/// Performance test for audit trail logging
|
|
#[tokio::test]
|
|
async fn test_audit_trail_performance() {
|
|
let audit_config = AuditTrailConfig::default();
|
|
let audit_engine = AuditTrailEngine::new(audit_config);
|
|
|
|
let start_time = std::time::Instant::now();
|
|
|
|
// Log 1000 events rapidly
|
|
for i in 0..1000 {
|
|
let order_details = OrderDetails {
|
|
transaction_id: format!("PERF-TXN-{}", i),
|
|
user_id: "perf_user".to_string(),
|
|
session_id: Some("perf_session".to_string()),
|
|
client_ip: Some("127.0.0.1".to_string()),
|
|
symbol: "AAPL".to_string(),
|
|
quantity: Decimal::from(100),
|
|
price: Some(Decimal::from(150)),
|
|
side: "BUY".to_string(),
|
|
order_type: "LIMIT".to_string(),
|
|
venue: Some("NYSE".to_string()),
|
|
account_id: "PERF-ACC".to_string(),
|
|
strategy_id: Some("PERF-STRAT".to_string()),
|
|
metadata: HashMap::new(),
|
|
};
|
|
|
|
let result = audit_engine.log_order_created(&format!("PERF-ORDER-{}", i), &order_details);
|
|
assert!(result.is_ok(), "Performance test logging should succeed");
|
|
}
|
|
|
|
let elapsed = start_time.elapsed();
|
|
|
|
// Should be able to log 1000 events in under 100ms for HFT performance
|
|
assert!(
|
|
elapsed.as_millis() < 100,
|
|
"Should log 1000 events in under 100ms, took {}ms",
|
|
elapsed.as_millis()
|
|
);
|
|
}
|