feat: Korea daily data foundation task and documentation updates

- Add agent-task/m-korea-data-foundation with plans and code reviews
- Update agent-roadmap data-foundation milestones
- Update README files for project and worker service
- Add worker testdata directory
This commit is contained in:
toki 2026-05-29 19:28:03 +09:00
parent 1ac32baf1c
commit 735dafe927
14 changed files with 980 additions and 23 deletions

View file

@ -1,6 +1,6 @@
# ALT
ALT는 개인용 quant system workspace다. 한국장 일봉 기반 MVP에서 시작해, 장기적으로 미국장, 백테스트, 데이터 정규화, 페이퍼 트레이딩, 포트폴리오/리스크 관리, Flutter 클라이언트까지 확장할 수 있는 운영형 구조를 목표로 한다.
ALT는 개인용 quant system workspace다. 주식형 instrument의 venue-agnostic 일봉 데이터 기반에서 시작해, 장기적으로 여러 주식시장, 백테스트, 데이터 정규화, 페이퍼 트레이딩, 포트폴리오/리스크 관리, Flutter 클라이언트까지 확장할 수 있는 운영형 구조를 목표로 한다.
Go 서비스와 도구는 루트 `go.work`로 묶고, Flutter가 web/mobile/desktop 클라이언트 표면을 담당한다. 실시간 통신은 sibling workspace의 `../proto-socket/go`를 transport로 사용하며, ALT 애플리케이션 계약은 `packages/contracts/proto`의 protobuf schema를 원천으로 둔다.
@ -15,6 +15,7 @@ Go 서비스와 도구는 루트 `go.work`로 묶고, Flutter가 web/mobile/desk
- `packages/domain`에는 market/backtest vocabulary와 value object skeleton이 있다.
- PostgreSQL 17과 Redis 7 local stack은 `deployments/local/docker-compose.yml`에 있다.
- 로드맵 진입점은 `agent-roadmap/current.md`다. 일반 작업에서는 전체 `ROADMAP.md`를 매번 읽지 않고, 활성 Milestone 문서를 선택해 읽는다.
- market data의 현재 core 범위는 주식/ETF/지수처럼 주식시장 개념을 공유하는 instrument다. Crypto는 거래 구조가 달라 core 주식 모델에 넣지 않고, 향후 별도 asset-class domain에서 공유 가능한 일부 파이프라인만 재사용할지 검토한다.
## 빠른 시작
@ -87,6 +88,8 @@ AI agent는 작업 전에 루트 지침과 관련 domain rule을 먼저 확인
- `proto-socket`은 transport layer다. ALT application message는 `packages/contracts/proto`에 둔다.
- `packages/domain`은 transport나 persistence detail에 의존하지 않는다.
- market domain은 한국장/KIS 필드에 직접 종속되지 않는 global equity venue-agnostic vocabulary를 우선한다.
- 장별 특수값은 canonical column으로 끌어올리기보다 provider adapter, venue metadata, raw payload, 또는 별도 확장 metadata에 격리한다.
- `services/api`는 socket/session boundary를 담당한다.
- `services/worker`는 오래 걸리거나 비동기적인 데이터/백테스트 작업을 담당한다.
- `apps/client`는 Flutter feature-first 구조를 사용한다.
@ -98,6 +101,8 @@ AI agent는 작업 전에 루트 지침과 관련 domain rule을 먼저 확인
- protobuf generated output은 source schema에서 생성하고 손으로 편집하지 않는다.
- 새 Go module을 추가하면 `go.work`에 등록한다.
- 로컬 secret이나 개인 설정 파일은 커밋하지 않는다.
- KIS 같은 provider credential은 실제 KIS smoke/live 단계에서만 필요하며, 그때도 `.env` 파일에 저장하지 않고 1Password CLI 또는 service account를 통해 실행 시점에 주입한다.
- 현재 KIS adapter mapping 참조는 로컬 cache의 공식 API 샘플 repo를 우선한다. Credential 없는 mock 검증용 샘플은 `services/worker/testdata/providers/kis/` 아래에 secret-free JSON fixture로 둔다.
## 환경 변수
@ -111,10 +116,26 @@ AI agent는 작업 전에 루트 지침과 관련 domain rule을 먼저 확인
| `DATABASE_URL` | worker에서 사용할 PostgreSQL URL. local fallback 있음. | 아니오 |
| `REDIS_URL` | worker에서 사용할 Redis URL. local fallback 있음. | 아니오 |
## Secret 관리
ALT의 provider credential은 실제 provider 호출 단계에서 1Password를 기본 secret source로 둔다. 현재 mock/fixture 테스트 단계에서는 KIS credential이 필요하지 않다. 실제 KIS smoke가 필요해지면 로컬 개발에서는 `op run -- <command>` 형태로 필요한 process에만 값을 주입하고, 자동화 환경에서는 개인 계정이 아닌 1Password service account를 사용한다.
Tracked 문서와 fixture에는 실제 key, token, account number, secret reference를 남기지 않는다. 환경별 secret item 이름, vault 이름, 계정별 운영 메모가 필요하면 git 추적 대상이 아닌 `agent-ops/rules/private/`에 둔다.
## Provider Reference and Fixture
KIS API 참조는 공식 샘플 repo의 로컬 cache를 우선한다. cache 위치와 갱신 방법은 git 추적 제외 private rule인 `agent-ops/rules/private/kis-api-local-cache.md`에 둔다.
Mock 테스트와 adapter mapping에 필요한 샘플은 `services/worker/testdata/providers/kis/` 아래에 secret-free JSON fixture로 둔다. 현재는 Postman export를 필수 입력으로 보지 않는다.
SQLite 보관은 샘플 수가 많아져 검색, 인덱싱, 비교 쿼리가 실제로 필요해진 뒤 검토한다. 초기 adapter mapping과 테스트 fixture에는 diff 가능한 JSON이 기본이다.
## 참고 문서
- `apps/client/README.md`
- `packages/contracts/README.md`
- `services/worker/README.md`
- `services/worker/testdata/providers/kis/README.md`
- `agent-ops/rules/project/rules.md`
- `agent-roadmap/current.md`
- `agent-ops/skills/common/create-roadmap/SKILL.md`

View file

