# Phase Segmentation: Bull/Bear/Sideways/Volatility Analysis (AGENTS.md v16.0)

## 1. SOURCE (Requirements)

**From README.md:**
- "복수 국면 OOS" (Multiple market phase out-of-sample validation)

**From research/K-ArtSell_12_2_quant_review_ko.md:**
- Strategy performance varies by market regime
- Bull/Bear/Sideways/Volatility phases require separate analysis
- Robustness proof: positive returns across all phases

**From CLAUDE.md:**
- § "Validation Gates": Phase breakdown with separate metrics
- § "Shadow Run Design": PhaseBreakdown record with Bull/Bear/Sideways/HighVolatility

**Business Logic:**
- Strategy must work across **all market conditions**
- Failure in any phase → production rejection
- PBO/DSR must hold in **each phase independently**

---

## 2. SLICE SPEC (Vertical Slice)

### Goal
Segment shadow run portfolio returns by market regime; compute phase-specific metrics.

### Non-Goal
- Real-time regime detection (historical only)
- Regime switching strategy (static classification)
- Multi-period lookahead (single-period PIT)

### Workflow

1. **Input:** Daily returns + trading sessions (shadow run replay result)
2. **Detect regimes:** Classify each day into Bull/Bear/Sideways/Volatility
   - Bull: 30-day MA trending up
   - Bear: 30-day MA trending down
   - Sideways: 30-day MA flat (±5% band)
   - Volatility: Realized volatility > 2σ
3. **Aggregate:** Group returns by regime
4. **Calculate:** Per-regime metrics (Sharpe, Calmar, Max DD, Win Rate)
5. **Output:** PhaseMetrics{TradingDays, Return%, Sharpe, WinRate, MaxDD}

---

## 3. CONTRACT (Input/Output/Status)

### Input
```csharp
ReplayResult {
  DailyReturns: List<(DateOnly, decimal)>,
  PortfolioHistory: List<Portfolio>
}

OHLCV Bars {
  Date, Ticker, Close, Volume
}
```

### Output
```csharp
PhaseBreakdown {
  BullMarket: PhaseMetrics,
  BearMarket: PhaseMetrics,
  Sideways: PhaseMetrics,
  HighVolatility: PhaseMetrics
}

PhaseMetrics {
  TradingDays: int,
  Return: decimal,
  Sharpe: decimal,
  WinRate: decimal,
  MaxDrawdown: decimal
}
```

### Idempotency
- **Same input** → same regime classification (deterministic)
- **PIT safety:** No lookahead bias (classify using data available at time t only)

### Error Handling
| Scenario | Action |
|----------|--------|
| No bull days | PhaseMetrics with TradingDays=0 |
| Insufficient data for Sharpe | Return default 0m |
| Single-day regime | Skip (Sharpe undefined) |

---

## 4. DATA (Schema + Calculation)

### Regime Classification Logic

```
For each trading day t:
  price_30d_ma = EMA(close[t-30:t], span=30)
  
  IF price_30d_ma trending up (slope > 0 for last 5 days)
    CLASSIFY: Bull
  ELSE IF price_30d_ma trending down (slope < 0 for last 5 days)
    CLASSIFY: Bear
  ELSE IF ABS(price - price_30d_ma) / price_30d_ma < 0.05
    CLASSIFY: Sideways
  ELSE IF realized_vol[t] > mean_vol + 2*std_vol
    CLASSIFY: HighVolatility
  ELSE
    CLASSIFY: Sideways (default)
```

### Metrics Calculation (Per Phase)

```sql
-- Phase 1: Collect returns by regime
phase_returns = filter(daily_returns, regime == phase)

-- Phase 2: Calculate metrics
total_return = (product(1 + r for r in phase_returns) - 1)
sharpe = mean(phase_returns) / std(phase_returns) * sqrt(252)
win_rate = count(r > 0) / len(phase_returns)
max_dd = calculate_max_drawdown(cumulative_returns)
calmar = total_return / max_dd
```

### Storage
- No database persistence (computed on-demand)
- Included in `ShadowRunResult.phase_analysis_json`
- Immutable after shadow run completion

---

## 5. TESTS (Verification)

### Unit Tests

