critical: Fix Bug #1 - Smart Entry using wrong signal price

PROBLEM:
Smart Entry showed 'Signal Price: $70.80' when actual SOL price was ~$139.70
Calculated 'Pullback: -97.38%' when actual price change was <1%
Smart Entry queue completely broken due to wrong price

ROOT CAUSE:
TradingView webhook (or n8n workflow) sends pricePosition percentage (73.77)
as signalPrice instead of actual dollar price ($139.70)
Code used body.signalPrice directly without validation

EVIDENCE:
Webhook payload: "pricePosition": 73.7704918033, "signalPrice": 73.7704918033
Identical values = pricePosition mapped incorrectly to signalPrice
Percentage value (0-100) treated as dollar price = 100× too low

FIXES:
1. Added detection: If signalPrice < $10, log warning (likely percentage)
2. Changed signalPrice source: Use currentPrice from Pyth (NOT body.signalPrice)
3. At signal time: priceChange = 0, pullbackMagnitude = 0 (no pullback yet)
4. Queue with correct price: Smart Entry timer gets current market price
5. Added comments explaining bug and fix

IMPACT:
 Smart Entry will now use correct signal price ($130-150 for SOL)
 Pullback calculations will be accurate (0.15-0.5% range, not 97%)
 Queue will work correctly (wait for actual dips/bounces)
 Next signal will validate fix in production logs

TESTING REQUIRED:
- Wait for next signal (LONG or SHORT)
- Verify log: 'Signal Price: $XXX.XX (using current market price)'
- Verify log: 'Current Price: $XXX.XX (same as signal)'
- Verify: No more -97% pullback calculations
- Verify: Smart Entry queues correctly if no pullback yet

FILES CHANGED:
- app/api/trading/execute/route.ts lines 485-555 (rewritten Smart Entry logic)

LOCATION:
- Line 495: Added currentPrice null check
- Line 502: Added percentage detection warning
- Line 507: Changed to use currentPrice as signalPrice
- Line 509-511: Set priceChange/pullback to 0 at signal time
- Line 517: Queue with corrected signalPrice

RELATED:
- Bug #2: Leverage thresholds (FIXED separately, commit 58f812f)
- Bug #3: Missing Telegram entry notifications (pending investigation)
This commit is contained in:
mindesbunister
2025-12-03 08:16:27 +01:00
parent 58f812f0a7
commit 7d0d38a8b0

View File

@@ -489,40 +489,54 @@ export async function POST(request: NextRequest): Promise<NextResponse<ExecuteTr
if (smartEntryTimer.isEnabled() && body.signalPrice) { if (smartEntryTimer.isEnabled() && body.signalPrice) {
console.log(`🎯 Smart Entry: Evaluating entry timing...`) console.log(`🎯 Smart Entry: Evaluating entry timing...`)
// Get current price to check if already at favorable level // CRITICAL FIX (Dec 3, 2025): Use current market price, not body.signalPrice
// Bug: TradingView webhook sends pricePosition (percentage 0-100) as signalPrice
// Result: Shows "$70.80" when actual price is $139.70, calculates wrong pullback
const priceMonitor = getPythPriceMonitor() const priceMonitor = getPythPriceMonitor()
const latestPrice = priceMonitor.getCachedPrice(driftSymbol) const latestPrice = priceMonitor.getCachedPrice(driftSymbol)
const currentPrice = latestPrice?.price || body.signalPrice const currentPrice = latestPrice?.price
const priceChange = ((currentPrice - body.signalPrice) / body.signalPrice) * 100 if (!currentPrice) {
const isPullbackDirection = body.direction === 'long' ? priceChange < 0 : priceChange > 0 console.warn(`⚠️ Smart Entry: No current price available, skipping timing check`)
const pullbackMagnitude = Math.abs(priceChange) } else {
// CRITICAL: Detect if body.signalPrice looks like percentage (< $10)
const pullbackMin = parseFloat(process.env.SMART_ENTRY_PULLBACK_MIN || '0.15') const signalPriceIsPercentage = body.signalPrice && body.signalPrice < 10
const pullbackMax = parseFloat(process.env.SMART_ENTRY_PULLBACK_MAX || '0.50') if (signalPriceIsPercentage) {
console.warn(`⚠️ signalPrice (${body.signalPrice.toFixed(2)}) looks like percentage, using current price instead`)
console.log(` Signal Price: $${body.signalPrice.toFixed(2)}`) }
console.log(` Current Price: $${currentPrice.toFixed(2)} (${priceChange >= 0 ? '+' : ''}${priceChange.toFixed(2)}%)`)
if (isPullbackDirection && pullbackMagnitude >= pullbackMin && pullbackMagnitude <= pullbackMax) {
// Already at favorable entry - execute immediately!
console.log(`✅ Smart Entry: Already at favorable level (${pullbackMagnitude.toFixed(2)}% pullback)`)
console.log(` Executing immediately - no need to wait`)
} else if (!isPullbackDirection || pullbackMagnitude < pullbackMin) {
// Not favorable yet - queue for smart entry
console.log(`⏳ Smart Entry: Queuing signal for optimal entry timing`)
console.log(` Waiting for ${body.direction === 'long' ? 'dip' : 'bounce'} of ${pullbackMin}-${pullbackMax}%`)
// Queue the signal with full context // FIXED: Use current price as both signal and entry price (not body.signalPrice)
const queuedSignal = smartEntryTimer.queueSignal({ const signalPrice = currentPrice
symbol: driftSymbol,
direction: body.direction, const priceChange = 0 // At signal time, price change is always 0
signalPrice: body.signalPrice, const isPullbackDirection = false // No pullback yet
atr: body.atr, const pullbackMagnitude = 0
adx: body.adx,
rsi: body.rsi, const pullbackMin = parseFloat(process.env.SMART_ENTRY_PULLBACK_MIN || '0.15')
volumeRatio: body.volumeRatio, const pullbackMax = parseFloat(process.env.SMART_ENTRY_PULLBACK_MAX || '0.50')
pricePosition: body.pricePosition,
console.log(` Signal Price: $${signalPrice.toFixed(2)} (using current market price)`)
console.log(` Current Price: $${currentPrice.toFixed(2)} (same as signal)`)
if (isPullbackDirection && pullbackMagnitude >= pullbackMin && pullbackMagnitude <= pullbackMax) {
// Already at favorable entry - execute immediately!
console.log(`✅ Smart Entry: Already at favorable level (${pullbackMagnitude.toFixed(2)}% pullback)`)
console.log(` Executing immediately - no need to wait`)
} else if (!isPullbackDirection || pullbackMagnitude < pullbackMin) {
// Not favorable yet - queue for smart entry
console.log(`⏳ Smart Entry: Queuing signal for optimal entry timing`)
console.log(` Waiting for ${body.direction === 'long' ? 'dip' : 'bounce'} of ${pullbackMin}-${pullbackMax}%`)
// Queue the signal with CORRECTED signal price (current market price)
const queuedSignal = smartEntryTimer.queueSignal({
symbol: driftSymbol,
direction: body.direction,
signalPrice: signalPrice, // FIXED: Use current price, not body.signalPrice
atr: body.atr,
adx: body.adx,
rsi: body.rsi,
volumeRatio: body.volumeRatio,
pricePosition: body.pricePosition,
indicatorVersion: body.indicatorVersion, indicatorVersion: body.indicatorVersion,
qualityScore: qualityResult.score, qualityScore: qualityResult.score,
}) })