pequeños cambios para que el step 1 sea mas robusto
This commit is contained in:
@@ -98,9 +98,11 @@ def inspect_strategies_config(
|
||||
data_quality: Dict[str, Any],
|
||||
include_series: bool,
|
||||
progress_callback=None,
|
||||
df: pd.DataFrame | None = None,
|
||||
) -> Dict[str, Any]:
|
||||
|
||||
df = storage.load_ohlcv(symbol=payload.symbol, timeframe=payload.timeframe)
|
||||
if df is None:
|
||||
df = storage.load_ohlcv(symbol=payload.symbol, timeframe=payload.timeframe)
|
||||
if df is None or df.empty:
|
||||
return {
|
||||
"valid": False,
|
||||
@@ -117,14 +119,24 @@ def inspect_strategies_config(
|
||||
}
|
||||
|
||||
if data_quality.get("status") == "fail":
|
||||
return {
|
||||
out = {
|
||||
"valid": False,
|
||||
"status": "fail",
|
||||
"checks": checks,
|
||||
"message": "Step 1 data quality is FAIL. Strategies cannot be validated.",
|
||||
"results": [],
|
||||
"series": {} if include_series else None,
|
||||
"config": {
|
||||
"wf": payload.wf.model_dump(),
|
||||
"risk": payload.risk.model_dump(),
|
||||
"stop": payload.stop.model_dump(),
|
||||
"global_rules": payload.global_rules.model_dump(),
|
||||
"commission": payload.commission,
|
||||
"slippage": payload.slippage,
|
||||
},
|
||||
}
|
||||
if include_series:
|
||||
out["series"] = {"strategies": {}}
|
||||
return out
|
||||
|
||||
stop_loss = _build_stop_loss(payload.stop)
|
||||
base_sizer = _build_position_sizer(payload.risk)
|
||||
@@ -183,7 +195,7 @@ def inspect_strategies_config(
|
||||
"message": msg,
|
||||
"warnings": [],
|
||||
"series_available": False,
|
||||
"series_error": "Unknown strategy_id (not in registry)",
|
||||
"series_error": msg,
|
||||
"n_windows": 0,
|
||||
"oos_final_equity": payload.account_equity,
|
||||
"oos_total_return_pct": 0.0,
|
||||
@@ -204,9 +216,10 @@ def inspect_strategies_config(
|
||||
|
||||
|
||||
# Wrapper sizer
|
||||
class _CappedSizer(type(base_sizer)):
|
||||
def __init__(self, inner):
|
||||
class _CappedSizer:
|
||||
def __init__(self, inner, max_position_fraction: float):
|
||||
self.inner = inner
|
||||
self.max_position_fraction = max_position_fraction
|
||||
|
||||
def calculate_size(self, *, capital, entry_price, stop_price=None, max_capital=None, volatility=None):
|
||||
u = self.inner.calculate_size(
|
||||
@@ -220,10 +233,10 @@ def inspect_strategies_config(
|
||||
units=float(u),
|
||||
capital=float(capital),
|
||||
entry_price=float(entry_price),
|
||||
max_position_fraction=float(payload.risk.max_position_fraction),
|
||||
max_position_fraction=float(self.max_position_fraction),
|
||||
)
|
||||
|
||||
capped_sizer = _CappedSizer(base_sizer)
|
||||
|
||||
capped_sizer = _CappedSizer(base_sizer, payload.risk.max_position_fraction)
|
||||
|
||||
log.info(f"🧠 Step3 | WF run | strategy={sid}")
|
||||
|
||||
@@ -302,11 +315,6 @@ def inspect_strategies_config(
|
||||
oos_dd = win_df["max_dd_pct"].tolist()
|
||||
n_windows = len(win_df)
|
||||
|
||||
required_cols = {"return_pct", "max_dd_pct", "trades", "window", "train_start", "train_end", "test_start", "test_end", "sharpe", "params"}
|
||||
missing = required_cols - set(win_df.columns)
|
||||
if missing:
|
||||
raise ValueError(f"WF windows missing required columns: {sorted(missing)}")
|
||||
|
||||
trades = win_df["trades"].astype(int).tolist()
|
||||
too_few = sum(t < int(payload.wf.min_trades_test) for t in trades)
|
||||
|
||||
@@ -401,6 +409,14 @@ def inspect_strategies_config(
|
||||
"checks": checks,
|
||||
"message": human_msg,
|
||||
"results": results,
|
||||
"config": {
|
||||
"wf": payload.wf.model_dump(),
|
||||
"risk": payload.risk.model_dump(),
|
||||
"stop": payload.stop.model_dump(),
|
||||
"global_rules": payload.global_rules.model_dump(),
|
||||
"commission": payload.commission,
|
||||
"slippage": payload.slippage,
|
||||
},
|
||||
}
|
||||
|
||||
if include_series:
|
||||
|
||||
Reference in New Issue
Block a user