diff --git a/lib/health/position-manager-health.ts b/lib/health/position-manager-health.ts index 3459a77..bf5d021 100644 --- a/lib/health/position-manager-health.ts +++ b/lib/health/position-manager-health.ts @@ -14,7 +14,7 @@ */ import { getInitializedPositionManager } from '../trading/position-manager' -import { getOpenTrades } from '../database/trades' +import { getOpenTrades, getPrismaClient } from '../database/trades' import { getDriftService } from '../drift/client' export interface HealthCheckResult { diff --git a/workflows/trading/moneyline_v11_all_filters.pinescript b/workflows/trading/moneyline_v11_all_filters.pinescript index d7a3a18..915d983 100644 --- a/workflows/trading/moneyline_v11_all_filters.pinescript +++ b/workflows/trading/moneyline_v11_all_filters.pinescript @@ -16,8 +16,8 @@ profileOverride = input.string("Auto", "Profile Override", options=["Auto", "Min // Timeframe profile parameters // Minutes (<= 59m) -atr_m = input.int(12, "ATR Period (Minutes)", minval=1, group="Profiles — Minutes") -mult_m = input.float(3.8, "Multiplier (Minutes)", minval=0.1, step=0.1, group="Profiles — Minutes", tooltip="V8: Increased from 3.3 for stickier trend") +atr_m = input.int(7, "ATR Period (Minutes)", minval=1, group="Profiles — Minutes") +mult_m = input.float(2.0, "Multiplier (Minutes)", minval=0.1, step=0.1, group="Profiles — Minutes", tooltip="V11.2 RUTHLESS: 2.0× ATR = aggressive early entry, filtered for quality by other metrics") // Hours (>=1h and <1d) atr_h = input.int(10, "ATR Period (Hours)", minval=1, group="Profiles — Hours") @@ -40,32 +40,34 @@ macdSigLen = input.int(9, "Signal", minval=1, inline="macdLens") // Signal timing (ALWAYS applies to all signals) groupTiming = "Signal Timing" -confirmBars = input.int(1, "Bars to confirm after flip", minval=0, maxval=3, group=groupTiming, tooltip="V11.1 USER-VALIDATED: 1 bar confirmation - fast response while avoiding instant whipsaws.") -flipThreshold = input.float(0.15, "Flip threshold %", minval=0.0, maxval=2.0, step=0.1, group=groupTiming, tooltip="V11.1 USER-VALIDATED: 0.15% - 40% faster trend detection for 5-minute chart. Catches big moves earlier while filters block false signals.") +confirmBars = input.int(1, "Bars to confirm after flip", minval=0, maxval=3, group=groupTiming, tooltip="V11.2 BALANCED: 1 bar confirmation filters micro-crosses without adding significant lag.") +flipThreshold = input.float(0.10, "Flip threshold %", minval=0.0, maxval=2.0, step=0.1, group=groupTiming, tooltip="V11.2 BALANCED: 0.10% filters noise while staying responsive to real trends.") // Entry filters (optional) groupFilters = "Entry filters" -useEntryBuffer = input.bool(true, "Require entry buffer (ATR)", group=groupFilters, tooltip="V11: Enabled by default. Close must be beyond the Money Line by buffer amount to avoid wick flips.") -entryBufferATR = input.float(0.10, "Buffer size (in ATR)", minval=0.0, step=0.05, group=groupFilters, tooltip="V11 OPTIMIZED: 0.10 ATR (from exhaustive sweep) - balanced flip protection.") +useEntryBuffer = input.bool(false, "Require entry buffer (ATR)", group=groupFilters, tooltip="V11.2 FIX: DISABLED - buffer adds lag, causing signals after trends finish. Let other filters handle quality.") +entryBufferATR = input.float(0.0, "Buffer size (in ATR)", minval=0.0, step=0.05, group=groupFilters, tooltip="V11.2 FIX: 0.0 ATR - no buffer delay.") useAdx = input.bool(true, "Use ADX trend-strength filter", group=groupFilters, tooltip="V11: Enabled by default to reduce choppy trades.") adxLen = input.int(16, "ADX Length", minval=1, group=groupFilters) -adxMin = input.int(18, "ADX minimum", minval=0, maxval=100, group=groupFilters, tooltip="V11.2 CRITICAL FIX: 18 minimum (all ADX <18 trades were losses: 13.2=-$20, 15.8=-$4, 17.0=-$7). Filters weak chop.") +adxMin = input.int(21, "ADX minimum (LONG)", minval=0, maxval=100, group=groupFilters, tooltip="V11.2 BALANCED: 21 for LONGs - require confirmed momentum, not early noise.") +adxMinShort = input.int(26, "ADX minimum (SHORT)", minval=0, maxval=100, group=groupFilters, tooltip="V11.2 BALANCED: 26 for SHORTs - strong downtrends, not extreme-only.") // NEW v6 FILTERS groupV6Filters = "v6 Quality Filters" usePricePosition = input.bool(true, "Use price position filter", group=groupV6Filters, tooltip="Prevent chasing extremes - don't buy at top of range or sell at bottom.") -longPosMax = input.float(100, "Long max position %", minval=0, maxval=100, group=groupV6Filters, tooltip="V11 OPTIMIZED: 100% (from exhaustive sweep) - no long position limit, filters work via other metrics.") -shortPosMin = input.float(5, "Short min position %", minval=0, maxval=100, group=groupV6Filters, tooltip="V11 OPTIMIZED: 5% (from exhaustive sweep) - catches early short momentum signals.") +longPosMax = input.float(80, "Long max position %", minval=0, maxval=100, group=groupV6Filters, tooltip="V11.2 BALANCED: 80% max - catch strong moves but avoid extreme chase.") +shortPosMin = input.float(40, "Short min position %", minval=0, maxval=100, group=groupV6Filters, tooltip="V11.2 BALANCED: 40% min - short from mid-range, allow quality breakdown signals.") useVolumeFilter = input.bool(true, "Use volume filter", group=groupV6Filters, tooltip="Filter signals with extreme volume (too low = dead, too high = climax).") -volMin = input.float(0.1, "Volume min ratio", minval=0.0, step=0.1, group=groupV6Filters, tooltip="V11 OPTIMIZED: 0.1 (from exhaustive sweep) - minimal volume floor, quality via trend structure.") +volMin = input.float(0.7, "Volume min ratio (LONG)", minval=0.0, step=0.1, group=groupV6Filters, tooltip="V11.2 BALANCED: 0.7× for LONGs - require conviction, filter dead moves.") +volMinShort = input.float(1.0, "Volume min ratio (SHORT)", minval=0.0, step=0.1, group=groupV6Filters, tooltip="V11.2 BALANCED: 1.0× for SHORTs - average volume sufficient for quality signals.") volMax = input.float(3.5, "Volume max ratio", minval=0.5, step=0.5, group=groupV6Filters, tooltip="Maximum volume relative to 20-bar MA.") useRsiFilter = input.bool(true, "Use RSI momentum filter", group=groupV6Filters, tooltip="Ensure momentum confirms direction.") -rsiLongMin = input.float(58, "RSI long minimum", minval=0, maxval=100, group=groupV6Filters, tooltip="V11.2 TIGHTENED: 58-68 range (LONG trades at 59.5 lost -$40, need stronger momentum). Quality 95 still lost with RSI 59.5.") -rsiLongMax = input.float(68, "RSI long maximum", minval=0, maxval=100, group=groupV6Filters, tooltip="V11.2 TIGHTENED: 68 max (RSI 73.5 was -$17 loss, avoid overbought entries entirely).") -rsiShortMin = input.float(30, "RSI short minimum", minval=0, maxval=100, group=groupV6Filters, tooltip="V11.1 DATA-DRIVEN: 30-70 captures winners (Both winning SHORTs at RSI 38.8 and 44). Filter was blocking good signals!") -rsiShortMax = input.float(70, "RSI short maximum", minval=0, maxval=100, group=groupV6Filters, tooltip="V11.1 DATA-DRIVEN: 70 max avoids overbought chasing. User test showed 4 signals blocked with min=45!") +rsiLongMin = input.float(48, "RSI long minimum", minval=0, maxval=100, group=groupV6Filters, tooltip="V11.2 BALANCED: 48-80 catches confirmed momentum, filters noise at 45-48 neutral zone.") +rsiLongMax = input.float(80, "RSI long maximum", minval=0, maxval=100, group=groupV6Filters, tooltip="V11.2 BALANCED: 80 max allows strong trending moves.") +rsiShortMin = input.float(40, "RSI short minimum", minval=0, maxval=100, group=groupV6Filters, tooltip="V11.2 BALANCED: 40-65 shorts weakness from strength, allows breakdown signals.") +rsiShortMax = input.float(65, "RSI short maximum", minval=0, maxval=100, group=groupV6Filters, tooltip="V11.2 BALANCED: 65 max - short weakness/tops, not strength.") // V9 NEW: MA GAP VISUALIZATION OPTIONS groupV9MA = "v9 MA Gap Options" @@ -200,7 +202,9 @@ plusDI = atrADX == 0.0 ? 0.0 : 100.0 * plusDMSmooth / atrADX minusDI = atrADX == 0.0 ? 0.0 : 100.0 * minusDMSmooth / atrADX dx = (plusDI + minusDI == 0.0) ? 0.0 : 100.0 * math.abs(plusDI - minusDI) / (plusDI + minusDI) adxVal = ta.rma(dx, adxLen) -adxOk = not useAdx or (adxVal >= adxMin) +// RUTHLESS: Direction-specific ADX - LONGs 18+, SHORTs 24+ +adxOkLong = not useAdx or (adxVal >= adxMin) +adxOkShort = not useAdx or (adxVal >= adxMinShort) // Entry buffer gates relative to current Money Line longBufferOk = not useEntryBuffer or (calcC > supertrend + entryBufferATR * atr) @@ -249,20 +253,20 @@ longPositionOk = not usePricePosition or (pricePosition < longPosMax) shortPositionOk = not usePricePosition or (pricePosition > shortPosMin) // Volume filter - avoid dead or overheated moves -volumeOk = not useVolumeFilter or (volumeRatio >= volMin and volumeRatio <= volMax) +// RUTHLESS: Direction-specific volume - LONGs 0.5+, SHORTs 0.8+ +volumeOkLong = not useVolumeFilter or (volumeRatio >= volMin and volumeRatio <= volMax) +volumeOkShort = not useVolumeFilter or (volumeRatio >= volMinShort and volumeRatio <= volMax) // RSI momentum filter rsiLongOk = not useRsiFilter or (rsi14 >= rsiLongMin and rsi14 <= rsiLongMax) rsiShortOk = not useRsiFilter or (rsi14 >= rsiShortMin and rsi14 <= rsiShortMax) -// V11: OPTIMIZED STICKY TREND SIGNALS - 10× BETTER THAN V9 -// Parameters from exhaustive sweep (2,000/26,244 configs tested) -// Protection: 0.25% flip threshold + 0.10 ATR buffer + ADX 5+ + quality filters -// Result: $4,158 PnL vs v9 $406 baseline (72.5% WR, 1.755 PF, $95 max DD) -// V11 trades 2.7× more signals while maintaining 93% less drawdown -// CRITICAL FIX (v11.1): Apply ALL filter checks to signals (previously filters were calculated but not applied!) -finalLongSignal = buyReady and longOk and adxOk and longBufferOk and rsiLongOk and longPositionOk and volumeOk -finalShortSignal = sellReady and shortOk and adxOk and shortBufferOk and rsiShortOk and shortPositionOk and volumeOk +// V11.2 RUTHLESS: Asymmetric optimization for maximum profit extraction +// LONGs = Buy early momentum (relaxed filters, catch wave start) +// SHORTs = Sell exhaustion/breakdown (strict filters, high conviction) +// 1.8× bands + direction-specific ADX/RSI/Volume/Position = exploit both directions +finalLongSignal = buyReady and longOk and adxOkLong and longBufferOk and rsiLongOk and longPositionOk and volumeOkLong +finalShortSignal = sellReady and shortOk and adxOkShort and shortBufferOk and rsiShortOk and shortPositionOk and volumeOkShort plotshape(finalLongSignal, title="Buy Signal", location=location.belowbar, color=color.green, style=shape.circle, size=size.small) plotshape(finalShortSignal, title="Sell Signal", location=location.abovebar, color=color.red, style=shape.circle, size=size.small) @@ -274,7 +278,7 @@ baseCurrency := str.replace(baseCurrency, "USD", "") baseCurrency := str.replace(baseCurrency, "PERP", "") // Indicator version for tracking in database -indicatorVer = "v11" +indicatorVer = "v11.2" // Build enhanced alert messages with context (timeframe.period is dynamic) // V9 NEW: Added MAGAP field for MA gap percentage