//! Sample data for AlgoArena demos. use algoarena_shared::{AgentConfig, AgentParameters, AssetConfig, StrategyType, TournamentConfig}; /// Create a sample tournament configuration. #[must_use] pub fn create_sample_tournament() -> TournamentConfig { TournamentConfig { name: "Strategy Showdown 2026".to_string(), num_steps: 252, // One trading year assets: create_diverse_assets(), agents: create_competing_agents(), transaction_cost_bps: 10.0, seed: Some(42), } } /// Create a diverse set of assets for trading. #[must_use] pub fn create_diverse_assets() -> Vec { vec![ AssetConfig { symbol: "SPY".to_string(), initial_price: 500.0, volatility: 0.012, // ~19% annual drift: 0.0003, // ~7.5% annual }, AssetConfig { symbol: "QQQ".to_string(), initial_price: 450.0, volatility: 0.015, // ~24% annual drift: 0.0004, // ~10% annual }, AssetConfig { symbol: "TLT".to_string(), initial_price: 95.0, volatility: 0.010, // ~16% annual drift: 0.0001, // ~2.5% annual }, AssetConfig { symbol: "GLD".to_string(), initial_price: 200.0, volatility: 0.008, // ~13% annual drift: 0.0002, // ~5% annual }, ] } /// Create a set of competing agents with different strategies. #[must_use] pub fn create_competing_agents() -> Vec { vec![ // Momentum Strategies AgentConfig { id: "momentum_fast".to_string(), name: "Fast Momentum".to_string(), strategy: StrategyType::Momentum, initial_capital: 100_000.0, parameters: AgentParameters { lookback: 10, momentum_threshold: 0.015, position_size: 0.15, ..Default::default() }, }, AgentConfig { id: "momentum_slow".to_string(), name: "Slow Momentum".to_string(), strategy: StrategyType::Momentum, initial_capital: 100_000.0, parameters: AgentParameters { lookback: 30, momentum_threshold: 0.03, position_size: 0.2, ..Default::default() }, }, // Mean Reversion Strategies AgentConfig { id: "reversion_tight".to_string(), name: "Tight Reverter".to_string(), strategy: StrategyType::MeanReversion, initial_capital: 100_000.0, parameters: AgentParameters { lookback: 15, reversion_threshold: 1.5, position_size: 0.1, ..Default::default() }, }, AgentConfig { id: "reversion_wide".to_string(), name: "Wide Reverter".to_string(), strategy: StrategyType::MeanReversion, initial_capital: 100_000.0, parameters: AgentParameters { lookback: 30, reversion_threshold: 2.5, position_size: 0.15, ..Default::default() }, }, // Trend Following Strategies AgentConfig { id: "trend_classic".to_string(), name: "Classic Trend".to_string(), strategy: StrategyType::TrendFollowing, initial_capital: 100_000.0, parameters: AgentParameters { short_ma_period: 10, long_ma_period: 50, position_size: 0.15, ..Default::default() }, }, AgentConfig { id: "trend_fast".to_string(), name: "Fast Trend".to_string(), strategy: StrategyType::TrendFollowing, initial_capital: 100_000.0, parameters: AgentParameters { short_ma_period: 5, long_ma_period: 20, position_size: 0.2, ..Default::default() }, }, // Passive Strategy AgentConfig { id: "buyhold".to_string(), name: "Buy & Hold".to_string(), strategy: StrategyType::BuyAndHold, initial_capital: 100_000.0, parameters: AgentParameters::default(), }, // Random Baseline AgentConfig { id: "random".to_string(), name: "Random Walker".to_string(), strategy: StrategyType::Random, initial_capital: 100_000.0, parameters: AgentParameters::default(), }, ] } /// Create a quick demo tournament (fewer steps for testing). #[must_use] pub fn create_quick_tournament() -> TournamentConfig { TournamentConfig { name: "Quick Demo".to_string(), num_steps: 50, // ~2 months assets: vec![ AssetConfig { symbol: "SPY".to_string(), initial_price: 500.0, volatility: 0.012, drift: 0.0003, }, AssetConfig { symbol: "QQQ".to_string(), initial_price: 450.0, volatility: 0.015, drift: 0.0004, }, ], agents: vec![ AgentConfig { id: "momentum".to_string(), name: "Momentum".to_string(), strategy: StrategyType::Momentum, initial_capital: 100_000.0, parameters: AgentParameters::default(), }, AgentConfig { id: "reversion".to_string(), name: "Mean Reversion".to_string(), strategy: StrategyType::MeanReversion, initial_capital: 100_000.0, parameters: AgentParameters::default(), }, AgentConfig { id: "buyhold".to_string(), name: "Buy & Hold".to_string(), strategy: StrategyType::BuyAndHold, initial_capital: 100_000.0, parameters: AgentParameters::default(), }, ], transaction_cost_bps: 10.0, seed: Some(42), } } /// Create a high-volatility tournament. #[must_use] pub fn create_volatile_tournament() -> TournamentConfig { TournamentConfig { name: "Volatility Challenge".to_string(), num_steps: 100, assets: vec![ AssetConfig { symbol: "CRYPTO".to_string(), initial_price: 50000.0, volatility: 0.04, // ~63% annual drift: 0.001, // ~25% annual }, AssetConfig { symbol: "MEME".to_string(), initial_price: 10.0, volatility: 0.08, // ~127% annual drift: 0.0, // No drift }, ], agents: create_competing_agents(), transaction_cost_bps: 25.0, // Higher costs seed: Some(123), } } /// Create a low-volatility tournament. #[must_use] pub fn create_stable_tournament() -> TournamentConfig { TournamentConfig { name: "Stability Test".to_string(), num_steps: 200, assets: vec![ AssetConfig { symbol: "BOND1".to_string(), initial_price: 100.0, volatility: 0.003, // ~5% annual drift: 0.0001, // ~2.5% annual }, AssetConfig { symbol: "BOND2".to_string(), initial_price: 100.0, volatility: 0.004, // ~6% annual drift: 0.00015, // ~3.8% annual }, ], agents: vec![ AgentConfig { id: "reversion".to_string(), name: "Mean Reversion".to_string(), strategy: StrategyType::MeanReversion, initial_capital: 100_000.0, parameters: AgentParameters { reversion_threshold: 1.0, // Tighter for low vol ..Default::default() }, }, AgentConfig { id: "trend".to_string(), name: "Trend Following".to_string(), strategy: StrategyType::TrendFollowing, initial_capital: 100_000.0, parameters: AgentParameters::default(), }, AgentConfig { id: "buyhold".to_string(), name: "Buy & Hold".to_string(), strategy: StrategyType::BuyAndHold, initial_capital: 100_000.0, parameters: AgentParameters::default(), }, ], transaction_cost_bps: 5.0, // Lower costs for bonds seed: Some(456), } } #[cfg(test)] mod tests { use super::*; #[test] fn test_sample_tournament() { let config = create_sample_tournament(); assert_eq!(config.num_steps, 252); assert!(!config.assets.is_empty()); assert!(!config.agents.is_empty()); } #[test] fn test_diverse_assets() { let assets = create_diverse_assets(); assert_eq!(assets.len(), 4); // Check all have positive prices for asset in &assets { assert!(asset.initial_price > 0.0); assert!(asset.volatility > 0.0); } } #[test] fn test_competing_agents() { let agents = create_competing_agents(); assert_eq!(agents.len(), 8); // Check all have positive capital for agent in &agents { assert!(agent.initial_capital > 0.0); } // Check unique IDs let ids: Vec<_> = agents.iter().map(|a| &a.id).collect(); let unique_ids: std::collections::HashSet<_> = ids.iter().collect(); assert_eq!(ids.len(), unique_ids.len()); } #[test] fn test_quick_tournament() { let config = create_quick_tournament(); assert_eq!(config.num_steps, 50); assert_eq!(config.agents.len(), 3); } #[test] fn test_volatile_tournament() { let config = create_volatile_tournament(); assert!(config.assets[0].volatility > 0.03); // High volatility } #[test] fn test_stable_tournament() { let config = create_stable_tournament(); assert!(config.assets[0].volatility < 0.01); // Low volatility } #[test] fn test_strategy_diversity() { let agents = create_competing_agents(); let strategies: std::collections::HashSet<_> = agents.iter().map(|a| a.strategy).collect(); assert!(strategies.contains(&StrategyType::Momentum)); assert!(strategies.contains(&StrategyType::MeanReversion)); assert!(strategies.contains(&StrategyType::TrendFollowing)); assert!(strategies.contains(&StrategyType::BuyAndHold)); assert!(strategies.contains(&StrategyType::Random)); } }