🚨 ARCHITECTURAL DISASTER: THREE Competing Type Sources Discovered

## Critical Investigation Results

**DISASTER CONFIRMED**: Agents discovered THREE type sources instead of ONE:
1. foxhunt-common-types/ (SHOULD NOT EXIST - still active!)
2. trading_engine/src/types/ (massive duplication)
3. common/src/types.rs (depends on competing crate)

## Evidence of Violations
- foxhunt-common-types still in workspace members (line 86)
- common/Cargo.toml depends on foxhunt-common-types (line 48)
- 48+ duplicate type definitions across OrderSide, OrderStatus, OrderType
- Compilation failures due to competing imports

## Immediate Action Required
- Choose ONE canonical source
- DELETE foxhunt-common-types completely
- Consolidate ALL types to single source
- Fix THREE-WAY import chaos

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
jgrusewski
2025-09-26 15:33:34 +02:00
parent f58d14ccc3
commit ea9d8f2c88
87 changed files with 2192 additions and 817 deletions

View File

@@ -42,12 +42,8 @@ pub struct HFTOrder {
pub strategy_id: u16,
}
#[repr(u8)]
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum OrderSide {
Buy = 0,
Sell = 1,
}
// OrderSide now imported from canonical source
use trading_engine::types::prelude::OrderSide;
/// High-performance market data tick
#[derive(Debug, Clone, Copy)]

View File

@@ -39,18 +39,10 @@ pub struct MockOrder {
}
#[derive(Debug, Clone, PartialEq)]
pub enum OrderSide {
Buy,
Sell,
}
// OrderSide and OrderType now imported from canonical source
use trading_engine::types::prelude::{OrderSide, OrderType};
#[derive(Debug, Clone, PartialEq)]
pub enum OrderType {
Market,
Limit,
Stop,
StopLimit,
}
// OrderType now imported from canonical source above
/// Mock Risk Metrics for testing
#[derive(Debug, Clone)]

View File

