1use crate::backtesting::strategy::StrategyContext;
2use crate::indicators::Indicator;
3
4use super::IndicatorRef;
5
6#[derive(Debug, Clone)]
8pub struct AtrRef {
9 pub period: usize,
10 key: String,
11}
12
13impl IndicatorRef for AtrRef {
14 fn key(&self) -> &str {
15 &self.key
16 }
17
18 fn required_indicators(&self) -> Vec<(String, Indicator)> {
19 vec![(self.key.clone(), Indicator::Atr(self.period))]
20 }
21
22 fn value(&self, ctx: &StrategyContext) -> Option<f64> {
23 ctx.indicator(self.key())
24 }
25
26 fn prev_value(&self, ctx: &StrategyContext) -> Option<f64> {
27 ctx.indicator_prev(self.key())
28 }
29}
30
31#[inline]
33pub fn atr(period: usize) -> AtrRef {
34 AtrRef {
35 period,
36 key: format!("atr_{period}"),
37 }
38}
39
40#[derive(Debug, Clone, Copy)]
42pub struct TrueRangeRef;
43
44#[inline]
46pub fn true_range() -> TrueRangeRef {
47 TrueRangeRef
48}
49
50impl IndicatorRef for TrueRangeRef {
51 fn key(&self) -> &str {
52 "true_range"
53 }
54
55 fn required_indicators(&self) -> Vec<(String, Indicator)> {
56 vec![("true_range".to_string(), Indicator::TrueRange)]
57 }
58
59 fn value(&self, ctx: &StrategyContext) -> Option<f64> {
60 ctx.indicator(self.key())
61 }
62
63 fn prev_value(&self, ctx: &StrategyContext) -> Option<f64> {
64 ctx.indicator_prev(self.key())
65 }
66}
67
68#[derive(Debug, Clone, Copy)]
70pub struct BollingerConfig {
71 pub period: usize,
73 pub std_dev: f64,
75}
76
77impl BollingerConfig {
78 pub fn upper(&self) -> BollingerUpperRef {
80 BollingerUpperRef::new(self.period, self.std_dev)
81 }
82
83 pub fn middle(&self) -> BollingerMiddleRef {
85 BollingerMiddleRef::new(self.period, self.std_dev)
86 }
87
88 pub fn lower(&self) -> BollingerLowerRef {
90 BollingerLowerRef::new(self.period, self.std_dev)
91 }
92}
93
94#[inline]
106pub fn bollinger(period: usize, std_dev: f64) -> BollingerConfig {
107 BollingerConfig { period, std_dev }
108}
109
110#[derive(Debug, Clone)]
112pub struct BollingerUpperRef {
113 pub period: usize,
115 pub std_dev: f64,
117 key: String,
118}
119
120impl BollingerUpperRef {
121 fn new(period: usize, std_dev: f64) -> Self {
122 Self {
123 period,
124 std_dev,
125 key: format!("bollinger_upper_{period}_{std_dev}"),
126 }
127 }
128}
129
130impl IndicatorRef for BollingerUpperRef {
131 fn key(&self) -> &str {
132 &self.key
133 }
134
135 fn required_indicators(&self) -> Vec<(String, Indicator)> {
136 vec![(
137 self.key.clone(),
138 Indicator::Bollinger {
139 period: self.period,
140 std_dev: self.std_dev,
141 },
142 )]
143 }
144
145 fn value(&self, ctx: &StrategyContext) -> Option<f64> {
146 ctx.indicator(self.key())
147 }
148
149 fn prev_value(&self, ctx: &StrategyContext) -> Option<f64> {
150 ctx.indicator_prev(self.key())
151 }
152}
153
154#[derive(Debug, Clone)]
156pub struct BollingerMiddleRef {
157 pub period: usize,
159 pub std_dev: f64,
161 key: String,
162}
163
164impl BollingerMiddleRef {
165 fn new(period: usize, std_dev: f64) -> Self {
166 Self {
167 period,
168 std_dev,
169 key: format!("bollinger_middle_{period}_{std_dev}"),
170 }
171 }
172}
173
174impl IndicatorRef for BollingerMiddleRef {
175 fn key(&self) -> &str {
176 &self.key
177 }
178
179 fn required_indicators(&self) -> Vec<(String, Indicator)> {
180 vec![(
181 self.key.clone(),
182 Indicator::Bollinger {
183 period: self.period,
184 std_dev: self.std_dev,
185 },
186 )]
187 }
188
189 fn value(&self, ctx: &StrategyContext) -> Option<f64> {
190 ctx.indicator(self.key())
191 }
192
193 fn prev_value(&self, ctx: &StrategyContext) -> Option<f64> {
194 ctx.indicator_prev(self.key())
195 }
196}
197
198#[derive(Debug, Clone)]
200pub struct BollingerLowerRef {
201 pub period: usize,
203 pub std_dev: f64,
205 key: String,
206}
207
208impl BollingerLowerRef {
209 fn new(period: usize, std_dev: f64) -> Self {
210 Self {
211 period,
212 std_dev,
213 key: format!("bollinger_lower_{period}_{std_dev}"),
214 }
215 }
216}
217
218impl IndicatorRef for BollingerLowerRef {
219 fn key(&self) -> &str {
220 &self.key
221 }
222
223 fn required_indicators(&self) -> Vec<(String, Indicator)> {
224 vec![(
225 self.key.clone(),
226 Indicator::Bollinger {
227 period: self.period,
228 std_dev: self.std_dev,
229 },
230 )]
231 }
232
233 fn value(&self, ctx: &StrategyContext) -> Option<f64> {
234 ctx.indicator(self.key())
235 }
236
237 fn prev_value(&self, ctx: &StrategyContext) -> Option<f64> {
238 ctx.indicator_prev(self.key())
239 }
240}
241
242#[derive(Debug, Clone, Copy)]
244pub struct DonchianConfig {
245 pub period: usize,
246}
247
248impl DonchianConfig {
249 pub fn upper(&self) -> DonchianUpperRef {
251 DonchianUpperRef::new(self.period)
252 }
253
254 pub fn middle(&self) -> DonchianMiddleRef {
256 DonchianMiddleRef::new(self.period)
257 }
258
259 pub fn lower(&self) -> DonchianLowerRef {
261 DonchianLowerRef::new(self.period)
262 }
263}
264
265#[inline]
267pub fn donchian(period: usize) -> DonchianConfig {
268 DonchianConfig { period }
269}
270
271#[derive(Debug, Clone)]
273pub struct DonchianUpperRef {
274 pub period: usize,
275 key: String,
276}
277
278impl DonchianUpperRef {
279 fn new(period: usize) -> Self {
280 Self {
281 period,
282 key: format!("donchian_upper_{period}"),
283 }
284 }
285}
286
287impl IndicatorRef for DonchianUpperRef {
288 fn key(&self) -> &str {
289 &self.key
290 }
291
292 fn required_indicators(&self) -> Vec<(String, Indicator)> {
293 vec![(self.key.clone(), Indicator::DonchianChannels(self.period))]
294 }
295
296 fn value(&self, ctx: &StrategyContext) -> Option<f64> {
297 ctx.indicator(self.key())
298 }
299
300 fn prev_value(&self, ctx: &StrategyContext) -> Option<f64> {
301 ctx.indicator_prev(self.key())
302 }
303}
304
305#[derive(Debug, Clone)]
307pub struct DonchianMiddleRef {
308 pub period: usize,
309 key: String,
310}
311
312impl DonchianMiddleRef {
313 fn new(period: usize) -> Self {
314 Self {
315 period,
316 key: format!("donchian_middle_{period}"),
317 }
318 }
319}
320
321impl IndicatorRef for DonchianMiddleRef {
322 fn key(&self) -> &str {
323 &self.key
324 }
325
326 fn required_indicators(&self) -> Vec<(String, Indicator)> {
327 vec![(self.key.clone(), Indicator::DonchianChannels(self.period))]
328 }
329
330 fn value(&self, ctx: &StrategyContext) -> Option<f64> {
331 ctx.indicator(self.key())
332 }
333
334 fn prev_value(&self, ctx: &StrategyContext) -> Option<f64> {
335 ctx.indicator_prev(self.key())
336 }
337}
338
339#[derive(Debug, Clone)]
341pub struct DonchianLowerRef {
342 pub period: usize,
343 key: String,
344}
345
346impl DonchianLowerRef {
347 fn new(period: usize) -> Self {
348 Self {
349 period,
350 key: format!("donchian_lower_{period}"),
351 }
352 }
353}
354
355impl IndicatorRef for DonchianLowerRef {
356 fn key(&self) -> &str {
357 &self.key
358 }
359
360 fn required_indicators(&self) -> Vec<(String, Indicator)> {
361 vec![(self.key.clone(), Indicator::DonchianChannels(self.period))]
362 }
363
364 fn value(&self, ctx: &StrategyContext) -> Option<f64> {
365 ctx.indicator(self.key())
366 }
367
368 fn prev_value(&self, ctx: &StrategyContext) -> Option<f64> {
369 ctx.indicator_prev(self.key())
370 }
371}
372
373#[derive(Debug, Clone, Copy)]
375pub struct KeltnerConfig {
376 pub period: usize,
377 pub multiplier: f64,
378 pub atr_period: usize,
379}
380
381impl KeltnerConfig {
382 pub fn upper(&self) -> KeltnerUpperRef {
384 KeltnerUpperRef::new(self.period, self.multiplier, self.atr_period)
385 }
386
387 pub fn middle(&self) -> KeltnerMiddleRef {
389 KeltnerMiddleRef::new(self.period, self.multiplier, self.atr_period)
390 }
391
392 pub fn lower(&self) -> KeltnerLowerRef {
394 KeltnerLowerRef::new(self.period, self.multiplier, self.atr_period)
395 }
396}
397
398#[inline]
400pub fn keltner(period: usize, multiplier: f64, atr_period: usize) -> KeltnerConfig {
401 KeltnerConfig {
402 period,
403 multiplier,
404 atr_period,
405 }
406}
407
408#[derive(Debug, Clone)]
410pub struct KeltnerUpperRef {
411 pub period: usize,
412 pub multiplier: f64,
413 pub atr_period: usize,
414 key: String,
415}
416
417impl KeltnerUpperRef {
418 fn new(period: usize, multiplier: f64, atr_period: usize) -> Self {
419 Self {
420 period,
421 multiplier,
422 atr_period,
423 key: format!("keltner_upper_{period}_{multiplier}_{atr_period}"),
424 }
425 }
426}
427
428impl IndicatorRef for KeltnerUpperRef {
429 fn key(&self) -> &str {
430 &self.key
431 }
432
433 fn required_indicators(&self) -> Vec<(String, Indicator)> {
434 vec![(
435 self.key.clone(),
436 Indicator::KeltnerChannels {
437 period: self.period,
438 multiplier: self.multiplier,
439 atr_period: self.atr_period,
440 },
441 )]
442 }
443
444 fn value(&self, ctx: &StrategyContext) -> Option<f64> {
445 ctx.indicator(self.key())
446 }
447
448 fn prev_value(&self, ctx: &StrategyContext) -> Option<f64> {
449 ctx.indicator_prev(self.key())
450 }
451}
452
453#[derive(Debug, Clone)]
455pub struct KeltnerMiddleRef {
456 pub period: usize,
457 pub multiplier: f64,
458 pub atr_period: usize,
459 key: String,
460}
461
462impl KeltnerMiddleRef {
463 fn new(period: usize, multiplier: f64, atr_period: usize) -> Self {
464 Self {
465 period,
466 multiplier,
467 atr_period,
468 key: format!("keltner_middle_{period}_{multiplier}_{atr_period}"),
469 }
470 }
471}
472
473impl IndicatorRef for KeltnerMiddleRef {
474 fn key(&self) -> &str {
475 &self.key
476 }
477
478 fn required_indicators(&self) -> Vec<(String, Indicator)> {
479 vec![(
480 self.key.clone(),
481 Indicator::KeltnerChannels {
482 period: self.period,
483 multiplier: self.multiplier,
484 atr_period: self.atr_period,
485 },
486 )]
487 }
488
489 fn value(&self, ctx: &StrategyContext) -> Option<f64> {
490 ctx.indicator(self.key())
491 }
492
493 fn prev_value(&self, ctx: &StrategyContext) -> Option<f64> {
494 ctx.indicator_prev(self.key())
495 }
496}
497
498#[derive(Debug, Clone)]
500pub struct KeltnerLowerRef {
501 pub period: usize,
502 pub multiplier: f64,
503 pub atr_period: usize,
504 key: String,
505}
506
507impl KeltnerLowerRef {
508 fn new(period: usize, multiplier: f64, atr_period: usize) -> Self {
509 Self {
510 period,
511 multiplier,
512 atr_period,
513 key: format!("keltner_lower_{period}_{multiplier}_{atr_period}"),
514 }
515 }
516}
517
518impl IndicatorRef for KeltnerLowerRef {
519 fn key(&self) -> &str {
520 &self.key
521 }
522
523 fn required_indicators(&self) -> Vec<(String, Indicator)> {
524 vec![(
525 self.key.clone(),
526 Indicator::KeltnerChannels {
527 period: self.period,
528 multiplier: self.multiplier,
529 atr_period: self.atr_period,
530 },
531 )]
532 }
533
534 fn value(&self, ctx: &StrategyContext) -> Option<f64> {
535 ctx.indicator(self.key())
536 }
537
538 fn prev_value(&self, ctx: &StrategyContext) -> Option<f64> {
539 ctx.indicator_prev(self.key())
540 }
541}
542
543#[cfg(test)]
544mod tests {
545 use super::*;
546
547 #[test]
548 fn test_bollinger_keys() {
549 let bb = bollinger(20, 2.0);
550 assert_eq!(bb.upper().key(), "bollinger_upper_20_2");
551 assert_eq!(bb.middle().key(), "bollinger_middle_20_2");
552 assert_eq!(bb.lower().key(), "bollinger_lower_20_2");
553 }
554
555 #[test]
556 fn test_donchian_keys() {
557 let dc = donchian(20);
558 assert_eq!(dc.upper().key(), "donchian_upper_20");
559 assert_eq!(dc.middle().key(), "donchian_middle_20");
560 assert_eq!(dc.lower().key(), "donchian_lower_20");
561 }
562
563 #[test]
564 fn test_keltner_keys() {
565 let kc = keltner(20, 2.0, 10);
566 assert_eq!(kc.upper().key(), "keltner_upper_20_2_10");
567 assert_eq!(kc.middle().key(), "keltner_middle_20_2_10");
568 assert_eq!(kc.lower().key(), "keltner_lower_20_2_10");
569 }
570}