| Test | Scenario | Expected |
|------|----------|----------|
| Regime_BullTrend | 30-day MA rising consistently | All days → Bull |
| Regime_BearTrend | 30-day MA falling consistently | All days → Bear |
| Regime_Sideways | Price oscillates ±5% around MA | All days → Sideways |
| Regime_HighVolatility | Realized vol > mean + 2σ | All days → HighVolatility |
| Metrics_SinglePhase | All returns in Bull phase | Sharpe ≤ 5, WinRate [0,1] |
| Metrics_MultiPhase | Mixed returns across phases | Each phase computed separately |
| Metrics_EmptyPhase | No returns in Bear phase | TradingDays=0, Return=0 |

### Integration Tests

| Test | Scenario | Expected |
|------|----------|----------|
| PhaseBreakdown_SumsDays | Sum(TradingDays across phases) | = Total trading days |
| PhaseBreakdown_Consistency | Bull + Bear + Sideways + Vol days | = Portfolio history length |
| PhaseBreakdown_NoLookahead | Regime known only from t-30 data | Classification deterministic |

### Data Tests

| Test | Scenario | Expected |
|------|----------|----------|
| Sharpe_Calculation | Known returns + vol | Matches manual calculation |
| MaxDD_Calculation | Simulated drawdown sequence | Matches cumulative peak-to-trough |

---

## 6. OPS (Deployment + Monitoring)

### Startup
- Phase segmentation runs **after replay** (inside ShadowRunJob)
- No external dependencies (uses replay results + OHLCV bars from backfill)
- Deterministic: No randomness, no API calls

### Monitoring
- Alert if any phase has 0 trading days (data gap)
- Alert if Sharpe calculation fails (log error, use default 0)
- Metrics validation: WinRate ∈ [0,1], Sharpe ∈ [-5,5]

### Rollback
- Phase segmentation is read-only compute (no state changes)
- If calculation fails: return zeros for that phase
- Job continues (non-blocking)

---

## 7. OUTPUT RULE (Deliverables)

**Changed files:**
```
src/KArtSell.Modules.ModelOperations/
  ShadowRun/
    PhaseSegmentation.cs          (Main calculator)
    RegimeClassifier.cs           (Bull/Bear/Sideways/Vol logic)
    PhaseMetricsCalculator.cs     (Sharpe, Calmar, etc.)

tests/KArtSell.Integration.Tests/
  PhaseSegmentationTests.cs       (Unit tests)
  PhaseSegmentationIntegrationTests.cs (Integration tests)
```

**Verification:**
```bash
dotnet test --filter "PhaseSegmentation" -c Release
# Expected: All tests green
```

---

## 8. AGENTS.md v16.0 CHECKLIST

| Criterion | Status | Evidence |
|-----------|--------|----------|
| **SOLID** | ✅ Design | RegimeClassifier (single responsibility), DI ready |
| **Complexity** | ✅ Design | Regime logic cyclomatic < 10, metrics calc < 10 |
| **Audit** | ✅ Design | PIT safety: classify using only historical data |
| **Necessity** | ✅ Sourced | README.md: "복수 국면 OOS" requirement |
| **Normalization** | ✅ Design | Read-only compute, immutable output in JSONB |
| **Simplicity** | ✅ Design | Clear regime rules, deterministic classification |
| **Pattern** | ✅ Design | Vertical component (Segmenter → Classifier → Metrics) |
| **Guardrails** | ✅ Design | No lookahead, error handling (empty phases), bounds checking |
| **Traceability** | ✅ Design | Regime per-day logged, metrics tagged with phase name |
| **Safety** | ✅ Design | Idempotent (same input = same regime), read-only |
| **Maturity** | ✅ Design | Contract → Test → Implementation sequencing |
| **Right Way** | ✅ Design | PIT-safe classification, no shortcuts |
| **Debt** | ✅ Design | Zero new tech debt, uses existing infrastructure |

---

## NEXT STEPS (Sequenced)

### Step 1: RegimeClassifier
- Implement regime detection logic (Bull/Bear/Sideways/Vol)
- Unit tests: Each regime type

### Step 2: PhaseMetricsCalculator
- Calculate Sharpe, Calmar, Max DD, Win Rate per phase
- Unit tests: Metric calculations

### Step 3: PhaseSegmentation (Orchestrator)
- Integrate classifier + metrics calculator
- Integration tests: Full phase breakdown

### Step 4: ShadowRunJob Integration
- Call PhaseSegmentation after MetricsCalculator
- Populate result.PhaseAnalysis
- Tests: End-to-end shadow run with phase breakdown

### Step 5: Validation
- Build passes, tests 100% green
- Commit & push
