Files
QuantEngineByItz/spec/01_objective_profile.yaml
T
kjh2064 ee3e799de1 feat: 리밸런싱 엔진 V1 + GAS 버그 수정 (2026-06-13)
주요 변경:
- tools/build_rebalance_engine_v1.py: REBALANCE_ENGINE_V1 신규
  * account_snapshot 직접 합산(_build_snap_position_map) → 소수주 분리 행 병합
  * 레짐 소스 macro.REGIME_PRELIM 최우선 (GAS 와 동일)
- src/gas_adapter_parts/gdf_06_rebalance.gs: runRebalanceSheet_() 신규
  * Logger.log / getSpreadsheet_() 로 run_all 연동 수정
- src/gas_adapter_parts/gdc_01_fetch_fundamentals.gs
  * _mergePositionRecord_(): 소수주 중복 행 합산 신규
  * parseInt → parseFloat (qty, availQty)
- src/gas_adapter_parts/gdf_01_price_metrics.gs
  * 미보유 종목 SELL_READY → WATCH_EXIT_SIGNAL
- spec/41_release_dag.yaml: build_rebalance_sheet 노드 추가 (step_count 63)
- spec/51_formula_lifecycle_registry.yaml: REBALANCE_ENGINE_V1 등록

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 13:20:14 +09:00

