docs: Add Common Pitfall #55 - BlockedSignalTracker Pyth cache bug

- Documented Nov 20, 2025 fix for multi-timeframe data collection
- Tracker was using Pyth cache (empty) instead of Drift oracle prices
- Result: 30+ hours with no price tracking, all priceAfter* fields NULL
- Fix: Changed to initializeDriftService() + getOraclePrice()
- Now working: Price tracking every 5min, analysisComplete transitions, TP/SL detection
- Impact: Multi-timeframe data collection now operational for Phase 1 analysis
This commit is contained in:
mindesbunister
2025-11-20 10:38:00 +01:00
parent 6b00303970
commit 5db7d7cc0a

View File

@@ -2798,6 +2798,92 @@ trade.realizedPnL += actualRealizedPnL // NOT: result.realizedPnL from SDK
* `config/trading.ts` - Bot reads `MIN_SIGNAL_QUALITY_SCORE` (correct name)
* `.env` file - Contains `MIN_SIGNAL_QUALITY_SCORE=60` (correct name)
- **Fix:**
- **Lesson:** When creating settings UI, always use EXACT ENV variable names from actual bot code. Mismatched names cause silent failures where user actions have no effect. Test settings changes end-to-end (UI → .env → bot behavior).
55. **BlockedSignalTracker using Pyth cache instead of Drift oracle (CRITICAL - Fixed Nov 20, 2025):**
- **Symptom:** All `priceAfter1Min/5Min/15Min/30Min` fields staying NULL, no price tracking happening
- **Root Cause:** BlockedSignalTracker was calling `getPythPriceMonitor().getCachedPrice()` which didn't have SOL-PERP prices
- **Real incident (Nov 20):**
* Multi-timeframe data collection running for 30+ hours
* 4 signals saved to BlockedSignal table (15min: 2, 60min: 2)
* Tracker running every 5 minutes: "📊 Tracking 4 blocked signals..."
* But logs showed: "⚠️ No price available for SOL-PERP, skipping" (repeated 100+ times)
* All priceAfter* fields remained NULL
* No analysisComplete transitions
* No wouldHitTP1/TP2/SL detection
- **Why Pyth cache empty:**
* Pyth price monitor used for Position Manager real-time monitoring
* BlockedSignalTracker runs every 5 minutes (not real-time)
* Cache may not have recent prices when tracker runs
* Wrong data source for background job
- **Impact:** Multi-timeframe data collection completely non-functional for Phase 1 analysis
- **Fix (Nov 20, 2025):**
```typescript
// BEFORE (BROKEN - lib/analysis/blocked-signal-tracker.ts):
import { getPythPriceMonitor } from '../pyth/price-monitor'
private async trackSignal(signal: BlockedSignalWithTracking): Promise<void> {
const priceMonitor = getPythPriceMonitor()
const latestPrice = priceMonitor.getCachedPrice(signal.symbol)
if (!latestPrice || !latestPrice.price) {
console.log(`⚠️ No price available for ${signal.symbol}, skipping`)
return
}
const currentPrice = latestPrice.price
// ... rest of tracking
}
// AFTER (FIXED):
import { initializeDriftService } from '../drift/client'
import { SUPPORTED_MARKETS } from '../../config/trading'
private async trackPrices(): Promise<void> {
// Initialize Drift service ONCE before processing all signals
const driftService = await initializeDriftService()
if (!driftService) {
console.log('⚠️ Drift service not available, skipping price tracking')
return
}
// ... process signals
}
private async trackSignal(signal: BlockedSignalWithTracking): Promise<void> {
// Get current price from Drift oracle (always available)
const driftService = await initializeDriftService()
const marketConfig = SUPPORTED_MARKETS[signal.symbol]
if (!marketConfig) {
console.log(`⚠️ No market config for ${signal.symbol}, skipping`)
return
}
const currentPrice = await driftService.getOraclePrice(marketConfig.driftMarketIndex)
const entryPrice = Number(signal.entryPrice)
if (entryPrice === 0) {
console.log(`⚠️ Entry price is 0 for ${signal.symbol}, skipping`)
return
}
// ... rest of tracking with actual prices
}
```
- **Behavior now:**
* Tracker gets fresh prices from Drift oracle every run
* Logs show: "📍 SOL-PERP long @ 1min: $142.34 (4.10%)"
* Database updates: priceAfter1Min, priceAfter5Min, priceAfter15Min, priceAfter30Min all populate
* analysisComplete transitions to true after 30 minutes
* wouldHitTP1/TP2/SL detection working based on ATR targets
- **Verification (Nov 20):**
* 2 signals now complete with full price tracking data
* 15min signal: wouldHitTP1=true, wouldHitTP2=true (both targets hit)
* 60min signal: wouldHitTP1=true (TP1 hit, TP2 pending)
* analysisComplete=true for both after 30min window
- **Files changed:**
* `lib/analysis/blocked-signal-tracker.ts` - Changed price source + added Drift init
- **Commits:** 6b00303 "fix: BlockedSignalTracker now uses Drift oracle prices"
- **Impact:** Multi-timeframe data collection now operational for Phase 1 analysis (50+ signals per timeframe target)
- **Lesson:** Background jobs should use Drift oracle prices (always available) not Pyth cache (real-time only). Always initialize external services before calling their methods. Verify background jobs are actually working by checking database state, not just logs.
```typescript
// In app/api/settings/route.ts (lines ~150, ~270)
// BEFORE (BROKEN):