feat: competitive intelligence & historical pattern matching layer
This commit is contained in:
@@ -32,6 +32,8 @@ class SuppressionReason(str, Enum):
|
||||
LOW_SOURCE_DIVERSITY = "low_source_diversity"
|
||||
HIGH_EXTRACTION_FAILURE_RATE = "high_extraction_failure_rate"
|
||||
INSUFFICIENT_VALID_DOCUMENTS = "insufficient_valid_documents"
|
||||
MACRO_ONLY_SIGNAL = "macro_only_signal"
|
||||
PATTERN_ONLY_SIGNAL = "pattern_only_signal"
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -240,3 +242,116 @@ def evaluate_suppression(
|
||||
data_quality_score=quality_score,
|
||||
context=ctx,
|
||||
)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Macro-only suppression (Requirements: 10.3)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
MACRO_ONLY_CAVEAT = (
|
||||
"[Macro-only signal] This trend direction is driven solely by macro/geopolitical "
|
||||
"signals with no supporting company-specific evidence. Recommendation is "
|
||||
"informational only and should not be used for automated trading decisions."
|
||||
)
|
||||
|
||||
|
||||
def evaluate_macro_only_suppression(
|
||||
summary: TrendSummary,
|
||||
macro_signal_count: int,
|
||||
company_signal_count: int,
|
||||
) -> bool:
|
||||
"""Evaluate whether a recommendation should be suppressed due to macro-only signals.
|
||||
|
||||
When macro signals are the sole basis for a trend direction change
|
||||
(no supporting company-specific signals), the recommendation should
|
||||
be forced to informational mode with a macro-only caveat.
|
||||
|
||||
Args:
|
||||
summary: The trend summary to evaluate.
|
||||
macro_signal_count: Number of macro signals contributing to the trend.
|
||||
company_signal_count: Number of company-specific signals contributing.
|
||||
|
||||
Returns:
|
||||
True if the recommendation should be suppressed (macro-only), False otherwise.
|
||||
|
||||
Requirements: 10.3
|
||||
"""
|
||||
# No macro signals means no macro-only suppression
|
||||
if macro_signal_count <= 0:
|
||||
return False
|
||||
|
||||
# If there are company-specific signals, no suppression needed
|
||||
if company_signal_count > 0:
|
||||
return False
|
||||
|
||||
# Macro signals are the sole basis — suppress
|
||||
logger.info(
|
||||
"Macro-only suppression triggered for %s/%s: "
|
||||
"macro_signals=%d, company_signals=%d, direction=%s",
|
||||
summary.entity_id,
|
||||
summary.window.value,
|
||||
macro_signal_count,
|
||||
company_signal_count,
|
||||
summary.trend_direction.value,
|
||||
)
|
||||
return True
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Pattern-only suppression (Requirements: 9.3)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
PATTERN_ONLY_CAVEAT = (
|
||||
"[Pattern-only signal] This trend direction is driven solely by historical "
|
||||
"pattern and competitive signals with no supporting company-specific or macro "
|
||||
"evidence. Recommendation is informational only."
|
||||
)
|
||||
|
||||
|
||||
def evaluate_pattern_only_suppression(
|
||||
summary: TrendSummary,
|
||||
pattern_signal_count: int,
|
||||
company_signal_count: int,
|
||||
macro_signal_count: int,
|
||||
) -> bool:
|
||||
"""Evaluate whether a recommendation should be suppressed due to pattern-only signals.
|
||||
|
||||
When pattern-based signals are the sole basis for a trend direction change
|
||||
(no supporting company-specific or macro signals), the recommendation should
|
||||
be forced to informational mode with a pattern-only caveat.
|
||||
|
||||
Args:
|
||||
summary: The trend summary to evaluate.
|
||||
pattern_signal_count: Number of pattern/competitive signals contributing.
|
||||
company_signal_count: Number of company-specific signals contributing.
|
||||
macro_signal_count: Number of macro signals contributing.
|
||||
|
||||
Returns:
|
||||
True if the recommendation should be suppressed (pattern-only), False otherwise.
|
||||
|
||||
Requirements: 9.3
|
||||
"""
|
||||
# No pattern signals means no pattern-only suppression
|
||||
if pattern_signal_count <= 0:
|
||||
return False
|
||||
|
||||
# If there are company-specific signals, no suppression needed
|
||||
if company_signal_count > 0:
|
||||
return False
|
||||
|
||||
# If there are macro signals, no suppression needed
|
||||
if macro_signal_count > 0:
|
||||
return False
|
||||
|
||||
# Pattern signals are the sole basis — suppress
|
||||
logger.info(
|
||||
"Pattern-only suppression triggered for %s/%s: "
|
||||
"pattern_signals=%d, company_signals=%d, macro_signals=%d, direction=%s",
|
||||
summary.entity_id,
|
||||
summary.window.value,
|
||||
pattern_signal_count,
|
||||
company_signal_count,
|
||||
macro_signal_count,
|
||||
summary.trend_direction.value,
|
||||
)
|
||||
return True
|
||||
|
||||
Reference in New Issue
Block a user