# VS-03: Market Data Ingestion - Vertical Slice Specification **Slice ID:** VS-03 **Batch:** 2 (depends on VS-00, VS-02, which are complete) **Status:** 📋 SPECIFICATION **Created:** 2026-08-05 --- ## Executive Summary Establish **Market Data Ingestion** system that pulls stock prices, indices, and financial data from external sources (KRX, OpenDart) and normalizes them for downstream signal generation. **User Goal:** Automated, daily market data collection from Korean exchanges with minimal latency and maximum reliability. **Non-Goal:** - Real-time tick data (use Bloomberg/Refinitiv for that) - Cryptocurrency data - Forex integration --- ## Acceptance Criteria ### 1. Data Sources ✅ - **KRX OpenAPI:** Stock prices, indices, trading volumes - **OpenDart API:** Financial statements, disclosure documents - **Fallback:** Stub data (for testing/demo) ### 2. Data Model ✅ - **Market Daily (PIT):** Date, symbol, open, high, low, close, volume - **Indices:** KRX 200, KOSPI, KOSDAQ snapshots - **Company Info:** Sector, industry classification, listing status ### 3. Ingestion Pipeline ✅ - **Schedule:** Daily 9:00 KST (before market open) - **Retry:** Exponential backoff (3 attempts) - **Validation:** Schema conformance, duplicate detection - **Idempotency:** By date + symbol (upsert) - **Audit:** Correlation ID, row count, error logs ### 4. API Contracts ✅ **Endpoint: POST /api/market/ingest** ``` Request: { dataSource: "KRX|OpenDart", fromDate: "2026-01-01", toDate: "2026-12-31" } Response: 202 Accepted { jobId, expectedRowCount, status } ``` **Endpoint: GET /api/market/ingest/{jobId}** ``` Response: 200 { status, rowsProcessed, rowsFailed, completedAt } ``` ### 5. Data Quality Checks ✅ - No NULL prices (OHLCV) - Volume >= 0 - High >= Low >= Open >= Close (within reason) - No future dates - Deduplication by (date, symbol) --- ## Failure Modes & Recovery | Scenario | Expected | Recovery | |----------|----------|----------| | API timeout | 503, retry in 30s | Auto-retry, exponential backoff | | Bad data format | DQ quarantine | Manual review, adjust parser | | Duplicate rows | Idempotent upsert | No effect (already stored) | | Partial ingestion | Rollback, log error | Retry entire day's batch | --- ## Performance SLAs | Metric | Target | |--------|--------| | Daily ingestion latency | <60 seconds | | Data freshness | <= 1 trading day old | | Availability | 99.5% (allow 1 failure/week) | | Max rows/day | 100,000 (stocks + indices) | --- ## Dependencies ### Inbound (Blocked By) - ✅ **VS-00:** Platform foundation (complete) - ✅ **VS-02:** Permission model (complete) ### Outbound (Unblocks) - 🔄 **VS-04:** Trade Execution (uses VS-03's price data) - 🔄 **VS-05:** Signal Generation (consumes VS-03 data) - 🔄 **VS-06:** Portfolio Optimization (requires clean price history) --- ## Component Breakdown (7 items) | Component | Status | |-----------|--------| | **GOV** | 📋 This spec | | **DATA** | ⏳ Next: PIT schema | | **DOMAIN** | ⏳ Data validation + normalization | | **BE** | ⏳ Ingestion API | | **ASYNC** | ⏳ Hangfire scheduler + event publishing | | **FE** | ⏳ Ingestion status dashboard | | **TESTOPS** | ⏳ Data quality tests | **Total Duration:** ~6 hours (wall-clock 1 day) --- ## Branching Strategy All work on `Phase-2-Batch-2` branch, squash to main. **Commits:** 1. GOV + DATA (spec + contract) 2. DOMAIN (validation logic) 3. BE + ASYNC (API + scheduler) 4. FE + TESTOPS (dashboard + tests) --- ## Sign-Off | Role | Status | Date | |------|--------|------| | Architect | ✅ Draft | 2026-08-05 | | Data Quality | ⏳ Review | TBD |