Skip to main content

sandbox_quant/runtime/
strategy_runtime.rs

1use crate::model::signal::Signal;
2use crate::model::tick::Tick;
3use crate::strategy::aroon_trend::AroonTrendStrategy;
4use crate::strategy::atr_expansion::AtrExpansionStrategy;
5use crate::strategy::bollinger_reversion::BollingerReversionStrategy;
6use crate::strategy::channel_breakout::ChannelBreakoutStrategy;
7use crate::strategy::donchian_trend::DonchianTrendStrategy;
8use crate::strategy::ema_crossover::EmaCrossover;
9use crate::strategy::ensemble_vote::EnsembleVoteStrategy;
10use crate::strategy::ma_crossover::MaCrossover;
11use crate::strategy::ma_reversion::MaReversionStrategy;
12use crate::strategy::macd_crossover::MacdCrossoverStrategy;
13use crate::strategy::opening_range_breakout::OpeningRangeBreakoutStrategy;
14use crate::strategy::regime_switch::RegimeSwitchStrategy;
15use crate::strategy::roc_momentum::RocMomentumStrategy;
16use crate::strategy::rsa::RsaStrategy;
17use crate::strategy::stochastic_reversion::StochasticReversionStrategy;
18use crate::strategy::volatility_compression::VolatilityCompressionStrategy;
19use crate::strategy_catalog::{StrategyKind, StrategyProfile};
20
21#[derive(Debug)]
22pub enum StrategyRuntime {
23    Ma(MaCrossover),
24    Ema(EmaCrossover),
25    Atr(AtrExpansionStrategy),
26    Vlc(VolatilityCompressionStrategy),
27    Chb(ChannelBreakoutStrategy),
28    Orb(OpeningRangeBreakoutStrategy),
29    Rsa(RsaStrategy),
30    Dct(DonchianTrendStrategy),
31    Mrv(MaReversionStrategy),
32    Bbr(BollingerReversionStrategy),
33    Sto(StochasticReversionStrategy),
34    Reg(RegimeSwitchStrategy),
35    Ens(EnsembleVoteStrategy),
36    Mac(MacdCrossoverStrategy),
37    Roc(RocMomentumStrategy),
38    Arn(AroonTrendStrategy),
39}
40
41impl StrategyRuntime {
42    pub fn from_profile(profile: &StrategyProfile) -> Self {
43        let (fast, slow, min_ticks) = profile.periods_tuple();
44        match profile.strategy_kind() {
45            StrategyKind::Rsa => {
46                let period = fast.max(2);
47                let upper = slow.clamp(51, 95) as f64;
48                let lower = 100.0 - upper;
49                Self::Rsa(RsaStrategy::new(period, lower, upper, min_ticks))
50            }
51            StrategyKind::Dct => Self::Dct(DonchianTrendStrategy::new(fast, slow, min_ticks)),
52            StrategyKind::Mrv => Self::Mrv(MaReversionStrategy::new(fast, slow, min_ticks)),
53            StrategyKind::Bbr => Self::Bbr(BollingerReversionStrategy::new(fast, slow, min_ticks)),
54            StrategyKind::Sto => Self::Sto(StochasticReversionStrategy::new(fast, slow, min_ticks)),
55            StrategyKind::Atr => Self::Atr(AtrExpansionStrategy::new(fast, slow, min_ticks)),
56            StrategyKind::Vlc => {
57                Self::Vlc(VolatilityCompressionStrategy::new(fast, slow, min_ticks))
58            }
59            StrategyKind::Chb => Self::Chb(ChannelBreakoutStrategy::new(fast, slow, min_ticks)),
60            StrategyKind::Orb => {
61                Self::Orb(OpeningRangeBreakoutStrategy::new(fast, slow, min_ticks))
62            }
63            StrategyKind::Ema => Self::Ema(EmaCrossover::new(fast, slow, min_ticks)),
64            StrategyKind::Reg => Self::Reg(RegimeSwitchStrategy::new(fast, slow, min_ticks)),
65            StrategyKind::Ens => Self::Ens(EnsembleVoteStrategy::new(fast, slow, min_ticks)),
66            StrategyKind::Mac => Self::Mac(MacdCrossoverStrategy::new(fast, slow, min_ticks)),
67            StrategyKind::Roc => Self::Roc(RocMomentumStrategy::new(fast, slow, min_ticks)),
68            StrategyKind::Arn => Self::Arn(AroonTrendStrategy::new(fast, slow, min_ticks)),
69            StrategyKind::Ma => Self::Ma(MaCrossover::new(fast, slow, min_ticks)),
70        }
71    }
72
73    pub fn on_tick(&mut self, tick: &Tick) -> Signal {
74        match self {
75            Self::Ma(s) => s.on_tick(tick),
76            Self::Ema(s) => s.on_tick(tick),
77            Self::Atr(s) => s.on_tick(tick),
78            Self::Vlc(s) => s.on_tick(tick),
79            Self::Chb(s) => s.on_tick(tick),
80            Self::Orb(s) => s.on_tick(tick),
81            Self::Rsa(s) => s.on_tick(tick),
82            Self::Dct(s) => s.on_tick(tick),
83            Self::Mrv(s) => s.on_tick(tick),
84            Self::Bbr(s) => s.on_tick(tick),
85            Self::Sto(s) => s.on_tick(tick),
86            Self::Reg(s) => s.on_tick(tick),
87            Self::Ens(s) => s.on_tick(tick),
88            Self::Mac(s) => s.on_tick(tick),
89            Self::Roc(s) => s.on_tick(tick),
90            Self::Arn(s) => s.on_tick(tick),
91        }
92    }
93
94    pub fn fast_sma_value(&self) -> Option<f64> {
95        match self {
96            Self::Ma(s) => s.fast_sma_value(),
97            Self::Ema(s) => s.fast_ema_value(),
98            Self::Atr(_) => None,
99            Self::Vlc(s) => s.mean_value(),
100            Self::Chb(_) => None,
101            Self::Orb(_) => None,
102            Self::Rsa(_) => None,
103            Self::Dct(_) => None,
104            Self::Mrv(s) => s.mean_value(),
105            Self::Bbr(s) => s.mean_value(),
106            Self::Sto(_) => None,
107            Self::Reg(_) => None,
108            Self::Ens(_) => None,
109            Self::Mac(_) => None,
110            Self::Roc(_) => None,
111            Self::Arn(_) => None,
112        }
113    }
114
115    pub fn slow_sma_value(&self) -> Option<f64> {
116        match self {
117            Self::Ma(s) => s.slow_sma_value(),
118            Self::Ema(s) => s.slow_ema_value(),
119            Self::Atr(_) => None,
120            Self::Vlc(_) => None,
121            Self::Chb(_) => None,
122            Self::Orb(_) => None,
123            Self::Rsa(_) => None,
124            Self::Dct(_) => None,
125            Self::Mrv(_) => None,
126            Self::Bbr(_) => None,
127            Self::Sto(_) => None,
128            Self::Reg(_) => None,
129            Self::Ens(_) => None,
130            Self::Mac(_) => None,
131            Self::Roc(_) => None,
132            Self::Arn(_) => None,
133        }
134    }
135}