1use crate::backtesting::refs::IndicatorRef;
7use crate::backtesting::strategy::StrategyContext;
8use crate::indicators::Indicator;
9
10use super::Condition;
11
12#[derive(Clone)]
18pub struct Above<R: IndicatorRef> {
19 indicator: R,
20 threshold: f64,
21}
22
23impl<R: IndicatorRef> Above<R> {
24 pub fn new(indicator: R, threshold: f64) -> Self {
26 Self {
27 indicator,
28 threshold,
29 }
30 }
31}
32
33impl<R: IndicatorRef> Condition for Above<R> {
34 fn evaluate(&self, ctx: &StrategyContext) -> bool {
35 self.indicator
36 .value(ctx)
37 .map(|v| v > self.threshold)
38 .unwrap_or(false)
39 }
40
41 fn required_indicators(&self) -> Vec<(String, Indicator)> {
42 self.indicator.required_indicators()
43 }
44
45 fn description(&self) -> String {
46 format!("{} > {:.2}", self.indicator.key(), self.threshold)
47 }
48}
49
50#[derive(Clone)]
52pub struct Below<R: IndicatorRef> {
53 indicator: R,
54 threshold: f64,
55}
56
57impl<R: IndicatorRef> Below<R> {
58 pub fn new(indicator: R, threshold: f64) -> Self {
60 Self {
61 indicator,
62 threshold,
63 }
64 }
65}
66
67impl<R: IndicatorRef> Condition for Below<R> {
68 fn evaluate(&self, ctx: &StrategyContext) -> bool {
69 self.indicator
70 .value(ctx)
71 .map(|v| v < self.threshold)
72 .unwrap_or(false)
73 }
74
75 fn required_indicators(&self) -> Vec<(String, Indicator)> {
76 self.indicator.required_indicators()
77 }
78
79 fn description(&self) -> String {
80 format!("{} < {:.2}", self.indicator.key(), self.threshold)
81 }
82}
83
84#[derive(Clone)]
89pub struct CrossesAbove<R: IndicatorRef> {
90 indicator: R,
91 threshold: f64,
92}
93
94impl<R: IndicatorRef> CrossesAbove<R> {
95 pub fn new(indicator: R, threshold: f64) -> Self {
97 Self {
98 indicator,
99 threshold,
100 }
101 }
102}
103
104impl<R: IndicatorRef> Condition for CrossesAbove<R> {
105 fn evaluate(&self, ctx: &StrategyContext) -> bool {
106 let current = self.indicator.value(ctx);
107 let prev = self.indicator.prev_value(ctx);
108
109 match (current, prev) {
110 (Some(curr), Some(p)) => p <= self.threshold && curr > self.threshold,
111 _ => false,
112 }
113 }
114
115 fn required_indicators(&self) -> Vec<(String, Indicator)> {
116 self.indicator.required_indicators()
117 }
118
119 fn description(&self) -> String {
120 format!(
121 "{} crosses above {:.2}",
122 self.indicator.key(),
123 self.threshold
124 )
125 }
126}
127
128#[derive(Clone)]
133pub struct CrossesBelow<R: IndicatorRef> {
134 indicator: R,
135 threshold: f64,
136}
137
138impl<R: IndicatorRef> CrossesBelow<R> {
139 pub fn new(indicator: R, threshold: f64) -> Self {
141 Self {
142 indicator,
143 threshold,
144 }
145 }
146}
147
148impl<R: IndicatorRef> Condition for CrossesBelow<R> {
149 fn evaluate(&self, ctx: &StrategyContext) -> bool {
150 let current = self.indicator.value(ctx);
151 let prev = self.indicator.prev_value(ctx);
152
153 match (current, prev) {
154 (Some(curr), Some(p)) => p >= self.threshold && curr < self.threshold,
155 _ => false,
156 }
157 }
158
159 fn required_indicators(&self) -> Vec<(String, Indicator)> {
160 self.indicator.required_indicators()
161 }
162
163 fn description(&self) -> String {
164 format!(
165 "{} crosses below {:.2}",
166 self.indicator.key(),
167 self.threshold
168 )
169 }
170}
171
172#[derive(Clone)]
176pub struct Between<R: IndicatorRef> {
177 indicator: R,
178 low: f64,
179 high: f64,
180}
181
182impl<R: IndicatorRef> Between<R> {
183 pub fn new(indicator: R, low: f64, high: f64) -> Self {
185 Self {
186 indicator,
187 low,
188 high,
189 }
190 }
191}
192
193impl<R: IndicatorRef> Condition for Between<R> {
194 fn evaluate(&self, ctx: &StrategyContext) -> bool {
195 self.indicator
196 .value(ctx)
197 .map(|v| v > self.low && v < self.high)
198 .unwrap_or(false)
199 }
200
201 fn required_indicators(&self) -> Vec<(String, Indicator)> {
202 self.indicator.required_indicators()
203 }
204
205 fn description(&self) -> String {
206 format!(
207 "{:.2} < {} < {:.2}",
208 self.low,
209 self.indicator.key(),
210 self.high
211 )
212 }
213}
214
215#[derive(Clone)]
217pub struct Equals<R: IndicatorRef> {
218 indicator: R,
219 value: f64,
220 tolerance: f64,
221}
222
223impl<R: IndicatorRef> Equals<R> {
224 pub fn new(indicator: R, value: f64, tolerance: f64) -> Self {
226 Self {
227 indicator,
228 value,
229 tolerance,
230 }
231 }
232}
233
234impl<R: IndicatorRef> Condition for Equals<R> {
235 fn evaluate(&self, ctx: &StrategyContext) -> bool {
236 self.indicator
237 .value(ctx)
238 .map(|v| (v - self.value).abs() <= self.tolerance)
239 .unwrap_or(false)
240 }
241
242 fn required_indicators(&self) -> Vec<(String, Indicator)> {
243 self.indicator.required_indicators()
244 }
245
246 fn description(&self) -> String {
247 format!(
248 "{} ≈ {:.2} (±{:.4})",
249 self.indicator.key(),
250 self.value,
251 self.tolerance
252 )
253 }
254}
255
256#[derive(Clone)]
262pub struct AboveRef<R1: IndicatorRef, R2: IndicatorRef> {
263 indicator: R1,
264 other: R2,
265}
266
267impl<R1: IndicatorRef, R2: IndicatorRef> AboveRef<R1, R2> {
268 pub fn new(indicator: R1, other: R2) -> Self {
270 Self { indicator, other }
271 }
272}
273
274impl<R1: IndicatorRef, R2: IndicatorRef> Condition for AboveRef<R1, R2> {
275 fn evaluate(&self, ctx: &StrategyContext) -> bool {
276 let v1 = self.indicator.value(ctx);
277 let v2 = self.other.value(ctx);
278
279 match (v1, v2) {
280 (Some(a), Some(b)) => a > b,
281 _ => false,
282 }
283 }
284
285 fn required_indicators(&self) -> Vec<(String, Indicator)> {
286 let mut indicators = self.indicator.required_indicators();
287 indicators.extend(self.other.required_indicators());
288 indicators
289 }
290
291 fn description(&self) -> String {
292 format!("{} > {}", self.indicator.key(), self.other.key())
293 }
294}
295
296#[derive(Clone)]
298pub struct BelowRef<R1: IndicatorRef, R2: IndicatorRef> {
299 indicator: R1,
300 other: R2,
301}
302
303impl<R1: IndicatorRef, R2: IndicatorRef> BelowRef<R1, R2> {
304 pub fn new(indicator: R1, other: R2) -> Self {
306 Self { indicator, other }
307 }
308}
309
310impl<R1: IndicatorRef, R2: IndicatorRef> Condition for BelowRef<R1, R2> {
311 fn evaluate(&self, ctx: &StrategyContext) -> bool {
312 let v1 = self.indicator.value(ctx);
313 let v2 = self.other.value(ctx);
314
315 match (v1, v2) {
316 (Some(a), Some(b)) => a < b,
317 _ => false,
318 }
319 }
320
321 fn required_indicators(&self) -> Vec<(String, Indicator)> {
322 let mut indicators = self.indicator.required_indicators();
323 indicators.extend(self.other.required_indicators());
324 indicators
325 }
326
327 fn description(&self) -> String {
328 format!("{} < {}", self.indicator.key(), self.other.key())
329 }
330}
331
332#[derive(Clone)]
337pub struct CrossesAboveRef<R1: IndicatorRef, R2: IndicatorRef> {
338 fast: R1,
339 slow: R2,
340}
341
342impl<R1: IndicatorRef, R2: IndicatorRef> CrossesAboveRef<R1, R2> {
343 pub fn new(fast: R1, slow: R2) -> Self {
345 Self { fast, slow }
346 }
347}
348
349impl<R1: IndicatorRef, R2: IndicatorRef> Condition for CrossesAboveRef<R1, R2> {
350 fn evaluate(&self, ctx: &StrategyContext) -> bool {
351 let fast_now = self.fast.value(ctx);
352 let slow_now = self.slow.value(ctx);
353 let fast_prev = self.fast.prev_value(ctx);
354 let slow_prev = self.slow.prev_value(ctx);
355
356 match (fast_now, slow_now, fast_prev, slow_prev) {
357 (Some(fn_), Some(sn), Some(fp), Some(sp)) => fp <= sp && fn_ > sn,
358 _ => false,
359 }
360 }
361
362 fn required_indicators(&self) -> Vec<(String, Indicator)> {
363 let mut indicators = self.fast.required_indicators();
364 indicators.extend(self.slow.required_indicators());
365 indicators
366 }
367
368 fn description(&self) -> String {
369 format!("{} crosses above {}", self.fast.key(), self.slow.key())
370 }
371}
372
373#[derive(Clone)]
378pub struct CrossesBelowRef<R1: IndicatorRef, R2: IndicatorRef> {
379 fast: R1,
380 slow: R2,
381}
382
383impl<R1: IndicatorRef, R2: IndicatorRef> CrossesBelowRef<R1, R2> {
384 pub fn new(fast: R1, slow: R2) -> Self {
386 Self { fast, slow }
387 }
388}
389
390impl<R1: IndicatorRef, R2: IndicatorRef> Condition for CrossesBelowRef<R1, R2> {
391 fn evaluate(&self, ctx: &StrategyContext) -> bool {
392 let fast_now = self.fast.value(ctx);
393 let slow_now = self.slow.value(ctx);
394 let fast_prev = self.fast.prev_value(ctx);
395 let slow_prev = self.slow.prev_value(ctx);
396
397 match (fast_now, slow_now, fast_prev, slow_prev) {
398 (Some(fn_), Some(sn), Some(fp), Some(sp)) => fp >= sp && fn_ < sn,
399 _ => false,
400 }
401 }
402
403 fn required_indicators(&self) -> Vec<(String, Indicator)> {
404 let mut indicators = self.fast.required_indicators();
405 indicators.extend(self.slow.required_indicators());
406 indicators
407 }
408
409 fn description(&self) -> String {
410 format!("{} crosses below {}", self.fast.key(), self.slow.key())
411 }
412}
413
414#[cfg(test)]
415mod tests {
416 use super::*;
417 use crate::backtesting::refs::{rsi, sma};
418
419 #[test]
420 fn test_above_description() {
421 let cond = Above::new(rsi(14), 70.0);
422 assert_eq!(cond.description(), "rsi_14 > 70.00");
423 }
424
425 #[test]
426 fn test_below_description() {
427 let cond = Below::new(rsi(14), 30.0);
428 assert_eq!(cond.description(), "rsi_14 < 30.00");
429 }
430
431 #[test]
432 fn test_crosses_above_description() {
433 let cond = CrossesAbove::new(rsi(14), 30.0);
434 assert_eq!(cond.description(), "rsi_14 crosses above 30.00");
435 }
436
437 #[test]
438 fn test_crosses_below_description() {
439 let cond = CrossesBelow::new(rsi(14), 70.0);
440 assert_eq!(cond.description(), "rsi_14 crosses below 70.00");
441 }
442
443 #[test]
444 fn test_between_description() {
445 let cond = Between::new(rsi(14), 30.0, 70.0);
446 assert_eq!(cond.description(), "30.00 < rsi_14 < 70.00");
447 }
448
449 #[test]
450 fn test_above_ref_description() {
451 let cond = AboveRef::new(sma(10), sma(20));
452 assert_eq!(cond.description(), "sma_10 > sma_20");
453 }
454
455 #[test]
456 fn test_crosses_above_ref_description() {
457 let cond = CrossesAboveRef::new(sma(50), sma(200));
458 assert_eq!(cond.description(), "sma_50 crosses above sma_200");
459 }
460
461 #[test]
462 fn test_required_indicators() {
463 let cond = Above::new(rsi(14), 70.0);
464 let indicators = cond.required_indicators();
465 assert_eq!(indicators.len(), 1);
466 assert_eq!(indicators[0].0, "rsi_14");
467 }
468
469 #[test]
470 fn test_cross_ref_required_indicators() {
471 let cond = CrossesAboveRef::new(sma(10), sma(20));
472 let indicators = cond.required_indicators();
473 assert_eq!(indicators.len(), 2);
474 }
475}