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:
mindesbunister
2025-11-01 17:00:37 +01:00
parent 7788327a4e
commit 056440bf8f
9 changed files with 110 additions and 49 deletions

View File

@@ -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,

View File

@@ -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)

View File

@@ -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)