diff --git a/backtests/vbt_runner.py b/backtests/vbt_runner.py index 1a9f160..39b0b28 100644 --- a/backtests/vbt_runner.py +++ b/backtests/vbt_runner.py @@ -232,26 +232,22 @@ def _generate_signals(strategy: str, data: dict[str, pd.DataFrame]) -> tuple[pd. exits = ((imbalance.shift(1) > exit_threshold) & (imbalance < exit_threshold)) | \ ((imbalance.shift(1) < -exit_threshold) & (imbalance > -exit_threshold)) exits = exits.fillna(False) - # Force exit after 5 bars of being in trade (stale signal) - entries.fillna(False, inplace=True) - exits.fillna(False, inplace=True) - return entries, exits elif strategy == "iceberg": # Volume spike detection: large-volume bars signal whale activity avg_vol = df["volume"].rolling(20).mean() - vol_spike = df["volume"] > avg_vol * 1.3 + vol_spike = df["volume"] > avg_vol * 1.15 - # Direction: buy if close > open, sell if close < open + # Require at least 2 consecutive same-direction spikes buy_spike = vol_spike & (df["close"] > df["open"]) sell_spike = vol_spike & (df["close"] < df["open"]) - # Consecutive same-direction spikes (>= 2) - buy_consec = buy_spike.rolling(1).sum() >= 1 - sell_consec = sell_spike.rolling(1).sum() >= 1 + buy_consec = buy_spike.rolling(3).sum() >= 2 + sell_consec = sell_spike.rolling(3).sum() >= 2 - entries = buy_consec | sell_consec - exits = entries.shift(5).fillna(False) + entries = (buy_consec | sell_consec).astype(bool) + # Exit when volume spike subsides (not fixed 5-bar hold) + exits = entries.shift(3).fillna(False).astype(bool) & ~entries elif strategy == "funding_arb": entries[:] = False