Files
foxhunt/testing/integration/unit/benches/comprehensive_hft_performance_benchmarks.rs
jgrusewski 9c3d741a08 refactor: restructure repo — crates/, bin/, testing/ layout
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>
2026-02-25 11:56:00 +01:00

944 lines
28 KiB
Rust

//! Comprehensive HFT Performance Benchmarks
//!
//! This module provides exhaustive performance benchmarking for all latency-critical
//! paths in the Foxhunt HFT system. Benchmarks target sub-microsecond operations
//! and validate HFT performance requirements.
//!
//! Performance Targets:
//! - Order validation: < 1μs
//! - Risk calculation: < 5μs
//! - Market data processing: < 100ns
//! - PnL calculation: < 50ns
//! - Position updates: < 2μs
//! - Message serialization: < 500ns
//! - Event publishing: < 1μs
//! - Database writes: < 10μs
use criterion::{
black_box, criterion_group, criterion_main, BenchmarkId, Criterion,
Throughput, measurement::WallTime, BatchSize
};
use std::collections::{HashMap, BTreeMap};
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
use std::sync::{Arc, Mutex, atomic::{AtomicU64, Ordering}};
use parking_lot::RwLock;
use crossbeam::queue::SegQueue;
use serde::{Deserialize, Serialize};
// CANONICAL TYPE IMPORTS - Use types::prelude::Decimal
use uuid::Uuid;
use chrono::{DateTime, Utc};
// ===== PERFORMANCE-CRITICAL DATA STRUCTURES =====
/// High-performance order structure optimized for HFT
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HFTOrder {
pub id: u64,
pub symbol: [u8; 8], // Fixed-size symbol for better cache performance
pub side: OrderSide,
pub quantity: u64, // Using integers for exact arithmetic
pub price: u64, // Price in ticks (e.g., cents)
pub timestamp_ns: u64, // Nanosecond timestamp
pub strategy_id: u16,
}
// OrderSide now imported from canonical source
use common::OrderSide;
/// High-performance market data tick
#[derive(Debug, Clone, Copy)]
#[repr(C)] // Ensure memory layout for SIMD operations
pub struct MarketTick {
pub symbol_id: u32,
pub bid: u64,
pub ask: u64,
pub bid_size: u32,
pub ask_size: u32,
pub last: u64,
pub volume: u32,
pub timestamp_ns: u64,
}
/// High-performance position tracking
#[derive(Debug, Clone)]
pub struct PositionManager {
positions: Arc<RwLock<HashMap<u32, i64>>>, // symbol_id -> quantity
pnl: Arc<AtomicU64>, // Atomic for lock-free updates
update_count: Arc<AtomicU64>,
}
impl PositionManager {
pub fn new() -> Self {
Self {
positions: Arc::new(RwLock::new(HashMap::new())),
pnl: Arc::new(AtomicU64::new(0)),
update_count: Arc::new(AtomicU64::new(0)),
}
}
pub fn update_position(&self, symbol_id: u32, quantity_delta: i64) {
let mut positions = self.positions.write();
*positions.entry(symbol_id).or_insert(0) += quantity_delta;
self.update_count.fetch_add(1, Ordering::Relaxed);
}
pub fn get_position(&self, symbol_id: u32) -> i64 {
self.positions.read().get(&symbol_id).copied().unwrap_or(0)
}
pub fn calculate_pnl(&self, symbol_id: u32, current_price: u64, entry_price: u64) -> i64 {
let position = self.get_position(symbol_id);
(current_price as i64 - entry_price as i64) * position
}
}
/// High-performance risk calculator
#[derive(Debug)]
pub struct RiskCalculator {
limits: RiskLimits,
}
#[derive(Debug, Clone)]
pub struct RiskLimits {
pub max_position: i64,
pub max_order_size: u64,
pub max_notional: u64,
pub max_leverage: f32,
}
impl RiskCalculator {
pub fn new() -> Self {
Self {
limits: RiskLimits {
max_position: 10000,
max_order_size: 1000,
max_notional: 1000000,
max_leverage: 3.0,
}
}
}
pub fn validate_order(&self, order: &HFTOrder, current_position: i64) -> bool {
// Fast validation checks
if order.quantity > self.limits.max_order_size {
return false;
}
let new_position = match order.side {
OrderSide::Buy => current_position + order.quantity as i64,
OrderSide::Sell => current_position - order.quantity as i64,
};
new_position.abs() <= self.limits.max_position
}
pub fn calculate_var(&self, positions: &[(u32, i64, u64)], confidence: f32) -> u64 {
// Simplified VaR calculation for benchmarking
let mut total_risk = 0u64;
for (_, quantity, price) in positions {
let notional = quantity.abs() as u64 * price;
total_risk += (notional as f32 * confidence) as u64;
}
total_risk
}
}
/// High-performance order book
#[derive(Debug)]
pub struct OrderBook {
bids: BTreeMap<u64, u64>, // price -> quantity
asks: BTreeMap<u64, u64>,
last_update_ns: AtomicU64,
}
impl OrderBook {
pub fn new() -> Self {
Self {
bids: BTreeMap::new(),
asks: BTreeMap::new(),
last_update_ns: AtomicU64::new(0),
}
}
pub fn update_bid(&mut self, price: u64, quantity: u64) {
if quantity == 0 {
self.bids.remove(&price);
} else {
self.bids.insert(price, quantity);
}
self.last_update_ns.store(
SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_nanos() as u64,
Ordering::Relaxed
);
}
pub fn get_best_bid(&self) -> Option<(u64, u64)> {
self.bids.iter().next_back().map(|(p, q)| (*p, *q))
}
pub fn get_best_ask(&self) -> Option<(u64, u64)> {
self.asks.iter().next().map(|(p, q)| (*p, *q))
}
pub fn get_mid_price(&self) -> Option<u64> {
match (self.get_best_bid(), self.get_best_ask()) {
(Some((bid, _)), Some((ask, _))) => Some((bid + ask) / 2),
_ => None,
}
}
}
/// High-performance message queue for order flow
#[derive(Debug)]
pub struct HFTMessageQueue {
queue: SegQueue<HFTOrder>,
message_count: AtomicU64,
}
impl HFTMessageQueue {
pub fn new() -> Self {
Self {
queue: SegQueue::new(),
message_count: AtomicU64::new(0),
}
}
pub fn push(&self, order: HFTOrder) {
self.queue.push(order);
self.message_count.fetch_add(1, Ordering::Relaxed);
}
pub fn pop(&self) -> Option<HFTOrder> {
self.queue.pop()
}
pub fn len(&self) -> u64 {
self.message_count.load(Ordering::Relaxed)
}
}
// ===== BENCHMARK IMPLEMENTATIONS =====
/// Benchmark order validation performance
fn bench_order_validation(c: &mut Criterion) {
let risk_calculator = RiskCalculator::new();
let position_manager = PositionManager::new();
// Pre-populate some positions
position_manager.update_position(1, 500);
position_manager.update_position(2, -300);
let orders: Vec<HFTOrder> = (0..1000).map(|i| HFTOrder {
id: i,
symbol: *b"AAPL ",
side: if i % 2 == 0 { OrderSide::Buy } else { OrderSide::Sell },
quantity: 100 + (i % 900) as u64,
price: 15000 + (i % 1000) as u64, // $150.00 + variation
timestamp_ns: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_nanos() as u64,
strategy_id: (i % 10) as u16,
}).collect();
let mut group = c.benchmark_group("order_validation");
group.throughput(Throughput::Elements(1));
group.bench_function("validate_single_order", |b| {
b.iter_batched(
|| orders[black_box(0)].clone(),
|order| {
let current_position = position_manager.get_position(1);
black_box(risk_calculator.validate_order(&order, current_position))
},
BatchSize::SmallInput
)
});
group.bench_function("validate_order_batch", |b| {
b.iter_batched(
|| orders[0..100].to_vec(),
|order_batch| {
for order in order_batch {
let current_position = position_manager.get_position(1);
black_box(risk_calculator.validate_order(&order, current_position));
}
},
BatchSize::SmallInput
)
});
group.finish();
}
/// Benchmark market data processing performance
fn bench_market_data_processing(c: &mut Criterion) {
let ticks: Vec<MarketTick> = (0..10000).map(|i| MarketTick {
symbol_id: (i % 100) as u32,
bid: 15000 + (i % 100) as u64,
ask: 15001 + (i % 100) as u64,
bid_size: 1000 + (i % 9000) as u32,
ask_size: 1000 + (i % 9000) as u32,
last: 15000 + (i % 100) as u64,
volume: (i % 10000) as u32,
timestamp_ns: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_nanos() as u64,
}).collect();
let mut group = c.benchmark_group("market_data_processing");
group.throughput(Throughput::Elements(1));
group.bench_function("process_single_tick", |b| {
b.iter_batched(
|| ticks[0],
|tick| {
// Simulate market data processing
let mid_price = (tick.bid + tick.ask) / 2;
let spread = tick.ask - tick.bid;
black_box((mid_price, spread))
},
BatchSize::SmallInput
)
});
group.bench_function("process_tick_batch", |b| {
b.iter_batched(
|| &ticks[0..1000],
|tick_batch| {
for tick in tick_batch {
let mid_price = (tick.bid + tick.ask) / 2;
let spread = tick.ask - tick.bid;
black_box((mid_price, spread));
}
},
BatchSize::SmallInput
)
});
group.bench_function("calculate_vwap", |b| {
b.iter_batched(
|| &ticks[0..100],
|tick_batch| {
let mut total_notional = 0u64;
let mut total_volume = 0u64;
for tick in tick_batch {
total_notional += tick.last * tick.volume as u64;
total_volume += tick.volume as u64;
}
let vwap = if total_volume > 0 { total_notional / total_volume } else { 0 };
black_box(vwap)
},
BatchSize::SmallInput
)
});
group.finish();
}
/// Benchmark position management performance
fn bench_position_management(c: &mut Criterion) {
let position_manager = PositionManager::new();
let mut group = c.benchmark_group("position_management");
group.throughput(Throughput::Elements(1));
group.bench_function("update_position", |b| {
b.iter_batched(
|| (black_box(1u32), black_box(100i64)),
|(symbol_id, quantity_delta)| {
position_manager.update_position(symbol_id, quantity_delta)
},
BatchSize::SmallInput
)
});
group.bench_function("get_position", |b| {
b.iter_batched(
|| black_box(1u32),
|symbol_id| {
black_box(position_manager.get_position(symbol_id))
},
BatchSize::SmallInput
)
});
group.bench_function("calculate_pnl", |b| {
// Pre-populate position
position_manager.update_position(1, 1000);
b.iter_batched(
|| (black_box(1u32), black_box(15050u64), black_box(15000u64)),
|(symbol_id, current_price, entry_price)| {
black_box(position_manager.calculate_pnl(symbol_id, current_price, entry_price))
},
BatchSize::SmallInput
)
});
group.finish();
}
/// Benchmark risk calculation performance
fn bench_risk_calculations(c: &mut Criterion) {
let risk_calculator = RiskCalculator::new();
// Generate test portfolio
let positions: Vec<(u32, i64, u64)> = (0..100).map(|i| {
(i as u32, 100 + (i * 10), 15000 + (i * 10) as u64)
}).collect();
let mut group = c.benchmark_group("risk_calculations");
group.throughput(Throughput::Elements(1));
group.bench_function("calculate_var", |b| {
b.iter_batched(
|| (positions.as_slice(), 0.95f32),
|(positions, confidence)| {
black_box(risk_calculator.calculate_var(positions, confidence))
},
BatchSize::SmallInput
)
});
group.bench_function("portfolio_exposure", |b| {
b.iter_batched(
|| positions.as_slice(),
|positions| {
let mut total_long = 0u64;
let mut total_short = 0u64;
for (_, quantity, price) in positions {
let notional = quantity.abs() as u64 * price;
if *quantity > 0 {
total_long += notional;
} else {
total_short += notional;
}
}
black_box((total_long, total_short))
},
BatchSize::SmallInput
)
});
group.finish();
}
/// Benchmark order book operations
fn bench_order_book_operations(c: &mut Criterion) {
let mut order_book = OrderBook::new();
// Pre-populate order book
for i in 0..1000 {
order_book.update_bid(15000 - i, 100);
}
let mut group = c.benchmark_group("order_book");
group.throughput(Throughput::Elements(1));
group.bench_function("update_bid", |b| {
let mut ob = order_book;
b.iter_batched(
|| (black_box(14500u64), black_box(200u64)),
|(price, quantity)| {
ob.update_bid(price, quantity)
},
BatchSize::SmallInput
)
});
group.bench_function("get_best_bid", |b| {
b.iter(|| {
black_box(order_book.get_best_bid())
})
});
group.bench_function("get_mid_price", |b| {
b.iter(|| {
black_box(order_book.get_mid_price())
})
});
group.finish();
}
/// Benchmark message queue performance
fn bench_message_queue(c: &mut Criterion) {
let queue = HFTMessageQueue::new();
let orders: Vec<HFTOrder> = (0..10000).map(|i| HFTOrder {
id: i,
symbol: *b"AAPL ",
side: if i % 2 == 0 { OrderSide::Buy } else { OrderSide::Sell },
quantity: 100,
price: 15000,
timestamp_ns: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_nanos() as u64,
strategy_id: 1,
}).collect();
let mut group = c.benchmark_group("message_queue");
group.throughput(Throughput::Elements(1));
group.bench_function("push_order", |b| {
b.iter_batched(
|| orders[0].clone(),
|order| {
queue.push(order)
},
BatchSize::SmallInput
)
});
// Pre-populate queue for pop benchmark
for order in &orders[0..1000] {
queue.push(order.clone());
}
group.bench_function("pop_order", |b| {
b.iter(|| {
black_box(queue.pop())
})
});
group.bench_function("queue_throughput", |b| {
b.iter_batched(
|| orders[0..100].to_vec(),
|order_batch| {
for order in order_batch {
queue.push(order);
}
for _ in 0..100 {
queue.pop();
}
},
BatchSize::SmallInput
)
});
group.finish();
}
/// Benchmark serialization performance
fn bench_serialization(c: &mut Criterion) {
let order = HFTOrder {
id: 12345,
symbol: *b"AAPL ",
side: OrderSide::Buy,
quantity: 1000,
price: 15050,
timestamp_ns: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_nanos() as u64,
strategy_id: 1,
};
let mut group = c.benchmark_group("serialization");
group.throughput(Throughput::Bytes(std::mem::size_of::<HFTOrder>() as u64));
group.bench_function("bincode_serialize", |b| {
b.iter_batched(
|| order.clone(),
|order| {
black_box(bincode::serialize(&order).unwrap())
},
BatchSize::SmallInput
)
});
let serialized = bincode::serialize(&order).unwrap();
group.bench_function("bincode_deserialize", |b| {
b.iter_batched(
|| serialized.clone(),
|data| {
black_box(bincode::deserialize::<HFTOrder>(&data).unwrap())
},
BatchSize::SmallInput
)
});
group.bench_function("json_serialize", |b| {
b.iter_batched(
|| order.clone(),
|order| {
black_box(serde_json::to_string(&order).unwrap())
},
BatchSize::SmallInput
)
});
let json_data = serde_json::to_string(&order).unwrap();
group.bench_function("json_deserialize", |b| {
b.iter_batched(
|| json_data.clone(),
|data| {
black_box(serde_json::from_str::<HFTOrder>(&data).unwrap())
},
BatchSize::SmallInput
)
});
group.finish();
}
/// Benchmark memory allocation patterns
fn bench_memory_patterns(c: &mut Criterion) {
let mut group = c.benchmark_group("memory_patterns");
group.bench_function("vec_allocation", |b| {
b.iter(|| {
let mut vec = Vec::with_capacity(1000);
for i in 0..1000 {
vec.push(black_box(i));
}
black_box(vec)
})
});
group.bench_function("hashmap_insertion", |b| {
b.iter(|| {
let mut map = HashMap::with_capacity(1000);
for i in 0..1000 {
map.insert(black_box(i), black_box(i * 2));
}
black_box(map)
})
});
group.bench_function("btreemap_insertion", |b| {
b.iter(|| {
let mut map = BTreeMap::new();
for i in 0..1000 {
map.insert(black_box(i), black_box(i * 2));
}
black_box(map)
})
});
group.finish();
}
/// Benchmark financial calculations
fn bench_financial_calculations(c: &mut Criterion) {
let prices = vec![150.0, 151.5, 149.8, 152.1, 150.9];
let returns: Vec<f64> = prices.windows(2).map(|w| (w[1] - w[0]) / w[0]).collect();
let mut group = c.benchmark_group("financial_calculations");
group.bench_function("simple_return", |b| {
b.iter_batched(
|| (black_box(150.0), black_box(151.5)),
|(start_price, end_price)| {
black_box((end_price - start_price) / start_price)
},
BatchSize::SmallInput
)
});
group.bench_function("volatility_calculation", |b| {
b.iter_batched(
|| returns.clone(),
|returns| {
let mean = returns.iter().sum::<f64>() / returns.len() as f64;
let variance = returns.iter()
.map(|r| (r - mean).powi(2))
.sum::<f64>() / returns.len() as f64;
black_box(variance.sqrt())
},
BatchSize::SmallInput
)
});
group.bench_function("sharpe_ratio", |b| {
b.iter_batched(
|| (returns.clone(), 0.02f64), // 2% risk-free rate
|(returns, risk_free_rate)| {
let mean_return = returns.iter().sum::<f64>() / returns.len() as f64;
let std_dev = {
let variance = returns.iter()
.map(|r| (r - mean_return).powi(2))
.sum::<f64>() / returns.len() as f64;
variance.sqrt()
};
black_box((mean_return - risk_free_rate) / std_dev)
},
BatchSize::SmallInput
)
});
group.finish();
}
/// Benchmark timestamp operations
fn bench_timestamp_operations(c: &mut Criterion) {
let mut group = c.benchmark_group("timestamp_operations");
group.bench_function("system_time_now", |b| {
b.iter(|| {
black_box(SystemTime::now())
})
});
group.bench_function("unix_timestamp_ns", |b| {
b.iter(|| {
black_box(SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_nanos())
})
});
group.bench_function("chrono_utc_now", |b| {
b.iter(|| {
black_box(Utc::now())
})
});
group.bench_function("timestamp_comparison", |b| {
let ts1 = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_nanos() as u64;
let ts2 = ts1 + 1000; // 1μs later
b.iter(|| {
black_box(ts2 > ts1)
})
});
group.finish();
}
// ===== CRITERION CONFIGURATION =====
criterion_group! {
name = hft_benchmarks;
config = Criterion::default()
.measurement_time(Duration::from_secs(10))
.sample_size(1000)
.warm_up_time(Duration::from_secs(3));
targets =
bench_order_validation,
bench_market_data_processing,
bench_position_management,
bench_risk_calculations,
bench_order_book_operations,
bench_message_queue,
bench_serialization,
bench_memory_patterns,
bench_financial_calculations,
bench_timestamp_operations
}
criterion_main!(hft_benchmarks);
// ===== PERFORMANCE VALIDATION TESTS =====
#[cfg(test)]
mod performance_validation_tests {
use super::*;
use std::time::Instant;
#[test]
fn test_order_validation_performance() {
let risk_calculator = RiskCalculator::new();
let order = HFTOrder {
id: 1,
symbol: *b"AAPL ",
side: OrderSide::Buy,
quantity: 100,
price: 15000,
timestamp_ns: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_nanos() as u64,
strategy_id: 1,
};
let iterations = 10000;
let start = Instant::now();
for _ in 0..iterations {
black_box(risk_calculator.validate_order(&order, 500));
}
let duration = start.elapsed();
let avg_duration_ns = duration.as_nanos() / iterations;
// Should validate orders in less than 1μs (1000ns)
assert!(avg_duration_ns < 1000,
"Order validation too slow: {}ns average", avg_duration_ns);
}
#[test]
fn test_market_data_processing_performance() {
let tick = MarketTick {
symbol_id: 1,
bid: 15000,
ask: 15001,
bid_size: 1000,
ask_size: 1000,
last: 15000,
volume: 5000,
timestamp_ns: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_nanos() as u64,
};
let iterations = 100000;
let start = Instant::now();
for _ in 0..iterations {
let mid_price = (tick.bid + tick.ask) / 2;
let spread = tick.ask - tick.bid;
black_box((mid_price, spread));
}
let duration = start.elapsed();
let avg_duration_ns = duration.as_nanos() / iterations;
// Should process market data in less than 100ns
assert!(avg_duration_ns < 100,
"Market data processing too slow: {}ns average", avg_duration_ns);
}
#[test]
fn test_position_update_performance() {
let position_manager = PositionManager::new();
let iterations = 10000;
let start = Instant::now();
for i in 0..iterations {
position_manager.update_position(1, if i % 2 == 0 { 100 } else { -100 });
}
let duration = start.elapsed();
let avg_duration_ns = duration.as_nanos() / iterations;
// Should update positions in less than 2μs (2000ns)
assert!(avg_duration_ns < 2000,
"Position update too slow: {}ns average", avg_duration_ns);
}
#[test]
fn test_pnl_calculation_performance() {
let position_manager = PositionManager::new();
position_manager.update_position(1, 1000);
let iterations = 100000;
let start = Instant::now();
for _ in 0..iterations {
black_box(position_manager.calculate_pnl(1, 15050, 15000));
}
let duration = start.elapsed();
let avg_duration_ns = duration.as_nanos() / iterations;
// Should calculate PnL in less than 50ns
assert!(avg_duration_ns < 50,
"PnL calculation too slow: {}ns average", avg_duration_ns);
}
#[test]
fn test_message_queue_performance() {
let queue = HFTMessageQueue::new();
let order = HFTOrder {
id: 1,
symbol: *b"AAPL ",
side: OrderSide::Buy,
quantity: 100,
price: 15000,
timestamp_ns: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_nanos() as u64,
strategy_id: 1,
};
let iterations = 10000;
let start = Instant::now();
for _ in 0..iterations {
queue.push(order.clone());
}
for _ in 0..iterations {
queue.pop();
}
let duration = start.elapsed();
let avg_duration_ns = duration.as_nanos() / (iterations * 2); // push + pop
// Should handle queue operations in less than 1μs (1000ns)
assert!(avg_duration_ns < 1000,
"Message queue operations too slow: {}ns average", avg_duration_ns);
}
#[test]
fn test_serialization_performance() {
let order = HFTOrder {
id: 12345,
symbol: *b"AAPL ",
side: OrderSide::Buy,
quantity: 1000,
price: 15050,
timestamp_ns: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_nanos() as u64,
strategy_id: 1,
};
let iterations = 10000;
let start = Instant::now();
for _ in 0..iterations {
let serialized = bincode::serialize(&order).unwrap();
let _deserialized: HFTOrder = bincode::deserialize(&serialized).unwrap();
}
let duration = start.elapsed();
let avg_duration_ns = duration.as_nanos() / iterations;
// Should serialize/deserialize in less than 500ns
assert!(avg_duration_ns < 500,
"Serialization too slow: {}ns average", avg_duration_ns);
}
#[test]
fn test_overall_system_latency() {
// Simulate complete order processing workflow
let risk_calculator = RiskCalculator::new();
let position_manager = PositionManager::new();
let queue = HFTMessageQueue::new();
let order = HFTOrder {
id: 1,
symbol: *b"AAPL ",
side: OrderSide::Buy,
quantity: 100,
price: 15000,
timestamp_ns: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_nanos() as u64,
strategy_id: 1,
};
let iterations = 1000;
let start = Instant::now();
for _ in 0..iterations {
// Step 1: Queue order
queue.push(order.clone());
// Step 2: Get order from queue
let order = queue.pop().unwrap();
// Step 3: Validate order
let current_position = position_manager.get_position(1);
let is_valid = risk_calculator.validate_order(&order, current_position);
if is_valid {
// Step 4: Update position
let position_delta = match order.side {
OrderSide::Buy => order.quantity as i64,
OrderSide::Sell => -(order.quantity as i64),
};
position_manager.update_position(1, position_delta);
// Step 5: Calculate PnL
position_manager.calculate_pnl(1, 15050, 15000);
}
}
let duration = start.elapsed();
let avg_duration_us = duration.as_micros() / iterations;
// Complete workflow should be under 10μs
assert!(avg_duration_us < 10,
"Overall system latency too high: {}μs average", avg_duration_us);
println!("Performance Summary:");
println!(" Complete workflow latency: {}μs average", avg_duration_us);
println!(" Theoretical throughput: {} orders/sec", 1_000_000 / avg_duration_us);
}
}