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:
parent
1ac32baf1c
commit
735dafe927
14 changed files with 980 additions and 23 deletions
23
README.md
23
README.md
|
|
@ -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`
|
||||
|
|
|
|||
|
|
@ -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 사례
|
||||
|
|
|
|||
|
|
@ -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?**
|
||||
|
|
@ -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`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
|
||||
|
|
@ -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/...
|
||||
```
|
||||
|
|
@ -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`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
|
||||
|
|
@ -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
|
||||
```
|
||||
|
|
@ -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`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
|
||||
|
|
@ -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
|
||||
|
|
|
|||
39
services/worker/testdata/providers/kis/README.md
vendored
Normal file
39
services/worker/testdata/providers/kis/README.md
vendored
Normal 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.
|
||||
37
services/worker/testdata/providers/kis/daily_bars_normalized.expected.json
vendored
Normal file
37
services/worker/testdata/providers/kis/daily_bars_normalized.expected.json
vendored
Normal 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"
|
||||
}
|
||||
]
|
||||
}
|
||||
13
services/worker/testdata/providers/kis/daily_itemchartprice_request.sample.json
vendored
Normal file
13
services/worker/testdata/providers/kis/daily_itemchartprice_request.sample.json
vendored
Normal 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"
|
||||
}
|
||||
}
|
||||
43
services/worker/testdata/providers/kis/daily_itemchartprice_response.sample.json
vendored
Normal file
43
services/worker/testdata/providers/kis/daily_itemchartprice_response.sample.json
vendored
Normal 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": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
43
services/worker/testdata/providers/kis/provider_symbols.sample.json
vendored
Normal file
43
services/worker/testdata/providers/kis/provider_symbols.sample.json
vendored
Normal 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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
Reference in a new issue