Trend-following strategy using simple moving averages
The Moving Average Crossover strategy generates buy and sell signals based on the relationship between short-term and long-term moving averages. Itβs a classic trend-following approach.
if let (Some(short), Some(long)) = (short_ma, long_ma) { let current_signal = if short > long { Some(Signal::Buy) } else if short < long { Some(Signal::Sell) } else { None }; // Check for signal change if current_signal != self.last_signal { match current_signal { Some(Signal::Buy) => { // Close any short positions // Open long position }, Some(Signal::Sell) => { // Close any long positions // Open short position }, None => {} } self.last_signal = current_signal; }}
From crates/gb-types/examples/basic_usage.rs:131-141:
let mut ma_strategy = MovingAverageCrossoverStrategy::new(5, 20);let mut ma_config = StrategyConfig::new( "ma_crossover".to_string(), "MA Crossover".to_string());ma_config.add_symbol(symbol.clone());ma_config.set_parameter("position_size", 0.90f64);if let Ok(()) = ma_strategy.initialize(&ma_config) { println!(" β’ Initialized: 5-day vs 20-day moving average crossover"); println!(" β’ Position size: 90% of capital");}
#[test]fn test_moving_average_crossover_strategy() { let mut strategy = MovingAverageCrossoverStrategy::new(5, 10); let mut config = StrategyConfig::new( "test_ma".to_string(), "Test MA Crossover".to_string() ); config.add_symbol(create_test_symbol()); assert!(strategy.initialize(&config).is_ok()); // Create test data with upward trend let mut bars = Vec::new(); let base_time = Utc::now(); for i in 0..15 { let price = dec!(100) + Decimal::from(i); // Increasing prices let bar = create_test_bar(price, base_time + chrono::Duration::days(i)); bars.push(bar); } let context = create_test_context_with_data(bars); // Test market event processing let actions = strategy.on_market_event(&event, &context); assert!(actions.is_ok()); // Should generate buy signal as short MA crosses above long MA}