Files
trading_bot_v4/docs/V11_ANALYSIS_DEC15_2025.md
mindesbunister aa16daffa2 critical: Fix Bug #87 - Add 3-tier SL verification with circuit breaker
CRITICAL FIX: Prevents silent stop-loss placement failures that caused $1,000+ losses

Created lib/safety/sl-verification.ts (334 lines):
 60s → 90s delays
- Queries Drift protocol directly via user.getOpenOrders()
- Filters SL orders: marketIndex + reduceOnly + TRIGGER_MARKET/LIMIT
- Circuit breaker: haltTrading() blocks new trades on verification failure
- Emergency shutdown: Force-closes position after 3 failed attempts
- Event-driven architecture: Triggered once post-open (not polling)
- Reduces Drift API calls by ~95% vs continuous polling

Integrated in app/api/trading/execute/route.ts:
- Line 54: Import shouldAcceptNewTrade for pre-execution check
- Lines 215-221: Circuit breaker validates trading allowed (HTTP 503 if halted)
- Lines 583-592: Triggers SL verification post-open (fire-and-forget)

Root Cause - Bug #76: Silent SL placement failure
Database Evidence: Trade cmj8abpjo00w8o407m3fndmx0
- tp1OrderTx: 'DsRv7E8vtAS4dKFmoQoTZMdiLTUju9cfmr9DPCgquP3V...'  EXISTS
- tp2OrderTx: '3cmYgGE828hZAhpepShXmpxqCTACFvXijqEjEzoed5PG...'  EXISTS
- slOrderTx: NULL 
- softStopOrderTx: NULL 
- hardStopOrderTx: NULL 

User Report: 'RISK MANAGEMENT WAS REMOVED WHEN PRICE WENT TO SL!!!!! POSITION STILL OPEN'
Reality: SL orders never placed from start (not cancelled later)

Solution Philosophy: 'better safe than sorry' - user's words
Safety: Query on-chain state directly, don't trust internal success flags

Deployed: 2025-12-16 13:50:18 UTC
Docker Image: SHA256:80fd45004e71fa490fc4f472b252ecb25db91c6d90948de1516646b12a00446f
Container: trading-bot-v4 restarted successfully
2025-12-16 14:50:18 +01:00

359 lines
13 KiB
Markdown

