feat: Add ADX-based trend strength multiplier for trailing stops
Implements graduated trailing stop widening based on ADX at entry: - ADX > 30: 1.5x wider trail (very strong trends) - ADX 25-30: 1.25x wider trail (strong trends) - ADX < 25: Base trail (weak/moderate trends) Also adds profit acceleration: - Profit > 2%: Additional 1.3x multiplier - Combines with ADX for maximum trail width Purpose: Capture more of massive trend moves (like 38% MFE trades) - Current system exits at ~1% with tight 0.67% trail - ADX 29.3 + 2% profit: Trail widens to ~1.1-1.3% - Expected improvement: 50%+ better profit capture on big moves Example impact (Nov 19 trade): - Entry: $140.17, MFE: 38.12%, Captured: 0.99% - With ADX multiplier: Would capture ~1.5-2% (50%+ improvement) Changes: - lib/trading/position-manager.ts: Added adxAtEntry to ActiveTrade interface - Trail calculation now checks trade.adxAtEntry and applies multipliers - Backward compatible: Trades without ADX use base multiplier - Logs show: "Strong trend (ADX 29.3): Trail multiplier 1.5x → 1.88x" Data-driven decision based on: - 4 recent v8 trades with ADX: 29.3, 20.8, 21.4, 18.3 - Nov 19 trade: ADX 29.3, MFE 38.12%, only captured 0.99% - System needed wider trail for strong trends
This commit is contained in:
@@ -23,6 +23,7 @@ export interface ActiveTrade {
|
||||
positionSize: number
|
||||
leverage: number
|
||||
atrAtEntry?: number // ATR value at entry for ATR-based trailing stop
|
||||
adxAtEntry?: number // ADX value at entry for trend strength multiplier
|
||||
|
||||
// Targets
|
||||
stopLossPrice: number
|
||||
@@ -1203,13 +1204,37 @@ export class PositionManager {
|
||||
|
||||
// If trailing stop is active, adjust SL dynamically
|
||||
if (trade.trailingStopActive) {
|
||||
// Calculate ATR-based trailing distance
|
||||
// Calculate ATR-based trailing distance with ADX trend strength multiplier
|
||||
let trailingDistancePercent: number
|
||||
|
||||
if (trade.atrAtEntry && trade.atrAtEntry > 0) {
|
||||
// ATR-based: Use ATR% * multiplier
|
||||
// Start with base ATR multiplier
|
||||
let trailMultiplier = this.config.trailingStopAtrMultiplier
|
||||
|
||||
// ADX-based trend strength adjustment (graduated)
|
||||
if (trade.adxAtEntry && trade.adxAtEntry > 0) {
|
||||
if (trade.adxAtEntry > 30) {
|
||||
// Very strong trend (ADX > 30): 50% wider trail
|
||||
trailMultiplier *= 1.5
|
||||
console.log(`📈 Very strong trend (ADX ${trade.adxAtEntry.toFixed(1)}): Trail multiplier ${this.config.trailingStopAtrMultiplier}x → ${trailMultiplier.toFixed(2)}x`)
|
||||
} else if (trade.adxAtEntry > 25) {
|
||||
// Strong trend (ADX 25-30): 25% wider trail
|
||||
trailMultiplier *= 1.25
|
||||
console.log(`📈 Strong trend (ADX ${trade.adxAtEntry.toFixed(1)}): Trail multiplier ${this.config.trailingStopAtrMultiplier}x → ${trailMultiplier.toFixed(2)}x`)
|
||||
}
|
||||
// Else: weak/moderate trend, use base multiplier
|
||||
}
|
||||
|
||||
// Profit acceleration: bigger profit = wider trail
|
||||
if (profitPercent > 2.0) {
|
||||
const oldMultiplier = trailMultiplier
|
||||
trailMultiplier *= 1.3
|
||||
console.log(`🚀 Large profit (${profitPercent.toFixed(2)}%): Trail multiplier ${oldMultiplier.toFixed(2)}x → ${trailMultiplier.toFixed(2)}x`)
|
||||
}
|
||||
|
||||
// ATR-based: Use ATR% * adjusted multiplier
|
||||
const atrPercent = (trade.atrAtEntry / currentPrice) * 100
|
||||
const rawDistance = atrPercent * this.config.trailingStopAtrMultiplier
|
||||
const rawDistance = atrPercent * trailMultiplier
|
||||
|
||||
// Clamp between min and max
|
||||
trailingDistancePercent = Math.max(
|
||||
@@ -1217,7 +1242,7 @@ export class PositionManager {
|
||||
Math.min(this.config.trailingStopMaxPercent, rawDistance)
|
||||
)
|
||||
|
||||
console.log(`📊 ATR-based trailing: ${trade.atrAtEntry.toFixed(4)} (${atrPercent.toFixed(2)}%) × ${this.config.trailingStopAtrMultiplier}x = ${trailingDistancePercent.toFixed(2)}%`)
|
||||
console.log(`📊 ATR-based trailing: ${trade.atrAtEntry.toFixed(4)} (${atrPercent.toFixed(2)}%) × ${trailMultiplier.toFixed(2)}x = ${trailingDistancePercent.toFixed(2)}%`)
|
||||
} else {
|
||||
// Fallback to configured legacy percent with min/max clamping
|
||||
trailingDistancePercent = Math.max(
|
||||
|
||||
Reference in New Issue
Block a user