# Direct Invocation Testing & Verification ## Quick Start ### 1. Call Direct API ```powershell $headers = @{ "Content-Type" = "application/json" } $body = @{ modelId = "00000000-0000-0000-0000-000000000004" windowStart = "2026-05-01" windowEnd = "2026-05-31" phaseFilter = "All" } | ConvertTo-Json $response = Invoke-WebRequest -Uri "http://127.0.0.1:5002/api/test/shadow-run-direct" ` -Method POST -Headers $headers -Body $body $response.Content | ConvertFrom-Json ``` Returns: ```json { "Success": true, "RunId": "af5a7555-7673-43ac-9701-d5978fcbcf83", "CorrelationId": "...", "DurationMs": 1668.3, "Message": "Shadow run executed successfully. Check database for persisted results." } ``` ### 2. Verify Database Results **Using psql:** ```bash psql -h 127.0.0.1 -U kartsell -d kartselldb -c " SELECT run_id, model_id, window_start, window_end, status, (metrics_json->>'TotalReturn')::numeric as total_return, (metrics_json->>'SharpeRatio')::numeric as sharpe, (metrics_json->>'ProbOfBacktestOverfit')::numeric as pbo, (metrics_json->>'DailySharePercentile')::numeric as dsr, created_at FROM model_operations.shadow_run WHERE model_id = '00000000-0000-0000-0000-000000000004' ORDER BY created_at DESC LIMIT 5; " ``` **Using .NET DbMigrator (E2E):** ```bash dotnet test tests/KArtSell.Integration.Tests -c Release --filter "ShadowRunDirectInvocation" ``` ## Performance Characteristics | Window | Duration | Metrics Calculated | |--------|----------|-------------------| | **252 days** (2025-08-12 ~ 2026-08-12) | 8.6s | ✅ Full year | | **90 days** (2026-05-15 ~ 2026-08-12) | 2.3s | ✅ Q2-Q3 | | **30 days** (2026-04-01 ~ 2026-04-30) | 1.6s | ⚠️ Insufficient (needs 252+ days) | ## Key Improvements ✅ **No Queue Wait** - Direct synchronous execution ✅ **Stub API Data** - No external API calls (KRX_OPENAPI not set → stub) ✅ **Fast Feedback** - 2-3 min vs 7+ min with Hangfire ✅ **Persistence Verified** - Results saved to model_operations.shadow_run ## Architecture ``` API Request ↓ ShadowRunJob.ExecuteAsync (direct, no queue) ├─ Phase 1: DataBackfiller.BackfillOhlcvAsync │ └─ Uses StubKrxData (no real API call) ├─ Phase 2: ReplayEngine.ReplayAsync ├─ Phase 3: MetricsCalculator.CalculateAsync ├─ Phase 4: PhaseSegmentation.Segment └─ InsertShadowRunAsync (DB persist) └─ Outbox event emitted └─ Inbox consumer processes async ``` ## Testing Notes - **Unit Tests**: `ShadowRunDirectInvocationTests` (2/2 passing) - **Integration Tests**: `ShadowRunTests` (all passing) - **E2E Gateway Tests**: `ShadowRunGate3Tests` (via Hangfire queue) ## Next Steps 1. ✅ Direct invocation endpoint implemented 2. ✅ DB persistence verified 3. ⏳ **TODO**: Isolate API mock for faster unit tests (separate from integration tests) 4. ⏳ **TODO**: Add performance benchmarks (target <3s for 90-day windows)