use eframe::egui; use rfd::FileDialog; use std::path::PathBuf; use crate::engine::backtester::BacktestConfig; pub struct BacktestPanel { pub initial_deposit_str: String, pub leverage_str: String, pub spread_modifier_str: String, pub selected_symbols: Vec, pub new_symbol_input: String, pub loaded_mql5_path: Option, pub compiler_log: String, pub is_running: bool, } impl BacktestPanel { pub fn new() -> Self { Self { initial_deposit_str: "10000.0".to_string(), leverage_str: "100.0".to_string(), spread_modifier_str: "0".to_string(), selected_symbols: vec!["EURUSD".to_string()], new_symbol_input: "".to_string(), loaded_mql5_path: None, compiler_log: "Ready.".to_string(), is_running: false, } } pub fn draw(&mut self, ui: &mut egui::Ui) -> Option { ui.heading("⚙️ Backtest Configuration"); ui.separator(); // Account Settings ui.group(|ui| { ui.label("Account Settings"); egui::Grid::new("config_grid").num_columns(2).spacing([10.0, 5.0]).show(ui, |ui| { ui.label("Initial Deposit ($):"); ui.text_edit_singleline(&mut self.initial_deposit_str); ui.end_row(); ui.label("Leverage (1:X):"); ui.text_edit_singleline(&mut self.leverage_str); ui.end_row(); ui.label("Spread Modifier (points):"); ui.text_edit_singleline(&mut self.spread_modifier_str); ui.end_row(); }); }); ui.add_space(10.0); // Symbol Selection ui.group(|ui| { ui.label("Symbols for Backtest"); ui.horizontal(|ui| { ui.text_edit_singleline(&mut self.new_symbol_input); if ui.button("Add").clicked() { if !self.new_symbol_input.is_empty() && !self.selected_symbols.contains(&self.new_symbol_input) { self.selected_symbols.push(self.new_symbol_input.clone()); self.new_symbol_input.clear(); } } }); ui.horizontal_wrapped(|ui| { let mut to_remove = None; for (i, sym) in self.selected_symbols.iter().enumerate() { ui.group(|ui| { ui.horizontal(|ui| { ui.label(sym); if ui.small_button("x").clicked() { to_remove = Some(i); } }); }); } if let Some(i) = to_remove { self.selected_symbols.remove(i); } }); }); ui.add_space(10.0); // MQL5 File Loading ui.group(|ui| { ui.label("MQL5 Strategy Code"); ui.horizontal(|ui| { if ui.button("📂 Load .mq5 File").clicked() { if let Some(path) = FileDialog::new() .add_filter("MQL5 Source", &["mq5"]) .pick_file() { self.loaded_mql5_path = Some(path); self.compiler_log = "File loaded. Ready to compile.".to_string(); } } if let Some(p) = &self.loaded_mql5_path { ui.label(p.display().to_string()); } else { ui.label("No file selected."); } }); }); ui.add_space(10.0); // Start button ui.horizontal(|ui| { if self.is_running { ui.add_enabled(false, egui::Button::new("Running Backtest...")); } else { if ui.button("🚀 Compile & Run Backtest").clicked() { if self.loaded_mql5_path.is_none() { self.compiler_log = "Error: Please load an .mq5 file first.".to_string(); return None; } if self.selected_symbols.is_empty() { self.compiler_log = "Error: Please add at least one symbol.".to_string(); return None; } if let (Ok(dep), Ok(lev), Ok(spr)) = ( self.initial_deposit_str.parse::(), self.leverage_str.parse::(), self.spread_modifier_str.parse::(), ) { self.compiler_log = "Starting compilation...".to_string(); self.is_running = true; return Some(BacktestConfig { initial_deposit: dep, leverage: lev, spread_modifier: spr, }); } else { self.compiler_log = "Error: Invalid numeric configuration fields.".to_string(); } } } }); ui.add_space(5.0); // Logs ui.group(|ui| { ui.set_min_height(60.0); ui.label(&self.compiler_log); }); None } }