@ -7,7 +7,7 @@
## 목표
한국장 일봉 데이터를 첫 MVP market data로 삼아 provider-neutral import, normalization, persistence 파이프라인을 만든다. 한투/KIS는 초기 provider 후보로 보되, domain model은 한국장에만 종속되지 않게 유지한다.
주식형 instrument의 일봉 데이터를 첫 MVP market data로 삼아 provider-neutral import, normalization, persistence 파이프라인을 만든다. 한국장/KIS는 첫 provider와 venue 검증 단위로 보되, domain model은 특정 장이나 KIS 응답 필드에 종속되지 않게 유지한다. Crypto는 현재 core 주식 모델 범위에서 제외하고, 향후 별도 asset-class domain에서 공유 가능한 일부 파이프라인만 재사용할지 검토한다.
## 상태
@ -15,45 +15,49 @@
## 구현 잠금
- 상태: 잠금
- 결정 필요: 아래 체크리스트
- [ ] MVP에서 우선 수집할 한국장 universe를 watchlist, KOSPI/KOSDAQ 전체, 또는 특정 섹터 중 무엇으로 둘지 결정한다.
- [ ] KIS credential과 계정 환경을 local secret/env 기준으로 어떻게 제공할지 결정한다.
- 상태: 해제
- 결정 필요: 없음
- 확정된 기준:
- 주식/ETF/지수처럼 주식시장 개념을 공유하는 instrument를 venue-agnostic core 대상으로 둔다.
- Crypto는 현재 core 주식 모델에 포함하지 않고, 나중에 별도 asset-class domain으로 분리 검토한다.
- Universe는 watchlist, exchange-wide, sector-like selector를 갈아 끼울 수 있는 provider-neutral selector로 설계하고, 특정 selector를 instrument identity에 박지 않는다.
- 현재 검증은 KIS credential 없는 mock/fixture 테스트를 우선한다.
- 실제 KIS smoke 단계에서만 credential을 준비하며, 그때도 `.env`가 아니라 1Password CLI 또는 service account 기반 runtime injection으로 제공한다.
- KIS adapter mapping 참조는 로컬 cache의 공식 API 샘플 repo를 우선하고, Postman export는 필수 입력으로 보지 않는다.
- KIS mock/sample 데이터는 secret을 제거한 JSON artifact로 보관하고, SQLite는 대량 fixture 검색이 필요해진 뒤 검토한다.
## 범위
- KRX/Korea daily bar import pipeline
- provider symbol mapping
- KRX/Korea daily bar import pipeline as the first venue path
- venue-agnostic equity instrument identity and provider symbol mapping
- provider-neutral universe selector
- normalized instrument/bar storage
- trading calendar/timezone/currency 기본 처리
- KIS adapter boundary
- local KIS API sample repo reference handling
- sanitized mock/sample response artifact handling
- deferred 1Password-injected secret boundary for live smoke
- fixture 또는 mock provider를 통한 credential 없는 검증 경로
## 필수 기능
## 기능
### Epic: [market-data] Korea daily market data
한국장 일봉 데이터의 provider-neutral 수집, 정규화, 저장, 검증 흐름을 묶는다.
- [ ] [instrument-map] provider symbol과 ALT instrument identity를 매핑한다.
- [ ] [daily-bars] 한국장 일봉 OHLCV를 normalized bar 모델로 저장한다.
- [ ] [instrument-map] provider symbol과 ALT의 venue-agnostic equity instrument identity를 매핑한다.
- [ ] [universe-selector] watchlist, exchange-wide, sector-like 입력을 provider-neutral universe selector로 다룬다.
- [ ] [daily-bars] 한국장 일봉 OHLCV를 normalized bar 모델로 저장한다. 검증: 선택된 equity universe의 일봉 입력이 저장소에 들어가고, 같은 입력을 다시 import해도 중복/갱신 정책이 일관된다.
- [ ] [calendar-rules] `Asia/Seoul`, KRX, KRW 기준의 최소 calendar/currency 처리를 갖는다.
- [ ] [kis-adapter] KIS provider adapter 경계가 worker 내부에 격리된다.
- [ ] [kis-adapter] KIS provider adapter 경계가 worker 내부에 격리된다. 검증: 로컬 cache의 KIS API 샘플 repo와 sanitized mock/sample response를 기준으로 request/auth/response mapping을 확정할 수 있고 secret 값은 저장하지 않는다.
- [ ] [mock-provider] KIS credential 없이도 pipeline을 검증할 fixture/mock provider가 있다.
- [ ] [data-check] import 결과를 재현 가능하게 검증하는 테스트 또는 CLI/smoke 명령이 있다.
## 완료 기준
- [ ] 선택된 한국장 universe의 일봉 데이터가 저장소에 들어간다.
- [ ] 같은 입력을 다시 import해도 중복/갱신 정책이 일관된다.
- [ ] normalized data가 backtest milestone에서 소비 가능한 형태로 조회된다.
- [ ] `bin/test`와 관련 worker 검증이 통과한다.
- [ ] [data-check] import 결과를 재현 가능하게 검증하는 테스트 또는 CLI/smoke 명령이 있다. 검증: normalized data가 backtest milestone에서 소비 가능한 형태로 조회되고 `bin/test`와 관련 worker 검증이 통과한다.
## 완료 리뷰
- 상태: 없음
- 요청일: 없음
- 완료 근거: 아직 필수 기능과 완료 기준이 충족되지 않았다.
- 완료 근거: 아직 기능 Task와 각 Task의 검증 조건이 충족되지 않았다.
- 리뷰 필요:
- [ ] 사용자가 완료 결과를 확인했다
- [ ] archive 이동을 승인했다
@ -65,11 +69,16 @@
- 분봉/틱/실시간 streaming
- 실거래 주문 API
- 고급 corporate action adjustment
- crypto/디지털 자산 core model 통합
- 실제 KIS secret 값 저장 또는 문서화
## 작업 컨텍스트
- 관련 경로: `services/worker/`, `packages/domain/market/`, `packages/contracts/proto/alt/v1/market.proto`
- 관련 경로: `services/worker/`, `services/worker/testdata/providers/kis/`, `packages/domain/market/`, `packages/contracts/proto/alt/v1/market.proto`
- 표준선(선택): 첫 데이터 단위는 일봉이고, 구조는 분봉/실시간 확장을 막지 않는다.
- 표준선(선택): canonical model은 global equity venue-agnostic vocabulary를 우선하고, 한국장/KIS 특수 필드는 adapter, venue metadata, raw payload, 또는 명시적 extension metadata에 격리한다.
- 표준선(선택): KIS API mapping은 로컬 cache의 공식 샘플 repo를 먼저 보고, mock/sample artifact는 sanitized JSON을 기본으로 둔다. SQLite는 대량 fixture 검색이나 쿼리 비교가 필요해질 때 도입한다.
- 표준선(선택): mock/fixture 테스트에는 KIS credential이 필요 없다. 실제 KIS smoke 단계에서만 1Password CLI 또는 service account로 실행 시점에 주입하며 `.env`에 저장하지 않는다.
- 선행 작업: Persistence and Worker Backbone
- 후속 작업: Backtest Engine Baseline
- 확인 필요: MVP universe와 KIS credential 제공 방식
- 확인 필요: mock 테스트에 사용할 최소 KIS daily bar fixture와 expected normalized bar 사례

