Files
foxhunt/crates/data/src/providers/common.rs
jgrusewski 9c3d741a08 refactor: restructure repo — crates/, bin/, testing/ layout
Move 17 library crates into crates/, CLI binary into bin/fxt,
consolidate 10 test crates into testing/, split config crate
from deployment config files.

Root directory reduced from 38+ to ~17 directories.
All Cargo.toml paths and build.rs proto refs updated.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 11:56:00 +01:00

1235 lines
44 KiB
Rust

//! # Common Provider Types
//!
//! Shared data structures and enumerations used across different market data providers
//! in the Foxhunt HFT trading system. This module provides:
//!
//! - **News Events**: Breaking news, earnings, analyst ratings
//! - **Sentiment Analysis**: Market sentiment scores and trends
//! - **Options Activity**: Unusual options flow and block trades
//! - **Error Classification**: Standardized error categorization
//!
//! ## Provider Integration
//!
//! These types serve as a bridge between provider-specific APIs and the unified
//! `ExtendedMarketDataEvent` system, allowing consistent handling of alternative
//! data sources alongside traditional market data.
//!
//! ## Usage
//!
//! ```rust
//! use data::providers::common::{NewsEvent, SentimentEvent, AnalystRatingEvent};
//! use data::types::ExtendedMarketDataEvent;
//!
//! // Convert provider-specific events to extended events
//! let news_event = ExtendedMarketDataEvent::NewsAlert(news_event);
//! let sentiment_event = ExtendedMarketDataEvent::SentimentUpdate(sentiment_event);
//! ```
use ::common::{Price, Quantity, Symbol};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
/// Error category classification for provider-specific errors.
///
/// Standardizes error types across different data providers to enable
/// consistent error handling and recovery strategies in the trading system.
/// Each category has specific implications for reconnection logic and alerting.
///
/// # Error Recovery Strategies
///
/// - **Connection**: Implement exponential backoff reconnection
/// - **Authentication**: Refresh tokens or credentials, alert operations
/// - **RateLimit**: Implement adaptive throttling and request queuing
/// - **DataFormat**: Log for debugging, potentially skip malformed messages
/// - **Internal**: Restart provider connection, escalate to monitoring
/// - **Unknown**: Treat as transient, implement general retry logic
///
/// # Examples
///
/// ```rust
/// use data::providers::common::ProviderErrorCategory;
///
/// match error_category {
/// ProviderErrorCategory::RateLimit => {
/// // Implement exponential backoff
/// tokio::time::sleep(Duration::from_millis(1000)).await;
/// },
/// ProviderErrorCategory::Authentication => {
/// // Refresh credentials and reconnect
/// provider.refresh_auth().await?;
/// },
/// _ => {
/// // General error handling
/// }
/// }
/// ```
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ProviderErrorCategory {
/// Network connectivity issues, WebSocket disconnections
///
/// Indicates problems with the underlying network connection to the
/// data provider. Recovery strategy should include exponential backoff
/// reconnection attempts and connection health monitoring.
Connection,
/// API key invalid, token expired, permission denied
///
/// Authentication or authorization failures that require credential
/// refresh or manual intervention. These errors should trigger
/// immediate alerts to operations teams.
Authentication,
/// API rate limits exceeded, quota exhausted
///
/// Provider is throttling requests due to rate limit violations.
/// Recovery should implement adaptive request throttling and
/// request queuing with appropriate delays.
RateLimit,
/// Malformed data, parsing errors, schema mismatches
///
/// Indicates problems with data format or structure that prevent
/// proper parsing. These should be logged for debugging but may
/// not require immediate reconnection.
DataFormat,
/// Provider-side internal errors, service unavailable
///
/// Errors originating from the data provider's infrastructure.
/// Recovery strategy should include service status checks and
/// potential failover to alternative providers.
Internal,
/// Unclassified or unexpected errors
///
/// Default category for errors that don't fit other classifications.
/// Should be treated conservatively with general retry logic.
Unknown,
}
/// Classification of news event types for filtering and priority routing.
///
/// Categorizes news events by their nature and potential market impact,
/// allowing trading algorithms to apply different processing logic based
/// on event type. Each type has different latency requirements and
/// impact characteristics.
///
/// # Market Impact
///
/// - **Earnings**: High impact, quarterly/annual reporting cycles
/// - **Rating**: Medium to high impact, analyst opinion changes
/// - **Economic**: Market-wide impact, affects multiple sectors
/// - **CorporateAction**: Company-specific, varies by action type
/// - **News**: General news, impact depends on content
///
/// # Usage in Trading
///
/// ```rust
/// use data::providers::common::NewsEventType;
///
/// match event.event_type {
/// NewsEventType::Earnings => {
/// // High priority processing for earnings events
/// priority_queue.push_high(event);
/// },
/// NewsEventType::Rating => {
/// // Analyst rating changes - medium priority
/// priority_queue.push_medium(event);
/// },
/// _ => {
/// // Standard processing
/// standard_queue.push(event);
/// }
/// }
/// ```
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum NewsEventType {
/// General news articles and press releases
///
/// Broad category covering company announcements, industry news,
/// regulatory updates, and other general market information.
/// Impact varies widely based on content.
News,
/// Earnings announcements, financial results, guidance updates
///
/// Quarterly and annual earnings reports, revenue guidance,
/// earnings per share announcements. These events typically
/// have high market impact and require immediate processing.
Earnings,
/// Analyst upgrades, downgrades, price target changes
///
/// Research analyst opinion changes including rating upgrades/downgrades,
/// price target adjustments, and initiation of coverage. Can significantly
/// impact stock price in the short term.
Rating,
/// Economic indicators, Federal Reserve announcements, policy changes
///
/// Macroeconomic events that affect broader market conditions,
/// including GDP data, inflation reports, interest rate decisions,
/// and monetary policy announcements.
Economic,
/// Mergers, acquisitions, dividends, stock splits, spin-offs
///
/// Corporate structure changes that directly affect stock mechanics
/// and ownership. Includes M&A announcements, dividend declarations,
/// stock splits, and other corporate reorganizations.
CorporateAction,
}
/// News event data structure containing breaking news and market-moving information.
///
/// Represents real-time news events from providers like Benzinga that can impact
/// trading decisions. Contains both the news content and metadata for automated
/// processing and sentiment analysis.
///
/// # Field Categories
///
/// - **Identification**: `story_id`, `source`, `url`
/// - **Content**: `headline`, `content`, `summary`
/// - **Classification**: `category`, `tags`, `event_type`
/// - **Impact Assessment**: `impact_score`, `importance`, `sentiment_score`
/// - **Timing**: `timestamp`, `published_at`
/// - **Symbols**: `symbol`, `symbols` (affected securities)
///
/// # Processing Pipeline
///
/// ```text
/// News Event → Sentiment Analysis → Symbol Extraction → Impact Scoring → Trading Signal
/// ```
///
/// # Examples
///
/// ```rust
/// use data::providers::common::{NewsEvent, NewsEventType};
/// use common::Symbol;
///
/// let news = NewsEvent {
/// symbol: Some(Symbol::from("AAPL")),
/// symbols: vec![Symbol::from("AAPL")],
/// story_id: "BZ123456".to_string(),
/// headline: "Apple Reports Strong Q3 Earnings".to_string(),
/// event_type: NewsEventType::Earnings,
/// impact_score: Some(0.85), // High impact
/// // ... other fields
/// };
///
/// // Check if this is a high-impact earnings event
/// if news.event_type == NewsEventType::Earnings &&
/// news.impact_score.unwrap_or(0.0) > 0.8 {
/// // Process as priority event
/// }
/// ```
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NewsEvent {
/// Primary symbol affected by this news (if applicable)
///
/// The main security ticker that this news event relates to.
/// May be `None` for market-wide or sector-wide news.
pub symbol: Option<Symbol>,
/// All symbols mentioned or affected by this news
///
/// Complete list of securities that may be impacted by this news event.
/// Includes the primary symbol plus any additional mentioned tickers.
pub symbols: Vec<Symbol>,
/// Unique identifier for this news story
///
/// Provider-specific ID used for deduplication and reference.
/// Format varies by provider (e.g., Benzinga: "BZ123456").
pub story_id: String,
/// News headline or title
///
/// Brief summary of the news event, typically optimized for
/// algorithmic parsing and sentiment analysis.
pub headline: String,
/// Full news article content
///
/// Complete text of the news article. May be truncated for
/// performance reasons in high-frequency scenarios.
pub content: String,
/// Executive summary or abstract
///
/// Condensed version of the news content highlighting key points.
/// Useful for quick algorithmic processing without parsing full content.
pub summary: String,
/// News category classification
///
/// Provider-specific category string (e.g., "Earnings", "M&A", "Analyst").
/// Used for filtering and routing to appropriate processing pipelines.
pub category: String,
/// Associated tags and keywords
///
/// List of relevant tags that help categorize and filter the news.
/// Examples: ["earnings", "beat", "revenue", "guidance"].
pub tags: Vec<String>,
/// Algorithmic impact score (0.0 to 1.0)
///
/// Machine-generated assessment of potential market impact.
/// Higher scores indicate greater expected price movement.
/// `None` if impact scoring is not available.
pub impact_score: Option<f64>,
/// News importance rating (0.0 to 1.0)
///
/// Editorial or algorithmic assessment of news significance.
/// Different from impact_score - measures newsworthiness rather
/// than expected price impact.
pub importance: f64,
/// Article author or reporter
///
/// Journalist or analyst who authored the news piece.
/// Can be used for author-based filtering or credibility weighting.
pub author: String,
/// Event processing timestamp (when received by our system)
///
/// When this news event was received and processed by the
/// Foxhunt system. Used for latency analysis and sequencing.
pub timestamp: DateTime<Utc>,
/// Original publication timestamp
///
/// When the news was originally published by the news source.
/// May differ from `timestamp` due to processing delays.
pub published_at: DateTime<Utc>,
/// News source identifier
///
/// Name of the news organization or wire service that published
/// this story (e.g., "Reuters", "PR Newswire", "Benzinga").
pub source: String,
/// Link to the full article
///
/// URL where the complete news article can be accessed.
/// Useful for manual review and audit trails.
pub url: String,
/// Overall sentiment score (-1.0 to 1.0)
///
/// Algorithmic sentiment analysis of the news content.
/// Positive values indicate bullish sentiment, negative values
/// indicate bearish sentiment. `None` if sentiment analysis unavailable.
pub sentiment_score: Option<f64>,
/// Legacy sentiment field (deprecated)
///
/// Maintained for backwards compatibility. New code should use
/// `sentiment_score` instead. May be removed in future versions.
#[deprecated(since = "1.0.0", note = "Use sentiment_score instead")]
pub sentiment: Option<f64>,
/// Classification of the news event type
///
/// Structured categorization for automated processing and filtering.
/// Determines processing priority and routing logic.
pub event_type: NewsEventType,
}
/// Market sentiment analysis event containing aggregated sentiment metrics.
///
/// Represents sentiment analysis data from providers like Benzinga that aggregate
/// sentiment from various sources including news articles, social media, and
/// analyst reports. Used for incorporating market mood into trading decisions.
///
/// # Sentiment Interpretation
///
/// - **sentiment_score > 0.6**: Strong bullish sentiment
/// - **sentiment_score 0.4-0.6**: Moderate bullish sentiment
/// - **sentiment_score 0.4-0.6**: Neutral sentiment
/// - **sentiment_score 0.2-0.4**: Moderate bearish sentiment
/// - **sentiment_score < 0.2**: Strong bearish sentiment
///
/// # Confidence Assessment
///
/// The `confidence` field indicates the reliability of the sentiment analysis:
/// - **confidence > 0.8**: High confidence, large sample size
/// - **confidence 0.5-0.8**: Moderate confidence
/// - **confidence < 0.5**: Low confidence, small sample or conflicting signals
///
/// # Usage in Trading
///
/// ```rust
/// use data::providers::common::SentimentEvent;
///
/// fn assess_sentiment_signal(sentiment: &SentimentEvent) -> Option<f64> {
/// if sentiment.confidence > 0.7 && sentiment.sample_size > 100 {
/// // High confidence signal
/// Some(sentiment.sentiment_score * sentiment.confidence)
/// } else {
/// // Low confidence, ignore signal
/// None
/// }
/// }
/// ```
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SentimentEvent {
/// Symbol this sentiment analysis applies to
///
/// The specific security ticker for which sentiment has been analyzed.
pub symbol: Symbol,
/// Overall sentiment score (0.0 = very bearish, 1.0 = very bullish)
///
/// Normalized sentiment metric where:
/// - 0.0-0.3: Bearish sentiment
/// - 0.3-0.7: Neutral sentiment
/// - 0.7-1.0: Bullish sentiment
pub sentiment_score: f64,
/// Ratio of bullish mentions (0.0 to 1.0)
///
/// Percentage of analyzed content that expressed bullish sentiment.
/// `bullish_ratio + bearish_ratio` may not equal 1.0 due to neutral content.
pub bullish_ratio: f64,
/// Ratio of bearish mentions (0.0 to 1.0)
///
/// Percentage of analyzed content that expressed bearish sentiment.
/// Complement to `bullish_ratio` but may not sum to 1.0.
pub bearish_ratio: f64,
/// Number of data points used in sentiment calculation
///
/// Size of the sample used for sentiment analysis. Larger sample
/// sizes generally indicate more reliable sentiment scores.
pub sample_size: u32,
/// Data sources used for sentiment analysis
///
/// List of sources that contributed to this sentiment calculation
/// (e.g., ["twitter", "reddit", "news", "analyst_reports"]).
pub sources: Vec<String>,
/// Confidence level in the sentiment analysis (0.0 to 1.0)
///
/// Statistical confidence in the sentiment score based on:
/// - Sample size
/// - Source diversity
/// - Consistency across sources
/// - Time-based stability
pub confidence: f64,
/// Time period this sentiment analysis covers
///
/// Indicates whether this is real-time sentiment or aggregated
/// over a specific time window (hourly, daily, etc.).
pub period: SentimentPeriod,
/// When this sentiment analysis was generated
///
/// Timestamp when the sentiment calculation was completed.
/// Important for time-series analysis and sentiment trends.
pub timestamp: DateTime<Utc>,
/// Provider that generated this sentiment analysis
///
/// Name of the sentiment analysis provider (e.g., "Benzinga", "StockTwits").
pub source: String,
}
/// Time period classification for sentiment analysis aggregation.
///
/// Defines the time window over which sentiment data has been aggregated.
/// Different periods serve different use cases in trading strategies:
///
/// - **Real-time**: Immediate sentiment for breaking news response
/// - **Minute-level**: Short-term sentiment shifts for scalping strategies
/// - **Hourly**: Intraday sentiment trends for day trading
/// - **Daily**: Medium-term sentiment for swing trading
/// - **Weekly**: Long-term sentiment for position strategies
///
/// # Trading Applications
///
/// ```rust
/// use data::providers::common::{SentimentEvent, SentimentPeriod};
///
/// fn route_sentiment_event(event: &SentimentEvent) {
/// match event.period {
/// SentimentPeriod::RealTime => {
/// // Route to high-frequency trading algorithms
/// hft_processor.process(event);
/// },
/// SentimentPeriod::Daily => {
/// // Route to swing trading strategies
/// swing_processor.process(event);
/// },
/// _ => {
/// // Route to appropriate time-based processor
/// }
/// }
/// }
/// ```
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum SentimentPeriod {
/// Real-time sentiment analysis (streaming)
///
/// Immediate sentiment calculated from live data feeds.
/// Minimal aggregation, highest frequency updates.
RealTime,
/// 1-minute aggregated sentiment
///
/// Sentiment aggregated over 1-minute windows.
/// Suitable for high-frequency trading strategies.
Minute1,
/// 5-minute aggregated sentiment
///
/// Sentiment aggregated over 5-minute windows.
/// Balances responsiveness with noise reduction.
Minute5,
/// 15-minute aggregated sentiment
///
/// Sentiment aggregated over 15-minute windows.
/// Good for short-term trend identification.
Minute15,
/// 1-hour aggregated sentiment
///
/// Sentiment aggregated over 1-hour windows.
/// Smooths out short-term noise while maintaining responsiveness.
Hour1,
/// Hourly sentiment (alias for Hour1)
///
/// Alternative naming for 1-hour aggregation.
/// Maintained for backwards compatibility.
Hourly,
/// 1-day aggregated sentiment
///
/// Sentiment aggregated over daily windows.
/// Suitable for swing trading and position strategies.
Day1,
/// Daily sentiment (alias for Day1)
///
/// Alternative naming for daily aggregation.
/// Maintained for backwards compatibility.
Daily,
/// Weekly aggregated sentiment
///
/// Sentiment aggregated over weekly windows.
/// Long-term sentiment trends for position trading.
Weekly,
}
/// Analyst rating change event from sell-side research firms.
///
/// Represents analyst upgrades, downgrades, price target changes, and coverage
/// initiations from research analysts. These events can significantly impact
/// stock prices and are closely watched by institutional and retail investors.
///
/// # Rating Actions
///
/// - **Upgrade**: Analyst raises rating (e.g., Hold → Buy)
/// - **Downgrade**: Analyst lowers rating (e.g., Buy → Hold)
/// - **Initiate**: Analyst begins coverage with initial rating
/// - **Maintain**: Analyst reaffirms existing rating (often with price target change)
///
/// # Price Target Impact
///
/// Price target changes can be more impactful than rating changes:
/// - Large price target increases often drive immediate buying
/// - Price target cuts can trigger selling even without rating downgrades
/// - Multiple analysts changing targets in same direction amplifies impact
///
/// # Usage in Trading
///
/// ```rust
/// use data::providers::common::{AnalystRatingEvent, RatingAction};
///
/// fn assess_rating_impact(rating: &AnalystRatingEvent) -> f64 {
/// let base_impact = match rating.action {
/// RatingAction::Upgrade => 0.05, // +5% expected impact
/// RatingAction::Downgrade => -0.05, // -5% expected impact
/// RatingAction::Initiate => 0.02, // +2% expected impact
/// _ => 0.0,
/// };
///
/// // Adjust for price target changes
/// if let (Some(current), Some(previous)) = (rating.price_target, rating.previous_price_target) {
/// let pt_change = (current - previous) / previous;
/// base_impact + pt_change * 0.3 // Price target changes have 30% weight
/// } else {
/// base_impact
/// }
/// }
/// ```
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AnalystRatingEvent {
/// Symbol being rated by the analyst
///
/// The security ticker that this rating change applies to.
pub symbol: Symbol,
/// Type of rating action taken
///
/// Classification of what the analyst did (upgrade, downgrade, initiate, etc.).
/// Determines the expected market reaction and processing priority.
pub action: RatingAction,
/// Current rating string
///
/// The new rating assigned by the analyst. Format varies by firm
/// (e.g., "Buy", "Outperform", "Strong Buy", "1" (numeric scale)).
pub rating: String,
/// Current rating after this change (normalized)
///
/// Standardized version of the current rating for easier comparison
/// across different firms' rating systems.
pub current_rating: String,
/// Previous rating before this change (normalized)
///
/// Standardized version of the previous rating, allowing calculation
/// of rating change magnitude and direction.
pub previous_rating: String,
/// New price target set by the analyst
///
/// Target price the analyst expects the stock to reach over their
/// forecast horizon (typically 12 months). `None` if no price target provided.
pub price_target: Option<Price>,
/// Previous price target before this change
///
/// Allows calculation of price target change percentage and magnitude.
/// `None` if this is the first price target or previous target unavailable.
pub previous_price_target: Option<Price>,
/// Analyst commentary or research note summary
///
/// Optional text explanation of the rating change rationale.
/// May contain key points from the research report.
pub comment: Option<String>,
/// Date when the rating was published
///
/// Original publication date of the analyst report or rating change.
/// May differ from `timestamp` due to processing delays.
pub rating_date: DateTime<Utc>,
/// Name of the analyst who issued the rating
///
/// Individual analyst name for tracking analyst performance and
/// implementing analyst-specific weightings.
pub analyst: String,
/// Research firm or investment bank name
///
/// Name of the institution employing the analyst (e.g., "Goldman Sachs",
/// "Morgan Stanley"). Used for firm-based credibility weighting.
pub firm: String,
/// When this rating event was processed by our system
///
/// Timestamp when the rating change was received and processed
/// by the Foxhunt system. Used for latency analysis.
pub timestamp: DateTime<Utc>,
}
/// Type of action taken by an analyst on a stock rating.
///
/// Classifies the nature of analyst rating changes for automated processing
/// and impact assessment. Each action type has different implications for
/// expected price movement and market reaction.
///
/// # Market Impact Rankings (typical)
///
/// 1. **Upgrade**: Highest positive impact
/// 2. **Initiate**: Moderate positive impact (new coverage)
/// 3. **Maintain**: Low impact (reaffirmation)
/// 4. **Downgrade**: High negative impact
/// 5. **Suspend**: Moderate negative impact (uncertainty)
/// 6. **Discontinue**: Low impact (loss of coverage)
///
/// # Processing Priorities
///
/// - **Upgrade/Downgrade**: Immediate processing, high priority alerts
/// - **Initiate**: Medium priority, good for discovery of new opportunities
/// - **Maintain**: Low priority unless significant price target change
/// - **Suspend/Discontinue**: Medium priority, may indicate issues
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum RatingAction {
/// Analyst raised the rating (e.g., Hold → Buy)
///
/// Positive rating change indicating improved outlook.
/// Typically drives immediate buying pressure and positive price movement.
Upgrade,
/// Analyst lowered the rating (e.g., Buy → Hold)
///
/// Negative rating change indicating deteriorated outlook.
/// Often triggers selling pressure and negative price movement.
Downgrade,
/// Analyst initiated coverage with new rating
///
/// First-time coverage of a stock by this analyst/firm.
/// Can increase visibility and trading volume for the security.
Initiate,
/// Analyst reaffirmed existing rating
///
/// No rating change but often accompanied by updated price targets
/// or commentary. Lower impact than upgrades/downgrades.
Maintain,
/// Analyst temporarily suspended rating
///
/// Rating removed due to pending corporate actions, lack of information,
/// or other temporary factors. Creates uncertainty.
Suspend,
/// Analyst permanently discontinued coverage
///
/// Analyst no longer following the stock. May indicate reduced
/// institutional interest or resource reallocation.
Discontinue,
}
impl std::fmt::Display for RatingAction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
RatingAction::Upgrade => write!(f, "Upgrade"),
RatingAction::Downgrade => write!(f, "Downgrade"),
RatingAction::Initiate => write!(f, "Initiate"),
RatingAction::Maintain => write!(f, "Maintain"),
RatingAction::Suspend => write!(f, "Suspend"),
RatingAction::Discontinue => write!(f, "Discontinue"),
}
}
}
/// Unusual options activity event indicating potential informed trading.
///
/// Represents detection of abnormal options trading patterns that may signal
/// informed trading ahead of corporate events, earnings, or other catalysts.
/// These events are valuable for identifying potential price movements before
/// they occur in the underlying stock.
///
/// # Types of Unusual Activity
///
/// - **Block Trades**: Large single transactions indicating institutional activity
/// - **Sweeps**: Aggressive orders that sweep through multiple price levels
/// - **Volume Spikes**: Unusually high volume compared to historical averages
/// - **High Open Interest**: Large number of contracts relative to normal activity
///
/// # Trading Applications
///
/// ```rust
/// use data::providers::common::{UnusualOptionsEvent, UnusualOptionsType, OptionsSentiment};
///
/// fn assess_options_signal(event: &UnusualOptionsEvent) -> Option<f64> {
/// // High confidence signals
/// if event.confidence > 0.8 {
/// match (event.unusual_type, event.sentiment) {
/// (UnusualOptionsType::Block, OptionsSentiment::Bullish) => Some(0.75),
/// (UnusualOptionsType::Sweep, OptionsSentiment::Bearish) => Some(-0.60),
/// _ => Some(0.25), // Lower weight for other combinations
/// }
/// } else {
/// None // Low confidence, ignore signal
/// }
/// }
/// ```
///
/// # Risk Considerations
///
/// - Options activity can be hedging rather than directional betting
/// - High implied volatility may indicate uncertainty rather than conviction
/// - Time decay affects options differently than stocks
/// - Consider underlying stock liquidity when interpreting signals
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UnusualOptionsEvent {
/// Underlying stock symbol
///
/// The stock ticker for which unusual options activity was detected.
pub symbol: Symbol,
/// Specific options contract details
///
/// Complete specification of the options contract including strike price,
/// expiration date, and option type (call/put).
pub contract: OptionsContract,
/// Type of unusual activity detected
///
/// Classification of what made this options activity unusual
/// (block trade, sweep, volume spike, etc.).
pub unusual_type: UnusualOptionsType,
/// Alternative classification for activity type
///
/// Secondary classification that may provide additional context.
/// Often duplicates `unusual_type` but may offer different perspective.
pub activity_type: UnusualOptionsType,
/// Total volume of options contracts traded
///
/// Number of options contracts involved in the unusual activity.
/// Compare to average daily volume to assess significance.
pub volume: Quantity,
/// Current open interest for this contract
///
/// Total number of outstanding contracts. High volume relative
/// to open interest suggests new position opening.
pub open_interest: Quantity,
/// Total premium paid for the options
///
/// Dollar amount spent on the options trade. Higher premiums
/// suggest greater conviction or larger position sizes.
pub premium: Option<Price>,
/// Implied volatility of the options contract
///
/// Market's expectation of future volatility implied by option prices.
/// Sudden IV spikes may indicate upcoming news or events.
pub implied_volatility: Option<f64>,
/// Directional sentiment inferred from the activity
///
/// Whether the unusual activity suggests bullish, bearish, or
/// neutral expectations for the underlying stock.
pub sentiment: OptionsSentiment,
/// Confidence level in the unusual activity detection (0.0 to 1.0)
///
/// Algorithmic confidence that this activity is truly unusual
/// and not random market noise. Higher values indicate stronger signals.
pub confidence: f64,
/// Human-readable description of the unusual activity
///
/// Textual explanation of what made this activity unusual,
/// suitable for alerts and reporting.
pub description: String,
/// When this unusual activity was detected
///
/// Timestamp when the unusual options activity was identified
/// and processed by the detection system.
pub timestamp: DateTime<Utc>,
}
/// Options contract specification with complete contract details.
///
/// Defines all parameters necessary to uniquely identify an options contract.
/// Used within unusual options events to specify exactly which contract
/// exhibited unusual activity.
///
/// # Contract Identification
///
/// Options contracts are uniquely identified by:
/// - Underlying symbol
/// - Expiration date
/// - Strike price
/// - Option type (call/put)
///
/// # Examples
///
/// ```rust
/// use data::providers::common::{OptionsContract, OptionsType};
/// use common::{Symbol, Price};
/// use chrono::{Utc, Duration};
///
/// // AAPL $150 Call expiring in 30 days
/// let contract = OptionsContract {
/// symbol: Symbol::from("AAPL"),
/// expiry: Utc::now() + Duration::days(30),
/// expiration: Utc::now() + Duration::days(30),
/// strike: Price::from(150.0),
/// option_type: OptionsType::Call,
/// multiplier: 100, // Standard equity option multiplier
/// };
/// ```
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OptionsContract {
/// Underlying stock symbol
///
/// The stock ticker that this options contract is based on.
pub symbol: Symbol,
/// Contract expiration date (primary field)
///
/// Date when the options contract expires and becomes worthless if unexercised.
/// This is the canonical expiration field.
pub expiry: DateTime<Utc>,
/// Contract expiration date (alias for backwards compatibility)
///
/// Duplicate of `expiry` field maintained for backwards compatibility.
/// New code should use `expiry` instead.
#[deprecated(since = "1.0.0", note = "Use expiry instead")]
pub expiration: DateTime<Utc>,
/// Strike price of the options contract
///
/// The price at which the option can be exercised to buy (call) or sell (put)
/// the underlying stock.
pub strike: Price,
/// Type of option (call or put)
///
/// - Call: Right to buy the underlying at the strike price
/// - Put: Right to sell the underlying at the strike price
pub option_type: OptionsType,
/// Contract multiplier (typically 100 for equity options)
///
/// Number of shares controlled by one options contract.
/// Standard equity options control 100 shares per contract.
pub multiplier: u32,
}
/// Type of options contract (call or put).
///
/// Defines the rights granted by an options contract:
///
/// - **Call Options**: Right to buy the underlying asset at the strike price
/// - **Put Options**: Right to sell the underlying asset at the strike price
///
/// # Market Sentiment Implications
///
/// - **Call Buying**: Generally bullish (expecting price increase)
/// - **Put Buying**: Generally bearish (expecting price decrease)
/// - **Call Selling**: Neutral to bearish (collecting premium)
/// - **Put Selling**: Neutral to bullish (collecting premium)
///
/// # Examples
///
/// ```rust
/// use data::providers::common::OptionsType;
///
/// // Assess directional bias from options type
/// match option_type {
/// OptionsType::Call => {
/// // Buyer expects stock to rise above strike + premium
/// println!("Bullish bias detected");
/// },
/// OptionsType::Put => {
/// // Buyer expects stock to fall below strike - premium
/// println!("Bearish bias detected");
/// }
/// }
/// ```
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum OptionsType {
/// Call option - right to buy the underlying asset
///
/// Grants the holder the right (but not obligation) to purchase
/// the underlying stock at the strike price before expiration.
/// Profitable when stock price > strike + premium paid.
Call,
/// Put option - right to sell the underlying asset
///
/// Grants the holder the right (but not obligation) to sell
/// the underlying stock at the strike price before expiration.
/// Profitable when stock price < strike - premium paid.
Put,
}
/// Sentiment classification derived from options trading activity.
///
/// Algorithmic assessment of the directional bias implied by unusual
/// options activity. Takes into account option type, trading patterns,
/// and market context to infer trader sentiment.
///
/// # Sentiment Determination Factors
///
/// - **Option Type**: Calls generally bullish, puts generally bearish
/// - **Buy vs Sell**: Aggressive buying more significant than selling
/// - **Strike Price**: In-the-money vs out-of-the-money implications
/// - **Time to Expiration**: Near-term options suggest immediate expectations
/// - **Volume Profile**: Large blocks suggest institutional conviction
///
/// # Usage in Signal Generation
///
/// ```rust
/// use data::providers::common::{OptionsSentiment, UnusualOptionsEvent};
///
/// fn weight_options_signal(event: &UnusualOptionsEvent) -> f64 {
/// let base_weight = match event.sentiment {
/// OptionsSentiment::Bullish => 1.0,
/// OptionsSentiment::Bearish => -1.0,
/// OptionsSentiment::Neutral => 0.0,
/// };
///
/// // Adjust based on confidence and premium
/// base_weight * event.confidence *
/// event.premium.map(|p| p.min(1000000.0) / 1000000.0).unwrap_or(0.5)
/// }
/// ```
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum OptionsSentiment {
/// Positive sentiment - expecting stock price to rise
///
/// Unusual activity suggests traders expect the underlying
/// stock to increase in value. Typically associated with:
/// - Heavy call buying
/// - Put selling
/// - Low strike calls or high strike puts
Bullish,
/// Negative sentiment - expecting stock price to fall
///
/// Unusual activity suggests traders expect the underlying
/// stock to decrease in value. Typically associated with:
/// - Heavy put buying
/// - Call selling
/// - High strike puts or low strike calls
Bearish,
/// Neutral sentiment - no clear directional bias
///
/// Unusual activity doesn't indicate clear directional expectations.
/// May suggest:
/// - Volatility plays (straddles/strangles)
/// - Hedging activity
/// - Arbitrage strategies
/// - Unclear or mixed signals
Neutral,
}
/// Classification of unusual options activity patterns.
///
/// Categorizes the specific type of unusual trading behavior detected
/// in options markets. Each type has different implications for market
/// sentiment and potential price movements in the underlying stock.
///
/// # Activity Type Significance
///
/// **High Impact:**
/// - `Block`: Large institutional trades, often informed
/// - `Sweep`: Aggressive market orders suggesting urgency
///
/// **Medium Impact:**
/// - `VolumeSpike`: Sudden interest, check for news catalysts
/// - `VolatilitySpike`: Expectation of significant price movement
///
/// **Lower Impact:**
/// - `HighVolume`/`HighOpenInterest`: Sustained interest over time
/// - `Split`: Large order broken into pieces, less urgent
///
/// # Detection Thresholds
///
/// Each type has specific detection criteria:
/// - Volume thresholds relative to historical averages
/// - Open interest comparisons
/// - Price and volatility change requirements
/// - Time-based clustering analysis
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum UnusualOptionsType {
/// Large block trade executed as single transaction
///
/// Large institutional-sized trade executed at once, typically indicating
/// informed trading by sophisticated market participants. High significance.
Block,
/// Aggressive order sweeping through multiple price levels
///
/// Market order that aggressively takes liquidity across multiple bid/ask
/// levels, suggesting urgency and strong conviction. Very high significance.
Sweep,
/// Large order split into smaller pieces
///
/// Detection of coordinated smaller trades that appear to be part of
/// a larger strategy. Lower urgency than blocks but still significant.
Split,
/// Volume significantly above historical average
///
/// Trading volume for this contract is unusually high compared to
/// recent historical patterns. Medium significance.
HighVolume,
/// Open interest unusually high for this contract
///
/// Number of outstanding contracts is abnormally high, suggesting
/// sustained institutional interest. Medium significance.
HighOpenInterest,
/// Alternative classification for block trades
///
/// Alias for `Block` to handle different provider naming conventions.
/// Represents the same type of large institutional trade.
BlockTrade,
/// Sudden spike in trading volume
///
/// Rapid increase in volume over a short time period, often associated
/// with breaking news or imminent announcements. High significance.
VolumeSpike,
/// Rapid increase in open interest
///
/// Quick buildup of new positions in this contract, suggesting
/// institutional accumulation. Medium to high significance.
OpenInterestSpike,
/// Implied volatility increase indicating expected price movement
///
/// Market pricing in higher expected volatility, often preceding
/// earnings or major announcements. High significance for timing.
VolatilitySpike,
}
/// Order book price level change for Level 2 market data updates.
///
/// Represents a change to a specific price level in the order book,
/// including additions, updates, or deletions of orders at that price.
/// Used for maintaining real-time order book state in high-frequency
/// trading systems.
///
/// # Order Book Mechanics
///
/// - **Add**: New orders added to a price level
/// - **Update**: Existing price level quantity modified (usually reduced due to fills)
/// - **Delete**: Price level completely removed (all orders filled or cancelled)
///
/// # Usage in Order Book Reconstruction
///
/// ```rust
/// use data::providers::common::{PriceLevelChange, PriceLevelChangeType, OrderBookSide};
/// use std::collections::BTreeMap;
/// use common::Price;
///
/// fn apply_level_change(order_book: &mut BTreeMap<Price, f64>, change: &PriceLevelChange) {
/// match change.change_type {
/// PriceLevelChangeType::Add | PriceLevelChangeType::Update => {
/// order_book.insert(change.price, change.quantity.into());
/// },
/// PriceLevelChangeType::Delete => {
/// order_book.remove(&change.price);
/// }
/// }
/// }
/// ```
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PriceLevelChange {
/// Price level being modified
///
/// The specific price at which the order book change occurred.
pub price: Price,
/// New quantity at this price level
///
/// - For Add/Update: The new total quantity at this price
/// - For Delete: Typically 0 (price level removed)
pub quantity: Quantity,
/// Type of change applied to this price level
///
/// Indicates whether this is an addition, update, or deletion
/// of orders at the specified price level.
pub change_type: PriceLevelChangeType,
/// Which side of the order book (bid or ask)
///
/// Specifies whether this change affects the buy side (bids)
/// or sell side (asks) of the order book.
pub side: OrderBookSide,
}
/// Type of change applied to an order book price level.
///
/// Classifies the nature of order book modifications for proper
/// reconstruction and analysis of market depth changes.
///
/// # Change Semantics
///
/// - **Add**: New price level created with initial quantity
/// - **Update**: Existing price level quantity modified (partial fill)
/// - **Delete**: Price level removed entirely (all orders filled/cancelled)
///
/// # HFT Considerations
///
/// In high-frequency trading, the sequence and timing of these changes
/// can provide insights into:
/// - Large order execution patterns
/// - Iceberg order detection
/// - Market maker behavior
/// - Liquidity provider strategies
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum PriceLevelChangeType {
/// New price level added to the order book
///
/// Indicates that orders were placed at a price level that
/// previously had no quantity. Creates new market depth.
Add,
/// Existing price level quantity modified
///
/// Partial execution or cancellation at an existing price level.
/// The price level remains but with different total quantity.
Update,
/// Price level completely removed from order book
///
/// All orders at this price level have been filled or cancelled.
/// The price level no longer exists in the order book.
Delete,
}
/// Side of the order book affected by a price level change.
///
/// Distinguishes between the buy side (bids) and sell side (asks)
/// of the order book for proper routing of level changes.
///
/// # Order Book Structure
///
/// ```text
/// Ask Side (Sell Orders)
/// ----------------------
/// $100.03 | 500 shares
/// $100.02 | 750 shares ← Best Ask
/// $100.01 | 1000 shares
/// ========================
/// $100.00 | 1200 shares ← Best Bid
/// $ 99.99 | 800 shares
/// $ 99.98 | 600 shares
/// ----------------------
/// Bid Side (Buy Orders)
/// ```
///
/// # Trading Implications
///
/// - **Bid Changes**: Affect buying pressure and support levels
/// - **Ask Changes**: Affect selling pressure and resistance levels
/// - **Best Bid/Ask**: Most important levels for spread calculation
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum OrderBookSide {
/// Buy side of the order book
///
/// Orders from traders willing to buy the security.
/// Higher bid prices indicate stronger buying pressure.
Bid,
/// Sell side of the order book
///
/// Orders from traders willing to sell the security.
/// Lower ask prices indicate stronger selling pressure.
Ask,
}