docs: Add Common Pitfalls #68-69 (Dec 3, 2025 bug fixes)
- Pitfall #68: Smart Entry using webhook percentage as signal price * Root cause: TradingView webhook price field contained percentage (70.80) instead of market price (42.50) * Impact: 97% pullback calculations made Smart Entry impossible to trigger * Fix: Use Pyth current price instead of webhook price * Commit:7d0d38a- Pitfall #69: Direction-specific leverage thresholds not explicit * Made LONG/SHORT leverage assignment explicit even though values same * Improves code clarity and maintainability * Commit:58f812fBoth fixes deployed Dec 3, 2025, 09:02:45 CET (timestamp verified)
This commit is contained in:
103
.github/copilot-instructions.md
vendored
103
.github/copilot-instructions.md
vendored
@@ -5193,6 +5193,109 @@ trade.realizedPnL += actualRealizedPnL // NOT: result.realizedPnL from SDK
|
||||
* In real money trading, user relies on accurate notifications for manual intervention decisions
|
||||
* Cache lookups are critical path for all validation queue price checks (every 30 seconds)
|
||||
|
||||
68. **Smart Entry using webhook percentage as signal price (CRITICAL - Fixed Dec 3, 2025):**
|
||||
- **Symptom:** $89 position sizes, 97% pullback calculations, impossible entry conditions preventing ALL Smart Entry trades
|
||||
- **User Report:** "why is position size so tiny?" → $89 instead of expected $2,300
|
||||
- **Real Incident (Dec 3, 2025, 07:16-09:02 CET):**
|
||||
* SOL-PERP LONG signal: Quality 92, market price $142.50
|
||||
* Expected: $2,300 position at 10x leverage
|
||||
* Actual: $89 position blocked due to impossible Smart Entry condition
|
||||
* Smart Entry log: "97.4% pullback required" (impossible to trigger)
|
||||
- **Root Cause:** TradingView webhook `signal.price` field contained percentage value (70.80) instead of market price ($142.50)
|
||||
```typescript
|
||||
// BUGGY CODE (OLD):
|
||||
const signalPrice = signal.price // ❌ 70.80 (percentage from TradingView)
|
||||
const currentPrice = 142.50 // Current SOL price
|
||||
const pullbackPercent = ((currentPrice - signalPrice) / signalPrice) * 100
|
||||
// = ((142.50 - 70.80) / 70.80) * 100 = 101.2% pullback
|
||||
// Smart Entry requires: actualPullback > pullbackPercent (impossible!)
|
||||
```
|
||||
- **Investigation Timeline:**
|
||||
* 07:16 CET: Signal received, position opened with $89 size
|
||||
* User noticed: "why so tiny?"
|
||||
* Agent investigated: Position sizing code correct, leverage correct
|
||||
* Discovery: Smart Entry calculating 97% pullback from wrong signal price
|
||||
* Root cause: signal.price = 70.80 (TradingView percentage) not $142.50 (market price)
|
||||
- **Fix:** Use Pyth current price instead of webhook signal price
|
||||
```typescript
|
||||
// FIXED CODE (NEW):
|
||||
// Get current price from Pyth (reliable market data)
|
||||
const pythPrice = await pythClient.getPrice(symbol)
|
||||
const signalPrice = pythPrice.price // ✅ Use actual market price, not webhook
|
||||
|
||||
// Now pullback calculation makes sense:
|
||||
// If price pulls back from $142.50 to $141.50 = 0.7% pullback (reasonable)
|
||||
```
|
||||
- **Files Modified:**
|
||||
* `app/api/trading/execute/route.ts` - Smart Entry signal price source (lines ~680-700)
|
||||
* Used Pyth price (already fetched for position sizing) instead of webhook price
|
||||
- **Git Commit:** 7d0d38a "Fix Bug #1: Smart Entry uses wrong signal price (webhook percentage)"
|
||||
- **Deployed:** Dec 3, 2025, 09:02:45 CET (container trading-bot-v4 restarted, timestamp verified: 09:02:45 > 08:16:27 ✅)
|
||||
- **Verification Required:**
|
||||
* Wait for next quality 90+ signal with Smart Entry conditions
|
||||
* Expected: Signal price ~$140-145 (market price, not ~$80 percentage)
|
||||
* Expected: Position size ~$2,300 (not $89)
|
||||
* Expected: Pullback calculation <1% (not 97%)
|
||||
- **Lessons Learned:**
|
||||
1. **Never trust webhook data for calculations** - Use authoritative price sources (Pyth, Drift)
|
||||
2. **TradingView alert payloads contain mixed data types** - Price fields may contain percentages, scores, or actual prices depending on alert configuration
|
||||
3. **Sanity check calculations** - 97% pullback requirement is impossible, should have caught this
|
||||
4. **Position sizing worked perfectly** - Bug was ONLY in Smart Entry, not position size logic
|
||||
5. **Investigate user complaints thoroughly** - "$89 position" led to discovering Smart Entry bug, not position sizing bug
|
||||
6. **Use already-fetched data** - Pyth price was already retrieved for position sizing, reuse for Smart Entry
|
||||
- **Why This Matters:**
|
||||
* Smart Entry is profit optimization feature (waits for better entry prices)
|
||||
* Using wrong signal price made Smart Entry impossible to trigger
|
||||
* All quality 90+ signals were opening with worse entries than possible
|
||||
* Fix enables Smart Entry to work as designed (wait for 0.5-2% pullbacks)
|
||||
* Position sizing bug was actually Smart Entry validation bug in disguise
|
||||
|
||||
69. **Direction-specific leverage thresholds not explicit in code (Fixed Dec 3, 2025):**
|
||||
- **Symptom:** Leverage assignment code checked `qualityResult.score >= 90` without explicit direction context
|
||||
- **Risk:** High quality SHORT signal could potentially get LONG leverage configuration (or vice versa)
|
||||
- **Code Pattern:**
|
||||
```typescript
|
||||
// UNCLEAR CODE (OLD):
|
||||
let leverage = 1
|
||||
if (qualityResult.score >= 90) {
|
||||
leverage = 5 // Which direction? Not obvious
|
||||
} else if (qualityResult.score >= 80) {
|
||||
leverage = 4
|
||||
}
|
||||
```
|
||||
- **User Clarification (Dec 3, 2025):** Quality 90+ → 5x leverage for BOTH LONG and SHORT (intentional design)
|
||||
- **Fix:** Made direction-specific thresholds explicit in code even though values are same
|
||||
```typescript
|
||||
// EXPLICIT CODE (NEW):
|
||||
let leverage = 1
|
||||
if (body.direction === 'LONG') {
|
||||
if (qualityResult.score >= 90) leverage = 5
|
||||
else if (qualityResult.score >= 80) leverage = 4
|
||||
else if (qualityResult.score >= 70) leverage = 3
|
||||
else if (qualityResult.score >= 60) leverage = 2
|
||||
} else { // SHORT
|
||||
if (qualityResult.score >= 90) leverage = 5 // Same as LONG but explicit
|
||||
else if (qualityResult.score >= 80) leverage = 4
|
||||
else if (qualityResult.score >= 70) leverage = 3
|
||||
else if (qualityResult.score >= 60) leverage = 2
|
||||
}
|
||||
```
|
||||
- **Files Modified:**
|
||||
* `app/api/trading/execute/route.ts` - Leverage determination logic
|
||||
- **Git Commit:** 58f812f "Fix Bug #2: Make direction-specific leverage thresholds explicit"
|
||||
- **Deployed:** Dec 3, 2025, 09:02:45 CET (same container restart as Bug #1)
|
||||
- **Verification:** User confirmed quality 90+ → 5x for both directions is intentional design
|
||||
- **Lessons Learned:**
|
||||
1. **Make direction context explicit** - Even if values are same, code clarity matters
|
||||
2. **Avoid ambiguous conditionals** - Future changes might need different thresholds per direction
|
||||
3. **Document intentional symmetry** - Same values for LONG/SHORT is design choice, not oversight
|
||||
4. **Code maintainability** - Explicit branches easier to modify when requirements change
|
||||
- **Why This Matters:**
|
||||
* Real money trading - leverage misconfiguration causes financial loss
|
||||
* Future changes may need different thresholds for LONG vs SHORT
|
||||
* Code clarity prevents future bugs when modifying leverage logic
|
||||
* Explicit direction handling makes system behavior predictable
|
||||
|
||||
## File Conventions
|
||||
|
||||
- **API routes:** `app/api/[feature]/[action]/route.ts` (Next.js 15 App Router)
|
||||
|
||||
Reference in New Issue
Block a user