Files
QuantEngineByItz/spec/14_raw_workbook_mapping.yaml

690 lines
32 KiB
YAML
Raw Permalink 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: "GatherTradingData.json — Raw Data Mapping"
parent_file: "RetirementAssetPortfolio.yaml"
version: "2026-05-16-F15_valuation_mapping"
language: "ko-KR"
timezone: "Asia/Seoul"
role: "canonical"
has_code_implementation: true
code_path: "src/quant_engine/convert_xlsx_to_json.py"
purpose: >
제공 raw JSON의 data.<sheet> 배열과 컬럼을 canonical field로 매핑한다.
xlsx는 JSON 재생성 소스이며 일반 LLM 분석에서는 직접 파싱하지 않는다.
Snapshot Admin의 workbook inventory와 migration classification은
GatherTradingData.xlsx를 직접 읽어서 계산한다.
이 파일은 시장/종목/섹터/매크로 데이터만 담당하며 계좌·보유·현금 데이터는
spec/15_account_snapshot_contract.yaml이 담당한다.
raw_json:
file: "GatherTradingData.json"
source_workbook: "GatherTradingData.xlsx"
schema_version: "2026-05-18-json-raw-data-v1"
role: "market_raw_json"
root_paths:
metadata: "metadata"
data: "data"
required_paths:
data_feed: "data.data_feed"
sector_flow: "data.sector_flow"
macro: "data.macro"
event_risk: "data.event_risk"
core_satellite: "data.core_satellite"
validation_tool: "tools/validate_data_sample_json.py"
conversion_tool: "tools/convert_xlsx_to_json.py"
raw_workbook:
file: "GatherTradingData.xlsx"
role: "market_raw_workbook_source_for_json"
header_policy:
header_search_rows: 8
meta_row_allowed: true
required_sheets:
data_feed:
role: "보유/관심 핵심 종목 시장 데이터"
required_columns: ["Ticker", "Name", "Close", "ATR20", "Flow_OK", "Frg_5D", "Inst_5D"]
recommended_columns:
- "Open"
- "PrevClose"
- "High"
- "Low"
- "Volume"
- "AvgVolume_5D"
- "MA20"
- "MA60"
- "Ret5D"
- "Ret10D"
- "Ret20D"
- "Ret60D"
- "AvgTradeValue_5D_KRW"
- "AvgTradeValue_20D_KRW"
- "TradeValue_Unit"
- "Timing_Action"
- "Timing_Score_Entry"
- "Timing_Score_Exit"
- "Entry_Mode"
- "Entry_Mode_Gate"
- "Entry_Mode_Reason"
- "Candidate_Quality_Grade"
- "T1_Forced_Sell_Risk_Score"
- "T1_Forced_Sell_Risk_State"
- "Sell_Conflict_Score"
- "Sell_Conflict_State"
- "Execution_Recommendation_State"
- "Forward_PE"
- "PBR"
- "EPS_Revision_Status"
- "EPS_Growth_1Y_Pct" # Yahoo earningsTrend +1y 성장률 → KOSDAQ PEG 계산 (A2)
- "DividendYield"
- "DPS" # 주당 배당금 Yahoo lastDividendValue (A4)
- "ROE_Pct" # 자기자본이익률(%) Yahoo financialData.returnOnEquity×100
- "Operating_Margin_Pct" # 영업이익률(%) Yahoo financialData.operatingMargins×100
- "Debt_To_Equity" # 부채비율(D/E) Yahoo defaultKeyStatistics.debtToEquity
- "Current_Ratio" # 유동비율 Yahoo financialData.currentRatio
- "FCF_B" # 잉여현금흐름(억원) Yahoo financialData.freeCashflow÷1e8
- "Revenue_Growth_Pct" # 매출 성장률(%) Yahoo financialData.revenueGrowth×100
- "Beta"
- "High52W"
- "Low52W"
- "Pct_52W_High"
- "Pct_From_52W_Low"
- "Target_Price"
- "Upside_Pct"
- "Earnings_Date"
- "Days_To_Earnings"
- "Ex_Dividend_Date" # 배당락일 (A4)
- "Days_To_Ex_Div" # 배당락일 잔여 일수
- "Timing_Score_Entry" # 진입 타이밍 종합 점수(0~100)
- "Timing_Score_Exit" # 청산/축소 타이밍 종합 점수(0~100)
- "Timing_Action" # BUY_STAGE1_READY/NO_BUY_OVERHEATED 등 실행 액션
- "Timing_Block_Reason" # 타이밍 액션 산출 핵심 사유
- "Sell_Action" # HOLD/TRIM_50/EXIT_100 등 매도 액션
- "Sell_Ratio_Pct" # 보유수량 확인 시 적용할 매도 비율
- "Sell_Qty" # 보유수량 확인 시 정수 매도수량. 미확인 시 blank
- "Sell_Limit_Price" # HTS 입력용 매도 지정가
- "Sell_Price_Source" # TP/Trailing/Close 등 가격 출처
- "Sell_Price_Basis" # PRIOR_CLOSE_X_0.998/TRAILING_STOP_TRIGGER 등 산출 기준
- "Sell_Execution_Window" # INTRADAY_AFTER_09_30/CLOSE_REVIEW_OR_NEXT_OPEN 등 실행 시간대
- "Sell_Order_Type" # LIMIT_SELL/PROTECTIVE_LIMIT_SELL
- "Sell_Reason" # RW_EXIT/TIME_STOP/PROFIT_PROTECT 등 근거
- "Sell_Validation" # PASS/NO_HOLDING_QTY/NO_SELL_PRICE 등 검산상태
- "Account_Holding_Qty" # account_snapshot에서 확인한 보유수량
- "Account_Avg_Cost" # account_snapshot에서 확인한 평단
- "Account_Market_Value" # account_snapshot에서 확인한 평가금액
- "Account_Parse_Status" # CAPTURE_READ_OK 등 캡처 판독 상태
- "Rule_Sell_Qty" # 룰엔진 기본 매도수량
- "Rebalance_Target_Cash_Pct" # 주간 D+2 현금 목표
- "Rebalance_Need_KRW" # 목표 D+2 현금까지 부족액
- "Override_Sell_Qty" # 부족현금만 채우는 최소 조정 매도수량
- "Override_Reason" # 조정 수량 사유
- "Override_Validation" # PASS_USER_CASH_TARGET 등
- "Final_Action" # 룰엔진 최종 액션. LLM 임의 재판단 금지
- "Action_Priority" # 낮을수록 우선 처리
- "Priority_Score" # 동일 액션 내 정렬 점수
- "Final_Rank" # Action_Priority ASC, Priority_Score DESC 기준 순위
- "Decision_Source" # RULE_ENGINE / RULE_ENGINE_WITH_MISSING_DATA
- "Limit_Price_Est"
- "Stop_Price_Est" # account_snapshot 우선, ATR 추정 폴백 (A7)
- "Stop_Price_Source" # 출처 표시
- "EE_Est" # Bayesian multiplier 반영 기대우위 (S1)
- "Pos_Size_Qty" # POSITION_SIZE_V1 간략 추정 수량 (A6)
- "Breakout_Score"
- "Breakout_Gate"
- "AC_S1"
- "AC_S2"
- "AC_S3"
- "AC_S4"
- "AC_S5"
- "AC_Total"
- "AC_Gate"
- "C1_Price"
- "C2_RelStr"
- "C3_VolSurge"
- "C4_Flow"
- "C5_Sector"
- "Leader_Scan_Total"
- "Leader_Gate"
- "RW1"
- "RW2"
- "RW3"
- "RW4"
- "RW5"
- "RW_Partial"
core_satellite:
role: "위성 후보군 시장 데이터"
required_columns: ["Ticker", "Name", "Sector", "Close", "ATR20", "Flow_OK", "Rotation_Score", "Alert_Level"]
recommended_columns:
- "Open"
- "PrevClose"
- "High"
- "Low"
- "Volume"
- "AvgVolume_5D"
- "MA20"
- "MA60"
- "Ret10D"
- "Ret20D"
- "Ret60D"
- "AvgTradeValue_5D_KRW"
- "AvgTradeValue_20D_KRW"
- "TradeValue_Unit"
sector_flow:
role: "섹터 수급·상대강도 canonical 분석 시트"
required_columns: ["Sector", "Sector_Score", "Sector_Rank", "Alert_Level"]
status: "canonical"
usage_limit: >
옛 sector_flow_v2의 역할을 sector_flow가 대신한다.
ETF_Code/ETF_Ret* 컬럼명과 Rotation_* 컬럼은 legacy 호환용 별칭이며 실제 의미는 Proxy_Ticker/Proxy_Ret* 및 Sector_Score/Sector_Rank이다.
Frg_5D_SUM/Inst_5D_SUM은 v2 원화 수급 집계값을 legacy 호환 컬럼에 매핑한 값으로 해석한다.
added_columns:
- "Sector_Median_PE"
- "Sector_Median_PBR"
- "ETF_Ret10D" # ETF 10일 수익률 → RW2 상대약세 판단 입력
- "Rotation_Rank" # Sector_Score 내림차순 순위 (1=최고) → C5, RW1 판단
sector_universe:
role: "sector_flow canonical 섹터 구성 원장"
optional_sheet: true
fallback: "시트가 없으면 gas_data_feed.gs DEFAULT_SECTOR_UNIVERSE_V2 사용 후 sector_universe 기본 템플릿 생성"
external_seed_policy: "sector_targets.json은 legacy seed/archive이며 실행 입력·LLM 업로드 대상이 아니다."
canonical_source_note: "sector_flow의 구성종목 universe는 sector_universe 시트 또는 DEFAULT_SECTOR_UNIVERSE_V2만 사용한다."
required_columns:
- "Sector"
- "Proxy_Ticker"
- "Proxy_Name"
- "Proxy_Type"
- "Base_Ticker"
- "Constituent_Code"
- "Constituent_Name"
- "Weight"
- "Is_ETF"
- "Enabled"
- "Effective_Date"
- "Source"
aggregation_rule: >
Is_ETF=Y 행은 proxy/실행상품 식별용으로 보존하되 sector_flow의 구성종목 smart money,
Flow_Breadth_5D, Coverage_Weight 산출에서는 제외한다. ETF 자체 수급·NAV·괴리율은 후속 etf_raw가 담당한다.
sector_flow_v2:
status: "deprecated"
note: "sector_flow가 sector_flow_v2 canonical 분석 시트를 대체한다."
quality_gate:
A: "Coverage_Weight >= 0.80 AND Flow_Rows_Min >= 20 AND Stale_Count=0 AND 원화 수급/거래대금 산출 가능"
B: "Coverage_Weight >= 0.60 AND 핵심 가격·수급 대부분 정상"
C: "coverage 부족 또는 proxy/거래대금 일부 누락. Decision_Use=WATCH_ONLY"
D: "가격·수급 핵심 실패. Decision_Use=INVALID"
usage_rule: "Data_Quality C/D는 Strong_Buy 또는 섹터 단독 강매도 근거로 사용 금지"
etf_raw:
role: "ETF 실행 유동성·자체 수급 원천 시트"
optional_sheet: true
required_columns:
- "Sector"
- "ETF_Ticker"
- "ETF_Name"
- "Close"
- "NAV"
- "iNAV"
- "Premium_Discount_Pct"
- "Tracking_Error"
- "AUM"
- "Bid"
- "Ask"
- "Spread_Pct"
- "AvgTradeValue_5D_KRW"
- "AvgTradeValue_20D_KRW"
- "ETF_Frg_5D_KRW"
- "ETF_Inst_5D_KRW"
- "LP_Quality_Flag"
- "ETF_Liquidity_Score"
- "ETF_NAV_Risk"
- "ETF_Liquidity_Status"
- "ETF_Execution_Use"
- "ETF_Data_Status"
- "NAV_Source"
- "NAV_Source_Date"
limitation: >
Phase 3 interim은 Yahoo/Naver 기반 가격·스프레드·거래대금·ETF 자체 수급을 자동 산출하고,
NAV/iNAV/괴리율/추적오차/AUM은 etf_nav_manual 시트 값이 있으면 반영한다.
수동 NAV 입력이 없으면 blank 및 ETF_NAV_Risk=NAV_DATA_MISSING으로 둔다.
이 경우 ETF_Execution_Use는 WATCH_ONLY이며 ETF 매매 실행 핵심 근거로 사용하지 않는다.
etf_nav_manual:
role: "ETF NAV·괴리율·추적오차 수동 검증 입력 시트"
optional_sheet: true
required_columns:
- "ETF_Ticker"
- "ETF_Name"
- "Close"
- "NAV"
- "iNAV"
- "Premium_Discount_Pct"
- "Tracking_Error"
- "AUM"
- "Source_Date"
- "Source"
- "Enabled"
usage_rule: >
KRX/KIND/운용사 자료를 수동 확인해 입력한다. Enabled=Y 행만 etf_raw에 반영한다.
Premium_Discount_Pct가 비어 있으면 Close와 NAV 또는 iNAV로 자동 산출한다.
importer: "tools/import_etf_nav_manual.py — KRX/KIND/운용사 CSV/XLSX export를 etf_nav_manual 시트로 변환. --enable 옵션은 NAV/iNAV와 Source_Date가 있는 etf_raw 매칭 행만 Enabled=Y 처리."
rebalance:
role: "리밸런싱 실행 계획 시트 (bucket drift → 레짐 적응 밴드 → 비용효익 게이트 → 3단계 분할 실행)"
optional_sheet: true
generator: "tools/build_rebalance_engine_v1.py (Python) + GAS src/gas_adapter_parts/gdf_06_rebalance.gs:runRebalanceSheet_()"
artifact: "Temp/rebalance_engine_v1.json"
layout: "multi-section — 4섹션이 단일 시트에 순서대로 배치됨 (구분: === SECTION_NAME === 행)"
sections:
SUMMARY:
description: "포트폴리오 전체 요약 (key-value 2열 형식)"
fields:
- "Run_Date" # 실행 시각 (ISO-8601 KST)
- "Regime" # 시장 레짐 (RISK_ON/NEUTRAL/RISK_OFF 등)
- "Regime_Band" # 적용된 밴드 레이블 (예: RISK_ON ±15%p)
- "Total_Portfolio_KRW" # 전체 포트폴리오 평가금액 (원)
- "Core_Pct" # 현재 코어 비중 (%)
- "Satellite_Pct" # 현재 위성 비중 (%)
- "Cash_Pct" # 현재 현금 비중 (%)
- "Target_Core_Pct" # 목표 코어 비중 (%)
- "Target_Sat_Pct" # 목표 위성 비중 (%)
- "Target_Cash_Pct" # 목표 현금 비중 (%)
- "Rebalance_Needed" # 리밸런싱 필요 여부 (true/false)
- "Holdings_Count" # 보유 종목 수
- "Orders_Count" # 생성된 주문 수
- "Min_Actionable_Drift_Pct" # 최소 실행 기준 드리프트 (%)
BUCKETS:
description: "버킷별 드리프트 분석 (행 형식)"
columns:
- "Bucket" # Core / Satellite / Cash
- "Target_Pct" # 목표 비중 (%)
- "Current_Pct" # 현재 비중 (%)
- "Drift_Pct" # 드리프트 (현재 목표, %)
- "Band_Min" # 레짐 적응 하단 경계 (%)
- "Band_Max" # 레짐 적응 상단 경계 (%)
- "Regime_Band" # 적용 밴드 레이블
- "Drift_Status" # NORMAL / WARN / BREACH_LOW / BREACH_HIGH
TICKERS:
description: "종목별 드리프트 분석 + 강제 신호 + 3단계 분할 수량 (행 형식)"
columns:
- "Ticker" # 종목 코드
- "Name" # 종목명
- "Bucket" # Core / Satellite
- "Target_Pct" # 버킷 내 equal-weight 목표 비중 (%)
- "Current_Pct" # 현재 보유 비중 (%)
- "Drift_Pct" # 드리프트 (현재 목표, %)
- "Band_Min" # 레짐 적응 하단 경계 (%)
- "Band_Max" # 레짐 적응 상단 경계 (%)
- "Regime_Band" # 적용 밴드 레이블
- "Drift_Status" # NORMAL/WARN/BREACH_LOW/BREACH_HIGH/FORCE_ABS_FLOOR/FORCE_TIME_STOP
- "Force_Signal" # ABS_FLOOR / TIME_STOP / (empty)
- "Gate_Status" # PASS / BLOCKED_BY_COST / FORCE_OVERRIDE
- "Action" # SELL / BUY / WATCH / HOLD
- "Stage1_Qty" # 1단계 수량 (전체의 30%)
- "Stage1_Price" # 1단계 지정가 (원)
- "Stage2_Qty" # 2단계 수량 (전체의 30%)
- "Stage2_Price" # 2단계 지정가 (원)
- "Stage3_Qty" # 3단계 수량 (전체의 40%)
- "Stage3_Price" # 3단계 지정가 (원)
- "Trade_Value_KRW" # 예상 거래금액 (원)
- "Cost_Est_KRW" # 예상 비용 (수수료+세금, 원)
- "Net_Benefit_Pct" # 비용 차감 순 드리프트 개선 효과 (%)
- "Close" # 직전 종가 (원)
ORDERS:
description: "실행 주문 목록 (행 형식) — gate_status=PASS 또는 FORCE_OVERRIDE 종목만 포함"
columns:
- "Order_No" # 주문 순번
- "Ticker" # 종목 코드
- "Name" # 종목명
- "Bucket" # Core / Satellite
- "Action" # SELL / BUY
- "Stage" # 1 / 2 / 3
- "Qty" # 수량
- "Limit_Price_KRW" # 지정가 (원)
- "Trade_Value_KRW" # 예상 거래금액 (원)
- "Reason" # 주문 근거 (BREACH_HIGH / ABS_FLOOR / TIME_STOP 등)
sector_flow_history:
role: "sector_flow 누적 스냅샷 및 RW1/RW3 이력 근거"
optional_sheet: true
required_columns:
- "Snapshot_Date"
- "Sector"
- "Sector_Score"
- "Sector_Rank"
- "SmartMoney_5D_KRW"
- "SmartMoney_20D_KRW"
- "Flow_Breadth_5D"
- "Alert_Level"
- "Data_Quality"
- "Decision_Use"
- "ETF_Execution_Use"
usage_rule: "legacy sector_flow의 RW1/RW3는 sector_flow_history를 우선 사용하고, 이력이 없을 때만 기존 sector_flow/PropertiesService 값을 fallback으로 사용한다."
backdata_feature_bank:
role: "GAS 자동 수집 진입-청산 백데이터 원장"
optional_sheet: true
required_columns:
- "Record_Date"
- "Trade_ID"
- "Signal_Date"
- "Ticker"
- "Name"
- "Account"
- "Entry_Stage"
- "Source_Origin"
- "Entry_Price"
- "Close_At_Entry"
- "MA20_At_Entry"
- "MA60_At_Entry"
- "ATR20_At_Entry"
- "Volume_Ratio_5D"
- "Flow_Credit"
- "RSI14_At_Entry"
- "Late_Chase_Risk_Score"
- "Follow_Through_Score"
- "Breakout_Score"
- "Rebound_Preservation_Score"
- "Setup_Decision"
- "Exit_Reason"
- "PnL_Pct"
- "Holding_Days"
- "MAE_Pct"
- "MFE_Pct"
usage_rule: >
GAS가 data_feed / alpha_lead_json / sell_priority / performance를 합쳐 자동 생성한
1차 원장이다. 사용자가 직접 등록한 기록은 Source_Origin=MANUAL_CORRECTION일 때만
보정용으로 해석하며, 신규 전략 판단의 primary source로 쓰지 않는다.
source_priority:
1: "GAS daily snapshot"
2: "performance trade journal"
3: "manual correction"
macro:
role: "행 기반 macro indicator table"
required_columns: ["Symbol", "Name", "Category", "Close", "Status"]
added_columns:
- "Ret2D" # USD/JPY 2일 변화율 → MRS usd_jpy_score 입력
- "Ret10D" # KOSPI/KOSDAQ 10일 수익률 → C2 daily_leader_scan
- "MA60" # KOSPI MA60 → RISK_ON 판정 조건
- "HYG_HY_Bond" # 신용위험 proxy (credit_stress_status 산출 기반)
computed_rows:
MRS_COMPUTED: "MARKET_RISK_SCORE_V1 자동 계산 결과 (score/10, target_cash_pct)"
REGIME_PRELIM: "1차 시장국면 판정 (sector_flow 미포함 간이 판정)"
row_based_mapping:
vix_close: "row where Symbol or Name contains VIX -> Close"
kospi_close: "row where Symbol or Name contains KOSPI -> Close"
usd_krw: "row where Symbol or Name contains USD/KRW or USDKRW -> Close"
sp500_ret5d: "row where Symbol or Name contains S&P500 -> Ret5D"
missing_policy:
kospi_ma20: "JSON 미제공 시 formula_registry.MARKET_RISK_SCORE_V1의 missing_points 적용"
usd_jpy_2d_change_pct: "JSON 미제공 시 missing_points 적용"
credit_stress_status: "JSON 미제공 시 caution equivalent missing_points 적용"
event_calendar:
role: "이벤트 일정 입력 탭. 운영자가 직접 관리하는 source-of-truth. GAS seedEventCalendar_()가 최초 seed를 제공하며 이후 수동 갱신."
required_columns: ["Date", "Event", "Type", "Impact", "Alert"]
update_policy: "수동 갱신 (FOMC 연 8회, CPI 월 1회, IPO/만기 수시). seedEventCalendar_()로 초기화 가능."
note: "event_risk 탭의 원본 소스. GAS 코드에 날짜를 hardcode하지 않는다."
event_risk:
role: "이벤트 리스크 calendar (event_calendar 탭에서 DaysLeft 계산 후 기록된 runtime output)"
required_columns: ["Date", "Event", "Impact"]
core_satellite_status:
role: "core_satellite 청크 실행 완료 상태"
optional_sheet: true
required_columns:
- "Status"
- "Universe_Count"
- "Processed_Count"
- "Coverage_Pct"
- "Chunk_Size"
- "Total_Chunks"
- "Next_Chunk_Idx"
- "Updated_At"
usage_rule: "Status=COMPLETE AND Coverage_Pct>=99.9일 때 core_satellite 전체 갱신 완료로 본다."
transient_sheets:
cs_chunk_N:
role: "core_satellite 생성 중 임시 청크"
lifecycle: "runCoreSatelliteFinalize()가 core_satellite 병합을 완료하면 삭제"
deletion_allowed_when: "core_satellite_status.Status=COMPLETE AND Coverage_Pct>=99.9"
prohibition:
- "FINALIZING 또는 IN_PROGRESS 상태에서 삭제 금지"
- "core_satellite 병합 실패 상태에서 시트 다이어트 목적으로 삭제 금지"
sheet_diet_policy:
keep:
canonical_required: ["data_feed", "sector_flow", "macro", "event_risk", "core_satellite"]
support: ["settings", "account_snapshot", "sector_universe", "sector_flow_history", "etf_nav_manual", "universe", "monthly_history", "performance", "backdata_feature_bank", "event_calendar", "daily_history", "pa1_feedback", "alpha_history", "evaluation_dashboard", "trade_quality_history", "rebalance"]
deprecated: ["positions", "chat_input", "etf_raw", "core_satellite_status", "orbit_gap", "asset_history"]
delete:
transient_after_complete: ["cs_chunk_N"]
notes:
- "orbit_gap·asset_history → monthly_history 통합 (Month당 1행, 16컬럼)."
- "etf_raw → GAS in-memory map 전환. 시트 쓰기 제거."
- "core_satellite_status → ScriptProperties 이전."
- "sector_flow는 sector_flow_v2 역할을 대체하는 canonical 분석 시트다."
canonical_field_mapping:
ticker: {sheet: ["data_feed", "core_satellite"], column: "Ticker"}
name: {sheet: ["data_feed", "core_satellite"], column: "Name"}
close_price: {sheet: ["data_feed", "core_satellite"], column: "Close"}
open_price: {sheet: ["data_feed", "core_satellite"], column: "Open", fallback: "DATA_MISSING"}
previous_close_price: {sheet: ["data_feed", "core_satellite"], column: "PrevClose", fallback: "DATA_MISSING"}
volume: {sheet: ["data_feed", "core_satellite"], column: "Volume", fallback: "DATA_MISSING"}
avg_volume_5d: {sheet: ["data_feed", "core_satellite"], column: "AvgVolume_5D", fallback: "DATA_MISSING"}
ma20: {sheet: ["data_feed", "core_satellite"], column: "MA20", fallback: "DATA_MISSING"}
ma60: {sheet: ["data_feed", "core_satellite"], column: "MA60", fallback: "DATA_MISSING"}
atr20: {sheet: ["data_feed", "core_satellite"], column: "ATR20"}
avg_trade_value_5d:
sheet: ["data_feed", "core_satellite"]
preferred_column: "AvgTradeValue_5D_KRW"
legacy_column: "AvgTradeValue_5D_M"
unit_rule: "preferred_column은 KRW. legacy_column은 million KRW로 해석해 ×1,000,000 적용."
avg_trade_value_20d:
sheet: ["data_feed", "core_satellite"]
preferred_column: "AvgTradeValue_20D_KRW"
legacy_column: "AvgTradeValue_20D_M"
unit_rule: "preferred_column은 KRW. legacy_column은 million KRW로 해석해 ×1,000,000 적용."
frg_5d_sh: {sheet: ["data_feed", "core_satellite"], column: "Frg_5D"}
inst_5d_sh: {sheet: ["data_feed", "core_satellite"], column: "Inst_5D"}
flow_ok: {sheet: ["data_feed", "core_satellite"], column: "Flow_OK"}
flow_rows: {sheet: ["data_feed", "core_satellite"], column: "Flow_Rows"}
vix_close: {sheet: "macro", row_mapping: "macro.row_based_mapping.vix_close"}
kospi_close: {sheet: "macro", row_mapping: "macro.row_based_mapping.kospi_close"}
usd_krw: {sheet: "macro", row_mapping: "macro.row_based_mapping.usd_krw"}
# ── 밸류에이션 필드 매핑 (proposal_96 1단계 / 2026-05-16) ───────────────────────
# data_feed 시트 recommended_columns에 이미 존재하나 canonical_field_mapping 누락이었음.
forward_pe:
sheet: ["data_feed"]
column: "Forward_PE"
fallback: "DATA_MISSING"
note: "recommended_column — 미입력 시 PEG_SCORE_V1.fallback(sector_median 기준) 발동. 추정 생성 금지."
pbr:
sheet: ["data_feed"]
column: "PBR"
fallback: "DATA_MISSING"
note: "recommended_column — 미입력 시 SS001_VAL_VALUATION valuation_score_zero 처리."
eps_revision_status:
sheet: ["data_feed"]
column: "EPS_Revision_Status"
fallback: "DATA_MISSING"
allowed_values: ["UP", "FLAT", "DOWN"]
note: "recommended_column — 미입력 시 SS001_E_EARNINGS_REVISION 0점 처리."
# ── 신규 추가 필드 (2026-05-17) ──────────────────────────────────────────────
dividend_yield:
sheet: ["data_feed"]
column: "DividendYield"
unit: "percent"
fallback: "DATA_MISSING"
source_priority: ["Naver main _dvr", "Yahoo v7 trailingAnnualDividendYield"]
note: "배당수익률(%). 은퇴포트폴리오 현금흐름 평가에 사용."
beta:
sheet: ["data_feed"]
column: "Beta"
unit: "ratio"
fallback: "DATA_MISSING"
source_priority: ["Yahoo v7 quote beta", "Yahoo quoteSummary defaultKeyStatistics.beta"]
note: "1년 베타. 포트폴리오 전체 리스크 계산에 사용."
high_52w:
sheet: ["data_feed"]
column: "High52W"
unit: "KRW_per_share"
fallback: "DATA_MISSING"
source_priority: ["Naver main 52주최고", "Yahoo v7 fiftyTwoWeekHigh"]
note: "52주 최고가. Pct_52W_High 계산의 기준값."
low_52w:
sheet: ["data_feed"]
column: "Low52W"
unit: "KRW_per_share"
fallback: "DATA_MISSING"
source_priority: ["Naver main 52주최저", "Yahoo v7 fiftyTwoWeekLow"]
pct_52w_high:
sheet: ["data_feed"]
column: "Pct_52W_High"
unit: "percent"
fallback: "DATA_MISSING"
expression: "(Close / High52W - 1) * 100"
note: "현재가의 52주 고점 대비 위치(%). 음수=고점 아래. -20 이하 → 눌림 구간."
target_price:
sheet: ["data_feed"]
column: "Target_Price"
unit: "KRW_per_share"
fallback: "DATA_MISSING"
source_priority: ["Naver coinfo estimate 목표주가", "Yahoo quoteSummary financialData.targetMeanPrice"]
note: "애널리스트 컨센서스 목표주가. Upside_Pct 계산 기준."
upside_pct:
sheet: ["data_feed"]
column: "Upside_Pct"
unit: "percent"
fallback: "DATA_MISSING"
expression: "(Target_Price / Close - 1) * 100"
note: "목표주가 대비 상승여력(%). 포지션 진입/청산 판단 보조."
# ── 2026-05-17 추가 필드 ──────────────────────────────────────────────────────
sector_median_pe:
sheet: ["sector_flow"]
column: "Sector_Median_PE"
unit: "ratio"
fallback: "DATA_MISSING"
note: "섹터 구성 3종목 PER 중앙값. SS001_VAL_VALUATION의 sector_median_forward_pe 대용."
sector_median_pbr:
sheet: ["sector_flow"]
column: "Sector_Median_PBR"
unit: "ratio"
fallback: "DATA_MISSING"
note: "섹터 구성 3종목 PBR 중앙값. SS001_VAL_VALUATION의 sector_median_pbr 대용."
rs_rank_20d:
sheet: ["core_satellite"]
column: "RS_Rank_20D"
unit: "rank_integer"
fallback: "DATA_MISSING"
note: "섹터 내 20D 수익률 기준 순위 (1=최상위). SS001_P price_strength 입력값."
rs_pct_20d:
sheet: ["core_satellite"]
column: "RS_Pct_20D"
unit: "percent"
fallback: "DATA_MISSING"
note: "섹터 내 20D 수익률 백분위 (100=최상위). relative_strength_1m_percentile 대용."
earnings_date:
sheet: ["data_feed"]
column: "Earnings_Date"
unit: "date_ISO8601"
fallback: "DATA_MISSING"
source_priority: ["Yahoo quoteSummary calendarEvents.earnings.earningsDate"]
note: "다음 실적 발표 예정일. 발표 3일 이내 신규매수 자제 기준으로 활용."
days_to_earnings:
sheet: ["data_feed"]
column: "Days_To_Earnings"
unit: "integer_days"
fallback: "DATA_MISSING"
expression: "(Earnings_Date - AsOfDate).days"
note: "실적 발표까지 잔여 영업일. 음수=이미 지남. event_risk 필터 입력값."
# ── 2026-05-17 추가 필드 (3단계) ────────────────────────────────────────────
eps_growth_1y_pct:
sheet: ["data_feed"]
column: "EPS_Growth_1Y_Pct"
unit: "percent"
fallback: "DATA_MISSING → SS001_VAL_KOSDAQ_PEG.fallback_per_only 발동"
source: "Yahoo earningsTrend +1y earningsEstimate.growth (A2)"
note: "KOSDAQ PEG = Forward_PE / EPS_Growth_1Y_Pct. 양수 성장률만 유효."
dps:
sheet: ["data_feed"]
column: "DPS"
unit: "KRW_per_share"
fallback: "DATA_MISSING"
source: "Yahoo defaultKeyStatistics.lastDividendValue (A4)"
note: "주당 배당금. DividendYield와 함께 은퇴 현금흐름 평가."
ex_dividend_date:
sheet: ["data_feed"]
column: "Ex_Dividend_Date"
unit: "date_ISO8601"
fallback: "DATA_MISSING"
source: "Yahoo calendarEvents.exDividendDate (A4)"
note: "배당락일. Days_To_Ex_Div 계산 기준."
days_to_ex_div:
sheet: ["data_feed"]
column: "Days_To_Ex_Div"
unit: "integer_days"
fallback: "DATA_MISSING"
expression: "(Ex_Dividend_Date - AsOfDate).days"
note: "배당락일 잔여 일수. 음수=이미 지남."
stop_price_est:
sheet: ["data_feed"]
column: "Stop_Price_Est"
unit: "KRW_per_share"
fallback: "DATA_MISSING"
source_priority: ["account_snapshot stop_price", "average_cost - ATR20 × 1.5 추정"]
note: "account_snapshot 실제 손절가 우선. ATR 추정은 참고값. Stop_Price_Source로 출처 구분."
stop_price_source:
sheet: ["data_feed"]
column: "Stop_Price_Source"
unit: "string"
values: ["account_snapshot", "ATR추정"]
note: "Stop_Price_Est의 데이터 출처."
pos_size_qty:
sheet: ["data_feed"]
column: "Pos_Size_Qty"
unit: "integer_shares"
fallback: "DATA_MISSING (settings total_asset_krw 미입력)"
expression: "min(floor(total_asset × risk_budget × bayesian / (ATR20 × 1.5)), floor(total_asset × 0.05 / Close))"
note: "POSITION_SIZE_V1 간략 추정. cash/sector/유동성 한도 미적용 — account_snapshot 제공 시 정밀화 가능."
# ── 2단계 보완 예정 필드 (현재 JSON 미포함) ──────────────────────────────────
# 아래 필드는 spec에 정의되어 있으나 JSON 컬럼이 없어 DATA_MISSING으로만 처리됨.
# 2단계 워크북 보완 완료 후 이 주석을 제거하고 매핑 활성화.
# eps_growth_3y_cagr_pct:
# sheet: ["data_feed"]
# column: "EPS_Growth_3Y_CAGR_pct" # 추가 예정 컬럼
# fallback: "DATA_MISSING → PEG_SCORE_V1.fallback"
# sector_median_forward_pe:
# sheet: ["sector_flow"]
# column: "Sector_Median_PE" # 추가 예정 컬럼
# fallback: "DATA_MISSING"
# sector_median_pbr:
# sheet: ["sector_flow"]
# column: "Sector_Median_PBR" # 추가 예정 컬럼
# fallback: "DATA_MISSING"
# ── 재무 건전성 필드 (2026-05-18_FINANCIAL_HEALTH_V1) ──────────────────────
roe_pct:
sheet: ["data_feed"]
column: "ROE_Pct"
fallback: "DATA_MISSING"
note: "자기자본이익률(%). FINANCIAL_HEALTH_SCORE_V1 수익성 축 입력."
operating_margin_pct:
sheet: ["data_feed"]
column: "Operating_Margin_Pct"
fallback: "DATA_MISSING"
note: "영업이익률(%). 음수=영업적자 → HF007 하드필터."
debt_to_equity:
sheet: ["data_feed"]
column: "Debt_To_Equity"
fallback: "DATA_MISSING"
note: "부채비율(D/E). 금융업(은행·보험·증권) 제외 적용. >400% → HF008."
current_ratio:
sheet: ["data_feed"]
column: "Current_Ratio"
fallback: "DATA_MISSING"
note: "유동비율. <1.0이면 단기 유동성 위험."
fcf_b:
sheet: ["data_feed"]
column: "FCF_B"
fallback: "DATA_MISSING"
note: "잉여현금흐름(억원). 양수=실제 현금 창출. 음수=현금 소각."
revenue_growth_pct:
sheet: ["data_feed"]
column: "Revenue_Growth_Pct"
fallback: "DATA_MISSING"
note: "전년 대비 매출 성장률(%). 성장성 판단 보조."
prohibited_use:
- "이 JSON/xlsx에서 보유수량·평단·현금·미체결 주문을 추정하지 않는다."
- "시장 raw JSON 누락 필드를 LLM이 임의 생성하지 않는다."
- "legacy AvgTradeValue_5D_M를 억원 단위로 해석하지 않는다. million KRW로 해석한다."