meta: title: "은퇴자산포트폴리오 — 포트폴리오 제약·계좌 라우팅 명세" parent_file: "RetirementAssetPortfolio.yaml" version: "2026-05-24-F4_portfolio_rules_proposal50" language: "ko-KR" timezone: "Asia/Seoul" role: "derived_adapter" purpose: > 계좌, 납입한도, 비중, 중복노출, 현금 룰을 별도 포트폴리오 규칙으로 제공한다. canonical 계산은 기존 risk/account 섹션을 참조하되, LLM 적용 순서를 고정한다. authority_rule: "이 파일은 포트폴리오 제약 적용 순서를 제공하는 adapter다. 수치 임계값 충돌 시 canonical_refs 대상 파일을 우선한다." portfolio_rules: priority: "risk_policy 다음, position_sizing 이전에 적용" canonical_refs: account_policy: "spec/01_objective_profile.yaml:account_policy" contribution_policy: "spec/01_objective_profile.yaml:user_profile.contribution_policy" exposure_framework: "spec/risk/portfolio_exposure.yaml:portfolio_exposure_framework" cash_floor: "spec/risk/portfolio_exposure.yaml:portfolio_exposure_framework.cash_floor" duplicate_exposure: "spec/risk/portfolio_exposure.yaml:portfolio_exposure_framework.duplicate_exposure_rule" target_allocation: "spec/risk/portfolio_exposure.yaml:portfolio_exposure_framework.target_allocation_structure" account_constraints: accounts_allowed: ["일반계좌", "ISA", "연금저축"] accounts_excluded: ["IRP"] contribution_limits: ISA: monthly_limit_krw: 2000000 rule: "월 납입 가능액과 기납입액 확인 전 추가 납입 가정 금지" pension: monthly_limit_krw: 500000 account_name: "연금저축" rule: "연금저축 납입 한도 확인 전 초과 납입 전제 금지" integer_quantity_only: true fractional_share_prohibited: true asset_location_rules: domestic_tactical_stock: preferred_account: "일반계좌" rationale: "전술 위성·단기매매는 세제보다 유동성과 실행 자유도가 우선" high_dividend_or_yield: preferred_accounts: ["ISA", "연금저축"] rationale: "세제 혜택과 과세 이연 우선" overseas_long_term_etf: preferred_accounts: ["연금저축", "ISA"] rationale: "장기투자·세제효율 우선" cash_or_short_duration: preferred_accounts: ["ISA", "연금저축", "일반계좌"] rationale: "cash_floor와 대기자금 성격에 따라 배치" exposure_limits: target_buckets: core: target_pct: 65 band: "60~72" canonical_ref: "spec/risk/portfolio_exposure.yaml:portfolio_exposure_framework.target_allocation_structure.buckets.core_bucket" tactical_satellite: target_pct: 20 band: "10~25" canonical_ref: "spec/risk/portfolio_exposure.yaml:portfolio_exposure_framework.target_allocation_structure.buckets.tactical_satellite_bucket" cash_fc: target_pct: 15 band: "10~22" canonical_ref: "spec/risk/portfolio_exposure.yaml:portfolio_exposure_framework.target_allocation_structure.buckets.cash_fc_bucket" single_satellite_max_pct: 7 duplicate_exposure_action_order: - "중복 섹터 ETF" - "20D 수급 이탈·20일선 하회 위성" - "동일 섹터 내 후순위" - "시장지배 코어 직접보유" # ── M5 V1.1 (proposal_50 2-4): 반도체 클러스터 강제 감축 (2026-05-24) ───────── sector_concentration: O2_semiconductor_cluster: cluster_limit_pct: 25 single_stock_limit_pct: 30 regime_limit_pct: EVENT_SHOCK: 20 RISK_OFF: 20 RISK_ON: 25 SECULAR_LEADER_RISK_ON: 35 CONCENTRATED_LEADER_ADVANCE: 60 mandatory_reduction_trigger: "cluster_pct > cluster_limit * 2.0" reduction_plan: "MANDATORY_REDUCTION_PLAN_V1" weekly_reduction_target: "ceil((cluster_pct - cluster_limit) / 4)" reduction_priority_order: 1: "rs_verdict=BROKEN 코어 클러스터 종목" 2: "KODEX반도체 등 ETF (세금·슬리피지 유리)" 3: "SK하이닉스 APEX_SUPER trailing_stop 발동 분" 4: "삼성전자 CLA_EXIT_CONFIRMED 이후" enforcement: - "cluster_limit은 market_regime_state 및 CLA 상태에 따라 20/25/35/60으로 상향 조정 가능" - "cluster_pct <= cluster_limit * 2.0이면 MANDATORY_REDUCTION 비활성 (추가 BUY만 금지)" - "mandatory_reduction=true이면 weekly_target 미만 매도 시 REDUCTION_BEHIND_SCHEDULE 경고" - "is_mandatory=true 상태에서 반도체 종목 신규 BUY/ADD_ON 절대 금지" cash_rules: cash_basis: "즉시 인출 가능한 현금성 자산 기준" buy_power_formula: "즉시현금 + D+2 추정현금성자산 - 예약된 주문금액" post_trade_check_required: true prohibition: - "D+2 추정현금을 cash_floor 충족 현금으로 오인 금지" - "post_trade_immediate_cash_ratio 미확인 상태에서 신규매수 확정 금지" portfolio_decision_gate: sequence: 1: "계좌 허용 여부 확인" 2: "납입 한도 및 현금 원천 확인" 3: "현재 보유/목표 비중/중복 노출 확인" 4: "cash_floor 및 post-trade cash 확인" 4_5: "[MRG001] 이격도 과열 체크 -- MEAN_REVERSION_GATE_V1: deviation_ratio >= 1.15 -> BUY_HARD_BLOCK" # [2026-05-19_ALPHA_SHIELD_V1] 5: "position_sizing으로 전달할 계좌별 최대 주문 예산 산출" pass_output: - "account" - "max_order_budget_krw" - "target_bucket" - "current_weight_pct" - "post_trade_cash_ratio" - "portfolio_constraint_status" fail_action: cash_floor_fail: "BUY_BLOCKED" duplicate_exposure_fail: "TRIM_OR_WAIT" account_limit_fail: "ROUTE_TO_OTHER_ACCOUNT_OR_WAIT" holdings_unknown: "NO_SELL_QUANTITY" executable_rules: field_dictionary_ref: "spec/12_field_dictionary.yaml:field_dictionary" formula_refs: cash_ratios: "spec/13_formula_registry.yaml:formula_registry.formulas.CASH_RATIOS_V1" portfolio_band_status: "spec/13_formula_registry.yaml:formula_registry.formulas.PORTFOLIO_BAND_STATUS_V1" mean_reversion_gate: "spec/13_formula_registry.yaml:formula_registry.formulas.MEAN_REVERSION_GATE_V1" # [2026-05-19_ALPHA_SHIELD_V1] rules: - id: "PG001_ACCOUNT_ALLOWED" input_field: "account_type" pass_if: "account_type in ['일반계좌', 'ISA', '연금저축']" fail_action: "ACCOUNT_NOT_ALLOWED" - id: "PG002_CONTRIBUTION_LIMIT" input_fields: ["account_type", "monthly_contribution_planned", "monthly_contribution_used"] pass_if: "account_type == '일반계좌' OR monthly_contribution_planned + monthly_contribution_used <= account_monthly_limit" fail_action: "ACCOUNT_LIMIT_FAIL" - id: "PG003_CASH_GATE" formula_ref: "CASH_RATIOS_V1" pass_if: "post_trade_immediate_cash_ratio >= min_cash_ratio" fail_action: "BUY_BLOCKED" - id: "MRG001_MEAN_REVERSION_GATE" # [2026-05-19_ALPHA_SHIELD_V1] X1 formula_ref: "MEAN_REVERSION_GATE_V1" pass_if: "deviation_ratio < 1.10" caution_if: "1.10 <= deviation_ratio < 1.15" fail_action: "BUY_HARD_BLOCK (deviation_ratio >= 1.15)" - id: "PG004_EXPOSURE_BUDGET_OUTPUT" formula_ref: "PORTFOLIO_BAND_STATUS_V1" output_fields: ["max_order_budget_krw", "target_bucket", "portfolio_constraint_status"] fail_action: "NO_POSITION_SIZING_INPUT" reporting_requirement: table_columns: - "계좌" - "목표버킷" - "현재비중(%)" - "목표밴드" - "중복노출상태" - "즉시현금비중(%)" - "매수가능현금" - "계좌한도상태" - "허용행동" prohibition: - "계좌 한도·현금·보유수량 미확인 상태에서 최종 주문수량 출력 금지" - "포트폴리오 제약 실패를 종목 점수로 상쇄 금지"