critical: Fix Smart Validation Queue blockReason mismatch (Bug #84)
Root Cause: check-risk endpoint passes blockReason='SMART_VALIDATION_QUEUED'
but addSignal() only accepted 'QUALITY_SCORE_TOO_LOW' → signals blocked but never queued
Impact: Quality 85 LONG signal at 08:40:03 saved to database but never monitored
User missed validation opportunity when price moved favorably
Fix: Accept both blockReason variants in addSignal() validation check
Evidence:
- Database record cmj41pdqu0101pf07mith5s4c has blockReason='SMART_VALIDATION_QUEUED'
- No logs showing addSignal() execution (would log '⏰ Smart validation queued')
- check-risk code line 451 passes 'SMART_VALIDATION_QUEUED'
- addSignal() line 76 rejected signals != 'QUALITY_SCORE_TOO_LOW'
Result: Quality 50-89 signals will now be properly queued for validation
This commit is contained in:
82
scripts/place-exit-orders.ts
Normal file
82
scripts/place-exit-orders.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env ts-node
|
||||
|
||||
/**
|
||||
* Place fresh TP1 + SL orders for existing position
|
||||
* Does NOT close or modify the position itself
|
||||
*/
|
||||
|
||||
import { initializeDriftService } from '../lib/drift/client'
|
||||
import { placeExitOrders } from '../lib/drift/orders'
|
||||
import { getPythClient } from '../lib/pyth/client'
|
||||
|
||||
async function placeExitOrdersForPosition() {
|
||||
try {
|
||||
console.log('🔧 Initializing services...')
|
||||
|
||||
// Initialize Drift
|
||||
const driftService = await initializeDriftService()
|
||||
const driftClient = driftService.getDriftClient()
|
||||
|
||||
// Get current position
|
||||
const position = await driftService.getPosition(0) // SOL-PERP market index
|
||||
if (!position || position.baseAssetAmount.toString() === '0') {
|
||||
console.error('❌ No open SOL-PERP position found')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
console.log(`✅ Found position: ${position.baseAssetAmount.toString()} base units`)
|
||||
|
||||
// Get current price
|
||||
const pythClient = getPythClient()
|
||||
const currentPrice = await pythClient.getPrice('SOL-PERP')
|
||||
console.log(`💰 Current SOL price: $${currentPrice}`)
|
||||
|
||||
// Position details from database
|
||||
const entryPrice = 131.7993991266376
|
||||
const positionSizeUSD = 903.1306122
|
||||
const tp1Price = 132.8537943196507
|
||||
const stopLossPrice = 129.822408139738
|
||||
const tp1SizePercent = 60 // Close 60% at TP1
|
||||
|
||||
console.log(`\n📊 Position Configuration:`)
|
||||
console.log(` Entry: $${entryPrice}`)
|
||||
console.log(` Size: $${positionSizeUSD} (${(positionSizeUSD / currentPrice).toFixed(2)} SOL)`)
|
||||
console.log(` TP1: $${tp1Price} (+${((tp1Price / entryPrice - 1) * 100).toFixed(2)}%)`)
|
||||
console.log(` SL: $${stopLossPrice} (${((stopLossPrice / entryPrice - 1) * 100).toFixed(2)}%)`)
|
||||
console.log(` TP1 will close: ${tp1SizePercent}%`)
|
||||
console.log(` Runner: ${100 - tp1SizePercent}% (software-monitored, no on-chain TP2)`)
|
||||
|
||||
// Place orders
|
||||
console.log(`\n🔨 Placing exit orders...`)
|
||||
const result = await placeExitOrders({
|
||||
symbol: 'SOL-PERP',
|
||||
direction: 'long',
|
||||
entryPrice: entryPrice,
|
||||
positionSizeUSD: positionSizeUSD,
|
||||
tp1Price: tp1Price,
|
||||
tp1SizePercent: tp1SizePercent,
|
||||
tp2Price: 134.171788310917, // Not used (tp2SizePercent = 0)
|
||||
tp2SizePercent: 0, // No TP2 order (runner only)
|
||||
stopLossPrice: stopLossPrice,
|
||||
useDualStops: false, // Single SL only
|
||||
})
|
||||
|
||||
if (result.success) {
|
||||
console.log(`\n✅ Orders placed successfully!`)
|
||||
console.log(` Signatures:`, result.signatures)
|
||||
console.log(`\n📝 Update database with these signatures:`)
|
||||
console.log(` tp1OrderTx: ${result.signatures[0]}`)
|
||||
console.log(` slOrderTx: ${result.signatures[1]}`)
|
||||
console.log(` tp2OrderTx: NULL (runner-only, no on-chain order)`)
|
||||
} else {
|
||||
console.error(`\n❌ Failed to place orders:`, result.error)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Error:', error)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
placeExitOrdersForPosition()
|
||||
Reference in New Issue
Block a user