Phase 1 · Event Encoder (20 channels)
Priority: High Status: Pending Depends on: None
Context
Section titled “Context”- Brainstorm report:
plans/reports/brainstorm-260423-0059-event-conditioned-kronos-research.md - Economic calendar data:
economic_calendartable (Supabase) - Event types: FOMC, CPI, NFP, GDP, PCE, earnings, rate decisions
Overview
Section titled “Overview”Build a standalone module that maps economic calendar events + cross-asset leaders to aligned (T, 20) feature tensors matching OHLCV candle timestamps.
Requirements
Section titled “Requirements”Functional
Section titled “Functional”- Query
economic_calendarfor events within a date range - Compute continuous surprise z-score per event type (NOT sign() — magnitude matters)
- Align events to OHLCV timestamps (daily: fire on event day; intraday: fire on release hour)
- Encode days-until-event as sinusoidal features (anticipatory vol)
- Fetch cross-asset leader returns (BTC, SPY, DXY, VIX) with prior-close-only enforcement
- Output: numpy array (seq_len, 20) aligned with OHLCV input
Non-Functional
Section titled “Non-Functional”- No external API calls at inference time (calendar + leader data pre-loaded)
- Support both daily and intraday timeframes
- Cache historical surprise std per event type
- Mask cross-asset channels when leader market closed (no forward-fill bias)
Architecture
Section titled “Architecture”Event Channels (20 features per timestep)
Section titled “Event Channels (20 features per timestep)”| Index | Channel | Values | Source |
|---|---|---|---|
| 0 | is_fomc | 0/1 | economic_calendar |
| 1 | is_cpi | 0/1 | economic_calendar |
| 2 | is_nfp | 0/1 | economic_calendar |
| 3 | is_gdp | 0/1 | economic_calendar |
| 4 | is_pce | 0/1 | economic_calendar |
| 5 | cpi_surprise_z | continuous float | (actual - forecast) / σ, clip to [-3,3] |
| 6 | fomc_hawkish_score | continuous float | statement tone NLP, range [-1,1] |
| 7 | nfp_surprise_z | continuous float | (actual - forecast) / σ, clip to [-3,3] |
| 8 | is_earnings | 0/1 | earnings calendar |
| 9 | is_rate_decision | 0/1 | central_bank_rates |
| 10 | days_to_fomc_sin | [-1,1] | sin(2π · days_to_next_fomc / 30) |
| 11 | days_to_fomc_cos | [-1,1] | cos(2π · days_to_next_fomc / 30) |
| 12 | days_to_cpi_sin | [-1,1] | sin(2π · days_to_next_cpi / 30) |
| 13 | days_to_cpi_cos | [-1,1] | cos(2π · days_to_next_cpi / 30) |
| 14 | btc_log_return_1h | continuous | prior bar only |
| 15 | spy_log_return_1h | continuous | prior bar only, mask when NYSE closed |
| 16 | dxy_log_return_1h | continuous | prior bar only, mask when FX session closed |
| 17 | vix_level_z | continuous | z-scored VIX level |
| 18 | reserved | 0 | future expansion |
| 19 | reserved | 0 | future expansion |
Surprise Computation (continuous, not discrete)
Section titled “Surprise Computation (continuous, not discrete)”surprise_z = (actual - forecast) / rolling_std(past_20_surprises)# keep continuous value, clip to [-3, 3] to bound outliers# DO NOT quantize to {-1, 0, +1} — magnitude carries signalCross-Asset Leader — Leakage Prevention
Section titled “Cross-Asset Leader — Leakage Prevention”def get_leader_return(leader_symbol, target_timestamp): # MUST use bar STRICTLY before target_timestamp prior_bar = query_ohlcv(leader_symbol, end=target_timestamp - 1_bar) return log(prior_bar.close / prior_prior_bar.close) # If market closed (SPY on weekend, during target's session): # return (value=0, mask=1) — paired mask channelLeakage rule: Leader bar timestamp MUST be < target bar timestamp. Never == or >.
Intraday Alignment
Section titled “Intraday Alignment”For hourly candles:
- CPI/NFP release at 8:30 ET (13:30 UTC) → flag on 13:00 or 14:00 UTC bar
- FOMC statement at 14:00 ET (19:00 UTC) → flag on 19:00 or 20:00 UTC bar
- For daily candles: flag entire day
Implementation Steps
Section titled “Implementation Steps”- Create
kronos-service/event_encoder.py - Implement
EventEncoder.__init__()— load calendar, compute surprise stats - Implement
EventEncoder.encode(timestamps, timeframe)— returns (T, 20) tensor - Implement
EventEncoder._compute_surprise_z()— continuous z-score per event - Implement
EventEncoder._days_until_sinusoidal()— channels 10–13 - Implement
EventEncoder._fetch_leader_returns()— BTC/SPY/DXY/VIX w/ leakage guard - Implement
EventEncoder._align_to_candles()— timestamp alignment - Add unit tests for edge cases (no events, multi-event day, market-closed leader, leakage guard)
Key Files
Section titled “Key Files”- Create:
kronos-service/event_encoder.py - Read:
scripts/kronos-batch-predict.py(DB connection pattern) - Read:
scripts/daily-refresh.py(FRED_SERIES list) - Read: Supabase
economic_calendarschema
Success Criteria
Section titled “Success Criteria”- Produces (T, 20) array for any symbol/timeframe/date_range
- Handles missing forecast/actual gracefully (outputs 0)
- Unit tests pass for: no events, single event, multi-event, intraday alignment
- Cross-asset leader leakage guard verified (timestamp strict <)
- Market-closed leader channels correctly masked (no forward-fill)
- Inference <5ms per encode call (added leader fetch cost)