Story 2.2: Implement WARNING Triggers
Story ID: STORY-2.2
Epic: EPIC-002 (Phase 2 - Complete Grid Exit Strategy)
Priority: P0
Effort: 4-6 hours (Actual: ~2 hours)
Status: review
Story
Implement WARNING state trigger logic requiring 2+ conditions to fire (not single condition). This prevents false alarms from single noisy indicators.
WARNING Conditions (require 2+ to trigger):
- TRANSITION probability ≥ 40% (configurable)
- Regime confidence declining over 3 bars
- Efficiency Ratio rising above 0.6 (configurable)
- Mean reversion speed slowing
- Volatility expansion 1.1-1.25×
Acceptance Criteria
-
evaluate_warning_conditions()function implemented insrc/exit_strategy/triggers/warning.py - Requires 2+ conditions to trigger WARNING (NOT single condition)
- All 5 condition checks implemented
- Configurable thresholds via YAML (parameters accepted, schema in Story 2.6)
- Unit tests cover edge cases (0, 1, 2, 5 conditions met)
- Returns (ExitState, List[str]) with reasons for conditions met
Tasks/Subtasks
Task 1: Create WARNING triggers module ✅
- Create
src/exit_strategy/triggers/warning.py - Import
ExitStateenum from evaluator (already exists) - Import necessary types and dependencies
Task 2: Implement condition check functions ✅
- Implement
check_transition_probability()- TRANSITION prob ≥ threshold - Implement
check_confidence_declining()- regime confidence declining over 3 bars - Implement
check_efficiency_ratio_rising()- ER rising above threshold - Implement
check_mean_reversion_slowing()- OU half-life increasing - Implement
check_volatility_expansion_warning()- ATR expansion 1.1-1.25×
Task 3: Implement main evaluation function ✅
- Implement
evaluate_warning_conditions()function - Check all 5 conditions
- Collect reasons for conditions met
- Return WARNING only if ≥2 conditions met
- Return NORMAL if 0-1 conditions met
- Include descriptive reasons in return value
Task 4: Write comprehensive unit tests ✅
- Test WARNING requires 2+ conditions (1 condition = NORMAL)
- Test WARNING triggers with exactly 2 conditions
- Test WARNING triggers with all 5 conditions
- Test each individual condition in isolation
- Test boundary cases (threshold values)
- Test missing/None data handling
- Test empty history handling
- Verified 90%+ code coverage (34 tests, 100% passing)
Task 5: Configuration integration ✅
- Define configuration schema for WARNING thresholds (in docstrings)
- Document default values
- Test with different threshold configurations
Task 6: Manual validation ✅
- Test with real metrics showing 1 condition met (should be NORMAL)
- Test with real metrics showing 2+ conditions met (should be WARNING)
- Verify no false positives on stable RANGE_OK periods
Dev Notes
Architecture Context
- Working directory:
.builders/0013-market-maker-mvp/repos/market-making/metrics-service/ - Module path:
src/exit_strategy/triggers/warning.py - Test path:
tests/exit_strategy/triggers/test_warning.py
Technical Specifications
Function Signature:
from enum import Enum
from typing import Dict, List, Tuple
class ExitState(Enum):
NORMAL = "normal"
WARNING = "warning"
LATEST_ACCEPTABLE_EXIT = "latest_acceptable_exit"
MANDATORY_EXIT = "mandatory_exit"
def evaluate_warning_conditions(
regime_history: List[Dict],
config: Dict
) -> Tuple[ExitState, List[str]]:
"""
Evaluate all warning conditions.
Returns WARNING if 2+ conditions met, else NORMAL.
CRITICAL: Single condition is NOT sufficient to trigger WARNING.
This prevents false alarms from noisy indicators.
Args:
regime_history: List of recent regime evaluations (last 3-6 hours)
Each dict contains: timestamp, regime_verdict, confidence,
transition_probability, efficiency_ratio, ou_halflife, atr
config: Configuration dict with thresholds:
- warning_transition_threshold: float (default 0.40)
- warning_confidence_decline_bars: int (default 3)
- warning_efficiency_ratio_threshold: float (default 0.6)
- warning_mean_reversion_slowdown: float (default 1.5)
- warning_volatility_expansion_min: float (default 1.10)
- warning_volatility_expansion_max: float (default 1.25)
Returns:
(ExitState, reasons: List[str])
- ExitState.WARNING if ≥2 conditions met
- ExitState.NORMAL if 0-1 conditions met
- reasons: List of descriptive strings for conditions met
"""
conditions_met = []
# Condition 1: TRANSITION probability rising
if check_transition_probability(regime_history, config):
conditions_met.append("TRANSITION probability rising")
# Condition 2: Regime confidence declining
if check_confidence_declining(regime_history, config):
conditions_met.append("Regime confidence declining")
# Condition 3: Efficiency Ratio rising
if check_efficiency_ratio_rising(regime_history, config):
conditions_met.append("Efficiency Ratio rising above threshold")
# Condition 4: Mean reversion slowing
if check_mean_reversion_slowing(regime_history, config):
conditions_met.append("Mean reversion speed slowing")
# Condition 5: Volatility expansion (warning range)
if check_volatility_expansion_warning(regime_history, config):
conditions_met.append("Volatility expanding (warning range)")
# CRITICAL: Require 2+ conditions to trigger WARNING
if len(conditions_met) >= 2:
return ExitState.WARNING, conditions_met
else:
if len(conditions_met) == 1:
return ExitState.NORMAL, [f"Single warning condition ({conditions_met[0]}) - not actionable"]
else:
return ExitState.NORMAL, ["No warning conditions met"]Helper Functions:
def check_transition_probability(regime_history: List[Dict], config: Dict) -> bool:
"""Check if TRANSITION probability ≥ threshold"""
pass
def check_confidence_declining(regime_history: List[Dict], config: Dict) -> bool:
"""Check if regime confidence declining over N bars (default 3)"""
pass
def check_efficiency_ratio_rising(regime_history: List[Dict], config: Dict) -> bool:
"""Check if Efficiency Ratio rising above threshold"""
pass
def check_mean_reversion_slowing(regime_history: List[Dict], config: Dict) -> bool:
"""Check if OU half-life increasing (mean reversion slowing)"""
pass
def check_volatility_expansion_warning(regime_history: List[Dict], config: Dict) -> bool:
"""Check if ATR expansion in warning range (1.1-1.25×)"""
passDependencies
- Story 2.4 (Historical Data Loading) - COMPLETE (PR #7 merged)
- Phase 1 metrics (ADX, ER, OU half-life, ATR) available in metrics YAMLs
Testing Standards
- Use pytest
- 90%+ code coverage required
- Test with mocked data
- Integration tests use real metrics data
- Test file:
tests/exit_strategy/triggers/test_warning.py
Configuration Schema
exit_rules:
warning:
minimum_conditions_required: 2 # CRITICAL: Prevents single-condition false alarms
transition_probability_threshold: 0.40
regime_confidence_decline_bars: 3
efficiency_ratio_threshold: 0.6
mean_reversion_slowdown_threshold: 1.5 # Half-life increase ratio
volatility_expansion_min: 1.10
volatility_expansion_max: 1.25Dev Agent Record
Implementation Plan
Followed TDD approach:
- Created
warning.pymodule with 6 functions (5 condition checks + main evaluator) - Implemented 2+ condition requirement (CRITICAL for preventing false alarms)
- Wrote 34 comprehensive unit tests
- All tests passed on first run (clean implementation)
- Updated triggers
__init__.pyto export WARNING functions
Debug Log
No issues - all 34 tests passed on first run! Clean implementation with proper error handling.
Completion Notes
✅ Story 2.2 COMPLETE - 2026-02-02
Implementation Summary:
- Created
src/exit_strategy/triggers/warning.pywith main evaluation function - Implements CRITICAL 2+ condition requirement to prevent false alarms
- 5 condition checks: transition probability, confidence declining, ER rising, mean reversion slowing, volatility expansion
- Returns
(ExitState, List[str])with descriptive reasons - 34 unit tests, 100% passing, no regressions
Key Features:
evaluate_warning_conditions(): Main evaluator requiring 2+ conditionscheck_transition_probability(): Detects rising TRANSITION probabilitycheck_confidence_declining(): Detects declining confidence over N barscheck_efficiency_ratio_rising(): Detects ER above threshold (trending behavior)check_mean_reversion_slowing(): Detects OU half-life increasingcheck_volatility_expansion_warning(): Detects ATR expansion in warning range (1.1-1.25×)
Test Coverage:
- 5 tests for main
evaluate_warning_conditions()(0, 1, 2, 5 conditions) - 5 tests for
check_transition_probability() - 5 tests for
check_confidence_declining() - 5 tests for
check_efficiency_ratio_rising() - 5 tests for
check_mean_reversion_slowing() - 7 tests for
check_volatility_expansion_warning() - 2 integration tests
Actual Effort: ~2 hours (vs estimated 4-6h) - leveraged Story 2.1 patterns
Test Results: 515 total tests passing (added 34 new tests, no regressions)
File List
-
src/exit_strategy/triggers/warning.py(created - 302 lines) -
src/exit_strategy/triggers/__init__.py(updated - added exports) -
tests/exit_strategy/triggers/test_warning.py(created - 329 lines)
Change Log
- 2026-02-02: Story created from EPIC-phase-2-exit-strategy.md
- 2026-02-02: Implementation complete - 5 condition checks + main evaluator, 34 tests passing
Related Artifacts
- Epic:
.ai/projects/market-making/EPIC-phase-2-exit-strategy.md - Story 2.1: LATEST_ACCEPTABLE_EXIT Triggers (dependency)