mod handlers; use crate::engine::PaperTradingEngine; use crate::metrics::BacktestResult; use crate::store::SqliteStore; use axum::routing::{get, post}; use axum::Router; use chrono::{DateTime, Utc}; use std::path::PathBuf; use std::sync::Arc; use tokio::sync::broadcast; use tower_http::services::ServeDir; pub enum BacktestRunStatus { Idle, Running { started_at: DateTime }, Complete, Failed, } pub struct BacktestProgress { pub phase: std::sync::atomic::AtomicU8, pub current_step: std::sync::atomic::AtomicU64, pub total_steps: std::sync::atomic::AtomicU64, } impl BacktestProgress { pub const PHASE_LOADING: u8 = 0; pub const PHASE_RUNNING: u8 = 1; pub fn new(total_steps: u64) -> Self { Self { phase: std::sync::atomic::AtomicU8::new( Self::PHASE_LOADING, ), current_step: std::sync::atomic::AtomicU64::new(0), total_steps: std::sync::atomic::AtomicU64::new( total_steps, ), } } pub fn phase_name(&self) -> &'static str { match self .phase .load(std::sync::atomic::Ordering::Relaxed) { Self::PHASE_LOADING => "loading data", Self::PHASE_RUNNING => "simulating", _ => "unknown", } } } pub struct BacktestState { pub status: BacktestRunStatus, pub progress: Option>, pub result: Option, pub error: Option, } pub struct AppState { pub engine: Arc, pub store: Arc, pub shutdown_tx: broadcast::Sender<()>, pub backtest: Arc>, pub data_dir: PathBuf, } pub fn build_router(state: Arc) -> Router { Router::new() .route("/api/status", get(handlers::get_status)) .route("/api/portfolio", get(handlers::get_portfolio)) .route("/api/positions", get(handlers::get_positions)) .route("/api/trades", get(handlers::get_trades)) .route("/api/equity", get(handlers::get_equity)) .route( "/api/circuit-breaker", get(handlers::get_circuit_breaker), ) .route( "/api/control/pause", post(handlers::post_pause), ) .route( "/api/control/resume", post(handlers::post_resume), ) .route( "/api/backtest/run", post(handlers::post_backtest_run), ) .route( "/api/backtest/status", get(handlers::get_backtest_status), ) .route( "/api/backtest/result", get(handlers::get_backtest_result), ) .fallback_service(ServeDir::new("static")) .with_state(state) }