Files
trading_bot_v4/app/api/drift/history/route.ts
mindesbunister 881a99242d feat: Add per-symbol trading controls for SOL and ETH
- Add SymbolSettings interface with enabled/positionSize/leverage fields
- Implement per-symbol ENV variables (SOLANA_*, ETHEREUM_*)
- Add SOL and ETH sections to settings UI with enable/disable toggles
- Add symbol-specific test buttons (SOL LONG/SHORT, ETH LONG/SHORT)
- Update execute and test endpoints to check symbol enabled status
- Add real-time risk/reward calculator per symbol
- Rename 'Position Sizing' to 'Global Fallback' for clarity
- Fix position manager P&L calculation for externally closed positions
- Fix zero P&L bug affecting 12 historical trades
- Add SQL scripts for recalculating historical P&L data
- Move archive TypeScript files to .archive to fix build

Defaults:
- SOL: 10 base × 10x leverage = 100 notional (profit trading)
- ETH:  base × 1x leverage =  notional (data collection)
- Global: 10 × 10x for BTC and other symbols

Configuration priority: Per-symbol ENV > Market config > Global ENV > Defaults
2025-11-03 10:28:48 +01:00

117 lines
3.6 KiB
TypeScript

/**
* Query Drift History API
* GET /api/drift/history
*
* Queries Drift Protocol directly to compare with database
*/
import { NextResponse } from 'next/server'
import { initializeDriftService, getDriftService } from '@/lib/drift/client'
import { getPrismaClient } from '@/lib/database/trades'
export async function GET() {
try {
console.log('🔍 Querying Drift Protocol...')
// Initialize Drift service if not already done
console.log('⏳ Calling initializeDriftService()...')
const driftService = await initializeDriftService()
console.log('✅ Drift service initialized, got service object')
console.log('⏳ Getting Drift client...')
const driftClient = driftService.getClient()
console.log('✅ Got Drift client')
// Get user account
const userAccount = driftClient.getUserAccount()
if (!userAccount) {
return NextResponse.json({ error: 'User account not found' }, { status: 404 })
}
// Get account equity and P&L
const equity = driftClient.getUser().getTotalCollateral()
const unrealizedPnL = driftClient.getUser().getUnrealizedPNL()
// Get settled P&L from perp positions
const perpPositions = userAccount.perpPositions
let totalSettledPnL = 0
const positionDetails: any[] = []
for (const position of perpPositions) {
if (position.marketIndex === 0 || position.marketIndex === 1 || position.marketIndex === 2) {
const marketName = position.marketIndex === 0 ? 'SOL-PERP' :
position.marketIndex === 1 ? 'BTC-PERP' : 'ETH-PERP'
const settledPnL = Number(position.settledPnl) / 1e6
const baseAssetAmount = Number(position.baseAssetAmount) / 1e9
totalSettledPnL += settledPnL
positionDetails.push({
market: marketName,
currentPosition: baseAssetAmount,
settledPnL: settledPnL,
})
}
}
// Get spot balance (USDC)
const spotPositions = userAccount.spotPositions
let usdcBalance = 0
let cumulativeDeposits = 0
for (const spot of spotPositions) {
if (spot.marketIndex === 0) { // USDC
usdcBalance = Number(spot.scaledBalance) / 1e9
cumulativeDeposits = Number(spot.cumulativeDeposits) / 1e6
}
}
// Query database for comparison
const prisma = getPrismaClient()
const dbStats = await prisma.trade.aggregate({
where: {
exitReason: { not: null },
entryTime: { gte: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) }
},
_sum: { realizedPnL: true },
_count: true
})
const dbPnL = Number(dbStats._sum.realizedPnL || 0)
const dbTrades = dbStats._count
const discrepancy = totalSettledPnL - dbPnL
const estimatedFeePerTrade = dbTrades > 0 ? discrepancy / dbTrades : 0
return NextResponse.json({
drift: {
totalCollateral: Number(equity) / 1e6,
unrealizedPnL: Number(unrealizedPnL) / 1e6,
settledPnL: totalSettledPnL,
usdcBalance,
cumulativeDeposits,
positions: positionDetails,
},
database: {
totalTrades: dbTrades,
totalPnL: dbPnL,
},
comparison: {
discrepancy,
estimatedFeePerTrade,
note: 'Discrepancy includes funding rates, trading fees, and any manual trades not tracked by bot',
}
})
} catch (error) {
console.error('❌ Error querying Drift:', error)
return NextResponse.json(
{ error: error instanceof Error ? error.message : 'Unknown error' },
{ status: 500 }
)
}
}