fix: use Pyth price data for flip-flop context check

CRITICAL FIX: Previous implementation showed incorrect price movements
(100% instead of 0.2%) because currentPrice wasn't available in
check-risk endpoint.

Changes:
- app/api/trading/check-risk/route.ts: Fetch current price from Pyth
  price monitor before quality scoring
- lib/trading/signal-quality.ts: Added validation and detailed logging
  - Check if currentPrice available, apply penalty if missing
  - Log actual prices: $X → $Y = Z%
  - Include prices in penalty/allowance messages

Example outputs:
 Flip-flop in tight range: 4min ago, only 0.20% move ($143.86 → $143.58) (-25 pts)
 Direction change after 10.2% move ($170.00 → $153.00, 12min ago) - reversal allowed

This fixes the false positive that allowed a 0.2% flip-flop earlier today.

Deployed: 09:42 CET Nov 14, 2025
This commit is contained in:
mindesbunister
2025-11-14 08:23:04 +01:00
parent 669c54206d
commit 795026aed1
2 changed files with 32 additions and 17 deletions

View File

@@ -213,30 +213,40 @@ export async function scoreSignalQuality(params: {
// BUT: Only penalize if price hasn't moved significantly (< 2% from opposite signal)
// This distinguishes chop (bad) from legitimate reversals (good)
if (recentSignals.oppositeDirectionInWindow && recentSignals.oppositeDirectionPrice) {
const priceChangePercent = Math.abs(
((params.currentPrice || 0) - recentSignals.oppositeDirectionPrice) / recentSignals.oppositeDirectionPrice * 100
)
if (priceChangePercent < 2.0) {
// Small price move = consolidation/chop = BAD
if (!params.currentPrice || params.currentPrice === 0) {
// No current price available - apply penalty (conservative)
console.warn(`⚠️ Flip-flop check: No currentPrice available, applying penalty`)
frequencyPenalties.flipFlop = -25
score -= 25
reasons.push(
`⚠️ Flip-flop in tight range: ${recentSignals.oppositeDirectionMinutesAgo}min ago, ` +
`only ${priceChangePercent.toFixed(2)}% move (-25 pts)`
)
reasons.push(`⚠️ Flip-flop detected: opposite direction ${recentSignals.oppositeDirectionMinutesAgo}min ago, no price data (-25 pts)`)
} else {
// Large price move = potential reversal = ALLOW
reasons.push(
`✅ Direction change after ${priceChangePercent.toFixed(1)}% move ` +
`(${recentSignals.oppositeDirectionMinutesAgo}min ago) - reversal allowed`
const priceChangePercent = Math.abs(
(params.currentPrice - recentSignals.oppositeDirectionPrice) / recentSignals.oppositeDirectionPrice * 100
)
console.log(`🔍 Flip-flop price check: $${recentSignals.oppositeDirectionPrice.toFixed(2)}$${params.currentPrice.toFixed(2)} = ${priceChangePercent.toFixed(2)}%`)
if (priceChangePercent < 2.0) {
// Small price move = consolidation/chop = BAD
frequencyPenalties.flipFlop = -25
score -= 25
reasons.push(
`⚠️ Flip-flop in tight range: ${recentSignals.oppositeDirectionMinutesAgo}min ago, ` +
`only ${priceChangePercent.toFixed(2)}% move ($${recentSignals.oppositeDirectionPrice.toFixed(2)}$${params.currentPrice.toFixed(2)}) (-25 pts)`
)
} else {
// Large price move = potential reversal = ALLOW
reasons.push(
`✅ Direction change after ${priceChangePercent.toFixed(1)}% move ` +
`($${recentSignals.oppositeDirectionPrice.toFixed(2)}$${params.currentPrice.toFixed(2)}, ${recentSignals.oppositeDirectionMinutesAgo}min ago) - reversal allowed`
)
}
}
} else if (recentSignals.oppositeDirectionInWindow && !recentSignals.oppositeDirectionPrice) {
// Fallback: If we don't have price data, apply penalty (conservative)
// Fallback: If we don't have opposite price data, apply penalty (conservative)
frequencyPenalties.flipFlop = -25
score -= 25
reasons.push(`⚠️ Flip-flop detected: opposite direction ${recentSignals.oppositeDirectionMinutesAgo}min ago (-25 pts)`)
reasons.push(`⚠️ Flip-flop detected: opposite direction ${recentSignals.oppositeDirectionMinutesAgo}min ago, no historical price (-25 pts)`)
}
// Penalty 3: Alternating pattern (last 3 trades flip directions)