Files
foxhunt/data/src/providers/common.rs
jgrusewski 144a0a0ea7 🚀 MAJOR COMPILATION FIXES: Resolved Critical API Breaking Changes
**CORRECTED FALSE CLAIMS:**
- CLAUDE.md falsely claimed "🎉 ZERO COMPILATION ERRORS" - Reality: 556+ errors remain
- Documentation stated "100% COMPLETE - PRODUCTION DEPLOYED" - Status: In development

**CRITICAL FIXES IMPLEMENTED:**

🔧 **API Breaking Changes Resolved:**
- Fixed OrderManager::new() signature change (1-arg → 0-arg)
- Fixed PositionManager::new() signature change (1-arg → 0-arg)
- Fixed AccountManager::new() signature change (1-arg → 0-arg)
- Added missing SystemMetrics::new() constructor method

📦 **Config System Exports Fixed:**
- Exported AdaptiveStrategyConfig from config crate lib.rs
- Exported ExecutionAlgorithm, PositionSizingMethod, RegimeDetectionMethod
- Added missing enum variants: ExecutionAlgorithm::POV
- Added missing position sizing methods: FixedFraction, RiskParity, VolatilityTarget, Custom

🧠 **ML Model Infrastructure:**
- Added basic Mamba2SSM implementations (new, predict_single_fast, get_performance_metrics)
- Added TLOBTransformer::new() and TLOBConfig::clone() implementations
- Fixed field name consistency: position_sizing_method vs position_sizing
- Added missing RiskConfig fields: max_portfolio_var, max_drawdown_threshold

**IMPACT:**
- Services can now import required config types without "cannot find type" errors
- Constructor call sites match updated API signatures
- Basic ML model infrastructure compiles with stub implementations
- Config system exports properly aligned across workspace

**BEFORE:** 77+ critical compilation errors blocking workspace build
**AFTER:** 556 remaining errors (mostly implementation stubs and type conversions)

**NEXT STEPS:**
- Complete ML model method implementations
- Fix remaining type conversion issues (Option<f64> operations)
- Add missing trait implementations (Clone, Debug)
- Address missing struct fields and method signatures

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-27 21:30:39 +02:00

617 lines
15 KiB
Rust