View file

@ -0,0 +1,109 @@
<!-- task=m-korea-daily-data-foundation/01_provider_foundation plan=0 tag=KIS_FOUNDATION -->
# Code Review Reference - KIS_FOUNDATION
> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.**
> The task is NOT complete until every implementation-owned section below is filled in.
> Complete the `구현 체크리스트`; the final checklist item is mandatory before saving.
> Fill implementation-owned sections, then stop with active files in place and report ready for review.
> If implementation is blocked by a user-only decision, external environment prerequisite, or scope conflict, fill `사용자 리뷰 요청` with evidence and stop with active files in place; code-review decides whether to write `USER_REVIEW.md`.
> Finalization (`코드리뷰 결과`, log rename, `complete.log`, archive moves, `코드리뷰 전용 체크리스트`) is review-agent-only, even after compaction/resume.
> Follow the ownership table at the bottom of this file for which sections you own.
## 개요
date=2026-05-29
task=m-korea-daily-data-foundation/01_provider_foundation, plan=0, tag=KIS_FOUNDATION
## 이 파일을 읽는 리뷰 에이전트에게
> **[REVIEW AGENT ONLY]** 아래 종결 절차는 코드리뷰 에이전트 전용이다. 구현 에이전트는 이 섹션을 실행하지 않는다.
각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.
리뷰 완료는 plan skill의 code-review 절차를 따른다.
---
## 구현 항목별 완료 여부
| 항목 | 완료 여부 |
|------|---------|
| [KIS_FOUNDATION-1] Domain Selector Vocabulary | [ ] |
| [KIS_FOUNDATION-2] KIS Fixture Decoder | [ ] |
| [KIS_FOUNDATION-3] KIS Row Normalization | [ ] |
## 구현 체크리스트
- [ ] `packages/domain/market`에 provider-neutral universe selector와 provider symbol vocabulary를 추가하고 unit test를 작성한다.
- [ ] `services/worker/internal/providers/kis` 또는 동등한 worker-owned provider package에 KIS daily chart fixture decoder와 normalization 함수를 추가한다.
- [ ] KIS `output2` rows를 `market.Bar`로 변환할 때 `Asia/Seoul`, `KRX`, `KRW`, `TimeframeDaily` 기본선을 테스트한다.
- [ ] fixture JSON 전체가 secret-free이고 parser test에 사용되는지 검증한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
## 코드리뷰 전용 체크리스트
> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다.
- [ ] `코드리뷰 결과``PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
- [ ] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
- [ ] active `CODE_REVIEW-*-G??.md``code_review_cloud_G07_N.log`로 아카이브한다.
- [ ] active `PLAN-*-G??.md``plan_cloud_G07_M.log`로 아카이브한다.
- [ ] PASS이면 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
- [ ] PASS이면 active task 디렉터리를 archive로 이동한다.
- [ ] PASS이고 task group이 `m-<milestone-slug>`이면 완료 이벤트 메타데이터를 보고하고 roadmap 수정은 런타임에 맡긴다.
- [ ] WARN/FAIL이면 다음 active plan/review 또는 `USER_REVIEW.md`를 작성한다.
## 계획 대비 변경 사항
_구현 에이전트가 계획과 다르게 구현한 부분을 이유와 함께 기록한다._
## 주요 설계 결정
_구현 에이전트가 주요 설계 결정 사항을 기록한다._
## 사용자 리뷰 요청
_기본값은 `없음`이다. 구현 중 사용자 결정, 외부 환경 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다. code-review가 이 내용을 검증해 `USER_REVIEW.md`를 작성한다._
- 상태: 없음
- 사유 유형: 없음
- 결정 필요: 없음
- 차단 근거: 없음
- 실행한 검증/명령: 없음
- 재개 조건: 없음
## 리뷰어를 위한 체크포인트
- domain package가 worker/protobuf/storage dependency를 새로 갖지 않는지 확인한다.
- KIS fixture normalization이 KRX/KRW/Asia-Seoul 일봉 기준을 테스트로 고정하는지 확인한다.
- secret-like 값이 fixture에 들어가지 않았는지 확인한다.
## 검증 결과
_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._
### KIS_FOUNDATION-1 중간 검증
```bash
$ cd packages/domain && go test -count=1 ./market
```
### KIS_FOUNDATION-2 중간 검증
```bash
$ cd services/worker && go test -count=1 ./internal/providers/kis
```
### KIS_FOUNDATION-3 중간 검증
```bash
$ cd services/worker && go test -count=1 ./internal/providers/kis
```
### 최종 검증
```bash
$ cd packages/domain && go test -count=1 ./...
$ cd services/worker && go test -count=1 ./internal/providers/kis
```
---
> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section: completion table, implementation checklist, changes from plan, design decisions, and verification output?**

View file

@ -0,0 +1,184 @@
<!-- task=m-korea-daily-data-foundation/01_provider_foundation plan=0 tag=KIS_FOUNDATION -->
# Plan - KIS Provider Foundation
## 이 파일을 읽는 구현 에이전트에게
`CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채우는 것이 구현의 마지막 단계다. 구현 중 사용자 결정, 외부 환경, 범위 충돌로 막히면 active review stub의 `사용자 리뷰 요청`에 정확한 근거를 남기고 멈춘다. `USER_REVIEW.md`, `complete.log`, archive 이동은 code-review 전용이다.
## 배경
Korea Daily Data Foundation은 KIS credential 없이 mock/fixture 기반으로 먼저 검증한다. 현재 domain model은 instrument와 bar만 있고 provider selector, KIS daily response normalization, KRX date/currency 기본선이 없다. 이 작업은 후속 import/storage pipeline이 소비할 안정적인 provider boundary를 만든다.
## 사용자 리뷰 요청 흐름
구현 중 blocker는 active `CODE_REVIEW-cloud-G07.md``사용자 리뷰 요청` 섹션에 기록한다. code-review가 그 요청을 검증하고 실제 `USER_REVIEW.md` 작성 여부를 결정한다.
## 분석 결과
### 읽은 파일
- `agent-roadmap/current.md`
- `agent-roadmap/phase/data-foundation/PHASE.md`
- `agent-roadmap/phase/data-foundation/milestones/korea-daily-data-foundation.md`
- `agent-ops/rules/project/domain/domain-model/rules.md`
- `agent-ops/rules/project/domain/worker/rules.md`
- `packages/domain/market/types.go`
- `services/worker/internal/storage/ports.go`
- `services/worker/internal/storage/postgres/mapping.go`
- `services/worker/internal/storage/postgres/mapping_test.go`
- `services/worker/testdata/providers/kis/README.md`
- `services/worker/testdata/providers/kis/daily_itemchartprice_request.sample.json`
- `services/worker/testdata/providers/kis/daily_itemchartprice_response.sample.json`
- `services/worker/testdata/providers/kis/daily_bars_normalized.expected.json`
- `.agent-cache/koreainvestment/open-trading-api/examples_llm/domestic_stock/inquire_daily_itemchartprice/inquire_daily_itemchartprice.py`
- `.agent-cache/koreainvestment/open-trading-api/examples_llm/domestic_stock/inquire_daily_itemchartprice/chk_inquire_daily_itemchartprice.py`
### 테스트 커버리지 공백
- Provider-neutral universe selector: 기존 테스트 없음. 새 domain unit test 필요.
- KIS daily chart response normalization: 기존 테스트 없음. 새 worker provider fixture test 필요.
- KRX daily timestamp/currency default: 기존 테스트 없음. 새 worker provider fixture test 필요.
### 심볼 참조
none. 이 계획은 신규 타입/패키지 추가를 우선하며 기존 심볼 rename/remove는 하지 않는다.
### 분할 판단
Split decision policy를 먼저 평가했다. 공유 foundation 없이 import/storage/job을 바로 만들면 후속 작업이 provider API를 추정하게 되므로 분할한다.
- 공통 task group: `m-korea-daily-data-foundation`
- 현재 subtask: `01_provider_foundation`, 의존 없음
- 후속 subtask: `02+01_import_storage_pipeline`, `01_provider_foundation` 완료 필요
- 후속 subtask: `03+01,02_data_check_smoke`, `01_provider_foundation``02+01_import_storage_pipeline` 완료 필요
### 범위 결정 근거
실제 KIS HTTP 호출, credential/1Password wiring, PostgreSQL migration, CLI smoke는 제외한다. 이 작업은 provider-neutral selector와 KIS mock fixture normalization까지만 닫는다.
### 빌드 등급
build=`cloud-G07`, review=`cloud-G07`. domain과 worker 경계를 새로 만들고 후속 storage 작업의 API가 되므로 cloud review가 필요하다.
## 구현 체크리스트
- [ ] `packages/domain/market`에 provider-neutral universe selector와 provider symbol vocabulary를 추가하고 unit test를 작성한다.
- [ ] `services/worker/internal/providers/kis` 또는 동등한 worker-owned provider package에 KIS daily chart fixture decoder와 normalization 함수를 추가한다.
- [ ] KIS `output2` rows를 `market.Bar`로 변환할 때 `Asia/Seoul`, `KRX`, `KRW`, `TimeframeDaily` 기본선을 테스트한다.
- [ ] fixture JSON 전체가 secret-free이고 parser test에 사용되는지 검증한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
### [KIS_FOUNDATION-1] Domain Selector Vocabulary
문제: [types.go](/config/workspace/alt/packages/domain/market/types.go:37)는 `Instrument.ProviderSymbols`만 있고 watchlist, exchange-wide, sector-like selector를 표현할 타입이 없다.
해결 방법: `packages/domain/market/types.go``Provider`, `UniverseSelectorKind`, `UniverseSelector`를 추가한다. 기존 `Instrument.ProviderSymbols map[string]string`은 유지하고, 새 타입은 provider-neutral request vocabulary로만 둔다.
Before:
```go
type Instrument struct {
ID InstrumentID
Market Market
Venue Venue
Symbol string
Name string
Currency Currency
ProviderSymbols map[string]string
}
```
After:
```go
type Provider string
const ProviderKIS Provider = "kis"
type UniverseSelectorKind string
const (
UniverseSelectorWatchlist UniverseSelectorKind = "watchlist"
UniverseSelectorExchange UniverseSelectorKind = "exchange"
UniverseSelectorSector UniverseSelectorKind = "sector"
)
type UniverseSelector struct {
Kind UniverseSelectorKind
Market Market
Venue Venue
Symbols []string
Name string
}
```
수정 파일 및 체크리스트:
- [ ] `packages/domain/market/types.go`에 타입/상수 추가
- [ ] `packages/domain/market/types_test.go` 추가
테스트 작성: `TestUniverseSelectorVocabulary`를 추가해 watchlist/exchange/sector 값이 안정적인 string 값을 갖는지 확인한다.
중간 검증:
```bash
cd packages/domain && go test -count=1 ./market
```
### [KIS_FOUNDATION-2] KIS Fixture Decoder
문제: [daily_itemchartprice_response.sample.json](/config/workspace/alt/services/worker/testdata/providers/kis/daily_itemchartprice_response.sample.json:1)은 fixture로 존재하지만 이를 KIS response shape로 decode하는 worker package가 없다.
해결 방법: worker 내부에 `internal/providers/kis` package를 만들고 KIS daily item chart request/response structs, fixture loader test, response validation을 둔다.
수정 파일 및 체크리스트:
- [ ] `services/worker/internal/providers/kis/daily_itemchartprice.go` 추가
- [ ] `services/worker/internal/providers/kis/daily_itemchartprice_test.go` 추가
- [ ] fixture path는 `services/worker/testdata/providers/kis/*.json`을 사용
테스트 작성: `TestLoadDailyItemChartPriceFixture`에서 request endpoint/TR ID와 response `output1`, `output2` row count를 검증한다.
중간 검증:
```bash
cd services/worker && go test -count=1 ./internal/providers/kis
```
### [KIS_FOUNDATION-3] KIS Row Normalization
문제: KIS row의 `stck_bsop_date`, `stck_oprc`, `stck_hgpr`, `stck_lwpr`, `stck_clpr`, `acml_vol`을 ALT `market.Bar`로 바꾸는 규칙이 없다.
해결 방법: `NormalizeDailyBars`를 추가해 KIS rows를 `market.Bar`로 변환한다. 날짜는 `Asia/Seoul` 자정, currency는 `KRW`, timeframe은 `1d`, instrument id는 provider symbol metadata에서 받은 `KRX:<symbol>`을 사용한다.
수정 파일 및 체크리스트:
- [ ] `services/worker/internal/providers/kis/daily_itemchartprice.go`에 normalization 함수 추가
- [ ] `services/worker/internal/providers/kis/daily_itemchartprice_test.go`에 expected normalized fixture 대조 추가
테스트 작성: `TestNormalizeDailyItemChartPriceBars`에서 [daily_bars_normalized.expected.json](/config/workspace/alt/services/worker/testdata/providers/kis/daily_bars_normalized.expected.json:1)의 두 bar와 완전 대조한다.
중간 검증:
```bash
cd services/worker && go test -count=1 ./internal/providers/kis
```
## 수정 파일 요약
| 파일 | 항목 |
|------|------|
| `packages/domain/market/types.go` | KIS_FOUNDATION-1 |
| `packages/domain/market/types_test.go` | KIS_FOUNDATION-1 |
| `services/worker/internal/providers/kis/daily_itemchartprice.go` | KIS_FOUNDATION-2, KIS_FOUNDATION-3 |
| `services/worker/internal/providers/kis/daily_itemchartprice_test.go` | KIS_FOUNDATION-2, KIS_FOUNDATION-3 |
## 최종 검증
```bash
cd packages/domain && go test -count=1 ./...
cd services/worker && go test -count=1 ./internal/providers/kis
```
모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.

