정성매도전략 공식 레지스트리 등록 + 로드맵 비판적 리뷰 종합 갱신
- spec/13b_harness_formulas.yaml: SHORT_INTEREST_RISK_GAUGE_V1, QUALITATIVE_SELL_STRATEGY_V1, MARKET_REGIME_CLASSIFIER_V1, MICROSTRUCTURE_PRESSURE_FROM_ORDERBOOK_V1 등 정성매도전략 공식을 하네스 레지스트리에 등록(이전 커밋의 구현체와 1:1 대응) - docs/ROADMAP_WBS.md: 2026-06-21 비판적 리뷰(0c절) + WBS-7.1~7.11 보완·고도화 전체를 반영 — 캘리브레이션 0/191 CALIBRATED 실태, T+5 지표 불일치 해소, GAS 마이그레이션 재검토, deprecated 정리, 통합테스트, Tabler 그리드, spec-코드 동기화 게이트, KRX 자동화 실측까지 포함한 완성도 매트릭스·KPI·스프린트 체크리스트 갱신
This commit is contained in:
+470
-1
@@ -18,6 +18,60 @@
|
||||
|
||||
---
|
||||
|
||||
## 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` — 오늘 기준 9일 전 데드라인, WBS 추적 없음 | `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. 프로젝트 비전 & 방향성
|
||||
|
||||
### 핵심 목표
|
||||
@@ -48,6 +102,8 @@ Phase 2 ████████████████░░░░ 신호
|
||||
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 | 기간 목표 | 핵심 산출물 | 완료 기준 |
|
||||
@@ -57,6 +113,8 @@ Phase 5 ████████████████████ 완전
|
||||
| **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 |
|
||||
|
||||
---
|
||||
|
||||
@@ -526,6 +584,355 @@ CI 게이트:
|
||||
|
||||
---
|
||||
|
||||
### 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 전체를 원문부터 재검증 |
|
||||
| **현재 상태** | 2건 DONE(F01/F09, 레저가 stale했을 뿐 실제론 이미 등록됨), 1건 KEEP_IN_GAS, **12건 TODO 유지 — 의도적 보류** |
|
||||
| **담당 파일** | `governance/gas_logic_migration_ledger_v1.yaml` |
|
||||
| **상태** | 부분 완료 — 안전하게 처리 가능한 항목만 종결, 나머지는 근거 있는 보류 |
|
||||
|
||||
**재검증으로 발견한 사실**:
|
||||
```
|
||||
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({'TODO': 12, 'DONE': 2, '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 기준으로 판정됨을 확인)
|
||||
잔여 12건은 전용 parity 테스트 스프린트(별도 WBS)로 이관 — 이번 세션에서는 시도하지 않음.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### WBS-7.4 Deprecated 별칭·시트 정리 (데드라인 2026-06-30)
|
||||
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| **작업** | `spec/aliases.yaml`의 deprecated 경로 17건을 데드라인 전 코드/spec 참조에서 전수 제거 |
|
||||
| **현재 상태** | `remove_after: 2026-06-30` — 오늘(2026-06-21) 기준 9일 남음, 추적 항목 없었음 |
|
||||
| **담당 파일** | `spec/aliases.yaml`, `tools/validate_specs.py` |
|
||||
| **상태** | TODO — **긴급(데드라인 임박)** |
|
||||
|
||||
**성공 하네스 (데이터 기준)**:
|
||||
```
|
||||
검증: grep -rl "old_portfolio_exposure_framework\|old_risk_control" spec/ src/ tools/ | wc -l
|
||||
현재: deprecated 별칭 17건 등록, 참조 잔존 여부 미확인
|
||||
목표: 2026-06-30 이전 참조 0건 + spec/aliases.yaml에서 deprecated 항목 제거
|
||||
python tools/validate_specs.py → deprecated 경로 사용 시 FAIL 처리로 전환
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 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에서 상시 서비스로 운영할 수 있는지 검토 |
|
||||
| **현재 상태** | **기술적으로는 가능, 단 3가지 제약 확인됨** (아래) |
|
||||
| **담당 파일** | `.gitea/workflows/ci.yml`, `tools/run_snapshot_admin_server_v1.py`, `src/quant_engine/snapshot_admin_server_v1.py` |
|
||||
| **상태** | TODO — 구현 전 보안·접근 정책 결정 필요 |
|
||||
|
||||
**조사 결과**:
|
||||
|
||||
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분 뒤에도 프로세스 생존 확인
|
||||
```
|
||||
|
||||
> **이 항목은 "구현 가능"으로 결론났으나, 인증 부재 상태로 상시 서비스화하는 것은 보안 리스크이므로 사용자의 명시적 정책 결정(인증 추가 여부, 노출 범위) 없이는 실제 배포 스텝을 작성하지 않는다.**
|
||||
|
||||
---
|
||||
|
||||
#### 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 -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
|
||||
결과: {"total_spec_files": 159, "checked_count": 12, "missing_code_path_count": 0,
|
||||
"sync_field_coverage_pct": 7.55, "gate": "PASS"}
|
||||
회귀: python -m pytest tests/unit tests/integration -q → 85 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만 지우고 파일은 남겨뒀던 부분의 후속 정리)
|
||||
목표(2차, 분기별 확장): sync_field_coverage_pct ≥ 50% — formula registry급 파일들의
|
||||
공식 단위 동기화 메커니즘(calibration_registry gs_location/py_location) 커버리지 확장과 별개 트랙
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 완성도 로드맵 매트릭스
|
||||
|
||||
| WBS | 우선순위 | 난이도 | 선행조건 | 예상 기간 | 현재 완성도 |
|
||||
@@ -551,6 +958,19 @@ CI 게이트:
|
||||
| 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 테스트 | 부분완료 + 12건 의도적 보류 | 2/15 DONE, 12 TODO(근거기록), 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 | 중간 | 보안정책 결정 | 완료(검토만) | **100%** ✅ (구현은 정책 결정 대기) |
|
||||
| 7.10 어드민 테이블 그리드(Tabler) | 🟢 Low | 낮음 | 없음 | 완료 | **100%** ✅ (2026-06-21, 8 passed) |
|
||||
| 7.11 spec-코드 동기화 게이트 | 🔴 Critical | 중간 | 없음 | 완료 | **100%** ✅ (2026-06-22, 12/159 태깅, 85 passed) |
|
||||
|
||||
---
|
||||
|
||||
@@ -583,10 +1003,21 @@ CI 게이트:
|
||||
|
||||
성과:
|
||||
T+20 레저 건수: 0건 → 목표: 30건 (~2026-07-12) DATA_GATED
|
||||
예측 적중률(T+5): 54.76% (t5_ap_combined) → 목표: ≥55% ≈달성 근접
|
||||
예측 적중률(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: 0/14 완료 (0%) → 목표: 14/14 (100%, KEEP_IN_GAS 1건 제외)
|
||||
deprecated_alias_remaining: 17건 (데드라인 2026-06-30) → 목표: 0건
|
||||
e2e_integration_test_count: 0건 → 목표: ≥1건 (KIS수집→스냅샷→정성매도 체인)
|
||||
|
||||
자동화:
|
||||
run_all 성공률: 98단계 DAG PASS → 목표: ≥95% ✅ (step_count=98, wave_0~9)
|
||||
CI/CD 커버리지: 100% → 목표: 100% ✅ (Synology act_runner 온라인, 4게이트 PASS)
|
||||
@@ -676,6 +1107,44 @@ 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 마이그레이션 재검토 완료(2건 DONE 정정, 12건 의도적 보류+근거기록, 2026-06-21) — 잔여는 별도 parity 테스트 스프린트
|
||||
[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 완료)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 부록: 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` |
|
||||
| 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 항목의 구현 시 반드시 **하네스 성공 기준**을 먼저 충족 후 다음 단계로 진행합니다.
|
||||
|
||||
Reference in New Issue
Block a user