critical: FIX adaptive leverage broken - smart entry used 1x instead of 10x (Bug #85)
SYMPTOM:
- Database shows leverage=10 for quality 95 signals
- Drift shows actual leverage 0.99x (essentially 1x)
- User expected ,960 position (10x), got 92 (1x)
ROOT CAUSE:
- Dec 14 fix (commit 5aad42f) passed wrong variable to smart entry queue
- Line 569: positionSizeUSD: positionSize (BASE size without leverage)
- Should be: positionSizeUSD: positionSizeUSD (LEVERAGED size)
- positionSizeUSD correctly calculated at line 504: positionSize * leverage
IMPACT:
- ALL smart entry timeout trades since Dec 14 used 1x leverage
- Adaptive leverage completely bypassed for queued signals
- User losing 90% of profit potential on quality 95+ signals
THE FIX:
- Changed line 569 from positionSize to positionSizeUSD
- Now passes correctly leveraged size to queue
- Smart entry timeouts will use adaptive 10x leverage
VERIFICATION:
- Container restarted: 2025-12-16 09:44:24 UTC
- Next smart entry timeout trade will show 10x leverage in Drift
See Common Pitfalls #85 for full details.
This commit is contained in:
@@ -556,6 +556,9 @@ export async function POST(request: NextRequest): Promise<NextResponse<ExecuteTr
|
||||
// CRITICAL FIX (Dec 13, 2025): Pass positionSizeUSD and leverage to prevent recalculation on timeout
|
||||
// Bug: Timeout recalculates size fresh, gets $10.40 instead of $435 (97.6% loss)
|
||||
// Fix: Store calculated size when queueing, use stored value during execution
|
||||
// CRITICAL FIX (Dec 16, 2025): Pass LEVERAGED size, not base size
|
||||
// Bug: Passed positionSize instead of positionSizeUSD = 1x leverage instead of 10x
|
||||
// Fix: Use positionSizeUSD variable (calculated as positionSize * leverage at line 504)
|
||||
const queuedSignal = smartEntryTimer.queueSignal({
|
||||
symbol: driftSymbol,
|
||||
direction: body.direction,
|
||||
@@ -567,7 +570,7 @@ export async function POST(request: NextRequest): Promise<NextResponse<ExecuteTr
|
||||
pricePosition: body.pricePosition,
|
||||
indicatorVersion: body.indicatorVersion,
|
||||
qualityScore: qualityResult.score,
|
||||
positionSizeUSD: positionSize, // CRITICAL: Store calculated USD size
|
||||
positionSizeUSD: positionSizeUSD, // CRITICAL: Store LEVERAGED USD size (positionSize * leverage)
|
||||
leverage: leverage, // CRITICAL: Store calculated leverage
|
||||
})
|
||||
|
||||
|
||||
@@ -708,6 +708,7 @@ export class PositionManager {
|
||||
// Calculate trade age in seconds
|
||||
const tradeAgeSeconds = (Date.now() - trade.entryTime) / 1000
|
||||
console.log(`🔍 AGE: ${trade.symbol} age=${tradeAgeSeconds.toFixed(1)}s | threshold=30s`)
|
||||
console.log(`🔍 CONDITION: position=${position ? 'exists' : 'null'}, size=${position?.size || 0}`)
|
||||
|
||||
if (position === null || position.size === 0) {
|
||||
// IMPORTANT: Skip "external closure" detection for NEW trades (<30 seconds old)
|
||||
@@ -754,11 +755,15 @@ export class PositionManager {
|
||||
// Position closed externally (by on-chain TP/SL order or manual closure)
|
||||
logger.log(`⚠️ Position ${trade.symbol} was closed externally (by on-chain order)`)
|
||||
} else {
|
||||
console.log(`🔍 ELSE: Entering else block (position exists and size > 0)`)
|
||||
// Position exists - check if size changed (TP1/TP2 filled)
|
||||
// CRITICAL FIX: position.size from Drift SDK is base asset tokens, must convert to USD
|
||||
const positionSizeUSD = Math.abs(position.size) * currentPrice // Convert tokens to USD
|
||||
console.log(`🔍 CALC1: positionSizeUSD calculated = $${positionSizeUSD.toFixed(2)}`)
|
||||
const trackedSizeUSD = trade.currentSize
|
||||
console.log(`🔍 CALC2: trackedSizeUSD = $${trackedSizeUSD.toFixed(2)}`)
|
||||
const sizeDiffPercent = Math.abs(positionSizeUSD - trackedSizeUSD) / trackedSizeUSD * 100
|
||||
console.log(`🔍 CALC3: sizeDiffPercent = ${sizeDiffPercent.toFixed(1)}%`)
|
||||
|
||||
logger.log(`📊 Position check: Drift=$${positionSizeUSD.toFixed(2)} Tracked=$${trackedSizeUSD.toFixed(2)} Diff=${sizeDiffPercent.toFixed(1)}%`)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user