View file

@ -0,0 +1,92 @@
<!-- task=m-korea-daily-data-foundation/02+01_import_storage_pipeline plan=0 tag=KIS_IMPORT -->
# Code Review Reference - KIS_IMPORT
> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.**
> Complete implementation-owned sections, then stop with active files in place and report ready for review.
> Finalization is review-agent-only.
## 개요
date=2026-05-29
task=m-korea-daily-data-foundation/02+01_import_storage_pipeline, plan=0, tag=KIS_IMPORT
## 이 파일을 읽는 리뷰 에이전트에게
> **[REVIEW AGENT ONLY]** 종결 절차는 코드리뷰 에이전트 전용이다.
---
## 구현 항목별 완료 여부
| 항목 | 완료 여부 |
|------|---------|
| [KIS_IMPORT-1] Import Service | [ ] |
| [KIS_IMPORT-2] Idempotent Re-import | [ ] |
| [KIS_IMPORT-3] Worker Job Boundary | [ ] |
## 구현 체크리스트
- [ ] `01_provider_foundation``complete.log`를 확인하고 provider API를 그대로 사용한다.
- [ ] worker 내부에 daily bar import service를 추가해 selector -> instruments/bars -> store upsert 흐름을 구현한다.
- [ ] 같은 fixture를 두 번 import해도 instrument/bar 결과가 중복 없이 갱신되는 test를 작성한다.
- [ ] `KindImportDailyBars` payload decode와 handler registration을 실제 import service에 연결할 수 있게 분리한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
## 코드리뷰 전용 체크리스트
> **[REVIEW AGENT ONLY]** 구현 에이전트는 수정하지 않는다.
- [ ] `코드리뷰 결과`에 판정을 append한다.
- [ ] active plan/review를 log로 아카이브한다.
- [ ] PASS이면 `complete.log` 작성 후 task directory를 archive로 이동한다.
- [ ] PASS이고 task group이 `m-<milestone-slug>`이면 완료 이벤트 메타데이터를 보고한다.
- [ ] WARN/FAIL이면 다음 active plan/review 또는 `USER_REVIEW.md`를 작성한다.
## 계획 대비 변경 사항
_구현 에이전트가 계획과 다르게 구현한 부분을 이유와 함께 기록한다._
## 주요 설계 결정
_구현 에이전트가 주요 설계 결정 사항을 기록한다._
## 사용자 리뷰 요청
_기본값은 `없음`이다. 구현 중 사용자 결정, 외부 환경 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다._
- 상태: 없음
- 사유 유형: 없음
- 결정 필요: 없음
- 차단 근거: 없음
- 실행한 검증/명령: 없음
- 재개 조건: 없음
## 리뷰어를 위한 체크포인트
- `01_provider_foundation/complete.log` 확인 없이 구현이 시작되지 않았는지 확인한다.
- Import service가 provider와 storage를 느슨하게 결합했는지 확인한다.
- 같은 fixture 재import가 중복을 만들지 않는지 테스트 출력으로 확인한다.
## 검증 결과
### KIS_IMPORT-1 중간 검증
```bash
$ cd services/worker && go test -count=1 ./internal/marketdata/importer
```
### KIS_IMPORT-2 중간 검증
```bash
$ cd services/worker && go test -count=1 ./internal/marketdata/importer
```
### KIS_IMPORT-3 중간 검증
```bash
$ cd services/worker && go test -count=1 ./internal/jobs ./internal/marketdata/importer
```
### 최종 검증
```bash
$ test -f agent-task/m-korea-daily-data-foundation/01_provider_foundation/complete.log
$ cd services/worker && go test -count=1 ./internal/jobs ./internal/marketdata/importer ./internal/storage/...
```

