| 1 | # Market Data |
| 2 | |
| 3 | Phase 2B defines the real market-data connectivity boundary without claiming a live quote source. |
| 4 | |
| 5 | ## Provider Order |
| 6 | |
| 7 | 1. Broker-supported market data after official provider docs and read-only validation exist. |
| 8 | 2. Secondary documented and permitted source. |
| 9 | 3. Stale cache. |
| 10 | 4. Mock quotes only when demo mode is enabled. |
| 11 | |
| 12 | ## Freshness Vocabulary |
| 13 | |
| 14 | - `REAL_TIME` |
| 15 | - `DELAYED` |
| 16 | - `END_OF_DAY` |
| 17 | - `STALE` |
| 18 | - `MOCK`, displayed as `DEMO` |
| 19 | - `UNAVAILABLE` |
| 20 | |
| 21 | ## Current Implementation |
| 22 | |
| 23 | `FallbackMarketDataProvider` is the primary portfolio-service provider. It checks usable cached quotes first, exposes expired cache entries as `STALE`, returns mock quotes only when `MARKET_DATA_DEMO_MODE=true`, and otherwise returns `UNAVAILABLE` with source `NoVerifiedMarketDataProvider`. |
| 24 | |
| 25 | The base runtime default is `MARKET_DATA_DEMO_MODE=false`. DEV and test profiles may explicitly enable demo mode. Cached `MOCK` quotes are ignored when demo mode is disabled, so a real/non-demo runtime cannot silently reuse fake prices. |
| 26 | |
| 27 | Quotes carry `source`, `sourceTimestamp`, `receivedAt`, and `freshness`. The older `timestamp` field remains the quote/source timestamp for API compatibility. |
| 28 | |
| 29 | Redis stores deterministic fresh and stale keys: |
| 30 | |
| 31 | - `market:quote:{instrumentId}` |
| 32 | - `market:quote:stale:{instrumentId}` |
| 33 | |
| 34 | No arbitrary quote website scraping is implemented. No paid API is configured. |
| 35 | |
| 36 | ## Validation Status |
| 37 | |
| 38 | - Real market-data source validated: NO |
| 39 | - Broker market data validated: NO |
| 40 | - Mock fallback available in DEV/demo mode: YES |