Enhance trailing stop with ATR-based sizing
This commit is contained in:
@@ -27,6 +27,7 @@ export interface OpenPositionResult {
|
||||
transactionSignature?: string
|
||||
fillPrice?: number
|
||||
fillSize?: number
|
||||
fillNotionalUSD?: number
|
||||
slippage?: number
|
||||
error?: string
|
||||
isPhantom?: boolean // Position opened but size mismatch detected
|
||||
@@ -124,6 +125,7 @@ export async function openPosition(
|
||||
transactionSignature: mockTxSig,
|
||||
fillPrice: oraclePrice,
|
||||
fillSize: baseAssetSize,
|
||||
fillNotionalUSD: baseAssetSize * oraclePrice,
|
||||
slippage: 0,
|
||||
}
|
||||
}
|
||||
@@ -179,19 +181,22 @@ export async function openPosition(
|
||||
|
||||
if (position && position.side !== 'none') {
|
||||
const fillPrice = position.entryPrice
|
||||
const filledBaseSize = Math.abs(position.size)
|
||||
const fillNotionalUSD = filledBaseSize * fillPrice
|
||||
const slippage = Math.abs((fillPrice - oraclePrice) / oraclePrice) * 100
|
||||
|
||||
// CRITICAL: Validate actual position size vs expected
|
||||
// Phantom trade detection: Check if position is significantly smaller than expected
|
||||
const actualSizeUSD = position.size * fillPrice
|
||||
const expectedSizeUSD = params.sizeUSD
|
||||
const sizeRatio = actualSizeUSD / expectedSizeUSD
|
||||
const sizeRatio = expectedSizeUSD > 0 ? fillNotionalUSD / expectedSizeUSD : 1
|
||||
|
||||
console.log(`💰 Fill details:`)
|
||||
console.log(` Fill price: $${fillPrice.toFixed(4)}`)
|
||||
console.log(` Filled base size: ${filledBaseSize.toFixed(4)} ${params.symbol.split('-')[0]}`)
|
||||
console.log(` Filled notional: $${fillNotionalUSD.toFixed(2)}`)
|
||||
console.log(` Slippage: ${slippage.toFixed(3)}%`)
|
||||
console.log(` Expected size: $${expectedSizeUSD.toFixed(2)}`)
|
||||
console.log(` Actual size: $${actualSizeUSD.toFixed(2)}`)
|
||||
console.log(` Actual size: $${fillNotionalUSD.toFixed(2)}`)
|
||||
console.log(` Size ratio: ${(sizeRatio * 100).toFixed(1)}%`)
|
||||
|
||||
// Flag as phantom if actual size is less than 50% of expected
|
||||
@@ -200,7 +205,7 @@ export async function openPosition(
|
||||
if (isPhantom) {
|
||||
console.error(`🚨 PHANTOM POSITION DETECTED!`)
|
||||
console.error(` Expected: $${expectedSizeUSD.toFixed(2)}`)
|
||||
console.error(` Actual: $${actualSizeUSD.toFixed(2)}`)
|
||||
console.error(` Actual: $${fillNotionalUSD.toFixed(2)}`)
|
||||
console.error(` This indicates the order was rejected or partially filled by Drift`)
|
||||
}
|
||||
|
||||
@@ -208,10 +213,11 @@ export async function openPosition(
|
||||
success: true,
|
||||
transactionSignature: txSig,
|
||||
fillPrice,
|
||||
fillSize: position.size, // Use actual size from Drift, not calculated
|
||||
fillSize: filledBaseSize,
|
||||
fillNotionalUSD,
|
||||
slippage,
|
||||
isPhantom,
|
||||
actualSizeUSD,
|
||||
actualSizeUSD: fillNotionalUSD,
|
||||
}
|
||||
} else {
|
||||
// Position not found yet (may be DRY_RUN mode)
|
||||
@@ -223,6 +229,7 @@ export async function openPosition(
|
||||
transactionSignature: txSig,
|
||||
fillPrice: oraclePrice,
|
||||
fillSize: baseAssetSize,
|
||||
fillNotionalUSD: baseAssetSize * oraclePrice,
|
||||
slippage: 0,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user