View file

@ -0,0 +1,141 @@
<!-- task=m-korea-daily-data-foundation/02+01_import_storage_pipeline plan=0 tag=KIS_IMPORT -->
# Plan - Daily Bar Import Storage Pipeline
## 이 파일을 읽는 구현 에이전트에게
이 subtask는 `agent-task/m-korea-daily-data-foundation/01_provider_foundation/complete.log`가 생긴 뒤 시작한다. 구현 완료 전 active `CODE_REVIEW-cloud-G07.md`의 구현 에이전트 소유 섹션을 채운다. blocker가 있으면 review stub의 `사용자 리뷰 요청`에 근거를 기록하고 멈춘다.
## 배경
Foundation provider가 KIS mock rows를 `market.Instrument``market.Bar`로 만들면, worker는 이를 idempotent하게 저장하는 import pipeline이 필요하다. 현재 storage port는 instrument/bar upsert를 제공하지만 import orchestration, selector payload, idempotent 검증이 없다.
## 사용자 리뷰 요청 흐름
구현 중 blocker는 active `CODE_REVIEW-cloud-G07.md``사용자 리뷰 요청` 섹션에 기록한다. code-review가 검증과 종료 처리를 소유한다.
## 분석 결과
### 읽은 파일
- `services/worker/internal/storage/ports.go`
- `services/worker/internal/storage/postgres/store.go`
- `services/worker/internal/storage/postgres/mapping.go`
- `services/worker/internal/storage/postgres/queries/queries.sql`
- `services/worker/internal/jobs/job.go`
- `services/worker/internal/jobs/builtin.go`
- `services/worker/internal/jobs/runner.go`
- `services/worker/internal/jobs/runner_test.go`
- `services/worker/testdata/providers/kis/*.json`
- `agent-task/m-korea-daily-data-foundation/01_provider_foundation/PLAN-cloud-G07.md`
### 테스트 커버리지 공백
- Import orchestration: 기존 테스트 없음. in-memory store와 mock provider test 필요.
- Idempotent re-import: storage upsert는 있으나 import-level 중복/갱신 정책 테스트 없음.
- Worker job payload: built-in handler는 placeholder라 payload decode test 없음.
### 심볼 참조
none. 기존 job kind는 유지하고 handler wiring을 보강한다.
### 분할 판단
`02+01_import_storage_pipeline`은 directory name상 `01_provider_foundation`에 의존한다. Provider API와 normalization이 완료되어야 import service가 안정적으로 컴파일된다.
### 범위 결정 근거
PostgreSQL schema 변경은 우선 제외한다. 기존 `instruments``bars` 테이블, `UpsertInstrument`, `UpsertBar`로 idempotent 저장을 검증한다. 실제 KIS HTTP client와 credential wiring도 제외한다.
### 빌드 등급
build=`cloud-G07`, review=`cloud-G07`. worker orchestration과 storage idempotency를 다루므로 storage/behavior review가 필요하다.
## 의존 관계 및 구현 순서
1. `agent-task/m-korea-daily-data-foundation/01_provider_foundation/complete.log` 확인
2. import service 구현
3. job payload/handler wiring 구현
4. worker tests 실행
## 구현 체크리스트
- [ ] `01_provider_foundation``complete.log`를 확인하고 provider API를 그대로 사용한다.
- [ ] worker 내부에 daily bar import service를 추가해 selector -> instruments/bars -> store upsert 흐름을 구현한다.
- [ ] 같은 fixture를 두 번 import해도 instrument/bar 결과가 중복 없이 갱신되는 test를 작성한다.
- [ ] `KindImportDailyBars` payload decode와 handler registration을 실제 import service에 연결할 수 있게 분리한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
### [KIS_IMPORT-1] Import Service
문제: [ports.go](/config/workspace/alt/services/worker/internal/storage/ports.go:11)는 store interface만 있고 provider output을 저장하는 orchestration이 없다.
해결 방법: `services/worker/internal/marketdata/importer` 또는 동등한 worker-owned package를 추가한다. `Importer.ImportDailyBars(ctx, selector)`는 provider에서 instruments/bars를 받고 `InstrumentStore.UpsertInstrument`, `BarStore.UpsertBar`를 호출한다.
수정 파일 및 체크리스트:
- [ ] `services/worker/internal/marketdata/importer/importer.go` 추가
- [ ] `services/worker/internal/marketdata/importer/importer_test.go` 추가
테스트 작성: fake provider와 in-memory stores로 instrument 1개, bar 2개가 저장되는지 검증한다.
중간 검증:
```bash
cd services/worker && go test -count=1 ./internal/marketdata/importer
```
### [KIS_IMPORT-2] Idempotent Re-import
문제: [queries.sql](/config/workspace/alt/services/worker/internal/storage/postgres/queries/queries.sql:21)의 `UpsertBar`는 DB upsert를 제공하지만 import service가 같은 fixture를 다시 처리할 때 정책이 유지되는지 테스트가 없다.
해결 방법: importer test에서 같은 provider result를 두 번 import한다. in-memory store는 primary key `(instrument_id,timeframe,timestamp)`로 replace하도록 구현하고 최종 bar 수가 2개인지 확인한다.
수정 파일 및 체크리스트:
- [ ] `services/worker/internal/marketdata/importer/importer_test.go`에 재실행 test 추가
테스트 작성: `TestImporterIsIdempotentForSameDailyBars`.
중간 검증:
```bash
cd services/worker && go test -count=1 ./internal/marketdata/importer
```
### [KIS_IMPORT-3] Worker Job Boundary
문제: [builtin.go](/config/workspace/alt/services/worker/internal/jobs/builtin.go:11)는 `import_daily_bars`를 log-only placeholder로 처리한다.
해결 방법: 기존 `RegisterBuiltins`는 placeholder count test를 유지하되, 실제 import handler를 등록할 수 있는 별도 function 또는 option을 추가한다. payload는 provider, selector kind, symbols/date range를 포함하는 struct로 decode한다.
수정 파일 및 체크리스트:
- [ ] `services/worker/internal/jobs/builtin.go` 또는 새 `marketdata_jobs.go`에 import handler registration 추가
- [ ] `services/worker/internal/jobs/runner_test.go` 또는 새 test에 payload decode/dispatch 검증 추가
테스트 작성: `TestRegisterDailyBarImportHandlerDispatchesImporter`.
중간 검증:
```bash
cd services/worker && go test -count=1 ./internal/jobs ./internal/marketdata/importer
```
## 수정 파일 요약
| 파일 | 항목 |
|------|------|
| `services/worker/internal/marketdata/importer/importer.go` | KIS_IMPORT-1, KIS_IMPORT-2 |
| `services/worker/internal/marketdata/importer/importer_test.go` | KIS_IMPORT-1, KIS_IMPORT-2 |
| `services/worker/internal/jobs/builtin.go` 또는 새 job file | KIS_IMPORT-3 |
| `services/worker/internal/jobs/*_test.go` | KIS_IMPORT-3 |
## 최종 검증
```bash
test -f agent-task/m-korea-daily-data-foundation/01_provider_foundation/complete.log
cd services/worker && go test -count=1 ./internal/jobs ./internal/marketdata/importer ./internal/storage/...
```
모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.

