1+ import streamlit as st
2+ import pandas as pd
3+ from pathlib import Path
4+ import json
5+ from services .backtest import run_backtest # Importiamo la funzione backend
6+
7+ st .set_page_config (page_title = "Backtest Lab" , page_icon = "🧪" , layout = "wide" )
8+
9+ st .title ("🧪 Backtest Laboratory" )
10+
11+ # Sidebar: Configurazione
12+ with st .sidebar :
13+ st .header ("⚙️ Configuration" )
14+
15+ strategy = st .selectbox ("Strategy" , ["RSI" , "MACD (Coming Soon)" ])
16+
17+ st .subheader ("Parameters" )
18+ initial_cap = st .number_input ("Initial Capital (€)" , value = 10000 , step = 1000 )
19+ years = st .slider ("Years History" , 1 , 5 , 2 )
20+
21+ # Parametri Dinamici per RSI
22+ params = {}
23+ if strategy == "RSI" :
24+ params ['rsi_period' ] = st .slider ("RSI Period" , 5 , 30 , 14 )
25+ params ['rsi_lower' ] = st .slider ("Oversold (<)" , 10 , 45 , 30 )
26+ params ['rsi_upper' ] = st .slider ("Overbought (>)" , 55 , 90 , 70 )
27+ params ['atr_period' ] = st .slider ("ATR Period" , 5 , 30 , 14 )
28+
29+ run_btn = st .button ("🚀 RUN BACKTEST" , type = "primary" )
30+
31+ # Main Area
32+ tab_run , tab_history = st .tabs (["Current Run" , "History Archive" ])
33+
34+ with tab_run :
35+ if run_btn :
36+ with st .spinner ("Running simulation... (This may take a moment)" ):
37+ try :
38+ # Eseguiamo il backtest
39+ result_path = run_backtest (
40+ strategy_name = strategy ,
41+ initial_capital = initial_cap ,
42+ days_history = years * 365 ,
43+ strategy_params = params
44+ )
45+ st .success (f"Simulation completed! Saved in: { result_path } " )
46+
47+ # Visualizzazione Rapida Risultati
48+ p = Path (result_path )
49+
50+ # Immagine
51+ if (p / "chart.png" ).exists ():
52+ # CORRETTO: use_container_width invece di width
53+ st .image (str (p / "chart.png" ), use_container_width = True )
54+
55+ # Metriche da JSON
56+ if (p / "config.json" ).exists ():
57+ with open (p / "config.json" ) as f :
58+ res = json .load (f )
59+
60+ m1 , m2 , m3 = st .columns (3 )
61+ m1 .metric ("Final Equity" , f"€ { res .get ('final_equity' , 0 ):,.2f} " )
62+ m2 .metric ("Total Trades" , res .get ('total_trades' , 0 ))
63+ # Calcolo ROI al volo
64+ roi = ((res .get ('final_equity' , 0 ) - initial_cap ) / initial_cap ) * 100
65+ m3 .metric ("Total ROI" , f"{ roi :+.2f} %" )
66+
67+ except Exception as e :
68+ st .error (f"Errore durante il backtest: { e } " )
69+
70+ with tab_history :
71+ st .write ("📂 **Previous Runs Browser**" )
72+ base_dir = Path ("data/backtests" )
73+
74+ if base_dir .exists ():
75+ # Logica per esplorare le cartelle
76+ strategies = [x .name for x in base_dir .iterdir () if x .is_dir ()]
77+
78+ # --- LAYOUT A COLONNE PER I SELETTORI ---
79+ c_strat , c_run = st .columns (2 )
80+
81+ with c_strat :
82+ sel_strat = st .selectbox ("Select Strategy Folder" , strategies )
83+
84+ sel_run = None
85+ if sel_strat :
86+ with c_run :
87+ # Controllo se la cartella esiste e non è vuota
88+ strat_path = base_dir / sel_strat
89+ if strat_path .exists ():
90+ runs = sorted ([x .name for x in strat_path .iterdir ()], reverse = True )
91+ sel_run = st .selectbox ("Select Timestamp" , runs )
92+
93+ if sel_run :
94+ run_path = base_dir / sel_strat / sel_run
95+ st .caption (f"Path: { run_path } " )
96+ st .markdown ("---" )
97+
98+ # Visualizzazione Dati
99+ col_img , col_data = st .columns ([1 , 1 ])
100+
101+ with col_img :
102+ if (run_path / "chart.png" ).exists ():
103+ # CORRETTO: use_container_width
104+ st .image (str (run_path / "chart.png" ), use_container_width = True )
105+
106+ with col_data :
107+ if (run_path / "config.json" ).exists ():
108+ with open (run_path / "config.json" ) as f :
109+ conf = json .load (f )
110+ st .json (conf , expanded = False )
111+
112+ if (run_path / "trades.csv" ).exists ():
113+ # CORRETTO: use_container_width e height numerico
114+ st .dataframe (pd .read_csv (run_path / "trades.csv" ), use_container_width = True , height = 300 )
0 commit comments