use std::collections::VecDeque;
use crate::strategy_engine::Strategy;
#[derive(Debug, Clone)]
pub struct TrendFollowing {
pub short_window: VecDeque<f64>,
pub long_window: VecDeque<f64>,
pub short_window_size: usize,
pub long_window_size: usize,
}
impl TrendFollowing {
pub fn new(short_window_size: usize, long_window_size: usize) -> Self {
Self {
short_window: VecDeque::with_capacity(short_window_size),
long_window: VecDeque::with_capacity(long_window_size),
short_window_size,
long_window_size,
}
}
pub fn update_price(&mut self, price: f64) {
self.short_window.push_back(price);
self.long_window.push_back(price);
if self.short_window.len() > self.short_window_size {
self.short_window.pop_front();
}
if self.long_window.len() > self.long_window_size {
self.long_window.pop_front();
}
}
}
impl Strategy for TrendFollowing {
fn evaluate(&self, _price: &f64) -> f64 {
if self.short_window.len() < self.short_window_size || self.long_window.len() < self.long_window_size {
return 0.0; }
let short_avg = self.short_window.iter().sum::<f64>() / self.short_window_size as f64;
let long_avg = self.long_window.iter().sum::<f64>() / self.long_window_size as f64;
if short_avg > long_avg {
1.0 } else if short_avg < long_avg {
-1.0 } else {
0.0 }
}
fn calculate_indicator(&self, prices: &Vec<f64>) -> f64 {
let mut total_return = 1.0;
for price in prices {
let signal = self.evaluate(price);
if signal > 0.0 {
total_return *= 1.0 + (*price / prices[0]) - 1.0; } else if signal < 0.0 {
total_return *= 1.0 - (*price / prices[0]) + 1.0; }
}
total_return - 1.0 }
}