View file

@ -0,0 +1,87 @@
<!-- task=m-korea-daily-data-foundation/03+01,02_data_check_smoke plan=0 tag=KIS_SMOKE -->
# Code Review Reference - KIS_SMOKE
> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.**
> Complete implementation-owned sections, then stop with active files in place and report ready for review.
> Finalization is review-agent-only.
## 개요
date=2026-05-29
task=m-korea-daily-data-foundation/03+01,02_data_check_smoke, plan=0, tag=KIS_SMOKE
## 이 파일을 읽는 리뷰 에이전트에게
> **[REVIEW AGENT ONLY]** 종결 절차는 코드리뷰 에이전트 전용이다.
---
## 구현 항목별 완료 여부
| 항목 | 완료 여부 |
|------|---------|
| [KIS_SMOKE-1] Mock Data Check Command | [ ] |
| [KIS_SMOKE-2] Whole Worker Regression | [ ] |
## 구현 체크리스트
- [ ] 선행 `01_provider_foundation``02+01_import_storage_pipeline``complete.log`를 확인한다.
- [ ] mock fixture import와 normalized bar 조회를 실행하는 CLI 또는 worker command를 추가한다.
- [ ] command output이 instrument count, bar count, first/last timestamp를 안정적으로 출력하도록 테스트한다.
- [ ] `bin/test` 또는 focused worker command가 credential 없이 통과함을 검증한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
## 코드리뷰 전용 체크리스트
> **[REVIEW AGENT ONLY]** 구현 에이전트는 수정하지 않는다.
- [ ] `코드리뷰 결과`에 판정을 append한다.
- [ ] active plan/review를 log로 아카이브한다.
- [ ] PASS이면 `complete.log` 작성 후 task directory를 archive로 이동한다.
- [ ] PASS이고 task group이 `m-<milestone-slug>`이면 완료 이벤트 메타데이터를 보고한다.
- [ ] WARN/FAIL이면 다음 active plan/review 또는 `USER_REVIEW.md`를 작성한다.
## 계획 대비 변경 사항
_구현 에이전트가 계획과 다르게 구현한 부분을 이유와 함께 기록한다._
## 주요 설계 결정
_구현 에이전트가 주요 설계 결정 사항을 기록한다._
## 사용자 리뷰 요청
_기본값은 `없음`이다. 구현 중 사용자 결정, 외부 환경 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다._
- 상태: 없음
- 사유 유형: 없음
- 결정 필요: 없음
- 차단 근거: 없음
- 실행한 검증/명령: 없음
- 재개 조건: 없음
## 리뷰어를 위한 체크포인트
- 실제 KIS credential/1Password가 smoke command에 필요하지 않은지 확인한다.
- stdout contract가 안정적이고 테스트로 고정되는지 확인한다.
- `bin/test` 결과가 실제 출력으로 기록되는지 확인한다.
## 검증 결과
### KIS_SMOKE-1 중간 검증
```bash
$ cd apps/cli && go test -count=1 ./...
```
### KIS_SMOKE-2 중간 검증
```bash
$ bin/test
```
### 최종 검증
```bash
$ test -f agent-task/m-korea-daily-data-foundation/01_provider_foundation/complete.log
$ test -f agent-task/m-korea-daily-data-foundation/02+01_import_storage_pipeline/complete.log
$ bin/test
```

