From d09838d1dc1805fbbd62ac2b4caac6447aa90894 Mon Sep 17 00:00:00 2001 From: mindesbunister Date: Wed, 19 Nov 2025 11:57:21 +0100 Subject: [PATCH] feat: Add ADX-based trend strength multiplier for trailing stops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- lib/trading/position-manager.ts | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/lib/trading/position-manager.ts b/lib/trading/position-manager.ts index 6221978..86bbb2c 100644 --- a/lib/trading/position-manager.ts +++ b/lib/trading/position-manager.ts @@ -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(