alt/agent-roadmap/sdd/backtest-loop/scheduled-market-data-refresh/SDD.md
toki 91602a66c7 docs(backtest): SDD 문서와 마일스톤을 업데이트하고 USER_REVIEW 정리한다
backtest-multi-timeframe-coverage와 scheduled-market-data-refresh의 SDD 및 마일스톤 문서 수정
USER_REVIEW 파일 삭제 (검증 완료로 간주)
2026-06-17 21:31:45 +09:00

9.9 KiB

SDD: Scheduled Market Data Refresh

위치

  • Milestone: agent-roadmap/phase/backtest-loop/milestones/scheduled-market-data-refresh.md
  • Phase: agent-roadmap/phase/backtest-loop/PHASE.md

상태

[승인됨]

SDD 잠금

  • 상태: 해제
  • 사용자 리뷰: 없음
  • 잠금 항목: 없음

문제 / 비목표

  • 문제: market data import가 수동 scenario 실행에만 의존하면 원격 서버의 backtest input freshness를 반복 확인하기 어렵다. scheduler는 provider 호출, DB upsert, retry/backfill, freshness/readiness, remote smoke까지 같은 운영 경계로 묶어야 한다.
  • 비목표:
    • Flutter 운영 화면 구현
    • 새 strategy 판단 로직 또는 투자 의사결정 알고리즘 설계
    • paper/live order routing과 실거래 adapter 변경
    • 월봉/분봉 provider import와 backtest engine 지원 확장 전체
    • 외부 provider credential 값이나 개인 secret 문서화

Source of Truth

영역 기준 메모
Roadmap agent-roadmap/phase/backtest-loop/milestones/scheduled-market-data-refresh.md Milestone 목표, 기능 Task, 범위 제외, 완료 후보 반영 기준
Code services/worker/cmd/alt-worker/main.go worker runtime wiring과 job runner 등록 기준
Code services/worker/internal/config/config.go worker runtime env/config source of truth. scheduler config는 secret 값을 직접 보관하지 않는다.
Code services/worker/internal/jobs/marketdata_jobs.go import_daily_bars job payload, provider capability gate, importer dispatch 기준
Code services/worker/internal/storage/postgres/queries/queries.sql bars upsert idempotency 기준
Code apps/cli/internal/operator/scenario.go scenario validation, collection_freshness, matrix/readiness smoke 기준
Code apps/cli/testdata/operator/headless_validation.md operator-facing headless evidence key와 scenario handoff 기준
External Provider KIS scheduled tick이 호출할 provider이며 delay, gap, missing, typed error를 상태로 남겨야 한다.
User Decision user_review_0.log D01: scheduler는 services/worker 내장 loop가 1차 실행 주체다. OS/systemd는 process supervision만 맡고 external cron은 사용하지 않는다. worker scheduler는 설정된 한도 안에서 병렬 수집을 지원해야 한다.

State Machine

상태 진입 조건 다음 상태 근거
config-candidate schedule config가 named universe, provider, selector, timeframe, cadence, timezone, backfill window, parallelism limit를 선언한다. config-valid 또는 config-rejected validate/dry-run output
config-rejected 필수 필드 누락 또는 provider/timeframe 조합 미지원이다. terminal typed validation error, stable text/JSONL
config-valid schedule config가 validation을 통과한다. scheduled next window calculation
scheduled worker 내장 scheduler loop에서 tick 시간이 도래하거나 manual tick smoke가 실행된다. dispatching 또는 skipped scheduler log/status
dispatching worker scheduler가 tick lock을 획득하고 universe를 수집 작업 단위로 펼친다. running bounded parallel dispatch log/status
skipped 동일 tick이 이미 running이거나 lock/idempotency guard가 막는다. terminal duplicate tick evidence
running 하나 이상의 import job이 설정된 병렬 한도 안에서 provider 호출과 DB upsert를 실행한다. succeeded, stale, 또는 failed job result, importer result, DB state
succeeded import와 freshness/readiness가 expected window를 만족한다. ready-for-backtest status JSONL, freshness output
stale provider delay, missing, gap이 남아 backfill/retry가 필요하다. scheduled 또는 terminal retry/backfill calculation, stale status
failed provider, config, DB, runtime 오류가 발생한다. scheduled 또는 terminal last_error, error status
ready-for-backtest scheduler가 적재한 데이터로 selector가 bars를 찾는다. terminal backtest matrix/result smoke exit code 0

