From 63c01bcf5146088f1b27070bce0c26da19ba0312 Mon Sep 17 00:00:00 2001 From: DiTus Date: Fri, 19 Dec 2025 22:50:05 +0100 Subject: [PATCH] feat(hedger): add edge protection and large hedge override to clp_hedger.py --- clp_hedger.py | 52 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/clp_hedger.py b/clp_hedger.py index 1b6ecba..99172ef 100644 --- a/clp_hedger.py +++ b/clp_hedger.py @@ -683,21 +683,65 @@ class ScalperHedger: time.sleep(CHECK_INTERVAL) continue - # 6. Execute Trade + # 6. Execute Trade (with Edge Protection) + bypass_cooldown = False + override_reason = "" + + # Edge Proximity Check + if active_pos.get('status') == 'OPEN': + position_edge_proximity = POSITION_OPEN_EDGE_PROXIMITY_PCT + + range_width = self.strategy.high_range - self.strategy.low_range + distance_from_bottom = price - self.strategy.low_range + distance_from_top = self.strategy.high_range - price + + edge_distance = range_width * position_edge_proximity + + is_near_bottom = distance_from_bottom <= edge_distance + is_near_top = distance_from_top <= edge_distance + + if is_near_bottom or is_near_top: + bypass_cooldown = True + override_reason = f"EDGE PROXIMITY ({position_edge_proximity*100:.1f}% edge)" + if is_near_bottom: + override_reason += f" ({distance_from_bottom:.2f} from bottom)" + else: + override_reason += f" ({distance_from_top:.2f} from top)" + + # Large Hedge Check + if not bypass_cooldown: + if diff_abs > (rebalance_threshold * LARGE_HEDGE_MULTIPLIER): + bypass_cooldown = True + override_reason = f"LARGE HEDGE NEEDED ({diff_abs:.4f} vs {rebalance_threshold:.4f})" + + can_trade = False + cooldown_text = "" + if diff_abs > rebalance_threshold: - if time.time() - self.last_trade_time > MIN_TIME_BETWEEN_TRADES: + if bypass_cooldown: + can_trade = True + logger.info(f"[WARN] COOLDOWN BYPASSED: {override_reason}") + elif time.time() - self.last_trade_time > MIN_TIME_BETWEEN_TRADES: + can_trade = True + else: + time_left = MIN_TIME_BETWEEN_TRADES - (time.time() - self.last_trade_time) + cooldown_text = f" | [WAIT] Cooldown ({time_left:.0f}s)" + + if can_trade: is_buy = (calc['action'] == "BUY") # Taker execution for rebalance exec_price = levels['ask'] * Decimal("1.001") if is_buy else levels['bid'] * Decimal("0.999") - logger.info(f"[TRIG] Rebalance: {calc['action']} {diff_abs:.4f} (Diff > {rebalance_threshold:.4f})") + urgency = "URGENT" if bypass_cooldown else "NORMAL" + logger.info(f"[TRIG] Rebalance ({urgency}): {calc['action']} {diff_abs:.4f} (Diff > {rebalance_threshold:.4f})") + oid = self.place_limit_order(COIN_SYMBOL, is_buy, diff_abs, exec_price, "Ioc") if oid: self.last_trade_time = time.time() self.track_fills_and_pnl(force=True) else: if time.time() - self.last_idle_log_time > 30: - logger.info(f"[WAIT] Cooldown. Diff: {diff_abs:.4f}") + logger.info(f"[WAIT] Cooldown. Diff: {diff_abs:.4f}{cooldown_text}") self.last_idle_log_time = time.time() else: if time.time() - self.last_idle_log_time > 30: