227b563ba2
Fluent UI Blazor v5 / InteractiveServer 방침을 폐기하고 MudBlazor 컴포넌트 + Interactive WebAssembly 렌더 모드 + API-First 를 신규 표준으로 확정한다. 기존 CLAUDE.md(Fluent UI)와 AGENTS.md §5b(MudBlazor)의 상충을 해소한다. - CLAUDE.md: Framework & Design System, Component Rules, 매핑표를 MudBlazor 로 갱신 - AGENTS.md §5b: 렌더 모드 표준(Interactive WebAssembly) 신설, Server 표기 정렬 - ROADMAP_WBS.md: WBS-10 보강 문서 상호 참조 링크 추가 - WBS_10_DOTNET_MIGRATION_HARDENING: 마이그레이션 완성/상용화 로드맵 신규, UI 코드 전환을 WBS-A7 로 등록 코드 전환(csproj/Program.cs/.razor)은 미수행, 본 커밋은 방침 문서만 수정. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2251 lines
151 KiB
Markdown
2251 lines
151 KiB
Markdown
# 퀀트투자 엔진 — 전체 로드맵 & WBS & 하네스 성공 기준
|
||
|
||
> 작성일: 2026-06-13 | 엔진 버전: REBALANCE_ENGINE_V1 기준
|
||
> 원칙: **모든 수치는 공식 ID 기반 산출 → 하네스 검증 → LLM은 렌더링 전용**
|
||
|
||
---
|
||
|
||
## 0a. 현재 실행 우선순위
|
||
|
||
> 2026-06-24 기준, v8.9 채택안(P0~P3)은 검증 완료 상태이며 새 구현 백로그의 최우선 순위는 아래 순서로 고정한다.
|
||
|
||
1. `WBS-7.1` 캘리브레이션 임계값 실증 전환
|
||
2. `WBS-7.7` 신규 시스템 E2E 통합 테스트 및 snapshot_admin 스모크 테스트
|
||
3. `WBS-7.8` ETF NAV/괴리율/추적오차/AUM 수집 경로 확정
|
||
4. `WBS-7.5` 임시 하드코딩 폴백 비례화의 실증 보정
|
||
5. `WBS-7.6` 슬리피지 실측 보정
|
||
6. `WBS-7.9` PostgreSQL history-first operating model 전환
|
||
|
||
`WBS-7.2`, `WBS-7.3`, `WBS-7.4`, `WBS-7.10`~`WBS-7.14`는 현재 문서상 완료 또는 정리 완료로 유지한다.
|
||
|
||
---
|
||
|
||
## 0b. 완료 조건
|
||
|
||
모든 작업은 아래 4가지 증빙이 함께 있을 때만 완료로 본다.
|
||
|
||
- `YAML` 증빙
|
||
- `코드` 증빙
|
||
- `데이터 실체` 증빙
|
||
- `검증 증빙`
|
||
|
||
하나라도 빠지면 완료로 보지 않는다.
|
||
|
||
## 0c. 작업 절차 강제
|
||
|
||
모든 변경은 아래 순서를 지켜야 한다.
|
||
|
||
1. 로드맵/현황 확인
|
||
2. WBS 작성
|
||
3. 목표 설정
|
||
4. 성공판단 데이터 정의
|
||
5. 구현
|
||
6. 사후 검증
|
||
7. 증빙 기록
|
||
|
||
작업 시작 전에 WBS와 성공판단 데이터를 먼저 확정해야 하며, 작은 수정도 예외가 아니다.
|
||
작업 도중 범위가 바뀌면 먼저 WBS를 갱신한 뒤 구현을 계속한다.
|
||
검증 증빙이 없으면 완료로 볼 수 없다.
|
||
|
||
---
|
||
|
||
## 0c. 비판적 리뷰 (2026-06-21)
|
||
|
||
> 본 절은 기존 WBS-1~6의 "완료 ✅" 표시를 그대로 신뢰하지 않고, 코드·spec·산출물 원본을 다시 대조해 발견한 문제를 가감 없이 기록한다. 발견된 문제는 Phase 7(WBS-7)로 추적한다.
|
||
|
||
### 재검증 결과 — 두 문서가 서로 다른 T+5 수치를 인용하고 있었다
|
||
|
||
기존 §4(엔진 완성도 KPI)는 `예측 적중률(T+5) = 54.76%`(목표 근접 PASS 톤)를 인용했고, `spec/27_bch_calibration_runbook.yaml` Phase 4는 `T+5 = 35.86%`(목표 55%, BELOW_TARGET)를 인용했다. **2026-06-21 기준 `Temp/prediction_accuracy_harness_v2.json` 원본을 재확인한 결과, 두 수치 모두 이미 stale 하다:**
|
||
|
||
```
|
||
as_of_date: 2026-06-21
|
||
calibration_state: INSUFFICIENT_SAMPLES
|
||
t1_op_rate: 52.94% (sample=68, decisive_sample=53, rate_decisive=67.92%)
|
||
t5_op_rate: null (sample=0) ← 두 문서의 54.76%/35.86% 모두 현재는 산출 불가
|
||
t20_op_rate: null (sample=0)
|
||
```
|
||
|
||
즉 T+5 표본이 현재 **0건**이라 어느 쪽 수치도 "지금" 유효하지 않다. 파일 mtime 대조 결과 `Temp/honest_performance_guard_v1.json`(35.86%, 2026-06-14 생성)이 `Temp/prediction_accuracy_harness_v2.json`(sample=0, 2026-06-21 생성)보다 7일 더 오래된 스냅샷이었다 — **cases_analyzed가 141건(05-30 기준)에서 0건(06-21)으로 줄어든 것**으로, `evaluation_methodology: ACTIVE_PASSIVE_SPLIT_V1_INCONCLUSIVE_EXCLUDED` 적용으로 inconclusive/replay 표본이 제외된 영향으로 추정된다(근본원인 미조사). → **WBS-7.2 완료**: `spec/27_bch_calibration_runbook.yaml`에 `current_status_2026_06_21` 블록을 신설해 단일 진실원천으로 지정했고, 기존 `current_status_2026_05_30` 블록은 "역사적 스냅샷, 현재로 인용 금지"로 명시했다.
|
||
|
||
### 재검증 결과 — 캘리브레이션 레지스트리는 "형식 완료"일 뿐 "실증 완료"가 아니다
|
||
|
||
`spec/27_bch_calibration_runbook.yaml` Phase 2(CALIB-V1)는 `overclaimed_count=0`, `unregistered_threshold_count=0`을 근거로 **COMPLETE**로 표시되어 있다. 그러나 `spec/calibration_registry.yaml` 전체(190개 임계값)를 직접 집계하면:
|
||
|
||
| source | 건수 | 비율 | 의미 |
|
||
|--------|------|------|------|
|
||
| `SPEC_DERIVED` | 123 | 64.7% | spec 문서 값을 그대로 복사 — 실거래 검증 없음 |
|
||
| `EXPERT_PRIOR` | 59 | 31.1% | 30년 경험 기반 직관값 — sample_n<30, 실거래 검증 없음 |
|
||
| `PROVISIONAL` | 8 | 4.2% | 표본 축적 중, 아직 확정 아님 |
|
||
| `CALIBRATED` | **0** | **0%** | 실거래로 완전 검증된 임계값 — **전혀 없음** |
|
||
|
||
**190개 임계값 중 단 하나도 `CALIBRATED` 상태가 아니다.** "overclaimed_count=0"은 "거짓 주장이 없다"는 뜻일 뿐 "검증되었다"는 뜻이 아니다 — 레지스트리가 정직하게 미검증 상태를 등록해 둔 것뿐이며, Phase 2 "COMPLETE" 표시는 **구조적 완료(스키마·등록 완료)**와 **실증적 완료(데이터로 검증됨)**를 혼동할 위험이 있다. → **⚠️ 표시 수정**: Phase 2(CALIB-V1) = "구조적으로 COMPLETE, 실증적으로는 0/190 검증" 으로 재서술. → **WBS-7.1**로 추적.
|
||
|
||
### 비판 항목 종합표
|
||
|
||
| # | 발견된 문제 | 근거 파일 | 영향도 | 조치 |
|
||
|---|------------|----------|--------|------|
|
||
| 1 | 캘리브레이션 0/190 CALIBRATED (59건 EXPERT_PRIOR, 123건 SPEC_DERIVED 미검증) | `spec/calibration_registry.yaml` (직접 집계) | 🔴 | WBS-7.1 |
|
||
| 2 | T+5 정확도 지표가 문서마다 다른 stale 캐시값을 인용 (54.76% vs 35.86%, 실제는 sample=0) | `Temp/prediction_accuracy_harness_v2.json`, `spec/27_bch_calibration_runbook.yaml` | 🔴 | WBS-7.2 |
|
||
| 3 | GAS→Python 공식 마이그레이션 14건(15건 중) `status: TODO` 방치, 로드맵에 미추적 | `governance/gas_logic_migration_ledger_v1.yaml` | 🟠 | WBS-7.3 |
|
||
| 4 | Deprecated 별칭 17건 `remove_after: 2026-06-30` — 2026-06-21 기준 전수 제거 완료, 현재는 문서 고정만 유지 | `spec/aliases.yaml` | 🟢 | WBS-7.4 |
|
||
| 5 | `OVERHANG_PRESSURE_V1` 등 "임시" 하드코딩 폴백(-500K 절대값, MRS +2점, CLA 25→60%)이 영구화 계획 없이 방치 | `spec/13_formula_registry.yaml:1222`, `spec/risk/circuit_breakers.yaml:192`, `spec/risk/portfolio_exposure.yaml:403` | 🟡 | WBS-7.5 |
|
||
| 6 | 슬리피지 5bps가 이론치, 실측 보정 트리거/일정 없음 | `spec/55_execution_simulator_contract.yaml:21` | 🟡 | WBS-7.6 |
|
||
| 7 | 신규 시스템(KIS 수집→스냅샷 적재→정성매도평가) E2E 통합 테스트 부재, snapshot_admin 웹 JS(~1400줄) 스모크 테스트 없음 | `src/quant_engine/snapshot_admin_server_v1.py`, `tests/unit/test_*_v1.py` (단위 61건은 양호, 통합 0건) | 🟠 | WBS-7.7 |
|
||
| 8 | ETF NAV/괴리율/추적오차/AUM 자동 수집 미구현(KRX/KIND 경로 미확정) — 장기 방치 | `spec/16_data_gaps_roadmap.yaml` S4/S5 | 🟡 | WBS-7.8 |
|
||
| 9 | Naver 스크래핑 폴백의 Cloudflare 403 차단 이력에도 대체 경로·모니터링 없음 | `spec/exit/qualitative_sell_strategy_v1.yaml:81-82` | 🟡 | WBS-7.7 |
|
||
| 10 | 공매도 잔고율 자동화 영구 차단(KIS 미제공, KRX CSV 수동만 유효) | WBS-6 본문(이미 정직하게 USER_ACTION 표기됨) | 🟢 | 운영절차 명문화(WBS-7.8 부속) |
|
||
|
||
### 기존 "완료 ✅" 표시 재검토
|
||
|
||
- **WBS-4.1/4.2/4.3 (DATA_GATED)**: 정직하게 표기됨 — 도전 불필요, 그대로 유지.
|
||
- **Phase 2 캘리브레이션(CALIB-V1) "COMPLETE"**: → **"⚠️ 구조적 완료, 실증 미완료(0/190 CALIBRATED)"**로 정정.
|
||
- **WBS-6 (비기계적 매도전략·위성추천) "100% ✅"**: 엔진·데이터·게이트 코드 자체는 실제로 완성되어 표시는 유지하나, **잔류 위험**(E2E 통합 테스트 부재, Naver Cloudflare 단일장애점)을 각주로 명시(허위 완료 아님, 누락된 리스크 고지).
|
||
|
||
---
|
||
|
||
## 0. 프로젝트 비전 & 방향성
|
||
|
||
### 핵심 목표
|
||
**"은퇴자산 포트폴리오를 운용하는 완전 결정론적 퀀트 투자 엔진"**
|
||
|
||
- 사람의 직관 개입 없이 규칙 기반 매수/매도/리밸런싱 결정
|
||
- 모든 숫자는 추적 가능한 공식 ID와 데이터 출처를 보유
|
||
- 레짐(시장국면) 적응형 — RISK_ON / NEUTRAL / RISK_OFF 자동 대응
|
||
- HTS 캡처 → GAS 분석 → Python 하네스 → 최종 결정 패킷 완전 자동화
|
||
|
||
### 5대 방향성 축
|
||
|
||
| 축 | 설명 | 현재 수준 |
|
||
|----|------|---------|
|
||
| **D1 데이터 완결성** | 194개 컬럼 전부 실데이터로 채움 | ~15개 NULL (8%) — WBS-2.1~2.4 완료 후 |
|
||
| **D2 공식 결정론** | 149개 공식 ID 전부 lifecycle 등록 | 269개 등록 (100%) ✅ |
|
||
| **D3 리스크 제어** | Core/Satellite/Cash 버킷 밴드 위반 0건 | RISK_ON 밴드 내 유지 중 |
|
||
| **D4 알파 피드백** | 예측→실현 수익 루프 30건 이상 누적 | 0건 (DATA_GATED ~2026-07-15) |
|
||
| **D5 실행 자동화** | run_all 1회 실행으로 전체 파이프라인 완결 | 98단계 DAG 구축 완료 ✅ |
|
||
|
||
---
|
||
|
||
## 1. 전체 로드맵 (5개 페이즈)
|
||
|
||
```
|
||
Phase 1 ████████████████████ 기반 경화 (Foundation Hardening) [완료 ✅]
|
||
Phase 2 ████████████████░░░░ 신호 엔진 완성 (Signal Engine) [80% — WBS-2.5 DATA_GATED]
|
||
Phase 3 ████████████████████ 실행·리스크 관리 (Execution & Risk) [완료 ✅]
|
||
Phase 4 █████░░░░░░░░░░░░░░░ 성과 인텔리전스 (Performance) [25% — 4.1~4.3 DATA_GATED]
|
||
Phase 5 ████████████████████ 완전 자동화 (Full Automation) [완료 ✅]
|
||
Phase 6 ████████████████████ 비기계적 매도전략·위성추천 [완료 ✅ — 잔류위험 명시, 0c절 참조]
|
||
Phase 7 ░░░░░░░░░░░░░░░░░░░░ 보완·고도화 (Critical Hardening) [0% — 0c절 비판 10건 대응, 신규 착수 대기]
|
||
Phase 10 ░░░░░░░░░░░░░░░░░░░░ C#/.NET 엔진 고도화 (Engine Parity) [0% — .NET 5~10% 구현, Python parity 미검증]
|
||
```
|
||
|
||
| Phase | 기간 목표 | 핵심 산출물 | 완료 기준 |
|
||
|-------|----------|-----------|---------|
|
||
| **P1 기반 경화** | ~2026-07 | GAS 버그 0건, data_feed NULL 40→10 이하 | `full-gate` PASS |
|
||
| **P2 신호 엔진** | ~2026-09 | 펀더멘털 피드 완성, RS/알파 신호 ACTIVE | 황금 테스트케이스 100% |
|
||
| **P3 실행·리스크** | 2026-06 완료 | 리밸런싱 엔진 V1, 3단계 분할 주문 | 실제 주문 3회 이상 |
|
||
| **P4 성과 인텔리전스** | ~2026-10 | T+20 결과 30건, 알파 보정 루프 | match_rate ≥ 55% |
|
||
| **P5 완전 자동화** | ~2026-12 | CI/CD + Gitea, 자율 실행 | 수동 개입 0회/주 |
|
||
| **P6 비기계적 매도전략** | 2026-06 완료 | 5팩터 confluence 엔진, KIS 조회연동, SQLite 자체평가 | WBS-6 본문 하네스 PASS (잔류위험은 P7에서 해소) |
|
||
| **P7 보완·고도화** | ~2026-08 | 캘리브레이션 실증 전환, GAS 마이그레이션 완결, deprecated 정리, E2E 통합테스트 | WBS-7.1~7.8 하네스 전부 PASS |
|
||
| **P10 .NET 엔진 고도화** | ~2026-12 | C# Domain Parity, 테스트 100+건, Application 서비스, Blazor 대시보드, 보안 경화 | `dotnet test` 전체 PASS + parity JSON gate PASS |
|
||
|
||
---
|
||
|
||
## 2. 상세 WBS (Work Breakdown Structure)
|
||
|
||
---
|
||
|
||
### WBS-1: 기반 경화 (Phase 1)
|
||
|
||
#### WBS-1.1 GAS 소수주 분리 행 병합 완결
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | `gdc_01_fetch_fundamentals.gs` `_mergePositionRecord_()` 배포 + 검증 |
|
||
| **트리거** | account_snapshot에 `(소수)` 접미사 행이 전체주 행과 동일 ticker |
|
||
| **담당 파일** | `src/gas_adapter_parts/gdc_01_fetch_fundamentals.gs:1648` |
|
||
| **하네스 검증** | `005930 Weight_Pct ≥ 40%`, `000660 Weight_Pct ≥ 30%` |
|
||
| **상태** | 완료 (배포 및 검증 PASS) |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
BEFORE: 005930 Weight_Pct = 0.05%, AcctQty = 0.647
|
||
AFTER: 005930 Weight_Pct ≥ 40%, AcctQty = 530.647
|
||
검증 쿼리: data_feed에서 Weight_Pct × total_asset_krw ≈ account_snapshot.market_value ±1%
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-1.2 total_asset_krw 실시간 재계산
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | Naver 가격 루프 완료 후 `Σ(close × qty) + settlementCashD2_` 재계산 |
|
||
| **현재 오차** | settings값(405M) vs Naver실가(385M) = **20.4M원(5%) 괴리** |
|
||
| **담당 파일** | `src/gas_adapter_parts/gdc_02_account_satellite.gs:529` (1차 가격 수집은 `gdc_01_fetch_fundamentals.gs` 구현) |
|
||
| **수정 방법** | 2-pass 루프: 1차 가격 수집 → totalAssetKrw_ 재계산 → 2차 Weight_Pct |
|
||
| **상태** | 완료 (실시간 2-pass 재계산 완료) |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증: |settings.total_asset_krw - Σ(Naver_close × qty) - cash| / settings.total_asset_krw ≤ 2%
|
||
현재: (405,489,183 - 385,052,321) / 405,489,183 = 5.0% → FAIL
|
||
목표: ≤ 2% → PASS
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-1.3 Time_Stop_Date / Days_To_Time_Stop 컬럼 채움
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | entry_date + time_stop_days 임계 초과 시 자동 계산 |
|
||
| **현재 상태** | 11개 행 전부 NULL (SK하이닉스·TIGER조선 TIME_STOP 신호 있으나 날짜 미기재) |
|
||
| **담당 파일** | `src/gas_adapter_parts/gdc_02_account_satellite.gs` |
|
||
| **로직** | `time_stop_date = entry_date + 60일`, `days_to_time_stop = time_stop_date - today` |
|
||
| **상태** | 완료 (디폴트 60일 자동 계산 완료) |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증: TIME_STOP Sell_Reason을 가진 모든 행에서 Days_To_Time_Stop IS NOT NULL
|
||
현재: 000660(SK하이닉스) entry_date=2026-05-07, 경과일=37일, 임계=60일
|
||
→ Days_To_Time_Stop = 60 - 37 = 23일 (이미 초과 → 0 또는 음수)
|
||
목표: TIME_STOP 신호 보유종목 null 비율 = 0%
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-1.4 Rule_Sell_Qty / Override_Sell_Qty 자동 산출
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | SELL_READY/FORCE 신호 발동 시 수량 자동 계산 |
|
||
| **현재 상태** | 11개 SELL 관련 행 전부 NULL |
|
||
| **공식 ID** | `POSITION_SIZE_V1` + `SELL_WATERFALL_ENGINE_V2` |
|
||
| **입력** | Account_Holding_Qty × Sell_Ratio_Pct / Tick_Unit |
|
||
| **상태** | 완료 (floor 기반 수량 계산 완료) |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증: Final_Action = 'SELL_READY' 인 행에서 Rule_Sell_Qty IS NOT NULL AND Rule_Sell_Qty > 0
|
||
Rule_Sell_Qty = floor(Account_Holding_Qty × Sell_Ratio_Pct / 100) ≥ 1
|
||
현재: 000660 holding=56, SELL_RATIO=50% → Rule_Sell_Qty = 28 (현재 NULL → FAIL)
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-1.5 공식 lifecycle 레지스트리 완결 (149개 → 100%)
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | `spec/51_formula_lifecycle_registry.yaml` 전체 공식 이관 |
|
||
| **현재 상태** | 13개 등록 (9%) |
|
||
| **목표** | 149개 전부 등록 + lifecycle_state 명시 |
|
||
| **우선순위** | ACTIVE 공식 먼저, DEPRECATED 표시 후 제거 |
|
||
| **상태** | 완료 (269개 공식 마이그레이션 및 대조 검증 PASS) |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증 명령: python tools/validate_formula_version_lifecycle_v1.py
|
||
목표: spec/13_formula_registry.yaml 의 모든 formula_id가 51_formula_lifecycle_registry.yaml에 존재
|
||
lifecycle_state in [ACTIVE, DEPRECATED, DATA_GATED, PENDING]
|
||
현재 미등록 수: 136개 → 목표: 0개
|
||
```
|
||
|
||
---
|
||
|
||
### WBS-2: 신호 엔진 완성 (Phase 2)
|
||
|
||
#### WBS-2.1 펀더멘털 데이터 피드 완성 (40개 NULL 컬럼)
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | Yahoo Finance / DART API 연동으로 40개 NULL 컬럼 채움 |
|
||
| **NULL 컬럼 목록** | EPS_Growth_1Y_Pct, Beta, High52W, Low52W, ROE_Pct, Operating_Margin_Pct, Debt_To_Equity, Current_Ratio, FCF_B, Revenue_Growth_Pct, Earnings_Date 등 |
|
||
| **데이터 소스** | DART(국내주), yfinance/Alpha Vantage(선택), Naver 금융 확장 |
|
||
| **담당 파일** | `tools/ingest_fundamental_raw.py` → `src/gas_adapter_parts/gdc_01_fetch_fundamentals.gs` |
|
||
| **상태** | ✅ 완료 (2026-06-14) — yfinance 연동, coverage=100%, full_advanced=8 |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
목표 컬럼별 채움 기준:
|
||
Beta: KR 주식 60일 일간 수익률 vs KOSPI 회귀계수 → |Beta| > 0
|
||
High52W: 최근 252 거래일 최고가 → High52W ≥ Close
|
||
ROE_Pct: DART 반기보고서 최신 → ROE_Pct ∈ (-50%, 100%)
|
||
EPS_Growth_1Y: 전년 동기 EPS 대비 % → IS NOT NULL
|
||
Earnings_Date: DART 공시 일정 → 향후 90일 이내 존재 시 기재
|
||
|
||
검증: NULL 컬럼 수 ≤ 10 (현재 40 → 목표 10)
|
||
핵심 4개(Beta/High52W/ROE/EPS) 완전 채움 = 100%
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-2.2 US 주식 가격 피드 (GOOGL/MSFT/NVDA)
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | US 주식 종가 수집 — Naver 대신 Yahoo Finance API 또는 Alpha Vantage |
|
||
| **현재 상태** | GOOGL/MSFT/NVDA market_value=0, Weight_Pct=0 (완전 누락) |
|
||
| **구현 방법** | `gdf_01_price_metrics.gs` 에서 알파벳 ticker 감지 시 별도 URL 분기 |
|
||
| **대안** | `settings` 탭에 당일 환율 + 전일 US 종가 수동 입력 → GAS 자동 계산 |
|
||
| **상태** | 완료 (미국 주식 자산가치 및 Weight_Pct 자동 원화 스케일 연동 완료) |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증: data_feed에서 GOOGL.Close > 0, MSFT.Close > 0, NVDA.Close > 0
|
||
Weight_Pct = Close_USD × 환율_KRW × qty / total_asset_krw × 100
|
||
현재: GOOGL Weight_Pct = 0.00% (qty=0.502주, Close=0 → FAIL)
|
||
목표: GOOGL Weight_Pct ≈ 0.502 × 200,000 / 405,489,183 × 100 ≈ 0.02% (IS NOT NULL)
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-2.3 RS(상대강도) 신호 V2 완성
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | RS_Verdict_V1_Raw, RS_Line_20D_Slope, RS_Line_60D_Slope 컬럼 채움 |
|
||
| **공식 ID** | `RS_MOMENTUM_V1`, `RS_VERDICT_V2` |
|
||
| **현재 상태** | 컬럼 존재하나 전부 NULL |
|
||
| **입력** | Close / MA20 / KOSPI 지수 대비 상대 퍼포먼스 |
|
||
| **담당 파일** | `src/gas_adapter_parts/gdf_01_price_metrics.gs` |
|
||
| **상태** | 완료 (KOSPI preReads 파싱 헤더 동적 스캔 적용 완료) |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
RS_Pct_20D = (Close_t - Close_t-20) / Close_t-20 × 100 - KOSPI_Ret_20D
|
||
RS_Line_20D_Slope = RS_Pct_20D의 5일 이동평균 변화율
|
||
|
||
검증: 보유 5개 종목 중 RS_Verdict_V1_Raw ∈ ['LEADER','MARKET','LAGGARD'] 100%
|
||
RS_Line_20D_Slope IS NOT NULL 100%
|
||
현재: NULL 100% → FAIL
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-2.4 PEG_SCORE_V1 실데이터 검증 및 ACTIVE 전환
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | PEG = P/E ÷ EPS_Growth_Rate 산출 → PEG_Gate 결정 |
|
||
| **공식 ID** | `PEG_SCORE_V1` |
|
||
| **현재 상태** | PEG, PEG_Gate 컬럼 NULL. lifecycle: ACTIVE 등록됨. 데이터 미입수 |
|
||
| **입력** | TTM_PE(`per`), EPS_Growth_1Y_Pct — `ingest_fundamental_raw.py` 출력 |
|
||
| **판정 기준** | PEG ≤ 1.0 → BUY_GRADE, 1.0~1.5 → HOLD, > 1.5 → CAUTION |
|
||
| **상태** | ✅ 완료 (2026-06-13) — TTM_PE 대체 사용, 비ETF 75% 커버 (6/8) |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증: 비ETF 주식 PEG_Gate IS NOT NULL 비율 = 75% (PASS — 목표 ≥ 80% 근접)
|
||
PEG = TTM_PE / eps_growth_1y_pct (eps_growth > 0 조건)
|
||
음수 성장 2종목은 정상 NULL (PEG 미정의)
|
||
결과:
|
||
000660 PEG=0.052 BUY_GRADE | 005930 PEG=0.053 BUY_GRADE
|
||
012450 PEG=0.119 BUY_GRADE | 010120 PEG=1.371 HOLD
|
||
064350 PEG=1.029 HOLD | 028050 PEG=4.409 CAUTION
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-2.5 섹터 플로우 신호 고도화 (SMART_MONEY_FLOW_V2)
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | sector_flow_history 탭 30일 이상 누적 → 섹터 모멘텀 신호 산출 |
|
||
| **공식 ID** | `FLOW_CREDIT_V1`, `SECTOR_ROTATION_MOMENTUM_V1` |
|
||
| **현재 상태** | sector_flow_history 탭 존재, 데이터 누적 중(21/30일) |
|
||
| **신호 로직** | 최근 5일 기관 순매수 상위 섹터 → Flow_Credit 가중치 부여 |
|
||
| **진척 아티팩트** | `Temp/sector_flow_history_progress_v1.json` |
|
||
| **상태** | 부분 구현 (일일 누적 필요) |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증: sector_flow_history 행 수 ≥ 30 × 섹터 수
|
||
Flow_Credit IS NOT NULL for 보유 종목 100%
|
||
Flow_Credit 범위: [0.0, 1.0]
|
||
현재: sector_flow_history = 21일 / 30일, Flow_Credit 11/11 non-null → 30일 데이터 누적 후 재검증
|
||
```
|
||
|
||
---
|
||
|
||
### WBS-3: 실행·리스크 관리 (Phase 3)
|
||
|
||
#### WBS-3.1 리밸런싱 엔진 V1 GAS 배포 및 검증 ✅ 코드 완성
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | `gdf_06_rebalance.gs:runRebalanceSheet_()` GAS 배포 |
|
||
| **현재 상태** | 코드 완성 + Logger.log/getSpreadsheet_() 수정 완료 |
|
||
| **산출물** | rebalance 시트: SUMMARY/BUCKETS/TICKERS/ORDERS 4섹션 |
|
||
| **상태** | 완료 (DAG 검증 PASS) |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
REGIME_PRELIM = RISK_ON 조건:
|
||
Core band: 51~81% → 현재 75.0% → WARN (PASS)
|
||
Satellite band: 2.5~32.5% → 현재 19.2% → WARN (PASS)
|
||
FORCE_TIME_STOP 주문: TIGER조선TOP10 337주 3단계 → orders_count = 3
|
||
|
||
검증: rebalance 시트 updated 타임스탬프 IS NOT NULL
|
||
orders[0].reason = 'TIME_STOP'
|
||
rebalance_needed = false (RISK_ON, 밴드 내)
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-3.2 리밸런싱 엔진 V2 — equal_weight 개선 (비중 기반 목표배분)
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | V1의 `equal_weight_within_bucket` → 신호 강도·MDD 가중 목표 배분 |
|
||
| **한계** | V1: 코어 2종목 각 33% 고정. 실제 삼성(43%) > SK하이닉스(31%) 불균형 |
|
||
| **개선 방법** | SS001 점수 × 리스크 예산 → 종목별 목표 비중 동적 산출 |
|
||
| **공식 ID** | `POSITION_SIZE_V1` + `RISK_BUDGET_CASCADE_V1` |
|
||
| **상태** | 완료 (`signal_weighted_ss001_v1`; 삼성 36.84% > SK 29.16% PASS, 버킷 합 ±0.0%) |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
목표 배분 알고리즘:
|
||
ticker_target_pct = bucket_target_pct × (SS001_Score / Σ(SS001_Score in bucket))
|
||
|
||
검증: 모든 ticker target_pct ∈ (0%, bucket_max%)
|
||
Σ(ticker target_pct per bucket) = bucket_target_pct ±0.1%
|
||
삼성전자 target > SK하이닉스 target iff SS001_삼성 > SS001_SK
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-3.3 주문 실행 시뮬레이터 (EXECUTION_SIMULATOR_V1)
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | rebalance orders → HTS 지정가 주문 형식 변환 + 슬리피지 추정 |
|
||
| **공식 ID** | `TICK_NORMALIZER_V1`, `EXECUTION_QUALITY_SCORE_V1` |
|
||
| **입력** | orders 배열 + 호가 단위 테이블 |
|
||
| **산출물** | `Temp/execution_simulator_v1.json` — HTS 입력용 주문표 |
|
||
| **상태** | 완료 (ETF 및 미국 주식 호가 단위 세분화 완료, H004 검증 PASS) |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증: 지정가 = floor(Close × (1 - 0.2%) / tick_unit) × tick_unit
|
||
TIGER조선(494670): Close=27,685원, tick=5원 → limit_price=27,630원 ✅
|
||
슬리피지 추정: (Close - limit_price) / Close × 100 ≤ 0.2%
|
||
execution_simulator.json orders 수 = rebalance orders 수
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-3.4 드로우다운 가드 & 포트폴리오 MDD 모니터링
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | 포트폴리오 MDD 실시간 모니터링 → 임계(15%) 초과 시 강제 현금화 |
|
||
| **공식 ID** | `PORTFOLIO_DRAWDOWN_GATE_V1`, `SMART_CASH_RECOVERY_V9` |
|
||
| **현재 상태** | `logDailyAssetHistory_()` 구현 완료. `daily_history` 시트 자동 생성 |
|
||
| **입력** | totalAssetKrw_ (WBS-1.2 실시간 재계산값) |
|
||
| **상태** | 완료 (getSpreadsheet_() 수정 포함, run_all MDD 자동 기록) |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
MDD = (peak_total_asset - current_total_asset) / peak_total_asset × 100
|
||
검증: MDD IS NOT NULL (daily 기록 테이블 필요)
|
||
MDD ≥ 15% → CASH_RAISE_FORCED = true 트리거
|
||
현재: settings.total_asset_krw 단일값 → 시계열 없음 → FAIL
|
||
```
|
||
|
||
---
|
||
|
||
### WBS-4: 성과 인텔리전스 (Phase 4)
|
||
|
||
**진행 순서 고정**
|
||
- `WBS-4.1`에서 T+20 실측 표본을 30건까지 누적해야 한다.
|
||
- `WBS-4.2`는 `WBS-4.1`의 실측 결과가 쌓인 뒤에만 match rate를 계산할 수 있다.
|
||
- `WBS-4.3`는 `WBS-4.2`의 match/miss 누적이 있어야만 재보정 입력을 받을 수 있다.
|
||
- 지금 시점에서는 `WBS-4.1`만 데이터 누적형 과제이고, `WBS-4.2`/`WBS-4.3`은 구조는 있으나 실증 대기 상태다.
|
||
|
||
#### WBS-4.1 T+20 아웃컴 레저 구축 (DATA_GATED)
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | 매수 신호 발생 후 20 거래일 뒤 수익률 자동 기록 |
|
||
| **공식 ID** | `ALPHA_FEEDBACK_LOOP_V2` (lifecycle: DATA_GATED) |
|
||
| **활성화 조건** | live_t20_count ≥ 30 건 (~2026-07-15 예상) |
|
||
| **담당 파일** | `tools/build_operational_t20_outcome_ledger_v1.py` |
|
||
| **진척 아티팩트** | `Temp/data_gated_progress_v1.json` |
|
||
| **현재 상태** | 스키마 완성, 데이터 0건 |
|
||
|
||
> 2026-06-21 누적 상태: `Temp/realized_performance_v1.json` 기준 `t1_operational.n=68`, `t5_operational.n=0`, `t20_replay_estimated.n=0`. 레저 구조는 있으나 T+20 실측 종료 조건은 아직 충족하지 못했다.
|
||
> 상세 상태 스냅샷: [`docs/WBS_4_1_4_3_STATUS_2026_06_21.md`](/C:/Temp/data_feed/docs/WBS_4_1_4_3_STATUS_2026_06_21.md)
|
||
> 현재 대기 순서: `WBS-4.1`은 T+20 실측 30건 누적까지 대기, `WBS-4.2`는 `WBS-4.1` 완료 전에는 match rate 하네스 산출 불가, `WBS-4.3`은 `WBS-4.2`의 결과가 쌓이기 전에는 보정 루프를 돌릴 수 없다.
|
||
> 2026-06-22 상태 스냅샷: `Temp/wbs_4_1_7_1_status_v1.json` 기준 `live_t20=0/30`, `t20_due_capture_count=0`, `operational_queue_state=EMPTY`.
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
활성화 체크:
|
||
python tools/validate_live_data_activation_gate_v1.py
|
||
→ live_t20_count ≥ 30 → ALPHA_FEEDBACK_LOOP_V2 → ACTIVE 전환
|
||
|
||
T+20 수익률 계산:
|
||
outcome_pct = (Close_t+20 - entry_price) / entry_price × 100
|
||
|
||
검증: outcome_ledger 행수 ≥ 30
|
||
Σ(outcome_pct > 0) / total × 100 = win_rate_pct (목표 ≥ 55%)
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-4.2 예측 정확도 하네스 (PREDICTION_ACCURACY_HARNESS_V5)
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | 매수/매도 예측 → 실현 결과 매칭 정확도 추적 |
|
||
| **공식 ID** | `PREDICTION_ACCURACY_HARNESS_V5` (lifecycle: ACTIVE) |
|
||
| **현재 상태** | 하네스 구조 완성, match_rate 데이터 부족 |
|
||
| **목표 지표** | match_rate_pct ≥ 55% (은퇴자산 허용 오차) |
|
||
| **산출물** | `Temp/prediction_accuracy_harness_v2.json` |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
match_rate_pct = 예측방향 맞춘 건수 / 전체 예측 건수 × 100
|
||
|
||
검증: Temp/prediction_accuracy_harness_v2.json
|
||
match_rate_pct ≥ 55% → ACTIVE 유지
|
||
match_rate_pct < 40% → PREDICTION_ACCURACY_HARNESS_V5 retirement 검토
|
||
|
||
현재: 데이터 부족으로 산출 불가 → WBS-4.1 완료 선행
|
||
```
|
||
|
||
> 2026-06-21 누적 상태: `Temp/prediction_accuracy_harness_v2.json` 기준 `calibration_state=INSUFFICIENT_SAMPLES`, `t1_sample=68`, `t5_sample=0`, `t20_sample=0`, `t20_replay_sample=0`.
|
||
> 대기 의미: `WBS-4.2`는 실현값이 없어서 하네스가 비어 있는 상태이며, `WBS-4.1`이 30건 누적되기 전까지는 정량 판정이 발생하지 않는다.
|
||
|
||
---
|
||
|
||
#### WBS-4.3 알파 보정 루프 (ALPHA_CALIBRATION_V2)
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | T+20 수익률 → SS001 점수 가중치 재보정 자동화 |
|
||
| **공식 ID** | `ALPHA_FEEDBACK_LOOP_V2` |
|
||
| **현재 상태** | DATA_GATED. 30건 이상 후 활성화 |
|
||
| **보정 대상** | SS001_P(가격강도), SS001_V(거래량), SS001_F(플로우) 가중치 |
|
||
| **상태** | 설계 완성, 데이터 대기 |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
보정 사이클: 30건마다 1회 실행
|
||
calibrated_weight_P = 기본0.25 × (관측 승률_P 기여도 / 기대치)
|
||
|
||
검증: 보정 후 match_rate_pct 개선 ≥ 2%p
|
||
calibration_registry_v1.json 업데이트 타임스탬프 IS NOT NULL
|
||
```
|
||
|
||
> 2026-06-21 누적 상태: `Temp/alpha_feedback_loop_v2.json` 기준 `status=DATA_INSUFFICIENT`, `cases_analyzed=0`, `recommended_adjustments={}`.
|
||
> 대기 의미: `WBS-4.3`는 `WBS-4.2`에서 유의미한 match/miss 누적이 생겨야만 재보정 입력을 받을 수 있다. 지금은 설계와 하네스만 있고, 보정 데이터는 없다.
|
||
|
||
---
|
||
|
||
#### WBS-4.4 성과 모니터링 대시보드 (EVALUATION_DASHBOARD_V1)
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | 일별 포트폴리오 수익률, 벤치마크 대비 Alpha, 공식 예측 적중률 시각화 |
|
||
| **공식 ID** | `CONTINUOUS_EVALUATION_DASHBOARD_V1` |
|
||
| **현재 상태** | `updateEvaluationDashboard_()` GAS 함수 구현 완료 (`gdf_04_execution_quality.gs`) |
|
||
| **산출물** | GatherTradingData.xlsx의 evaluation_dashboard 탭 (run_all Step-8 자동 실행) |
|
||
| **상태** | ✅ 완료 (2026-06-13) |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증: evaluation_dashboard 탭에 아래 지표 IS NOT NULL
|
||
- portfolio_return_1d_pct: (오늘 total_asset - 어제) / 어제 × 100
|
||
- kospi_return_1d_pct: KOSPI 일간 수익률
|
||
- alpha_1d_pct: portfolio - kospi
|
||
- cumulative_alpha_pct: Σ(alpha_1d_pct)
|
||
- match_rate_pct: WBS-4.2 연동
|
||
목표: 30일 누적 데이터 → CAGR, Sharpe Ratio 산출 가능
|
||
```
|
||
|
||
---
|
||
|
||
### WBS-5: 완전 자동화 (Phase 5)
|
||
|
||
#### WBS-5.1 Gitea CI/CD 파이프라인 구축
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | main 브랜치 push → 자동 validate → Temp/ 산출물 갱신 → GAS 배포 패키지 생성 |
|
||
| **담당** | `.gitea/workflows/ci.yml` |
|
||
| **단계** | validate_specs → validate_formula_registry → validate_golden_coverage_100 → build_rebalance_engine_v2 → ingest_fundamental_raw --no-naver → run_release_dag_v3 --strict → build_bundle |
|
||
| **상태** | ✅ 완료 (2026-06-13) — Synology Gitea act_runner 환경 최적화 (`runs-on: self-hosted`, python3 직접 실행) |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
CI 게이트:
|
||
python tools/validate_specs.py → EXIT 0
|
||
python tools/validate_formula_registry.py → EXIT 0
|
||
python tools/validate_golden_coverage_100.py → EXIT 0
|
||
python tools/build_rebalance_engine_v1.py → rebalance_engine_v1.json 생성
|
||
|
||
검증: CI 전체 소요 시간 ≤ 5분
|
||
main 브랜치 모든 커밋 → CI 통과율 100%
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-5.2 GAS 자동 배포 스크립트
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | `clasp push` 또는 `prepare_upload_zip.py` → GAS 배포 자동화 |
|
||
| **현재 상태** | `tools/deploy_gas.py` 완성 (dry-run PASS, 17개 파일 번들 경로 WARN 0건) |
|
||
| **목표** | 코드 수정 → 1개 명령으로 GAS 반영 + run_all 실행 |
|
||
| **담당 파일** | `tools/deploy_gas.py` + `tools/automate_routine.py` |
|
||
| **상태** | 완료 (번들 빌드 자동화 완성; clasp push는 clasp 로그인 필요) |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증: python tools/run_deployment_checklist_v1.py
|
||
→ spec 검증 PASS
|
||
→ dist/retirement_portfolio_bundle.yaml 생성
|
||
→ GAS 업로드 패키지 생성
|
||
소요시간 ≤ 60초
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-5.3 일일 자율 실행 사이클 완성
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | 장 마감(오후 3:30) → HTS 캡처 → ChatGPT 파싱 → GAS run_all → Python 하네스 → 결정 패킷 → 알림 |
|
||
| **현재 자동화 수준** | GAS run_all 63단계 DAG 존재, 수동 트리거 |
|
||
| **목표** | 타이머 트리거 설정 → 완전 자율화 |
|
||
| **상태** | 완료 (gdf_06_rebalance.gs `setupDailyRunAllTrigger()` 추가; GAS 편집기에서 1회 실행 필요) |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
일일 사이클 KPI:
|
||
- HTS 캡처 → GAS 반영 소요시간 ≤ 30분
|
||
- run_all 성공률 ≥ 95% (주 5일 기준)
|
||
- 수동 개입 필요 횟수 ≤ 1회/주
|
||
- final_decision_packet_active.json 일별 업데이트 100%
|
||
```
|
||
|
||
---
|
||
|
||
### WBS-6: 비기계적 매도전략 & 위성추천 (Phase 6, 2026-06-21)
|
||
|
||
**운영 원칙(30년 시니어 퀀트 관점 — 이 Phase의 모든 작업이 따르는 단일 기준)**
|
||
|
||
| 원칙 | 이 Phase에서의 구현 |
|
||
|------|---------------------|
|
||
| 가치보존이 목적, 매도가 목적 아님 | confluence 최소 3/5 합의 없이는 매도 트리거 금지(`mechanical_sell_prohibited=true`) |
|
||
| 추정 금지, 신뢰 데이터만 | 데이터 결측 시 항상 `DATA_MISSING`/`INSUFFICIENT_DATA_NO_ACTION` — 추정값으로 채우지 않음 |
|
||
| 데이터 정합성 | 출처별 실측 상태를 코드 주석·spec에 고정(WORKING/MANUAL_CSV_ONLY/USER_ACTION 등), 추측 표기 금지 |
|
||
| 일관된 알고리즘 | 5팩터·confluence 규칙·국면 가중치가 보유종목/위성후보 평가에 동일하게 적용 |
|
||
| 지속적 자체평가 | SQLite 시계열(`qualitative_sell_strategy.db`) + 사후 적중률 평가(`evaluate_qualitative_sell_strategy_accuracy_v1.py`) — T+5 가격과 대조해 hit_rate 산출, 표본<10건이면 DATA_GATED로 보류 |
|
||
| 안전(불변 원칙) | KIS Open API는 조회만 — 매수/매도 직접 실행·계좌조회 절대 금지, CI 강제 게이트 |
|
||
|
||
**구성요소 요약**
|
||
|
||
| 구분 | 핵심 파일 | 상태 |
|
||
|------|----------|------|
|
||
| 매도판단 엔진 | `src/quant_engine/qualitative_sell_strategy_v1.py` (`QUALITATIVE_SELL_STRATEGY_V1`/`SHORT_INTEREST_RISK_GAUGE_V1`/`MARKET_REGIME_CLASSIFIER_V1`/`SATELLITE_CANDIDATE_SCORE_V1`/`MICROSTRUCTURE_PRESSURE_FROM_ORDERBOOK_V1`) | ✅ 완료 |
|
||
| 데이터 수집(보유종목) | `tools/build_qualitative_sell_inputs_v1.py` + `build_macro_context_from_workbook_v1.py`(실워크북 연동) + `fetch_naver_market_data_v1.py` + `fetch_trade_statistics_motie_v1.py` | ✅ 완료 — 10/10 보유종목 오류 0건 |
|
||
| KIS Open API 보강 | `src/quant_engine/kis_api_client_v1.py` — 호가10단계·공매도거래비중 실측 연동(`--kis-account real`) | ✅ 완료 — 잔고율(`short_balance_ratio`)만 미해결(KIS도 미제공, `--short-csv` 수동 경로만 유효, USER_ACTION 대기) |
|
||
| **[CRITICAL] 안전 게이트** | `governance/rules/06_no_direct_api_trading.yaml`, `07_no_kis_account_balance_query.yaml`, `tools/validate_no_direct_api_trading_v1.py`(CI 강제, strict) | ✅ 완료 — 가드 제거 실험으로 FAIL 탐지 실측 검증 |
|
||
| 위성 후보 추천 | `tools/build_satellite_candidate_recommendations_v1.py` — universe 60종목 평가, 보유종목 제외 | ✅ 완료 — 섹터 매핑 버그(바이오헬스→바이오, 방산 추가) 수정 후 매칭 11→18건 |
|
||
| 시계열 저장 + 자체평가 | `src/quant_engine/qualitative_sell_strategy_store_v1.py`(SQLite, GAS/xlsx와 독립) + `tools/evaluate_qualitative_sell_strategy_accuracy_v1.py` | ✅ 완료 — 평가 루프는 결정 누적 전까지 정직하게 DATA_GATED 보고 |
|
||
| 운영 스케줄러 | `.gitea/workflows/kis_data_collection.yml` — 영업일 08~17시 2시간 간격 + 수동 실행 | ✅ 완료 — Gitea repo secrets(`KIS_APP_KEY` 등) 등록은 USER_ACTION |
|
||
|
||
**향후 확장 시 고려사항(지금 구현하지 않음, 설계만 호환 유지)**
|
||
- DB 엔진: SQLite → PostgreSQL 전환 가능성을 고려해 `qualitative_sell_strategy_store_v1.py`는 `insert_*`/`fetch_*` 함수 뒤로 SQL을 전부 숨겼다 — 호출부(오케스트레이터)는 DB 엔진을 모른다. 전환 시 이 한 파일의 내부 구현만 바꾸면 된다(AUTOINCREMENT→SERIAL 등 방언 차이만 해당 파일 내부 문제).
|
||
- 공매도 잔고율은 KRX 공매도종합포털 CSV 외 경로가 없음을 실측으로 확정했으므로, 재시도성 스크래핑 시도는 더 이상 하지 않는다.
|
||
|
||
**검증 명령**:
|
||
```
|
||
python -m pytest tests/unit -q → 40 passed
|
||
python tools/validate_no_direct_api_trading_v1.py → PASS (strict)
|
||
python tools/validate_specs.py / validate_formula_registry.py /
|
||
validate_golden_coverage_100.py / validate_harness_coverage_auditor.py → 전부 PASS
|
||
python tools/build_qualitative_sell_inputs_v1.py --batch --workbook GatherTradingData.xlsx --kis-account real
|
||
→ 10/10 종목 오류 0건, BATCH_GATE: PASS
|
||
```
|
||
|
||
---
|
||
|
||
### WBS-7: 보완·고도화 (Phase 7, 2026-06-21 비판적 리뷰 대응)
|
||
|
||
> 0c절에서 발견된 10개 문제에 대한 추적 WBS. 모든 항목은 착수 전이며 상태는 `TODO`.
|
||
|
||
#### WBS-7.1 캘리브레이션 임계값 실증 전환 (EXPERT_PRIOR/SPEC_DERIVED → PROVISIONAL → CALIBRATED)
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | 190개 임계값 중 `EXPERT_PRIOR`(59)·`SPEC_DERIVED`(123)를 실거래 표본 누적 순으로 `PROVISIONAL`→`CALIBRATED` 전환 |
|
||
| **현재 상태** | `CALIBRATED` 0/190 (0%), `PROVISIONAL` 8/190 (4.2%) |
|
||
| **우선순위** | `Temp/calibration_priority_v1.json`의 urgency score 상위 항목부터 |
|
||
| **담당 파일** | `tools/build_calibration_priority_v1.py`(`registry_source_breakdown`/`live_t5_status` 신규), `spec/calibration_registry.yaml` |
|
||
| **상태** | 도구 보강 완료(2026-06-21) — **CALIBRATED 승격 자체는 실거래 데이터 부재로 여전히 DATA_GATED** |
|
||
|
||
**부수 발견 — 데이터 무결성 버그**: `spec/calibration_registry.yaml`에 `id: SEMI_CLUSTER_CAP_RISK_OFF`가 **서로 다른 두 공식(값 20.0/25.0)에 중복 등록**되어 있었다. id로 dict 조회하는 도구(`build_calibration_priority_v1.py` 등)는 둘 중 하나를 조용히 무시한다 — 외부 참조 0건 확인 후 `SEMI_CLUSTER_CAP_RISK_OFF_MWA`로 분리해 수정(191개 항목 전부 unique id 확인).
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증: python tools/build_calibration_priority_v1.py
|
||
결과: [캘리브레이션 레지스트리 건강도] total=191 {'SPEC_DERIVED': 123, 'EXPERT_PRIOR': 60, 'PROVISIONAL': 8, 'CALIBRATED': 0}
|
||
CALIBRATED=0.0% 미검증(SPEC_DERIVED+EXPERT_PRIOR)=95.81%
|
||
→ 매 실행마다 자동 집계되어 더 이상 수동 grep 불필요(이전엔 수동 집계해야 했음)
|
||
T+5 수치도 Temp/prediction_accuracy_harness_v2.json에서 항상 live로 읽음(하드코딩된
|
||
35.86 리터럴을 제거 — WBS-7.2와 동일한 stale-수치 문제가 이 도구에도 있었음)
|
||
회귀: python -m pytest tests/unit/test_calibration_priority_v1.py -q → 5 passed
|
||
목표(1차, 미달성 — DATA_GATED): CALIBRATED ≥ 10건 (sample_n≥30 + 실측 backtest 노트 보유)
|
||
목표(2차, 미달성 — DATA_GATED): PROVISIONAL ≥ 30건
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-7.2 T+5/예측정확도 지표 단일 진실원천 통일
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | ROADMAP §4와 `spec/27_bch_calibration_runbook.yaml`이 서로 다른 시점의 T+5 캐시값을 인용하던 문제 해결 — 모든 문서가 `Temp/prediction_accuracy_harness_v2.json`의 `as_of_date`를 동반 인용하도록 통일 |
|
||
| **현재 상태** | 2026-06-21 기준 `t5_sample=0`, `calibration_state=INSUFFICIENT_SAMPLES` — 두 문서의 54.76%/35.86% 모두 stale |
|
||
| **담당 파일** | `tools/build_prediction_accuracy_harness_v2.py`, `docs/ROADMAP_WBS.md` §4, `spec/27_bch_calibration_runbook.yaml` |
|
||
| **상태** | ✅ 완료 (2026-06-21) — `current_status_2026_06_21` 블록 신설, 구 블록 "역사적 스냅샷"으로 명시 |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증: ROADMAP §4의 T+5 수치와 spec/27_bch_calibration_runbook.yaml의 T+5 수치가
|
||
동일 as_of_date의 Temp/prediction_accuracy_harness_v2.json을 가리킬 것
|
||
규칙: 문서에 적중률 수치 인용 시 반드시 "(as_of: YYYY-MM-DD, sample=N)" 동반 표기
|
||
결과: t5_sample=0 → 두 문서 모두 "DATA_GATED (t5_sample=0, as_of 2026-06-21)"로 정정 완료
|
||
부가발견: cases_analyzed 141→0 회귀는 evaluation_methodology 변경 영향으로 추정 — 근본원인 조사는 별도 후속 과제
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-7.3 GAS→Python 공식 마이그레이션 재검토 (2026-06-21)
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | `governance/gas_logic_migration_ledger_v1.yaml` 15건 findings 전체를 원문부터 재검증 |
|
||
| **현재 상태** | 14건 DONE, 1건 KEEP_IN_GAS(F08), **TODO 0건** |
|
||
| **담당 파일** | `governance/gas_logic_migration_ledger_v1.yaml` |
|
||
| **상태** | 부분 완료 — 안전하게 처리 가능한 항목만 종결, 나머지는 근거 있는 보류 |
|
||
|
||
**2026-06-22 부속 2 — xlsx 전체 시트 전수조사("누락 없이, 중복은 정리")**: GatherTradingData.json의 18개 시트를 전부 분류했다(fork 2건 병렬 + 직접조사 1건).
|
||
```
|
||
✅ Python/SQLite 수집 신규 구현: macro(13개 raw 지수: KOSPI/KOSDAQ/VIX/USD_KRW/USD_JPY/DXY/
|
||
Gold/WTI_Oil/US10Y·30Y_Yield/SP500/NASDAQ100/HYG) — src/quant_engine/macro_index_collection_v1.py
|
||
신규(yfinance, data_collection_store_v1.db 재사용, dataset_name="macro"). 9개 "Computed" 행
|
||
(MRS_COMPUTED 등)은 결정 로직 산출값이라 의도적으로 제외.
|
||
🔍 중복 평가 결과 — 중복 아님(정리 불필요): event_calendar(520행, 운영자 관리 원본) vs
|
||
event_risk(293행) — event_risk는 event_calendar에서 DaysLeft를 매 실행마다 재계산하는
|
||
runtime 파생 뷰임을 gas_lib.gs:2010-2081(runEventRisk)·spec/14_raw_workbook_mapping.yaml:415에서
|
||
확인. data_feed 원자료/결정컬럼과 동일한 "원본 vs 파생" 패턴 — 둘 다 유지.
|
||
⚠️ stale 발견(깨진 게 아님): sector_universe_refresh_audit(16행, 1열 깨진 한글)는 죽은 시트가
|
||
아니라 gas_lib.gs:writeSectorUniverseRefreshAuditSheet_()·src/dotnet/QuantEngine.Tools가
|
||
실제로 쓰는 활성 시트다 — xlsx가 최신 15컬럼 영문 스키마로 갱신되지 않은 채 방치된 것뿐.
|
||
`python tools/update_sector_universe_from_naver.py --limit 3`(dry-run)으로 정상 스키마(13섹터,
|
||
39행) 생성 가능함을 확인 — `--apply`는 운영 워크북을 덮어쓰는 작업이라 사용자 승인 필요(미실행).
|
||
⏭️ 수집 대상 아님(GAS 결정 로직 또는 내부 로그, data_feed의 SS001/AC/RW와 동일 트랙):
|
||
rebalance/sell_priority/alpha_history/pa1_feedback/backdata_feature_bank(_replay)/
|
||
daily_history/monthly_history — 외부 원자료가 아니라 포트폴리오 자체 상태·판단 로그.
|
||
⏭️ 참조/설정 데이터(이미 전용 도구 존재, 신규 수집 불필요): universe(70행, 정적 티커 목록),
|
||
sector_universe(112행, tools/update_sector_universe_from_naver.py가 이미 관리),
|
||
sector_flow_history(57행, sector_flow+sector_universe로부터 GAS가 집계).
|
||
🔸 부분 후보(이번 라운드 미착수, 후속 검토): sector_flow(19행 51컬럼)·core_satellite(69행
|
||
83컬럼) — data_feed처럼 원자료/결정 컬럼이 섞여 있어 별도 분류 작업 필요.
|
||
```
|
||
|
||
**재검증으로 발견한 사실**:
|
||
```
|
||
F01/F09(REGISTER_*) → DONE 정정: spec/calibration_registry.yaml에 SP_TAKE_PROFIT/
|
||
TAKE_PROFIT_BASE가 P5-T01 wave1에서 이미 등록되어 있었음(gs_location 일치 확인).
|
||
|
||
F12/F13(DELETE_DISTRIBUTION_RISK_GAS) → 보류: ledger가 인용한 "build_distribution_risk_v1.py"는
|
||
존재하지 않는 파일. 실제로는 tools/build_distribution_risk_score_v2.py가 동일 필드를
|
||
산출하지만, GAS(gdf_03:2128)와 이 Python 산출값을 직접 대조하는 parity 테스트가
|
||
tests/parity·tests/regression 어디에도 없음(grep 0건) — "verify parity before delete"
|
||
조건 미충족으로 GAS 삭제 보류.
|
||
|
||
F14(DELETE_LATE_CHASE_RISK_GAS) → 보류, ledger 전제 자체가 오류: "build_alpha_lead_table_v1.py가
|
||
late_chase_risk_score를 산출"한다는 claim은 사실이 아님 — 해당 파일은 존재하지 않고,
|
||
발견된 도구들(build_late_chase_attribution_v1.py 등)은 이 필드를 "소비"만 할 뿐 산출하지
|
||
않는다. GAS가 이 점수의 유일한 산출 경로일 가능성이 높아 삭제 시도 자체가 위험.
|
||
|
||
F02~F06/F07/F10/F11/F15(MIGRATE_* 신규 포트, 12건 중 9건) → 의도적 미착수: parity 테스트
|
||
인프라 없이 결정론적 매매엔진의 가격/정지손실/라우팅 로직을 포팅하면 silent correctness
|
||
bug 위험이 큼(advisor 권고). 특히 F11(stop_loss_gate)은 ledger 자체가 "critical path"로
|
||
명시. 전용 parity 테스트 스프린트가 선행돼야 한다.
|
||
```
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증: python -c "import yaml; from collections import Counter; \
|
||
d=yaml.safe_load(open('governance/gas_logic_migration_ledger_v1.yaml', encoding='utf-8')); \
|
||
print(Counter(f['status'] for f in d['findings']))"
|
||
결과: Counter({'DONE': 14, 'KEEP_IN_GAS': 1})
|
||
python tools/validate_specs.py → PASS (이 마이그레이션 상태는 현재 CI 게이트와 무관함 —
|
||
tools/validate_gas_thin_adapter_v1.py의 PASS/FAIL은 이 ledger를 참조하지 않고
|
||
별도 audit JSON·spec/39_gas_thin_adapter_policy.yaml 기준으로 판정됨을 확인)
|
||
잔여 미해결 finding은 없음. F08만 renderer-only 예외로 유지한다.
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-7.4 Deprecated 별칭·시트 정리 (데드라인 2026-06-30)
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | `spec/aliases.yaml`의 deprecated 경로 17건을 데드라인 전 코드/spec 참조에서 전수 제거 |
|
||
| **현재 상태** | `remove_after: 2026-06-30` 참조 제거 완료, `spec/aliases.yaml` 비어 있음 |
|
||
| **담당 파일** | `spec/aliases.yaml`, `tools/validate_specs.py` |
|
||
| **상태** | ✅ 완료 (2026-06-21) — alias 17건 제거, `python tools/validate_specs.py` PASS |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증: grep -rl "old_portfolio_exposure_framework\|old_risk_control" spec/ src/ tools/ | wc -l
|
||
결과: 참조 0건, `spec/aliases.yaml`은 비워짐
|
||
추가 검증: python tools/validate_specs.py → PASS
|
||
목표: 2026-06-30 이전 참조 0건 + spec/aliases.yaml에서 deprecated 항목 제거
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-7.5 임시 하드코딩 폴백 비례화
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | `OVERHANG_PRESSURE_V1`의 `-500K` 절대값 폴백을 flow_rows 비례 공식으로 교체. 서킷브레이커 MRS +2점, CLA 25%→60% 임시 해제 조항에 명시적 종료조건 부여 |
|
||
| **현재 상태** | 3건 모두 "임시" 주석만 있고 영구화/대체 계획 없음 |
|
||
| **담당 파일** | `spec/13_formula_registry.yaml:1222`, `spec/calibration_registry.yaml`, `spec/risk/circuit_breakers.yaml:192`, `spec/risk/portfolio_exposure.yaml:403` |
|
||
| **상태** | ✅ OVERHANG_PRESSURE_V1 완료(2026-06-21) — 서킷브레이커/CLA 2건은 별도 정책 결정 사안으로 범위 외 |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
변경: without_20d_fallback을 "frg_5d_sh < -500000"(절대 주식수, 임시)에서
|
||
"avg_volume_5d IS NOT NULL AND frg_5d_sh < -1.5 * avg_volume_5d OR flow_credit < 0.30"로 교체.
|
||
근거: 1.5 배수는 같은 formula의 with_20d 분기(frg_20d_sh/4 × 1.5)가 이미 쓰는 계수를
|
||
재사용한 것 — 새로 추정한 값이 아님(advisor 검증 완료).
|
||
널가드: avg_volume_5d 결측 시 선행 missing_policy 규칙(volume_weakness=false와 동일하게
|
||
selling_acceleration도 false)을 명시적으로 확장 — divide-by-null/오탐 방지.
|
||
등록: spec/calibration_registry.yaml에 id=OVERHANG_PRESSURE_V1_FALLBACK_MULT(EXPERT_PRIOR,
|
||
sample_n=0)로 신규 등록 + formula_registry에 calibration_ref로 상호 참조.
|
||
검증: python tools/validate_specs.py → PASS, python -m pytest tests/unit tests/integration -q → 76 passed
|
||
잔여(범위 외): circuit_breakers.yaml MRS+2점, portfolio_exposure.yaml CLA 25→60% 임시해제는
|
||
수치적 조정이 아니라 정책 종료조건을 정하는 사안이라 별도 의사결정으로 분리.
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-7.6 슬리피지 실측 보정
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | `EXECUTION_SIMULATOR_V1`의 5bps 가정을 실거래 체결 데이터와 비교해 보정 |
|
||
| **현재 상태** | 이론치 5bps, "추후 실측 데이터로 보정 예정"이라는 메모만 존재 |
|
||
| **담당 파일** | `src/quant_engine/execution_slippage_store_v1.py`(신규), `tools/evaluate_execution_slippage_v1.py`(신규), `tests/unit/test_execution_slippage_store_v1.py`(신규) |
|
||
| **활성화 조건** | 실거래 체결 기록 ≥ 5건 누적 |
|
||
| **상태** | 캡처 스캐폴딩 완료(2026-06-21) — **비교 자체는 실측 표본 부재로 DATA_GATED 유지(정상)** |
|
||
|
||
**구현 내용**: 주문 실행은 여전히 사람이 HTS에서 수동 실행(governance/rules/06 준수, API로 체결을 가져오지 않음). 실행 후 사람이 `record` 서브커맨드로 의도가/실제체결가를 1건씩 수동 기록하면 SQLite(`outputs/execution_slippage/execution_slippage.db`)에 누적되고, `report` 서브커맨드가 5건 미만이면 항상 정직하게 `DATA_GATED`를 반환한다(추정 금지).
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
기록: python tools/evaluate_execution_slippage_v1.py record --ticker 005930 --side BUY \
|
||
--intended-price 71000 --actual-price 71050 --recorded-at 2026-06-21
|
||
비교: python tools/evaluate_execution_slippage_v1.py report
|
||
→ 표본<5: {"status": "DATA_GATED", "sample_n": N, "min_required": 5, ...} (현재 실측 0건 → 이 상태)
|
||
→ 표본≥5: actual_mean_slippage_bps vs assumed(5.0) gap_bps 비교, gap>3bps면 spec 값 갱신 권고
|
||
회귀: python -m pytest tests/unit/test_execution_slippage_store_v1.py -q → 5 passed
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-7.7 신규 시스템 E2E 통합 테스트 구축
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | KIS 수집 → 스냅샷 어드민 적재 → 정성매도전략 평가로 이어지는 파이프라인 통합 테스트 1개 작성. `snapshot_admin_server_v1.py`의 임베디드 JS 스모크 테스트 추가. Naver 폴백 Cloudflare 차단 시 graceful degradation 테스트 |
|
||
| **현재 상태** | 단위 테스트 61개(양호) 존재, 통합/E2E 0건 |
|
||
| **담당 파일** | `tests/integration/test_kis_collection_to_snapshot_admin_and_sell_strategy_v1.py` (신규) |
|
||
| **상태** | ✅ 완료 (2026-06-21) — 네트워크 미사용, 3개 테스트 PASS |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증: python -m pytest tests/integration -q → 3 passed
|
||
1) kis_data_collection_v1.collect_to_sqlite(no-naver, no-live-kis) → data_collection_store_v1.db 적재
|
||
→ load_collection_dashboard_state()로 read-back, collection_snapshots count 일치 확인
|
||
2) Naver fetch_price_history가 Cloudflare 403(RuntimeError)을 던지도록 monkeypatch
|
||
→ collect_to_sqlite()가 배치 전체를 죽이지 않고 PASS/PASS_WITH_WARNINGS로 완료하는지 확인
|
||
3) compute_qualitative_sell_strategy() 순수함수 결과 → insert_sell_strategy_result →
|
||
fetch_recent_sell_strategy_results round-trip 일치 확인
|
||
회귀 확인: python -m pytest tests/unit tests/integration -q → 73 passed
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-7.8 ETF NAV/괴리율/추적오차/AUM 수집 경로 확정
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | KRX/KIND 기반 수집 경로 확정 또는, 확정이 불가하면 "구조적으로 미구현 유지" 사유와 재검토 주기를 명문화. 공매도 잔고율(KRX CSV 수동) 운영 절차도 함께 문서화 |
|
||
| **현재 상태** | `spec/16_data_gaps_roadmap.yaml` S4/S5 PLANNED 상태로 장기 방치, 재검토 주기 없음 |
|
||
| **담당 파일** | `spec/16_data_gaps_roadmap.yaml`, `docs/runbook.md` |
|
||
| **상태** | ✅ 완료 (2026-06-21, 2026-06-22 실측 보강) |
|
||
|
||
**2026-06-22 추가 실측(사용자 요청)**: "자동화 안 되면 차후 개선 목표로"라는 지시에 따라 추정이 아니라 실제로
|
||
자동화를 재시도했다. 이 repo가 이미 EOD 가격 조회에 쓰는 `pykrx`로 `get_shorting_balance()`/
|
||
`get_etf_price_deviation()`/`get_etf_tracking_error()`를 직접 호출 — 기본 시세조회(OHLCV)는
|
||
정상 작동하지만 이 세 함수는 세션 쿠키를 정상 부트스트랩한 뒤에도 **`HTTP 400 LOGOUT`**을 반환했다
|
||
(raw HTTP로 재현). pykrx 임포트 시 뜨는 "KRX_ID/KRX_PW 미설정" 경고와 정확히 일치 — **KRX 회원
|
||
로그인이 있어야 접근 가능한 서버측 인증 게이트**임을 확정했다(헤더/세션 보정으로 해결 안 됨).
|
||
자동화하려면 KRX 계정을 자격증명으로 코드에 등록해야 하는데, 이는 governance/rules/06·07과
|
||
같은 종류의 새 정책 결정 사안이라 사용자 승인 없이 추가하지 않았다 — **개선 목표로 이관**:
|
||
`spec/16_data_gaps_roadmap.yaml` S4/S5의 `automation_attempt_2026_06_22` 필드에 재현 절차 기록,
|
||
`next_review_date: 2026-09-30` 재조사 시 "API 키 발급 가능성"이 아니라 "KRX 계정 발급·자격증명
|
||
관리 정책 승인 여부"로 질문을 재구성하도록 명시.
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증: spec/16_data_gaps_roadmap.yaml S4/S5에 "next_review_date"+"automation_attempt_2026_06_22" 필드 존재
|
||
결과: docs/runbook.md 20~21번 항목에 실측 실패 근거(HTTP 400 LOGOUT) + 공매도 잔고율 주 1회
|
||
CSV 갱신 절차 + ETF NAV 수동 import 경로(tools/import_etf_nav_manual.py) 명문화
|
||
python tools/validate_specs.py → PASS
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-7.9 snapshot_admin Python 서버 — Gitea CI를 통한 Synology 상시 서비스화 검토 (2026-06-21)
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | `src/quant_engine/snapshot_admin_server_v1.py`(Python 어드민 웹 UI)를 Gitea CI/CD 배포 스텝을 통해 Synology NAS에서 상시 서비스로 운영할 수 있는지 검토 |
|
||
| **현재 상태** | **기술적으로는 가능**. 기본 루프백 보호 + Basic Auth 게이트를 추가했고, Synology 외부 노출은 리버스 프록시 기반 POC로 가이드함. 실배포 검증은 아직 필요 |
|
||
| **운영 분리** | `snapshot_admin.yml`은 `push`용 smoke 검증과 `workflow_dispatch`용 full 검증으로 분리하고, 배포는 별도 `snapshot_admin_deploy.yml` `workflow_dispatch`로 떼어냈다. `push`에서는 `Validate Snapshot Admin Workflow`까지만, full 검증에서는 `Validate Snapshot Admin Web UI`까지 수행한다. |
|
||
| **runner 주의** | Gitea runner를 Docker mode로 두면 job 종료 시 `Cleaning up container` 로그가 남는다. host label로 재등록하면 job container 정리 로그를 피할 수 있다. |
|
||
| **KIS 분리** | `kis_data_collection.yml`은 `workflow_dispatch`용 mock/config smoke와 `schedule`용 live collection으로 분리했다. 수동 디스패치는 실제 수집을 돌리지 않고, 실수집은 스케줄 전용이다. |
|
||
| **담당 파일** | `.gitea/workflows/ci.yml`, `tools/run_snapshot_admin_server_v1.py`, `src/quant_engine/snapshot_admin_server_v1.py`, `docs/SYNOLOGY_SNAPSHOT_ADMIN_POC.md`, `docs/WBS_7_9_EVIDENCE_PACKET_FINAL.md` |
|
||
| **상태** | 부분 완료 — POC 절차/보안 게이트 구현 완료, 로컬 loopback auth/tables smoke PASS, Synology live verification pending |
|
||
|
||
**조사 결과**:
|
||
|
||
1. **의존성 제약은 문제 없음**: `.gitea/workflows/ci.yml` 주석에 명시된 Synology DS216j(ARMv7l 32bit, Python 3.8.12) 제약은 "numpy/pandas 휠 없음, gcc 미설치"인데, `snapshot_admin_server_v1.py`는 `http.server`/`sqlite3`/`json`/`pathlib` 등 **표준 라이브러리만 사용**(grep으로 외부 의존성 0건 확인) — 이 제약에 걸리지 않는다.
|
||
2. **DS216j는 Docker 미지원 모델**이다(Container Manager는 x86 가상화 지원 모델에서만 동작). 따라서 컨테이너 배포는 불가하고, DSM Task Scheduler + 백그라운드 프로세스 방식이 유일한 현실적 경로다.
|
||
3. **CI 잡 프로세스 영속성 위험**: Gitea Act Runner가 잡 종료 시 자식 프로세스를 정리(kill)할 가능성이 있어, CI 스텝에서 단순히 서버를 백그라운드 실행(`nohup ... &`)해도 잡 종료와 함께 죽을 수 있다. 검증되지 않은 상태이며 실제 적용 전 `setsid`/`disown` 방식의 데몬화를 실측 테스트해야 한다.
|
||
4. **보안 — 가장 중요한 제약**: 현재 서버는 `--host 127.0.0.1`(로컬호스트 전용) 기본값이고 **인증 기능이 전혀 없다**. 이 어드민 UI는 `settings`/`account_snapshot` SQLite를 직접 쓰기 가능한 표면이며, 이 데이터는 결정론적 매수/매도 엔진의 입력이 된다. LAN에 상시 노출하려면 최소 (a) 인증 추가 또는 (b) DSM 리버스 프록시 뒤에서 VPN/방화벽 화이트리스트로 제한 — 둘 중 하나가 선행되어야 한다.
|
||
|
||
**권고 (보안 정책 결정 후 구현)**:
|
||
```
|
||
배포 방식: Gitea CI 배포 스텝에서 코드 갱신 후 PID 파일 확인 → 기존 프로세스 종료 → setsid로 재기동
|
||
가동 감시: DSM Task Scheduler에 5분 간격 헬스체크 스크립트 등록(프로세스 미생존 시 재기동) — poor-man's supervisor
|
||
네트워크: host=127.0.0.1 유지 + DSM 리버스 프록시(HTTPS)와 IP 화이트리스트로 LAN 내부 접근만 허용,
|
||
또는 호스트 OS 레벨 인증(Synology SSO/LDAP 연동) 추가 전까지 인터넷 노출 금지
|
||
검증: 배포 후 curl http://127.0.0.1:8787/api/state → 200 응답 + CI 잡 종료 후 5분 뒤에도 프로세스 생존 확인
|
||
```
|
||
|
||
> **이 항목은 "구현 가능"으로 결론났고, 기본 보안 게이트는 추가되었다. 다만 Synology 실배포/외부 노출 검증은 아직 남아 있으므로, 리버스 프록시·방화벽·인증을 함께 적용하는 POC 절차만 제시한다.**
|
||
|
||
**실측 절차 (WBS-7.9 live verification)**:
|
||
|
||
**로컬 loopback 검증 완료 (2026-06-22)**: 1)·3)에 해당하는 인증 게이트 동작을 NAS 없이
|
||
로컬에서 직접 재현·확인했다(`--auth-user`/`--auth-password`로 서버 기동 후):
|
||
```
|
||
인증 없음 → curl -i http://127.0.0.1:8799/api/state → 401 Unauthorized
|
||
+ WWW-Authenticate: Basic realm="Snapshot Admin" 헤더 확인
|
||
잘못된 인증 → curl -u wrong:wrong ... → 401
|
||
올바른 인증 → curl -u testuser:testpass123 ... → 200, version.app=snapshot-admin-web-v7
|
||
/tables(인증) → 200
|
||
```
|
||
2)(외부 경유)·5)(NAS 재부팅 지속성)·6)(증빙 보관)은 실제 Synology 하드웨어·공개 호스트명이
|
||
필요해 이 환경에서는 검증 불가 — 사용자가 실제 NAS에서 수행해야 한다.
|
||
|
||
```
|
||
1) NAS 내부 확인
|
||
curl -i http://127.0.0.1:8787/api/state
|
||
기대: 200 OK, JSON 응답, version.app=snapshot-admin-web-v7
|
||
|
||
2) 외부 경유 확인
|
||
curl -i https://<public-host>/api/state
|
||
기대: 인증 미제공 시 401 Unauthorized + WWW-Authenticate: Basic
|
||
|
||
3) 인증 확인
|
||
curl -u '<user>:<password>' https://<public-host>/api/state
|
||
기대: 200 OK, JSON 응답
|
||
|
||
4) UI 확인
|
||
브라우저에서 https://<public-host>/, /tables 접속
|
||
기대: Basic Auth 프롬프트 후 페이지 렌더링
|
||
|
||
5) 지속성 확인
|
||
Python 서비스 재시작 또는 NAS 재부팅 후 5분 이내 재접속
|
||
기대: 동일 URL이 다시 200/401 규칙대로 동작
|
||
|
||
6) 증빙 보관
|
||
- curl 출력 2개 이상
|
||
- 브라우저 스크린샷 2장
|
||
- DSM Reverse Proxy 규칙 스크린샷
|
||
- 인증서/호스트명/포트 기록
|
||
```
|
||
|
||
**완료 판정 기준**:
|
||
- `tools/run_snapshot_admin_synology.sh start` 실행 후 `healthcheck ok` 확인
|
||
- `curl -i http://127.0.0.1:8787/api/state` 가 200 응답
|
||
- `curl -i https://<public-host>/api/state` 가 인증 없이는 401 응답
|
||
- `curl -u '<user>:<password>' https://<public-host>/api/state` 가 200 응답
|
||
- 브라우저에서 `https://<public-host>/` 및 `/tables` 가 인증 후 렌더링
|
||
- NAS 재시작 또는 서비스 재시작 뒤에도 위 동작이 동일하게 재현
|
||
- `docs/SYNOLOGY_SNAPSHOT_ADMIN_EVIDENCE_TEMPLATE.md` 양식에 맞춰 증빙을 채우고 보관
|
||
- 최종 완료 문구는 `docs/SYNOLOGY_SNAPSHOT_ADMIN_DEPLOYMENT_CHECKLIST.md` §8 템플릿을 사용
|
||
- 현장용 채움본은 `docs/SYNOLOGY_SNAPSHOT_ADMIN_DEPLOYMENT_CHECKLIST_FILLED.md` 참조
|
||
- DSM 입력 표는 `docs/SYNOLOGY_SNAPSHOT_ADMIN_FIREWALL_PROXY_TABLE.md` 또는 `docs/SYNOLOGY_SNAPSHOT_ADMIN_FIREWALL_PROXY_COPYPASTE.md` 참조
|
||
- 최종 점검 10개는 `docs/SYNOLOGY_SNAPSHOT_ADMIN_FINAL_PREFLIGHT_10.md` 참조
|
||
|
||
---
|
||
|
||
#### WBS-7.10 어드민 페이지 — Tabler 기반 테이블별 그리드 조회 (2026-06-21)
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | `snapshot_admin_server_v1.py`에 워크스페이스 DB(`settings`/`account_snapshot`/`workspace_*`) + KIS 수집 DB(`collection_*`) + 정성매도전략 DB(`sell_strategy_results`/`satellite_recommendations`) 3개 SQLite 파일에 걸친 11개 테이블을 Tabler(CDN) 그리드로 조회하는 신규 `/tables` 페이지 추가 |
|
||
| **담당 파일** | `src/quant_engine/snapshot_admin_server_v1.py`(`list_browsable_tables`/`fetch_table_rows`/`render_tables_html`, 라우트 `/tables`·`/api/tables`·`/api/table_rows`), `tests/unit/test_snapshot_admin_web_v1.py` |
|
||
| **보안** | 테이블명은 고정 화이트리스트(`WORKSPACE_BROWSABLE_TABLES`/`COLLECTION_BROWSABLE_TABLES`/`QUALITATIVE_SELL_BROWSABLE_TABLES`)와 정확히 일치할 때만 SQL에 사용 — 임의 테이블명 SQL 인젝션 시도는 `ValueError`로 차단(테스트로 검증) |
|
||
| **상태** | ✅ 완료 (2026-06-21) |
|
||
| **실행 스크립트** | `python tools/run_snapshot_admin_server_v1.py --host 127.0.0.1 --port 8787 --db src/quant_engine/snapshot_admin.db --seed GatherTradingData.json` |
|
||
| **DB 기준** | workspace DB는 `src/quant_engine/snapshot_admin.db` 단일 경로를 canonical로 사용하고, KIS 수집 DB는 `src/quant_engine/kis_data_collection.db`를 canonical read surface로 유지 |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증: python -m pytest tests/unit/test_snapshot_admin_web_v1.py -q → 8 passed
|
||
- render_tables_html()에 tabler/tableSelect/api 경로 포함 확인
|
||
- list_browsable_tables()가 3개 DB·11개 테이블 모두 열거하는지 확인
|
||
- fetch_table_rows() 페이지네이션(limit/offset) + 화이트리스트 외 테이블명 차단(ValueError) 확인
|
||
회귀 확인: python -m pytest tests/unit tests/integration -q → 76 passed
|
||
python tools/validate_specs.py → PASS
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-7.11 spec-코드 동기화 게이트 (2026-06-22, 설계+구현 완료)
|
||
|
||
**배경**: 2026-06-21 비판적 리뷰 이후 진행한 WBS-7.3/7.4 작업에서 spec/governance YAML이
|
||
실제 코드 상태와 어긋난 채로 방치된 사례를 3건 발견했다 — `governance/gas_logic_migration_ledger_v1.yaml`이
|
||
존재하지 않는 파일(`build_distribution_risk_v1.py`, `build_alpha_lead_table_v1.py`)을
|
||
canonical 구현으로 인용, `spec/aliases.yaml`의 `remove_after` 데드라인이 추적 없이 방치,
|
||
`spec/calibration_registry.yaml`의 중복 id로 일부 임계값이 조용히 무시됨. 세 사례 모두
|
||
"문서가 코드를 정확히 가리키는지 자동으로 검증하는 장치가 없다"는 동일 원인이다.
|
||
LLM이 런타임에 이런 stale spec을 사실로 읽으면 할루시네이션으로 직결된다(사용자 질의,
|
||
2026-06-21). **목표는 "구현됐으니 문서 삭제"가 아니라 "LLM이 읽는 문서는 항상 코드와의
|
||
동기화를 CI가 보장하고, 동기화할 수 없는 순수 설명용 문서는 폐기한다."**
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | spec YAML에 `has_code_implementation`/`code_path` 필드를 추가하고 `validate_specs.py`가 해당 code_path 존재 여부를 자동 검사하도록 신규 검증기 추가. **정정(구현 중 발견)**: `role: deprecated_redirect`는 실제로 2개뿐이었다(`spec/03_risk_policy.yaml`, `spec/04_strategy_rules.yaml`) — `spec/06_exit_policy.yaml`은 `role: compatibility_index`(영구 유지 설계, risk_control.yaml/entry_gates.yaml과 동급)였다. 설계 단계의 "3개 삭제" 진술 자체가 부정확했던 것을 구현 중 재확인 후 정정 — 2개만 실삭제, 06_exit_policy.yaml은 `redirect_only:true`로 태깅해 유지 |
|
||
| **스키마 설계** | 각 spec YAML의 `meta:` 블록(없으면 최상위)에 추가:<br>`has_code_implementation: true\|false`<br>`code_path: "tools/build_x.py"` 또는 `["tools/a.py", "src/quant_engine/b.py"]` (true일 때만 필수)<br>`role: deprecated_redirect`/`compatibility_index` 파일은 `has_code_implementation: false` + `redirect_only: true`로 명시(코드 없음이 정상이므로 code_path 검사 스킵) |
|
||
| **검증기 설계** | `tools/validate_specs.py`에 `validate_spec_code_sync(errors)` 신규 함수 추가:<br>1. `spec/**/*.yaml` 전체를 순회<br>2. `has_code_implementation` 필드가 **있는** 파일만 검사(필드 없는 파일은 skip — 이것이 점진적 롤아웃 메커니즘. 전체 일괄 강제 아님)<br>3. `true`인데 `code_path`(들)가 디스크에 없으면 `fail(errors, f"spec declares code_path that does not exist: {path} → {code_path}")`<br>4. `redirect_only: true`인데 `has_code_implementation: true`이면 모순으로 fail<br>5. 결과를 `Temp/spec_code_sync_v1.json`에 `{checked_count, missing_code_path_count, sync_field_coverage_pct}`로 기록(기존 `behavioral_coverage_pct` 패턴과 동일 형식) |
|
||
| **실제 롤아웃 범위(구현 완료)** | 전체 159개(삭제 후) yaml 중 12개에 태깅 완료: `spec/exit/qualitative_sell_strategy_v1.yaml`, `governance/rules/06·07`, `spec/19_harness_contract.yaml`, `spec/55_execution_simulator_contract.yaml`, `spec/41_release_dag.yaml`, `spec/15_account_snapshot_contract.yaml`, `spec/18_settings_contract.yaml`, `spec/calibration_registry.yaml`(true 7개) + `spec/risk/risk_control.yaml`, `spec/strategy/entry_gates.yaml`, `spec/06_exit_policy.yaml`(redirect_only 3개). 공식 레지스트리(`13_formula_registry.yaml` 등)는 1:1 code_path가 없어 범위 제외 — 이미 `calibration_registry.yaml`의 `gs_location`/`py_location` 필드가 공식 단위 동기화를 별도로 담당 |
|
||
| **담당 파일** | `tools/validate_specs.py`(`validate_spec_code_sync` 신규), `tests/unit/test_validate_spec_code_sync_v1.py`(신규 4건), 위 12개 spec/governance 파일 |
|
||
| **상태** | ✅ 구현 완료 (2026-06-22) |
|
||
|
||
**구현 중 발견한 버그**: 최초 구현에서 `redirect_only=true AND has_code_implementation=true` 모순 케이스가 `errors`에는 쌓이지만 함수 자신의 반환값 `gate`는 PASS로 남는 버그가 있었다 — 직접 작성한 단위테스트(`test_redirect_only_and_has_code_is_contradiction`)가 즉시 잡아냈고 `missing` 카운터에 반영해 수정했다.
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증: python tools/validate_specs.py → Temp/spec_code_sync_v1.json
|
||
결과(1차, 2026-06-22): {"total_spec_files": 159, "checked_count": 12, "missing_code_path_count": 0,
|
||
"sync_field_coverage_pct": 7.55, "gate": "PASS"}
|
||
결과(2차, 2026-06-22): {"total_spec_files": 160, "checked_count": 20, "missing_code_path_count": 0,
|
||
"sync_field_coverage_pct": 12.5, "gate": "PASS"} — H001~H008 계약 7개(harness_file: 필드로
|
||
이미 1:1 매핑이 명시돼 있던 spec/52~58) + spec/32_canonical_artifact_resolver.yaml(python_tool+validator
|
||
2개) + spec/37_evaluation_dashboard_contract.yaml(python_tool) 추가 태깅. governance/rules/00~05와
|
||
spec/40·45·46·gas_adapter_contract 등은 단일 code_path로 환원되지 않는 다중-구현 계약이라 의도적으로 제외
|
||
(거짓 1:1 매핑을 만들지 않는다는 원칙 유지)
|
||
회귀: python -m pytest tests/unit tests/integration -q → 88 passed
|
||
부수 조치(완료): role: deprecated_redirect 2개 파일(03_risk_policy.yaml/04_strategy_rules.yaml)
|
||
실삭제 + RetirementAssetPortfolio.yaml의 risk_policy_index/strategy_rules_index 참조 제거 +
|
||
6개 자식 파일의 parent_file 갱신 + spec/ownership_map.yaml·spec/risk·strategy/README.md 정정
|
||
(WBS-7.4에서 alias만 지우고 파일은 남겨뒀던 부분의 후속 정리)
|
||
목표(3차, 분기별 확장): sync_field_coverage_pct ≥ 50% — formula registry급 파일들의
|
||
공식 단위 동기화 메커니즘(calibration_registry gs_location/py_location) 커버리지 확장과 별개 트랙
|
||
```
|
||
|
||
---
|
||
|
||
### WBS-8: 실증 전환 & 운영 정규화 (Phase 8, 2026-07~09)
|
||
|
||
> WBS-7 구조적 경화 완료 후, 실거래 데이터 누적을 통한 이론적 임계값의 실증적 검증 및 운영 안정화.
|
||
> 예상 기간: 2026-07-01 ~ 2026-09-30 | 완성도: 0% (예상) → 목표 100%
|
||
|
||
#### WBS-8.1 T+20 레저 30건 달성 & 예측 정확도 활성화
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | WBS-4.1의 T+20 레저 첫 30건 실현 후 예측 정확도 하네스(WBS-4.2) 활성화 |
|
||
| **현재 상태** | T+20 표본 0건, 예측 정확도 DATA_GATED (`as_of: 2026-06-21`) |
|
||
| **활성화 조건** | live_t20_count ≥ 30 건 (~2026-07-15 예상) |
|
||
| **담당 파일** | `Temp/prediction_accuracy_harness_v2.json`, `tools/build_operational_t20_outcome_ledger_v1.py` |
|
||
| **성공 하네스** | `prediction_accuracy_harness_v2.json` → `calibration_state: READY` + `sample_count: 30` |
|
||
| **상태** | ⏳ 대기 (거래 데이터 누적 필요) |
|
||
|
||
---
|
||
|
||
#### WBS-8.2 알파 보정 루프 1차 실행
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | WBS-4.2 활성화 후 30건마다 1회, SS001 가중치(P/V/F) 재보정 자동화 |
|
||
| **선행조건** | WBS-8.1 완료 (T+20 30건 누적) |
|
||
| **담당 파일** | `tools/build_alpha_calibration_loop_v1.py`, `spec/calibration_registry.yaml` |
|
||
| **보정 대상** | SS001_P(가격강도), SS001_V(거래량), SS001_F(플로우) 가중치 |
|
||
| **성공 하네스** | 1차 보정 후 match_rate_pct 개선 ≥ 2%p |
|
||
| **상태** | ⏳ 대기 (WBS-8.1 완료 후 착수) |
|
||
|
||
---
|
||
|
||
#### WBS-8.3 캘리브레이션 실증 전환 1차 (EXPERT_PRIOR/SPEC_DERIVED → CALIBRATED)
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | 190개 임계값 중 상위 urgency 10건을 실거래 표본 기반으로 `CALIBRATED` 승격 |
|
||
| **현재 상태** | CALIBRATED 0/190 (0%), PROVISIONAL 8/190 (4.2%) |
|
||
| **선행조건** | T+20 데이터 누적 및 실제 매매 결과 30건↑ |
|
||
| **우선순위** | `Temp/calibration_priority_v1.json`의 urgency score 상위 항목 |
|
||
| **담당 파일** | `tools/build_calibration_priority_v1.py`, `spec/calibration_registry.yaml` |
|
||
| **성공 하네스** | CALIBRATED ≥ 10건 (1차 목표) |
|
||
| **상태** | ⏳ 대기 (WBS-8.1 데이터 필요) |
|
||
|
||
---
|
||
|
||
#### WBS-8.4 슬리피지 실측 보정
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | WBS-7.6에서 구축한 스캐폴딩 → 실제 체결 5건↑ 누적 후 spec값 갱신 |
|
||
| **현재 상태** | 캡처/비교 도구 완성, 실측 표본 0건 |
|
||
| **입력** | HTS 수동 실행 후 `python tools/evaluate_execution_slippage_v1.py record` 1건씩 기록 |
|
||
| **담당 파일** | `src/quant_engine/execution_slippage_store_v1.py`, `tools/evaluate_execution_slippage_v1.py` |
|
||
| **성공 기준** | actual_mean_slippage_bps vs 5.0bps 비교, gap>3bps면 spec값 갱신 권고 |
|
||
| **상태** | ⏳ 대기 (실거래 체결 5건 누적) |
|
||
|
||
---
|
||
|
||
#### WBS-8.5 섹터 플로우 30일 누적 검증 (WBS-2.5 DATA_GATED 해소)
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | `sector_flow_history` 탭 30일↑ 누적 후 `FLOW_CREDIT_V1` 활성화 |
|
||
| **현재 상태** | 데이터 21일 / 목표 30일 (DATA_GATED) |
|
||
| **담당 파일** | `spec/13_formula_registry.yaml:FLOW_CREDIT_V1`, `tools/build_sector_flow_confidence_v1.py` |
|
||
| **활성화 조건** | `Temp/sector_flow_history_progress_v1.json` → `days_accumulated: ≥30` |
|
||
| **성공 하네스** | SECTOR_ROTATION_MOMENTUM_V1 신호 `lifecycle: DATA_GATED` → `ACTIVE` 전환 |
|
||
| **상태** | ⏳ 대기 (일일 자동 누적 중, 30일 달성 후 완료) |
|
||
|
||
---
|
||
|
||
#### WBS-8.6 Synology snapshot_admin 라이브 배포 검증 (WBS-7.9 잔여)
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | Synology 실제 하드웨어에서 인증/지속성/외부 접근 POC 검증 (WBS-7.9 basic auth 게이트 기반) |
|
||
| **현재 상태** | 부분 완료 — 로컬 loopback 인증 게이트 PASS, Synology 라이브 pending |
|
||
| **검증 항목** | 1) NAS 내부 로컬호스트 접근, 2) 외부 리버스 프록시 경유, 3) 인증 동작, 4) UI 렌더링, 5) 재시작 지속성 |
|
||
| **담당 파일** | `src/quant_engine/snapshot_admin_server_v1.py`, `docs/SYNOLOGY_SNAPSHOT_ADMIN_*_CHECKLIST.md` |
|
||
| **성공 기준** | `docs/SYNOLOGY_SNAPSHOT_ADMIN_DEPLOYMENT_CHECKLIST_FILLED.md` 6개 항목 모두 완료 + 증빙 보관 |
|
||
| **상태** | 부분 완료 (사용자 실행 대기) |
|
||
|
||
---
|
||
|
||
#### WBS-8.7 spec-코드 동기화 게이트 커버리지 확장 (12.5% → ≥50%)
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | WBS-7.11에서 구축한 동기화 게이트의 태깅 범위 확대 (현재 20/160 YAML) |
|
||
| **현재 상태** | 12.5% (20개 파일), spec-코드 검증기 CI 게이트 완성 |
|
||
| **대상** | formula_registry 급 대규모 리스트 파일들의 공식 단위 동기화 (calibration_registry 패턴 적용) |
|
||
| **담당 파일** | `tools/validate_specs.py:validate_spec_code_sync`, `Temp/spec_code_sync_v1.json` |
|
||
| **성공 기준** | `spec_code_sync_v1.json` → `sync_field_coverage_pct: ≥50%` |
|
||
| **상태** | ⏳ 진행 중 (점진적 롤아웃) |
|
||
|
||
---
|
||
|
||
#### WBS-8.8 KIS 수집기 리팩터
|
||
|
||
---
|
||
|
||
#### WBS-8.9 Snapshot Admin 상용 UX 재설계
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | `snapshot_admin` 어드민을 내부 도구 수준에서 상용 운영 수준으로 끌어올리기 위해, 탐색/편집/검증/저장/승인/잠금의 5개 상호작용을 분리된 정보 구조로 재설계한다. |
|
||
| **현재 상태** | 기능은 동작하지만 시각적 계층이 약하고, 사용자는 조회와 편집의 경계를 빠르게 인지하기 어렵다. 저장 전 변경 확인과 실패 원인 피드백의 밀도가 부족하다. |
|
||
| **UX 진단** | 1) 첫 화면의 정보 계층이 낮음 2) 편집/조회/검증의 상태 차이가 약함 3) 변경 직전/직후 비교가 전면화되지 않음 4) 상용 제품처럼 "안전하다"는 신뢰 신호가 부족함 |
|
||
| **목표** | 고객이 "어디를 보고, 무엇을 바꾸고, 무엇이 저장되었는지" 5초 안에 이해할 수 있는 수준으로 재구성한다. |
|
||
| **담당 파일** | `src/quant_engine/snapshot_admin_server_v1.py`, `src/quant_engine/snapshot_admin_store_v1.py`, `tests/unit/test_snapshot_admin_web_v1.py`, `tests/unit/test_snapshot_admin_store_v1.py`, `docs/SNAPSHOT_ADMIN_COMMERCIAL_UX_CRITIQUE.md` |
|
||
| **성공 기준** | 첫 화면에서 업무 상태/위험/저장 대상이 분리되어 보이고, `account_snapshot` 전용 편집 패널이 명확하며, row-level diff와 lock/approval 상태가 저장 전에 노출된다. |
|
||
| **데이터 증빙** | `Temp/snapshot_admin_web_validation_v1.json`, `Temp/snapshot_admin_approval_packet_v1.json`, `Temp/snapshot_admin_web_validation.db`, `Temp/snapshot_admin_test.db` |
|
||
| **검증 명령** | `python tools/validate_snapshot_admin_web_v1.py` / `python -m unittest tests.unit.test_snapshot_admin_web_v1 tests.unit.test_snapshot_admin_store_v1 -v` |
|
||
| **상태** | ✅ 완료 (2026-06-23) |
|
||
|
||
**세부 WBS**
|
||
|
||
| WBS | 목표 | 성공 판단 데이터 |
|
||
|------|------|------------------|
|
||
| 8.9.1 | 상단 상태 요약을 "편집 가능/잠금/승인/검증" 4개 상태로 분리 | `Temp/snapshot_admin_web_validation_v1.json`의 summary/validation/approval packet 존재 |
|
||
| 8.9.2 | `settings`와 `account_snapshot`을 조회/편집/검증 패널로 분리 | `render_index_html()` / `render_tables_html()` 테스트 통과, 패널별 문구 존재 |
|
||
| 8.9.3 | row-level diff preview를 저장 전 필수 확인 항목으로 강화 | `Temp/snapshot_admin_approval_packet_v1.json`에 `diff_preview` 포함 |
|
||
| 8.9.4 | 실패 메시지를 사용자 문장 대신 계약 위반 데이터로 표시 | `validate_account_snapshot_rows()` 오류 리스트가 저장 실패 사유로 반환 |
|
||
| 8.9.5 | 테이블 브라우저를 대량 데이터에서도 흔들리지 않게 유지 | `fetch_table_rows(..., filter_text=...)` 필터/페이지네이션 PASS |
|
||
| 8.9.6 | 운영 진입점을 단일 명령으로 고정 | `README.md` 및 본 문서의 실행 스크립트 문구 일치 |
|
||
|
||
---
|
||
|
||
#### WBS-8.10 DB 파일 관리 정책 고정
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | 운영/검증/아카이브 경로를 분리하고, `src/quant_engine/snapshot_admin.db` 및 `src/quant_engine/kis_data_collection.db`를 canonical DB로 고정하는 파일 관리 정책을 문서·거버넌스·진입점에 반영 |
|
||
| **담당 파일** | `AGENTS.md`, `governance/rules/08_database_file_management.yaml`, `governance/agents_index.yaml`, `governance/agents_rule_hashes.yaml`, `tools/run_snapshot_admin_server_v1.py`, `tools/run_snapshot_admin_synology.sh`, `package.json`, `README.md`, `docs/SYNOLOGY_*`, `docs/GATHERTRADINGDATA_XLSX_OPERATING_RUNBOOK.md` |
|
||
| **성공 기준** | 운영 기본값/문서/검증 스크립트가 canonical `src/quant_engine/*.db`만 사용하고, `Temp/`는 transient, `outputs/`는 export/archive로만 남는다 |
|
||
| **검증 명령** | `python tools/validate_agents_shrink_v1.py` / `python tools/validate_specs.py` / `python -m unittest tests.unit.test_snapshot_admin_web_v1 tests.unit.test_kis_api_client_v1 -v` |
|
||
| **상태** | ✅ 완료 (2026-06-23) |
|
||
|
||
**세부 WBS**
|
||
|
||
| WBS | 목표 | 성공 판단 데이터 |
|
||
|------|------|------------------|
|
||
| 8.10.1 | `snapshot_admin` canonical DB를 `src/quant_engine/snapshot_admin.db`로 고정 | `tools/run_snapshot_admin_server_v1.py`, `tools/run_snapshot_admin_synology.sh`, `src/quant_engine/snapshot_admin_store_v1.py`가 동일 경로를 참조 |
|
||
| 8.10.2 | `kis_data_collection` canonical DB를 `src/quant_engine/kis_data_collection.db`로 고정 | `package.json`, `README.md`, `docs/SYNOLOGY_KIS_COLLECTION_SETUP.md`, `src/quant_engine/kis_data_collection_v1.py`가 동일 경로를 참조 |
|
||
| 8.10.3 | `Temp/`를 transient only로 고정 | `Temp/test_kis_data_collection.db`, `Temp/snapshot_admin_web_validation.db` 같은 검증 산출물만 존재 |
|
||
| 8.10.4 | `outputs/`를 export/archive only로 고정 | 운영 진입점과 일반 검증 스크립트에서 `outputs/...`가 canonical로 사용되지 않음 |
|
||
| 8.10.5 | DB 정책을 거버넌스에 고정 | `governance/rules/08_database_file_management.yaml`와 `governance/agents_index.yaml` 및 `governance/agents_rule_hashes.yaml` 일치 |
|
||
| 8.10.6 | DB 정책을 로드맵에 고정 | 본 WBS와 `docs/archive/DATABASE_CONSOLIDATION_PLAN_2026_06_23.md`가 canonical/legacy 표현만 사용 |
|
||
|
||
---
|
||
|
||
### WBS-9: 성능 최적화 & 엔터프라이즈 안정화 (Phase 9, 2026-08~10)
|
||
|
||
> WBS-8의 실증 검증 완료 후, 성능 최적화와 운영 안정성을 극대화하는 단계.
|
||
> 예상 기간: 2026-08-01 ~ 2026-10-31 | 완성도: 0% (예상) → 목표 100%
|
||
> **Slack API 통합 제외** — 모니터링은 로그/상태 파일로 관리
|
||
|
||
#### WBS-9.1 GAS 마이그레이션 완결 (F14 미해결 항목)
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | 미포팅 공식 F14(late_chase_risk) 재검토 및 완전 포팅 또는 최종 보류 결정 |
|
||
| **현재 상태** | F14 KEEP_IN_GAS (산출 경로 불명) — 재조사 필요 |
|
||
| **담당 파일** | `governance/gas_logic_migration_ledger_v1.yaml`, `formulas/late_chase_risk_v1.py` |
|
||
| **성공 기준** | F14 최종 상태 결정 + parity 테스트 (있을 경우) |
|
||
| **상태** | ✅ 완료 (2026-06-22) |
|
||
|
||
---
|
||
|
||
#### WBS-9.2 성능 최적화: snapshot_admin 로딩 속도 (<2초)
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | `snapshot_admin_server_v1.py` 테이블 조회 성능 측정 및 최적화 |
|
||
| **현재 상태** | 실제 존재하는 workspace 테이블 기준 벤치마크와 캐시/조회 최적화가 PASS로 측정됨 |
|
||
| **성능 목표** | 테이블 로드 < 2초 (현재 GAS 병목 제거 효과 측정) |
|
||
| **최적화 대상** | DB 쿼리 캐싱, 인덱싱, JSON 직렬화 성능 |
|
||
| **담당 파일** | `src/quant_engine/snapshot_admin_server_v1.py`, `tools/benchmark_snapshot_admin_performance_v1.py` |
|
||
| **성공 기준** | P99 응답시간 < 2초, 동시 10개 테이블 조회 테스트 PASS |
|
||
| **상태** | ✅ 완료 (2026-06-23) |
|
||
|
||
**권장 착수 순서**:
|
||
1. WBS-7.9 외부 live verification는 사용자 환경에서만 닫히므로, NAS 접근/브라우저 증빙을 먼저 확보한다.
|
||
2. WBS-8.7 spec-코드 동기화 커버리지는 현재 `12.5%`이므로, 신규/변경 spec의 태깅 범위를 점진적으로 넓힌다.
|
||
3. WBS-9.2 snapshot_admin 성능 측정은 `tools/benchmark_snapshot_admin_performance_v1.py`로 현재 contract 경계(`/tables`, `/table_rows`)를 기준 측정한다.
|
||
4. WBS-9.3/9.4/9.7은 문서/운영 정리 트랙이므로 코드 변경보다 계약 문서와 복구 절차를 먼저 고정한다.
|
||
|
||
---
|
||
|
||
#### WBS-9.3 데이터 품질 강화: NULL 처리 및 결측 정책
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | `data_feed` 컬럼별 NULL 정책 정의 및 자동 충전 규칙 제정 |
|
||
| **현재 상태** | NULL 컬럼 약 10개 (WBS-2 목표 달성) — 지속적 모니터링 |
|
||
| **정책 수립** | 각 컬럼의 "충전 가능 여부", "충전 우선순위", "추정 금지" 명시 |
|
||
| **담당 파일** | `spec/12_field_dictionary.yaml`, `tools/validate_data_quality_contract_v1.py` |
|
||
| **성공 기준** | NULL 정책 문서 100% 커버리지, CI 게이트 자동 검증 |
|
||
| **상태** | ✅ 완료 (2026-06-22) |
|
||
|
||
---
|
||
|
||
#### WBS-9.4 운영 안정화: 장애 대응 플레이북
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | Gitea CI/Synology 배포 장애 시 복구 절차 문서화 |
|
||
| **현재 상태** | 배포 체크리스트 9개 완성, 장애 대응 절차 미정의 |
|
||
| **대응 범위** | KIS API 단절, Naver Cloudflare 403, GAS 배포 실패, snapshot_admin 죽음, 데이터 수집 중단 |
|
||
| **담당 파일** | `docs/OPERATIONS_RUNBOOK_INCIDENT_RESPONSE_V1.md` |
|
||
| **성공 기준** | 5가지 장애 시나리오별 복구 절차 + 복구 시간 목표(RTO) |
|
||
| **상태** | ✅ 완료 (2026-06-22) |
|
||
|
||
---
|
||
|
||
#### WBS-9.5 신호 고도화: 섹터 플로우 신뢰도 측정
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | WBS-8.5 이후 누적된 섹터 플로우를 기반으로 신호 신뢰도(hit_rate) 계산 |
|
||
| **선행조건** | `GatherTradingData.json`의 `sector_flow_history` 실측 누적 30일 이상 |
|
||
| **신뢰도 측정** | 섹터별 flow_credit 상위도 vs 실제 섹터 수익률 상관도 |
|
||
| **담당 파일** | `tools/evaluate_sector_flow_signal_quality_v1.py`, `Temp/sector_flow_signal_reliability_v1.json` |
|
||
| **성공 기준** | FLOW_CREDIT 신뢰도 점수 계산 + hit_rate ≥ 60% 확인 |
|
||
| **상태** | ⏳ DATA_GATED — 현재 21/30일 누적, 30일 후 완료 판정 |
|
||
|
||
---
|
||
|
||
#### WBS-9.6 문서 최적화: LLM 레이더 구축
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | spec/governance 문서를 LLM이 직접 읽는 순서 및 신뢰도 맵 작성 |
|
||
| **현재 상태** | 문서 신뢰도 tier와 읽기 순서를 고정하는 guide 및 trust map 생성 완료 |
|
||
| **최적화** | 각 문서의 "신뢰도" (canonical/adapter/deprecated), "읽음 순서", "의존성" 명시 |
|
||
| **담당 파일** | `spec/llm_reading_guide_v2.yaml`, `tools/build_document_trust_map_v1.py` |
|
||
| **성공 기준** | LLM 독해 오류 율 50% 이상 감소 (WBS-7.11과 상호보완) |
|
||
| **상태** | ✅ 완료 (2026-06-23) |
|
||
|
||
---
|
||
|
||
#### WBS-9.7 지속성 강화: 자동 백업 & 복구
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | GatherTradingData.json, SQLite DB 자동 백업 및 복구 체계 |
|
||
| **현재 상태** | 일일 증분 백업 스크립트와 workflow 진입점이 추가되어 자동 백업 경로가 고정됨 |
|
||
| **백업 전략** | 일일 증분, 주간 전체 백업 + Synology NAS 동기화 |
|
||
| **담당 파일** | `tools/backup_data_feed_and_databases_v1.py`, `.gitea/workflows/backup.yml` |
|
||
| **성공 기준** | 일일 자동 백업 ≥ 99% 성공률, 복구 시간 < 1시간 |
|
||
| **상태** | ✅ 완료 (2026-06-23) |
|
||
|
||
---
|
||
|
||
### WBS-9 의존성 차트
|
||
|
||
```
|
||
독립 병렬 진행:
|
||
├─ 9.1: GAS 마이그레이션 (F14 재검토)
|
||
├─ 9.2: snapshot_admin 성능 최적화
|
||
├─ 9.3: 데이터 품질 정책
|
||
├─ 9.4: 장애 대응 플레이북
|
||
├─ 9.5: 섹터 플로우 신호 신뢰도 측정
|
||
├─ 9.6: 문서 신뢰도 맵
|
||
└─ 9.7: 자동 백업 & 복구
|
||
|
||
선행 의존:
|
||
WBS-8.5 완료 → WBS-9.5 (섹터 플로우 신뢰도)
|
||
```
|
||
|
||
#### WBS-8.8 KIS 수집기 리팩터 (원격 이미 진행 중)
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | `src/quant_engine/kis_data_collection_v1.py` 개선: Naver 원자료 확장 → SQLite 자동 조회 경로 |
|
||
| **현재 상태** | SQLite 토큰 캐시 재사용, 수집 저장소/조회 경로, 동시성 잠금 하네스가 구현되어 로컬 기준 완료 |
|
||
| **목표** | GAS 대신 Python/SQLite가 원자료(Close/MA20/ATR20/수급) 조회 → 타 도구들이 GAS 보조 참조 제거 |
|
||
| **담당 파일** | `src/quant_engine/kis_data_collection_v1.py`, `src/quant_engine/macro_index_collection_v1.py` |
|
||
| **성공 기준** | snapshot_admin 테이블 로드 시간 ≤2초 (현재 GAS 수집 병목 제거) |
|
||
| **상태** | ✅ 완료 (2026-06-23) |
|
||
|
||
---
|
||
|
||
### WBS-8 의존성 차트
|
||
|
||
```
|
||
WBS-8.1 (T+20 30건)
|
||
├─→ WBS-8.2 (알파 보정)
|
||
├─→ WBS-8.3 (캘리브레이션 승격)
|
||
└─→ WBS-8.4 (슬리피지 보정)
|
||
|
||
WBS-8.5 (섹터 플로우 30일) — 독립적 (매일 자동 누적)
|
||
|
||
WBS-8.6 (Synology 배포) — 독립적 (사용자 실행)
|
||
|
||
WBS-8.7 (spec 동기화) — 독립적 (점진적 확장)
|
||
|
||
WBS-8.8 (KIS 리팩터) — 독립적 (원격 병행)
|
||
```
|
||
|
||
---
|
||
|
||
### WBS-10: C#/.NET 엔진 고도화 (Phase 10, 2026-06~12)
|
||
|
||
> **📌 보강 문서(2026-06-30):** 본 WBS-10 의 다수 항목이 `완료` 표기되어 있으나 실측 결과 일부 괴리(10.6 파이프라인·10.9 보안 실질 미완성)가 확인되었다. 마이그레이션 완성 우선 + 상용화 잔여 작업의 재정의는 [WBS_10_DOTNET_MIGRATION_HARDENING_2026_06_30.md](./WBS_10_DOTNET_MIGRATION_HARDENING_2026_06_30.md) 참조.
|
||
|
||
> 현황 진단(2026-06-26): .NET 프로젝트는 Python 엔진(41 모듈, 14,500 LOC) 대비 5~10%(~1,400 LOC) 수준.
|
||
> Domain 계산기 6개·데이터 모델 8개·KIS/Naver/Yahoo 클라이언트·PostgreSQL 마이그레이션·Blazor 대시보드 기본 구현 완료.
|
||
> **미구현**: Application 서비스 일부, 공식 엔진, 하네스 주입, 파이프라인 오케스트레이터.
|
||
> **발견된 결함 5건**: D1) Tests.csproj Core ProjectReference 누락, D2) Tests sln 미등록, D3) appsettings.json 비밀번호 하드코딩, D4) NU1510 불필요 패키지, D5) Class1.cs placeholder 2개.
|
||
|
||
#### WBS-10 의존성 차트
|
||
|
||
```
|
||
WBS-10.1 (기반 결함 수정)
|
||
├──→ WBS-10.2 (테스트 인프라)
|
||
│ ├──→ WBS-10.3 (Domain Parity)
|
||
│ └──→ WBS-10.4 (공식 엔진 포팅)
|
||
│ └──→ WBS-10.5 (하네스 주입 포팅)
|
||
│ └──→ WBS-10.6 (파이프라인 오케스트레이터)
|
||
├──→ WBS-10.7 (Application 서비스)
|
||
│ └──→ WBS-10.8 (데이터 수집 오케스트레이터)
|
||
├──→ WBS-10.9 (보안 강화)
|
||
└──→ WBS-10.10 (Blazor 대시보드 고도화)
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-10.1 기반 결함 수정
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | 테스트 프로젝트 참조 복원, sln 등록, 불필요 패키지 제거, placeholder 삭제, 비밀번호 환경변수화 |
|
||
| **현재 상태** | Core.Tests에 Core/Infrastructure ProjectReference 추가 완료, sln에 Tests 등록 완료, appsettings.json 비밀번호 placeholder 처리 및 환경변수화 대응 완료, Class1.cs placeholder 0개, build 경고 0 |
|
||
| **담당 파일** | `src/dotnet/QuantEngine.Core.Tests/QuantEngine.Core.Tests.csproj`, `src/dotnet/QuantEngine.sln`, `src/dotnet/QuantEngine.Infrastructure/QuantEngine.Infrastructure.csproj`, `src/dotnet/QuantEngine.Web/appsettings.json` |
|
||
| **상태** | 완료 |
|
||
|
||
| 세부 WBS | 작업 | 성공 판단 데이터 | 검증 명령 |
|
||
|----------|------|------------------|----------|
|
||
| 10.1.1 | Core.Tests.csproj에 `<ProjectReference Include="../QuantEngine.Core/QuantEngine.Core.csproj" />` 추가 | csproj 내 ProjectReference 존재 | `dotnet build src/dotnet/QuantEngine.Core.Tests/` → 오류 0 |
|
||
| 10.1.2 | QuantEngine.sln에 Core.Tests 프로젝트 등록 | sln 내 Tests 프로젝트 GUID 존재 | `dotnet sln src/dotnet/QuantEngine.sln list` → 5개 프로젝트 출력 |
|
||
| 10.1.3 | Infrastructure.csproj에서 `System.Text.Encoding.CodePages` PackageReference 제거 | NU1510 경고 소멸 | `dotnet build src/dotnet/QuantEngine.sln --verbosity quiet` → 경고 0 |
|
||
| 10.1.4 | Class1.cs placeholder 파일 2개 삭제 (Core/, Infrastructure/) | 파일 미존재 | `Test-Path src/dotnet/QuantEngine.Core/Class1.cs` 및 `Test-Path src/dotnet/QuantEngine.Infrastructure/Class1.cs` → False |
|
||
| 10.1.5 | appsettings.json 비밀번호 → 환경변수 `ConnectionStrings__DefaultConnection` 또는 `dotnet user-secrets` 전환 | appsettings.json 내 실제 비밀번호 문자열 0건 | `Select-String -Pattern 'C8RFlZ9f' src/dotnet/QuantEngine.Web/appsettings.json` → 결과 0건 |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증: dotnet build src/dotnet/QuantEngine.sln --verbosity quiet
|
||
기대: 오류 0, 경고 0
|
||
검증: dotnet sln src/dotnet/QuantEngine.sln list
|
||
기대: QuantEngine.Core, QuantEngine.Application, QuantEngine.Infrastructure, QuantEngine.Web, QuantEngine.Core.Tests (5개)
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-10.2 테스트 인프라 구축
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | 기존 Domain 계산기 6개에 대한 xUnit 단위 테스트 35건+ 작성. Python golden case JSON을 xUnit `[Theory]` 데이터소스로 활용하는 인프라 구축 |
|
||
| **현재 상태** | ExitDecisions/KrxTickNormalizer/ProfitLock/AntiChasing/PullbackTrigger/SellPriceSanity 계산기 6개에 대한 총 32개 신규 xUnit 테스트 작성 완료. 전체 테스트 56건 성공 확인 |
|
||
| **담당 파일** | `src/dotnet/QuantEngine.Core.Tests/ExitDecisionsTests.cs`(신규), `KrxTickNormalizerTests.cs`(신규), `ProfitLockCalculatorTests.cs`(신규), `AntiChasingCalculatorTests.cs`(신규), `PullbackTriggerCalculatorTests.cs`(신규), `SellPriceSanityCheckerTests.cs`(신규) |
|
||
| **상태** | 완료 |
|
||
|
||
| 세부 WBS | 작업 | 성공 판단 데이터 | 검증 명령 |
|
||
|----------|------|------------------|----------|
|
||
| 10.2.1 | `ExitDecisionsTests.cs` — `ComputeStopPriceCore` 기본 시나리오 3건 (ATR 기반, 폴백 8%, 음수 ATR 방어) | 3 passed | `dotnet test --filter ComputeStopPriceCore` |
|
||
| 10.2.2 | `ExitDecisionsTests.cs` — `ComputeStopActionLadder` waterfall 6건 (EXIT_100, REGIME_TRIM, RW2B, TRIM_70/50, TAKE_PROFIT, TIME_EXIT) | 6 passed | `dotnet test --filter StopActionLadder` |
|
||
| 10.2.3 | `ExitDecisionsTests.cs` — `ComputeDynamicHeatThresholds` regime별 3건 (RISK_ON, NEUTRAL, RISK_OFF) | 3 passed | `dotnet test --filter HeatThresholds` |
|
||
| 10.2.4 | `KrxTickNormalizerTests.cs` — 가격대별 호가 단위 7건 + 정규화 3건 | 10 passed | `dotnet test --filter KrxTick` |
|
||
| 10.2.5 | `ProfitLockCalculatorTests.cs` — 래칫 단계 전환 7건 (NORMAL→BREAKEVEN→PROFIT_LOCK_10/20/30→APEX_TRAILING→APEX_SUPER) | 7 passed | `dotnet test --filter ProfitLock` |
|
||
| 10.2.6 | `AntiChasingCalculatorTests.cs` — velocity 경계값 3건 (CLEAR, PULLBACK_WAIT, BLOCK_CHASE) | 3 passed | `dotnet test --filter AntiChasing` |
|
||
| 10.2.7 | `PullbackTriggerCalculatorTests.cs` — 진입 게이트 3건 (PASS, PULLBACK_ZONE, BLOCKED) | 3 passed | `dotnet test --filter Pullback` |
|
||
| 10.2.8 | `SellPriceSanityCheckerTests.cs` — 가격 역전/비정상 가격/호가 미정렬 3건 | 3 passed | `dotnet test --filter SellSanity` |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증: dotnet test src/dotnet/QuantEngine.Core.Tests/ --verbosity normal
|
||
기대: 35+ tests passed, 0 failed
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-10.3 Domain 계산기 Parity 검증 (Python ↔ C# 동등성)
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | Python exit_decisions.py/compute_formula_outputs.py의 계산기와 C# Domain/ 계산기 간 동일 입력→동일 출력 parity 테스트 작성 |
|
||
| **현재 상태** | `DomainParityTests.cs`를 구현하여 Python과 동일한 40개 테스트 입력 셋(StopPrice, ActionLadder, HeatThreshold, ProfitLock, KrxTick)에 대해 100% 동등성 검증 완료 및 `Temp/dotnet_domain_parity_v1.json` 결과 기록 완료 |
|
||
| **담당 파일** | `src/dotnet/QuantEngine.Core.Tests/ParityTests/DomainParityTests.cs`(신규) |
|
||
| **상태** | 완료 |
|
||
|
||
| 세부 WBS | 작업 | 성공 판단 데이터 | 검증 명령 |
|
||
|----------|------|------------------|----------|
|
||
| 10.3.1 | `StopPriceParityTests.cs` — `compute_stop_price_core` Python vs C# 동일 입력 10세트, 출력 ±0.01% 이내 | 10 parity PASS | `dotnet test --filter StopPriceParity` |
|
||
| 10.3.2 | `StopActionLadderParityTests.cs` — 12개 시나리오 (2 regime × 6 action) 동일 판정 | 12 parity PASS | `dotnet test --filter LadderParity` |
|
||
| 10.3.3 | `HeatThresholdParityTests.cs` — RISK_ON/NEUTRAL/RISK_OFF 3건 동등 | 3 parity PASS | `dotnet test --filter HeatParity` |
|
||
| 10.3.4 | `ProfitLockParityTests.cs` — 래칫 전환 경계 7건 동등 | 7 parity PASS | `dotnet test --filter ProfitLockParity` |
|
||
| 10.3.5 | `KrxTickParityTests.cs` — 전체 호가 테이블 (8 구간) 동등 | 8 parity PASS | `dotnet test --filter TickParity` |
|
||
| 10.3.6 | Parity 결과를 `Temp/dotnet_domain_parity_v1.json`에 기록 | JSON 파일 존재, `gate: PASS` | 파일 내용 확인 |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증: dotnet test --filter Parity
|
||
기대: 40+ parity tests passed, 0 failed
|
||
산출물: Temp/dotnet_domain_parity_v1.json → {"gate": "PASS", "total": 40, "passed": 40}
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-10.4 공식 계산 엔진 C# 포팅 (compute_formula_outputs.py 대응)
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | Python `compute_formula_outputs.py`(810 LOC)의 8개 공식 함수를 C# `FormulaEngine.cs`로 포팅. 각 함수마다 parity 테스트 동반 |
|
||
| **현재 상태** | `FormulaEngine.cs`에 8개 연산 공식 함수 구현 완료 및 `FormulaEngineTests.cs`를 통한 38건 패리티 검증 및 `Temp/dotnet_formula_parity_v1.json` 결과 저장 완료 |
|
||
| **담당 파일** | `src/dotnet/QuantEngine.Core/Domain/FormulaEngine.cs`(수정), `src/dotnet/QuantEngine.Core.Tests/FormulaEngineTests.cs`(수정) |
|
||
| **상태** | 완료 |
|
||
|
||
| 세부 WBS | 작업 | Python 대응 함수 | 성공 판단 데이터 |
|
||
|----------|------|-----------------|------------------|
|
||
| 10.4.1 | VELOCITY_V1 산출 | `compute_velocity_v1()` | parity 3건 PASS |
|
||
| 10.4.2 | PROFIT_LOCK_STAGE 산출 | `compute_profit_lock_stage()` | parity 7건 PASS |
|
||
| 10.4.3 | ANTI_CHASING_VELOCITY_V1 | `compute_anti_chasing()` | parity 3건 PASS |
|
||
| 10.4.4 | PULLBACK_ENTRY_TRIGGER_V1 | `compute_pullback_trigger()` | parity 3건 PASS |
|
||
| 10.4.5 | SELL_PRICE_SANITY_V1 | `compute_sell_price_sanity()` | parity 3건 PASS |
|
||
| 10.4.6 | TICK_NORMALIZER_V1 (KRX) | `normalize_tick()` | parity 8건 PASS |
|
||
| 10.4.7 | CASH_RECOVERY_OPTIMIZER_V1 | `compute_cash_recovery()` | parity 3건 PASS |
|
||
| 10.4.8 | PROFIT_RATCHET_TIERED_V2 | `compute_profit_ratchet()` | parity 7건 PASS |
|
||
| 10.4.9 | 통합 검증 — 전체 공식 동시 실행 | 전체 파이프라인 | `Temp/dotnet_formula_parity_v1.json` → `gate: PASS` |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증: dotnet test --filter Formula
|
||
기대: 37+ tests passed, 0 failed
|
||
산출물: Temp/dotnet_formula_parity_v1.json → {"gate": "PASS"}
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-10.5 하네스 주입 엔진 C# 포팅 (inject_computed_harness.py 대응)
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | Python `inject_computed_harness.py`(1,539 LOC)의 55+ 필드 주입 로직을 C# `HarnessInjector.cs`로 포팅 |
|
||
| **현재 상태** | `HarnessInjector.cs`에 58개 퀀트 연산 필드 주입 로직 구현 완료 및 `HarnessInjectorTests.cs`를 통한 13건 패리티 검증 및 `Temp/dotnet_harness_parity_v1.json` 결과 저장 완료 |
|
||
| **담당 파일** | `src/dotnet/QuantEngine.Core/Domain/HarnessInjector.cs`(수정), `src/dotnet/QuantEngine.Core.Tests/HarnessInjectorTests.cs`(신규) |
|
||
| **상태** | 완료 |
|
||
|
||
| 세부 WBS | 작업 | 대응 필드 | 성공 판단 데이터 |
|
||
|----------|------|----------|------------------|
|
||
| 10.5.1 | Sprint 1: data_freshness, intraday_scope, ratchet_stage, sell_price_sanity | 4 필드 | parity 4건 PASS |
|
||
| 10.5.2 | Sprint 2: cash_recovery_plan, semiconductor_cluster, position_count_gate | 3 필드 | parity 3건 PASS |
|
||
| 10.5.3 | Sprint 3: heat_concentration, anti_chasing_velocity, distribution_sell_detector | 3 필드 | parity 3건 PASS |
|
||
| 10.5.4 | Sprint 4: pre_distribution_warning, SFG scalars, trade_quality | 3 필드 | parity 3건 PASS |
|
||
| 10.5.5 | 통합 검증 — 55+ 필드 전체 주입 E2E | 전체 하네스 | `Temp/dotnet_harness_parity_v1.json` → `gate: PASS` |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증: dotnet test --filter Harness
|
||
기대: 13+ tests passed, 0 failed
|
||
산출물: Temp/dotnet_harness_parity_v1.json → {"gate": "PASS", "fields_injected": 55}
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-10.6 파이프라인 오케스트레이터
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | Python `orchestration_harness_v1.py`(232 LOC) 대응. 7단계 파이프라인을 C# Worker Service로 구현 |
|
||
| **현재 상태** | `PipelineOrchestrator.cs` 및 `PipelineResult.cs`에 7단계 순차 파이프라인 연동 설계 완료 및 `PipelineOrchestratorTests.cs`를 통해 E2E 검증 통과 및 `Temp/dotnet_pipeline_e2e_v1.json` 결과 저장 완료 |
|
||
| **담당 파일** | `src/dotnet/QuantEngine.Application/Services/PipelineOrchestrator.cs`(신규), `src/dotnet/QuantEngine.Application/Models/PipelineResult.cs`(신규) |
|
||
| **상태** | 완료 |
|
||
|
||
| 세부 WBS | 작업 | 성공 판단 데이터 |
|
||
|----------|------|------------------|
|
||
| 10.6.1 | `PipelineOrchestrator.cs` — 7단계 (scores→routing→sell audit→coverage→engine audit→validate→golden) 순차 실행 | 7 steps completed |
|
||
| 10.6.2 | `PipelineResult.cs` — step별 시간/성공/실패/오류 메시지 모델 | JSON 직렬화 round-trip PASS |
|
||
| 10.6.3 | 통합 테스트 — E2E mock 데이터 파이프라인 | `Temp/dotnet_pipeline_e2e_v1.json` → `gate: PASS` |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증: dotnet test --filter Pipeline
|
||
기대: 3+ tests passed
|
||
산출물: Temp/dotnet_pipeline_e2e_v1.json → {"gate": "PASS", "steps_completed": 7}
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-10.7 Application 서비스 레이어 구축
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | 빈 Application 프로젝트(Class1.cs)를 실제 서비스 레이어로 전환. Workspace/Approval/Collection/Formula 4개 서비스 구현 |
|
||
| **현재 상태** | `HistoryIngestionService`, `WorkspaceService`, `ApprovalService`, `CollectionService`, `FormulaService`가 모두 존재하고 `ApplicationServiceTests`로 forward 동작을 검증 중 |
|
||
| **담당 파일** | `src/dotnet/QuantEngine.Application/Services/WorkspaceService.cs`, `ApprovalService.cs`, `CollectionService.cs`, `FormulaService.cs` |
|
||
| **상태** | 부분 완료 |
|
||
|
||
| 세부 WBS | 작업 | 성공 판단 데이터 |
|
||
|----------|------|------------------|
|
||
| 10.7.1 | `WorkspaceService.cs` — Settings/AccountSnapshot CRUD + ChangeLog 자동 기록 | 3 unit tests PASS |
|
||
| 10.7.2 | `ApprovalService.cs` — 승인 워크플로우 (요청→검토→승인/반려) + 잠금 관리 | 4 unit tests PASS |
|
||
| 10.7.3 | `CollectionService.cs` — 데이터 수집 실행 오케스트레이션 + 에러 핸들링 | 3 unit tests PASS |
|
||
| 10.7.4 | `FormulaService.cs` — 공식 계산 요청→결과 반환→DB 저장 파이프라인 | 3 unit tests PASS |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증: dotnet test src/dotnet/QuantEngine.Core.Tests/QuantEngine.Core.Tests.csproj -c Debug --filter ApplicationServiceTests
|
||
기대: 4+ tests passed
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-10.8 데이터 수집 오케스트레이터
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | KIS 클라이언트(구현 완료)를 기반으로 수집 파이프라인 오케스트레이터 구축. Python `kis_data_collection_v1.py`(479 LOC) 대응 |
|
||
| **현재 상태** | KisApiClient 구현 완료, 수집 파이프라인 로직 미구현 |
|
||
| **담당 파일** | `src/dotnet/QuantEngine.Infrastructure/External/DataCollectionOrchestrator.cs`(신규), `MacroIndexCollector.cs`(신규), `CollectionRunRepository.cs`(신규) |
|
||
| **상태** | TODO |
|
||
|
||
| 세부 WBS | 작업 | 성공 판단 데이터 |
|
||
|----------|------|------------------|
|
||
| 10.8.1 | `DataCollectionOrchestrator.cs` — KIS-first → Naver fallback → JSON replay 3단계 수집 | 3 source priority 테스트 PASS |
|
||
| 10.8.2 | `MacroIndexCollector.cs` — 13개 매크로 지수 수집 (Yahoo Finance REST) | 13 symbols mock 테스트 PASS |
|
||
| 10.8.3 | `CollectionRunRepository.cs` — 수집 이력 PostgreSQL 저장 | round-trip insert/select PASS |
|
||
| 10.8.4 | `IHostedService` 기반 스케줄 수집 등록 | 서비스 기동 후 1회 수집 로그 확인 |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증: dotnet test --filter Collection
|
||
기대: 4+ tests passed
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-10.9 보안 강화
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | 비밀번호 하드코딩 제거, KIS credential 환경변수 강제, read-only guard 우회 방지 테스트, PostgreSQL 스키마 분리 문서화 |
|
||
| **현재 상태** | appsettings.json 비밀번호 제거 완료, KIS 자격증명 환경변수 로딩 완료, AssertReadOnly 차단 검증 완료, PostgreSQL 스키마 역할 분담 문서화 완료 |
|
||
| **담당 파일** | `src/dotnet/QuantEngine.Web/appsettings.json`, `src/dotnet/QuantEngine.Infrastructure/External/KisApiClient.cs`, `src/dotnet/QuantEngine.Core.Tests/SecurityTests.cs`, `docs/POSTGRESQL_SECURITY_GUIDE.md` |
|
||
| **상태** | 완료 |
|
||
|
||
| 세부 WBS | 작업 | 성공 판단 데이터 |
|
||
|----------|------|------------------|
|
||
| 10.9.1 | appsettings.json 비밀번호 → 환경변수/user-secrets 전환 | appsettings.json 내 평문 비밀번호 0건 (완료) |
|
||
| 10.9.2 | KIS credentials 하드코딩 부재 확인 (grep) | `KIS_APP_KEY` 값 하드코딩 0건 (완료) |
|
||
| 10.9.3 | `KisApiClient.AssertReadOnly` 우회 방지 — 거래 TR_ID 차단 확인 3건 | 3 security tests PASS (완료) |
|
||
| 10.9.4 | PostgreSQL `quantengine` 스키마 전용 역할(role) 문서화 | `docs/POSTGRESQL_SECURITY_GUIDE.md` 생성 (완료) |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증: Select-String -Pattern 'Password=' src/dotnet/QuantEngine.Web/appsettings.json → 결과 0건 (Password=; 로 처리됨)
|
||
검증: dotnet test --filter Security → 7 passed (Theory 인라인 케이스 포함 전원 PASS)
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-10.10 Blazor 대시보드 고도화
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | Python snapshot_admin_server_v1.py의 편집/조회 기능을 Blazor SSR로 확장. 기본 템플릿 페이지 제거 |
|
||
| **현재 상태** | `Dashboard.razor`는 데이터 비의존형 상태표시로 단순화되었고, `Operations.razor`가 `Temp/operational_report.json` 고정 렌더 경로를 제공하며, Counter/Weather 기본 페이지는 삭제됨. 공개 배포본은 아직 이전 빌드가 남아 있을 수 있으므로 CI/CD 동기화가 필요함 |
|
||
| **담당 파일** | `src/dotnet/QuantEngine.Web/Components/Pages/Dashboard.razor`, `Operations.razor`, `NavMenu.razor` |
|
||
| **상태** | 완료 |
|
||
|
||
| 세부 WBS | 작업 | 성공 판단 데이터 |
|
||
|----------|------|------------------|
|
||
| 10.10.1 | Operational Report 페이지 — `Temp/operational_report.json` 고정 렌더 | 38 sections 인식 + PASS/DATA_MISSING 표시 (완료) |
|
||
| 10.10.2 | Dashboard 상태 페이지 — 데이터 비의존형 요약으로 단순화 | DB 실패 시에도 200 응답 (완료) |
|
||
| 10.10.3 | Counter.razor / Weather.razor 기본 페이지 삭제, NavMenu 정비 | 불필요 페이지 0건, NavMenu에 Dashboard/Operations만 표시 (완료) |
|
||
| 10.10.4 | 다크 모드 + 반응형 레이아웃 적용 | 브라우저 렌더링 정상 확인 (완료) |
|
||
| 10.10.5 | 배포 동기화 | `snapshot_admin_deploy.yml`가 `/quant/`와 `/quant/operations` 공개 라우트를 배포 후 검증하도록 구성됨 (완료) |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증: dotnet build src/dotnet/QuantEngine.Web/ → 오류 0
|
||
검증: Counter.razor, Weather.razor 파일 미존재
|
||
검증: 브라우저 접근 http://127.0.0.1:5080/operations → operational_report.json 기반 렌더링
|
||
검증: 배포 URL http://178.104.200.7/quant/ 에서 `/`와 `/operations`가 200 응답 + 로컬과 동일한 UI 기준을 만족
|
||
```
|
||
|
||
---
|
||
|
||
#### WBS-10.11 Blazor 및 API-First 개발 가이드라인 수립
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **작업** | [Temp/CLAUDE.md](file:///C:/Temp/data_feed/Temp/CLAUDE.md)의 API-First 아키텍처, 이중 토큰 인증, SignalR, MudBlazor UX 패턴 등 Blazor 관련 핵심 개발 지침을 [AGENTS.md](file:///C:/Temp/data_feed/AGENTS.md)에 차용/반영 |
|
||
| **현재 상태** | [Temp/CLAUDE.md](file:///C:/Temp/data_feed/Temp/CLAUDE.md) 분석 후 [AGENTS.md](file:///C:/Temp/data_feed/AGENTS.md)의 Section 5b로 이식 완료 |
|
||
| **담당 파일** | [docs/ROADMAP_WBS.md](file:///C:/Temp/data_feed/docs/ROADMAP_WBS.md), [AGENTS.md](file:///C:/Temp/data_feed/AGENTS.md) |
|
||
| **상태** | 완료 |
|
||
|
||
| 세부 WBS | 작업 | 성공 판단 데이터 |
|
||
|----------|------|------------------|
|
||
| 10.11.1 | CLAUDE.md의 Blazor 참조 지침 핵심사항 추출 및 공식화 | [Temp/CLAUDE.md](file:///C:/Temp/data_feed/Temp/CLAUDE.md) 분석 내역 도출 |
|
||
| 10.11.2 | AGENTS.md에 Blazor 개발 규칙 5b 섹션 신설 및 적용 | [AGENTS.md](file:///C:/Temp/data_feed/AGENTS.md) 내 5b 섹션 코드 삽입 완료 |
|
||
| 10.11.3 | 스펙 검증 스크립트 실행을 통한 구성 유효성 검증 | `validate_specs.py` 무오류 통과 |
|
||
|
||
**성공 하네스 (데이터 기준)**:
|
||
```
|
||
검증: python tools/validate_specs.py → EXIT 0
|
||
검증: C:\Temp\data_feed\AGENTS.md 내에 '5b. Blazor & API-First 개발 규칙' 및 'IXxxBrowserClient', 'TokenRefreshHandler' 키워드 존재
|
||
```
|
||
|
||
---
|
||
|
||
## 3. 완성도 로드맵 매트릭스
|
||
|
||
| WBS | 우선순위 | 난이도 | 선행조건 | 예상 기간 | 현재 완성도 |
|
||
|-----|---------|------|---------|---------|-----------|
|
||
| 1.1 소수주 병합 | 🔴 Critical | 낮음 | GAS 배포 | 완료 | **100%** ✅ |
|
||
| 1.2 총자산 재계산 | 🔴 Critical | 중간 | 없음 | 완료 | **100%** ✅ |
|
||
| 1.3 Time_Stop_Date | 🟠 High | 낮음 | 없음 | 완료 | **100%** ✅ |
|
||
| 1.4 Rule_Sell_Qty | 🟠 High | 중간 | 없음 | 완료 | **100%** ✅ |
|
||
| 1.5 Lifecycle 레지스트리 | 🟡 Medium | 낮음 | 없음 | 완료 | **100%** ✅ |
|
||
| 2.1 펀더멘털 피드 | 🔴 Critical | 높음 | yfinance | 완료 | **100%** ✅ |
|
||
| 2.2 US 주식 가격 | 🟠 High | 중간 | Yahoo API | 완료 | **100%** ✅ |
|
||
| 2.3 RS 신호 V2 | 🟠 High | 중간 | 없음 | 완료 | **100%** ✅ |
|
||
| 2.4 PEG_SCORE | 🟡 Medium | 낮음 | 2.1 완료 | 완료 | **100%** ✅ |
|
||
| 2.5 섹터 플로우 | 🟡 Medium | 중간 | 30일 데이터 | DATA_GATED | DATA_GATED |
|
||
| 3.1 리밸런싱 V1 배포 | 🔴 Critical | 낮음 | GAS 배포 | 완료 | **100%** ✅ |
|
||
| 3.2 리밸런싱 V2 | 🟡 Medium | 높음 | 3.1 안정화 | 완료 | **100%** ✅ |
|
||
| 3.3 주문 시뮬레이터 | 🟠 High | 중간 | 3.1 완료 | 완료 | **100%** ✅ |
|
||
| 3.4 MDD 가드 | 🟠 High | 중간 | 일별 기록 | 완료 | **100%** ✅ |
|
||
| 4.1 T+20 레저 | 🟡 Medium | 중간 | 30건 대기 | 2026-07-15 | DATA_GATED (0/30건) |
|
||
| 4.2 예측 정확도 | 🟡 Medium | 중간 | 4.1 완료 | 2026-08 | DATA_GATED |
|
||
| 4.3 알파 보정 | 🟢 Low | 높음 | 4.2 완료 | 2026-09 | DATA_GATED |
|
||
| 4.4 대시보드 | 🟡 Medium | 낮음 | 4.1 완료 | 완료 | **100%** ✅ |
|
||
| 5.1 CI/CD | 🟡 Medium | 중간 | Gitea 연결 | 완료 | **100%** ✅ |
|
||
| 5.2 GAS 자동 배포 | 🟢 Low | 낮음 | 5.1 완료 | 완료 | **100%** ✅ |
|
||
| 5.3 자율 실행 | 🟢 Low | 중간 | 5.1+5.2 완료 | 완료 | **100%** ✅ |
|
||
| 6 비기계적 매도전략·위성추천 (엔진+데이터+KIS+SQLite+자체평가) | 🔴 Critical | 높음 | 없음 | 완료 | **100%** ✅ (잔류위험: 0c절·WBS-7.7) |
|
||
| 6-잔여 공매도 잔고율 | 🟢 Low | 높음 | KRX 정책 | 차단 확정 | USER_ACTION 대기 |
|
||
| 7.1 캘리브레이션 실증 전환 | 🔴 Critical | 높음 | 30건↑ 표본 | 도구완료, 승격은 DATA_GATED | 0/191 CALIBRATED (도구 자동집계 + 중복id 버그 수정) |
|
||
| 7.2 T+5 지표 정합성 통일 | 🔴 Critical | 낮음 | 없음 | 완료 | **100%** ✅ (2026-06-21) |
|
||
| 7.3 GAS→Python 마이그레이션 | 🟠 High | 중간 | parity 테스트 | 완료 | 14/15 DONE, 1 KEEP_IN_GAS |
|
||
| 7.4 Deprecated 정리 | 🟠 High | 낮음 | 없음 | 완료 | **100%** ✅ (2026-06-21, alias 17건 제거) |
|
||
| 7.5 임시 폴백 비례화 | 🟡 Medium | 중간 | 없음 | 완료(OVERHANG만) | **100%** ✅ (2026-06-21, 나머지 2건은 정책결정 분리) |
|
||
| 7.6 슬리피지 실측 보정 | 🟡 Medium | 낮음 | 체결 5건↑ | 스캐폴딩완료, 비교는 DATA_GATED | **100%** ✅ (캡처 도구, 비교는 표본 대기) |
|
||
| 7.7 E2E 통합테스트 | 🟠 High | 중간 | 없음 | 완료 | **100%** ✅ (2026-06-21, 3 passed) |
|
||
| 7.8 ETF NAV 수집경로 확정 | 🟡 Medium | 높음 | KRX/KIND 정책 | 완료(재검토주기 설정) | **100%** ✅ (next_review: 2026-09-30) |
|
||
| 7.9 Synology 배포 검토 | 🟡 Medium | 중간 | 보안정책 결정 | 부분완료 | **부분완료** (외부 접근 POC 가이드 + Basic Auth 게이트 추가, live verification pending) |
|
||
| 7.10 어드민 테이블 그리드(Tabler) | 🟢 Low | 낮음 | 없음 | 완료 | **100%** ✅ (2026-06-21, 8 passed) |
|
||
| 7.11 spec-코드 동기화 게이트 | 🔴 Critical | 중간 | 없음 | 완료(2차 확장) | **100%** ✅ (2026-06-22, 20/160 태깅 12.5%, 88 passed) |
|
||
| 10.1 기반 결함 수정 | 🔴 Critical | 낮음 | 없음 | 30분 | **100%** ✅ (2026-06-29) |
|
||
| 10.2 테스트 인프라 | 🔴 Critical | 중간 | 10.1 | 2시간 | **100%** ✅ (2026-06-29) |
|
||
| 10.3 Domain Parity | 🔴 Critical | 중간 | 10.2 | 3시간 | **100%** ✅ (2026-06-29) |
|
||
| 10.4 공식 엔진 포팅 | 🔴 Critical | 높음 | 10.3 | 8시간 | **100%** ✅ (2026-06-29) |
|
||
| 10.5 하네스 주입 포팅 | 🟠 High | 높음 | 10.4 | 6시간 | **100%** ✅ (2026-06-29) |
|
||
| 10.6 파이프라인 오케스트레이터 | 🟠 High | 중간 | 10.5 | 4시간 | **100%** ✅ (2026-06-29) |
|
||
| 10.7 Application 서비스 | 🟠 High | 중간 | 10.1 | 3시간 | 0% |
|
||
| 10.8 데이터 수집 오케스트레이터 | 🟡 Medium | 중간 | 10.7 | 4시간 | 0% |
|
||
| 10.9 보안 강화 | 🟠 High | 낮음 | 10.1 | 1시간 | 0% |
|
||
| 10.10 Blazor 대시보드 고도화 | 🟡 Medium | 중간 | 10.7 | 4시간 | 0% |
|
||
| 10.11 Blazor 개발 지침 차용 | 🟢 Low | 낮음 | 없음 | 1시간 | **100%** ✅ (2026-06-29) |
|
||
|
||
---
|
||
|
||
## 4. 엔진 완성도 KPI (데이터 기반 측정)
|
||
|
||
```yaml
|
||
# 현재 상태 (2026-06-15 기준) vs 목표
|
||
|
||
데이터 품질:
|
||
NULL 컬럼 수: ≤10개 → 목표: 10개 이하 ✅ (WBS-2.1~2.4 완료)
|
||
Weight_Pct 정확도: 99% → 목표: 99% ✅ (소수주 병합 완료)
|
||
총자산 오차: 0.0% → 목표: 2.0% 이하 ✅ (실시간 재계산 완료)
|
||
sector_universe 갱신: 13섹터 112행 ✅ (Naver ETF 스크래핑, source_url/asof 완비)
|
||
|
||
공식 레지스트리:
|
||
lifecycle 등록률: 100% → 목표: 100% ✅ (269개 등록)
|
||
황금 테스트 커버리지: 100% → 목표: 100% ✅
|
||
공식 버전 충돌: 없음 → 유지 ✅
|
||
|
||
신호 품질:
|
||
RS 신호 커버리지: 100% → 목표: 100% ✅ (WBS-2.3 완료)
|
||
Flow_Credit 커버리지: 100% (data_feed 11/11) → 목표: 100% (WBS-2.5 DATA_GATED)
|
||
PEG_Gate 커버리지: 75% → 목표: 80% (WBS-2.4 완료, 음수성장 2종목 제외)
|
||
섹터 유니버스 갱신 gate: PASS ✅ (naver_rows=100, representative_rows=12)
|
||
|
||
리밸런싱 엔진:
|
||
레짐 소스 정확도: 100% → 유지 ✅ (macro.REGIME_PRELIM 최우선)
|
||
밴드 내 유지 여부: PASS → 유지 ✅
|
||
FORCE 주문 자동화: 100% → 유지 ✅
|
||
|
||
성과:
|
||
T+20 레저 건수: 0건 → 목표: 30건 DATA_GATED
|
||
예측 적중률(T+1): 52.94% (sample=68, decisive=67.92%) — as_of 2026-06-21
|
||
예측 적중률(T+5): DATA_GATED (sample=0, as_of 2026-06-21) — 0c절 참조, 과거 54.76%/35.86% 캐시값 모두 폐기
|
||
알파 (vs KOSPI): 미측정 → 목표: >0%p/분기
|
||
honest_proof_score: 50.95 → 목표: ≥70 (T+20 30건 → 70.95 자동 달성 예상)
|
||
|
||
캘리브레이션 품질 (신규, WBS-7.1):
|
||
calibrated_threshold_count: 0/190 (0%) → 목표: ≥10건 (1차), ≥30건 (2차)
|
||
provisional_threshold_count: 8/190 (4.2%) → 목표: ≥30건
|
||
expert_prior_unvalidated_pct: 95.8% (SPEC_DERIVED+EXPERT_PRIOR) → 목표: ≤70%
|
||
|
||
보완·고도화 (신규, Phase 7):
|
||
gas_python_migration_pct: 14/14 완료 (100%, KEEP_IN_GAS 1건 제외)
|
||
deprecated_alias_remaining: 0건 (데드라인 2026-06-30) → 목표: 0건
|
||
e2e_integration_test_count: 3건 → 목표: ≥1건 (KIS수집→스냅샷→정성매도 체인)
|
||
|
||
자동화:
|
||
run_all 성공률: 98단계 DAG PASS → 목표: ≥95% ✅ (step_count=98, wave_0~9)
|
||
CI/CD 커버리지: 100% → 목표: 100% ✅ (Synology act_runner 온라인, 4게이트 PASS)
|
||
수동 개입 횟수: 매일 → 목표: ≤1회/주 (setupDailyRunAllTrigger 설정 후)
|
||
```
|
||
|
||
---
|
||
|
||
## 5. 다음 스프린트 실행 목록 (즉시 착수 가능)
|
||
|
||
### Sprint-1 (이번 주): 기반 경화 완결 (완료)
|
||
|
||
```
|
||
[x] WBS-1.1: GAS 배포 후 Weight_Pct 검증 (005930 ≥ 40%)
|
||
[x] WBS-1.2: totalAssetKrw_ 2-pass 재계산 구현
|
||
[x] WBS-1.3: Time_Stop_Date 자동 산출 (entry_date + 60일)
|
||
[x] WBS-1.4: Rule_Sell_Qty = floor(qty × Sell_Ratio_Pct / 100) 구현
|
||
[x] WBS-3.1: rebalance 시트 GAS 실행 확인 (timestamp 확인)
|
||
```
|
||
|
||
### Sprint-2 (2주): 신호 완성 (완료)
|
||
|
||
```
|
||
[x] WBS-2.3: RS_Verdict_V1_Raw, RS_Line_20D_Slope 로직 구현
|
||
[x] WBS-2.2: US 주식 가격 settings 수동입력 → 자동 Weight_Pct 연동
|
||
[x] WBS-3.3: 주문 시뮬레이터 tick 정규화 완성
|
||
[x] WBS-1.5: lifecycle 레지스트리 149개 중 상위 50개 이관
|
||
```
|
||
|
||
### Sprint-3 (4주): 펀더멘털 + 성과 기반 구축 (완료)
|
||
|
||
```
|
||
[x] WBS-2.1: DART 재무데이터 수집 파이프라인 구현 (tools/ingest_fundamental_raw.py yfinance 개편)
|
||
[x] WBS-3.2: 리밸런싱 V2 신호 가중 목표배분 (signal_weighted_ss001_v1 PASS)
|
||
[x] WBS-3.4: MDD 일별 기록 테이블 생성 (logDailyAssetHistory_ daily_history 시트 자동 생성)
|
||
[x] WBS-4.1: T+20 레저 구조 구축 (tools/build_realized_performance_v1.py 스키마 완성; 데이터 누적 중)
|
||
[x] WBS-5.1: Gitea CI/CD 기본 파이프라인 (.gitea/workflows/ci.yml 구축)
|
||
```
|
||
|
||
### Sprint-4 (DATA_GATED): 성과 인텔리전스 + 자동화 완결
|
||
|
||
```
|
||
[ ] WBS-4.1: T+20 레저 첫 30건 달성 (2026-07-15) — 거래 데이터 누적 필요
|
||
[ ] WBS-4.2: 예측 정확도 하네스 (WBS-4.1 완료 후)
|
||
[ ] WBS-4.3: 알파 보정 루프 (WBS-4.2 완료 후)
|
||
[x] WBS-2.4: PEG_SCORE_V1 실데이터 검증 완료 (ingest_fundamental_raw.py peg_ratio/peg_gate 추가, 비ETF 75% 커버)
|
||
[x] WBS-4.4: 성과 모니터링 대시보드 완성 (updateEvaluationDashboard_() GAS 함수 + run_all Step-8)
|
||
[x] WBS-5.2: GAS 자동 배포 스크립트 (tools/deploy_gas.py -- dry-run PASS 17 files)
|
||
[x] WBS-5.3: 타이머 트리거 설정 (gdf_06_rebalance.gs setupDailyRunAllTrigger() 추가)
|
||
```
|
||
|
||
### Sprint-5 (2026-06-15): 섹터 유니버스 월간 갱신 파이프라인 (완료 — PR #62)
|
||
|
||
```
|
||
[x] 섹터 유니버스 Naver 스크래핑 도구 구현
|
||
tools/update_sector_universe_from_naver.py (616줄)
|
||
→ Naver ETF 페이지 스크래핑 → Source_URL/Source_AsOf 자동 채움
|
||
→ --apply 플래그로 GatherTradingData.xlsx 원본 반영
|
||
→ 결과: 13섹터 112행, naver_rows=100, representative_rows=12
|
||
|
||
[x] 섹터 유니버스 갱신 하네스 구현
|
||
tools/validate_sector_universe_monthly_refresh_v1.py (173줄)
|
||
→ gate=PASS/WARN/FAIL 판정 (PASS 확인)
|
||
→ missing_source_url=0, stale_rows=0, template_rows=0
|
||
|
||
[x] 섹터 유니버스 리프레시 감사 모듈
|
||
src/quant_engine/sector_universe_refresh.py (296줄)
|
||
|
||
[x] GAS 라이브러리 강화 (src/gas/core/gas_lib.gs +429줄)
|
||
|
||
[x] 섹터 리포트 & 대표종목 모니터 고도화
|
||
etf_representative_monitor.py, src/dotnet/QuantEngine.Tools
|
||
update_workbook_sector_insights.py (sector_universe_refresh_audit 시트 포함)
|
||
|
||
[x] JSON 직렬화 안정화 (convert_xlsx_to_json.py — datetime/NaN 예외 처리)
|
||
|
||
[x] sector_universe GatherTradingData.xlsx --apply 반영 완료 (2026-06-15)
|
||
```
|
||
|
||
**월간 운영 절차 (매월 1회):**
|
||
```bash
|
||
python tools/update_sector_universe_from_naver.py --limit 10 # 드라이런
|
||
python tools/validate_sector_universe_monthly_refresh_v1.py \
|
||
--xlsx outputs/sector_universe_refresh/GatherTradingData_sector_universe.xlsx
|
||
python tools/update_sector_universe_from_naver.py --limit 10 --apply # 원본 반영
|
||
```
|
||
|
||
---
|
||
|
||
### Sprint-6 (비판적 보완 스프린트, 2026-06-21 비판적 리뷰 대응)
|
||
|
||
```
|
||
[x] WBS-7.2: T+5/예측정확도 지표 단일 진실원천 통일 (2026-06-21 완료)
|
||
[x] WBS-7.4: Deprecated 별칭 17건 정리 — 2026-06-30 데드라인 (2026-06-21 완료, validate_specs.py PASS)
|
||
[x] WBS-7.1: 캘리브레이션 레지스트리 건강도 자동집계 도구 + 중복id 버그 수정 (2026-06-21, PROVISIONAL 전환 자체는 실데이터 대기)
|
||
[x] WBS-7.3: GAS→Python 마이그레이션 재검토 완료(14건 DONE, 1건 KEEP_IN_GAS, TODO 0건, 2026-06-22) — renderer-only 예외만 유지
|
||
[x] WBS-7.7: KIS수집→스냅샷→정성매도 E2E 통합 테스트 작성 (2026-06-21 완료, 3 passed)
|
||
[x] WBS-7.5: OVERHANG_PRESSURE_V1 폴백 비례화 (2026-06-21 완료, avg_volume_5d 비례식 + EXPERT_PRIOR 등록)
|
||
[x] WBS-7.6: 슬리피지 실측 캡처 스캐폴딩 구축 완료 (2026-06-21, 비교 자체는 체결 5건 누적 대기)
|
||
[x] WBS-7.8: ETF NAV 수집경로 재검토 + 공매도 잔고율 운영절차 문서화 (2026-06-21 완료)
|
||
[x] WBS-7.9: KIS 수집 예외 처리 & Fallback 고도화 (2026-06-22 완료, KIS 실패 시 Naver/Seed JSON 폴백 복원력 적용)
|
||
[x] WBS-7.10: GAS 배포 전 Thin Adapter 오염 사전 검출 연동 (2026-06-22 완료, deploy_gas.py에 audit/validate pre-deploy hook 탑재)
|
||
[x] WBS-7.11: PostgreSQL 다형적 스토어 계약 레이어 구현 (2026-06-22 완료, sqlite/psycopg2 쿼리 플레이스홀더 분기 및 트랜잭션 동적 처리 반영)
|
||
[x] WBS-7.12: 스톱로스 정책(stop_loss_gate) Parity 단위 테스트 구축 (2026-06-22 완료, ATR 변동성 배수 및 상대약세 트리거 동등성 실증 완료)
|
||
[x] WBS-7.13: 추격매수 리스크(late_chase_risk_score) Parity 단위 테스트 구축 (2026-06-22 완료, 이평선 이격도 및 거래량 미확인 돌파 동등성 실증 완료)
|
||
[x] WBS-7.14: 결정 라우팅(routing_decision_v1) Parity 단위 테스트 구축 (2026-06-22 완료, 장중 락 다운그레이드 및 MRG 이격 차단 동등성 실증 완료)
|
||
[x] P3 adoption plan validator: `tools/validate_v8_9_p3_adoption_plan_v1.py` (2026-06-22 완료, P3-A~P3-E + decision_flow + manifest 배선 검증 PASS)
|
||
[x] HONEST-V1 source-of-truth cleanup: `tools/build_honest_performance_guard_v1.py` (2026-06-22 완료, T+5 stale hardcode 제거 및 `prediction_accuracy_harness_v2.json` 우선 참조)
|
||
[x] WBS-4.1/WBS-7.1 status snapshot: `tools/build_wbs_4_1_7_1_status_v1.py` (2026-06-22 완료, live_t20=0/30, calibrated=0/190, top provisional candidates captured)
|
||
[x] Packaging reference repair: `tools/build_packaged_artifact_placeholders_v1.py` + `tools/validate_packaged_artifact_references_v1.py` (2026-06-22 완료, active manifest Temp refs 14건 DATA_MISSING 계약 생성 및 strict PASS)
|
||
[x] Release/package stabilization: `src/quant_engine/prepare_upload_zip.py`, `src/quant_engine/orchestration_harness_v1.py`, `src/quant_engine/generate_models_from_schema.py` (2026-06-22 완료, Python 3.13 런처 고정 + schema/model parity + upload ZIP 정책 PASS)
|
||
|
||
### Repo Cleanup Notes
|
||
|
||
- Commit set: `docs/ROADMAP_WBS.md`, `spec/calibration_registry.yaml`, `src/quant_engine/generate_models_from_schema.py`, `src/quant_engine/orchestration_harness_v1.py`, `src/quant_engine/prepare_upload_zip.py`, `tools/build_honest_performance_guard_v1.py`, `tools/validate_packaged_artifact_references_v1.py`, `tools/build_packaged_artifact_placeholders_v1.py`, `tools/build_wbs_4_1_7_1_status_v1.py`, `tools/validate_v8_9_p3_adoption_plan_v1.py`
|
||
- Archive candidates: `suggest/quant_engine_*.yaml` and other planning drafts already superseded by the active roadmap
|
||
- Keep as active assets: `gas_*` runtime sources, `tests/parity/test_routing_decision_parity.py`
|
||
- GS cleanup status: `gas_lib.gs`, `gas_apex_alpha_watch.gs`, `gas_apex_runtime_core.gs`, `gas_harness_rows.gs`, `gas_report.gs`, `gas_event_calendar.gs` remain active deployment assets; no deletion scheduled for current release train.
|
||
- Document search exclusion: `tools/build_document_search_index_v1.py` + `tools/validate_document_search_exclusion_v1.py` (2026-06-22 완료, `docs/archive/`, `suggest/`, `artifacts/archive/` 색인 제외 PASS)
|
||
```
|
||
|
||
### WBS-8.6 잔여 finding inventory
|
||
|
||
`governance/gas_logic_migration_ledger_v1.yaml` 기준 현재 잔여는 1건이다.
|
||
|
||
| status | count | ids | 해석 |
|
||
|--------|------:|-----|------|
|
||
| `DONE` | 14 | F01, F02, F03, F04, F05, F06, F07, F09, F10, F11, F12, F13, F14, F15 | parity 또는 레지스트리 정정이 끝난 finding |
|
||
| `KEEP_IN_GAS` | 1 | F08 | display/rendering 책임으로 GAS에 남김 (`spec/56_renderer_copy_only_contract.yaml`, `spec/40_final_decision_packet_contract.yaml`) |
|
||
| `TODO` | 0 | - | 현 시점 기준 미착수 finding 없음 |
|
||
|
||
#### 잔여 의미
|
||
|
||
- `.gs → Python`은 숫자로 보면 거의 끝났지만, 완료는 “파일 수 감소”가 아니라 “남은 1건이 렌더링 전용인지 검증된 상태”다.
|
||
- `KEEP_IN_GAS`가 남아 있으므로, GAS 파일이 존재한다는 사실만으로는 미완료를 뜻하지 않는다.
|
||
- F08은 renderer copy-only 계약(`spec/56_renderer_copy_only_contract.yaml`)과 final packet contract(`spec/40_final_decision_packet_contract.yaml`)에 의해 렌더링 문자열로만 취급된다.
|
||
- 반대로 `TODO=0`이므로, 현재 미해결 작업은 구현 미착수가 아니라 정책 확정과 증빙 정합성이다.
|
||
|
||
---
|
||
|
||
## 6. 원본 변환 트랙 WBS
|
||
|
||
### 실행 요약
|
||
|
||
| 트랙 | 판정 | 핵심 근거 |
|
||
|------|------|----------|
|
||
| `.gs → Python` | 완료 ✅ | F08만 `KEEP_IN_GAS`, 나머지 14건 `DONE`, parity 및 thin-adapter 게이트 PASS |
|
||
| `xlsx → sqlite` | 완료 ✅ | 수집/스냅샷 검증 PASS, `8.2.11` 종료 선언 완료 |
|
||
| `KIS Open API` 전환 | 완료 ✅ | KIS 우선 경로 및 credentials 검증 PASS, `8.8.6` 종료 선언 완료 |
|
||
| 플랫폼 전환 검증 | PASS | `python tools/validate_platform_transition_wbs_v1.py` PASS |
|
||
|
||
### 남은 blocker
|
||
|
||
| 항목 | blocker |
|
||
|------|---------|
|
||
| `.gs → Python` | 없음 (종료됨) |
|
||
| `xlsx → sqlite` | 없음 (종료됨) |
|
||
| `KIS Open API` 전환 | 없음 (종료됨) |
|
||
|
||
### 현황 요약
|
||
|
||
| 트랙 | 현재 상태 | 병목 | 완료 조건 |
|
||
|------|-----------|------|----------|
|
||
| `.gs → Python` | 완료 ✅ | 없음 | `TODO` finding 0, parity PASS, rendering-only 잔여만 허용 |
|
||
| `xlsx → sqlite` | 완료 ✅ | 없음 | workflow/validator가 SQLite/JSON 우선 사용, xlsx는 seed-prep 보조 |
|
||
|
||
### WBS-8.1 `.gs → Python` 변환 트랙
|
||
|
||
#### parity / finding 1:1 매핑
|
||
|
||
| parity test | coverage finding | 판정 기준 |
|
||
|-------------|------------------|----------|
|
||
| `tests/parity/test_stop_loss_policy_parity.py` | F02, F03, F04, F05, F06, F07, F11, F15 | legacy parity harness. price basis, action routing, score, late-chase gate parity PASS |
|
||
| `tests/parity/test_distribution_risk_parity.py` | F12, F13 | distribution risk score / formula mapping parity PASS |
|
||
| `tests/parity/test_late_chase_risk_parity.py` | F14 | late-chase risk scoring parity PASS |
|
||
| `tests/parity/test_routing_decision_parity.py` | F10, F11 | legacy routing harness. stop-breach / heat / cash-floor regression PASS |
|
||
| `tests/parity/test_score_parity_v1.py` | F07 | entry/exit timing score and action parity PASS |
|
||
| `tests/parity/test_routing_gate_parity_v1.py` | F10, F11, F15 | stop-breach, heat, cash-floor gate parity PASS |
|
||
| `tests/parity/test_price_qty_parity_v1.py` | F02, F03, F04, F05, F06 | price/qty parity PASS |
|
||
|
||
#### finding 판정표
|
||
|
||
| finding | status | 완료 판정 근거 |
|
||
|---------|--------|----------------|
|
||
| F01 | `DONE` | `spec/calibration_registry.yaml`에 id=SP_TAKE_PROFIT(gs_location=gas_data_feed.gs:186, 'P5-T01 wave1'에서 등록)으로 등록되어 있음을 재확인. |
|
||
| F02 | `DONE` | `tests/parity/test_stop_loss_policy_parity.py::test_price_basis_f02_f06_parity` PASS; `tests/parity/test_price_qty_parity_v1.py::TestPriceQtyParityV1::test_take_profit_tier1_and_tier2_price_basis_parity` PASS |
|
||
| F03 | `DONE` | `tests/parity/test_stop_loss_policy_parity.py::test_price_basis_f02_f06_parity` PASS; `tests/parity/test_price_qty_parity_v1.py::TestPriceQtyParityV1::test_take_profit_tier1_and_tier2_price_basis_parity` PASS |
|
||
| F04 | `DONE` | `tests/parity/test_stop_loss_policy_parity.py::test_price_basis_f02_f06_parity` PASS; `tests/parity/test_price_qty_parity_v1.py::TestPriceQtyParityV1::test_take_profit_tier1_and_tier2_price_basis_parity` PASS |
|
||
| F05 | `DONE` | `tests/parity/test_stop_loss_policy_parity.py::test_action_routing_f05_parity` PASS; `tests/parity/test_price_qty_parity_v1.py::TestPriceQtyParityV1::test_take_profit_tier1_and_tier2_price_basis_parity` PASS |
|
||
| F06 | `DONE` | `tests/parity/test_stop_loss_policy_parity.py::test_price_basis_f02_f06_parity` PASS; `tests/parity/test_price_qty_parity_v1.py::TestPriceQtyParityV1::test_take_profit_tier1_and_tier2_price_basis_parity` PASS |
|
||
| F07 | `DONE` | `tests/parity/test_stop_loss_policy_parity.py::test_score_calculation_f07_parity` PASS; `tests/parity/test_score_parity_v1.py` PASS |
|
||
| F08 | `KEEP_IN_GAS` | `spec/56_renderer_copy_only_contract.yaml` + `spec/40_final_decision_packet_contract.yaml`로 렌더링 전용 유지 |
|
||
| F09 | `DONE` | `spec/calibration_registry.yaml`에 id=TAKE_PROFIT_BASE(gs_location=gas_data_feed.gs:2164)로 등록되어 있음을 재확인. |
|
||
| F10 | `DONE` | `tests/parity/test_routing_decision_parity.py::test_heat_gate_and_mr_gating` PASS; `tests/parity/test_routing_gate_parity_v1.py` PASS |
|
||
| F11 | `DONE` | `tests/parity/test_stop_loss_policy_parity.py::test_stop_loss_gate_decision_routing_f11_parity` PASS; `tests/parity/test_routing_gate_parity_v1.py` PASS |
|
||
| F12 | `DONE` | `tests/parity/test_distribution_risk_parity.py::test_distribution_risk_parity_scenarios` PASS |
|
||
| F13 | `DONE` | `tests/parity/test_distribution_risk_parity.py::test_distribution_risk_parity_scenarios` PASS |
|
||
| F14 | `DONE` | `tests/parity/test_late_chase_risk_parity.py::test_close_vs_ma20_ranges_parity` PASS |
|
||
| F15 | `DONE` | `tests/parity/test_stop_loss_policy_parity.py::test_late_chase_gate_f15_parity` PASS; `tests/parity/test_routing_gate_parity_v1.py` PASS |
|
||
|
||
#### finding 종료 규칙
|
||
|
||
- `DONE`: parity test 또는 registry 정정이 있고, 해당 finding이 더 이상 GAS 삭제/이관의 blocker가 아니다.
|
||
- `KEEP_IN_GAS`: rendering 또는 platform stub처럼 GAS adapter 책임에 남는 경우만 허용한다.
|
||
- `TODO`: 현재 ledger 기준 0건이어야 한다.
|
||
- `BLOCKER`: 전용 parity 테스트가 없는 상태에서 migration_action을 삭제/이관으로 승격할 수 없다.
|
||
|
||
#### migration_action 기준 BLOCKER 연결
|
||
|
||
| migration_action | 관련 finding | 현재 판정 | 완료 조건 | 증빙 |
|
||
|------------------|--------------|-----------|----------|------|
|
||
| `REGISTER_SP_TAKE_PROFIT` | F01 | `DONE` | registry stale 정정만 남음 | `spec/calibration_registry.yaml` |
|
||
| `REGISTER_TAKE_PROFIT_BASE` | F09 | `DONE` | registry stale 정정만 남음 | `spec/calibration_registry.yaml` |
|
||
| `MIGRATE_PRICEBASIS_TO_PYTHON` | F02, F03, F04, F06 | `DONE` | `tests/parity/test_stop_loss_policy_parity.py`에 `test_price_basis_f02_f06_parity`를 추가해 가격 기준 및 가격 산출 로직에 대해 GAS와의 동등성을 입증 및 포팅 종결함 | `tests/parity/test_stop_loss_policy_parity.py::test_price_basis_f02_f06_parity` |
|
||
| `MIGRATE_SCORE_CALCULATION` | F07 | `DONE` | `tests/parity/test_stop_loss_policy_parity.py`에 `test_score_calculation_f07_parity`를 추가해 익절 조건 만족 시 매도 순위 점수 가산 로직의 동등성을 입증 및 포팅 종결함 | `tests/parity/test_stop_loss_policy_parity.py::test_score_calculation_f07_parity` |
|
||
| `MIGRATE_DECISIONS_ROUTING` | F05, F10 | `DONE` | `tests/parity/test_stop_loss_policy_parity.py`와 `tests/parity/test_routing_decision_parity.py`로 stop/heat/cash-floor 중심의 routing 동등성을 검증 완료함 | `tests/parity/test_stop_loss_policy_parity.py::test_action_routing_f05_parity`, `tests/parity/test_routing_decision_parity.py::test_heat_gate_and_mr_gating` |
|
||
| `MIGRATE_STOP_BREACH_DECISION` | F11 | `DONE` | `tests/parity/test_stop_loss_policy_parity.py`를 확장하여 F11 stop_loss_gate 의사결정의 Python 동등성을 검증하고 Parity 테스트를 통과함 | `tests/parity/test_stop_loss_policy_parity.py::test_stop_loss_gate_decision_routing_f11_parity` |
|
||
| `DELETE_DISTRIBUTION_RISK_GAS` | F12, F13 | `DONE` | `tests/parity/test_distribution_risk_parity.py`를 작성하여 GAS calcDistributionRiskRow_의 10가지 세부 팩터 조건과 Python build_distribution_risk_score_v2.py의 계산 일치를 검증 완료함. parity가 완벽히 입증되었으므로 DONE 처리 | `tests/parity/test_distribution_risk_parity.py::test_distribution_risk_parity_scenarios` |
|
||
| `DELETE_LATE_CHASE_RISK_GAS` | F14 | `DONE` | `tests/parity/test_late_chase_risk_parity.py`를 신규 구축하여 이평선 괴리도/DART 공시/분산 차단/거래량 미확인 돌파 등 6가지 late chase 가산 규칙에 대한 Python 계산 정합성 검증 완료 | `tests/parity/test_late_chase_risk_parity.py::test_close_vs_ma20_ranges_parity` |
|
||
| `MIGRATE_LATE_CHASE_GATE` | F15 | `DONE` | `tests/parity/test_stop_loss_policy_parity.py`를 확장하여 F15 late_chase_gate 의사결정의 Python 동등성을 검증하고 Parity 테스트를 통과함 | `tests/parity/test_stop_loss_policy_parity.py::test_late_chase_gate_f15_parity` |
|
||
| `DISPLAY_TEXT_PASSTHROUGH` | F08 | `KEEP_IN_GAS` | display_text는 pure narrative/rendering output이므로 GAS adapter에 렌더링 책임으로 남김 | `spec/56_renderer_copy_only_contract.yaml`, `spec/40_final_decision_packet_contract.yaml` |
|
||
|
||
| 세부 WBS | 작업 | 데이터 기반 완료 정의 | 현재 상태 |
|
||
|----------|------|-------------------|----------|
|
||
| 8.1.1 | 잔여 GAS finding 재분류 | `governance/gas_logic_migration_ledger_v1.yaml`에서 `status: TODO` = 0, `KEEP_IN_GAS`는 렌더링/플랫폼 스텁만 허용 | 완료 |
|
||
| 8.1.2 | parity 테스트 맵핑 | `tests/parity/test_stop_loss_policy_parity.py`, `tests/parity/test_distribution_risk_parity.py`, `tests/parity/test_late_chase_risk_parity.py`, `tests/parity/test_routing_decision_parity.py`가 ledger finding과 대응 | 완료 |
|
||
| 8.1.3 | parity PASS 증빙 | 위 parity 테스트가 로컬 검증에서 PASS이고 `Temp/gas_thin_adapter_validation_v1.json`이 `gate=PASS`를 유지 | 완료 |
|
||
| 8.1.4 | thin-adapter 정제 | `tools/validate_gas_thin_adapter_v1.py`의 `forbidden_gas_business_logic_count`가 정책 임계치 이내 | 완료 |
|
||
| 8.1.5 | GAS 배포 경로 정리 | `tools/deploy_gas.py`가 업로드/배포/검증만 수행하고 투자 판단 로직을 포함하지 않음 | 완료 |
|
||
| 8.1.6 | rendering-only 잔여 고정 | `F08`이 `spec/56_renderer_copy_only_contract.yaml`과 `spec/40_final_decision_packet_contract.yaml`로만 설명됨 | 완료 |
|
||
| 8.1.7 | 종료 선언 | `gas_*` 중 렌더링/배포 스텁 외의 결정 로직이 Python canonical로 귀속 | 완료 |
|
||
|
||
### WBS-8.2 `xlsx → sqlite` 변환 트랙
|
||
|
||
#### 현재 판정
|
||
|
||
| 항목 | 판정 | 근거 |
|
||
|------|------|------|
|
||
| `.gs → Python` | 부분 완료 | `WBS-8.1`의 `TODO`는 0, `KEEP_IN_GAS`는 F08 בלבד |
|
||
| `xlsx → sqlite` | 부분 완료 | `WBS-8.2.11` 종료 선언이 아직 진행 중 |
|
||
| `KIS Open API` 전환 | 진행 중 | `WBS-8.8.6` 전환 종료 선언이 미착수 |
|
||
| 플랫폼 전환 검증 | PASS | `python tools/validate_platform_transition_wbs_v1.py` PASS |
|
||
|
||
#### 목표 요약
|
||
|
||
- 최우선 핵심 키워드: **마이그레이션 완료 후 코드가 문제 없음을 데이터로 증빙**
|
||
- 그 다음 핵심 작업: **기존 Naver 스크래핑을 KIS Open API 우선 경로로 전환**
|
||
- 완료 판정은 구현 감상이 아니라 `YAML + 코드 + 데이터 실체 + 검증`의 동시 충족으로만 한다.
|
||
|
||
#### 재생성 명령
|
||
|
||
```powershell
|
||
python tools/run_kis_data_collection_v1.py --input-json GatherTradingData.json --sqlite-db Temp/test_kis_data_collection.db --output-json Temp/test_kis_data_collection.json --kis-account real --no-live-kis --no-naver
|
||
python tools/validate_platform_transition_wbs_v1.py
|
||
python tools/validate_snapshot_admin_web_v1.py
|
||
```
|
||
|
||
#### 증빙 파일 체크리스트
|
||
|
||
| 산출물 | 필수 필드/테이블 | 완료 기준 |
|
||
|--------|------------------|----------|
|
||
| `Temp/test_kis_data_collection.json` | `status`, `row_count`, `source_counts`, `started_at`, `finished_at`, `input_json`, `sqlite_db`, `rows[]` | `status=PASS`, `row_count>0`, `source_counts.gathertradingdata_json>0` |
|
||
| `Temp/test_kis_data_collection.db` | `collection_runs`, `collection_snapshots`, `collection_source_errors` | 3개 테이블 모두 존재하고 `collection_runs>0`, `collection_snapshots>0`, `collection_source_errors=0` |
|
||
| `Temp/snapshot_admin_web_validation.db` | `account_snapshot`, `settings`, `workspace_approval_v2`, `workspace_change_log`, `workspace_lock` | 테이블 5개가 존재하고 `single_workspace_sqlite=true`, `settings_and_snapshot_share_db=true` |
|
||
| `Temp/snapshot_admin_approval_packet_v1.json` | `approval_packet_path`, `settings_rows`, `account_snapshot_rows`, `summary`, `version` | approval packet 검증 산출물로 존재하고 snapshot admin smoke validator PASS |
|
||
| `GatherTradingData.json` | seed input | runbook과 workflow가 이 파일을 1차 seed로 사용 |
|
||
|
||
#### 재생성 판정
|
||
|
||
- `Temp/test_kis_data_collection.json`는 `status=PASS`와 `row_count>0`를 만족해야 한다.
|
||
- `Temp/test_kis_data_collection.json`는 `source_counts.gathertradingdata_json>0`를 만족해야 한다.
|
||
- `Temp/test_kis_data_collection.db`는 `collection_runs>0`, `collection_snapshots>0`, `collection_source_errors=0`를 만족해야 한다.
|
||
- `Temp/snapshot_admin_web_validation.db`는 5개 핵심 테이블이 모두 존재해야 한다.
|
||
- `Temp/snapshot_admin_approval_packet_v1.json`은 snapshot admin 검증의 승인 패킷으로 함께 존재해야 한다.
|
||
- 위 세 산출물은 `python tools/validate_platform_transition_wbs_v1.py`와 `python tools/validate_snapshot_admin_web_v1.py` PASS로 함께 판정한다.
|
||
|
||
#### WBS-8.2 성공 목표
|
||
|
||
| 목표 | 성공 판정 기준 | 기대 결과값 | 데이터 증빙 |
|
||
|------|----------------|-------------|-------------|
|
||
| M1 | `xlsx`가 직접 1차 입력이 아님 | `GatherTradingData.json` 우선, `GatherTradingData.xlsx` 보조 | `docs/GATHERTRADINGDATA_XLSX_OPERATING_RUNBOOK.md`, `.gitea/workflows/kis_data_collection.yml` |
|
||
| M2 | 수집 결과가 SQLite에 적재됨 | `collection_runs>=1`, `collection_snapshots>=1`, `collection_source_errors=0` | `Temp/test_kis_data_collection.db`, `Temp/test_kis_data_collection.json` |
|
||
| M3 | snapshot admin이 SQLite 단일 워크스페이스를 사용함 | `single_workspace_sqlite=true`, `settings_and_snapshot_share_db=true`, `collector_separate_db=true` | `Temp/snapshot_admin_web_validation.db`, `tools/validate_snapshot_admin_web_v1.py` |
|
||
| M4 | 전환 검증이 재현 가능함 | `python tools/validate_platform_transition_wbs_v1.py` PASS | `Temp/platform_transition_wbs_v1.json` |
|
||
| M5 | 검증 후 코드 무결성이 유지됨 | `gas_thin_adapter_gate=PASS`, `sqlite_schema_parity=PASS` | `Temp/gas_thin_adapter_validation_v1.json`, `tools/validate_gas_thin_adapter_v1.py` |
|
||
|
||
| 세부 WBS | 작업 | 데이터 기반 완료 정의 | 현재 상태 |
|
||
|----------|------|-------------------|----------|
|
||
| 8.2.1 | 수집 파이프라인 SQLite 1차화 | `.gitea/workflows/kis_data_collection.yml`이 xlsx를 직접 1차 입력으로 요구하지 않고 SQLite 적재를 수행 | 완료 |
|
||
| 8.2.2 | 어드민 편집기 SQLite 1차화 | `tools/validate_snapshot_admin_web_v1.py`가 `single_workspace_sqlite=true`, `settings_and_snapshot_share_db=true`를 PASS | 완료 |
|
||
| 8.2.3 | JSON 재생성성 | `Temp/test_kis_data_collection.json`이 `GatherTradingData.json` seed로 재생성되고 `status=PASS`를 유지 | 완료 |
|
||
| 8.2.4 | DB 재생성성 | `Temp/test_kis_data_collection.db`가 동일 seed 계열로 재생성되고 핵심 테이블 3개를 유지 | 완료 |
|
||
| 8.2.5 | snapshot DB 재생성성 | `Temp/snapshot_admin_web_validation.db`가 `GatherTradingData.json` seed로 재현되고 5개 핵심 테이블을 유지 | 완료 |
|
||
| 8.2.6 | approval packet 재현성 | `Temp/snapshot_admin_approval_packet_v1.json`이 snapshot admin validator와 함께 재생성 가능 | 완료 |
|
||
| 8.2.7 | xlsx 역할 축소 | `GatherTradingData.xlsx`는 `docs/GATHERTRADINGDATA_XLSX_OPERATING_RUNBOOK.md`에 적힌 보조 자산 역할만 수행 | 완료 |
|
||
| 8.2.8 | xlsx 직접 의존 제거 | workflow와 validator에서 `GatherTradingData.xlsx`를 직접 1차 입력으로 요구하지 않음 | 완료 |
|
||
| 8.2.9 | 증빙 파일 세트 고정 | 위 4개 Temp 산출물과 `python tools/validate_platform_transition_wbs_v1.py` PASS가 함께 존재 | 완료 |
|
||
| 8.2.10 | 재생성 절차 고정 | runbook에 `GatherTradingData.json` 우선, 이후 `tools/convert_xlsx_to_json.py`와 `tools/run_kis_data_collection_v1.py` 순서가 명시됨 | 완료 |
|
||
| 8.2.11 | 종료 선언 | operator guide와 workflow가 SQLite/JSON 우선을 유지 | 완료 |
|
||
|
||
#### 항목별 재생성 명령
|
||
|
||
| 항목 | 명령 |
|
||
|------|------|
|
||
| 8.2.3 JSON 재생성성 | `python tools/run_kis_data_collection_v1.py --input-json GatherTradingData.json --sqlite-db Temp/test_kis_data_collection.db --output-json Temp/test_kis_data_collection.json --kis-account real --no-live-kis` |
|
||
| 8.2.4 DB 재생성성 | `python tools/run_kis_data_collection_v1.py --input-json GatherTradingData.json --sqlite-db Temp/test_kis_data_collection.db --output-json Temp/test_kis_data_collection.json --kis-account real --no-live-kis` |
|
||
| 8.2.5 snapshot DB 재생성성 | `python tools/validate_snapshot_admin_web_v1.py` |
|
||
| 8.2.6 approval packet 재현성 | `python tools/validate_snapshot_admin_web_v1.py` |
|
||
|
||
#### 파일별 해석
|
||
|
||
- `GatherTradingData.json`: 수집 seed 입력이다.
|
||
- `Temp/test_kis_data_collection.json`: `run_kis_data_collection_v1.py`의 출력 요약이다.
|
||
- `Temp/test_kis_data_collection.db`: 같은 실행에서 생성되는 SQLite 수집 DB다.
|
||
- `Temp/snapshot_admin_web_validation.db`: snapshot admin web 검증이 사용하는 SQLite 워크스페이스 DB다.
|
||
- `Temp/snapshot_admin_approval_packet_v1.json`: snapshot admin 승인 패킷이다.
|
||
|
||
### WBS-8.8 Naver 스크래핑 → KIS Open API 전환 트랙
|
||
|
||
#### 목표 요약
|
||
|
||
- 핵심 키워드: **Naver 스크래핑 의존 축소 후 KIS Open API 우선화**
|
||
- 이 트랙은 시세/수급/호가 계열의 read-only 수집 경로를 KIS로 이동시키는 작업이다.
|
||
- Naver는 폴백 또는 보조 탐색으로만 남기고, 주요 운영 경로는 KIS API 결과로 판정한다.
|
||
- 운영 우선순위: `KIS 우선` > `Naver 폴백` > `seed JSON replay`.
|
||
- 저장 우선순위: `SQLite 우선` > `Temp JSON` > `xlsx archive`.
|
||
|
||
#### 성공 목표
|
||
|
||
| 목표 | 성공 판정 기준 | 기대 결과값 | 데이터 증빙 |
|
||
|------|----------------|-------------|-------------|
|
||
| K1 | KIS read-only 경로가 기본 경로임 | `KIS_APP_KEY`, `KIS_APP_SECRET` 기반 수집이 먼저 시도되고, KIS 성공 시 source_priority 선두에 위치함 | `.gitea/workflows/kis_data_collection.yml`, `tools/validate_kis_api_credentials_v1.py`, `Temp/test_kis_data_collection.json` |
|
||
| K2 | Naver 의존 축소 | 핵심 운영 입력에서 Naver가 보조/폴백으로만 남고, KIS 실패 시에만 선택됨 | `tools/build_qualitative_sell_inputs_v1.py`, `tools/fetch_naver_market_data_v1.py` |
|
||
| K3 | 결과값이 SQLite에 기록됨 | KIS 결과가 `src/quant_engine/kis_data_collection.db` 또는 `Temp/*db`로 적재되고 row_count>0 | SQLite DB 테이블, `tools/run_kis_data_collection_v1.py`, `Temp/test_kis_data_collection.db` |
|
||
| K4 | 실패가 투명하게 남음 | KIS 실패 시 `status`, `source_counts`, `error`가 숨지지 않고 JSON/DB에 남음 | `Temp/test_kis_data_collection.json`, validator 로그 |
|
||
| K5 | 운영 자동화가 유지됨 | 스케줄/수동 실행에서 동일 계약을 유지하고, seed-first/SQLite 우선 문구가 유지됨 | `.gitea/workflows/kis_data_collection.yml`, `tools/run_kis_data_collection_v1.py`, `docs/GATHERTRADINGDATA_XLSX_OPERATING_RUNBOOK.md` |
|
||
|
||
#### 세부 WBS
|
||
|
||
| 세부 WBS | 작업 | 데이터 기반 완료 정의 | 현재 상태 |
|
||
|----------|------|-------------------|----------|
|
||
| 8.8.1 | KIS 우선 수집 경로 고정 | workflow와 CLI가 read-only KIS를 먼저 시도 | 완료 ✅ |
|
||
| 8.8.2 | Naver 폴백 경계 확정 | KIS 실패 시에만 Naver가 선택됨 | 완료 ✅ |
|
||
| 8.8.3 | KIS credential 검증 | `tools/validate_kis_api_credentials_v1.py --dry-run` PASS | 완료 ✅ |
|
||
| 8.8.4 | SQLite 적재 검증 | KIS 수집 결과가 SQLite 테이블에 기록되고 row_count>0 | 완료 ✅ |
|
||
| 8.8.5 | 운영 보고서 증빙 | provenance와 실패 사유가 JSON/DB에 남음 | 완료 ✅ |
|
||
| 8.8.6 | 전환 종료 선언 | `source_priority[0] == kis_open_api`가 유지되고 `status=PASS`/`row_count>0`/`collection_runs>=1`/`collection_snapshots>=1`가 동시에 성립 | 완료 ✅ |
|
||
|
||
#### 8.8 작업 티켓
|
||
|
||
| 티켓 | 산출물 | 완료 정의 |
|
||
|------|--------|----------|
|
||
| 8.8.T1 | `tools/run_kis_data_collection_v1.py` | KIS 우선 경로가 기본 시도 경로로 남고 Naver는 폴백만 수행 |
|
||
| 8.8.T2 | `tools/validate_kis_api_credentials_v1.py` | dry-run 기준으로 credential/endpoint 증빙이 남음 |
|
||
| 8.8.T3 | `Temp/test_kis_data_collection.db` | collection_runs / collection_snapshots / collection_source_errors가 기대값을 만족 |
|
||
| 8.8.T4 | `Temp/test_kis_data_collection.json` | provenance, source_counts, row_count, status가 PASS로 남음 |
|
||
| 8.8.T5 | `docs/GATHERTRADINGDATA_XLSX_OPERATING_RUNBOOK.md` | xlsx는 seed-prep 보조 자산으로만 설명됨 |
|
||
| 8.8.T6 | `python tools/validate_platform_transition_wbs_v1.py` | WBS-8.2/8.8 검증이 PASS 유지 |
|
||
|
||
#### collector helper 증빙
|
||
|
||
- `tests/unit/test_kis_data_collection_v1.py`
|
||
- `tests/integration/test_kis_collection_to_snapshot_admin_and_sell_strategy_v1.py`
|
||
- `src/quant_engine/kis_data_collection_v1.py`
|
||
|
||
### WBS-8.3 공통 완료 정의
|
||
|
||
- `YAML`
|
||
- 트랙별 WBS가 `docs/ROADMAP_WBS.md`에 존재해야 한다.
|
||
- 관련 contract/spec/governance 문서가 같은 방향을 가리켜야 한다.
|
||
- `코드`
|
||
- `.gs → Python`은 canonical Python 구현과 parity test가 있어야 한다.
|
||
- `xlsx → sqlite`는 canonical SQLite store와 이를 사용하는 workflow/validator가 있어야 한다.
|
||
- `데이터`
|
||
- `Temp/*.json`, `Temp/*.db`, `GatherTradingData.json`, `GatherTradingData.xlsx` 중 해당 트랙의 실제 산출물이 존재해야 한다.
|
||
- `.gs → Python`은 `Temp/gas_thin_adapter_validation_v1.json`, parity test 결과, migration ledger가 함께 있어야 한다.
|
||
- `xlsx → sqlite`는 `Temp/test_kis_data_collection.db`, `Temp/test_kis_data_collection.json`, `Temp/snapshot_admin_web_validation.db`가 함께 있어야 한다.
|
||
- `검증`
|
||
- `python tools/validate_gas_thin_adapter_v1.py`
|
||
- `python tools/validate_platform_transition_wbs_v1.py`
|
||
- `python tools/validate_snapshot_admin_web_v1.py`
|
||
- `python tools/validate_packaged_artifact_references_v1.py --strict`
|
||
|
||
### WBS-8.4 실행 순서
|
||
|
||
1. `.gs → Python` 잔여 finding을 `TODO / DONE / KEEP_IN_GAS`로 재집계한다.
|
||
2. `tests/parity/test_stop_loss_policy_parity.py`, `tests/parity/test_distribution_risk_parity.py`, `tests/parity/test_late_chase_risk_parity.py`, `tests/parity/test_routing_decision_parity.py`를 ledger finding과 1:1 대응시킨다.
|
||
3. `src/quant_engine/kis_data_collection_v1.py`를 source selection / source normalization / persistence로 분리한 뒤, collector 단일 책임을 유지한다.
|
||
4. `xlsx → sqlite` 의존 경로를 workflow와 validator에서 제거한다.
|
||
5. `Temp/test_kis_data_collection.json`과 `Temp/test_kis_data_collection.db`를 재생성한다.
|
||
6. `Temp/snapshot_admin_web_validation.db`를 재생성하고 `python tools/validate_snapshot_admin_web_v1.py`를 다시 통과시킨다.
|
||
7. 완료 정의를 충족하는 항목만 `DONE`으로 승격한다.
|
||
8. `GatherTradingData.xlsx`는 seed-prep/복구용 보조 자산으로만 취급하고 직접 실행 경로에서 제외한다.
|
||
9. `spec/56_renderer_copy_only_contract.yaml`와 `spec/40_final_decision_packet_contract.yaml`의 F08 근거를 유지한다.
|
||
10. runbook과 workflow가 JSON/SQLite 우선을 1차 권위로 유지하는지 재검증한다.
|
||
|
||
### WBS-8.5 현재 결론
|
||
|
||
- `.gs → Python`: 아직 **부분 완료**다.
|
||
- `xlsx → sqlite`: 아직 **부분 완료**다.
|
||
- 둘 다 “파일 수를 줄이는 것”이 완료가 아니라, **결정 로직의 권위와 입력의 권위를 옮기는 것**이 완료다.
|
||
|
||
### WBS-8.6 GAS ledger 재분류 블로커
|
||
|
||
현재 `governance/gas_logic_migration_ledger_v1.yaml`의 23개 `forbidden_gas_business_logic_count`는 다음 이유로 즉시 재분류할 수 없다.
|
||
|
||
| blocker | 영향 | 판정 |
|
||
|---------|------|------|
|
||
| 전용 parity test 부재 | `MIGRATE_*` 계열은 GAS와 Python의 동일 입력/동일 출력 증빙이 있어야 `DONE` 승격 가능 | BLOCKED |
|
||
| canonical Python 부재/불명확 | `DELETE_*` 계열은 Python canonical 또는 동등 판정이 없으면 삭제 불가 | BLOCKED |
|
||
| renderer-only 경계만 확정 | `F08`만 `KEEP_IN_GAS`로 유지 가능 | READY |
|
||
| collector refactor는 범위 외 | KIS 우선 수집 경로는 GAS thin-adapter ledger가 아니라 WBS-8.8에서 추적 | OUT_OF_SCOPE |
|
||
|
||
즉, 현재 레저는 `TODO`가 아니라 `parity / canonical evidence` 부족 상태다.
|
||
다음 스프린트에서 해야 할 일은 "기계적 재분류"가 아니라 "증빙을 만들고 그 증빙으로 승격"이다.
|
||
|
||
#### 잔여 finding의 실제 작업 단위
|
||
|
||
| 카테고리 | 대상 finding | 다음 작업 |
|
||
|----------|--------------|----------|
|
||
| price/qty parity | F02, F03, F04, F05, F06 | `tests/parity/test_price_qty_parity_v1.py`로 동일 입력 포트 테스트를 고정하고 Python 출력과 대조. `compute_sell_decision()` / `compute_stop_action_ladder()` 동시 검증 |
|
||
| score parity | F07, F12, F13, F14 | `tests/parity/test_score_parity_v1.py`로 `BUY_BREAKOUT_PILOT_ONLY`, `BUY_PULLBACK_WAIT`, `EXIT_REVIEW`, `STOP_OR_TIME_EXIT_READY`, `OBSERVE_DATA_MISSING` golden case를 분리 검증 |
|
||
| routing parity | F10, F11, F15 | `tests/parity/test_routing_gate_parity_v1.py`로 `STOP_OR_TIME_EXIT_READY`, `RISK_OFF`, `HALVE_NEW_BUY_QUANTITY`, `HARD_BLOCK`, `RW2B_FAST_TRACK`, `trailing_stop`, `MEAN_REVERSION` golden case를 분리 검증 |
|
||
| registry confirmation | F01, F09 | 이미 DONE이므로 재작업 불필요 |
|
||
| presentation-only | F08 | `KEEP_IN_GAS` 유지 |
|
||
|
||
### WBS-8.7 실행 티켓
|
||
|
||
| 티켓 | 체크 | 증빙 | 상태 |
|
||
|------|------|------|------|
|
||
| 8.7.1 | [x] F08 유지 근거 고정 | `governance/gas_logic_migration_ledger_v1.yaml`의 `status: KEEP_IN_GAS` + `rationale` + roadmap inventory 반영 | 완료 |
|
||
| 8.7.2 | [x] xlsx 보조 자산 선언 | `docs/GATHERTRADINGDATA_XLSX_OPERATING_RUNBOOK.md` + roadmap 문구 | 완료 |
|
||
| 8.7.3 | [x] seed-prep 분리 | `kis_data_collection.yml`이 workbook 직접 regeneration을 수행하지 않음 | 완료 |
|
||
| 8.7.4 | [x] JSON 우선 운영 명시 | workflow/operator guide가 `GatherTradingData.json`을 1차 입력으로 취급 | 완료 |
|
||
| 8.7.5 | [x] xlsx 아카이브 통합 | archive policy를 operating runbook에 통합해 중복 문서를 제거 | 완료 |
|
||
| 8.7.6 | [x] renderer contract 연결 | `spec/56_renderer_copy_only_contract.yaml`와 `spec/40_final_decision_packet_contract.yaml`에 의해 F08이 rendering-only로 유지 | 완료 |
|
||
| 8.7.7 | [x] 종료 체크 | `validate_platform_transition_wbs_v1.py`와 `validate_snapshot_admin_web_v1.py` PASS | 완료 |
|
||
|
||
---
|
||
|
||
## 7. 부록: Phase 5 데이터 플랫폼 전환 WBS 성공값
|
||
|
||
> 원칙: 아래 항목은 모두 `기대 성공값 + 데이터 증빙 + 검증 명령`이 함께 있어야 성공으로 본다.
|
||
> 현재 구현된 항목은 로컬 `Temp/` 증빙을 기준으로 판정하고, 아직 미래 전환 항목은 `DATA_GATED`로 둔다.
|
||
|
||
| WBS | 기대 성공값 | 데이터 증빙 | 검증 명령 |
|
||
|-----|------------|------------|-----------|
|
||
| P1 KIS core collector | `collector_gate=PASS`, `output_json_gate=PASS`, `collection_runs>=1`, `collection_snapshots>=1`, `provenance_source_count>=1` | `Temp/test_kis_data_collection.json`, `Temp/test_kis_data_collection.db` | `python tools/run_kis_data_collection_v1.py --input-json GatherTradingData.json --sqlite-db Temp/test_kis_data_collection.db --output-json Temp/test_kis_data_collection.json --kis-account real --no-live-kis --no-naver` |
|
||
| P2 SQLite canonical store | `sqlite_schema_tables>=3`, `round_trip_snapshot_lookup=PASS`, `backend_contract_sqlite=PASS`, `backend_contract_postgresql=READY`, `single_workspace_sqlite=true`, `collector_separate_db=true` | `src/quant_engine/data_collection_store_v1.py`, `src/quant_engine/data_collection_backend_v1.py`, `tests/unit/test_data_collection_store_v1.py`, `src/quant_engine/snapshot_admin_store_v1.py` | `python -m pytest tests/unit/test_data_collection_store_v1.py -q` |
|
||
| P3 CI scheduler cutover | `xlsx_dependency_removed=true`, `json_seed_input=true`, `sqlite_output=true`, `mock_api_validation=PASS`, `no_direct_trading_gate=PASS` | `.gitea/workflows/kis_data_collection.yml`, `Temp/kis_api_credentials_validation_v1.json`, `Temp/test_kis_data_collection.json` | `python tools/validate_no_direct_api_trading_v1.py` |
|
||
| P4 GAS thin adapter minimize | `allowed_responsibilities_only=true`, `forbidden_responsibilities_present=false`, `thin_adapter_gate=PASS` | `tools/validate_gas_thin_adapter_v1.py`, `Temp/gas_thin_adapter_validation_v1.json`, `src/gas/core/gas_lib.gs` | `python tools/validate_gas_thin_adapter_v1.py` |
|
||
| P5 PostgreSQL upgrade path | `sqlite_schema_parity=PASS`, `backend_contract_present=true`, `postgres_execution=DATA_GATED`, `caller_compatibility_preserved=true` | `src/quant_engine/data_collection_backend_v1.py`, `src/quant_engine/kis_data_collection_v1.py`, `tests/unit/test_data_collection_store_v1.py`, `tools/generate_postgresql_upgrade_stub_v1.py` | `python -m pytest tests/unit/test_data_collection_store_v1.py -q` |
|
||
| P6 Snapshot admin web editor | `settings_sheet_web_editor=true`, `account_snapshot_sheet_web_editor=true`, `contenteditable_grid=true`, `api_save_round_trip=PASS`, `kis_collection_dashboard=true`, `workspace_db_is_single_file=true`, `collection_filter_controls=true`, `collection_dashboard_page=true`, `change_timeline_view=true` | `src/quant_engine/snapshot_admin_server_v1.py`, `src/quant_engine/data_collection_store_v1.py`, `src/quant_engine/snapshot_admin_store_v1.py`, `tools/validate_snapshot_admin_web_v1.py`, `tests/unit/test_snapshot_admin_web_v1.py`, `.gitea/workflows/snapshot_admin.yml` | `python tools/validate_snapshot_admin_web_v1.py` |
|
||
| P7 PostgreSQL history-first operating model | `market_raw_history=true`, `factor_version_history=true`, `factor_output_history=true`, `decision_result_history=true`, `market_vs_engine_gap_history=true`, `sheet_operating_path_removed=true`, `gas_operating_path_removed=true` | `spec/02_data_contract.yaml`, `spec/postgresql_history_contract.yaml`, `docs/DAILY_SIGNAL_TRACKING.md`, `docs/POSTGRESQL_HISTORY_FIRST_OPERATING_MODEL.md` | `python tools/validate_postgresql_history_contract_v1.py` |
|
||
| Q1 Qualitative sell pipeline | `mock_api_validation=PASS`, `pipeline_contract=PASS`, `workflow_present=true`, `schedule_present=true`, `package_scripts_present=true` | `.gitea/workflows/qualitative_sell_strategy.yml`, `tools/validate_qualitative_sell_strategy_pipeline_v1.py`, `Temp/qualitative_sell_strategy_pipeline_v1.json` | `python tools/validate_qualitative_sell_strategy_pipeline_v1.py` |
|
||
| Q2 Gitea secrets contract | `secrets_contract=PASS`, `workflow_secret_mapping=PASS`, `docs_present=true`, `ci_validation_present=true` | `docs/GITEA_SECRETS_SETUP.md`, `tools/validate_gitea_secrets_contract_v1.py`, `Temp/gitea_secrets_contract_v1.json` | `python tools/validate_gitea_secrets_contract_v1.py` |
|
||
|
||
### WBS 성공 판정 규칙
|
||
|
||
- `PASS`: 기대 성공값이 충족되고, 해당 증빙 파일이 실제로 존재한다.
|
||
- `READY`: 지금은 실행하지 않지만, 다음 단계 전환에 필요한 코드/계약이 존재한다.
|
||
- `DATA_GATED`: 의도적으로 아직 실제 데이터가 쌓이지 않아 보류된 항목이다.
|
||
- `FAIL`: 기대 성공값을 만족하지 못하거나 증빙이 없다.
|
||
|
||
> 이 문서는 `docs/ROADMAP_WBS.md` 에 저장됩니다.
|
||
> 스프린트 완료마다 **완성도 KPI 섹션**을 업데이트하세요.
|
||
> 모든 WBS 항목의 구현 시 반드시 **하네스 성공 기준**을 먼저 충족 후 다음 단계로 진행합니다.
|