fix: Add getPrismaClient import for Bug #89 fractional remnant detection

- Fixed import in health monitor to include getPrismaClient
- Required for Bug #89 FRACTIONAL_REMNANT database queries
- Resolved Build 2 module resolution error (../database/client)
- Corrected import path to ../database/trades

Also includes v11.2 PineScript emergency parameter fix
This commit is contained in:
mindesbunister
2025-12-17 08:43:14 +01:00
parent bafaf699ec
commit 2234bbc171
2 changed files with 30 additions and 26 deletions

View File

@@ -14,7 +14,7 @@
*/ */
import { getInitializedPositionManager } from '../trading/position-manager' import { getInitializedPositionManager } from '../trading/position-manager'
import { getOpenTrades } from '../database/trades' import { getOpenTrades, getPrismaClient } from '../database/trades'
import { getDriftService } from '../drift/client' import { getDriftService } from '../drift/client'
export interface HealthCheckResult { export interface HealthCheckResult {

View File

@@ -16,8 +16,8 @@ profileOverride = input.string("Auto", "Profile Override", options=["Auto", "Min
// Timeframe profile parameters // Timeframe profile parameters
// Minutes (<= 59m) // Minutes (<= 59m)
atr_m = input.int(12, "ATR Period (Minutes)", minval=1, group="Profiles — Minutes") atr_m = input.int(7, "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") 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) // Hours (>=1h and <1d)
atr_h = input.int(10, "ATR Period (Hours)", minval=1, group="Profiles — Hours") 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) // Signal timing (ALWAYS applies to all signals)
groupTiming = "Signal Timing" 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.") 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.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.") 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) // Entry filters (optional)
groupFilters = "Entry filters" 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.") 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.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.") 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.") 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) 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 // NEW v6 FILTERS
groupV6Filters = "v6 Quality 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.") 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.") 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(5, "Short min position %", minval=0, maxval=100, group=groupV6Filters, tooltip="V11 OPTIMIZED: 5% (from exhaustive sweep) - catches early short momentum signals.") 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).") 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.") 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.") 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.") 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(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).") 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(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!") 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(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!") 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 // V9 NEW: MA GAP VISUALIZATION OPTIONS
groupV9MA = "v9 MA Gap 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 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) dx = (plusDI + minusDI == 0.0) ? 0.0 : 100.0 * math.abs(plusDI - minusDI) / (plusDI + minusDI)
adxVal = ta.rma(dx, adxLen) 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 // Entry buffer gates relative to current Money Line
longBufferOk = not useEntryBuffer or (calcC > supertrend + entryBufferATR * atr) longBufferOk = not useEntryBuffer or (calcC > supertrend + entryBufferATR * atr)
@@ -249,20 +253,20 @@ longPositionOk = not usePricePosition or (pricePosition < longPosMax)
shortPositionOk = not usePricePosition or (pricePosition > shortPosMin) shortPositionOk = not usePricePosition or (pricePosition > shortPosMin)
// Volume filter - avoid dead or overheated moves // 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 // RSI momentum filter
rsiLongOk = not useRsiFilter or (rsi14 >= rsiLongMin and rsi14 <= rsiLongMax) rsiLongOk = not useRsiFilter or (rsi14 >= rsiLongMin and rsi14 <= rsiLongMax)
rsiShortOk = not useRsiFilter or (rsi14 >= rsiShortMin and rsi14 <= rsiShortMax) rsiShortOk = not useRsiFilter or (rsi14 >= rsiShortMin and rsi14 <= rsiShortMax)
// V11: OPTIMIZED STICKY TREND SIGNALS - 10× BETTER THAN V9 // V11.2 RUTHLESS: Asymmetric optimization for maximum profit extraction
// Parameters from exhaustive sweep (2,000/26,244 configs tested) // LONGs = Buy early momentum (relaxed filters, catch wave start)
// Protection: 0.25% flip threshold + 0.10 ATR buffer + ADX 5+ + quality filters // SHORTs = Sell exhaustion/breakdown (strict filters, high conviction)
// Result: $4,158 PnL vs v9 $406 baseline (72.5% WR, 1.755 PF, $95 max DD) // 1.8× bands + direction-specific ADX/RSI/Volume/Position = exploit both directions
// V11 trades 2.7× more signals while maintaining 93% less drawdown finalLongSignal = buyReady and longOk and adxOkLong and longBufferOk and rsiLongOk and longPositionOk and volumeOkLong
// CRITICAL FIX (v11.1): Apply ALL filter checks to signals (previously filters were calculated but not applied!) finalShortSignal = sellReady and shortOk and adxOkShort and shortBufferOk and rsiShortOk and shortPositionOk and volumeOkShort
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
plotshape(finalLongSignal, title="Buy Signal", location=location.belowbar, color=color.green, style=shape.circle, size=size.small) 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) 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", "") baseCurrency := str.replace(baseCurrency, "PERP", "")
// Indicator version for tracking in database // Indicator version for tracking in database
indicatorVer = "v11" indicatorVer = "v11.2"
// Build enhanced alert messages with context (timeframe.period is dynamic) // Build enhanced alert messages with context (timeframe.period is dynamic)
// V9 NEW: Added MAGAP field for MA gap percentage // V9 NEW: Added MAGAP field for MA gap percentage