Files
trading_bot_v4/docs/EXIT_FIXES_IMPLEMENTATION_PLAN.md
mindesbunister 9c65124743 docs: Complete exit strategy analysis - ,400 loss root cause identified
- Root cause: Exit strategy, NOT entry timing
- Smoking gun: Identical entry conditions (+83 winner AND -,129 loser)
- Key problems: SL too wide (ATR 3.0), no catastrophic cap, trailing too tight
- Phase 1 fixes: Tighten SL to ATR 2.0, add -2 avg winner cap, block extreme longs
- Phase 2 fixes: Widen trailing to ATR 2.5, earlier profit acceleration
- Expected impact: -,400 → +4 over 78 trades
- Validation: 10/30/50 trade milestones
- Files: Full analysis, implementation plan, executive summary
2025-12-23 17:25:54 +01:00

331 lines
9.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Exit Strategy Fixes - Implementation Plan
**Date:** December 23, 2025
**Status:** READY TO IMPLEMENT
**Expected Impact:** -$1,400 loss → +$200 profit over 78 trades
---
## 🎯 Phase 1: Emergency Fixes (Deploy Immediately)
### Fix #1: Tighten Stop Loss Distance
**File:** `config/trading.ts` or `.env`
**Change:**
```typescript
// BEFORE:
ATR_MULTIPLIER_SL=3.0
// AFTER:
ATR_MULTIPLIER_SL=2.0 // 33% tighter, caps losses at ~0.86% instead of 1.29%
```
**Rationale:** Average loser ($42.43) is 2× average winner ($21.05). Tighter SL brings them closer to 1:1 ratio.
**Expected Impact:**
- Average loser: -$42.43 → -$28 (34% improvement)
- May increase stop-out rate by 3-5% (acceptable trade-off)
- Net effect: $882 improvement over current performance
---
### Fix #2: Catastrophic Loss Protection
**File:** `lib/trading/position-manager.ts`
**Add new function:**
```typescript
private async checkCatastrophicLoss(trade: ActiveTrade, currentPrice: number): Promise<boolean> {
// Get average winner from last 50 trades
const recentTrades = await this.prisma.trade.findMany({
where: {
exitReason: { not: null },
realizedPnL: { gt: 0 },
createdAt: { gte: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) } // Last 30 days
},
orderBy: { createdAt: 'desc' },
take: 50,
select: { realizedPnL: true }
})
if (recentTrades.length === 0) {
// No recent winners, use default $30 threshold
return trade.unrealizedPnL < -60 // 2× $30
}
const averageWinner = recentTrades.reduce((sum, t) => sum + (t.realizedPnL || 0), 0) / recentTrades.length
const catastrophicThreshold = -(2 * averageWinner)
if (trade.unrealizedPnL < catastrophicThreshold) {
console.log(`🚨 CATASTROPHIC LOSS DETECTED: ${trade.symbol}`)
console.log(` Current P&L: ${trade.unrealizedPnL.toFixed(2)}`)
console.log(` Avg Winner: ${averageWinner.toFixed(2)}`)
console.log(` Threshold: ${catastrophicThreshold.toFixed(2)}`)
console.log(` FORCING IMMEDIATE CLOSE`)
return true
}
return false
}
```
**Add to monitoring loop (in `monitorTrades()`):**
```typescript
// BEFORE checking TP1/TP2/SL, add this:
if (await this.checkCatastrophicLoss(trade, currentPrice)) {
await this.executeExit(trade, currentPrice, 100, 'CATASTROPHIC_LOSS_PROTECTION')
continue
}
```
**Expected Impact:**
- Prevents losses >$50 (currently worst was -$1,129)
- Would have saved $1,087 on the catastrophic v5 trade
- Zero downside (only triggers on disaster scenarios)
---
### Fix #3: Block Extreme Long Positions
**File:** `workflows/trading/moneyline_v11_all_filters.pinescript`
**Change:**
```pinescript
// BEFORE:
longPosMax = input.float(100, "Long max position %", ...)
// AFTER:
longPosMax = input.float(85, "Long max position %", ...)
// Tooltip: "Block chasing tops - don't buy in top 15% of 100-bar range"
```
**Rationale:** LONGs at price_pos 94-96% + RSI 73-84 consistently lose. These are "chasing the top" entries.
**Expected Impact:**
- Filters 3-4 losing trades per 78 trades
- Saves ~$60 total
- Prevents entries like: RSI 73.5 at 94.4% pos = -$17.09, RSI 84.4 at 96.7% = -$13.05
---
## 🚀 Phase 2: Runner Optimization (Deploy After 20 Trades)
### Fix #4: Widen Trailing Stop After TP2
**File:** `lib/trading/position-manager.ts` around lines 1356-1450
**Change trailing stop multiplier:**
```typescript
// FIND this section (around line 1394):
let trailMultiplier = 1.5 // Base multiplier for trailing stop
// CHANGE TO:
let trailMultiplier = 2.5 // Wider to capture bigger moves (was 1.5)
```
**AND adjust ADX multipliers:**
```typescript
// FIND (around line 1410):
if (freshADX > 30) {
trailMultiplier *= 1.5 // Very strong trend
} else if (freshADX >= 25) {
trailMultiplier *= 1.25 // Strong trend
}
// CHANGE TO:
if (freshADX > 30) {
trailMultiplier *= 2.0 // Very strong trend (was 1.5)
} else if (freshADX >= 25) {
trailMultiplier *= 1.5 // Strong trend (was 1.25)
}
```
**Rationale:** $183 winner proves big moves exist. Need more room for runners to breathe. Current trailing too tight.
**Expected Impact:**
- Average winner: $21.05 → $35 (67% improvement)
- Some runners will give back gains (2-3% WR drop acceptable)
- Net effect: Positive P&L even with slightly lower WR
---
### Fix #5: Earlier Profit Acceleration
**File:** `lib/trading/position-manager.ts` around line 1425
**Change:**
```typescript
// FIND:
if (profitPercent > 2.0) { // Was 2%
trailMultiplier *= 1.3
console.log(`💰 Large profit (${profitPercent.toFixed(2)}%): Trail multiplier ${oldMult}×${trailMultiplier.toFixed(2)}×`)
}
// CHANGE TO:
if (profitPercent > 1.5) { // Changed to 1.5%
trailMultiplier *= 1.5 // Increased from 1.3
console.log(`💰 Profit acceleration (${profitPercent.toFixed(2)}%): Trail multiplier ${oldMult}×${trailMultiplier.toFixed(2)}×`)
}
```
**Rationale:** Trigger wider trailing sooner to capture mid-sized moves (1.5-3% range).
**Expected Impact:**
- Captures 1.5-3% moves that currently hit trailing too soon
- Estimated +$5-10 per winning trade in this range
- More winning TRAILING_SL exits (currently only 1 out of 34 winners)
---
## 📋 Deployment Checklist
### Pre-Deployment
- [ ] **Backup current .env:** `cp .env .env.backup_dec23`
- [ ] **Backup Position Manager:** `cp lib/trading/position-manager.ts lib/trading/position-manager.ts.backup_dec23`
- [ ] **Document current parameters:**
```
ATR_MULTIPLIER_SL=3.0
longPosMax=100
Base trail multiplier=1.5
```
### Phase 1 Deployment (Do All 3 Together)
- [ ] **Update .env:** Change `ATR_MULTIPLIER_SL=3.0` to `ATR_MULTIPLIER_SL=2.0`
- [ ] **Update v11 indicator:** Change `longPosMax=100` to `longPosMax=85` in TradingView
- [ ] **Add catastrophic protection:** Implement `checkCatastrophicLoss()` in Position Manager
- [ ] **Test compilation:** `npm run build`
- [ ] **Restart Docker:** `docker compose restart trading-bot`
- [ ] **Verify logs:** Check "CATASTROPHIC" appears in monitoring logs
- [ ] **Test with small position:** Open test trade, verify SL distance ~0.86% instead of 1.29%
### Phase 2 Deployment (After 20 Trades)
- [ ] **Analyze Phase 1 results:**
```sql
SELECT
COUNT(*) as trades,
ROUND(AVG(CASE WHEN "realizedPnL" > 0 THEN "realizedPnL" ELSE NULL END)::numeric, 2) as avg_winner,
ROUND(AVG(CASE WHEN "realizedPnL" <= 0 THEN "realizedPnL" ELSE NULL END)::numeric, 2) as avg_loser,
MAX("realizedPnL") as best_winner,
MIN("realizedPnL") as worst_loser
FROM "Trade"
WHERE "createdAt" > NOW() - INTERVAL '7 days'
AND "exitReason" IS NOT NULL;
```
- [ ] **If Phase 1 working (avg loser <$35):** Proceed with Phase 2
- [ ] **Update trailing multipliers:** Change base 1.5 → 2.5, ADX 1.5/1.25 → 2.0/1.5
- [ ] **Update profit acceleration:** Change 2.0% → 1.5%, 1.3× → 1.5×
- [ ] **Restart Docker**
- [ ] **Monitor first 10 trades:** Watch for TRAILING_SL exits increasing
---
## 📊 Validation Metrics
### After 10 Trades (Phase 1 Check)
**Must See:**
- ✅ Average loser <$35 (target: <$30)
- ✅ Zero losses >$50 (catastrophic protection working)
- ✅ No LONGs at price_pos >85% (extreme filter working)
**If Not:** Rollback and investigate
### After 30 Trades (Phase 2 Check)
**Must See:**
- ✅ Average winner >$28 (target: >$30)
- ✅ Win/Loss ratio >0.8 (target: >1.0)
- ✅ At least 3-5 TRAILING_SL exits (runner system working)
**If Not:** Adjust trailing multipliers (try 2.0× instead of 2.5×)
### After 50 Trades (Full Validation)
**Success Criteria:**
- ✅ Total P&L >$0 (profitable)
- ✅ Win rate 38-45% (acceptable range)
- ✅ Average winner / average loser ratio >1.0
- ✅ Zero catastrophic losses (no single loss >$60)
**If Success:** System is fixed, continue monitoring
**If Failure:** Review data and adjust (may need Phase 3 advanced logic)
---
## 🔄 Rollback Plan
**If fixes make things worse:**
1. **Restore .env:**
```bash
cp .env.backup_dec23 .env
docker compose restart trading-bot
```
2. **Restore TradingView indicator:**
- Change `longPosMax=85` back to `longPosMax=100`
- Update alert
3. **Restore Position Manager:**
```bash
cp lib/trading/position-manager.ts.backup_dec23 lib/trading/position-manager.ts
npm run build
docker compose build trading-bot
docker compose up -d --force-recreate trading-bot
```
4. **Verify rollback:**
- Check logs for old SL distance (~1.29%)
- Check no CATASTROPHIC messages
- Open test trade to confirm old behavior
---
## 💡 Alternative Approaches (If Above Fails)
### Plan B: Time-Based Exits
If asymmetric risk persists after tightening SL:
**Add time-based exit rules:**
- If no TP1 hit within 30 minutes: Close 50% at breakeven
- If no TP2 hit within 60 minutes: Close runner at +0.5%
- Forces exits before losses can compound
**Expected:** Reduces average loser AND average winner, but ratio improves
### Plan C: Adaptive SL Based on Volatility
If tighter SL increases stop-out rate too much:
**Use dynamic SL:**
- Low volatility (ATR <0.3%): SL = ATR × 2.0
- Medium volatility (ATR 0.3-0.6%): SL = ATR × 2.5
- High volatility (ATR >0.6%): SL = ATR × 3.0
**Expected:** Preserves tight stops in calm markets, allows room in volatile markets
---
## 📝 Notes for User
**This is NOT about:**
- ❌ Entry optimization (dynamic thresholds wouldn't help)
- ❌ Better indicators (v11 already has 60% WR)
- ❌ Signal quality (entries are fine)
**This IS about:**
- ✅ Cutting losses faster (SL too wide)
- ✅ Letting winners run longer (trailing too tight)
- ✅ Preventing catastrophic losses (no protection currently)
- ✅ Achieving 1:1 or better risk/reward ratio
**Bottom Line:**
Your entries are good enough (43.6% WR with v11 at 60% proves this). The problem is exits: winners close too soon, losers run too far. Fix the exits → system becomes profitable immediately.
**The $1,400 loss taught us:** It's not WHEN you enter (dynamic thresholds), it's WHEN you exit (stop loss + trailing stop tuning).