diff --git a/Cargo.lock b/Cargo.lock index 79bff655d..2228861ed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7623,6 +7623,7 @@ dependencies = [ "arc-swap", "async-trait", "chrono", + "common", "criterion", "crossbeam", "data", diff --git a/adaptive-strategy/examples/ppo_position_sizing_demo.rs b/adaptive-strategy/examples/ppo_position_sizing_demo.rs index 877b40c8a..3ffca42ce 100644 --- a/adaptive-strategy/examples/ppo_position_sizing_demo.rs +++ b/adaptive-strategy/examples/ppo_position_sizing_demo.rs @@ -10,7 +10,7 @@ use adaptive_strategy::{ }; use rust_decimal_macros::dec; use std::collections::HashMap; -use trading_engine::types::prelude::*; +use common::types::prelude::*; #[tokio::main] async fn main() -> Result<(), Box> { diff --git a/adaptive-strategy/src/models/deep_learning.rs b/adaptive-strategy/src/models/deep_learning.rs index 1d85fb3f3..8e63eb458 100644 --- a/adaptive-strategy/src/models/deep_learning.rs +++ b/adaptive-strategy/src/models/deep_learning.rs @@ -9,7 +9,7 @@ use super::{ModelConfig, ModelTrait}; use tracing::{debug, info, warn}; // Add missing core types -use trading_engine::types::prelude::*; +use common::types::prelude::*; // Add ML types (specific imports to avoid ModelMetadata conflict) use ml::dqn::{AgentMetrics, DQNAgent, DQNConfig, Experience, TradingAction, TradingState}; use ml::mamba::{Mamba2Config, Mamba2SSM}; diff --git a/adaptive-strategy/src/models/mod.rs b/adaptive-strategy/src/models/mod.rs index dbdf16cf5..36053b6ce 100644 --- a/adaptive-strategy/src/models/mod.rs +++ b/adaptive-strategy/src/models/mod.rs @@ -11,7 +11,7 @@ use std::collections::HashMap; use tracing::{debug, info, warn}; // Add missing core types -use trading_engine::types::prelude::*; +use common::types::prelude::*; // Add ML types (specific imports to avoid conflicts) use ml::prelude::{MarketRegime, TensorSpec}; diff --git a/adaptive-strategy/src/models/tlob_model.rs b/adaptive-strategy/src/models/tlob_model.rs index 98d3ed303..d8c4e1068 100644 --- a/adaptive-strategy/src/models/tlob_model.rs +++ b/adaptive-strategy/src/models/tlob_model.rs @@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize}; use tracing::{debug, instrument, warn}; // Add missing core types -use trading_engine::types::prelude::*; +use common::types::prelude::*; use ml::tlob::features::FeatureVector; use ml::tlob::transformer::TLOBFeatures; diff --git a/adaptive-strategy/src/regime/mod.rs b/adaptive-strategy/src/regime/mod.rs index ece8ebb98..865804141 100644 --- a/adaptive-strategy/src/regime/mod.rs +++ b/adaptive-strategy/src/regime/mod.rs @@ -14,7 +14,7 @@ use tokio::sync::{Mutex, RwLock}; use tracing::{debug, info, warn}; // Add missing core types -use trading_engine::types::prelude::*; +use common::types::prelude::*; // Add ML types use ml::prelude::*; // Add risk types diff --git a/adaptive-strategy/src/risk/ppo_position_sizer.rs b/adaptive-strategy/src/risk/ppo_position_sizer.rs index 6962e8d54..09eb77acc 100644 --- a/adaptive-strategy/src/risk/ppo_position_sizer.rs +++ b/adaptive-strategy/src/risk/ppo_position_sizer.rs @@ -28,7 +28,7 @@ use std::collections::HashMap; use tracing::{debug, info, warn}; // Add missing core types -use trading_engine::types::prelude::*; +use common::types::prelude::*; // Add ML types use ml::prelude::*; // Add data types diff --git a/common/src/trading.rs b/common/src/trading.rs index 335a90c28..2d90b3391 100644 --- a/common/src/trading.rs +++ b/common/src/trading.rs @@ -46,7 +46,7 @@ impl Default for TimeInForce { } } -// Currency moved to canonical source: trading_engine::types::Currency +// Currency moved to canonical source: common::types::Currency /// Tick type for market data #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] diff --git a/common/src/types.rs b/common/src/types.rs index 191ddb1ec..eeae8d9b2 100644 --- a/common/src/types.rs +++ b/common/src/types.rs @@ -1001,6 +1001,174 @@ impl Default for TimeInForce { } } +// ============================================================================= +// CORE ID TYPES (MIGRATED FROM TRADING_ENGINE) +// ============================================================================= + +// Duplicate TradeId removed - using definition from line 1008 + +/// Event identifier for tracking system events +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct EventId(String); + +impl EventId { + pub fn new() -> Self { + use uuid::Uuid; + Self(Uuid::new_v4().to_string()) + } + + pub fn from_string>(id: S) -> Self { + let id = id.into(); + if id.is_empty() { + Self::new() // Generate new ID if empty + } else { + Self(id) + } + } + + pub fn value(&self) -> &str { + &self.0 + } +} + +impl fmt::Display for EventId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +impl From for EventId { + fn from(s: String) -> Self { + Self(s) + } +} + +impl Default for EventId { + fn default() -> Self { + Self::new() + } +} + +/// Fill identifier with validation +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct FillId(String); + +impl FillId { + pub fn new>(id: S) -> Result { + let id = id.into(); + if id.is_empty() { + return Err(CommonTypeError::ValidationError { + field: "fill_id".to_owned(), + reason: "Fill ID cannot be empty".to_owned(), + }); + } + Ok(Self(id)) + } + + pub fn as_str(&self) -> &str { + &self.0 + } + pub fn into_string(self) -> String { + self.0 + } +} + +impl fmt::Display for FillId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +/// Aggregate identifier with validation +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct AggregateId(String); + +impl AggregateId { + pub fn new>(id: S) -> Result { + let id = id.into(); + if id.is_empty() { + return Err(CommonTypeError::ValidationError { + field: "aggregate_id".to_owned(), + reason: "Aggregate ID cannot be empty".to_owned(), + }); + } + Ok(Self(id)) + } + + pub fn as_str(&self) -> &str { + &self.0 + } + pub fn into_string(self) -> String { + self.0 + } +} + +impl fmt::Display for AggregateId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +/// Asset identifier with validation +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct AssetId(String); + +impl AssetId { + pub fn new>(id: S) -> Result { + let id = id.into(); + if id.is_empty() { + return Err(CommonTypeError::ValidationError { + field: "asset_id".to_owned(), + reason: "Asset ID cannot be empty".to_owned(), + }); + } + Ok(Self(id)) + } + + pub fn as_str(&self) -> &str { + &self.0 + } + pub fn into_string(self) -> String { + self.0 + } +} + +impl fmt::Display for AssetId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +/// Client identifier with validation +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct ClientId(String); + +impl ClientId { + pub fn new>(id: S) -> Result { + let id = id.into(); + if id.is_empty() { + return Err(CommonTypeError::ValidationError { + field: "client_id".to_owned(), + reason: "Client ID cannot be empty".to_owned(), + }); + } + Ok(Self(id)) + } + + pub fn as_str(&self) -> &str { + &self.0 + } + pub fn into_string(self) -> String { + self.0 + } +} + +impl fmt::Display for ClientId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} + // ============================================================================= // CORE TRADING TYPES - MIGRATED FROM TRADING_ENGINE // ============================================================================= @@ -1207,9 +1375,34 @@ impl Order { self.update_status(OrderStatus::PartiallyFilled); } - Ok(()) - } -} + Ok(()) + } + + /// Create a limit order - convenience constructor + pub fn limit(symbol: Symbol, side: OrderSide, quantity: Quantity, price: Price) -> Self { + Self::new(symbol, side, quantity, Some(price), OrderType::Limit) + } + + /// Create a market order - convenience constructor + pub fn market(symbol: Symbol, side: OrderSide, quantity: Quantity) -> Self { + Self::new(symbol, side, quantity, None, OrderType::Market) + } + + /// Get symbol hash for performance-critical operations + pub fn symbol_hash(&self) -> u64 { + use std::collections::hash_map::DefaultHasher; + use std::hash::{Hash, Hasher}; + + let mut hasher = DefaultHasher::new(); + self.symbol.as_str().hash(&mut hasher); + hasher.finish() + } + + /// Get order timestamp + pub fn timestamp(&self) -> HftTimestamp { + self.created_at + } + } /// Represents a trading position - CANONICAL DEFINITION #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] @@ -2210,14 +2403,14 @@ impl PartialEq for String { } } -// TimeInForce moved to canonical source: trading_engine::types::TimeInForce +// TimeInForce moved to canonical source: common::types::TimeInForce -// Currency moved to canonical source: trading_engine::types::Currency +// Currency moved to canonical source: common::types::Currency -// Price moved to canonical source: trading_engine::types::Price +// Price moved to canonical source: common::types::Price -// Quantity moved to canonical source: trading_engine::types::Quantity -// Volume moved to canonical source: trading_engine::types::Quantity (as Volume alias) +// Quantity moved to canonical source: common::types::Quantity +// Volume moved to canonical source: common::types::Quantity (as Volume alias) /// Money amount with currency #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] @@ -2239,11 +2432,11 @@ impl fmt::Display for Money { } } -// OrderId moved to canonical source: trading_engine::types::OrderId +// OrderId moved to canonical source: common::types::OrderId -// TradeId moved to canonical source: trading_engine::types::TradeId +// TradeId moved to canonical source: common::types::TradeId -// Symbol moved to canonical source: trading_engine::types::Symbol +// Symbol moved to canonical source: common::types::Symbol /// Type-safe account identifier #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] @@ -2299,6 +2492,18 @@ impl HftTimestamp { .as_nanos() as u64; Ok(Self { nanos }) } + + /// Get current timestamp with error handling for financial safety (CommonTypeError version) + pub fn now_common() -> Result { + use std::time::{SystemTime, UNIX_EPOCH}; + let nanos = SystemTime::now() + .duration_since(UNIX_EPOCH) + .map_err(|e| CommonTypeError::ConversionError { + message: format!("System time before UNIX epoch: {e}"), + })? + .as_nanos() as u64; + Ok(Self { nanos }) + } /// Get current timestamp or zero if system time is invalid #[must_use] @@ -2364,3 +2569,333 @@ impl GenericTimestamp { self.nanos } } + +// ============================================================================= +// MARKET TYPES (MIGRATED FROM TRADING_ENGINE) +// ============================================================================= + +/// Market regime enumeration for position sizing scaling and risk management +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum MarketRegime { + /// Normal market conditions + Normal, + /// Crisis/stress market conditions + Crisis, + /// Trending market (strong directional movement) + Trending, + /// Sideways/ranging market (low volatility) + Sideways, + /// Bull market (sustained upward trend) + Bull, + /// Bear market (sustained downward trend) + Bear, + /// High volatility market conditions + HighVolatility, + /// Low volatility market conditions + LowVolatility, + /// Volatile market conditions (alias for `HighVolatility`) + Volatile, + /// Calm market conditions (alias for `LowVolatility`) + Calm, + /// Unknown/unclassified regime + Unknown, + /// Recovery regime - transitioning from crisis + Recovery, + /// Bubble regime - unsustainable upward movement + Bubble, + /// Correction regime - temporary downward adjustment + Correction, + /// Custom regime with numeric identifier + Custom(usize), +} + +impl Default for MarketRegime { + fn default() -> Self { + Self::Normal + } +} + +impl fmt::Display for MarketRegime { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Normal => write!(f, "Normal"), + Self::Crisis => write!(f, "Crisis"), + Self::Trending => write!(f, "Trending"), + Self::Sideways => write!(f, "Sideways"), + Self::Bull => write!(f, "Bull"), + Self::Bear => write!(f, "Bear"), + Self::HighVolatility => write!(f, "HighVolatility"), + Self::LowVolatility => write!(f, "LowVolatility"), + Self::Volatile => write!(f, "Volatile"), + Self::Calm => write!(f, "Calm"), + Self::Unknown => write!(f, "Unknown"), + Self::Recovery => write!(f, "Recovery"), + Self::Bubble => write!(f, "Bubble"), + Self::Correction => write!(f, "Correction"), + Self::Custom(id) => write!(f, "Custom({id})"), + } + } +} + +/// Tick type enumeration for market data +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum TickType { + Trade, + Bid, + Ask, + Quote, +} + +/// Market tick data structure - CANONICAL SINGLE SOURCE OF TRUTH +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct MarketTick { + pub symbol: Symbol, + pub price: Price, + pub size: Quantity, + pub timestamp: HftTimestamp, + pub tick_type: TickType, + pub exchange: String, + pub sequence_number: u64, +} + +impl MarketTick { + /// Create a new market tick with current timestamp + pub fn new( + symbol: Symbol, + price: Price, + size: Quantity, + tick_type: TickType, + exchange: String, + sequence_number: u64, + ) -> Result { + Ok(Self { + symbol, + price, + size, + timestamp: HftTimestamp::now()?, + tick_type, + exchange, + sequence_number, + }) + } + + /// Create a new market tick with specified timestamp (for backtesting) + #[must_use] + pub const fn with_timestamp( + symbol: Symbol, + price: Price, + size: Quantity, + timestamp: HftTimestamp, + tick_type: TickType, + exchange: String, + sequence_number: u64, + ) -> Self { + Self { + symbol, + price, + size, + timestamp, + tick_type, + exchange, + sequence_number, + } + } +} + +/// Trading signal for algorithmic trading +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct TradingSignal { + /// Signal ID + pub signal_id: Uuid, + /// Symbol this signal applies to + pub symbol: Symbol, + /// Signal strength (-1.0 to 1.0) + pub strength: f64, + /// Signal direction + pub direction: OrderSide, + /// Confidence level (0.0 to 1.0) + pub confidence: f64, + /// Signal generation timestamp + pub timestamp: HftTimestamp, + /// Signal source/strategy + pub source: String, + /// Additional metadata + pub metadata: std::collections::HashMap, +} + +impl TradingSignal { + /// Create a new trading signal + pub fn new( + symbol: Symbol, + strength: f64, + direction: OrderSide, + confidence: f64, + source: String, + ) -> Result { + if !(0.0..=1.0).contains(&confidence) { + return Err(CommonTypeError::ValidationError { + field: "confidence".to_owned(), + reason: "Confidence must be between 0.0 and 1.0".to_owned(), + }); + } + if !(-1.0..=1.0).contains(&strength) { + return Err(CommonTypeError::ValidationError { + field: "strength".to_owned(), + reason: "Strength must be between -1.0 and 1.0".to_owned(), + }); + } + + Ok(Self { + signal_id: Uuid::new_v4(), + symbol, + strength, + direction, + confidence, + timestamp: HftTimestamp::now_common()?, + source, + metadata: std::collections::HashMap::new(), + }) + } + + /// Add metadata to the signal + #[must_use] + pub fn with_metadata(mut self, key: String, value: String) -> Self { + self.metadata.insert(key, value); + self + } + } + + // ============================================================================= + // HIGH-PERFORMANCE TYPES FOR COPY/CLONE OPTIMIZATION + // ============================================================================= + + /// Lightweight Order reference for high-performance contexts requiring Copy trait + /// + /// This struct contains only the essential order data needed for performance-critical + /// operations like `SmallBatchRing` processing, while maintaining Copy semantics. + /// For full order details, use the complete Order struct. + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] + pub struct OrderRef { + /// Order ID (u64 for performance) + pub id: u64, + /// Symbol hash for fast lookups + pub symbol_hash: u64, + /// Order side (Buy/Sell) + pub side: OrderSide, + /// Order type + pub order_type: OrderType, + /// Quantity (fixed-point u64) + pub quantity: u64, + /// Price (fixed-point u64, 0 for market orders) + pub price: u64, + /// Timestamp (nanoseconds since epoch) + pub timestamp: u64, + } + + impl OrderRef { + /// Create `OrderRef` from a full Order struct + #[must_use] + pub fn from_order(order: &Order) -> Self { + Self { + id: order.id.value(), + symbol_hash: Self::hash_symbol(&order.symbol), + side: order.side, + order_type: order.order_type, + quantity: order.quantity.raw_value(), + price: order.price.map_or(0, |p| p.raw_value()), + timestamp: order.created_at.nanos(), + } + } + + /// Create a limit order reference + #[must_use] + pub fn limit(symbol_hash: u64, side: OrderSide, quantity: u64, price: u64) -> Self { + Self { + id: OrderId::new().value(), + symbol_hash, + side, + order_type: OrderType::Limit, + quantity, + price, + timestamp: HftTimestamp::now_or_zero().nanos(), + } + } + + /// Create a market order reference + #[must_use] + pub fn market(symbol_hash: u64, side: OrderSide, quantity: u64) -> Self { + Self { + id: OrderId::new().value(), + symbol_hash, + side, + order_type: OrderType::Market, + quantity, + price: 0, + timestamp: HftTimestamp::now_or_zero().nanos(), + } + } + + /// Simple hash function for symbol strings (for performance) + fn hash_symbol(symbol: &Symbol) -> u64 { + use std::collections::hash_map::DefaultHasher; + use std::hash::{Hash, Hasher}; + + let mut hasher = DefaultHasher::new(); + symbol.as_str().hash(&mut hasher); + hasher.finish() + } + + /// Get quantity as Quantity type + #[must_use] + pub const fn get_quantity(&self) -> Quantity { + Quantity::from_raw(self.quantity) + } + + /// Get price as Price type (None for market orders) + #[must_use] + pub const fn get_price(&self) -> Option { + if self.price == 0 { + None + } else { + Some(Price::from_raw(self.price)) + } + } + + /// Check if this is a buy order + #[must_use] + pub fn is_buy(&self) -> bool { + self.side == OrderSide::Buy + } + + /// Check if this is a sell order + #[must_use] + pub fn is_sell(&self) -> bool { + self.side == OrderSide::Sell + } + + /// Check if this is a market order + #[must_use] + pub fn is_market_order(&self) -> bool { + self.order_type == OrderType::Market || self.price == 0 + } + + /// Check if this is a limit order + #[must_use] + pub fn is_limit_order(&self) -> bool { + self.order_type == OrderType::Limit && self.price > 0 + } + } + + impl Default for OrderRef { + fn default() -> Self { + Self { + id: 0, + symbol_hash: 0, + side: OrderSide::Buy, + order_type: OrderType::Market, + quantity: 0, + price: 0, + timestamp: 0, + } + } + } diff --git a/data/src/providers/benzinga/historical.rs b/data/src/providers/benzinga/historical.rs index 1b599118a..873bd859e 100644 --- a/data/src/providers/benzinga/historical.rs +++ b/data/src/providers/benzinga/historical.rs @@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize}; use std::collections::HashMap; use crate::error::{DataError, Result}; -use trading_engine::types::Symbol; +use common::types::Symbol; /// Configuration for Benzinga Historical Provider #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/data/src/providers/benzinga/integration.rs b/data/src/providers/benzinga/integration.rs index 90c8d6765..6d19d137b 100644 --- a/data/src/providers/benzinga/integration.rs +++ b/data/src/providers/benzinga/integration.rs @@ -19,7 +19,7 @@ //! ```rust,no_run //! use data::providers::benzinga::integration::BenzingaHFTIntegration; //! use config::ConfigManager; -//! use trading_engine::types::Symbol; +//! use common::types::Symbol; //! //! # async fn example() -> anyhow::Result<()> { //! // Initialize with configuration @@ -65,7 +65,7 @@ use crate::providers::benzinga::{ }; use crate::providers::traits::RealTimeProvider; use config::{ConfigManager, TrainingBenzingaConfig}; -use trading_engine::types::{Symbol, prelude::Decimal}; +use common::types::{Symbol, prelude::Decimal}; use tokio_stream::{Stream, StreamExt}; use tokio::sync::{mpsc, RwLock, Mutex}; use std::collections::{HashMap, VecDeque}; diff --git a/data/src/providers/benzinga/ml_integration.rs b/data/src/providers/benzinga/ml_integration.rs index 435ee20cb..5e285e97e 100644 --- a/data/src/providers/benzinga/ml_integration.rs +++ b/data/src/providers/benzinga/ml_integration.rs @@ -29,7 +29,7 @@ use std::sync::{ }; use tokio::sync::RwLock; use tracing::{debug, info, instrument}; -use trading_engine::types::{prelude::Decimal, Symbol}; +use common::types::{prelude::Decimal, Symbol}; /// Configuration for ML integration #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/data/src/providers/benzinga/mod.rs b/data/src/providers/benzinga/mod.rs index 1006e7b99..76228a7fd 100644 --- a/data/src/providers/benzinga/mod.rs +++ b/data/src/providers/benzinga/mod.rs @@ -28,7 +28,7 @@ //! ```rust,no_run //! use data::providers::benzinga::{ProductionBenzingaProvider, ProductionBenzingaConfig}; //! use data::providers::traits::RealTimeProvider; -//! use trading_engine::types::Symbol; +//! use common::types::Symbol; //! //! # async fn example() -> anyhow::Result<()> { //! let config = ProductionBenzingaConfig { @@ -107,7 +107,7 @@ //! use data::providers::benzinga::{BenzingaMLExtractor, BenzingaMLConfig}; //! use data::providers::common::MarketDataEvent; //! use chrono::Utc; -//! use trading_engine::types::Symbol; +//! use common::types::Symbol; //! //! # async fn example() -> anyhow::Result<()> { //! let config = BenzingaMLConfig { @@ -144,7 +144,7 @@ //! ```rust,no_run //! use data::providers::benzinga::{BenzingaHFTIntegration, BenzingaIntegrationConfig, TradingSignal, TradingSignalType}; //! use config::ConfigManager; -//! use trading_engine::types::Symbol; +//! use common::types::Symbol; //! use std::sync::Arc; //! //! # async fn example() -> anyhow::Result<()> { @@ -425,7 +425,7 @@ mod tests { #[tokio::test] async fn test_hft_integration_creation() { - use trading_engine::types::Symbol; + use common::types::Symbol; let config = BenzingaStreamingConfig { api_key: "test-key".to_string(), diff --git a/data/src/providers/benzinga/production_historical.rs b/data/src/providers/benzinga/production_historical.rs index ff1537c2f..d04c50dd8 100644 --- a/data/src/providers/benzinga/production_historical.rs +++ b/data/src/providers/benzinga/production_historical.rs @@ -34,7 +34,7 @@ use std::sync::{ use std::time::{Duration, Instant}; use tokio::sync::{RwLock, Semaphore}; use tracing::{debug, error, info, instrument, warn}; -use trading_engine::types::{prelude::Decimal, Symbol}; +use common::types::{prelude::Decimal, Symbol}; use async_trait::async_trait; /// Production Benzinga historical provider configuration diff --git a/data/src/providers/databento/client.rs b/data/src/providers/databento/client.rs index 4b64edec8..8ede72eff 100644 --- a/data/src/providers/databento/client.rs +++ b/data/src/providers/databento/client.rs @@ -408,12 +408,12 @@ impl DatabentoClient { Ok(()) } - async fn subscribe(&mut self, symbols: Vec) -> Result<()> { + async fn subscribe(&mut self, symbols: Vec) -> Result<()> { let symbol_strings: Vec = symbols.into_iter().map(|s| s.to_string()).collect(); self.subscribe_symbols(symbol_strings).await } - async fn unsubscribe(&mut self, symbols: Vec) -> Result<()> { + async fn unsubscribe(&mut self, symbols: Vec) -> Result<()> { let symbol_strings: Vec = symbols.into_iter().map(|s| s.to_string()).collect(); self.unsubscribe_symbols(symbol_strings).await } @@ -449,7 +449,7 @@ impl DatabentoClient { impl HistoricalProvider for DatabentoClient { async fn fetch( &self, - symbol: &trading_engine::types::Symbol, + symbol: &common::types::Symbol, schema: HistoricalSchema, range: TimeRange, ) -> Result> { diff --git a/data/src/providers/databento_streaming.rs b/data/src/providers/databento_streaming.rs index 55fbada00..1dd4b8fb1 100644 --- a/data/src/providers/databento_streaming.rs +++ b/data/src/providers/databento_streaming.rs @@ -17,7 +17,7 @@ use tracing::{debug, error, info, warn}; use trading_engine::trading::data_interface::{ MarketDataEvent as CoreMarketDataEvent, OrderBookEvent, QuoteEvent, TradeEvent, }; -use trading_engine::types::{Price, Quantity, Symbol}; +use common::types::{Price, Quantity, Symbol}; use url::Url; /// Databento WebSocket client for real-time market data diff --git a/data/src/providers/mod.rs b/data/src/providers/mod.rs index c764e657e..364d05462 100644 --- a/data/src/providers/mod.rs +++ b/data/src/providers/mod.rs @@ -53,7 +53,7 @@ use async_trait::async_trait; use rust_decimal::Decimal; use serde::{Deserialize, Serialize}; use tokio::sync::mpsc; -use trading_engine::types::Symbol; +use common::types::Symbol; /// Configuration for market data providers #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/data/src/providers/traits.rs b/data/src/providers/traits.rs index f215dc439..aa41b60bf 100644 --- a/data/src/providers/traits.rs +++ b/data/src/providers/traits.rs @@ -23,7 +23,7 @@ use serde::{Deserialize, Serialize}; use std::time::Duration; use futures_core::Stream; use std::pin::Pin; -use trading_engine::types::Symbol; +use common::types::Symbol; use std::error::Error as StdError; /// Real-time streaming data provider trait for WebSocket/TCP feeds @@ -35,7 +35,7 @@ use std::error::Error as StdError; /// /// ```no_run /// # use async_trait::async_trait; -/// # use trading_engine::types::Symbol; +/// # use common::types::Symbol; /// # use tokio_stream::Stream; /// # struct MyProvider; /// # impl MyProvider { @@ -149,7 +149,7 @@ pub trait RealTimeProvider: Send + Sync { /// /// ```no_run /// # use chrono::{DateTime, Utc}; -/// # use trading_engine::types::Symbol; +/// # use common::types::Symbol; /// # struct MyHistoricalProvider; /// # impl MyHistoricalProvider { /// # async fn fetch(&self, symbol: &Symbol, schema: HistoricalSchema, range: TimeRange) -> Result, Box> { Ok(vec![]) } diff --git a/ml/src/features.rs b/ml/src/features.rs index de4c33e73..92d4791fe 100644 --- a/ml/src/features.rs +++ b/ml/src/features.rs @@ -25,7 +25,7 @@ use tracing::{debug, warn}; // use error_handling::{AppResult, TradingError}; // Commented out - crate doesn't exist use common::types::*; -use trading_engine::types::basic::OrderBookLevel; +use common::types::basic::OrderBookLevel; use crate::common::MarketData; use crate::safety::{MLSafetyError, MLSafetyManager, SafetyResult}; diff --git a/ml/src/microstructure/types.rs b/ml/src/microstructure/types.rs index e1b827f80..804e2d1ab 100644 --- a/ml/src/microstructure/types.rs +++ b/ml/src/microstructure/types.rs @@ -5,7 +5,7 @@ use std::collections::HashMap; use serde::{Deserialize, Serialize}; -use trading_engine::types::AlertSeverity; +use common::types::AlertSeverity; use super::*; use super::{PRECISION_FACTOR, TradeDirection}; diff --git a/src/bin/trading_service.rs b/src/bin/trading_service.rs index 7eb27bd47..55dd4e80e 100644 --- a/src/bin/trading_service.rs +++ b/src/bin/trading_service.rs @@ -20,7 +20,7 @@ use risk::{RiskConfig, RiskEngine}; use trading_engine::config::ConfigManager; use trading_engine::trading::{OrderManager, PositionManager}; use common::types::*; -use trading_engine::types::{OrderStatus, OrderType, TradingOrder}; +use common::types::{OrderStatus, OrderType, TradingOrder}; // Import proto definitions and service implementations use tli::proto::trading::trading_service_server::TradingServiceServer; diff --git a/tests/Cargo.toml b/tests/Cargo.toml index ff3a9fd67..413688bcf 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -15,6 +15,7 @@ risk.workspace = true ml.workspace = true data.workspace = true tli.workspace = true +common.workspace = true # Serialization and time serde.workspace = true diff --git a/tests/common/database_test_helper.rs b/tests/common/database_test_helper.rs index e95f5f679..143d0fca6 100644 --- a/tests/common/database_test_helper.rs +++ b/tests/common/database_test_helper.rs @@ -15,7 +15,7 @@ use std::time::Duration; use chrono::Utc; // CANONICAL TYPE IMPORTS - Use core types throughout -use trading_engine::types::prelude::*; +use common::types::prelude::*; // All Decimal operations use core::types::prelude::Decimal use sqlx::{PgPool, Row}; use tokio::time::timeout; diff --git a/tests/compliance_validation_tests.rs b/tests/compliance_validation_tests.rs index c02a09dac..565595a69 100644 --- a/tests/compliance_validation_tests.rs +++ b/tests/compliance_validation_tests.rs @@ -23,7 +23,7 @@ use trading_engine::compliance::{ ClientInfo, ComplianceConfig, ComplianceEngine, ComplianceResult, ComplianceStatus, MarketContext, OrderInfo, }; -use trading_engine::types::prelude::*; +use common::types::prelude::*; /// Compliance test suite #[derive(Debug)] diff --git a/tests/e2e/src/utils.rs b/tests/e2e/src/utils.rs index 76fef5510..7110e97c7 100644 --- a/tests/e2e/src/utils.rs +++ b/tests/e2e/src/utils.rs @@ -2,8 +2,8 @@ use anyhow::Result; use chrono::{DateTime, Utc}; use rand::{thread_rng, Rng}; use std::collections::HashMap; -use trading_engine::types::prelude::Decimal; -use trading_engine::types::{ +use common::types::prelude::Decimal; +use common::types::{ basic::{Price, Quantity, Symbol}, events::MarketDataEvent, financial::{OrderSide, OrderType, TimeInForce}, diff --git a/tests/fixtures/lib.rs b/tests/fixtures/lib.rs index 01dbe5f71..5020ff53a 100644 --- a/tests/fixtures/lib.rs +++ b/tests/fixtures/lib.rs @@ -1,7 +1,7 @@ pub mod test_data; // CANONICAL TYPE IMPORTS - Use core::types::prelude::Decimal -use trading_engine::types::prelude::*; +use common::types::prelude::*; use std::str::FromStr; /// Production-grade test fixtures with no hardcoded values diff --git a/tests/fixtures/mod.rs b/tests/fixtures/mod.rs index 4c135f04a..1c7ac299d 100644 --- a/tests/fixtures/mod.rs +++ b/tests/fixtures/mod.rs @@ -12,7 +12,7 @@ use uuid::Uuid; use serde_json::json; use chrono::{DateTime, Utc, Duration as ChronoDuration}; -use trading_engine::types::prelude::*; +use common::types::prelude::*; use tli::prelude::*; pub mod test_config; diff --git a/tests/framework.rs b/tests/framework.rs index 4890c42a5..fda6f4f53 100644 --- a/tests/framework.rs +++ b/tests/framework.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use tokio::sync::RwLock; -use trading_engine::types::prelude::*; +use common::types::prelude::*; /// Test framework for setting up common test infrastructure pub struct TestFramework { diff --git a/tests/framework/mocks.rs b/tests/framework/mocks.rs index 602401e88..bf9c7b5fa 100644 --- a/tests/framework/mocks.rs +++ b/tests/framework/mocks.rs @@ -124,10 +124,10 @@ pub struct MockMarketData { #[derive(Debug, Clone)] // OrderSide now imported from canonical source -use trading_engine::types::prelude::OrderSide; +use common::types::prelude::OrderSide; // OrderStatus now imported from canonical source -use trading_engine::types::prelude::OrderStatus; +use common::types::prelude::OrderStatus; impl MockTradingService { pub fn new() -> Self { diff --git a/tests/helpers.rs b/tests/helpers.rs index 68a67e317..cc6d53ab6 100644 --- a/tests/helpers.rs +++ b/tests/helpers.rs @@ -3,7 +3,7 @@ use chrono::{DateTime, Utc}; use std::collections::HashMap; use trading_engine::prelude::TradingOrder; -use trading_engine::types::prelude::*; +use common::types::prelude::*; // Generate a simple test ID instead of using uuid fn generate_test_id() -> String { diff --git a/tests/integration/backtesting_flow.rs b/tests/integration/backtesting_flow.rs index dea1b26b6..ba3d38672 100644 --- a/tests/integration/backtesting_flow.rs +++ b/tests/integration/backtesting_flow.rs @@ -14,7 +14,7 @@ use uuid::Uuid; use serde_json::json; use chrono::{DateTime, Utc, Duration as ChronoDuration}; -use trading_engine::types::prelude::*; +use common::types::prelude::*; use tli::prelude::*; use backtesting::*; use ml::*; diff --git a/tests/integration/backtesting_service_tests.rs b/tests/integration/backtesting_service_tests.rs index 89989607f..be767c169 100644 --- a/tests/integration/backtesting_service_tests.rs +++ b/tests/integration/backtesting_service_tests.rs @@ -8,7 +8,7 @@ use crate::framework::{TestOrchestrator, TestFrameworkConfig, PerformanceThresho use crate::framework::mocks::MockServiceRegistry; use config::{ConfigManager, BacktestingConfig, MLConfig}; -use trading_engine::types::{Order, OrderType, Position, MarketData, TimeRange}; +use common::types::{Order, OrderType, Position, MarketData, TimeRange}; use ml::models::{ModelPrediction, TradingSignal}; /// Backtesting Service Integration Tests diff --git a/tests/integration/broker_failover.rs b/tests/integration/broker_failover.rs index e6e72d6ad..9c3cf83b0 100644 --- a/tests/integration/broker_failover.rs +++ b/tests/integration/broker_failover.rs @@ -26,7 +26,7 @@ use trading_engine::brokers::routing::decision::RoutingDecision; use trading_engine::brokers::routing::metrics::LatencyMetrics; use trading_engine::trading::data_interface::{BrokerInterface, BrokerConnectionStatus}; use trading_engine::prelude::{TradingOrder, OrderSide}; -use trading_engine::types::prelude::*; +use common::types::prelude::*; use trading_engine::trading_operations::OrderType; use common::types::TimeInForce; diff --git a/tests/integration/broker_integration_tests.rs b/tests/integration/broker_integration_tests.rs index 9ed3d4241..971dd51f5 100644 --- a/tests/integration/broker_integration_tests.rs +++ b/tests/integration/broker_integration_tests.rs @@ -5,7 +5,7 @@ use std::time::{Duration, Instant}; use tokio::time::timeout; -use trading_engine::types::prelude::*; +use common::types::prelude::*; // Note: These broker types should be imported from actual crate when available // use data::brokers::{InteractiveBrokers, ICMarkets, BrokerManager}; use risk::{RiskEngine, PositionTracker}; diff --git a/tests/integration/comprehensive_backtesting_tests.rs b/tests/integration/comprehensive_backtesting_tests.rs index 2b9e9dbf6..5dd37c755 100644 --- a/tests/integration/comprehensive_backtesting_tests.rs +++ b/tests/integration/comprehensive_backtesting_tests.rs @@ -14,7 +14,7 @@ use std::time::{Duration, Instant}; use tokio::sync::RwLock; use uuid::Uuid; -use trading_engine::types::prelude::*; +use common::types::prelude::*; use trading_engine::prelude::*; use risk::prelude::*; use ml::prelude::*; diff --git a/tests/integration/comprehensive_order_lifecycle_tests.rs b/tests/integration/comprehensive_order_lifecycle_tests.rs index 4c2501d5d..82b0e5821 100644 --- a/tests/integration/comprehensive_order_lifecycle_tests.rs +++ b/tests/integration/comprehensive_order_lifecycle_tests.rs @@ -15,7 +15,7 @@ use tokio::sync::{RwLock, mpsc}; use tokio::time::timeout; use uuid::Uuid; -use trading_engine::types::prelude::*; +use common::types::prelude::*; use trading_engine::prelude::*; use risk::prelude::*; use tli::prelude::*; diff --git a/tests/integration/config_hot_reload.rs b/tests/integration/config_hot_reload.rs index 3ca4c2b6f..831bccf46 100644 --- a/tests/integration/config_hot_reload.rs +++ b/tests/integration/config_hot_reload.rs @@ -15,7 +15,7 @@ use uuid::Uuid; use serde_json::json; use chrono::{DateTime, Utc}; -use trading_engine::types::prelude::*; +use common::types::prelude::*; use tli::prelude::*; use crate::fixtures::{IntegrationTestConfig, TestEnvironment, TestMetricsCollector}; use crate::mocks::{MockTradingService, TestDatabaseManager}; diff --git a/tests/integration/database_integration.rs b/tests/integration/database_integration.rs index 68f05605a..a456989cd 100644 --- a/tests/integration/database_integration.rs +++ b/tests/integration/database_integration.rs @@ -88,7 +88,7 @@ impl TradeRecord { #[derive(Debug, Clone)] // OrderSide now imported from canonical source -use trading_engine::types::prelude::OrderSide; +use common::types::prelude::OrderSide; /// Market data point for time-series storage #[derive(Debug, Clone)] diff --git a/tests/integration/dual_provider_test.rs b/tests/integration/dual_provider_test.rs index 98a7cf471..97232e535 100644 --- a/tests/integration/dual_provider_test.rs +++ b/tests/integration/dual_provider_test.rs @@ -17,8 +17,8 @@ use data::{ types::{MarketDataEvent, QuoteEvent, TradeEvent, Subscription, DataType, ConnectionEvent, ConnectionStatus}, DataManager, DataConfig, DataSettings, }; -use trading_engine::types::{prelude::*, events::OrderEvent}; -use trading_engine::types::prelude::Decimal; +use common::types::{prelude::*, events::OrderEvent}; +use common::types::prelude::Decimal; use std::collections::HashMap; use std::sync::Arc; use std::time::Duration; diff --git a/tests/integration/event_storage.rs b/tests/integration/event_storage.rs index f943632f5..330d40740 100644 --- a/tests/integration/event_storage.rs +++ b/tests/integration/event_storage.rs @@ -14,7 +14,7 @@ use uuid::Uuid; use serde_json::json; use chrono::{DateTime, Utc, Duration as ChronoDuration}; -use trading_engine::types::prelude::*; +use common::types::prelude::*; use sqlx::{PgPool, Row}; use tli::prelude::*; use crate::fixtures::*; diff --git a/tests/integration/icmarkets_validation.rs b/tests/integration/icmarkets_validation.rs index d52b2ddca..476668b16 100644 --- a/tests/integration/icmarkets_validation.rs +++ b/tests/integration/icmarkets_validation.rs @@ -20,7 +20,7 @@ use trading_engine::brokers::brokers::icmarkets::{ICMarketsClient, FixMessageBui use trading_engine::brokers::config::ICMarketsConfig; use trading_engine::trading::data_interface::{BrokerInterface, BrokerConnectionStatus}; use trading_engine::prelude::{TradingOrder, OrderSide}; -use trading_engine::types::prelude::*; +use common::types::prelude::*; use trading_engine::trading_operations::OrderType; use common::types::TimeInForce; diff --git a/tests/integration/interactive_brokers_validation.rs b/tests/integration/interactive_brokers_validation.rs index 39cefbe16..5320b63ef 100644 --- a/tests/integration/interactive_brokers_validation.rs +++ b/tests/integration/interactive_brokers_validation.rs @@ -20,7 +20,7 @@ use trading_engine::brokers::brokers::interactive_brokers::{InteractiveBrokersCl use trading_engine::brokers::config::InteractiveBrokersConfig; use trading_engine::trading::data_interface::{BrokerInterface, BrokerConnectionStatus}; use trading_engine::prelude::{TradingOrder, Side}; -use trading_engine::types::prelude::*; +use common::types::prelude::*; use trading_engine::trading_operations::OrderType; use common::types::TimeInForce; diff --git a/tests/integration/ml_trading_integration.rs b/tests/integration/ml_trading_integration.rs index 74a272d72..d154b455f 100644 --- a/tests/integration/ml_trading_integration.rs +++ b/tests/integration/ml_trading_integration.rs @@ -30,7 +30,7 @@ use tokio::time::timeout; use uuid::Uuid; // Import core system types -use trading_engine::types::prelude::*; +use common::types::prelude::*; use trading_engine::timing::HardwareTimestamp; use ml::prelude::*; use ml::tlob_transformer::*; diff --git a/tests/integration/order_lifecycle.rs b/tests/integration/order_lifecycle.rs index bd95a9fc2..577e9a455 100644 --- a/tests/integration/order_lifecycle.rs +++ b/tests/integration/order_lifecycle.rs @@ -25,7 +25,7 @@ use trading_engine::brokers::brokers::icmarkets::ICMarketsClient; use trading_engine::brokers::config::{InteractiveBrokersConfig, ICMarketsConfig}; use trading_engine::trading::data_interface::{BrokerInterface, BrokerConnectionStatus, ExecutionReport, Position}; use trading_engine::prelude::{TradingOrder, OrderSide}; -use trading_engine::types::prelude::*; +use common::types::prelude::*; use trading_engine::trading_operations::{OrderType, OrderStatus}; use common::types::TimeInForce; diff --git a/tests/integration/risk_enforcement.rs b/tests/integration/risk_enforcement.rs index 493640e11..70a4cbbb0 100644 --- a/tests/integration/risk_enforcement.rs +++ b/tests/integration/risk_enforcement.rs @@ -13,7 +13,7 @@ use uuid::Uuid; use serde_json::json; use chrono::{DateTime, Utc}; -use trading_engine::types::prelude::*; +use common::types::prelude::*; use tli::prelude::*; use crate::fixtures::{IntegrationTestConfig, TestEnvironment, TestMetricsCollector}; use crate::mocks::{MockTradingService, MockRiskService, TestDatabaseManager}; diff --git a/tests/integration/streaming_data.rs b/tests/integration/streaming_data.rs index e74d53cb2..3fcdbc32c 100644 --- a/tests/integration/streaming_data.rs +++ b/tests/integration/streaming_data.rs @@ -14,7 +14,7 @@ use uuid::Uuid; use serde_json::json; use chrono::{DateTime, Utc}; -use trading_engine::types::prelude::*; +use common::types::prelude::*; use tli::prelude::*; use crate::fixtures::{IntegrationTestConfig, TestEnvironment, TestMetricsCollector}; use crate::mocks::{MockTradingService, MockDataProvider, TestDatabaseManager}; diff --git a/tests/integration/tli_trading_integration.rs b/tests/integration/tli_trading_integration.rs index 9930e5257..bd04fc193 100644 --- a/tests/integration/tli_trading_integration.rs +++ b/tests/integration/tli_trading_integration.rs @@ -30,7 +30,7 @@ use tokio::time::timeout; use uuid::Uuid; // Import core system types -use trading_engine::types::prelude::*; +use common::types::prelude::*; use trading_engine::timing::HardwareTimestamp; use tli::prelude::*; use tli::proto::trading::*; diff --git a/tests/integration/trading_flow.rs b/tests/integration/trading_flow.rs index 83d5b87b8..a7df0ed39 100644 --- a/tests/integration/trading_flow.rs +++ b/tests/integration/trading_flow.rs @@ -13,7 +13,7 @@ use tokio::time::timeout; use uuid::Uuid; use serde_json::json; -use trading_engine::types::prelude::*; +use common::types::prelude::*; use tli::prelude::*; use risk::prelude::*; use crate::fixtures::*; diff --git a/tests/integration/trading_risk_integration.rs b/tests/integration/trading_risk_integration.rs index 9ebf3a877..86dfea244 100644 --- a/tests/integration/trading_risk_integration.rs +++ b/tests/integration/trading_risk_integration.rs @@ -30,7 +30,7 @@ use tokio::time::timeout; use uuid::Uuid; // Import core system types -use trading_engine::types::prelude::*; +use common::types::prelude::*; use trading_engine::timing::HardwareTimestamp; use risk::prelude::*; diff --git a/tests/integration/trading_service_tests.rs b/tests/integration/trading_service_tests.rs index dcbe0053f..49ac010ac 100644 --- a/tests/integration/trading_service_tests.rs +++ b/tests/integration/trading_service_tests.rs @@ -7,10 +7,10 @@ use crate::framework::{TestOrchestrator, TestFrameworkConfig, PerformanceThresho use crate::framework::mocks::MockServiceRegistry; use config::{ConfigManager, TradingConfig, RiskConfig, MLConfig}; -use trading_engine::types::{Order, OrderType, OrderStatus, Position, MarketData, Tick}; +use common::types::{Order, OrderType, OrderStatus, Position, MarketData, Tick}; use trading_engine::services::trading::{TradingService, OrderExecutor, PositionManager}; use risk::safety::KillSwitchController; -use trading_engine::types::events::{OrderEvent, PositionEvent, RiskEvent}; +use common::types::events::{OrderEvent, PositionEvent, RiskEvent}; use trading_engine::events::EventBus; /// Comprehensive Trading Service Integration Tests @@ -94,7 +94,7 @@ impl TradingServiceTests { id: uuid::Uuid::new_v4(), symbol: "EURUSD".to_string(), order_type: OrderType::Market, - side: trading_engine::types::OrderSide::Buy, + side: common::types::OrderSide::Buy, quantity: 100000.0, // Standard lot price: None, // Market order status: OrderStatus::Pending, @@ -154,7 +154,7 @@ impl TradingServiceTests { id: uuid::Uuid::new_v4(), symbol: "GBPUSD".to_string(), order_type: OrderType::Limit, - side: trading_engine::types::OrderSide::Sell, + side: common::types::OrderSide::Sell, quantity: 50000.0, price: Some(1.2650), // Limit price status: OrderStatus::Pending, @@ -199,7 +199,7 @@ impl TradingServiceTests { id: uuid::Uuid::new_v4(), symbol: "EURUSD".to_string(), order_type: OrderType::Market, - side: trading_engine::types::OrderSide::Buy, + side: common::types::OrderSide::Buy, quantity: 10_000_000.0, // Intentionally large to trigger risk checks price: None, status: OrderStatus::Pending, @@ -264,7 +264,7 @@ impl TradingServiceTests { id: uuid::Uuid::new_v4(), symbol: "EURUSD".to_string(), order_type: OrderType::Market, - side: trading_engine::types::OrderSide::Buy, + side: common::types::OrderSide::Buy, quantity: 100000.0, price: None, status: OrderStatus::Pending, @@ -309,7 +309,7 @@ impl TradingServiceTests { id: uuid::Uuid::new_v4(), symbol: "EURUSD".to_string(), order_type: OrderType::Market, - side: trading_engine::types::OrderSide::Sell, + side: common::types::OrderSide::Sell, quantity: 50000.0, // Close half price: None, status: OrderStatus::Pending, @@ -346,7 +346,7 @@ impl TradingServiceTests { id: uuid::Uuid::new_v4(), symbol: "GBPUSD".to_string(), order_type: OrderType::Market, - side: trading_engine::types::OrderSide::Buy, + side: common::types::OrderSide::Buy, quantity: 75000.0, price: None, status: OrderStatus::Pending, @@ -484,7 +484,7 @@ impl TradingServiceTests { id: uuid::Uuid::new_v4(), symbol: "EURUSD".to_string(), order_type: OrderType::Limit, - side: trading_engine::types::OrderSide::Buy, + side: common::types::OrderSide::Buy, quantity: 100000.0, price: Some(1.0000), // Far from market to stay pending status: OrderStatus::Pending, diff --git a/tests/mocks/mod.rs b/tests/mocks/mod.rs index 5bcb9e2f6..13e75e7e2 100644 --- a/tests/mocks/mod.rs +++ b/tests/mocks/mod.rs @@ -13,7 +13,7 @@ use uuid::Uuid; use serde_json::json; use chrono::{DateTime, Utc}; -use trading_engine::types::prelude::*; +use common::types::prelude::*; use tli::prelude::*; use crate::fixtures::*; @@ -61,7 +61,7 @@ impl Default for MockServiceConfig { } // OrderStatus now imported from canonical source -use trading_engine::types::prelude::OrderStatus; +use common::types::prelude::OrderStatus; /// Circuit breaker status #[derive(Debug, Clone)] diff --git a/tests/performance/critical_path_tests.rs b/tests/performance/critical_path_tests.rs index a546a2d6b..25e1bed7e 100644 --- a/tests/performance/critical_path_tests.rs +++ b/tests/performance/critical_path_tests.rs @@ -26,7 +26,7 @@ use std::collections::HashMap; use tokio::time::timeout; // Import unified types from the core prelude -use trading_engine::types::prelude::*; +use common::types::prelude::*; // Import risk management system use risk::prelude::*; diff --git a/tests/performance/hft_benchmarks.rs b/tests/performance/hft_benchmarks.rs index 034a36f6b..078766e56 100644 --- a/tests/performance/hft_benchmarks.rs +++ b/tests/performance/hft_benchmarks.rs @@ -29,7 +29,7 @@ use std::collections::HashMap; use tokio::time::timeout; // Import unified types -use trading_engine::types::prelude::*; +use common::types::prelude::*; // Import risk and ML systems use risk::prelude::*; diff --git a/tests/performance/memory_performance.rs b/tests/performance/memory_performance.rs index 0973e2c88..9e21a9c33 100644 --- a/tests/performance/memory_performance.rs +++ b/tests/performance/memory_performance.rs @@ -62,7 +62,7 @@ impl HftPerformanceValidator { } // Import core components -use trading_engine::types::prelude::*; +use common::types::prelude::*; /// Memory pool implementation for high-frequency allocations struct HftMemoryPool { diff --git a/tests/performance_and_stress_tests.rs b/tests/performance_and_stress_tests.rs index 86200397d..d32fd4240 100644 --- a/tests/performance_and_stress_tests.rs +++ b/tests/performance_and_stress_tests.rs @@ -22,7 +22,7 @@ use trading_engine::lockfree::*; use trading_engine::prelude::*; use trading_engine::simd::*; use trading_engine::timing::*; -use trading_engine::types::*; +use common::types::*; #[cfg(test)] mod performance_and_stress_tests { diff --git a/tests/production_integration_tests.rs b/tests/production_integration_tests.rs index 1e7e7518e..7563af618 100644 --- a/tests/production_integration_tests.rs +++ b/tests/production_integration_tests.rs @@ -676,7 +676,7 @@ pub struct TradingSignal { } // OrderSide now imported from canonical source -use trading_engine::types::prelude::OrderSide; +use common::types::prelude::OrderSide; /// ML Model trait for testing #[async_trait::async_trait] diff --git a/tests/real_broker_integration_tests.rs b/tests/real_broker_integration_tests.rs index b2ab9e2dc..8392e10b8 100644 --- a/tests/real_broker_integration_tests.rs +++ b/tests/real_broker_integration_tests.rs @@ -230,10 +230,10 @@ pub struct TestOrder { /// Order side enumeration #[derive(Debug, Clone, Copy)] // OrderSide now imported from canonical source -use trading_engine::types::prelude::OrderSide; +use common::types::prelude::OrderSide; // OrderStatus now imported from canonical source -use trading_engine::types::prelude::OrderStatus; +use common::types::prelude::OrderStatus; impl RealBrokerTestHarness { /// Create new real broker test harness diff --git a/tests/risk_validation_tests.rs b/tests/risk_validation_tests.rs index 4fd150e05..137df25fd 100644 --- a/tests/risk_validation_tests.rs +++ b/tests/risk_validation_tests.rs @@ -19,7 +19,7 @@ use risk::{ ComplianceEngine, HistoricalPrice, KillSwitchScope, OrderInfo, OrderSide, OrderType, Portfolio, PositionInfo, Symbol, TimeInForce, }; -use trading_engine::types::prelude::*; +use common::types::prelude::*; /// Test data constants for reproducible testing const TEST_SYMBOL: &str = "EURUSD"; diff --git a/tests/unit/benches/comprehensive_hft_performance_benchmarks.rs b/tests/unit/benches/comprehensive_hft_performance_benchmarks.rs index ce6ed44ff..c1a77d20a 100644 --- a/tests/unit/benches/comprehensive_hft_performance_benchmarks.rs +++ b/tests/unit/benches/comprehensive_hft_performance_benchmarks.rs @@ -43,7 +43,7 @@ pub struct HFTOrder { } // OrderSide now imported from canonical source -use trading_engine::types::prelude::OrderSide; +use common::types::prelude::OrderSide; /// High-performance market data tick #[derive(Debug, Clone, Copy)] diff --git a/tests/unit/broker_execution_tests.rs b/tests/unit/broker_execution_tests.rs index 9dc7d3b2b..c12ea76da 100644 --- a/tests/unit/broker_execution_tests.rs +++ b/tests/unit/broker_execution_tests.rs @@ -11,7 +11,7 @@ use broker_execution::{ BrokerExecutionState, ExecutionRequest, BrokerType, Instrument, AssetType, Side, OrderType, TimeInForce }; -use trading_engine::types::prelude::*; +use common::types::prelude::*; #[tokio::test] async fn test_real_broker_execution_state_creation() { diff --git a/tests/unit/comprehensive_concurrency_safety_tests.rs b/tests/unit/comprehensive_concurrency_safety_tests.rs index 454a89f01..26cbef07b 100644 --- a/tests/unit/comprehensive_concurrency_safety_tests.rs +++ b/tests/unit/comprehensive_concurrency_safety_tests.rs @@ -15,7 +15,7 @@ use tokio::task::JoinSet; use futures::future::join_all; use proptest::prelude::*; use criterion::black_box; -use trading_engine::types::prelude::*; +use common::types::prelude::*; /// Concurrency test configuration for high-throughput scenarios #[derive(Debug, Clone)] diff --git a/tests/unit/comprehensive_core_unit_tests.rs b/tests/unit/comprehensive_core_unit_tests.rs index 90bbd9d00..b7ff3ce44 100644 --- a/tests/unit/comprehensive_core_unit_tests.rs +++ b/tests/unit/comprehensive_core_unit_tests.rs @@ -40,7 +40,7 @@ pub struct MockOrder { #[derive(Debug, Clone, PartialEq)] // OrderSide and OrderType now imported from canonical source -use trading_engine::types::prelude::{OrderSide, OrderType}; +use common::types::prelude::{OrderSide, OrderType}; // OrderType now imported from canonical source above diff --git a/tests/unit/core/critical_paths.rs b/tests/unit/core/critical_paths.rs index cd72c43fa..bf82cf89b 100644 --- a/tests/unit/core/critical_paths.rs +++ b/tests/unit/core/critical_paths.rs @@ -22,7 +22,7 @@ use std::sync::atomic::{AtomicU64, Ordering}; use tokio::time::timeout; // Import types from canonical types crate -use trading_engine::types::prelude::*; +use common::types::prelude::*; // Define test framework types locally for now type TestResult = Result; diff --git a/tests/unit/core/safety_tests.rs b/tests/unit/core/safety_tests.rs index be7c2a861..3c90f299a 100644 --- a/tests/unit/core/safety_tests.rs +++ b/tests/unit/core/safety_tests.rs @@ -28,7 +28,7 @@ use std::collections::HashMap; use tokio::time::timeout; // Import unified types -use trading_engine::types::prelude::*; +use common::types::prelude::*; // Import risk and safety systems use risk::prelude::*; diff --git a/tests/unit/core/unified_extractor_tests.rs b/tests/unit/core/unified_extractor_tests.rs index 0110376c9..950405b5b 100644 --- a/tests/unit/core/unified_extractor_tests.rs +++ b/tests/unit/core/unified_extractor_tests.rs @@ -18,7 +18,7 @@ use trading_engine::features::unified_extractor::{ DatabentoBuData, BenzingaNewsData, NewsArticle, SentimentScore, AnalystRating, UnusualOptionsActivity, }; -use trading_engine::types::prelude::*; +use common::types::prelude::*; use common::types::QuoteEvent; // Test fixtures and mock data generators diff --git a/tests/unit/data/unified_feature_extractor_tests.rs b/tests/unit/data/unified_feature_extractor_tests.rs index e6b76545f..7d01607ca 100644 --- a/tests/unit/data/unified_feature_extractor_tests.rs +++ b/tests/unit/data/unified_feature_extractor_tests.rs @@ -24,7 +24,7 @@ use foxhunt_data::{ TLOBConfig, TemporalConfig, RegimeDetectionConfig, MACDConfig }, }; -use trading_engine::types::prelude::*; +use common::types::prelude::*; // Test fixtures and helpers diff --git a/tests/unit/ml/model_tests.rs b/tests/unit/ml/model_tests.rs index 86409dfb1..64e9e2f51 100644 --- a/tests/unit/ml/model_tests.rs +++ b/tests/unit/ml/model_tests.rs @@ -5,7 +5,7 @@ use std::time::{Duration, Instant}; use tokio::time::timeout; -use trading_engine::types::prelude::*; +use common::types::prelude::*; // Note: ML models not yet available - commenting out for compilation // use ml::{ // MLModel, ModelRegistry, TLOBTransformer, MAMBAModel, diff --git a/tests/unit/performance_benchmarks.rs b/tests/unit/performance_benchmarks.rs index 6f941f639..fa77d525f 100644 --- a/tests/unit/performance_benchmarks.rs +++ b/tests/unit/performance_benchmarks.rs @@ -512,7 +512,7 @@ struct TestOrder { #[derive(Debug)] // OrderSide now imported from canonical source -use trading_engine::types::prelude::OrderSide; +use common::types::prelude::OrderSide; #[derive(Debug)] struct TestOrderProcessor; diff --git a/tests/unit/trading_algorithm_correctness.rs b/tests/unit/trading_algorithm_correctness.rs index 9263c83e9..e5e8fd19b 100644 --- a/tests/unit/trading_algorithm_correctness.rs +++ b/tests/unit/trading_algorithm_correctness.rs @@ -458,7 +458,7 @@ struct IcebergOrder { #[derive(Debug, Clone)] // OrderSide now imported from canonical source -use trading_engine::types::prelude::OrderSide; +use common::types::prelude::OrderSide; #[derive(Debug)] struct OrderSlice { diff --git a/tests/unit/unit-tests-src/execution.rs b/tests/unit/unit-tests-src/execution.rs index 42a4e94b8..00ab86386 100644 --- a/tests/unit/unit-tests-src/execution.rs +++ b/tests/unit/unit-tests-src/execution.rs @@ -3,7 +3,7 @@ //! Tests order routing, execution algorithms, and venue selection //! with focus on best execution and latency optimization. -use trading_engine::types::prelude::*; +use common::types::prelude::*; // CANONICAL TYPE IMPORTS - Use types::prelude::Decimal use std::collections::HashMap; use std::time::{Duration, Instant}; diff --git a/tests/unit/unit-tests-src/financial.rs b/tests/unit/unit-tests-src/financial.rs index 7b620e442..5722a3a99 100644 --- a/tests/unit/unit-tests-src/financial.rs +++ b/tests/unit/unit-tests-src/financial.rs @@ -3,7 +3,7 @@ //! Tests mathematical accuracy, edge cases, and precision requirements //! for financial calculations in the trading system. -use trading_engine::types::prelude::*; +use common::types::prelude::*; // CANONICAL TYPE IMPORTS - Use types::prelude::Decimal use proptest::prelude::*; diff --git a/tests/unit/unit-tests-src/risk.rs b/tests/unit/unit-tests-src/risk.rs index 160036e79..50edfccd7 100644 --- a/tests/unit/unit-tests-src/risk.rs +++ b/tests/unit/unit-tests-src/risk.rs @@ -3,7 +3,7 @@ //! Tests risk controls, position limits, and safety mechanisms //! with focus on preventing financial losses. -use trading_engine::types::prelude::*; +use common::types::prelude::*; // CANONICAL TYPE IMPORTS - Use types::prelude::Decimal use std::collections::HashMap; diff --git a/tests/unit/unit-tests-src/trading.rs b/tests/unit/unit-tests-src/trading.rs index 1024c0153..e7cf8a8c8 100644 --- a/tests/unit/unit-tests-src/trading.rs +++ b/tests/unit/unit-tests-src/trading.rs @@ -3,7 +3,7 @@ //! Tests order processing, matching engine, and trade execution logic //! with focus on correctness and edge case handling. -use trading_engine::types::prelude::*; +use common::types::prelude::*; // CANONICAL TYPE IMPORTS - Use types::prelude::Decimal use std::collections::HashMap; diff --git a/tests/unit/unit-tests-src/types.rs b/tests/unit/unit-tests-src/types.rs index 1fdced5f9..a4aadcbb8 100644 --- a/tests/unit/unit-tests-src/types.rs +++ b/tests/unit/unit-tests-src/types.rs @@ -3,7 +3,7 @@ //! Tests the fundamental types that underpin the entire trading system, //! with focus on precision, validation, and safety. -use trading_engine::types::prelude::*; +use common::types::prelude::*; #[cfg(test)] mod tests { diff --git a/tests/unit/unit-tests-src/utils.rs b/tests/unit/unit-tests-src/utils.rs index 45af477f9..9e967ed0b 100644 --- a/tests/unit/unit-tests-src/utils.rs +++ b/tests/unit/unit-tests-src/utils.rs @@ -2,7 +2,7 @@ //! //! Common testing utilities shared across all test modules. -use trading_engine::types::prelude::*; +use common::types::prelude::*; // CANONICAL TYPE IMPORTS - Use types::prelude::Decimal use std::collections::HashMap; diff --git a/tests/utils/hft_test_utils.rs b/tests/utils/hft_test_utils.rs index e3caa287c..5ebcf3497 100644 --- a/tests/utils/hft_test_utils.rs +++ b/tests/utils/hft_test_utils.rs @@ -7,7 +7,7 @@ use super::test_safety::{TestError, TestResult}; use chrono::{DateTime, Utc}; use std::collections::VecDeque; use std::time::{Duration, Instant}; -use trading_engine::types::prelude::*; +use common::types::prelude::*; /// Performance measurement utilities for HFT testing pub mod performance { @@ -328,7 +328,7 @@ pub mod orders { } // OrderSide, OrderType, and OrderStatus now imported from canonical source - pub use trading_engine::types::prelude::{OrderSide, OrderType, OrderStatus}; + pub use common::types::prelude::{OrderSide, OrderType, OrderStatus}; impl TestOrder { pub fn new_market_order(symbol: &str, side: OrderSide, quantity: Decimal) -> Self { diff --git a/trading_engine/src/compliance/best_execution.rs b/trading_engine/src/compliance/best_execution.rs index 582e08545..a991f3643 100644 --- a/trading_engine/src/compliance/best_execution.rs +++ b/trading_engine/src/compliance/best_execution.rs @@ -967,6 +967,34 @@ impl From for BestExecutionError { BestExecutionError::DataAccessError(format!("Generic error: {}", err)) } } + + impl From for BestExecutionError { + fn from(err: CommonTypeError) -> Self { + match err { + CommonTypeError::InvalidPrice { value, reason } => { + BestExecutionError::CostCalculationError(format!( + "Invalid price: {} - {}", value, reason + )) + } + CommonTypeError::InvalidQuantity { value, reason } => { + BestExecutionError::CostCalculationError(format!( + "Invalid quantity: {} - {}", value, reason + )) + } + CommonTypeError::InvalidIdentifier { field, reason } => { + BestExecutionError::VenueAnalysisFailed(format!( + "Invalid identifier {}: {}", field, reason + )) + } + CommonTypeError::ValidationError { field, reason } => { + BestExecutionError::VenueAnalysisFailed(format!( + "Validation error for {}: {}", field, reason + )) + } + _ => BestExecutionError::DataAccessError(format!("CommonTypeError: {}", err)), + } + } + } impl Default for VenueExecutionMonitor { fn default() -> Self { diff --git a/trading_engine/src/trading_operations.rs b/trading_engine/src/trading_operations.rs index a53c14be1..8006437e1 100644 --- a/trading_engine/src/trading_operations.rs +++ b/trading_engine/src/trading_operations.rs @@ -4,7 +4,7 @@ //! with comprehensive Prometheus metrics collection for all critical paths. // Public re-exports for types used by this module - use canonical types -pub use crate::types::basic::{OrderSide, OrderStatus, OrderType, Side}; +pub use crate::types::basic::{OrderSide, OrderStatus, OrderType, Side, TimeInForce}; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; diff --git a/trading_engine/src/types/basic.rs b/trading_engine/src/types/basic.rs index 00bf8e2cd..c461dce06 100644 --- a/trading_engine/src/types/basic.rs +++ b/trading_engine/src/types/basic.rs @@ -1,4 +1,7 @@ -//! Minimal types for multi-asset-trading compilation +//! Basic types - Clean imports from canonical common::types +//! +//! This module provides clean re-exports of types from the canonical common::types module. +//! All type definitions have been moved to common::types to establish a single source of truth. #![deny( clippy::unwrap_used, @@ -9,37 +12,52 @@ )] #![warn(clippy::pedantic, clippy::nursery, clippy::perf)] -// CANONICAL TYPE IMPORTS - Import directly from financial module to avoid circular dependency +// ============================================================================ +// CANONICAL TYPE IMPORTS - Single Source of Truth from common::types +// ============================================================================ + +// Re-export all canonical types from common crate +pub use common::types::{ + // Core Trading Types + Order, OrderId, OrderSide, OrderStatus, OrderType, OrderRef, + Price, Quantity, Volume, Symbol, Currency, TimeInForce, + + // Market Data Types + MarketTick, TickType, MarketRegime, TradingSignal, + QuoteEvent, TradeEvent, BarEvent, Level2Update, PriceLevel, + MarketStatus, ConnectionEvent, ConnectionStatus, ErrorEvent, ErrorCategory, + OrderBookEvent, DataType, Subscription, MarketDataEvent, + + // Identifiers + TradeId, EventId, FillId, AggregateId, AssetId, ClientId, AccountId, + + // Infrastructure Types + ServiceId, ServiceStatus, ConfigVersion, RequestId, Timestamp, + ConnectionInfo, ResourceLimits, + + // Error Types + CommonTypeError, + + // Time Types + HftTimestamp, GenericTimestamp, + + // Financial Types + Position, Execution, Money, + + // Aggregate Types + Aggregate, +}; + +// Import error type from crate for backward compatibility use crate::types::errors::FoxhuntError; -use std::fmt; -use std::error::Error; -// Import canonical types from common crate -use common::types::{Order, Symbol, Quantity}; +// ============================================================================ +// COMPATIBILITY BRIDGE FUNCTIONS +// ============================================================================ -// Re-export canonical trading types from common crate -/// `TradingError` - Bridge type that provides static methods for creating `FoxhuntError` instances -/// This maintains backward compatibility with existing code while using the unified error system. -#[derive(Debug, Clone, PartialEq)] -pub struct TradingError(pub FoxhuntError); - -impl fmt::Display for TradingError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -impl Error for TradingError { - fn source(&self) -> Option<&(dyn Error + 'static)> { - Some(&self.0) - } -} - -impl From for TradingError { - fn from(err: FoxhuntError) -> Self { - Self(err) - } -} +/// Bridge functions for existing code that expects TradingError static methods +/// These maintain backward compatibility while using the unified error system +pub struct TradingError; impl TradingError { /// Create an invalid price error @@ -70,2361 +88,45 @@ impl TradingError { context: None, } } - - /// Create a financial safety error - #[must_use] - pub const fn financial_safety(message: String) -> Self { - Self(FoxhuntError::FinancialSafety { - message, - context: None, - asset: None, - }) - } - - /// Create an invalid address error - #[must_use] - pub fn invalid_address(message: &str) -> Self { - Self(FoxhuntError::Validation { - field: "address".to_owned(), - reason: message.to_owned(), - expected: None, - actual: None, - }) - } - - /// Create an invalid signal error - #[must_use] - pub fn invalid_signal(message: &str) -> Self { - Self(FoxhuntError::Validation { - field: "signal".to_owned(), - reason: message.to_owned(), - expected: None, - actual: None, - }) - } - - /// Create an invalid risk error - #[must_use] - pub fn invalid_risk(message: &str) -> Self { - Self(FoxhuntError::Validation { - field: "risk".to_owned(), - reason: message.to_owned(), - expected: None, - actual: None, - }) - } -} - -// Note: Decimal and FromPrimitive are re-exported in prelude for services -use crate::types::financial::{Decimal, FromPrimitive}; -use chrono::{DateTime, Utc}; -use common::prelude::{Currency, Price, Side, TimeInForce, Volume}; -use serde::{Deserialize, Serialize}; -use std::collections::HashMap; -use std::time::{SystemTime, UNIX_EPOCH}; -use std::{convert::TryFrom, str::FromStr}; -use std::{ - env, - iter::Sum, - num::ParseIntError, - ops::{Add, Div, Mul, Sub}, -}; -use uuid::Uuid; - -// ============================================================================ -// CONCRETE TYPES - PRODUCTION READY WITH TYPE SAFETY -// ============================================================================ - -/// Profit and Loss with decimal precision and validation -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] -pub struct PnL(pub Decimal); - -impl PnL { - pub const ZERO: Self = Self(Decimal::ZERO); - - pub fn new(value: Decimal) -> Self { - Self(value) - } - - pub fn from_f64(value: f64) -> Result { - Ok(Self(Decimal::from_f64_retain(value).ok_or_else(|| { - FoxhuntError::InvalidPrice { - value: value.to_string(), - reason: "Invalid PnL value".to_owned(), - symbol: None, - } - })?)) - } - - pub fn value(&self) -> Decimal { - self.0 - } -} - - -/// Trade identifier with validation -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct TradeId(String); - -impl TradeId { - pub fn new>(id: S) -> Result { - let id = id.into(); - if id.is_empty() { - return Err(FoxhuntError::Validation { - field: "trade_id".to_owned(), - reason: "Trade ID cannot be empty".to_owned(), - expected: Some("non-empty string".to_owned()), - actual: Some("empty string".to_owned()), - }); - } - Ok(Self(id)) - } - - pub fn as_str(&self) -> &str { - &self.0 - } - pub fn into_string(self) -> String { - self.0 - } -} - -impl fmt::Display for TradeId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -/// Event identifier for tracking system events -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct EventId(String); - -impl EventId { - pub fn new() -> Self { - use uuid::Uuid; - Self(Uuid::new_v4().to_string()) - } - - pub fn from_string>(id: S) -> Self { - let id = id.into(); - if id.is_empty() { - Self::new() // Generate new ID if empty - } else { - Self(id) - } - } - - pub fn value(&self) -> &str { - &self.0 - } -} - -impl fmt::Display for EventId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -impl From for EventId { - fn from(s: String) -> Self { - Self(s) - } -} - -impl Default for EventId { - fn default() -> Self { - Self::new() - } -} - -/// Fill identifier with validation -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct FillId(String); - -impl FillId { - pub fn new>(id: S) -> Result { - let id = id.into(); - if id.is_empty() { - return Err(FoxhuntError::Validation { - field: "fill_id".to_owned(), - reason: "Fill ID cannot be empty".to_owned(), - expected: Some("non-empty string".to_owned()), - actual: Some("empty string".to_owned()), - }); - } - Ok(Self(id)) - } - - pub fn as_str(&self) -> &str { - &self.0 - } - pub fn into_string(self) -> String { - self.0 - } -} - -impl fmt::Display for FillId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -// TECHNICAL DEBT ELIMINATED - Use Side directly instead of Side alias - -/// Account identifier with validation -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct AccountId(String); - -impl AccountId { - pub fn new>(id: S) -> Result { - let id = id.into(); - if id.is_empty() { - return Err(FoxhuntError::Validation { - field: "account_id".to_owned(), - reason: "Account ID cannot be empty".to_owned(), - expected: Some("non-empty string".to_owned()), - actual: Some("empty string".to_owned()), - }); - } - Ok(Self(id)) - } - - pub fn as_str(&self) -> &str { - &self.0 - } - pub fn into_string(self) -> String { - self.0 - } -} - -impl fmt::Display for AccountId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -/// Aggregate identifier with validation -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct AggregateId(String); - -impl AggregateId { - pub fn new>(id: S) -> Result { - let id = id.into(); - if id.is_empty() { - return Err(FoxhuntError::Validation { - field: "aggregate_id".to_owned(), - reason: "Aggregate ID cannot be empty".to_owned(), - expected: Some("non-empty string".to_owned()), - actual: Some("empty string".to_owned()), - }); - } - Ok(Self(id)) - } - - pub fn as_str(&self) -> &str { - &self.0 - } - pub fn into_string(self) -> String { - self.0 - } -} - -impl fmt::Display for AggregateId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -/// Aggregate version with validation -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] -pub struct AggregateVersion(u64); - -impl AggregateVersion { - pub const INITIAL: Self = Self(1); - - pub fn new(version: u64) -> Result { - if version == 0 { - return Err(FoxhuntError::Validation { - field: "aggregate_version".to_owned(), - reason: "Aggregate version must be greater than 0".to_owned(), - expected: Some("> 0".to_owned()), - actual: Some("0".to_owned()), - }); - } - Ok(Self(version)) - } - - pub fn value(&self) -> u64 { - self.0 - } - pub fn next(&self) -> Self { - Self(self.0 + 1) - } -} - -impl fmt::Display for AggregateVersion { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -/// Amount with decimal precision and validation -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] -pub struct Amount(pub Decimal); - -impl Amount { - pub const ZERO: Self = Self(Decimal::ZERO); - - pub fn new(value: Decimal) -> Self { - Self(value) - } - - pub fn from_f64(value: f64) -> Result { - Ok(Self(Decimal::from_f64_retain(value).ok_or_else(|| { - FoxhuntError::InvalidQuantity { - value: value.to_string(), - reason: "Invalid amount value".to_owned(), - symbol: None, - } - })?)) - } - - pub fn value(&self) -> Decimal { - self.0 - } -} - -/// Asset identifier with validation -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct AssetId(String); - -impl AssetId { - pub fn new>(id: S) -> Result { - let id = id.into(); - if id.is_empty() { - return Err(FoxhuntError::Validation { - field: "asset_id".to_owned(), - reason: "Asset ID cannot be empty".to_owned(), - expected: Some("non-empty string".to_owned()), - actual: Some("empty string".to_owned()), - }); - } - Ok(Self(id)) - } - - pub fn as_str(&self) -> &str { - &self.0 - } - pub fn into_string(self) -> String { - self.0 - } -} - -impl fmt::Display for AssetId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -/// Client identifier with validation -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct ClientId(String); - -impl ClientId { - pub fn new>(id: S) -> Result { - let id = id.into(); - if id.is_empty() { - return Err(FoxhuntError::Validation { - field: "client_id".to_owned(), - reason: "Client ID cannot be empty".to_owned(), - expected: Some("non-empty string".to_owned()), - actual: Some("empty string".to_owned()), - }); - } - Ok(Self(id)) - } - - pub fn as_str(&self) -> &str { - &self.0 - } - pub fn into_string(self) -> String { - self.0 - } -} - -impl fmt::Display for ClientId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -/// Rejection reason with validation -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct RejectionReason(String); - -impl RejectionReason { - pub fn new>(reason: S) -> Result { - let reason = reason.into(); - if reason.is_empty() { - return Err(FoxhuntError::Validation { - field: "rejection_reason".to_owned(), - reason: "Rejection reason cannot be empty".to_owned(), - expected: Some("non-empty string".to_owned()), - actual: Some("empty string".to_owned()), - }); - } - Ok(Self(reason)) - } - - pub fn as_str(&self) -> &str { - &self.0 - } - pub fn into_string(self) -> String { - self.0 - } -} - -impl fmt::Display for RejectionReason { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -/// Tick direction with validation -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct TickDirection(String); - -impl TickDirection { - pub fn new>(direction: S) -> Result { - let direction = direction.into(); - if direction.is_empty() { - return Err(FoxhuntError::Validation { - field: "tick_direction".to_owned(), - reason: "Tick direction cannot be empty".to_owned(), - expected: Some("non-empty string".to_owned()), - actual: Some("empty string".to_owned()), - }); - } - Ok(Self(direction)) - } - - pub fn as_str(&self) -> &str { - &self.0 - } - pub fn into_string(self) -> String { - self.0 - } -} - -impl fmt::Display for TickDirection { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -// TECHNICAL DEBT ELIMINATED - Use DateTime directly instead of DateTime alias - -/// User identifier with validation -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct UserId(String); - -impl UserId { - pub fn new>(id: S) -> Result { - let id = id.into(); - if id.is_empty() { - return Err(FoxhuntError::Validation { - field: "user_id".to_owned(), - reason: "User ID cannot be empty".to_owned(), - expected: Some("non-empty string".to_owned()), - actual: Some("empty string".to_owned()), - }); - } - Ok(Self(id)) - } - - pub fn as_str(&self) -> &str { - &self.0 - } - pub fn into_string(self) -> String { - self.0 - } -} - -impl fmt::Display for UserId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - - -// Quantity struct DELETED - using canonical import from common::types - -// Currency moved to common::types - import from there - -/// Market regime enumeration for position sizing scaling and risk management -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum MarketRegime { - /// Normal market conditions - Normal, - /// Crisis/stress market conditions - Crisis, - /// Trending market (strong directional movement) - Trending, - /// Sideways/ranging market (low volatility) - Sideways, - /// Bull market (sustained upward trend) - Bull, - /// Bear market (sustained downward trend) - Bear, - /// High volatility market conditions - HighVolatility, - /// Low volatility market conditions - LowVolatility, - /// Volatile market conditions (alias for `HighVolatility`) - Volatile, - /// Calm market conditions (alias for `LowVolatility`) - Calm, - /// Unknown/unclassified regime - Unknown, - /// Recovery regime - transitioning from crisis - Recovery, - /// Bubble regime - unsustainable upward movement - Bubble, - /// Correction regime - temporary downward adjustment - Correction, - /// Custom regime with numeric identifier - Custom(usize), -} - -impl Default for MarketRegime { - fn default() -> Self { - Self::Normal - } -} - -impl fmt::Display for MarketRegime { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Normal => write!(f, "Normal"), - Self::Crisis => write!(f, "Crisis"), - Self::Trending => write!(f, "Trending"), - Self::Sideways => write!(f, "Sideways"), - Self::Bull => write!(f, "Bull"), - Self::Bear => write!(f, "Bear"), - Self::HighVolatility => write!(f, "HighVolatility"), - Self::LowVolatility => write!(f, "LowVolatility"), - Self::Volatile => write!(f, "Volatile"), - Self::Calm => write!(f, "Calm"), - Self::Unknown => write!(f, "Unknown"), - Self::Recovery => write!(f, "Recovery"), - Self::Bubble => write!(f, "Bubble"), - Self::Correction => write!(f, "Correction"), - Self::Custom(id) => write!(f, "Custom({id})"), - } - } -} - -impl FromStr for common::prelude::Currency { - type Err = String; - - fn from_str(s: &str) -> Result { - match s.to_uppercase().as_str() { - "USD" => Ok(Self::USD), - "EUR" => Ok(Self::EUR), - "GBP" => Ok(Self::GBP), - "JPY" => Ok(Self::JPY), - "CHF" => Ok(Self::CHF), - "CAD" => Ok(Self::CAD), - "AUD" => Ok(Self::AUD), - "NZD" => Ok(Self::NZD), - "BTC" => Ok(Self::BTC), - "ETH" => Ok(Self::ETH), - _ => Err(format!("Unknown currency: {s}")), - } - } -} - -// Symbol struct DELETED - using canonical import from common::types - -// Order types moved to common crate - import from there - -// TimeInForce moved to common::types - import from there - -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct Position { - pub symbol: Symbol, - pub quantity: common::prelude::Volume, - pub avg_cost: common::prelude::Price, - pub average_price: common::prelude::Price, - pub market_value: common::prelude::Price, - pub unrealized_pnl: Decimal, - pub realized_pnl: Decimal, - pub last_updated: DateTime, -} - -// Portfolio definition moved to later in file for better organization and to avoid duplicates - -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct Money { - pub amount: Decimal, - pub currency: common::prelude::Currency, -} - -impl Money { - #[must_use] - pub const fn new(amount: Decimal, currency: common::prelude::Currency) -> Self { - Self { amount, currency } - } - - #[must_use] - pub fn from_f64(amount: f64, currency: common::prelude::Currency) -> Self { - Self { - amount: Decimal::from_f64(amount).unwrap_or_else(|| { - tracing::warn!("Failed to convert f64 {} to Decimal, using ZERO", amount); - Decimal::ZERO - }), - currency, - } - } -} - -// TIMESTAMP TYPES - Using local FoxhuntError since common creates circular dependency -#[derive( - Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Default, -)] -pub struct HftTimestamp { - nanos: u64, -} - -impl HftTimestamp { - /// Get current timestamp with error handling for financial safety - pub fn now() -> Result { - let nanos = SystemTime::now() - .duration_since(UNIX_EPOCH) - .map_err(|e| FoxhuntError::FinancialSafety { - message: format!("System time before UNIX epoch: {e}"), - context: None, - asset: None, - })? - .as_nanos() as u64; - Ok(Self { nanos }) - } - - /// Get current timestamp or zero if system time is invalid - #[must_use] - pub fn now_or_zero() -> Self { - Self::now().unwrap_or(Self { nanos: 0 }) - } - - /// Get nanoseconds since epoch - #[must_use] - pub const fn nanos(self) -> u64 { - self.nanos - } - - /// Create from nanoseconds since epoch - #[must_use] - pub const fn from_nanos(nanos: u64) -> Self { - Self { nanos } - } - - /// Create from signed nanoseconds (cast to unsigned) - #[must_use] - pub const fn from_nanos_i64(nanos: i64) -> Self { - Self { - nanos: nanos as u64, - } - } - - /// Get nanoseconds since epoch (legacy method for compatibility) - pub const fn as_nanos(&self) -> u64 { - self.nanos - } -} - -/// Generic timestamp for general use cases -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] -pub struct GenericTimestamp { - nanos: u64, -} - -impl GenericTimestamp { - /// Create from nanoseconds since epoch - #[must_use] - pub const fn from_nanos(nanos: u64) -> Self { - Self { nanos } - } - - /// Get nanoseconds since epoch - #[must_use] - pub const fn nanos(&self) -> u64 { - self.nanos - } -} - -// ORDER TYPES - Import canonical types from common crate (circular dependency resolved) -pub use common::types::{OrderSide, OrderStatus, OrderType}; -// Required type aliases -/// High-performance `OrderId` using atomic counter for <50ns generation -/// Replaces slow UUID generation (1ms+) with atomic increment (~5ns) -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] -pub struct OrderId(u64); - -impl Default for OrderId { - fn default() -> Self { - Self::new() - } -} - -impl OrderId { - /// Generate next `OrderId` using atomic counter - <50ns performance - pub fn new() -> Self { - use std::sync::atomic::{AtomicU64, Ordering}; - static COUNTER: AtomicU64 = AtomicU64::new(1); - Self(COUNTER.fetch_add(1, Ordering::Relaxed)) - } - - /// Create `OrderId` from u64 value - #[must_use] - pub const fn from_u64(value: u64) -> Self { - Self(value) - } - - /// Get u64 value - #[must_use] - pub const fn value(&self) -> u64 { - self.0 - } - - /// Get u64 value for performance-critical code (alias for value) - #[must_use] - pub const fn as_u64(&self) -> u64 { - self.0 - } - - /// Get as string for compatibility - #[must_use] - pub fn as_str(&self) -> String { - self.0.to_string() - } -} - -impl fmt::Display for OrderId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -impl From for OrderId { - fn from(value: u64) -> Self { - Self(value) - } -} - -impl From for u64 { - fn from(order_id: OrderId) -> Self { - order_id.0 - } -} - -impl FromStr for OrderId { - type Err = ParseIntError; - - fn from_str(s: &str) -> Result { - s.parse::().map(OrderId) - } -} - -impl From for OrderId { - fn from(s: String) -> Self { - s.parse().unwrap_or_else(|_| Self::new()) - } -} - -impl From<&str> for OrderId { - fn from(s: &str) -> Self { - s.parse().unwrap_or_else(|_| Self::new()) - } -} - -// BrokerError removed - use canonical enum from crate::trading::data_interface::BrokerError via types::prelude::* - -/// Trade execution record -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Trade { - pub trade_id: TradeId, - pub symbol: Symbol, - pub side: common::prelude::Side, - pub quantity: Quantity, - pub price: common::prelude::Price, - pub timestamp: DateTime, -} - -/// Order book level with price and size -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct OrderBookLevel { - pub price: Price, - pub size: Quantity, - pub count: u32, -} - -// Order struct removed - using canonical definition from common::types::Order - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Fill { - pub fill_id: FillId, - pub order_id: OrderId, - pub symbol: Symbol, - pub side: Side, - pub quantity: Quantity, - pub price: Price, - pub timestamp: DateTime, - pub commission: Option, - pub trade_id: Option, -} - -/// Tick type enumeration for market data -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum TickType { - Trade, - Bid, - Ask, - Quote, -} - -/// Market tick data structure - CANONICAL SINGLE SOURCE OF TRUTH -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct MarketTick { - pub symbol: Symbol, - pub price: Price, - pub size: Quantity, - pub timestamp: HftTimestamp, - pub tick_type: TickType, - pub exchange: String, - pub sequence_number: u64, -} - -impl MarketTick { - /// Create a new market tick with current timestamp - pub fn new( - symbol: Symbol, - price: common::prelude::Price, - size: Quantity, - tick_type: TickType, - exchange: String, - sequence_number: u64, - ) -> Result { - Ok(Self { - symbol, - price, - size, - timestamp: HftTimestamp::now()?, - tick_type, - exchange, - sequence_number, - }) - } - - /// Create a new market tick with specified timestamp (for backtesting) - #[must_use] - pub const fn with_timestamp( - symbol: Symbol, - price: Price, - size: Quantity, - timestamp: HftTimestamp, - tick_type: TickType, - exchange: String, - sequence_number: u64, - ) -> Self { - Self { - symbol, - price, - size, - timestamp, - tick_type, - exchange, - sequence_number, - } - } } // ============================================================================ -// ADDITIONAL PRODUCTION TYPES - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum BookAction { - Update, - Delete, - Clear, -} - -impl fmt::Display for BookAction { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Update => write!(f, "UPDATE"), - Self::Delete => write!(f, "DELETE"), - Self::Clear => write!(f, "CLEAR"), - } - } -} - -/// Causation ID for tracking order flow relationships -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct CausationId(Uuid); - -impl CausationId { - /// Generate a new causation ID - #[must_use] - pub fn new() -> Self { - Self(Uuid::new_v4()) - } - - /// Create from existing UUID - #[must_use] - pub const fn from_uuid(uuid: Uuid) -> Self { - Self(uuid) - } - - /// Get the underlying UUID - #[must_use] - pub const fn as_uuid(&self) -> &Uuid { - &self.0 - } - - /// Get as string representation - #[must_use] - pub fn as_str(&self) -> String { - self.0.to_string() - } -} - -impl Default for CausationId { - fn default() -> Self { - Self::new() - } -} - -impl fmt::Display for CausationId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -/// Correlation ID for tracking related operations -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct CorrelationId(Uuid); - -impl CorrelationId { - /// Generate a new correlation ID - #[must_use] - pub fn new() -> Self { - Self(Uuid::new_v4()) - } - - /// Create from existing UUID - #[must_use] - pub const fn from_uuid(uuid: Uuid) -> Self { - Self(uuid) - } - - /// Get the underlying UUID - #[must_use] - pub const fn as_uuid(&self) -> &Uuid { - &self.0 - } - - /// Get as string representation - #[must_use] - pub fn as_str(&self) -> String { - self.0.to_string() - } -} - -impl Default for CorrelationId { - fn default() -> Self { - Self::new() - } -} - -impl fmt::Display for CorrelationId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -/// Deployment configuration settings -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct DeploymentConfig { - /// Environment name - pub environment: DeploymentEnvironment, - /// Service version - pub version: String, - /// Deployment region - pub region: String, - /// Hardware requirements - pub hardware_requirements: HardwareRequirements, - /// Performance profile - pub performance_profile: PerformanceProfile, - /// Monitoring configuration - pub monitoring: MonitoringConfig, - /// Service level objectives - pub slo: ServiceLevelObjectives, -} - -impl DeploymentConfig { - /// Create a new deployment configuration - #[must_use] - pub fn new(environment: DeploymentEnvironment, version: String, region: String) -> Self { - Self { - environment, - version, - region, - hardware_requirements: HardwareRequirements::default(), - performance_profile: PerformanceProfile::default(), - monitoring: MonitoringConfig::default(), - slo: ServiceLevelObjectives::default(), - } - } -} - -/// Deployment environment types -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum DeploymentEnvironment { - /// Development environment - Development, - /// Testing environment - Testing, - /// Staging environment - Staging, - /// Production environment - Production, - /// Disaster recovery environment - DisasterRecovery, -} - -impl fmt::Display for DeploymentEnvironment { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Development => write!(f, "development"), - Self::Testing => write!(f, "testing"), - Self::Staging => write!(f, "staging"), - Self::Production => write!(f, "production"), - Self::DisasterRecovery => write!(f, "disaster-recovery"), - } - } -} - -/// Service endpoint address -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct EndpointAddress { - /// Host name or IP address - pub host: String, - /// Port number - pub port: u16, - /// Protocol scheme (http, https, grpc, etc.) - pub scheme: String, - /// Optional path - pub path: Option, -} - -impl EndpointAddress { - /// Create a new endpoint address - #[must_use] - pub const fn new(host: String, port: u16, scheme: String) -> Self { - Self { - host, - port, - scheme, - path: None, - } - } - - /// Create with path - #[must_use] - pub const fn with_path(host: String, port: u16, scheme: String, path: String) -> Self { - Self { - host, - port, - scheme, - path: Some(path), - } - } - - /// Get full URL string - #[must_use] - pub fn to_url(&self) -> String { - match &self.path { - Some(path) => format!("{}://{}:{}/{}", self.scheme, self.host, self.port, path), - None => format!("{}://{}:{}", self.scheme, self.host, self.port), - } - } -} - -impl fmt::Display for EndpointAddress { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.to_url()) - } -} - -/// Event sequence number for ordering -#[derive( - Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Default, -)] -pub struct EventSequence(u64); - -impl EventSequence { - /// Create a new event sequence - #[must_use] - pub const fn new(seq: u64) -> Self { - Self(seq) - } - - /// Get the sequence number - #[must_use] - pub const fn value(&self) -> u64 { - self.0 - } - - /// Get the next sequence number - #[must_use] - pub const fn next(&self) -> Self { - Self(self.0 + 1) - } -} - -impl fmt::Display for EventSequence { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -/// Failure information for error handling -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct FailureInfo { - /// Type of failure - pub failure_type: FailureType, - /// Error message - pub message: String, - /// DateTime of failure - pub timestamp: DateTime, - /// Additional context - pub context: HashMap, - /// Retry attempt count - pub retry_count: u32, -} - -impl FailureInfo { - /// Create a new failure info - #[must_use] - pub fn new(failure_type: FailureType, message: String) -> Self { - Self { - failure_type, - message, - timestamp: Utc::now(), - context: HashMap::new(), - retry_count: 0, - } - } - - /// Add context information - #[must_use] - pub fn with_context(mut self, key: String, value: String) -> Self { - self.context.insert(key, value); - self - } - - /// Increment retry count - pub fn retry(&mut self) { - self.retry_count += 1; - } -} - -/// Types of failures that can occur -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum FailureType { - /// Network connectivity failure - NetworkFailure, - /// Database operation failure - DatabaseFailure, - /// Authentication failure - AuthenticationFailure, - /// Authorization failure - AuthorizationFailure, - /// Validation failure - ValidationFailure, - /// Business logic failure - BusinessLogicFailure, - /// External service failure - ExternalServiceFailure, - /// System resource failure - ResourceFailure, - /// Configuration error - ConfigurationError, - /// Unknown error - UnknownFailure, -} - -impl fmt::Display for FailureType { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::NetworkFailure => write!(f, "network_failure"), - Self::DatabaseFailure => write!(f, "database_failure"), - Self::AuthenticationFailure => write!(f, "authentication_failure"), - Self::AuthorizationFailure => write!(f, "authorization_failure"), - Self::ValidationFailure => write!(f, "validation_failure"), - Self::BusinessLogicFailure => write!(f, "business_logic_failure"), - Self::ExternalServiceFailure => write!(f, "external_service_failure"), - Self::ResourceFailure => write!(f, "resource_failure"), - Self::ConfigurationError => write!(f, "configuration_error"), - Self::UnknownFailure => write!(f, "unknown_failure"), - } - } -} - -/// Hardware requirements specification -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct HardwareRequirements { - /// Minimum CPU cores - pub min_cpu_cores: u32, - /// Minimum memory in GB - pub min_memory_gb: u32, - /// Minimum disk space in GB - pub min_disk_gb: u32, - /// Required network bandwidth in Mbps - pub min_network_mbps: u32, - /// GPU requirements - pub gpu_required: bool, - /// Special hardware requirements - pub special_requirements: Vec, -} - -impl Default for HardwareRequirements { - fn default() -> Self { - Self { - min_cpu_cores: 4, - min_memory_gb: 8, - min_disk_gb: 100, - min_network_mbps: 1000, - gpu_required: false, - special_requirements: Vec::new(), - } - } -} - -/// Log level enumeration -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] -pub enum LogLevel { - /// Trace level logging - Trace, - /// Debug level logging - Debug, - /// Info level logging - Info, - /// Warning level logging - Warning, - /// Error level logging - Error, - /// Fatal level logging - Fatal, -} - -impl fmt::Display for LogLevel { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Trace => write!(f, "TRACE"), - Self::Debug => write!(f, "DEBUG"), - Self::Info => write!(f, "INFO"), - Self::Warning => write!(f, "WARN"), - Self::Error => write!(f, "ERROR"), - Self::Fatal => write!(f, "FATAL"), - } - } -} - -/// ML Framework enumeration -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum MLFramework { - /// `PyTorch` framework - PyTorch, - /// TensorFlow framework - TensorFlow, - /// Candle (Rust-native) framework - Candle, - /// ONNX runtime - ONNX, - /// Custom implementation - Custom, -} - -impl fmt::Display for MLFramework { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::PyTorch => write!(f, "pytorch"), - Self::TensorFlow => write!(f, "tensorflow"), - Self::Candle => write!(f, "candle"), - Self::ONNX => write!(f, "onnx"), - Self::Custom => write!(f, "custom"), - } - } -} - -/// ML Model metadata -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct MLModelMetadata { - /// Model unique identifier - pub model_id: String, - /// Model name - pub name: String, - /// Model version - pub version: String, - /// Model type - pub model_type: MLModelType, - /// Framework used - pub framework: MLFramework, - /// Training timestamp - pub trained_at: DateTime, - /// Model accuracy metrics - pub accuracy_metrics: HashMap, - /// Input feature names - pub input_features: Vec, - /// Output labels - pub output_labels: Vec, -} - -impl MLModelMetadata { - /// Create new model metadata - #[must_use] - pub fn new( - model_id: String, - name: String, - version: String, - model_type: MLModelType, - framework: MLFramework, - ) -> Self { - Self { - model_id, - name, - version, - model_type, - framework, - trained_at: Utc::now(), - accuracy_metrics: HashMap::new(), - input_features: Vec::new(), - output_labels: Vec::new(), - } - } -} - -/// ML Model types -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum MLModelType { - /// Deep Q-Network for reinforcement learning - DQN, - /// Long Short-Term Memory network - LSTM, - /// Transformer model - Transformer, - /// Temporal Fusion Transformer - TFT, - /// Support Vector Machine - SVM, - /// Random Forest - RandomForest, - /// Linear Regression - LinearRegression, - /// Neural Network (generic) - NeuralNetwork, - /// Custom model type - Custom(String), -} - -impl fmt::Display for MLModelType { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::DQN => write!(f, "dqn"), - Self::LSTM => write!(f, "lstm"), - Self::Transformer => write!(f, "transformer"), - Self::TFT => write!(f, "tft"), - Self::SVM => write!(f, "svm"), - Self::RandomForest => write!(f, "random_forest"), - Self::LinearRegression => write!(f, "linear_regression"), - Self::NeuralNetwork => write!(f, "neural_network"), - Self::Custom(name) => write!(f, "custom_{name}"), - } - } -} - -/// Market data event for real-time processing - renamed for clarity -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct ProcessingMarketDataEvent { - /// Event ID - pub event_id: Uuid, - /// Symbol affected - pub symbol: Symbol, - /// Event type - pub event_type: String, - /// Event timestamp - pub timestamp: HftTimestamp, - /// Event data as key-value pairs - pub data: HashMap, - /// Event sequence number - pub sequence: EventSequence, -} - -impl ProcessingMarketDataEvent { - /// Create a new market data event - pub fn new( - symbol: Symbol, - event_type: String, - data: HashMap, - sequence: EventSequence, - ) -> Result { - Ok(Self { - event_id: Uuid::new_v4(), - symbol, - event_type, - timestamp: HftTimestamp::now()?, - data, - sequence, - }) - } -} - -/// Monitoring configuration -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct MonitoringConfig { - /// Enable metrics collection - pub metrics_enabled: bool, - /// Enable distributed tracing - pub tracing_enabled: bool, - /// Enable health checks - pub health_checks_enabled: bool, - /// Metrics collection interval in seconds - pub metrics_interval_secs: u64, - /// Health check interval in seconds - pub health_check_interval_secs: u64, - /// Alert endpoints - pub alert_endpoints: Vec, -} - -impl Default for MonitoringConfig { - fn default() -> Self { - Self { - metrics_enabled: true, - tracing_enabled: true, - health_checks_enabled: true, - metrics_interval_secs: 30, - health_check_interval_secs: 10, - alert_endpoints: Vec::new(), - } - } -} - -/// Node identifier in distributed systems -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct NodeId(String); - -impl NodeId { - /// Create a new node ID - #[must_use] - pub const fn new(id: String) -> Self { - Self(id) - } - - /// Generate a random node ID - #[must_use] - pub fn generate() -> Self { - Self(Uuid::new_v4().to_string()) - } - - /// Get the node ID as string - #[must_use] - pub fn as_str(&self) -> &str { - &self.0 - } -} - -/// Performance profile configuration -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct PerformanceProfile { - /// Expected latency percentiles in microseconds - pub latency_p99_us: u64, - /// Expected throughput in operations per second - pub throughput_ops_per_sec: u64, - /// Memory usage limits in MB - pub memory_limit_mb: u64, - /// CPU usage target percentage - pub cpu_target_percent: u32, - /// Network bandwidth requirements in Mbps - pub network_bandwidth_mbps: u32, -} - -impl Default for PerformanceProfile { - fn default() -> Self { - Self { - latency_p99_us: 50, // 50 microsecond target for HFT - throughput_ops_per_sec: 100_000, - memory_limit_mb: 1024, - cpu_target_percent: 80, - network_bandwidth_mbps: 1000, - } - } -} - -/// Portfolio structure for position management -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Portfolio { - /// Portfolio ID - pub portfolio_id: String, - /// Account ID - pub account_id: String, - /// Current positions - pub positions: HashMap, - /// Total portfolio value - pub total_value: Money, - /// Available cash - pub available_cash: Money, - /// Portfolio creation timestamp - pub created_at: DateTime, - /// Last updated timestamp - pub updated_at: DateTime, -} - -impl Portfolio { - /// Create a new empty portfolio - #[must_use] - pub fn new(portfolio_id: String, account_id: String, initial_cash: Money) -> Self { - let now = Utc::now(); - Self { - portfolio_id, - account_id, - positions: HashMap::new(), - total_value: initial_cash.clone(), - available_cash: initial_cash, - created_at: now, - updated_at: now, - } - } - - /// Add or update a position - pub fn update_position(&mut self, symbol: Symbol, position: Position) { - self.positions.insert(symbol, position); - self.updated_at = Utc::now(); - } - - /// Get position for a symbol - #[must_use] - pub fn get_position(&self, symbol: &Symbol) -> Option<&Position> { - self.positions.get(symbol) - } -} - -/// Scaling configuration for services -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct ScalingConfig { - /// Minimum number of instances - pub min_instances: u32, - /// Maximum number of instances - pub max_instances: u32, - /// Target CPU utilization percentage for scaling - pub target_cpu_percent: u32, - /// Target memory utilization percentage for scaling - pub target_memory_percent: u32, - /// Scale up threshold - pub scale_up_threshold: f64, - /// Scale down threshold - pub scale_down_threshold: f64, - /// Cooldown period in seconds - pub cooldown_seconds: u64, -} - -impl Default for ScalingConfig { - fn default() -> Self { - Self { - min_instances: 1, - max_instances: 10, - target_cpu_percent: 70, - target_memory_percent: 80, - scale_up_threshold: 0.8, - scale_down_threshold: 0.3, - cooldown_seconds: 300, - } - } -} - -/// Service identifier -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct ServiceId(String); - -impl ServiceId { - /// Create a new service ID - #[must_use] - pub const fn new(id: String) -> Self { - Self(id) - } - - /// Get the service ID as string - #[must_use] - pub fn as_str(&self) -> &str { - &self.0 - } -} - -impl fmt::Display for ServiceId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -/// Service Level Objectives -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct ServiceLevelObjectives { - /// Uptime percentage (e.g., 99.9%) - pub uptime_percent: f64, - /// Maximum response time in milliseconds - pub max_response_time_ms: u64, - /// Error rate percentage threshold - pub error_rate_percent: f64, - /// Throughput requirement in requests per second - pub min_throughput_rps: u64, - /// Data consistency requirements - pub consistency_level: String, -} - -impl Default for ServiceLevelObjectives { - fn default() -> Self { - Self { - uptime_percent: 99.9, - max_response_time_ms: 100, - error_rate_percent: 0.1, - min_throughput_rps: 1000, - consistency_level: "strong".to_owned(), - } - } -} - -/// Slippage model for execution simulation -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct SlippageModel { - /// Model type identifier - pub model_type: String, - /// Base slippage in basis points - pub base_slippage_bps: f64, - /// Volume impact factor - pub volume_impact_factor: f64, - /// Volatility adjustment factor - pub volatility_adjustment: f64, - /// Time impact factor - pub time_impact_factor: f64, -} - -impl Default for SlippageModel { - fn default() -> Self { - Self { - model_type: "linear".to_owned(), - base_slippage_bps: 5.0, - volume_impact_factor: 0.1, - volatility_adjustment: 1.0, - time_impact_factor: 0.05, - } - } -} - -/// Tensor data type enumeration -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum TensorDType { - /// 32-bit floating point - F32, - /// 64-bit floating point - F64, - /// 32-bit signed integer - I32, - /// 64-bit signed integer - I64, - /// Boolean - Bool, - /// 8-bit unsigned integer - U8, -} - -impl fmt::Display for TensorDType { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::F32 => write!(f, "f32"), - Self::F64 => write!(f, "f64"), - Self::I32 => write!(f, "i32"), - Self::I64 => write!(f, "i64"), - Self::Bool => write!(f, "bool"), - Self::U8 => write!(f, "u8"), - } - } -} - -/// Tensor specification -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct TensorSpec { - /// Tensor shape (dimensions) - pub shape: Vec, - /// Data type - pub dtype: TensorDType, - /// Tensor name - pub name: String, - /// Whether tensor requires gradients - pub requires_grad: bool, -} - -impl TensorSpec { - /// Create a new tensor specification - #[must_use] - pub const fn new(shape: Vec, dtype: TensorDType, name: String) -> Self { - Self { - shape, - dtype, - name, - requires_grad: false, - } - } - - /// Set gradient requirement - #[must_use] - pub const fn requires_grad(mut self, requires_grad: bool) -> Self { - self.requires_grad = requires_grad; - self - } - - /// Get total number of elements - #[must_use] - pub fn numel(&self) -> usize { - self.shape.iter().product() - } -} - -/// Token address for blockchain/DeFi operations -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct TokenAddress(String); - -impl TokenAddress { - /// Create a new token address - pub fn new(address: String) -> Result { - if address.trim().is_empty() { - return Err(FoxhuntError::Validation { - field: "address".to_owned(), - reason: "Token address cannot be empty".to_owned(), - expected: Some("non-empty string".to_owned()), - actual: Some("empty string".to_owned()), - }); - } - Ok(Self(address)) - } - - /// Get the address as string - #[must_use] - pub fn as_str(&self) -> &str { - &self.0 - } -} - -impl fmt::Display for TokenAddress { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -/// Token standard enumeration -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum TokenStandard { - /// ERC-20 (Ethereum) - ERC20, - /// ERC-721 (NFT) - ERC721, - /// ERC-1155 (Multi-token) - ERC1155, - /// BEP-20 (Binance Smart Chain) - BEP20, - /// SPL Token (Solana) - SPL, - /// Custom token standard - Custom(String), -} - -impl fmt::Display for TokenStandard { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::ERC20 => write!(f, "ERC-20"), - Self::ERC721 => write!(f, "ERC-721"), - Self::ERC1155 => write!(f, "ERC-1155"), - Self::BEP20 => write!(f, "BEP-20"), - Self::SPL => write!(f, "SPL"), - Self::Custom(name) => write!(f, "Custom-{name}"), - } - } -} - -/// Trading signal for algorithmic trading -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct TradingSignal { - /// Signal ID - pub signal_id: Uuid, - /// Symbol this signal applies to - pub symbol: Symbol, - /// Signal strength (-1.0 to 1.0) - pub strength: f64, - /// Signal direction - pub direction: common::prelude::Side, - /// Confidence level (0.0 to 1.0) - pub confidence: f64, - /// Signal generation timestamp - pub timestamp: HftTimestamp, - /// Signal source/strategy - pub source: String, - /// Additional metadata - pub metadata: HashMap, -} - -impl TradingSignal { - /// Create a new trading signal - pub fn new( - symbol: Symbol, - strength: f64, - direction: common::prelude::Side, - confidence: f64, - source: String, - ) -> Result { - if !(0.0..=1.0).contains(&confidence) { - return Err(FoxhuntError::Validation { - field: "confidence".to_owned(), - reason: "Confidence must be between 0.0 and 1.0".to_owned(), - expected: Some("0.0 <= value <= 1.0".to_owned()), - actual: Some(confidence.to_string()), - }); - } - if !(-1.0..=1.0).contains(&strength) { - return Err(FoxhuntError::Validation { - field: "strength".to_owned(), - reason: "Strength must be between -1.0 and 1.0".to_owned(), - expected: Some("-1.0 <= value <= 1.0".to_owned()), - actual: Some(strength.to_string()), - }); - } - - Ok(Self { - signal_id: Uuid::new_v4(), - symbol, - strength, - direction, - confidence, - timestamp: HftTimestamp::now()?, - source, - metadata: HashMap::new(), - }) - } - - /// Add metadata to the signal - #[must_use] - pub fn with_metadata(mut self, key: String, value: String) -> Self { - self.metadata.insert(key, value); - self - } -} - -/// Training information for ML models -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct TrainingInfo { - /// Training job ID - pub job_id: String, - /// Model being trained - pub model_metadata: MLModelMetadata, - /// Training start time - pub started_at: DateTime, - /// Training end time - pub completed_at: Option>, - /// Training status - pub status: String, - /// Training metrics - pub metrics: HashMap, - /// Training parameters - pub hyperparameters: HashMap, - /// Training dataset information - pub dataset_info: HashMap, -} - -impl TrainingInfo { - /// Create new training info - #[must_use] - pub fn new(job_id: String, model_metadata: MLModelMetadata) -> Self { - Self { - job_id, - model_metadata, - started_at: Utc::now(), - completed_at: None, - status: "started".to_owned(), - metrics: HashMap::new(), - hyperparameters: HashMap::new(), - dataset_info: HashMap::new(), - } - } - - /// Mark training as completed - pub fn complete(&mut self) { - self.completed_at = Some(Utc::now()); - self.status = "completed".to_owned(); - } -} - -/// `VaR` (Value at Risk) prediction -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct VarPrediction { - /// Portfolio ID this prediction applies to - pub portfolio_id: String, - /// `VaR` value (positive number representing potential loss) - pub var_value: Money, - /// Confidence level (e.g., 0.95 for 95% `VaR`) - pub confidence_level: f64, - /// Time horizon in days - pub time_horizon_days: u32, - /// Prediction timestamp - pub timestamp: DateTime, - /// Model used for prediction - pub model_name: String, - /// Breakdown by asset class - pub component_vars: HashMap, -} - -impl VarPrediction { - /// Create a new `VaR` prediction - pub fn new( - portfolio_id: String, - var_value: Money, - confidence_level: f64, - time_horizon_days: u32, - model_name: String, - ) -> Result { - if !(0.0..=1.0).contains(&confidence_level) { - return Err(FoxhuntError::Validation { - field: "confidence_level".to_owned(), - reason: "Confidence level must be between 0.0 and 1.0".to_owned(), - expected: Some("0.0 <= value <= 1.0".to_owned()), - actual: Some(confidence_level.to_string()), - }); - } - if time_horizon_days == 0 { - return Err(FoxhuntError::Validation { - field: "time_horizon".to_owned(), - reason: "Time horizon must be positive".to_owned(), - expected: Some("positive number".to_owned()), - actual: Some(time_horizon_days.to_string()), - }); - } - - Ok(Self { - portfolio_id, - var_value, - confidence_level, - time_horizon_days, - timestamp: Utc::now(), - model_name, - component_vars: HashMap::new(), - }) - } - - /// Add component `VaR` - pub fn add_component_var(&mut self, component: String, var: Money) { - self.component_vars.insert(component, var); - } -} - -/// Market State for ML agents -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct MarketState { - /// Current balance - pub balance: f64, - /// Feature vector for ML models - pub features: Vec, -} - -impl MarketState { - /// Validate the market state - pub fn validate(&self) -> Result<(), String> { - // Check balance is finite - if !self.balance.is_finite() { - return Err("Balance must be finite".to_owned()); - } - - // Check all features are finite - for (i, &feature) in self.features.iter().enumerate() { - if !feature.is_finite() { - return Err(format!("Feature at index {i} is not finite: {feature}")); - } - } - - Ok(()) - } - - /// Get the number of features - #[must_use] - pub fn feature_count(&self) -> usize { - self.features.len() - } - - /// Create a new `MarketState` for ML agents with the specified parameters - /// - /// # Arguments - /// * `_symbol` - Trading symbol (currently not stored in `MarketState`) - /// * `features` - Feature vector for ML models (converted to f64) - /// * `_current_position` - Current position (used for balance calculation) - /// * `cash_balance` - Available cash balance - /// - /// # Returns - /// A new `MarketState` instance suitable for ML agent processing - #[must_use] - pub fn for_agent( - _symbol: Symbol, - features: Vec, - _current_position: f64, - cash_balance: f64, - ) -> Self { - Self { - balance: cash_balance, - features, - } - } -} - -/// Order execution status from broker - CANONICAL SINGLE SOURCE OF TRUTH -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub enum ExecutionStatus { - /// Order is pending submission - Pending, - /// Order submitted to broker - Submitted, - /// Order partially filled - PartiallyFilled { - /// Quantity filled so far - filled_quantity: Quantity, - /// Average fill price - average_price: common::prelude::Price, - }, - /// Order completely filled - Filled { - /// Total quantity filled - filled_quantity: Quantity, - /// Average fill price - average_price: Price, - }, - /// Order cancelled - Cancelled, - /// Order rejected by broker - Rejected { - /// Rejection reason - reason: String, - }, - /// Order expired - Expired, -} - -impl Default for ExecutionStatus { - fn default() -> Self { - Self::Pending - } -} - -impl Order { - /// Create a new order with safe defaults - #[must_use] - pub fn new( - symbol: Symbol, - side: common::prelude::Side, - order_type: OrderType, - quantity: Quantity, - price: Option, - time_in_force: common::prelude::TimeInForce, - ) -> Self { - let order_id = OrderId::new(); - let now = Utc::now(); - - Self { - id: order_id, - order_id, - client_order_id: format!("client_{}", Uuid::new_v4()), - broker_order_id: None, - account_id: env::var("DEFAULT_ACCOUNT_ID") - .unwrap_or_else(|_| "default_account".to_owned()), - symbol, - side, - order_type, - quantity, - price, - stop_price: None, - filled_quantity: Quantity::ZERO, - remaining_quantity: quantity, - average_price: None, - time_in_force, - status: OrderStatus::New, - timestamp: now, - created_at: now, - } - } - - /// Calculate hash of the symbol for performance optimizations - #[must_use] - pub fn symbol_hash(&self) -> u64 { - use std::collections::hash_map::DefaultHasher; - use std::hash::{Hash, Hasher}; - - let mut hasher = DefaultHasher::new(); - self.symbol.as_str().hash(&mut hasher); - hasher.finish() - } - - /// Create a limit order - #[must_use] - pub fn limit(symbol: Symbol, side: common::prelude::Side, quantity: Quantity, price: common::prelude::Price) -> Self { - Self::new( - symbol, - side, - OrderType::Limit, - quantity, - Some(price), - common::prelude::TimeInForce::Day, - ) - } - - /// Create a market order - #[must_use] - pub fn market(symbol: Symbol, side: common::prelude::Side, quantity: Quantity) -> Self { - Self::new( - symbol, - side, - OrderType::Market, - quantity, - None, - common::prelude::TimeInForce::IOC, - ) - } - - /// Check if the order is in an active state - #[must_use] - pub const fn is_active(&self) -> bool { - matches!( - self.status, - OrderStatus::Working - | OrderStatus::PartiallyFilled - | OrderStatus::PendingCancel - | OrderStatus::PendingReplace - ) - } - /// Check if the order is in a final state - #[must_use] - pub const fn is_final(&self) -> bool { - matches!( - self.status, - OrderStatus::Filled | OrderStatus::Cancelled | OrderStatus::Rejected - ) - } -} - -impl Position { - /// Update position timestamp - pub fn update_timestamp(&mut self) { - self.last_updated = Utc::now(); - } -} - -/// Timeframe for market data and trading signals -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum Timeframe { - /// 1 minute - M1, - /// 5 minutes - M5, - /// 15 minutes - M15, - /// 30 minutes - M30, - /// 1 hour - H1, - /// 4 hours - H4, - /// Daily - D1, - /// Weekly - W1, - /// Monthly - MN1, -} - -impl Timeframe { - /// Get the duration in seconds for this timeframe - #[must_use] - pub const fn duration_seconds(&self) -> u64 { - match self { - Self::M1 => 60, - Self::M5 => 300, - Self::M15 => 900, - Self::M30 => 1800, - Self::H1 => 3600, - Self::H4 => 14400, - Self::D1 => 86400, - Self::W1 => 604_800, - Self::MN1 => 2_592_000, // Approximate month - } - } - - /// Get the string representation - #[must_use] - pub const fn as_str(&self) -> &'static str { - match self { - Self::M1 => "1m", - Self::M5 => "5m", - Self::M15 => "15m", - Self::M30 => "30m", - Self::H1 => "1h", - Self::H4 => "4h", - Self::D1 => "1d", - Self::W1 => "1w", - Self::MN1 => "1M", - } - } -} - -impl fmt::Display for Timeframe { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.as_str()) - } -} - -// ============================================================================ -// HIGH-PERFORMANCE TYPES FOR COPY/CLONE OPTIMIZATION +// TYPE ALIASES FOR BACKWARD COMPATIBILITY // ============================================================================ -/// Lightweight Order reference for high-performance contexts requiring Copy trait -/// -/// This struct contains only the essential order data needed for performance-critical -/// operations like `SmallBatchRing` processing, while maintaining Copy semantics. -/// For full order details, use the complete Order struct. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct OrderRef { - /// Order ID (u64 for performance) - pub id: u64, - /// Symbol hash for fast lookups - pub symbol_hash: u64, - /// Order side (Buy/Sell) - pub side: Side, - /// Order type - pub order_type: OrderType, - /// Quantity (fixed-point u64) - pub quantity: u64, - /// Price (fixed-point u64, 0 for market orders) - pub price: u64, - /// DateTime (nanoseconds since epoch) - pub timestamp: u64, -} +// IMPORTANT: These are clean re-exports, not deprecated aliases +// They provide stable API for existing code while using canonical types -impl OrderRef { - /// Create `OrderRef` from a full Order struct - #[must_use] - pub fn from_order(order: &Order) -> Self { - Self { - id: order.id.value(), - symbol_hash: Self::hash_symbol(&order.symbol), - side: order.side, - order_type: order.order_type, - quantity: order.quantity.raw_value(), - price: order.price.map_or(0, |p| p.raw_value()), - timestamp: order.timestamp.timestamp_nanos_opt().unwrap_or(0) as u64, - } - } +/// Trading side alias for backward compatibility +pub use common::types::OrderSide as Side; - /// Create a limit order reference - #[must_use] - pub fn limit(symbol_hash: u64, side: common::prelude::Side, quantity: u64, price: u64) -> Self { - Self { - id: OrderId::new().value(), - symbol_hash, - side, - order_type: OrderType::Limit, - quantity, - price, - timestamp: HftTimestamp::now_or_zero().nanos(), - } - } +/// DateTime alias for convenience +pub use chrono::{DateTime, Utc}; - /// Create a market order reference - #[must_use] - pub fn market(symbol_hash: u64, side: common::prelude::Side, quantity: u64) -> Self { - Self { - id: OrderId::new().value(), - symbol_hash, - side, - order_type: OrderType::Market, - quantity, - price: 0, - timestamp: HftTimestamp::now_or_zero().nanos(), - } - } +/// Decimal type for financial calculations +pub use rust_decimal::Decimal; +pub use rust_decimal::prelude::FromPrimitive; - /// Simple hash function for symbol strings (for performance) - fn hash_symbol(symbol: &Symbol) -> u64 { - use std::collections::hash_map::DefaultHasher; - use std::hash::{Hash, Hasher}; +/// UUID for unique identifiers +pub use uuid::Uuid; - let mut hasher = DefaultHasher::new(); - symbol.as_str().hash(&mut hasher); - hasher.finish() - } +// ============================================================================ +// PRELUDE FOR COMMON IMPORTS +// ============================================================================ - /// Get quantity as Quantity type - #[must_use] - pub const fn get_quantity(&self) -> Quantity { - Quantity::from_raw(self.quantity) - } - - /// Get price as Price type (None for market orders) - #[must_use] - pub const fn get_price(&self) -> Option { - if self.price == 0 { - None - } else { - Some(common::prelude::Price::from_raw(self.price)) - } - } - - /// Check if this is a buy order - #[must_use] - pub fn is_buy(&self) -> bool { - self.side == common::prelude::Side::Buy - } - - /// Check if this is a sell order - #[must_use] - pub fn is_sell(&self) -> bool { - self.side == common::prelude::Side::Sell - } - - /// Check if this is a market order - #[must_use] - pub fn is_market_order(&self) -> bool { - self.order_type == OrderType::Market || self.price == 0 - } - - /// Check if this is a limit order - #[must_use] - pub fn is_limit_order(&self) -> bool { - self.order_type == OrderType::Limit && self.price > 0 - } -} - -impl Default for OrderRef { - fn default() -> Self { - Self { - id: 0, - symbol_hash: 0, - side: common::prelude::Side::Buy, - order_type: OrderType::Market, - quantity: 0, - price: 0, - timestamp: 0, - } - } +/// Common types and traits that are frequently used together +pub mod prelude { + pub use super::{ + Order, OrderId, OrderSide, OrderStatus, OrderType, + Price, Quantity, Volume, Symbol, Currency, TimeInForce, + MarketTick, TickType, MarketRegime, TradingSignal, + TradeId, EventId, AccountId, HftTimestamp, + CommonTypeError, Side, + }; + + pub use chrono::{DateTime, Utc}; + pub use rust_decimal::Decimal; + pub use uuid::Uuid; } #[cfg(test)] @@ -2432,307 +134,31 @@ mod tests { use super::*; #[test] - fn test_price_basic() -> Result<(), Box> { - let price = Price::from_f64(123.45)?; - assert!((price.to_f64() - 123.45).abs() < 1e-6); - Ok(()) + fn test_canonical_imports() { + // Test that canonical types are properly imported + let price = Price::from_f64(100.0).expect("Valid price"); + assert!((price.to_f64() - 100.0).abs() < f64::EPSILON); + + let qty = Quantity::from_f64(50.0).expect("Valid quantity"); + assert!((qty.to_f64() - 50.0).abs() < f64::EPSILON); + + let symbol = Symbol::from("AAPL"); + assert_eq!(symbol.as_str(), "AAPL"); + + let order_id = OrderId::new(); + assert!(order_id.value() > 0); } #[test] - fn test_quantity_basic() -> Result<(), Box> { - let qty = Quantity::from_f64(100.0)?; - assert_eq!(qty.to_f64(), 100.0); - - let symbol = Symbol::from("AAPL".to_string()); - assert_eq!(symbol.to_string(), "AAPL"); - Ok(()) - } -} - -// ============================================================================ -// BROKER TYPES - Moved from deleted common.rs file -// ============================================================================ - -/// Broker types supported by the connector -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum BrokerType { - /// Interactive Brokers TWS/Gateway - InteractiveBrokers, - /// `ICMarkets` cTrader - ICMarkets, -} - -impl fmt::Display for BrokerType { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::InteractiveBrokers => write!(f, "InteractiveBrokers"), - Self::ICMarkets => write!(f, "ICMarkets"), + fn test_compatibility_bridges() { + // Test that compatibility bridges work + let error = TradingError::invalid_price(0.0, "Price cannot be zero"); + match error { + FoxhuntError::InvalidPrice { value, reason, .. } => { + assert_eq!(value, "0"); + assert_eq!(reason, "Price cannot be zero"); + } + _ => panic!("Wrong error type"), } } -} - -/// Order side enumeration (alias for Side for backward compatibility) - - - -/// Trade event structure - canonical version used throughout the system -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct TradeEvent { - /// Symbol - pub symbol: String, - /// Trade price - pub price: Decimal, - /// Trade size - pub size: Decimal, - /// Trade ID - pub trade_id: Option, - /// Exchange - pub exchange: Option, - /// Trade conditions - pub conditions: Vec, - /// DateTime - pub timestamp: DateTime, -} - -/// Broker execution report -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ExecutionReport { - /// Original order ID - pub order_id: OrderId, - /// Broker-specific order ID - pub broker_order_id: String, - /// Execution status - pub status: ExecutionStatus, - /// Symbol - pub symbol: Symbol, - /// Order side (Buy/Sell) - pub side: Side, - /// Original order quantity (for backward compatibility) - pub quantity: Quantity, - /// Executed quantity for this report - pub executed_quantity: Option, - /// Execution price for this report - pub execution_price: Option, - /// Cumulative filled quantity (for backward compatibility) - pub filled_quantity: Quantity, - /// Cumulative filled quantity - pub cumulative_quantity: Quantity, - /// Average fill price - pub average_price: Option, - /// Remaining quantity - pub remaining_quantity: Quantity, - /// Execution timestamp - pub timestamp: DateTime, - /// Execution venue - pub venue: Option, - /// Broker name - pub broker_name: String, - /// Execution ID - pub execution_id: String, - /// Commission charged - pub commission: Option, - /// Additional broker-specific data - pub metadata: HashMap, -} - -/// Connection event for broker status updates -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ConnectionEvent { - /// Provider name - pub provider: String, - /// Connection status - pub status: ConnectionStatus, - /// Optional message - pub message: Option, - /// DateTime - pub timestamp: DateTime, -} - -/// Connection status enumeration -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum ConnectionStatus { - Connected, - Disconnected, - Reconnecting, -} - -/// Error event structure for detailed error information -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ErrorEvent { - /// Provider name - pub provider: String, - /// Error message - pub message: String, - /// DateTime - pub timestamp: DateTime, - /// Error code (optional) - pub code: Option, - /// Whether error is recoverable - pub recoverable: bool, -} - -// ============================================================================ -// IMPLEMENTATION BLOCKS -// ============================================================================ - -impl Default for BrokerType { - fn default() -> Self { - Self::InteractiveBrokers - } -} - -impl Default for ConnectionStatus { - fn default() -> Self { - Self::Disconnected - } -} - -impl fmt::Display for ConnectionStatus { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Connected => write!(f, "Connected"), - Self::Disconnected => write!(f, "Disconnected"), - Self::Reconnecting => write!(f, "Reconnecting"), - } - } -} - -impl ExecutionReport { - /// Create a new execution report - #[must_use] - pub fn new( - order_id: OrderId, - broker_order_id: String, - status: ExecutionStatus, - symbol: Symbol, - side: common::prelude::Side, - quantity: Quantity, - broker_name: String, - execution_id: String, - ) -> Self { - Self { - order_id, - broker_order_id, - status, - symbol, - side, - quantity, - executed_quantity: None, - execution_price: None, - filled_quantity: Quantity::ZERO, - cumulative_quantity: Quantity::ZERO, - average_price: None, - remaining_quantity: quantity, - timestamp: Utc::now(), - venue: None, - broker_name, - execution_id, - commission: None, - metadata: HashMap::new(), - } - } - - /// Update with execution details - #[must_use] - pub fn with_execution(mut self, executed_quantity: Quantity, execution_price: common::prelude::Price) -> Self { - self.executed_quantity = Some(executed_quantity); - self.execution_price = Some(execution_price); - self.cumulative_quantity = self.cumulative_quantity + executed_quantity; - self.filled_quantity = self.cumulative_quantity; - self.remaining_quantity = self.quantity - self.cumulative_quantity; - - // Update average price if we have execution data - if let Some(exec_price) = self.execution_price { - self.average_price = Some(exec_price); - } - - self - } -} - -/// Quote event structure - CANONICAL DEFINITION -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] -pub struct QuoteEvent { - /// Symbol - pub symbol: String, - /// Bid price - pub bid: Option, - /// Ask price - pub ask: Option, - /// Bid size - pub bid_size: Option, - /// Ask size - pub ask_size: Option, - /// Exchange - pub exchange: Option, - /// Timestamp - pub timestamp: DateTime, -} - -impl QuoteEvent { - /// Create a new quote event - #[must_use] - pub fn new(symbol: String, timestamp: DateTime) -> Self { - Self { - symbol, - bid: None, - ask: None, - bid_size: None, - ask_size: None, - exchange: None, - timestamp, - } - } - - /// Get the spread (ask - bid) - #[must_use] - pub fn spread(&self) -> Option { - match (self.bid, self.ask) { - (Some(bid), Some(ask)) => Some(ask - bid), - _ => None, - } - } - - /// Get the mid price - #[must_use] - pub fn mid_price(&self) -> Option { - match (self.bid, self.ask) { - (Some(bid), Some(ask)) => Some((bid + ask) / Decimal::from(2)), - _ => None, - } - } -} - -// TradeEvent removed - no longer available without data crate dependency - -impl ConnectionEvent { - /// Create a new connection event - #[must_use] - pub fn new(provider: String, status: ConnectionStatus) -> Self { - Self { - provider, - status, - message: None, - timestamp: Utc::now(), - } - } -} - -/// Simple execution record for performance benchmarks -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct Execution { - /// Execution ID - pub id: u64, - /// Order ID - pub order_id: u64, - /// Symbol hash for performance - pub symbol_hash: u64, - /// Order side - pub side: Side, - /// Quantity - pub quantity: u64, - /// Price - pub price: u64, - /// DateTime - pub timestamp: u64, -} +} \ No newline at end of file diff --git a/trading_engine/src/types/financial.rs b/trading_engine/src/types/financial.rs index e56a0d6f7..82027d9be 100644 --- a/trading_engine/src/types/financial.rs +++ b/trading_engine/src/types/financial.rs @@ -127,8 +127,8 @@ impl IntegerPrice { /// /// # Example /// ``` - /// use trading_engine::types::financial::IntegerPrice; - /// use trading_engine::types::financial::Decimal; + /// use common::types::financial::IntegerPrice; + /// use common::types::financial::Decimal; /// /// let price = IntegerPrice::from_f64(123.456789); /// let decimal = price.to_decimal(); @@ -275,8 +275,8 @@ impl IntegerQuantity { /// /// # Example /// ``` - /// use trading_engine::types::financial::IntegerQuantity; - /// use trading_engine::types::financial::Decimal; + /// use common::types::financial::IntegerQuantity; + /// use common::types::financial::Decimal; /// /// let quantity = IntegerQuantity::from_f64(123.456789); /// let decimal = quantity.to_decimal();