kestrel_chartkit/indicator/
mod.rs1pub mod adx;
2pub mod alligator;
3pub mod anchored_vwap;
4pub mod atr;
5pub mod bbtrend;
6pub mod bollinger;
7pub mod bop;
8pub mod bos_choch;
9pub mod buy_sell_pressure;
10pub mod candle_story;
11pub mod cci;
12pub mod chaikin_osc;
13pub mod chande_kroll;
14pub mod chandelier_exit;
15pub mod chandelier_flip_radar;
16pub mod chart_patterns;
17pub mod choppiness;
18pub mod connors_rsi;
19pub mod coppock;
20pub mod cvd_intrabar;
21pub mod divergence;
22pub mod dpo;
23pub mod efficiency;
24pub mod elliott;
25pub mod envelope;
26pub mod eom;
27pub mod fisher_transform;
28pub mod force_index;
29pub mod harmonics;
30pub mod kst;
31pub mod liquidity_fvg;
32pub mod liquidity_sweeps;
33pub mod lsma;
34pub mod macd;
35pub mod market_structure_breaks;
36pub mod mass_index;
37pub mod mcginley;
38pub mod mfi;
39pub mod midas;
40pub mod momentum_indicators;
41pub mod money_flow_profile;
42pub mod moving_averages;
43pub mod multi_factor;
44pub mod nvi_pvi;
45pub mod order_block;
46pub mod params;
47pub mod pivot_sets;
48pub mod pivots_structure;
49pub mod pmo;
50pub mod price_levels;
51pub mod pvt;
52pub mod rci;
53pub mod registry;
54pub mod relative_strength;
55pub mod relative_volatility;
56pub mod rsi;
57pub mod rvat;
58pub mod rvi;
59pub mod smart_money_structure;
60pub mod smi;
61pub mod smoothing;
62pub mod source_mapped;
63pub mod stoch_rsi;
64pub mod swing_structure;
65pub mod t3;
66pub mod tema;
67pub mod trend_quality;
68pub mod trend_relationship;
69pub mod trend_structural;
70pub mod trix;
71pub mod tsi;
72pub mod twap;
73pub mod ulcer;
74pub mod vidya;
75pub mod vix_fix;
76pub mod volatility_indicators;
77pub mod volatility_regime;
78pub mod volume_flow;
79pub mod volume_flow_hires;
80pub mod volume_indicators;
81pub mod volume_profile;
82pub mod volume_profile_extended;
83pub mod volume_profile_persistent;
84pub mod vortex;
85pub mod vwap;
86pub mod wavetrend;
87pub mod williams_r;
88pub mod wyckoff;
89pub mod zigzag;
90pub mod zigzag_advanced;
91pub mod zscore;
92
93use std::collections::HashMap;
94use std::fmt;
95
96#[cfg(feature = "serde")]
97use serde::{Deserialize, Serialize};
98
99use crate::artifact::Artifact;
100use crate::model::{Bar, BarValidationError, SeriesCapabilities};
101
102#[derive(Debug, Clone, PartialEq)]
104#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
105pub struct IndicatorOutput {
106 pub value: f64,
107 pub secondary: Option<f64>,
108 pub signal: Option<f64>,
109 pub extra: HashMap<String, f64>,
110 pub state: Option<String>,
113 pub reason: Option<String>,
115 pub artifacts: Vec<Artifact>,
117 pub series_capabilities: Option<SeriesCapabilities>,
129}
130
131impl IndicatorOutput {
132 pub fn new(value: f64) -> Self {
133 Self {
134 value,
135 secondary: None,
136 signal: None,
137 extra: HashMap::new(),
138 state: None,
139 reason: None,
140 artifacts: Vec::new(),
141 series_capabilities: None,
142 }
143 }
144
145 pub fn with_secondary(mut self, secondary: f64) -> Self {
146 self.secondary = Some(secondary);
147 self
148 }
149
150 pub fn with_signal(mut self, signal: f64) -> Self {
151 self.signal = Some(signal);
152 self
153 }
154
155 pub fn with_extra(value: f64, extra: HashMap<String, f64>) -> Self {
156 Self {
157 value,
158 secondary: None,
159 signal: None,
160 extra,
161 state: None,
162 reason: None,
163 artifacts: Vec::new(),
164 series_capabilities: None,
165 }
166 }
167
168 pub fn with_state(mut self, state: impl Into<String>) -> Self {
169 self.state = Some(state.into());
170 self
171 }
172
173 pub fn with_reason(mut self, reason: impl Into<String>) -> Self {
174 self.reason = Some(reason.into());
175 self
176 }
177
178 pub fn with_artifact(mut self, artifact: impl Into<Artifact>) -> Self {
179 self.artifacts.push(artifact.into());
180 self
181 }
182
183 pub fn with_capabilities(mut self, capabilities: SeriesCapabilities) -> Self {
186 self.series_capabilities = Some(capabilities);
187 self
188 }
189}
190
191#[derive(Debug, Clone, PartialEq)]
193#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
194pub struct IndicatorAlert {
195 pub kind: String,
196 pub note: String,
197 pub strength: f64,
198}
199
200impl IndicatorAlert {
201 pub fn new(kind: impl Into<String>, note: impl Into<String>, strength: f64) -> Self {
202 Self {
203 kind: kind.into(),
204 note: note.into(),
205 strength,
206 }
207 }
208}
209
210impl fmt::Display for IndicatorAlert {
211 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
212 write!(f, "{} ({})", self.note, self.kind)
213 }
214}
215
216pub trait Indicator: Send + Sync {
218 fn name(&self) -> &str;
219 fn warmup_period(&self) -> usize {
220 0
221 }
222 fn reset(&mut self);
223 fn on_bar(&mut self, bar: &Bar) -> Option<IndicatorOutput>;
224 fn on_checked_bar(&mut self, bar: &Bar) -> Result<Option<IndicatorOutput>, BarValidationError> {
226 bar.validate()?;
227 Ok(self.on_bar(bar))
228 }
229 fn alerts(&self) -> Vec<IndicatorAlert> {
230 Vec::new()
231 }
232}
233
234impl<T: Indicator + ?Sized> Indicator for Box<T> {
238 fn name(&self) -> &str {
239 (**self).name()
240 }
241 fn warmup_period(&self) -> usize {
242 (**self).warmup_period()
243 }
244 fn reset(&mut self) {
245 (**self).reset()
246 }
247 fn on_bar(&mut self, bar: &Bar) -> Option<IndicatorOutput> {
248 (**self).on_bar(bar)
249 }
250 fn on_checked_bar(&mut self, bar: &Bar) -> Result<Option<IndicatorOutput>, BarValidationError> {
251 (**self).on_checked_bar(bar)
252 }
253 fn alerts(&self) -> Vec<IndicatorAlert> {
254 (**self).alerts()
255 }
256}