fix(drift): calculate realizedPnL with leverage on USD notional, not base asset
- Old calculation: (closePrice - entryPrice) * sizeInBaseAsset = tiny P&L in dollars - New calculation: profitPercent * leverage * notionalUSD / 100 = correct leveraged P&L - Example: -0.13% price move * 10x leverage * $540 notional = -$7.02 (not -$0.38) - Fixes trades showing -$0.10 to -$0.77 losses when they should be -$5 to -$40 - Applied to both DRY_RUN and real execution paths
This commit is contained in:
@@ -486,9 +486,12 @@ export async function closePosition(
|
||||
if (isDryRun) {
|
||||
console.log('🧪 DRY RUN MODE: Simulating close order (not executing on blockchain)')
|
||||
|
||||
// Calculate realized P&L
|
||||
const pnlPerUnit = oraclePrice - position.entryPrice
|
||||
const realizedPnL = pnlPerUnit * sizeToClose * (position.side === 'long' ? 1 : -1)
|
||||
// Calculate realized P&L with leverage (default 10x in dry run)
|
||||
const profitPercent = ((oraclePrice - position.entryPrice) / position.entryPrice) * 100 * (position.side === 'long' ? 1 : -1)
|
||||
const leverage = 10 // Use 10x for dry run
|
||||
const accountPnLPercent = profitPercent * leverage
|
||||
const closedNotional = sizeToClose * oraclePrice
|
||||
const realizedPnL = (closedNotional * accountPnLPercent) / 100
|
||||
|
||||
const mockTxSig = `DRY_RUN_CLOSE_${Date.now()}_${Math.random().toString(36).substring(7)}`
|
||||
|
||||
@@ -534,12 +537,32 @@ export async function closePosition(
|
||||
|
||||
console.log('✅ Transaction confirmed on-chain')
|
||||
|
||||
// Calculate realized P&L
|
||||
const pnlPerUnit = oraclePrice - position.entryPrice
|
||||
const realizedPnL = pnlPerUnit * sizeToClose * (position.side === 'long' ? 1 : -1)
|
||||
// Calculate realized P&L with leverage
|
||||
// CRITICAL: P&L must account for leverage and be calculated on USD notional, not base asset size
|
||||
const profitPercent = ((oraclePrice - position.entryPrice) / position.entryPrice) * 100 * (position.side === 'long' ? 1 : -1)
|
||||
|
||||
// Get leverage from user account (defaults to 10x if not found)
|
||||
let leverage = 10
|
||||
try {
|
||||
const userAccount = driftClient.getUserAccount()
|
||||
if (userAccount && userAccount.maxMarginRatio) {
|
||||
// maxMarginRatio is in 1e4 scale, leverage = 1 / (margin / 10000)
|
||||
leverage = 10000 / Number(userAccount.maxMarginRatio)
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('⚠️ Could not determine leverage from account, using 10x default')
|
||||
}
|
||||
|
||||
const accountPnLPercent = profitPercent * leverage
|
||||
|
||||
// Calculate closed notional value (USD)
|
||||
const closedNotional = sizeToClose * oraclePrice
|
||||
const realizedPnL = (closedNotional * accountPnLPercent) / 100
|
||||
|
||||
console.log(`💰 Close details:`)
|
||||
console.log(` Close price: $${oraclePrice.toFixed(4)}`)
|
||||
console.log(` Profit %: ${profitPercent.toFixed(3)}% | Account P&L (${leverage}x): ${accountPnLPercent.toFixed(2)}%`)
|
||||
console.log(` Closed notional: $${closedNotional.toFixed(2)}`)
|
||||
console.log(` Realized P&L: $${realizedPnL.toFixed(2)}`)
|
||||
|
||||
// If closing 100%, cancel all remaining orders for this market
|
||||
|
||||
Reference in New Issue
Block a user