feat: Automated multi-timeframe price tracking system

Implemented comprehensive price tracking for multi-timeframe signal analysis.

**Components Added:**
- lib/analysis/blocked-signal-tracker.ts - Background job tracking prices
- app/api/analytics/signal-tracking/route.ts - Status/metrics endpoint

**Features:**
- Automatic price tracking at 1min, 5min, 15min, 30min intervals
- TP1/TP2/SL hit detection using ATR-based targets
- Max favorable/adverse excursion tracking (MFE/MAE)
- Analysis completion after 30 minutes
- Background job runs every 5 minutes
- Entry price captured from signal time

**Database Changes:**
- Added entryPrice field to BlockedSignal (for price tracking baseline)
- Added maxFavorablePrice, maxAdversePrice fields
- Added maxFavorableExcursion, maxAdverseExcursion fields

**Integration:**
- Auto-starts on container startup
- Tracks all DATA_COLLECTION_ONLY signals
- Uses same TP/SL calculation as live trades (ATR-based)
- Calculates profit % based on direction (long vs short)

**API Endpoints:**
- GET /api/analytics/signal-tracking - View tracking status and metrics
- POST /api/analytics/signal-tracking - Manually trigger update (auth required)

**Purpose:**
Enables data-driven multi-timeframe comparison. After 50+ signals per
timeframe, can analyze which timeframe (5min vs 15min vs 1H vs 4H vs Daily)
has best win rate, profit potential, and signal quality.

**What It Tracks:**
- Price at 1min, 5min, 15min, 30min after signal
- Would TP1/TP2/SL have been hit?
- Maximum profit/loss during 30min window
- Complete analysis of signal profitability

**How It Works:**
1. Signal comes in (15min, 1H, 4H, Daily) → saved to BlockedSignal
2. Background job runs every 5min
3. Queries current price from Pyth
4. Calculates profit % from entry
5. Checks if TP/SL thresholds crossed
6. Updates MFE/MAE if new highs/lows
7. After 30min, marks analysisComplete=true

**Future Analysis:**
After 50+ signals per timeframe:
- Compare TP1 hit rates across timeframes
- Identify which timeframe has highest win rate
- Determine optimal signal frequency vs quality trade-off
- Switch production to best-performing timeframe

User requested: "i want all the bells and whistles. lets make the
powerhouse more powerfull. i cant see any reason why we shouldnt"
This commit is contained in:
mindesbunister
2025-11-19 17:18:47 +01:00
parent e1bce56065
commit 60fc571aa6
7 changed files with 487 additions and 3 deletions

View File

@@ -147,6 +147,18 @@ export async function POST(request: NextRequest): Promise<NextResponse<RiskCheck
console.log('🔍 Risk check for:', body)
// 🔬 MULTI-TIMEFRAME DATA COLLECTION
// Allow all non-5min signals to bypass risk checks (they'll be saved as data collection in execute endpoint)
const timeframe = body.timeframe || '5'
if (timeframe !== '5') {
console.log(`📊 DATA COLLECTION: ${timeframe}min signal bypassing risk checks (will save in execute endpoint)`)
return NextResponse.json({
allowed: true,
reason: 'Multi-timeframe data collection',
details: `${timeframe}min signal will be saved for analysis but not executed`,
})
}
const config = getMergedConfig()
// Check for existing positions on the same symbol

View File

@@ -14,6 +14,7 @@ import { getInitializedPositionManager, ActiveTrade } from '@/lib/trading/positi
import { createTrade, updateTradeExit } from '@/lib/database/trades'
import { scoreSignalQuality } from '@/lib/trading/signal-quality'
import { getMarketDataCache } from '@/lib/trading/market-data-cache'
import { getPythPriceMonitor } from '@/lib/pyth/price-monitor'
export interface ExecuteTradeRequest {
symbol: string // TradingView symbol (e.g., 'SOLUSDT')
@@ -111,6 +112,11 @@ export async function POST(request: NextRequest): Promise<NextResponse<ExecuteTr
if (timeframe !== '5') {
console.log(`📊 DATA COLLECTION: ${timeframe}min signal from ${driftSymbol}, saving for analysis (not executing)`)
// Get current price for entry tracking
const priceMonitor = getPythPriceMonitor()
const latestPrice = priceMonitor.getCachedPrice(driftSymbol)
const currentPrice = latestPrice?.price || body.signalPrice || 0
// Save to BlockedSignal for cross-timeframe analysis
const { createBlockedSignal } = await import('@/lib/database/trades')
try {
@@ -125,13 +131,13 @@ export async function POST(request: NextRequest): Promise<NextResponse<ExecuteTr
volumeRatio: body.volumeRatio,
pricePosition: body.pricePosition,
timeframe: timeframe,
signalPrice: body.signalPrice || 0,
signalPrice: currentPrice,
signalQualityScore: 0, // Not scored since not executed
signalQualityVersion: 'data-collection',
minScoreRequired: 0,
scoreBreakdown: {},
})
console.log(`${timeframe}min signal saved to database for future analysis`)
console.log(`${timeframe}min signal saved at $${currentPrice.toFixed(2)} for future analysis`)
} catch (dbError) {
console.error(`❌ Failed to save ${timeframe}min signal:`, dbError)
}