use crate::core::signal::direction::Direction;
use crate::core::signal::kind::{SignalKind, VolatilitySub};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum VolatilityLevel {
Low,
Normal,
High,
}
#[derive(Debug, Clone)]
pub struct VolatilityRegimeDetector {
low_threshold: f64,
high_threshold: f64,
current: Option<VolatilityLevel>,
}
impl VolatilityRegimeDetector {
pub fn new(low_threshold: f64, high_threshold: f64) -> Self {
Self {
low_threshold,
high_threshold,
current: None,
}
}
fn classify(&self, value: f64) -> VolatilityLevel {
if value < self.low_threshold {
VolatilityLevel::Low
} else if value > self.high_threshold {
VolatilityLevel::High
} else {
VolatilityLevel::Normal
}
}
pub fn detect_from_values(&mut self, atr_or_stddev: f64) -> Option<(SignalKind, Direction)> {
let new_level = self.classify(atr_or_stddev);
let prev = self.current;
self.current = Some(new_level);
let prev_level = match prev {
None => return None,
Some(l) => l,
};
if prev_level == new_level {
return None;
}
let result = match (prev_level, new_level) {
(_, VolatilityLevel::High) => {
Some((SignalKind::Volatility(VolatilitySub::Extreme), Direction::Up))
}
(VolatilityLevel::High, _) => {
Some((SignalKind::Volatility(VolatilitySub::Shift), Direction::Down))
}
(_, VolatilityLevel::Low) => {
Some((SignalKind::Volatility(VolatilitySub::Squeeze), Direction::Down))
}
(VolatilityLevel::Low, _) => {
Some((SignalKind::Volatility(VolatilitySub::Shift), Direction::Up))
}
_ => None,
};
result
}
pub fn current_level(&self) -> Option<VolatilityLevel> {
self.current
}
pub fn reset(&mut self) {
self.current = None;
}
}