Improve signal quality scoring for breakdowns/breakouts
- Allow shorts at range bottom (<5%) with volume >1.2x OR RSI <40 - Allow longs at range bottom with volume >1.2x OR RSI >60 - Reduce ADX penalty from -15 to -5 when strong volume (>1.2x) present - Reduce price position penalties from -15 to -10 (less harsh) - Volume compensation recognizes breakdowns start before ADX strengthens Test case (blocked signal that would have profited): - OLD: ATR 0.32, ADX 17.3, RSI 32.5, Vol 1.27x, Price 0.9% → Score 45 (blocked) - NEW: Same metrics → Score 85 (executes) Rationale: Breakdowns continue lower, volume confirms conviction, ADX lags price action
This commit is contained in:
@@ -85,24 +85,41 @@ export function scoreSignalQuality(params: {
|
||||
if (params.adx > 0) {
|
||||
if (is5min) {
|
||||
// 5min: ADX 15+ is actually trending, 20+ is strong
|
||||
// High volume can compensate for lower ADX in breakouts/breakdowns
|
||||
const hasStrongVolume = params.volumeRatio > 1.2
|
||||
|
||||
if (params.adx > 22) {
|
||||
score += 15
|
||||
reasons.push(`Strong 5min trend (ADX ${params.adx.toFixed(1)})`)
|
||||
} else if (params.adx < 12) {
|
||||
score -= 15
|
||||
reasons.push(`Weak 5min trend (ADX ${params.adx.toFixed(1)})`)
|
||||
// Reduce penalty if strong volume present (breakdown/breakout in progress)
|
||||
if (hasStrongVolume) {
|
||||
score -= 5
|
||||
reasons.push(`Lower 5min ADX (${params.adx.toFixed(1)}) but strong volume compensates`)
|
||||
} else {
|
||||
score -= 15
|
||||
reasons.push(`Weak 5min trend (ADX ${params.adx.toFixed(1)})`)
|
||||
}
|
||||
} else {
|
||||
score += 5
|
||||
reasons.push(`Moderate 5min trend (ADX ${params.adx.toFixed(1)})`)
|
||||
}
|
||||
} else {
|
||||
// Higher timeframes: stricter ADX requirements
|
||||
const hasStrongVolume = params.volumeRatio > 1.2
|
||||
|
||||
if (params.adx > 25) {
|
||||
score += 15
|
||||
reasons.push(`Strong trend (ADX ${params.adx.toFixed(1)})`)
|
||||
} else if (params.adx < 18) {
|
||||
score -= 15
|
||||
reasons.push(`Weak trend (ADX ${params.adx.toFixed(1)})`)
|
||||
// Reduce penalty if strong volume present
|
||||
if (hasStrongVolume) {
|
||||
score -= 5
|
||||
reasons.push(`Lower ADX (${params.adx.toFixed(1)}) but strong volume compensates`)
|
||||
} else {
|
||||
score -= 15
|
||||
reasons.push(`Weak trend (ADX ${params.adx.toFixed(1)})`)
|
||||
}
|
||||
} else {
|
||||
score += 5
|
||||
reasons.push(`Moderate trend (ADX ${params.adx.toFixed(1)})`)
|
||||
@@ -145,7 +162,7 @@ export function scoreSignalQuality(params: {
|
||||
}
|
||||
}
|
||||
|
||||
// Price position check (avoid chasing vs breakout detection)
|
||||
// Price position check (avoid chasing vs breakout/breakdown detection)
|
||||
if (params.pricePosition > 0) {
|
||||
if (params.direction === 'long' && params.pricePosition > 95) {
|
||||
// High volume breakout at range top can be good
|
||||
@@ -158,12 +175,22 @@ export function scoreSignalQuality(params: {
|
||||
}
|
||||
} else if (params.direction === 'short' && params.pricePosition < 5) {
|
||||
// High volume breakdown at range bottom can be good
|
||||
if (params.volumeRatio > 1.4) {
|
||||
// Also allow if RSI is bearish (< 40) - breakdowns continue lower
|
||||
if (params.volumeRatio > 1.2 || (params.rsi > 0 && params.rsi < 40)) {
|
||||
score += 5
|
||||
reasons.push(`Volume breakdown at range bottom (${params.pricePosition.toFixed(0)}%, vol ${params.volumeRatio.toFixed(2)}x)`)
|
||||
reasons.push(`Valid breakdown at range bottom (${params.pricePosition.toFixed(0)}%, vol ${params.volumeRatio.toFixed(2)}x, RSI ${params.rsi.toFixed(1)})`)
|
||||
} else {
|
||||
score -= 15
|
||||
reasons.push(`Price near bottom of range (${params.pricePosition.toFixed(0)}%) - risky short`)
|
||||
score -= 10
|
||||
reasons.push(`Price near bottom of range (${params.pricePosition.toFixed(0)}%) - reduced penalty for short`)
|
||||
}
|
||||
} else if (params.direction === 'long' && params.pricePosition < 5) {
|
||||
// Longs at bottom with good volume = potential reversal
|
||||
if (params.volumeRatio > 1.2 || (params.rsi > 0 && params.rsi > 60)) {
|
||||
score += 5
|
||||
reasons.push(`Potential reversal at bottom (${params.pricePosition.toFixed(0)}%, vol ${params.volumeRatio.toFixed(2)}x, RSI ${params.rsi.toFixed(1)})`)
|
||||
} else {
|
||||
score -= 10
|
||||
reasons.push(`Price near bottom (${params.pricePosition.toFixed(0)}%) - reduced penalty for reversal long`)
|
||||
}
|
||||
} else {
|
||||
score += 5
|
||||
|
||||
Reference in New Issue
Block a user