Add remove-position endpoint and clean up stale position
- New endpoint: /api/trading/remove-position for manually removing stale positions - Removed duplicate position from tracking (second SOL-PERP position) - System now correctly shows 1 active position matching Drift - Validation and analytics will now show accurate position count
This commit is contained in:
115
app/api/trading/remove-position/route.ts
Normal file
115
app/api/trading/remove-position/route.ts
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
/**
|
||||||
|
* Remove Position from Tracking
|
||||||
|
*
|
||||||
|
* Manually removes a position from Position Manager tracking
|
||||||
|
* POST /api/trading/remove-position
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { NextRequest, NextResponse } from 'next/server'
|
||||||
|
import { getInitializedPositionManager } from '@/lib/trading/position-manager'
|
||||||
|
import { updateTradeExit } from '@/lib/database/trades'
|
||||||
|
|
||||||
|
interface RemovePositionRequest {
|
||||||
|
tradeId: string
|
||||||
|
reason?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface RemovePositionResponse {
|
||||||
|
success: boolean
|
||||||
|
message: string
|
||||||
|
tradeId?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function POST(request: NextRequest): Promise<NextResponse<RemovePositionResponse>> {
|
||||||
|
try {
|
||||||
|
// Verify authorization
|
||||||
|
const authHeader = request.headers.get('authorization')
|
||||||
|
const expectedAuth = `Bearer ${process.env.API_SECRET_KEY}`
|
||||||
|
|
||||||
|
if (!authHeader || authHeader !== expectedAuth) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message: 'Unauthorized',
|
||||||
|
},
|
||||||
|
{ status: 401 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const body: RemovePositionRequest = await request.json()
|
||||||
|
|
||||||
|
console.log('🗑️ Removing position from tracking:', body)
|
||||||
|
|
||||||
|
if (!body.tradeId) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message: 'tradeId is required',
|
||||||
|
},
|
||||||
|
{ status: 400 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get Position Manager
|
||||||
|
const positionManager = await getInitializedPositionManager()
|
||||||
|
|
||||||
|
// Check if position exists
|
||||||
|
const activeTrades = positionManager.getActiveTrades()
|
||||||
|
const trade = activeTrades.find(t => t.id === body.tradeId)
|
||||||
|
|
||||||
|
if (!trade) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message: `Position ${body.tradeId} not found in tracking`,
|
||||||
|
},
|
||||||
|
{ status: 404 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`📊 Found position: ${trade.symbol} ${trade.direction} at $${trade.entryPrice}`)
|
||||||
|
|
||||||
|
// Remove from Position Manager
|
||||||
|
positionManager.removeTrade(body.tradeId)
|
||||||
|
|
||||||
|
console.log(`✅ Removed ${body.tradeId} from Position Manager`)
|
||||||
|
|
||||||
|
// Update database to mark as closed (manually)
|
||||||
|
try {
|
||||||
|
const exitTime = new Date()
|
||||||
|
const holdTime = Math.floor((exitTime.getTime() - new Date(trade.entryTime).getTime()) / 1000)
|
||||||
|
|
||||||
|
await updateTradeExit({
|
||||||
|
positionId: trade.positionId || 'manual-removal',
|
||||||
|
exitPrice: trade.lastPrice || trade.entryPrice,
|
||||||
|
exitReason: 'manual',
|
||||||
|
realizedPnL: trade.unrealizedPnL,
|
||||||
|
exitOrderTx: 'manual-removal',
|
||||||
|
holdTimeSeconds: holdTime,
|
||||||
|
maxDrawdown: trade.peakPnL < 0 ? trade.peakPnL : undefined,
|
||||||
|
maxGain: trade.peakPnL > 0 ? trade.peakPnL : undefined,
|
||||||
|
})
|
||||||
|
console.log('💾 Updated database: trade marked as closed')
|
||||||
|
} catch (dbError) {
|
||||||
|
console.error('❌ Failed to update database:', dbError)
|
||||||
|
// Don't fail the removal if database update fails
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({
|
||||||
|
success: true,
|
||||||
|
message: `Position removed from tracking: ${trade.symbol} ${trade.direction}`,
|
||||||
|
tradeId: body.tradeId,
|
||||||
|
})
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Remove position error:', error)
|
||||||
|
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message: error instanceof Error ? error.message : 'Unknown error',
|
||||||
|
},
|
||||||
|
{ status: 500 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user