# v11 Indicator Analysis - December 15, 2025
## Executive Summary
**Overall Performance:** 7 trades, 57.1% win rate, -$1.80 total P&L
**Sample Size:** TOO SMALL for definitive conclusions (need 20+ trades)
**Data Quality:** Average quality score 88.6 (good filtering)
---
## 🚨 CRITICAL FINDINGS - IMMEDIATE ACTION REQUIRED
### 1. **LONG TRADES ARE LOSING MONEY** (-$2.22 total, 40% WR)
- **Problem:** LONGs at top of range (80-100%) are mixed results
- **Worst Loser:** Quality 75, RSI 73.5 (overbought), Position 94.4% → **-$17.09 loss**
- **Pattern:** Buying overbought conditions at range tops = disaster
### 2. **SHORT TRADES ARE PERFECT** (+$0.42 total, 100% WR)
- **2 trades, 2 wins** (Quality 85-105, ADX 22-34)
- **Both:** RSI 38-44 (bearish zone), good momentum
### 3. **QUALITY 95-99 FAILED** (-$4.72 on 1 trade)
- **Single failure:** Q95, LONG at 63.5% position, RSI 59.5 → stopped out
- **Contradicts:** Q100+ had 100% WR (+$24.01)
- **Issue:** Quality 95 threshold may be too low, or 95-99 tier unlucky
### 4. **RSI SWEET SPOT FOR LONGS: 60-70** (100% WR, +$26.97)
- **Avoid:** RSI >70 (overbought) → -$17.09
- **Avoid:** RSI 50-60 (weak bullish) → -$12.10
- **Trade:** RSI 60-70 (strong but not overbought) → +$26.97
---
## Detailed Pattern Analysis
### Direction Performance
| Direction | Trades | Win Rate | Total P&L | Avg P&L |
|-----------|--------|----------|-----------|---------|
| **SHORT** | 2 | **100.0%** | **+$0.42** | +$0.21 |
| **LONG** | 5 | **40.0%** | **-$2.22** | -$0.44 |
**Conclusion:** v11 SHORTs are working, LONGs need filter improvements.
---
### Quality Score Tiers
| Quality Tier | Trades | Win Rate | Total P&L | Avg P&L |
|--------------|--------|----------|-----------|---------|
| **100+** | 2 | **100.0%** | **+$24.01** | +$12.01 |
| **95-99** | 1 | **0.0%** | -$4.72 | -$4.72 |
| **85-89** | 2 | **100.0%** | +$3.37 | +$1.69 |
| **<85** | 2 | **0.0%** | -$24.47 | -$12.23 |
**Findings:**
- ✅ Quality 100+ = perfect edge (2/2 wins)
- ✅ Quality 85-89 = solid (2/2 wins)
- ❌ Quality 95-99 = single failure (1/1 loss) - **SAMPLE SIZE TOO SMALL**
- ❌ Quality <85 = disaster (0/2 wins)
**Action:** Need 5+ more trades in 95-99 tier to validate if real problem or outlier.
---
### ADX Strength Analysis
| ADX Tier | Trades | Avg ADX | Win Rate | Total P&L |
|----------|--------|---------|----------|-----------|
| **30+ Very Strong** | 1 | 34.2 | **100.0%** | +$0.38 |
| **20-25 Moderate** | 4 | 23.6 | **50.0%** | +$1.85 |
| **15-20 Weak** | 2 | 16.2 | **50.0%** | -$4.04 |
**Finding:** Strong ADX (30+) only 1 trade but won. Moderate (20-25) is 50/50.
---
### Price Position Analysis (LONGs Only)
| Price Zone | Trades | Avg Pos | Win Rate | Total P&L |
|------------|--------|---------|----------|-----------|
| **80-100 Top** | 3 | 89.5% | **66.7%** | **+$9.88** |
| **60-80 Upper** | 1 | 63.5% | **0.0%** | -$4.72 |
| **40-60 Middle** | 1 | 54.2% | **0.0%** | -$7.38 |
**CRITICAL FINDING:**
- ✅ LONGs at TOP of range (80-100%) = **66.7% WR, +$9.88**
- ❌ LONGs at MIDDLE/UPPER (40-80%) = **0% WR, -$12.10**
**Explanation:** This seems counterintuitive but:
1. **Top of range (80-100%):** Strong momentum breakouts, continuation plays
2. **Middle/upper (40-80%):** Weak momentum, often rejects or chops
**BUT WARNING:** Top winner (Q100, +$23.63) skews this. Need more data.
---
### RSI Analysis by Direction
#### LONG Trades RSI Performance
| RSI Zone | Trades | Avg RSI | Win Rate | Total P&L |
|----------|--------|---------|----------|-----------|
| **70+ Overbought** | 1 | 73.5 | **0.0%** | **-$17.09** ⚠️ |
| **60-70 Strong** | 2 | 63.2 | **100.0%** | **+$26.97** ✅ |
| **50-60 Bullish** | 2 | 57.3 | **0.0%** | -$12.10 |
**ACTIONABLE RULE FOR LONGs:**
-**ENTER:** RSI 60-70 (strong but not overbought) = **100% WR**
-**BLOCK:** RSI >70 (overbought) = biggest single loss (-$17.09)
-**BLOCK:** RSI <60 (weak momentum) = 0% WR
#### SHORT Trades RSI Performance
| RSI Zone | Trades | Avg RSI | Win Rate | Total P&L |
|----------|--------|---------|----------|-----------|
| **40-50 Bearish** | 1 | 44.0 | 100.0% | +$0.03 |
| **30-40 Weak** | 1 | 38.8 | 100.0% | +$0.38 |
**Finding:** Both SHORTs won with RSI 38-44 (bearish/weak zones) ✅
---
### Exit Reason Breakdown
| Exit Reason | Count | Percentage | Avg P&L |
|-------------|-------|------------|---------|
| **SL** | 4 | 57.1% | -$1.39 |
| **TP1** | 2 | 28.6% | +$1.86 |
| **manual** | 1 | 14.3% | +$0.03 |
**Finding:** 57% of trades hit SL (stopped out). Only 29% hit TP1.
---
## Winner vs Loser Comparison
### Top Winner: Quality 100 LONG (+$23.63)
- **Time:** 12-10 19:35
- **Metrics:** ADX 24.8, RSI 63.0, Position 93.8%, Vol 1.30
- **Exit:** SL (but made profit somehow - check this)
- **Pattern:** Top of range (93.8%), RSI sweet spot (63.0), good volume
### Worst Loser: Quality 75 LONG (-$17.09)
- **Time:** 12-15 02:19
- **Metrics:** ADX 23.4, RSI 73.5, Position 94.4%, Vol 1.41
- **Exit:** SL
- **Pattern:** **Overbought RSI (73.5)** at top of range
**Key Difference:** Winner at RSI 63, loser at RSI 73.5 → **RSI 70+ is death zone**
---
## 📊 OPTIMIZATION RECOMMENDATIONS
### Immediate Filters (High Confidence)
#### 1. **BLOCK OVERBOUGHT LONGs** (RSI >70)
```typescript
if (direction === 'long' && rsi > 70) {
score -= 50 // Major penalty
blockReason = 'OVERBOUGHT_RSI_LONG'
}
```
**Impact:** Would have blocked -$17.09 loss (worst trade)
#### 2. **REQUIRE RSI 60-70 FOR LONGs**
```typescript
if (direction === 'long' && (rsi < 60 || rsi > 70)) {
score -= 30 // Significant penalty
}
```
**Impact:** Would have blocked 3 losers (-$29.19 total)
#### 3. **KEEP SHORT ENTRY LOGIC AS-IS**
- SHORTs are 100% WR (2/2) with current filters
- RSI 30-50 range is working
- Don't change what's not broken
---
### Medium Confidence Filters (Need More Data)
#### 4. **CONSIDER BLOCKING LOW ADX (<20)**
- ADX 15-20 had 50% WR (-$4.04)
- But only 2 trades - need 5+ more
- **Wait for more data**
#### 5. **VALIDATE QUALITY 95-99 TIER**
- Single failure at Q95 (-$4.72)
- Could be outlier
- Need 5+ trades in this tier before adjusting threshold
---
### Research Questions (Collect More Data)
1. **Price Position Paradox:** Why do LONGs at top (80-100%) win more than middle (40-80%)?
- Hypothesis: Top = breakout momentum, middle = chop/rejection
- Need 10+ more trades to validate
2. **Quality 95-99 Anomaly:** Is Q95-99 actually worse than Q85-89?
- Current: Q85-89 = 100% WR, Q95-99 = 0% WR
- Need 5+ more trades at Q95-99
3. **Volume Impact:** Vol 1.30-1.42 on winners, 0.95-1.41 on losers
- Insufficient sample to determine threshold
- Need 20+ trades
---
## Data Quality Assessment
### Sample Size Status
- **Total Trades:** 7 (❌ Need 20+ minimum)
- **LONG Trades:** 5 (⚠️ Need 10+ minimum)
- **SHORT Trades:** 2 (❌ Need 10+ minimum)
- **Quality Tiers:** 1-2 per tier (❌ Need 5+ per tier)
- **ADX Tiers:** 1-4 per tier (⚠️ Borderline)
- **RSI Zones:** 1-2 per zone (❌ Need 5+ per zone)
**Confidence Level:** LOW - Most patterns need more data for validation
**Exception:** RSI >70 LONG disaster is strong signal (single worst trade, clear overbought condition)
---
## Action Plan
### Phase 1: Immediate (Today)
1.**Add RSI >70 penalty for LONGs** (-50 points)
2.**Add RSI <60 penalty for LONGs** (-30 points)
3. 📊 **Monitor next 10-15 trades** to validate pattern
### Phase 2: Data Collection (Next 7 Days)
1. Collect 15+ more v11 trades (target: 20+ total)
2. Validate RSI 60-70 sweet spot holds
3. Check if quality 95-99 failure was outlier
4. Analyze price position paradox with more data
### Phase 3: Refinement (After 20+ Trades)
1. Optimize ADX thresholds if pattern emerges
2. Adjust quality score tiers based on larger sample
3. Consider volume multiplier if correlation found
4. Review position sizing based on RSI zones
---
## Technical Notes
- **Database:** All queries from `Trade` table with `indicatorVersion = 'v11'`
- **Column Names:** `adxAtEntry`, `rsiAtEntry`, `pricePositionAtEntry`, `volumeAtEntry`
- **P&L:** `realizedPnL` field (post-exit calculated values)
- **Date Range:** Dec 10-15, 2025 (5 days of trading)
---
## Appendix: All v11 Trades
### Sorted by P&L (Best to Worst)
| Date | Symbol | Dir | Quality | ADX | RSI | Pos | Vol | Exit | P&L |
|------|--------|-----|---------|-----|-----|-----|-----|------|-----|
| 12-10 19:35 | SOL | LONG | 100 | 24.8 | 63.0 | 93.8 | 1.30 | SL | +$23.63 |
| 12-11 19:12 | SOL | LONG | 85 | 15.4 | 63.3 | 80.3 | 1.31 | TP1 | +$3.34 |
| 12-14 10:37 | SOL | SHORT | 105 | 34.2 | 38.8 | - | - | TP1 | +$0.38 |
| 12-10 22:37 | SOL | SHORT | 85 | 22.4 | 44.0 | - | - | manual | +$0.03 |
| 12-10 04:55 | SOL | LONG | 95 | 23.9 | 59.5 | 63.5 | 1.42 | SL | -$4.72 |
| 12-12 13:07 | SOL | LONG | 75 | 17.0 | 55.0 | 54.2 | 0.95 | SL | -$7.38 |
| 12-15 02:19 | SOL | LONG | 75 | 23.4 | 73.5 | 94.4 | 1.41 | SL | -$17.09 |
**Total:** -$1.80 (57.1% WR, 4 wins, 3 losses)
---
## Conclusion
**v11 has potential but needs RSI filter refinement for LONGs.**
**Clear Signal:** RSI >70 for LONGs = disaster zone (-$17.09 worst trade)
**Winning Pattern:** RSI 60-70 for LONGs = 100% WR (+$26.97)
**SHORTs:** Working perfectly (2/2 wins), don't change
**Next Steps:**
1. Add RSI 60-70 requirement for LONGs
2. Block RSI >70 LONGs entirely
3. Collect 15+ more trades to validate patterns
4. Re-analyze after reaching 20+ trade sample size
---
## 🛡️ Bug #76 Protection System - DEPLOYED Dec 16, 2025
**Root Cause Confirmed:** Position cmj8abpjo00w8o407m3fndmx0 opened 07:52 UTC with TP1/TP2 orders but **NO stop loss order** (Bug #76 - Silent SL Placement Failure). Database shows:
- `tp1OrderTx`: DsRv7E8v... ✅ (exists)
- `tp2OrderTx`: 3cmYgGE8... ✅ (exists)
- `slOrderTx`: NULL ❌ (never placed)
- `softStopOrderTx`: NULL ❌
- `hardStopOrderTx`: NULL ❌
**User Impact:** Position left completely unprotected. User saw TP orders in Drift UI and assumed SL existed. As price approached danger zone, checked more carefully and discovered SL missing.
**User Interpretation:** "TP1 and SL vanished as price approached stop loss" - but actually SL was never placed from the beginning (Drift order history only shows filled orders, not cancelled).
**Prevention System Implemented:**
### Architecture: 3-Tier Exponential Backoff Verification
- **Attempt 1:** 30 seconds after position opens
- **Attempt 2:** 60 seconds (if Attempt 1 fails)
- **Attempt 3:** 90 seconds (if Attempt 2 fails)
- **If all fail:** Halt trading + close position immediately
### Implementation Files
1. **lib/safety/sl-verification.ts** (new file)
- `querySLOrdersFromDrift()` - Query Drift on-chain state for SL orders
- `verifySLWithRetries()` - 3-tier verification with exponential backoff
- `haltTradingAndClosePosition()` - Emergency halt + position closure
- `checkTradingAllowed()` - Circuit breaker check before new trades
2. **app/api/trading/execute/route.ts** (modified)
- Circuit breaker check at line ~95 - rejects trades when halted
- Verification trigger at line ~1128 - starts after position added to manager
- Runs asynchronously in background (doesn't block trade execution)
### Safety Features
- **Drift On-Chain Verification:** Queries actual Drift orders, not just database
- **Circuit Breaker:** Halts all new trades after critical SL placement failures
- **Automatic Position Closure:** Closes unprotected position immediately for safety
- **Critical Telegram Alerts:** Notifies user of halt + closure actions
- **Rate Limit Efficient:** 3-9 queries per position (vs 360/hour with interval-based)
### User Mandate
> "i mean the opening of the positions was/is working flawlessly so far. so i think simply check 30s/60s/90s after the position was opened that the risk management is in place. 3 calls after an action took place. thats still not much as we dont open trades that often.
>
> if it fails. stop trading and close the current position. better safe than sorry"
### Expected Behavior
1. Position opens successfully at T+0s
2. Verification Attempt 1 at T+30s → queries Drift for SL orders
3. If SL found: SUCCESS, verification complete ✅
4. If SL missing: Wait, retry at T+60s
5. If still missing: Wait, retry at T+90s
6. If still missing after 3 attempts:
- Set `tradingHalted = true` (global flag)
- Close position immediately via market order
- Send critical Telegram alert
- Reject all new trade requests with "Trading halted" error
- Require manual reset via API or Telegram command
### Deployment
- **Date:** Dec 16, 2025 11:30 UTC
- **Status:** Code complete, ready for Docker build + deployment
- **Git commits:** Pending (to be committed after testing)
- **Manual Reset:** Required after halt - prevents cascading failures
**"Better safe than sorry" - User's mandate prioritizes capital preservation over opportunity.**