indexes_rs/v2/mfi/
types.rs

1use serde::{Deserialize, Serialize};
2use std::collections::VecDeque;
3
4/// Configuration for MFI calculation
5#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
6pub struct MFIConfig {
7    /// Period for MFI calculation (default: 14)
8    pub period: usize,
9    /// Overbought threshold (default: 80.0)
10    pub overbought: f64,
11    /// Oversold threshold (default: 20.0)
12    pub oversold: f64,
13}
14
15impl Default for MFIConfig {
16    fn default() -> Self {
17        Self {
18            period: 14,
19            overbought: 80.0,
20            oversold: 20.0,
21        }
22    }
23}
24
25/// Input data for MFI calculation (OHLCV)
26#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
27pub struct MFIInput {
28    /// High price
29    pub high: f64,
30    /// Low price
31    pub low: f64,
32    /// Close price
33    pub close: f64,
34    /// Volume
35    pub volume: f64,
36}
37
38/// Raw Money Flow data point
39#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
40pub struct MoneyFlow {
41    /// Typical price ((H+L+C)/3)
42    pub typical_price: f64,
43    /// Raw money flow (typical_price * volume)
44    pub raw_money_flow: f64,
45    /// Money flow direction (1.0 = positive, -1.0 = negative, 0.0 = neutral)
46    pub flow_direction: f64,
47}
48
49/// Output from MFI calculation
50#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
51pub struct MFIOutput {
52    /// Money Flow Index value (0-100)
53    pub mfi: f64,
54    /// Current typical price
55    pub typical_price: f64,
56    /// Current raw money flow
57    pub raw_money_flow: f64,
58    /// Money flow direction
59    pub flow_direction: f64,
60    /// Market condition based on thresholds
61    pub market_condition: MFIMarketCondition,
62}
63
64/// Market condition based on MFI value
65#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
66pub enum MFIMarketCondition {
67    /// MFI above overbought threshold
68    Overbought,
69    /// MFI below oversold threshold
70    Oversold,
71    /// MFI in normal range
72    Normal,
73    /// Not enough data yet
74    Insufficient,
75}
76
77/// MFI calculation state
78#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
79pub struct MFIState {
80    /// Configuration
81    pub config: MFIConfig,
82    /// History of money flow data points
83    pub money_flows: VecDeque<MoneyFlow>,
84    /// Previous typical price for comparison
85    pub previous_typical_price: Option<f64>,
86    /// Sum of positive money flows in current period
87    pub positive_money_flow_sum: f64,
88    /// Sum of negative money flows in current period
89    pub negative_money_flow_sum: f64,
90    /// Whether we have enough data for calculation
91    pub has_sufficient_data: bool,
92}
93
94impl MFIState {
95    pub fn new(config: MFIConfig) -> Self {
96        Self {
97            config,
98            money_flows: VecDeque::with_capacity(config.period),
99            previous_typical_price: None,
100            positive_money_flow_sum: 0.0,
101            negative_money_flow_sum: 0.0,
102            has_sufficient_data: false,
103        }
104    }
105}
106
107/// Error types for MFI calculation
108#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
109pub enum MFIError {
110    /// Invalid input data
111    InvalidInput(String),
112    /// Invalid OHLC relationship (e.g., high < low)
113    InvalidOHLC,
114    /// Negative volume
115    NegativeVolume,
116    /// Invalid price (NaN or infinite)
117    InvalidPrice,
118    /// Invalid period (must be > 0)
119    InvalidPeriod,
120    /// Invalid threshold values
121    InvalidThresholds,
122    /// Division by zero in calculation
123    DivisionByZero,
124}