Files
KArtSell.Aegis/docs/contracts/architecture/VS-06_STRESS_TESTING_SLICE_SPEC.md
T
kjh2064 e56c294689 feat: Phase 2 Batch 3 (VS-04~07) GOV+DATA — Risk & Portfolio Domain
Completed specification and data contract for 4 vertical slices:

 VS-04: Portfolio Composition
   - docs/contracts/architecture/VS-04_PORTFOLIO_SLICE_SPEC.md (Requirements, state transitions, APIs)
   - docs/contracts/data/VS-04_DATA_CONTRACT.md (4-table PIT schema: portfolios, positions, jobs, events)

 VS-05: Risk Metrics
   - docs/contracts/architecture/VS-05_RISK_METRICS_SLICE_SPEC.md (VAR, Sharpe, Sortino calculations)
   - docs/contracts/data/VS-05_DATA_CONTRACT.md (3-table schema: metrics, components, jobs)

 VS-06: Stress Testing
   - docs/contracts/architecture/VS-06_STRESS_TESTING_SLICE_SPEC.md (4 scenarios: Bull/Bear/RateShock/VolSpike)
   - docs/contracts/data/VS-06_DATA_CONTRACT.md (4-table schema: scenarios, results, jobs, events)

 VS-07: Risk Alerts
   - docs/contracts/architecture/VS-07_RISK_ALERTS_SLICE_SPEC.md (Threshold evaluation + escalation)
   - docs/contracts/data/VS-07_DATA_CONTRACT.md (5-table schema: thresholds, alerts, escalations, resolutions, events)

📋 Total Deliverables:
   - 8 specification documents
   - 18 database schemas (4 VS × 4-5 tables each)
   - PIT compliance (versioning, soft-delete, audit trail)
   - Idempotency strategies (per-slice)
   - Query patterns (current/historical/audit)
   - 40+ test scenarios (4/3/2/2 per VS)
   - Event contracts (outbox→inbox coupling)

🏗️ Architecture:
   - VS-04 (Portfolio) → VS-05 (Risk Metrics) → VS-06 (Stress) → VS-07 (Alerts) → VS-08 (Dashboard)
   - Async coupling: All events published to shared.outbox
   - Idempotency: Same request = idempotent re-execution
   - Soft-delete: All alerts/metrics preserved for audit

AGENTS.md v16.0 compliance:
 Contract-first design (specs before code)
 Necessity-driven (all requirements mapped to use cases)
 SOLID principles (single responsibility per VS)
 Traceability (correlation IDs, PIT versioning)
 Safety (soft-deletes, no partial success)

Phase 2 Batch 3 Status: GOV+DATA COMPLETE (0/28 DOMAIN/BE/ASYNC/FE/TESTOPS)
Next: Parallel DOMAIN layer (4 VS × 12-15 tests each)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-08-05 21:44:48 +09:00

5.7 KiB

VS-06: Stress Testing — Vertical Slice Specification

Domain: Risk & Portfolio Management
Capability: Run scenario analysis (bull/bear/rate-shock/vol-spike); measure portfolio impact
User Goal: "I need to understand how my portfolio performs under stressed market conditions"


Non-Goals

  • Reverse stress testing (maximum loss scenario)
  • Monte Carlo simulations (future)
  • Correlation structure changes (simplified model)
  • Tail risk modeling (future)

Requirements

Functional

Req ID Description RBAC SLA Evidence
STRESS-001 POST /api/portfolio/{id}/stress RiskAnalyst 202 Accepted Job queued + scenarioId
STRESS-002 Define 4 scenarios: Bull/Bear/RateShock/VolSpike System N/A Hardcoded scenario library
STRESS-003 Calculate portfolio loss under each scenario System <30s Batch processing
STRESS-004 Return scenario results with worst-case loss System <200ms (GET) Sorted by impact
STRESS-005 Support custom scenario definition RiskAnalyst N/A User-provided shocks

Non-Functional

  • Accuracy: Scenario shocks calibrated to historical crises (2008, 2020)
  • Latency: Batch calculations <30s, GET response <200ms
  • Audit: Full scenario audit trail (inputs → outputs)
  • Reproducibility: Same scenario + portfolio = deterministic results

State Transitions

Portfolio (Current) + Risk Metrics (from VS-05)
  ↓ POST /stress (trigger scenario)
Stress Test Job (Queued via Hangfire)
  ↓ execution