442 lines
27 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
meta:
title: "은퇴자산포트폴리오 — 목표·계좌·사용자 제약 명세"
parent_file: "RetirementAssetPortfolio.yaml"
version: "2026-05-15-F1_modular"
language: "ko-KR"
timezone: "Asia/Seoul"
purpose: "메인 manifest에서 로드되는 구조화 규칙 명세 파일."
role:
identity: "한국시장 은퇴자산 포트폴리오 리스크 관리자"
style: "성장 목표를 추적하되 파산확률·최대손실·유동성 리스크를 우선 통제"
principles:
- "감정·뉴스편향·확증편향 배제"
- "데이터·확률·세후수익률·유동성·리스크 우선"
- "데이터 부족 시 추정 금지·보류·관찰"
- "매매 회전율 최소화: 단타 지양. 위성 평균 보유 목표 20~60거래일, 코어 60거래일 이상. 조기 청산은 손절·이상 급등 방어에만 한정. D+20 성과 미달 청산은 보유기간 목표 위반이 아니라 성과 기반 별도 규칙(time_based_realization)임."
objective:
target_asset_krw: 500000000
target_deadline: "2026-12-31"
basis: "세후·수수료 차감 후 원화 기준"
reality_grade:
aggressive: "월평균 필요수익률 > 5%"
high_risk: "월평균 필요수익률 > 8%"
unrealistic: "월평균 필요수익률 > 12% 또는 레버리지·신용·미수·집중투자 필요"
goal_reality_gate:
required_calculation: ["현재총자산", "연말까지 추가납입예정액", "필요순수익률", "필요월평균수익률", "최근 3개월 실현월수익률", "최대허용손실률"]
decision_rule:
achievable: "필요월수익률 <= 최근3개월평균 + 2%p 이고 예상MDD <= 허용MDD → 정상 공격모드"
stretch: "필요월수익률 5~8% → 위성 비중 허용, 단일종목 손실예산 1.0% 이내"
unrealistic: "필요월수익률 > 8% → 목표추격 매수 금지. 생존·손실복구·현금흐름 우선"
prohibition: "필요수익률이 높다는 이유로 risk_budget·sector_cap·cash_floor를 완화하지 않는다."
goal_orbit_check:
frequency: "매월 마지막 거래일"
calculations:
required_remaining_monthly_return: "(목표금액 / 현재자산) ^ (1 / 잔여월) - 1"
orbit_state: "goal_reality_gate.decision_rule 분류 적용"
output: ["orbit_state를 다음 플레이북 상단 1번 항목에 표시", "unrealistic 판정 시 신규 매수 전 경고 박스", "전월 대비 궤도 개선/악화 방향", "최근 3개월 실현 월수익률 이동평균 갱신"]
guardrail: "orbit_state=unrealistic이면 해당 월 A등급 신규매수 최대 1건 제한."
# [P_D / 2026-05-15] 목표 궤도 이탈 재조정 프로토콜 — unrealistic 연속 판정 시 "1건 제한"만으로는
# 행동재무학적 목표 추격 함정(목표 달성을 위한 risk_budget 완화 압박)을 차단하지 못하는 공백 해소.
revision_protocol:
trigger: "orbit_state=unrealistic이 2개월(8주) 연속 유지"
required_output_table:
columns: ["항목", "현재값", "목표값", "갭", "의사결정"]
rows:
- ["현재 총자산", "[실측]", "5억원", "[차이]", "자동계산"]
- ["필요 잔여월수익률", "[산출]", "실현3개월평균+3%p이내", "[초과여부]", "아래 규칙 적용"]
- ["대안 목표기한", "2026-12-31", "[수정안]", "[연장개월]", "사용자 선택"]
- ["대안 목표금액", "5억원", "[하향안]", "[차이]", "사용자 선택"]
decision_rule:
continue_current:
condition: "필요잔여월수익률 <= 실현3개월평균 + 3%p AND 최근 1개월 실현수익률 > 0"
action: "현재 목표 유지. risk_budget·cash_floor 현상 유지. 다음 월 재점검."
revise_target:
condition: "필요잔여월수익률 > 실현3개월평균 + 3%p OR 최근 1개월 실현수익률 <= 0"
action: >
목표기한 연장(예: 2027-06-30) 또는 목표금액 하향(예: 4억원) 중 하나를
사용자에게 제안하고 선택을 기다린다.
선택 전까지 orbit_state=unrealistic 규칙(A등급 1건 제한) 유지.
note: "제안은 LLM이 결정하지 않는다. 수치 산출 후 사용자 선택 대기."
prohibition:
- "revision_protocol 발동을 이유로 risk_budget·cash_floor·sector_cap 완화 금지"
- "unrealistic 추격 지속 시 레버리지·신용·미수·집중투자 허용 금지"
orbit_state_action_map: # [R2] orbit_state별 수치 행동 매핑 — 정성 서술을 실행 규칙으로 전환
achievable: # [proposal_46 / 2026-05-15] 수치 재조정 — 방어55:공격45 목표
required_monthly_return_range: "< 4%" # 하향 조정: 기존 < 5%
new_buy_limit: "A·B등급 주 최대 4건 (공격 슬롯 +1건 확대)"
risk_budget_multiplier: "1.1x (목표 궤도 정상 시 소폭 상향 허용)"
cash_floor: "portfolio_exposure_framework.normal 기준"
offensive_slot:
definition: "weekly_trade_count 내에서 A등급 주도주 탐색매수에 한해 별도 1건 추가 허용"
gate: "Total_Heat < 7% AND cash_floor 충족 AND orbit_state=achievable"
stretch: # [proposal_46 / 2026-05-15] 기존 5~8% → 4% 이상으로 하향
required_monthly_return_range: "4~8%"
new_buy_limit: "A등급만, 주 최대 3건 (기존 2건 → +1건)"
risk_budget_multiplier: "1.0x (위성 비중 허용)"
cash_floor: "portfolio_exposure_framework.normal 기준"
single_stock_loss_budget: "총자산의 1.0% 이내"
offensive_slot:
definition: "탐색매수(staged_entry_v2) 1건은 weekly_trade_count 별도 계좌"
gate: "Total_Heat < 7% AND cash_floor 충족"
unrealistic:
required_monthly_return_range: "> 8%"
new_buy_limit: "A등급 최대 1건/월 (secular_leader_quality_bypass 예외 시 최대 2건/월)"
risk_budget_multiplier: "0.5x — cascade_risk_budget bayesian_multiplier에 반영"
cash_floor: "portfolio_exposure_framework.risk_off 기준 이상 강제"
prohibition: "신규매수·레버리지·신용·미수·집중투자 금지. → master_prohibitions.P3 전역 적용"
# ── [2026-05-18_CONFLICT_RESOLUTION_V1] Quality-Based Goal Bypass ──────────
# 배경: unrealistic 상태에서 SECULAR_LEADER_RISK_ON 주도주 탑승 기회 원천 차단
# 문제를 해소. P3(risk_block 무력화)는 위반하지 않음:
# - 이 bypass는 '매수건수 한도'에만 적용 (cash_floor/heat/circuit_breaker 무관).
# - 삼성전자·SK하이닉스는 파산확률 최저의 시장지배 주도주 — 위성 투기와 다르다.
secular_leader_quality_bypass:
purpose: >
unrealistic 궤도에서도 시장 최상위 품질(CSCS>=90) 주도주에 한해
월 1건 슬롯을 추가 허용함으로써 수익 회복 기회를 보장한다.
P3(risk_block 무력화) 위반 없음: 매수건수 한도 조정이며 가드레일 해제가 아님.
activation_required_all:
- "orbit_state == unrealistic"
- "market_regime_state == SECULAR_LEADER_RISK_ON"
- "대상 종목: 삼성전자 OR SK하이닉스 (CSCS >= 90 필수 확인)"
- "Total_Heat < 7% (총 포트폴리오 리스크 여유 필수)"
- "cash_floor 충족 (post_trade_immediate_cash_ratio >= min_cash_ratio)"
- "anti_climax_buy_gate 통과 (기본 진입 게이트 면제 없음)"
allowed_action:
additional_slots: "+1건/월 (기존 unrealistic 1건/월 → 최대 2건/월)"
position_class: "core (코어 직접보유 한정. 위성·ETF 적용 금지)"
risk_budget: "0.5x 유지 (unrealistic 감액 비율 그대로 적용. 증액 없음)"
max_weight: "삼성전자+SK하이닉스 합산 한도 내 (special_exception 준수)"
hard_prohibitions:
- "CSCS 미확인 상태에서 이 bypass 적용 금지"
- "market_regime_state 미확인 상태에서 이 bypass 적용 금지"
- "cash_floor 미달 상태에서 이 bypass로 매수 강행 금지 (P3 위반)"
- "Total_Heat >= 7% 시 이 bypass 적용 금지"
- "위성·테마주·ETF에 이 bypass 적용 금지 — 삼성전자·SK하이닉스 직접보유만"
- "orbit_state=unrealistic 3개월 연속 → revision_protocol 우선 진행 후 bypass 적용"
output_requirement: >
bypass 발동 시 보고서에 [Quality Bypass 발동] 박스 출력:
"orbit=unrealistic + SECULAR_LEADER_RISK_ON → {종목명} +1슬롯 허용
조건: Total_Heat={X}%, cash_floor=충족, CSCS={Y}"
output_required:
- "매월 goal_orbit_check 출력 시 orbit_state_action_map 상태 테이블 병기 필수"
- "목표 재설정 없이 2개월 더 경과하면 신규 위성 매수 전면 보류 (코어 유지만)"
- "revision_protocol 산출표 없이 목표 수정 결정 금지"
# [proposal_20260518_SLP] 목표 보호 착륙 프로토콜 — Safe Landing Protocol
safe_landing_protocol:
purpose: "목표 자산 근접 시 추가 수익보다 자산 보호를 우선하여 '완주'를 보장한다."
trigger_90pct:
condition: "현재 총자산 >= 450,000,000 (목표 5억의 90%)"
actions:
- "mode: FINAL_APPROACH"
- "risk_budget_cap: 0.005 (기본 0.007에서 30% 감축)"
- "tactical_satellite_cap: 12% (기존 20~25%에서 대폭 축소)"
- "new_buy_limit: 주 최대 2건 (A등급만)"
trigger_95pct:
condition: "현재 총자산 >= 475,000,000 (목표 5억의 95%)"
actions:
- "mode: GOAL_LOCK"
- "new_buy: PROHIBITED (신규 탐색매수 전면 중단)"
- "exit_strategy: Trailing Stop 빡빡하게 상향 (ATR 1.5 -> 1.0)"
- "cash_floor: 30% 이상 강제"
prohibition:
- "목표 달성률 90% 초과 시 '기회비용'을 이유로 공격성 유지 금지"
- "GOAL_LOCK 상태에서 '마지막 한 종목' 식의 예외 매수 금지"
offensive_slot_count_formula: # [proposal_80 / 2026-05-15] 최종 주간 신규 매수 허용 건수 계산 공식
purpose: "orbit_state 기본값과 orbit_gap 조정 합산 후 weekly_trade_count 상한과 경합 시 최종값 결정"
base_counts:
achievable: 4
stretch: 3
unrealistic: 1
formula: "최종_허용_신규매수 = min(orbit_state_base + orbit_gap_adjustment, weekly_trade_count.hard_block)"
hard_block_cap: "weekly_trade_count.hard_block = 5 (절대 상한)"
unrealistic_exception: "unrealistic 상태 시 formula 무시. max 1건/월 고정 적용."
orbit_gap_adjustment_reference: "objective.orbit_monthly_tracker.adjustment_rules 참조"
output_requirement: "블록11A section_A에 [orbit_state base + gap조정 = 최종허용건수] 계산 과정 출력 필수"
example:
case_A: "achievable(base=4) + on_track(0) → min(4, 5) = 4건"
case_B: "stretch(base=3) + mild_behind(+1) → min(4, 5) = 4건"
case_C: "achievable(base=4) + ahead_of_target(-1) → min(3, 5) = 3건"
orbit_monthly_tracker: # [proposal_62 / 2026-05-15] 월간 목표 궤도 자동 조정
purpose: >
매월 말일(또는 주간 점검일) 목표 누적 수익률과 실제 누적 수익률의
갭(orbit_gap)을 계산해 다음 달 공격 슬롯 수·현금 하한을 자동 조정한다.
risk_block(P1~P5, unified_engine, cash_floor)은 어떤 경우에도 완화하지 않는다.
baseline_target:
monthly_required_return: "4.8~5.0% (3.55억 → 5억, 잔여기간 환산)"
note: >
매달 실제 달성 수익률이 누적되면 잔여 목표 수익률이 달라진다.
orbit_monthly_tracker는 이 잔여 목표를 매월 재계산한다.
orbit_gap_formula:
formula: >
orbit_gap(%) =
(목표_누적수익률_to_date) - (실제_누적수익률_to_date)
목표_누적수익률_to_date = ((5억 / 시작자산) ^ (경과월 / 잔여총월)) - 1
실제_누적수익률_to_date = (현재총자산 / 시작자산) - 1
note: "시작자산 = 각 년도 1월 기준 총자산. 경과월은 1월부터 현재까지 완성된 월 수."
adjustment_rules:
on_track:
condition: "-1%p <= orbit_gap <= +1%p"
action: "현행 offensive_slot_count 유지. 현금 하한 MRS 기준 그대로."
mild_behind:
condition: "orbit_gap > +1%p AND orbit_gap <= +3%p (목표 대비 소폭 뒤처짐)"
action:
offensive_slot_count: "+1건 확대 (최대 주 5건 이내)"
cash_floor_adjustment: "MRS 기반 target_cash_pct에서 -1%p (최저 5% 유지)"
prohibition:
- "risk_block 완화 금지"
- "anti_climax_buy_gate 임계치 완화 금지"
significantly_behind:
condition: "orbit_gap > +3%p (목표 대비 크게 뒤처짐)"
action:
offensive_slot_count: "+1건 추가 확대 (최대 주 6건 이내)"
cash_floor_adjustment: "MRS 기반 target_cash_pct에서 -2%p (최저 5% 유지)"
additional: >
daily_leader_scan C5 조건 완화 불가. 대신 Tier_1 섹터
(sector_priority_ranking 참조) 종목 탐색 주기를 매일 → 장중으로 단축.
prohibition:
- "risk_block 완화 금지 (P3 절대 준수)"
- "orbit_gap 만회 압박을 이유로 설거지 허용 금지"
- "orbit_gap > +5%p 시 sector_crash_intraday_protocol과 이 규칙 동시 적용 금지 (이미 tier_B 이상 발동 중이면 공격 슬롯 확대 중단)"
ahead_of_target:
condition: "orbit_gap < -2%p (목표보다 유의미하게 앞서 있음)"
action:
offensive_slot_count: "현행 유지 (추가 확대 금지)"
cash_floor_adjustment: "+1%p 상향 (방어 강화. 초과 수익 일부 방어)"
note: >
목표보다 앞서 있을 때 공격성을 높이는 것은 과욕이다.
초과 달성 기간에는 트레일링 관리에 집중한다.
monthly_review_checklist:
- "이번 달 실제 수익률(%) — 총자산 기준"
- "orbit_gap 계산값 (%p)"
- "적용 구간 판정 (on_track/mild_behind/significantly_behind/ahead)"
- "다음 달 offensive_slot_count"
- "다음 달 MRS 기반 현금 하한 조정값"
- "risk_block 충돌 여부 확인 (항상 '없음' 이어야 함)"
output_table:
columns:
- "측정월"
- "시작자산(원)"
- "현재자산(원)"
- "실제누적수익률(%)"
- "목표누적수익률(%)"
- "orbit_gap(%p)"
- "적용구간"
- "다음달슬롯수"
- "현금하한조정"
prohibition:
- "orbit_gap 수치를 계산 없이 '감' 또는 '대략'으로 표기 금지"
- "orbit_gap > +3%p 이유만으로 P3(risk_block 무력화) 위반 금지"
- "ahead_of_target 구간에서 공격 슬롯 자의적 확대 금지"
user_profile:
birth_year: 1976
retirement_goal: "2037년 만 60세"
accounts: ["일반계좌", "ISA", "연금저축"]
excluded: ["IRP"]
contribution_policy:
ISA: "월 200만원. 한도·기납입액·이월한도 확인 후 조정. 납입 당일 전액 일괄매수 금지."
pension: "월 50만원, 연 600만원 세액공제 한도 우선. 단기 테마 추격 금지."
contribution_timing_rule:
both_accounts: "매월 1~5 영업일 이내 납입. Risk-Off 또는 caution 이상이면 MMF·단기채 ETF 대기 후 집행."
ISA_investment: "납입 후 당주 수요일 정기점검에서 A등급 종목에 분산 집행. 납입 후 5거래일 내 완료."
pension_investment: "목표 ETF 비중 리밸런싱 차원 분산 집행. 지정가 주문 원칙."
input_required:
- 현재 총 투자자산
- 일반계좌/ISA/연금저축 잔고
- 보유종목·티커·수량·평단·평가금액·평가손익률
- 올해 ISA/연금저축 기납입액
- 현금성 대기자금
- 미체결 주문 여부
- quant_feed:
required_fields: ["섹터별 1M/3M 수익률 또는 상대강도", "외국인·기관 5D/20D 순매수", "거래대금 또는 거래대금 증가율", "종목별 20일 ATR 또는 최근 20거래일 OHLC", "컨센서스 상향/하향 근거"]
rule: "핵심 필드 미확인 시 A등급·즉시매수·정수수량·기대수익비 산출 금지. .js 파일 부재는 분석 중단 사유 아님."
account_policy:
taxable:
role: "공격형 수익 엔진"
assets: ["국내 실적 주도주", "섹터 대장주", "위성 고베타"]
holdings: "6~10개"
max_single: "일반 종목 18%; KOSPI 시장지배 주도주는 special_exception·market_context 우선"
ISA:
role: "절세형 중기 수익 엔진"
assets: ["국내상장 ETF", "국내주식", "국내상장 해외 ETF"]
tax: "손익통산·9.9% 분리과세 반영 (해외 ETF는 장기투자 우선)"
limit_rule: "법적 납입 한도(월 200만원, 이월 한도 포함) 체크 후 실행 자금 배정"
pension:
role: "세액공제와 장기복리"
assets: ["미국 대표지수", "나스닥", "반도체", "채권", "현금성 ETF"]
warning: "중도해지 기타소득세 리스크 명시. 연 세액공제 최적화 월 50만원 한도 우선."
execution_constraints:
- "IRP 계좌는 관리 대상에서 원천 제외."
- "모든 매수/매도 수량은 환헤지·거래 수수료 선차감 후 반드시 정수 단위(소수점 매수 불가)."
cost_parity_rule:
principle: "동일 종목이라도 계좌별 세금·비용 구조가 달라 실현 순수익이 다르다. 배치 계좌를 결정하기 전 세후 비교를 수행한다."
cost_reference:
일반계좌: "거래세 0.18%, 배당소득세 15.4%, 국내주식 양도세 면제"
ISA: "손익통산·비과세 200만원(서민형 400만원)/9.9% 분리과세, 거래세 0.18%, 납입한도 월 200만원"
연금저축: "세액공제(연 400만원 한도), 연금 수령 시 3.3~5.5%, 중도해지 기타소득세 16.5%"
routing_priority:
ISA_우선: ["배당수익률 > 2% 종목", "30거래일 이내 익절 계획 위성", "손익통산 효과로 세후 유리한 경우"]
일반계좌_우선: ["ISA 납입한도 소진 시", "장기보유 코어 (국내주식 양도세 면제 활용)", "ISA 내 동일 섹터 중복 시"]
연금저축_우선: ["해외 대표지수 ETF (세액공제 + 장기복리 최적화)"]
hard_rule:
- "ISA 납입한도(월 200만원, 이월 포함) 미확인 상태에서 ISA 매수 수량 산출 금지"
- "세후 수익 비교 없이 계좌 선택 후 '유리하다'는 표현 사용 금지"
- "동일 종목을 복수 계좌에 동시 보유할 경우 합산 비중으로 집중도 한도 계산"
xref: "익절·손절 시 계좌별 세금 우선순위 → take_profit.account_tax_optimization 참조"
position_count_limit:
id: "PCL_POSITION_COUNT_LIMIT"
purpose: >
개인 투자자가 소화·모니터링할 수 있는 종목 수를 계좌별로 하드 제한한다.
계좌 성격이 다르므로 통합 합산 제한은 두지 않는다.
연금저축은 ETF 전용 계좌로 개별주 카운트 대상에서 제외한다.
ETF(국내외 상장 ETF, MMF, 단기채)는 모든 계좌에서 카운트 제외.
counting_scope:
include: "개별주 직접 보유 (코어 + 위성)"
exclude: ["ETF", "국내상장 해외ETF", "MMF", "RP", "단기채 ETF", "현금성 상품"]
pension_rule: "연금저축은 ETF 전용 계좌. 개별주 카운트 대상 아님 — 별도 관리."
account_limits:
taxable:
core_max: 4
satellite_max: 6
total_max: 10
hard_block: "taxable_individual_count >= 10 → ROTATE_REQUIRED (일반계좌)"
caution: "taxable_individual_count == 9 → CAUTION_FLAG (일반계좌)"
note: "기존 account_policy.taxable.holdings '6~10개' 상단을 하드 상한(10개)으로 사용"
ISA:
total_max: 4
hard_block: "isa_individual_count >= 4 → ROTATE_REQUIRED (ISA)"
caution: "isa_individual_count == 3 → CAUTION_FLAG (ISA)"
note: "ETF 별도. ISA 개별주는 손익통산 목적 중기 보유 위주."
pension:
individual_stock_max: 0
note: >
ETF 전용 계좌 (미국 대표지수·나스닥·반도체·채권 ETF).
개별주 진입 금지. 카운트 집계 대상 아님.
settings_override:
source: "data.settings (settings 시트)"
keys:
- "position_count_max_normal (일반국면 상한)"
- "position_count_max_risk_off 또는 position_count_max_risk (리스크국면 상한)"
default_policy: "설정값 미존재 시 기본값 사용(일반국면 10, 리스크국면 6)"
rotation_priority_when_full:
purpose: "계좌별 한도 도달 시 교체 후보 선정 기준"
priority_order:
1: "financial_health_score 최저 종목 (재무 부실 우선 정리)"
2: "relative_weakness_exit (RW) 점수 가장 높은 종목"
3: "위성 버킷 내 보유 기간 가장 긴 성과 미달 종목"
prohibition:
- "코어 주도주(삼성전자·SK하이닉스)를 단순 '자리 비우기' 목적으로 교체 금지"
- "rotation_priority를 이유로 손절라인 미도달 종목 강제 매도 금지"
executable_rules:
- id: "PCL001_TAXABLE_HARD_BLOCK"
input_field: "taxable_individual_count"
rules:
- {if: "taxable_individual_count >= 10", action: "ROTATE_REQUIRED", account: "일반계좌"}
- {if: "taxable_individual_count == 9", action: "CAUTION_FLAG", account: "일반계좌"}
- {if: "taxable_individual_count <= 8", action: "COUNT_GATE_PASS", account: "일반계좌"}
- id: "PCL002_ISA_HARD_BLOCK"
input_field: "isa_individual_count"
rules:
- {if: "isa_individual_count >= 4", action: "ROTATE_REQUIRED", account: "ISA"}
- {if: "isa_individual_count == 3", action: "CAUTION_FLAG", account: "ISA"}
- {if: "isa_individual_count <= 2", action: "COUNT_GATE_PASS", account: "ISA"}
- id: "PCL003_SATELLITE_ROTATION_REVIEW"
condition: "satellite_count >= 3 AND new_buy_target_bucket == satellite"
action: "SATELLITE_ROTATION_REVIEW"
output: >
위성 3종목 이상 보유 중 추가 위성 진입 검토 시
financial_health_score 가장 낮은 기존 위성 종목을 교체 후보로 우선 표시.
output_field: "position_count_status"
xref: "spec/risk/portfolio_exposure.yaml:portfolio_exposure_framework.position_count_limit"
investment_horizon_policy:
id: "IHP_INVESTMENT_HORIZON"
purpose: >
중장기 추세 추종을 기본 전략으로 고정하고,
단기 전술 포지션은 엄격한 조건이 충족될 때만 예외적으로 허용한다.
투자 전략은 보유 기간 목표와 익절 방식에 직접 연결된다.
default_mode:
name: "MEDIUM_LONG_TERM"
label: "중장기 추세 추종 (기본값)"
description: >
시장 주도 추세를 확인 후 진입. 충분한 이익이 쌓일 때까지 보유.
변동성 노이즈에 흔들리지 않고 추세가 훼손될 때 청산.
core_holding_target: "60거래일 이상"
satellite_holding_target: "20~60거래일"
entry_method: "staged_entry_v2 (탐색→확인→주력 분할 진입)"
exit_method: "take_profit_ladder_V2 (ATR 사다리 1/3 단계적 익절)"
stop_loss: "ATR × 1.5 (중장기 노이즈 허용)"
re_entry_rule: "추세 재확인 후 재진입 허용. 단, 손절 후 즉일 재진입 금지."
short_term_tactical:
name: "SHORT_TERM_TACTICAL"
label: "단기 전술 (예외적·조건부)"
description: >
중장기 원칙의 예외. 고확신도 돌파 국면에서만 제한적 허용.
위성 버킷 전용. 코어 종목 단기매매 절대 금지.
required_conditions_all:
- "orbit_state == achievable"
- "market_regime IN [RISK_ON, SECULAR_LEADER_RISK_ON]"
- "Total_Heat < 5%"
- "grade == A AND financial_health_score >= 12"
- "satellite 버킷 내 잔여 슬롯 존재 (PCL 통과)"
constraints:
max_holding_days: 10
max_concurrent_positions: 1
profit_target: "+5% 이상 또는 D+10 gate 도달 시 검토"
stop_loss: "ATR × 1.0 (중장기보다 타이트)"
exit_method: "D+10 강제 검토 → 목표 미달 시 TRIM 또는 CLOSE"
prohibition:
- "코어 종목(삼성전자·SK하이닉스 등 CSCS >= 70)에 단기 전술 적용 금지"
- "중장기 보유 중 '단기로 변경' 허용 금지 — 전략 변심은 전략 일관성 훼손"
- "단기 전술 포지션이 이미 1건 있을 때 추가 단기 포지션 금지"
- "재무 건전성 미달(financial_health_score < 12) 종목 단기 전술 허용 금지"
horizon_enforcement:
tracker_field: "position_mode"
values: ["MEDIUM_LONG_TERM", "SHORT_TERM_TACTICAL"]
default_value: "MEDIUM_LONG_TERM"
override_condition: "short_term_tactical.required_conditions_all 전부 충족"
audit_rule: "매주 수요일 정기점검 시 position_mode 불일치 종목 플래그"
xref:
- "spec/exit/take_profit.yaml:take_profit_rules.time_based_realization.satellite_time_return_gate"
- "spec/exit/stop_loss.yaml:stop_loss_rules.RW2b_5d_rapid_weakness"
- "spec/01_objective_profile.yaml:position_count_limit"
asset_location_matrix:
priority_rule: "Tax Drag가 큰 자산일수록 절세 계좌에 우선 배치."
routing:
high_dividend_or_yield: {examples: ["배당주", "리츠", "채권ETF", "월배당ETF"], priority: ["ISA", "연금저축"]}
overseas_growth_ETF: {examples: ["S&P500 ETF", "Nasdaq100 ETF", "글로벌 반도체 ETF"], priority: ["연금저축", "ISA"]}
domestic_growth_stock: {examples: ["국내 개별 성장주", "국내 주도주"], priority: ["일반계좌"]}
high_turnover_tactical:
examples: ["전술 위성(단기보유)", "위성 고베타"]
priority: ["일반계좌"]
routing_note: "세제 최적 계좌 routing 지침. role.principles 4번(단타 지양) 준수 — 위성도 평균 20거래일 이상 보유 목표."
cash_management:
depositor_protection_limit_krw: 100000000
operating_cap_per_institution_krw: 90000000
rule: "현금성 자산 1억 초과 시 동일 금융회사 단일 예치 금지. Risk-Off 25% 적용 시 기관별 예치 한도표 출력."
not_same_as_protected: ["MMF", "RP", "채권형 ETF", "단기채 ETF", "비보호 CMA"]
guardrails:
- "세법·계좌 한도·기납입액 미확인 시 세후 최적화 수치 산출 금지."
- "현금성 상품은 예금자보호 여부 확인 전까지 무위험자산으로 표시 금지."
hedge_policy:
USDKRW:
below_1300: "환노출 확대"
1300_1370: "H/UH 혼합"
1370_1400: "환헤지 50~70%"
above_1400: "환헤지 70~90%, 신규 환노출 축소"
above_1450: "해외위험자산 신규 보류 또는 H클래스 우선"