Interface Contract

  • 계약 원문: 없음
  • 입력:
    • schedule_config: named universe별 provider, selector, timeframe, cadence, timezone, backfill window, parallelism limit.
    • tick: worker 내장 scheduler loop 또는 manual smoke로 실행되는 refresh trigger. 1차 구현에서 external cron은 사용하지 않는다.
    • provider_capability: provider, market, venue, timeframe별 accepted/rejected 판정.
    • runtime_env: provider credential과 DB URL은 config 파일에 쓰지 않고 원격 runtime env/SOPS 주입 경계에서 제공한다.
    • freshness_window: latest, expected dates, missing/gap/duplicate/provider delay를 계산할 기간.
  • 출력:
    • refresh_status: last_success, last_error, next_run, imported bar count, missing/gap/duplicate/provider_delay.
    • job_result: import job success/stale/error와 retry/backfill decision, parallel dispatch item별 result.
    • readiness: backtest selector가 scheduled import 결과를 사용할 수 있는지에 대한 headless result.
    • remote_smoke: migration, runtime startup, tick, freshness query, backtest selector/result scenario exit code.
  • 금지:
    • external cron을 1차 scheduler 실행 주체로 사용하지 않는다.
    • OS/systemd timer가 schedule state나 tick 판단을 소유하지 않는다. OS/systemd는 worker process supervision까지만 맡는다.
    • schedule config에 secret 값을 저장하지 않는다.
    • 동일 tick 재실행이 duplicate bars row를 만들지 않는다.
    • provider delay나 gap을 성공으로 조용히 숨기지 않는다.
    • scheduler가 Flutter 화면 구현을 전제하지 않는다.
    • 월봉/분봉 import 확장은 이 Milestone에서 새로 확정하지 않고 지원되는 timeframe만 대상으로 삼는다.

Acceptance Scenarios

ID Milestone Task Given When Then
S01 schedule-config named universe별 provider, selector, timeframe, cadence, timezone, backfill window가 있다. validate/dry-run을 실행한다. next window와 rejected combination이 text/JSONL로 출력된다.
S02 scheduled-runner 원격 worker runtime, idempotent bars upsert, 병렬 수집 대상이 있다. worker 내장 scheduler tick을 2회 실행하고 병렬 수집을 수행한다. external cron 없이 duplicate row 없이 item별 job result와 freshness/readiness output이 남는다.
S03 retry-backfill provider delay, missing, gap fixture가 있다. retry/backfill calculation을 실행한다. stale/error 상태와 backfill window가 stable text/JSONL로 구분된다.
S04 refresh-status success, stale, error 상태가 있다. status scenario를 실행한다. last_success, last_error, next_run, bar count, missing/gap/duplicate/provider_delay가 구분된다.
S05 backtest-readiness scheduler tick이 bars를 적재했다. remote runner에서 backtest matrix 또는 result summary scenario를 실행한다. exit code 0과 result/readiness evidence가 남는다.

Evidence Map

Scenario Required Evidence agent-task 연결 Spec Completion 기대
S01 schedule config validate test와 dry-run text/JSONL agent-task/m-scheduled-market-data-refresh/... schedule-config task와 next window/rejected combination evidence
S02 worker 내장 scheduler tick smoke, bounded parallel dispatch output, bars key 중복 없음, freshness/readiness output agent-task/m-scheduled-market-data-refresh/... scheduled-runner task와 2회 tick idempotency 및 병렬 수집 evidence
S03 missing/gap/provider delay fixture 또는 local smoke agent-task/m-scheduled-market-data-refresh/... retry-backfill task와 stale/error/backfill evidence
S04 success/stale/error status scenario expected JSONL agent-task/m-scheduled-market-data-refresh/... refresh-status task와 status field evidence
S05 remote runner smoke after scheduler tick agent-task/m-scheduled-market-data-refresh/... backtest-readiness task와 exit code 0 evidence

Cross-repo Dependencies

  • 없음

Drift Check

  • Milestone 기능 Task와 Acceptance Scenario가 일치한다.
  • Evidence Map이 plan/code-review/complete.log에서 검증 가능하다.
  • agent-contract를 쓰는 경우 SDD에 계약 원문을 복제하지 않았다.
  • 사용자 리뷰 항목은 user_review_0.log로 해결 기록을 남겼다.

사용자 리뷰 이력

  • user_review_0.log: D01은 services/worker 내장 scheduler loop를 1차 실행 주체로 결정했고, external cron은 사용하지 않으며, worker scheduler는 설정된 한도 안에서 병렬 수집을 지원해야 한다.

작업 컨텍스트

  • 표준선: 운영 기능은 먼저 화면 없이 CLI, YAML scenario, JSONL/text output, fixture, remote smoke로 검증한다.
  • 표준선: scheduled import는 provider 호출과 DB upsert를 idempotent하게 유지하고 동일 tick 재실행이 중복 row를 만들지 않아야 한다.
  • 표준선: services/worker가 데이터 수집, 정규화, backtest, scheduled job처럼 오래 걸리거나 비동기적인 일을 담당한다.
  • 표준선: scheduler의 일정 판단과 상태 관리는 worker 내부에 둔다. OS/systemd는 worker process supervision만 맡고 external cron은 쓰지 않는다.
  • 표준선: worker scheduler는 provider/API 부하를 제어할 수 있는 bounded parallelism으로 여러 수집 작업을 병렬 실행할 수 있어야 한다.
  • 표준선: scheduler config에는 secret 값을 넣지 않고 원격 runtime env/SOPS 주입 경계를 따른다.
  • 표준선: services/api는 client-facing 요청을 worker 실행/조회 경계로 중계하는 control plane으로 남긴다.
  • 후속 SDD: 없음