feat: Add position scaling for strong confirmation signals

**Feature: Position Scaling**
Allows adding to existing profitable positions when high-quality signals confirm trend strength.

**Configuration (config/trading.ts):**
- enablePositionScaling: false (disabled by default - enable after testing)
- minScaleQualityScore: 75 (higher bar than initial 60)
- minProfitForScale: 0.4% (must be at/past TP1)
- maxScaleMultiplier: 2.0 (max 200% of original size)
- scaleSizePercent: 50% (add 50% of original position)
- minAdxIncrease: 5 (ADX must strengthen)
- maxPricePositionForScale: 70% (don't chase resistance)

**Validation Logic (check-risk endpoint):**
Same-direction signal triggers scaling check if enabled:
1. Quality score ≥75 (stronger than initial entry)
2. Position profitable ≥0.4% (at/past TP1)
3. ADX increased ≥5 points (trend strengthening)
4. Price position <70% (not near resistance)
5. Total size <2x original (risk management)
6. Returns 'allowed: true, reason: Position scaling' if all pass

**Execution (execute endpoint):**
- Opens additional position at scale size (50% of original)
- Updates ActiveTrade: timesScaled, totalScaleAdded, currentSize
- Tracks originalAdx from first entry for comparison
- Returns 'action: scaled' with scale details

**ActiveTrade Interface:**
Added fields:
- originalAdx?: number (for scaling validation)
- timesScaled?: number (track scaling count)
- totalScaleAdded?: number (total USD added)

**Example Scenario:**
1. LONG SOL at $176 (quality: 45, ADX: 13.4) - weak but entered
2. Price hits $176.70 (+0.4%) - at TP1
3. New LONG signal (quality: 78, ADX: 19) - strong confirmation
4. Scaling validation:  Quality 78  Profit +0.4%  ADX +5.6  Price 68%
5. Adds 50% more position at $176.70
6. Total position: 150% of original size

**Conservative Design:**
- Disabled by default (requires manual enabling)
- Only scales INTO profitable positions (never averaging down)
- Requires significant quality improvement (75 vs 60)
- Requires trend confirmation (ADX increase)
- Hard cap at 2x original size
- Won't chase near resistance levels

**Next Steps:**
1. Enable in settings: ENABLE_POSITION_SCALING=true
2. Test with small positions first
3. Monitor data: do scaled positions outperform?
4. Adjust thresholds based on results

**Safety:**
- All existing duplicate prevention logic intact
- Flip logic unchanged (still requires quality check)
- Position Manager tracks scaling state
- Can be toggled on/off without code changes
This commit is contained in:
mindesbunister
2025-11-03 15:35:33 +01:00
parent 57f0457f95
commit 8a8d4a348c
4 changed files with 233 additions and 6 deletions

View File

@@ -41,6 +41,15 @@ export interface TradingConfig {
trailingStopPercent: number // Trail by this % below peak
trailingStopActivation: number // Activate when runner profits exceed this %
// Position Scaling (add to winning positions)
enablePositionScaling: boolean // Allow scaling into existing positions
minScaleQualityScore: number // Minimum quality score for scaling signal (0-100)
minProfitForScale: number // Position must be this % profitable to scale
maxScaleMultiplier: number // Max total position size (e.g., 2.0 = 200% of original)
scaleSizePercent: number // Scale size as % of original position (e.g., 50)
minAdxIncrease: number // ADX must increase by this much for scaling
maxPricePositionForScale: number // Don't scale if price position above this %
// DEX specific
priceCheckIntervalMs: number // How often to check prices
slippageTolerance: number // Max acceptable slippage (%)
@@ -109,6 +118,15 @@ export const DEFAULT_TRADING_CONFIG: TradingConfig = {
trailingStopPercent: 0.3, // Trail by 0.3% below peak price
trailingStopActivation: 0.5, // Activate trailing when runner is +0.5% in profit
// Position Scaling (conservative defaults)
enablePositionScaling: false, // Disabled by default - enable after testing
minScaleQualityScore: 75, // Only scale with strong signals (vs 60 for initial entry)
minProfitForScale: 0.4, // Position must be at/past TP1 to scale
maxScaleMultiplier: 2.0, // Max 2x original position size total
scaleSizePercent: 50, // Scale with 50% of original position size
minAdxIncrease: 5, // ADX must increase by 5+ points (trend strengthening)
maxPricePositionForScale: 70, // Don't scale if price >70% of range (near resistance)
// DEX settings
priceCheckIntervalMs: 2000, // Check every 2 seconds
slippageTolerance: 1.0, // 1% max slippage on market orders
@@ -306,6 +324,27 @@ export function getConfigFromEnv(): Partial<TradingConfig> {
trailingStopActivation: process.env.TRAILING_STOP_ACTIVATION
? parseFloat(process.env.TRAILING_STOP_ACTIVATION)
: undefined,
enablePositionScaling: process.env.ENABLE_POSITION_SCALING
? process.env.ENABLE_POSITION_SCALING === 'true'
: undefined,
minScaleQualityScore: process.env.MIN_SCALE_QUALITY_SCORE
? parseInt(process.env.MIN_SCALE_QUALITY_SCORE)
: undefined,
minProfitForScale: process.env.MIN_PROFIT_FOR_SCALE
? parseFloat(process.env.MIN_PROFIT_FOR_SCALE)
: undefined,
maxScaleMultiplier: process.env.MAX_SCALE_MULTIPLIER
? parseFloat(process.env.MAX_SCALE_MULTIPLIER)
: undefined,
scaleSizePercent: process.env.SCALE_SIZE_PERCENT
? parseFloat(process.env.SCALE_SIZE_PERCENT)
: undefined,
minAdxIncrease: process.env.MIN_ADX_INCREASE
? parseFloat(process.env.MIN_ADX_INCREASE)
: undefined,
maxPricePositionForScale: process.env.MAX_PRICE_POSITION_FOR_SCALE
? parseFloat(process.env.MAX_PRICE_POSITION_FOR_SCALE)
: undefined,
maxDailyDrawdown: process.env.MAX_DAILY_DRAWDOWN
? parseFloat(process.env.MAX_DAILY_DRAWDOWN)
: undefined,