Enhance trailing stop with ATR-based sizing

This commit is contained in:
mindesbunister
2025-11-05 15:28:12 +01:00
parent 149294084e
commit a100945864
8 changed files with 183 additions and 35 deletions

View File

@@ -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,
}
}