Deploy Q≥95 strategy: unified thresholds + instant-reversal filter + 5-candle time exit

Backtest results (28 days):
- Original: 32 trades, 43.8% win rate, -16.82 loss
- New: 13 trades, 69.2% win rate, +49.99 profit
- Improvement: +66.81 (+991%), +25.5% hit rate

Changes:
1. Set MIN_SIGNAL_QUALITY_SCORE_LONG/SHORT=95 (was 90/85)
2. Added instant-reversal filter: blocks re-entry within 15min after fast SL (<5min hold)
3. Added 5-candle time exit: exits after 25min if MFE <0
4. HTF filter already effective (no Q≥95 trades blocked)

Expected outcome: Turn consistent losses into consistent profits with 69% win rate
This commit is contained in:
mindesbunister
2025-12-18 09:35:36 +01:00
parent de2e6bf2e5
commit 634738bfb4
10 changed files with 2419 additions and 5 deletions

View File

@@ -373,7 +373,63 @@ export async function POST(request: NextRequest): Promise<NextResponse<RiskCheck
}
}
// 4. Check signal quality (if context metrics provided)
// 4. Check for instant reversal (fast SL within 1 candle - Dec 17, 2025)
// Detect if most recent trade on this symbol was stopped out within 5 minutes
// This prevents re-entering immediately after being whipsawed
if (hasContextMetrics && body.timeframe === '5') {
const recentTrades = await getTradesInLastHour()
const symbolRecentTrades = recentTrades.filter(t =>
t.symbol === body.symbol &&
t.exitReason === 'SL' &&
t.holdTimeSeconds !== null &&
t.holdTimeSeconds <= 300 // 5 minutes = 1 candle
)
if (symbolRecentTrades.length > 0) {
const lastFastSL = symbolRecentTrades[0]
const timeSinceLastSL = Date.now() - new Date(lastFastSL.exitTime!).getTime()
const cooldownMs = 15 * 60 * 1000 // 15 minute cooldown after instant reversal
if (timeSinceLastSL < cooldownMs) {
const remainingMinutes = Math.ceil((cooldownMs - timeSinceLastSL) / 60000)
console.log('🚫 Risk check BLOCKED: Instant reversal detected', {
symbol: body.symbol,
lastSLTime: lastFastSL.exitTime,
holdTime: lastFastSL.holdTimeSeconds,
remainingCooldown: remainingMinutes,
})
const currentPrice = await getCurrentPrice(body.symbol, fallbackPrice)
if (currentPrice > 0) {
await createBlockedSignal({
symbol: body.symbol,
direction: body.direction,
timeframe: body.timeframe,
signalPrice: currentPrice,
atr: body.atr,
adx: body.adx,
rsi: body.rsi,
volumeRatio: body.volumeRatio,
pricePosition: body.pricePosition,
signalQualityScore: 0,
minScoreRequired: config.minSignalQualityScore,
blockReason: 'INSTANT_REVERSAL_RISK',
blockDetails: `Fast SL ${remainingMinutes}min ago (${lastFastSL.holdTimeSeconds}s hold). Wait ${remainingMinutes}min.`,
indicatorVersion: body.indicatorVersion || 'v5',
})
}
return NextResponse.json({
allowed: false,
reason: 'Instant reversal risk',
details: `Last trade stopped out in ${lastFastSL.holdTimeSeconds}s. Wait ${remainingMinutes} more minutes to avoid whipsaw.`,
})
}
}
}
// 5. Check signal quality (if context metrics provided)
if (hasContextMetrics) {
// Get current price from Pyth for flip-flop price context check
const priceMonitor = getPythPriceMonitor()