View file

@ -0,0 +1,122 @@
<!-- task=m-korea-daily-data-foundation/03+01,02_data_check_smoke plan=0 tag=KIS_SMOKE -->
# Plan - Mock Data Check Smoke
## 이 파일을 읽는 구현 에이전트에게
이 subtask는 `01_provider_foundation``02+01_import_storage_pipeline` 완료 후 시작한다. 구현 완료 전 active review stub의 구현 에이전트 소유 섹션을 채운다. 실제 KIS credential이나 1Password 준비를 요구하지 않는다.
## 배경
Milestone의 `data-check`는 normalized data가 backtest milestone에서 소비 가능한 형태로 조회되고 관련 검증이 통과해야 한다. 현재는 mock fixture 기반 흐름을 사람이 반복 실행할 수 있는 smoke 표면이 없다.
## 사용자 리뷰 요청 흐름
구현 중 blocker는 active `CODE_REVIEW-cloud-G07.md``사용자 리뷰 요청` 섹션에 기록한다. code-review가 검증과 종료 처리를 소유한다.
## 분석 결과
### 읽은 파일
- `bin/dev`
- `bin/test`
- `bin/worker-storage-check`
- `apps/cli/cmd/alt/main.go`
- `services/worker/cmd/alt-worker/main.go`
- `services/worker/internal/jobs/builtin.go`
- `services/worker/testdata/providers/kis/*.json`
- `agent-task/m-korea-daily-data-foundation/01_provider_foundation/PLAN-cloud-G07.md`
- `agent-task/m-korea-daily-data-foundation/02+01_import_storage_pipeline/PLAN-cloud-G07.md`
### 테스트 커버리지 공백
- End-to-end mock import command: 기존 없음. CLI 또는 worker command test 필요.
- Human-runnable data check output: 기존 없음. stdout contract test 필요.
- Full worker package regression after import pipeline: 기존 `bin/test`는 있으나 feature-specific smoke 없음.
### 심볼 참조
none. 기존 `bin/test`와 storage check는 유지한다.
### 분할 판단
`03+01,02_data_check_smoke`는 directory name상 `01_provider_foundation``02+01_import_storage_pipeline`에 의존한다. Smoke command는 실제 provider/import API가 완료된 뒤 작성해야 한다.
### 범위 결정 근거
실제 KIS network smoke, 1Password credential injection, Postgres Docker orchestration은 제외한다. 이 작업은 mock fixture를 읽어 normalized daily bar 조회 가능성을 보여주는 local command/test만 만든다.
### 빌드 등급
build=`cloud-G07`, review=`cloud-G07`. terminal-facing smoke output과 bin/CLI behavior가 포함된다.
## 의존 관계 및 구현 순서
1. `agent-task/m-korea-daily-data-foundation/01_provider_foundation/complete.log` 확인
2. `agent-task/m-korea-daily-data-foundation/02+01_import_storage_pipeline/complete.log` 확인
3. mock smoke command 구현
4. full verification 실행
## 구현 체크리스트
- [ ] 선행 `01_provider_foundation``02+01_import_storage_pipeline``complete.log`를 확인한다.
- [ ] mock fixture import와 normalized bar 조회를 실행하는 CLI 또는 worker command를 추가한다.
- [ ] command output이 instrument count, bar count, first/last timestamp를 안정적으로 출력하도록 테스트한다.
- [ ] `bin/test` 또는 focused worker command가 credential 없이 통과함을 검증한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
### [KIS_SMOKE-1] Mock Data Check Command
문제: [apps/cli main](/config/workspace/alt/apps/cli/cmd/alt/main.go:8)은 `version` 외에 운영자 command가 없고, worker import 결과를 재현 가능하게 확인할 표면도 없다.
해결 방법: 가장 작은 표면으로 `apps/cli` 또는 `services/worker/cmd`에 mock data check command를 추가한다. command는 KIS fixture를 import pipeline에 넣고 in-memory store에서 bars를 조회한 뒤 stable summary를 출력한다.
수정 파일 및 체크리스트:
- [ ] `apps/cli/cmd/alt/main.go` 또는 새 `services/worker/cmd/alt-worker-data-check/main.go` 추가/수정
- [ ] command test 추가
테스트 작성: stdout에 `instrument_count=1`, `bar_count=2`, `first=2024-05-27`, `last=2024-05-28`이 있는지 확인한다.
중간 검증:
```bash
cd apps/cli && go test -count=1 ./...
```
### [KIS_SMOKE-2] Whole Worker Regression
문제: mock provider/import/smoke가 여러 package를 가로지른 뒤 worker 전체 regression 명령이 명시되어 있지 않다.
해결 방법: focused tests와 `bin/test`를 모두 실행한다. sqlc generated drift는 storage query 변경이 있을 때만 `bin/worker-storage-check`를 추가 실행한다.
수정 파일 및 체크리스트:
- [ ] smoke command 구현 후 `bin/test` 통과 확인
- [ ] storage query/migration 변경이 있었다면 `bin/worker-storage-check` 실행
테스트 작성: 별도 새 테스트는 KIS_SMOKE-1에 포함한다.
중간 검증:
```bash
bin/test
```
## 수정 파일 요약
| 파일 | 항목 |
|------|------|
| `apps/cli/cmd/alt/main.go` 또는 `services/worker/cmd/alt-worker-data-check/main.go` | KIS_SMOKE-1 |
| command test file | KIS_SMOKE-1 |
| `bin/*` only if an entrypoint is needed | KIS_SMOKE-2 |
## 최종 검증
```bash
test -f agent-task/m-korea-daily-data-foundation/01_provider_foundation/complete.log
test -f agent-task/m-korea-daily-data-foundation/02+01_import_storage_pipeline/complete.log
bin/test
```
모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.

