Files
Trading-Bot/tests/test_walkforwad.py
DaM f85c522f22 feat: finalize portfolio system and quantitative validation- Finalized MA_Crossover(30,100) and TrendFiltered_MA(30,100,ADX=15)
- Implemented portfolio engine with risk-based allocation (50/50)
- Added equity-based metrics for system-level evaluation
- Validated portfolio against standalone strategies
- Reduced max drawdown and volatility at system level
- Quantitative decision closed before paper trading phase
2026-02-02 14:38:05 +01:00

161 lines
5.1 KiB
Python

# tests/test_walkforward.py
"""
Script para probar Walk-Forward Validation
Guarda resultados en CSV para análisis posterior
"""
import os
import sys
from dotenv import load_dotenv
from pathlib import Path
import pandas as pd
# Añadir raíz del proyecto al path
sys.path.insert(0, str(Path(__file__).parent.parent))
from src.utils.logger import log
from src.data.storage import StorageManager
from src.strategies import MovingAverageCrossover
from src.core.walk_forward import WalkForwardValidator
def setup_environment():
"""Carga variables de entorno"""
env_path = Path(__file__).parent.parent / "config" / "secrets.env"
load_dotenv(dotenv_path=env_path)
log.success("✓ Variables de entorno cargadas")
def test_walkforward():
"""
Test de Walk-Forward Validation con múltiples configuraciones
"""
log.info("=" * 70)
log.info("🪜 TEST: WALK-FORWARD VALIDATION (MULTI CONFIG)")
log.info("=" * 70)
# --------------------------------------------------
# Setup
# --------------------------------------------------
setup_environment()
storage = StorageManager(
db_host=os.getenv("DB_HOST"),
db_port=int(os.getenv("DB_PORT", 5432)),
db_name=os.getenv("DB_NAME"),
db_user=os.getenv("DB_USER"),
db_password=os.getenv("DB_PASSWORD"),
)
log.info("\n📥 Cargando datos...")
data = storage.load_ohlcv(
symbol="BTC/USDT",
timeframe="1h",
start_date=None,
end_date=None,
use_cache=False,
)
log.success(f"✓ Datos cargados: {len(data)} velas")
# --------------------------------------------------
# Grid de parámetros de la estrategia
# --------------------------------------------------
param_grid = {
"fast_period": [10, 15],
"slow_period": [30, 50],
"ma_type": ["sma"],
"use_adx": [True],
"adx_threshold": [20, 25, 30],
}
# --------------------------------------------------
# Configuraciones Walk-Forward a comparar
# --------------------------------------------------
wf_configs = [
{"name": "WF_12_3", "train_days": 365, "test_days": 90},
{"name": "WF_24_3", "train_days": 365 * 2, "test_days": 90},
{"name": "WF_24_6", "train_days": 365 * 2, "test_days": 180},
]
all_windows = []
summary_rows = []
# --------------------------------------------------
# Ejecutar Walk-Forward por configuración
# --------------------------------------------------
for cfg in wf_configs:
log.info("\n" + "=" * 70)
log.info(f"🧪 EJECUTANDO {cfg['name']}")
log.info("=" * 70)
wf = WalkForwardValidator(
strategy_class=MovingAverageCrossover,
param_grid=param_grid,
data=data,
train_window=pd.Timedelta(days=cfg["train_days"]),
test_window=pd.Timedelta(days=cfg["test_days"]),
initial_capital=10_000,
commission=0.001,
slippage=0.0005,
position_size=0.95,
optimizer_metric="sharpe_ratio",
)
wf_result = wf.run()
# -------------------------------
# Validaciones básicas
# -------------------------------
assert isinstance(wf_result, dict), "wf_result debe ser dict"
assert "windows" in wf_result, "wf_result debe contener 'windows'"
df_windows = wf_result["windows"].copy()
df_windows["wf_name"] = cfg["name"]
all_windows.append(df_windows)
# -------------------------------
# Métricas agregadas por WF
# -------------------------------
summary_rows.append({
"wf_name": cfg["name"],
"train_days": cfg["train_days"],
"test_days": cfg["test_days"],
"windows": len(df_windows),
"avg_return_pct": df_windows["return_pct"].mean(),
"avg_sharpe": df_windows["sharpe"].mean(),
"avg_max_dd_pct": df_windows["max_dd_pct"].mean(),
"avg_trades": df_windows["trades"].mean(),
})
# --------------------------------------------------
# Consolidar resultados
# --------------------------------------------------
df_all_windows = pd.concat(all_windows, ignore_index=True)
df_summary = pd.DataFrame(summary_rows)
# --------------------------------------------------
# Guardar CSVs
# --------------------------------------------------
output_dir = Path("backtest_results/walkforward")
output_dir.mkdir(parents=True, exist_ok=True)
windows_path = output_dir / "walkforward_windows.csv"
summary_path = output_dir / "walkforward_summary.csv"
df_all_windows.to_csv(windows_path, index=False)
df_summary.to_csv(summary_path, index=False)
log.success(f"💾 CSV ventanas guardado: {windows_path}")
log.success(f"💾 CSV resumen guardado: {summary_path}")
print("\n📊 RESUMEN WALK-FORWARD:")
print(df_summary.to_string(index=False))
storage.close()
log.success("\n✅ TEST WALK-FORWARD COMPLETADO")
if __name__ == "__main__":
test_walkforward()