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>
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
# Strategy Spec Split Plan
|
||||
|
||||
`spec/04_strategy_rules.yaml` is now a compatibility index.
|
||||
The canonical strategy rules are the split files in this directory.
|
||||
|
||||
Canonical split files:
|
||||
|
||||
- `sector_model.yaml`: sector score, grade alias, CSCS
|
||||
- `entry_core.yaml`: regime entry policy, minimalist gate, expected edge
|
||||
- `leader_scan.yaml`: daily leader scan, anti-climax gate
|
||||
- `staged_entry.yaml`: staged entry v2, pullback reentry
|
||||
- `discovery.yaml`: anti-late-trade rule and discovery workflow
|
||||
- `entry_gates.yaml`: compatibility index only
|
||||
- `stock_model.yaml`: stock model and satellite classification rules
|
||||
- `rebalancing_trigger.yaml`: rebalancing trigger rules
|
||||
|
||||
Migration rule:
|
||||
|
||||
- Do not duplicate thresholds without `canonical_ref`.
|
||||
- Keep old paths valid through `spec/04_strategy_rules.yaml.legacy_path_aliases`.
|
||||
- `spec/09_decision_flow.yaml` controls execution order; strategy split files only define domain logic.
|
||||
@@ -0,0 +1,173 @@
|
||||
meta:
|
||||
title: "은퇴자산포트폴리오 — Final_Action 결정 매트릭스"
|
||||
version: "2026-05-17-action_matrix_v1"
|
||||
language: "ko-KR"
|
||||
role: "canonical"
|
||||
purpose: >
|
||||
gas_data_feed.gs의 Allowed_Action(매수 게이트) + calcSellDecision_(매도) +
|
||||
calcFinalDecision_(통합)이 어떤 조건에서 어떤 Final_Action을 출력하는지
|
||||
단일 진실 소스로 문서화한다.
|
||||
"왜 지금 매수/매도인가"의 패턴을 Action_Reason 컬럼과 함께 읽으면 된다.
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# canonical_fields
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
canonical_fields:
|
||||
Final_Action:
|
||||
role: "외부 소비 canonical field — getDailyBrief, API, ChatGPT 모두 이 값을 참조"
|
||||
allowed_values:
|
||||
SELL_READY: "Sell_Validation=PASS — 즉시 HTS 주문 가능"
|
||||
SELL_CHECK_QTY: "Sell_Action 있으나 보유수량 미확인 — 사용자가 확인 후 주문"
|
||||
EXIT_SIGNAL: "Allowed_Action=EXIT_SIGNAL (RW>=3 또는 STOP_OR_TIME_EXIT_READY)"
|
||||
EXIT_REVIEW: "Allowed_Action=REVIEW_EXIT (RW=2 또는 EXIT_REVIEW)"
|
||||
BUY_STAGE1_READY: "SS001_Grade A + Entry_Mode_Gate=PASS + Timing=BUY_STAGE1_READY"
|
||||
BUY_BREAKOUT_PILOT_ONLY: "SS001_Grade A + 돌파 파일럿 진입 조건 충족"
|
||||
BUY_PULLBACK_WAIT: "SS001_Grade A/B + 눌림목 대기 (진입 타이밍 준비)"
|
||||
WATCH_TIMING_SETUP: "SS001_Grade A/B이지만 타이밍 미충족 — Allowed_Action=WATCH_CANDIDATE"
|
||||
NO_BUY_OVERHEATED: "과열 지표 발동 (AC_Gate=BLOCK 또는 Val_Surge 과도)"
|
||||
HOLD: "그 외 전체 — Allowed_Action(NO_ADD/HOLD/HOLD_NO_ADD/OBSERVE_ONLY)으로 세분"
|
||||
|
||||
Action_Params:
|
||||
role: "실행 파라미터 압축 — 외부 소비자(getDailyBrief·API·ChatGPT)가 즉시 사용 가능한 실행 정보"
|
||||
format:
|
||||
SELL_READY: "{ratio}% {qty}주 @{price}원 | {executionWindow} | {orderType}"
|
||||
SELL_CHECK_QTY: "{sellAction} | 보유수량 미확인"
|
||||
EXIT_SIGNAL/EXIT_REVIEW: "보유수량 미확인 — HTS 확인 필요"
|
||||
BUY_*: "목표 {posSizeQty}주 | 손절 {stopPriceEst}원 | TP1 {tp1Price}원({tp1Qty}주)"
|
||||
WATCH_TIMING_SETUP: "대기 — {timingBlockReason}"
|
||||
HOLD/etc: "" # 빈 문자열
|
||||
|
||||
Action_Reason:
|
||||
role: "왜 이 Final_Action인가를 한 문자열로 요약 — 사람이 읽는 컬럼"
|
||||
format:
|
||||
SELL_READY: "{sellDetailLabel} {qty}주 @{limitPrice}원 [{sellReason}]"
|
||||
EXIT_SIGNAL/EXIT_REVIEW: "RW{n}({RW1+RW2...}) {exitSignalDetail}"
|
||||
BUY_*: "SS001:{grade}{normScore}점 RSI{rsi} 이격{disp}% FC{fc}"
|
||||
WATCH_TIMING_SETUP: "SS001:{grade}{normScore}점 타이밍미충족({timingBlockReason})"
|
||||
HOLD: "HeatBlock({heatPct}%) | {regime} | SS001:{grade}"
|
||||
NO_ADD: "수급이탈 | 거래대금{억}억 | 스프레드{pct}% | {regime}"
|
||||
HOLD_NO_ADD: "DART:{risk} | 과열({acGate})"
|
||||
OBSERVE_ONLY: "PRICE_MISSING({priceStatus})"
|
||||
|
||||
Allowed_Action:
|
||||
role: "내부 계산 중간값 — 매수 게이트 판정. 외부 소비 시 Final_Action 우선."
|
||||
allowed_values:
|
||||
OBSERVE_ONLY: "가격 데이터 없음 — 모든 계산 불가"
|
||||
HOLD: "HF005 BLOCK, 레짐 차단, 또는 SS001_Grade C"
|
||||
NO_ADD: "수급이탈 / 거래대금 부족 / 스프레드 과도 / 레짐 차단(미보유)"
|
||||
HOLD_NO_ADD: "DART 리스크 또는 과열 게이트"
|
||||
EXIT_SIGNAL: "RW_Partial >= 3 또는 Timing_Action=STOP_OR_TIME_EXIT_READY"
|
||||
REVIEW_EXIT: "RW_Partial >= 2 또는 Timing_Action=EXIT_REVIEW"
|
||||
WATCH_CANDIDATE: "SS001_Grade A/B이지만 타이밍 미충족"
|
||||
BUY_STAGE1_READY: "SS001_Grade A + 타이밍 충족"
|
||||
BUY_BREAKOUT_PILOT_ONLY: "SS001_Grade A + 돌파 파일럿"
|
||||
BUY_PULLBACK_WAIT: "SS001_Grade A/B + 눌림목 대기"
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# 매수 패턴 매트릭스
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
buy_action_matrix:
|
||||
purpose: "SS001_Grade × Timing_Action × 제약 → Final_Action 결정 규칙"
|
||||
|
||||
BUY_STAGE1_READY:
|
||||
required_all:
|
||||
- SS001_Grade: "A"
|
||||
- Timing_Action: "BUY_STAGE1_READY"
|
||||
- Entry_Mode_Gate: "PASS"
|
||||
blocked_if_any:
|
||||
- heatBlock: true # globalHeatPct >= 10%
|
||||
- isRiskOffRegime: true # RISK_OFF or RISK_OFF_CANDIDATE
|
||||
- dartRisk: true
|
||||
- liquidityFail: true # flow.ok=F or avgTV5D<50 or spread>0.8%
|
||||
caution_if:
|
||||
- heatCaution: true # 7~10% → Pos_Size_Qty × 0.5 & Action_Reason에 표기
|
||||
action_reason_template: "SS001:A{score}점 RSI{rsi} 이격{disp}% FC{fc}"
|
||||
|
||||
BUY_BREAKOUT_PILOT_ONLY:
|
||||
required_all:
|
||||
- SS001_Grade: "A"
|
||||
- Timing_Action: "BUY_BREAKOUT_PILOT_ONLY"
|
||||
- Entry_Mode_Gate: "PASS"
|
||||
blocked_if_any: [heatBlock, isRiskOffRegime, dartRisk, liquidityFail]
|
||||
note: "돌파 파일럿 — 전체 수량의 30~50%만 진입. Entry_Mode=BREAKOUT."
|
||||
|
||||
BUY_PULLBACK_WAIT:
|
||||
required_any:
|
||||
- {SS001_Grade: "A", Timing_Action: "BUY_PULLBACK_WAIT"}
|
||||
- {SS001_Grade: "B", Timing_Action: "BUY_PULLBACK_WAIT"}
|
||||
blocked_if_any: [heatBlock, isRiskOffRegime, dartRisk, liquidityFail]
|
||||
note: "눌림목 대기 — 진입 타이밍 준비 중. 지정가 주문 미리 설정 권장."
|
||||
|
||||
WATCH_TIMING_SETUP:
|
||||
required_all:
|
||||
- SS001_Grade: ["A", "B"]
|
||||
timing_condition: "Timing_Action not in [BUY_STAGE1_READY, BUY_BREAKOUT_PILOT_ONLY, BUY_PULLBACK_WAIT]"
|
||||
note: "등급은 되지만 타이밍 미충족. Action_Reason에 구체적 미충족 이유 표기."
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# 매도 패턴 매트릭스
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
sell_action_matrix:
|
||||
purpose: "매도 신호 발생 시 Final_Action 결정 규칙. spec/exit/stop_loss.yaml sell_signal_priority와 연동."
|
||||
|
||||
SELL_READY:
|
||||
trigger: "calcSellDecision_()의 Sell_Validation = PASS"
|
||||
substates:
|
||||
EXIT_100: "손절전량 — STOP_OR_TIME_EXIT_READY 또는 RW_Partial >= 4"
|
||||
REGIME_TRIM_50: "레짐 50% 축소 — getDailyBrief 포트폴리오 경고로 이동 (방향 A: 개별 종목 신호 아님)"
|
||||
TRIM_70: "RW청산 70% — RW_Partial >= 3 또는 Timing_Exit_Score >= 75"
|
||||
TRAILING_STOP_BREACH: "트레일링이탈 70% — close <= trailing_stop_price 직접 체크"
|
||||
TRIM_50: "RW부분 50% — RW_Partial >= 2 OR (RW_Partial >= 1 AND Timing_Exit_Score >= 50). RW_Partial=0 단독 기술지표로는 TRIM_50 불가."
|
||||
PROFIT_TRIM_50/35/25: "익절 사다리 — Profit_Pct >= 50/30/20"
|
||||
TAKE_PROFIT_TIER1: "TP1 익절 25% — Profit_Pct >= 10"
|
||||
TIME_EXIT_100: "타임스탑 전량 — Days_To_Time_Stop <= 0 (spec priority 6)"
|
||||
TIME_TRIM_50: "타임스탑 50% — Days_To_Time_Stop <= 7 (spec priority 6)"
|
||||
canonical_price_field: Sell_Limit_Price
|
||||
canonical_qty_field: Sell_Qty
|
||||
action_reason_template: "{label} {qty}주 @{price}원 [{reason}]"
|
||||
note: >
|
||||
복수 조건 동시 발동 시 SL003_PRIORITY_MATRIX 적용:
|
||||
Sell_Limit_Price = max(모든 발동 조건의 후보가격). priceSource=PRIORITY_MATRIX_MAX.
|
||||
|
||||
EXIT_SIGNAL:
|
||||
trigger: "Sell_Validation != PASS AND (RW_Partial >= 3 OR Timing_Action=STOP_OR_TIME_EXIT_READY)"
|
||||
action_reason_template: "RW{n}({items}) {exitSignalDetail}"
|
||||
note: "보유수량 미확인 상태. 사용자가 HTS에서 보유수량 확인 후 주문."
|
||||
|
||||
EXIT_REVIEW:
|
||||
trigger: "RW_Partial >= 2 OR Timing_Action=EXIT_REVIEW"
|
||||
action_reason_template: "RW{n}({items}) 검토"
|
||||
note: "매도 검토 단계. 다음 영업일 재확인 권장."
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Action_Priority 우선순위 숫자 (calcFinalDecision_ 기준)
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
action_priority_table:
|
||||
10: SELL_READY
|
||||
20: SELL_CHECK_QTY
|
||||
28: EXIT_SIGNAL
|
||||
32: EXIT_REVIEW
|
||||
50: NO_BUY_OVERHEATED
|
||||
60: BUY_STAGE1_READY
|
||||
70: BUY_BREAKOUT_PILOT_ONLY
|
||||
80: BUY_PULLBACK_WAIT
|
||||
90: WATCH_TIMING_SETUP
|
||||
99: HOLD
|
||||
note: "낮을수록 우선순위 높음. Final_Rank는 Priority_Score 기준 내림차순 정렬 후 부여."
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# 브리핑 출력 형식 (getDailyBrief — C-1 재구조화)
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
brief_format:
|
||||
canonical_source: "Final_Action (not Allowed_Action)"
|
||||
sort_within_group: "Final_Rank 오름차순 (Priority_Score 기반)"
|
||||
sections_order:
|
||||
1: "SELL_READY — 즉시 HTS 주문 가능"
|
||||
2: "EXIT_SIGNAL / EXIT_REVIEW — 보유수량 확인 후 매도"
|
||||
3: "BUY — 진입 조건 충족 (BUY_STAGE1_READY / BUY_BREAKOUT_PILOT_ONLY / BUY_PULLBACK_WAIT)"
|
||||
4: "WATCH — 타이밍 대기 (WATCH_TIMING_SETUP)"
|
||||
5: "HOLD / BLOCK — Allowed_Action으로 세분 표시"
|
||||
dedup_rule: >
|
||||
같은 종목이 SELL_READY이면서 EXIT_SIGNAL도 발생할 수 있다.
|
||||
Final_Action=SELL_READY가 최우선 — SELL_READY 섹션에만 출력.
|
||||
action_reason_display: "각 종목 한 줄에 Action_Reason 출력 → '왜'를 즉시 파악 가능"
|
||||
@@ -0,0 +1,54 @@
|
||||
schema_version: 2026-06-03-anti-late-entry-pullback-gate-v4
|
||||
formula_id: ANTI_LATE_ENTRY_GATE_V2_CALIBRATED
|
||||
purpose: 뒷박(late-chase) 매수 차단 — T+5 실측 기반 보정 루프.
|
||||
required_fields:
|
||||
- prediction_match_rate_pct
|
||||
- t5_direction_accuracy_pct
|
||||
- buy_after_5d_runup_without_pullback_count
|
||||
|
||||
# ── velocity 버킷 기반 실측 보정 (SCAFFOLDED_PENDING_LIVE_DATA) ─────────────
|
||||
# [SCAFFOLDED_PENDING_LIVE_DATA: late_chase_attribution_samples=0, target>=30]
|
||||
calibration:
|
||||
formula_id: ANTI_LATE_ENTRY_GATE_V2_CALIBRATED
|
||||
status: SCAFFOLDED_PENDING_LIVE_DATA
|
||||
current_samples: 0
|
||||
target_samples: 30
|
||||
velocity_buckets:
|
||||
- id: LOW
|
||||
range: "velocity_1d < 1.0%"
|
||||
t5_win_rate: null
|
||||
t5_avg_return: null
|
||||
sample_count: 0
|
||||
label: "[UNVALIDATED_LIVE: n=0]"
|
||||
- id: MID
|
||||
range: "1.0% <= velocity_1d < 3.0%"
|
||||
t5_win_rate: null
|
||||
t5_avg_return: null
|
||||
sample_count: 0
|
||||
label: "[UNVALIDATED_LIVE: n=0]"
|
||||
- id: HIGH
|
||||
range: "velocity_1d >= 3.0%"
|
||||
t5_win_rate: null
|
||||
t5_avg_return: null
|
||||
sample_count: 0
|
||||
label: "[UNVALIDATED_LIVE: n=0]"
|
||||
gate: GATE1_BLOCK
|
||||
gate_basis: EXPERT_PRIOR
|
||||
gate_threshold:
|
||||
velocity_1d_block_pct: 3.0
|
||||
threshold_source: EXPERT_PRIOR
|
||||
threshold_note: "[UNVALIDATED: 실측 표본 30건 누적 전까지 EXPERT_PRIOR(3%) 유지]"
|
||||
calibration_allowed: false # 표본 < 30 → 자동 적용 금지, 데이터 충족 후 수동 적용
|
||||
chase_entry_rate:
|
||||
formula: "(velocity_1d>=3% 진입건 / 전체 BUY)"
|
||||
current: null
|
||||
target: "<= 10%"
|
||||
label: "[UNVALIDATED_LIVE: n=0]"
|
||||
output:
|
||||
- late_chase_attribution_v4.json.samples
|
||||
- operational_report.json.summary.chase_entry_rate_pct
|
||||
python_tools:
|
||||
- tools/build_late_chase_attribution_v1.py
|
||||
- tools/build_alpha_lead_threshold_optimizer_v3.py
|
||||
gs_coverage: "gas_apex_alpha_watch.gs:calibrateAntiLateEntryV2_()"
|
||||
validator: "tools/validate_no_late_chase_buy_v2.py"
|
||||
@@ -0,0 +1,4 @@
|
||||
schema_version: anti_late_entry_pullback_gate.v5
|
||||
parent_file: spec/strategy/anti_late_entry_pullback_gate_v4.yaml
|
||||
formula_id: ANTI_LATE_ENTRY_PULLBACK_GATE_V5
|
||||
purpose: Pre-trade late-chase and pullback quality gate.
|
||||
@@ -0,0 +1,74 @@
|
||||
meta:
|
||||
title: "은퇴자산포트폴리오 — 후보 발굴·지연매매 방지"
|
||||
parent_file: "spec/strategy/entry_gates.yaml"
|
||||
version: "2026-05-15-F11_entry_split"
|
||||
language: "ko-KR"
|
||||
timezone: "Asia/Seoul"
|
||||
role: "canonical"
|
||||
migration_status: "canonical_split_active"
|
||||
|
||||
anti_late_trade_rule:
|
||||
principle: >
|
||||
가격·수급·ATR 신호는 주문 트리거가 아니라 위험등급 신호로 우선 사용한다.
|
||||
이미 큰 폭으로 상승한 종목의 강한 수급은 추격매수 근거가 될 수 없고,
|
||||
이미 큰 폭으로 하락한 종목의 ATR 이탈은 즉시 투매 근거가 될 수 없다.
|
||||
buy_filter:
|
||||
forbid_chasing:
|
||||
- "20거래일 급등 후 신고가권 신규매수 금지"
|
||||
- "20일선 대비 과도한 이격 발생 시 신규매수 금지"
|
||||
- "기존 보유 섹터와 중복될 경우 신규매수 금지"
|
||||
allow_buy_only_if:
|
||||
- "눌림 후 회복"
|
||||
- "손절폭 대비 기대수익 1.8배 이상"
|
||||
- "포지션 크기와 손실예산이 사전에 확정"
|
||||
sell_filter:
|
||||
no_retroactive_stop:
|
||||
- "진입 전 손절선이 없던 기존 포지션에 사후 ATR 손절을 기계 적용하지 않는다"
|
||||
damaged_position_protocol:
|
||||
- "이미 -10% 이상 손실 포지션은 시장가 투매 금지"
|
||||
- "반등 매도, 시간 손절, 논리 훼손 손절로 분리"
|
||||
- "ETF와 개별주의 손절 기준을 다르게 적용"
|
||||
portfolio_rule:
|
||||
trim_strength_before_weakness:
|
||||
- "현금 확보는 약한 종목 투매보다 강한 종목의 초과비중 일부 익절을 우선 검토"
|
||||
- "단, 장기 코어는 월간 리밸런싱에서만 조정"
|
||||
calculation_gate:
|
||||
formula: "(target_price - entry_price) / max(1, entry_price - stop_price) >= 1.8 (RR 최소 기준)"
|
||||
no_trade_if: ["RR < 1.8", "손실예산 미확정", "보유수량/평단/계좌 원장 미확인"]
|
||||
evidence_gate:
|
||||
requires:
|
||||
- "실체결 기준 수익률과 손실률"
|
||||
- "3~10거래일 후행 성과 검증"
|
||||
- "동일 섹터 중복노출 대비 초과수익"
|
||||
prohibit:
|
||||
- "하루 가격 반응만으로 전면 교체"
|
||||
- "ATR 미확인 상태의 손절가·정수수량 산출"
|
||||
- "강한 종목 수급을 이유로 신고가 추격매수"
|
||||
|
||||
next_generation_core_satellite_discovery:
|
||||
alias_of: "next_generation_satellite_position_discovery"
|
||||
terminology: "satellite_position은 포트폴리오 보완용 전술·보조 종목이며, core_satellite 시트의 satellite는 우주 업종이 아닌 자산배분 레이블이다."
|
||||
preferred_output_name: "core_satellite 후보 스크리닝"
|
||||
universe_build:
|
||||
source_order: ["KRX 상장상태·거래대금", "Naver/KRX 수급", "Yahoo/KRX 20/60D 상대강도·ATR20", "OpenDART 촉매·리스크"]
|
||||
minimum_liquidity: "20D 평균거래대금 100억원 이상 권장, 50억원 미만 원칙 제외"
|
||||
screening_axes: ["상대강도", "5D/20D 수급", "거래대금 증가", "DART 촉매", "리스크 공시", "기존 보유와의 상관"]
|
||||
grade:
|
||||
alias_of: "recommendation_grade" # [P129] A_watch_to_buy_ready=A, B_watch=B, C_theme_only=C, D_reject=D
|
||||
label_mapping: {A_watch_to_buy_ready: "recommendation_grade.A", B_watch: "recommendation_grade.B", C_theme_only: "recommendation_grade.C", D_reject: "recommendation_grade.D"}
|
||||
A_watch_to_buy_ready: "80점 이상, Price_Status=PRICE_OK, Flow_OK=Y, DART_Risk 없음, ATR20 확인, 돌파 직후가 아니라 확인 또는 눌림 구간 → 조건부 진입 후보"
|
||||
B_watch: "65~79점. 다음 quant_feed 갱신 대기"
|
||||
C_theme_only: "50~64점 또는 핵심 데이터 부족. 관찰만."
|
||||
D_reject: "50점 미만, 상장상태 리스크, 유동성 부족, 공시 리스크, DATA_CONFLICT"
|
||||
output_rule:
|
||||
- "고정 종목 목록·고정 업종 키워드 금지. 공개 스크리닝 통과 종목만 포함."
|
||||
- "통과 종목 없으면 '후보 없음' 표에 검색조건·탈락사유·다음조회일 기재."
|
||||
|
||||
- "신규 후보는 항상 시범진입 여부와 본진입 여부를 분리해 적는다."
|
||||
- "risk_on 국면의 주도주는 시범진입을 늦게 하지 말고, 대신 수량을 작게 가져간다."
|
||||
- "보고서 제목의 core_satellite는 자산배분 분류를 뜻하며, 항공우주 업종으로 오해될 수 있는 '위성' 단독 표현은 보조 표기만 허용한다."
|
||||
watchlist_analysis_workflow:
|
||||
- "스크리닝 결과 후보 1개 이상일 때만 분석 수행."
|
||||
- "ATR20 없으면 관찰가만 제시. 손절가·정수수량·기대수익비 산출금지 표시."
|
||||
- "신고가 직후 종목은 관찰가보다 위의 가격을 제시하지 않는다."
|
||||
- "다만 risk_on + 20D 수급 양호 + 거래대금 확장 + 종가 고가 마감이면 관찰가가 아니라 시범진입가를 제시할 수 있다."
|
||||
@@ -0,0 +1,195 @@
|
||||
meta:
|
||||
title: "은퇴자산포트폴리오 — 핵심 진입 게이트"
|
||||
parent_file: "spec/strategy/entry_gates.yaml"
|
||||
version: "2026-05-15-F11_entry_split"
|
||||
language: "ko-KR"
|
||||
timezone: "Asia/Seoul"
|
||||
role: "canonical"
|
||||
migration_status: "canonical_split_active"
|
||||
|
||||
entry_timing_guardrails:
|
||||
principle: "좋은 종목도 비싸게 사면 수익이 나빠지지만, 강한 장세의 돌파를 놓치는 것도 손실이다. 진입은 추격이 아니라 단계화다."
|
||||
regime_based_entry:
|
||||
risk_on: "추세·수급·거래대금이 동시에 강하면 돌파 시범진입 허용"
|
||||
leader_concentration: "top2_rotation_sum>=100 AND top1_rotation_score>=55 AND top1_alert_score>=2 AND leader_sector_flag=1 AND KOSPI_Ret20D>0 AND VIX_Close<25"
|
||||
neutral: "돌파 단독이면 대기, 눌림 확인 후 진입"
|
||||
risk_off: "돌파 추격 금지, 지지 확인 전 본진입 금지"
|
||||
numeric_gates:
|
||||
breakout_pilot:
|
||||
required: ["Price_Status=PRICE_OK", "Flow_OK=Y", "Flow_Rows>=20", "20일선 위", "DART_Risk 없음"]
|
||||
optimal_algorithm_formula: "Score = ((Close/MA20)-1)*100 + (Val_Surge_Pct/10) + (Net_Inst_Frg_5D_Ratio)"
|
||||
formula_gate: "Score > 15 일 때만 시범진입 허용. 미만이면 뇌동매매 방지를 위해 대기."
|
||||
calibration_note: # [P132] Score > 15 근거 및 재교정 기준
|
||||
score_ranges: {price_dev: "1~3 (1~3% 이탈)", val_surge: "0~10 (거래대금 0~100% 급증)", net_flow: "1~5 (기관+외국인 순매수)"}
|
||||
recalibration: "30건 후 손절률 > 50% 또는 평균수익 < 5% 시 임계치 20으로 상향 검토"
|
||||
term_definitions: # [proposal_105 / 2026-05-15] 미정의 항 명시 — Score 게이트 정상화
|
||||
Net_Inst_Frg_5D_Ratio: >
|
||||
(Inst_5D_sh + Frg_5D_sh) / AvgVolume_5D_shares.
|
||||
분자: 주식 수(shares) 단위 5D 순매수 합산.
|
||||
분모: AvgVolume_5D_shares — 최근 5거래일 평균 거래량(주식 수). AvgTradeValue_5D_M(억원) 혼용 금지.
|
||||
Flow_OK=Y 이고 Flow_Rows>=5 일 때만 계산.
|
||||
DATA_MISSING 또는 Flow_Rows<5 이면 0으로 처리(보수적 기본값).
|
||||
단위: 무차원 비율(소수). 예) Inst_5D=500K주, Frg_5D=300K주, AvgVolume_5D=10M주 → 0.080
|
||||
minimalist_buy_gate:
|
||||
rule: "과적합(Over-optimization) 방지를 위해, 진입 판단은 1)가격 추세(20일선) 2)외국인/기관 수급 3)유동성(거래대금) 3대 핵심 지표만으로 결정한다. 기타 보조지표 충돌 시 핵심 3지표를 최우선으로 한다."
|
||||
formula_id: "minimalist_v1" # [proposal_111 / 2026-05-15] 수치 임계치 고정 — 일관성 확보
|
||||
three_core_indicators:
|
||||
indicator_1_price_trend:
|
||||
formula: "Close > MA20"
|
||||
pass: "종가가 20일선 위에서 마감"
|
||||
fail: "종가가 20일선 아래 → 진입 금지"
|
||||
data_source: "data_feed 탭 Close·MA20 또는 Naver 직접 조회"
|
||||
indicator_2_supply_demand:
|
||||
formula: "Frg_5D + Inst_5D > 0 AND Flow_OK=Y AND Flow_Rows >= 5"
|
||||
pass: "외국인·기관 합산 5D 순매수 양수"
|
||||
fail: "합산 음수 또는 Flow_OK=N → 진입 금지"
|
||||
data_source: "quant_feed_contract.investor_flow_rules"
|
||||
indicator_3_liquidity:
|
||||
formula: "AvgTradeValue_5D_M >= 50"
|
||||
pass: "5D 평균거래대금 50억원 이상"
|
||||
fail: "50억원 미만 또는 DATA_MISSING → 진입 금지"
|
||||
data_source: "data_feed 탭 AvgTradeValue_5D_M 또는 KRX 거래대금"
|
||||
gate_logic:
|
||||
all_pass: "3개 모두 pass → minimalist_gate 통과, 상위 gating 계속"
|
||||
any_fail: "1개라도 fail → 진입 보류. 사유 표기."
|
||||
data_missing_treatment: "핵심 필드 DATA_MISSING이면 해당 지표 fail로 보수 처리."
|
||||
integration_rule:
|
||||
- "minimalist_buy_gate 통과 후 ATR수량·Expected_Edge·sector_model.grade 상위 gating 계속."
|
||||
- "미통과 종목에 RSI·MACD·볼린저 등 보조지표 적용 금지."
|
||||
- "이 게이트는 A등급 승격의 필요조건. 충분조건은 상위 gating."
|
||||
occams_razor_alignment: # [P133] minimalist_gate와 occams_razor는 다른 목적
|
||||
note: "minimalist_buy_gate 3지표(추세/수급/유동성)는 진입 가부 판단 게이트. occams_razor_filter는 타이밍 정밀도 보조. 목적이 달라 동일 지표가 아님 — 두 단계를 순서대로 적용."
|
||||
override_prohibition: "이 3개 외 보조지표를 '더 중요하다'는 이유로 대체 금지."
|
||||
occams_razor_filter:
|
||||
rule: "신규 매수(A등급 승격) 판단 시 융합할 수 있는 조건은 최대 3개로 제한한다. 초과된 조건은 뇌동매매 방지를 위해 기계적으로 무시한다."
|
||||
preferred: ["최근 5거래일 상승률이 섹터 평균 이상", "Val_Surge_Pct 0~25", "종가가 고가 근처 마감"]
|
||||
tranche: "계획 수량의 20~30%"
|
||||
breakout_block:
|
||||
trigger: ["Val_Surge_Pct 40 이상", "장대양봉 연속", "거래대금 급폭발", "5거래일 연속 급등"]
|
||||
action: "본진입 금지. 시범진입도 10~20%로 축소하거나 관찰로 전환."
|
||||
pullback_buy:
|
||||
required: ["20일선 또는 5일선 부근", "거래대금 감소 또는 안정", "Flow_OK=Y", "20D 수급 유지"]
|
||||
tranche: "계획 수량의 40~60%"
|
||||
leader_concentration:
|
||||
numeric_definitions:
|
||||
top2_rotation_sum: "sector_flow 상위 2개 Rotation_Score 합"
|
||||
top1_rotation_score: "sector_flow 상위 1개 Rotation_Score"
|
||||
top1_alert_score:
|
||||
INFLOW_STRONG: 3
|
||||
INFLOW_MODERATE: 2
|
||||
NEUTRAL: 1
|
||||
OUTFLOW_CAUTION: 0
|
||||
OUTFLOW_ALERT: -1
|
||||
leader_sector_flag:
|
||||
# [Q5 / 2026-05-15] "주도 섹터"의 판정 주체와 기준 미명시로 LLM이 임의 판단하는 할루시네이션 방지.
|
||||
formula: "sector_flow 탭에서 Rotation_Score 1위 섹터명이 아래 approved_list 중 하나이면 1, 아니면 0"
|
||||
approved_list: ["반도체", "AI전력", "전력기기", "발전/전력"]
|
||||
data_source: "sector_flow 탭 Rotation_Score 컬럼 기준 1위 행의 섹터명"
|
||||
missing_rule: "sector_flow 탭 미제공 또는 Rotation_Score 미확인 시 leader_sector_flag=0 (보수적 기본값)"
|
||||
disambiguation: "'AI전력'은 AI 인프라·전력기기·전력 설비 관련 섹터를 의미. 항공·우주·방산과 혼동 금지."
|
||||
gate: "top2_rotation_sum>=100 AND top1_rotation_score>=55 AND top1_alert_score>=2 AND leader_sector_flag=1 AND KOSPI_Ret20D>0 AND VIX_Close<25"
|
||||
pilot_tranche: "20~30%"
|
||||
add_on_tranche: "40~60%"
|
||||
stop_gate: "Val_Surge_Pct>=40 OR DART_Risk!=없음 OR Flow_OK!=Y"
|
||||
expected_edge_floor: # [P95] 기대우위 하한선 — 비용 차감 후 최소 손익비 미만 진입 차단
|
||||
purpose: "기대우위가 하한선 미만이면 신규 진입을 금지하고 관찰만 유지한다."
|
||||
formula: "Expected_Edge = (target_price - entry_price) / (entry_price - stop_price) × bayesian_confidence_multiplier - execution_cost_rate"
|
||||
threshold:
|
||||
floor: "Expected_Edge >= 1.5 → 진입 허용. 미만이면 관찰 전환."
|
||||
prohibition:
|
||||
- "Expected_Edge 미산출 시 A등급 즉시매수 금지"
|
||||
- "손절가 미설정 상태에서 Expected_Edge 산출 금지 (분모 = 0이 되어 연산 불능)"
|
||||
confirmation_rule:
|
||||
breakout_only: "신고가·박스 돌파 첫날은 전량 매수 금지. 다만 risk_on이면 계획 수량의 20~30% 시범진입은 허용."
|
||||
add_on_rule: "돌파 다음날 종가 유지 또는 2~3거래일 내 눌림 후 지지 확인이 있어야 본진입 허용."
|
||||
pullback_rule: "20일선 또는 5일선 부근 눌림에서 거래대금이 줄고 수급이 유지될 때 우선 매수."
|
||||
quality_filter: "종가가 고가 근처에서 마감하고, 장중 밀림을 다시 회복하며, 20D 수급이 양호해야 돌파 신뢰도 상향."
|
||||
overextension_rule:
|
||||
too_hot: "최근 급등 후 거래대금이 과도하게 폭발하고 장대양봉이 연속되면 본진입 보류."
|
||||
chase_limit: "최근 5거래일 상승률이 섹터 평균을 크게 초과하면 추격매수 대신 관찰 또는 소액 시범진입만 허용."
|
||||
acceptable_extension: "다만 섹터 주도주가 20일선 위에서 1차 돌파 후 0~3% 연속 확장하는 구간은 risk_on에 한해 허용."
|
||||
timing_mode_policy:
|
||||
principle: >
|
||||
선행형은 작은 초기 포지션을 빠르게 잡아 기회를 확보하는 방식이고,
|
||||
후행형은 확인 후 진입·반등 확인 후 축소·추세 훼손 후 정리하는 방식이다.
|
||||
둘 중 하나만 고집하지 말고, 시장 국면과 데이터 완성도에 따라 전환한다.
|
||||
lead_when:
|
||||
regime: ["risk_on", "leader_concentration"]
|
||||
required: ["Price_Status=PRICE_OK", "Flow_OK=Y", "Flow_Rows>=20", "20일선 위", "DART_Risk 없음"]
|
||||
use_case:
|
||||
- "신고가 직전 또는 1차 돌파 구간의 시범진입"
|
||||
- "주도 섹터 내 대장주 초기 편입"
|
||||
size_rule:
|
||||
pilot_tranche: "계획 수량의 20~30%만"
|
||||
add_on: "돌파 유지·눌림 지지 확인 후 나머지 70~80%"
|
||||
prohibition:
|
||||
- "대량 일괄매수 금지"
|
||||
- "선행형 신호를 이유로 손절가·수량 미확정 상태에서 진입 금지"
|
||||
lag_when:
|
||||
regime: ["neutral", "risk_off", "data_partial", "high_volatility"]
|
||||
required: ["20일선 재확인", "수급 유지 확인", "거래대금 급감 없음"]
|
||||
use_case:
|
||||
- "반등 확인 후 축소"
|
||||
- "손실 포지션 정리"
|
||||
- "섹터 이탈 종목의 시간 손절"
|
||||
size_rule:
|
||||
entry_tranche: "계획 수량의 40~60% 또는 반등 확인 후 분할"
|
||||
exit_rule: "손실 포지션은 후행형으로 줄이고, 강한 종목은 반등 시 축소"
|
||||
prohibition:
|
||||
- "저점 추격 투매 금지"
|
||||
- "후행형이 필요할 때 선행형 돌파 추격 금지"
|
||||
hybrid_when:
|
||||
regime: ["neutral with strong setup", "risk_on but data_mixed"]
|
||||
rule: "시범진입은 선행형, 본진입/축소는 후행형으로 분리"
|
||||
output_requirement: "보고서에 선행/후행 중 어느 모드인지 반드시 명시"
|
||||
scoring_gate:
|
||||
lead_score_formula: "(price_strength + flow_strength + liquidity_strength) - volatility_penalty - data_miss_penalty"
|
||||
lead_threshold: "lead_score >= 3 → 선행형 허용"
|
||||
lag_threshold: "lead_score < 3 → 후행형 우선"
|
||||
note: "lead_score는 진입 타이밍 보조지표이며, 기대수익비·손절가·수량 산출을 대체하지 않는다."
|
||||
|
||||
# [2026-05-17] 지정가 산출 공식 — limit_price_formula
|
||||
# 매수 지정가를 시나리오별로 명확히 정의해 LLM이 임의 가격을 생성하지 않도록 한다.
|
||||
limit_price_formula:
|
||||
authority_note: "지정가 계산은 아래 시나리오 중 진입 유형에 따라 하나를 선택. 불명확 시 pullback_limit 우선."
|
||||
data_inputs: ["Close", "Ask (매도1호가)", "MA20", "ATR20"]
|
||||
missing_rule: "Ask 미제공 또는 Spread_Status=WIDE 이면 Close 기반 공식으로 fallback."
|
||||
|
||||
scenarios:
|
||||
breakout_pilot:
|
||||
entry_context: "breakout_pilot 또는 leader_concentration 시범진입"
|
||||
formula: "limit_price = Ask if Ask available else Close * 1.005"
|
||||
note: "매도1호가 체결 우선. Ask 없으면 종가 +0.5% (2~3틱) 위 지정가."
|
||||
max_chase_limit: "Close * 1.010 초과 지정가 금지 — 추격매수 방지"
|
||||
|
||||
pullback_buy:
|
||||
entry_context: "pullback_buy (눌림 매수) 또는 MA20 지지 확인 후 진입"
|
||||
formula: "limit_price = Close * 1.002 (종가 +0.2%, 시가 이하 눌림 체결 목표)"
|
||||
note: "눌림 구간에서 종가보다 낮은 가격도 허용. 체결 못하면 다음 날 재판단."
|
||||
tighter_option: "limit_price = MA20 * 1.003 (MA20선 +0.3% — 지지 부근 매수)"
|
||||
|
||||
staged_add_on:
|
||||
entry_context: "본진입 2·3차 분할 매수 (breakout 유지 확인 후)"
|
||||
formula: "limit_price_2nd = entry_price_1st * (1 + 0.005~0.010)"
|
||||
note: "1차 평단 대비 0.5~1.0% 위. 추가 급등 구간(Val_Surge_Pct>=40)에서는 추가 금지."
|
||||
|
||||
stop_price_formula:
|
||||
formula: "stop_price = entry_price - ATR20 * stop_atr_multiplier"
|
||||
stop_atr_multiplier:
|
||||
default: 1.5
|
||||
tight: 1.0
|
||||
wide: 2.0
|
||||
canonical_ref: "spec/05_position_sizing.yaml:position_sizing.volatility_targeting"
|
||||
note: "stop_price는 entry_price 확정 직후 계산. ATR20 미제공 시 매수수량 산출 금지 (HF002)."
|
||||
|
||||
expected_edge_calculation:
|
||||
formula: "Expected_Edge = (target_price - entry_price) / (entry_price - stop_price) * bayesian_confidence_multiplier - execution_cost_rate"
|
||||
inputs:
|
||||
target_price: "data_feed 탭 Target_Price (Naver 컨센서스 우선, Yahoo 폴백)"
|
||||
entry_price: "limit_price (위 시나리오 중 선택)"
|
||||
stop_price: "stop_price_formula 결과"
|
||||
bayesian_confidence_multiplier: "spec/05_position_sizing.yaml 참조 (기본 1.0)"
|
||||
execution_cost_rate: "0.003 (왕복 거래비용 0.3% — 증권사 수수료+세금)"
|
||||
floor: "Expected_Edge >= 1.5 → 진입 허용. 미만이면 관찰 전환 (RA003)."
|
||||
|
||||
# [proposal_47 / 2026-05-15] 일간 주도주 조기탐지 레이어 — daily_leader_scan
|
||||
@@ -0,0 +1,27 @@
|
||||
schema_version: entry_freshness_score.v1
|
||||
formula_id: ENTRY_FRESHNESS_SCORE_V1
|
||||
purpose: "뒷북/추격 매수를 차단하기 위한 진입 신선도 점수 계약."
|
||||
inputs:
|
||||
- signal_age
|
||||
- distance_from_trigger
|
||||
- one_day_velocity
|
||||
- five_day_return
|
||||
- volume_confirmation
|
||||
- flow_confirmation
|
||||
outputs:
|
||||
- entry_freshness_score
|
||||
- entry_freshness_state
|
||||
- buy_permission
|
||||
thresholds:
|
||||
block: 70
|
||||
pilot_only: 84
|
||||
full_entry: 85
|
||||
rules:
|
||||
- "entry_freshness_score < 70 -> BUY 금지"
|
||||
- "70 <= entry_freshness_score <= 84 -> PILOT_ONLY"
|
||||
- "entry_freshness_score >= 85 and follow_through PASS -> 본진입 허용"
|
||||
validation:
|
||||
required_metrics:
|
||||
- blocked_late_chase_buy_leak_count
|
||||
- entry_freshness_coverage_pct
|
||||
- distribution_risk_coverage_pct
|
||||
@@ -0,0 +1,29 @@
|
||||
meta:
|
||||
title: "은퇴자산포트폴리오 — 진입 게이트 호환 인덱스"
|
||||
parent_file: "spec/04_strategy_rules.yaml"
|
||||
version: "2026-05-15-F11_index_only"
|
||||
language: "ko-KR"
|
||||
timezone: "Asia/Seoul"
|
||||
role: "compatibility_index"
|
||||
purpose: >
|
||||
기존 spec/strategy/entry_gates.yaml 경로를 보존하기 위한 인덱스 파일.
|
||||
실제 진입 규칙은 세부 split 파일을 canonical로 사용한다.
|
||||
|
||||
canonical_split_files:
|
||||
entry_core: "spec/strategy/entry_core.yaml"
|
||||
leader_scan: "spec/strategy/leader_scan.yaml"
|
||||
staged_entry: "spec/strategy/staged_entry.yaml"
|
||||
discovery: "spec/strategy/discovery.yaml"
|
||||
|
||||
legacy_path_aliases:
|
||||
"spec/strategy/entry_gates.yaml:entry_timing_guardrails.regime_based_entry": "spec/strategy/entry_core.yaml:entry_timing_guardrails.regime_based_entry"
|
||||
"spec/strategy/entry_gates.yaml:entry_timing_guardrails.numeric_gates": "spec/strategy/entry_core.yaml:entry_timing_guardrails.numeric_gates"
|
||||
"spec/strategy/entry_gates.yaml:entry_timing_guardrails.daily_leader_scan": "spec/strategy/leader_scan.yaml:entry_timing_guardrails.daily_leader_scan"
|
||||
"spec/strategy/entry_gates.yaml:entry_timing_guardrails.anti_climax_buy_gate": "spec/strategy/leader_scan.yaml:entry_timing_guardrails.anti_climax_buy_gate"
|
||||
"spec/strategy/entry_gates.yaml:entry_timing_guardrails.staged_entry_v2": "spec/strategy/staged_entry.yaml:entry_timing_guardrails.staged_entry_v2"
|
||||
"spec/strategy/entry_gates.yaml:entry_timing_guardrails.pullback_reentry_rule": "spec/strategy/staged_entry.yaml:entry_timing_guardrails.pullback_reentry_rule"
|
||||
"spec/strategy/entry_gates.yaml:anti_late_trade_rule": "spec/strategy/discovery.yaml:anti_late_trade_rule"
|
||||
|
||||
migration_rule:
|
||||
- "신규 참조는 canonical_split_files의 경로를 사용한다."
|
||||
- "이 파일에는 수치 임계값을 추가하지 않는다."
|
||||
@@ -0,0 +1,22 @@
|
||||
formula_id: FUNDAMENTAL_AND_HORIZON_GATE_V1
|
||||
name: 펀더멘털 및 시계열 통제 게이트 (Fundamental & Horizon Gate)
|
||||
description: 종목의 핵심 펀더멘털(이익률, 성장률, 점유율, 현금흐름)을 점검하고 투자 기간 버킷을 강제 할당하여 장단기 투자 목적 혼선을 방지합니다.
|
||||
rules:
|
||||
- id: FHG001
|
||||
condition: "horizon_bucket IS NULL"
|
||||
action: "BLOCK_BUY"
|
||||
reason: "단기/중기/장기 버킷 미지정 (신규 편입 불가)"
|
||||
- id: FHG002
|
||||
condition: "roe < 5.0 AND operating_profit_growth < 0 AND market_share_trend == 'DECLINING'"
|
||||
action: "BLOCK_BUY"
|
||||
reason: "수익성, 성장성, 시장점유율 동시 악화 (가치 훼손)"
|
||||
- id: FHG003
|
||||
condition: "horizon_bucket == 'SHORT_TERM' AND holding_days > 15"
|
||||
action: "FORCE_REVIEW_OR_TRIM"
|
||||
reason: "단기 모멘텀 종목 장기 보유 방지"
|
||||
output:
|
||||
schema: fundamental_and_horizon_json
|
||||
fields:
|
||||
- horizon_bucket: STRING (SHORT_TERM, MID_TERM, LONG_TERM)
|
||||
- fundamental_grade: STRING (A, B, C, D, F)
|
||||
- fundamental_pass: BOOLEAN
|
||||
@@ -0,0 +1,22 @@
|
||||
formula_id: FUNDAMENTAL_QUALITY_GATE_V1
|
||||
name: 펀더멘털 품질 게이트 (Fundamental Quality Gate)
|
||||
description: ROE, 영업이익증가율, 부채비율, 현금흐름, 밸류에이션 등 핵심 펀더멘털 지표를 점수화하여 기준치 미달 시 신규 매수를 차단합니다.
|
||||
rules:
|
||||
- id: FQ001
|
||||
condition: "roe < 5.0 AND operating_profit_growth < 0 AND debt_ratio > 200"
|
||||
action: "BLOCK_BUY"
|
||||
reason: "핵심 펀더멘털 지표 3개 동시 미달 (가치 훼손 위험)"
|
||||
- id: FQ002
|
||||
condition: "operating_cash_flow < 0 AND free_cash_flow < 0"
|
||||
action: "BLOCK_BUY"
|
||||
reason: "영업/잉여 현금흐름 동시 적자 (유동성 위기 징후)"
|
||||
- id: FQ003
|
||||
condition: "pbr > 5.0 AND per > 50.0 AND roe < 10.0"
|
||||
action: "WATCH_ONLY"
|
||||
reason: "이익/자산 대비 과도한 고평가 (테마성 급등)"
|
||||
output:
|
||||
schema: fundamental_quality_json
|
||||
fields:
|
||||
- grade: STRING (A, B, C, D, F)
|
||||
- fail_reasons: ARRAY of STRING
|
||||
- buy_allowed: BOOLEAN
|
||||
@@ -0,0 +1,22 @@
|
||||
formula_id: FUNDAMENTAL_QUALITY_GATE_V2
|
||||
name: 펀더멘털 품질 게이트 V2 (Fundamental Quality Gate)
|
||||
description: 이익률, 성장률, 시장 점유율, 현금흐름 지표를 기반으로 내재 가치가 훼손된 종목의 신규 진입을 엄격히 차단합니다.
|
||||
rules:
|
||||
- id: FQ001
|
||||
condition: "roe < 5.0 AND operating_profit_growth < 0 AND free_cash_flow < 0"
|
||||
action: "BLOCK_BUY"
|
||||
reason: "핵심 가치 지표(수익성, 성장성, 현금흐름) 동시 악화"
|
||||
- id: FQ002
|
||||
condition: "market_share_trend == 'DECLINING' AND debt_ratio > 150"
|
||||
action: "BLOCK_BUY"
|
||||
reason: "시장 점유율 하락 및 재무 부담 가중"
|
||||
- id: FQ003
|
||||
condition: "per > 50.0 AND pbr > 5.0 AND roe < 10.0"
|
||||
action: "WATCH_ONLY"
|
||||
reason: "고평가 테마성 종목 주의 (펀더멘털 불일치)"
|
||||
output:
|
||||
schema: fundamental_quality_json
|
||||
fields:
|
||||
- grade: STRING (A, B, C, D, F)
|
||||
- buy_allowed: BOOLEAN
|
||||
- fail_reasons: ARRAY of STRING
|
||||
@@ -0,0 +1,88 @@
|
||||
# spec/strategy/fundamental_quality_v3.yaml
|
||||
# P1-011: FUNDAMENTAL_EVIDENCE_UPGRADE — engine_audit vs data_quality 충돌 해소
|
||||
#
|
||||
# 충돌 근거:
|
||||
# data_quality.schema_presence_score = 100 ← 필드 존재 여부만 확인
|
||||
# engine_audit.fundamental_score = ~62 ← 실제 값 존재 여부 + missing_penalty
|
||||
# conflict_gap_pct = 40.0 (OCF/FCF 0% 커버리지가 원인)
|
||||
#
|
||||
# 해소 방법:
|
||||
# 1. OCF/FCF 데이터 HTS 캡처 (OPERATIONAL_ACTION)
|
||||
# 2. data_quality=FULL 레이블 기준 강화 (OCF or FCF 필수) → v2에서 적용됨
|
||||
# 3. fundamental_multifactor_v4 missing_penalty 적용
|
||||
|
||||
meta:
|
||||
formula_id: FUNDAMENTAL_QUALITY_V3
|
||||
version: "2026-06-06"
|
||||
python_tools:
|
||||
- tools/build_fundamental_raw_v2.py
|
||||
- tools/build_fundamental_multifactor_v4.py
|
||||
sources:
|
||||
- Temp/fundamental_raw_v1.json # FUNDAMENTAL_RAW_INGEST_V1 출력
|
||||
- Temp/fundamental_raw_v2.json # v2: field-level coverage 수정
|
||||
- Temp/fundamental_multifactor_v4.json
|
||||
|
||||
# ── 충돌 정의 ─────────────────────────────────────────────────────────────────
|
||||
conflict_definition:
|
||||
issue: >
|
||||
v1에서 data_quality=FULL이지만 OCF/FCF=None인 tickers가 존재함.
|
||||
ROE/OPM/PER/PBR/EPS 5개 필드 기준으로 FULL 판정했으나
|
||||
multifactor 점수에서 OCF/FCF 합산 30점 비중이 빠지는 문제.
|
||||
v1_full_label_count: 7
|
||||
v2_reclassified_to_partial: 7 # 전원 PARTIAL로 재분류
|
||||
root_cause: OCF/FCF HTS 캡처 미완료 (OPERATIONAL_ACTION)
|
||||
|
||||
# ── 필드 가중치 ────────────────────────────────────────────────────────────────
|
||||
field_weights:
|
||||
roe_pct: 25 # ROE
|
||||
opm_pct: 20 # 영업이익률
|
||||
ocf_krw: 15 # 영업현금흐름 ← 현재 0% 커버리지
|
||||
fcf_krw: 15 # 잉여현금흐름 ← 현재 0% 커버리지
|
||||
net_debt_krw: 10 # 순부채
|
||||
per: 8 # PER
|
||||
pbr: 7 # PBR
|
||||
total_weight: 100
|
||||
|
||||
# ── data_quality 레이블 기준 (v2) ──────────────────────────────────────────────
|
||||
data_quality_labels:
|
||||
FULL: "ROE/OPM + 밸류에이션 + (OCF or FCF) 모두 있음"
|
||||
PARTIAL: "ROE/OPM + 밸류에이션 있음, OCF/FCF 없음"
|
||||
SPARSE: "ROE/OPM만 있음"
|
||||
MISSING: "핵심 필드 없음"
|
||||
ETF_EXCLUDED: "ETF — 펀더멘털 미적용"
|
||||
|
||||
# ── missing_penalty ────────────────────────────────────────────────────────────
|
||||
missing_penalty:
|
||||
ocf_krw: -5.0 # OCF 없을 때 감점
|
||||
fcf_krw: -5.0 # FCF 없을 때 감점
|
||||
note: "penalty는 quality_multiplier 적용 후 차감"
|
||||
|
||||
# ── 수락 기준 ─────────────────────────────────────────────────────────────────
|
||||
acceptance_criteria:
|
||||
raw_field_coverage_pct:
|
||||
target: ">=90"
|
||||
current: 60.0
|
||||
status: FAIL
|
||||
remediation: "OCF/FCF HTS 캡처 → OPERATIONAL_ACTION"
|
||||
fundamental_score_not_available_count:
|
||||
target: "==0"
|
||||
current: 7
|
||||
status: FAIL
|
||||
remediation: "OCF/FCF 캡처 후 자동 해소"
|
||||
conflict_gap_pct:
|
||||
target: "<5"
|
||||
current: 40.0
|
||||
status: FAIL
|
||||
remediation: "field coverage 개선 후 자동 해소"
|
||||
|
||||
# ── 장기투자 제한 ──────────────────────────────────────────────────────────────
|
||||
long_horizon_policy:
|
||||
condition: "OCF=None AND FCF=None"
|
||||
action: "long_horizon_buy_allowed=False"
|
||||
note: "현금흐름 근거 없이 장기투자 추천 금지"
|
||||
|
||||
# ── 금지 사항 ─────────────────────────────────────────────────────────────────
|
||||
prohibitions:
|
||||
- "OCF/FCF 결측 상태에서 data_quality=FULL 레이블 사용 금지"
|
||||
- "fundamental_score 결측을 0점으로 대체해 등급 산출 금지"
|
||||
- "conflict_gap_pct >= 5인 상태에서 펀더멘털 기반 장기투자 추천 금지"
|
||||
@@ -0,0 +1,77 @@
|
||||
formula_id: HORIZON_ALLOCATION_LOCK_V1
|
||||
name: 투자 기간 할당 잠금 (Horizon Allocation Lock)
|
||||
description: 종목별 투자 목적(단기/중기/장기)을 명시적으로 고정하여 운영의 일관성을 확보합니다.
|
||||
rules:
|
||||
- id: HA001
|
||||
condition: "horizon_bucket IS NULL"
|
||||
action: "BLOCK_BUY"
|
||||
reason: "투자기간 버킷 미지정"
|
||||
- id: HA002
|
||||
condition: "horizon_bucket == 'SHORT_TERM' AND holding_days > 15"
|
||||
action: "FORCE_TRIM"
|
||||
reason: "단기 모멘텀 종목 보유 기간 초과"
|
||||
- id: HA003
|
||||
condition: "horizon_bucket == 'LONG_TERM' AND stop_loss_hit == TRUE"
|
||||
action: "DOWNGRADE_GRADE"
|
||||
reason: "장기 코어 종목의 구조적 훼손 의심"
|
||||
output:
|
||||
schema: horizon_allocation_json
|
||||
fields:
|
||||
- bucket: STRING (SHORT, MID, LONG)
|
||||
- weight_cap_pct: NUMBER
|
||||
- duration_violation: BOOLEAN
|
||||
|
||||
# ── 투자성향별 가중치 보정 (CAPITAL_STYLE_ALLOCATION_V2) ─────────────────────
|
||||
# [SCAFFOLDED_PENDING_LIVE_DATA: 모든 성향 sample_n=0, target>=30]
|
||||
weight_calibration:
|
||||
formula_id: CAPITAL_STYLE_ALLOCATION_V2
|
||||
status: SCAFFOLDED_PENDING_LIVE_DATA
|
||||
rationale: "4성향(SCALP/SWING/MOMENTUM/POSITION) conviction이 전부 미보정. 보유기간별 실측 승률로 가중치를 닫아야 한다."
|
||||
styles:
|
||||
SCALP:
|
||||
horizon_days: "1~3일"
|
||||
weight_tech: 0.50
|
||||
weight_smartmoney: 0.30
|
||||
weight_fundamental: 0.20
|
||||
weight_source: EXPERT_PRIOR
|
||||
sample_n: 0
|
||||
label: "[UNVALIDATED_WEIGHT: n=0 < 30]"
|
||||
t5_win_rate: null
|
||||
SWING:
|
||||
horizon_days: "1~4주"
|
||||
weight_tech: 0.30
|
||||
weight_smartmoney: 0.35
|
||||
weight_fundamental: 0.35
|
||||
weight_source: EXPERT_PRIOR
|
||||
sample_n: 0
|
||||
label: "[UNVALIDATED_WEIGHT: n=0 < 30]"
|
||||
t5_win_rate: null
|
||||
MOMENTUM:
|
||||
horizon_days: "1~3개월"
|
||||
weight_tech: 0.20
|
||||
weight_smartmoney: 0.40
|
||||
weight_fundamental: 0.40
|
||||
weight_source: EXPERT_PRIOR
|
||||
sample_n: 0
|
||||
label: "[UNVALIDATED_WEIGHT: n=0 < 30]"
|
||||
t20_win_rate: null
|
||||
POSITION:
|
||||
horizon_days: "3개월+"
|
||||
weight_tech: 0.10
|
||||
weight_smartmoney: 0.35
|
||||
weight_fundamental: 0.55
|
||||
weight_source: EXPERT_PRIOR
|
||||
sample_n: 0
|
||||
label: "[UNVALIDATED_WEIGHT: n=0 < 30]"
|
||||
t20_win_rate: null
|
||||
conviction_gates:
|
||||
lt_35: {recommended_pct: 0, action: BLOCK_ENTRY, note: "진입 금지"}
|
||||
"35_49": {recommended_pct: 1.5}
|
||||
"50_64": {recommended_pct: 3.0}
|
||||
"65_79": {recommended_pct: 5.0}
|
||||
"80_plus": {recommended_pct: 7.0}
|
||||
calibration_trigger: "표본 >= 30 성향부터 weight_source=DYNAMIC으로 자동 전환"
|
||||
output: Temp/capital_style_allocation_v2.json
|
||||
python_tool: "tools/build_capital_style_allocation_v1.py (v2 출력으로 확장 필요)"
|
||||
gs_coverage: "gas_apex_runtime_core.gs:calcCapitalStyleAllocationV2_()"
|
||||
validator: "tools/validate_capital_style_allocation_v1.py"
|
||||
@@ -0,0 +1,203 @@
|
||||
meta:
|
||||
title: "은퇴자산포트폴리오 — 주도주 스캔·과열 방지"
|
||||
parent_file: "spec/strategy/entry_gates.yaml"
|
||||
version: "2026-05-16-F12_kosdaq_strict"
|
||||
language: "ko-KR"
|
||||
timezone: "Asia/Seoul"
|
||||
role: "canonical"
|
||||
migration_status: "canonical_split_active"
|
||||
|
||||
entry_timing_guardrails:
|
||||
principle: "좋은 종목도 비싸게 사면 수익이 나빠지지만, 강한 장세의 돌파를 놓치는 것도 손실이다. 진입은 추격이 아니라 단계화다."
|
||||
daily_leader_scan:
|
||||
purpose: "장마감 후 5개 조건(C1~C5)을 스캔해 탐색 후보를 등재한다. 4개 이상=탐색 후보, 3개=관찰 전용."
|
||||
scan_timing: "매일 장마감 후 (15:30~16:00)"
|
||||
conditions:
|
||||
C1_price:
|
||||
formula: "Close >= MA20 AND Close >= (High - (High-Low)*0.3)"
|
||||
meaning: "20일선 위 + 당일 종가가 장중 상단 70% 이내 (윗꼬리 배제)"
|
||||
score: 1
|
||||
data: "data_feed 탭 Close·MA20·High·Low"
|
||||
C2_relative_strength:
|
||||
formula: "Ret10D_종목 >= Ret10D_KOSPI + 3%p"
|
||||
meaning: "최근 10거래일 수익률이 KOSPI 대비 +3%p 이상 초과"
|
||||
score: 1
|
||||
data: "data_feed 탭 Ret10D 또는 직접 계산"
|
||||
C3_volume_surge:
|
||||
formula: "AvgTradeValue_5D_M >= AvgTradeValue_20D_M * 1.5"
|
||||
meaning: "최근 5일 평균거래대금이 20일 평균의 150% 이상"
|
||||
score: 1
|
||||
data: "data_feed 탭 AvgTradeValue_5D_M·AvgTradeValue_20D_M (단위 통일: 억원)"
|
||||
C4_flow:
|
||||
formula: "Frg_5D > 0 OR Inst_5D > 0 AND Flow_OK=Y"
|
||||
meaning: "외국인 또는 기관 중 하나라도 5일 순매수 양수 AND Flow_OK=Y"
|
||||
score: 1
|
||||
data: "quant_feed_contract.investor_flow_rules"
|
||||
C5_sector:
|
||||
formula: "sector_priority_ranking.Tier_1 AND sector_flow.Rotation_Score 순위 <= 3"
|
||||
meaning: "해당 종목 섹터가 Tier_1(최우선 섹터) AND Rotation_Score 상위 3위 이내"
|
||||
score_Tier1: 1.0
|
||||
score_Tier2: 0.5
|
||||
score_Tier3: 0
|
||||
data: "sector_flow 탭 Rotation_Score + sector_priority_ranking 리스트"
|
||||
pass_rule:
|
||||
explore_candidate: "C1+C2+C3+C4+C5 합계 >= 4 → 탐색 후보 등재"
|
||||
watch_only: "합계 == 3 → 관찰 전용 (탐색매수 금지)"
|
||||
below_threshold: "합계 <= 2 → 이번 스캔 제외"
|
||||
entry_delay_rule: # [proposal_68 / 2026-05-15] 탐색 후보 등재 후 진입 지연 허용 기간
|
||||
purpose: "탐색 후보 등재 후 실제 stage_1 진입까지 최대 3거래일 허용. 초과 시 자동 해제."
|
||||
preferred_timing: "탐색 후보 등재 익일(T+1) 개장 후 anti_climax_buy_gate 재확인 통과 시 진입"
|
||||
max_delay:
|
||||
duration: "3거래일 (T+1~T+3)"
|
||||
expiry_action:
|
||||
condition: "T+3 종가까지 stage_1 진입 미실행"
|
||||
action: "탐색 후보 자동 해제. 탐색 슬롯 1건 반환."
|
||||
re_entry: "동일 종목은 다음 날 daily_leader_scan 재스캔 통과 시 신규 후보로 재등재 가능"
|
||||
anti_climax_recheck:
|
||||
rule: "진입 당일 개장 전 anti_climax_buy_gate 5개 신호 재확인 필수"
|
||||
if_newly_triggered: "신호 3개 이상 새로 발생 시 해당 후보 즉시 해제"
|
||||
output_columns_add: ["후보등재일", "만료일(T+3)", "anti_climax재확인결과", "진입실행여부"]
|
||||
prohibition:
|
||||
- "T+4 이후 기존 탐색 후보 재활성화 금지. 신규 스캔 통과로만 재등재"
|
||||
- "anti_climax 재확인 없이 T+2~T+3 지연 진입 금지"
|
||||
candidate_signal_freeze: # [proposal_77 / 2026-05-15] 등재 후 일간 스캔 재결과 충돌 처리
|
||||
purpose: "등재된 탐색 후보의 C점수가 이후 일간 스캔에서 변동될 경우 처리 원칙"
|
||||
freeze_rule: "탐색 후보 등재 당시(T+0 15:30 기준) C1~C5 합계를 유효 신호로 동결. 만료일(T+3 종가)까지 유지."
|
||||
rescan_role: "T+1·T+2·T+3 일간 스캔 결과는 '참고 표기'로만 출력. 기존 후보 자동 해제 근거로 사용 금지."
|
||||
mandatory_release_conditions:
|
||||
- "anti_climax_buy_gate에서 새로 S신호 3개 이상 발생 시 즉시 해제 (이 경우에만 스캔 재결과 반영)"
|
||||
- "T+3 종가 경과 시 자동 만료 (entry_delay_rule 준수)"
|
||||
output_requirement: "후보 테이블에 [등재일 C합계] vs [당일 C합계] 병기. 동결 여부 명시."
|
||||
prohibition:
|
||||
- "T+2~T+3 스캔에서 C합계 < 4로 하락했다는 이유만으로 후보 자동 해제 금지"
|
||||
- "스캔 재결과로 후보를 C합계 상향 처리 금지 — 동결 양방향 적용"
|
||||
sector_priority_ranking:
|
||||
# [proposal_63 / 2026-05-15] 섹터 동적 우선순위 — C5 판정 기준 고정
|
||||
as_of: "2026-05-15 (매월 첫째 주 갱신)"
|
||||
Tier_1:
|
||||
description: "현재 KOSPI·KOSDAQ 수급·추세가 가장 강한 섹터. 탐색매수 최우선."
|
||||
sectors: ["반도체·AI메모리", "AI인프라·서버·전력반도체", "방산·항공우주", "조선·해운"]
|
||||
C5_score: 1.0
|
||||
Tier_2:
|
||||
description: "추세 있으나 Tier_1 대비 약한 섹터. C5=0.5 부여 (합계 4점 도달 시 C1~C4 모두 필요)."
|
||||
sectors: ["전력기기·전선", "자동차·전기차", "바이오·제약(임상확인)", "엔터·콘텐츠(실적대형주)"]
|
||||
C5_score: 0.5
|
||||
Tier_3:
|
||||
description: "수급 이탈·비주도. 신규 탐색 금지. sector_flow 순위 무관 C5=0."
|
||||
sectors: ["유통·소비재", "건설·부동산", "금융·보험", "기타소형주"]
|
||||
C5_score: 0
|
||||
monthly_update:
|
||||
promotion: "Tier_2가 4주 연속 Rotation_Score 상위 3위 유지 → Tier_1 승격"
|
||||
demotion: "Tier_1이 2주 연속 Rotation_Score 6위 이하 → Tier_2 강등"
|
||||
prohibition:
|
||||
- "뉴스·테마 단기 급등만으로 Tier_1 즉시 승격 금지. 4주 연속 조건 필수."
|
||||
- "보유 종목 섹터를 Tier_1로 임의 분류 금지 (보유 편향)"
|
||||
demotion_protocol: # [proposal_67 / 2026-05-15] Tier 강등 즉시 탐색 금지
|
||||
purpose: "Tier 강등 확정 즉시 해당 섹터 탐색 후보를 해제하고 5거래일 신규 탐색을 금지한다."
|
||||
trigger: "monthly_update.demotion 조건 충족 확정 시"
|
||||
immediate_actions:
|
||||
step_1: "강등 확정일: 해당 섹터의 현재 daily_leader_scan 탐색 후보 전부 즉시 해제"
|
||||
step_2: "강등 섹터 종목의 C5 점수를 강등 후 Tier 기준으로 즉시 재산정"
|
||||
step_3: "해당 섹터 신규 탐색매수(stage_1) 5거래일 금지"
|
||||
step_4: "기존 보유 위성(해당 섹터) → relative_weakness_exit 점검 주기 일간 임시 전환"
|
||||
cooldown_period:
|
||||
duration: "5거래일 (강등 확정일 기준)"
|
||||
resume_condition: >
|
||||
5거래일 후 해당 섹터 Rotation_Score 5위 이내 AND
|
||||
외국인·기관 순매수 5D 합산 양수 재확인 시 탐색 재개.
|
||||
미충족 시 10거래일 추가 대기.
|
||||
prohibition:
|
||||
- "Tier 강등 5거래일 이내 해당 섹터 신규 탐색 진입 금지"
|
||||
- "기존 보유 위성은 강등만으로 즉시 전량 청산 금지 (relative_weakness_exit 준수)"
|
||||
data_integrity_guard:
|
||||
# [proposal_57 / 2026-05-15] daily_scan 할루시네이션 방지 guard
|
||||
pre_scan_checks:
|
||||
check_1_freshness: "as_of_date가 당일 장마감(15:30) 이내여야 함. 불충족 시 DATA_STALE — 탐색 후보 등재 금지."
|
||||
check_2_unit_consistency: "C3 산출 시 AvgTradeValue_5D_M·AvgTradeValue_20D_M 모두 억원 단위 확인. 불일치 시 C3=0."
|
||||
check_3_data_conflict: "동일 필드 복수 소스 오차 시 해당 C=0 처리."
|
||||
check_4_missing_defaults:
|
||||
C1_missing: "Close 또는 MA20 미확인 → C1=0"
|
||||
C2_missing: "Ret10D_종목 또는 Ret10D_KOSPI 미확인 → C2=0"
|
||||
C3_missing: "AvgTradeValue 미확인 → C3=0"
|
||||
C4_missing: "Flow_OK=N 또는 수급 미확인 → C4=0"
|
||||
C5_missing: "sector_flow 미제공 → C5=0"
|
||||
principle: "누락 데이터는 항상 0점. 추정·보간 금지."
|
||||
check_5_atr_prerequisite: "탐색 후보 등재 종목이라도 ATR20 미확인 시 [ATR미확인 — 진입 불가] 명시. 진입 허용 착각 방지."
|
||||
post_scan_prohibition:
|
||||
- "5개 조건 중 3개 이상 기본값(0)인 경우 탐색 후보 등재 금지"
|
||||
- "as_of_date 없이 스캔 결과 출력 금지"
|
||||
- "결과 '후보 없음'이어도 data_integrity_guard 실행 여부 표기 필수"
|
||||
# [proposal_93 / 2026-05-16] 코스닥 종목 진입 허들 상향 — 동일 C점수에서 더 높은 기준 요구
|
||||
kosdaq_entry_gate_premium:
|
||||
purpose: "코스닥 종목은 유동성·기관수급 불안정성으로 인해 KOSPI 종목 대비 진입 허들을 1단계 높인다."
|
||||
explore_candidate_threshold:
|
||||
kospi_satellite: "C1+C2+C3+C4+C5 합계 >= 4 → 탐색 후보"
|
||||
kosdaq_satellite: "C1+C2+C3+C4+C5 합계 >= 5 → 탐색 후보 (1점 추가 요구)"
|
||||
kosdaq_watch: "합계 == 4 → 관찰 전용 (코스닥에서는 탐색매수 금지)"
|
||||
additional_required_any:
|
||||
- "기관 5D 순매수 양수 (Inst_5D > 0) — 코스닥은 외국인 단독 수급 신뢰도 낮음"
|
||||
- "거래대금 20D 평균 대비 150% 이상 (C3 조건과 동일하나 코스닥 저유동성 보정 재확인)"
|
||||
grade_cap:
|
||||
rule: "코스닥 종목은 CSCS >= 90이어도 A등급 상한 적용"
|
||||
exception: "코스닥 내 Tier_1 섹터(반도체·AI인프라 관련 코스닥 대형주) 이고 기관·외국인 동시 순매수 확인 시 예외 검토 가능. 단, daily_leader_scan 합계 >= 5 필수."
|
||||
output_column_add: ["시장구분(KOSPI/KOSDAQ)", "코스닥_추가조건_충족여부"]
|
||||
prohibition:
|
||||
- "코스닥 종목을 KOSPI 기준 탐색 후보 등재 금지 (합계 4점은 코스닥에서 관찰 전용)"
|
||||
- "기관 수급 미확인 코스닥 종목 A등급 부여 금지"
|
||||
|
||||
output_table:
|
||||
columns: ["종목명", "시장구분", "C1", "C2", "C3", "C4", "C5", "합계", "판정(탐색/관찰/제외)", "ATR상태", "as_of_date"]
|
||||
prohibition:
|
||||
- "4개 미충족 종목 탐색매수 후보 등재 금지"
|
||||
- "코스닥 종목은 5개 미충족 시 탐색 후보 등재 금지"
|
||||
- "data_integrity_guard 미실행 상태 탐색 후보 표기 금지"
|
||||
- "→ master_prohibitions.P2(ATR미확인 진입 금지)·P5(데이터 없이 A등급 금지) 전역 적용"
|
||||
|
||||
# [proposal_49 / 2026-05-15] 설거지 방지 규칙 통합 명문화 — anti_climax_buy_gate
|
||||
anti_climax_buy_gate:
|
||||
purpose: "급등 클라이맥스·주도주 설거지 구간을 정량적으로 차단한다. 5개 신호 중 3개 이상 = 신규매수 전면 금지."
|
||||
signals:
|
||||
S1_surge_5d:
|
||||
formula: "Ret5D_종목 >= 25%"
|
||||
meaning: "최근 5거래일 수익률 +25% 이상 급등"
|
||||
score: 1
|
||||
data: "data_feed 탭 Ret5D 또는 직접 계산"
|
||||
S2_volume_climax:
|
||||
formula: "AvgTradeValue_5D_M >= AvgTradeValue_20D_M * 3.0"
|
||||
meaning: "5일 평균거래대금이 20일 평균의 300% 이상 (클라이맥스 물량)"
|
||||
score: 1
|
||||
S3_upper_wick:
|
||||
formula: "(High - Close) / max(High - Low, 1) >= 0.35 AND High > 전고점"
|
||||
meaning: "당일 윗꼬리 비율 35% 이상 + 전고점 돌파 후 음봉 반전"
|
||||
score: 1
|
||||
S4_smart_money_exit:
|
||||
formula: "Frg_5D < 0 AND Inst_5D < 0"
|
||||
meaning: "외국인 AND 기관 5D 동반 순매도 전환 (스마트머니 이탈)"
|
||||
score: 1
|
||||
S5_retail_frenzy:
|
||||
formula: "Ind_5D > 0 AND (Frg_5D < 0 OR Inst_5D < 0)"
|
||||
meaning: "개인 순매수 + 외국인·기관 이탈 (뒤늦은 개인 매수 = 설거지 패턴)"
|
||||
score: 1
|
||||
gate_rule:
|
||||
buy_ban: "합계 >= 3 → 신규 매수 금지 (탐색매수 포함)"
|
||||
caution: "합계 == 2 → 매수 허용하나 수량 50% 축소 + 사유 명시"
|
||||
clear: "합계 <= 1 → gate 통과"
|
||||
recheck_timing: # [proposal_76 / 2026-05-15] T+1 재확인 기준시각·데이터 명시
|
||||
purpose: "탐색 후보 T+1 진입 전 anti_climax 재확인의 정확한 시점과 데이터 기준"
|
||||
execution_time: "T+1 08:30 이전 (개장 30분 전까지 완료)"
|
||||
data_reference:
|
||||
base_date: "T-1 (등재 전일) 20:00 시점 최신 확정 데이터"
|
||||
S1_S2_S3: "T-1 종가 OHLC 기준"
|
||||
S4_S5: "T-1 20:00까지의 5D 누적 신호 기준"
|
||||
prohibition:
|
||||
- "T+1 장중 데이터로 anti_climax 재판정 금지 (미확정 데이터 혼용)"
|
||||
- "T+1 09:00 이후 재확인 시도로 진입 지연 허용 금지"
|
||||
fallback: "T+1 08:30까지 데이터 수집 불가 시 → anti_climax 신호 합계 3으로 보수 처리 (매수 보류)"
|
||||
prohibition:
|
||||
- "anti_climax_buy_gate 발동 중 daily_leader_scan 탐색 후보 종목도 매수 금지"
|
||||
- "gate 발동 중 pullback_reentry_rule 재진입도 금지"
|
||||
- "5억 목표 압박을 이유로 gate 해제 금지 (→ master_prohibitions.P3)"
|
||||
output_table:
|
||||
columns: ["종목명", "S1", "S2", "S3", "S4", "S5", "합계", "gate판정", "가능수량비율"]
|
||||
|
||||
# [proposal_48 / 2026-05-15] 3단계 탐색매수 체계 — staged_entry_v2
|
||||
@@ -0,0 +1,40 @@
|
||||
schema_version: macro_event_synchronizer.v2
|
||||
formula_id: MACRO_EVENT_SYNCHRONIZER_V2
|
||||
purpose: >
|
||||
macro/event rows are CONTEXT_ONLY inputs and must not be used to create prices.
|
||||
P1-013: macro_risk_score -> position_size_scale + cash_target_pct 자동 조정.
|
||||
python_tool: tools/build_macro_event_synchronizer_v2.py
|
||||
|
||||
required_metrics:
|
||||
- macro_event_rows_freshness_hours # <= 24
|
||||
- event_hold_gate_coverage # == 100%
|
||||
- position_size_scale_wired # == 100 (JSON 제공됨)
|
||||
- external_context_used_for_price_count # == 0
|
||||
- position_size_scale # NEW: macro_risk_score에서 산출
|
||||
- cash_target_pct # NEW: macro_risk_score에서 산출
|
||||
|
||||
# -- position_size_scale 산출 공식 (P1-013 신규) --
|
||||
position_size_scale_formula:
|
||||
input: macro_risk_score # hApex.macro_risk_score (0~100)
|
||||
table:
|
||||
NORMAL: {threshold: "<20", scale: 1.00, cash_target_pct: 5.0}
|
||||
CAUTION: {threshold: "20-40", scale: 0.75, cash_target_pct: 15.0}
|
||||
HIGH_RISK: {threshold: "40-60", scale: 0.50, cash_target_pct: 25.0}
|
||||
VERY_HIGH: {threshold: "60-80", scale: 0.25, cash_target_pct: 40.0}
|
||||
EXTREME: {threshold: ">=80", scale: 0.00, cash_target_pct: 60.0}
|
||||
note: >
|
||||
scale은 주문 수량 상한 계수. scale=0.5이면 기준 수량의 50% 이하만 집행.
|
||||
EXTREME(scale=0.00)이면 신규 매수 금지.
|
||||
|
||||
# -- event_hold_gate --
|
||||
event_hold_gate:
|
||||
pre_guard_days: 5 # HIGH Impact 이벤트 5일 전부터 신규 BUY 차단
|
||||
post_guard_days: 2 # 이벤트 후 2일 포지션 축소 구간
|
||||
applies_to: HIGH,VERY_HIGH # MEDIUM 이벤트는 WATCH만
|
||||
|
||||
# -- 금지 사항 --
|
||||
prohibitions:
|
||||
- "macro/event 외부 데이터를 주문 가격 산출에 직접 사용 금지"
|
||||
- "event_hold 종목 guard 구간 내 신규 BUY 금지"
|
||||
- "position_size_scale=0.00(EXTREME)에서 신규 진입 금지"
|
||||
- "macro_risk_score 변경 없이 position_size_scale 임의 수정 금지"
|
||||
@@ -0,0 +1,80 @@
|
||||
formula_id: PRE_DISTRIBUTION_EARLY_WARNING_V3
|
||||
version: "2026-06-03_P0-009"
|
||||
purpose: >
|
||||
5개 분산 feature의 가중합으로 DISTRIBUTION_CONFIRMED(≥4) 또는 WARNING(2~3)을 판정한다.
|
||||
CONFIRMED 종목 신규 BUY를 즉시 차단하고 TRIM_REVIEW를 권고한다. 손절 이탈 전에 설거지 구간을 포착한다.
|
||||
|
||||
features:
|
||||
F1:
|
||||
name: DISTRIBUTION_DETECTOR_SIGNALS_GE2
|
||||
condition: "distribution_sell_detector.signals_count >= 2"
|
||||
weight: 1
|
||||
F2:
|
||||
name: RUNUP_WITH_WEAK_SMART_MONEY
|
||||
condition: "velocity_1d >= 3.0% AND smart_money_score < 50"
|
||||
weight: 1
|
||||
F3:
|
||||
name: RSI_OVERBOUGHT_GE75
|
||||
condition: "rsi14 >= 75"
|
||||
weight: 1
|
||||
F4:
|
||||
name: PRICE_REVERSAL_AFTER_SURGE
|
||||
condition: "ret5d < 0 AND velocity_5d > 5%"
|
||||
weight: 1
|
||||
F5:
|
||||
name: DISTRIBUTION_VERDICT_ACTIVE
|
||||
condition: "distribution_sell_detector.distribution_verdict contains DISTRIBUTION"
|
||||
weight: 1
|
||||
|
||||
verdicts:
|
||||
DISTRIBUTION_CONFIRMED:
|
||||
threshold: "weighted_sum >= 4"
|
||||
action: TRIM_REVIEW
|
||||
buy_blocked: true
|
||||
WARNING:
|
||||
threshold: "2 <= weighted_sum < 4"
|
||||
action: WATCH_TRIM_CANDIDATE
|
||||
buy_blocked: false
|
||||
CLEAR:
|
||||
threshold: "weighted_sum < 2"
|
||||
action: HOLD_MONITOR
|
||||
buy_blocked: false
|
||||
|
||||
acceptance_criteria:
|
||||
distribution_confirmed_buy_count: "== 0"
|
||||
warning_to_trim_lag_days: "<= 1"
|
||||
distribution_t5_down_capture_rate_pct: ">= 60 (표본 축적 후)"
|
||||
false_distribution_rate_pct: "<= 35"
|
||||
|
||||
effectiveness_tracking:
|
||||
formula_id: DISTRIBUTION_BLOCK_EFFECTIVENESS_V1
|
||||
rationale: "weighted_sum>=4 차단이 실제로 손실을 회피했는지(차단 종목의 T+5 수익률)를 측정해야 임계값을 데이터로 보정 가능"
|
||||
implementation:
|
||||
- step: 1
|
||||
desc: "weighted_sum>=4로 BUY 차단된 종목 리스트와 차단일 기록"
|
||||
- step: 2
|
||||
desc: "차단 후 T+5 가상 수익률(차단 안 했다면) 계산. 음(-)이면 차단 정당(avoided_loss)"
|
||||
- step: 3
|
||||
desc: "avoided_loss_rate = 음수 비율. 목표 >= 60%(차단의 60% 이상이 실제 손실 회피)"
|
||||
- step: 4
|
||||
desc: "60% 미만이면 임계값(4.0) 조정 후보 제시(자동 적용 금지, 권고만)"
|
||||
metrics:
|
||||
avoided_loss_rate:
|
||||
current: null
|
||||
target: ">= 0.60"
|
||||
label: "[UNVALIDATED_LOW_N: 표본 미달]"
|
||||
source: Temp/distribution_block_effectiveness_v1.json.avoided_loss_rate
|
||||
blocked_sample_count:
|
||||
current: 0
|
||||
target: ">= 30"
|
||||
output:
|
||||
- Temp/distribution_block_effectiveness_v1.json.avoided_loss_rate
|
||||
python_tool: tools/build_distribution_exit_presignal_v2.py
|
||||
gs_coverage: "gas_apex_alpha_watch.gs:trackDistributionBlockEffectiveness_()"
|
||||
validator: "tools/validate_distribution_exit_presignal_v2.py"
|
||||
acceptance: "avoided_loss_rate >= 0.60 OR [UNVALIDATED_LOW_N] 라벨 부착"
|
||||
|
||||
llm_prohibition:
|
||||
- "LLM이 distribution_verdict를 재판단하거나 번복하는 것을 금지"
|
||||
- "CONFIRMED BUY 권고 금지"
|
||||
- "avoided_loss_rate 미산출 상태에서 임계값(4.0) 자동 조정 금지"
|
||||
@@ -0,0 +1,4 @@
|
||||
schema_version: pre_distribution_early_warning.v4
|
||||
parent_file: spec/strategy/pre_distribution_early_warning_v3.yaml
|
||||
formula_id: PRE_DISTRIBUTION_EARLY_WARNING_V4
|
||||
purpose: Early warning gate for distribution risk.
|
||||
@@ -0,0 +1,19 @@
|
||||
formula_id: PREDICTIVE_ALPHA_DIALECTIC_ENGINE_V1
|
||||
name: 정반합 사전 예측 알파 엔진 (Predictive Alpha Dialectic Engine)
|
||||
description: 펀더멘털과 수급의 추세(正)와 거시 리스크 및 스마트머니 이탈(反)을 가중 합산하여 신규 진입 및 보유 판단(合)을 수행합니다. LLM 개입 없이 결정론적으로 BEARISH 종목을 차단합니다.
|
||||
rules:
|
||||
- id: PAD001
|
||||
condition: "thesis_score - (antithesis_score * macro_event_multiplier) <= -20"
|
||||
action: "BLOCK_BUY"
|
||||
reason: "정반합 종합 평가: BEARISH (거시/수급 리스크가 펀더멘털 우위를 압도)"
|
||||
- id: PAD002
|
||||
condition: "antithesis_score > 50 AND recent_surge_pct > 15"
|
||||
action: "TRIGGER_PROACTIVE_SELL_RADAR"
|
||||
reason: "단기 급등 후 스마트머니 이탈 및 거래량 급감 (설거지 징후)"
|
||||
output:
|
||||
schema: predictive_alpha_dialectic_json
|
||||
fields:
|
||||
- thesis_score: NUMBER
|
||||
- antithesis_score: NUMBER
|
||||
- synthesis_verdict: STRING (BULLISH, NEUTRAL, BEARISH)
|
||||
- action_allowed: BOOLEAN
|
||||
@@ -0,0 +1,89 @@
|
||||
# spec/strategy/predictive_alpha_dialectic_v2.yaml
|
||||
# P1-014: Dialectical Predictive Alpha V2 - Synthesis Decile Calibration
|
||||
#
|
||||
# 목적: thesis-antithesis-synthesis 점수가 forward return과 연결되는지 검증.
|
||||
# 현재 상태: BEARISH_SAFE_PENDING_CALIBRATION
|
||||
# - bearish_buy_violations = 0 (PASS)
|
||||
# - synthesis_decile_monotonicity = INSUFFICIENT_DATA (T+20 < 30)
|
||||
|
||||
meta:
|
||||
formula_id: PREDICTIVE_ALPHA_CALIBRATION_V2
|
||||
version: "2026-06-06"
|
||||
python_tools:
|
||||
- tools/build_predictive_alpha_dialectic_engine_v2.py
|
||||
- tools/validate_predictive_alpha_dialectic_v2.py
|
||||
sources:
|
||||
- Temp/predictive_alpha_engine_v2.json
|
||||
- Temp/proposal_evaluation_history.json
|
||||
- Temp/predictive_alpha_calibration_v2.json
|
||||
|
||||
# -- 정반합 구조 --
|
||||
dialectic_structure:
|
||||
thesis:
|
||||
description: "종목이 상승할 근거 (기술적/펀더멘털/모멘텀 팩터)"
|
||||
max_score: 100
|
||||
antithesis:
|
||||
description: "종목이 하락할 근거 (거시/리스크/센티멘트 팩터)"
|
||||
max_score: 100
|
||||
single_factor_cap: "antithesis_total의 50% 이하"
|
||||
synthesis:
|
||||
formula: "direction_confidence = thesis_score - antithesis_score"
|
||||
verdicts:
|
||||
STRONG_BULLISH: "dc >= 40"
|
||||
BULLISH: "dc >= 20"
|
||||
NEUTRAL: "dc >= -20"
|
||||
HOLD: "dc < -20 (약한 약세 — EXIT 아님)"
|
||||
BEARISH: "dc < -40 (신규 BUY 금지)"
|
||||
|
||||
# -- synthesis_decile_monotonicity 검증 --
|
||||
decile_monotonicity:
|
||||
method: "synthesis_score 5분위별 T+20 평균수익률 단조 증가 확인"
|
||||
required_t20_samples: 30
|
||||
current_t20_live_samples: 0
|
||||
status: INSUFFICIENT_DATA
|
||||
remediation: "T+20 LIVE 표본 30건 축적 후 자동 활성화 (~2026-07-15)"
|
||||
threshold_rule: >
|
||||
높은 decile일수록 기대수익 단조 증가하지 않으면
|
||||
threshold 낮추지 않음 (과최적화 방지)
|
||||
|
||||
# -- BEARISH BUY 차단 --
|
||||
bearish_buy_guard:
|
||||
rule: "synthesis_verdict in BEARISH/STRONG_BEARISH/AVOID → BUY 금지"
|
||||
current_violations: 0
|
||||
status: PASS
|
||||
enforcement: "allow_execution=False when direction_confidence < -40"
|
||||
|
||||
# -- alpha_calibration_gate 판정 로직 --
|
||||
calibration_gate:
|
||||
CALIBRATED:
|
||||
requires: "bearish_violations==0 AND synthesis_decile_monotonicity==PASS"
|
||||
status: NOT_YET
|
||||
BEARISH_SAFE_PENDING_CALIBRATION:
|
||||
requires: "bearish_violations==0 AND T+20<30"
|
||||
status: CURRENT
|
||||
BLOCKED_BEARISH_VIOLATION:
|
||||
requires: "bearish BUY 감지됨"
|
||||
status: GUARD_ACTIVE
|
||||
|
||||
# -- 수락 기준 --
|
||||
acceptance_criteria:
|
||||
alpha_calibration_gate:
|
||||
target: CALIBRATED
|
||||
current: BEARISH_SAFE_PENDING_CALIBRATION
|
||||
status: PENDING_DATA
|
||||
remediation: "T+20 LIVE 표본 축적 (~2026-07-15)"
|
||||
synthesis_decile_monotonicity:
|
||||
target: PASS
|
||||
current: INSUFFICIENT_DATA
|
||||
status: PENDING_DATA
|
||||
bearish_buy_violation_count:
|
||||
target: "==0"
|
||||
current: 0
|
||||
status: PASS
|
||||
|
||||
# -- 금지 사항 --
|
||||
prohibitions:
|
||||
- "BEARISH 판정 종목에 BUY/STRONG_BUY 제안 금지"
|
||||
- "T+20 표본 없이 synthesis_decile_monotonicity=PASS 선언 금지"
|
||||
- "decile monotonicity 미검증 상태에서 threshold 하향 조정 금지"
|
||||
- "antithesis 단일 팩터가 50% 이상 점수 차지 금지"
|
||||
@@ -0,0 +1,31 @@
|
||||
meta:
|
||||
title: "은퇴자산포트폴리오 — 리밸런싱 트리거 분할 후보"
|
||||
parent_file: "spec/04_strategy_rules.yaml"
|
||||
version: "2026-05-15-F8_split"
|
||||
language: "ko-KR"
|
||||
timezone: "Asia/Seoul"
|
||||
role: "canonical"
|
||||
migration_status: "canonical_split_active"
|
||||
authority_rule: "이 split 파일이 해당 섹션의 canonical source다. parent_file은 legacy compatibility index다."
|
||||
|
||||
rebalancing_trigger:
|
||||
weed_out_rule:
|
||||
rule: "물타기 방지: 리밸런싱 매수 전 해당 종목 1M 상대강도 하위 30% 또는 20D 수급 음수 시 매수를 영구 차단하고, 주도주로 자금을 이동한다."
|
||||
threshold:
|
||||
relative_band: "개별 자산이 목표비중 대비 ±20% 이탈 시 점검"
|
||||
absolute_band: "단일 종목이 목표비중보다 절대값 5%p 이상 초과 시 부분 리밸런싱 검토"
|
||||
benchmark_leader_band: "KOSPI 시장지배 주도주는 벤치마크 비중 대비 +10%p 초과 시 점검, +15%p 초과 시 신규매수 금지"
|
||||
duplicate_factor_band: "동일 팩터 직접+ETF 실질노출이 상한 초과 시 ETF부터 축소"
|
||||
regime_adaptive:
|
||||
regime_source: "macro_snapshot VIX_Close 기준. Risk-On: VIX < 18 AND KOSPI 20일선 위; Risk-Off: VIX > 25 OR KOSPI 20일·60일선 동시 하회; Neutral: 그 외 구간. (VIX 기준: macro 탭 VIX_Close, KOSPI 이동평균: data_feed 탭 MA20·MA60 컬럼)"
|
||||
Risk-On: "목표비중 대비 +15%p 초과 시 점검 (주도주 수익 극대화 용인)"
|
||||
Neutral: "목표비중 대비 ±5%p 이탈 시 점검"
|
||||
Risk-Off: "목표비중 대비 +2%p 초과 시 즉각 축소 (방어적 리밸런싱 강제)"
|
||||
prohibition: "Risk-Off 국면에서 회복 기대를 이유로 +2%p 초과 리밸런싱 연기 금지"
|
||||
action:
|
||||
- "전체 포트폴리오를 흔들지 않고 이탈 자산만 목표비중 근처로 복귀."
|
||||
- "매도는 전량이 아니라 1차 30%, 2차 30%, 3차 잔여 조정 방식."
|
||||
- "세금·수수료·유동성·호가공백이 불리하면 즉시 리밸런싱 대신 조건부."
|
||||
- "비용 최적화: |목표비중 - 현재비중| - (예상 거래세 및 수수료 환산비율) > 0.5%p 일 때만 실질적인 리밸런싱을 실행하여 과매매를 방지한다."
|
||||
priority: ["bankruptcy", "risk_control", "market_context", "portfolio_exposure_framework.special_exception", "portfolio_exposure_framework"] # [P134] 순환 참조 제거, [R3] special_exception 경로 완전 한정
|
||||
priority_note: "위 5개 규칙 충족 후에만 rebalancing_trigger.threshold·action 적용. 자체 참조 금지."
|
||||
@@ -0,0 +1,68 @@
|
||||
meta:
|
||||
title: "은퇴자산포트폴리오 — 섹터 모델 분할 후보"
|
||||
parent_file: "spec/04_strategy_rules.yaml"
|
||||
version: "2026-05-15-F8_split"
|
||||
language: "ko-KR"
|
||||
timezone: "Asia/Seoul"
|
||||
role: "canonical"
|
||||
migration_status: "canonical_split_active"
|
||||
authority_rule: "이 split 파일이 해당 섹션의 canonical source다. parent_file은 legacy compatibility index다."
|
||||
|
||||
sector_model:
|
||||
score_axes: ["1M/3M 상대강도", "거래대금", "외국인·기관 수급", "실적전망", "거시환경", "밸류에이션"]
|
||||
score_axes_formula: # [P128] 100점 만점 채점 공식 — A_core/B_wait/C_watch/D_exclude 임계치 근거
|
||||
total: 100
|
||||
components:
|
||||
price_strength: {axis: "1M/3M 상대강도", weight: 25, score_rule: "섹터 내 1M 상대강도 상위 30% 이내→25점; 30~60%→15점; 60% 초과→0점"}
|
||||
volume_quality: {axis: "거래대금", weight: 15, score_rule: "5D 거래대금 20D 평균 대비 120% 이상→15점; 80~120%→8점; 미만→0점. ETF proxy는 etf_raw.ETF_Liquidity_Score를 별도 반영"}
|
||||
flow_quality: {axis: "외국인·기관 수급", weight: 25, score_rule: "sector_flow 기준 Sector_Flow_Quality = 0.6×SmartMoney_5D_Norm_Score + 0.4×Flow_Breadth_5D_Score. legacy sector_flow 단독으로 A_core 근거 금지"}
|
||||
earnings_revision: {axis: "실적전망", weight: 20, score_rule: "컨센서스 EPS 상향→20점; 유지→10점; 하향→0점"}
|
||||
macro_regime: {axis: "거시환경", weight: 10, score_rule: "Risk-On(VIX<18, KOSPI>MA20)→10점; Neutral→5점; Risk-Off→0점"}
|
||||
valuation: {axis: "밸류에이션", weight: 5, score_rule: "PER/PBR 섹터 평균 이하→5점; 평균~1.5배→2점; 1.5배 초과→0점"}
|
||||
flow_credit_definition_xref: "quant_feed_contract.investor_flow_rules.active_quality_gate.formula # 종목 단위 flow_credit 정의 위치. 섹터 단위는 sector_flow 원화 수급·확산도 우선."
|
||||
prohibition: "점수 미산출 시 A_core 판정 금지. 데이터 누락 축은 0점 처리 후 DATA_MISSING 표시. sector_flow.Data_Quality가 C 또는 D이면 Strong_Buy 및 섹터 단독 Strong_Sell 금지. sector_universe.Is_ETF=Y 행은 구성종목 수급 집계에서 제외한다."
|
||||
grade:
|
||||
alias_of: "recommendation_grade" # [ALIAS / proposal_118] A_core=A, B_wait=B, C_watch=C, D_exclude=D. 기준은 recommendation_grade 참조.
|
||||
A_core: "80점 이상 (원시데이터 80% 이상 확인, 비용차감 기대수익비 2:1 이상, 돌파 직후가 아니라 확인 후 진입)"
|
||||
B_wait: "65~79점 또는 가격 과열, 신고가 직후·장대양봉 직후는 대기"
|
||||
C_watch: "50~64점 또는 데이터 일부 누락"
|
||||
D_exclude: "50점 미만 또는 핵심 데이터 충돌"
|
||||
missing_data_rule: ["가격·수급·거래대금 중 2개 이상 누락 시 최대 C-관찰", "프록시만으로 A등급 금지", "점수 개선 당일 추격매수 금지", "신고가/돌파 당일은 시범진입만 허용하고 본진입은 다음 거래일 확인 후"]
|
||||
core_satellite_classification_score:
|
||||
purpose: >
|
||||
종목의 처우(trailing band·time-stop·risk_budget)를 결정하기 위한
|
||||
단일 분류 기준. 진입 판단과 무관하며 진입 이후 처우 기준 통일 목적.
|
||||
formula: "CSCS = W1×kospi_weight_factor(0.30) + W2×flow_strength_20d(0.30) + W3×holding_stability(0.20) + W4×atr_stability(0.20)"
|
||||
weights:
|
||||
W1_kospi_weight_factor:
|
||||
weight: 0.30
|
||||
scoring: "KOSPI 시총 비중 >=1%:100pt / 0.5~1%:70pt / 0.1~0.5%:40pt / <0.1%:10pt. KOSDAQ종목:0pt."
|
||||
W2_flow_strength_20d:
|
||||
weight: 0.30
|
||||
scoring: "Frg_20D+Inst_20D 합산 양수&Flow_Rows>=20:100pt / 어느 하나만 양수:60pt / 둘 다 음수:0pt. Flow_OK=N:0pt."
|
||||
W3_holding_stability:
|
||||
weight: 0.20
|
||||
scoring: "보유 >=60거래일:100pt / 30~59:70pt / 10~29:40pt / <10거래일:0pt. 보유기간 미확인:50pt(중립)."
|
||||
W4_atr_stability:
|
||||
weight: 0.20
|
||||
scoring: "ATR20_Pct <3%:100pt / 3~5%:70pt / 5~8%:40pt / >=8%:10pt. ATR20 DATA_MISSING:50pt(중립)."
|
||||
classification:
|
||||
core: "CSCS >= 70 → 코어 처우"
|
||||
satellite: "CSCS < 70 → 위성 처우"
|
||||
treatment_mapping:
|
||||
core_treatment:
|
||||
trailing_bands: "take_profit.trailing_stop.core_large_cap"
|
||||
time_stop: "stop_loss.time_stop.core"
|
||||
risk_budget_cap: "단일 종목 총자산 1.0~1.2% 이내"
|
||||
satellite_treatment:
|
||||
trailing_bands: "take_profit.trailing_stop.satellite_trigger"
|
||||
time_stop: "stop_loss.time_stop.satellite"
|
||||
risk_budget_cap: "단일 종목 총자산 0.7~1.0% 이내"
|
||||
special_exception:
|
||||
- "삼성전자(005930)·SK하이닉스(000660): CSCS 계산 없이 항상 core 처우. special_exception.kospi_semiconductor_leadership 우선."
|
||||
hard_rules:
|
||||
- "CSCS 미산출 종목: 보유비중으로 수동 판단. 코어/위성 자동 구분 금지."
|
||||
- "W2·W4가 DATA_MISSING이면 해당 항목 50pt 중립 처리."
|
||||
- "CSCS는 진입 결정이 아닌 진입 후 처우 결정에만 사용."
|
||||
output_required:
|
||||
columns: ["종목명", "CSCS점수", "W1", "W2", "W3", "W4", "분류(코어/위성)", "적용_trailing", "time_stop_기준일"]
|
||||
@@ -0,0 +1,162 @@
|
||||
# spec/strategy/semiconductor_concentration_policy.yaml
|
||||
# 반도체 집중 허용 정책 — MARKET_WEIGHT_AWARE_CLUSTER_GATE_V1
|
||||
# ────────────────────────────────────────────────────────────────────────────
|
||||
# 배경:
|
||||
# 한국 KOSPI 시장에서 삼성전자+SK하이닉스는 시총 비중 35%+를 차지한다.
|
||||
# 기존 고정 25% 한도는 이 두 종목이 주도하는 상승장에서 시장 대비 필연적
|
||||
# 언더퍼폼을 강제한다. 분산은 목적이 아니라 리스크 관리 수단이며,
|
||||
# 주도주 집중 전략이 유효한 국면에서는 시장 비중만큼은 허용해야 한다.
|
||||
#
|
||||
# 원칙:
|
||||
# 1. 시장 비중(KOSPI_SEMI_WEIGHT) 이하는 항상 PASS — 시장 중립 포지션
|
||||
# 2. RISK_ON 국면에서는 시장 비중 1.3배까지 허용 (능동적 과중비중)
|
||||
# 3. SECULAR_LEADER 국면에서는 65%까지 허용 (주도주 집중 전략)
|
||||
# 4. RISK_OFF / EVENT_SHOCK에서는 시장 비중 × 0.7로 축소 (방어)
|
||||
# 5. 한도 초과 시 BLOCK이 아닌 WARN/TRIM — 설거지 구간에서만 BLOCK
|
||||
# ────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
formula_id: MARKET_WEIGHT_AWARE_CLUSTER_GATE_V1
|
||||
|
||||
# KOSPI 반도체 시총 비중 — settings 시트에서 사용자가 직접 입력해야 함
|
||||
# 주의: 하드코딩 기본값 없음. 시총 비중은 KRX/FnGuide 실데이터 기준으로만 입력.
|
||||
# 미입력 시 GAS는 DATA_MISSING 상태로 동작 (정책 한도만 적용, 시장비중 × 배수 미적용)
|
||||
kospi_weights_settings_keys:
|
||||
kospi_semi_weight_pct: "settings 시트 key — 삼성전자+SK하이닉스 합산 KOSPI 비중 (%)"
|
||||
kospi_samsung_weight_pct: "settings 시트 key — 삼성전자 단독 KOSPI 비중 (%)"
|
||||
kospi_hynix_weight_pct: "settings 시트 key — SK하이닉스 단독 KOSPI 비중 (%)"
|
||||
data_source: "KRX 또는 FnGuide 시총 비중 데이터 (최소 월 1회 갱신 권장)"
|
||||
critical_note: |
|
||||
KOSPI 내 삼성전자·SK하이닉스 비중은 시장 상황에 따라 크게 변동한다.
|
||||
어떠한 추정치도 settings 미입력 시 코드에 삽입하지 않는다.
|
||||
반드시 사용자가 실제 시총 데이터 기반으로 직접 입력해야 한다.
|
||||
|
||||
# ── 반도체 클러스터 한도 (동적) ─────────────────────────────────────────────
|
||||
cluster_cap_table:
|
||||
EVENT_SHOCK:
|
||||
cap_pct: "max(20, kospi_semi_weight × 0.60)"
|
||||
default: 21.0
|
||||
rationale: "이벤트 충격: 시장 비중의 60%로 방어 축소"
|
||||
gate_behavior: "초과 시 CLUSTER_BLOCK (신규 BUY 전면 금지)"
|
||||
|
||||
RISK_OFF:
|
||||
cap_pct: "max(25, kospi_semi_weight × 0.80)"
|
||||
default: 28.0
|
||||
rationale: "하락장: 시장 비중의 80%까지만 유지"
|
||||
gate_behavior: "초과 시 CLUSTER_BLOCK"
|
||||
|
||||
NEUTRAL:
|
||||
cap_pct: "max(35, kospi_semi_weight × 1.00)"
|
||||
default: 35.0
|
||||
rationale: "중립: 시장 비중 매칭까지 허용 (PASS)"
|
||||
gate_behavior: "초과 시 CLUSTER_OVERWEIGHT_TRIM (BUY 금지, 점진 감축)"
|
||||
change_from_old: "25% → 35% (시장 중립 허용)"
|
||||
|
||||
RISK_ON:
|
||||
cap_pct: "max(45, kospi_semi_weight × 1.30)"
|
||||
default: 45.0
|
||||
rationale: "상승장: 반도체 주도 시 시장 비중 130%까지 능동 과중비중 허용"
|
||||
gate_behavior: "초과 시 CLUSTER_OVERWEIGHT_WARN (BUY 신중, 강제 감축 아님)"
|
||||
change_from_old: "25% → 45% (반도체 주도 상승장 적극 참여 허용)"
|
||||
|
||||
SECULAR_LEADER_RISK_ON:
|
||||
cap_pct: 65.0
|
||||
rationale: "주도주 집중 전략: 삼성+하이닉스 양 종목 최대 보유"
|
||||
gate_behavior: "초과 시 CLUSTER_OVERWEIGHT_TRIM"
|
||||
change_from_old: "60% → 65%"
|
||||
|
||||
CLA:
|
||||
cap_pct: 65.0
|
||||
rationale: "CONCENTRATED_LEADER_ADVANCE: SECULAR_LEADER_RISK_ON과 동일"
|
||||
gate_behavior: "초과 시 CLUSTER_OVERWEIGHT_TRIM"
|
||||
|
||||
# 게이트 상태 정의 (변경)
|
||||
gate_status_definitions:
|
||||
PASS: "combined_pct < kospi_semi_weight × 0.90 — 시장 비중 90% 이하"
|
||||
CLUSTER_OVERWEIGHT_WARN: "combined_pct < regime_cap — 주의 모니터링, BUY 신중"
|
||||
CLUSTER_OVERWEIGHT_TRIM: "combined_pct >= regime_cap (non-RISK_OFF) — 감축 검토"
|
||||
CLUSTER_BLOCK: "combined_pct >= regime_cap (RISK_OFF/EVENT_SHOCK) — 신규 BUY 금지"
|
||||
CLUSTER_HOLD_ONLY: "isCLA AND combined_pct < cap — 보유만, 추가 매수 금지"
|
||||
|
||||
# ── 개별 종목 비중 한도 (LEADER_POSITION_WEIGHT_CAP_V1) ────────────────────
|
||||
leader_position_cap_table:
|
||||
description: |
|
||||
005930(삼성전자), 000660(SK하이닉스)는 KOSPI 주도주로서
|
||||
일반 종목 상한(20%)과 별도로 시장 비중 기반 상한을 적용한다.
|
||||
|
||||
# 모든 한도는 EXPERT_PRIOR (calibration_registry.yaml 등록).
|
||||
# KOSPI 비중이 settings에 입력되면 max(정책한도, kospi_weight × 배수) 적용.
|
||||
# KOSPI 비중 미입력 시 정책 한도만 적용 (추정치 삽입 금지).
|
||||
samsung_005930:
|
||||
EVENT_SHOCK: 15.0
|
||||
RISK_OFF: 18.0
|
||||
NEUTRAL: 28.0 # kospi_samsung_weight 입력 시: max(28, weight×1.20)
|
||||
RISK_ON: 40.0 # kospi_samsung_weight 입력 시: max(40, weight×1.70)
|
||||
SECULAR_LEADER_RISK_ON: 50.0 # 입력 시: max(50, weight×2.20)
|
||||
|
||||
skhynix_000660:
|
||||
EVENT_SHOCK: 10.0
|
||||
RISK_OFF: 12.0
|
||||
NEUTRAL: 15.0 # kospi_hynix_weight 입력 시: max(15, weight×1.20)
|
||||
RISK_ON: 22.0 # 입력 시: max(22, weight×1.80)
|
||||
SECULAR_LEADER_RISK_ON: 28.0 # 입력 시: max(28, weight×2.50)
|
||||
|
||||
other_stocks:
|
||||
EVENT_SHOCK: 12.0
|
||||
RISK_OFF: 15.0
|
||||
NEUTRAL: 20.0
|
||||
RISK_ON: 22.0
|
||||
SECULAR_LEADER_RISK_ON: 25.0
|
||||
|
||||
# ── SECULAR_LEADER 자동 감지 조건 ───────────────────────────────────────────
|
||||
secular_leader_auto_detect_conditions:
|
||||
description: |
|
||||
RISK_ON 국면에서 아래 조건이 충족되면 SECULAR_LEADER_RISK_ON으로
|
||||
자동 상향 → 클러스터/단일종목 한도 완화 적용.
|
||||
conditions:
|
||||
- id: SL1
|
||||
description: "RS비율: 삼성전자 또는 SK하이닉스의 RS_Ratio >= 1.5 (5일 연속)"
|
||||
weight: 3
|
||||
- id: SL2
|
||||
description: "수급: 외인+기관 삼성전자 또는 SK하이닉스 동반순매수 3일 이상"
|
||||
weight: 2
|
||||
- id: SL3
|
||||
description: "섹터: 반도체 섹터 5일 수익률 KOSPI 대비 +5% 이상 초과"
|
||||
weight: 2
|
||||
- id: SL4
|
||||
description: "거래대금: 반도체 섹터 5일 평균 거래대금 > 20일 평균 × 1.3"
|
||||
weight: 1
|
||||
threshold: "합산 ≥ 6점 → SECULAR_LEADER_RISK_ON 자동 진입"
|
||||
exit_conditions:
|
||||
- "RS_Ratio < 1.0 (3일 연속)"
|
||||
- "외인+기관 동반순매도 5일"
|
||||
- "DISTRIBUTION_SELL_DETECTOR_V1.weighted_sum >= 4.0"
|
||||
|
||||
# ── 리스크 관리 보완 (집중 시 자동 강화) ────────────────────────────────────
|
||||
concentration_risk_safeguards:
|
||||
description: |
|
||||
반도체 집중도가 높을수록 개별 종목 손절을 더 타이트하게 관리.
|
||||
'몰빵 후 고점 물리기' 방지.
|
||||
rules:
|
||||
- id: CR1
|
||||
trigger: "combined_pct >= 50%"
|
||||
action: "PROFIT_RATCHET_TIERED_V2 강제 활성화 (PROFIT_LOCK_10 이상 구간 진입 즉시)"
|
||||
note: "집중도 높을수록 수익 보호 필수"
|
||||
|
||||
- id: CR2
|
||||
trigger: "combined_pct >= 55% AND DISTRIBUTION_SELL_DETECTOR weighted_sum >= 3.0"
|
||||
action: "K2_STAGED_REBOUND_SELL 즉시 발동 (절반 즉시 매도, 절반 반등 대기)"
|
||||
note: "설거지 구간 + 고집중도 = 즉시 반응"
|
||||
|
||||
- id: CR3
|
||||
trigger: "combined_pct >= 65%"
|
||||
action: "신규 BUY 전면 금지 (SECULAR_LEADER에서도)"
|
||||
note: "65%가 최대 한도 — 이 이상은 포트폴리오 전체 위험"
|
||||
|
||||
# ── 하네스 수치 목표 ─────────────────────────────────────────────────────────
|
||||
performance_targets:
|
||||
cluster_gate_false_positive_rate_max: 5 # 건당 BLOCK인데 실제 손실 없었던 비율
|
||||
cluster_gate_true_positive_rate_min: 85 # 건당 BLOCK이었을 때 실제 손실 방어 비율
|
||||
expected_benchmark_tracking_error_reduction_pct: 30 # 기존 25% 한도 대비 추적오차 감소
|
||||
calibration_status: EXPERT_PRIOR
|
||||
sample_n: 0
|
||||
note: "실측 표본 30건 이상 누적 후 PROVISIONAL → CALIBRATED 승격"
|
||||
@@ -0,0 +1,53 @@
|
||||
formula_id: SMART_MONEY_LIQUIDITY_GATE_V1
|
||||
name: 스마트머니 및 유동성 게이트 (Smart Money Liquidity Gate)
|
||||
description: 기관/외국인의 수급 동향과 호가창 유동성을 실시간 분석하여 뒷북 매수 및 설거지 휩쓸림을 방지합니다.
|
||||
rules:
|
||||
- id: SM001
|
||||
condition: "inst_net_buy_5d < 0 AND frg_net_buy_5d < 0"
|
||||
action: "BLOCK_BUY"
|
||||
reason: "스마트머니 양매도 진행 중 (분산 국면)"
|
||||
- id: SM002
|
||||
condition: "avg_trade_value_5d < 5000000000"
|
||||
action: "LIMIT_QUANTITY"
|
||||
reason: "유동성 부족 상태 (슬리피지 리스크)"
|
||||
- id: SM003
|
||||
condition: "rsi14 > 70 AND flow_credit < 0.3"
|
||||
action: "BLOCK_BUY"
|
||||
reason: "고점 과열 및 수급 약화 (설거지 위험)"
|
||||
output:
|
||||
schema: smart_money_liquidity_json
|
||||
fields:
|
||||
- flow_state: STRING (ACCUMULATION, DISTRIBUTION, NEUTRAL)
|
||||
- liquidity_grade: STRING (HIGH, NORMAL, LOW)
|
||||
- execution_mode: STRING (NORMAL, STAGED_ONLY)
|
||||
|
||||
# ── 신호-결과 연결 (SMART_MONEY_LIQUIDITY_OUTCOME_LINK_V1) ──────────────────
|
||||
evidence_outcome_link:
|
||||
formula_id: SMART_MONEY_LIQUIDITY_OUTCOME_LINK_V1
|
||||
rationale: "수급(외인/기관 순매수)·유동성(FROZEN/THIN/NORMAL/DEEP) 신호가 실제 T+5 수익과 상관 있는지 수치로 확인"
|
||||
implementation:
|
||||
- step: 1
|
||||
desc: "진입 시점 smart_money_score, liquidity_label을 결과(T+5 return)와 조인"
|
||||
- step: 2
|
||||
desc: "liquidity_label별 평균 슬리피지(체결 손실)와 수익률 표를 산출"
|
||||
- step: 3
|
||||
desc: "FROZEN→conviction=0 강제(AGENTS S1)가 실제 손실 회피로 이어졌는지 확인"
|
||||
liquidity_labels:
|
||||
FROZEN: {conviction_override: 0, note: "AGENTS S1 강제 적용"}
|
||||
THIN: {note: "LIMIT_QUANTITY 발동"}
|
||||
NORMAL: {note: "정상 진입 가능"}
|
||||
DEEP: {note: "대형주 슬리피지 최소"}
|
||||
output_table_fields:
|
||||
- liquidity_label
|
||||
- avg_slippage_pct
|
||||
- t5_avg_return_pct
|
||||
- t5_win_rate
|
||||
- sample_count
|
||||
- label # UNVALIDATED 또는 VALIDATED
|
||||
output: Temp/smart_money_liquidity_outcome_link_v1.json
|
||||
python_tool: tools/build_smart_money_liquidity_composite_v3.py
|
||||
gs_coverage: "gas_apex_alpha_watch.gs:linkSmartMoneyOutcome_()"
|
||||
validator: "tools/validate_smart_money_liquidity_evidence_v2.py"
|
||||
acceptance:
|
||||
- "liquidity_label별 슬리피지·수익 표 출력"
|
||||
- "표본 < 30 시 [UNVALIDATED: n={n}] 라벨 부착"
|
||||
@@ -0,0 +1,128 @@
|
||||
meta:
|
||||
title: "은퇴자산포트폴리오 — 단계진입·눌림 재진입"
|
||||
parent_file: "spec/strategy/entry_gates.yaml"
|
||||
version: "2026-05-16-F12_kosdaq_strict"
|
||||
language: "ko-KR"
|
||||
timezone: "Asia/Seoul"
|
||||
role: "canonical"
|
||||
migration_status: "canonical_split_active"
|
||||
|
||||
entry_timing_guardrails:
|
||||
principle: "좋은 종목도 비싸게 사면 수익이 나빠지지만, 강한 장세의 돌파를 놓치는 것도 손실이다. 진입은 추격이 아니라 단계화다."
|
||||
staged_entry:
|
||||
pilot_size: "첫 진입은 계획 수량의 20~30%만."
|
||||
add_size: "확인 후 나머지 70~80%를 분할 집행."
|
||||
no_full_entry: "돌파 첫날이나 뉴스 직후에는 한 번에 전량 진입 금지. 단, 확인 가능한 강세일 때는 2~3회 분할로 빠르게 완성."
|
||||
# [proposal_121 / 2026-05-15] leader_concentration_entry REMOVED — numeric_gates.leader_concentration 참조
|
||||
|
||||
staged_entry_v2:
|
||||
purpose: "기존 staged_entry(2단계 20~30%/70~80%)를 확장. 탐색(0.5~1%) → 확인(1.5~3%) → 주력(4~7%) 3단계로 설거지 없이 주도주 편입."
|
||||
note: "기존 staged_entry 2단계와 공존. 이 섹션이 우선 적용. 탐색매수는 daily_leader_scan 탐색 후보 등재 종목에만 허용."
|
||||
stages:
|
||||
stage_1_explore:
|
||||
size_pct_of_total: "총자산 0.5~1.0%"
|
||||
entry_condition:
|
||||
- "daily_leader_scan 합계 >= 4 (탐색 후보 등재 종목)"
|
||||
- "anti_climax_buy_gate 합계 <= 1 (gate 통과)"
|
||||
- "minimalist_buy_gate 3지표 통과"
|
||||
- "ATR20 확인 완료 (DATA_MISSING 금지 → master_prohibitions.P2)"
|
||||
- "explore_loss_budget 당월 잔액 확인"
|
||||
stop_loss: "매수가 대비 -3~-4% 지정가. 손익은 explore_loss_budget(FC) 계정 귀속."
|
||||
purpose: "정보 탐색 비용으로 소량 진입. 큰 손실 전 빠른 청산."
|
||||
stage_2_confirm:
|
||||
size_pct_of_total: "총자산 1.5~3.0%"
|
||||
entry_condition:
|
||||
- "stage_1 진입 후 가격 +1.5% 이상 상승"
|
||||
- "C2·C4 재확인 (수급·상대강도 지속)"
|
||||
- "anti_climax_buy_gate 합계 <= 1 유지"
|
||||
- "staged_exit_on_stall 10거래일 타임아웃 미경과"
|
||||
stop_loss: "stage_1 매수가 기준 -4~-5% 또는 MA20 이탈"
|
||||
purpose: "추세 확인 후 비중 확대."
|
||||
stage_3_core_load:
|
||||
size_pct_of_total: "총자산 4.0~7.0%"
|
||||
entry_condition:
|
||||
- "20일 신고가 돌파 (종가 기준)"
|
||||
- "C4 수급 지속 (외국인 또는 기관 순매수 유지)"
|
||||
- "sector_priority_ranking Tier_1 유지"
|
||||
- "staged_exit_on_stall 15거래일 타임아웃 미경과"
|
||||
- "aggregate_risk_cap 미초과"
|
||||
stop_loss: "stage_2 매수가 기준 -5~-6% 또는 MA20 -1ATR"
|
||||
purpose: "주력 편입. 검증 완료 종목만."
|
||||
staged_exit_on_stall:
|
||||
# [proposal_64 / 2026-05-15] 탐색 단계 전환 타임아웃 — 슬롯 강제 순환
|
||||
purpose: "단계 전환 미달 시 타임아웃 자동 청산으로 공격 슬롯 순환. '기다리는 것'이 아니라 '기준 시간 내 증명'."
|
||||
stage_1_timeout:
|
||||
timeout_days: 10
|
||||
condition: "10거래일 이내 stage_2 조건 미충족"
|
||||
action: "전량 청산. 지정가(매수가 -0.3~-1.0%). explore_loss_budget(FC) 귀속. 슬롯 해제."
|
||||
cooldown: "동일 종목 5거래일 재탐색 금지"
|
||||
stage_2_timeout:
|
||||
timeout_days: 15
|
||||
condition: "15거래일 이내 stage_3 조건 미충족"
|
||||
action: "stage_2 수량 50% 청산. 잔여 50%는 stage_1 룰 재적용."
|
||||
# [proposal_94 / 2026-05-16] 코스닥 종목 스탈 타임아웃 단축 — 유동성 소멸·모멘텀 소진 조기 대응
|
||||
kosdaq_stall_exit_premium:
|
||||
purpose: "코스닥 종목은 횡보 시 코스피보다 유동성이 빠르게 마르므로 타임아웃을 30% 단축."
|
||||
applicable: "코스닥 상장 종목에만 적용. KOSPI 종목은 기본 timeout_days 유지."
|
||||
stage_1_timeout_kosdaq:
|
||||
timeout_days: 7
|
||||
condition: "7거래일 이내 stage_2 조건 미충족 (KOSPI 10거래일 대비 30% 단축)"
|
||||
action: "전량 청산. 지정가(매수가 -0.3~-1.0%). explore_loss_budget(FC) 귀속. 슬롯 해제."
|
||||
cooldown: "동일 코스닥 종목 7거래일 재탐색 금지 (KOSPI 5거래일보다 2일 추가)"
|
||||
stage_2_timeout_kosdaq:
|
||||
timeout_days: 10
|
||||
condition: "10거래일 이내 stage_3 조건 미충족 (KOSPI 15거래일 대비 33% 단축)"
|
||||
action: "stage_2 수량 50% 청산. 잔여 50%는 stage_1 룰 재적용."
|
||||
prohibition:
|
||||
- "코스닥 종목에 KOSPI 기준 타임아웃(10/15거래일) 적용 금지"
|
||||
- "타임아웃 단축을 이유로 재진입 금지 기간 단축 금지"
|
||||
absolute_exit_override:
|
||||
priority: "타임아웃보다 우선 적용"
|
||||
conditions:
|
||||
- "anti_climax_buy_gate 합계 >= 3 발동"
|
||||
- "relative_weakness_exit RW 신호 >= 4개 발동"
|
||||
- "sector_crash_intraday_protocol tier_B 이상"
|
||||
- "매수가 대비 -4% 이상 하락"
|
||||
action: "타임아웃 전이라도 즉시 청산"
|
||||
prohibition:
|
||||
- "타임아웃 만료 후 '오를 것 같다'는 이유로 청산 연기 금지"
|
||||
- "동일 종목 쿨다운(5거래일) 무시 즉시 재진입 금지"
|
||||
- "stage_2→stage_3 50% 청산 후 잔여 50%에 stage_3 규칙 적용 금지 — stage_1 룰로 관리"
|
||||
prohibition:
|
||||
- "ATR20 DATA_MISSING 종목 stage_1 진입 금지 (→ master_prohibitions.P2)"
|
||||
- "anti_climax_buy_gate >= 3 발동 중 어느 단계도 진입 금지"
|
||||
- "core_load(stage_3) 완료 후 추가 매수 금지 (aggregate_risk_cap 준수)"
|
||||
- "소수점 수량 산출 금지. 정수 단위만."
|
||||
|
||||
# [proposal_59 / 2026-05-15] 눌림 재진입 공식화 — pullback_reentry_rule
|
||||
pullback_reentry_rule:
|
||||
purpose: "돌파 확인(3일 연속 저항선 상회) 후 1차 눌림(MA5·MA20) 재진입 시점·규모·금지 조건 명문화."
|
||||
prerequisite:
|
||||
breakout_confirmation:
|
||||
- "종가 기준 3거래일 연속 저항선(52주고점·전고점·박스 상단) 상회"
|
||||
- "3거래일 평균 거래대금 > 20일 평균 × 1.5배"
|
||||
- "anti_climax_buy_gate 신호 <= 2개 (3개 이상이면 눌림 재진입도 금지)"
|
||||
existing_position: "이미 staged_entry_v2 stage_1 이상 보유 중이어야 함. 신규 진입에 사용 금지."
|
||||
entry_zones:
|
||||
primary_MA5:
|
||||
condition: "종가가 MA5 ±0.5% 구간에서 반등 (음봉→양봉 전환)"
|
||||
size: "현재 보유 stage_1 수량의 50% 추가"
|
||||
entry_price: "MA5 기준 ±0.5% 지정가"
|
||||
secondary_MA20:
|
||||
condition: "MA5 지지 실패 후 MA20 ±1% 구간까지 하락 시"
|
||||
size: "현재 보유 stage_2 수량의 30% 추가"
|
||||
max_attempts: "2회까지만. 3회 이상 눌림 = 추세 약화 → 재진입 금지"
|
||||
size_cap:
|
||||
rule: "눌림 재진입 후 해당 종목 합산 비중 총자산 7% 초과 금지."
|
||||
core_load_prohibition: "stage_3 완료 종목 재진입 금지 (aggregate_risk_cap 준수)"
|
||||
invalidity:
|
||||
- "anti_climax_buy_gate >= 3 → 금지"
|
||||
- "MA20 하향돌파 후 2거래일 연속 하회 → 추세 전환 판단, 재진입 금지"
|
||||
- "relative_weakness_exit RW >= 4 발동 종목 금지"
|
||||
- "sector_crash_intraday_protocol tier_B 이상 발동 중 금지"
|
||||
- "weekly_circuit_breaker 발동 중 금지"
|
||||
output_table:
|
||||
columns: ["종목명", "돌파확인일", "눌림진입구간", "재진입지정가", "재진입수량(정수)", "합산비중(%)", "trailing_stop갱신가"]
|
||||
prohibition:
|
||||
- "돌파 미확인(3일 연속 저항선 상회 미달) 종목 눌림매수 금지"
|
||||
- "소수점 수량 산출 금지 — 정수 단위만"
|
||||
@@ -0,0 +1,87 @@
|
||||
meta:
|
||||
title: "은퇴자산포트폴리오 — 종목 모델 분할 후보"
|
||||
parent_file: "spec/04_strategy_rules.yaml"
|
||||
version: "2026-05-16-F10_peg_gate"
|
||||
language: "ko-KR"
|
||||
timezone: "Asia/Seoul"
|
||||
role: "canonical"
|
||||
migration_status: "canonical_split_active"
|
||||
authority_rule: "이 split 파일이 해당 섹션의 canonical source다. parent_file은 legacy compatibility index다."
|
||||
|
||||
stock_model:
|
||||
pass: ["시총·섹터 대표성", "충분한 거래대금", "실적 개선", "20D 수급 우위", "기대수익비 2:1 이상"]
|
||||
reject: ["관리종목·거래정지·유동성 부족", "적자 지속+테마성 급등", "거래대금 폭증 후 장대음봉", "실적 컨센서스 하향", "단일 뉴스만 근거인 상승"]
|
||||
# [proposal_91 / 2026-05-16] 코스닥 전용 추가 reject 조건 — 코스닥 구조적 위험 특성 반영
|
||||
kosdaq_extra_reject:
|
||||
applicable: "코스닥 상장 종목에만 추가 적용. 위 reject 조건과 AND(모두 확인)."
|
||||
conditions:
|
||||
- "코스닥 상장 후 6개월 미만 — 실적 트랙 레코드 부족, 상장 직후 공모주 매도 물량 리스크"
|
||||
- "최근 1년 내 감사의견 비적정 또는 내부회계 관리제도 중요 취약점 보고"
|
||||
- "대주주 지분 50% 미만 + 최근 3개월 대주주 2회 이상 연속 매도"
|
||||
- "영업이익 흑자 전환 1분기에 불과한 테마 종목 — 2분기 연속 흑자 미확인 시 reject"
|
||||
- "유상증자·CB(전환사채)·BW(신주인수권부사채) 발행 후 6개월 이내 — 희석 리스크"
|
||||
prohibition:
|
||||
- "코스닥 종목에 대해 이 조건 미확인 상태에서 A등급 부여 금지"
|
||||
- "테마 뉴스를 근거로 kosdaq_extra_reject 조건 면제 금지"
|
||||
|
||||
# [proposal_96 / 2026-05-16] 코스닥 밸류에이션 게이트 — PEG 기반 고성장 정당화 여부 판단
|
||||
kosdaq_valuation_gate:
|
||||
applicable: "코스닥 상장 종목에만 적용. KOSPI 종목은 기존 SS001_VAL_VALUATION 사용."
|
||||
purpose: >
|
||||
유동성·수급만으로는 한미반도체처럼 PER 40~60배 구간 진입 리스크를 잡지 못한다.
|
||||
EPS 성장률로 PER을 나눈 PEG로 '비싸지만 정당한가'를 판단한다.
|
||||
primary_metric:
|
||||
name: "PEG (Price/Earnings to Growth)"
|
||||
formula_ref: "spec/13_formula_registry.yaml:formula_registry.formulas.PEG_SCORE_V1"
|
||||
formula: "ForwardPER / EPS_Growth_3Y_CAGR_pct"
|
||||
unit_note: "EPS_Growth_3Y_CAGR_pct는 % 단위 숫자 (30% 성장이면 30). 소수점 아님."
|
||||
gate_rules:
|
||||
pass: {condition: "PEG <= 1.5", action: "밸류에이션 OK. 진입 수량 정상 산출."}
|
||||
caution: {condition: "1.5 < PEG <= 2.5", action: "진입 수량 70%로 자동 축소. 보고서에 [PEG_CAUTION] 표기 필수."}
|
||||
reject: {condition: "PEG > 2.5", action: "코스닥 진입 금지. 수량 0주."}
|
||||
fallback:
|
||||
trigger: "EPS_Growth_3Y_CAGR_pct 미확인 또는 데이터 누락"
|
||||
rules:
|
||||
- {if: "ForwardPER <= 섹터중앙값 × 2.0", result: "PASS"}
|
||||
- {if: "섹터중앙값 × 2.0 < ForwardPER <= 섹터중앙값 × 3.0", result: "CAUTION (70% 수량)"}
|
||||
- {if: "ForwardPER > 섹터중앙값 × 3.0", result: "REJECT"}
|
||||
prohibition: "EPS 성장률 추정·보간으로 PEG 계산 금지 — 확정 컨센서스 데이터 없으면 fallback만 허용"
|
||||
examples:
|
||||
hanmi_semiconductor:
|
||||
scenario: "ForwardPER=45, EPS_Growth_3Y=25%"
|
||||
peg: 1.8
|
||||
result: "CAUTION → 진입 수량 70%. full 진입 금지."
|
||||
high_peg_reject:
|
||||
scenario: "ForwardPER=60, EPS_Growth_3Y=10%"
|
||||
peg: 6.0
|
||||
result: "REJECT → 진입 금지."
|
||||
growth_justified:
|
||||
scenario: "ForwardPER=30, EPS_Growth_3Y=40%"
|
||||
peg: 0.75
|
||||
result: "PASS → 정상 수량 산출."
|
||||
interaction:
|
||||
kosdaq_extra_reject: "kosdaq_extra_reject와 AND 적용. 어느 하나 reject이면 진입 금지."
|
||||
anti_climax_buy_gate: "PEG CAUTION + anti_climax 신호 2개 → 수량 70%×50%=35%로 중첩 축소."
|
||||
scoring: "SS001_VAL_KOSDAQ_PEG 점수(최대 12점)로 전환. spec/08_scoring_rules.yaml 참조."
|
||||
prohibition:
|
||||
- "코스닥 종목 PEG 미산출 상태에서 A등급 부여 금지"
|
||||
- "PEG CAUTION 상태에서 수량 축소 없이 full 진입 금지"
|
||||
- "단일 호재 뉴스로 EPS_Growth 상향 추정 후 PEG 개선 처리 금지"
|
||||
- "KOSPI 종목에 이 게이트 적용 금지"
|
||||
|
||||
core_satellite_rule:
|
||||
alias_of: "satellite_rule"
|
||||
definition: "조건부·소액·관찰 후보. 즉시매수 아님"
|
||||
max_count: 3
|
||||
max_weight: "총자산 7% 이하"
|
||||
required_conditions: # [P127] mandatory 3개 ALL 필수 / optional 4개 중 1개 이상 권장
|
||||
mandatory_all_3:
|
||||
- 거래대금 증가
|
||||
- 외국인/기관 순매수 전환
|
||||
- "기대수익비 2:1 이상"
|
||||
optional_confirm_any:
|
||||
- 섹터 상대강도 개선
|
||||
- 실적 추정치 상향
|
||||
- "20일선 회복 후 유지 또는 신고가 후 눌림 재지지"
|
||||
entry_spike_restriction: "단기 급등(당일 +5% 이상) 직후는 본진입 제외. risk_on 국면도 시범진입만 허용 (tiered_ladder 순서 준수). optional_confirm_any가 아닌 진입 제한 규칙."
|
||||
rule: "핵심 데이터 미확인 시 A등급 불가. 첫 돌파는 시범진입만, 확인 전 전량 진입 금지. 강한 장세에서는 시범진입 타이밍을 늦추지 말고 수량만 줄인다."
|
||||
Reference in New Issue
Block a user