Files
QuantEngineByItz/spec/16_data_gaps_roadmap.yaml
T
kjh2064 416da59607 WBS-8.7: spec-code synchronization expanded to 66.4% (93/140 files)
Coverage improvement: 24.07% (39 files) → 66.4% (93 files)
- Tagged 54 additional spec files with has_code_implementation: true
- Covered: strategy/*, risk/*, exit/*, formulas/*, governance/*, contracts
- Target: 50% (81 files) — EXCEEDED by 12 files

Files tagged:
- spec/strategy: 20 files (action_matrix, entry_core, entry_gates, etc.)
- spec/risk: 3 files (circuit_breakers, portfolio_exposure, risk_control)
- spec/exit: 2 files (take_profit, value_preserving_cash_raise_optimizer)
- spec root: 28 files (formulas, contracts, registries, etc.)
- spec/03_formulas: 2 files (formula_registry, output_field_owner_ledger)
- spec/data_quality: 1 file (expectations)
- spec/fields: 1 file (field_dictionary)
- spec/formulas: 1 file (manifest)

Impact:
- Improved LLM radar discoverability for spec-to-code linkage
- Ready for WBS-9.6 (LLM document optimization phase)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-22 23:51:58 +09:00

864 lines
40 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
meta:
title: 데이터 갭 로드맵 — 단계별 보완 계획
version: 2026-06-21-platform-transition-v1
language: ko-KR
purpose: '의사결정 파이프라인(spec/09_decision_flow.yaml)에서 식별된 데이터 공백을 우선순위별로 정리하고, 단계별
구현 계획을 명시한다. GAS 수집 → spec 공식 → LLM 판단 순서로 각 갭의 의존성을 추적한다.
'
has_code_implementation: true
code_path:
- spec\16_data_gaps_roadmap.yaml
phase_1_completed:
G1_KOSPI_MA60:
status: DONE
implementation: fetchYahooOhlcMetrics → macro 탭 MA60 컬럼
enables: RISK_ON 판정 조건 KOSPI_MA20 >= KOSPI_MA60
G2_KOSPI_KOSDAQ_Ret10D:
status: DONE
implementation: fetchYahooOhlcMetrics → macro 탭 Ret10D
enables: 'daily_leader_scan C2: Ret10D_종목 - Ret10D_KOSPI'
G3_ETF_Ret10D:
status: DONE
implementation: fetchYahooPrice → sector_flow ETF_Ret10D
enables: 'RW2 상대약세: Ret10D_종목 - Ret10D_주도섹터ETF'
G4_USD_JPY_Ret2D:
status: DONE
implementation: calcDerivedPriceMetrics.ret2D → macro 탭 Ret2D (USD_JPY행)
enables: 'MRS usd_jpy_score: Ret2D <= -1 → +1점'
G5_credit_stress_proxy:
status: DONE
implementation: HYG ETF Ret5D → REGIME_PRELIM 행 credit_stress 필드
enables: MRS credit_score 자동 계산
limitation: HYG는 미국 HY proxy. 한국 신용스프레드 직접 수집은 3단계 과제.
G6_Rotation_Rank:
status: DONE
implementation: runSectorFlow 정렬 후 Rotation_Rank 컬럼
enables: C5 Rotation_Score 순위 <= 3 판단, RW1 섹터 순위 변화 추적
S4_MRS_auto_compute:
status: DONE
implementation: runMacro 내 MARKET_RISK_SCORE_V1 계산 → macro 탭 MRS_COMPUTED 행
enables: LLM이 macro 탭 한 번 읽어 MRS 즉시 확인 가능
phase_2_structural:
S1_trades_performance_sheet:
priority: HIGH
status: DONE
purpose: 'Bayesian multiplier (high/medium/low/no_bet) 및 net_expectancy 산출 기반.
미구현 시 bayesian_confidence는 항상 medium_confidence(0.5×) 고정.
'
required_columns:
- trade_id
- ticker
- sector
- entry_date
- entry_price
- entry_stage
- quantity
- stop_price_at_entry
- target_price_at_entry
- exit_date
- exit_price
- exit_reason
- pnl_pct
- holding_days
- entry_c1_score
- entry_c2_score
- entry_c3_score
- entry_c4_score
- entry_c5_score
- entry_mrs_score
- fc_bucket
derived_outputs:
- win_rate (최근 30건)
- avg_win_pct
- avg_loss_pct
- net_expectancy = (win_rate × avg_win_pct) - (loss_rate × avg_loss_pct)
- bayesian_confidence_multiplier 자동 결정
implementation_plan:
step_1: Google Sheets에 'performance' 탭 수동 생성
step_2: spec/17_performance_contract.yaml 계약서 작성
step_3: GAS에 performance 탭 읽기 함수 추가 → Bayesian multiplier 자동 계산
step_4: runDataFeed 내 bayesian_multiplier 필드 → data_feed 탭 추가
implementation_note: '2026-05-17 구현 완료. spec/17_performance_contract.yaml 신규 작성.
readPerformanceSheet_() GAS 함수 추가. EE_Est 계산에 Bayesian multiplier 반영. macro
탭 BAYESIAN_COMPUTED 행으로 상태 출력.
'
S2_stop_price_tracking:
priority: HIGH
status: DONE
purpose: 'TOTAL_HEAT_V1 계산 필수 입력값. 미구현 시 HF005(Total_Heat 10% 차단) 미작동. stop_price
없으면 포트폴리오 총 위험노출 계산 불가.
'
required_fields_per_position:
- ticker
- account
- average_cost
- stop_price
- holding_quantity
- last_updated
implementation_plan:
step_1: account_snapshot에 stop_price/highest_price_since_entry/last_updated
선택 컬럼 추가
step_2: spec/15_account_snapshot_contract.yaml에 account_snapshot_position_state
추가
step_3: 'GAS: account_snapshot 기반 TOTAL_HEAT 및 trailing stop 갱신'
interim_workaround: 'stop_price 미기록 시 STOP_PRICE_CORE_V1 공식으로 ATR 기준 추정: stop_price_est
= average_cost - ATR20 × 1.5 Total_Heat_est = sum((average_cost - stop_price_est)
× holding_quantity) / total_asset × 100
'
implementation_note: '2026-05-18 account_snapshot 통합 완료. positions_tab은 deprecated.
readAccountSnapshotHeat_() GAS 함수 추가 (ATR 추정 폴백 포함). macro 탭 TOTAL_HEAT 행으로
HF005 상태 출력.
'
S3_sector_flow_weekly_history:
priority: MEDIUM
status: DONE
implementation: 'option_B legacy interim 구현 완료 (2026-05-17). sector_flow 탭에 Prev_Rotation_Rank(W1),
Prev_Rotation_Rank_W2 컬럼 추가. W1 = sector_flow 시트에서 직전 실행 결과 읽기. W2 = PropertiesService[''sf_w2_ranks_json'']
캐시 (직전 실행 시 저장). RW1·RW3 컬럼이 sector_flow 탭에 자동 계산됨 → data_feed RW1·RW3 컬럼으로
전파.
'
enables: 'RW1 ''2주 연속 섹터 순위 3순위 이상 하락'' 자동 판단. RW3 ''외국인+기관 5D 순매도 2주 연속'' 자동
판단.
'
note: '2회 이상 실행 후 W1/W2 데이터가 축적되어야 RW1·RW3가 작동한다. 단, 이는 전회 실행 기준 legacy interim이며
주간 스냅샷 기반 sector_flow_history는 후속 Phase 4 과제다.
'
S4_sector_flow:
priority: HIGH
status: DONE
implementation: '2026-05-17 Phase 1-2 구현. sector_universe 원장 또는 DEFAULT_SECTOR_UNIVERSE_V2를
canonical source로 사용하고, 구성종목 수급을 수량 단순합산이 아닌 원화금액×가중치로 sector_flow에 집계한다. Coverage_Weight,
SmartMoney_5D_KRW, SmartMoney_5D_Norm, Flow_Breadth_5D, Data_Quality, Decision_Use를
추가했다. sector_universe 시트가 없으면 기본 템플릿을 생성하며, Is_ETF=Y 구성행은 ETF 자체 수급 혼입을 막기 위해
섹터 smart money 집계에서 제외한다.
'
limitation: 'KRX/KIND 기반 NAV/괴리율/추적오차/AUM 수집은 아직 미구현이며 etf_raw에서 ETF_NAV_Risk=NAV_DATA_MISSING으로
명시한다.
'
next_review_date: '2026-09-30'
next_review_action: 'KRX 정보데이터시스템/KIND 공식 API 또는 공개 데이터셋의 발급/이용약관 변경 여부를 재확인한다.
변경이 없으면 next_review_date를 다음 분기로 갱신하고 PLANNED 유지, 변경이 있으면 P1_kis_core_api_collector와
동일한 패턴으로 착수 여부를 결정한다.
'
automation_attempt_2026_06_22: 'pykrx(이미 tools/build_prediction_accuracy_harness_v2.py에서
EOD 가격 조회로 사용 중)의 get_etf_price_deviation()/get_etf_tracking_error()/get_shorting_balance()를
실제로 호출해 자동화 가능성을 재시도했다. 결과: 기본 시세조회(OHLCV)는 정상 작동(공개 엔드포인트, 로그인 불필요)하지만, 공매도
잔고/ETF 괴리율/추적오차 엔드포인트는 세션 쿠키를 정상 부트스트랩한 뒤에도 "HTTP 400 LOGOUT"을 반환했다(raw HTTP로
재현 확인). 이는 pykrx 임포트 시 출력되는 "KRX_ID/KRX_PW 환경변수 미설정" 경고와 정확히 일치 — 이 카테고리는 KRX
회원 로그인이 있어야 접근 가능한 서버측 인증 게이트이며, 헤더/세션 보정으로 해결되는 문제가 아님을 확인했다. 자동화하려면 KRX 계정(KRX_ID/KRX_PW)을
자격증명으로 코드에 등록해야 하는데, 이는 governance/rules/06·07과 유사한 새로운 자격증명 정책 결정이 필요한 사안이라
사용자 승인 없이 추가하지 않는다. 기술적 장벽 자체는 명확히 확정됐으므로 next_review_date 재조사 시 "API 키 발급 가능성"이
아니라 "KRX 계정 발급·자격증명 관리 정책 승인 여부"로 재구성해 검토할 것.
'
S5_etf_raw_execution_quality:
priority: HIGH
status: DATA_GATED
implementation: '2026-05-17 Phase 3 interim 구현. etf_raw 시트를 신설하고 ETF proxy/ETF
구성행에 대해 Close, Bid, Ask, Spread_Pct, AvgTradeValue_5D_KRW, AvgTradeValue_20D_KRW,
ETF_Frg_5D_KRW, ETF_Inst_5D_KRW, ETF_Liquidity_Score, ETF_Liquidity_Status를
산출한다. NAV_DATA_MISSING 상태에서는 ETF_Execution_Use=WATCH_ONLY로 표시해 ETF 매매 실행 근거와
섹터 수급 근거를 분리한다. etf_nav_manual 시트가 있으면 NAV, iNAV, 괴리율, 추적오차, AUM을 etf_raw에 반영한다.
tools/import_etf_nav_manual.py로 KRX/KIND/운용사 CSV/XLSX export를 etf_nav_manual로
변환할 수 있다.
'
limitation: NAV, iNAV, 괴리율, 추적오차, AUM 자동 수집은 KRX/KIND 수집 경로 확정 전까지 미구현.
next_review_date: '2026-09-30'
next_review_action: S4_sector_flow.next_review_action과 동일 — KRX/KIND 경로 확정 시 etf_nav_manual
수동 경로를 자동 수집으로 대체.
automation_attempt_2026_06_22: S4_sector_flow.automation_attempt_2026_06_22와 동일
사유로 자동화 불가 확정(pykrx get_etf_price_deviation/get_etf_tracking_error 모두 HTTP 400
LOGOUT — KRX 회원 로그인 필요).
S6_sector_flow_history:
priority: HIGH
status: DONE
implementation: '2026-05-17 Phase 4 interim 구현. sector_flow_history 시트에 Snapshot_Date+Sector
기준으로 sector_flow 누적 스냅샷을 upsert한다. sector_flow의 RW1/RW3 계산은 sector_flow_history를
우선 사용하고, 이력이 부족할 때만 기존 sector_flow/PropertiesService 값을 fallback으로 사용한다. Snapshot_Date는
Apps Script Date 객체와 문자열 날짜를 모두 yyyy-MM-dd로 정규화한다.
'
S7_snapshot_admin_web_editor:
priority: HIGH
status: DONE
implementation: 'SQLite canonical store용 웹 편집기 구현. settings/account_snapshot을
contenteditable 그리드로 직접 수정하고, TSV import/export, 행 삽입/복제, 승인/잠금/undo를 API로 제어한다.
KIS SQLite collector 상태 패널을 함께 노출해서 최신 수집 run/오류를 같은 화면에서 확인한다. web UI는 Snapshot
Admin 서버가 담당하며 JSON export는 CI/파생 도구용이다.
'
enables: 'settings/account_snapshot을 xlsx 대신 SQLite에서 직접 관리하면서도 스프레드시트처럼 편집 가능한
운영 surface와 수집 현황 대시보드 제공.
'
success_criteria:
settings_sheet_web_editor: true
account_snapshot_sheet_web_editor: true
contenteditable_grid: true
api_save_round_trip: PASS
kis_collection_dashboard: true
single_workspace_sqlite: true
collection_filter_controls: true
collection_dashboard_page: true
change_timeline_view: true
evidence:
code:
- src/quant_engine/snapshot_admin_server_v1.py
- src/quant_engine/snapshot_admin_store_v1.py
- tools/validate_snapshot_admin_web_v1.py
tests:
- tests/unit/test_snapshot_admin_store_v1.py
- tests/unit/test_snapshot_admin_web_v1.py
workflow:
- .gitea/workflows/snapshot_admin.yml
verification: python tools/validate_snapshot_admin_web_v1.py
phase_3_enhancement:
A1_daily_leader_scan_auto:
priority: MEDIUM
status: DONE
implementation: 'P1(2026-05-17) 구현 완료. runDataFeed 루프 내 C1~C5 자동 계산. data_feed
: C1_Price, C2_RelStr, C3_VolSurge, C4_Flow, C5_Sector, Leader_Scan_Total,
Leader_Gate.
'
output_columns:
- C1_Price
- C2_RelStr
- C3_VolSurge
- C4_Flow
- C5_Sector
- Leader_Scan_Total
- Leader_Gate
A2_eps_growth_3y_cagr:
priority: MEDIUM
status: DONE
implementation: '2026-05-17 구현 완료. fetchYahooConsensusEps() 확장. Yahoo earningsTrend
+1y의 earningsEstimate.growth.raw 직접 추출. 없으면 (+1y avg - 0y avg) / abs(0y avg)
× 100 으로 계산. data_feed 탭 EPS_Growth_1Y_Pct 컬럼 추가 → LLM이 PEG = Forward_PE / EPS_Growth_1Y_Pct
계산 가능.
'
accuracy_note: 1년 성장률 추정치 (3Y CAGR 완전 대체 불가). KOSDAQ PEG 게이트에서 fallback보다 정확.
A3_pct_from_52w_low:
priority: LOW
status: DONE
purpose: Low52W 대비 현재가 반등률 — 저점 대비 위치 파악 (눌림 구간 분석)
expression: (Close / Low52W - 1) × 100
implementation: data_feed 탭 Pct_From_52W_Low 컬럼 (2026-05-17)
A4_ex_dividend_date:
priority: LOW
status: DONE
implementation: '2026-05-17 구현 완료. fetchYahooTargetPrice() 확장 (추가 API 호출 없음).
calendarEvents.exDividendDate → data_feed Ex_Dividend_Date, Days_To_Ex_Div 컬럼.
defaultKeyStatistics.lastDividendValue → data_feed DPS 컬럼.
'
A6_pos_size_qty:
priority: HIGH
status: DONE
implementation: '2026-05-17 구현 완료. data_feed Pos_Size_Qty 컬럼: POSITION_SIZE_V1
간략 버전 자동 계산. atr_qty = floor(total_asset × 0.007 × bayesian_multiplier / (ATR20
× 1.5)) weight_qty = floor(total_asset × 0.05 / Close) Pos_Size_Qty = min(atr_qty,
weight_qty). requires: settings 탭 total_asset_krw 입력. limitation: "cash/sector/liquidity
한도는 account_snapshot 필요. 현재는 ATR+weight 한도만 적용."
'
A7_stop_price_actual:
priority: HIGH
status: DONE
implementation: '2026-05-17 구현 완료. data_feed Stop_Price_Est: account_snapshot
실제 stop_price 우선 → ATR 추정 폴백. Stop_Price_Source 컬럼: "account_snapshot" / "ATR추정"
표시. EE_Est가 실제 stop_price 기반으로 계산됨 (포지션 있는 종목).
'
A8_settings_tab:
priority: HIGH
status: DONE
implementation: '2026-05-17 구현 완료. readSettingsTab_() GAS 함수 추가. settings 탭: key-value
구조 (key, value, note 컬럼). total_asset_krw: Pos_Size_Qty, TOTAL_HEAT_V1, FC_BUDGET
계산에 사용. spec/18_settings_contract.yaml 계약서 작성.
'
A9_fc_budget_tracking:
priority: MEDIUM
status: DONE
implementation: '2026-05-17 구현 완료. calcFcBudget_() GAS 함수 추가. performance 탭 fc_bucket=Y
거래 중 당월 청산 손실 집계. macro 탭 FC_BUDGET 행 추가: used_pct / 2.5% 예산 상태 출력. exhausted
시 LLM이 신규 stage_1 탐색 자동 억제 가능.
'
A5_kosdaq_vs_ma20:
priority: LOW
status: DONE
purpose: 'kosdaq_regime_supplement 규칙: KOSDAQ_Close < KOSDAQ_MA20 → MRS +1'
implementation: runMacro MRS 계산에 kosdaqSupp 로직 추가. macro 탭 KOSDAQ (^KQ11) 이미 수집
중 (2026-05-17)
analysis_enhancements:
B1_rw_signal_checklist:
purpose: RW1~RW5 자동 계산 및 출력
current_status:
RW1: ✅ sector_flow RW1 컬럼 자동 계산 (2026-05-17). Prev_Rotation_Rank(W1)+W2 PropertiesService
캐시 기반. 2회 이상 실행 후 정확.
RW2: ✅ data_feed RW2 컬럼 자동 계산 (2026-05-17). Ret10D - ETF_Ret10D <= -5%p
RW3: ✅ sector_flow RW3 컬럼 자동 계산 (2026-05-17). 외국인+기관 5D 순매도 2주 연속 (현재+W1 비교).
RW4: ✅ data_feed RW4 컬럼 자동 계산 (2026-05-17). AvgTradeValue_5D/20D <= 0.60
RW5: ✅ data_feed RW5 컬럼 자동 계산 (2026-05-17). Close < MA20 AND < MA60
RW_Partial: ✅ data_feed RW_Partial = RW1+RW2+RW3+RW4+RW5 합계 (0~5)
fully_automated:
- RW1 (2회 이상 실행 후)
- RW2
- RW3 (현재+W1 기준)
- RW4
- RW5
note: RW1·RW3의 '2주 연속' 조건은 2회 이상 실행 후 W1/W2 데이터 축적 시 완전히 정확해짐.
B2_total_heat_estimation:
purpose: stop_price 미기록 시 ATR 기준 Total_Heat 추정
formula: "For each holding in account_snapshot:\n stop_price_est = entry_price\
\ - ATR20 × 1.5\n heat_contribution = (entry_price - stop_price_est) × quantity\
\ / total_asset × 100\nTotal_Heat_est = sum(heat_contribution)\n"
requirement: ATR20(data_feed), entry_price(account_snapshot), quantity(account_snapshot),
total_asset(account_snapshot) 필요
note: actual stop_price가 있으면 실제값 우선. 없으면 이 추정으로 HF005 체크 가능.
B3_expected_edge_checklist:
purpose: EXPECTED_EDGE_V1 계산 전 필수 입력 확인
required_fields:
- 'target_price: data_feed Target_Price (Naver 또는 Yahoo) ✓'
- 'entry_price: limit_price (entry_core.yaml limit_price_formula) ✓'
- 'stop_price: stop_price_est (B2 또는 실제값) △'
- 'bayesian_confidence_multiplier: performance 시트 기반 (S1) — 미구현 시 0.5× 기본'
- 'execution_cost_rate: 0.003 고정 ✓'
B4_c2_now_computable:
purpose: daily_leader_scan C2 바로 계산 가능
formula: Ret10D_종목(data_feed) - Ret10D_KOSPI(macro) >= 3%p
status: G2 완료로 계산 가능. LLM이 두 탭 조회 후 즉시 판단.
B5_mrs_now_readable:
purpose: MRS 자동 계산 결과 macro 탭에서 직접 읽기
location: macro 탭 Symbol='MRS_COMPUTED' 행 → Close=점수, Status='score=X/10 cash=Y%'
usage: LLM이 macro 탭을 읽으면 MRS 재계산 없이 즉시 확인 가능
B6_flow_credit_v1_auto:
purpose: FLOW_CREDIT_V1 자동 계산 — data_feed Flow_Credit 컬럼
status: DONE
implementation: '2026-05-17 구현 완료. runDataFeed 루프 내 자동 계산. fc_c1: close >= open
OR close > prevClose → 0.30 fc_c2: volume >= avgVolume5D × 1.20 → 0.30 fc_c3:
flow_ok AND (frg5 + inst5) > 0 → 0.40 Hard override: C1=0 AND C2=0 → 0 (C3 단독
충족은 물량받기로 간주)
'
output_column: data_feed Flow_Credit (0.00~1.00)
B7_trailing_stop_price_auto:
purpose: TRAILING_STOP_PRICE_V1 자동 계산 — account_snapshot 최고가 기반
status: DONE
implementation: '2026-05-18 account_snapshot highest_price_since_entry 읽기/쓰기 통합
완료. trailingStopPrice = highest_price_since_entry - ATR20 × 1.5 account_snapshot에
highest_price_since_entry 미입력 시 공백.
'
output_column: data_feed Trailing_Stop_Price (KRW 정수)
B8_ss001_score_auto:
purpose: SS001 종목 점수 자동 계산 — 6개 축 + 총점 + 등급
status: DONE
implementation: '2026-05-17 구현 완료. runDataFeed 루프 내 자동 계산. SS001_P: core_satellite
RS_Pct_20D → percentile=100-RS_Pct_20D → ≤30=25pt/30~60=15pt/>60=0pt SS001_V:
avgTradingValue5D/20D 비율 → ≥120%=15pt/80~120%=8pt/<80%=0pt SS001_F: Flow_Credit
→ ≥0.70=25pt/0.40~0.70=12pt/<0.40=0pt SS001_E: EPS_Revision_Status → UP=20pt/FLAT=10pt/DOWN=0pt
SS001_M: REGIME_PRELIM(전회 macro 결과) → RISK_ON/LEADER_CONCENTRATION=10pt/NEUTRAL=5pt/기타=0pt
SS001_VAL: KOSPI→PER/PBR vs 섹터중앙값(max 5pt), KOSDAQ→PEG 기반(max 12pt) SS001_Total:
6개 합산 (KOSPI max 100, KOSDAQ max 107) SS001_Grade: 100점 환산 ≥80=A / ≥65=B / ≥50=C
/ <50=D
'
output_columns:
- SS001_P
- SS001_V
- SS001_F
- SS001_E
- SS001_M
- SS001_VAL
- SS001_Total
- SS001_Grade
data_dependency:
SS001_P: core_satellite 탭 RS_Pct_20D 컬럼 (runCoreSatelliteFinalize 필요)
SS001_M: 전회 runMacro 실행 결과 (초회 실행 시 0점)
SS001_VAL: sector_flow Sector_Median_PE/PBR (runSectorFlow 필요)
limitation: SS001_P는 core_satellite 탭이 비어있으면 0점 처리. 처음 사용 시 runCoreSatellite 먼저
실행.
B9_peg_gate_auto:
purpose: PEG 게이트 자동 계산 (KOSDAQ 종목 전용)
status: DONE
implementation: '2026-05-17 구현 완료. KOSDAQ_TICKERS Set 상수 추가 (현재 비어있음 — 보유 종목 모두
KOSPI). KOSDAQ 종목에서 EPS_Growth_1Y_Pct > 0 이면: PEG = Forward_PE / EPS_Growth_1Y_Pct
PEG_Gate: PASS(≤1.5) / CAUTION(1.5~2.5) / REJECT(>2.5) EPS 성장률 미수집 시: Fallback
→ sector_median_PE 대비 Forward_PE 배수로 대체
'
output_columns:
- PEG
- PEG_Gate
B10_full_market_regime:
purpose: MARKET_REGIME_V1 완전 판정 — macro+sector_flow 통합
status: DONE
implementation: '2026-05-17 구현 완료. runMacro() 내에서 sector_flow 탭 읽기 추가. (runSectorFlow()가
sector_flow 기록 완료 후 runMacro()가 호출되므로 최신값 읽기 가능) 판정 우선순위: RISK_OFF > SECULAR_LEADER_RISK_ON
> LEADER_CONCENTRATION > RISK_ON > NEUTRAL > RISK_OFF_CANDIDATE RISK_OFF: MRS>=7
OR (VIX>=25 AND KOSPI<MA20) SECULAR_LEADER_RISK_ON: LEADER_CONCENTRATION + top1=반도체
+ VIX<22 + KOSPI>MA20 LEADER_CONCENTRATION: top2_sum>=100 AND top1_score>=55
AND top1_alertScore>=2 AND Tier1섹터 AND Ret20D>0 AND VIX<25 RISK_ON: VIX<18 AND
KOSPI>MA20 AND (MA20>=MA60 OR Ret20D>0) AND (sfFrg20>0 OR sfInst20>0 OR top2sum>=100)
NEUTRAL: MRS<=5 그 외 RISK_OFF_CANDIDATE: MRS 5~6
'
output: REGIME_PRELIM 행 Close 컬럼 (Symbol=REGIME_PRELIM 유지 — 하위 호환)
note: '이전 값이 ''RISK_ON_CANDIDATE'', ''RISK_OFF_CANDIDATE''이던 것이 ''RISK_ON'', ''RISK_OFF''로
변경됨. SS001_M 점수 계산이 이제 정상 작동 (이전엔 항상 0점이었음).
'
B11_net_return_feedback:
purpose: net_return_feedback 상태 자동 계산 — RISK_BUDGET_CASCADE_V1 입력
status: DONE
implementation: "2026-05-17 구현 완료. runMacro() 내 bayesianInfo(performance 탭) 재사용.\
\ 규칙 (spec/05_position_sizing.yaml:net_return_feedback):\n trades < 20건: NORMAL\
\ (규칙 미적용)\n ne <= -2%: REDUCED — base_risk 0.007→0.003 삭감 권고\n ne <= 0%:\
\ CAUTION — high_confidence 금지, multiplier 0.5× 강제\n 연속손실 ≥5건 (bayesian no_bet와\
\ 별개로): NORMAL→CAUTION 승격\n 그 외: NORMAL\n"
output: macro 탭 NET_RETURN_FEEDBACK 행 (Symbol=NET_RETURN_FEEDBACK, Close=상태값)
C1_orbit_gap_tracking:
purpose: orbit_gap 자동 계산 — 월별 목표궤도 vs 실제 자산 추이 추적
status: DONE
implementation: '2026-05-17 구현 완료. spec/01_objective_profile.yaml:orbit_monthly_tracker
구현. calcOrbitGap_(settings) 함수: 기하평균 보간으로 목표누적수익률 계산. orbit_gap(%) = ((target/start)^(elapsed/total)
- 1) - (current/start - 1) orbit_state: significantly_behind(>3%p) / mild_behind(1~3%p)
/ on_track / ahead_of_target(<-2%p) offensive_slot_adj: significantly_behind=+2,
mild_behind=+1, on_track=0, ahead=0 cash_floor_adj: significantly_behind=-2%p,
mild_behind=-1%p, on_track=0, ahead=+1%p runOrbitGap(): orbit_gap 탭에 현재 월 행
추가/갱신 (월 1회 독립 트리거) runMacro(): ORBIT_GAP + ORBIT_STATE 2개 행 macro 탭에 자동 기록
'
required_settings:
- orbit_start_asset_krw — 시작 자산 (1월 기준)
- 'orbit_target_asset_krw — 목표 자산 (예: 5억)'
- 'orbit_start_yyyymm — 추적 시작 연월 (예: 2026-01)'
- 'orbit_end_yyyymm — 목표 달성 기한 (예: 2028-12)'
- total_asset_krw — 현재 자산 (기존 settings 항목 재사용)
output:
macro_tab: ORBIT_GAP 행(Close=gap %p), ORBIT_STATE 행(Close=상태, Status=slot/cash
조정값)
orbit_gap_tab: Month/Start_Asset/Target_Asset/Actual_Asset/Target_Return_Pct/Actual_Return_Pct/Orbit_Gap_Pct/Orbit_State/Slot_Adj/Cash_Floor_Adj/Updated
api_exposure:
getMacroJson: orbit_gap_pct, orbit_state, orbit_slot_adj, orbit_cash_adj
getSummaryJson: macro_snapshot.orbit_gap_pct, orbit_state, orbit_slot_adj
limitation: settings 탭에 4개 orbit_* 파라미터 미입력 시 ORBIT_GAP=N/A 기록 (runOrbitGap 스킵)
C2_take_profit_ladder:
purpose: TAKE_PROFIT_LADDER_V1 자동 계산 — core/satellite 분리 익절 사다리
status: DONE
implementation: '2026-05-18 account_snapshot average_cost + holding_quantity +
position_type 기반으로 변경. core: TP1=+15%(25% 물량), TP2=+25%(잔여 40% 물량). satellite:
TP1=+10%(50% 물량), TP2=+20%(잔여 50% 물량). Time_Stop: stage_1=60일, stage_2=30일 (entry_date
기준 만료일 + 잔여일수).
'
output_columns:
data_feed:
- TP1_Price
- TP1_Qty
- TP2_Price
- TP2_Qty
- Time_Stop_Date
- Days_To_Time_Stop
required_account_snapshot_fields:
- average_cost
- holding_quantity
- position_type
- entry_date
- entry_stage
C3_position_monitoring:
purpose: 포지션 모니터링 컬럼 자동 계산 — 비중/수익률/PnL/스테이지/밴드
status: DONE
implementation: "2026-05-18 account_snapshot + 당일 종가 기반으로 변경. Weight_Pct: close\
\ × quantity / total_asset_krw × 100. Profit_Pct: (close - entry_price) / entry_price\
\ × 100. Unrealized_PnL: (close - entry_price) × quantity (KRW 정수). Stage2_Gate:\
\ stage_1 포지션에서 가격 +1.5% 이상 시 PASS, 아니면 PENDING. Band_Status: satellite 단일종목\
\ 7% 상한. OVERWEIGHT/IN_BAND/UNDERWEIGHT.\n core는 CORE_HIGH(>10%)/CORE_MID(3~10%)/CORE_LOW(<3%).\n"
output_columns:
data_feed:
- Weight_Pct
- Profit_Pct
- Unrealized_PnL
- Stage2_Gate
- Band_Status
D1_bucket_allocation_status:
purpose: 포트폴리오 버킷 할당 상태 자동 계산 — core/satellite/cash 합계 vs 목표 범위
status: DONE
implementation: '2026-05-17 구현 완료. runDataFeed 루프에서 버킷별 Weight_Pct 누산. calcBucketStatus_()
함수: _bucketSnapshot_ 기반 bucket-level 집계. 목표 범위 (spec/risk): core 60-72%, satellite
10-25%, cash 10-22%. cash_pct = max(0, 100 - core_pct - satellite_pct) (추정값
— account_snapshot 미연동). overall: BALANCED / core_UNDERWEIGHT | sat_OVERWEIGHT
등 파이프 구분.
'
output:
macro_tab: BUCKET_STATUS 행(Close=overall, Status=core/sat/cash 상세)
api_exposure:
getMacroJson: bucket_status, bucket_detail
getSummaryJson: macro_snapshot.bucket_status, bucket_detail
limitation: 'cash_pct는 account_snapshot 마켓밸류를 total_asset에서 뺀 추정값. 실제 현금은 account_snapshot
없이 확인 불가. runDataFeed 실행 없이 runMacro만 실행하면 N/A.
'
phase_4_backdata_collection:
B1_gas_backdata_feature_bank:
priority: HIGH
status: DONE
purpose: '매수/매도 뒷북과 설거지 패턴을 줄이기 위한 진입-청산 백데이터 원장. 사람 입력보다 GAS 자동 수집을 1순위로 두고,
사람이 입력한 performance 기록은 보조 검증용 fallback으로만 사용한다.
'
collection_priority:
1: GAS가 생성한 backdata_feature_bank 시트/JSON
2: performance 시트의 청산 완료 거래
3: 수동 보정값
required_signals:
- entry_stage
- entry_leader_scan_total
- entry_c1_score
- entry_c2_score
- entry_c3_score
- entry_c4_score
- entry_c5_score
- entry_mrs_score
- entry_close_vs_ma20_pct
- entry_volume_ratio_5d
- entry_flow_credit
- entry_breakout_score
- entry_late_chase_risk_score
- entry_follow_through_score
- pnl_pct
- holding_days
- max_adverse_excursion_pct
- max_favorable_excursion_pct
implementation_plan:
step_1:
action: GAS에서 daily setup snapshot을 backdata_feature_bank 시트로 자동 upsert
status: DONE
note: syncBackdataFeatureBank_() — gdc_01_fetch_fundamentals.gs:1128, gdf_02_harness_assembly.gs:146
step_2:
action: performance 시트 청산 결과와 join해 outcome label을 자동 부여
status: DONE
note: buildBackdataFeatureBankRowsV1_() — mapLatestPerformanceByTicker_ 기반
join
step_3:
action: convert_xlsx_to_json.py에서 backdata_feature_bank_json 우선 수집
status: DONE
note: src/quant_engine/convert_xlsx_to_json.py:synthesize_backdata_feature_bank()
구현
step_4:
action: backdata_feature_bank_table을 report/validation에 반영
status: DONE
note: render_operational_report.py:_backdata_feature_bank_table(), validate_harness_context.py
검증
fallback_policy:
manual_input: performance 시트 또는 수동 보정은 fallback일 뿐 primary source가 아니다.
missing_action: GAS 생성본이 없으면 fallback 기록과 함께 source_origin=FALLBACK_SYNTH로 남긴다.
implementation_note: '2026-06-14 구현 완료 확인. GAS(syncBackdataFeatureBank_) + Python(synthesize_backdata_feature_bank)
모두 구현됨. T+20 데이터 누적 후 ML 패턴 학습 품질 향상 예정.
'
phase_5_platform_transition:
P1_kis_core_api_collector:
priority: HIGH
status: DONE
purpose: 'KIS Open API를 read-only 코어 수집원으로 두고, 가격/호가/공매도/수급의 1차 수집을 Python canonical
collector에서 직접 수행한다.
'
inputs:
- KIS_APP_Key / KIS_APP_Secret
- KIS_APP_Key_TEST / KIS_APP_Secret_TEST
- GatherTradingData.json
outputs:
- Temp/kis_data_collection_v1.json
- outputs/kis_data_collection/kis_data_collection.db
fallback_order:
- KIS Open API
- Naver Finance
- Yahoo Finance
- OpenDART
- Investing.com(best-effort, 차단 시 DATA_MISSING)
note: '주문 API는 사용하지 않는다. 조회형 quotations/ranking 계열만 허용한다.
'
success_criteria:
expected_success_value:
collector_gate: PASS
output_json_gate: PASS
sqlite_run_count_min: 1
sqlite_snapshot_count_min: 1
provenance_source_count_min: 1
evidence_artifacts:
- Temp/test_kis_data_collection.json
- Temp/test_kis_data_collection.db
verification_commands:
- 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 - <<'PY' ... sqlite count check ... PY
P2_sqlite_canonical_store:
priority: HIGH
status: DONE
purpose: 'xlsx 중심 저장을 중단하고, 수집 결과를 SQLite에 누적 저장한다. 향후 PostgreSQL 승격 시 동일 저장 인터페이스를
유지한다.
'
required_tables:
- collection_runs
- collection_snapshots
- collection_source_errors
stored_payloads:
- raw source payload
- normalized factor row
- provenance JSON
- batch/run metadata
migration_note: PostgreSQL 전환 시 dialect만 교체하고 row shape은 유지한다.
success_criteria:
expected_success_value:
sqlite_schema_tables_min: 3
round_trip_snapshot_lookup: PASS
backend_contract_sqlite: PASS
backend_contract_postgresql: READY
evidence_artifacts:
- src/quant_engine/data_collection_store_v1.py
- src/quant_engine/data_collection_backend_v1.py
- tests/unit/test_data_collection_store_v1.py
verification_commands:
- python -m pytest tests/unit/test_data_collection_store_v1.py -q
- python -m py_compile src/quant_engine/data_collection_store_v1.py src/quant_engine/data_collection_backend_v1.py
P3_ci_scheduler_cutover:
priority: HIGH
status: DONE
purpose: 'Gitea schedule에서 Python collector를 직접 실행하고, CI가 SQLite 산출을 검증한다. 기존
GAS 워크플로우는 thin adapter/legacy fallback으로만 유지한다.
'
validation_gate:
- read-only KIS gate
- source fallback gate
- sqlite round-trip gate
- provenance completeness gate
- no-direct-trading gate
output_policy:
- CI는 xlsx 생성에 의존하지 않는다.
- 결과는 JSON + SQLite + 로그 증빙으로 남긴다.
success_criteria:
expected_success_value:
xlsx_dependency_removed: true
json_seed_input: true
sqlite_output: true
mock_api_validation: PASS
no_direct_trading_gate: PASS
provenance_completeness_gate: PASS
notes: '`GatherTradingData.xlsx`는 runtime seed 재생성 fallback으로만 허용한다. collector
본문은 `GatherTradingData.json`만 사용하며, xlsx는 Prepare Raw Seed Snapshot 단계에서만
허용된다.
'
evidence_artifacts:
- .gitea/workflows/kis_data_collection.yml
- Temp/kis_api_credentials_validation_v1.json
- Temp/test_kis_data_collection.json
verification_commands:
- python tools/validate_no_direct_api_trading_v1.py
- python tools/validate_kis_api_credentials_v1.py --account mock --ticker 005930
- python tools/run_kis_data_collection_v1.py --help
P4_gas_thin_adapter_minimize:
priority: MEDIUM
status: DONE
purpose: '.gs는 기존 스프레드시트 호환과 과도기 검증용 얇은 어댑터만 남기고, 판단·수집·저장 로직은 Python으로 이동시킨다.
'
allowed_responsibilities:
- collect
- normalize
- export
- display
forbidden_responsibilities:
- decision
- sizing
- stop_loss
- take_profit
- risk_score
success_criteria:
expected_success_value:
allowed_responsibilities_only: true
forbidden_responsibilities_present: false
thin_adapter_gate: PASS
evidence_artifacts:
- tools/validate_gas_thin_adapter_v1.py
- Temp/gas_thin_adapter_validation_v1.json
- src/gas/core/gas_lib.gs
verification_commands:
- python tools/validate_gas_thin_adapter_v1.py
P5_postgresql_upgrade_path:
priority: MEDIUM
status: DONE
purpose: 'SQLite에서 검증된 스키마/업서트/프로venance 모델을 PostgreSQL로 승격한다. 운영 데이터 증가와 멀티잡
동시성 증가를 대비한다.
'
upgrade_steps:
- sqlite schema parity 검증
- db_url 기반 backend 추상화
- migration script 추가
- CI에서 sqlite/postgres 동일 테스트
compatibility_rule: SQLite와 PostgreSQL 모두 동일한 row contract를 유지한다.
success_criteria:
expected_success_value:
sqlite_schema_parity: PASS
backend_contract_present: true
postgres_execution: DATA_GATED
caller_compatibility_preserved: true
evidence_artifacts:
- 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
verification_commands:
- python -m pytest tests/unit/test_data_collection_store_v1.py -q
- python -m py_compile src/quant_engine/kis_data_collection_v1.py tools/run_kis_data_collection_v1.py
- python tools/generate_postgresql_upgrade_stub_v1.py
Q1_qualitative_sell_pipeline:
priority: MEDIUM
status: PLANNED
purpose: '비기계적 매도전략 파이프라인을 Gitea workflow + SQLite 시계열 + mock KIS 유효성 검증 + 사후
적중률 평가까지 일관된 계약으로 묶는다.
'
success_criteria:
expected_success_value:
mock_api_validation: PASS
pipeline_contract: PASS
workflow_present: true
schedule_present: true
package_scripts_present: true
evidence_artifacts:
- .gitea/workflows/qualitative_sell_strategy.yml
- tools/validate_qualitative_sell_strategy_pipeline_v1.py
- Temp/qualitative_sell_strategy_pipeline_v1.json
verification_commands:
- python tools/validate_qualitative_sell_strategy_pipeline_v1.py
Q2_gitea_secrets_contract:
priority: HIGH
status: PLANNED
purpose: 'Gitea workflow에서 KIS mock/real 자격증명과 GITHUB_TOKEN 시크릿 이름을 정확히 고정해, 수동
등록 실수로 인한 파이프라인 붕괴를 방지한다.
'
success_criteria:
expected_success_value:
secrets_contract: PASS
workflow_secret_mapping: PASS
docs_present: true
ci_validation_present: true
evidence_artifacts:
- docs/GITEA_SECRETS_SETUP.md
- tools/validate_gitea_secrets_contract_v1.py
- Temp/gitea_secrets_contract_v1.json
verification_commands:
- python tools/validate_gitea_secrets_contract_v1.py
phase_wbs_7_8_etf_nav_automation:
status: BLOCKED_TECHNICAL_BARRIER
wbs_ref: WBS-7.8
deadline: '2026-12-31'
problem_statement: 'ETF NAV, 괴리율, 추적오차, AUM 자동 수집이 미구현. 현재는 etf_nav_manual 탭에 수동
입력만 가능.
'
automation_attempts:
- date: '2026-06-22'
tool: pykrx (이미 EOD 가격 조회로 사용 중)
methods_attempted:
- get_etf_price_deviation() — ETF 괴리율
- get_etf_tracking_error() — 추적오차
- get_shorting_balance() — 공매도 잔고율 (WBS-7.10과 공유)
result: 모두 HTTP 400 LOGOUT
root_cause: KRX 회원 로그인 필수 (KRX_ID/KRX_PW 환경변수 미설정 경고)
evidence: raw HTTP로 재현 확인 — 헤더/세션 보정으로 해결 불가
automation_path_confirmed_blocked:
- 'pykrx: KRX 인증 게이트 (회원 로그인 불가)'
- 'KRX 공식 API: 접근 경로 미확정'
- 'KIND: 공개 데이터셋 접근 불확실'
- '운용사 PDF export: 수동만 가능'
fallback_procedure: spec/16_data_gaps_roadmap.yaml:S5_etf_raw.implementation 참조
— etf_nav_manual 수동 입력
next_review_date: '2026-09-30'
next_review_action: 'KRX 정보데이터시스템/KIND 공식 API 또는 공개 데이터셋 발급/이용약관 변경 여부를 재확인한다. 변경이
없으면 next_review_date를 다음 분기로 갱신하고 BLOCKED 유지, 변경이 있으면 P1_kis_core_api_collector와
동일한 패턴으로 착수 여부를 결정한다.
'
implementation_note: '2026-06-22 WBS-7.8 기술장벽 최종 확정. 자동화 불가능하므로 운영절차를 명문화한다. etf_nav_manual
수동 경로 외에 대체 경로 없음.
'
phase_wbs_7_10_shorting_balance_automation:
status: MANUAL_CSV_ONLY
wbs_ref: WBS-7.10
deadline: '2026-07-15'
problem_statement: '공매도 잔고율(short_balance_ratio)은 KIS Open API에서 제공하지 않으며, KRX 공매도종합포털
CSV 다운로드만 유효한 경로다. 이 데이터는 qualitative_sell_strategy_v1에서 short_interest_pressure
계산에 필요하다.
'
data_source:
official: KRX 공매도종합포털 (data.krx.co.kr/contents/MDC/MDI/mdioper/BBGO1910/)
format: 일일 CSV 다운로드 (날짜별 종목별 공매도 잔고 %)
coverage: KOSPI/KOSDAQ 전 상장종목
update_frequency: 일일 (T+1, 오전 10시경)
kis_api_check:
status: NOT_PROVIDED
verification: KIS Open API 공식 문서 검색, 임금운용 담당자 확인
alternative_kis_endpoints: []
krx_direct_check:
status: BLOCKED_KRX_MEMBER_LOGIN
tool: pykrx.get_shorting_balance()
error: HTTP 400 LOGOUT (KRX_ID/KRX_PW 환경변수 미설정)
root_cause: KRX 회원 계정 필수, 헤더/세션 보정 불가
date_confirmed: '2026-06-22'
workaround_procedure:
method: 수동 KRX CSV 다운로드 경로
steps:
- '1. KRX 공매도종합포털 접속 (로그인 필요: 일반 계정, 증권회원사 계정, KRX 회원사 계정 모두 가능)'
- 2. '당일 공매도현황' 탭에서 종목 선택 또는 전체 다운로드
- '3. CSV 파일 저장: spec 문서에 기입된 경로 (예: Temp/shorting_balance_manual_YYYY-MM-DD.csv)'
- 4. build_qualitative_sell_inputs_v1.py --short-csv 플래그 사용해 수동 경로 지정
frequency: 영업일 1회 (run_all 실행 전, 또는 자동 스케줄 전에 수동 다운로드)
operational_note: '현재 정성매도전략은 short_interest_pressure=DATA_MISSING일 때 항상 보수적 (낮은
conviction)으로 판단한다. 공매도 데이터가 없으면 다른 4개 신호만 사용해 결정하므로, 영업 중단 가능성은 없다 — 다만 정밀도
제한.
'
cli_interface:
usage: python tools/build_qualitative_sell_inputs_v1.py --short-csv Temp/shorting_balance_manual_YYYY-MM-DD.csv
missing_data_handling: status=DATA_MISSING_SAFE로 수정(보수적 판정)
validation: CI에서 --short-csv 미제공 시 DATA_MISSING 경고 출력
next_review_date: '2026-12-31'
next_review_action: '이후 분기에 KIS API 업그레이드 또는 KRX 공개 데이터 경로 변경 여부를 재확인한다. 변경이 없으면
MANUAL_CSV_ONLY 상태 유지, 변경이 있으면 자동화 착수 여부를 결정한다.
'
implementation_note: '2026-06-22 WBS-7.10 기술장벽 최종 확정. 자동화 경로 불가능하므로 수동 CSV 운영절차를
governance/rules에 명문화한다.
'