//! Sample asset data generation use crate::{Asset, PortfolioPreset, Result}; /// Available sample presets pub const SAMPLE_PRESETS: &[PortfolioPreset] = &[ PortfolioPreset::Conservative, PortfolioPreset::Balanced, PortfolioPreset::Aggressive, PortfolioPreset::GlobalDiversified, PortfolioPreset::TechFocus, ]; /// Generate sample assets for a given preset pub fn generate_sample_assets(preset: PortfolioPreset) -> Result> { let assets = match preset { PortfolioPreset::Conservative => conservative_portfolio(), PortfolioPreset::Balanced => balanced_portfolio(), PortfolioPreset::Aggressive => aggressive_portfolio(), PortfolioPreset::GlobalDiversified => global_diversified_portfolio(), PortfolioPreset::TechFocus => tech_focus_portfolio(), }; Ok(assets) } fn conservative_portfolio() -> Vec { vec![ Asset { ticker: "BND".to_string(), name: "Vanguard Total Bond Market ETF".to_string(), asset_class: "bond".to_string(), sector: Some("Fixed Income".to_string()), expected_return: 0.03, volatility: 0.04, }, Asset { ticker: "TLT".to_string(), name: "iShares 20+ Year Treasury Bond ETF".to_string(), asset_class: "bond".to_string(), sector: Some("Fixed Income".to_string()), expected_return: 0.04, volatility: 0.12, }, Asset { ticker: "VNQ".to_string(), name: "Vanguard Real Estate ETF".to_string(), asset_class: "equity".to_string(), sector: Some("Real Estate".to_string()), expected_return: 0.06, volatility: 0.18, }, Asset { ticker: "GLD".to_string(), name: "SPDR Gold Trust".to_string(), asset_class: "commodity".to_string(), sector: Some("Precious Metals".to_string()), expected_return: 0.04, volatility: 0.15, }, ] } fn balanced_portfolio() -> Vec { vec![ Asset { ticker: "SPY".to_string(), name: "SPDR S&P 500 ETF".to_string(), asset_class: "equity".to_string(), sector: Some("Broad Market".to_string()), expected_return: 0.10, volatility: 0.16, }, Asset { ticker: "BND".to_string(), name: "Vanguard Total Bond Market ETF".to_string(), asset_class: "bond".to_string(), sector: Some("Fixed Income".to_string()), expected_return: 0.03, volatility: 0.04, }, Asset { ticker: "VNQ".to_string(), name: "Vanguard Real Estate ETF".to_string(), asset_class: "equity".to_string(), sector: Some("Real Estate".to_string()), expected_return: 0.06, volatility: 0.18, }, Asset { ticker: "GLD".to_string(), name: "SPDR Gold Trust".to_string(), asset_class: "commodity".to_string(), sector: Some("Precious Metals".to_string()), expected_return: 0.04, volatility: 0.15, }, Asset { ticker: "VWO".to_string(), name: "Vanguard FTSE Emerging Markets ETF".to_string(), asset_class: "equity".to_string(), sector: Some("Emerging Markets".to_string()), expected_return: 0.08, volatility: 0.22, }, ] } fn aggressive_portfolio() -> Vec { vec![ Asset { ticker: "SPY".to_string(), name: "SPDR S&P 500 ETF".to_string(), asset_class: "equity".to_string(), sector: Some("Broad Market".to_string()), expected_return: 0.10, volatility: 0.16, }, Asset { ticker: "QQQ".to_string(), name: "Invesco QQQ Trust".to_string(), asset_class: "equity".to_string(), sector: Some("Technology".to_string()), expected_return: 0.13, volatility: 0.20, }, Asset { ticker: "VWO".to_string(), name: "Vanguard FTSE Emerging Markets ETF".to_string(), asset_class: "equity".to_string(), sector: Some("Emerging Markets".to_string()), expected_return: 0.12, volatility: 0.25, }, Asset { ticker: "IWM".to_string(), name: "iShares Russell 2000 ETF".to_string(), asset_class: "equity".to_string(), sector: Some("Small Cap".to_string()), expected_return: 0.11, volatility: 0.22, }, ] } fn global_diversified_portfolio() -> Vec { vec![ Asset { ticker: "SPY".to_string(), name: "SPDR S&P 500 ETF".to_string(), asset_class: "equity".to_string(), sector: Some("US Equity".to_string()), expected_return: 0.10, volatility: 0.16, }, Asset { ticker: "EFA".to_string(), name: "iShares MSCI EAFE ETF".to_string(), asset_class: "equity".to_string(), sector: Some("International Equity".to_string()), expected_return: 0.08, volatility: 0.18, }, Asset { ticker: "VWO".to_string(), name: "Vanguard FTSE Emerging Markets ETF".to_string(), asset_class: "equity".to_string(), sector: Some("Emerging Markets".to_string()), expected_return: 0.09, volatility: 0.24, }, Asset { ticker: "BND".to_string(), name: "Vanguard Total Bond Market ETF".to_string(), asset_class: "bond".to_string(), sector: Some("US Bonds".to_string()), expected_return: 0.03, volatility: 0.04, }, Asset { ticker: "BNDX".to_string(), name: "Vanguard Total International Bond ETF".to_string(), asset_class: "bond".to_string(), sector: Some("International Bonds".to_string()), expected_return: 0.02, volatility: 0.06, }, Asset { ticker: "VNQ".to_string(), name: "Vanguard Real Estate ETF".to_string(), asset_class: "equity".to_string(), sector: Some("Real Estate".to_string()), expected_return: 0.06, volatility: 0.18, }, Asset { ticker: "GLD".to_string(), name: "SPDR Gold Trust".to_string(), asset_class: "commodity".to_string(), sector: Some("Precious Metals".to_string()), expected_return: 0.04, volatility: 0.15, }, ] } fn tech_focus_portfolio() -> Vec { vec![ Asset { ticker: "QQQ".to_string(), name: "Invesco QQQ Trust".to_string(), asset_class: "equity".to_string(), sector: Some("Technology".to_string()), expected_return: 0.14, volatility: 0.22, }, Asset { ticker: "ARKK".to_string(), name: "ARK Innovation ETF".to_string(), asset_class: "equity".to_string(), sector: Some("Technology".to_string()), expected_return: 0.15, volatility: 0.35, }, Asset { ticker: "SOXX".to_string(), name: "iShares Semiconductor ETF".to_string(), asset_class: "equity".to_string(), sector: Some("Technology".to_string()), expected_return: 0.16, volatility: 0.28, }, Asset { ticker: "CLOU".to_string(), name: "Global X Cloud Computing ETF".to_string(), asset_class: "equity".to_string(), sector: Some("Technology".to_string()), expected_return: 0.13, volatility: 0.26, }, ] } #[cfg(test)] mod tests { use super::*; #[test] fn test_sample_presets_available() { assert_eq!(SAMPLE_PRESETS.len(), 5); assert!(SAMPLE_PRESETS.contains(&PortfolioPreset::Conservative)); assert!(SAMPLE_PRESETS.contains(&PortfolioPreset::TechFocus)); } #[test] fn test_generate_conservative_assets() { let assets = generate_sample_assets(PortfolioPreset::Conservative).unwrap(); assert_eq!(assets.len(), 4); assert!(assets.iter().any(|a| a.ticker == "BND")); assert!(assets.iter().any(|a| a.asset_class == "bond")); } #[test] fn test_generate_balanced_assets() { let assets = generate_sample_assets(PortfolioPreset::Balanced).unwrap(); assert_eq!(assets.len(), 5); assert!(assets.iter().any(|a| a.ticker == "SPY")); assert!(assets.iter().any(|a| a.ticker == "BND")); } #[test] fn test_generate_aggressive_assets() { let assets = generate_sample_assets(PortfolioPreset::Aggressive).unwrap(); assert_eq!(assets.len(), 4); assert!(assets.iter().all(|a| a.asset_class == "equity")); } #[test] fn test_generate_global_diversified_assets() { let assets = generate_sample_assets(PortfolioPreset::GlobalDiversified).unwrap(); assert_eq!(assets.len(), 7); assert!(assets.iter().any(|a| a.ticker == "EFA")); } #[test] fn test_generate_tech_focus_assets() { let assets = generate_sample_assets(PortfolioPreset::TechFocus).unwrap(); assert_eq!(assets.len(), 4); assert!(assets.iter().all(|a| { a.sector .as_ref() .map(|s| s.contains("Technology")) .unwrap_or(false) })); } #[test] fn test_asset_properties() { let assets = generate_sample_assets(PortfolioPreset::Balanced).unwrap(); for asset in assets { assert!(!asset.ticker.is_empty()); assert!(!asset.name.is_empty()); assert!(!asset.asset_class.is_empty()); assert!(asset.expected_return >= 0.0); assert!(asset.volatility > 0.0); } } }