View file

@ -2,6 +2,23 @@
The Worker service handles background tasks, such as market data imports, data normalization, and backtest execution.
## Market Data Provider Boundary
ALT starts with KIS/Korea daily bars as the first provider and venue validation path, but the worker boundary should keep the canonical model equity venue-agnostic. KRX-specific or KIS-specific fields belong in provider adapters, venue metadata, raw payload storage, or explicit extension metadata instead of becoming required core columns.
Crypto is out of scope for the current stock-oriented market model. If a later crypto data domain is added, it may reuse generic import-run, provider mapping, raw-payload, and OHLCV pipeline concepts, but pair/funding/24-7 market semantics should not be forced into the equity model.
## Provider Reference and Mock Fixtures
KIS adapter mapping should start from the locally cached official sample repository, not from a required Postman export. The cache path is documented in the private rules because it is local machine state, not an ALT source dependency.
- Store mock-provider request/response fixtures under `services/worker/testdata/providers/kis/`.
- Remove app keys, tokens, account numbers, personal identifiers, and live secret references before committing any fixture.
- Prefer JSON for initial adapter mapping because it is readable, diffable, and close to the KIS REST payload shape.
- Consider SQLite only after the fixture corpus is large enough to need indexed lookup or query-based comparison.
Provider credentials are not required for mock tests. When live KIS smoke tests are added later, credentials should be supplied at runtime through 1Password CLI or a later secret-provider implementation. Do not use checked-in `.env` files for provider secrets.
## Redis Usage Guidelines
### Purpose

View file

@ -0,0 +1,39 @@
# KIS Provider Fixtures
This directory is the landing zone for KIS mock-provider fixtures used by worker adapter tests and mapping work.
## Source Reference
Use the locally cached official KIS sample repository first:
- `.agent-cache/koreainvestment/open-trading-api`
The first daily-bar mapping reference is:
- `examples_llm/domestic_stock/inquire_daily_itemchartprice/inquire_daily_itemchartprice.py`
- `examples_llm/kis_auth.py`
- `kis_devlp.yaml`
- `stocks_info/`
Postman exports are not required for the current milestone now that the official API sample repo is available locally.
## Mock Test Fixtures
Keep fixtures small, deterministic, and secret-free. The current minimum set is:
- `daily_itemchartprice_request.sample.json`: KIS daily chart request parameters.
- `daily_itemchartprice_response.sample.json`: KIS-like response payload with `output1` metadata and `output2` OHLCV rows.
- `daily_bars_normalized.expected.json`: expected normalized daily bars used by worker tests.
- `provider_symbols.sample.json`: provider symbol metadata for watchlist, exchange-wide, and sector-like selector tests.
## Sanitization
Before committing fixtures, remove:
- app keys, app secrets, access tokens, refresh tokens, approval keys
- account numbers or personal identifiers
- live authorization headers
- local hostnames or machine-specific paths
- 1Password secret references or item names
Runtime credentials are not required for mock tests. Later live KIS smoke tests should inject credentials at runtime through 1Password CLI or a later secret-provider implementation.

View file

@ -0,0 +1,37 @@
{
"instrument": {
"id": "KRX:005930",
"market": "KR",
"venue": "KRX",
"symbol": "005930",
"name": "Samsung Electronics",
"currency": "KRW",
"provider_symbols": {
"kis": "005930"
}
},
"bars": [
{
"instrument_id": "KRX:005930",
"timeframe": "1d",
"timestamp": "2024-05-27T00:00:00+09:00",
"open": "74800",
"high": "75600",
"low": "74400",
"close": "75000",
"volume": "9100000",
"currency": "KRW"
},
{
"instrument_id": "KRX:005930",
"timeframe": "1d",
"timestamp": "2024-05-28T00:00:00+09:00",
"open": "75200",
"high": "76200",
"low": "75100",
"close": "76000",
"volume": "10500000",
"currency": "KRW"
}
]
}

View file

@ -0,0 +1,13 @@
{
"provider": "kis",
"endpoint": "/uapi/domestic-stock/v1/quotations/inquire-daily-itemchartprice",
"tr_id": "FHKST03010100",
"params": {
"FID_COND_MRKT_DIV_CODE": "J",
"FID_INPUT_ISCD": "005930",
"FID_INPUT_DATE_1": "20240527",
"FID_INPUT_DATE_2": "20240528",
"FID_PERIOD_DIV_CODE": "D",
"FID_ORG_ADJ_PRC": "0"
}
}

View file

@ -0,0 +1,43 @@
{
"rt_cd": "0",
"msg_cd": "MCA00000",
"msg1": "success",
"output1": {
"hts_kor_isnm": "Samsung Electronics",
"stck_shrn_iscd": "005930",
"stck_prpr": "76000",
"prdy_vrss": "1000",
"prdy_vrss_sign": "2",
"prdy_ctrt": "1.33",
"acml_vol": "10500000",
"acml_tr_pbmn": "798000000000"
},
"output2": [
{
"stck_bsop_date": "20240527",
"stck_oprc": "74800",
"stck_hgpr": "75600",
"stck_lwpr": "74400",
"stck_clpr": "75000",
"acml_vol": "9100000",
"acml_tr_pbmn": "682500000000",
"flng_cls_code": "00",
"prtt_rate": "0.00",
"mod_yn": "N",
"revl_issu_reas": ""
},
{
"stck_bsop_date": "20240528",
"stck_oprc": "75200",
"stck_hgpr": "76200",
"stck_lwpr": "75100",
"stck_clpr": "76000",
"acml_vol": "10500000",
"acml_tr_pbmn": "798000000000",
"flng_cls_code": "00",
"prtt_rate": "0.00",
"mod_yn": "N",
"revl_issu_reas": ""
}
]
}

View file

@ -0,0 +1,43 @@
{
"provider": "kis",
"selectors": [
{
"kind": "watchlist",
"symbols": ["005930", "000660"]
},
{
"kind": "exchange",
"venue": "KRX",
"symbols": ["005930", "000660"]
},
{
"kind": "sector",
"name": "semiconductors",
"symbols": ["005930", "000660"]
}
],
"instruments": [
{
"id": "KRX:005930",
"market": "KR",
"venue": "KRX",
"symbol": "005930",
"name": "Samsung Electronics",
"currency": "KRW",
"provider_symbols": {
"kis": "005930"
}
},
{
"id": "KRX:000660",
"market": "KR",
"venue": "KRX",
"symbol": "000660",
"name": "SK Hynix",
"currency": "KRW",
"provider_symbols": {
"kis": "000660"
}
}
]
}