feat: add quality score display and timezone fixes
- Add qualityScore to ExecuteTradeResponse interface and response object - Update analytics page to always show Signal Quality card (N/A if unavailable) - Fix n8n workflow to pass context metrics and qualityScore to execute endpoint - Fix timezone in Telegram notifications (Europe/Berlin) - Fix symbol normalization in /api/trading/close endpoint - Update Drift ETH-PERP minimum order size (0.002 ETH not 0.01) - Add transaction confirmation to closePosition() to prevent phantom closes - Add 30-second grace period for new trades in Position Manager - Fix execution order: database save before Position Manager.addTrade() - Update copilot instructions with transaction confirmation pattern
This commit is contained in:
@@ -7,12 +7,13 @@
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { closePosition } from '@/lib/drift/orders'
|
||||
import { initializeDriftService } from '@/lib/drift/client'
|
||||
import { normalizeTradingViewSymbol } from '@/config/trading'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
export const runtime = 'nodejs'
|
||||
|
||||
interface CloseRequest {
|
||||
symbol: string // e.g., 'SOL-PERP'
|
||||
symbol: string // e.g., 'SOL-PERP' or 'SOLUSDT'
|
||||
percentToClose?: number // 0-100, default 100 (close entire position)
|
||||
}
|
||||
|
||||
@@ -46,14 +47,16 @@ export async function POST(request: NextRequest) {
|
||||
)
|
||||
}
|
||||
|
||||
console.log(`📊 Closing position: ${symbol} (${percentToClose}%)`)
|
||||
// Normalize symbol (SOLUSDT -> SOL-PERP)
|
||||
const driftSymbol = normalizeTradingViewSymbol(symbol)
|
||||
console.log(`📊 Closing position: ${driftSymbol} (${percentToClose}%)`)
|
||||
|
||||
// Initialize Drift service if not already initialized
|
||||
await initializeDriftService()
|
||||
|
||||
// Close position
|
||||
const result = await closePosition({
|
||||
symbol,
|
||||
symbol: driftSymbol,
|
||||
percentToClose,
|
||||
slippageTolerance: 1.0,
|
||||
})
|
||||
@@ -72,7 +75,7 @@ export async function POST(request: NextRequest) {
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
transactionSignature: result.transactionSignature,
|
||||
symbol,
|
||||
symbol: driftSymbol,
|
||||
closePrice: result.closePrice,
|
||||
closedSize: result.closedSize,
|
||||
realizedPnL: result.realizedPnL,
|
||||
|
||||
@@ -25,6 +25,7 @@ export interface ExecuteTradeRequest {
|
||||
rsi?: number
|
||||
volumeRatio?: number
|
||||
pricePosition?: number
|
||||
qualityScore?: number // Calculated by check-risk endpoint
|
||||
}
|
||||
|
||||
export interface ExecuteTradeResponse {
|
||||
@@ -43,6 +44,7 @@ export interface ExecuteTradeResponse {
|
||||
tp2Percent?: number
|
||||
entrySlippage?: number
|
||||
timestamp?: string
|
||||
qualityScore?: number // Signal quality score (0-100)
|
||||
error?: string
|
||||
message?: string
|
||||
}
|
||||
@@ -281,11 +283,6 @@ export async function POST(request: NextRequest): Promise<NextResponse<ExecuteTr
|
||||
console.error('❌ Unexpected error placing exit orders:', err)
|
||||
}
|
||||
|
||||
// Add to position manager for monitoring AFTER orders are placed
|
||||
await positionManager.addTrade(activeTrade)
|
||||
|
||||
console.log('✅ Trade added to position manager for monitoring')
|
||||
|
||||
// Create response object
|
||||
const response: ExecuteTradeResponse = {
|
||||
success: true,
|
||||
@@ -303,6 +300,7 @@ export async function POST(request: NextRequest): Promise<NextResponse<ExecuteTr
|
||||
tp2Percent: config.takeProfit2Percent,
|
||||
entrySlippage: openResult.slippage,
|
||||
timestamp: new Date().toISOString(),
|
||||
qualityScore: body.qualityScore, // Include quality score in response
|
||||
}
|
||||
|
||||
// Attach exit order signatures to response
|
||||
@@ -341,6 +339,7 @@ export async function POST(request: NextRequest): Promise<NextResponse<ExecuteTr
|
||||
rsiAtEntry: body.rsi,
|
||||
volumeAtEntry: body.volumeRatio,
|
||||
pricePositionAtEntry: body.pricePosition,
|
||||
signalQualityScore: body.qualityScore,
|
||||
})
|
||||
|
||||
console.log('💾 Trade saved to database')
|
||||
@@ -349,6 +348,11 @@ export async function POST(request: NextRequest): Promise<NextResponse<ExecuteTr
|
||||
// Don't fail the trade if database save fails
|
||||
}
|
||||
|
||||
// NOW add to position manager for monitoring (after database save)
|
||||
await positionManager.addTrade(activeTrade)
|
||||
|
||||
console.log('✅ Trade added to position manager for monitoring')
|
||||
|
||||
console.log('✅ Trade executed successfully!')
|
||||
|
||||
return NextResponse.json(response)
|
||||
|
||||
@@ -190,12 +190,6 @@ export async function POST(request: NextRequest): Promise<NextResponse<TestTrade
|
||||
lastUpdateTime: Date.now(),
|
||||
}
|
||||
|
||||
// Add to position manager for monitoring
|
||||
const positionManager = await getInitializedPositionManager()
|
||||
await positionManager.addTrade(activeTrade)
|
||||
|
||||
console.log('✅ Trade added to position manager for monitoring')
|
||||
|
||||
// Create response object
|
||||
const response: TestTradeResponse = {
|
||||
success: true,
|
||||
@@ -248,7 +242,7 @@ export async function POST(request: NextRequest): Promise<NextResponse<TestTrade
|
||||
console.error('❌ Unexpected error placing exit orders:', err)
|
||||
}
|
||||
|
||||
// Save trade to database
|
||||
// Save trade to database FIRST (before Position Manager)
|
||||
try {
|
||||
await createTrade({
|
||||
positionId: openResult.transactionSignature!,
|
||||
@@ -281,6 +275,12 @@ export async function POST(request: NextRequest): Promise<NextResponse<TestTrade
|
||||
// Don't fail the trade if database save fails
|
||||
}
|
||||
|
||||
// NOW add to position manager for monitoring (after database save)
|
||||
const positionManager = await getInitializedPositionManager()
|
||||
await positionManager.addTrade(activeTrade)
|
||||
|
||||
console.log('✅ Trade added to position manager for monitoring')
|
||||
|
||||
console.log('✅ Test trade executed successfully!')
|
||||
|
||||
return NextResponse.json(response)
|
||||
|
||||
Reference in New Issue
Block a user