- 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
130 lines
4.3 KiB
TypeScript
130 lines
4.3 KiB
TypeScript
/**
|
|
* Query Drift Protocol directly to get actual trade history
|
|
* Compare with database to find discrepancies
|
|
*/
|
|
|
|
import { initializeDriftService, getDriftService } from '../lib/drift/client'
|
|
import { getPrismaClient } from '../lib/database/trades'
|
|
|
|
async function queryDriftHistory() {
|
|
console.log('🔍 Querying Drift Protocol for trade history...\n')
|
|
|
|
try {
|
|
// Initialize Drift service
|
|
await initializeDriftService()
|
|
const driftService = getDriftService()
|
|
const driftClient = driftService.getClient()
|
|
|
|
// Get user account
|
|
const userAccount = driftClient.getUserAccount()
|
|
|
|
if (!userAccount) {
|
|
throw new Error('User account not found')
|
|
}
|
|
|
|
console.log('📊 Drift Account Summary:')
|
|
console.log('='.repeat(60))
|
|
|
|
// Get account equity and P&L
|
|
const equity = driftClient.getUser().getTotalCollateral()
|
|
const unrealizedPnL = driftClient.getUser().getUnrealizedPNL()
|
|
|
|
console.log(`Total Collateral: $${(Number(equity) / 1e6).toFixed(2)}`)
|
|
console.log(`Unrealized P&L: $${(Number(unrealizedPnL) / 1e6).toFixed(2)}`)
|
|
|
|
// Get settled P&L from perp positions
|
|
console.log('\n📈 Perp Position History:')
|
|
console.log('='.repeat(60))
|
|
|
|
const perpPositions = userAccount.perpPositions
|
|
let totalSettledPnL = 0
|
|
|
|
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
|
|
|
|
console.log(`\n${marketName}:`)
|
|
console.log(` Current Position: ${baseAssetAmount.toFixed(4)}`)
|
|
console.log(` Settled P&L: $${settledPnL.toFixed(2)}`)
|
|
}
|
|
}
|
|
|
|
console.log('\n' + '='.repeat(60))
|
|
console.log(`Total Settled P&L: $${totalSettledPnL.toFixed(2)}`)
|
|
|
|
// Get spot positions (USDC balance)
|
|
console.log('\n💵 Spot Balances:')
|
|
console.log('='.repeat(60))
|
|
|
|
const spotPositions = userAccount.spotPositions
|
|
for (const spot of spotPositions) {
|
|
if (spot.marketIndex === 0) { // USDC
|
|
const balance = Number(spot.scaledBalance) / 1e9
|
|
const cumDepositInterest = Number(spot.cumulativeDeposits) / 1e6
|
|
|
|
console.log(`USDC Balance: $${balance.toFixed(2)}`)
|
|
console.log(`Cumulative Deposits: $${cumDepositInterest.toFixed(2)}`)
|
|
}
|
|
}
|
|
|
|
// Now compare with database
|
|
console.log('\n\n📚 Database Comparison:')
|
|
console.log('='.repeat(60))
|
|
|
|
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 = dbStats._sum.realizedPnL || 0
|
|
const dbTrades = dbStats._count
|
|
|
|
console.log(`Database Tracked Trades: ${dbTrades}`)
|
|
console.log(`Database Total P&L: $${dbPnL.toFixed(2)}`)
|
|
console.log(`\nDrift Settled P&L: $${totalSettledPnL.toFixed(2)}`)
|
|
console.log(`Discrepancy: $${(totalSettledPnL - dbPnL).toFixed(2)}`)
|
|
|
|
// Try to get funding payment history
|
|
console.log('\n\n💸 Funding Payments Analysis:')
|
|
console.log('='.repeat(60))
|
|
console.log('Note: Funding payments are not directly queryable from SDK')
|
|
console.log('The discrepancy may include:')
|
|
console.log(' - Hourly funding rate payments/receipts')
|
|
console.log(' - Trading fees (maker/taker fees)')
|
|
console.log(' - Liquidation fees (if any)')
|
|
console.log(' - Manual trades not tracked by bot')
|
|
|
|
const estimatedFees = totalSettledPnL - dbPnL
|
|
if (dbTrades > 0) {
|
|
console.log(`\nEstimated avg fee per trade: $${(estimatedFees / dbTrades).toFixed(2)}`)
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('❌ Error querying Drift:', error)
|
|
throw error
|
|
}
|
|
}
|
|
|
|
// Run the query
|
|
queryDriftHistory()
|
|
.then(() => {
|
|
console.log('\n✅ Query complete')
|
|
process.exit(0)
|
|
})
|
|
.catch((error) => {
|
|
console.error('\n❌ Query failed:', error)
|
|
process.exit(1)
|
|
})
|