//! # Common Data Types for Market Data Providers
//!
//! This module defines common data structures and enums used across different
//! market data providers in the Foxhunt HFT system.
//!
//! ## Architecture
//!
//! The system supports dual-provider architecture:
//! - **Databento**: Market microstructure data (trades, quotes, order books)
//! - **Benzinga Pro**: News, sentiment, analyst ratings, unusual options
//!
//! All events are unified through the `MarketDataEvent` enum from crate::types
//! for consistent processing in the trading pipeline.
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
// Re-export the canonical MarketDataEvent and event types from types module
pub use crate::types::{MarketDataEvent, TradeEvent, QuoteEvent};
// Re-export ErrorCategory for provider modules
pub use common::error::ErrorCategory;
// === PROVIDER-SPECIFIC STRUCTURES ===
// Only types that are NOT duplicated in types.rs should be defined here
/// Order book snapshot from Databento MBO/MBP
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OrderBookSnapshot {
/// Symbol
pub symbol: Symbol,
/// Bid levels (price, size) sorted by price descending
pub bids: Vec<PriceLevel>,
/// Ask levels (price, size) sorted by price ascending
pub asks: Vec<PriceLevel>,
/// Exchange
pub exchange: String,
/// Timestamp of snapshot
pub timestamp: DateTime<Utc>,
/// Sequence number
pub sequence: u64,
}
/// Incremental order book update from Databento
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OrderBookUpdate {
/// Symbol
pub symbol: Symbol,
/// Changes to bid levels
pub bid_changes: Vec<PriceLevelChange>,
/// Changes to ask levels
pub ask_changes: Vec<PriceLevelChange>,
/// Exchange
pub exchange: String,
/// Timestamp of update
pub timestamp: DateTime<Utc>,
/// Sequence number
pub sequence: u64,
}
/// Extended price level for provider-specific data (MBO order count)
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PriceLevelExt {
/// Core price level data
#[serde(flatten)]
pub inner: common::types::PriceLevel,
/// Number of orders at this price (MBO only)
pub order_count: Option<u32>,
}
/// Type alias for backward compatibility during transition
#[deprecated(note = "Use PriceLevelExt for extended functionality or common::types::PriceLevel for core data")]
pub type PriceLevel = PriceLevelExt;
/// Change to a price level
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PriceLevelChange {
/// Price level being modified
pub price: Decimal,
/// New size (0 = remove level)
pub size: Decimal,
/// Type of change
pub change_type: PriceLevelChangeType,
/// Side (bid or ask)
pub side: OrderBookSide,
}
/// Type of price level change
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum PriceLevelChangeType {
/// Add new price level
Add,
/// Update existing price level
Update,
/// Remove price level
Delete,
}
/// Order book side
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum OrderBookSide {
/// Bid side (buy orders)
Bid,
/// Ask side (sell orders)
Ask,
}
/// Bar event structure (alias for AggregateEvent but with different field names)
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BarEvent {
/// Symbol
pub symbol: Symbol,
/// Open price
pub open: Decimal,
/// High price
pub high: Decimal,
/// Low price
pub low: Decimal,
/// Close price
pub close: Decimal,
/// Volume
pub volume: Volume,
/// Timestamp
pub timestamp: DateTime<Utc>,
/// Sequence number
pub sequence: Option<u64>,
}
/// OHLCV aggregate event from Databento
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AggregateEvent {
/// Symbol
pub symbol: Symbol,
/// Open price
pub open: Decimal,
/// High price
pub high: Decimal,
/// Low price
pub low: Decimal,
/// Close price
pub close: Decimal,
/// Volume
pub volume: Volume,
/// Volume weighted average price
pub vwap: Option<Decimal>,
/// Number of trades
pub trade_count: Option<u32>,
/// Start timestamp of the bar
pub start_timestamp: DateTime<Utc>,
/// End timestamp of the bar
pub end_timestamp: DateTime<Utc>,
}
// === BENZINGA EVENT STRUCTURES ===
/// News alert event from Benzinga Pro
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NewsEvent {
/// Unique news story ID
pub story_id: String,
/// Headline text
pub headline: String,
/// Full story text (may be truncated)
pub summary: Option<String>,
/// Symbols mentioned in the story
pub symbols: Vec<Symbol>,
/// News category (earnings, merger, FDA approval, etc.)
pub category: String,
/// News tags for classification
pub tags: Vec<String>,
/// Impact score (-1.0 to 1.0, where -1 = very bearish, 1 = very bullish)
pub impact_score: Option<f64>,
/// Author/source of the news
pub author: Option<String>,
/// News source (Reuters, Bloomberg, etc.)
pub source: String,
/// Publication timestamp
pub published_at: DateTime<Utc>,
/// When we received/processed the news
pub timestamp: DateTime<Utc>,
/// URL to full article
pub url: Option<String>,
}
/// Sentiment analysis event from Benzinga Pro
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SentimentEvent {
/// Symbol
pub symbol: Symbol,
/// Overall sentiment score (-1.0 to 1.0)
pub sentiment_score: f64,
/// Bullish sentiment ratio (0.0 to 1.0)
pub bullish_ratio: f64,
/// Bearish sentiment ratio (0.0 to 1.0)
pub bearish_ratio: f64,
/// Sample size for sentiment calculation
pub sample_size: u32,
/// Time period for sentiment calculation
pub period: SentimentPeriod,
/// Data sources contributing to sentiment
pub sources: Vec<String>,
/// Confidence in the sentiment score (0.0 to 1.0)
pub confidence: Option<f64>,
/// Timestamp of sentiment calculation
pub timestamp: DateTime<Utc>,
}
/// Time period for sentiment analysis
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum SentimentPeriod {
/// Real-time (last few minutes)
RealTime,
/// Last hour
Hourly,
/// Last 24 hours
Daily,
/// Last week
Weekly,
}
/// Analyst rating event from Benzinga Pro
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AnalystRatingEvent {
/// Symbol being rated
pub symbol: Symbol,
/// Analyst or firm name
pub analyst: String,
/// Investment firm
pub firm: String,
/// Rating action (upgrade, downgrade, initiate, maintain)
pub action: RatingAction,
/// Current rating (Buy, Hold, Sell, etc.)
pub current_rating: String,
/// Previous rating (if upgrade/downgrade)
pub previous_rating: Option<String>,
/// Price target
pub price_target: Option<Decimal>,
/// Previous price target
pub previous_price_target: Option<Decimal>,
/// Rating reason/comment
pub comment: Option<String>,
/// When the rating was issued
pub rating_date: DateTime<Utc>,
/// When we received the rating
pub timestamp: DateTime<Utc>,
}
/// Type of rating action
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum RatingAction {
/// New coverage initiated
Initiate,
/// Rating upgraded
Upgrade,
/// Rating downgraded
Downgrade,
/// Rating maintained
Maintain,
/// Coverage discontinued
Discontinue,
}
impl std::fmt::Display for RatingAction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
RatingAction::Initiate => write!(f, "Initiate"),
RatingAction::Upgrade => write!(f, "Upgrade"),
RatingAction::Downgrade => write!(f, "Downgrade"),
RatingAction::Maintain => write!(f, "Maintain"),
RatingAction::Discontinue => write!(f, "Discontinue"),
}
}
}
/// Unusual options activity event from Benzinga Pro
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UnusualOptionsEvent {
/// Underlying symbol
pub symbol: Symbol,
/// Options contract details
pub contract: OptionsContract,
/// Type of unusual activity detected
pub activity_type: UnusualOptionsType,
/// Trade volume
pub volume: u32,
/// Open interest
pub open_interest: Option<u32>,
/// Premium/cost of the trade
pub premium: Option<Decimal>,
/// Implied volatility
pub implied_volatility: Option<f64>,
/// Sentiment inferred from the trade (bullish/bearish)
pub sentiment: OptionsSentiment,
/// Confidence in the signal (0.0 to 1.0)
pub confidence: f64,
/// Description of the unusual activity
pub description: String,
/// When the activity was detected
pub timestamp: DateTime<Utc>,
}
/// Options contract specification
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OptionsContract {
/// Strike price
pub strike: Decimal,
/// Expiration date
pub expiration: chrono::NaiveDate,
/// Option type (call or put)
pub option_type: OptionsType,
/// Contract multiplier (usually 100 for equity options)
pub multiplier: u32,
}
/// Option type
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum OptionsType {
/// Call option
Call,
/// Put option
Put,
}
/// Type of unusual options activity
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum UnusualOptionsType {
/// Large block trade
BlockTrade,
/// Sweep order (aggressive buying/selling)
Sweep,
/// Unusual volume spike
VolumeSpike,
/// High open interest
OpenInterestSpike,
/// Unusual implied volatility
VolatilitySpike,
}
/// Options sentiment
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum OptionsSentiment {
/// Bullish positioning
Bullish,
/// Bearish positioning
Bearish,
/// Neutral/unclear
Neutral,
}
// === SYSTEM EVENT STRUCTURES ===
/// Connection status event
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConnectionStatusEvent {
/// Provider name
pub provider: String,
/// Connection state
pub status: ConnectionState,
/// Optional status message
pub message: Option<String>,
/// Timestamp
pub timestamp: DateTime<Utc>,
}
/// Connection state
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum ConnectionState {
Connected,
Disconnected,
Reconnecting,
Failed,
}
/// Error event
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ErrorEvent {
/// Provider name
pub provider: String,
/// Error message
pub message: String,
/// Error code (provider-specific)
pub code: Option<String>,
/// Error category
pub category: ErrorCategory,
/// Whether the error is recoverable
pub recoverable: bool,
/// Timestamp
pub timestamp: DateTime<Utc>,
}
// ErrorCategory is now imported from common::error
/// Market status event
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MarketStatusEvent {
/// Market identifier
pub market: String,
/// Current status
pub status: MarketState,
/// Next market open time
pub next_open: Option<DateTime<Utc>>,
/// Next market close time
pub next_close: Option<DateTime<Utc>>,
/// Extended hours trading available
pub extended_hours: bool,
/// Timestamp
pub timestamp: DateTime<Utc>,
}
/// Market state
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum MarketState {
/// Market is open for regular trading
Open,
/// Market is closed
Closed,
/// Pre-market trading hours
PreMarket,
/// After-market trading hours
AfterMarket,
/// Market holiday
Holiday,
}
#[cfg(test)]
mod tests {
use super::*;
use chrono::Utc;
use rust_decimal_macros::dec;
#[test]
fn test_order_book_snapshot() {
let snapshot = OrderBookSnapshot {
symbol: Symbol::from("SPY"),
bids: vec![
PriceLevel {
price: dec!(400.49),
size: dec!(100),
order_count: Some(5),
},
PriceLevel {
price: dec!(400.48),
size: dec!(200),
order_count: Some(3),
},
],
asks: vec![
PriceLevel {
price: dec!(400.50),
size: dec!(150),
order_count: Some(2),
},
PriceLevel {
price: dec!(400.51),
size: dec!(300),
order_count: Some(7),
},
],
exchange: "NYSE".to_string(),
timestamp: Utc::now(),
sequence: 1500,
};
assert_eq!(snapshot.symbol, Symbol::from("SPY"));
assert_eq!(snapshot.bids.len(), 2);
assert_eq!(snapshot.asks.len(), 2);
}
#[test]
fn test_news_event() {
let news = NewsEvent {
story_id: "news123".to_string(),
headline: "Company XYZ beats earnings".to_string(),
summary: None,
symbols: vec![Symbol::from("XYZ")],
category: "earnings".to_string(),
tags: vec!["earnings".to_string()],
impact_score: Some(0.75),
author: Some("Analyst Name".to_string()),
source: "Reuters".to_string(),
published_at: Utc::now(),
timestamp: Utc::now(),
url: None,
};
assert_eq!(news.symbols.first(), Some(&Symbol::from("XYZ")));
assert_eq!(news.category, "earnings");
}
#[test]
fn test_sentiment_event() {
let sentiment = SentimentEvent {
symbol: Symbol::from("TSLA"),
sentiment_score: 0.65,
bullish_ratio: 0.75,
bearish_ratio: 0.25,
sample_size: 1000,
period: SentimentPeriod::Hourly,
sources: vec!["twitter".to_string(), "reddit".to_string()],
confidence: Some(0.85),
timestamp: Utc::now(),
};
assert_eq!(sentiment.symbol, Symbol::from("TSLA"));
assert_eq!(sentiment.sentiment_score, 0.65);
}
#[test]
fn test_unusual_options_event() {
let options = UnusualOptionsEvent {
symbol: Symbol::from("AAPL"),
contract: OptionsContract {
strike: dec!(160.00),
expiration: chrono::NaiveDate::from_ymd_opt(2024, 1, 19).unwrap(),
option_type: OptionsType::Call,
multiplier: 100,
},
activity_type: UnusualOptionsType::Sweep,
volume: 5000,
open_interest: Some(10000),
premium: Some(dec!(250000)),
implied_volatility: Some(0.35),
sentiment: OptionsSentiment::Bullish,
confidence: 0.85,
description: "Large call sweep near market".to_string(),
timestamp: Utc::now(),
};
assert_eq!(options.symbol, Symbol::from("AAPL"));
assert_eq!(options.activity_type, UnusualOptionsType::Sweep);
}
}