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}