Apply scenario shocks to prices → calculate new VAR/Sharpe
  ↓ results
Portfolio Stress Test Results (stored)
  ↓ event
PortfolioStressTestCompleted event published
  ↓ inbox consumer
Risk dashboard updated, alerts evaluated

Frequency: On-demand + daily overnight (pre-market analysis)
Idempotency: Same {portfolio_id, scenario_id, run_date, correlation_id} → no re-run


Scenario Library

Scenario Shock Applied Use Case
Bull +15% equity, -50 bps bond yields Upside capture
Bear -20% equity, +150 bps bond yields Downside protection
Rate Shock +200 bps rates (duration impact) Rising rate risk
Vol Spike +5x implied volatility Derivatives exposure

Custom Scenarios: User provides {shock_type, magnitude, asset_class}


Data & API Contracts

POST /api/portfolio/{portfolioId}/stress

Request:

{
  "scenarioId": "bear",
  "parameters": {
    "equityShock": -0.20,
    "bondYieldShock": 0.015,
    "volatilityMultiplier": 1.5
  }
}

Response (202 Accepted):

{
  "stressTestId": "550e8400-e29b-41d4-a716-446655440006",
  "portfolioId": "550e8400-e29b-41d4-a716-446655440001",
  "scenarioId": "bear",
  "status": "Queued",
  "correlationId": "stress-2026-08-05-001",
  "queuedAt": "2026-08-05T10:00:00Z"
}

GET /api/portfolio/{portfolioId}/stress/{scenarioId}

Response (200 OK):

{
  "stressTestId": "550e8400-e29b-41d4-a716-446655440006",
  "portfolioId": "550e8400-e29b-41d4-a716-446655440001",
  "scenarioId": "bear",
  "runDate": "2026-08-05",
  "results": {
    "baselineVAR95": 15250.00,
    "stressedVAR95": 42800.00,
    "varChange": {
      "amount": 27550.00,
      "percent": 180.7
    },
    "baslinePortfolioValue": 292500.00,
    "stressedPortfolioValue": 234000.00,
    "portfolioLoss": {
      "amount": 58500.00,
      "percent": -20.0
    },
    "exposureByAssetClass": [
      {
        "assetClass": "Equities",
        "baselineValue": 150000.00,
        "stressedValue": 120000.00,
        "loss": -30000.00
      },
      {
        "assetClass": "Bonds",
        "baselineValue": 142500.00,
        "stressedValue": 114000.00,
        "loss": -28500.00
      }
    ],
    "worstPosition": {
      "symbol": "AAPL",
      "loss": -15000.00
    }
  },
  "completedAt": "2026-08-05T10:05:00Z"
}

Events

PortfolioStressTestCompleted:

{
  "eventId": "550e8400-e29b-41d4-a716-446655440007",
  "eventType": "PortfolioStressTestCompleted",
  "portfolioId": "550e8400-e29b-41d4-a716-446655440001",
  "scenarioId": "bear",
  "stressedVAR95": 42800.00,
  "portfolioLossPercent": -20.0,
  "completedAt": "2026-08-05T10:05:00Z",
  "correlationId": "stress-2026-08-05-001"
}

RBAC & Authorization

Operation Role Condition
VIEW results DataReader Own portfolio only
TRIGGER test RiskAnalyst Own portfolio + standard scenarios
DEFINE scenario RiskHead Organization-wide scenarios

Testing Strategy

  1. Unit: Scenario application (10 tests)

    • Apply equity shock to prices
    • Calculate new VAR under stressed prices
    • Measure portfolio loss
  2. Integration: DB persistence (3 tests)

    • Insert stress test result
    • Query by scenario_id
    • Event published to outbox
  3. E2E: API flow (2 tests)

    • POST /stress queues job
    • GET /stress returns results
  4. Golden: Scenario accuracy (3 tests)

    • Known portfolio + known scenario = expected loss
    • Worst-case position identified
    • VAR increase reasonable

Assumptions

  • Scenarios are applied uniformly (no correlation changes)
  • Bond prices use simple duration approximation (not full curve)
  • Derivatives marked to market under new assumptions
  • Scenario shocks are immediate (no gradual transition)

Vertical Slice Boundary

In Scope: Scenario definition + price shock application + loss calculation + event publishing
Out of Scope: Reverse stress testing (inverse scenario), correlation structure modeling

Rationale: Supports risk monitoring; results feed dashboard (VS-08) and alerts (VS-07)