meta:
  title: "은퇴자산포트폴리오 — LLM 실행용 필드 사전"
  parent_file: "RetirementAssetPortfolio.yaml"
  version: "2026-05-20-HARNESS_V4"
  language: "ko-KR"
  timezone: "Asia/Seoul"
  role: "canonical"
  purpose: >
    LLM이 동일 필드를 여러 이름으로 해석하지 않도록 canonical field, alias, 타입,
    단위, 누락 정책을 고정한다. 알고리즘 파일은 이 사전의 canonical_name을 사용한다.

field_dictionary:
  policy:
    canonical_name_required: true
    alias_resolution_order:
      - "exact canonical_name"
      - "aliases"
      - "source_column"
    unknown_field_action: "DATA_MISSING으로 처리하고 임의 추정 금지"
    unit_conflict_action: "DATA_CONFLICT. 계산·수량 산출 금지"

  fields:
    ticker:
      canonical_name: "ticker"
      type: "string"
      unit: "none"
      aliases: ["Ticker", "종목코드", "code", "symbol"]
    name:
      canonical_name: "name"
      type: "string"
      unit: "none"
      aliases: ["Name", "종목명"]
    close_price:
      canonical_name: "close_price"
      type: "number"
      unit: "KRW_per_share"
      aliases: ["Close", "현재가", "종가", "close"]
    velocity_1d:
      canonical_name: "velocity_1d"
      type: "number"
      unit: "percent"
      aliases: ["Velocity_1D", "v1d"]
      note: "VELOCITY_V1 산출 — 1일 가격 속도"
    velocity_5d:
      canonical_name: "velocity_5d"
      type: "number"
      unit: "percent"
      aliases: ["Velocity_5D", "v5d"]
      note: "VELOCITY_V1 산출 — 5일 가격 속도"
    open_price:
      canonical_name: "open_price"
      type: "number"
      unit: "KRW_per_share"
      aliases: ["Open", "시가", "open"]
    previous_close_price:
      canonical_name: "previous_close_price"
      type: "number"
      unit: "KRW_per_share"
      aliases: ["PrevClose", "전일종가", "previous_close"]
    volume:
      canonical_name: "volume"
      type: "number"
      unit: "shares"
      aliases: ["Volume", "거래량", "volume_shares"]
    entry_price:
      canonical_name: "entry_price"
      type: "number"
      unit: "KRW_per_share"
      aliases: ["limit_price", "지정가", "진입가", "entry"]
    limit_price:
      canonical_name: "limit_price"
      type: "number"
      unit: "KRW_per_share"
      aliases: ["entry_price", "limit", "주문지정가"]
    stop_price:
      canonical_name: "stop_price"
      type: "number"
      unit: "KRW_per_share"
      aliases: ["손절가", "stop", "stop_loss_price"]
    spsv2_verdict:
      canonical_name: "spsv2_verdict"
      type: "enum"
      unit: "none"
      aliases: ["SPSV2 판정", "sell_price_sanity_verdict"]
    target_price:
      canonical_name: "target_price"
      type: "number"
      unit: "KRW_per_share"
      aliases: ["목표가", "익절가", "take_profit_price"]
    quantity:
      canonical_name: "quantity"
      type: "integer"
      unit: "shares"
      aliases: ["수량", "보유수량", "confirmed_holding_quantity"]
    atr20:
      canonical_name: "atr20"
      type: "number"
      unit: "KRW_per_share"
      aliases: ["ATR20", "20일 ATR", "atr_20"]
    total_asset:
      canonical_name: "total_asset"
      type: "number"
      unit: "KRW"
      aliases: ["총자산", "portfolio_value", "account_total_asset"]
    available_cash:
      canonical_name: "available_cash"
      type: "number"
      unit: "KRW"
      aliases: ["주문가능현금", "buy_power_cash", "예수금", "Cash_Available"]
    avg_trade_value_5d:
      canonical_name: "avg_trade_value_5d"
      type: "number"
      unit: "KRW"
      aliases: ["AvgTradeValue_5D_KRW", "AvgTradeValue_5D_M", "5D평균거래대금", "avg_daily_value_5d"]
    avg_trade_value_20d:
      canonical_name: "avg_trade_value_20d"
      type: "number"
      unit: "KRW"
      aliases: ["AvgTradeValue_20D_KRW", "AvgTradeValue_20D_M", "20D평균거래대금"]
    avg_volume_5d:
      canonical_name: "avg_volume_5d"
      type: "number"
      unit: "shares"
      aliases: ["AvgVolume_5D", "AvgVolume_5D_shares", "5D평균거래량"]
    frg_5d_sh:
      canonical_name: "frg_5d_sh"
      type: "number"
      unit: "shares"
      aliases: ["Frg_5D(sh)", "Frg_5D", "Frg_5D_sh", "외국인5D"]
    frg_20d_sh:
      canonical_name: "frg_20d_sh"
      type: "number"
      unit: "shares"
      aliases: ["Frg_20D(sh)", "Frg_20D", "외국인20D"]
    inst_5d_sh:
      canonical_name: "inst_5d_sh"
      type: "number"
      unit: "shares"
      aliases: ["Inst_5D(sh)", "Inst_5D", "Inst_5D_sh", "기관5D"]
    inst_20d_sh:
      canonical_name: "inst_20d_sh"
      type: "number"
      unit: "shares"
      aliases: ["Inst_20D(sh)", "기관20D"]
    beta:
      canonical_name: "beta"
      type: "number"
      unit: "ratio"
      aliases: ["Beta", "종목베타", "stock_beta"]
    flow_rows:
      canonical_name: "flow_rows"
      type: "integer"
      unit: "rows"
      aliases: ["Flow_Rows", "수급행수"]
    flow_ok:
      canonical_name: "flow_ok"
      type: "boolean"
      unit: "none"
      aliases: ["Flow_OK", "flow_valid"]
    flow_credit:
      canonical_name: "flow_credit"
      type: "number"
      unit: "ratio_0_1"
      aliases: ["Flow_Credit", "수급점수_가중치"]
    ma20:
      canonical_name: "ma20"
      type: "number"
      unit: "KRW_per_share"
      aliases: ["MA20", "20일선", "moving_average_20"]
    vwap:
      canonical_name: "vwap"
      type: "number"
      unit: "KRW_per_share"
      aliases: ["VWAP", "거래량가중평균가"]
    rsi_15m:
      canonical_name: "rsi_15m"
      type: "number"
      unit: "points"
      aliases: ["RSI_15M", "15분봉RSI"]
    volume_climax:
      canonical_name: "volume_climax"
      type: "boolean"
      unit: "none"
      aliases: ["Volume_Climax", "거래량폭증"]
    total_asset_ma10:
      canonical_name: "total_asset_ma10"
      type: "number"
      unit: "KRW"
      aliases: ["자산MA10", "total_equity_ma10"]
    sea_action_tag:
      canonical_name: "sea_action_tag"
      type: "string"
      unit: "none"
      aliases: ["SEA액션태그"]
    equity_curve_status:
      canonical_name: "equity_curve_status"
      type: "enum"
      unit: "none"
      aliases: ["자산곡선상태"]
    relative_strength_1m_percentile:
      canonical_name: "relative_strength_1m_percentile"
      type: "number"
      unit: "percentile"
      aliases: ["RS_Pct_20D_Percentile", "상대강도_백분위"]
    rsi_14:
      canonical_name: "rsi_14"
      type: "number"
      unit: "points"
      aliases: ["RSI", "RSI_14", "상대강도지수"]
    cash_shortfall_krw:
      canonical_name: "cash_shortfall_krw"
      type: "number"
      unit: "KRW"
      aliases: ["현금부족액", "cash_deficit"]
    data_integrity_score:
      canonical_name: "data_integrity_score"
      type: "number"
      unit: "score_0_100"
      aliases: ["schema_presence_score", "data_quality_score"]
    data_maturity_score:
      canonical_name: "data_maturity_score"
      type: "number"
      unit: "score_0_100"
      aliases: ["data_maturity", "maturity_score"]
    pending_critical_category_count:
      canonical_name: "pending_critical_category_count"
      type: "integer"
      unit: "count"
      aliases: ["pending_categories_count", "critical_pending_count"]
    pending_critical_categories:
      canonical_name: "pending_critical_categories"
      type: "array"
      unit: "none"
      aliases: ["pending_categories", "missing_critical_categories"]
    stock_close_5d_return:
      canonical_name: "stock_close_5d_return"
      type: "number"
      unit: "percent"
      aliases: ["종목5D수익률"]
    kospi_close_5d_return:
      canonical_name: "kospi_close_5d_return"
      type: "number"
      unit: "percent"
      aliases: ["코스피5D수익률"]
    sector_smartmoney_5d:
      canonical_name: "sector_smartmoney_5d"
      type: "number"
      unit: "normalized_score"
      aliases: ["sector_flow.SmartMoney_5D_Norm_Score", "섹터스마트머니5D"]
    sector_rank:
      canonical_name: "sector_rank"
      type: "integer"
      unit: "none"
      aliases: ["sector_flow.Rank", "섹터순위"]
    sector_top2_names:
      canonical_name: "sector_top2_names"
      type: "list"
      unit: "none"
      aliases: ["sector_flow.Top2_Sectors", "상위2개섹터"]
    alpha_shield_status:
      canonical_name: "alpha_shield_status"
      type: "enum"
      unit: "none"
      aliases: ["알파실드상태"]
    rotation_radar_status:
      canonical_name: "rotation_radar_status"
      type: "enum"
      unit: "none"
      aliases: ["로테이션레이더상태"]
    flow_acceleration_status:
      canonical_name: "flow_acceleration_status"
      type: "enum"
      unit: "none"
      aliases: ["수급가속도상태"]
    oversold_exit_strategy:
      canonical_name: "oversold_exit_strategy"
      type: "string"
      unit: "none"
      aliases: ["과매도탈출전략"]
    divergence_score:
      canonical_name: "divergence_score"
      type: "number"
      unit: "ratio_0_1"
      aliases: ["다이버전스점수"]
    overhang_score:
      canonical_name: "overhang_score"
      type: "number"
      unit: "ratio_0_1"
      aliases: ["오버행점수"]
    rs_ratio:
      canonical_name: "rs_ratio"
      type: "number"
      unit: "ratio"
      aliases: ["RS비율"]
    deviation_ratio:
      canonical_name: "deviation_ratio"
      type: "number"
      unit: "ratio"
      aliases: ["이격비율"]
    vix_close:
      canonical_name: "vix_close"
      type: "number"
      unit: "index_points"
      aliases: ["VIX", "VIX_Close"]
    kospi_close:
      canonical_name: "kospi_close"
      type: "number"
      unit: "index_points"
      aliases: ["KOSPI", "KOSPI_Close"]
    kospi_ma20:
      canonical_name: "kospi_ma20"
      type: "number"
      unit: "index_points"
      aliases: ["KOSPI_MA20"]
    usd_krw:
      canonical_name: "usd_krw"
      type: "number"
      unit: "KRW_per_USD"
      aliases: ["USD/KRW", "USDKRW"]
    market_risk_score:
      canonical_name: "market_risk_score"
      type: "number"
      unit: "points_0_10"
      aliases: ["MRS", "market_risk_score", "MRS합계"]
    cash_floor_regime_min_pct:
      canonical_name: "cash_floor_regime_min_pct"
      type: "number"
      unit: "percent"
      aliases: ["regime_min_cash_pct", "cash_floor_min_pct"]
    usd_jpy_2d_change_pct:
      canonical_name: "usd_jpy_2d_change_pct"
      type: "number"
      unit: "percent"
      aliases: ["USD_JPY_2D_Change_Pct", "USD/JPY_2D"]
    credit_stress_status:
      canonical_name: "credit_stress_status"
      type: "enum"
      unit: "none"
      aliases: ["credit_stress", "HY_OAS_Status", "CP_CD_Spread_Status"]
    bayesian_confidence_multiplier:
      canonical_name: "bayesian_confidence_multiplier"
      type: "number"
      unit: "ratio"
      aliases: ["bayesian_multiplier", "confidence_multiplier"]
    execution_cost_rate:
      canonical_name: "execution_cost_rate"
      type: "number"
      unit: "ratio"
      aliases: ["cost_rate", "fee_slippage_rate"]
    base_risk_budget:
      canonical_name: "base_risk_budget"
      type: "number"
      unit: "ratio"
      aliases: ["risk_budget", "base_risk"]
    net_return_feedback_multiplier:
      canonical_name: "net_return_feedback_multiplier"
      type: "number"
      unit: "ratio"
      aliases: ["net_feedback_multiplier"]
    performance_brake_multiplier:
      canonical_name: "performance_brake_multiplier"
      type: "number"
      unit: "ratio"
      aliases: ["performance_multiplier"]
    regime_reset_multiplier:
      canonical_name: "regime_reset_multiplier"
      type: "number"
      unit: "ratio"
      aliases: ["regime_multiplier"]
    kelly_brake_multiplier:
      canonical_name: "kelly_brake_multiplier"
      type: "number"
      unit: "ratio"
      aliases: ["kelly_multiplier"]
    final_risk_budget:
      canonical_name: "final_risk_budget"
      type: "number"
      unit: "ratio"
      aliases: ["effective_risk_budget"]
    current_price:
      canonical_name: "current_price"
      type: "number"
      unit: "KRW_per_share"
      aliases: ["현재가", "CurrentPrice", "last_price"]
    average_cost:
      canonical_name: "average_cost"
      type: "number"
      unit: "KRW_per_share"
      aliases: ["평단", "Avg_Cost", "average_entry_price"]
    highest_price_since_entry:
      canonical_name: "highest_price_since_entry"
      type: "number"
      unit: "KRW_per_share"
      aliases: ["진입후최고가", "highest_high_since_entry"]
    ma60:
      canonical_name: "ma60"
      type: "number"
      unit: "KRW_per_share"
      aliases: ["MA60", "60일선", "moving_average_60"]
    current_weight_pct:
      canonical_name: "current_weight_pct"
      type: "number"
      unit: "percent"
      aliases: ["현재비중", "current_weight"]
    target_band_min_pct:
      canonical_name: "target_band_min_pct"
      type: "number"
      unit: "percent"
      aliases: ["목표밴드하단"]
    target_band_max_pct:
      canonical_name: "target_band_max_pct"
      type: "number"
      unit: "percent"
      aliases: ["목표밴드상단"]
    immediate_cash:
      canonical_name: "immediate_cash"
      type: "number"
      unit: "KRW"
      aliases: ["즉시현금", "출금가능현금"]
    settlement_cash:
      canonical_name: "settlement_cash"
      type: "number"
      unit: "KRW"
      aliases: ["D+2추정현금", "settlement_cash_d2"]
    reserved_order_amount:
      canonical_name: "reserved_order_amount"
      type: "number"
      unit: "KRW"
      aliases: ["예약주문금액", "open_order_amount"]
    planned_buy_amount:
      canonical_name: "planned_buy_amount"
      type: "number"
      unit: "KRW"
      aliases: ["신규매수예상금액", "planned_order_amount"]
    sell_cash_proceeds_d2:
      canonical_name: "sell_cash_proceeds_d2"
      type: "number"
      unit: "KRW"
      aliases: ["매도대금정산분", "sell_cash_proceeds_immediate", "매도대금즉시반영분"]
      note: "사용자 지침: D+2 정산현금이 현금이다. 매도 후 D+2에 정산될 현금 유입액."
    min_cash_ratio:
      canonical_name: "min_cash_ratio"
      type: "number"
      unit: "percent"
      aliases: ["최소현금비중"]
    trailing_atr_multiplier:
      canonical_name: "trailing_atr_multiplier"
      type: "number"
      unit: "ratio"
      aliases: ["trailing_ATR배수"]
    trailing_stop_price:
      canonical_name: "trailing_stop_price"
      type: "number"
      unit: "KRW_per_share"
      aliases: ["trailing_stop_가격", "트레일링스탑가"]
    position_class:
      canonical_name: "position_class"
      type: "enum"
      unit: "none"
      aliases: ["분류", "core_satellite_class", "position_type"]
    take_profit_ladder:
      canonical_name: "take_profit_ladder"
      type: "object"
      unit: "none"
      aliases: ["익절래더", "tiered_ladder_output"]
    cash_ratio_set:
      canonical_name: "cash_ratio_set"
      type: "object"
      unit: "none"
      aliases: ["현금비중세트"]
    portfolio_band_status:
      canonical_name: "portfolio_band_status"
      type: "enum"
      unit: "none"
      aliases: ["버킷밴드상태", "target_band_status"]
    atr_multiplier:
      canonical_name: "atr_multiplier"
      type: "number"
      unit: "ratio"
      aliases: ["ATR배수"]
    target_weight_limit_amount:
      canonical_name: "target_weight_limit_amount"
      type: "number"
      unit: "KRW"
      aliases: ["목표비중한도금액"]
    sector_limit_amount:
      canonical_name: "sector_limit_amount"
      type: "number"
      unit: "KRW"
      aliases: ["섹터한도금액"]
    liquidity_limit_amount:
      canonical_name: "liquidity_limit_amount"
      type: "number"
      unit: "KRW"
      aliases: ["유동성상한금액"]
    forward_pe:
      canonical_name: "forward_pe"
      type: "number"
      unit: "ratio"
      aliases: ["Forward_PE", "ForwardPER", "선행PER", "12M_Forward_PE"]
    pbr:
      canonical_name: "pbr"
      type: "number"
      unit: "ratio"
      aliases: ["PBR", "P/B", "주가순자산비율"]
    eps_revision_status:
      canonical_name: "eps_revision_status"
      type: "enum"
      unit: "none"
      aliases: ["EPS_Revision_Status", "eps_revision", "EPS방향"]
    sector_median_forward_pe:
      canonical_name: "sector_median_forward_pe"
      type: "number"
      unit: "ratio"
      aliases: ["sector_median_PE", "섹터중앙값PER", "SectorPE_Median"]
    sector_median_pbr:
      canonical_name: "sector_median_pbr"
      type: "number"
      unit: "ratio"
      aliases: ["sector_median_PBR", "섹터중앙값PBR"]
    eps_growth_3y_cagr_pct:
      canonical_name: "eps_growth_3y_cagr_pct"
      type: "number"
      unit: "percent"
      aliases: ["EPS_Growth_3Y", "EPS_CAGR_3Y", "EPS3Y성장률", "EPS_Growth_3Y_CAGR_pct"]
    roe_pct:
      canonical_name: "roe_pct"
      type: "number"
      unit: "percent"
      aliases: ["ROE_Pct", "ROE", "자기자본이익률", "return_on_equity"]
    operating_margin_pct:
      canonical_name: "operating_margin_pct"
      type: "number"
      unit: "percent"
      aliases: ["Operating_Margin_Pct", "영업이익률", "op_margin"]
    debt_to_equity:
      canonical_name: "debt_to_equity"
      type: "number"
      unit: "ratio"
      aliases: ["Debt_To_Equity", "D/E", "부채비율", "debtToEquity"]
    fcf_b:
      canonical_name: "fcf_b"
      type: "number"
      unit: "KRW_100million"
      aliases: ["FCF_B", "잉여현금흐름", "freeCashflow_B"]
    revenue_growth_pct:
      canonical_name: "revenue_growth_pct"
      type: "number"
      unit: "percent"
      aliases: ["Revenue_Growth_Pct", "매출성장률", "revenueGrowth"]
    sector_type:
      canonical_name: "sector_type"
      type: "enum"
      unit: "none"
      aliases: ["업종구분", "Sector_Type"]
    beta_i:
      canonical_name: "beta_i"
      type: "number"
      unit: "ratio"
      aliases: ["개별종목베타"]
    market_value_i:
      canonical_name: "market_value_i"
      type: "number"
      unit: "KRW"
      aliases: ["개별종목시가"]
    total_equity_value:
      canonical_name: "total_equity_value"
      type: "number"
      unit: "KRW"
      aliases: ["총주식가치"]
    take_profit_ladder_v2:
      canonical_name: "take_profit_ladder_v2"
      type: "object"
      unit: "none"
      aliases: ["V2익절래더"]
    financial_health_score:
      canonical_name: "financial_health_score"
      type: "number"
      unit: "points_neg5_to_20"
      aliases: ["FHS", "재무점수"]
    portfolio_beta:
      canonical_name: "portfolio_beta"
      type: "number"
      unit: "ratio"
      aliases: ["포트폴리오베타"]
    tier_completed:
      canonical_name: "tier_completed"
      type: "enum"
      unit: "none"
      aliases: ["완료단계", "익절완료단계"]
      note: "PROFIT_LOCK_RATCHET_V1 입력 — tier_1 또는 tier_2 익절 완료 단계"
    ratchet_stop_price:
      canonical_name: "ratchet_stop_price"
      type: "number"
      unit: "KRW_per_share"
      aliases: ["래칫손절가", "보호스탑가격"]
      note: "PROFIT_LOCK_RATCHET_V1 출력 — 익절 후 상향된 손절 보호가"
    raw_price:
      canonical_name: "raw_price"
      type: "number"
      unit: "KRW_per_share"
      aliases: ["정규화전가격"]
      note: "TICK_NORMALIZER_V1 입력 — 호가 단위 정규화 전 원시 가격"
    tick_normalized_price:
      canonical_name: "tick_normalized_price"
      type: "number"
      unit: "KRW_per_share"
      aliases: ["호가정규화가격", "HTS입력가격"]
      note: "TICK_NORMALIZER_V1 출력 — KRX 호가 단위 정규화 완료 가격"
    tp_price:
      canonical_name: "tp_price"
      type: "number"
      unit: "KRW_per_share"
      aliases: ["익절목표가", "take_profit_price_raw"]
      note: "TP_VALIDITY_CHECK_V1 입력 — TAKE_PROFIT_LADDER_V2가 산출한 티어별 TP 원시 가격 (tp1 또는 tp2)"
    tp_validated_price:
      canonical_name: "tp_validated_price"
      type: "number"
      unit: "KRW_per_share_or_null"
      aliases: ["유효익절가", "validated_tp"]
      note: "TP_VALIDITY_CHECK_V1 출력 — 현재가 이하 TP는 null. 유효한 경우만 HTS 입력 허용."
    market_regime_state:
      canonical_name: "market_regime_state"
      type: "enum"
      unit: "none"
      aliases: ["시장국면단계", "regime_phase", "market_phase"]
      note: "REGIME_TRIM_WEIGHT_V1 입력 — spec/11_market_regime.yaml 국면 분류 결과 (ADVANCE/PULLBACK_IN_UPTREND/DISTRIBUTION/BREAKDOWN)"
    frg_5d_krw:
      canonical_name: "frg_5d_krw"
      type: "number"
      unit: "KRW"
      aliases: ["Frg_5D", "Frg_5D_KRW", "외국인5D순매수금액"]
      note: "외국인 5일 순매수금액(KRW). 양수=순매수, 음수=순매도"
    inst_5d_krw:
      canonical_name: "inst_5d_krw"
      type: "number"
      unit: "KRW"
      aliases: ["Inst_5D", "Inst_5D_KRW", "기관5D순매수금액"]
      note: "기관 5일 순매수금액(KRW). 양수=순매수, 음수=순매도"
    secular_leader_gate_active:
      canonical_name: "secular_leader_gate_active"
      type: "boolean"
      unit: "none"
      aliases: ["주도주게이트활성"]
      note: "SECULAR_LEADER_REGIME_GATE_V1 출력 — 삼성전자·SK하이닉스 secular_leader_profit_lock 발동 여부"
    secular_leader_gate_status:
      canonical_name: "secular_leader_gate_status"
      type: "enum"
      unit: "none"
      aliases: ["주도주게이트상태"]
      note: "SECULAR_LEADER_REGIME_GATE_V1 출력 — ACTIVE/DEACTIVATED/ACTIVATION_FAIL/NOT_APPLICABLE"

    # ── [2026-05-20_HARNESS_V4] M4: 성과 및 목표 추적 입력 필드 ────────────────
    total_asset_krw:
      canonical_name: "total_asset_krw"
      type: "number"
      unit: "KRW"
      aliases: ["totalAsset", "total_asset", "총자산", "포트폴리오총자산"]
      note: "buildHarnessContext_ 집계값 — 보유종목 평가액 + 현금(D+2 기준) 합계"
    net_expectancy_30:
      canonical_name: "net_expectancy_30"
      type: "number_or_null"
      unit: "percent"
      aliases: ["net_exp_30", "monthly_net_expectancy"]
      note: "Bayesian 성과 계산기 출력 — 최근 30거래일 순기대 수익률(%). GOAL_RETIREMENT_V1 ETA 계산 기준."

    # ── [2026-05-20_HARNESS_V4] M4: 5억원 목표 자산 추적 필드 ─────────────────
    goal_asset_krw:
      canonical_name: "goal_asset_krw"
      type: "integer"
      unit: "KRW"
      aliases: ["목표자산", "goal_krw"]
      note: "GOAL_RETIREMENT_V1 고정값 — 500,000,000 KRW (5억원). LLM 재정의 금지."
    goal_current_asset_krw:
      canonical_name: "goal_current_asset_krw"
      type: "integer"
      unit: "KRW"
      aliases: ["현재자산", "current_asset_krw"]
      note: "GOAL_RETIREMENT_V1 산출 — 하네스 캡처 시점 총 자산(totalAsset)"
    goal_achievement_pct:
      canonical_name: "goal_achievement_pct"
      type: "number"
      unit: "percent"
      aliases: ["목표달성률", "achievement_pct"]
      note: "GOAL_RETIREMENT_V1 산출 — goal_current_asset_krw / goal_asset_krw * 100. 소수점 1자리."
    goal_remaining_krw:
      canonical_name: "goal_remaining_krw"
      type: "integer"
      unit: "KRW"
      aliases: ["목표잔여금", "remaining_krw"]
      note: "GOAL_RETIREMENT_V1 산출 — max(0, goal_asset_krw - goal_current_asset_krw)"
    goal_eta_months:
      canonical_name: "goal_eta_months"
      type: "integer_or_null"
      unit: "months"
      aliases: ["목표달성월수", "eta_months"]
      note: "GOAL_RETIREMENT_V1 복리 ETA — null이면 DATA_MISSING(net_expectancy_30 없음). 0이면 ACHIEVED."
    goal_eta_label:
      canonical_name: "goal_eta_label"
      type: "string"
      unit: "none"
      aliases: ["목표달성예상월", "eta_label"]
      note: "GOAL_RETIREMENT_V1 ETA 연월 — YYYY-MM 또는 ACHIEVED 또는 DATA_MISSING"
    goal_monthly_growth_pct:
      canonical_name: "goal_monthly_growth_pct"
      type: "number_or_null"
      unit: "percent"
      aliases: ["월간기대수익률", "monthly_growth_pct"]
      note: "GOAL_RETIREMENT_V1 ETA 계산 기준 — performance.net_expectancy_30 전달값"
    goal_status:
      canonical_name: "goal_status"
      type: "enum"
      unit: "none"
      aliases: ["목표상태", "goal_state"]
      values: ["ACHIEVED", "IN_PROGRESS"]
      note: "GOAL_RETIREMENT_V1 산출 — goal_current_asset_krw >= goal_asset_krw이면 ACHIEVED"
    # ── 하네스 스칼라 입력 필드 (공식 레지스트리 교차 참조용) ─────────────────────
    settlement_cash_d2_krw:
      canonical_name: "settlement_cash_d2_krw"
      type: "integer"
      unit: "KRW"
      aliases: ["d2_cash_krw", "D2현금"]
      note: "D+2 정산 현금 — cash_ledger_basis=D2_ONLY 기준 유일 허용 현금"
    cash_floor_min_pct:
      canonical_name: "cash_floor_min_pct"
      type: "number"
      unit: "percent"
      aliases: ["최소현금방어선", "min_cash_pct"]
      note: "calcCashFloor_() 산출 — MRS 기반 국면별 최소 현금 비율"
    mrs_score:
      canonical_name: "mrs_score"
      type: "number"
      unit: "score_0_100"
      aliases: ["시장위험점수", "market_risk_score"]
      note: "MARKET_RISK_SCORE_V1 산출값 (0~100). TARGET_CASH_PCT_V1 입력."
    sell_candidates_json:
      canonical_name: "sell_candidates_json"
      type: "json_array"
      unit: "none"
      aliases: ["매도후보목록", "h2_candidates"]
      note: "H2 calcSellPriority_() 산출 — sell_priority 기반 정렬 배열"
    sell_quantities_json:
      canonical_name: "sell_quantities_json"
      type: "json_array"
      unit: "none"
      aliases: ["매도수량목록", "h3_sell_qty"]
      note: "H3 calcQuantities_() 산출 — 종목별 매도수량 확정 배열"
    # ── G1: 현금 부족액 / 목표현금 (CASH_SHORTFALL_V1) ──────────────────────
    cash_current_pct_d2:
      canonical_name: "cash_current_pct_d2"
      type: "number"
      unit: "percent"
      aliases: ["현금비중d2", "d2_cash_pct"]
      note: "D+2 정산현금 / 총자산 × 100 — GAS 결정론적 산출 (LLM 재계산 금지)"
    cash_target_pct:
      canonical_name: "cash_target_pct"
      type: "number"
      unit: "percent"
      aliases: ["목표현금비중", "target_cash_pct"]
      note: "TARGET_CASH_PCT_V1: max(5 + (MRS/10)×15, cash_floor_min_pct)"
    cash_shortfall_min_krw:
      canonical_name: "cash_shortfall_min_krw"
      type: "integer"
      unit: "KRW"
      aliases: ["최소현금부족액", "shortfall_min"]
      note: "최소 현금 방어선까지 부족액 — 0이면 방어선 충족. LLM '약 N원' 계산 대체"
    cash_shortfall_target_krw:
      canonical_name: "cash_shortfall_target_krw"
      type: "integer"
      unit: "KRW"
      aliases: ["목표현금부족액", "shortfall_target"]
      note: "국면별 목표 현금비율까지 부족액 — TARGET_CASH_PCT_V1 기준"
    # ── G2: 현금 회복 TRIM 계획 (TRIM_PLAN_MIN_CASH_V1) ──────────────────────
    trim_plan_to_min_cash_json:
      canonical_name: "trim_plan_to_min_cash_json"
      type: "json_array"
      unit: "none"
      aliases: ["현금회복trim계획", "trim_plan_min"]
      note: "H2 매도우선순위 기반 종목별 TRIM 계획 — LLM 임의 종목·순서 선택 금지"
    # ── I5: 외부 시장 데이터 격리 (G3 EXTERNAL_CONTEXT_ISOLATION) ────────────
    external_context_json:
      canonical_name: "external_context_json"
      type: "json_array"
      unit: "none"
      aliases: ["외부시장데이터", "external_data"]
      note: "G3 격리 규칙 적용 — used_for=CONTEXT_ONLY 전용. 주문 판단에 사용 금지"
      required_sub_fields:
        - source_name
        - fetched_at
        - symbol
        - value
        - used_for

    # ── K1: 분할 매수 트랜치 엔진 입력·출력 ─────────────────────────────────
    alpha_lead_score:
      canonical_name: "alpha_lead_score"
      type: "number"
      unit: "score_0_100"
      note: "ALPHA_LEAD_SCORE_V1 산출 — 선행 파일럿 진입 가능성 점수"
    lead_entry_state:
      canonical_name: "lead_entry_state"
      type: "string"
      unit: "enum"
      note: "PILOT_ALLOWED | WATCH_ONLY | BLOCKED_LATE_CHASE | DATA_MISSING"
    follow_through_state:
      canonical_name: "follow_through_state"
      type: "string"
      unit: "enum"
      note: "FOLLOW_THROUGH_CONFIRM_V1 산출 — CONFIRMED_ADD_ON | WAIT_PULLBACK | FAILED_BREAKOUT"
    holding_quantity:
      canonical_name: "holding_quantity"
      type: "integer"
      unit: "shares"
      aliases: ["holdingQty", "보유수량_k1"]
      note: "K1 트랜치 판단용 현재 보유수량"
    profit_pct:
      canonical_name: "profit_pct"
      type: "number"
      unit: "percent"
      note: "PROFIT_PRESERVATION_STATE_V1 산출 — (close-avgCost)/avgCost×100"
    close_vs_ma20_pct:
      canonical_name: "close_vs_ma20_pct"
      type: "number"
      unit: "percent"
      note: "ALPHA_LEAD_SCORE_V1 산출 — (close/MA20-1)×100, 눌림 판단에 사용"
    tranche_phase:
      canonical_name: "tranche_phase"
      type: "string"
      unit: "enum"
      note: "STAGED_ENTRY_TRANCHE_V1 산출 — WAIT_PILOT_SETUP | TRANCHE_1_PILOT | TRANCHE_2_ADD_ON | TRANCHE_3_PULLBACK_ADD | HOLD_CURRENT"
    current_tranche_allowed_pct:
      canonical_name: "current_tranche_allowed_pct"
      type: "number"
      unit: "percent"
      note: "K1: 현재 단계에서 허용된 매수 비중 (0 | 30 | 40)"
    next_tranche_condition:
      canonical_name: "next_tranche_condition"
      type: "string"
      unit: "description"
      note: "K1: 다음 트랜치 진입 조건 코드"

    # ── K2: 반등 대기 분할 매도 입력·출력 ──────────────────────────────────
    close:
      canonical_name: "close"
      type: "number"
      unit: "KRW_per_share"
      aliases: ["Close", "close_price", "종가"]
      note: "당일 종가 — K2 반등 매도 예상금액 계산 기준"
    base_sell_qty:
      canonical_name: "base_sell_qty"
      type: "integer"
      unit: "shares"
      note: "K2: SELL_QUANTITY_ALLOCATOR_V1(H3) 산출 기준 매도수량"
    execution_style:
      canonical_name: "execution_style"
      type: "string"
      unit: "enum"
      note: "URGENT_LIQUIDITY_TRIM | OVERSOLD_REBOUND_SELL | DISTRIBUTION_EXIT | PROFIT_PROTECT_TRIM"
    profit_preservation_state:
      canonical_name: "profit_preservation_state"
      type: "string"
      unit: "enum"
      note: "PROFIT_PRESERVATION_STATE_V1 산출 — NORMAL | BREAKEVEN_RATCHET | PROFIT_LOCK_10/20/30 | APEX_TRAILING"
    profit_lock_stage:
      canonical_name: "profit_lock_stage"
      type: "string"
      unit: "enum"
      aliases: ["profitLockStage"]
      note: "PROFIT_LOCK_STAGE_CLASSIFIER_V1 산출 — NORMAL | PROFIT_LOCK_STAGE_10/20/30/50"
    immediate_sell_qty:
      canonical_name: "immediate_sell_qty"
      type: "integer"
      unit: "shares"
      note: "K2: 즉시 체결 대상 수량 (OVERSOLD_REBOUND_SELL의 경우 floor(base/2))"
    rebound_wait_qty:
      canonical_name: "rebound_wait_qty"
      type: "integer"
      unit: "shares"
      note: "K2: 반등 트리거 대기 수량 — 트리거 미충족 시 HTS 주문 금지"
    emergency_full_sell:
      canonical_name: "emergency_full_sell"
      type: "boolean"
      unit: "none"
      note: "K2: 비상 전량 매도 플래그 — half_krw×2 < shortfall일 때만 true"
    rebound_trigger_price:
      canonical_name: "rebound_trigger_price"
      type: "integer"
      unit: "KRW_per_share"
      note: "K2: 반등 매도 실행 트리거 가격 (prevClose+0.5×ATR20, tick 정규화)"
    execution_method_ladder_json:
      canonical_name: "execution_method_ladder_json"
      type: "json_object"
      unit: "none"
      note: "EXECUTION_METHOD_LADDER_V1 산출 — 매도 실행 방식 계약표"
    sell_timing_verdict:
      canonical_name: "sell_timing_verdict"
      type: "string"
      unit: "enum"
      note: "SELL_EXECUTION_TIMING_LOCK_V2 산출 — SELL_READY | TIMING_BLOCKED_INTRADAY | SELL_BLOCKED_DATA"
    sell_waterfall_gate:
      canonical_name: "sell_waterfall_gate"
      type: "string"
      unit: "enum"
      note: "SELL_WATERFALL_ENGINE_V2 산출 — PASS | WARN | FAIL"
    smart_cash_recovery_gate:
      canonical_name: "smart_cash_recovery_gate"
      type: "string"
      unit: "enum"
      note: "SMART_CASH_RECOVERY_V7 산출 — PASS | WARN | FAIL"

    # ── K3: 국면·섹터 연계 H2 동적 우선순위 출력 ─────────────────────────
    h2_candidates:
      canonical_name: "h2_candidates"
      type: "json_array"
      unit: "none"
      note: "K3 입력: H2 매도후보 배열"
    ret5d:
      canonical_name: "ret5d"
      type: "number"
      unit: "percent"
      aliases: ["Ret5D", "ret_5d"]
      note: "5일 수익률 — K3 베타 프록시 계산 및 섹터 상대강도 판단에 사용"
    kospi_ret5d:
      canonical_name: "kospi_ret5d"
      type: "number"
      unit: "percent"
      aliases: ["KOSPI_Ret5D", "kospiRet5d"]
      note: "K3: KOSPI 5일 수익률 — 고베타 판단 기준"
    frg_5d:
      canonical_name: "frg_5d"
      type: "number"
      unit: "KRW"
      aliases: ["Frg_5D", "frg5d"]
      note: "K3/DISTRIBUTION_RISK_SCORE_V1 입력 — 외국인 5일 순매수금액"
    inst_5d:
      canonical_name: "inst_5d"
      type: "number"
      unit: "KRW"
      aliases: ["Inst_5D", "inst5d"]
      note: "K3/DISTRIBUTION_RISK_SCORE_V1 입력 — 기관 5일 순매수금액"
    ac_gate:
      canonical_name: "ac_gate"
      type: "string"
      unit: "enum"
      aliases: ["AC_Gate", "acGate"]
      note: "J2/K3: 안티클라이막스 게이트 상태 — CLIMAX 포함 시 설거지 위험 신호"
    regime_adjusted_sell_priority_json:
      canonical_name: "regime_adjusted_sell_priority_json"
      type: "json_array"
      unit: "none"
      aliases: ["regime_sell_priority", "k3_priority"]
      note: "K3_REGIME_SELL_PRIORITY_V1 산출 — final_regime_rank 기준 매도 순서. sell_priority_lock=true이면 LLM 재정렬 금지"
    regime_trim_guidance:
      canonical_name: "regime_trim_guidance"
      type: "json_array"
      unit: "none"
      aliases: ["regimeTrimGuidance"]
      note: "REGIME_TRIM_GUIDANCE_V1 산출 — 국면별 현금확보 TRIM 우선순위"
    anti_whipsaw_status:
      canonical_name: "anti_whipsaw_status"
      type: "string"
      unit: "enum"
      aliases: ["antiWhipsawStatus"]
      note: "ANTI_WHIPSAW_GATE_V1 산출 — WHIPSAW_BLOCK/WARN/CLEAR"
    breakeven_stop_price:
      canonical_name: "breakeven_stop_price"
      type: "number"
      unit: "KRW_per_share"
      aliases: ["breakevenStopPrice"]
      note: "BREAKEVEN_RATCHET_V1 산출 — 손익분기 래칫 손절가"
    # ── 공통 포지션 필드 (M2/M3/M5 공유)
    weight_pct:
      canonical_name: "weight_pct"
      type: "number"
      unit: "pct"
      aliases: ["weightPct", "Weight_Pct"]
      note: "보유 비중(%) — M2 베타 가중, M5 섹터 편중 계산 입력"
    holding_qty:
      canonical_name: "holding_qty"
      type: "number"
      unit: "shares"
      aliases: ["holdingQty", "holding_quantity"]
      note: "현재 보유 수량 — M3 익절 수량 계산 입력"
    proposed_quantity:
      canonical_name: "proposed_quantity"
      type: "number_or_null"
      unit: "shares"
      aliases: ["proposal_qty"]
      note: "proposal_reference_json 제안 수량 — 보유수량 부재 시 stop proposal ladder fallback 입력"
    tp1_price:
      canonical_name: "tp1_price"
      type: "number_or_null"
      unit: "KRW_per_share"
      aliases: ["TP1_Price", "tp1Price"]
      note: "M3/prices_json 필드 — TP1 목표 가격. null=이미 통과 또는 미계산"
    tp1_qty:
      canonical_name: "tp1_qty"
      type: "number"
      unit: "shares"
      aliases: ["TP1_Qty", "tp1Qty"]
      note: "M3 — TP1 도달 시 매도 수량 (수동 입력 또는 AUTO_33PCT)"
    tp2_price:
      canonical_name: "tp2_price"
      type: "number_or_null"
      unit: "KRW_per_share"
      aliases: ["TP2_Price", "tp2Price"]
      note: "M3/prices_json 필드 — TP2 목표 가격"
    tp2_qty:
      canonical_name: "tp2_qty"
      type: "number"
      unit: "shares"
      aliases: ["TP2_Qty", "tp2Qty"]
      note: "M3 — TP2 도달 시 매도 수량"
    tp3_qty:
      canonical_name: "tp3_qty"
      type: "number"
      unit: "shares"
      aliases: ["TP3_Qty", "tp3Qty", "tp3_quantity"]
      note: "M3 — TP3/잔량 수량"
    proposal_stop_ladder:
      canonical_name: "proposal_stop_ladder"
      type: "json_object"
      unit: "none"
      note: "STOP_PROPOSAL_LADDER_V1 산출 — proposal_reference_sheet용 손절 1/2/3 가격·수량 묶음"
    dart_risk:
      canonical_name: "dart_risk"
      type: "string"
      unit: "Y/N"
      aliases: ["DART_Risk", "dartRisk"]
      note: "M4 입력 — DART 공시 리스크 플래그 (Y=위험, N/''=없음)"
    # ── M1 필드
    drawdown_guard_state:
      canonical_name: "drawdown_guard_state"
      type: "string"
      unit: "enum"
      aliases: ["drawdownGuardState"]
      note: "M1_DRAWDOWN_GUARD_V1 산출 — NO_BUY/REDUCE_BUY/CAUTION_BUY/NORMAL"
    drawdown_buy_scale:
      canonical_name: "drawdown_buy_scale"
      type: "number"
      unit: "0~1"
      aliases: ["drawdownBuyScale", "buy_scale"]
      note: "M1 — atrQty 곱셈 배수. 1.0=정상, 0.5=50% 축소, 0=매수 금지"
    consecutive_losses:
      canonical_name: "consecutive_losses"
      type: "number"
      unit: "integer"
      aliases: ["consecutiveLosses"]
      note: "M1 입력 — 최근 연속 손절 횟수 (performance 시트 기준)"
    # ── M2 필드
    portfolio_beta:
      canonical_name: "portfolio_beta"
      type: "number_or_null"
      unit: "ratio"
      aliases: ["portfolioBeta"]
      note: "M2_PORTFOLIO_BETA_GATE_V1 산출 — 보유 종목 가중평균 베타. null=데이터 부족"
    portfolio_beta_gate:
      canonical_name: "portfolio_beta_gate"
      type: "string"
      unit: "enum"
      aliases: ["portfolioBetaGate"]
      note: "M2 — OVER_BETA/WARN_BETA/PASS/INSUFFICIENT_DATA"
    portfolio_beta_gate_json:
      canonical_name: "portfolio_beta_gate_json"
      type: "json_object"
      unit: "none"
      aliases: ["betaGateJson"]
      note: "M2 — per-holding beta_proxy 상세 및 포트폴리오 베타 요약"
    beta_proxy:
      canonical_name: "beta_proxy"
      type: "number"
      unit: "ratio"
      aliases: ["betaProxy"]
      note: "M2/K3 — ret5d/kospiRet5d 기반 베타 근사값. 비정상 시 1.0 사용"
    # ── M3 필드
    tp_quantity_ladder_json:
      canonical_name: "tp_quantity_ladder_json"
      type: "json_array"
      unit: "none"
      aliases: ["tpLadderJson"]
      note: "M3_TP_QUANTITY_LADDER_V1 산출 — TP1/2/3 도달 시 매도 수량. tp_quantity_ladder_lock=true이면 LLM 변경 금지"
    qty_source:
      canonical_name: "qty_source"
      type: "string"
      unit: "enum"
      aliases: ["qtySource"]
      note: "M3 — MANUAL(수동 입력)/AUTO_33PCT(자동 33%)/NO_HOLDING"
    # ── M4 필드
    event_hold_days:
      canonical_name: "event_hold_days"
      type: "number_or_null"
      unit: "integer"
      aliases: ["eventHoldDays", "Event_Hold_Days"]
      note: "M4 입력 — 이벤트(실적/공시) 홀드 잔여일. <=5이면 EVENT_HOLD"
    event_hold_gate:
      canonical_name: "event_hold_gate"
      type: "string"
      unit: "enum"
      aliases: ["eventHoldGate"]
      note: "M4_EVENT_RISK_HOLD_GATE_V1 산출 — EVENT_HOLD/PASS"
    event_risk_json:
      canonical_name: "event_risk_json"
      type: "json_array"
      unit: "none"
      aliases: ["eventRiskJson"]
      note: "M4 — per-holding 이벤트 홀드 게이트 상태 배열"
    # ── M5 필드
    sector_concentration_gate:
      canonical_name: "sector_concentration_gate"
      type: "string"
      unit: "enum"
      aliases: ["sectorConcentrationGate"]
      note: "M5_SECTOR_CONCENTRATION_LIMIT_V1 산출 — BLOCK_SECTOR/WARN_TOP2/PASS"
    sector_concentration_json:
      canonical_name: "sector_concentration_json"
      type: "json_array"
      unit: "none"
      aliases: ["sectorConcentrationJson"]
      note: "M5 — 섹터별 weight_pct 및 gate 상태 배열"
    # ── 공통
    sector:
      canonical_name: "sector"
      type: "string"
      unit: "none"
      aliases: ["sectorName", "sector_name"]
      note: "L1/K3 입력 — 섹터명 (TICKER_SECTOR_MAP 기반). sectorFlowRadar key"
    rank:
      canonical_name: "rank"
      type: "number"
      unit: "integer"
      aliases: ["sectorRank", "Rotation_Rank", "Sector_Rank"]
      note: "L1 입력 — 현재 주 섹터 로테이션 순위 (낮을수록 우수)"
    prev_rank_w1:
      canonical_name: "prev_rank_w1"
      type: "number_or_null"
      unit: "integer"
      aliases: ["prevRank", "Prev_Rotation_Rank"]
      note: "L1 입력 — 1주 전 섹터 순위. 미제공 시 null"
    prev_rank_w2:
      canonical_name: "prev_rank_w2"
      type: "number_or_null"
      unit: "integer"
      aliases: ["prevRankW2", "Prev_Rotation_Rank_W2"]
      note: "L1 입력 — 2주 전 섹터 순위. 미제공 시 null"
    sector_rotation_momentum_json:
      canonical_name: "sector_rotation_momentum_json"
      type: "json_array"
      unit: "none"
      aliases: ["sectorMomentumJson", "sector_momentum_json"]
      note: "L1_SECTOR_ROTATION_MOMENTUM_V1 산출 — 섹터별 rank_delta/momentum_state. sector_rotation_momentum_lock=true이면 LLM 재산출 금지"
    rank_delta_w1:
      canonical_name: "rank_delta_w1"
      type: "number_or_null"
      unit: "integer"
      aliases: ["rankDeltaW1"]
      note: "L1 입력 — 1주 섹터 순위 변화 (양수=순위 하락). prev_rank_w1 미제공 시 null"
    rank_delta_w2:
      canonical_name: "rank_delta_w2"
      type: "number_or_null"
      unit: "integer"
      aliases: ["rankDeltaW2"]
      note: "L1 입력 — 2주 섹터 순위 변화. prev_rank_w2 미제공 시 null"
    momentum_state:
      canonical_name: "momentum_state"
      type: "string"
      unit: "enum"
      aliases: ["momentumState"]
      note: "L1_SECTOR_ROTATION_MOMENTUM_V1 산출 — RISING/STABLE/TOPPING_OUT/FADING"
    pre_distribution_warning:
      canonical_name: "pre_distribution_warning"
      type: "string"
      unit: "enum"
      aliases: ["preDistributionWarning", "pre_dist_warning"]
      note: "L4_PRE_DISTRIBUTION_EARLY_WARNING_V1 산출 — EARLY_WARNING(신고점수축/급등약류)/NONE. 이 값이 EARLY_WARNING이면 신규 매수 신중 재검토"
    high52w:
      canonical_name: "high52w"
      type: "number"
      unit: "KRW_per_share"
      aliases: ["High52W", "high_52w", "52w_high"]
      note: "L4 입력 — 52주 최고가. 데이터 미제공 시 MA20×1.15 대체 판단"
    auto_trailing_stop:
      canonical_name: "auto_trailing_stop"
      type: "number_or_null"
      unit: "KRW_per_share"
      aliases: ["autoTrailingStop", "trailing_stop"]
      note: "L2_RATCHET_TRAILING_AUTO_V1 산출 — PROFIT_LOCK_20/30/APEX_TRAILING 구간 ATR 트레일링 손절가. null=비해당. LLM이 이 값보다 낮은 손절가 제시 금지"
    protected_stop_price:
      canonical_name: "protected_stop_price"
      type: "number_or_null"
      unit: "KRW_per_share"
      aliases: ["protectedStopPrice", "ratchet_stop_price"]
      note: "profit_preservation_json 출력 — 수익보전 단계에서 유지해야 하는 보호 손절가"
    auto_trailing_note:
      canonical_name: "auto_trailing_note"
      type: "string_or_null"
      unit: "none"
      aliases: ["autoTrailingNote"]
      note: "L2_RATCHET_TRAILING_AUTO_V1 산출 근거 — 'max(ratchet,{highest}-N.N×ATR)' 형식"
    highest_price_since_entry:
      canonical_name: "highest_price_since_entry"
      type: "number"
      unit: "KRW_per_share"
      aliases: ["highestPriceSinceEntry", "highest_close"]
      note: "진입 후 최고 종가 — L2 ATR 트레일링 기준가. prices_json에 포함"
    total_heat_pct:
      canonical_name: "total_heat_pct"
      type: "number"
      unit: "pct"
      aliases: ["totalHeatPct", "total_heat"]
      note: "포트폴리오 총 Heat 비율 — DYNAMIC_HEAT_GATE_V1/TOTAL_HEAT_V1 입력. heat_gate_threshold_pct와 비교해 gate 판정"
    heat_gate_threshold_pct:
      canonical_name: "heat_gate_threshold_pct"
      type: "number"
      unit: "pct"
      aliases: ["heatGateThresholdPct", "heat_threshold_pct"]
      note: "L3_DYNAMIC_HEAT_GATE_V1 산출 — 현재 국면에서 적용된 BLOCK_NEW_BUY 임계값(%). GAS 결정론적 산출, LLM 재계산 금지"
    market_regime:
      canonical_name: "market_regime"
      type: "string"
      unit: "enum"
      aliases: ["marketRegime", "regime"]
      note: "현재 시장 국면 — DYNAMIC_HEAT_GATE_V1/K3/L3 등 국면 감응 공식의 공통 입력"

    # ── N-group 출력 필드 (2026-05-20) ─────────────────────────────────────
    regime_size_scale:
      canonical_name: "regime_size_scale"
      type: "number"
      unit: "multiplier"
      aliases: ["regimeSizeScale"]
      note: "N1_POSITION_SIZE_REGIME_SCALE_V1 — 국면별 atrQty 스케일 배수 (0.25~1.2). GAS 결정론적 산출"

    stop_adequacy_json:
      canonical_name: "stop_adequacy_json"
      type: "json"
      unit: "array"
      aliases: ["stopAdequacyJson"]
      note: "N3_STOP_PRICE_ADEQUACY_V1 — 보유 종목별 손절가 적정성 검증 결과 배열"

    absolute_risk_stop_rows:
      canonical_name: "absolute_risk_stop_rows"
      type: "json"
      unit: "array"
      aliases: ["absoluteRiskStopRows"]
      note: "P3 ABSOLUTE_RISK_STOP_V1 — 절대 리스크 손절 taxonomy 결과 배열"

    relative_underperf_alert:
      canonical_name: "relative_underperf_alert"
      type: "json"
      unit: "object"
      aliases: ["relativeUnderperfAlert"]
      note: "P3 RELATIVE_UNDERPERF_ALERT_V1 — 상대약세 경보 taxonomy 객체"

    stop_action_ladder:
      canonical_name: "stop_action_ladder"
      type: "json"
      unit: "object"
      aliases: ["stopActionLadder"]
      note: "P3 STOP_ACTION_LADDER_V1 — 최종 손절/익절/시간손절 액션 래더"

    df_map:
      canonical_name: "df_map"
      type: "json"
      unit: "object"
      aliases: ["dfMap"]
      note: "P3 taxonomy wrapper 입력용 data feed map"

    kospi_ret20d:
      canonical_name: "kospi_ret20d"
      type: "number"
      unit: "percent"
      aliases: ["kospiRet20d"]
      note: "P3 RELATIVE_UNDERPERF_ALERT_V1 입력용 KOSPI 20D 수익률"

    context:
      canonical_name: "context"
      type: "json"
      unit: "object"
      aliases: ["ctx"]
      note: "P3 STOP_ACTION_LADDER_V1 입력용 calcSellDecision_ 컨텍스트 객체"

    stop_gap_pct:
      canonical_name: "stop_gap_pct"
      type: "number"
      unit: "pct"
      aliases: ["stopGapPct"]
      note: "N3: (recommended_stop - manual_stop) / recommended_stop × 100"

    adequacy_status:
      canonical_name: "adequacy_status"
      type: "string"
      unit: "enum"
      aliases: ["adequacyStatus"]
      note: "N3: PASS/STOP_WIDE/STOP_CRITICAL/INSUFFICIENT_DATA"

    recommended_stop:
      canonical_name: "recommended_stop"
      type: "number"
      unit: "KRW_per_share"
      aliases: ["recommendedStop", "recommended_stop_price"]
      note: "N3: ATR 기반 권고 손절가 — max(avgCost×0.92, avgCost-ATR20×mul), tick 정규화 적용"

    candidate_quality_grade:
      canonical_name: "candidate_quality_grade"
      type: "string"
      unit: "enum"
      aliases: ["Candidate_Quality_Grade"]
      note: "core_satellite 후보 품질 등급. 실행 추천이 아님."

    execution_recommendation_state:
      canonical_name: "execution_recommendation_state"
      type: "string"
      unit: "enum"
      aliases: ["Execution_Recommendation_State"]
      note: "BUY_PILOT_ALLOWED/WATCH/BLOCK 상태. HTS 주문은 order_blueprint PASS만 허용."

    expected_edge:
      canonical_name: "expected_edge"
      type: "number"
      unit: "ratio"
      aliases: ["Expected_Edge"]
      note: "기대우위. 손절가와 목표가 기반 매수 허용 하한 검증."

    entry_mode_gate:
      canonical_name: "entry_mode_gate"
      type: "string"
      unit: "enum"
      aliases: ["Entry_Mode_Gate"]
      note: "진입 모드 PASS/PENDING/BLOCK 게이트."

    timing_score_entry:
      canonical_name: "timing_score_entry"
      type: "number"
      unit: "score_0_100"
      aliases: ["Timing_Score_Entry"]
      note: "진입 타이밍 점수."

    timing_score_exit:
      canonical_name: "timing_score_exit"
      type: "number"
      unit: "score_0_100"
      aliases: ["Timing_Score_Exit"]
      note: "청산/감축 타이밍 점수."

    liquidity_status:
      canonical_name: "liquidity_status"
      type: "string"
      unit: "enum"
      aliases: ["Liquidity_Status"]
      note: "거래대금 기반 유동성 상태."
    smart_money_flow_signal_v2_json:
      canonical_name: "smart_money_flow_signal_v2_json"
      type: "json"
      unit: "array"
      aliases: ["smartMoneyFlowSignalV2Json"]
      note: "CAPITAL_STYLE_ALLOCATION_V1 입력 — 스마트머니 흐름 배열"
    fundamental_multifactor_v3_json:
      canonical_name: "fundamental_multifactor_v3_json"
      type: "json"
      unit: "array"
      aliases: ["fundamentalMultifactorV3Json"]
      note: "CAPITAL_STYLE_ALLOCATION_V1 입력 — 펀더멘털 멀티팩터 배열"
    macro_event_ticker_impact_v1_json:
      canonical_name: "macro_event_ticker_impact_v1_json"
      type: "json"
      unit: "array"
      aliases: ["macroEventTickerImpactV1Json"]
      note: "CAPITAL_STYLE_ALLOCATION_V1 입력 — 거시 이벤트 영향 배열"
    liquidity_flow_signal_v1_json:
      canonical_name: "liquidity_flow_signal_v1_json"
      type: "json"
      unit: "array"
      aliases: ["liquidityFlowSignalV1Json"]
      note: "CAPITAL_STYLE_ALLOCATION_V1 입력 — 유동성 흐름 배열"
    capital_style_conviction:
      canonical_name: "capital_style_conviction"
      type: "number"
      unit: "score_0_100"
      aliases: ["capitalStyleConviction"]
      note: "CAPITAL_STYLE_ALLOCATION_V1 산출 — 투자성향별 conviction"
    capital_style_label:
      canonical_name: "capital_style_label"
      type: "string"
      unit: "enum"
      aliases: ["capitalStyleLabel"]
      note: "CAPITAL_STYLE_ALLOCATION_V1 산출 — 투자성향 라벨"

    spread_status:
      canonical_name: "spread_status"
      type: "string"
      unit: "enum"
      aliases: ["Spread_Status"]
      note: "호가 스프레드 상태."

    sell_action:
      canonical_name: "sell_action"
      type: "string"
      unit: "enum"
      aliases: ["Sell_Action"]
      note: "하네스 산출 매도/감축 액션."

    sell_validation:
      canonical_name: "sell_validation"
      type: "string"
      unit: "enum"
      aliases: ["Sell_Validation"]
      note: "매도 신호 검산 상태."

    rw_partial:
      canonical_name: "rw_partial"
      type: "number"
      unit: "count"
      aliases: ["RW_Partial"]
      note: "상대약세 부분 신호 개수."

    distribution_risk_score:
      canonical_name: "distribution_risk_score"
      type: "number"
      unit: "score_0_100"
      aliases: ["Distribution_Risk_Score"]
      note: "분산위험 점수."

    late_chase_risk_score:
      canonical_name: "late_chase_risk_score"
      type: "number"
      unit: "score_0_100"
      aliases: ["Late_Chase_Risk_Score"]
      note: "추격매수 위험 점수."

    rsi14:
      canonical_name: "rsi14"
      type: "number"
      unit: "points"
      aliases: ["RSI14"]
      note: "14일 RSI."

    disparity:
      canonical_name: "disparity"
      type: "number"
      unit: "pct"
      aliases: ["Disparity"]
      note: "이격도."

    val_surge_pct:
      canonical_name: "val_surge_pct"
      type: "number"
      unit: "pct"
      aliases: ["Val_Surge_Pct"]
      note: "거래대금 급증률."

    ret5d:
      canonical_name: "ret5d"
      type: "number"
      unit: "pct"
      aliases: ["Ret5D"]
      note: "5거래일 수익률."

    ret_1d:
      canonical_name: "ret_1d"
      type: "number"
      unit: "percent"
      aliases: ["Ret_1D", "ret1d", "1D_Return_Pct"]
      note: "전일 대비 수익률 (%)."

    ret_3d:
      canonical_name: "ret_3d"
      type: "number"
      unit: "percent"
      aliases: ["Ret_3D", "ret3d", "3D_Return_Pct"]
      note: "3거래일 수익률 (%)."

    days_since_breakout:
      canonical_name: "days_since_breakout"
      type: "number"
      unit: "trading_days"
      aliases: ["Days_Since_Breakout", "daysSinceBreakout"]
      note: "돌파 발생 후 경과 거래일 수."

    ret_since_breakout:
      canonical_name: "ret_since_breakout"
      type: "number"
      unit: "pct"
      aliases: ["Ret_Since_Breakout", "retSinceBreakout"]
      note: "돌파일 종가 대비 현재 수익률."

    follow_through_day_state:
      canonical_name: "follow_through_day_state"
      type: "string"
      unit: "enum"
      aliases: ["Follow_Through_Day_State", "followThroughDayState"]
      note: "Follow-Through Day 판정 상태."

    vol_ratio_vs_breakout_day:
      canonical_name: "vol_ratio_vs_breakout_day"
      type: "number"
      unit: "ratio"
      aliases: ["Vol_Ratio_Vs_Breakout_Day", "volRatioVsBreakoutDay"]
      note: "돌파일 대비 거래량 비율."

    vol_today:
      canonical_name: "vol_today"
      type: "number"
      unit: "shares"
      aliases: ["Vol_Today", "volToday"]
      note: "당일 거래량."

    vol_breakout_day:
      canonical_name: "vol_breakout_day"
      type: "number"
      unit: "shares"
      aliases: ["Vol_Breakout_Day", "volBreakoutDay", "volumeBreakoutDay"]
      note: "돌파일 거래량."

    consecutive_sell_signals_5d:
      canonical_name: "consecutive_sell_signals_5d"
      type: "number"
      unit: "count"
      aliases: ["Consecutive_Sell_Signals_5D", "consecutiveSellSignals5d"]
      note: "최근 5일간 연속 매도 신호 수."

    vol_surge_pct:
      canonical_name: "vol_surge_pct"
      type: "number"
      unit: "pct"
      aliases: ["Vol_Surge_Pct", "volSurgePct"]
      note: "당일 거래량 급증률."

    allowed_intraday_actions:
      canonical_name: "allowed_intraday_actions"
      type: "array"
      unit: "enum_list"
      aliases: ["Allowed_Intraday_Actions", "allowedIntradayActions"]
      note: "장중 허용 액션 목록."

    blocked_intraday_actions:
      canonical_name: "blocked_intraday_actions"
      type: "array"
      unit: "enum_list"
      aliases: ["Blocked_Intraday_Actions", "blockedIntradayActions"]
      note: "장중 차단 액션 목록."

    execution_quality_score:
      canonical_name: "execution_quality_score"
      type: "number"
      unit: "score"
      aliases: ["Execution_Quality_Score", "executionQualityScore"]
      note: "실행 품질 점수."

    execution_quality_grade:
      canonical_name: "execution_quality_grade"
      type: "string"
      unit: "enum"
      aliases: ["Execution_Quality_Grade", "executionQualityGrade"]
      note: "실행 품질 등급."

    execution_quality_outcome:
      canonical_name: "execution_quality_outcome"
      type: "string"
      unit: "enum"
      aliases: ["Execution_Quality_Outcome", "executionQualityOutcome"]
      note: "실행 품질 결과 분류."

    threshold_adjustment_proposals:
      canonical_name: "threshold_adjustment_proposals"
      type: "array"
      unit: "json"
      aliases: ["Threshold_Adjustment_Proposals", "thresholdAdjustmentProposals"]
      note: "임계치 조정 제안 목록."

    max_child_qty:
      canonical_name: "max_child_qty"
      type: "number"
      unit: "count"
      aliases: ["Max_Child_Qty", "maxChildQty"]
      note: "TWAP 분할 최대 자식 주문 수량."

    n_slices:
      canonical_name: "n_slices"
      type: "number"
      unit: "count"
      aliases: ["N_Slices", "nSlices"]
      note: "분할 주문 횟수."

    participation_rate:
      canonical_name: "participation_rate"
      type: "number"
      unit: "ratio"
      aliases: ["Participation_Rate", "participationRate"]
      note: "시장 참여율."

    twap_required:
      canonical_name: "twap_required"
      type: "boolean"
      unit: "boolean"
      aliases: ["Twap_Required", "twapRequired"]
      note: "TWAP 필요 여부."

    institutional_flow_5d:
      canonical_name: "institutional_flow_5d"
      type: "number"
      unit: "KRW"
      aliases: ["Institutional_Flow_5D", "institutionalFlow5d"]
      note: "기관 5일 누적 순매수 금액."

    foreign_flow_5d:
      canonical_name: "foreign_flow_5d"
      type: "number"
      unit: "KRW"
      aliases: ["Foreign_Flow_5D", "foreignFlow5d"]
      note: "외국인 5일 누적 순매수 금액."

    sector_relative_strength_5d:
      canonical_name: "sector_relative_strength_5d"
      type: "number"
      unit: "ratio"
      aliases: ["Sector_Relative_Strength_5D", "sectorRelativeStrength5d"]
      note: "섹터 5일 상대강도."

    secular_leader_gate:
      canonical_name: "secular_leader_gate"
      type: "string"
      unit: "enum"
      aliases: ["secularLeaderGate"]
      note: "SECULAR_LEADER_REGIME_GATE_V1 결과 enum."

    breakout_quality_gate:
      canonical_name: "breakout_quality_gate"
      type: "string"
      unit: "enum"
      aliases: ["breakoutQualityGate", "breakout_quality_gate_state"]
      note: "BREAKOUT_QUALITY_GATE_V2 상태 enum."

    dart_risk:
      canonical_name: "dart_risk"
      type: "string"
      unit: "text"
      aliases: ["DART_Risk"]
      note: "공시 리스크 요약."

    final_action:
      canonical_name: "final_action"
      type: "string"
      unit: "enum"
      aliases: ["Final_Action"]
      note: "하네스 최종 액션."

    cash_preserve_style:
      canonical_name: "cash_preserve_style"
      type: "string"
      unit: "enum"
      aliases: ["Cash_Preserve_Style"]
      note: "현금확보 매도 스타일."

    allowed_action:
      canonical_name: "allowed_action"
      type: "string"
      unit: "enum"
      aliases: ["Allowed_Action"]
      note: "내부 허용 액션."

    t1_forced_sell_risk_score:
      canonical_name: "t1_forced_sell_risk_score"
      type: "number"
      unit: "score_0_100"
      aliases: ["T1_Forced_Sell_Risk_Score"]
      note: "매수 후 다음 거래일 강제 매도 위험 점수."

    sell_conflict_score:
      canonical_name: "sell_conflict_score"
      type: "number"
      unit: "score_0_100"
      aliases: ["Sell_Conflict_Score"]
      note: "매도/현금확보 게이트와 신규매수 충돌 점수."

    holding_stale_json:
      canonical_name: "holding_stale_json"
      type: "json"
      unit: "array"
      aliases: ["holdingStaleJson"]
      note: "N4_HOLDING_STALE_REVIEW_V1 — 보유 기간 기반 재검토 플래그 배열"

    holding_days:
      canonical_name: "holding_days"
      type: "number"
      unit: "integer_days"
      aliases: ["holdingDays"]
      note: "N4: entry_date 기준 보유 일수"

    stale_status:
      canonical_name: "stale_status"
      type: "string"
      unit: "enum"
      aliases: ["staleStatus"]
      note: "N4: STALE_POSITION(>60d)/REVIEW_SOON(>30d)/FRESH(<=30d)/ENTRY_DATE_MISSING"

    entry_date:
      canonical_name: "entry_date"
      type: "string"
      unit: "ISO_date"
      aliases: ["entryDate", "Entry_Date", "entry_date_iso"]
      note: "N4: account_snapshot의 진입일 컬럼 — HOLDING_STALE_REVIEW_V1 입력"

    regime_cash_uplift_min_pct:
      canonical_name: "regime_cash_uplift_min_pct"
      type: "number"
      unit: "pct"
      aliases: ["regimeCashUpliftMinPct"]
      note: "N5_REGIME_CASH_UPLIFT_V1 — 국면 상향 적용 후 실제 현금 최소 비율 (%). GAS 결정론적 산출"

    # ── O4 입력 필드 (performance sheet) ────────────────────────────────────
    win_rate_30:
      canonical_name: "win_rate_30"
      type: "number"
      unit: "ratio_0_to_1"
      aliases: ["winRate30", "win_rate"]
      note: "O4 입력: 최근 30거래 승률 (0.0~1.0). readPerformanceSheet_() 산출"

    trades_used:
      canonical_name: "trades_used"
      type: "number"
      unit: "integer"
      aliases: ["tradesUsed"]
      note: "O4 입력: 성능 계산에 사용된 거래 수. 10 미만이면 INSUFFICIENT_HISTORY"

    # ── O-group 출력 필드 (2026-05-20) ─────────────────────────────────────
    single_position_weight_gate:
      canonical_name: "single_position_weight_gate"
      type: "string"
      unit: "enum"
      aliases: ["singlePositionWeightGate"]
      note: "O1_SINGLE_POSITION_WEIGHT_CAP_V1 — OVERWEIGHT_TRIM/PASS. 개별 종목 비중 상한 초과 여부"

    single_position_weight_json:
      canonical_name: "single_position_weight_json"
      type: "json"
      unit: "array"
      aliases: ["singlePositionWeightJson"]
      note: "O1: 종목별 weight_pct vs cap_pct 상태 배열"

    semiconductor_cluster_gate:
      canonical_name: "semiconductor_cluster_gate"
      type: "string"
      unit: "enum"
      aliases: ["semiconductorClusterGate"]
      note: "O2_SEMICONDUCTOR_CLUSTER_GATE_V1 — CLUSTER_BLOCK/PASS. 005930+000660 합산 비중의 국면별 상한 초과 여부"

    semiconductor_cluster_json:
      canonical_name: "semiconductor_cluster_json"
      type: "json"
      unit: "object"
      aliases: ["semiconductorClusterJson"]
      note: "O2: 반도체 클러스터 합산 비중 및 종목별 상세. threshold_pct는 국면별 가변"

    portfolio_drawdown_gate:
      canonical_name: "portfolio_drawdown_gate"
      type: "string"
      unit: "enum"
      aliases: ["portfolioDrawdownGate"]
      note: "O3_PORTFOLIO_DRAWDOWN_GATE_V1 — DRAWDOWN_FORCE_RISK_OFF/DRAWDOWN_CAUTION/PASS/INSUFFICIENT_DATA"

    portfolio_drawdown_pct:
      canonical_name: "portfolio_drawdown_pct"
      type: "number"
      unit: "pct"
      aliases: ["portfolioDrawdownPct"]
      note: "O3: 고점 대비 낙폭 % (양수=낙폭). GAS 결정론적 산출"

    portfolio_peak_krw:
      canonical_name: "portfolio_peak_krw"
      type: "number"
      unit: "KRW"
      aliases: ["portfolioPeakKrw"]
      note: "O3: 역대 총자산 고점 (원). settings 시트 자동 갱신"

    win_loss_streak_state:
      canonical_name: "win_loss_streak_state"
      type: "string"
      unit: "enum"
      aliases: ["winLossStreakState"]
      note: "O4_WIN_LOSS_STREAK_GUARD_V1 — EDGE_OK/EDGE_WEAK/EDGE_DEGRADED/EDGE_CRITICAL/INSUFFICIENT_HISTORY"

    win_loss_streak_buy_scale:
      canonical_name: "win_loss_streak_buy_scale"
      type: "number"
      unit: "multiplier"
      aliases: ["winLossStreakBuyScale"]
      note: "O4: atrQty에 곱해지는 배수 (0.25~1.0). GAS 결정론적 산출"

    win_loss_streak_win_rate_pct:
      canonical_name: "win_loss_streak_win_rate_pct"
      type: "number"
      unit: "pct"
      aliases: ["winLossStreakWinRatePct"]
      note: "O4: 최근 30거래 승률 % (0~100)"

    position_count_gate:
      canonical_name: "position_count_gate"
      type: "string"
      unit: "enum"
      aliases: ["positionCountGate"]
      note: "O5_POSITION_COUNT_LIMIT_V1 — POSITION_COUNT_BLOCK/PASS"

    position_count:
      canonical_name: "position_count"
      type: "number"
      unit: "integer"
      aliases: ["positionCount"]
      note: "O5: 현재 보유 종목 수 (holdings.length)"

    position_count_max:
      canonical_name: "position_count_max"
      type: "number"
      unit: "integer"
      aliases: ["positionCountMax"]
      note: "O5: 국면별 최대 허용 종목 수 (NEUTRAL:8, RISK_OFF:6)"

    # ── P5 입력 필드 (게이트 열거형) ────────────────────────────────────────
    heat_gate_status:
      canonical_name: "heat_gate_status"
      type: "string"
      unit: "enum"
      aliases: ["heatGateStatus", "heat_gate"]
      note: "P5 입력: BLOCK_NEW_BUY/HALVE_NEW_BUY_QUANTITY/ALLOW_CONTINUE"

    cash_floor_status:
      canonical_name: "cash_floor_status"
      type: "string"
      unit: "enum"
      aliases: ["cashFloorStatus"]
      note: "P5 입력: HARD_BLOCK/TRIM_REQUIRED/PASS — cash_floor 게이트 상태"

    # ── P-group 출력 필드 (2026-05-20) ─────────────────────────────────────
    stop_breach_gate:
      canonical_name: "stop_breach_gate"
      type: "string"
      unit: "enum"
      aliases: ["stopBreachGate"]
      note: "P1_STOP_BREACH_ALERT_V1 — BREACH/APPROACHING/PASS"

    stop_breach_alert_json:
      canonical_name: "stop_breach_alert_json"
      type: "json"
      unit: "array"
      aliases: ["stopBreachAlertJson"]
      note: "P1: 종목별 손절가 이탈 경보 상태·gap_pct 배열"

    gap_pct:
      canonical_name: "gap_pct"
      type: "number"
      unit: "pct"
      aliases: ["gapPct"]
      note: "P1: (close - stop_price) / stop_price × 100. 양수=여유, 음수=이탈"

    tp_trigger_gate:
      canonical_name: "tp_trigger_gate"
      type: "string"
      unit: "enum"
      aliases: ["tpTriggerGate"]
      note: "P2_TP_TRIGGER_ALERT_V1 — TRIGGERED/PASS"

    tp_trigger_alert_json:
      canonical_name: "tp_trigger_alert_json"
      type: "json"
      unit: "array"
      aliases: ["tpTriggerAlertJson"]
      note: "P2: 익절가 도달 종목·tp_qty 연계 배열"

    heat_concentration_gate:
      canonical_name: "heat_concentration_gate"
      type: "string"
      unit: "enum"
      aliases: ["heatConcentrationGate"]
      note: "P3_HEAT_CONCENTRATION_ALERT_V1 — HEAT_CONCENTRATED/PASS/INSUFFICIENT_DATA"

    heat_concentration_json:
      canonical_name: "heat_concentration_json"
      type: "json"
      unit: "array"
      aliases: ["heatConcentrationJson"]
      note: "P3: 종목별 heat_krw·heat_share_pct 배열"

    heat_share_pct:
      canonical_name: "heat_share_pct"
      type: "number"
      unit: "pct"
      aliases: ["heatSharePct"]
      note: "P3: 해당 종목 Heat / totalHeatKrw × 100"

    regime_transition_type:
      canonical_name: "regime_transition_type"
      type: "string"
      unit: "enum"
      aliases: ["regimeTransitionType"]
      note: "P4_REGIME_TRANSITION_ALERT_V1 — UPGRADE/DOWNGRADE/LATERAL_SHIFT/NO_CHANGE"

    regime_transition_json:
      canonical_name: "regime_transition_json"
      type: "json"
      unit: "object"
      aliases: ["regimeTransitionJson"]
      note: "P4: 국면 전환 상세 (prev_regime, current_regime, affected_gates)"

    portfolio_health_label:
      canonical_name: "portfolio_health_label"
      type: "string"
      unit: "enum"
      aliases: ["portfolioHealthLabel"]
      note: "P5_PORTFOLIO_HEALTH_SCORE_V1 — HEALTHY/CAUTION/CRITICAL. 보고서 첫 줄 표시 의무"

    portfolio_health_score:
      canonical_name: "portfolio_health_score"
      type: "number"
      unit: "score_0_to_100"
      aliases: ["portfolioHealthScore"]
      note: "P5: 0~100 건전성 점수. max(0, 100-critical×30-caution×10)"

    portfolio_health_blocked_json:
      canonical_name: "portfolio_health_blocked_json"
      type: "json"
      unit: "array"
      aliases: ["portfolioHealthBlockedJson"]
      note: "P5: 활성화된 게이트별 severity(CRITICAL/CAUTION) 상세 배열"

    # ── [2026-05-21_CLA_HARNESS_V1] RS/Composite/RAG/SFG 판정 필드 ─────────────
    ss001_grade:
      canonical_name: "ss001_grade"
      type: "string"
      unit: "enum [A, B, C, D]"
      aliases: ["SS001_Grade", "ss001Grade"]
      note: "SS001_SCORE_V1 종합 등급. A=최우수, D=최하. composite_verdict 입력값."

    excess_ret_10d:
      canonical_name: "excess_ret_10d"
      type: "number"
      unit: "pct"
      aliases: ["Excess_Ret_10D", "excessRet10D"]
      note: "RS_VERDICT_V1: 종목 10일 수익률 − KOSPI 10일 수익률."

    rs_verdict:
      canonical_name: "rs_verdict"
      type: "string"
      unit: "enum [LEADER, MARKET, LAGGARD, BROKEN, UNKNOWN]"
      aliases: ["RS_Verdict", "rsVerdict"]
      note: "RS_VERDICT_V1 판정. COMPOSITE_VERDICT_V1 및 RAG_V1 선행 입력."

    composite_verdict:
      canonical_name: "composite_verdict"
      type: "string"
      unit: "enum [PRIME_CANDIDATE, WATCH_CANDIDATE, REDUCE_CANDIDATE, EXIT_REVIEW, CLOSE_POSITION]"
      aliases: ["Composite_Verdict", "compositeVerdict"]
      note: "COMPOSITE_VERDICT_V1: ss001_grade × rs_verdict 매트릭스 판정."

    rag_v1:
      canonical_name: "rag_v1"
      type: "string"
      unit: "enum [PASS, FAIL, EXEMPT]"
      aliases: ["RAG_Verdict", "ragV1"]
      note: "REPLACEMENT_ALPHA_GATE_V1: 위성 신규 BUY 알파 검증 결과. FAIL → HOLD 강제."

    sfg_v1:
      canonical_name: "sfg_v1"
      type: "string"
      unit: "enum [TRIGGERED, CLEAR]"
      aliases: ["SFG_V1", "sfgV1"]
      note: "SATELLITE_FAILURE_GATE_V1: 위성 집단 실패 게이트. TRIGGERED → 모든 위성 BUY 차단."

    stock_drawdown_from_high_pct:
      canonical_name: "stock_drawdown_from_high_pct"
      type: "number"
      unit: "pct"
      aliases: ["Stock_Drawdown_From_High_Pct", "stockDrawdownFromHighPct"]
      note: "BENCHMARK_RELATIVE_TIMESERIES_V1: 종목 52주/가용 고점 대비 낙폭."

    excess_drawdown_pctp:
      canonical_name: "excess_drawdown_pctp"
      type: "number"
      unit: "pct_points"
      aliases: ["Excess_Drawdown_PctP", "excessDrawdownPctp"]
      note: "BENCHMARK_RELATIVE_TIMESERIES_V1: 종목 낙폭 - KOSPI 낙폭. 양수=시장보다 더 빠짐."

    recovery_ratio_5d:
      canonical_name: "recovery_ratio_5d"
      type: "number"
      unit: "ratio"
      aliases: ["Recovery_Ratio_5D", "recoveryRatio5d"]
      note: "BENCHMARK_RELATIVE_TIMESERIES_V1: KOSPI 5D 양수 구간 회복률."

    recovery_ratio_20d:
      canonical_name: "recovery_ratio_20d"
      type: "number"
      unit: "ratio"
      aliases: ["Recovery_Ratio_20D", "recoveryRatio20d"]
      note: "BENCHMARK_RELATIVE_TIMESERIES_V1: KOSPI 20D 양수 구간 회복률."

    downside_beta:
      canonical_name: "downside_beta"
      type: "number"
      unit: "ratio"
      aliases: ["Downside_Beta", "downsideBeta"]
      note: "BENCHMARK_RELATIVE_TIMESERIES_V1: KOSPI 하락 구간 수익률 비율. 프록시 사용 시 brt_method에 표시."

    rs_line_20d_slope:
      canonical_name: "rs_line_20d_slope"
      type: "number"
      unit: "slope"
      aliases: ["RS_Line_20D_Slope", "rsLine20dSlope"]
      note: "BENCHMARK_RELATIVE_TIMESERIES_V1: 20D 상대강도선 기울기."

    rs_line_60d_slope:
      canonical_name: "rs_line_60d_slope"
      type: "number"
      unit: "slope"
      aliases: ["RS_Line_60D_Slope", "rsLine60dSlope"]
      note: "BENCHMARK_RELATIVE_TIMESERIES_V1: 60D 상대강도선 기울기."

    brt_verdict:
      canonical_name: "brt_verdict"
      type: "string"
      unit: "enum [LEADER, MARKET, LAGGARD, BROKEN, UNKNOWN]"
      aliases: ["BRT_Verdict", "brtVerdict"]
      note: "BENCHMARK_RELATIVE_TIMESERIES_V1 최종 판정. RS_VERDICT_V2 입력."

    brt_method:
      canonical_name: "brt_method"
      type: "string"
      unit: "text"
      aliases: ["BRT_Method", "brtMethod"]
      note: "BRT 산출 방식. 과거 시계열 부재 시 PROXY_FROM_RET20_RET60."

    rs_verdict_v1_raw:
      canonical_name: "rs_verdict_v1_raw"
      type: "string"
      unit: "enum [LEADER, MARKET, LAGGARD, BROKEN, UNKNOWN]"
      aliases: ["RS_Verdict_V1_Raw", "rsVerdictV1Raw"]
      note: "RS_VERDICT_V2 감사용 V1 원본."

    saqg_v1:
      canonical_name: "saqg_v1"
      type: "string"
      unit: "enum [ELIGIBLE, WATCHLIST_ONLY, EXCLUDED, EXEMPT]"
      aliases: ["SAQG_V1", "saqgV1"]
      note: "SATELLITE_ALPHA_QUALITY_GATE_V1: 위성 후보 품질 게이트."

    sapg_status:
      canonical_name: "sapg_status"
      type: "string"
      unit: "enum [PASS, SAPG_ALERT, SAPG_CRITICAL, INSUFFICIENT_DATA]"
      aliases: ["SAPG_Status", "sapgStatus"]
      note: "SATELLITE_AGGREGATE_PNL_GATE_V1: 위성 합산 손익 게이트."

    globalKospiRet5D_:
      canonical_name: "globalKospiRet5D_"
      type: "number"
      unit: "pct"
      aliases: ["KOSPI_Ret5D_PreRead"]
      note: "GAS preReads: KOSPI 5D 수익률."

    globalKospiRet20D_:
      canonical_name: "globalKospiRet20D_"
      type: "number"
      unit: "pct"
      aliases: ["KOSPI_Ret20D_PreRead"]
      note: "GAS preReads: KOSPI 20D 수익률."

    globalKospiRet60D_:
      canonical_name: "globalKospiRet60D_"
      type: "number"
      unit: "pct"
      aliases: ["KOSPI_Ret60D_PreRead"]
      note: "GAS preReads: KOSPI 60D 수익률."

    globalKospiDrawdown_:
      canonical_name: "globalKospiDrawdown_"
      type: "number"
      unit: "pct"
      aliases: ["KOSPI_Drawdown_PreRead"]
      note: "GAS preReads: KOSPI 가용 고점 대비 낙폭."

    profit_loss:
      canonical_name: "profit_loss"
      type: "number"
      unit: "KRW"
      aliases: ["unrealized_pnl_krw", "profit_loss_krw"]
      note: "account_snapshot 평가손익. SATELLITE_AGGREGATE_PNL_GATE_V1 입력."

    cash_creation_purpose_lock:
      canonical_name: "cash_creation_purpose_lock"
      type: "string"
      unit: "enum"
      aliases: ["Cash_Creation_Purpose_Lock"]
      note: "CASH_CREATION_PURPOSE_LOCK_V1 출력 상태."

    alpha_evaluation_window_json:
      canonical_name: "alpha_evaluation_window_json"
      type: "json"
      unit: "array"
      aliases: ["Alpha_Evaluation_Window_JSON"]
      note: "ALPHA_EVALUATION_WINDOW_V1 T+20/T+60 알파 평가 결과."

    t20_return_pct:
      canonical_name: "t20_return_pct"
      type: "number"
      unit: "pct"
      aliases: ["T20_Return_Pct"]
      note: "ALPHA_EVALUATION_WINDOW_V1 입력."

    t60_return_pct:
      canonical_name: "t60_return_pct"
      type: "number"
      unit: "pct"
      aliases: ["T60_Return_Pct"]
      note: "ALPHA_EVALUATION_WINDOW_V1 입력."

    benchmark_core_return_pct:
      canonical_name: "benchmark_core_return_pct"
      type: "number"
      unit: "pct"
      aliases: ["Benchmark_Core_Return_Pct"]
      note: "ALPHA_EVALUATION_WINDOW_V1 벤치마크 코어 수익률."

    # ── [2026-05-23_PROPOSAL46] 신규 하네스 입력 필드 ────────────────────────────

    volume_ratio_5d:
      canonical_name: "volume_ratio_5d"
      type: "number"
      unit: "ratio"
      aliases: ["Volume_Ratio_5D", "vol_ratio_5d"]
      note: "최근 당일 거래량 / 5일 평균 거래량. PREDICTIVE_ALPHA_ENGINE_V1 thesis 입력."

    distribution_signals_count:
      canonical_name: "distribution_signals_count"
      type: "number"
      unit: "float"
      aliases: ["weighted_sum", "Distribution_Signals_Count"]
      note: "DISTRIBUTION_SELL_DETECTOR_V1 가중합산 점수. ANTI_LATE_ENTRY_GATE_V2 GATE_3 입력."

    foreign_sell_consecutive_days:
      canonical_name: "foreign_sell_consecutive_days"
      type: "integer"
      unit: "days"
      aliases: ["foreign_consecutive_sell_days", "Foreign_Sell_Consecutive_Days"]
      note: "외국인 순매도 연속 일수. PREDICTIVE_ALPHA_ENGINE_V1 antithesis 및 MACRO_EVENT_SYNCHRONIZER_V1 입력."

    foreign_sell_krw_today:
      canonical_name: "foreign_sell_krw_today"
      type: "number"
      unit: "KRW"
      aliases: ["Foreign_Sell_KRW_Today"]
      note: "당일 외국인 순매도 금액(원). mega_sell_alert 판정 기준. macro 시트 _foreignFlow."

    days_since_entry:
      canonical_name: "days_since_entry"
      type: "integer"
      unit: "days"
      aliases: ["Days_Since_Entry"]
      note: "진입 후 경과 영업일 수. PREDICTIVE_ALPHA_ENGINE_V1 stale_position 판정 입력."

    fomc_days_remaining:
      canonical_name: "fomc_days_remaining"
      type: "integer"
      unit: "days"
      aliases: ["FOMC_Days_Remaining"]
      note: "다음 FOMC까지 남은 일수. settings 시트 event_calendar. MACRO_EVENT_SYNCHRONIZER_V1 입력."

    domestic_cpi:
      canonical_name: "domestic_cpi"
      type: "number"
      unit: "percent"
      aliases: ["Domestic_CPI", "cpi_yoy"]
      note: "국내 소비자물가지수 전년비(%). macro 시트. MACRO_EVENT_SYNCHRONIZER_V1 입력."

    vix:
      canonical_name: "vix"
      type: "number"
      unit: "index"
      aliases: ["VIX", "cboe_vix"]
      note: "CBOE VIX 공포지수. macro 시트 _vix. MACRO_EVENT_SYNCHRONIZER_V1 입력."

    us500_1w_change:
      canonical_name: "us500_1w_change"
      type: "number"
      unit: "percent"
      aliases: ["US500_1W_Change", "sp500_1w_change"]
      note: "S&P500 1주일 등락률(%). macro 시트 _us500Close. MACRO_EVENT_SYNCHRONIZER_V1 입력."

    base_qty:
      canonical_name: "base_qty"
      type: "integer"
      unit: "shares"
      aliases: ["Base_Qty", "base_sell_qty"]
      note: "SELL_QUANTITY_ALLOCATOR_V1 산출 기준 매도 수량. CASH_PRESERVATION_SELL_ENGINE_V2 입력."

normalization_rules:
  - id: "FIELD_ALIAS_CANONICALIZATION"
    rule: "모든 입력은 계산 전 canonical_name으로 변환한다."
  - id: "KRW_100M_TO_KRW"
    applies_to: ["avg_trade_value_5d"]
    condition: "source field suffix is _M or value labeled 억원"
    transform: "value * 100000000"
  - id: "FLOW_YN_TO_BOOLEAN"
    applies_to: ["flow_ok"]
    transform: "Y=true, N=false"
  - id: "SHARES_INTEGER"
    applies_to: ["quantity", "flow_rows"]
    transform: "must be integer; decimal shares are invalid except final floor in sizing"
