1use serde::{Deserialize, Serialize};
2use std::collections::VecDeque;
3
4#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
6pub struct ADXConfig {
7 pub period: usize,
9 pub adx_smoothing: usize,
11 pub strong_trend_threshold: f64,
13 pub very_strong_trend_threshold: f64,
15}
16
17impl Default for ADXConfig {
18 fn default() -> Self {
19 Self {
20 period: 14,
21 adx_smoothing: 14,
22 strong_trend_threshold: 25.0,
23 very_strong_trend_threshold: 50.0,
24 }
25 }
26}
27
28#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
30pub struct ADXInput {
31 pub high: f64,
33 pub low: f64,
35 pub close: f64,
37}
38
39#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
41pub enum TrendStrength {
42 Weak,
44 Strong,
46 VeryStrong,
48 Insufficient,
50}
51
52#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
54pub enum TrendDirection {
55 Up,
57 Down,
59 Sideways,
61}
62
63#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
65pub struct ADXOutput {
66 pub adx: f64,
68 pub plus_di: f64,
70 pub minus_di: f64,
72 pub dx: f64,
74 pub true_range: f64,
76 pub trend_strength: TrendStrength,
78 pub trend_direction: TrendDirection,
80 pub di_spread: f64,
82}
83
84#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
86pub struct ADXPeriodData {
87 pub true_range: f64,
89 pub plus_dm: f64,
91 pub minus_dm: f64,
93 pub plus_di: f64,
95 pub minus_di: f64,
97 pub dx: f64,
99}
100
101#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
103pub struct ADXState {
104 pub config: ADXConfig,
106 pub previous_high: Option<f64>,
108 pub previous_low: Option<f64>,
110 pub previous_close: Option<f64>,
112 pub period_data: VecDeque<ADXPeriodData>,
114 pub smoothed_tr: Option<f64>,
116 pub smoothed_plus_dm: Option<f64>,
118 pub smoothed_minus_dm: Option<f64>,
120 pub dx_history: VecDeque<f64>,
122 pub current_adx: Option<f64>,
124 pub has_di_data: bool,
126 pub has_adx_data: bool,
128 pub is_first: bool,
130}
131
132impl ADXState {
133 pub fn new(config: ADXConfig) -> Self {
134 Self {
135 config,
136 previous_high: None,
137 previous_low: None,
138 previous_close: None,
139 period_data: VecDeque::with_capacity(config.period),
140 smoothed_tr: None,
141 smoothed_plus_dm: None,
142 smoothed_minus_dm: None,
143 dx_history: VecDeque::with_capacity(config.adx_smoothing),
144 current_adx: None,
145 has_di_data: false,
146 has_adx_data: false,
147 is_first: true,
148 }
149 }
150}
151
152#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
154pub enum ADXError {
155 InvalidInput(String),
157 InvalidHLC,
159 InvalidPrice,
161 InvalidPeriod,
163 InvalidThresholds,
165 DivisionByZero,
167}