@@ -15,19 +15,19 @@ mod tests {
// Test Types - Simplified versions for property testing
#[derive(Debug, Clone, Copy, PartialEq)]
struct Price(u64); // Fixed-point representation, 8 decimals
struct TestPrice(u64); // Fixed-point representation, 8 decimals
#[derive(Debug, Clone, Copy, PartialEq)]
struct Quantity(u64);
#[derive(Debug, Clone, Copy, PartialEq)]
struct Volume(u64);
struct TestVolume(u64);
#[derive(Debug, Clone, Copy, PartialEq)]
struct Amount(i64);
// Implementations
impl Price {
impl TestPrice {
pub fn new(value: f64) -> Self {
// Convert to fixed-point representation matching production types
let decimal_value = Decimal::from_f64(value).unwrap_or(Decimal::ZERO);
@@ -40,22 +40,22 @@ impl Price {
}
pub fn from_f64(value: f64) -> Self {
Price::new(value.max(0.0)) // Clamp to non-negative
TestTestPrice::new(value.max(0.0)) // Clamp to non-negative
}
pub fn to_f64(&self) -> f64 {
self.value()
}
pub fn add(&self, other: &Price) -> Price {
Price::from_f64(self.value().expect("Valid price") + other.value())
pub fn add(&self, other: &TestPrice) -> TestPrice {
TestTestPrice::from_f64(self.value() + other.value())
}
pub fn multiply(&self, factor: f64) -> Price {
Price::from_f64(self.value().expect("Valid price") * factor)
pub fn multiply(&self, factor: f64) -> TestPrice {
TestTestPrice::from_f64(self.value() * factor)
}
pub fn percentage_change(&self, old_price: &Price) -> f64 {
pub fn percentage_change(&self, old_price: &TestPrice) -> f64 {
let old_val = old_price.value();
if old_val == 0.0 {
0.0
@@ -88,11 +88,11 @@ impl Quantity {
}
}
impl Volume {
impl TestVolume {
pub fn new(value: u64) -> Self {
Volume(value)
TestVolume(value)
}
pub fn to_u64(&self) -> u64 {
self.0
}
@@ -104,13 +104,13 @@ pub struct Position {
pub symbol: String,
pub side: Side,
pub quantity: Quantity,
pub average_price: Price,
pub current_price: Price,
pub average_price: TestPrice,
pub current_price: TestPrice,
pub unrealized_pnl: Amount,
}
impl Position {
pub fn new(symbol: String, side: Side, quantity: Quantity, average_price: Price) -> Self {
pub fn new(symbol: String, side: Side, quantity: Quantity, average_price: TestPrice) -> Self {
Self {
symbol,
side,
@@ -121,7 +121,7 @@ impl Position {
}
}
pub fn calculate_unrealized_pnl(&mut self, current_price: &Price) -> f64 {
pub fn calculate_unrealized_pnl(&mut self, current_price: &TestPrice) -> f64 {
self.current_price = current_price.clone();
let price_diff = match self.side {
@@ -189,8 +189,8 @@ proptest! {
a in valid_price_strategy(),
b in valid_price_strategy()
) {
let price_a = Price::from_f64(a).expect("Valid price");
let price_b = Price::from_f64(b).expect("Valid price");
let price_a = TestPrice::from_f64(a).expect("Valid price");
let price_b = TestPrice::from_f64(b).expect("Valid price");
let sum_ab = price_a.add(&price_b);
let sum_ba = price_b.add(&price_a);
@@ -205,9 +205,9 @@ proptest! {
b in valid_price_strategy(),
c in valid_price_strategy()
) {
let price_a = Price::from_f64(a).expect("Valid price");
let price_b = Price::from_f64(b).expect("Valid price");
let price_c = Price::from_f64(c).expect("Valid price");
let price_a = TestPrice::from_f64(a).expect("Valid price");
let price_b = TestPrice::from_f64(b).expect("Valid price");
let price_c = TestPrice::from_f64(c).expect("Valid price");
let left = price_a.add(&price_b).add(&price_c);
let right = price_a.add(&price_b.add(&price_c));
@@ -223,8 +223,8 @@ proptest! {
a in any::<f64>(),
b in any::<f64>()
) {
let price_a = Price::from_f64(a).expect("Valid price");
let price_b = Price::from_f64(b).expect("Valid price");
let price_a = TestPrice::from_f64(a).expect("Valid price");
let price_b = TestPrice::from_f64(b).expect("Valid price");
prop_assert!(price_a.to_f64() >= 0.0);
prop_assert!(price_b.to_f64() >= 0.0);
@@ -242,7 +242,7 @@ proptest! {
price in valid_price_strategy(),
factor in -1000.0f64..1000.0f64
) {
let p = Price::from_f64(price).expect("Valid price");
let p = TestPrice::from_f64(price).expect("Valid price");
let result = p.multiply(factor);
// Result should always be non-negative due to clamping
@@ -271,8 +271,8 @@ proptest! {
old_price in valid_price_strategy(),
new_price in valid_price_strategy()
) {
let old_p = Price::from_f64(old_price).expect("Valid price");
let new_p = Price::from_f64(new_price).expect("Valid price");
let old_p = TestPrice::from_f64(old_price).expect("Valid price");
let new_p = TestPrice::from_f64(new_price).expect("Valid price");
let pct_change = new_p.percentage_change(&old_p);
@@ -379,10 +379,10 @@ proptest! {
"EURUSD".to_string(),
Side::Buy,
Quantity::new(quantity),
Price::from_f64(entry_price).expect("Valid price")
TestPrice::from_f64(entry_price).expect("Valid price")
);
let pnl = position.calculate_unrealized_pnl(&Price::from_f64(current_price).expect("Valid price"));
let pnl = position.calculate_unrealized_pnl(&TestPrice::from_f64(current_price).expect("Valid price"));
// P&L should equal (current_price - entry_price) * quantity
let expected_pnl = (current_price - entry_price) * quantity as f64;
@@ -416,10 +416,10 @@ proptest! {
"EURUSD".to_string(),
Side::Sell,
Quantity::new(quantity),
Price::from_f64(entry_price).expect("Valid price")
TestPrice::from_f64(entry_price).expect("Valid price")
);
let pnl = position.calculate_unrealized_pnl(&Price::from_f64(current_price).expect("Valid price"));
let pnl = position.calculate_unrealized_pnl(&TestPrice::from_f64(current_price).expect("Valid price"));
// P&L should equal (entry_price - current_price) * quantity
let expected_pnl = (entry_price - current_price) * quantity as f64;
@@ -452,7 +452,7 @@ proptest! {
"EURUSD".to_string(),
Side::Buy,
Quantity::new(quantity),
Price::from_f64(price).expect("Valid price")
TestPrice::from_f64(price).expect("Valid price")
);
let notional = position.notional_value();
@@ -482,10 +482,10 @@ proptest! {
"EURUSD".to_string(),
Side::Buy,
Quantity::new(quantity),
Price::from_f64(entry_price).expect("Valid price")
TestPrice::from_f64(entry_price).expect("Valid price")
);
let pnl = position.calculate_unrealized_pnl(&Price::from_f64(current_price).expect("Valid price"));
let pnl = position.calculate_unrealized_pnl(&TestPrice::from_f64(current_price).expect("Valid price"));
// P&L calculation should not overflow to infinity
prop_assert!(pnl.is_finite());
@@ -514,7 +514,7 @@ proptest! {
fn extreme_price_handling(
price in extreme_price_strategy()
) {
let p = Price::from_f64(price).expect("Valid price");
let p = TestPrice::from_f64(price).expect("Valid price");
// Should handle extreme values gracefully
prop_assert!(p.to_f64().is_finite());
@@ -524,7 +524,7 @@ proptest! {
let doubled = p.multiply(2.0);
prop_assert!(doubled.to_f64().is_finite());
let added = p.add(&Price::from_f64(1.0).expect("Valid price"));
let added = p.add(&TestPrice::from_f64(1.0).expect("Valid price"));
prop_assert!(added.to_f64().is_finite());
}
@@ -537,8 +537,8 @@ proptest! {
let pip_value = 0.0001; // Standard pip for EUR/USD
let price_movement = pip_count as f64 * pip_value;
let entry_price = Price::from_f64(base_price).expect("Valid price");
let exit_price = Price::from_f64(base_price + price_movement).expect("Valid price");
let entry_price = TestPrice::from_f64(base_price).expect("Valid price");
let exit_price = TestPrice::from_f64(base_price + price_movement).expect("Valid price");
// Calculate P&L for a standard lot (100,000 units)
let mut position = Position::new(
@@ -570,7 +570,7 @@ proptest! {
Just(f64::MIN_POSITIVE)
]
) {
let price = Price::from_f64(special_value).expect("Valid price");
let price = TestPrice::from_f64(special_value).expect("Valid price");
// Should convert special values to safe values
prop_assert!(price.to_f64().is_finite());
@@ -588,11 +588,11 @@ proptest! {
prices in prop::collection::vec(valid_price_strategy(), 1..100)
) {
// Sum all prices
let mut total = Price::from_f64(0.0).expect("Valid price");
let mut total = TestPrice::from_f64(0.0).expect("Valid price");
let mut expected_sum = 0.0;
for price_val in &prices {
let price = Price::from_f64(*price_val).expect("Valid price");
let price = TestPrice::from_f64(*price_val).expect("Valid price");
total = total.add(&price);
expected_sum += price_val;
}
@@ -617,7 +617,7 @@ proptest! {
#[tokio::test]
async fn test_realistic_trading_scenario_precision() {
// Test a realistic EUR/USD trading scenario
let entry_price = Price::from_f64(1.1000).expect("Valid price");
let entry_price = TestPrice::from_f64(1.1000).expect("Valid price");
let position_size = Quantity::new(100_000); // Standard lot
let mut position = Position::new(
@@ -631,7 +631,7 @@ async fn test_realistic_trading_scenario_precision() {
let pip_movements = vec![1, 5, 10, 20];
for pips in pip_movements {
let current_price = Price::from_f64(1.1000 + pips as f64 * 0.0001).expect("Valid price");
let current_price = TestPrice::from_f64(1.1000 + pips as f64 * 0.0001).expect("Valid price");
let pnl = position.calculate_unrealized_pnl(&current_price);
// Each pip should be worth approximately $10 for EUR/USD standard lot
@@ -650,8 +650,8 @@ async fn test_portfolio_level_precision() {
let mut total_pnl = 0.0;
for (i, symbol) in symbols.iter().enumerate() {
let entry_price = Price::from_f64(1.0 + i as f64 * 0.1).expect("Valid price");
let current_price = Price::from_f64(1.0 + i as f64 * 0.1 + 0.01).expect("Valid price"); // 100 pip profit each
let entry_price = TestPrice::from_f64(1.0 + i as f64 * 0.1).expect("Valid price");
let current_price = TestPrice::from_f64(1.0 + i as f64 * 0.1 + 0.01).expect("Valid price"); // 100 pip profit each
let quantity = Quantity::new(10_000 * (i as i64 + 1)); // Different sizes
let mut position = Position::new(
@@ -679,8 +679,8 @@ async fn test_portfolio_level_precision() {
#[test]
fn test_stress_financial_calculations() {
// Stress test with many small operations
let base_price = Price::from_f64(1.0).expect("Valid price");
let increment = Price::from_f64(0.00001).expect("Valid price"); // Half pip
let base_price = TestPrice::from_f64(1.0).expect("Valid price");
let increment = TestPrice::from_f64(0.00001).expect("Valid price"); // Half pip
let mut accumulated = base_price.clone();

View File

@@ -19,6 +19,7 @@ use trading_engine::features::unified_extractor::{
AnalystRating, UnusualOptionsActivity,
};
use trading_engine::types::prelude::*;
use data::types::QuoteEvent;
// Test fixtures and mock data generators
@@ -90,14 +91,15 @@ fn create_test_databento_data() -> DatabentoBuData {
},
],
quotes: vec![
crate::types::basic::QuoteEvent {
QuoteEvent {
timestamp: Utc::now(),
symbol: "AAPL".to_string(),
bid: Price::from_f64(99.95).unwrap(),
ask: Price::from_f64(100.05).unwrap(),
bid_size: Volume::from_u64(1000).unwrap(),
ask_size: Volume::from_u64(1500).unwrap(),
},
bid: Some(Decimal::from_f64(99.95).unwrap()),
ask: Some(Decimal::from_f64(100.05).unwrap()),
bid_size: Some(Decimal::from_u64(1000).unwrap()),
ask_size: Some(Decimal::from_u64(1500).unwrap()),
exchange: Some("NASDAQ".to_string()),
},
],
timestamp: Utc::now(),
}

View File

@@ -511,10 +511,8 @@ struct TestOrder {
}
#[derive(Debug)]
enum OrderSide {
Buy,
Sell,
}
// OrderSide now imported from canonical source
use trading_engine::types::prelude::OrderSide;
#[derive(Debug)]
struct TestOrderProcessor;

View File

@@ -457,10 +457,8 @@ struct IcebergOrder {
}
#[derive(Debug, Clone)]
enum OrderSide {
Buy,
Sell,
}
// OrderSide now imported from canonical source
use trading_engine::types::prelude::OrderSide;
#[derive(Debug)]
struct OrderSlice {