name: scheduled_backtest_readiness timeout: 5s universes: - name: kr-backtest-smoke provider: kis selector_kind: watchlist market: kr venue: krx symbols: ["005930"] steps: # 1) Prove the scheduler tick filled market data: refresh status must be # success with a non-zero imported bar count. No import_daily_bars seed # step runs here on purpose; the data must come from the scheduler tick. - id: refresh_status action: scheduler_refresh_status request: schedule_name: kr-daily expect: status: ok scheduler_status: success min_imported_bar_count: 1 # 2) Run a backtest on the scheduler-backed data and prove it reaches a # terminal succeeded status with exit code 0 result evidence. # # Reproducibility contract (SDD S05): the KIS daily-bars importer issues a # SINGLE non-paginated call per tick (live_client.go fetchDomesticDailyBars, # tr_cont="") that returns only the most recent ~100 trading rows of the # requested range. The scheduler tick therefore loads [now-backfill_window, # now] as recent data — it cannot reach an arbitrary far-past window. So this # backtest window MUST be a RECENT window that falls inside the schedule's # rolling backfill_window, NOT a fixed long-past range. Current window: # 2026-05-26..2026-06-12 UTC (inside a >=90d backfill from a mid-2026 tick). # The field schedule (kr-backtest-smoke / 005930, daily, backfill_window # spanning this window) loads exactly these bars. If the gate is run much # later, refresh this window to a recent one. See headless_validation.md # "S05 schedule config 계약 (재현성)". - id: start action: start_backtest request: strategy_id: strategy-v1 universe: kr-backtest-smoke timeframe: daily from_unix_ms: 1779753600000 to_unix_ms: 1781222400000 expect: status: ok - id: poll action: poll_backtest_run request: run_id: "{{steps.start.run.id}}" polling_interval: 50ms expect: status: ok run_status: succeeded - id: result action: get_backtest_result request: run_id: "{{steps.start.run.id}}" expect: status: ok