21d3ba609d
Trovate e promosse 3 strategie con edge netto distinto da MR01, stessa metodologia (ingresso close[i], netto fee 0.10% RT + leva 3x, OOS ultimo 30%, robustezza su griglia + sweep fee 0.00-0.20%): - MR02 Donchian Fade: fade rottura canale H/L, TP al centro. BTC +172% OOS. - MR03 Keltner Fade: canale ATR su EMA (indipendente da Bollinger). BTC +112%. - MR07 Return Reversal: fade movimento di barra estremo (z dei rendimenti). BTC +105%. Tutte positive netto OOS su entrambi gli asset e su tutto lo sweep fee, anche 0.20% RT pessimista (validate anche via oos_validation live-path). Scartate MR04 (= MR01 riparametrizzato), MR05 (ADX non robusto), MR06 (RSI2 ETH neg). Base condivisa fade_base.FadeStrategy (backtest intrabar TP/SL/max_bars). Aggiunte a strategy_loader e strategies.yml (BTC+ETH 1h). Ricerca in strategy_research_v2.py. Diario e CLAUDE.md aggiornati. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
55 lines
1.8 KiB
Python
55 lines
1.8 KiB
Python
"""Import dinamico delle classi Strategy da scripts/strategies/."""
|
|
from __future__ import annotations
|
|
|
|
import importlib
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
from src.strategies.base import Strategy
|
|
|
|
PROJECT_ROOT = Path(__file__).resolve().parents[2]
|
|
STRATEGIES_DIR = PROJECT_ROOT / "scripts" / "strategies"
|
|
|
|
_REGISTRY: dict[str, type[Strategy]] = {}
|
|
|
|
# Solo strategie con edge netto validato out-of-sample (fee-aware).
|
|
# La famiglia squeeze-breakout (SQ/MT/ML/AD/CM/PD) e' stata spostata in
|
|
# scripts/waste/: l'edge storico era un artefatto di look-ahead
|
|
# (vedi scripts/analysis/oos_validation.py).
|
|
MODULE_MAP = {
|
|
"MR01_bollinger_fade": ("MR01_bollinger_fade", "BollingerFade"),
|
|
"MR02_donchian_fade": ("MR02_donchian_fade", "DonchianFade"),
|
|
"MR03_keltner_fade": ("MR03_keltner_fade", "KeltnerFade"),
|
|
"MR07_return_reversal": ("MR07_return_reversal", "ReturnReversal"),
|
|
}
|
|
|
|
|
|
def load_strategy(name: str) -> Strategy:
|
|
"""Carica e istanzia una Strategy per nome."""
|
|
if name in _REGISTRY:
|
|
return _REGISTRY[name]()
|
|
|
|
if name not in MODULE_MAP:
|
|
raise ValueError(f"Strategia sconosciuta: {name}. Disponibili: {list(MODULE_MAP)}")
|
|
|
|
module_file, class_name = MODULE_MAP[name]
|
|
module_path = STRATEGIES_DIR / f"{module_file}.py"
|
|
|
|
if not module_path.exists():
|
|
raise FileNotFoundError(f"File strategia non trovato: {module_path}")
|
|
|
|
if str(PROJECT_ROOT) not in sys.path:
|
|
sys.path.insert(0, str(PROJECT_ROOT))
|
|
|
|
spec = importlib.util.spec_from_file_location(f"strategies.{module_file}", module_path)
|
|
module = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(module)
|
|
|
|
cls = getattr(module, class_name)
|
|
_REGISTRY[name] = cls
|
|
return cls()
|
|
|
|
|
|
def list_available() -> list[str]:
|
|
return list(MODULE_MAP.keys())
|