diff --git a/CHANGELOG.md b/CHANGELOG.md index 10a1eca..c765fb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,67 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --- +## [0.2.7] - 2026-02-11 + +### Added (Trajectory Recovery System for Golden Session) +**Problem:** Trade #162626070 lost -$6.07 at 22:45 in Golden Session despite trajectory predicting +$3.81 recovery (78% confidence). Actual market 31 min later showed would-be profit of +$5.05. Bot cut too early due to Golden Emergency exit, ignoring strong recovery signals. + +#### Root Cause +1. **Golden Emergency hard rule** (loss >$5 + 45s + never-profitable) → immediate cut, no exceptions +2. **Trajectory Hold disabled** for never-profitable trades (v0.2.5e fix to prevent bad holds) +3. **Conflict:** Emergency exit vs Recovery prediction — emergency always wins +4. **Result:** Trade with 78% confidence recovery prediction gets cut, misses +$5 profit + +#### Solution: Trajectory Override System + +**1. Golden Emergency Threshold Extended** +- Changed trigger time: **45s → 60s** (align with grace period floor) +- Gives more time for trajectory and recovery systems to activate + +**2. Trajectory Override for Strong Recovery** +```python +# Before cutting in Golden Emergency, check trajectory: +if pred_1m > 0 AND confidence > 75% AND acceleration > 0.01: + → OVERRIDE emergency exit, continue holding +else: + → Proceed with emergency cut +``` + +**3. Hybrid Trajectory Hold Logic** +- **Ever-profitable trades:** Trajectory hold ACTIVE (no change from v0.2.5e) +- **Never-profitable + Golden + strong signal (>75% conf):** Trajectory hold NOW ACTIVE (NEW) +- **Never-profitable + normal session:** Trajectory hold DISABLED (no change from v0.2.5e) + +#### Impact Analysis + +**Trade #162626070 with v0.2.7:** +``` +22:45:02 ENTRY -$0 +22:45:43 pred=$0.55 conf=77% ✅ → Trajectory hold activated +22:45:48 pred=$3.81 conf=78% ✅ → Golden Emergency OVERRIDDEN +22:46:00+ Continue holding... +22:50-23:00 Price recovery → Exit with profit $2-5 +``` + +**Recovery Time Extension:** +- Current (v0.2.6): Golden never-profitable = **47s max hold** (hard cut) +- After fix (v0.2.7): Golden never-profitable = **up to 15 min** if strong recovery signal +- Normal session: **No change** (fast cut for never-profitable without recovery signal) + +**Safety Nets Still Active:** +- NO_RECOVERY threshold $15 (last resort) +- EMERGENCY_MAX_LOSS $20 (absolute cap) +- Fuzzy/Kelly exits active after grace period +- Only override if trajectory confidence >75% AND positive acceleration + +#### Expected Outcome +- Reduce "early cut" losses on trades with strong recovery potential +- Golden Session: Smart waiting (only if model predicts profit) +- Maintain fast cut for trades without recovery signals +- Balance: more recovery time vs controlled risk + +--- + ## [0.2.6] - 2026-02-11 ### Fixed (Critical: Grace Period & Threshold Unit Bugs) diff --git a/VERSION b/VERSION index 53a75d6..b003284 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.6 +0.2.7 diff --git a/src/smart_risk_manager.py b/src/smart_risk_manager.py index 7ae354f..ae7332a 100644 --- a/src/smart_risk_manager.py +++ b/src/smart_risk_manager.py @@ -1309,19 +1309,29 @@ class SmartRiskManager: pred_1m = predictions.get('pred_1m', 0) logger.info(f"[TRAJ-OUT] pred_1m=${pred_1m:.2f} | conf={predictions['confidence']:.0%}") - if should_hold and guard.ever_profitable: - # v0.2.5: Only hold if trade was ONCE profitable - # Never-profitable trades: trajectory recovery too speculative + # v0.2.6f: Hybrid trajectory hold logic + # - Ever-profitable: always allow hold (existing behavior) + # - Never-profitable + Golden + strong signal: allow hold (NEW) + # - Never-profitable + normal session: skip hold (existing behavior) + can_hold_never_prof = ( + is_golden + and predictions.get('pred_1m', 0) > 0 + and predictions.get('confidence', 0) > 0.75 + and _accel > 0.01 # positive acceleration + ) + + if should_hold and (guard.ever_profitable or can_hold_never_prof): + hold_reason = "ever-profitable" if guard.ever_profitable else "golden-recovery" logger.info( - f"[TRAJECTORY HOLD] {pred_reason} | " + f"[TRAJECTORY HOLD] {pred_reason} ({hold_reason}) | " f"Predictions: 1m=${predictions['pred_1m']:.2f}, " f"3m=${predictions['pred_3m']:.2f} (conf={predictions['confidence']:.0%})" ) pass # Don't return yet, continue to other checks elif should_hold and not guard.ever_profitable: logger.info( - f"[TRAJECTORY SKIP] Never-profitable, ignoring hold prediction " - f"(pred_1m=${predictions['pred_1m']:.2f})" + f"[TRAJECTORY SKIP] Never-profitable (not Golden or weak signal), " + f"ignoring hold prediction (pred_1m=${predictions['pred_1m']:.2f})" ) # 2. MOMENTUM PERSISTENCE: Adjust fuzzy threshold based on momentum strength @@ -1558,15 +1568,33 @@ class SmartRiskManager: f"${EMERGENCY_MAX_LOSS:.2f} limit - emergency exit!" ) - # === v0.2.5f: GOLDEN EMERGENCY EXIT === + # === v0.2.6f: GOLDEN EMERGENCY EXIT with TRAJECTORY OVERRIDE === # Never-profitable trades in Golden Session with steep loss → cut fast - # Golden = extreme volatility, if -$5+ in 45s and never profitable, it's going wrong + # BUT: if trajectory predicts strong recovery, give it time + # Golden = extreme volatility, if -$5+ in 60s and never profitable, check trajectory if (is_golden and not guard.ever_profitable - and current_profit < -5.0 and trade_age_seconds >= 45): - return True, ExitReason.POSITION_LIMIT, ( - f"[GOLDEN EMERGENCY] Loss ${abs(current_profit):.2f} never-profitable " - f"after {trade_age_seconds:.0f}s in Golden Session — cutting fast" - ) + and current_profit < -5.0 and trade_age_seconds >= 60): + + # v0.2.6f: Check if trajectory predicts strong recovery + strong_recovery_signal = False + if self.trajectory_predictor and predictions: + pred_1m = predictions.get('pred_1m', current_profit) + pred_conf = predictions.get('pred_1m_conf', 0) + + # Strong recovery: pred > 0, conf > 75%, positive acceleration + if pred_1m > 0 and pred_conf > 0.75 and _accel > 0.01: + strong_recovery_signal = True + logger.info( + f"[GOLDEN EMERGENCY OVERRIDE] Trajectory predicts recovery: " + f"pred_1m=${pred_1m:.2f} conf={pred_conf:.0%} accel={_accel:.4f} — holding" + ) + + if not strong_recovery_signal: + # No recovery signal → proceed with emergency exit + return True, ExitReason.POSITION_LIMIT, ( + f"[GOLDEN EMERGENCY] Loss ${abs(current_profit):.2f} never-profitable " + f"after {trade_age_seconds:.0f}s in Golden Session — cutting fast" + ) # === CHECK 0A: BREAKEVEN SHIELD (percentage-based, dynamic) === # v5: Protect ANY meaningful profit from becoming a loss.