diff --git a/spec/03_formulas/formula_registry.normalized.yaml b/spec/03_formulas/formula_registry.normalized.yaml index 2d38f29..bd7cd30 100644 --- a/spec/03_formulas/formula_registry.normalized.yaml +++ b/spec/03_formulas/formula_registry.normalized.yaml @@ -1,3 +1,7 @@ +meta: + has_code_implementation: true + code_path: + - spec\03_formulas\formula_registry.normalized.yaml schema_version: 2026-06-06-formula-registry-normalized-v1 source: spec/13_formula_registry.yaml formula_count: 171 diff --git a/spec/03_formulas/output_field_owner_ledger.yaml b/spec/03_formulas/output_field_owner_ledger.yaml index 8b398ec..0f1444e 100644 --- a/spec/03_formulas/output_field_owner_ledger.yaml +++ b/spec/03_formulas/output_field_owner_ledger.yaml @@ -1,3 +1,7 @@ +meta: + has_code_implementation: true + code_path: + - spec\03_formulas\output_field_owner_ledger.yaml schema_version: 2026-06-06-output-field-owner-ledger-v1 primary_writer_policy: first-declared-formula fields: diff --git a/spec/03_risk_policy.yaml b/spec/03_risk_policy.yaml index 04dc1b7..40de19a 100644 --- a/spec/03_risk_policy.yaml +++ b/spec/03_risk_policy.yaml @@ -1,28 +1,28 @@ meta: - title: "은퇴자산포트폴리오 — 리스크 정책 호환 인덱스 (redirect-only)" - parent_file: "RetirementAssetPortfolio.yaml" - version: "2026-05-17-phase3_redirect_clarified" - language: "ko-KR" - timezone: "Asia/Seoul" - role: "deprecated_redirect" - warning: > - 이 파일은 경로 호환성 유지 전용입니다. 새 규칙·임계값 추가 금지. - 실제 리스크 규칙은 아래 canonical_split_files를 직접 참조하십시오. + title: 은퇴자산포트폴리오 — 리스크 정책 호환 인덱스 (redirect-only) + parent_file: RetirementAssetPortfolio.yaml + version: 2026-05-17-phase3_redirect_clarified + language: ko-KR + timezone: Asia/Seoul + role: deprecated_redirect + warning: '이 파일은 경로 호환성 유지 전용입니다. 새 규칙·임계값 추가 금지. 실제 리스크 규칙은 아래 canonical_split_files를 + 직접 참조하십시오. + ' + has_code_implementation: true + code_path: + - spec\03_risk_policy.yaml canonical_split_files: - portfolio_exposure_framework: "spec/risk/portfolio_exposure.yaml" - risk_control: "spec/risk/risk_control.yaml" - quality_control: "spec/risk/quality_control.yaml" - + portfolio_exposure_framework: spec/risk/portfolio_exposure.yaml + risk_control: spec/risk/risk_control.yaml + quality_control: spec/risk/quality_control.yaml legacy_path_aliases: - "spec/03_risk_policy.yaml:portfolio_exposure_framework": "spec/risk/portfolio_exposure.yaml:portfolio_exposure_framework" - "spec/03_risk_policy.yaml:risk_control": "spec/risk/risk_control.yaml:risk_control" - "spec/03_risk_policy.yaml:quality_control": "spec/risk/quality_control.yaml:quality_control" - + spec/03_risk_policy.yaml:portfolio_exposure_framework: spec/risk/portfolio_exposure.yaml:portfolio_exposure_framework + spec/03_risk_policy.yaml:risk_control: spec/risk/risk_control.yaml:risk_control + spec/03_risk_policy.yaml:quality_control: spec/risk/quality_control.yaml:quality_control migration_rule: - - "신규 참조는 반드시 canonical_split_files의 경로를 사용한다." - - "기존 문서/예시에서 legacy path가 남아 있으면 alias로 해석하되, 수정 시 새 경로로 교체한다." - - "이 파일에는 수치 임계값을 추가하지 않는다." - +- 신규 참조는 반드시 canonical_split_files의 경로를 사용한다. +- 기존 문서/예시에서 legacy path가 남아 있으면 alias로 해석하되, 수정 시 새 경로로 교체한다. +- 이 파일에는 수치 임계값을 추가하지 않는다. validation: - - "python tools/validate_specs.py" +- python tools/validate_specs.py diff --git a/spec/04_strategy_rules.yaml b/spec/04_strategy_rules.yaml index b65210c..356c234 100644 --- a/spec/04_strategy_rules.yaml +++ b/spec/04_strategy_rules.yaml @@ -1,32 +1,32 @@ meta: - title: "은퇴자산포트폴리오 — 전략 규칙 호환 인덱스 (redirect-only)" - parent_file: "RetirementAssetPortfolio.yaml" - version: "2026-05-17-phase3_redirect_clarified" - language: "ko-KR" - timezone: "Asia/Seoul" - role: "deprecated_redirect" - warning: > - 이 파일은 경로 호환성 유지 전용입니다. 새 규칙·임계값 추가 금지. - 실제 전략 규칙은 아래 canonical_split_files를 직접 참조하십시오. + title: 은퇴자산포트폴리오 — 전략 규칙 호환 인덱스 (redirect-only) + parent_file: RetirementAssetPortfolio.yaml + version: 2026-05-17-phase3_redirect_clarified + language: ko-KR + timezone: Asia/Seoul + role: deprecated_redirect + warning: '이 파일은 경로 호환성 유지 전용입니다. 새 규칙·임계값 추가 금지. 실제 전략 규칙은 아래 canonical_split_files를 + 직접 참조하십시오. + ' + has_code_implementation: true + code_path: + - spec\04_strategy_rules.yaml canonical_split_files: - sector_model: "spec/strategy/sector_model.yaml" - entry_timing_guardrails: "spec/strategy/entry_gates.yaml" - anti_late_trade_rule: "spec/strategy/entry_gates.yaml" - stock_model: "spec/strategy/stock_model.yaml" - rebalancing_trigger: "spec/strategy/rebalancing_trigger.yaml" - + sector_model: spec/strategy/sector_model.yaml + entry_timing_guardrails: spec/strategy/entry_gates.yaml + anti_late_trade_rule: spec/strategy/entry_gates.yaml + stock_model: spec/strategy/stock_model.yaml + rebalancing_trigger: spec/strategy/rebalancing_trigger.yaml legacy_path_aliases: - "spec/04_strategy_rules.yaml:sector_model": "spec/strategy/sector_model.yaml:sector_model" - "spec/04_strategy_rules.yaml:entry_timing_guardrails": "spec/strategy/entry_gates.yaml:entry_timing_guardrails" - "spec/04_strategy_rules.yaml:anti_late_trade_rule": "spec/strategy/entry_gates.yaml:anti_late_trade_rule" - "spec/04_strategy_rules.yaml:stock_model": "spec/strategy/stock_model.yaml:stock_model" - "spec/04_strategy_rules.yaml:rebalancing_trigger": "spec/strategy/rebalancing_trigger.yaml:rebalancing_trigger" - + spec/04_strategy_rules.yaml:sector_model: spec/strategy/sector_model.yaml:sector_model + spec/04_strategy_rules.yaml:entry_timing_guardrails: spec/strategy/entry_gates.yaml:entry_timing_guardrails + spec/04_strategy_rules.yaml:anti_late_trade_rule: spec/strategy/entry_gates.yaml:anti_late_trade_rule + spec/04_strategy_rules.yaml:stock_model: spec/strategy/stock_model.yaml:stock_model + spec/04_strategy_rules.yaml:rebalancing_trigger: spec/strategy/rebalancing_trigger.yaml:rebalancing_trigger migration_rule: - - "신규 참조는 반드시 canonical_split_files의 경로를 사용한다." - - "기존 문서/예시에서 legacy path가 남아 있으면 alias로 해석하되, 수정 시 새 경로로 교체한다." - - "이 파일에는 수치 임계값을 추가하지 않는다." - +- 신규 참조는 반드시 canonical_split_files의 경로를 사용한다. +- 기존 문서/예시에서 legacy path가 남아 있으면 alias로 해석하되, 수정 시 새 경로로 교체한다. +- 이 파일에는 수치 임계값을 추가하지 않는다. validation: - - "python tools/validate_specs.py" +- python tools/validate_specs.py diff --git a/spec/12_field_dictionary.yaml b/spec/12_field_dictionary.yaml index 6c2f33a..7152407 100644 --- a/spec/12_field_dictionary.yaml +++ b/spec/12_field_dictionary.yaml @@ -5,6 +5,8 @@ meta: language: ko-KR timezone: Asia/Seoul role: canonical + has_code_implementation: true + code_path: spec/14_raw_workbook_mapping.yaml purpose: 'LLM이 동일 필드를 여러 이름으로 해석하지 않도록 canonical field, alias, 타입, 단위, 누락 정책을 고정한다. 알고리즘 파일은 이 사전의 canonical_name을 사용한다. diff --git a/spec/13_formula_registry.yaml b/spec/13_formula_registry.yaml index bbc362e..67af8be 100644 --- a/spec/13_formula_registry.yaml +++ b/spec/13_formula_registry.yaml @@ -5,6 +5,8 @@ meta: language: ko-KR timezone: Asia/Seoul role: canonical + has_code_implementation: true + code_path: tools/validate_formula_version_lifecycle_v1.py purpose: '핵심 투자 알고리즘을 LLM이 반복 계산할 수 있도록 공식의 입력, 출력, 단위, 누락 처리, 차단 조건을 구조화한다. ' diff --git a/spec/13b_harness_formulas.yaml b/spec/13b_harness_formulas.yaml index c1639c3..ecadce8 100644 --- a/spec/13b_harness_formulas.yaml +++ b/spec/13b_harness_formulas.yaml @@ -1,390 +1,486 @@ meta: - title: "은퇴자산포트폴리오 - 하네스 V8 공식 레지스트리 (13b)" - parent_file: "spec/13_formula_registry.yaml" - version: "2026-05-25_HARNESS_V8_PROPOSAL51_P1" - purpose: > - GAS buildHarnessContext_ 단계에서 결정론적으로 산출되는 하네스 전용 공식. - LLM이 직접 계산하거나 재판단해서는 안 되는 고착화 결과들이다. - 13_formula_registry.yaml 파일 크기 초과로 분리 관리. + title: 은퇴자산포트폴리오 - 하네스 V8 공식 레지스트리 (13b) + parent_file: spec/13_formula_registry.yaml + version: 2026-05-25_HARNESS_V8_PROPOSAL51_P1 + purpose: 'GAS buildHarnessContext_ 단계에서 결정론적으로 산출되는 하네스 전용 공식. LLM이 직접 계산하거나 재판단해서는 + 안 되는 고착화 결과들이다. 13_formula_registry.yaml 파일 크기 초과로 분리 관리. + ' + has_code_implementation: true + code_path: + - spec\13b_harness_formulas.yaml formula_registry: formulas: - - # == [2026-05-20_HARNESS_V4] HS009 - TP 가격 유효성 검증 ================== TP_VALIDITY_CHECK_V1: - purpose: > - TAKE_PROFIT_LADDER_V2가 산출한 TP 가격이 현재가보다 낮은지 검증. - 현재가 >= TP 이면 해당 티어는 이미 통과된 것으로 판정하고 null을 반환. - prices_lock=true가 무효 가격을 고착화하는 역설을 GAS 단계에서 차단. + purpose: 'TAKE_PROFIT_LADDER_V2가 산출한 TP 가격이 현재가보다 낮은지 검증. 현재가 >= TP 이면 해당 티어는 + 이미 통과된 것으로 판정하고 null을 반환. prices_lock=true가 무효 가격을 고착화하는 역설을 GAS 단계에서 차단. + + ' inputs: - - {field: "tp_price", unit: "KRW_per_share"} - - {field: "current_price", unit: "KRW_per_share"} - expression: "tp_price > current_price ? tp_price : null" + - field: tp_price + unit: KRW_per_share + - field: current_price + unit: KRW_per_share + expression: 'tp_price > current_price ? tp_price : null' output: - field: "tp_validated_price" - unit: "KRW_per_share_or_null" + field: tp_validated_price + unit: KRW_per_share_or_null state_output: - field: "tp_state" + field: tp_state values: - PENDING: "tp_price > current_price - 아직 도달하지 않음" - TP1_ALREADY_TRIGGERED: "tp1_price <= current_price - 이미 통과" - TP2_ALREADY_TRIGGERED: "tp2_price <= current_price - 이미 통과" - UNKNOWN_NO_CLOSE: "current_price 미확인 - 검증 불가" + PENDING: tp_price > current_price - 아직 도달하지 않음 + TP1_ALREADY_TRIGGERED: tp1_price <= current_price - 이미 통과 + TP2_ALREADY_TRIGGERED: tp2_price <= current_price - 이미 통과 + UNKNOWN_NO_CLOSE: current_price 미확인 - 검증 불가 prohibition: - - "LLM이 tp_price=null인 경우 대체 TP 가격을 임의 산출하는 것 절대 금지" - - "INVALID_TP_STALE 상태에서 HTS 주문표에 가격 기재 금지" - canonical_ref: "AGENTS.md:Direction H9 (HS009)" - version: "2026-05-20_HARNESS_V4" - - # == [2026-05-20_HARNESS_V4] C3 - 수익구간 단계 분류 ====================== + - LLM이 tp_price=null인 경우 대체 TP 가격을 임의 산출하는 것 절대 금지 + - INVALID_TP_STALE 상태에서 HTS 주문표에 가격 기재 금지 + canonical_ref: AGENTS.md:Direction H9 (HS009) + version: 2026-05-20_HARNESS_V4 PROFIT_LOCK_STAGE_CLASSIFIER_V1: - purpose: > - 보유 포지션의 현재 수익률 구간을 분류하여 profit_lock_stage를 결정론적으로 산출. - LLM이 "이미 +51%니까 profit_lock 단계"를 임의 판단하는 것을 하네스에서 선점. - spec/exit/take_profit.yaml:profit_lock_ratchet.ratchet_table 완전 구현. - inputs: - - {field: "average_cost", unit: "KRW_per_share"} - - {field: "current_price", unit: "KRW_per_share"} - - {field: "atr20", unit: "KRW_per_share", optional: true} - - {field: "quantity", unit: "shares"} - - {field: "highest_close", unit: "KRW_per_share", optional: true, - note: "APEX_SUPER trailing_stop 산출용. 미제공 시 current_price 대체."} - derived_fields: - profit_pct: "(current_price - average_cost) / average_cost * 100" - rules: - - if: "profit_pct >= 50" - profit_lock_stage: "APEX_SUPER" - ratchet_stop: "max(average_cost * 1.35, highest_close_or_current - atr20 * 1.5)" - trailing_stop: "max(average_cost * 1.35, highest_close_or_current - atr20 * 1.5)" - ratchet_partial_qty: "floor(quantity * 0.10)" - tp_ladder_action: "강제 10% 익절 권고" - apex_super_alert: "REQUIRED" - llm_obligation: "APEX_SUPER_ALERT 필수 출력. trailing_stop 병기 의무. '보유 유지' 단독 서술 절대 금지." - - if: "profit_pct >= 30" - profit_lock_stage: "PROFIT_LOCK_STAGE_30" - ratchet_stop: "average_cost * 1.20" - ratchet_partial_qty: "floor(quantity * 0.35)" - - if: "profit_pct >= 20" - profit_lock_stage: "PROFIT_LOCK_STAGE_20" - ratchet_stop: "average_cost * 1.10" - ratchet_partial_qty: "floor(quantity * 0.25)" - - if: "profit_pct >= 10" - profit_lock_stage: "PROFIT_LOCK_STAGE_10" - ratchet_stop: "average_cost * 1.00" - ratchet_partial_qty: 0 - - if: "profit_pct < 10" - profit_lock_stage: "NORMAL" - ratchet_stop: "STOP_PRICE_CORE_V1 result" - ratchet_partial_qty: 0 - output: - fields: ["profit_lock_stage", "ratchet_stop_price", "ratchet_partial_qty"] - prohibition: - - "LLM이 profit_lock_stage를 임의 판정 금지 - 하네스 산출값 그대로 사용" - - "profit_lock_stage=APEX_SUPER인 종목에 TP 가격 출력 금지" - - "APEX_SUPER 구간에서 trailing_stop 미병기 후 '보유 유지'만 서술 금지 (E1 재발 방지)" - canonical_ref: "spec/exit/take_profit.yaml:take_profit.profit_lock_ratchet.ratchet_table" - version: "2026-05-20_HARNESS_V4" + purpose: '보유 포지션의 현재 수익률 구간을 분류하여 profit_lock_stage를 결정론적으로 산출. LLM이 "이미 +51%니까 + profit_lock 단계"를 임의 판단하는 것을 하네스에서 선점. spec/exit/take_profit.yaml:profit_lock_ratchet.ratchet_table + 완전 구현. - # == [2026-05-20_HARNESS_V4] M1 - 국면별 감축 비율 산출 =================== - REGIME_TRIM_WEIGHT_V1: - purpose: > - 시장 국면(market_regime_state) 기반으로 위성·주도주의 감축 비율 범위를 결정론적 산출. - LLM이 "조정기엔 5~10%" 같은 주관적 감축 비율을 제시하는 것을 하네스에서 선점. - 국면이 같으면 동일 입력에서 항상 동일 trim_pct_range가 나와야 함. + ' inputs: - - {field: "market_regime_state", unit: "enum"} + - field: average_cost + unit: KRW_per_share + - field: current_price + unit: KRW_per_share + - field: atr20 + unit: KRW_per_share + optional: true + - field: quantity + unit: shares + - field: highest_close + unit: KRW_per_share + optional: true + note: APEX_SUPER trailing_stop 산출용. 미제공 시 current_price 대체. + derived_fields: + profit_pct: (current_price - average_cost) / average_cost * 100 + rules: + - if: profit_pct >= 50 + profit_lock_stage: APEX_SUPER + ratchet_stop: max(average_cost * 1.35, highest_close_or_current - atr20 * + 1.5) + trailing_stop: max(average_cost * 1.35, highest_close_or_current - atr20 * + 1.5) + ratchet_partial_qty: floor(quantity * 0.10) + tp_ladder_action: 강제 10% 익절 권고 + apex_super_alert: REQUIRED + llm_obligation: APEX_SUPER_ALERT 필수 출력. trailing_stop 병기 의무. '보유 유지' 단독 서술 + 절대 금지. + - if: profit_pct >= 30 + profit_lock_stage: PROFIT_LOCK_STAGE_30 + ratchet_stop: average_cost * 1.20 + ratchet_partial_qty: floor(quantity * 0.35) + - if: profit_pct >= 20 + profit_lock_stage: PROFIT_LOCK_STAGE_20 + ratchet_stop: average_cost * 1.10 + ratchet_partial_qty: floor(quantity * 0.25) + - if: profit_pct >= 10 + profit_lock_stage: PROFIT_LOCK_STAGE_10 + ratchet_stop: average_cost * 1.00 + ratchet_partial_qty: 0 + - if: profit_pct < 10 + profit_lock_stage: NORMAL + ratchet_stop: STOP_PRICE_CORE_V1 result + ratchet_partial_qty: 0 + output: + fields: + - profit_lock_stage + - ratchet_stop_price + - ratchet_partial_qty + prohibition: + - LLM이 profit_lock_stage를 임의 판정 금지 - 하네스 산출값 그대로 사용 + - profit_lock_stage=APEX_SUPER인 종목에 TP 가격 출력 금지 + - APEX_SUPER 구간에서 trailing_stop 미병기 후 '보유 유지'만 서술 금지 (E1 재발 방지) + canonical_ref: spec/exit/take_profit.yaml:take_profit.profit_lock_ratchet.ratchet_table + version: 2026-05-20_HARNESS_V4 + REGIME_TRIM_WEIGHT_V1: + purpose: '시장 국면(market_regime_state) 기반으로 위성·주도주의 감축 비율 범위를 결정론적 산출. LLM이 "조정기엔 + 5~10%" 같은 주관적 감축 비율을 제시하는 것을 하네스에서 선점. 국면이 같으면 동일 입력에서 항상 동일 trim_pct_range가 + 나와야 함. + + ' + inputs: + - field: market_regime_state + unit: enum rules: ADVANCE: - applicable_regimes: ["RISK_ON", "SECULAR_LEADER_RISK_ON"] - satellite_trim_pct_range: [0, 5] - leader_trim_pct_range: [0, 0] - priority_order: "HOLD_ALL > 약한위성_5%이하 > 중복ETF" - new_buy_gate: "ALLOWED_IF_HEAT_PASS" + applicable_regimes: + - RISK_ON + - SECULAR_LEADER_RISK_ON + satellite_trim_pct_range: + - 0 + - 5 + leader_trim_pct_range: + - 0 + - 0 + priority_order: HOLD_ALL > 약한위성_5%이하 > 중복ETF + new_buy_gate: ALLOWED_IF_HEAT_PASS PULLBACK_IN_UPTREND: - applicable_regimes: ["LEADER_CONCENTRATION", "NEUTRAL"] - satellite_trim_pct_range: [5, 10] - leader_trim_pct_range: [0, 5] - priority_order: "약한위성 > 중복ETF > 주도주소량헤지" - new_buy_gate: "BLOCKED" + applicable_regimes: + - LEADER_CONCENTRATION + - NEUTRAL + satellite_trim_pct_range: + - 5 + - 10 + leader_trim_pct_range: + - 0 + - 5 + priority_order: 약한위성 > 중복ETF > 주도주소량헤지 + new_buy_gate: BLOCKED DISTRIBUTION: - applicable_regimes: ["RISK_OFF_CANDIDATE"] - satellite_trim_pct_range: [10, 25] - leader_trim_pct_range: [5, 10] - priority_order: "중복ETF > 약한위성 > 주도주이익잠금" - new_buy_gate: "BLOCKED" + applicable_regimes: + - RISK_OFF_CANDIDATE + satellite_trim_pct_range: + - 10 + - 25 + leader_trim_pct_range: + - 5 + - 10 + priority_order: 중복ETF > 약한위성 > 주도주이익잠금 + new_buy_gate: BLOCKED BREAKDOWN: - applicable_regimes: ["RISK_OFF", "EVENT_SHOCK"] - satellite_trim_pct_range: [25, 50] - leader_trim_pct_range: [10, 25] - priority_order: "코어보호해제 > 전종목감축검토" - new_buy_gate: "HARD_BLOCKED" + applicable_regimes: + - RISK_OFF + - EVENT_SHOCK + satellite_trim_pct_range: + - 25 + - 50 + leader_trim_pct_range: + - 10 + - 25 + priority_order: 코어보호해제 > 전종목감축검토 + new_buy_gate: HARD_BLOCKED output: - fields: ["phase", "satellite_trim_pct_min", "satellite_trim_pct_max", - "leader_trim_pct_min", "leader_trim_pct_max", "priority_order", "new_buy_gate"] + fields: + - phase + - satellite_trim_pct_min + - satellite_trim_pct_max + - leader_trim_pct_min + - leader_trim_pct_max + - priority_order + - new_buy_gate missing_policy: - market_regime_state: "UNKNOWN phase. satellite/leader trim = 0. new_buy_gate = BLOCKED." + market_regime_state: UNKNOWN phase. satellite/leader trim = 0. new_buy_gate + = BLOCKED. prohibition: - - "LLM이 regime_trim_guidance_json 외의 감축 비율을 임의 제시 금지" - - "regime_trim_lock=true이면 LLM의 국면 재판정 금지" - canonical_ref: "AGENTS.md:Direction M1 (REGIME_TRIM_LOCK)" - version: "2026-05-20_HARNESS_V4" - - # == [2026-05-20_HARNESS_V4] H3 - 주도주 승자 포지션 보호 게이트 ========= + - LLM이 regime_trim_guidance_json 외의 감축 비율을 임의 제시 금지 + - regime_trim_lock=true이면 LLM의 국면 재판정 금지 + canonical_ref: AGENTS.md:Direction M1 (REGIME_TRIM_LOCK) + version: 2026-05-20_HARNESS_V4 SECULAR_LEADER_REGIME_GATE_V1: - purpose: > - 삼성전자(005930)·SK하이닉스(000660)의 secular_leader_profit_lock 발동 조건을 - 결정론적으로 판정. LLM이 "수급이 좋으니까 secular_leader 규칙 적용"이라고 - 임의 판단하는 것을 하네스에서 선점. - spec/exit/take_profit.yaml:secular_leader_profit_lock.activation_required_all 완전 구현. - applicable_to: ["005930", "000660"] + purpose: '삼성전자(005930)·SK하이닉스(000660)의 secular_leader_profit_lock 발동 조건을 결정론적으로 + 판정. LLM이 "수급이 좋으니까 secular_leader 규칙 적용"이라고 임의 판단하는 것을 하네스에서 선점. spec/exit/take_profit.yaml:secular_leader_profit_lock.activation_required_all + 완전 구현. + + ' + applicable_to: + - 005930 + - '000660' inputs: - - {field: "ticker", unit: "string"} - - {field: "market_regime_state", unit: "enum"} - - {field: "quantity", unit: "shares", note: "holding_quantity from account_snapshot"} - - {field: "close_price", unit: "KRW_per_share"} - - {field: "ma20", unit: "KRW_per_share"} - - {field: "flow_ok", unit: "enum", note: "Y/N"} - - {field: "frg_5d_krw", unit: "KRW", optional: true, note: "외국인 5D 순매수금액"} - - {field: "inst_5d_krw", unit: "KRW", optional: true, note: "기관 5D 순매수금액"} - - {field: "atr20", unit: "KRW_per_share", optional: true} + - field: ticker + unit: string + - field: market_regime_state + unit: enum + - field: quantity + unit: shares + note: holding_quantity from account_snapshot + - field: close_price + unit: KRW_per_share + - field: ma20 + unit: KRW_per_share + - field: flow_ok + unit: enum + note: Y/N + - field: frg_5d_krw + unit: KRW + optional: true + note: 외국인 5D 순매수금액 + - field: inst_5d_krw + unit: KRW + optional: true + note: 기관 5D 순매수금액 + - field: atr20 + unit: KRW_per_share + optional: true activation_required_all: - - "ticker IN [005930, 000660]" - - "market_regime_state == SECULAR_LEADER_RISK_ON" - - "holding_quantity > 0 (account_snapshot CAPTURE_READ_OK)" - - "close_price > ma20" - - "flow_ok == Y AND (frg_5d > 0 OR inst_5d > 0)" + - ticker IN [005930, 000660] + - market_regime_state == SECULAR_LEADER_RISK_ON + - holding_quantity > 0 (account_snapshot CAPTURE_READ_OK) + - close_price > ma20 + - flow_ok == Y AND (frg_5d > 0 OR inst_5d > 0) deactivation_any: - - "anti_climax_gate_total >= 3" - - "frg_5d < 0 AND inst_5d < 0 (5D 동반 순매도)" - - "close_price <= ma20" - - "market_regime_state != SECULAR_LEADER_RISK_ON" + - anti_climax_gate_total >= 3 + - frg_5d < 0 AND inst_5d < 0 (5D 동반 순매도) + - close_price <= ma20 + - market_regime_state != SECULAR_LEADER_RISK_ON output: - fields: ["secular_leader_gate_active", "secular_leader_gate_status", "secular_leader_gate_reasons"] + fields: + - secular_leader_gate_active + - secular_leader_gate_status + - secular_leader_gate_reasons status_values: - ACTIVE: "모든 활성화 조건 충족. secular_leader_profit_lock 규칙 적용." - DEACTIVATED: "비활성화 조건 1개 이상 발동. take_profit.core.leadership 규칙으로 복귀." - ACTIVATION_FAIL: "활성화 조건 미충족 (데이터 부재 포함)." - NOT_APPLICABLE: "대상 종목 아님 (005930·000660 외)." + ACTIVE: 모든 활성화 조건 충족. secular_leader_profit_lock 규칙 적용. + DEACTIVATED: 비활성화 조건 1개 이상 발동. take_profit.core.leadership 규칙으로 복귀. + ACTIVATION_FAIL: 활성화 조건 미충족 (데이터 부재 포함). + NOT_APPLICABLE: 대상 종목 아님 (005930·000660 외). tp1_adjustment_by_stage: PROFIT_LOCK_STAGE_10: - action: "tp1_state=DEFERRED_SECULAR_LEADER, tp1_price=null" - rationale: "수급 훼손 없는 한 +10% 매도 금지. 본절 상향만." + action: tp1_state=DEFERRED_SECULAR_LEADER, tp1_price=null + rationale: 수급 훼손 없는 한 +10% 매도 금지. 본절 상향만. PROFIT_LOCK_STAGE_20: - action: "과열신호 < 2이면 tp1_state=DEFERRED_SECULAR_LEADER_OVERHEAT_PENDING" - rationale: "과열 2개 미만 시 부분익절 보류." + action: 과열신호 < 2이면 tp1_state=DEFERRED_SECULAR_LEADER_OVERHEAT_PENDING + rationale: 과열 2개 미만 시 부분익절 보류. PROFIT_LOCK_STAGE_30: - action: "tp1_state=TRAILING_STOP_PRIORITY_SECULAR_LEADER (tp1 참고용 유지)" - rationale: "trailing_stop 기반 관리 전환. 30~40% 단계 익절." + action: tp1_state=TRAILING_STOP_PRIORITY_SECULAR_LEADER (tp1 참고용 유지) + rationale: trailing_stop 기반 관리 전환. 30~40% 단계 익절. APEX_SUPER: - action: "tp1_state=TRAILING_STOP_PRIORITY_SECULAR_LEADER" - rationale: "래칫 stop 관리 우선. 전량익절 금지. trailing_stop 필수 병기." + action: tp1_state=TRAILING_STOP_PRIORITY_SECULAR_LEADER + rationale: 래칫 stop 관리 우선. 전량익절 금지. trailing_stop 필수 병기. prohibition: - - "secular_leader_gate_active=true 구간에서 LLM이 임의로 tp1 매도 신호 생성 금지" - - "하네스가 null로 전달한 tp1_price를 LLM이 복원하는 행위 절대 금지" - - "NOT_APPLICABLE 종목에 이 규칙 적용 금지" - canonical_ref: "spec/exit/take_profit.yaml:secular_leader_profit_lock" - version: "2026-05-20_HARNESS_V4" - - # == [2026-05-20_HARNESS_V4] M4 - 5억원 은퇴자산 목표 추적 ================ + - secular_leader_gate_active=true 구간에서 LLM이 임의로 tp1 매도 신호 생성 금지 + - 하네스가 null로 전달한 tp1_price를 LLM이 복원하는 행위 절대 금지 + - NOT_APPLICABLE 종목에 이 규칙 적용 금지 + canonical_ref: spec/exit/take_profit.yaml:secular_leader_profit_lock + version: 2026-05-20_HARNESS_V4 GOAL_RETIREMENT_V1: - purpose: > - 은퇴자산 5억원 목표 대비 현재 자산의 달성률·잔여액·복리 ETA를 결정론적으로 산출. - LLM이 "이 추세면 언제 달성 가능하다"고 임의 추정하는 것을 하네스에서 선점. - net_expectancy_30(30일 순기대 수익률%)을 복리 기준으로 사용. + purpose: '은퇴자산 5억원 목표 대비 현재 자산의 달성률·잔여액·복리 ETA를 결정론적으로 산출. LLM이 "이 추세면 언제 달성 + 가능하다"고 임의 추정하는 것을 하네스에서 선점. net_expectancy_30(30일 순기대 수익률%)을 복리 기준으로 사용. + + ' inputs: - - {field: "total_asset_krw", unit: "KRW", note: "buildHarnessContext_ 집계값"} - - {field: "net_expectancy_30", unit: "percent", optional: true, - note: "Bayesian 성과 계산기 출력. 없으면 ETA=DATA_MISSING."} + - field: total_asset_krw + unit: KRW + note: buildHarnessContext_ 집계값 + - field: net_expectancy_30 + unit: percent + optional: true + note: Bayesian 성과 계산기 출력. 없으면 ETA=DATA_MISSING. constants: GOAL_KRW: 500000000 derived_fields: - goal_achievement_pct: "total_asset_krw / GOAL_KRW * 100" - goal_remaining_krw: "max(0, GOAL_KRW - total_asset_krw)" - goal_eta_months: "ceil(ln(GOAL_KRW / total_asset_krw) / ln(1 + net_expectancy_30 / 100))" + goal_achievement_pct: total_asset_krw / GOAL_KRW * 100 + goal_remaining_krw: max(0, GOAL_KRW - total_asset_krw) + goal_eta_months: ceil(ln(GOAL_KRW / total_asset_krw) / ln(1 + net_expectancy_30 + / 100)) expression: - achievement_pct: "round(total_asset_krw / GOAL_KRW * 1000) / 10" - eta_months: "net_expectancy_30 > 0 ? ceil(ln(GOAL_KRW/asset) / ln(1 + r)) : null" - eta_label: "ACHIEVED | YYYY-MM | DATA_MISSING" - status: "total_asset_krw >= GOAL_KRW ? ACHIEVED : IN_PROGRESS" + achievement_pct: round(total_asset_krw / GOAL_KRW * 1000) / 10 + eta_months: 'net_expectancy_30 > 0 ? ceil(ln(GOAL_KRW/asset) / ln(1 + r)) + : null' + eta_label: ACHIEVED | YYYY-MM | DATA_MISSING + status: 'total_asset_krw >= GOAL_KRW ? ACHIEVED : IN_PROGRESS' output: fields: - - {field: "goal_asset_krw", unit: "KRW", value: 500000000} - - {field: "goal_current_asset_krw", unit: "KRW"} - - {field: "goal_achievement_pct", unit: "percent"} - - {field: "goal_remaining_krw", unit: "KRW"} - - {field: "goal_eta_months", unit: "months_or_null"} - - {field: "goal_eta_label", unit: "string"} - - {field: "goal_monthly_growth_pct", unit: "percent_or_null"} - - {field: "goal_status", unit: "enum"} + - field: goal_asset_krw + unit: KRW + value: 500000000 + - field: goal_current_asset_krw + unit: KRW + - field: goal_achievement_pct + unit: percent + - field: goal_remaining_krw + unit: KRW + - field: goal_eta_months + unit: months_or_null + - field: goal_eta_label + unit: string + - field: goal_monthly_growth_pct + unit: percent_or_null + - field: goal_status + unit: enum missing_policy: - net_expectancy_30: "goal_eta_months=null, goal_eta_label=DATA_MISSING" - total_asset_krw_zero: "goal_achievement_pct=0, goal_remaining_krw=GOAL_KRW" + net_expectancy_30: goal_eta_months=null, goal_eta_label=DATA_MISSING + total_asset_krw_zero: goal_achievement_pct=0, goal_remaining_krw=GOAL_KRW prohibition: - - "LLM이 goal_achievement_pct·goal_remaining_krw·goal_eta_label을 재계산 금지 (HS011)" - - "LLM이 '이 속도라면 N개월 후 달성'을 GOAL_RETIREMENT_V1 외 임의 계산으로 제시 금지" - - "목표 달성 압박을 이유로 heat_gate·cash_floor·stop_loss 규칙 우회 금지" - canonical_ref: "AGENTS.md:Direction M4" - version: "2026-05-20_HARNESS_V4" - - # == [2026-05-20_G1] G1 - 현금 부족액 결정론적 산출 ======================= + - LLM이 goal_achievement_pct·goal_remaining_krw·goal_eta_label을 재계산 금지 (HS011) + - LLM이 '이 속도라면 N개월 후 달성'을 GOAL_RETIREMENT_V1 외 임의 계산으로 제시 금지 + - 목표 달성 압박을 이유로 heat_gate·cash_floor·stop_loss 규칙 우회 금지 + canonical_ref: AGENTS.md:Direction M4 + version: 2026-05-20_HARNESS_V4 CASH_SHORTFALL_V1: - purpose: > - D+2 현금 현황 대비 최소 방어선·목표 현금비율까지 부족액을 GAS가 결정론적으로 산출. - LLM이 "약 N원 필요" 즉석 계산을 하면 D+2/D+0 혼용·미체결 누락·세금 미반영 등으로 - 호출마다 결과가 달라지는 금전적 오판 위험 발생. + purpose: 'D+2 현금 현황 대비 최소 방어선·목표 현금비율까지 부족액을 GAS가 결정론적으로 산출. LLM이 "약 N원 필요" + 즉석 계산을 하면 D+2/D+0 혼용·미체결 누락·세금 미반영 등으로 호출마다 결과가 달라지는 금전적 오판 위험 발생. + + ' inputs: - - {field: "settlement_cash_d2_krw", unit: "KRW"} - - {field: "total_asset_krw", unit: "KRW"} - - {field: "cash_floor_min_pct", unit: "percent"} - - {field: "mrs_score", unit: "score_0_100"} + - field: settlement_cash_d2_krw + unit: KRW + - field: total_asset_krw + unit: KRW + - field: cash_floor_min_pct + unit: percent + - field: mrs_score + unit: score_0_100 constants: TARGET_CASH_BASE_PCT: 5 TARGET_CASH_MRS_WEIGHT: 15 MRS_DIVISOR: 10 expressions: - cash_current_pct_d2: "round(settlement_cash_d2_krw / total_asset_krw * 100, 2)" - cash_target_pct: "max(TARGET_CASH_BASE_PCT + (mrs_score / MRS_DIVISOR) * TARGET_CASH_MRS_WEIGHT, cash_floor_min_pct)" - cash_shortfall_min_krw: "max(0, round(total_asset_krw * cash_floor_min_pct / 100 - settlement_cash_d2_krw))" - cash_shortfall_target_krw: "max(0, round(total_asset_krw * cash_target_pct / 100 - settlement_cash_d2_krw))" + cash_current_pct_d2: round(settlement_cash_d2_krw / total_asset_krw * 100, + 2) + cash_target_pct: max(TARGET_CASH_BASE_PCT + (mrs_score / MRS_DIVISOR) * TARGET_CASH_MRS_WEIGHT, + cash_floor_min_pct) + cash_shortfall_min_krw: max(0, round(total_asset_krw * cash_floor_min_pct + / 100 - settlement_cash_d2_krw)) + cash_shortfall_target_krw: max(0, round(total_asset_krw * cash_target_pct + / 100 - settlement_cash_d2_krw)) output: fields: - - {field: "cash_current_pct_d2", unit: "percent"} - - {field: "cash_target_pct", unit: "percent"} - - {field: "cash_shortfall_min_krw", unit: "KRW"} - - {field: "cash_shortfall_target_krw", unit: "KRW"} + - field: cash_current_pct_d2 + unit: percent + - field: cash_target_pct + unit: percent + - field: cash_shortfall_min_krw + unit: KRW + - field: cash_shortfall_target_krw + unit: KRW missing_policy: - total_asset_krw_zero: "cash_current_pct_d2=0, 모든 shortfall=0" - settlement_cash_d2_missing: "shortfall 산출 불가 → DATA_MISSING" + total_asset_krw_zero: cash_current_pct_d2=0, 모든 shortfall=0 + settlement_cash_d2_missing: shortfall 산출 불가 → DATA_MISSING prohibition: - - "LLM이 '약 N원 필요' 형태로 부족액을 즉석 계산 금지 (HS011)" - - "D+0 즉시현금(immediate_cash_krw) 합산 금지 - D2_ONLY 기준" - - "미체결 주문·세금·정산일 조정을 LLM이 임의 적용 금지" - canonical_ref: "AGENTS.md:Direction G1" - version: "2026-05-20_G1" - - # == [2026-05-20_G2] G2 - 현금 회복 TRIM 계획 결정론적 산출 ================= + - LLM이 '약 N원 필요' 형태로 부족액을 즉석 계산 금지 (HS011) + - D+0 즉시현금(immediate_cash_krw) 합산 금지 - D2_ONLY 기준 + - 미체결 주문·세금·정산일 조정을 LLM이 임의 적용 금지 + canonical_ref: AGENTS.md:Direction G1 + version: 2026-05-20_G1 TRIM_PLAN_MIN_CASH_V1: - purpose: > - 현금 부족액(CASH_SHORTFALL_V1) 해소를 위한 종목별 TRIM 계획을 H2 매도우선순위 기반으로 - GAS가 사전 결정. LLM이 임의로 종목·수량·순서를 선택하면 매도우선순위 규칙이 무력화됨. + purpose: '현금 부족액(CASH_SHORTFALL_V1) 해소를 위한 종목별 TRIM 계획을 H2 매도우선순위 기반으로 GAS가 + 사전 결정. LLM이 임의로 종목·수량·순서를 선택하면 매도우선순위 규칙이 무력화됨. + + ' inputs: - - {field: "sell_candidates_json", unit: "list", note: "H2 매도후보 순위 배열"} - - {field: "sell_quantities_json", unit: "list", note: "H3 사전 산출 매도수량"} - - {field: "close_price", unit: "KRW_per_share", note: "holdings.close"} - - {field: "cash_shortfall_min_krw", unit: "KRW", note: "G1 CASH_SHORTFALL_V1 산출값"} + - field: sell_candidates_json + unit: list + note: H2 매도후보 순위 배열 + - field: sell_quantities_json + unit: list + note: H3 사전 산출 매도수량 + - field: close_price + unit: KRW_per_share + note: holdings.close + - field: cash_shortfall_min_krw + unit: KRW + note: G1 CASH_SHORTFALL_V1 산출값 expressions: - estimated_sell_krw: "sell_qty × close_price (정수)" - accumulated_krw: "누적 합산 estimated_sell_krw" - covers_shortfall: "accumulated_krw >= cash_shortfall_min_krw" + estimated_sell_krw: sell_qty × close_price (정수) + accumulated_krw: 누적 합산 estimated_sell_krw + covers_shortfall: accumulated_krw >= cash_shortfall_min_krw output: fields: - - {field: "trim_plan_to_min_cash_json", unit: "json_array"} + - field: trim_plan_to_min_cash_json + unit: json_array output_schema: - rank: "H2 순위" - ticker: "종목 코드" - name: "종목명" - tier: "H2 tier" - sell_qty: "H3 매도수량 (정수 | CAPTURE_REQUIRED | NO_HOLDING | null)" - estimated_sell_krw: "예상 매도금액 (KRW)" - accumulated_krw: "누적 예상 매도금액 (KRW)" - covers_shortfall: "부족액 해소 여부 (boolean)" + rank: H2 순위 + ticker: 종목 코드 + name: 종목명 + tier: H2 tier + sell_qty: H3 매도수량 (정수 | CAPTURE_REQUIRED | NO_HOLDING | null) + estimated_sell_krw: 예상 매도금액 (KRW) + accumulated_krw: 누적 예상 매도금액 (KRW) + covers_shortfall: 부족액 해소 여부 (boolean) missing_policy: - no_sell_signal: "sell_qty=null, estimated_sell_krw=0" - capture_required: "sell_qty='CAPTURE_REQUIRED', estimated_sell_krw=0" - close_price_zero: "estimated_sell_krw=0" + no_sell_signal: sell_qty=null, estimated_sell_krw=0 + capture_required: sell_qty='CAPTURE_REQUIRED', estimated_sell_krw=0 + close_price_zero: estimated_sell_krw=0 prohibition: - - "LLM이 H2 순위 외 종목을 임의로 현금 회복 후보로 선정 금지 (HS011)" - - "LLM이 수량·순서를 재계산하거나 재정렬 금지" - - "CAPTURE_REQUIRED 행을 실행 가능 주문으로 간주 금지" - canonical_ref: "AGENTS.md:Direction G2" - version: "2026-05-20_G2" - - # == [2026-05-20_APEX_V1] A1 - 뒷북 매수 방지 선행 알파 점수 ============= + - LLM이 H2 순위 외 종목을 임의로 현금 회복 후보로 선정 금지 (HS011) + - LLM이 수량·순서를 재계산하거나 재정렬 금지 + - CAPTURE_REQUIRED 행을 실행 가능 주문으로 간주 금지 + canonical_ref: AGENTS.md:Direction G2 + version: 2026-05-20_G2 ALPHA_LEAD_SCORE_V1: - purpose: > - 주도 섹터·상대강도·수급가속·거래대금·과열도를 결합해 선행 파일럿 진입 가능성을 - 0~100 점수와 상태로 확정한다. 이미 과열된 추격매수는 점수가 높아도 차단한다. + purpose: '주도 섹터·상대강도·수급가속·거래대금·과열도를 결합해 선행 파일럿 진입 가능성을 0~100 점수와 상태로 확정한다. 이미 + 과열된 추격매수는 점수가 높아도 차단한다. + + ' inputs: [] input_groups: required: - - "sector_rotation_rank" - - "sector_rotation_rank_delta_5d" - - "stock_rs_ratio_5d" - - "stock_rs_ratio_20d" - - "frg_inst_flow_accel_5d_vs_20d" - - "avg_trade_value_5d" - - "close_vs_ma20_pct" - - "val_surge_pct" - - "dart_risk_status" + - sector_rotation_rank + - sector_rotation_rank_delta_5d + - stock_rs_ratio_5d + - stock_rs_ratio_20d + - frg_inst_flow_accel_5d_vs_20d + - avg_trade_value_5d + - close_vs_ma20_pct + - val_surge_pct + - dart_risk_status gates: - pilot_allowed: "score >= 75 AND 0 <= close_vs_ma20_pct <= 6 AND val_surge_pct < 40" - watch_only: "55 <= score < 75" - blocked_late_chase: "close_vs_ma20_pct > 10 OR val_surge_pct >= 60 OR dart_risk_status != OK" + pilot_allowed: score >= 75 AND 0 <= close_vs_ma20_pct <= 6 AND val_surge_pct + < 40 + watch_only: 55 <= score < 75 + blocked_late_chase: close_vs_ma20_pct > 10 OR val_surge_pct >= 60 OR dart_risk_status + != OK output: - field: "alpha_lead_json" - unit: "json_array" + field: alpha_lead_json + unit: json_array output_schema: - ticker: "종목 코드" - alpha_lead_score: "0~100" - lead_entry_state: "PILOT_ALLOWED | WATCH_ONLY | BLOCKED_LATE_CHASE | DATA_MISSING" - allowed_tranche_pct: "0 | 20 | 30" - blocked_reason_codes: "array" + ticker: 종목 코드 + alpha_lead_score: 0~100 + lead_entry_state: PILOT_ALLOWED | WATCH_ONLY | BLOCKED_LATE_CHASE | DATA_MISSING + allowed_tranche_pct: 0 | 20 | 30 + blocked_reason_codes: array prohibition: - - "blocked_late_chase 상태에서 LLM이 뉴스·테마를 이유로 BUY 승격 금지" - - "pilot_allowed여도 계획수량 30% 초과 금지" - canonical_ref: "proposals/2026-05-20_APEX_ALPHA_PRESERVATION_EXECUTION_HARNESS_V1.md" - version: "2026-05-20_APEX_V1" - + - blocked_late_chase 상태에서 LLM이 뉴스·테마를 이유로 BUY 승격 금지 + - pilot_allowed여도 계획수량 30% 초과 금지 + canonical_ref: proposals/2026-05-20_APEX_ALPHA_PRESERVATION_EXECUTION_HARNESS_V1.md + version: 2026-05-20_APEX_V1 FOLLOW_THROUGH_CONFIRM_V1: - purpose: > - 돌파 이후 1~3거래일 내 가격 유지·거래대금 과열 완화·수급 유지 여부를 확인해 - 본진입, 대기, 실패를 결정론적으로 분류한다. - inputs: [] - input_groups: - required: - - "breakout_day_close" - - "current_close" - - "ma5" - - "ma20" - - "volume_vs_5d" - - "frg_inst_flow_3d" - - "intraday_low_recovery_pct" - states: - CONFIRMED_ADD_ON: "돌파 가격 유지 + 거래대금 과열 완화 + 수급 유지" - FAILED_BREAKOUT: "돌파 이탈 또는 외국인/기관 동반 매도" - WAIT_PULLBACK: "가격은 유지되나 거래대금 과열 또는 눌림 미확인" - output: - field: "follow_through_json" - unit: "json_array" - prohibition: - - "WAIT_PULLBACK을 LLM이 본진입 허용으로 승격 금지" - - "FAILED_BREAKOUT 후 물타기 금지" - canonical_ref: "proposals/2026-05-20_APEX_ALPHA_PRESERVATION_EXECUTION_HARNESS_V1.md" - version: "2026-05-20_APEX_V1" + purpose: '돌파 이후 1~3거래일 내 가격 유지·거래대금 과열 완화·수급 유지 여부를 확인해 본진입, 대기, 실패를 결정론적으로 + 분류한다. - DISTRIBUTION_RISK_SCORE_V1: - purpose: > - 가격 유지 또는 상승 중 스마트머니 이탈, 거래대금 둔화, 윗꼬리, 낮은 flow_credit, - 섹터 대비 상대약세를 결합해 설거지·분산 위험을 0~100으로 산출한다. - related_formula: > - spec/13_formula_registry.yaml:DISTRIBUTION_SELL_DETECTOR_V1과 별개의 독립 - 공식이다(2026-06-22 역할 분리 확정, governance/gas_logic_migration_ledger_v1.yaml - F12/F13). 이 공식(점수식, BUY/STAGED_BUY/ADD_ON 차단 게이트)과 SELL_DETECTOR(6신호 - 카운트, PRE_DISTRIBUTION_EARLY_WARNING 정밀도 보완)는 입력·출력·목적이 다르며 - 하나가 다른 하나의 중복이 아니다 — 둘 다 유지한다. + ' inputs: [] input_groups: required: - - "price_above_ma20" - - "frg_5d_sh" - - "inst_5d_sh" - - "frg_20d_sh" - - "inst_20d_sh" - - "volume_5d_vs_20d" - - "close_location_value" - - "upper_wick_ratio" - - "flow_credit" - - "ret5d_vs_sector" + - breakout_day_close + - current_close + - ma5 + - ma20 + - volume_vs_5d + - frg_inst_flow_3d + - intraday_low_recovery_pct + states: + CONFIRMED_ADD_ON: 돌파 가격 유지 + 거래대금 과열 완화 + 수급 유지 + FAILED_BREAKOUT: 돌파 이탈 또는 외국인/기관 동반 매도 + WAIT_PULLBACK: 가격은 유지되나 거래대금 과열 또는 눌림 미확인 + output: + field: follow_through_json + unit: json_array + prohibition: + - WAIT_PULLBACK을 LLM이 본진입 허용으로 승격 금지 + - FAILED_BREAKOUT 후 물타기 금지 + canonical_ref: proposals/2026-05-20_APEX_ALPHA_PRESERVATION_EXECUTION_HARNESS_V1.md + version: 2026-05-20_APEX_V1 + DISTRIBUTION_RISK_SCORE_V1: + purpose: '가격 유지 또는 상승 중 스마트머니 이탈, 거래대금 둔화, 윗꼬리, 낮은 flow_credit, 섹터 대비 상대약세를 + 결합해 설거지·분산 위험을 0~100으로 산출한다. + + ' + related_formula: 'spec/13_formula_registry.yaml:DISTRIBUTION_SELL_DETECTOR_V1과 + 별개의 독립 공식이다(2026-06-22 역할 분리 확정, governance/gas_logic_migration_ledger_v1.yaml + F12/F13). 이 공식(점수식, BUY/STAGED_BUY/ADD_ON 차단 게이트)과 SELL_DETECTOR(6신호 카운트, + PRE_DISTRIBUTION_EARLY_WARNING 정밀도 보완)는 입력·출력·목적이 다르며 하나가 다른 하나의 중복이 아니다 — + 둘 다 유지한다. + + ' + inputs: [] + input_groups: + required: + - price_above_ma20 + - frg_5d_sh + - inst_5d_sh + - frg_20d_sh + - inst_20d_sh + - volume_5d_vs_20d + - close_location_value + - upper_wick_ratio + - flow_credit + - ret5d_vs_sector components: smart_money_outflow: 30 volume_fade_after_surge: 20 @@ -392,2837 +488,3525 @@ formula_registry: flow_credit_low: 20 sector_relative_lag: 15 gates: - BLOCK_BUY: "score >= 70" - TRIM_REVIEW: "55 <= score < 70" - PASS: "score < 55" + BLOCK_BUY: score >= 70 + TRIM_REVIEW: 55 <= score < 70 + PASS: score < 55 output: - field: "distribution_risk_json" - unit: "json_array" + field: distribution_risk_json + unit: json_array prohibition: - - "BLOCK_BUY 상태에서 BUY/STAGED_BUY/ADD_ON 출력 금지" - - "분산 위험이 높아도 과매도 매도는 SMART_CASH_RAISE_PLAN_V1을 거쳐 실행" - canonical_ref: "spec/exit/proactive_exit_radar.yaml" - version: "2026-05-20_APEX_V1" - + - BLOCK_BUY 상태에서 BUY/STAGED_BUY/ADD_ON 출력 금지 + - 분산 위험이 높아도 과매도 매도는 SMART_CASH_RAISE_PLAN_V1을 거쳐 실행 + canonical_ref: spec/exit/proactive_exit_radar.yaml + version: 2026-05-20_APEX_V1 PROFIT_PRESERVATION_STATE_V1: - purpose: > - 수익률, ATR, 고점 대비 하락, 수급 훼손, 분산 위험을 이용해 수익 보호 단계를 분류하고 - 래칫·트레일링·부분 이익잠금 적용 여부를 잠근다. + purpose: '수익률, ATR, 고점 대비 하락, 수급 훼손, 분산 위험을 이용해 수익 보호 단계를 분류하고 래칫·트레일링·부분 이익잠금 + 적용 여부를 잠근다. + + ' inputs: [] input_groups: required: - - "profit_pct" - - "atr20_pct" - - "highest_price_since_entry" - - "current_close" - - "ma20" - - "frg_inst_flow_5d" - - "distribution_risk_score" + - profit_pct + - atr20_pct + - highest_price_since_entry + - current_close + - ma20 + - frg_inst_flow_5d + - distribution_risk_score states: - NORMAL: "profit_pct < 8" - BREAKEVEN_RATCHET: "profit_pct >= 8 OR current_close >= average_cost + atr20" - PROFIT_LOCK_10: "profit_pct >= 10" - PROFIT_LOCK_20: "profit_pct >= 20" - PROFIT_LOCK_30: "profit_pct >= 30" - APEX_TRAILING: "profit_pct >= 30 AND trend_intact" + NORMAL: profit_pct < 8 + BREAKEVEN_RATCHET: profit_pct >= 8 OR current_close >= average_cost + atr20 + PROFIT_LOCK_10: profit_pct >= 10 + PROFIT_LOCK_20: profit_pct >= 20 + PROFIT_LOCK_30: profit_pct >= 30 + APEX_TRAILING: profit_pct >= 30 AND trend_intact output: - field: "profit_preservation_json" - unit: "json_array" + field: profit_preservation_json + unit: json_array prohibition: - - "수익 보호 상태를 LLM이 장기 전망으로 해제 금지" - - "래칫 가격은 PROFIT_LOCK_RATCHET_V1/TRAILING_STOP_PRICE_V1/TICK_NORMALIZER_V1 결과만 허용" - canonical_ref: "spec/13_formula_registry.yaml:PROFIT_LOCK_RATCHET_V1" - version: "2026-05-20_APEX_V1" - + - 수익 보호 상태를 LLM이 장기 전망으로 해제 금지 + - 래칫 가격은 PROFIT_LOCK_RATCHET_V1/TRAILING_STOP_PRICE_V1/TICK_NORMALIZER_V1 결과만 + 허용 + canonical_ref: spec/13_formula_registry.yaml:PROFIT_LOCK_RATCHET_V1 + version: 2026-05-20_APEX_V1 SMART_CASH_RAISE_PLAN_V1: - purpose: > - cash_shortfall을 해소하되 가격 훼손을 줄이기 위해 즉시 매도수량, 반등 대기수량, - 최대 일일 매도수량, 실행 스타일을 결정론적으로 배정한다. + purpose: 'cash_shortfall을 해소하되 가격 훼손을 줄이기 위해 즉시 매도수량, 반등 대기수량, 최대 일일 매도수량, 실행 + 스타일을 결정론적으로 배정한다. + + ' inputs: [] input_groups: required: - - "cash_shortfall_min_krw" - - "cash_shortfall_target_krw" - - "sell_candidates_json" - - "current_price" - - "atr20" - - "rsi14" - - "bb_position" - - "ma20_distance_pct" - - "avg_trade_value_5d" - - "distribution_risk_score" - - "profit_preservation_state" + - cash_shortfall_min_krw + - cash_shortfall_target_krw + - sell_candidates_json + - current_price + - atr20 + - rsi14 + - bb_position + - ma20_distance_pct + - avg_trade_value_5d + - distribution_risk_score + - profit_preservation_state execution_styles: - URGENT_LIQUIDITY_TRIM: "cash_floor_status=HARD_BLOCK AND not oversold" - OVERSOLD_REBOUND_SELL: "rsi14 < 35 OR bb_position < 20 OR close < ma20 - 8%" - DISTRIBUTION_EXIT: "distribution_risk_score >= 70" - PROFIT_PROTECT_TRIM: "profit_preservation_state IN [PROFIT_LOCK_20, PROFIT_LOCK_30]" + URGENT_LIQUIDITY_TRIM: cash_floor_status=HARD_BLOCK AND not oversold + OVERSOLD_REBOUND_SELL: rsi14 < 35 OR bb_position < 20 OR close < ma20 - 8% + DISTRIBUTION_EXIT: distribution_risk_score >= 70 + PROFIT_PROTECT_TRIM: profit_preservation_state IN [PROFIT_LOCK_20, PROFIT_LOCK_30] output: - field: "cash_raise_plan_json" - unit: "json_array" + field: cash_raise_plan_json + unit: json_array prohibition: - - "OVERSOLD_REBOUND_SELL에서 즉시 매도수량 cap 초과 금지" - - "코어 주도주는 tier 1~8 후보 소진 전 현금확보 1순위 금지" - canonical_ref: "spec/risk/portfolio_exposure.yaml:sell_priority_engine" - version: "2026-05-20_APEX_V1" - + - OVERSOLD_REBOUND_SELL에서 즉시 매도수량 cap 초과 금지 + - 코어 주도주는 tier 1~8 후보 소진 전 현금확보 1순위 금지 + canonical_ref: spec/risk/portfolio_exposure.yaml:sell_priority_engine + version: 2026-05-20_APEX_V1 REBOUND_SELL_TRIGGER_V1: - purpose: "과매도 현금확보 후보의 잔여 매도를 반등 조건 충족 시점으로 지연한다." + purpose: 과매도 현금확보 후보의 잔여 매도를 반등 조건 충족 시점으로 지연한다. inputs: [] input_groups: required: - - "current_price" - - "prior_close" - - "intraday_vwap" - - "ma5" - - "rsi14" - - "volume_vs_5d" - - "atr20" + - current_price + - prior_close + - intraday_vwap + - ma5 + - rsi14 + - volume_vs_5d + - atr20 trigger_any: - - "current_price >= prior_close + 0.5 * atr20" - - "current_price > intraday_vwap AND rsi14 recovers above 40" - - "current_price >= ma5 AND volume_vs_5d >= 0.8" + - current_price >= prior_close + 0.5 * atr20 + - current_price > intraday_vwap AND rsi14 recovers above 40 + - current_price >= ma5 AND volume_vs_5d >= 0.8 output: - field: "rebound_sell_trigger_json" - unit: "json_array" + field: rebound_sell_trigger_json + unit: json_array prohibition: - - "trigger_state 미충족 잔여수량을 LLM이 즉시 매도로 승격 금지" - canonical_ref: "proposals/2026-05-20_APEX_ALPHA_PRESERVATION_EXECUTION_HARNESS_V1.md" - version: "2026-05-20_APEX_V1" - + - trigger_state 미충족 잔여수량을 LLM이 즉시 매도로 승격 금지 + canonical_ref: proposals/2026-05-20_APEX_ALPHA_PRESERVATION_EXECUTION_HARNESS_V1.md + version: 2026-05-20_APEX_V1 EXECUTION_QUALITY_GUARD_V1: - purpose: "주문금액/거래대금/스프레드/변동성을 이용해 체결 품질과 분할 필요 여부를 검증한다." + purpose: 주문금액/거래대금/스프레드/변동성을 이용해 체결 품질과 분할 필요 여부를 검증한다. inputs: [] input_groups: required: - - "avg_trade_value_5d" - - "order_amount_krw" - - "spread_pct" - - "tick_size" - - "intraday_volatility_pct" + - avg_trade_value_5d + - order_amount_krw + - spread_pct + - tick_size + - intraday_volatility_pct rules: - max_order_vs_adv: "order_amount_krw <= avg_trade_value_5d * 0.03" - split_required: "order_amount_krw > avg_trade_value_5d * 0.01" - market_order_ban: "항상 시장가 금지. 비상 hard stop 예외도 하네스 명시 필요" - reprice_limit: "불리한 방향 2회 이상 추격 정정 금지" + max_order_vs_adv: order_amount_krw <= avg_trade_value_5d * 0.03 + split_required: order_amount_krw > avg_trade_value_5d * 0.01 + market_order_ban: 항상 시장가 금지. 비상 hard stop 예외도 하네스 명시 필요 + reprice_limit: 불리한 방향 2회 이상 추격 정정 금지 output: - field: "execution_quality_json" - unit: "json_array" + field: execution_quality_json + unit: json_array prohibition: - - "execution_quality_status != PASS이면 HTS 주문표 PASS 금지" - canonical_ref: "spec/05_position_sizing.yaml:liquidity_constraint" - version: "2026-05-20_APEX_V1" - + - execution_quality_status != PASS이면 HTS 주문표 PASS 금지 + canonical_ref: spec/05_position_sizing.yaml:liquidity_constraint + version: 2026-05-20_APEX_V1 BUY_PERMISSION_MATRIX_V1: - purpose: "POSITION_SIZE_V1 이전에 매수 허가 상태와 최대 tranche를 확정한다." + purpose: POSITION_SIZE_V1 이전에 매수 허가 상태와 최대 tranche를 확정한다. inputs: [] required_pass_all: - - "cash_floor_status=PASS" - - "heat_gate_status != BLOCK_NEW_BUY" - - "distribution_risk_score < 55" - - "alpha_lead_score >= 75 OR follow_through_state=CONFIRMED_ADD_ON" - - "expected_edge >= floor" + - cash_floor_status=PASS + - heat_gate_status != BLOCK_NEW_BUY + - distribution_risk_score < 55 + - alpha_lead_score >= 75 OR follow_through_state=CONFIRMED_ADD_ON + - expected_edge >= floor output: - field: "buy_permission_json" - unit: "json_array" - states: ["ALLOW_PILOT", "ALLOW_ADD_ON", "WATCH", "BLOCKED"] + field: buy_permission_json + unit: json_array + states: + - ALLOW_PILOT + - ALLOW_ADD_ON + - WATCH + - BLOCKED prohibition: - - "BUY_PERMISSION_MATRIX_V1 != ALLOW_*이면 buy_qty_inputs_json.final_qty는 null" - canonical_ref: "spec/05_position_sizing.yaml:pre_permission_gate" - version: "2026-05-20_APEX_V1" - + - BUY_PERMISSION_MATRIX_V1 != ALLOW_*이면 buy_qty_inputs_json.final_qty는 null + canonical_ref: spec/05_position_sizing.yaml:pre_permission_gate + version: 2026-05-20_APEX_V1 SELL_QUANTITY_ALLOCATOR_V1: - purpose: "현금 부족액, 매도우선순위, 실행스타일, cap을 반영해 정수 매도수량을 확정한다." + purpose: 현금 부족액, 매도우선순위, 실행스타일, cap을 반영해 정수 매도수량을 확정한다. inputs: [] input_groups: required: - - "cash_shortfall_krw" - - "sell_priority_rank" - - "holding_quantity" - - "current_price" - - "execution_style" - - "max_daily_qty_pct" - - "immediate_qty_cap_pct" + - cash_shortfall_krw + - sell_priority_rank + - holding_quantity + - current_price + - execution_style + - max_daily_qty_pct + - immediate_qty_cap_pct output: - field: "smart_sell_quantities_json" - unit: "json_array" + field: smart_sell_quantities_json + unit: json_array output_schema: - immediate_sell_qty: "integer_or_null" - staged_sell_qty: "integer_or_null" - rebound_wait_qty: "integer_or_null" - expected_cash_recovered_krw: "KRW" + immediate_sell_qty: integer_or_null + staged_sell_qty: integer_or_null + rebound_wait_qty: integer_or_null + expected_cash_recovered_krw: KRW prohibition: - - "LLM이 Sell_Ratio_Pct × holding_quantity를 직접 계산해 대체 금지" - canonical_ref: "spec/00_execution_contract.yaml:signal_quantity_separation" - version: "2026-05-20_APEX_V1" - + - LLM이 Sell_Ratio_Pct × holding_quantity를 직접 계산해 대체 금지 + canonical_ref: spec/00_execution_contract.yaml:signal_quantity_separation + version: 2026-05-20_APEX_V1 LIMIT_PRICE_POLICY_V1: - purpose: "매수/매도 지정가를 실행 스타일별로 산출하고 TICK_NORMALIZER_V1을 강제 적용한다." + purpose: 매수/매도 지정가를 실행 스타일별로 산출하고 TICK_NORMALIZER_V1을 강제 적용한다. inputs: [] sell_styles: - normal_trim: "min(current_price, prior_close * 0.998)" - rebound_sell: "rebound_trigger_price 근처 지정가" - distribution_exit: "current_price - 0.25 * ATR20 범위 내 방어 지정가" - profit_protect: "current_price 또는 trailing_stop 상단 기준" + normal_trim: min(current_price, prior_close * 0.998) + rebound_sell: rebound_trigger_price 근처 지정가 + distribution_exit: current_price - 0.25 * ATR20 범위 내 방어 지정가 + profit_protect: current_price 또는 trailing_stop 상단 기준 buy_styles: - pilot: "close * 1.002 상한, chase cap 적용" - pullback: "ma20 * 1.003 또는 close * 1.002 중 낮은 값" - add_on: "follow_through_confirm 후 previous entry 대비 0.5~1.0% 상한" + pilot: close * 1.002 상한, chase cap 적용 + pullback: ma20 * 1.003 또는 close * 1.002 중 낮은 값 + add_on: follow_through_confirm 후 previous entry 대비 0.5~1.0% 상한 output: - field: "limit_price_policy_json" - unit: "json_array" - post_process: "TICK_NORMALIZER_V1" + field: limit_price_policy_json + unit: json_array + post_process: TICK_NORMALIZER_V1 prohibition: - - "심리적 가격·차트 지지선으로 limit_price 대체 금지" - - "TICK_OK 태그 없는 가격은 HTS 출력 금지" - canonical_ref: "spec/13_formula_registry.yaml:TICK_NORMALIZER_V1" - version: "2026-05-20_APEX_V1" - - # == [2026-05-20_K1] K1 - 분할 매수 트랜치 엔진 ========================== + - 심리적 가격·차트 지지선으로 limit_price 대체 금지 + - TICK_OK 태그 없는 가격은 HTS 출력 금지 + canonical_ref: spec/13_formula_registry.yaml:TICK_NORMALIZER_V1 + version: 2026-05-20_APEX_V1 STAGED_ENTRY_TRANCHE_V1: - purpose: > - 파일럿(T1) → 돌파확인(T2) → 눌림재진입(T3) 순서로 매수 비중을 3단계로 분할. - LLM이 한 번에 전량 매수를 지시하거나 PILOT_ALLOWED → ADD_ON 단계를 건너뛰는 것을 차단. - buy_permission_json의 tranche_phase를 GAS가 확정하고 LLM은 복사만 한다. + purpose: '파일럿(T1) → 돌파확인(T2) → 눌림재진입(T3) 순서로 매수 비중을 3단계로 분할. LLM이 한 번에 전량 매수를 + 지시하거나 PILOT_ALLOWED → ADD_ON 단계를 건너뛰는 것을 차단. buy_permission_json의 tranche_phase를 + GAS가 확정하고 LLM은 복사만 한다. + + ' inputs: - - {field: "alpha_lead_score", unit: "score_0_100"} - - {field: "lead_entry_state", unit: "enum"} - - {field: "follow_through_state", unit: "enum"} - - {field: "holding_quantity", unit: "shares"} - - {field: "profit_pct", unit: "percent"} - - {field: "close_vs_ma20_pct", unit: "percent"} + - field: alpha_lead_score + unit: score_0_100 + - field: lead_entry_state + unit: enum + - field: follow_through_state + unit: enum + - field: holding_quantity + unit: shares + - field: profit_pct + unit: percent + - field: close_vs_ma20_pct + unit: percent tranche_phases: - WAIT_PILOT_SETUP: "진입 조건 미충족 - 매수 금지" - TRANCHE_1_PILOT: "신규 파일럿 30% - PILOT_ALLOWED이며 포지션 없음" - TRANCHE_2_ADD_ON: "본진입 추가 30% - CONFIRMED_ADD_ON + 기보유" - TRANCHE_3_PULLBACK_ADD: "눌림 추가 40% - MA20 ±2% + 수익>3% + ADD_ON" - HOLD_CURRENT: "현 포지션 유지 - 추가 매수 조건 미충족" + WAIT_PILOT_SETUP: 진입 조건 미충족 - 매수 금지 + TRANCHE_1_PILOT: 신규 파일럿 30% - PILOT_ALLOWED이며 포지션 없음 + TRANCHE_2_ADD_ON: 본진입 추가 30% - CONFIRMED_ADD_ON + 기보유 + TRANCHE_3_PULLBACK_ADD: 눌림 추가 40% - MA20 ±2% + 수익>3% + ADD_ON + HOLD_CURRENT: 현 포지션 유지 - 추가 매수 조건 미충족 output: fields: - - {field: "tranche_phase", unit: "enum"} - - {field: "current_tranche_allowed_pct", unit: "percent"} - - {field: "next_tranche_condition", unit: "string"} + - field: tranche_phase + unit: enum + - field: current_tranche_allowed_pct + unit: percent + - field: next_tranche_condition + unit: string prohibition: - - "LLM이 tranche_phase를 임의로 TRANCHE_2·TRANCHE_3으로 승격 금지" - - "WAIT_PILOT_SETUP·HOLD_CURRENT 상태에서 current_tranche_allowed_pct > 0 출력 금지" - - "T1→T2→T3 순서 건너뜀 금지 - CONFIRMED_ADD_ON 없이 TRANCHE_3 진입 금지" - canonical_ref: "AGENTS.md:Direction K1" - version: "2026-05-20_K1" - - # == [2026-05-20_K2] K2 - 반등 대기 분할 매도 체계 ======================= + - LLM이 tranche_phase를 임의로 TRANCHE_2·TRANCHE_3으로 승격 금지 + - WAIT_PILOT_SETUP·HOLD_CURRENT 상태에서 current_tranche_allowed_pct > 0 출력 금지 + - T1→T2→T3 순서 건너뜀 금지 - CONFIRMED_ADD_ON 없이 TRANCHE_3 진입 금지 + canonical_ref: AGENTS.md:Direction K1 + version: 2026-05-20_K1 K2_STAGED_REBOUND_SELL_V1: - purpose: > - 현금확보 매도(OVERSOLD_REBOUND_SELL 스타일)를 즉시매도(50%) + 반등대기(50%)로 분할해 - 주식가치 훼손을 최소화하면서 현금 수요를 충족한다. - 즉시매도 예상금액 × 2가 shortfall을 충당하지 못할 때만 비상 전량 매도(emergency_full_sell=true)를 허용. + purpose: '현금확보 매도(OVERSOLD_REBOUND_SELL 스타일)를 즉시매도(50%) + 반등대기(50%)로 분할해 주식가치 + 훼손을 최소화하면서 현금 수요를 충족한다. 즉시매도 예상금액 × 2가 shortfall을 충당하지 못할 때만 비상 전량 매도(emergency_full_sell=true)를 + 허용. + + ' inputs: - - {field: "base_sell_qty", unit: "shares", note: "H3 SELL_QUANTITY_ALLOCATOR_V1 산출"} - - {field: "close", unit: "KRW_per_share"} - - {field: "cash_shortfall_min_krw", unit: "KRW", note: "G1 CASH_SHORTFALL_V1 산출"} - - {field: "profit_preservation_state", unit: "enum"} - - {field: "execution_style", unit: "enum", note: "OVERSOLD_REBOUND_SELL 이외 스타일은 미적용"} + - field: base_sell_qty + unit: shares + note: H3 SELL_QUANTITY_ALLOCATOR_V1 산출 + - field: close + unit: KRW_per_share + - field: cash_shortfall_min_krw + unit: KRW + note: G1 CASH_SHORTFALL_V1 산출 + - field: profit_preservation_state + unit: enum + - field: execution_style + unit: enum + note: OVERSOLD_REBOUND_SELL 이외 스타일은 미적용 expressions: - half_qty: "floor(base_sell_qty / 2)" - half_expected_krw: "half_qty × close" - emergency_full_sell: "cash_shortfall_min_krw > 0 AND half_expected_krw × 2 < cash_shortfall_min_krw" - immediate_sell_qty: "emergency_full_sell ? base_sell_qty : half_qty" - rebound_wait_qty: "emergency_full_sell ? 0 : max(0, base_sell_qty - half_qty)" - oversold_cap_qty: "floor(holding_qty × cap_pct/100)" + half_qty: floor(base_sell_qty / 2) + half_expected_krw: half_qty × close + emergency_full_sell: cash_shortfall_min_krw > 0 AND half_expected_krw × 2 + < cash_shortfall_min_krw + immediate_sell_qty: 'emergency_full_sell ? base_sell_qty : half_qty' + rebound_wait_qty: 'emergency_full_sell ? 0 : max(0, base_sell_qty - half_qty)' + oversold_cap_qty: floor(holding_qty × cap_pct/100) cap_pct_by_profit_state: PROFIT_LOCK_30: 40 - APEX_TRAILING: 40 + APEX_TRAILING: 40 PROFIT_LOCK_20: 35 PROFIT_LOCK_10: 30 - default: 50 + default: 50 output: fields: - - {field: "immediate_sell_qty", unit: "shares"} - - {field: "rebound_wait_qty", unit: "shares"} - - {field: "emergency_full_sell", unit: "boolean"} - - {field: "rebound_trigger_price", unit: "KRW_per_share", note: "prevClose + 0.5×ATR20 tick-normalized"} + - field: immediate_sell_qty + unit: shares + - field: rebound_wait_qty + unit: shares + - field: emergency_full_sell + unit: boolean + - field: rebound_trigger_price + unit: KRW_per_share + note: prevClose + 0.5×ATR20 tick-normalized prohibition: - - "rebound_wait_qty > 0인 물량을 반등 트리거 미충족 상태에서 즉시 매도 금지" - - "emergency_full_sell=false에서 rebound_wait_qty를 LLM이 즉시매도로 전환 금지" - - "OVERSOLD_REBOUND_SELL 외 스타일에 이 규칙 적용 금지" - canonical_ref: "AGENTS.md:Direction K2" - version: "2026-05-20_K2" - - # == [2026-05-20_K3] K3 - 국면·섹터 연계 H2 동적 우선순위 ================ + - rebound_wait_qty > 0인 물량을 반등 트리거 미충족 상태에서 즉시 매도 금지 + - emergency_full_sell=false에서 rebound_wait_qty를 LLM이 즉시매도로 전환 금지 + - OVERSOLD_REBOUND_SELL 외 스타일에 이 규칙 적용 금지 + canonical_ref: AGENTS.md:Direction K2 + version: 2026-05-20_K2 K3_REGIME_SELL_PRIORITY_V1: - purpose: > - H2 정적 순위에 시장 국면(regime) 신호를 오버레이하여 동적 우선순위를 부여한다. - EVENT_SHOCK에서는 KOSPI 고베타 종목이, RISK_ON에서는 섹터 상대약세 종목이 우선 정리된다. - H2 원래 rank는 변경하지 않고 regime_priority_adjustment(-3~0)와 final_regime_rank을 추가한다. + purpose: 'H2 정적 순위에 시장 국면(regime) 신호를 오버레이하여 동적 우선순위를 부여한다. EVENT_SHOCK에서는 KOSPI + 고베타 종목이, RISK_ON에서는 섹터 상대약세 종목이 우선 정리된다. H2 원래 rank는 변경하지 않고 regime_priority_adjustment(-3~0)와 + final_regime_rank을 추가한다. + + ' inputs: - - {field: "h2_candidates", unit: "list", note: "H2 매도후보 배열 (rank/tier/score)"} - - {field: "market_regime_state", unit: "enum"} - - {field: "ret5d", unit: "percent"} - - {field: "kospi_ret5d", unit: "percent"} - - {field: "frg_5d", unit: "KRW"} - - {field: "inst_5d", unit: "KRW"} - - {field: "flow_credit", unit: "score_0_1"} - - {field: "ac_gate", unit: "string"} + - field: h2_candidates + unit: list + note: H2 매도후보 배열 (rank/tier/score) + - field: market_regime_state + unit: enum + - field: ret5d + unit: percent + - field: kospi_ret5d + unit: percent + - field: frg_5d + unit: KRW + - field: inst_5d + unit: KRW + - field: flow_credit + unit: score_0_1 + - field: ac_gate + unit: string adjustment_rules: RISK_OFF_EVENT_SHOCK: high_beta_proxy_gt_1_3: -3 - dual_outflow: -2 - above_beta_proxy_gt_1: -1 + dual_outflow: -2 + above_beta_proxy_gt_1: -1 RISK_OFF_CANDIDATE: - flow_credit_lt_0_30: -2 - flow_credit_lt_0_45: -1 + flow_credit_lt_0_30: -2 + flow_credit_lt_0_45: -1 RISK_ON_SECULAR_LEADER: - sector_lag_gt_3pct: -2 - duplicate_etf: -2 + sector_lag_gt_3pct: -2 + duplicate_etf: -2 LEADER_CONCENTRATION_NEUTRAL: - anti_climax_gate: -1 + anti_climax_gate: -1 output: - field: "regime_adjusted_sell_priority_json" - unit: "json_array" + field: regime_adjusted_sell_priority_json + unit: json_array output_schema: - rank: "H2 원래 순위" - final_regime_rank: "국면 조정 후 최종 순위" - regime_priority_adjustment: "조정값 (음수=우선 상향)" - adjustment_reason: "조정 근거 코드" - regime_applied: "적용된 국면 상태" + rank: H2 원래 순위 + final_regime_rank: 국면 조정 후 최종 순위 + regime_priority_adjustment: 조정값 (음수=우선 상향) + adjustment_reason: 조정 근거 코드 + regime_applied: 적용된 국면 상태 prohibition: - - "LLM이 regime_adjusted_sell_priority_json을 임의로 재정렬 금지" - - "sell_priority_lock=true이면 LLM이 final_regime_rank도 번복 금지" - - "H2 tier 경계를 넘는 순위 이동 금지 (tier 1 → tier 2 크로스 불가)" - canonical_ref: "AGENTS.md:Direction K3" - version: "2026-05-20_K3" - - # == [2026-05-20_L1] L1 - 섹터 로테이션 모멘텀 추적 ==================== + - LLM이 regime_adjusted_sell_priority_json을 임의로 재정렬 금지 + - sell_priority_lock=true이면 LLM이 final_regime_rank도 번복 금지 + - H2 tier 경계를 넘는 순위 이동 금지 (tier 1 → tier 2 크로스 불가) + canonical_ref: AGENTS.md:Direction K3 + version: 2026-05-20_K3 SECTOR_ROTATION_MOMENTUM_V1: - purpose: > - sectorFlowRadar의 rank/prevRank/prevRankW2를 기반으로 각 섹터의 rank_delta를 계산하고 - RISING/STABLE/FADING/TOPPING_OUT 모멘텀 상태를 분류한다. - FADING(-15)/TOPPING_OUT(-10) 섹터 종목에 ALPHA_LEAD_SCORE_V1 페널티를 적용한다. - 결과는 sector_rotation_momentum_json으로 고착화 - LLM 재산출 금지. + purpose: 'sectorFlowRadar의 rank/prevRank/prevRankW2를 기반으로 각 섹터의 rank_delta를 + 계산하고 RISING/STABLE/FADING/TOPPING_OUT 모멘텀 상태를 분류한다. FADING(-15)/TOPPING_OUT(-10) + 섹터 종목에 ALPHA_LEAD_SCORE_V1 페널티를 적용한다. 결과는 sector_rotation_momentum_json으로 + 고착화 - LLM 재산출 금지. + + ' inputs: - - {field: "sector", unit: "string"} - - {field: "rank", unit: "integer", note: "현재 주 섹터 로테이션 순위"} - - {field: "prev_rank_w1", unit: "integer", note: "1주 전 순위"} - - {field: "prev_rank_w2", unit: "integer", note: "2주 전 순위"} + - field: sector + unit: string + - field: rank + unit: integer + note: 현재 주 섹터 로테이션 순위 + - field: prev_rank_w1 + unit: integer + note: 1주 전 순위 + - field: prev_rank_w2 + unit: integer + note: 2주 전 순위 derived_fields: - rank_delta_w1: "rank - prev_rank_w1 (양수=순위 하락=약화)" - rank_delta_w2: "rank - prev_rank_w2" + rank_delta_w1: rank - prev_rank_w1 (양수=순위 하락=약화) + rank_delta_w2: rank - prev_rank_w2 momentum_states: - RISING: "rank_delta_w1 <= -2 (순위 상승 → 로테이션 유입)" - STABLE: "변화 없음 또는 소폭 등락" - TOPPING_OUT: "rank <= 3 AND rank_delta_w1 >= 1 (상위권이지만 하락 전환)" - FADING: "rank_delta_w1 >= 2 AND rank_delta_w2 >= 2 (연속 순위 하락)" + RISING: rank_delta_w1 <= -2 (순위 상승 → 로테이션 유입) + STABLE: 변화 없음 또는 소폭 등락 + TOPPING_OUT: rank <= 3 AND rank_delta_w1 >= 1 (상위권이지만 하락 전환) + FADING: rank_delta_w1 >= 2 AND rank_delta_w2 >= 2 (연속 순위 하락) alpha_lead_penalty: - FADING: -15 + FADING: -15 TOPPING_OUT: -10 output: - field: "sector_rotation_momentum_json" - unit: "json_array" + field: sector_rotation_momentum_json + unit: json_array output_schema: - sector: "섹터명" - rank: "현재 순위" - rank_delta_w1: "1주 delta (양수=하락)" - rank_delta_w2: "2주 delta" - momentum_state: "RISING/STABLE/TOPPING_OUT/FADING" + sector: 섹터명 + rank: 현재 순위 + rank_delta_w1: 1주 delta (양수=하락) + rank_delta_w2: 2주 delta + momentum_state: RISING/STABLE/TOPPING_OUT/FADING prohibition: - - "LLM이 sector_rotation_momentum_json을 재정렬·재산출 금지" - - "sector_rotation_momentum_lock=true이면 LLM이 momentum_state를 번복 금지" - canonical_ref: "AGENTS.md:Direction L1" - version: "2026-05-20_L1" - - # == [2026-05-20_L4] L4 - 분배 선행경보 (신고점수축 / 급등약류) ========== + - LLM이 sector_rotation_momentum_json을 재정렬·재산출 금지 + - sector_rotation_momentum_lock=true이면 LLM이 momentum_state를 번복 금지 + canonical_ref: AGENTS.md:Direction L1 + version: 2026-05-20_L1 PRE_DISTRIBUTION_EARLY_WARNING_V1: - purpose: > - DISTRIBUTION_RISK_SCORE_V1에 두 가지 선행경보 신호를 추가한다. - (1) 신고점 근접 + 거래량 수축: 분배 직전 전형 패턴 (score +12) - (2) 5일 급등(+5% 이상) + 수급 약화(flowCredit<0.45): 급등 후 설거지 위험 (score +10) - 기존 BLOCK_BUY/TRIM_REVIEW 임계값(70/55)을 낮추지 않고 신호 누적으로 조기 반영. + purpose: 'DISTRIBUTION_RISK_SCORE_V1에 두 가지 선행경보 신호를 추가한다. (1) 신고점 근접 + 거래량 수축: + 분배 직전 전형 패턴 (score +12) (2) 5일 급등(+5% 이상) + 수급 약화(flowCredit<0.45): 급등 후 설거지 + 위험 (score +10) 기존 BLOCK_BUY/TRIM_REVIEW 임계값(70/55)을 낮추지 않고 신호 누적으로 조기 반영. + + ' inputs: - - {field: "close", unit: "KRW_per_share"} - - {field: "high52w", unit: "KRW_per_share", note: "미제공 시 MA20×1.15 대체"} - - {field: "volume", unit: "shares"} - - {field: "avg_volume_5d", unit: "shares"} - - {field: "ret5d", unit: "pct"} - - {field: "flow_credit", unit: "0~1"} + - field: close + unit: KRW_per_share + - field: high52w + unit: KRW_per_share + note: 미제공 시 MA20×1.15 대체 + - field: volume + unit: shares + - field: avg_volume_5d + unit: shares + - field: ret5d + unit: pct + - field: flow_credit + unit: 0~1 signals: new_high_volume_contraction: - condition: "(close >= high52w×0.97 OR close > MA20×1.15) AND volume < avgVol5d×0.80" + condition: (close >= high52w×0.97 OR close > MA20×1.15) AND volume < avgVol5d×0.80 score: 12 surge_weak_flow: - condition: "ret5d >= 5 AND flow_credit < 0.45" + condition: ret5d >= 5 AND flow_credit < 0.45 score: 10 output: - field: "pre_distribution_warning" + field: pre_distribution_warning values: - EARLY_WARNING: "신고점수축 또는 급등약류 신호 발생 - 분배 선행경보" - NONE: "선행경보 신호 없음" + EARLY_WARNING: 신고점수축 또는 급등약류 신호 발생 - 분배 선행경보 + NONE: 선행경보 신호 없음 prohibition: - - "LLM이 pre_distribution_warning=EARLY_WARNING 종목에 신규 BUY를 즉시 실행 금지" - - "선행경보 무시하고 '아직 BLOCK_BUY 아니니 OK' 판단 금지" - canonical_ref: "AGENTS.md:Direction L4" - version: "2026-05-20_L4" - - # == [2026-05-20_L2] L2 - ATR 기반 자동 트레일링 손절 =================== + - LLM이 pre_distribution_warning=EARLY_WARNING 종목에 신규 BUY를 즉시 실행 금지 + - 선행경보 무시하고 '아직 BLOCK_BUY 아니니 OK' 판단 금지 + canonical_ref: AGENTS.md:Direction L4 + version: 2026-05-20_L4 RATCHET_TRAILING_AUTO_V1: - purpose: > - 수익 구간(PROFIT_LOCK_20/30, APEX_TRAILING)에서 ATR20 기반 자동 트레일링 손절가를 산출한다. - 기존 ratchet_stop(하드 래칫)과 비교해 더 유리한(높은) 값을 auto_trailing_stop으로 고착화. - LLM이 "익절 후 홀드" 판단에서 임의로 손절가를 낮추는 것을 구조적으로 차단. - inputs: - - {field: "highest_price_since_entry", unit: "KRW_per_share"} - - {field: "stop_price", unit: "KRW_per_share", note: "기존 ratchet_stop"} - - {field: "atr20", unit: "KRW_per_share"} - - {field: "profit_preservation_state", unit: "enum"} - expression: > - PROFIT_LOCK_20: auto_trailing_stop = max(ratchet_stop, highest_close - 1.5×ATR20); - PROFIT_LOCK_30 / APEX_TRAILING: auto_trailing_stop = max(ratchet_stop, highest_close - 2.0×ATR20); - 이외: auto_trailing_stop = null - 최종값은 KRX 호가단위로 floor 정규화 (tickNormalize_) - output: - field: "auto_trailing_stop" - unit: "KRW_per_share_or_null" - description: "ATR 트레일링 손절가. null이면 해당 수익 구간 아님. LLM이 이 값보다 낮은 손절가 제시 금지." - prohibition: - - "LLM이 auto_trailing_stop보다 낮은 손절가를 손절 원장에 기재 금지" - - "profit_lock 구간에서 ATR 조건 없이 임의로 홀드 연장하는 서술 금지" - canonical_ref: "AGENTS.md:Direction L2" - version: "2026-05-20_L2" + purpose: '수익 구간(PROFIT_LOCK_20/30, APEX_TRAILING)에서 ATR20 기반 자동 트레일링 손절가를 산출한다. + 기존 ratchet_stop(하드 래칫)과 비교해 더 유리한(높은) 값을 auto_trailing_stop으로 고착화. LLM이 "익절 + 후 홀드" 판단에서 임의로 손절가를 낮추는 것을 구조적으로 차단. - # == [2026-05-20_L3] L3 - 국면별 동적 Heat Gate ========================== + ' + inputs: + - field: highest_price_since_entry + unit: KRW_per_share + - field: stop_price + unit: KRW_per_share + note: 기존 ratchet_stop + - field: atr20 + unit: KRW_per_share + - field: profit_preservation_state + unit: enum + expression: 'PROFIT_LOCK_20: auto_trailing_stop = max(ratchet_stop, highest_close + - 1.5×ATR20); PROFIT_LOCK_30 / APEX_TRAILING: auto_trailing_stop = max(ratchet_stop, + highest_close - 2.0×ATR20); 이외: auto_trailing_stop = null 최종값은 KRX 호가단위로 floor + 정규화 (tickNormalize_) + + ' + output: + field: auto_trailing_stop + unit: KRW_per_share_or_null + description: ATR 트레일링 손절가. null이면 해당 수익 구간 아님. LLM이 이 값보다 낮은 손절가 제시 금지. + prohibition: + - LLM이 auto_trailing_stop보다 낮은 손절가를 손절 원장에 기재 금지 + - profit_lock 구간에서 ATR 조건 없이 임의로 홀드 연장하는 서술 금지 + canonical_ref: AGENTS.md:Direction L2 + version: 2026-05-20_L2 DYNAMIC_HEAT_GATE_V1: - purpose: > - marketRegime에 따라 Heat Gate 임계값을 동적으로 조정한다. - EVENT_SHOCK 국면에서는 임계값을 크게 낮춰 신규 매수를 강하게 억제하고, - RISK_ON/SECULAR_LEADER 국면에서는 임계값을 높여 매수 여지를 확장한다. - 고착화된 HEAT_HARD_BLOCK_PCT=10% 단일값을 국면 감응형으로 대체. - inputs: - - {field: "total_heat_pct", unit: "pct"} - - {field: "market_regime", unit: "string"} - thresholds_by_regime: - EVENT_SHOCK: {hard_block: 5.0, halve: 3.5} - RISK_OFF: {hard_block: 7.0, halve: 5.0} - NEUTRAL: {hard_block: 10.0, halve: 7.0} - RISK_ON: {hard_block: 12.0, halve: 8.5} - SECULAR_LEADER_RISK_ON: {hard_block: 13.0, halve: 9.0} - expression: > - heatThresholds = calcDynamicHeatThresholds_(marketRegime); - heatGate = total_heat_pct >= heatThresholds.hardBlock ? BLOCK_NEW_BUY - : total_heat_pct >= heatThresholds.halve ? HALVE_NEW_BUY_QUANTITY - : ALLOW_CONTINUE - output: - field: "heat_gate_threshold_pct" - unit: "pct" - description: "현재 국면에서 적용된 hard_block 임계값 (GAS 산출, LLM 변경 금지)" - prohibition: - - "LLM이 heat_gate_threshold_pct를 임의로 재계산하거나 무시 금지" - - "heat_gate_status=BLOCK_NEW_BUY이면 LLM이 BUY 액션을 복원 금지" - canonical_ref: "AGENTS.md:Direction L3" - version: "2026-05-20_L3" + purpose: 'marketRegime에 따라 Heat Gate 임계값을 동적으로 조정한다. EVENT_SHOCK 국면에서는 임계값을 + 크게 낮춰 신규 매수를 강하게 억제하고, RISK_ON/SECULAR_LEADER 국면에서는 임계값을 높여 매수 여지를 확장한다. 고착화된 + HEAT_HARD_BLOCK_PCT=10% 단일값을 국면 감응형으로 대체. - # == [2026-05-20_M1] M1 - 연속 손절 자동 매수 축소 ====================== + ' + inputs: + - field: total_heat_pct + unit: pct + - field: market_regime + unit: string + thresholds_by_regime: + EVENT_SHOCK: + hard_block: 5.0 + halve: 3.5 + RISK_OFF: + hard_block: 7.0 + halve: 5.0 + NEUTRAL: + hard_block: 10.0 + halve: 7.0 + RISK_ON: + hard_block: 12.0 + halve: 8.5 + SECULAR_LEADER_RISK_ON: + hard_block: 13.0 + halve: 9.0 + expression: "heatThresholds = calcDynamicHeatThresholds_(marketRegime); heatGate\ + \ = total_heat_pct >= heatThresholds.hardBlock ? BLOCK_NEW_BUY\n :\ + \ total_heat_pct >= heatThresholds.halve ? HALVE_NEW_BUY_QUANTITY\n \ + \ : ALLOW_CONTINUE\n" + output: + field: heat_gate_threshold_pct + unit: pct + description: 현재 국면에서 적용된 hard_block 임계값 (GAS 산출, LLM 변경 금지) + prohibition: + - LLM이 heat_gate_threshold_pct를 임의로 재계산하거나 무시 금지 + - heat_gate_status=BLOCK_NEW_BUY이면 LLM이 BUY 액션을 복원 금지 + canonical_ref: AGENTS.md:Direction L3 + version: 2026-05-20_L3 DRAWDOWN_GUARD_V1: - purpose: > - 연속 손절 횟수(consecutive_losses)에 따라 신규 매수 비중을 자동 축소한다. - bayesian_multiplier=0(>=5회) 위에 추가 방어층. 2~4회 구간에서도 조기 축소. + purpose: '연속 손절 횟수(consecutive_losses)에 따라 신규 매수 비중을 자동 축소한다. bayesian_multiplier=0(>=5회) + 위에 추가 방어층. 2~4회 구간에서도 조기 축소. + + ' inputs: - - {field: "consecutive_losses", unit: "integer"} + - field: consecutive_losses + unit: integer thresholds: - ">=5": {state: "NO_BUY", buy_scale: 0.0} - ">=3": {state: "REDUCE_BUY", buy_scale: 0.5} - ">=2": {state: "CAUTION_BUY", buy_scale: 0.75} - "0-1": {state: "NORMAL", buy_scale: 1.0} + '>=5': + state: NO_BUY + buy_scale: 0.0 + '>=3': + state: REDUCE_BUY + buy_scale: 0.5 + '>=2': + state: CAUTION_BUY + buy_scale: 0.75 + 0-1: + state: NORMAL + buy_scale: 1.0 output: fields: - drawdown_guard_state: "NO_BUY/REDUCE_BUY/CAUTION_BUY/NORMAL" - drawdown_buy_scale: "atrQty 곱셈 배수 (0~1.0). GAS 적용 후 고착화" - drawdown_consecutive_losses: "현재 연속 손절 횟수" + drawdown_guard_state: NO_BUY/REDUCE_BUY/CAUTION_BUY/NORMAL + drawdown_buy_scale: atrQty 곱셈 배수 (0~1.0). GAS 적용 후 고착화 + drawdown_consecutive_losses: 현재 연속 손절 횟수 prohibition: - - "LLM이 drawdown_buy_scale을 무시하고 정상 수량 제시 금지" - - "drawdown_guard_state=NO_BUY이면 BUY 주문 수량 0 또는 주문 생성 금지" - canonical_ref: "AGENTS.md:Direction M1" - version: "2026-05-20_M1" - - # == [2026-05-20_M2] M2 - 포트폴리오 가중평균 베타 관리 ================= + - LLM이 drawdown_buy_scale을 무시하고 정상 수량 제시 금지 + - drawdown_guard_state=NO_BUY이면 BUY 주문 수량 0 또는 주문 생성 금지 + canonical_ref: AGENTS.md:Direction M1 + version: 2026-05-20_M1 PORTFOLIO_BETA_GATE_V1: - purpose: > - 보유 종목 가중평균 베타(beta_proxy = ret5d/kospiRet5d)를 산출하고 - 국면별 상한과 비교해 OVER_BETA/WARN_BETA/PASS를 결정한다. - OVER_BETA 시 고베타 종목 TRIM 우선 조정. + purpose: '보유 종목 가중평균 베타(beta_proxy = ret5d/kospiRet5d)를 산출하고 국면별 상한과 비교해 OVER_BETA/WARN_BETA/PASS를 + 결정한다. OVER_BETA 시 고베타 종목 TRIM 우선 조정. + + ' inputs: - - {field: "weight_pct", unit: "pct"} - - {field: "ret5d", unit: "pct"} - - {field: "kospi_ret5d", unit: "pct"} - - {field: "market_regime", unit: "enum"} + - field: weight_pct + unit: pct + - field: ret5d + unit: pct + - field: kospi_ret5d + unit: pct + - field: market_regime + unit: enum beta_limits_by_regime: - EVENT_SHOCK: {over: 0.7, warn: 0.5} - RISK_OFF: {over: 0.8, warn: 0.6} - NEUTRAL: {over: 1.0, warn: 0.8} - RISK_ON: {over: 1.3, warn: 1.0} - SECULAR_LEADER_RISK_ON: {over: 1.5, warn: 1.2} + EVENT_SHOCK: + over: 0.7 + warn: 0.5 + RISK_OFF: + over: 0.8 + warn: 0.6 + NEUTRAL: + over: 1.0 + warn: 0.8 + RISK_ON: + over: 1.3 + warn: 1.0 + SECULAR_LEADER_RISK_ON: + over: 1.5 + warn: 1.2 output: fields: - portfolio_beta: "가중평균 베타 (GAS 산출)" - portfolio_beta_gate: "OVER_BETA/WARN_BETA/PASS/INSUFFICIENT_DATA" - portfolio_beta_gate_json: "per-holding 베타 상세" + portfolio_beta: 가중평균 베타 (GAS 산출) + portfolio_beta_gate: OVER_BETA/WARN_BETA/PASS/INSUFFICIENT_DATA + portfolio_beta_gate_json: per-holding 베타 상세 prohibition: - - "portfolio_beta_gate=OVER_BETA이면 고베타 종목 신규 BUY 금지" - - "LLM이 beta 값을 임의 재계산 금지" - canonical_ref: "AGENTS.md:Direction M2" - version: "2026-05-20_M2" - - # == [2026-05-20_M3] M3 - 분할 익절 수량 자동화 ========================= + - portfolio_beta_gate=OVER_BETA이면 고베타 종목 신규 BUY 금지 + - LLM이 beta 값을 임의 재계산 금지 + canonical_ref: AGENTS.md:Direction M2 + version: 2026-05-20_M2 TP_QUANTITY_LADDER_V1: - purpose: > - TP1/TP2/TP3 도달 시 매도할 수량을 GAS에서 자동 산출해 고착화한다. - 수동 입력(tp1_qty>0) 우선 사용, 없으면 보유수량의 33%/33%/34% 자동 분배. - LLM이 익절 수량을 임의로 결정하는 것을 구조적으로 차단. - inputs: - - {field: "holding_qty", unit: "shares"} - - {field: "tp1_price", unit: "KRW_per_share"} - - {field: "tp1_qty", unit: "shares", note: "수동 입력 우선"} - - {field: "tp2_price", unit: "KRW_per_share"} - - {field: "tp2_qty", unit: "shares"} - - {field: "tp3_qty", unit: "shares"} - output: - field: "tp_quantity_ladder_json" - schema: - tp1_qty: "TP1 도달 시 매도 수량 (수동/AUTO_33PCT)" - tp2_qty: "TP2 도달 시 매도 수량" - tp3_qty: "TP3/잔량 수량" - qty_source: "MANUAL/AUTO_33PCT/NO_HOLDING" - prohibition: - - "tp_quantity_ladder_lock=true이면 LLM이 익절 수량을 임의 변경 금지" - - "TP 가격 도달 시 tp_quantity_ladder_json의 수량을 반드시 사용" - canonical_ref: "AGENTS.md:Direction M3" - version: "2026-05-20_M3" + purpose: 'TP1/TP2/TP3 도달 시 매도할 수량을 GAS에서 자동 산출해 고착화한다. 수동 입력(tp1_qty>0) 우선 사용, + 없으면 보유수량의 33%/33%/34% 자동 분배. LLM이 익절 수량을 임의로 결정하는 것을 구조적으로 차단. - # == [2026-05-20_M4] M4 - 이벤트 리스크 신규 매수 홀드 ================== + ' + inputs: + - field: holding_qty + unit: shares + - field: tp1_price + unit: KRW_per_share + - field: tp1_qty + unit: shares + note: 수동 입력 우선 + - field: tp2_price + unit: KRW_per_share + - field: tp2_qty + unit: shares + - field: tp3_qty + unit: shares + output: + field: tp_quantity_ladder_json + schema: + tp1_qty: TP1 도달 시 매도 수량 (수동/AUTO_33PCT) + tp2_qty: TP2 도달 시 매도 수량 + tp3_qty: TP3/잔량 수량 + qty_source: MANUAL/AUTO_33PCT/NO_HOLDING + prohibition: + - tp_quantity_ladder_lock=true이면 LLM이 익절 수량을 임의 변경 금지 + - TP 가격 도달 시 tp_quantity_ladder_json의 수량을 반드시 사용 + canonical_ref: AGENTS.md:Direction M3 + version: 2026-05-20_M3 EVENT_RISK_HOLD_GATE_V1: - purpose: > - 이벤트 홀드 기간(Event_Hold_Days <= 5) 또는 DART 리스크 플래그가 있는 종목에 - 신규 매수 홀드 게이트를 적용한다. - Event_Hold_Days 컬럼이 없으면 DART_Risk='Y' 또는 DART_Status를 대체 기준으로 사용. - inputs: - - {field: "event_hold_days", unit: "integer_or_null", note: "Event_Hold_Days 컬럼"} - - {field: "dart_risk", unit: "string", note: "Y/N 또는 상태 문자열"} - output: - field: "event_risk_json" - schema: - event_hold_gate: "EVENT_HOLD/PASS" - event_hold_days: "남은 홀드 일수 (null=컬럼 없음)" - dart_risk: "true/false" - reason: "event_hold_days_le5:N / dart_risk / no_event_risk" - prohibition: - - "event_hold_gate=EVENT_HOLD인 종목에 신규 BUY 주문 생성 금지" - - "이벤트 홀드를 LLM이 임의 해제 금지" - canonical_ref: "AGENTS.md:Direction M4" - version: "2026-05-20_M4" + purpose: '이벤트 홀드 기간(Event_Hold_Days <= 5) 또는 DART 리스크 플래그가 있는 종목에 신규 매수 홀드 게이트를 + 적용한다. Event_Hold_Days 컬럼이 없으면 DART_Risk=''Y'' 또는 DART_Status를 대체 기준으로 사용. - # == [2026-05-20_M5] M5 - 섹터 편중도 한도 ============================== - SECTOR_CONCENTRATION_LIMIT_V1: - purpose: > - 단일 섹터 ≥40%(RISK_OFF:35%) 시 해당 섹터 추가 매수 차단. - 상위 2개 섹터 합산 ≥65%(RISK_OFF:55%) 시 WARN_TOP2. - 포트폴리오 섹터 분산을 GAS가 결정론적으로 산출 - LLM 임의 완화 금지. + ' inputs: - - {field: "weight_pct", unit: "pct"} - - {field: "sector", unit: "string"} - - {field: "market_regime", unit: "enum"} + - field: event_hold_days + unit: integer_or_null + note: Event_Hold_Days 컬럼 + - field: dart_risk + unit: string + note: Y/N 또는 상태 문자열 + output: + field: event_risk_json + schema: + event_hold_gate: EVENT_HOLD/PASS + event_hold_days: 남은 홀드 일수 (null=컬럼 없음) + dart_risk: true/false + reason: event_hold_days_le5:N / dart_risk / no_event_risk + prohibition: + - event_hold_gate=EVENT_HOLD인 종목에 신규 BUY 주문 생성 금지 + - 이벤트 홀드를 LLM이 임의 해제 금지 + canonical_ref: AGENTS.md:Direction M4 + version: 2026-05-20_M4 + SECTOR_CONCENTRATION_LIMIT_V1: + purpose: '단일 섹터 ≥40%(RISK_OFF:35%) 시 해당 섹터 추가 매수 차단. 상위 2개 섹터 합산 ≥65%(RISK_OFF:55%) + 시 WARN_TOP2. 포트폴리오 섹터 분산을 GAS가 결정론적으로 산출 - LLM 임의 완화 금지. + + ' + inputs: + - field: weight_pct + unit: pct + - field: sector + unit: string + - field: market_regime + unit: enum thresholds_by_regime: - EVENT_SHOCK_RISK_OFF: {single_block: 35, top2_warn: 55} - OTHER: {single_block: 40, top2_warn: 65} + EVENT_SHOCK_RISK_OFF: + single_block: 35 + top2_warn: 55 + OTHER: + single_block: 40 + top2_warn: 65 output: fields: - sector_concentration_gate: "BLOCK_SECTOR/WARN_TOP2/PASS" - sector_concentration_json: "섹터별 weight_pct 및 gate 상태" + sector_concentration_gate: BLOCK_SECTOR/WARN_TOP2/PASS + sector_concentration_json: 섹터별 weight_pct 및 gate 상태 prohibition: - - "sector_concentration_gate=BLOCK_SECTOR인 섹터 종목에 추가 BUY 금지" - - "LLM이 섹터 편중도를 임의로 재계산하거나 한도를 완화 금지" - canonical_ref: "AGENTS.md:Direction M5" - version: "2026-05-20_M5" - - # == [2026-05-20_N1] N1 - 국면별 포지션 사이즈 스케일 ===================== + - sector_concentration_gate=BLOCK_SECTOR인 섹터 종목에 추가 BUY 금지 + - LLM이 섹터 편중도를 임의로 재계산하거나 한도를 완화 금지 + canonical_ref: AGENTS.md:Direction M5 + version: 2026-05-20_M5 POSITION_SIZE_REGIME_SCALE_V1: - purpose: > - 국면에 따라 ATR 기반 신규 매수 수량(atrQty)에 스케일 배수를 적용한다. - M1(DrawdownGuard) 이후 독립적으로 곱해지는 방어/공격 층. - EVENT_SHOCK:0.25, RISK_OFF:0.5, NEUTRAL:1.0, RISK_ON:1.1, SECULAR_LEADER_RISK_ON:1.2 - inputs: - - {field: "market_regime", unit: "enum"} - output: - field: "regime_size_scale" - schema: - regime_size_scale: "0.25~1.2 배수 - atrQty에 곱해지는 국면 스케일" - prohibition: - - "regime_size_scale 값을 LLM이 임의 변경 금지" - - "매수 수량 산출 시 반드시 GAS 확정 regime_size_scale 사용" - canonical_ref: "AGENTS.md:Direction N1" - version: "2026-05-20_N1" + purpose: '국면에 따라 ATR 기반 신규 매수 수량(atrQty)에 스케일 배수를 적용한다. M1(DrawdownGuard) 이후 + 독립적으로 곱해지는 방어/공격 층. EVENT_SHOCK:0.25, RISK_OFF:0.5, NEUTRAL:1.0, RISK_ON:1.1, + SECULAR_LEADER_RISK_ON:1.2 - # == [2026-05-20_N2] N2 - 거래량 돌파 확인 게이트 ========================= - VOLUME_BREAKOUT_CONFIRM_V1: - purpose: > - 52주 신고가 97% 이상 부근에서 진입 시 당일 거래량이 5일 평균 거래량×1.2 미만이면 - UNCONFIRMED_BREAKOUT으로 alpha_lead_score에서 10점 차감. - 거래량 미확인 신고가 뒷박을 방지한다. + ' inputs: - - {field: "high52w", unit: "KRW_per_share"} - - {field: "close", unit: "KRW_per_share"} - - {field: "volume", unit: "shares_integer"} - - {field: "avg_volume_5d", unit: "shares_float"} + - field: market_regime + unit: enum + output: + field: regime_size_scale + schema: + regime_size_scale: 0.25~1.2 배수 - atrQty에 곱해지는 국면 스케일 + prohibition: + - regime_size_scale 값을 LLM이 임의 변경 금지 + - 매수 수량 산출 시 반드시 GAS 확정 regime_size_scale 사용 + canonical_ref: AGENTS.md:Direction N1 + version: 2026-05-20_N1 + VOLUME_BREAKOUT_CONFIRM_V1: + purpose: '52주 신고가 97% 이상 부근에서 진입 시 당일 거래량이 5일 평균 거래량×1.2 미만이면 UNCONFIRMED_BREAKOUT으로 + alpha_lead_score에서 10점 차감. 거래량 미확인 신고가 뒷박을 방지한다. + + ' + inputs: + - field: high52w + unit: KRW_per_share + - field: close + unit: KRW_per_share + - field: volume + unit: shares_integer + - field: avg_volume_5d + unit: shares_float threshold: near_new_high_pct: 97 vol_confirm_multiplier: 1.2 score_penalty: -10 late_chase_risk_add: 15 output: - field: "alpha_lead_json" - note: "reason_codes에 unconfirmed_breakout_volume 추가" + field: alpha_lead_json + note: reason_codes에 unconfirmed_breakout_volume 추가 prohibition: - - "거래량 미확인 신고가 부근 종목에 PILOT_ALLOWED 부여 금지" - canonical_ref: "AGENTS.md:Direction N2" - version: "2026-05-20_N2" - - # == [2026-05-20_N3] N3 - 손절가 적정성 검증 ============================= + - 거래량 미확인 신고가 부근 종목에 PILOT_ALLOWED 부여 금지 + canonical_ref: AGENTS.md:Direction N2 + version: 2026-05-20_N2 STOP_PRICE_ADEQUACY_V1: - purpose: > - 보유 종목의 수동 손절가가 ATR 기반 권고 손절가 대비 너무 넓게 설정되었는지 검증한다. - manual_stop < recommended_stop×0.60 → STOP_CRITICAL - manual_stop < recommended_stop×0.85 → STOP_WIDE - recommended_stop = max(avgCost×0.92, avgCost - ATR20×multiplier), tickNormalize 적용 - inputs: - - {field: "stop_price", unit: "KRW_per_share"} - - {field: "average_cost", unit: "KRW_per_share"} - - {field: "atr20", unit: "KRW_per_share"} - thresholds: - critical_ratio: 0.60 - wide_ratio: 0.85 - atr_multiplier_high_vol: 2.0 - atr_multiplier_normal: 1.5 - high_vol_threshold_pct: 8.0 - output: - field: "stop_adequacy_json" - schema: - ticker: "종목코드" - manual_stop: "수동 손절가" - recommended_stop: "ATR 기반 권고 손절가 (tick 정규화)" - stop_gap_pct: "gap = (recommended - manual) / recommended × 100" - adequacy_status: "PASS/STOP_WIDE/STOP_CRITICAL/INSUFFICIENT_DATA" - prohibition: - - "stop_adequacy_json을 LLM이 임의 수정 금지" - - "STOP_CRITICAL 종목에 추가 매수 신호 생성 금지" - canonical_ref: "AGENTS.md:Direction N3" - version: "2026-05-20_N3" + purpose: '보유 종목의 수동 손절가가 ATR 기반 권고 손절가 대비 너무 넓게 설정되었는지 검증한다. manual_stop < recommended_stop×0.60 + → STOP_CRITICAL manual_stop < recommended_stop×0.85 → STOP_WIDE recommended_stop + = max(avgCost×0.92, avgCost - ATR20×multiplier), tickNormalize 적용 - # == [2026-05-20_N4] N4 - 장기 보유 재검토 플래그 ========================= - HOLDING_STALE_REVIEW_V1: - purpose: > - account_snapshot의 entry_date 기준으로 보유 기간을 산출한다. - >60일: STALE_POSITION (근거 재검토 의무), >30일: REVIEW_SOON, <=30일: FRESH - entry_date 컬럼이 없으면 ENTRY_DATE_MISSING. + ' inputs: - - {field: "entry_date", unit: "ISO_date_string"} + - field: stop_price + unit: KRW_per_share + - field: average_cost + unit: KRW_per_share + - field: atr20 + unit: KRW_per_share thresholds: - stale_days: 60 + critical_ratio: 0.6 + wide_ratio: 0.85 + atr_multiplier_high_vol: 2.0 + atr_multiplier_normal: 1.5 + high_vol_threshold_pct: 8.0 + output: + field: stop_adequacy_json + schema: + ticker: 종목코드 + manual_stop: 수동 손절가 + recommended_stop: ATR 기반 권고 손절가 (tick 정규화) + stop_gap_pct: gap = (recommended - manual) / recommended × 100 + adequacy_status: PASS/STOP_WIDE/STOP_CRITICAL/INSUFFICIENT_DATA + prohibition: + - stop_adequacy_json을 LLM이 임의 수정 금지 + - STOP_CRITICAL 종목에 추가 매수 신호 생성 금지 + canonical_ref: AGENTS.md:Direction N3 + version: 2026-05-20_N3 + HOLDING_STALE_REVIEW_V1: + purpose: 'account_snapshot의 entry_date 기준으로 보유 기간을 산출한다. >60일: STALE_POSITION + (근거 재검토 의무), >30일: REVIEW_SOON, <=30일: FRESH entry_date 컬럼이 없으면 ENTRY_DATE_MISSING. + + ' + inputs: + - field: entry_date + unit: ISO_date_string + thresholds: + stale_days: 60 review_days: 30 output: - field: "holding_stale_json" + field: holding_stale_json schema: - ticker: "종목코드" - entry_date: "진입일 (ISO)" - holding_days: "보유 일수" - stale_status: "STALE_POSITION/REVIEW_SOON/FRESH/ENTRY_DATE_MISSING" + ticker: 종목코드 + entry_date: 진입일 (ISO) + holding_days: 보유 일수 + stale_status: STALE_POSITION/REVIEW_SOON/FRESH/ENTRY_DATE_MISSING prohibition: - - "holding_stale_json을 LLM이 임의 산출 금지" - - "STALE_POSITION 종목 보유 유지 시 근거 재확인 의무 (LLM 자동 승인 금지)" - canonical_ref: "AGENTS.md:Direction N4" - version: "2026-05-20_N4" - - # == [2026-05-20_N5] N5 - 국면별 현금 최소 비율 상향 ===================== + - holding_stale_json을 LLM이 임의 산출 금지 + - STALE_POSITION 종목 보유 유지 시 근거 재확인 의무 (LLM 자동 승인 금지) + canonical_ref: AGENTS.md:Direction N4 + version: 2026-05-20_N4 REGIME_CASH_UPLIFT_V1: - purpose: > - MRS 기반 cash_floor보다 더 높은 현금 최소 비율이 국면(regime)상 요구될 때 - cashFloorInfo.minPct를 상향 오버라이드하고 cashShortfallInfo를 재산출한다. - EVENT_SHOCK→20%, RISK_OFF→15%, RISK_ON→5% (MRS값보다 낮으면 MRS값 유지). + purpose: 'MRS 기반 cash_floor보다 더 높은 현금 최소 비율이 국면(regime)상 요구될 때 cashFloorInfo.minPct를 + 상향 오버라이드하고 cashShortfallInfo를 재산출한다. EVENT_SHOCK→20%, RISK_OFF→15%, RISK_ON→5% + (MRS값보다 낮으면 MRS값 유지). + + ' inputs: - - {field: "market_regime", unit: "enum"} - - {field: "cash_floor_min_pct", unit: "pct"} + - field: market_regime + unit: enum + - field: cash_floor_min_pct + unit: pct thresholds_by_regime: EVENT_SHOCK: 20 - RISK_OFF: 15 - RISK_ON: 5 - NEUTRAL: 0 + RISK_OFF: 15 + RISK_ON: 5 + NEUTRAL: 0 output: - field: "regime_cash_uplift_min_pct" - note: "max(mrs_cash_min_pct, regime_min_pct) - 실제 적용된 현금 최소 비율" + field: regime_cash_uplift_min_pct + note: max(mrs_cash_min_pct, regime_min_pct) - 실제 적용된 현금 최소 비율 prohibition: - - "regime_cash_uplift_min_pct를 LLM이 임의 낮추기 금지" - - "BELOW_FLOOR 상태에서 매수 신호 생성 금지" - canonical_ref: "AGENTS.md:Direction N5" - version: "2026-05-20_N5" - - # == [2026-05-20_O1] O1 - 개별 종목 비중 상한 ============================= + - regime_cash_uplift_min_pct를 LLM이 임의 낮추기 금지 + - BELOW_FLOOR 상태에서 매수 신호 생성 금지 + canonical_ref: AGENTS.md:Direction N5 + version: 2026-05-20_N5 SINGLE_POSITION_WEIGHT_CAP_V1: - purpose: > - 개별 종목의 포트폴리오 비중(weight_pct)이 국면별 상한을 초과하면 OVERWEIGHT_TRIM. - M5(섹터 편중)와 독립적인 종목 단위 비중 하드 캡. - NEUTRAL/RISK_ON:20%, EVENT_SHOCK/RISK_OFF:15% + purpose: '개별 종목의 포트폴리오 비중(weight_pct)이 국면별 상한을 초과하면 OVERWEIGHT_TRIM. M5(섹터 편중)와 + 독립적인 종목 단위 비중 하드 캡. NEUTRAL/RISK_ON:20%, EVENT_SHOCK/RISK_OFF:15% + + ' inputs: - - {field: "weight_pct", unit: "pct"} - - {field: "market_regime", unit: "enum"} + - field: weight_pct + unit: pct + - field: market_regime + unit: enum thresholds_by_regime: - EVENT_SHOCK_RISK_OFF: {cap_pct: 15} - OTHER: {cap_pct: 20} + EVENT_SHOCK_RISK_OFF: + cap_pct: 15 + OTHER: + cap_pct: 20 output: fields: - single_position_weight_gate: "OVERWEIGHT_TRIM/PASS" - single_position_weight_json: "종목별 weight_pct vs cap_pct 상태" + single_position_weight_gate: OVERWEIGHT_TRIM/PASS + single_position_weight_json: 종목별 weight_pct vs cap_pct 상태 prohibition: - - "OVERWEIGHT_TRIM 종목에 추가 매수 신호 생성 금지" - - "LLM이 비중 상한을 임의 완화 금지" - canonical_ref: "AGENTS.md:Direction O1" - version: "2026-05-20_O1" - - # == [2026-05-20_O2] O2 - 반도체 클러스터 합산 비중 게이트 ================= + - OVERWEIGHT_TRIM 종목에 추가 매수 신호 생성 금지 + - LLM이 비중 상한을 임의 완화 금지 + canonical_ref: AGENTS.md:Direction O1 + version: 2026-05-20_O1 SEMICONDUCTOR_CLUSTER_GATE_V1: - purpose: > - 005930(삼성전자) + 000660(SK하이닉스) 합산 비중이 시장 국면별 상한을 초과하면 CLUSTER_BLOCK. - 두 종목이 같은 메모리 사이클에서 동반 하락하는 상관 리스크 통제. - EVENT_SHOCK/RISK_OFF: ≥20%, NEUTRAL/RISK_ON: ≥25%, SECULAR_LEADER_RISK_ON: ≥35%, - CONCENTRATED_LEADER_ADVANCE(CLA): ≥60% → CLUSTER_BLOCK + purpose: '005930(삼성전자) + 000660(SK하이닉스) 합산 비중이 시장 국면별 상한을 초과하면 CLUSTER_BLOCK. + 두 종목이 같은 메모리 사이클에서 동반 하락하는 상관 리스크 통제. EVENT_SHOCK/RISK_OFF: ≥20%, NEUTRAL/RISK_ON: + ≥25%, SECULAR_LEADER_RISK_ON: ≥35%, CONCENTRATED_LEADER_ADVANCE(CLA): ≥60% + → CLUSTER_BLOCK + + ' inputs: - - {field: "weight_pct", unit: "pct"} - - {field: "market_regime", unit: "enum"} + - field: weight_pct + unit: pct + - field: market_regime + unit: enum thresholds_by_regime: - EVENT_SHOCK_RISK_OFF: {cap_pct: 20} - NEUTRAL_RISK_ON: {cap_pct: 25} - SECULAR_LEADER_RISK_ON: {cap_pct: 35} - CONCENTRATED_LEADER_ADVANCE: {cap_pct: 60} + EVENT_SHOCK_RISK_OFF: + cap_pct: 20 + NEUTRAL_RISK_ON: + cap_pct: 25 + SECULAR_LEADER_RISK_ON: + cap_pct: 35 + CONCENTRATED_LEADER_ADVANCE: + cap_pct: 60 output: fields: - semiconductor_cluster_gate: "CLUSTER_BLOCK/PASS" - semiconductor_cluster_json: "클러스터 합산 비중 및 종목별 비중" + semiconductor_cluster_gate: CLUSTER_BLOCK/PASS + semiconductor_cluster_json: 클러스터 합산 비중 및 종목별 비중 prohibition: - - "CLUSTER_BLOCK 상태에서 005930 또는 000660 추가 매수 금지" - - "LLM이 하네스/국면별 클러스터 한도를 임의 상향 또는 하향 금지" - canonical_ref: "AGENTS.md:Direction O2" - version: "2026-05-20_O2" - - # == [2026-05-20_O3] O3 - 포트폴리오 고점 대비 낙폭 게이트 ================== + - CLUSTER_BLOCK 상태에서 005930 또는 000660 추가 매수 금지 + - LLM이 하네스/국면별 클러스터 한도를 임의 상향 또는 하향 금지 + canonical_ref: AGENTS.md:Direction O2 + version: 2026-05-20_O2 PORTFOLIO_DRAWDOWN_GATE_V1: - purpose: > - 총자산(total_asset_krw)의 역대 고점(settings.portfolio_peak_krw) 대비 낙폭을 산출한다. - -15% → DRAWDOWN_CAUTION(신규 매수 보류 권고) - -20% → DRAWDOWN_FORCE_RISK_OFF(신규 매수 전면 차단 권고) - 현재 자산이 고점 초과 시 GAS가 settings에 새 고점을 자동 기록. + purpose: '총자산(total_asset_krw)의 역대 고점(settings.portfolio_peak_krw) 대비 낙폭을 산출한다. + -15% → DRAWDOWN_CAUTION(신규 매수 보류 권고) -20% → DRAWDOWN_FORCE_RISK_OFF(신규 매수 + 전면 차단 권고) 현재 자산이 고점 초과 시 GAS가 settings에 새 고점을 자동 기록. + + ' inputs: - - {field: "total_asset_krw", unit: "KRW"} - - {field: "portfolio_peak_krw", unit: "KRW", note: "settings 시트 자동 갱신"} + - field: total_asset_krw + unit: KRW + - field: portfolio_peak_krw + unit: KRW + note: settings 시트 자동 갱신 thresholds: - caution_pct: 15 + caution_pct: 15 force_off_pct: 20 output: fields: - portfolio_drawdown_gate: "DRAWDOWN_FORCE_RISK_OFF/DRAWDOWN_CAUTION/PASS/INSUFFICIENT_DATA" - portfolio_drawdown_pct: "현재 낙폭 % (양수=낙폭)" - portfolio_peak_krw: "적용된 고점 자산 (원)" + portfolio_drawdown_gate: DRAWDOWN_FORCE_RISK_OFF/DRAWDOWN_CAUTION/PASS/INSUFFICIENT_DATA + portfolio_drawdown_pct: 현재 낙폭 % (양수=낙폭) + portfolio_peak_krw: 적용된 고점 자산 (원) prohibition: - - "DRAWDOWN_FORCE_RISK_OFF 상태에서 신규 매수 BUY 주문 생성 금지" - - "portfolio_peak_krw를 LLM이 임의 설정 금지" - canonical_ref: "AGENTS.md:Direction O3" - version: "2026-05-20_O3" - - # == [2026-05-20_O4] O4 - 최근 승률 하락 매수 축소 게이트 ==================== + - DRAWDOWN_FORCE_RISK_OFF 상태에서 신규 매수 BUY 주문 생성 금지 + - portfolio_peak_krw를 LLM이 임의 설정 금지 + canonical_ref: AGENTS.md:Direction O3 + version: 2026-05-20_O3 WIN_LOSS_STREAK_GUARD_V1: - purpose: > - 최근 30거래 승률(win_rate_30)이 임계값 이하로 하락하면 신규 매수 비중을 자동 축소한다. - M1(연속 손절 횟수)과 독립적인 전체 승률 축 방어층. - EDGE_CRITICAL(<30%):scale=0.25, EDGE_DEGRADED(<40%):scale=0.50, - EDGE_WEAK(<45%):scale=0.75, EDGE_OK(>=45%):scale=1.0 - trades_used<10 → INSUFFICIENT_HISTORY(scale=1.0) + purpose: '최근 30거래 승률(win_rate_30)이 임계값 이하로 하락하면 신규 매수 비중을 자동 축소한다. M1(연속 손절 + 횟수)과 독립적인 전체 승률 축 방어층. EDGE_CRITICAL(<30%):scale=0.25, EDGE_DEGRADED(<40%):scale=0.50, + EDGE_WEAK(<45%):scale=0.75, EDGE_OK(>=45%):scale=1.0 trades_used<10 → INSUFFICIENT_HISTORY(scale=1.0) + + ' inputs: - - {field: "win_rate_30", unit: "ratio_0_to_1"} - - {field: "trades_used", unit: "integer"} + - field: win_rate_30 + unit: ratio_0_to_1 + - field: trades_used + unit: integer thresholds: - edge_critical: 0.30 - edge_degraded: 0.40 - edge_weak: 0.45 - min_trades: 10 + edge_critical: 0.3 + edge_degraded: 0.4 + edge_weak: 0.45 + min_trades: 10 output: fields: - win_loss_streak_state: "EDGE_OK/EDGE_WEAK/EDGE_DEGRADED/EDGE_CRITICAL/INSUFFICIENT_HISTORY" - win_loss_streak_buy_scale: "0.25/0.50/0.75/1.0 - atrQty에 곱해지는 배수" - win_loss_streak_win_rate_pct: "최근 30거래 승률 %" + win_loss_streak_state: EDGE_OK/EDGE_WEAK/EDGE_DEGRADED/EDGE_CRITICAL/INSUFFICIENT_HISTORY + win_loss_streak_buy_scale: 0.25/0.50/0.75/1.0 - atrQty에 곱해지는 배수 + win_loss_streak_win_rate_pct: 최근 30거래 승률 % prohibition: - - "win_loss_streak_buy_scale를 LLM이 임의 복원 금지" - - "EDGE_CRITICAL 상태에서 atr_qty 수동 상향 금지" - canonical_ref: "AGENTS.md:Direction O4" - version: "2026-05-20_O4" - - # == [2026-05-20_O5] O5 - 동시 보유 종목 수 상한 ============================ + - win_loss_streak_buy_scale를 LLM이 임의 복원 금지 + - EDGE_CRITICAL 상태에서 atr_qty 수동 상향 금지 + canonical_ref: AGENTS.md:Direction O4 + version: 2026-05-20_O4 POSITION_COUNT_LIMIT_V1: - purpose: > - 동시 보유 종목 수가 국면별 상한을 초과하면 POSITION_COUNT_BLOCK. - 과다 분산으로 인한 집중 모니터링 불가 및 Total Heat 과소 추정 방지. - NEUTRAL/RISK_ON:10종목, EVENT_SHOCK/RISK_OFF:6종목 + purpose: '동시 보유 종목 수가 국면별 상한을 초과하면 POSITION_COUNT_BLOCK. 과다 분산으로 인한 집중 모니터링 + 불가 및 Total Heat 과소 추정 방지. NEUTRAL/RISK_ON:10종목, EVENT_SHOCK/RISK_OFF:6종목 + + ' inputs: - - {field: "market_regime", unit: "enum"} - - {field: "holding_qty", unit: "integer", note: "보유 종목 수 (holdings.length)"} + - field: market_regime + unit: enum + - field: holding_qty + unit: integer + note: 보유 종목 수 (holdings.length) thresholds_by_regime: - EVENT_SHOCK_RISK_OFF: {max_count: 6} - OTHER: {max_count: 10} + EVENT_SHOCK_RISK_OFF: + max_count: 6 + OTHER: + max_count: 10 output: fields: - position_count_gate: "POSITION_COUNT_BLOCK/PASS" - position_count: "현재 보유 종목 수" - position_count_max: "국면별 최대 허용 종목 수" + position_count_gate: POSITION_COUNT_BLOCK/PASS + position_count: 현재 보유 종목 수 + position_count_max: 국면별 최대 허용 종목 수 prohibition: - - "POSITION_COUNT_BLOCK 상태에서 신규 BUY 주문 생성 금지" - - "LLM이 position_count_max를 임의 상향 금지" - canonical_ref: "AGENTS.md:Direction O5" - version: "2026-05-20_O5" - - # == [2026-05-20_P1] P1 - 손절가 이탈 즉시 경보 ========================= + - POSITION_COUNT_BLOCK 상태에서 신규 BUY 주문 생성 금지 + - LLM이 position_count_max를 임의 상향 금지 + canonical_ref: AGENTS.md:Direction O5 + version: 2026-05-20_O5 STOP_BREACH_ALERT_V1: - purpose: > - 보유 종목 중 close <= stop_price인 종목을 즉시 경보한다. - close <= stop_price → BREACH_IMMEDIATE_EXIT (정규 게이트값=BREACH) - close <= stop_price × 1.03 → STOP_APPROACHING (게이트=APPROACHING) + purpose: '보유 종목 중 close <= stop_price인 종목을 즉시 경보한다. close <= stop_price → + BREACH_IMMEDIATE_EXIT (정규 게이트값=BREACH) close <= stop_price × 1.03 → STOP_APPROACHING (게이트=APPROACHING) 현재 stopBreach 필드를 하네스 레벨 gate로 올린 것. + + ' inputs: - - {field: "close", unit: "KRW_per_share"} - - {field: "stop_price", unit: "KRW_per_share"} + - field: close + unit: KRW_per_share + - field: stop_price + unit: KRW_per_share thresholds: approaching_ratio: 1.03 output: fields: - stop_breach_gate: "BREACH/APPROACHING/PASS" - stop_breach_alert_json: "종목별 경보 상태·gap_pct 배열" + stop_breach_gate: BREACH/APPROACHING/PASS + stop_breach_alert_json: 종목별 경보 상태·gap_pct 배열 prohibition: - - "stop_breach_gate=BREACH 종목에 추가 매수 또는 HOLD 서술 금지" - - "stop_breach_alert_json을 LLM이 임의 수정 금지" - canonical_ref: "AGENTS.md:Direction P1" - version: "2026-05-20_P1" - - # == [2026-05-20_P2] P2 - 익절가 도달 즉각 수량 연계 ==================== + - stop_breach_gate=BREACH 종목에 추가 매수 또는 HOLD 서술 금지 + - stop_breach_alert_json을 LLM이 임의 수정 금지 + canonical_ref: AGENTS.md:Direction P1 + version: 2026-05-20_P1 TP_TRIGGER_ALERT_V1: - purpose: > - 보유 종목 중 close >= tp1_price 또는 close >= tp2_price인 종목을 감지한다. - tp_quantity_ladder_json과 연계해 즉각 매도 수량을 확정론적으로 제공한다. - tp_trigger_gate=TRIGGERED이면 해당 종목의 tp_qty를 LLM이 임의 변경 금지. + purpose: '보유 종목 중 close >= tp1_price 또는 close >= tp2_price인 종목을 감지한다. tp_quantity_ladder_json과 + 연계해 즉각 매도 수량을 확정론적으로 제공한다. tp_trigger_gate=TRIGGERED이면 해당 종목의 tp_qty를 LLM이 + 임의 변경 금지. + + ' inputs: - - {field: "close", unit: "KRW_per_share"} - - {field: "tp1_price", unit: "KRW_per_share"} - - {field: "tp2_price", unit: "KRW_per_share"} - - {field: "tp_quantity_ladder_json", unit: "json"} + - field: close + unit: KRW_per_share + - field: tp1_price + unit: KRW_per_share + - field: tp2_price + unit: KRW_per_share + - field: tp_quantity_ladder_json + unit: json output: fields: - tp_trigger_gate: "TRIGGERED/PASS" - tp_trigger_alert_json: "트리거된 종목·tp_qty 배열" + tp_trigger_gate: TRIGGERED/PASS + tp_trigger_alert_json: 트리거된 종목·tp_qty 배열 prohibition: - - "TRIGGERED 종목의 매도 수량을 LLM이 tp1_qty/tp2_qty 외 값으로 변경 금지" - - "TP 가격 도달 여부를 LLM이 재계산 금지" - canonical_ref: "AGENTS.md:Direction P2" - version: "2026-05-20_P2" - - # == [2026-05-20_P3] P3 - Heat 편중도 경보 =============================== + - TRIGGERED 종목의 매도 수량을 LLM이 tp1_qty/tp2_qty 외 값으로 변경 금지 + - TP 가격 도달 여부를 LLM이 재계산 금지 + canonical_ref: AGENTS.md:Direction P2 + version: 2026-05-20_P2 HEAT_CONCENTRATION_ALERT_V1: - purpose: > - 단일 종목의 Heat(=(avgCost-stopPrice)×qty)가 전체 totalHeatKrw의 50% 이상이면 - HEAT_CONCENTRATED 경보. 해당 종목 급락 시 total_heat_pct가 급변해 - 다른 게이트가 무력화되는 구조적 리스크를 사전 차단. + purpose: '단일 종목의 Heat(=(avgCost-stopPrice)×qty)가 전체 totalHeatKrw의 50% 이상이면 HEAT_CONCENTRATED + 경보. 해당 종목 급락 시 total_heat_pct가 급변해 다른 게이트가 무력화되는 구조적 리스크를 사전 차단. + + ' inputs: - - {field: "average_cost", unit: "KRW_per_share"} - - {field: "stop_price", unit: "KRW_per_share"} - - {field: "total_heat_pct", unit: "pct", note: "total_heat_krw 기준"} + - field: average_cost + unit: KRW_per_share + - field: stop_price + unit: KRW_per_share + - field: total_heat_pct + unit: pct + note: total_heat_krw 기준 threshold: concentration_pct: 50 output: fields: - heat_concentration_gate: "HEAT_CONCENTRATED/PASS/INSUFFICIENT_DATA" - heat_concentration_json: "종목별 heat_krw·heat_share_pct" + heat_concentration_gate: HEAT_CONCENTRATED/PASS/INSUFFICIENT_DATA + heat_concentration_json: 종목별 heat_krw·heat_share_pct prohibition: - - "HEAT_CONCENTRATED 종목에 추가 매수 신호 생성 금지" - - "heat_share_pct를 LLM이 임의 계산 금지" - canonical_ref: "AGENTS.md:Direction P3" - version: "2026-05-20_P3" - - # == [2026-05-20_P4] P4 - 국면 전환 경보 ================================= + - HEAT_CONCENTRATED 종목에 추가 매수 신호 생성 금지 + - heat_share_pct를 LLM이 임의 계산 금지 + canonical_ref: AGENTS.md:Direction P3 + version: 2026-05-20_P3 REGIME_TRANSITION_ALERT_V1: - purpose: > - 직전 실행 국면(settings.prev_market_regime) vs 현재 marketRegime를 비교한다. - UPGRADE(완화): RISK_OFF→NEUTRAL 등, DOWNGRADE(긴축): NEUTRAL→RISK_OFF 등 - LATERAL_SHIFT: 동급 국면 변경, NO_CHANGE: 변동 없음. - 국면 전환 시 영향 받는 게이트 목록을 affected_gates에 자동 생성. + purpose: '직전 실행 국면(settings.prev_market_regime) vs 현재 marketRegime를 비교한다. UPGRADE(완화): + RISK_OFF→NEUTRAL 등, DOWNGRADE(긴축): NEUTRAL→RISK_OFF 등 LATERAL_SHIFT: 동급 국면 + 변경, NO_CHANGE: 변동 없음. 국면 전환 시 영향 받는 게이트 목록을 affected_gates에 자동 생성. + + ' inputs: - - {field: "market_regime", unit: "enum"} - - {field: "portfolio_peak_krw", unit: "KRW", note: "settings 시트"} + - field: market_regime + unit: enum + - field: portfolio_peak_krw + unit: KRW + note: settings 시트 output: fields: - regime_transition_type: "UPGRADE/DOWNGRADE/LATERAL_SHIFT/NO_CHANGE" - regime_transition_json: "전환 상세 (prev/current/affected_gates)" + regime_transition_type: UPGRADE/DOWNGRADE/LATERAL_SHIFT/NO_CHANGE + regime_transition_json: 전환 상세 (prev/current/affected_gates) prohibition: - - "DOWNGRADE 국면에서 기존 포지션 규모 자동 유지 서술 금지" - - "LLM이 regime_transition_type을 임의 판단 금지" - canonical_ref: "AGENTS.md:Direction P4" - version: "2026-05-20_P4" - - # == [2026-05-20_P5] P5 - 포트폴리오 건전성 종합 점수 ==================== + - DOWNGRADE 국면에서 기존 포지션 규모 자동 유지 서술 금지 + - LLM이 regime_transition_type을 임의 판단 금지 + canonical_ref: AGENTS.md:Direction P4 + version: 2026-05-20_P4 PORTFOLIO_HEALTH_SCORE_V1: - purpose: > - O1~P4까지 모든 게이트 상태를 집계해 단일 건전성 레이블을 산출한다. - CRITICAL 게이트 ≥1개, 또는 CAUTION ≥3개 → CRITICAL - CAUTION 1~2개 → CAUTION, 0개 → HEALTHY - score = max(0, 100 - critical×30 - caution×10) - 보고서 첫 줄에 반드시 표시. LLM이 개별 게이트 확인 없이 이 레이블로 우선 판단. + purpose: 'O1~P4까지 모든 게이트 상태를 집계해 단일 건전성 레이블을 산출한다. CRITICAL 게이트 ≥1개, 또는 CAUTION + ≥3개 → CRITICAL CAUTION 1~2개 → CAUTION, 0개 → HEALTHY score = max(0, 100 - critical×30 + - caution×10) 보고서 첫 줄에 반드시 표시. LLM이 개별 게이트 확인 없이 이 레이블로 우선 판단. + + ' inputs: - - {field: "heat_gate_status", unit: "enum"} - - {field: "cash_floor_status", unit: "enum"} - - {field: "portfolio_drawdown_gate", unit: "enum"} - - {field: "stop_breach_gate", unit: "enum"} - - {field: "tp_trigger_gate", unit: "enum"} + - field: heat_gate_status + unit: enum + - field: cash_floor_status + unit: enum + - field: portfolio_drawdown_gate + unit: enum + - field: stop_breach_gate + unit: enum + - field: tp_trigger_gate + unit: enum output: fields: - portfolio_health_label: "HEALTHY/CAUTION/CRITICAL" - portfolio_health_score: "0~100 점수" - portfolio_health_critical_count: "CRITICAL 상태 게이트 수" - portfolio_health_caution_count: "CAUTION 상태 게이트 수" - portfolio_health_blocked_json: "게이트별 severity 상세" + portfolio_health_label: HEALTHY/CAUTION/CRITICAL + portfolio_health_score: 0~100 점수 + portfolio_health_critical_count: CRITICAL 상태 게이트 수 + portfolio_health_caution_count: CAUTION 상태 게이트 수 + portfolio_health_blocked_json: 게이트별 severity 상세 prohibition: - - "보고서 시작 전에 portfolio_health_label을 반드시 표시" - - "CRITICAL 레이블이면 보고서 본문 이전에 '긴급 주의' 섹션 필수" - - "LLM이 health_score를 재계산하거나 임의로 CRITICAL→CAUTION 완화 금지" - canonical_ref: "AGENTS.md:Direction P5" - version: "2026-05-20_P5" - + - 보고서 시작 전에 portfolio_health_label을 반드시 표시 + - CRITICAL 레이블이면 보고서 본문 이전에 '긴급 주의' 섹션 필수 + - LLM이 health_score를 재계산하거나 임의로 CRITICAL→CAUTION 완화 금지 + canonical_ref: AGENTS.md:Direction P5 + version: 2026-05-20_P5 BUY_TIMING_SUITABILITY_V1: - purpose: "core_satellite 후보 품질과 실제 매수 타이밍을 분리한다." + purpose: core_satellite 후보 품질과 실제 매수 타이밍을 분리한다. inputs: - - {field: "candidate_quality_grade", unit: "enum"} - - {field: "entry_mode_gate", unit: "enum"} - - {field: "timing_score_entry", unit: "score_0_100"} - - {field: "timing_score_exit", unit: "score_0_100"} - - {field: "expected_edge", unit: "ratio", optional: true} - - {field: "liquidity_status", unit: "enum"} - - {field: "spread_status", unit: "enum"} - output: {field: "execution_recommendation_state", unit: "enum"} + - field: candidate_quality_grade + unit: enum + - field: entry_mode_gate + unit: enum + - field: timing_score_entry + unit: score_0_100 + - field: timing_score_exit + unit: score_0_100 + - field: expected_edge + unit: ratio + optional: true + - field: liquidity_status + unit: enum + - field: spread_status + unit: enum + output: + field: execution_recommendation_state + unit: enum gates: - - "timing_score_exit >= 50 -> BUY_BLOCKED_T1_EXIT_RISK" - - "entry_mode_gate != PASS -> WATCH_TIMING_SETUP" - - "candidate_quality_grade=A AND entry_mode_gate=PASS AND timing_score_entry>=75 -> BUY_PILOT_ALLOWED" - missing_policy: "핵심 입력 누락 시 CANDIDATE_ONLY. LLM이 BUY로 승격 금지." - version: "2026-05-20_CORE_SAT_TIMING_V1" - + - timing_score_exit >= 50 -> BUY_BLOCKED_T1_EXIT_RISK + - entry_mode_gate != PASS -> WATCH_TIMING_SETUP + - candidate_quality_grade=A AND entry_mode_gate=PASS AND timing_score_entry>=75 + -> BUY_PILOT_ALLOWED + missing_policy: 핵심 입력 누락 시 CANDIDATE_ONLY. LLM이 BUY로 승격 금지. + version: 2026-05-20_CORE_SAT_TIMING_V1 T1_FORCED_SELL_RISK_V1: - purpose: "오늘 매수하면 다음 거래일 손절·매도검토가 발생할 위험을 0~100점으로 산출한다." + purpose: 오늘 매수하면 다음 거래일 손절·매도검토가 발생할 위험을 0~100점으로 산출한다. inputs: - - {field: "sell_action", unit: "enum"} - - {field: "sell_validation", unit: "enum"} - - {field: "timing_score_exit", unit: "score_0_100"} - - {field: "rw_partial", unit: "count"} - - {field: "distribution_risk_score", unit: "score_0_100", optional: true} - - {field: "late_chase_risk_score", unit: "score_0_100", optional: true} - - {field: "rsi14", unit: "points", optional: true} - - {field: "disparity", unit: "pct", optional: true} - - {field: "val_surge_pct", unit: "pct", optional: true} - - {field: "ret5d", unit: "pct", optional: true} - - {field: "dart_risk", unit: "string", optional: true} - output: {field: "t1_forced_sell_risk_score", unit: "score_0_100"} - expression: "min(100, sell_action_active*40 + timing_exit_ge_50*25 + rw_ge_2*25 + distribution_ge_70*30 + late_chase_ge_70*25 + overheated*20 + surge_after_runup*15 + dart_risk*30)" + - field: sell_action + unit: enum + - field: sell_validation + unit: enum + - field: timing_score_exit + unit: score_0_100 + - field: rw_partial + unit: count + - field: distribution_risk_score + unit: score_0_100 + optional: true + - field: late_chase_risk_score + unit: score_0_100 + optional: true + - field: rsi14 + unit: points + optional: true + - field: disparity + unit: pct + optional: true + - field: val_surge_pct + unit: pct + optional: true + - field: ret5d + unit: pct + optional: true + - field: dart_risk + unit: string + optional: true + output: + field: t1_forced_sell_risk_score + unit: score_0_100 + expression: min(100, sell_action_active*40 + timing_exit_ge_50*25 + rw_ge_2*25 + + distribution_ge_70*30 + late_chase_ge_70*25 + overheated*20 + surge_after_runup*15 + + dart_risk*30) gates: - - "score>=70 -> BUY_BLOCKED_T1_EXIT_RISK" - - "50<=score<70 -> WATCH_ONLY_T1_RISK" - - "score<50 -> PASS" - version: "2026-05-20_CORE_SAT_TIMING_V1" - + - score>=70 -> BUY_BLOCKED_T1_EXIT_RISK + - 50<=score<70 -> WATCH_ONLY_T1_RISK + - score<50 -> PASS + version: 2026-05-20_CORE_SAT_TIMING_V1 SELL_CONFLICT_AWARE_RECOMMENDATION_V1: - purpose: "매도·현금확보·NO_ADD 게이트와 충돌하는 신규 core_satellite 매수 추천을 차단한다." + purpose: 매도·현금확보·NO_ADD 게이트와 충돌하는 신규 core_satellite 매수 추천을 차단한다. inputs: - - {field: "final_action", unit: "enum"} - - {field: "sell_action", unit: "enum"} - - {field: "cash_preserve_style", unit: "enum"} - - {field: "allowed_action", unit: "enum"} - output: {field: "sell_conflict_score", unit: "score_0_100"} - expression: "min(100, sell_signal_active*55 + cash_preserve_active*20 + no_add_gate*20)" + - field: final_action + unit: enum + - field: sell_action + unit: enum + - field: cash_preserve_style + unit: enum + - field: allowed_action + unit: enum + output: + field: sell_conflict_score + unit: score_0_100 + expression: min(100, sell_signal_active*55 + cash_preserve_active*20 + no_add_gate*20) gates: - - "score>=70 -> BUY_BLOCKED_SELL_CONFLICT" - - "40<=score<70 -> SELL_OR_TRIM_FIRST" - - "score<40 -> PASS" - version: "2026-05-20_CORE_SAT_TIMING_V1" - - # == [2026-05-20_H6] H6 - 가짜 매도 신호 차단 홀드 게이트 ================= + - score>=70 -> BUY_BLOCKED_SELL_CONFLICT + - 40<=score<70 -> SELL_OR_TRIM_FIRST + - score<40 -> PASS + version: 2026-05-20_CORE_SAT_TIMING_V1 ANTI_WHIPSAW_HOLD_GATE_V1: - purpose: > - 연속 매도 신호 5일 이상 + 기관·외국인 순매수 조합을 감지해 가짜 매도(whipsaw)를 - 차단한다. WHIPSAW_SUSPECTED이면 당일 매도를 1거래일 홀드시키고, 다음날 재평가. - 설거지(distribution sell) 패턴과 구별해 실제 분산매도인지 재확인. + purpose: '연속 매도 신호 5일 이상 + 기관·외국인 순매수 조합을 감지해 가짜 매도(whipsaw)를 차단한다. WHIPSAW_SUSPECTED이면 + 당일 매도를 1거래일 홀드시키고, 다음날 재평가. 설거지(distribution sell) 패턴과 구별해 실제 분산매도인지 재확인. + + ' inputs: - - {field: "consecutive_sell_signals_5d", unit: "count", note: "최근 5일간 연속 매도 신호 수"} - - {field: "vol_surge_pct", unit: "pct", note: "당일 거래량/avg_vol_5d - 1 (0 이상)"} - - {field: "institutional_flow_5d", unit: "KRW", note: "기관 5일 누적 순매수 (양수=순매수)"} - - {field: "foreign_flow_5d", unit: "KRW", note: "외국인 5일 누적 순매수 (양수=순매수)"} - - {field: "sector_relative_strength_5d", unit: "ratio", note: "섹터 5일 상대강도, 100=시장동률"} + - field: consecutive_sell_signals_5d + unit: count + note: 최근 5일간 연속 매도 신호 수 + - field: vol_surge_pct + unit: pct + note: 당일 거래량/avg_vol_5d - 1 (0 이상) + - field: institutional_flow_5d + unit: KRW + note: 기관 5일 누적 순매수 (양수=순매수) + - field: foreign_flow_5d + unit: KRW + note: 외국인 5일 누적 순매수 (양수=순매수) + - field: sector_relative_strength_5d + unit: ratio + note: 섹터 5일 상대강도, 100=시장동률 scoring: whipsaw_score_components: - - {condition: "consecutive_sell_signals_5d >= 5", score: +20, note: "연속 매도신호 누적"} - - {condition: "institutional_flow_5d > 0", score: +30, note: "기관 순매수 중 매도신호 = 의심"} - - {condition: "foreign_flow_5d > 0", score: +20, note: "외인 순매수 중 매도신호 = 의심"} - - {condition: "sector_relative_strength_5d > 100", score: +15, note: "섹터 강세 중 매도신호 = 의심"} - - {condition: "vol_surge_pct >= 50", score: -25, note: "대규모 거래량 = 실제 매도 가능성"} - - {condition: "vol_surge_pct >= 100", score: -20, note: "거래량 폭증 추가 패널티"} + - condition: consecutive_sell_signals_5d >= 5 + score: 20 + note: 연속 매도신호 누적 + - condition: institutional_flow_5d > 0 + score: 30 + note: 기관 순매수 중 매도신호 = 의심 + - condition: foreign_flow_5d > 0 + score: 20 + note: 외인 순매수 중 매도신호 = 의심 + - condition: sector_relative_strength_5d > 100 + score: 15 + note: 섹터 강세 중 매도신호 = 의심 + - condition: vol_surge_pct >= 50 + score: -25 + note: 대규모 거래량 = 실제 매도 가능성 + - condition: vol_surge_pct >= 100 + score: -20 + note: 거래량 폭증 추가 패널티 base_score: 0 states: - WHIPSAW_SUSPECTED: "whipsaw_score >= 30" - CONFIRMED_SELL: "whipsaw_score < 10" - INCONCLUSIVE: "10 <= whipsaw_score < 30" + WHIPSAW_SUSPECTED: whipsaw_score >= 30 + CONFIRMED_SELL: whipsaw_score < 10 + INCONCLUSIVE: 10 <= whipsaw_score < 30 hold_policy: - WHIPSAW_SUSPECTED: "1거래일 매도 연기. 다음 거래일 재평가 필수." - CONFIRMED_SELL: "매도 진행 허용" - INCONCLUSIVE: "50% 수량만 매도 허용. 나머지 1거래일 후 재평가." + WHIPSAW_SUSPECTED: 1거래일 매도 연기. 다음 거래일 재평가 필수. + CONFIRMED_SELL: 매도 진행 허용 + INCONCLUSIVE: 50% 수량만 매도 허용. 나머지 1거래일 후 재평가. output: fields: - anti_whipsaw_gate: "WHIPSAW_SUSPECTED/CONFIRMED_SELL/INCONCLUSIVE" - anti_whipsaw_score: "0~100 점수" - anti_whipsaw_hold_days: "0 또는 1 (홀드 일수)" - anti_whipsaw_json: "상태·점수·홀드 사유 JSON" + anti_whipsaw_gate: WHIPSAW_SUSPECTED/CONFIRMED_SELL/INCONCLUSIVE + anti_whipsaw_score: 0~100 점수 + anti_whipsaw_hold_days: 0 또는 1 (홀드 일수) + anti_whipsaw_json: 상태·점수·홀드 사유 JSON prohibition: - - "WHIPSAW_SUSPECTED 상태에서 당일 전량 매도 신호 생성 금지" - - "anti_whipsaw_score를 LLM이 임의 계산 금지" - - "anti_whipsaw_gate를 LLM이 재판단하거나 우회 금지" + - WHIPSAW_SUSPECTED 상태에서 당일 전량 매도 신호 생성 금지 + - anti_whipsaw_score를 LLM이 임의 계산 금지 + - anti_whipsaw_gate를 LLM이 재판단하거나 우회 금지 harness_lock: true llm_override: forbidden - canonical_ref: "engine_harness_upgrade_proposal_result.txt:ANTI_WHIPSAW_HOLD_GATE_V1" - version: "2026-05-20_HARNESS_H6" - - # == [2026-05-20_H7] H7 - 4경로 결정론적 현금확보 라우터 =================== + canonical_ref: engine_harness_upgrade_proposal_result.txt:ANTI_WHIPSAW_HOLD_GATE_V1 + version: 2026-05-20_HARNESS_H6 SMART_CASH_RAISE_V2: - purpose: > - 현금 부족 상황에서 포트폴리오·종목 상태에 따라 4가지 경로(ROUTE_A~D) 중 하나를 - 결정론적으로 선택한다. 임의 전량매도·즉흥 트림을 차단하고 주식가치 훼손을 - 최소화하면서 반등 수익을 보존하는 구조화된 현금확보를 보장한다. + purpose: '현금 부족 상황에서 포트폴리오·종목 상태에 따라 4가지 경로(ROUTE_A~D) 중 하나를 결정론적으로 선택한다. 임의 + 전량매도·즉흥 트림을 차단하고 주식가치 훼손을 최소화하면서 반등 수익을 보존하는 구조화된 현금확보를 보장한다. + + ' inputs: - - {field: "position_class", unit: "enum", note: "CORE/SATELLITE"} - - {field: "rsi14", unit: "points"} - - {field: "profit_lock_stage", unit: "enum", note: "PROFIT_LOCK_STAGE_CLASSIFIER_V1 결과"} - - {field: "secular_leader_gate", unit: "enum", note: "SECULAR_LEADER_REGIME_GATE_V1 결과"} - - {field: "emergency_full_sell", unit: "bool", note: "긴급 전량매도 플래그 (인간 승인 필수)"} - - {field: "cash_shortfall_krw", unit: "KRW", note: "필요 현금 부족분"} - - {field: "stop_breach_gate", unit: "enum", note: "STOP_BREACH_ALERT_V1 결과"} + - field: position_class + unit: enum + note: CORE/SATELLITE + - field: rsi14 + unit: points + - field: profit_lock_stage + unit: enum + note: PROFIT_LOCK_STAGE_CLASSIFIER_V1 결과 + - field: secular_leader_gate + unit: enum + note: SECULAR_LEADER_REGIME_GATE_V1 결과 + - field: emergency_full_sell + unit: bool + note: 긴급 전량매도 플래그 (인간 승인 필수) + - field: cash_shortfall_krw + unit: KRW + note: 필요 현금 부족분 + - field: stop_breach_gate + unit: enum + note: STOP_BREACH_ALERT_V1 결과 route_selection: - priority_order: [ROUTE_D, ROUTE_A, ROUTE_B, ROUTE_C, ROUTE_E] + priority_order: + - ROUTE_D + - ROUTE_A + - ROUTE_B + - ROUTE_C + - ROUTE_E routes: ROUTE_D: - label: "긴급 전량매도" - trigger: "emergency_full_sell=true OR stop_breach_gate=BREACH" - action: "전량 매도. 즉시 실행." - qty_formula: "full_qty" + label: 긴급 전량매도 + trigger: emergency_full_sell=true OR stop_breach_gate=BREACH + action: 전량 매도. 즉시 실행. + qty_formula: full_qty rebound_wait_pct: 0 - note: "반드시 인간 승인 또는 stop 트리거 자동 발동만 허용" + note: 반드시 인간 승인 또는 stop 트리거 자동 발동만 허용 ROUTE_A: - label: "위성 비중 트림" - trigger: "position_class=SATELLITE AND rsi14 >= 35" - action: "보유수량의 33~50% 즉시 트림. 나머지 유지." - qty_formula: "ROUND(qty * 0.33 ~ 0.50)" + label: 위성 비중 트림 + trigger: position_class=SATELLITE AND rsi14 >= 35 + action: 보유수량의 33~50% 즉시 트림. 나머지 유지. + qty_formula: ROUND(qty * 0.33 ~ 0.50) rebound_wait_pct: 0 - note: "과매도 아닌 위성 종목 비중 축소. 반등 대기 없음." + note: 과매도 아닌 위성 종목 비중 축소. 반등 대기 없음. ROUTE_B: - label: "과매도 종목 분할 매도" - trigger: "rsi14 < 35" - action: "50% 즉시 매도 + 50% rebound_trigger_price 도달 시 매도" - qty_formula: "K2_STAGED_REBOUND_SELL_V1 공식 적용" - rebound_trigger_formula: "prevClose + 0.5 × ATR20" + label: 과매도 종목 분할 매도 + trigger: rsi14 < 35 + action: 50% 즉시 매도 + 50% rebound_trigger_price 도달 시 매도 + qty_formula: K2_STAGED_REBOUND_SELL_V1 공식 적용 + rebound_trigger_formula: prevClose + 0.5 × ATR20 rebound_wait_pct: 50 - note: "과매도 반등 수익 보존. K2와 동일 로직 재사용." + note: 과매도 반등 수익 보존. K2와 동일 로직 재사용. ROUTE_C: - label: "코어 익절 잠금" - trigger: "position_class=CORE AND profit_lock_stage IN [PROFIT_LOCK_STAGE_20,PROFIT_LOCK_STAGE_30] AND secular_leader_gate=PASS" - action: "PROFIT_LOCK_STAGE_CLASSIFIER_V1 지정 수량만 매도. 잔여 HOLD." - qty_formula: "profit_lock_qty (PROFIT_LOCK_STAGE_CLASSIFIER_V1 계산값)" + label: 코어 익절 잠금 + trigger: position_class=CORE AND profit_lock_stage IN [PROFIT_LOCK_STAGE_20,PROFIT_LOCK_STAGE_30] + AND secular_leader_gate=PASS + action: PROFIT_LOCK_STAGE_CLASSIFIER_V1 지정 수량만 매도. 잔여 HOLD. + qty_formula: profit_lock_qty (PROFIT_LOCK_STAGE_CLASSIFIER_V1 계산값) rebound_wait_pct: 0 - note: "코어 시큘러 리더는 최소 매도. 익절 수량 외 강제 매도 금지." + note: 코어 시큘러 리더는 최소 매도. 익절 수량 외 강제 매도 금지. ROUTE_E: - label: "일반 현금부족 단계적 매도" - trigger: "cash_shortfall_krw > 0 AND stop_breach_gate != BREACH AND rsi14 >= 35 AND ROUTE_A~D 조건 미해당" - action: "H2 sell_priority 순서로 SELL_WATERFALL_ENGINE_V1 Stage 1→2→3 실행." - qty_formula: "SELL_WATERFALL_ENGINE_V1 stage1_qty (prevClose 지정가 기준)" + label: 일반 현금부족 단계적 매도 + trigger: cash_shortfall_krw > 0 AND stop_breach_gate != BREACH AND rsi14 + >= 35 AND ROUTE_A~D 조건 미해당 + action: H2 sell_priority 순서로 SELL_WATERFALL_ENGINE_V1 Stage 1→2→3 실행. + qty_formula: SELL_WATERFALL_ENGINE_V1 stage1_qty (prevClose 지정가 기준) rebound_wait_pct: 50 - note: "비상 아닌 일반 현금부족 전용 폴백 경로. ROUTE_A~D 조건 미충족 시 실행." + note: 비상 아닌 일반 현금부족 전용 폴백 경로. ROUTE_A~D 조건 미충족 시 실행. output: fields: - smart_cash_raise_route: "ROUTE_A/ROUTE_B/ROUTE_C/ROUTE_D/NO_ACTION" - smart_cash_raise_qty: "결정론적 매도 수량 (주)" - smart_cash_raise_json: "경로·수량·사유·rebound_wait_pct 상세 JSON" + smart_cash_raise_route: ROUTE_A/ROUTE_B/ROUTE_C/ROUTE_D/NO_ACTION + smart_cash_raise_qty: 결정론적 매도 수량 (주) + smart_cash_raise_json: 경로·수량·사유·rebound_wait_pct 상세 JSON prohibition: - - "smart_cash_raise_route를 LLM이 임의 선택 금지" - - "smart_cash_raise_qty를 LLM이 재계산 금지" - - "ROUTE_D는 emergency_full_sell=true 또는 stop_breach_gate=BREACH 외 발동 금지" - - "ROUTE_C에서 profit_lock_qty 이상 매도 서술 금지" - - "현금 부족 시 코어 시큘러 리더 전량 매도 권고 금지" + - smart_cash_raise_route를 LLM이 임의 선택 금지 + - smart_cash_raise_qty를 LLM이 재계산 금지 + - ROUTE_D는 emergency_full_sell=true 또는 stop_breach_gate=BREACH 외 발동 금지 + - ROUTE_C에서 profit_lock_qty 이상 매도 서술 금지 + - 현금 부족 시 코어 시큘러 리더 전량 매도 권고 금지 harness_lock: true llm_override: forbidden - canonical_ref: "engine_harness_upgrade_proposal_result.txt:SMART_CASH_RAISE_V2" - version: "2026-05-23_HARNESS_V5_PROPOSAL46" - - # == [2026-05-23_PROPOSAL46] PA1 - 정반합 사전 예측 알파 엔진 ============= + canonical_ref: engine_harness_upgrade_proposal_result.txt:SMART_CASH_RAISE_V2 + version: 2026-05-23_HARNESS_V5_PROPOSAL46 PREDICTIVE_ALPHA_ENGINE_V1: - purpose: > - 正(매수 모멘텀) + 反(분배/과열 신호)를 합산한 방향성 신뢰도(合)를 결정론적으로 산출. - LLM이 "분위기가 좋으니까" BUY 권고하는 구조를 3계층 점수로 대체. - T+5 피드백 루프로 예측 정확도를 자동 추적하여 45.59% → 70%+ 목표. + purpose: '正(매수 모멘텀) + 反(분배/과열 신호)를 합산한 방향성 신뢰도(合)를 결정론적으로 산출. LLM이 "분위기가 좋으니까" + BUY 권고하는 구조를 3계층 점수로 대체. T+5 피드백 루프로 예측 정확도를 자동 추적하여 45.59% → 70%+ 목표. + + ' inputs: - - {field: "close", unit: "KRW_per_share"} - - {field: "ma20", unit: "KRW_per_share"} - - {field: "flow_credit", unit: "ratio_0_1"} - - {field: "rs_verdict", unit: "enum"} - - {field: "brt_verdict", unit: "enum"} - - {field: "volume_ratio_5d", unit: "ratio"} - - {field: "rsi14", unit: "score_0_100"} - - {field: "velocity_1d", unit: "percent"} - - {field: "distribution_signals_count", unit: "integer"} - - {field: "foreign_sell_consecutive_days", unit: "integer"} - - {field: "usd_krw", unit: "KRW", optional: true} - - {field: "days_since_entry", unit: "integer", optional: true} - - {field: "profit_pct", unit: "percent", optional: true} + - field: close + unit: KRW_per_share + - field: ma20 + unit: KRW_per_share + - field: flow_credit + unit: ratio_0_1 + - field: rs_verdict + unit: enum + - field: brt_verdict + unit: enum + - field: volume_ratio_5d + unit: ratio + - field: rsi14 + unit: score_0_100 + - field: velocity_1d + unit: percent + - field: distribution_signals_count + unit: integer + - field: foreign_sell_consecutive_days + unit: integer + - field: usd_krw + unit: KRW + optional: true + - field: days_since_entry + unit: integer + optional: true + - field: profit_pct + unit: percent + optional: true thesis_score: max: 100 components: - pullback_entry: {condition: "close > ma20 AND close < ma20 * 1.03", score: 20} - flow_strong: {condition: "flow_credit >= 0.55", score: 20} - rs_leader: {condition: "rs_verdict = LEADER", score: 15} - volume_confirm: {condition: "volume_ratio_5d >= 1.2", score: 15} - rsi_healthy: {condition: "rsi14 BETWEEN 45 AND 65", score: 15} - brt_leader: {condition: "brt_verdict = LEADER", score: 15} + pullback_entry: + condition: close > ma20 AND close < ma20 * 1.03 + score: 20 + flow_strong: + condition: flow_credit >= 0.55 + score: 20 + rs_leader: + condition: rs_verdict = LEADER + score: 15 + volume_confirm: + condition: volume_ratio_5d >= 1.2 + score: 15 + rsi_healthy: + condition: rsi14 BETWEEN 45 AND 65 + score: 15 + brt_leader: + condition: brt_verdict = LEADER + score: 15 antithesis_score: max: 100 components: - chase_risk: {condition: "velocity_1d >= 3.0", score: 25} - distribution: {condition: "distribution_signals_count >= 2", score: 20} - rsi_overbought: {condition: "rsi14 >= 75", score: 20} - foreign_sell: {condition: "foreign_sell_consecutive_days >= 5", score: 15} - usd_krw_weak: {condition: "usd_krw >= 1480", score: 10} - stale_position: {condition: "days_since_entry >= 60 AND profit_pct < 5", score: 10} + chase_risk: + condition: velocity_1d >= 3.0 + score: 25 + distribution: + condition: distribution_signals_count >= 2 + score: 20 + rsi_overbought: + condition: rsi14 >= 75 + score: 20 + foreign_sell: + condition: foreign_sell_consecutive_days >= 5 + score: 15 + usd_krw_weak: + condition: usd_krw >= 1480 + score: 10 + stale_position: + condition: days_since_entry >= 60 AND profit_pct < 5 + score: 10 synthesis: - direction_confidence: "thesis_score - antithesis_score" + direction_confidence: thesis_score - antithesis_score verdicts: - STRONG_BUY_SIGNAL: {condition: "direction_confidence >= 40"} - MODERATE_BUY_SIGNAL: {condition: "direction_confidence >= 20"} - HOLD_NEUTRAL: {condition: "direction_confidence >= -10"} - TRIM_SIGNAL: {condition: "direction_confidence >= -30"} - EXIT_SIGNAL: {condition: "direction_confidence < -30"} + STRONG_BUY_SIGNAL: + condition: direction_confidence >= 40 + MODERATE_BUY_SIGNAL: + condition: direction_confidence >= 20 + HOLD_NEUTRAL: + condition: direction_confidence >= -10 + TRIM_SIGNAL: + condition: direction_confidence >= -30 + EXIT_SIGNAL: + condition: direction_confidence < -30 feedback_loop: - metric: "prediction_accuracy_rate" - storage: "monthly_history sheet" + metric: prediction_accuracy_rate + storage: monthly_history sheet auto_adjust: - antithesis_weight_up: "accuracy < 60% → ANTITHESIS 가중치 +10%" - thesis_weight_up: "accuracy > 75% → THESIS 가중치 +5%" + antithesis_weight_up: accuracy < 60% → ANTITHESIS 가중치 +10% + thesis_weight_up: accuracy > 75% → THESIS 가중치 +5% output: - field: "predictive_alpha_json" + field: predictive_alpha_json schema: - direction_confidence: "integer (-100 ~ +100)" - thesis_score: "integer (0 ~ 100)" - antithesis_score: "integer (0 ~ 100)" - synthesis_verdict: "enum" - prediction_confidence_pct: "percent" - thesis_breakdown: "array" - antithesis_breakdown: "array" + direction_confidence: integer (-100 ~ +100) + thesis_score: integer (0 ~ 100) + antithesis_score: integer (0 ~ 100) + synthesis_verdict: enum + prediction_confidence_pct: percent + thesis_breakdown: array + antithesis_breakdown: array prohibition: - - "synthesis_verdict 없이 신규 BUY 서술 금지 (Direction PA1)" - - "LLM이 thesis/antithesis 점수를 직접 계산 금지" - - "direction_confidence 재계산 또는 번복 금지" - canonical_ref: "AGENTS.md:Direction PA1, temp/request_result.txt:proposal_46" - version: "2026-05-23_PROPOSAL46" - - # == [2026-05-23_PROPOSAL46] PA2 - 뒷박 방지 3중 게이트 V2 ================== + - synthesis_verdict 없이 신규 BUY 서술 금지 (Direction PA1) + - LLM이 thesis/antithesis 점수를 직접 계산 금지 + - direction_confidence 재계산 또는 번복 금지 + canonical_ref: AGENTS.md:Direction PA1, temp/request_result.txt:proposal_46 + version: 2026-05-23_PROPOSAL46 ANTI_LATE_ENTRY_GATE_V2: - purpose: > - 기존 ANTI_CHASING_VELOCITY_V1(당일 속도만 체크)의 허점 보완. - 2~3일 연속 급등 후 당일 잠시 쉬는 경우도 5일 누적 속도 GATE_2로 차단. - 분배 신호 GATE_3을 추가해 3중 AND 게이트 구성. - inputs: - - {field: "velocity_1d", unit: "percent", note: "(close-prevClose)/prevClose*100"} - - {field: "velocity_5d", unit: "percent", note: "(close-close_5d)/close_5d*100"} - - {field: "distribution_signals_count", unit: "integer", note: "DISTRIBUTION_SELL_DETECTOR_V1 결과"} - - {field: "pre_distribution_warning", unit: "enum", optional: true} - - {field: "flow_credit", unit: "ratio_0_1", optional: true} - - {field: "ma20", unit: "KRW_per_share", optional: true} - gate_1_velocity_1d: - BLOCK_CHASE: "velocity_1d >= 3.0%" - PULLBACK_WAIT: "velocity_1d >= 1.5%" - PASS: "velocity_1d < 1.5%" - gate_2_velocity_5d: - BLOCK_CHASE_5D: "velocity_5d >= 8.0%" - PULLBACK_WAIT_5D: "velocity_5d >= 5.0%" - PASS: "velocity_5d < 5.0%" - gate_3_distribution: - BLOCK_DISTRIBUTION: "distribution_signals_count >= 2 (weighted_sum >= 3.0)" - PULLBACK_WAIT_DIST: "pre_distribution_warning = EARLY_WARNING" - PASS: "otherwise" - final_gate_logic: - logic: "AND" - BLOCK: "gate_1=BLOCK OR gate_2=BLOCK OR gate_3=BLOCK" - PULLBACK_WAIT: "any PULLBACK_WAIT (BLOCK 없을 때)" - PASS: "gate_1=PASS AND gate_2=PASS AND gate_3=PASS" - entry_grade: - A: "velocity_1d < 0.5% AND pullback_zone AND flow_credit > 0.55" - B: "velocity_1d < 1.5% AND close near MA20" - C: "PULLBACK_WAIT 통과 진입" - D: "velocity_5d > 5% 이지만 gate_1 PASS" - F: "BLOCK 우회 진입 → PATTERN_BLACKLIST_AUTO_V1 카운트 자동 +1" - output: - field: "anti_late_entry_json" - schema: - gate1_status: "BLOCK_CHASE | PULLBACK_WAIT | PASS" - gate2_status: "BLOCK_CHASE_5D | PULLBACK_WAIT_5D | PASS" - gate3_status: "BLOCK_DISTRIBUTION | PULLBACK_WAIT_DIST | PASS" - final_gate_status: "BLOCK | PULLBACK_WAIT | PASS" - entry_grade: "A | B | C | D | F" - block_reason: "string" - velocity_1d: "percent" - velocity_5d: "percent" - prohibition: - - "BLOCK 상태에서 BUY/STAGED_BUY/ADD_ON 출력 금지" - - "entry_grade=F 자동 입력 시 PATTERN_BLACKLIST 카운트 +1 강제" - - "ANTI_CHASING_VELOCITY_V1(V1) 단독 인용 금지 - 이 V2가 V1을 완전 대체" - canonical_ref: "AGENTS.md:Direction A2 (V2로 업그레이드)" - version: "2026-05-23_PROPOSAL46" + purpose: '기존 ANTI_CHASING_VELOCITY_V1(당일 속도만 체크)의 허점 보완. 2~3일 연속 급등 후 당일 잠시 + 쉬는 경우도 5일 누적 속도 GATE_2로 차단. 분배 신호 GATE_3을 추가해 3중 AND 게이트 구성. - # == [2026-05-23_PROPOSAL46] PA3 - 현금확보 매도 세련화 엔진 V2 ============= - CASH_PRESERVATION_SELL_ENGINE_V2: - purpose: > - K2(50/50 분할) + C1(4단계 폭포수) + C2(타이밍 결정)를 단일 엔진으로 통합. - 현금이 급해도 과매도 구간 전량 즉시 청산 방지 + 반등 시 추가 수익 포착. - value_preservation_score < 50이면 SELL_VALUE_DAMAGE_WARNING 경보 발령. + ' inputs: - - {field: "rsi14", unit: "score_0_100"} - - {field: "atr20", unit: "KRW_per_share"} - - {field: "prev_close", unit: "KRW_per_share"} - - {field: "ma20", unit: "KRW_per_share", optional: true} - - {field: "base_qty", unit: "shares", note: "H3 SELL_QUANTITY_ALLOCATOR 산출"} - - {field: "stop_loss_price", unit: "KRW_per_share"} - - {field: "cash_shortfall_min_krw", unit: "KRW", note: "CASH_SHORTFALL_V1 산출"} - - {field: "distribution_signals_count", unit: "integer", optional: true} - - {field: "emergency_full_sell", unit: "boolean", optional: true, note: "K2 산출값"} - - {field: "oversold_gate", unit: "enum", optional: true} + - field: velocity_1d + unit: percent + note: (close-prevClose)/prevClose*100 + - field: velocity_5d + unit: percent + note: (close-close_5d)/close_5d*100 + - field: distribution_signals_count + unit: integer + note: DISTRIBUTION_SELL_DETECTOR_V1 결과 + - field: pre_distribution_warning + unit: enum + optional: true + - field: flow_credit + unit: ratio_0_1 + optional: true + - field: ma20 + unit: KRW_per_share + optional: true + gate_1_velocity_1d: + BLOCK_CHASE: velocity_1d >= 3.0% + PULLBACK_WAIT: velocity_1d >= 1.5% + PASS: velocity_1d < 1.5% + gate_2_velocity_5d: + BLOCK_CHASE_5D: velocity_5d >= 8.0% + PULLBACK_WAIT_5D: velocity_5d >= 5.0% + PASS: velocity_5d < 5.0% + gate_3_distribution: + BLOCK_DISTRIBUTION: distribution_signals_count >= 2 (weighted_sum >= 3.0) + PULLBACK_WAIT_DIST: pre_distribution_warning = EARLY_WARNING + PASS: otherwise + final_gate_logic: + logic: AND + BLOCK: gate_1=BLOCK OR gate_2=BLOCK OR gate_3=BLOCK + PULLBACK_WAIT: any PULLBACK_WAIT (BLOCK 없을 때) + PASS: gate_1=PASS AND gate_2=PASS AND gate_3=PASS + entry_grade: + A: velocity_1d < 0.5% AND pullback_zone AND flow_credit > 0.55 + B: velocity_1d < 1.5% AND close near MA20 + C: PULLBACK_WAIT 통과 진입 + D: velocity_5d > 5% 이지만 gate_1 PASS + F: BLOCK 우회 진입 → PATTERN_BLACKLIST_AUTO_V1 카운트 자동 +1 + output: + field: anti_late_entry_json + schema: + gate1_status: BLOCK_CHASE | PULLBACK_WAIT | PASS + gate2_status: BLOCK_CHASE_5D | PULLBACK_WAIT_5D | PASS + gate3_status: BLOCK_DISTRIBUTION | PULLBACK_WAIT_DIST | PASS + final_gate_status: BLOCK | PULLBACK_WAIT | PASS + entry_grade: A | B | C | D | F + block_reason: string + velocity_1d: percent + velocity_5d: percent + prohibition: + - BLOCK 상태에서 BUY/STAGED_BUY/ADD_ON 출력 금지 + - entry_grade=F 자동 입력 시 PATTERN_BLACKLIST 카운트 +1 강제 + - ANTI_CHASING_VELOCITY_V1(V1) 단독 인용 금지 - 이 V2가 V1을 완전 대체 + canonical_ref: AGENTS.md:Direction A2 (V2로 업그레이드) + version: 2026-05-23_PROPOSAL46 + CASH_PRESERVATION_SELL_ENGINE_V2: + purpose: 'K2(50/50 분할) + C1(4단계 폭포수) + C2(타이밍 결정)를 단일 엔진으로 통합. 현금이 급해도 과매도 구간 + 전량 즉시 청산 방지 + 반등 시 추가 수익 포착. value_preservation_score < 50이면 SELL_VALUE_DAMAGE_WARNING + 경보 발령. + + ' + inputs: + - field: rsi14 + unit: score_0_100 + - field: atr20 + unit: KRW_per_share + - field: prev_close + unit: KRW_per_share + - field: ma20 + unit: KRW_per_share + optional: true + - field: base_qty + unit: shares + note: H3 SELL_QUANTITY_ALLOCATOR 산출 + - field: stop_loss_price + unit: KRW_per_share + - field: cash_shortfall_min_krw + unit: KRW + note: CASH_SHORTFALL_V1 산출 + - field: distribution_signals_count + unit: integer + optional: true + - field: emergency_full_sell + unit: boolean + optional: true + note: K2 산출값 + - field: oversold_gate + unit: enum + optional: true execution_style_decision: - OVERSOLD_REBOUND_SELL: "oversold_gate=OVERSOLD AND rsi14 < 30" - EMERGENCY_FULL_EXIT: "emergency_full_sell=true" - STAGED_WATERFALL: "otherwise" + OVERSOLD_REBOUND_SELL: oversold_gate=OVERSOLD AND rsi14 < 30 + EMERGENCY_FULL_EXIT: emergency_full_sell=true + STAGED_WATERFALL: otherwise quantity_formulas: OVERSOLD_REBOUND_SELL: - immediate_qty: "floor(base_qty * 0.50)" - rebound_wait_qty: "base_qty - immediate_qty" - rebound_trigger: "TICK_NORMALIZER_V1(prev_close + 0.5 * atr20)" - deadline_days: 3 - deadline_action: "미체결 3영업일 후 prev_close 지정가로 자동 전환" + immediate_qty: floor(base_qty * 0.50) + rebound_wait_qty: base_qty - immediate_qty + rebound_trigger: TICK_NORMALIZER_V1(prev_close + 0.5 * atr20) + deadline_days: 3 + deadline_action: 미체결 3영업일 후 prev_close 지정가로 자동 전환 STAGED_WATERFALL: - stage1_qty: "floor(base_qty * 0.50)" - stage2_qty: "base_qty - stage1_qty" - stage2_deadline: "5 영업일 초과 시 EMERGENCY 전환" + stage1_qty: floor(base_qty * 0.50) + stage2_qty: base_qty - stage1_qty + stage2_deadline: 5 영업일 초과 시 EMERGENCY 전환 EMERGENCY_FULL_EXIT: - sell_qty: "base_qty" - order_type: "MARKET" + sell_qty: base_qty + order_type: MARKET rebound_scenario: - immediate_sell_krw: "immediate_qty * prev_close" - rebound_upside_krw: "rebound_wait_qty * rebound_trigger" - downside_risk_krw: "rebound_wait_qty * stop_loss_price" - risk_reward_ratio: "(rebound_upside_krw - immediate_sell_krw) / max(1, immediate_sell_krw - downside_risk_krw)" - low_rr_alert: "risk_reward_ratio < 1.0 → emergency_full_sell 검토 권고" + immediate_sell_krw: immediate_qty * prev_close + rebound_upside_krw: rebound_wait_qty * rebound_trigger + downside_risk_krw: rebound_wait_qty * stop_loss_price + risk_reward_ratio: (rebound_upside_krw - immediate_sell_krw) / max(1, immediate_sell_krw + - downside_risk_krw) + low_rr_alert: risk_reward_ratio < 1.0 → emergency_full_sell 검토 권고 value_preservation_score: base: 100 deductions: - full_sell_oversold: {condition: "immediate_qty=base_qty AND rsi14 < 30", deduct: 30} - price_below_prev: {condition: "limit_price < prev_close * 0.97", deduct: 20} - distribution_high: {condition: "distribution_signals_count >= 3", deduct: 15} + full_sell_oversold: + condition: immediate_qty=base_qty AND rsi14 < 30 + deduct: 30 + price_below_prev: + condition: limit_price < prev_close * 0.97 + deduct: 20 + distribution_high: + condition: distribution_signals_count >= 3 + deduct: 15 bonuses: - rebound_wait_exists: {condition: "rebound_wait_qty > 0", bonus: 15} - tight_trigger: {condition: "rebound_trigger <= prev_close * 1.03", bonus: 10} - alert: "score < 50 → SELL_VALUE_DAMAGE_WARNING" + rebound_wait_exists: + condition: rebound_wait_qty > 0 + bonus: 15 + tight_trigger: + condition: rebound_trigger <= prev_close * 1.03 + bonus: 10 + alert: score < 50 → SELL_VALUE_DAMAGE_WARNING output: - field: "cash_preservation_sell_json" + field: cash_preservation_sell_json schema: - execution_style: "OVERSOLD_REBOUND_SELL | STAGED_WATERFALL | EMERGENCY_FULL_EXIT" - immediate_qty: "shares" - rebound_wait_qty: "shares" - rebound_trigger_price: "KRW (tick-normalized)" - rebound_deadline_days: "integer" - risk_reward_ratio: "float" - value_preservation_score: "integer (0~100)" - immediate_sell_krw: "KRW" - rebound_upside_krw: "KRW" - emergency_full_sell_flag: "boolean" - sell_value_damage_warning: "boolean" + execution_style: OVERSOLD_REBOUND_SELL | STAGED_WATERFALL | EMERGENCY_FULL_EXIT + immediate_qty: shares + rebound_wait_qty: shares + rebound_trigger_price: KRW (tick-normalized) + rebound_deadline_days: integer + risk_reward_ratio: float + value_preservation_score: integer (0~100) + immediate_sell_krw: KRW + rebound_upside_krw: KRW + emergency_full_sell_flag: boolean + sell_value_damage_warning: boolean prohibition: - - "OVERSOLD_REBOUND_SELL에서 rebound_wait_qty를 반등 트리거 미충족 상태에서 즉시 매도 금지" - - "value_preservation_score 없이 매도 수량 제안 금지 (Direction D2[11])" - - "emergency_full_sell=false에서 전량 즉시 청산 지시 금지" - canonical_ref: "AGENTS.md:Direction K2/C1/C2, temp/request_result.txt:proposal_46#1-3" - version: "2026-05-23_PROPOSAL46" - - # == [2026-05-23_PROPOSAL46] PA4 - 미시/거시/국제정세 동기화 하네스 ========== + - OVERSOLD_REBOUND_SELL에서 rebound_wait_qty를 반등 트리거 미충족 상태에서 즉시 매도 금지 + - value_preservation_score 없이 매도 수량 제안 금지 (Direction D2[11]) + - emergency_full_sell=false에서 전량 즉시 청산 지시 금지 + canonical_ref: AGENTS.md:Direction K2/C1/C2, temp/request_result.txt:proposal_46#1-3 + version: 2026-05-23_PROPOSAL46 MACRO_EVENT_SYNCHRONIZER_V1: - purpose: > - 외국인 순매도 일수·USD/KRW·FOMC 일정·국내 CPI·VIX 등 거시 변수를 - heat_gate + buy_gate에 자동 반영. 현재 LLM 서술용으로만 쓰던 데이터를 - 결정론적 gate 조정에 연결. 매일 아침 GAS Trigger로 자동 갱신. + purpose: '외국인 순매도 일수·USD/KRW·FOMC 일정·국내 CPI·VIX 등 거시 변수를 heat_gate + buy_gate에 + 자동 반영. 현재 LLM 서술용으로만 쓰던 데이터를 결정론적 gate 조정에 연결. 매일 아침 GAS Trigger로 자동 갱신. + + ' inputs: - - {field: "usd_krw", unit: "KRW", note: "settings manual_input 또는 API"} - - {field: "foreign_sell_consecutive_days", unit: "integer", note: "macro 시트 누적"} - - {field: "foreign_sell_krw_today", unit: "KRW", optional: true} - - {field: "fomc_days_remaining", unit: "integer", optional: true, note: "event_calendar"} - - {field: "domestic_cpi", unit: "percent", optional: true} - - {field: "vix", unit: "float", optional: true} - - {field: "us500_1w_change", unit: "percent", optional: true} + - field: usd_krw + unit: KRW + note: settings manual_input 또는 API + - field: foreign_sell_consecutive_days + unit: integer + note: macro 시트 누적 + - field: foreign_sell_krw_today + unit: KRW + optional: true + - field: fomc_days_remaining + unit: integer + optional: true + note: event_calendar + - field: domestic_cpi + unit: percent + optional: true + - field: vix + unit: float + optional: true + - field: us500_1w_change + unit: percent + optional: true macro_risk_score: max: 100 components: - usd_krw_critical: {condition: "usd_krw > 1500", score: 20} - usd_krw_weak: {condition: "usd_krw > 1480 AND <= 1500", score: 15} - foreign_mega: {condition: "foreign_consecutive_sell_days >= 10", score: 20} - foreign_high: {condition: "foreign_consecutive_sell_days >= 5", score: 15} - fomc_near: {condition: "fomc_days_remaining <= 5", score: 15} - cpi_high: {condition: "domestic_cpi > 2.5", score: 10} - vix_elevated: {condition: "vix > 20", score: 10} - us500_drop: {condition: "us500_1w_change < -3.0", score: 10} + usd_krw_critical: + condition: usd_krw > 1500 + score: 20 + usd_krw_weak: + condition: usd_krw > 1480 AND <= 1500 + score: 15 + foreign_mega: + condition: foreign_consecutive_sell_days >= 10 + score: 20 + foreign_high: + condition: foreign_consecutive_sell_days >= 5 + score: 15 + fomc_near: + condition: fomc_days_remaining <= 5 + score: 15 + cpi_high: + condition: domestic_cpi > 2.5 + score: 10 + vix_elevated: + condition: vix > 20 + score: 10 + us500_drop: + condition: us500_1w_change < -3.0 + score: 10 macro_risk_regime: - MACRO_CRITICAL: {condition: "macro_risk_score >= 60", heat_gate_adj: -3} - MACRO_ELEVATED: {condition: "macro_risk_score >= 40", heat_gate_adj: -1} - MACRO_NEUTRAL: {condition: "macro_risk_score >= 20", heat_gate_adj: 0} - MACRO_FAVORABLE: {condition: "macro_risk_score < 20", heat_gate_adj: +1} + MACRO_CRITICAL: + condition: macro_risk_score >= 60 + heat_gate_adj: -3 + MACRO_ELEVATED: + condition: macro_risk_score >= 40 + heat_gate_adj: -1 + MACRO_NEUTRAL: + condition: macro_risk_score >= 20 + heat_gate_adj: 0 + MACRO_FAVORABLE: + condition: macro_risk_score < 20 + heat_gate_adj: 1 event_matrix: - FOMC_WEEK: {buy_gate_downgrade: true, sell_block: false} - EARNINGS_WEEK: {event_hold_gate: true, note: "해당 종목 M4 EVENT_HOLD 발동"} - DART_RISK: {event_hold_gate: true, note: "기존 M4 연동"} - GEOPOLITICAL: {regime_size_scale_adj: -0.25, note: "N1 연동"} + FOMC_WEEK: + buy_gate_downgrade: true + sell_block: false + EARNINGS_WEEK: + event_hold_gate: true + note: 해당 종목 M4 EVENT_HOLD 발동 + DART_RISK: + event_hold_gate: true + note: 기존 M4 연동 + GEOPOLITICAL: + regime_size_scale_adj: -0.25 + note: N1 연동 mega_sell_alert: - condition: "foreign_sell_krw_today >= 1_000_000_000_000" - effect: "buy_gate_block_until = today + 3 영업일" + condition: foreign_sell_krw_today >= 1_000_000_000_000 + effect: buy_gate_block_until = today + 3 영업일 data_sources: - usd_krw: "settings 시트 manual_input" - fomc_dates: "settings 시트 event_calendar" - foreign_flow: "macro 시트 _foreignFlow" - vix_us500: "macro 시트 _vix, _us500Close" + usd_krw: settings 시트 manual_input + fomc_dates: settings 시트 event_calendar + foreign_flow: macro 시트 _foreignFlow + vix_us500: macro 시트 _vix, _us500Close output: - field: "macro_event_json" + field: macro_event_json schema: - macro_risk_score: "integer (0~100)" - macro_risk_regime: "MACRO_CRITICAL | MACRO_ELEVATED | MACRO_NEUTRAL | MACRO_FAVORABLE" - macro_risk_breakdown: "array" - foreign_consecutive_sell_days: "integer" - mega_sell_alert: "boolean" - buy_gate_block_until: "date or null" - effective_heat_gate_adjustment: "integer" - event_matrix: "array" - fomc_days_remaining: "integer or null" + macro_risk_score: integer (0~100) + macro_risk_regime: MACRO_CRITICAL | MACRO_ELEVATED | MACRO_NEUTRAL | MACRO_FAVORABLE + macro_risk_breakdown: array + foreign_consecutive_sell_days: integer + mega_sell_alert: boolean + buy_gate_block_until: date or null + effective_heat_gate_adjustment: integer + event_matrix: array + fomc_days_remaining: integer or null prohibition: - - "MACRO_CRITICAL 상태에서 포지션 증가 서술 금지 (Direction D2[10])" - - "LLM이 macro_risk_score를 임의 계산 금지 - 하네스 출력만 인용" - - "external_context_json 데이터를 주문 판단에 혼입 금지 (G3)" - canonical_ref: "AGENTS.md:Direction G3/ME1, temp/request_result.txt:proposal_46#1-4" - version: "2026-05-23_PROPOSAL46" - - # == [2026-05-23_PROPOSAL46] PA5 - 데이터정합성/방향성/일관성 검증기 V2 ======= + - MACRO_CRITICAL 상태에서 포지션 증가 서술 금지 (Direction D2[10]) + - LLM이 macro_risk_score를 임의 계산 금지 - 하네스 출력만 인용 + - external_context_json 데이터를 주문 판단에 혼입 금지 (G3) + canonical_ref: AGENTS.md:Direction G3/ME1, temp/request_result.txt:proposal_46#1-4 + version: 2026-05-23_PROPOSAL46 CONSISTENCY_VALIDATOR_V2: - purpose: > - 기존 validate_harness_context.py(키 존재 여부만)를 12개 논리 검증 항목으로 확장. - 일관성 점수 < 90%이면 보고서 생성 자체 BLOCK - 오염 데이터 분석 원천 차단. - DETERMINISTIC_ROUTING_ENGINE_V1의 Step 2(pre-flight)에서 가장 먼저 실행. + purpose: '기존 validate_harness_context.py(키 존재 여부만)를 12개 논리 검증 항목으로 확장. 일관성 점수 + < 90%이면 보고서 생성 자체 BLOCK - 오염 데이터 분석 원천 차단. DETERMINISTIC_ROUTING_ENGINE_V1의 + Step 2(pre-flight)에서 가장 먼저 실행. + + ' inputs: - - {field: "settlement_cash_d2_krw", unit: "KRW", note: "CV_08 현금 경로 검증"} - - {field: "harness_context", unit: "json", note: "전체 harness_context 객체 - CV_01~CV_12 검증 원천"} + - field: settlement_cash_d2_krw + unit: KRW + note: CV_08 현금 경로 검증 + - field: harness_context + unit: json + note: 전체 harness_context 객체 - CV_01~CV_12 검증 원천 checks: CV_01: - name: "sell_priority 방향 일관성" - rule: "sell_candidates_json[n].tier >= sell_candidates_json[n-1].tier (tier 역전 금지)" + name: sell_priority 방향 일관성 + rule: sell_candidates_json[n].tier >= sell_candidates_json[n-1].tier (tier + 역전 금지) CV_02: - name: "가격 순서 검증" - rule: "stop_price < current_price < tp1_price < tp2_price (모든 종목)" + name: 가격 순서 검증 + rule: stop_price < current_price < tp1_price < tp2_price (모든 종목) CV_03: - name: "heat vs 보유 비중 일치" - rule: "sum(position_weight_pct) ≈ total_heat_pct (±0.5% 허용)" + name: heat vs 보유 비중 일치 + rule: sum(position_weight_pct) ≈ total_heat_pct (±0.5% 허용) CV_04: - name: "enum 값 유효성" - rule: "profit_lock_stage in VALID_STAGES, rs_verdict in {LEADER,NEUTRAL,LAGGARD,BROKEN}, tp_state in VALID_TP_STATES" + name: enum 값 유효성 + rule: profit_lock_stage in VALID_STAGES, rs_verdict in {LEADER,NEUTRAL,LAGGARD,BROKEN}, + tp_state in VALID_TP_STATES CV_05: - name: "상호 충돌 게이트 탐지" + name: 상호 충돌 게이트 탐지 rules: - - "heat_gate=BLOCK_NEW_BUY AND final_action=BUY → CONTRADICTION" - - "sfg_v1=TRIGGERED AND final_action=BUY → CONTRADICTION" - - "intraday_lock=true AND BUY not in blocked_actions → INCOMPLETE" + - heat_gate=BLOCK_NEW_BUY AND final_action=BUY → CONTRADICTION + - sfg_v1=TRIGGERED AND final_action=BUY → CONTRADICTION + - intraday_lock=true AND BUY not in blocked_actions → INCOMPLETE CV_06: - name: "수량 정수 검증" - rule: "모든 qty 필드 = floor(qty) (소수점 금지)" + name: 수량 정수 검증 + rule: 모든 qty 필드 = floor(qty) (소수점 금지) CV_07: - name: "날짜 신선도" + name: 날짜 신선도 rules: - - "data_date vs today > 1 영업일 → STALE_WARN" - - "data_date vs today > 3 영업일 → STALE_BLOCK" + - data_date vs today > 1 영업일 → STALE_WARN + - data_date vs today > 3 영업일 → STALE_BLOCK CV_08: - name: "현금 계산 경로" - rule: "settlement_cash_d2_krw 사용 확인. immediate_cash 합산 금지." + name: 현금 계산 경로 + rule: settlement_cash_d2_krw 사용 확인. immediate_cash 합산 금지. CV_09: - name: "라우팅 completeness" - rule: "routing_execution_log에 10단계 모두 존재 여부" + name: 라우팅 completeness + rule: routing_execution_log에 10단계 모두 존재 여부 CV_10: - name: "LLM 출력 checksum" - rule: "rendered_output_checksum 일치 여부 (blueprint vs LLM 출력 수치)" + name: LLM 출력 checksum + rule: rendered_output_checksum 일치 여부 (blueprint vs LLM 출력 수치) CV_11: - name: "GAS 하네스 키 동기화" - rule: "buildHarnessContext_() 출력 키 ⊇ validate_harness_context.py REQUIRED_KEYS" - gap_output: "HARNESS_KEY_MISSING 목록" + name: GAS 하네스 키 동기화 + rule: buildHarnessContext_() 출력 키 ⊇ validate_harness_context.py REQUIRED_KEYS + gap_output: HARNESS_KEY_MISSING 목록 CV_12: - name: "YAML-to-GAS 커버리지" - rule: "spec/ formula_id 목록 vs gas_data_feed.gs calc*_() 교차검증" - gap_output: "GAS_COVERAGE_GAP 목록" + name: YAML-to-GAS 커버리지 + rule: spec/ formula_id 목록 vs gas_data_feed.gs calc*_() 교차검증 + gap_output: GAS_COVERAGE_GAP 목록 scoring: - formula: "(통과 항목 수 / 12) * 100" - BLOCK: "score < 90 → 보고서 생성 중단" - WARNING: "score >= 90 AND < 100 → Gap 목록 출력 후 계속" - PASS: "score = 100" + formula: (통과 항목 수 / 12) * 100 + BLOCK: score < 90 → 보고서 생성 중단 + WARNING: score >= 90 AND < 100 → Gap 목록 출력 후 계속 + PASS: score = 100 output: - field: "consistency_report_json" + field: consistency_report_json schema: - score: "integer (0~100)" - passed: "array of check_ids" - failed: "array of {check_id, reason}" - gap_list: "array of {type: HARNESS_KEY_MISSING|GAS_COVERAGE_GAP, item}" - block_status: "BLOCK | WARNING | PASS" + score: integer (0~100) + passed: array of check_ids + failed: array of {check_id, reason} + gap_list: 'array of {type: HARNESS_KEY_MISSING|GAS_COVERAGE_GAP, item}' + block_status: BLOCK | WARNING | PASS prohibition: - - "consistency_score < 90인 상태에서 보고서 생성 금지" - - "LLM이 CV 검증 항목을 직접 계산하거나 우회 선언 금지" - - "ROUTING step 2에서 CV_02 통과 전 이후 단계 진행 금지" - canonical_ref: "AGENTS.md:Direction D1(Step 2), temp/request_result.txt:proposal_46#1-5" - version: "2026-05-23_PROPOSAL46" - - # == [2026-05-24_PROPOSAL50] EJCE-V1 - 전문가 3관점 합의 게이트 ============= + - consistency_score < 90인 상태에서 보고서 생성 금지 + - LLM이 CV 검증 항목을 직접 계산하거나 우회 선언 금지 + - ROUTING step 2에서 CV_02 통과 전 이후 단계 진행 금지 + canonical_ref: AGENTS.md:Direction D1(Step 2), temp/request_result.txt:proposal_46#1-5 + version: 2026-05-23_PROPOSAL46 EXPERT_JUDGMENT_CONSENSUS_ENGINE_V1: - purpose: > - Analyst(기술적 관점)·Trader(실행 타이밍)·Quant(리스크 수치) 3관점 중 - 2관점 이상 BLOCK이면 consensus_result=NO_BUY를 반환. - buy_permission_json.buy_permission_state=ALLOW여도 NO_BUY 종목 BUY 절대 차단. - inputs: - - {field: "ticker", unit: "string"} - - {field: "df", unit: "object - market data feed"} - - {field: "paeRow", unit: "object - PAE output row"} - - {field: "hApex", unit: "object - harness apex context"} - output: - field: "ejce_json" - schema: - ticker: "string" - analyst_view: "ALLOW | BLOCK" - trader_view: "ALLOW | BLOCK" - quant_view: "ALLOW | BLOCK" - consensus_result: "BUY_ALLOWED | NO_BUY" - block_reasons: "array of string" - formula_id: "EXPERT_JUDGMENT_CONSENSUS_ENGINE_V1" - prohibition: - - "consensus_result=NO_BUY 종목에 BUY/ADD_ON 권고 금지" - - "block_reasons 3관점 미인용 시 INCOMPLETE_EJCE_REPORT" - - "buy_permission=ALLOW만 확인하고 ejce_json 확인 생략 금지" - canonical_ref: "AGENTS.md:Direction EJ1" - version: "2026-05-24_PROPOSAL50" + purpose: 'Analyst(기술적 관점)·Trader(실행 타이밍)·Quant(리스크 수치) 3관점 중 2관점 이상 BLOCK이면 + consensus_result=NO_BUY를 반환. buy_permission_json.buy_permission_state=ALLOW여도 + NO_BUY 종목 BUY 절대 차단. - # == [2026-05-24_PROPOSAL50] SCRS-V2 - 현금확보 최적 매도조합 ============= + ' + inputs: + - field: ticker + unit: string + - field: df + unit: object - market data feed + - field: paeRow + unit: object - PAE output row + - field: hApex + unit: object - harness apex context + output: + field: ejce_json + schema: + ticker: string + analyst_view: ALLOW | BLOCK + trader_view: ALLOW | BLOCK + quant_view: ALLOW | BLOCK + consensus_result: BUY_ALLOWED | NO_BUY + block_reasons: array of string + formula_id: EXPERT_JUDGMENT_CONSENSUS_ENGINE_V1 + prohibition: + - consensus_result=NO_BUY 종목에 BUY/ADD_ON 권고 금지 + - block_reasons 3관점 미인용 시 INCOMPLETE_EJCE_REPORT + - buy_permission=ALLOW만 확인하고 ejce_json 확인 생략 금지 + canonical_ref: AGENTS.md:Direction EJ1 + version: 2026-05-24_PROPOSAL50 SMART_CASH_RECOVERY_SELL_ENGINE_V2: - purpose: > - 현금부족(cashShortfallInfo) 상황에서 value_damage_score 최소화 조합을 - 결정론적으로 산출. K2 50/50 분할(immediate_sell_qty + rebound_wait_qty) 포함. - LLM이 "이 종목 N주 팔면 될 것 같다"는 즉석 계산 HS011 위반으로 금지. - inputs: - - {field: "holdings", unit: "array"} - - {field: "dfMap", unit: "object"} - - {field: "cashShortfallInfo", unit: "object"} - - {field: "h2", unit: "object - regime layer"} - output: - field: "scrs_v2_json" - schema: - emergency_level: "TRIM_ONLY | FULL_RECOVERY | NO_ACTION" - selected_combo: "array of {ticker, immediate_sell_qty, rebound_wait_qty, value_damage_score, rebound_potential, recommended_action}" - total_recovery_krw: "integer" - formula_id: "SMART_CASH_RECOVERY_SELL_ENGINE_V2" - prohibition: - - "selected_combo 외 추가 매도 LLM 임의 추가 금지" - - "emergency_level=TRIM_ONLY 시 selected_combo 외 추가 매도 절대 금지" - - "immediate_sell_qty + rebound_wait_qty 합산해 '전체 X주 매도' 단순화 금지" - canonical_ref: "AGENTS.md:Direction C3" - version: "2026-05-24_PROPOSAL50" + purpose: '현금부족(cashShortfallInfo) 상황에서 value_damage_score 최소화 조합을 결정론적으로 산출. + K2 50/50 분할(immediate_sell_qty + rebound_wait_qty) 포함. LLM이 "이 종목 N주 팔면 될 + 것 같다"는 즉석 계산 HS011 위반으로 금지. - # == [2026-05-24_PROPOSAL50] MRAG-V2 - 거시 국면 적응 게이트 ============= + ' + inputs: + - field: holdings + unit: array + - field: dfMap + unit: object + - field: cashShortfallInfo + unit: object + - field: h2 + unit: object - regime layer + output: + field: scrs_v2_json + schema: + emergency_level: TRIM_ONLY | FULL_RECOVERY | NO_ACTION + selected_combo: array of {ticker, immediate_sell_qty, rebound_wait_qty, + value_damage_score, rebound_potential, recommended_action} + total_recovery_krw: integer + formula_id: SMART_CASH_RECOVERY_SELL_ENGINE_V2 + prohibition: + - selected_combo 외 추가 매도 LLM 임의 추가 금지 + - emergency_level=TRIM_ONLY 시 selected_combo 외 추가 매도 절대 금지 + - immediate_sell_qty + rebound_wait_qty 합산해 '전체 X주 매도' 단순화 금지 + canonical_ref: AGENTS.md:Direction C3 + version: 2026-05-24_PROPOSAL50 MACRO_REGIME_ADAPTIVE_GATE_V2: - purpose: > - L1(미시)·L2(거시)·L3(글로벌)·L4(이벤트) 4레이어 각 0~25점 합산 - total_mrag_score(0~100) 기반으로 heat_gate_threshold와 - position_size_scale을 결정론적으로 동적 조정. - ME1과 MRAG-V2 중 더 엄격한 값을 effective_heat_gate_threshold로 확정. - inputs: - - {field: "macroJson", unit: "object - macro event data"} - - {field: "mesResult", unit: "object - MACRO_EVENT_SYNCHRONIZER_V1 output"} - - {field: "hApex", unit: "object - harness apex context"} - output: - field: "mrag_v2_json" - schema: - micro_risk_score: "integer 0~25" - macro_risk_score_normalized: "integer 0~25" - global_risk_score: "integer 0~25" - event_risk_score: "integer 0~25" - total_mrag_score: "integer 0~100" - effective_heat_gate_threshold: "number (5|7|10|12) %" - effective_position_size_scale: "number (0.25|0.50|1.00|1.10)" - regime_label: "EXTREME_RISK|HIGH_RISK|MODERATE_RISK|LOW_RISK" - stale_events: "array of {event_name, registered_date, days_stale}" - stale_events_count: "integer" - formula_id: "MACRO_REGIME_ADAPTIVE_GATE_V2" - prohibition: - - "LLM이 total_mrag_score를 즉석 계산 금지 (HS011 위반)" - - "effective_heat_gate_threshold를 LLM이 임의 완화 금지" - - "stale_events_count>0 시 Section_B 이벤트 날짜 불일치 경보 누락 금지" - canonical_ref: "AGENTS.md:Direction ME2" - version: "2026-05-24_PROPOSAL50" + purpose: 'L1(미시)·L2(거시)·L3(글로벌)·L4(이벤트) 4레이어 각 0~25점 합산 total_mrag_score(0~100) + 기반으로 heat_gate_threshold와 position_size_scale을 결정론적으로 동적 조정. ME1과 MRAG-V2 + 중 더 엄격한 값을 effective_heat_gate_threshold로 확정. - # == [2026-05-24_PROPOSAL50] M5 V1.1 - 반도체 집중 비중 강제 감축 ========= + ' + inputs: + - field: macroJson + unit: object - macro event data + - field: mesResult + unit: object - MACRO_EVENT_SYNCHRONIZER_V1 output + - field: hApex + unit: object - harness apex context + output: + field: mrag_v2_json + schema: + micro_risk_score: integer 0~25 + macro_risk_score_normalized: integer 0~25 + global_risk_score: integer 0~25 + event_risk_score: integer 0~25 + total_mrag_score: integer 0~100 + effective_heat_gate_threshold: number (5|7|10|12) % + effective_position_size_scale: number (0.25|0.50|1.00|1.10) + regime_label: EXTREME_RISK|HIGH_RISK|MODERATE_RISK|LOW_RISK + stale_events: array of {event_name, registered_date, days_stale} + stale_events_count: integer + formula_id: MACRO_REGIME_ADAPTIVE_GATE_V2 + prohibition: + - LLM이 total_mrag_score를 즉석 계산 금지 (HS011 위반) + - effective_heat_gate_threshold를 LLM이 임의 완화 금지 + - stale_events_count>0 시 Section_B 이벤트 날짜 불일치 경보 누락 금지 + canonical_ref: AGENTS.md:Direction ME2 + version: 2026-05-24_PROPOSAL50 MANDATORY_REDUCTION_PLAN_V1: - purpose: > - 반도체 클러스터 비중이 cluster_limit * 2.0 초과 시 4주 분할 감축 계획을 - 결정론적으로 생성. RS_BROKEN→ETF→APEX_SUPER 우선순위로 주당 매도수량 배정. - LLM이 "시장 보면서 결정" 임의 유보 금지. - inputs: - - {field: "semiconductorClusterGate", unit: "object - cluster gate result"} - - {field: "holdings", unit: "array"} - - {field: "dfMap", unit: "object"} - - {field: "h3", unit: "object - cash floor layer"} - - {field: "totalAsset", unit: "KRW integer"} - output: - field: "mandatory_reduction_json" - schema: - is_mandatory: "boolean" - current_cluster_pct: "number %" - cluster_limit_pct: "number %" - current_excess_pct: "number %p" - weekly_reduction_target_krw: "integer KRW" - reduction_priority: "array of {ticker, reason, weekly_sell_qty}" - formula_id: "MANDATORY_REDUCTION_PLAN_V1" - prohibition: - - "is_mandatory=true 시 4주 감축 계획 미이행 금지" - - "LLM이 reduction_priority 순서 임의 변경 금지" - - "weekly_reduction_target_krw LLM 재계산 금지 (HS011 위반)" - canonical_ref: "AGENTS.md:Direction A2 (M5 V1.1)" - version: "2026-05-24_PROPOSAL50" + purpose: '반도체 클러스터 비중이 cluster_limit * 2.0 초과 시 4주 분할 감축 계획을 결정론적으로 생성. RS_BROKEN→ETF→APEX_SUPER + 우선순위로 주당 매도수량 배정. LLM이 "시장 보면서 결정" 임의 유보 금지. - # == [2026-05-24_PROPOSAL50] DSLE-V1 - 결정론적 서빙 잠금 ================= + ' + inputs: + - field: semiconductorClusterGate + unit: object - cluster gate result + - field: holdings + unit: array + - field: dfMap + unit: object + - field: h3 + unit: object - cash floor layer + - field: totalAsset + unit: KRW integer + output: + field: mandatory_reduction_json + schema: + is_mandatory: boolean + current_cluster_pct: number % + cluster_limit_pct: number % + current_excess_pct: number %p + weekly_reduction_target_krw: integer KRW + reduction_priority: array of {ticker, reason, weekly_sell_qty} + formula_id: MANDATORY_REDUCTION_PLAN_V1 + prohibition: + - is_mandatory=true 시 4주 감축 계획 미이행 금지 + - LLM이 reduction_priority 순서 임의 변경 금지 + - weekly_reduction_target_krw LLM 재계산 금지 (HS011 위반) + canonical_ref: AGENTS.md:Direction A2 (M5 V1.1) + version: 2026-05-24_PROPOSAL50 DETERMINISTIC_SERVING_LOCK_ENGINE_V1: - purpose: > - 11개 스테이지 토큰 및 numeric_generation_allowed=0을 통해 - LLM이 가격·수량·수익률 등 모든 숫자를 자체 생성하는 것을 완전 차단. - LLM 역할을 NARRATE_HARNESS_OUTPUT·SYNTHESIZE_RISK_CONTEXT·PRESENT_SCENARIO로 한정. + purpose: '11개 스테이지 토큰 및 numeric_generation_allowed=0을 통해 LLM이 가격·수량·수익률 등 모든 + 숫자를 자체 생성하는 것을 완전 차단. LLM 역할을 NARRATE_HARNESS_OUTPUT·SYNTHESIZE_RISK_CONTEXT·PRESENT_SCENARIO로 + 한정. + + ' inputs: - - {field: "hApex", unit: "object - harness apex context"} - - {field: "capturedAtIso", unit: "ISO8601 string"} - - {field: "now", unit: "Date object"} + - field: hApex + unit: object - harness apex context + - field: capturedAtIso + unit: ISO8601 string + - field: now + unit: Date object output: - field: "serving_lock_json" + field: serving_lock_json schema: - lock_status: "LOCKED | UNLOCKED" - llm_role: "CLERK_REPORTER" + lock_status: LOCKED | UNLOCKED + llm_role: CLERK_REPORTER llm_serving_budget: - numeric_generation_allowed: "integer (always 0)" - allowed_operations: "array ['NARRATE_HARNESS_OUTPUT','SYNTHESIZE_RISK_CONTEXT','PRESENT_SCENARIO']" - stage_tokens: "array of 11 token objects" - formula_id: "DETERMINISTIC_SERVING_LOCK_ENGINE_V1" + numeric_generation_allowed: integer (always 0) + allowed_operations: array ['NARRATE_HARNESS_OUTPUT','SYNTHESIZE_RISK_CONTEXT','PRESENT_SCENARIO'] + stage_tokens: array of 11 token objects + formula_id: DETERMINISTIC_SERVING_LOCK_ENGINE_V1 prohibition: - - "numeric_generation_allowed=0 무시하고 LLM 숫자 생성 절대 금지" - - "stage_tokens에 없는 행동 LLM이 권고 금지" - - "serving_lock_json.lock_status=LOCKED 시 LLM 계산 우회 선언 금지" - canonical_ref: "AGENTS.md:Direction D3" - version: "2026-05-24_PROPOSAL50" - - # == [2026-05-24_PROPOSAL50] HS007 - 조건부 접속사 Hard-Lock ============= + - numeric_generation_allowed=0 무시하고 LLM 숫자 생성 절대 금지 + - stage_tokens에 없는 행동 LLM이 권고 금지 + - serving_lock_json.lock_status=LOCKED 시 LLM 계산 우회 선언 금지 + canonical_ref: AGENTS.md:Direction D3 + version: 2026-05-24_PROPOSAL50 VALIDATE_ORDER_CONDITION_V1: - purpose: > - 주문 조건 텍스트에 다중 조건 접속사('또는', '동시 충족', '실패 시' 등)가 - 포함되면 INVALID_MULTI_CONDITION 반환. HTS 자동주문은 단일 지정가만 허용. - inputs: - - {field: "order_condition_text", unit: "string - 주문 조건 텍스트"} - output: - field: "order_condition_validation" - schema: - valid: "boolean" - status: "OK | INVALID_MULTI_CONDITION" - matched_conjunctions: "array of strings" - resolution: "string - 단일 조건 기재 안내" - formula_id: "VALIDATE_ORDER_CONDITION_V1" - prohibition: - - "INVALID_MULTI_CONDITION 판정된 행을 HTS 주문표에 포함 금지" - - "LLM이 복합 조건을 단일 조건으로 재해석하여 통과 처리 금지" - canonical_ref: "AGENTS.md:Direction 0 (HS007)" - version: "2026-05-24_PROPOSAL50" + purpose: '주문 조건 텍스트에 다중 조건 접속사(''또는'', ''동시 충족'', ''실패 시'' 등)가 포함되면 INVALID_MULTI_CONDITION + 반환. HTS 자동주문은 단일 지정가만 허용. - # == [2026-05-24_PROPOSAL50] H10 - 그림자 원장(Shadow Ledger) ============= + ' + inputs: + - field: order_condition_text + unit: string - 주문 조건 텍스트 + output: + field: order_condition_validation + schema: + valid: boolean + status: OK | INVALID_MULTI_CONDITION + matched_conjunctions: array of strings + resolution: string - 단일 조건 기재 안내 + formula_id: VALIDATE_ORDER_CONDITION_V1 + prohibition: + - INVALID_MULTI_CONDITION 판정된 행을 HTS 주문표에 포함 금지 + - LLM이 복합 조건을 단일 조건으로 재해석하여 통과 처리 금지 + canonical_ref: AGENTS.md:Direction 0 (HS007) + version: 2026-05-24_PROPOSAL50 SHADOW_LEDGER_V1: - purpose: > - BLOCKED/INVALID 블루프린트를 HTS 주문표에서 제외하되, 차단 사유 및 - 산출 지표를 투명하게 보존. 사용자의 사후 평가·오버라이드를 지원. + purpose: 'BLOCKED/INVALID 블루프린트를 HTS 주문표에서 제외하되, 차단 사유 및 산출 지표를 투명하게 보존. 사용자의 + 사후 평가·오버라이드를 지원. + + ' inputs: - - {field: "blueprints", unit: "array - order_blueprint_json"} - - {field: "dfMap", unit: "object - 종목별 data feed map"} + - field: blueprints + unit: array - order_blueprint_json + - field: dfMap + unit: object - 종목별 data feed map output: - field: "shadow_ledger_json" + field: shadow_ledger_json schema: - shadow_ledger: "array of blocked entries" - blocked_count: "integer" - formula_id: "SHADOW_LEDGER_V1" + shadow_ledger: array of blocked entries + blocked_count: integer + formula_id: SHADOW_LEDGER_V1 shadow_ledger_row: - ticker: "종목 코드" - name: "종목명" - block_reason: "차단 사유 코드" - order_type: "BUY | SELL | TRIM 등" - limit_price_calc: "산출 지정가 (KRW)" - stop_loss_calc: "산출 손절가 (KRW)" - take_profit_calc: "산출 익절가 (KRW)" - base_qty_calc: "이론 수량 (주)" - override_possible: "true - 사용자 오버라이드 가능" + ticker: 종목 코드 + name: 종목명 + block_reason: 차단 사유 코드 + order_type: BUY | SELL | TRIM 등 + limit_price_calc: 산출 지정가 (KRW) + stop_loss_calc: 산출 손절가 (KRW) + take_profit_calc: 산출 익절가 (KRW) + base_qty_calc: 이론 수량 (주) + override_possible: true - 사용자 오버라이드 가능 prohibition: - - "BLOCKED 종목의 산출 지표를 null 처리하거나 은폐 금지 (HS010 위반)" - - "Shadow Ledger 종목을 HTS 주문표에 포함 금지" - canonical_ref: "AGENTS.md:Direction H10 (HS010_REVISED)" - version: "2026-05-24_PROPOSAL50" - - # == [2026-05-24_PROPOSAL50] D2 - LLM 12가지 금지행동 잠금 ================= + - BLOCKED 종목의 산출 지표를 null 처리하거나 은폐 금지 (HS010 위반) + - Shadow Ledger 종목을 HTS 주문표에 포함 금지 + canonical_ref: AGENTS.md:Direction H10 (HS010_REVISED) + version: 2026-05-24_PROPOSAL50 LLM_SERVING_CONSTRAINT_V1: - purpose: > - LLM의 역할을 하네스 출력 복사·해설·위험 합성으로 엄격히 제한. - 12가지 금지행동 체크리스트를 보고서 조립 직전 GAS가 평가하여 - 위반 가능성이 있으면 INVALID_LLM_OVERRIDE 태그를 반환. - inputs: - - {field: "hApex", unit: "object - harness apex context (전체 하네스 결과)"} - output: - field: "llm_serving_constraint_json" - schema: - constraint_status: "PASS | WARN | INVALID_LLM_OVERRIDE" - violations: "array of {check, rule, status}" - violation_count: "integer" - warn_count: "integer" - total_checks: "12" - formula_id: "LLM_SERVING_CONSTRAINT_V1" - prohibition: - - "constraint_status=INVALID_LLM_OVERRIDE 시 보고서 계속 생성 금지" - - "violations 목록을 LLM이 임의로 해제·무시 금지" - canonical_ref: "AGENTS.md:Direction D2" - version: "2026-05-24_PROPOSAL50" + purpose: 'LLM의 역할을 하네스 출력 복사·해설·위험 합성으로 엄격히 제한. 12가지 금지행동 체크리스트를 보고서 조립 직전 GAS가 + 평가하여 위반 가능성이 있으면 INVALID_LLM_OVERRIDE 태그를 반환. - # == [2026-05-24_PROPOSAL50] H6 - 거래대금 급증 과열신호 ================= + ' + inputs: + - field: hApex + unit: object - harness apex context (전체 하네스 결과) + output: + field: llm_serving_constraint_json + schema: + constraint_status: PASS | WARN | INVALID_LLM_OVERRIDE + violations: array of {check, rule, status} + violation_count: integer + warn_count: integer + total_checks: '12' + formula_id: LLM_SERVING_CONSTRAINT_V1 + prohibition: + - constraint_status=INVALID_LLM_OVERRIDE 시 보고서 계속 생성 금지 + - violations 목록을 LLM이 임의로 해제·무시 금지 + canonical_ref: AGENTS.md:Direction D2 + version: 2026-05-24_PROPOSAL50 AVG_TRADE_VALUE_SIGNAL_V1: - purpose: > - secular_leader(005930·000660) PROFIT_LOCK_STAGE_20 구간에서 - 5일 평균 거래대금 > 20일 평균 × 3.0이면 과열신호 +1 판정. - 4개 과열신호 합산 판정에 반영하여 APEX_SUPER 구간 부분익절 허용 여부를 결정. + purpose: 'secular_leader(005930·000660) PROFIT_LOCK_STAGE_20 구간에서 5일 평균 거래대금 + > 20일 평균 × 3.0이면 과열신호 +1 판정. 4개 과열신호 합산 판정에 반영하여 APEX_SUPER 구간 부분익절 허용 여부를 + 결정. + + ' inputs: - - {field: "ticker", unit: "string"} - - {field: "avg_trade_val_5d", unit: "KRW - 5일 평균 거래대금"} - - {field: "avg_trade_val_20d", unit: "KRW - 20일 평균 거래대금"} - - {field: "profit_lock_stage", unit: "string - PROFIT_LOCK_STAGE_20 여부 확인"} + - field: ticker + unit: string + - field: avg_trade_val_5d + unit: KRW - 5일 평균 거래대금 + - field: avg_trade_val_20d + unit: KRW - 20일 평균 거래대금 + - field: profit_lock_stage + unit: string - PROFIT_LOCK_STAGE_20 여부 확인 expressions: - ratio_5d_vs_20d: "avg_trade_val_5d / avg_trade_val_20d" - overheat_triggered: "ratio_5d_vs_20d >= 3.0" - overheat_score_add: "1 if overheat_triggered else 0" + ratio_5d_vs_20d: avg_trade_val_5d / avg_trade_val_20d + overheat_triggered: ratio_5d_vs_20d >= 3.0 + overheat_score_add: 1 if overheat_triggered else 0 output: - field: "avg_trade_val_signal_json" + field: avg_trade_val_signal_json schema: - ticker: "종목 코드" - applicable: "boolean - secular_leader AND STAGE_20 여부" - signal: "OVERHEAT_TRADE_VALUE | NORMAL | NOT_APPLICABLE" - ratio_5d_vs_20d: "number" - overheat_triggered: "boolean" - overheat_score_add: "0 or 1" - formula_id: "AVG_TRADE_VALUE_SIGNAL_V1" + ticker: 종목 코드 + applicable: boolean - secular_leader AND STAGE_20 여부 + signal: OVERHEAT_TRADE_VALUE | NORMAL | NOT_APPLICABLE + ratio_5d_vs_20d: number + overheat_triggered: boolean + overheat_score_add: 0 or 1 + formula_id: AVG_TRADE_VALUE_SIGNAL_V1 prohibition: - - "LLM이 overheat_signals를 재집계·번복 금지 (하네스 산출값 우선)" - - "secular_leader 이외 종목에 적용 금지" - canonical_ref: "AGENTS.md:Direction H6" - version: "2026-05-24_PROPOSAL50" - - # == [PROPOSAL51] P0-B - 매도 주문 3중 가격 검증 ============================= + - LLM이 overheat_signals를 재집계·번복 금지 (하네스 산출값 우선) + - secular_leader 이외 종목에 적용 금지 + canonical_ref: AGENTS.md:Direction H6 + version: 2026-05-24_PROPOSAL50 SELL_PRICE_SANITY_V2: - purpose: > - buildOrderBlueprint_ 산출 매도/STOP_LOSS 주문에 대해 3조건 가격 역전을 검증. - validation_status를 인라인 재기록하여 EXPORT_GATE가 자동 차단. - LLM이 가격 역전 주문을 HTS에 입력하는 사고를 원천 차단. + purpose: 'buildOrderBlueprint_ 산출 매도/STOP_LOSS 주문에 대해 3조건 가격 역전을 검증. validation_status를 + 인라인 재기록하여 EXPORT_GATE가 자동 차단. LLM이 가격 역전 주문을 HTS에 입력하는 사고를 원천 차단. + + ' inputs: - - {field: "limit_price", unit: "KRW - 지정가"} - - {field: "stop_price", unit: "KRW - 손절가"} - - {field: "auto_trailing_stop", unit: "KRW - profit_preservation 자동 추적 손절가"} + - field: limit_price + unit: KRW - 지정가 + - field: stop_price + unit: KRW - 손절가 + - field: auto_trailing_stop + unit: KRW - profit_preservation 자동 추적 손절가 checks: - CHECK_1: "limit_price < final_stop → INVALID_PRICE_INVERSION" - CHECK_2: "stop_price < auto_trailing_stop → INVALID_TRAILING_STOP_BREACH" - CHECK_3: "limit_price == 0 → INVALID_ZERO_PRICE" + CHECK_1: limit_price < final_stop → INVALID_PRICE_INVERSION + CHECK_2: stop_price < auto_trailing_stop → INVALID_TRAILING_STOP_BREACH + CHECK_3: limit_price == 0 → INVALID_ZERO_PRICE output: - field: "spsv2_verdict" + field: spsv2_verdict values: - SPSV2_PASS: "3조건 모두 통과" - INVALID_PRICE_INVERSION: "지정가 < 최종 손절가 - 역전" - INVALID_TRAILING_STOP_BREACH: "손절가 < auto_trailing_stop - 추적 손절 위반" - INVALID_ZERO_PRICE: "지정가=0 - 미확정 가격" - NOT_SELL_SKIP: "SELL/STOP_LOSS 외 주문 - 검증 스킵" + SPSV2_PASS: 3조건 모두 통과 + INVALID_PRICE_INVERSION: 지정가 < 최종 손절가 - 역전 + INVALID_TRAILING_STOP_BREACH: 손절가 < auto_trailing_stop - 추적 손절 위반 + INVALID_ZERO_PRICE: 지정가=0 - 미확정 가격 + NOT_SELL_SKIP: SELL/STOP_LOSS 외 주문 - 검증 스킵 prohibition: - - "SPSV2 검증 전 Export Gate 실행 금지" - - "INVALID 상태 주문의 HTS 입력 절대 금지" - gs_function: "calcSellPriceSanityV2_" - version: "2026-05-25_PROPOSAL51" - - # == [PROPOSAL51] P1-A - Export Gate V2 ====================================== + - SPSV2 검증 전 Export Gate 실행 금지 + - INVALID 상태 주문의 HTS 입력 절대 금지 + gs_function: calcSellPriceSanityV2_ + version: 2026-05-25_PROPOSAL51 EXPORT_GATE_V2: - purpose: > - EXPORT_READY / REVIEW_ONLY / PENDING_EXPORT 3단계 분류. - V1 5개 체크 → V2 8개 체크 (SCRS 렌더링, 헬스 스코어 타입, 클러스터 동기화 추가). - REVIEW_ONLY: WARN 체크 있음 (HTS 입력 전 검토 필요). hts_entry_allowed=false. + purpose: 'EXPORT_READY / REVIEW_ONLY / PENDING_EXPORT 3단계 분류. V1 5개 체크 → V2 + 8개 체크 (SCRS 렌더링, 헬스 스코어 타입, 클러스터 동기화 추가). REVIEW_ONLY: WARN 체크 있음 (HTS 입력 + 전 검토 필요). hts_entry_allowed=false. + + ' checks: - CHECK_1: "account_snapshot 캡처 완료" - CHECK_2: "데이터 완성도 (buy_permission_json ≥ holdings)" - CHECK_3: "consistency_score >= 70" - CHECK_4: "INVALID 매도 주문 없음 (SPSV2 후)" - CHECK_5: "cash_floor_status != UNKNOWN" - CHECK_6: "SCRS-V2 immediate_sell_qty 유효값 확인" - CHECK_7: "portfolio_health_score 숫자형 확인" - CHECK_8: "SEMICONDUCTOR_CLUSTER_SYNC 정합성 확인" + CHECK_1: account_snapshot 캡처 완료 + CHECK_2: 데이터 완성도 (buy_permission_json ≥ holdings) + CHECK_3: consistency_score >= 70 + CHECK_4: INVALID 매도 주문 없음 (SPSV2 후) + CHECK_5: cash_floor_status != UNKNOWN + CHECK_6: SCRS-V2 immediate_sell_qty 유효값 확인 + CHECK_7: portfolio_health_score 숫자형 확인 + CHECK_8: SEMICONDUCTOR_CLUSTER_SYNC 정합성 확인 tiers: - EXPORT_READY: "모든 체크 PASS - HTS 입력 허용" - REVIEW_ONLY: "WARN 체크 존재, FAIL 없음 - 검토 후 진행" - PENDING_EXPORT: "FAIL 체크 존재 - HTS 입력 금지" - gs_function: "calcExportGate_" - version: "2026-05-25_PROPOSAL51" - - # == [PROPOSAL51] P0-C - 반도체 클러스터 단일 소스 동기화 ===================== + EXPORT_READY: 모든 체크 PASS - HTS 입력 허용 + REVIEW_ONLY: WARN 체크 존재, FAIL 없음 - 검토 후 진행 + PENDING_EXPORT: FAIL 체크 존재 - HTS 입력 금지 + gs_function: calcExportGate_ + version: 2026-05-25_PROPOSAL51 SEMICONDUCTOR_CLUSTER_SYNC_V1: - purpose: > - SEMICONDUCTOR_CLUSTER_GATE_V1 결과 ↔ MANDATORY_REDUCTION_PLAN_V1 is_mandatory 정합성 보장. - combined_pct > cap_pct * 2 → is_mandatory=true 강제. - 단일 소스(클러스터 게이트)가 의무 감축 여부를 결정. + purpose: 'SEMICONDUCTOR_CLUSTER_GATE_V1 결과 ↔ MANDATORY_REDUCTION_PLAN_V1 is_mandatory + 정합성 보장. combined_pct > cap_pct * 2 → is_mandatory=true 강제. 단일 소스(클러스터 게이트)가 + 의무 감축 여부를 결정. + + ' inputs: - - {field: "cluster_pct", unit: "% - mandatory_reduction_json.cluster_pct"} - - {field: "cluster_limit_pct", unit: "% - mandatory_reduction_json.cluster_limit_pct"} - - {field: "is_mandatory", unit: "boolean - 교정 전 값"} - expression: "cluster_pct > cluster_limit_pct * 2 ? is_mandatory=true : is_mandatory=false" + - field: cluster_pct + unit: '% - mandatory_reduction_json.cluster_pct' + - field: cluster_limit_pct + unit: '% - mandatory_reduction_json.cluster_limit_pct' + - field: is_mandatory + unit: boolean - 교정 전 값 + expression: 'cluster_pct > cluster_limit_pct * 2 ? is_mandatory=true : is_mandatory=false' output: - field: "cluster_sync_result_json" + field: cluster_sync_result_json schema: - status: "SYNCED | CORRECTED" - corrected: "boolean" - cluster_pct: "number" - threshold_pct: "cluster_limit_pct * 2" - gs_function: "syncSemiconductorCluster_" - version: "2026-05-25_PROPOSAL51" - - # == [PROPOSAL51] P2-B - 사전 분배 레이더 V2 ================================= + status: SYNCED | CORRECTED + corrected: boolean + cluster_pct: number + threshold_pct: cluster_limit_pct * 2 + gs_function: syncSemiconductorCluster_ + version: 2026-05-25_PROPOSAL51 PROACTIVE_SELL_RADAR_V2: - purpose: > - 8가지 신호로 분배(설거지) 3일 전 조기 감지 → CRITICAL/WARNING/WATCH/CLEAR 분류. - DISTRIBUTION_SELL_DETECTOR V1.1 (사후 확인) 보완 - 사전 예측 기능. + purpose: '8가지 신호로 분배(설거지) 3일 전 조기 감지 → CRITICAL/WARNING/WATCH/CLEAR 분류. DISTRIBUTION_SELL_DETECTOR + V1.1 (사후 확인) 보완 - 사전 예측 기능. + + ' signals: - SIG_1: "고가 2% 이내 + 거래량 30% 수축 (weight=2.0)" - SIG_2: "기관 5일 순매도 전환 (weight=2.0)" - SIG_3: "개인 집중유입 70% 초과 (weight=1.5)" - SIG_4: "풋/콜 비율 1.3 초과 (weight=1.5)" - SIG_5: "뉴스 감성 -20 미만 (weight=1.0)" - SIG_6: "거래량 1.5x 급증 + 음봉 (weight=1.5)" - SIG_7: "RSI 70이상 + 5일 수익률 음수 (weight=1.5)" - SIG_8: "auto_trailing_stop 2% 이내 근접 (weight=2.0)" + SIG_1: 고가 2% 이내 + 거래량 30% 수축 (weight=2.0) + SIG_2: 기관 5일 순매도 전환 (weight=2.0) + SIG_3: 개인 집중유입 70% 초과 (weight=1.5) + SIG_4: 풋/콜 비율 1.3 초과 (weight=1.5) + SIG_5: 뉴스 감성 -20 미만 (weight=1.0) + SIG_6: 거래량 1.5x 급증 + 음봉 (weight=1.5) + SIG_7: RSI 70이상 + 5일 수익률 음수 (weight=1.5) + SIG_8: auto_trailing_stop 2% 이내 근접 (weight=2.0) levels: - CRITICAL: "weighted_sum >= 5.0 - 즉시 매도 검토" - WARNING: "weighted_sum >= 3.0 - 감축 계획 수립" - WATCH: "weighted_sum >= 1.5 - 주의 모니터링" - CLEAR: "weighted_sum < 1.5 - 정상" - gs_function: "calcProactiveSellRadarV2_" - version: "2026-05-25_PROPOSAL51" - - # == [PROPOSAL51] P2-A - 뒷박 차단 게이트 V3 ================================ + CRITICAL: weighted_sum >= 5.0 - 즉시 매도 검토 + WARNING: weighted_sum >= 3.0 - 감축 계획 수립 + WATCH: weighted_sum >= 1.5 - 주의 모니터링 + CLEAR: weighted_sum < 1.5 - 정상 + gs_function: calcProactiveSellRadarV2_ + version: 2026-05-25_PROPOSAL51 ANTI_LATE_ENTRY_GATE_V3: - purpose: > - V2의 3게이트(velocity_1d/velocity_5d/distribution_ws) + GATE_4(PAE) + GATE_5(블랙리스트) → - V3: GATE_6(매크로 레짐) 추가. EVENT_SHOCK/RISK_OFF → 신규 매수 BLOCK. + purpose: 'V2의 3게이트(velocity_1d/velocity_5d/distribution_ws) + GATE_4(PAE) + + GATE_5(블랙리스트) → V3: GATE_6(매크로 레짐) 추가. EVENT_SHOCK/RISK_OFF → 신규 매수 BLOCK. 6게이트 AND 조건: 모두 통과해야 PASS. 하나라도 BLOCK → 전체 BLOCK. + + ' gates: - GATE_1: "velocity_1d >= 3.0% → BLOCK_CHASE" - GATE_2: "velocity_5d >= 8.0% → BLOCK_CHASE_5D" - GATE_3: "dist_weighted_sum >= 3.0 → BLOCK_DISTRIBUTION" - GATE_4: "PAE synthesis_verdict == EXIT/TRIM → BLOCK" - GATE_5: "패턴 블랙리스트 TRIGGERED → BLOCK" - GATE_6: "매크로 EVENT_SHOCK/RISK_OFF → BLOCK" + GATE_1: velocity_1d >= 3.0% → BLOCK_CHASE + GATE_2: velocity_5d >= 8.0% → BLOCK_CHASE_5D + GATE_3: dist_weighted_sum >= 3.0 → BLOCK_DISTRIBUTION + GATE_4: PAE synthesis_verdict == EXIT/TRIM → BLOCK + GATE_5: 패턴 블랙리스트 TRIGGERED → BLOCK + GATE_6: 매크로 EVENT_SHOCK/RISK_OFF → BLOCK quantity_scaling: - GATE_4_WARN: "direction_confidence < -10 → qty_scale=0.5" - GATE_6_WARN: "MACRO_CAUTION → qty_scale=0.7" - gs_function: "applyAlegGate4And5Impl_" - version: "2026-05-25_PROPOSAL51" - - # == [PROPOSAL51] P0-D - 5계층 가격 단일화 잠금 =========================== + GATE_4_WARN: direction_confidence < -10 → qty_scale=0.5 + GATE_6_WARN: MACRO_CAUTION → qty_scale=0.7 + gs_function: applyAlegGate4And5Impl_ + version: 2026-05-25_PROPOSAL51 PRICE_HIERARCHY_LOCK_V1: - purpose: > - 동일 종목의 가격을 5계층으로 분리 잠금. - LAYER_1(주문가)만 HTS 지정가로 사용. LAYER_5(참고방어가)가 LAYER_1 위치에 나타나면 - INVALID_LAYER_VIOLATION - 표간 가격 혼재 완전 차단. - layers: - LAYER_1: "order_blueprint_json.limit_price - HTS 주문표 지정가 전용" - LAYER_2: "prices_json.stop_price / tp1_price / tp2_price - 손절/익절 원장" - LAYER_3: "profit_preservation_json.auto_trailing_stop - LAYER_2 손절가 하한 보정용" - LAYER_4: "scrs_v2_json.rebound_trigger_price - SCRS-V2 반등대기 트리거 전용" - LAYER_5: "proposal_reference.reference_defense_price - WATCH 감시 원장 참고방어가 전용" - violation_types: - INVALID_LAYER_VIOLATION: "LAYER_5==LAYER_1 또는 LAYER_4==LAYER_2" - LAYER_PROXIMITY_WARNING: "LAYER_5와 LAYER_1이 5% 이내 근접" - output_contract: - price_hierarchy_json: "배열: 종목별 5계층 가격 + layer_violations" - gs_function: "applyPriceHierarchyLockAll_" - version: "2026-05-25_PROPOSAL51" + purpose: '동일 종목의 가격을 5계층으로 분리 잠금. LAYER_1(주문가)만 HTS 지정가로 사용. LAYER_5(참고방어가)가 + LAYER_1 위치에 나타나면 INVALID_LAYER_VIOLATION - 표간 가격 혼재 완전 차단. - # == [PROPOSAL51] P1-B - 데이터 완성도 필드충족률 게이트 ================== + ' + layers: + LAYER_1: order_blueprint_json.limit_price - HTS 주문표 지정가 전용 + LAYER_2: prices_json.stop_price / tp1_price / tp2_price - 손절/익절 원장 + LAYER_3: profit_preservation_json.auto_trailing_stop - LAYER_2 손절가 하한 보정용 + LAYER_4: scrs_v2_json.rebound_trigger_price - SCRS-V2 반등대기 트리거 전용 + LAYER_5: proposal_reference.reference_defense_price - WATCH 감시 원장 참고방어가 전용 + violation_types: + INVALID_LAYER_VIOLATION: LAYER_5==LAYER_1 또는 LAYER_4==LAYER_2 + LAYER_PROXIMITY_WARNING: LAYER_5와 LAYER_1이 5% 이내 근접 + output_contract: + price_hierarchy_json: '배열: 종목별 5계층 가격 + layer_violations' + gs_function: applyPriceHierarchyLockAll_ + version: 2026-05-25_PROPOSAL51 DATA_QUALITY_GATE_V2: - purpose: > - 핵심 8개 카테고리(prediction/trade_quality/pattern/stop_loss/cash/sell_engine/cluster/alpha_eval)의 - 필드 충족률로 데이터 완성도 등급 산출. 행수 기준 "정상" 표현 완전 폐기. - T+20=0건, trade_quality=0건 시 특수 경고 발동. + purpose: '핵심 8개 카테고리(prediction/trade_quality/pattern/stop_loss/cash/sell_engine/cluster/alpha_eval)의 + 필드 충족률로 데이터 완성도 등급 산출. 행수 기준 "정상" 표현 완전 폐기. T+20=0건, trade_quality=0건 시 특수 + 경고 발동. + + ' categories: - prediction: "[direction_confidence, synthesis_verdict, thesis_score, antithesis_score]" - trade_quality: "[grade, feedback_tag, t5_return_pct, t20_vs_core_pct]" - pattern: "[pattern_blacklist_status, accumulated_poor_count]" - stop_loss: "[auto_trailing_stop, final_stop_price, stop_price]" - cash: "[settlement_cash_d2_krw, cash_floor_status, cash_shortfall_min_krw]" - sell_engine: "[scrs_v2_verdict, immediate_qty, rebound_wait_qty]" - cluster: "[cluster_state, combined_pct]" - alpha_eval: "[alpha_gate_verdict, prediction_accuracy_rate]" + prediction: '[direction_confidence, synthesis_verdict, thesis_score, antithesis_score]' + trade_quality: '[grade, feedback_tag, t5_return_pct, t20_vs_core_pct]' + pattern: '[pattern_blacklist_status, accumulated_poor_count]' + stop_loss: '[auto_trailing_stop, final_stop_price, stop_price]' + cash: '[settlement_cash_d2_krw, cash_floor_status, cash_shortfall_min_krw]' + sell_engine: '[scrs_v2_verdict, immediate_qty, rebound_wait_qty]' + cluster: '[cluster_state, combined_pct]' + alpha_eval: '[alpha_gate_verdict, prediction_accuracy_rate]' grades: - COMPLETE: "overall_completeness_pct >= 90" - PARTIAL: "overall_completeness_pct >= 60" - INSUFFICIENT: "overall_completeness_pct < 60" + COMPLETE: overall_completeness_pct >= 90 + PARTIAL: overall_completeness_pct >= 60 + INSUFFICIENT: overall_completeness_pct < 60 output_contract: data_quality_gate_v2_json: - fields: "[overall_completeness_pct, completeness_grade, category_scores, special_warnings, confidence_ceiling]" - gs_function: "calcDataQualityGateV2_" - version: "2026-05-25_PROPOSAL51" - - # == [PROPOSAL51] P1-C - 현금회복 금액 3분리 표시 잠금 =================== + fields: '[overall_completeness_pct, completeness_grade, category_scores, + special_warnings, confidence_ceiling]' + gs_function: calcDataQualityGateV2_ + version: 2026-05-25_PROPOSAL51 CASH_RECOVERY_DISPLAY_LOCK_V1: - purpose: > - 현금회복 금액을 min_required / optimal_combo / reference_total 3분리 표시. - trim_plan 누적 전체 금액(예: 207억)을 주문 섹션에 표시하는 것을 완전 차단. - reference_total_krw는 "주문 아님" 레이블 강제. + purpose: '현금회복 금액을 min_required / optimal_combo / reference_total 3분리 표시. trim_plan + 누적 전체 금액(예: 207억)을 주문 섹션에 표시하는 것을 완전 차단. reference_total_krw는 "주문 아님" 레이블 + 강제. + + ' display_rules: - SECTION_CASH_RECOVERY: "min_required_krw + optimal_combo_krw만 표시 (SCRS-V2 즉시매도 합계)" - SECTION_REFERENCE_TRIM: "reference_total_krw - '참고용 전체 후보 누적 - 주문 아님'" + SECTION_CASH_RECOVERY: min_required_krw + optimal_combo_krw만 표시 (SCRS-V2 즉시매도 + 합계) + SECTION_REFERENCE_TRIM: reference_total_krw - '참고용 전체 후보 누적 - 주문 아님' consistency_checks: - UNCOVERED: "optimal_combo < min_required → CASH_SHORTFALL_UNCOVERED" - OVER_SELL: "optimal_combo > min_required*2 → OVER_SELL_WARNING" + UNCOVERED: optimal_combo < min_required → CASH_SHORTFALL_UNCOVERED + OVER_SELL: optimal_combo > min_required*2 → OVER_SELL_WARNING output_contract: cash_recovery_display_json: - fields: "[min_required_krw, optimal_combo_krw, reference_total_krw, coverage_status, display_mode]" - gs_function: "calcCashRecoveryDisplayLock_" - version: "2026-05-25_PROPOSAL51" - + fields: '[min_required_krw, optimal_combo_krw, reference_total_krw, coverage_status, + display_mode]' + gs_function: calcCashRecoveryDisplayLock_ + version: 2026-05-25_PROPOSAL51 FUNDAMENTAL_QUALITY_GATE_V1: - purpose: "펀더멘털 품질 점수화로 BUY 허용을 결정론적으로 잠금." + purpose: 펀더멘털 품질 점수화로 BUY 허용을 결정론적으로 잠금. inputs: - - {field: "holdings", unit: "array"} - - {field: "dfMap", unit: "object"} + - field: holdings + unit: array + - field: dfMap + unit: object output: - field: "fundamental_quality_json" + field: fundamental_quality_json output_contract: fundamental_quality_json: - fields: "[rows[].ticker, rows[].grade, rows[].buy_allowed, rows[].fail_reasons]" - gs_function: "calcFundamentalQualityGateV1_" - version: "2026-05-25_PROPOSAL53" - + fields: '[rows[].ticker, rows[].grade, rows[].buy_allowed, rows[].fail_reasons]' + gs_function: calcFundamentalQualityGateV1_ + version: 2026-05-25_PROPOSAL53 HORIZON_ALLOCATION_LOCK_V1: - purpose: "단기/중기/장기 버킷 비중 상한 위반을 잠금." + purpose: 단기/중기/장기 버킷 비중 상한 위반을 잠금. inputs: - - {field: "holdings", unit: "array"} - - {field: "total_asset_krw", unit: "KRW"} + - field: holdings + unit: array + - field: total_asset_krw + unit: KRW output: - field: "horizon_allocation_json" + field: horizon_allocation_json output_contract: horizon_allocation_json: - fields: "[bucket_summary[].bucket, bucket_summary[].cap_pct, bucket_summary[].current_pct, bucket_summary[].violation]" - gs_function: "calcHorizonAllocationLockV1_" - version: "2026-05-25_PROPOSAL53" - + fields: '[bucket_summary[].bucket, bucket_summary[].cap_pct, bucket_summary[].current_pct, + bucket_summary[].violation]' + gs_function: calcHorizonAllocationLockV1_ + version: 2026-05-25_PROPOSAL53 SMART_MONEY_LIQUIDITY_GATE_V1: - purpose: "스마트머니 흐름과 유동성 결합으로 실행 모드(NORMAL/SELL_SPLIT_ONLY) 고정." + purpose: 스마트머니 흐름과 유동성 결합으로 실행 모드(NORMAL/SELL_SPLIT_ONLY) 고정. inputs: - - {field: "holdings", unit: "array"} - - {field: "proactive_sell_radar_json", unit: "json"} + - field: holdings + unit: array + - field: proactive_sell_radar_json + unit: json output: - field: "smart_money_liquidity_json" + field: smart_money_liquidity_json output_contract: smart_money_liquidity_json: - fields: "[rows[].flow_state, rows[].liquidity_state, rows[].execution_mode, rows[].buy_allowed]" - gs_function: "calcSmartMoneyLiquidityGateV1_" - version: "2026-05-25_PROPOSAL53" - + fields: '[rows[].flow_state, rows[].liquidity_state, rows[].execution_mode, + rows[].buy_allowed]' + gs_function: calcSmartMoneyLiquidityGateV1_ + version: 2026-05-25_PROPOSAL53 ROUTING_SERVING_DECISION_TRACE_V2: - purpose: "라우팅-서빙-게이트 경로를 단일 trace json으로 고정." + purpose: 라우팅-서빙-게이트 경로를 단일 trace json으로 고정. inputs: - - {field: "routing_trace_json", unit: "json"} - - {field: "export_gate_json", unit: "json"} + - field: routing_trace_json + unit: json + - field: export_gate_json + unit: json output: - field: "routing_serving_trace_v2_json" + field: routing_serving_trace_v2_json output_contract: routing_serving_trace_v2_json: - fields: "[request_route, bundle_selected, prompt_entrypoint, gate_path, final_block_reason, json_validation_status]" - gs_function: "buildRoutingServingDecisionTraceV2_" - version: "2026-05-25_PROPOSAL53" - + fields: '[request_route, bundle_selected, prompt_entrypoint, gate_path, + final_block_reason, json_validation_status]' + gs_function: buildRoutingServingDecisionTraceV2_ + version: 2026-05-25_PROPOSAL53 FUNDAMENTAL_MULTI_FACTOR_SCORE_V2: - purpose: "이익률·성장률·점유율·현금흐름·부채 종합 점수로 BUY 잠금." + purpose: 이익률·성장률·점유율·현금흐름·부채 종합 점수로 BUY 잠금. output_contract: fundamental_multifactor_json: - fields: "[rows[].ticker, rows[].score_0_100, rows[].grade, rows[].buy_allowed, rows[].fail_reasons]" - gs_function: "calcFundamentalMultiFactorScoreV2_" - version: "2026-05-25_PROPOSAL54" - + fields: '[rows[].ticker, rows[].score_0_100, rows[].grade, rows[].buy_allowed, + rows[].fail_reasons]' + gs_function: calcFundamentalMultiFactorScoreV2_ + version: 2026-05-25_PROPOSAL54 EARNINGS_GROWTH_QUALITY_GATE_V1: - purpose: "이익 성장 추세 일관성 게이트." + purpose: 이익 성장 추세 일관성 게이트. output_contract: earnings_growth_quality_json: - fields: "[rows[].ticker, rows[].trend, rows[].consistency, rows[].gate]" - gs_function: "calcEarningsGrowthQualityGateV1_" - version: "2026-05-25_PROPOSAL54" - + fields: '[rows[].ticker, rows[].trend, rows[].consistency, rows[].gate]' + gs_function: calcEarningsGrowthQualityGateV1_ + version: 2026-05-25_PROPOSAL54 MARKET_SHARE_MOMENTUM_PROXY_V1: - purpose: "점유율 모멘텀 프록시로 공격 매수 차단." + purpose: 점유율 모멘텀 프록시로 공격 매수 차단. output_contract: market_share_proxy_json: - fields: "[rows[].ticker, rows[].proxy_state, rows[].confidence_band]" - gs_function: "calcMarketShareMomentumProxyV1_" - version: "2026-05-25_PROPOSAL54" - + fields: '[rows[].ticker, rows[].proxy_state, rows[].confidence_band]' + gs_function: calcMarketShareMomentumProxyV1_ + version: 2026-05-25_PROPOSAL54 CASHFLOW_STABILITY_GATE_V1: - purpose: "현금흐름 안정성 + 회계위험 결합 게이트." + purpose: 현금흐름 안정성 + 회계위험 결합 게이트. output_contract: cashflow_stability_json: - fields: "[rows[].ticker, rows[].stability_state, rows[].accrual_risk_flag, rows[].gate]" - gs_function: "calcCashflowStabilityGateV1_" - version: "2026-05-25_PROPOSAL54" - + fields: '[rows[].ticker, rows[].stability_state, rows[].accrual_risk_flag, + rows[].gate]' + gs_function: calcCashflowStabilityGateV1_ + version: 2026-05-25_PROPOSAL54 ROUTING_DECISION_EXPLAIN_LOCK_V1: - purpose: "최종 의사결정 게이트 경로/차단사유 잠금." + purpose: 최종 의사결정 게이트 경로/차단사유 잠금. output_contract: routing_decision_explain_json: - fields: "[gate_path, blocked_by, override_allowed]" - gs_function: "calcRoutingDecisionExplainLockV1_" - version: "2026-05-25_PROPOSAL54" - - # === Phase-4~5 신규 하네스 게이트 매핑 (2026-05-28) ======================= - + fields: '[gate_path, blocked_by, override_allowed]' + gs_function: calcRoutingDecisionExplainLockV1_ + version: 2026-05-25_PROPOSAL54 TRADE_QUALITY_FROM_T5_V1: - purpose: > - 운영 T+5 실측 기반 거래품질 점수. T+20 성숙 전 bridge. - gate=PASS: scored_count >= 30. + purpose: '운영 T+5 실측 기반 거래품질 점수. T+20 성숙 전 bridge. gate=PASS: scored_count >= + 30. + + ' output_contract: Temp/trade_quality_from_t5_v1.json: - fields: "[gate, summary_score, scored_count, trade_quality_basis, per_ticker[]]" - python_tool: "tools/build_trade_quality_from_t5_v1.py" - harness_check: "CHECK_74_TRADE_QUALITY_FROM_T5_V1" - version: "2026-05-28_PHASE4" - + fields: '[gate, summary_score, scored_count, trade_quality_basis, per_ticker[]]' + python_tool: tools/build_trade_quality_from_t5_v1.py + harness_check: CHECK_74_TRADE_QUALITY_FROM_T5_V1 + version: 2026-05-28_PHASE4 PREDICTION_ACCURACY_HARNESS_V2: - purpose: > - 운영 T+1/T+5/T+20 일치율 회전 윈도 + calibration_state. - calibration_state가 BUY_PROPOSAL_FROZEN_RECOMMEND이면 매수 동결 권고. + purpose: '운영 T+1/T+5/T+20 일치율 회전 윈도 + calibration_state. calibration_state가 + BUY_PROPOSAL_FROZEN_RECOMMEND이면 매수 동결 권고. + + ' output_contract: Temp/prediction_accuracy_harness_v2.json: - fields: "[calibration_state, t1_op_rate, t5_op_rate, t20_op_rate, windows.*]" - python_tool: "tools/build_prediction_accuracy_harness_v2.py" - harness_check: "CHECK_75_PREDICTION_ACCURACY_HARNESS_V2" - version: "2026-05-28_PHASE4" - + fields: '[calibration_state, t1_op_rate, t5_op_rate, t20_op_rate, windows.*]' + python_tool: tools/build_prediction_accuracy_harness_v2.py + harness_check: CHECK_75_PREDICTION_ACCURACY_HARNESS_V2 + version: 2026-05-28_PHASE4 MACRO_EVENT_TICKER_IMPACT_V1: - purpose: > - 거시이벤트 종목별 영향. action_gate=AVOID_NEW_BUY: 사전 5영업일 매수 차단 권고. - 뒷박 5중 AND 게이트의 macro_event 1표. + purpose: '거시이벤트 종목별 영향. action_gate=AVOID_NEW_BUY: 사전 5영업일 매수 차단 권고. 뒷박 5중 AND + 게이트의 macro_event 1표. + + ' output_contract: Temp/macro_event_ticker_impact_v1.json: - fields: "[gate, ticker_count, action_summary, tickers[].primary_gate, tickers[].impact_score]" - python_tool: "tools/build_macro_event_ticker_impact_v1.py" - harness_check: "CHECK_76_MACRO_EVENT_TICKER_IMPACT_V1" - version: "2026-05-28_PHASE4" - + fields: '[gate, ticker_count, action_summary, tickers[].primary_gate, tickers[].impact_score]' + python_tool: tools/build_macro_event_ticker_impact_v1.py + harness_check: CHECK_76_MACRO_EVENT_TICKER_IMPACT_V1 + version: 2026-05-28_PHASE4 SELL_WATERFALL_ENGINE_V2: - purpose: > - V1 4단계 + 슬리피지/exec_mode/에스컬레이션. - escalation_skip_violations=0 필수. + purpose: 'V1 4단계 + 슬리피지/exec_mode/에스컬레이션. escalation_skip_violations=0 필수. + + ' output_contract: Temp/sell_waterfall_engine_v2.json: - fields: "[gate, rows[].stage, rows[].exec_mode, rows[].split_count, rows[].est_slippage_bps, rows[].escalation_rule]" - python_tool: "tools/build_sell_waterfall_engine_v2.py" - harness_check: "CHECK_77_SELL_WATERFALL_ENGINE_V2" - version: "2026-05-28_PHASE4" - + fields: '[gate, rows[].stage, rows[].exec_mode, rows[].split_count, rows[].est_slippage_bps, + rows[].escalation_rule]' + python_tool: tools/build_sell_waterfall_engine_v2.py + harness_check: CHECK_77_SELL_WATERFALL_ENGINE_V2 + version: 2026-05-28_PHASE4 LLM_NARRATIVE_TEMPLATE_LOCK_V1: - purpose: > - 서술 금지어휘(같다/약간/곧 등) 스캔. total_violations=0 필수. - gate=PASS: narrative 결정론 잠금. + purpose: '서술 금지어휘(같다/약간/곧 등) 스캔. total_violations=0 필수. gate=PASS: narrative + 결정론 잠금. + + ' output_contract: Temp/llm_narrative_template_lock_v1.json: - fields: "[gate, total_violations, sections_checked, section_results[]]" - python_tool: "tools/build_llm_narrative_template_lock_v1.py" - harness_check: "CHECK_78_LLM_NARRATIVE_TEMPLATE_LOCK_V1" - version: "2026-05-28_PHASE5" - + fields: '[gate, total_violations, sections_checked, section_results[]]' + python_tool: tools/build_llm_narrative_template_lock_v1.py + harness_check: CHECK_78_LLM_NARRATIVE_TEMPLATE_LOCK_V1 + version: 2026-05-28_PHASE5 EJCE_DIVERGENCE_AUDIT_V1: - purpose: > - EJCE 3관점 합의 진정성. homogeneous_flag=true 또는 unique_reason_pct<60%이면 경고. - gate=WARN은 soft(hard-fail 아님). + purpose: 'EJCE 3관점 합의 진정성. homogeneous_flag=true 또는 unique_reason_pct<60%이면 + 경고. gate=WARN은 soft(hard-fail 아님). + + ' output_contract: Temp/ejce_divergence_audit_v1.json: - fields: "[gate, unique_reason_pct, homogeneous_flag, analyst_view_homogeneous, ticker_results[]]" - python_tool: "tools/build_ejce_divergence_audit_v1.py" - harness_check: "CHECK_79_EJCE_DIVERGENCE_AUDIT_V1" - version: "2026-05-28_PHASE5" - + fields: '[gate, unique_reason_pct, homogeneous_flag, analyst_view_homogeneous, + ticker_results[]]' + python_tool: tools/build_ejce_divergence_audit_v1.py + harness_check: CHECK_79_EJCE_DIVERGENCE_AUDIT_V1 + version: 2026-05-28_PHASE5 PREDICTIVE_ALPHA_REPORT_LOCK_V2: - purpose: > - PA1 정반합 표 강제. coverage_pct >= 80% 필요(ETF 제외 시 90.9% 달성). - weight_source=DYNAMIC 컬럼 의무. + purpose: 'PA1 정반합 표 강제. coverage_pct >= 80% 필요(ETF 제외 시 90.9% 달성). weight_source=DYNAMIC + 컬럼 의무. + + ' output_contract: Temp/predictive_alpha_report_lock_v2.json: - fields: "[gate, coverage_pct, pa1_report_table[].thesis_signals, pa1_report_table[].antithesis_signals, pa1_report_table[].synthesis_score]" - python_tool: "tools/build_predictive_alpha_report_lock_v2.py" - harness_check: "CHECK_80_PREDICTIVE_ALPHA_REPORT_LOCK_V2" - version: "2026-05-28_PHASE5" - + fields: '[gate, coverage_pct, pa1_report_table[].thesis_signals, pa1_report_table[].antithesis_signals, + pa1_report_table[].synthesis_score]' + python_tool: tools/build_predictive_alpha_report_lock_v2.py + harness_check: CHECK_80_PREDICTIVE_ALPHA_REPORT_LOCK_V2 + version: 2026-05-28_PHASE5 CANONICAL_METRICS_V1: - purpose: > - 단일 진실원천 아키텍처. 논리 지표를 정규 원천에서 산출해 렌더러 중복 읽기 버그 차단. - gate=PASS(unresolved=0) / gate=WARN(unresolved>0). + purpose: '단일 진실원천 아키텍처. 논리 지표를 정규 원천에서 산출해 렌더러 중복 읽기 버그 차단. gate=PASS(unresolved=0) + / gate=WARN(unresolved>0). + + ' output_contract: Temp/canonical_metrics_v1.json: - fields: "[gate, metrics.cluster_pct, metrics.cash_min_required_krw, metrics.cash_reference_total_krw, per_ticker.*, resolved_count, unresolved]" - python_tool: "tools/build_canonical_metrics_v1.py" - harness_check: "CHECK_89_CANONICAL_METRICS_RESOLVED" - version: "2026-05-29_PHASE7" - + fields: '[gate, metrics.cluster_pct, metrics.cash_min_required_krw, metrics.cash_reference_total_krw, + per_ticker.*, resolved_count, unresolved]' + python_tool: tools/build_canonical_metrics_v1.py + harness_check: CHECK_89_CANONICAL_METRICS_RESOLVED + version: 2026-05-29_PHASE7 CROSS_SECTION_CONSISTENCY_V1: - purpose: > - 교차섹션 정합성 게이트. canonical 지표가 여러 섹션에서 동일하게 렌더됐는지 검증. - enforcement_mode_until 이전 WARN, 이후 FAIL. score=100 목표. + purpose: '교차섹션 정합성 게이트. canonical 지표가 여러 섹션에서 동일하게 렌더됐는지 검증. enforcement_mode_until + 이전 WARN, 이후 FAIL. score=100 목표. + + ' output_contract: Temp/cross_section_consistency_v1.json: - fields: "[gate, score, conflict_count, conflicts[], forbidden_uniform_labels, incomplete_tables, enforcement_mode_until]" - python_tool: "tools/build_cross_section_consistency_v1.py" - harness_check: "CHECK_90_CROSS_SECTION_CONSISTENCY" - version: "2026-05-29_PHASE7" - + fields: '[gate, score, conflict_count, conflicts[], forbidden_uniform_labels, + incomplete_tables, enforcement_mode_until]' + python_tool: tools/build_cross_section_consistency_v1.py + harness_check: CHECK_90_CROSS_SECTION_CONSISTENCY + version: 2026-05-29_PHASE7 ALPHA_FEEDBACK_LOOP_V2: - purpose: > - T5 운영 데이터 기반 PA1 팩터 가중치 조정 권고 생성. - 기존 V1(T20 전용)을 확장해 T5≥10건으로 즉시 동작. + purpose: 'T5 운영 데이터 기반 PA1 팩터 가중치 조정 권고 생성. 기존 V1(T20 전용)을 확장해 T5≥10건으로 즉시 동작. AFL 원칙: 권고만 출력, 자동 적용 금지. + + ' output_contract: Temp/alpha_feedback_loop_v2.json: - fields: "[status, cases_analyzed, active_signal_rate_pct, passive_signal_rate_pct, pa1_current_ratio, recommended_adjustments[]]" - python_tool: "tools/build_alpha_feedback_loop_v2.py" - version: "2026-05-30_Work7" - + fields: '[status, cases_analyzed, active_signal_rate_pct, passive_signal_rate_pct, + pa1_current_ratio, recommended_adjustments[]]' + python_tool: tools/build_alpha_feedback_loop_v2.py + version: 2026-05-30_Work7 DYNAMIC_VALUE_PRESERVATION_SELL_V6: - purpose: > - 단순 맹목적 매도(V5) 폐기. 최신 알고리즘 매도 기법(VWAP/TWAP 기반 지지선 연동) 도입. - 현금 확보 시 종목의 Rebound_Elasticity_Score (반등 탄력 점수)를 계산하여 RSI < 30 및 이격도 과대 종목은 - 절대 즉시 매도 금지(EXECUTE_REBOUND_ONLY 강제). 호가창(Tick) 유동성을 고려한 - Dynamic Limit Price = Close + (ATR20 * 0.2) 산출하여 값 고정. LLM의 주관 개입 0% 통제. + purpose: '단순 맹목적 매도(V5) 폐기. 최신 알고리즘 매도 기법(VWAP/TWAP 기반 지지선 연동) 도입. 현금 확보 시 종목의 + Rebound_Elasticity_Score (반등 탄력 점수)를 계산하여 RSI < 30 및 이격도 과대 종목은 절대 즉시 매도 금지(EXECUTE_REBOUND_ONLY + 강제). 호가창(Tick) 유동성을 고려한 Dynamic Limit Price = Close + (ATR20 * 0.2) 산출하여 값 + 고정. LLM의 주관 개입 0% 통제. + + ' inputs: [] output: - field: "dynamic_value_preservation_sell_v6_json" + field: dynamic_value_preservation_sell_v6_json output_contract: Temp/dynamic_value_preservation_sell_v6.json: - fields: "[formula_id, status, execution_allowed, selected_sell_combo, cash_recovered_krw, value_damage_pct_avg]" - python_tool: "tools/build_dynamic_value_preservation_sell_v6.py" - version: "2026-05-31_Advanced1" - + fields: '[formula_id, status, execution_allowed, selected_sell_combo, cash_recovered_krw, + value_damage_pct_avg]' + python_tool: tools/build_dynamic_value_preservation_sell_v6.py + version: 2026-05-31_Advanced1 PREDICTIVE_ALPHA_DIALECTIC_ENGINE_V2: - purpose: > - 단순 정반합 강세/약세 합산 탈피. 거시 경제(Macro) 국면에 따라 팩터 가중치 동적 변환(Regime-Switching). - 국면이 RISK_OFF일 때 펀더멘털 점수 무시, 유동성(Liquidity) 및 스마트머니 점수 가중치 2.5배 상향. - 반환된 synthesis_verdict가 BEARISH이면 어떠한 예외 없이 ALLOW_EXECUTION = FALSE 하드락 적용. + purpose: '단순 정반합 강세/약세 합산 탈피. 거시 경제(Macro) 국면에 따라 팩터 가중치 동적 변환(Regime-Switching). + 국면이 RISK_OFF일 때 펀더멘털 점수 무시, 유동성(Liquidity) 및 스마트머니 점수 가중치 2.5배 상향. 반환된 synthesis_verdict가 + BEARISH이면 어떠한 예외 없이 ALLOW_EXECUTION = FALSE 하드락 적용. + + ' inputs: [] output: - field: "predictive_alpha_engine_v2_json" + field: predictive_alpha_engine_v2_json output_contract: Temp/predictive_alpha_engine_v2.json: - fields: "[formula_id, rows, gate, numeric_generation_allowed]" - python_tool: "tools/build_predictive_alpha_dialectic_engine_v2.py" - version: "2026-05-31_Advanced2" - + fields: '[formula_id, rows, gate, numeric_generation_allowed]' + python_tool: tools/build_predictive_alpha_dialectic_engine_v2.py + version: 2026-05-31_Advanced2 CAPITAL_STYLE_TIME_STOP_V1: - purpose: > - 투자 방법(단타/스윙/중장기) 결정론적 분리 및 진입 시점부터 타이머 작동. - SCALP(단타)로 진입한 종목이 T+3일 내 목표가(TP) 미도달 시 수익률 무관 무조건 TIME_STOP_EXIT 발송. - LLM 변명 불가, "타임스탑 청산" 단답형 출력 강제. + purpose: '투자 방법(단타/스윙/중장기) 결정론적 분리 및 진입 시점부터 타이머 작동. SCALP(단타)로 진입한 종목이 T+3일 + 내 목표가(TP) 미도달 시 수익률 무관 무조건 TIME_STOP_EXIT 발송. LLM 변명 불가, "타임스탑 청산" 단답형 출력 + 강제. + + ' inputs: [] output: - field: "capital_style_time_stop_v1_json" + field: capital_style_time_stop_v1_json output_contract: Temp/capital_style_time_stop_v1.json: - fields: "[formula_id, rows, gate]" - python_tool: "tools/build_capital_style_time_stop_v1.py" - version: "2026-05-31_Advanced3" - + fields: '[formula_id, rows, gate]' + python_tool: tools/build_capital_style_time_stop_v1.py + version: 2026-05-31_Advanced3 EXECUTION_INTEGRITY_GATE_V1: - purpose: > - 결정론적 직렬화 라우팅 통합 게이트. 파편화된 게이트들을 단일 파이프라인으로 통합하여 - 단 하나의 조건이라도 실패 시 전체 JSON 출력을 null 처리 및 PENDING_EXPORT 상태로 Lock. - LLM 예측 원천 차단. + purpose: '결정론적 직렬화 라우팅 통합 게이트. 파편화된 게이트들을 단일 파이프라인으로 통합하여 단 하나의 조건이라도 실패 시 전체 + JSON 출력을 null 처리 및 PENDING_EXPORT 상태로 Lock. LLM 예측 원천 차단. + + ' inputs: [] output: - field: "execution_integrity_gate_v1_json" + field: execution_integrity_gate_v1_json output_contract: Temp/execution_integrity_gate_v1.json: - fields: "[formula_id, status, failed_checks]" - python_tool: "tools/build_execution_integrity_gate_v1.py" - version: "2026-05-31_Advanced4" - + fields: '[formula_id, status, failed_checks]' + python_tool: tools/build_execution_integrity_gate_v1.py + version: 2026-05-31_Advanced4 IMPUTED_DATA_EXPOSURE_GATE_V1: - purpose: > - 실질 입력(펀더멘털 핵심 팩터 ROE/OPM/OCF/FCF, T+20 실현성과, 거래품질·패턴·알파평가)의 - 대체(imputed)·합성·PENDING 정도를 결정론적으로 측정하여, confidence_cap_basis가 - 대체데이터를 가리고 있는지(정직성 결함) 폭로하는 감사 게이트. - 시스템 자체 신뢰도 캡 공식(raw × (0.4 + 0.6 × coverage))을 재사용하되, 분모를 - schema_presence 기반 investment_quality(98.65 등)가 아니라 "실질 데이터 커버리지"로 - 교체하여 effective_confidence_honest를 산출한다. - 대체데이터 감지 시 long_horizon_allowed / fundamental_claim_allowed 를 false로 강제하여 - AGENTS.md "펀더멘털 결측 시 장기투자 추천 금지" 규칙을 결정론으로 집행한다. - ENGINE_AUDIT_V1 감사 산출물 전용이며 GAS 런타임·HTS 주문 판단에는 개입하지 않는다. + purpose: '실질 입력(펀더멘털 핵심 팩터 ROE/OPM/OCF/FCF, T+20 실현성과, 거래품질·패턴·알파평가)의 대체(imputed)·합성·PENDING + 정도를 결정론적으로 측정하여, confidence_cap_basis가 대체데이터를 가리고 있는지(정직성 결함) 폭로하는 감사 게이트. + 시스템 자체 신뢰도 캡 공식(raw × (0.4 + 0.6 × coverage))을 재사용하되, 분모를 schema_presence + 기반 investment_quality(98.65 등)가 아니라 "실질 데이터 커버리지"로 교체하여 effective_confidence_honest를 + 산출한다. 대체데이터 감지 시 long_horizon_allowed / fundamental_claim_allowed 를 false로 + 강제하여 AGENTS.md "펀더멘털 결측 시 장기투자 추천 금지" 규칙을 결정론으로 집행한다. ENGINE_AUDIT_V1 감사 산출물 + 전용이며 GAS 런타임·HTS 주문 판단에는 개입하지 않는다. + + ' inputs: [] formula: - weighted_coverage: "Σ(domain_weight_d × coverage_d) # 도메인: fundamental_core(0.30), realized_outcome(0.30), trade_quality(0.15), pattern(0.10), alpha_eval(0.15)" - imputed_field_ratio: "1 − weighted_coverage" - effective_confidence_honest: "raw_confidence_cap_basis × (0.4 + 0.6 × weighted_coverage)" - gate_status: "imputed_field_ratio ≥ 0.50 → IMPUTED_DATA_BLOCK / ≥ 0.25 → IMPUTED_DATA_WARN / else PASS" - long_horizon_allowed: "t20_sample > 0 AND fundamental_core_factor_coverage ≥ 0.50" - fundamental_claim_allowed: "fundamental_core_factor_coverage ≥ 0.50" + weighted_coverage: 'Σ(domain_weight_d × coverage_d) # 도메인: fundamental_core(0.30), + realized_outcome(0.30), trade_quality(0.15), pattern(0.10), alpha_eval(0.15)' + imputed_field_ratio: 1 − weighted_coverage + effective_confidence_honest: raw_confidence_cap_basis × (0.4 + 0.6 × weighted_coverage) + gate_status: imputed_field_ratio ≥ 0.50 → IMPUTED_DATA_BLOCK / ≥ 0.25 → IMPUTED_DATA_WARN + / else PASS + long_horizon_allowed: t20_sample > 0 AND fundamental_core_factor_coverage + ≥ 0.50 + fundamental_claim_allowed: fundamental_core_factor_coverage ≥ 0.50 output: - field: "imputed_data_exposure" + field: imputed_data_exposure output_contract: Temp/engine_audit_v1.json: - fields: "[imputed_data_exposure{gate_status, imputed_field_ratio, weighted_coverage, domain_coverage, fundamental_core_factor_coverage, surrogate_outcome_ratio, effective_confidence_honest, confidence_cap_inflation_gap, long_horizon_allowed, fundamental_claim_allowed, report_render_skew, exposure_reasons}]" + fields: '[imputed_data_exposure{gate_status, imputed_field_ratio, weighted_coverage, + domain_coverage, fundamental_core_factor_coverage, surrogate_outcome_ratio, + effective_confidence_honest, confidence_cap_inflation_gap, long_horizon_allowed, + fundamental_claim_allowed, report_render_skew, exposure_reasons}]' prohibition: - - "LLM이 gate_status / effective_confidence_honest 를 재계산하거나 완화하는 것 금지" - - "fundamental_claim_allowed=false 인데 장기·펀더멘털 우위를 단정하는 서술 금지" - python_tool: "tools/build_engine_audit_v1.py" - validator_tool: "tools/validate_engine_audit_v1.py" - canonical_ref: "ENGINE_AUDIT_V1 / spec/28_imputed_data_exposure_contract.yaml" - version: "2026-05-31_ENGINE_AUDIT_V1" - - # == 파이프라인 orphan 공식 일괄 등록 (orphan reconciliation 2026-06-03) ====== - + - LLM이 gate_status / effective_confidence_honest 를 재계산하거나 완화하는 것 금지 + - fundamental_claim_allowed=false 인데 장기·펀더멘털 우위를 단정하는 서술 금지 + python_tool: tools/build_engine_audit_v1.py + validator_tool: tools/validate_engine_audit_v1.py + canonical_ref: ENGINE_AUDIT_V1 / spec/28_imputed_data_exposure_contract.yaml + version: 2026-05-31_ENGINE_AUDIT_V1 ANTI_LATE_ENTRY_PULLBACK_GATE_V4: - purpose: > - 뒷박/설거지 진입 차단 게이트 V4. velocity·분배신호 복합 조건으로 진입 차단. - input_fields: [velocity_1d, velocity_5d, distribution_score] - expected_outputs: [anti_late_entry_gate, chase_risk_score] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '뒷박/설거지 진입 차단 게이트 V4. velocity·분배신호 복합 조건으로 진입 차단. + ' + input_fields: + - velocity_1d + - velocity_5d + - distribution_score + expected_outputs: + - anti_late_entry_gate + - chase_risk_score + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE ARCHITECTURE_BOUNDARIES_V2: - purpose: > - 하네스 컴포넌트 간 의존성·권한 경계를 정의하고 위반을 감지한다. - input_fields: [component_list, dependency_map] - expected_outputs: [boundary_violations, architecture_gate] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '하네스 컴포넌트 간 의존성·권한 경계를 정의하고 위반을 감지한다. + ' + input_fields: + - component_list + - dependency_map + expected_outputs: + - boundary_violations + - architecture_gate + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE CONFIDENCE_CALIBRATION_V2: - purpose: > - T+5/T+20 실적 기반 신뢰도 캘리브레이션 v2. 과신·과소신뢰 구간을 보정한다. - input_fields: [predicted_confidence, actual_outcome, sample_count] - expected_outputs: [calibrated_confidence, calibration_state] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: 'T+5/T+20 실적 기반 신뢰도 캘리브레이션 v2. 과신·과소신뢰 구간을 보정한다. + ' + input_fields: + - predicted_confidence + - actual_outcome + - sample_count + expected_outputs: + - calibrated_confidence + - calibration_state + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE DATA_QUALITY_RECONCILIATION_V1: - purpose: > - 섹션 간 동일 의미 수치의 불일치를 탐지해 데이터 품질 조정 보고서를 산출한다. - input_fields: [section_values, field_map] - expected_outputs: [reconciliation_status, mismatch_fields] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '섹션 간 동일 의미 수치의 불일치를 탐지해 데이터 품질 조정 보고서를 산출한다. + ' + input_fields: + - section_values + - field_map + expected_outputs: + - reconciliation_status + - mismatch_fields + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE DECISION_EVIDENCE_SCORE_V1: - purpose: > - 의사결정 근거의 출처 추적 가능성과 검증 가능성을 점수화한다. - input_fields: [decision_fields, source_paths, formula_ids] - expected_outputs: [decision_evidence_score_v1] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '의사결정 근거의 출처 추적 가능성과 검증 가능성을 점수화한다. + ' + input_fields: + - decision_fields + - source_paths + - formula_ids + expected_outputs: + - decision_evidence_score_v1 + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE DECISION_EVIDENCE_SCORE_V2: - purpose: > - DECISION_EVIDENCE_SCORE_V1 개선판. 비결정론 경로 탐지 추가. - input_fields: [decision_fields, source_paths, formula_ids] - expected_outputs: [decision_evidence_score_v2, non_deterministic_paths] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: 'DECISION_EVIDENCE_SCORE_V1 개선판. 비결정론 경로 탐지 추가. + ' + input_fields: + - decision_fields + - source_paths + - formula_ids + expected_outputs: + - decision_evidence_score_v2 + - non_deterministic_paths + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE DECISION_REPLAY_SNAPSHOT_PACK_V1: - purpose: > - 의사결정 시점 스냅샷 패키지를 생성해 재현·감사를 지원한다. - input_fields: [decision_date, harness_context_snapshot] - expected_outputs: [replay_snapshot_pack, snapshot_hash] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '의사결정 시점 스냅샷 패키지를 생성해 재현·감사를 지원한다. + ' + input_fields: + - decision_date + - harness_context_snapshot + expected_outputs: + - replay_snapshot_pack + - snapshot_hash + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE DERIVATION_VALIDITY_SCORE_V1: - purpose: > - order_blueprint 파생경로 커버리지와 결정론성을 종합해 파생유효성 점수를 산출한다. - input_fields: [harness_coverage_audit, order_blueprint_json] - expected_outputs: [derivation_validity_score, derivation_validity_grade, derivation_validity_gate] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: 'order_blueprint 파생경로 커버리지와 결정론성을 종합해 파생유효성 점수를 산출한다. + ' + input_fields: + - harness_coverage_audit + - order_blueprint_json + expected_outputs: + - derivation_validity_score + - derivation_validity_grade + - derivation_validity_gate + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE DFG_V1: - purpose: > - 데이터 흐름 그래프 V1. 하네스 파이프라인 의존성 방향그래프를 산출한다. - input_fields: [tool_list, dependency_map] - expected_outputs: [dfg_nodes, dfg_edges, cycle_detected] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '데이터 흐름 그래프 V1. 하네스 파이프라인 의존성 방향그래프를 산출한다. + ' + input_fields: + - tool_list + - dependency_map + expected_outputs: + - dfg_nodes + - dfg_edges + - cycle_detected + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE DISTRIBUTION_EXIT_PRESIGNAL_V2: - purpose: > - 분배 국면 선행 신호를 감지해 사전 매도 권고 신호를 산출한다. - input_fields: [flow_credit, volume_trend, price_structure] - expected_outputs: [distribution_presignal, exit_urgency_level] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '분배 국면 선행 신호를 감지해 사전 매도 권고 신호를 산출한다. + ' + input_fields: + - flow_credit + - volume_trend + - price_structure + expected_outputs: + - distribution_presignal + - exit_urgency_level + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE DYNAMIC_VALUE_PRESERVATION_SELL_V3_BRIDGE: - purpose: > - V3 가치보존 매도와 최신 엔진 간 호환성 브리지. 하위호환 경로 유지. - input_fields: [sell_plan_v3, current_engine_context] - expected_outputs: [bridged_sell_plan] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: 'V3 가치보존 매도와 최신 엔진 간 호환성 브리지. 하위호환 경로 유지. + ' + input_fields: + - sell_plan_v3 + - current_engine_context + expected_outputs: + - bridged_sell_plan + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE EVALUATION_HISTORY_COVERAGE_V1: - purpose: > - 종목별·기간별 평가 이력 커버리지를 집계한다. - input_fields: [evaluation_log, date_range] - expected_outputs: [history_coverage_pct, coverage_by_ticker] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '종목별·기간별 평가 이력 커버리지를 집계한다. + ' + input_fields: + - evaluation_log + - date_range + expected_outputs: + - history_coverage_pct + - coverage_by_ticker + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE EXECUTION_AUTHORITY_MATRIX_V1: - purpose: > - 게이트별 실행 권한 매트릭스를 산출해 HTS 주문 권한을 결정론적으로 고착화한다. - input_fields: [gate_states, execution_mode] - expected_outputs: [execution_authority_matrix, authorized_actions] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '게이트별 실행 권한 매트릭스를 산출해 HTS 주문 권한을 결정론적으로 고착화한다. + ' + input_fields: + - gate_states + - execution_mode + expected_outputs: + - execution_authority_matrix + - authorized_actions + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE EXECUTION_QUALITY_HARNESS_V1: - purpose: > - 매수·매도 실행품질(슬리피지·체결률·타이밍)을 측정해 품질 점수를 산출한다. - input_fields: [executed_orders, benchmark_prices] - expected_outputs: [execution_quality_score, slippage_pct] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '매수·매도 실행품질(슬리피지·체결률·타이밍)을 측정해 품질 점수를 산출한다. + ' + input_fields: + - executed_orders + - benchmark_prices + expected_outputs: + - execution_quality_score + - slippage_pct + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE EXECUTION_READINESS_MATRIX_V1: - purpose: > - HTS 주문 실행 준비 상태를 100% 기준으로 점검하는 매트릭스를 산출한다. - input_fields: [gate_states, sample_counts, data_completeness] - expected_outputs: [execution_readiness_matrix, readiness_gate] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: 'HTS 주문 실행 준비 상태를 100% 기준으로 점검하는 매트릭스를 산출한다. + ' + input_fields: + - gate_states + - sample_counts + - data_completeness + expected_outputs: + - execution_readiness_matrix + - readiness_gate + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE FINAL_CONTEXT_FOR_LLM_V2: - purpose: > - LLM에 전달할 최종 컨텍스트 패키지 V2. numeric_generation_allowed=0 강제. - input_fields: [harness_context, operational_report] - expected_outputs: [final_context_for_llm, llm_serving_budget] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: 'LLM에 전달할 최종 컨텍스트 패키지 V2. numeric_generation_allowed=0 강제. + ' + input_fields: + - harness_context + - operational_report + expected_outputs: + - final_context_for_llm + - llm_serving_budget + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE FINAL_DECISION_PACKET_V1: - purpose: > - 하네스 최종 산출 패키지. 모든 게이트·주문·성과 요약을 단일 JSON으로 통합한다. - input_fields: [all_gate_outputs, order_blueprint, operational_report] - expected_outputs: [final_decision_packet, input_hash, execution_mode] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '하네스 최종 산출 패키지. 모든 게이트·주문·성과 요약을 단일 JSON으로 통합한다. + ' + input_fields: + - all_gate_outputs + - order_blueprint + - operational_report + expected_outputs: + - final_decision_packet + - input_hash + - execution_mode + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE FINAL_EXECUTION_DECISION_V1: - purpose: > - 최종 실행 의사결정 V1. HTS 주문표 생성 여부와 실행 모드를 결정한다. - input_fields: [gate_states, global_execution_gate] - expected_outputs: [final_execution_decision, execution_mode] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '최종 실행 의사결정 V1. HTS 주문표 생성 여부와 실행 모드를 결정한다. + ' + input_fields: + - gate_states + - global_execution_gate + expected_outputs: + - final_execution_decision + - execution_mode + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE FINAL_EXECUTION_DECISION_V2: - purpose: > - 최종 실행 의사결정 V2. V1 + shadow_ledger 강제 생성 추가. - input_fields: [gate_states, global_execution_gate, shadow_ledger_data] - expected_outputs: [final_execution_decision_v2, shadow_ledger] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '최종 실행 의사결정 V2. V1 + shadow_ledger 강제 생성 추가. + ' + input_fields: + - gate_states + - global_execution_gate + - shadow_ledger_data + expected_outputs: + - final_execution_decision_v2 + - shadow_ledger + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE FORMULA_IMPLEMENTATION_REGISTRY_V1: - purpose: > - 공식별 GAS/Python 구현 상태를 추적하는 구현 레지스트리를 산출한다. - input_fields: [formula_ids, implementation_map] - expected_outputs: [implementation_registry, unimplemented_list] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '공식별 GAS/Python 구현 상태를 추적하는 구현 레지스트리를 산출한다. + ' + input_fields: + - formula_ids + - implementation_map + expected_outputs: + - implementation_registry + - unimplemented_list + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE FORMULA_REGISTRY_SYNC_V1: - purpose: > - GAS·Python·YAML 간 공식 레지스트리 동기화 상태를 검증한다. - input_fields: [gas_formulas, py_formulas, yaml_formulas] - expected_outputs: [sync_status, out_of_sync_formulas] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: 'GAS·Python·YAML 간 공식 레지스트리 동기화 상태를 검증한다. + ' + input_fields: + - gas_formulas + - py_formulas + - yaml_formulas + expected_outputs: + - sync_status + - out_of_sync_formulas + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE HARNESS_CONTEXT_VALIDATOR_V2: - purpose: > - 하네스 컨텍스트 전체의 형식·타입·필수 필드 유효성을 검증한다 (V2). - input_fields: [harness_context] - expected_outputs: [validation_result, missing_fields, type_errors] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '하네스 컨텍스트 전체의 형식·타입·필수 필드 유효성을 검증한다 (V2). + ' + input_fields: + - harness_context + expected_outputs: + - validation_result + - missing_fields + - type_errors + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE HORIZON_ALLOCATION_GUARD_V2: - purpose: > - 투자성향별 목표 보유기간 초과 여부를 감지해 TIME_STOP 플래그를 산출한다 (V2). - input_fields: [entry_date, current_date, target_horizon_days] - expected_outputs: [time_stop_flag, days_over_horizon] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '투자성향별 목표 보유기간 초과 여부를 감지해 TIME_STOP 플래그를 산출한다 (V2). + ' + input_fields: + - entry_date + - current_date + - target_horizon_days + expected_outputs: + - time_stop_flag + - days_over_horizon + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE HORIZON_REBALANCE_PLAN_V1: - purpose: > - 성향별 목표 비중 달성을 위한 리밸런싱 실행 계획을 산출한다. - input_fields: [current_allocation, target_allocation, rebalance_threshold] - expected_outputs: [rebalance_plan, rebalance_trades] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '성향별 목표 비중 달성을 위한 리밸런싱 실행 계획을 산출한다. + ' + input_fields: + - current_allocation + - target_allocation + - rebalance_threshold + expected_outputs: + - rebalance_plan + - rebalance_trades + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE HORIZON_ROUTING_LOCK_V6: - purpose: > - 진입 국면·성향·트랜치를 결합해 매수 라우팅을 결정론적으로 고착화한다 (V6). - input_fields: [market_regime, capital_style, tranche_phase, gate_states] - expected_outputs: [buy_route, routing_reason_codes] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '진입 국면·성향·트랜치를 결합해 매수 라우팅을 결정론적으로 고착화한다 (V6). + ' + input_fields: + - market_regime + - capital_style + - tranche_phase + - gate_states + expected_outputs: + - buy_route + - routing_reason_codes + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE IMPUTED_DATA_EXPOSURE_GATE_V2: - purpose: > - 대체(imputed) 데이터 비율을 측정해 신뢰도 과장 위험을 차단하는 게이트 V2. - input_fields: [domain_coverage, imputed_fields] - expected_outputs: [imputed_gate_v2, effective_confidence_honest] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '대체(imputed) 데이터 비율을 측정해 신뢰도 과장 위험을 차단하는 게이트 V2. + ' + input_fields: + - domain_coverage + - imputed_fields + expected_outputs: + - imputed_gate_v2 + - effective_confidence_honest + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE INDEX_RELATIVE_HEALTH_GATE_V1: - purpose: > - 종목의 KOSPI 대비 상대강도와 건전성을 측정해 인덱스 대비 게이트를 산출한다. - input_fields: [ticker_return, kospi_return, relative_strength] - expected_outputs: [index_relative_health_gate, underperformance_pct] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '종목의 KOSPI 대비 상대강도와 건전성을 측정해 인덱스 대비 게이트를 산출한다. + ' + input_fields: + - ticker_return + - kospi_return + - relative_strength + expected_outputs: + - index_relative_health_gate + - underperformance_pct + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE INTRADAY_V1: - purpose: > - 장중 데이터 제약(Intraday Restriction)을 적용해 장중 액션 매트릭스를 산출한다. - input_fields: [capture_time, market_close_time, data_type] - expected_outputs: [intraday_restriction_gate, allowed_actions] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '장중 데이터 제약(Intraday Restriction)을 적용해 장중 액션 매트릭스를 산출한다. + ' + input_fields: + - capture_time + - market_close_time + - data_type + expected_outputs: + - intraday_restriction_gate + - allowed_actions + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE LATE_CHASE_ATTRIBUTION_V1: - purpose: > - 뒷박 진입군 vs 정상 진입군의 T+5/T+20 승률 차이를 정량 측정한다. - input_fields: [trade_ledger, entry_velocity_threshold] - expected_outputs: [late_vs_normal_winrate_gap_pp, attribution_sample_count] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '뒷박 진입군 vs 정상 진입군의 T+5/T+20 승률 차이를 정량 측정한다. + ' + input_fields: + - trade_ledger + - entry_velocity_threshold + expected_outputs: + - late_vs_normal_winrate_gap_pp + - attribution_sample_count + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE LATE_REBOUND_BUCKET_SCORE_V1: - purpose: > - 반등 대기 분할매도의 실제 반등 수익 회수율을 측정해 지연 반등 버킷 점수를 산출한다. - input_fields: [rebound_wait_trades, trigger_prices, actual_sell_prices] - expected_outputs: [late_rebound_bucket_score, rebound_capture_rate] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '반등 대기 분할매도의 실제 반등 수익 회수율을 측정해 지연 반등 버킷 점수를 산출한다. + ' + input_fields: + - rebound_wait_trades + - trigger_prices + - actual_sell_prices + expected_outputs: + - late_rebound_bucket_score + - rebound_capture_rate + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE LLM_SERVING: - purpose: > - LLM 서빙 예산과 허용 범위를 정의한다. numeric_generation_allowed 포함. - input_fields: [serving_mode, allowed_operations] - expected_outputs: [llm_serving_budget, numeric_generation_allowed] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: 'LLM 서빙 예산과 허용 범위를 정의한다. numeric_generation_allowed 포함. + ' + input_fields: + - serving_mode + - allowed_operations + expected_outputs: + - llm_serving_budget + - numeric_generation_allowed + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE MACRO_REGIME_ALIGNMENT_GATE_V2: - purpose: > - 거시 국면과 포트폴리오 전략 정렬 여부를 측정해 국면 정합 게이트 V2를 산출한다. - input_fields: [market_regime, strategy_regime_assumption] - expected_outputs: [macro_regime_alignment_gate, alignment_score] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '거시 국면과 포트폴리오 전략 정렬 여부를 측정해 국면 정합 게이트 V2를 산출한다. + ' + input_fields: + - market_regime + - strategy_regime_assumption + expected_outputs: + - macro_regime_alignment_gate + - alignment_score + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE OPERATIONAL_ALPHA_CALIBRATION_V2: - purpose: > - 실운용 alpha_lead 예측의 T+5/T+20 적중률을 측정해 알파 캘리브레이션 상태를 산출한다. - input_fields: [alpha_predictions, actual_outcomes, sample_count] - expected_outputs: [alpha_calibration_state, t20_pass_rate] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '실운용 alpha_lead 예측의 T+5/T+20 적중률을 측정해 알파 캘리브레이션 상태를 산출한다. + ' + input_fields: + - alpha_predictions + - actual_outcomes + - sample_count + expected_outputs: + - alpha_calibration_state + - t20_pass_rate + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE OPERATIONAL_EVAL_QUEUE_V1: - purpose: > - T+20 평가 대기열을 관리해 평가 완료·미완료 건수를 추적한다. - input_fields: [trade_log, evaluation_date] - expected_outputs: [eval_queue, pending_count, completed_count] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: 'T+20 평가 대기열을 관리해 평가 완료·미완료 건수를 추적한다. + ' + input_fields: + - trade_log + - evaluation_date + expected_outputs: + - eval_queue + - pending_count + - completed_count + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE OPERATIONAL_EVIDENCE_AUDIT_V1: - purpose: > - 실운용 의사결정의 증거 추적 가능성을 감사한다. - input_fields: [decision_log, evidence_map] - expected_outputs: [evidence_audit_result, orphan_decisions] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '실운용 의사결정의 증거 추적 가능성을 감사한다. + ' + input_fields: + - decision_log + - evidence_map + expected_outputs: + - evidence_audit_result + - orphan_decisions + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE OPERATIONAL_OUTCOME_LOCK_V1: - purpose: > - 실운용 T+5/T+20 결과를 잠금 처리해 소급 수정을 방지한다. - input_fields: [outcome_ledger, lock_date] - expected_outputs: [locked_outcomes, lock_status] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '실운용 T+5/T+20 결과를 잠금 처리해 소급 수정을 방지한다. + ' + input_fields: + - outcome_ledger + - lock_date + expected_outputs: + - locked_outcomes + - lock_status + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE OPERATIONAL_T20_OUTCOME_LEDGER_V1: - purpose: > - 실운용 T+20 거래결과 원장. 실측 30건 이상 시 operational_t20로 인정한다. - input_fields: [trade_log, t20_prices, evaluation_date] - expected_outputs: [operational_t20_ledger, evaluated_count, pass_rate_pct] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '실운용 T+20 거래결과 원장. 실측 30건 이상 시 operational_t20로 인정한다. + ' + input_fields: + - trade_log + - t20_prices + - evaluation_date + expected_outputs: + - operational_t20_ledger + - evaluated_count + - pass_rate_pct + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE OPERATIONAL_TRUTH_SCORE_V1: - purpose: > - 실운용 결과 기반 진실성 점수. type_A/type_B 100%를 분리 측정한다. - input_fields: [operational_metrics, sample_counts] - expected_outputs: [operational_truth_score, true_100_axes, pending_axes] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '실운용 결과 기반 진실성 점수. type_A/type_B 100%를 분리 측정한다. + ' + input_fields: + - operational_metrics + - sample_counts + expected_outputs: + - operational_truth_score + - true_100_axes + - pending_axes + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE ORDER_MATH_RECONCILIATION_V1: - purpose: > - 주문 수량·금액 계산의 정합성(round-trip 검증)을 감사한다. - input_fields: [order_blueprint, portfolio_state] - expected_outputs: [math_reconciliation_result, calculation_errors] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '주문 수량·금액 계산의 정합성(round-trip 검증)을 감사한다. + ' + input_fields: + - order_blueprint + - portfolio_state + expected_outputs: + - math_reconciliation_result + - calculation_errors + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE OUTCOME_QUALITY_SCORE_V1: - purpose: > - T+5/T+20 실측 성과를 종합해 성과품질 점수를 산출한다. - input_fields: [t5_outcomes, t20_outcomes, sample_counts] - expected_outputs: [outcome_quality_score_v1, outcome_quality_gate] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: 'T+5/T+20 실측 성과를 종합해 성과품질 점수를 산출한다. + ' + input_fields: + - t5_outcomes + - t20_outcomes + - sample_counts + expected_outputs: + - outcome_quality_score_v1 + - outcome_quality_gate + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE PASS_100_CRITERIA_V1: - purpose: > - pass_100 기준 V1. 전체 게이트·점수 100% 충족 기준을 정의한다. - input_fields: [gate_states, metric_scores] - expected_outputs: [pass_100_score, failed_criteria] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: 'pass_100 기준 V1. 전체 게이트·점수 100% 충족 기준을 정의한다. + ' + input_fields: + - gate_states + - metric_scores + expected_outputs: + - pass_100_score + - failed_criteria + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE PERFORMANCE_MONITORING_DASHBOARD_V1: - purpose: > - T+5/T+20 성과 모니터링 대시보드. 주간 자동 갱신. - input_fields: [trade_outcomes, monitoring_period] - expected_outputs: [performance_dashboard, weekly_scorecard] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: 'T+5/T+20 성과 모니터링 대시보드. 주간 자동 갱신. + ' + input_fields: + - trade_outcomes + - monitoring_period + expected_outputs: + - performance_dashboard + - weekly_scorecard + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE PERFORMANCE_READINESS_REPLAY_BRIDGE_V1: - purpose: > - replay 백필 데이터를 operational_t20 판단에 연결하는 성과준비도 브리지. - input_fields: [replay_ledger, operational_threshold] - expected_outputs: [performance_readiness_score, readiness_gate] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: 'replay 백필 데이터를 operational_t20 판단에 연결하는 성과준비도 브리지. + ' + input_fields: + - replay_ledger + - operational_threshold + expected_outputs: + - performance_readiness_score + - readiness_gate + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE PERF_RECOVERY_HARNESS_V1: - purpose: > - 성과 하락 감지 시 자동 포지션 스케일 인하와 회복 계획을 산출한다. - input_fields: [recent_performance, degradation_threshold] - expected_outputs: [recovery_plan, scale_down_factor] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '성과 하락 감지 시 자동 포지션 스케일 인하와 회복 계획을 산출한다. + ' + input_fields: + - recent_performance + - degradation_threshold + expected_outputs: + - recovery_plan + - scale_down_factor + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE PERF_RECOVERY_OVERRIDES_V1: - purpose: > - 성과 회복 기간 중 허용 오버라이드 목록과 조건을 정의한다. - input_fields: [recovery_state, override_requests] - expected_outputs: [allowed_overrides, blocked_overrides] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '성과 회복 기간 중 허용 오버라이드 목록과 조건을 정의한다. + ' + input_fields: + - recovery_state + - override_requests + expected_outputs: + - allowed_overrides + - blocked_overrides + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE PHASE_CHECKS_50_60_V1: - purpose: > - 단계별 50%·60% 체크포인트에서 중간 평가를 수행한다. - input_fields: [completion_pct, phase_thresholds] - expected_outputs: [phase_check_result, checkpoint_flags] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '단계별 50%·60% 체크포인트에서 중간 평가를 수행한다. + ' + input_fields: + - completion_pct + - phase_thresholds + expected_outputs: + - phase_check_result + - checkpoint_flags + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE PIPELINE_RUNTIME_ANOMALY_CHECK_V1: - purpose: > - 파이프라인 실행 중 이상 징후(지연·오류·이상값)를 탐지한다. - input_fields: [runtime_profile, anomaly_thresholds] - expected_outputs: [anomaly_flags, anomaly_severity] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '파이프라인 실행 중 이상 징후(지연·오류·이상값)를 탐지한다. + ' + input_fields: + - runtime_profile + - anomaly_thresholds + expected_outputs: + - anomaly_flags + - anomaly_severity + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE PIPELINE_RUNTIME_CONTRACT_VALIDATOR_V1: - purpose: > - 파이프라인 실행 결과가 계약 명세를 준수하는지 검증한다. - input_fields: [pipeline_outputs, contract_spec] - expected_outputs: [contract_validation_result, violations] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '파이프라인 실행 결과가 계약 명세를 준수하는지 검증한다. + ' + input_fields: + - pipeline_outputs + - contract_spec + expected_outputs: + - contract_validation_result + - violations + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE PIPELINE_RUNTIME_PROFILE_SUMMARY_V1: - purpose: > - 파이프라인 실행 시간·메모리·산출물 수를 요약한다. - input_fields: [runtime_profile] - expected_outputs: [runtime_summary, bottleneck_steps] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '파이프라인 실행 시간·메모리·산출물 수를 요약한다. + ' + input_fields: + - runtime_profile + expected_outputs: + - runtime_summary + - bottleneck_steps + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE PIPELINE_RUNTIME_PROFILE_V1: - purpose: > - 파이프라인 전체 실행 프로파일을 생성한다. - input_fields: [execution_log] - expected_outputs: [runtime_profile, step_durations] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '파이프라인 전체 실행 프로파일을 생성한다. + ' + input_fields: + - execution_log + expected_outputs: + - runtime_profile + - step_durations + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE PORTFOLIO_HEALTH_V1: - purpose: > - 포트폴리오 건전성 점수와 레이블(HEALTHY/CAUTION/CRITICAL)을 산출한다. - input_fields: [gate_states, heat_pct, drawdown_pct] - expected_outputs: [portfolio_health_score, portfolio_health_label] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '포트폴리오 건전성 점수와 레이블(HEALTHY/CAUTION/CRITICAL)을 산출한다. + ' + input_fields: + - gate_states + - heat_pct + - drawdown_pct + expected_outputs: + - portfolio_health_score + - portfolio_health_label + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE PREDICTIVE_ALPHA_DIALECTIC_ENGINE_V1_BRIDGE: - purpose: > - 정반합 예측 엔진 V1과 V2 간 호환성 브리지. - input_fields: [v1_output, v2_context] - expected_outputs: [bridged_prediction, bridge_status] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '정반합 예측 엔진 V1과 V2 간 호환성 브리지. + ' + input_fields: + - v1_output + - v2_context + expected_outputs: + - bridged_prediction + - bridge_status + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE REALIZED_PERFORMANCE_V1: - purpose: > - 실현 손익·승률·기대수익을 집계한다. - input_fields: [closed_trades, evaluation_period] - expected_outputs: [realized_pnl, win_rate, expectancy] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '실현 손익·승률·기대수익을 집계한다. + ' + input_fields: + - closed_trades + - evaluation_period + expected_outputs: + - realized_pnl + - win_rate + - expectancy + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE REBOUND_SELL_EFFICIENCY_V1: - purpose: > - 반등 대기 분할매도의 효율성(반등 포착율)을 측정한다. - input_fields: [rebound_wait_qty, rebound_captured_qty, expected_gain] - expected_outputs: [rebound_sell_efficiency_score, efficiency_gate] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '반등 대기 분할매도의 효율성(반등 포착율)을 측정한다. + ' + input_fields: + - rebound_wait_qty + - rebound_captured_qty + - expected_gain + expected_outputs: + - rebound_sell_efficiency_score + - efficiency_gate + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE REPORT_AUTHORITY_DIFF_V1: - purpose: > - 보고서 버전 간 권한 차이를 탐지해 미인가 변경을 감지한다. - input_fields: [report_v_prev, report_v_curr, authority_map] - expected_outputs: [authority_diff, unauthorized_changes] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '보고서 버전 간 권한 차이를 탐지해 미인가 변경을 감지한다. + ' + input_fields: + - report_v_prev + - report_v_curr + - authority_map + expected_outputs: + - authority_diff + - unauthorized_changes + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE REQUEST_RESULT_ADOPTION_V1: - purpose: > - 사용자 요청 결과의 채택 여부와 적용 경로를 추적한다. - input_fields: [request_log, adoption_status] - expected_outputs: [adoption_rate, pending_requests] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '사용자 요청 결과의 채택 여부와 적용 경로를 추적한다. + ' + input_fields: + - request_log + - adoption_status + expected_outputs: + - adoption_rate + - pending_requests + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE ROOT_CAUSE_ATTRIBUTION_V1: - purpose: > - 성과 저하·게이트 실패의 근본 원인을 추적하고 귀인 분석을 수행한다. - input_fields: [failure_events, causal_graph] - expected_outputs: [root_causes, attribution_confidence] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '성과 저하·게이트 실패의 근본 원인을 추적하고 귀인 분석을 수행한다. + ' + input_fields: + - failure_events + - causal_graph + expected_outputs: + - root_causes + - attribution_confidence + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE ROOT_CAUSE_RECOVERY_PLAN_V1: - purpose: > - 근본 원인 분석 결과를 기반으로 회복 계획을 산출한다. - input_fields: [root_causes, available_actions] - expected_outputs: [recovery_plan, estimated_recovery_time] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '근본 원인 분석 결과를 기반으로 회복 계획을 산출한다. + ' + input_fields: + - root_causes + - available_actions + expected_outputs: + - recovery_plan + - estimated_recovery_time + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE RS_V2_FUSION: - purpose: > - 상대강도 V2 신호를 다른 기술적 신호와 융합한 복합 신호를 산출한다. - input_fields: [rs_v2_score, tech_signals] - expected_outputs: [rs_fusion_score, fusion_gate] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '상대강도 V2 신호를 다른 기술적 신호와 융합한 복합 신호를 산출한다. + ' + input_fields: + - rs_v2_score + - tech_signals + expected_outputs: + - rs_fusion_score + - fusion_gate + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE SATELLITE_CANDIDATE_SCREEN_V1: - purpose: > - 위성 종목 후보군을 기술·펀더멘털·수급 기준으로 스크리닝한다. - input_fields: [universe, screening_criteria] - expected_outputs: [satellite_candidates, screen_scores] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '위성 종목 후보군을 기술·펀더멘털·수급 기준으로 스크리닝한다. + ' + input_fields: + - universe + - screening_criteria + expected_outputs: + - satellite_candidates + - screen_scores + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE SCORES_HARNESS_V1: - purpose: > - 모든 하네스 점수(quality/proof/evidence)를 단일 구조로 통합·검증한다. - input_fields: [all_score_outputs] - expected_outputs: [scores_harness, score_consistency_check] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '모든 하네스 점수(quality/proof/evidence)를 단일 구조로 통합·검증한다. + ' + input_fields: + - all_score_outputs + expected_outputs: + - scores_harness + - score_consistency_check + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE SELL_ENGINE_AUDIT_V1: - purpose: > - 매도 엔진 산출값의 결정론성·수량·가격 유효성을 감사한다. - input_fields: [sell_engine_output, order_blueprint] - expected_outputs: [sell_engine_audit_result, audit_gate] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '매도 엔진 산출값의 결정론성·수량·가격 유효성을 감사한다. + ' + input_fields: + - sell_engine_output + - order_blueprint + expected_outputs: + - sell_engine_audit_result + - audit_gate + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE SELL_EXECUTION_QUALITY_GATE_V1: - purpose: > - 매도 실행 품질이 슬리피지·체결률 기준을 충족하는지 검증한다. - input_fields: [executed_sells, quality_thresholds] - expected_outputs: [sell_execution_quality_gate, quality_score] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '매도 실행 품질이 슬리피지·체결률 기준을 충족하는지 검증한다. + ' + input_fields: + - executed_sells + - quality_thresholds + expected_outputs: + - sell_execution_quality_gate + - quality_score + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE SELL_EXECUTION_TIMING_LOCK_V2: - purpose: > - 매도 실행 타이밍을 과매도 구간·반등대기·긴급전량 조건에 따라 고착화한다 (V2). - input_fields: [sell_timing_signals, emergency_condition] - expected_outputs: [sell_timing_lock, execution_window] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '매도 실행 타이밍을 과매도 구간·반등대기·긴급전량 조건에 따라 고착화한다 (V2). + ' + input_fields: + - sell_timing_signals + - emergency_condition + expected_outputs: + - sell_timing_lock + - execution_window + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE SEMANTIC_FORMULA_COVERAGE_HARNESS_V1: - purpose: > - 공식의 의미적 커버리지(입력·출력·성과 바인딩)를 측정한다. - input_fields: [formula_ids, semantic_bindings] - expected_outputs: [semantic_coverage_score, uncovered_formulas] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '공식의 의미적 커버리지(입력·출력·성과 바인딩)를 측정한다. + ' + input_fields: + - formula_ids + - semantic_bindings + expected_outputs: + - semantic_coverage_score + - uncovered_formulas + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE SHORT_HORIZON_OUTCOME_MONITOR_V1: - purpose: > - 단타·단기 포지션의 T+1/T+3/T+5 성과를 실시간 모니터링한다. - input_fields: [short_horizon_trades, monitoring_prices] - expected_outputs: [short_horizon_outcomes, early_exit_signals] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '단타·단기 포지션의 T+1/T+3/T+5 성과를 실시간 모니터링한다. + ' + input_fields: + - short_horizon_trades + - monitoring_prices + expected_outputs: + - short_horizon_outcomes + - early_exit_signals + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE SMART_CASH_RECOVERY_V4: - purpose: > - 스마트 현금회복 V4. K2 분할·TRIM 우선순위·반등대기 통합. - input_fields: [portfolio_state, cash_shortfall_krw, sell_priority] - expected_outputs: [smart_cash_recovery_plan_v4, expected_recovery_krw] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '스마트 현금회복 V4. K2 분할·TRIM 우선순위·반등대기 통합. + ' + input_fields: + - portfolio_state + - cash_shortfall_krw + - sell_priority + expected_outputs: + - smart_cash_recovery_plan_v4 + - expected_recovery_krw + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE SMART_CASH_RECOVERY_V7: - purpose: > - 스마트 현금회복 V7. V6 + 반도체 클러스터 게이트·베타 조정 통합. - input_fields: [portfolio_state, cash_shortfall_krw, regime_context] - expected_outputs: [smart_cash_recovery_plan_v7, expected_recovery_krw] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '스마트 현금회복 V7. V6 + 반도체 클러스터 게이트·베타 조정 통합. + ' + input_fields: + - portfolio_state + - cash_shortfall_krw + - regime_context + expected_outputs: + - smart_cash_recovery_plan_v7 + - expected_recovery_krw + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE STOP_BREACH_V1: - purpose: > - 손절가 이탈 여부를 판정해 BREACH_IMMEDIATE_EXIT 플래그를 산출한다. - input_fields: [current_price, stop_loss_price, gap_threshold] - expected_outputs: [stop_breach_gate, gap_pct] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '손절가 이탈 여부를 판정해 BREACH_IMMEDIATE_EXIT 플래그를 산출한다. + ' + input_fields: + - current_price + - stop_loss_price + - gap_threshold + expected_outputs: + - stop_breach_gate + - gap_pct + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE STRATEGY_DECISION_RESULT_V3: - purpose: > - 전략 의사결정 결과 V3를 구조화해 final_decision_packet에 통합한다. - input_fields: [buy_decisions, sell_decisions, hold_decisions] - expected_outputs: [strategy_decision_result_v3, decision_summary] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '전략 의사결정 결과 V3를 구조화해 final_decision_packet에 통합한다. + ' + input_fields: + - buy_decisions + - sell_decisions + - hold_decisions + expected_outputs: + - strategy_decision_result_v3 + - decision_summary + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE STRATEGY_EXECUTION_LOCKS_REGRESSION_V1: - purpose: > - 전략 실행 잠금 규칙의 회귀 테스트를 수행한다. - input_fields: [lock_rules, test_cases] - expected_outputs: [regression_result, failed_locks] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '전략 실행 잠금 규칙의 회귀 테스트를 수행한다. + ' + input_fields: + - lock_rules + - test_cases + expected_outputs: + - regression_result + - failed_locks + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE STRATEGY_EXECUTION_LOCKS_V1: - purpose: > - 전략 실행 잠금 규칙 V1. 게이트별 액션 허용/차단 매트릭스. - input_fields: [gate_states, action_requests] - expected_outputs: [execution_locks, blocked_actions] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '전략 실행 잠금 규칙 V1. 게이트별 액션 허용/차단 매트릭스. + ' + input_fields: + - gate_states + - action_requests + expected_outputs: + - execution_locks + - blocked_actions + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE STRATEGY_HARDENING_HARNESS_V1: - purpose: > - 전략 경화 검증 하네스 V1. 규칙 준수·일관성·완전성을 측정한다. - input_fields: [strategy_outputs, hardening_spec] - expected_outputs: [hardening_score, hardening_gate] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '전략 경화 검증 하네스 V1. 규칙 준수·일관성·완전성을 측정한다. + ' + input_fields: + - strategy_outputs + - hardening_spec + expected_outputs: + - hardening_score + - hardening_gate + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE STRATEGY_HARDENING_HARNESS_V2: - purpose: > - 전략 경화 검증 하네스 V2. V1 + LLM 의존도 추가 측정. - input_fields: [strategy_outputs, hardening_spec, llm_fields] - expected_outputs: [hardening_score_v2, llm_dependency_ratio] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '전략 경화 검증 하네스 V2. V1 + LLM 의존도 추가 측정. + ' + input_fields: + - strategy_outputs + - hardening_spec + - llm_fields + expected_outputs: + - hardening_score_v2 + - llm_dependency_ratio + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE STRATEGY_ROUTING_AUDIT_V1: - purpose: > - 전략 라우팅 경로의 결정론성과 권한을 감사한다. - input_fields: [routing_decisions, authority_matrix] - expected_outputs: [routing_audit_result, unauthorized_routes] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '전략 라우팅 경로의 결정론성과 권한을 감사한다. + ' + input_fields: + - routing_decisions + - authority_matrix + expected_outputs: + - routing_audit_result + - unauthorized_routes + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE TICK_NORM_V1: - purpose: > - TICK_NORMALIZER_V1의 별칭 식별자. 동일 로직의 코드 내 단축 참조. - input_fields: [price, tick_table] - expected_outputs: [normalized_price] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: 'TICK_NORMALIZER_V1의 별칭 식별자. 동일 로직의 코드 내 단축 참조. + ' + input_fields: + - price + - tick_table + expected_outputs: + - normalized_price + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE TRUTHFULNESS_GUARD_V1: - purpose: > - 거짓 100% 차단 수문장. type_B 표본 부족 축의 100% 표기를 차단한다. - input_fields: [outcome_metrics, sample_counts, t20_source] - expected_outputs: [truthfulness_gate, contradiction_count, violations] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '거짓 100% 차단 수문장. type_B 표본 부족 축의 100% 표기를 차단한다. + ' + input_fields: + - outcome_metrics + - sample_counts + - t20_source + expected_outputs: + - truthfulness_gate + - contradiction_count + - violations + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE TRUTHFUL_DECISION_LEDGER_V2: - purpose: > - 진실성 기반 의사결정 원장 V2. 거짓 100% 없이 모든 결정 근거를 기록한다. - input_fields: [decision_log, truthfulness_check] - expected_outputs: [truthful_ledger_v2, ledger_integrity_score] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '진실성 기반 의사결정 원장 V2. 거짓 100% 없이 모든 결정 근거를 기록한다. + ' + input_fields: + - decision_log + - truthfulness_check + expected_outputs: + - truthful_ledger_v2 + - ledger_integrity_score + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE VALUE_PRESERVATION_SCORER_V2: - purpose: > - 현금확보 매도의 가치훼손·반등포착을 종합해 가치보존 점수 V2를 산출한다. - input_fields: [sell_plan, rebound_data, value_damage_pct] - expected_outputs: [value_preservation_score_v2, preservation_gate] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '현금확보 매도의 가치훼손·반등포착을 종합해 가치보존 점수 V2를 산출한다. + ' + input_fields: + - sell_plan + - rebound_data + - value_damage_pct + expected_outputs: + - value_preservation_score_v2 + - preservation_gate + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE WALK_FORWARD_CALIBRATION_V1: - purpose: > - 워크포워드 방식으로 전략 파라미터를 순차 캘리브레이션한다. - input_fields: [historical_data, strategy_params, validation_window] - expected_outputs: [calibrated_params, walk_forward_score] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: '워크포워드 방식으로 전략 파라미터를 순차 캘리브레이션한다. + ' + input_fields: + - historical_data + - strategy_params + - validation_window + expected_outputs: + - calibrated_params + - walk_forward_score + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE YAML_TO_CODE_COVERAGE_V1: - purpose: > - YAML 명세 → 코드 커버리지를 측정하고 orphan·미구현 공식을 탐지한다. - input_fields: [yaml_formula_ids, code_text, golden_test_text] - expected_outputs: [coverage_ratio, orphan_code_formula_count, unimplemented_rules] - llm_allowed: cite_only - version: "2026-06-03_ORPHAN_RECONCILE" + purpose: 'YAML 명세 → 코드 커버리지를 측정하고 orphan·미구현 공식을 탐지한다. - # == [2026-06-21_PHASE8] 비기계적 매도전략 — 공매도 합성 + confluence 판단 ========= + ' + input_fields: + - yaml_formula_ids + - code_text + - golden_test_text + expected_outputs: + - coverage_ratio + - orphan_code_formula_count + - unimplemented_rules + llm_allowed: cite_only + version: 2026-06-03_ORPHAN_RECONCILE SHORT_INTEREST_RISK_GAUGE_V1: - purpose: > - 공매도잔고율 추세 + 공매도거래비중 + 상대수익률(섹터·지수 대비) + 거래량 이상 + - 실적전망 5요소를 가중합성해 -1(매수지지)~+1(매도압력) 점수로 계량화한다. - 잔고율 단독을 매수/매도 트리거로 쓰지 않으며, 잔고율이 1% 미만(현대로템형)인 - 저잔고율 종목은 거래비중·상대수익률 가중치를 자동 상향한다. + purpose: '공매도잔고율 추세 + 공매도거래비중 + 상대수익률(섹터·지수 대비) + 거래량 이상 + 실적전망 5요소를 가중합성해 -1(매수지지)~+1(매도압력) + 점수로 계량화한다. 잔고율 단독을 매수/매도 트리거로 쓰지 않으며, 잔고율이 1% 미만(현대로템형)인 저잔고율 종목은 거래비중·상대수익률 + 가중치를 자동 상향한다. + + ' output_contract: short_interest_composite_json: - fields: "[short_interest_pressure, status, low_balance_regime, label, components, weights_used, missing_inputs]" + fields: '[short_interest_pressure, status, low_balance_regime, label, components, + weights_used, missing_inputs]' python_tool: src/quant_engine/qualitative_sell_strategy_v1.py:compute_short_interest_composite - version: "2026-06-21_PHASE8" - + version: 2026-06-21_PHASE8 QUALITATIVE_SELL_STRATEGY_V1: - purpose: > - 매크로(macro_pressure)·실적/펀더멘털 추세(fundamental_trajectory)·공매도수급 - (short_interest_pressure)·호가 10단계 미시구조(microstructure_pressure)· - 대내외 변수/대형 IPO·섹터 로테이션(liquidity_rotation_risk) 5개 독립 팩터군의 - confluence(최소 3/5 동일방향 합의)로만 매도/보유/추가 확신도를 산출한다. - 단일 팩터 임계값 돌파만으로는 행동을 트리거하지 않는다(기계적 매도 금지). - 현금부족 사유는 입력에서 의도적으로 배제되며(cash_shortfall_excluded=true), - 주식가치 보존이 유일한 목적함수다. 매도/추가 판단 시 실제 실적발표일·고영향 - 매크로 이벤트일 기준으로 검토구간(review_window)을 역산한다(임의 고정일 금지). - market_regime(PERFORMANCE_MARKET/TECHNICAL_MARKET)이 ctx.rate_trend로 주어지면 - 금리국면에 따라 팩터 가중치를 조정한다(MARKET_REGIME_CLASSIFIER_V1). + purpose: '매크로(macro_pressure)·실적/펀더멘털 추세(fundamental_trajectory)·공매도수급 (short_interest_pressure)·호가 + 10단계 미시구조(microstructure_pressure)· 대내외 변수/대형 IPO·섹터 로테이션(liquidity_rotation_risk) + 5개 독립 팩터군의 confluence(최소 3/5 동일방향 합의)로만 매도/보유/추가 확신도를 산출한다. 단일 팩터 임계값 돌파만으로는 + 행동을 트리거하지 않는다(기계적 매도 금지). 현금부족 사유는 입력에서 의도적으로 배제되며(cash_shortfall_excluded=true), + 주식가치 보존이 유일한 목적함수다. 매도/추가 판단 시 실제 실적발표일·고영향 매크로 이벤트일 기준으로 검토구간(review_window)을 + 역산한다(임의 고정일 금지). market_regime(PERFORMANCE_MARKET/TECHNICAL_MARKET)이 ctx.rate_trend로 + 주어지면 금리국면에 따라 팩터 가중치를 조정한다(MARKET_REGIME_CLASSIFIER_V1). + + ' output_contract: qualitative_sell_strategy_json: - fields: "[action, conviction, market_regime, composite_score, sell_agreeing_factors, hold_add_agreeing_factors, missing_factors, review_window, rationale, cash_shortfall_excluded, mechanical_sell_prohibited]" + fields: '[action, conviction, market_regime, composite_score, sell_agreeing_factors, + hold_add_agreeing_factors, missing_factors, review_window, rationale, + cash_shortfall_excluded, mechanical_sell_prohibited]' python_tool: src/quant_engine/qualitative_sell_strategy_v1.py:compute_qualitative_sell_strategy - version: "2026-06-21_PHASE8" - + version: 2026-06-21_PHASE8 MARKET_REGIME_CLASSIFIER_V1: - purpose: > - 금리 추세(rate_trend: RISING/FLAT/FALLING)를 실적장세(PERFORMANCE_MARKET)/ - 기술장세(TECHNICAL_MARKET)로 분류한다. 금리 상승기엔 유동성보다 실적·수출입 - 펀더멘털이 가격을 주도(실적장세) — fundamental_trajectory 가중 상향. - 금리 보합·하락기엔 유동성이 풍부해 수급·미시구조가 가격을 주도(기술장세) — - microstructure_pressure/short_interest_pressure 가중 상향. - QUALITATIVE_SELL_STRATEGY_V1·SATELLITE_CANDIDATE_SCORE_V1의 가중치 산출에 사용. + purpose: '금리 추세(rate_trend: RISING/FLAT/FALLING)를 실적장세(PERFORMANCE_MARKET)/ + 기술장세(TECHNICAL_MARKET)로 분류한다. 금리 상승기엔 유동성보다 실적·수출입 펀더멘털이 가격을 주도(실적장세) — fundamental_trajectory + 가중 상향. 금리 보합·하락기엔 유동성이 풍부해 수급·미시구조가 가격을 주도(기술장세) — microstructure_pressure/short_interest_pressure + 가중 상향. QUALITATIVE_SELL_STRATEGY_V1·SATELLITE_CANDIDATE_SCORE_V1의 가중치 산출에 + 사용. + + ' output_contract: market_regime_json: - fields: "[market_regime]" + fields: '[market_regime]' python_tool: src/quant_engine/qualitative_sell_strategy_v1.py:classify_market_regime - version: "2026-06-21_PHASE8" - + version: 2026-06-21_PHASE8 MICROSTRUCTURE_PRESSURE_FROM_ORDERBOOK_V1: - purpose: > - KIS Open API 호가10단계(inquire-asking-price-exp-ccn, FHKST01010200) output1의 - total_askp_rsqn/total_bidp_rsqn으로 -1(매수우위)~+1(매도우위) 미시구조 압력을 - 계량화. QUALITATIVE_SELL_STRATEGY_V1의 microstructure_pressure 입력으로 쓰이며, - 전략 방향 결정이 아니라 confluence 성립 후 집행 타이밍 보조로만 사용한다. - [CRITICAL] 이 공식이 사용하는 KIS API는 조회(read-only)만 수행 — - governance/rules/06_no_direct_api_trading.yaml, 07_no_kis_account_balance_query.yaml. + purpose: 'KIS Open API 호가10단계(inquire-asking-price-exp-ccn, FHKST01010200) output1의 + total_askp_rsqn/total_bidp_rsqn으로 -1(매수우위)~+1(매도우위) 미시구조 압력을 계량화. QUALITATIVE_SELL_STRATEGY_V1의 + microstructure_pressure 입력으로 쓰이며, 전략 방향 결정이 아니라 confluence 성립 후 집행 타이밍 보조로만 + 사용한다. [CRITICAL] 이 공식이 사용하는 KIS API는 조회(read-only)만 수행 — governance/rules/06_no_direct_api_trading.yaml, + 07_no_kis_account_balance_query.yaml. + + ' output_contract: microstructure_pressure_json: - fields: "[microstructure_pressure, status, total_askp_rsqn, total_bidp_rsqn]" + fields: '[microstructure_pressure, status, total_askp_rsqn, total_bidp_rsqn]' python_tool: src/quant_engine/qualitative_sell_strategy_v1.py:compute_microstructure_pressure_from_orderbook - version: "2026-06-21_PHASE8" - + version: 2026-06-21_PHASE8 SATELLITE_CANDIDATE_SCORE_V1: - purpose: > - 미보유 위성 유니버스 종목을 섹터 수출입 추세(sector_export_trend, 관세청/산업 - 통상부 무역통계 기반)·펀더멘털 추세·상대수익률로 평가해 BUY_CANDIDATE/WATCH/ - NEUTRAL_NO_EDGE/AVOID를 산출한다. market_regime에 따라 수출입 비중을 조정 - (실적장세에서 sector_export_trend 가중 상향). + purpose: '미보유 위성 유니버스 종목을 섹터 수출입 추세(sector_export_trend, 관세청/산업 통상부 무역통계 기반)·펀더멘털 + 추세·상대수익률로 평가해 BUY_CANDIDATE/WATCH/ NEUTRAL_NO_EDGE/AVOID를 산출한다. market_regime에 + 따라 수출입 비중을 조정 (실적장세에서 sector_export_trend 가중 상향). + + ' output_contract: satellite_candidate_json: - fields: "[satellite_action, attractiveness_score, market_regime, components, weights_used]" + fields: '[satellite_action, attractiveness_score, market_regime, components, + weights_used]' python_tool: src/quant_engine/qualitative_sell_strategy_v1.py:compute_satellite_candidate_score - version: "2026-06-21_PHASE8" + version: 2026-06-21_PHASE8 diff --git a/spec/16_data_gaps_roadmap.yaml b/spec/16_data_gaps_roadmap.yaml index dcb9ee0..a4be3ed 100644 --- a/spec/16_data_gaps_roadmap.yaml +++ b/spec/16_data_gaps_roadmap.yaml @@ -1,209 +1,209 @@ meta: - title: "데이터 갭 로드맵 — 단계별 보완 계획" - version: "2026-06-21-platform-transition-v1" - language: "ko-KR" - purpose: > - 의사결정 파이프라인(spec/09_decision_flow.yaml)에서 식별된 데이터 공백을 - 우선순위별로 정리하고, 단계별 구현 계획을 명시한다. - GAS 수집 → spec 공식 → LLM 판단 순서로 각 갭의 의존성을 추적한다. + title: 데이터 갭 로드맵 — 단계별 보완 계획 + version: 2026-06-21-platform-transition-v1 + language: ko-KR + purpose: '의사결정 파이프라인(spec/09_decision_flow.yaml)에서 식별된 데이터 공백을 우선순위별로 정리하고, 단계별 + 구현 계획을 명시한다. GAS 수집 → spec 공식 → LLM 판단 순서로 각 갭의 의존성을 추적한다. -# ───────────────────────────────────────────────────────────────────────────── -# 1단계 완료 (2026-05-17 구현됨) -# ───────────────────────────────────────────────────────────────────────────── + ' + has_code_implementation: true + code_path: + - spec\16_data_gaps_roadmap.yaml phase_1_completed: G1_KOSPI_MA60: status: DONE - implementation: "fetchYahooOhlcMetrics → macro 탭 MA60 컬럼" - enables: "RISK_ON 판정 조건 KOSPI_MA20 >= KOSPI_MA60" + implementation: fetchYahooOhlcMetrics → macro 탭 MA60 컬럼 + enables: RISK_ON 판정 조건 KOSPI_MA20 >= KOSPI_MA60 G2_KOSPI_KOSDAQ_Ret10D: status: DONE - implementation: "fetchYahooOhlcMetrics → macro 탭 Ret10D" - enables: "daily_leader_scan C2: Ret10D_종목 - Ret10D_KOSPI" + implementation: fetchYahooOhlcMetrics → macro 탭 Ret10D + enables: 'daily_leader_scan C2: Ret10D_종목 - Ret10D_KOSPI' G3_ETF_Ret10D: status: DONE - implementation: "fetchYahooPrice → sector_flow ETF_Ret10D" - enables: "RW2 상대약세: Ret10D_종목 - Ret10D_주도섹터ETF" + implementation: fetchYahooPrice → sector_flow ETF_Ret10D + enables: 'RW2 상대약세: Ret10D_종목 - Ret10D_주도섹터ETF' G4_USD_JPY_Ret2D: status: DONE - implementation: "calcDerivedPriceMetrics.ret2D → macro 탭 Ret2D (USD_JPY행)" - enables: "MRS usd_jpy_score: Ret2D <= -1 → +1점" + implementation: calcDerivedPriceMetrics.ret2D → macro 탭 Ret2D (USD_JPY행) + enables: 'MRS usd_jpy_score: Ret2D <= -1 → +1점' G5_credit_stress_proxy: status: DONE - implementation: "HYG ETF Ret5D → REGIME_PRELIM 행 credit_stress 필드" - enables: "MRS credit_score 자동 계산" - limitation: "HYG는 미국 HY proxy. 한국 신용스프레드 직접 수집은 3단계 과제." + implementation: HYG ETF Ret5D → REGIME_PRELIM 행 credit_stress 필드 + enables: MRS credit_score 자동 계산 + limitation: HYG는 미국 HY proxy. 한국 신용스프레드 직접 수집은 3단계 과제. G6_Rotation_Rank: status: DONE - implementation: "runSectorFlow 정렬 후 Rotation_Rank 컬럼" - enables: "C5 Rotation_Score 순위 <= 3 판단, RW1 섹터 순위 변화 추적" + implementation: runSectorFlow 정렬 후 Rotation_Rank 컬럼 + enables: C5 Rotation_Score 순위 <= 3 판단, RW1 섹터 순위 변화 추적 S4_MRS_auto_compute: status: DONE - implementation: "runMacro 내 MARKET_RISK_SCORE_V1 계산 → macro 탭 MRS_COMPUTED 행" - enables: "LLM이 macro 탭 한 번 읽어 MRS 즉시 확인 가능" - -# ───────────────────────────────────────────────────────────────────────────── -# 2단계 — 구조적 갭 (시트 신설 필요, 중간 우선순위) -# ───────────────────────────────────────────────────────────────────────────── + implementation: runMacro 내 MARKET_RISK_SCORE_V1 계산 → macro 탭 MRS_COMPUTED 행 + enables: LLM이 macro 탭 한 번 읽어 MRS 즉시 확인 가능 phase_2_structural: S1_trades_performance_sheet: priority: HIGH status: DONE - purpose: > - Bayesian multiplier (high/medium/low/no_bet) 및 net_expectancy 산출 기반. + purpose: 'Bayesian multiplier (high/medium/low/no_bet) 및 net_expectancy 산출 기반. 미구현 시 bayesian_confidence는 항상 medium_confidence(0.5×) 고정. - required_columns: - - "trade_id" - - "ticker" - - "sector" - - "entry_date" - - "entry_price" - - "entry_stage" # stage_1/2/3 - - "quantity" - - "stop_price_at_entry" - - "target_price_at_entry" - - "exit_date" - - "exit_price" - - "exit_reason" # stop_loss/take_profit/time_stop/rw_exit/manual - - "pnl_pct" - - "holding_days" - - "entry_c1_score" # daily_leader_scan 입장 시 C1~C5 - - "entry_c2_score" - - "entry_c3_score" - - "entry_c4_score" - - "entry_c5_score" - - "entry_mrs_score" - - "fc_bucket" # Y/N: explore_loss_budget 귀속 여부 - derived_outputs: - - "win_rate (최근 30건)" - - "avg_win_pct" - - "avg_loss_pct" - - "net_expectancy = (win_rate × avg_win_pct) - (loss_rate × avg_loss_pct)" - - "bayesian_confidence_multiplier 자동 결정" - implementation_plan: - step_1: "Google Sheets에 'performance' 탭 수동 생성" - step_2: "spec/17_performance_contract.yaml 계약서 작성" - step_3: "GAS에 performance 탭 읽기 함수 추가 → Bayesian multiplier 자동 계산" - step_4: "runDataFeed 내 bayesian_multiplier 필드 → data_feed 탭 추가" - implementation_note: > - 2026-05-17 구현 완료. spec/17_performance_contract.yaml 신규 작성. - readPerformanceSheet_() GAS 함수 추가. EE_Est 계산에 Bayesian multiplier 반영. - macro 탭 BAYESIAN_COMPUTED 행으로 상태 출력. + ' + required_columns: + - trade_id + - ticker + - sector + - entry_date + - entry_price + - entry_stage + - quantity + - stop_price_at_entry + - target_price_at_entry + - exit_date + - exit_price + - exit_reason + - pnl_pct + - holding_days + - entry_c1_score + - entry_c2_score + - entry_c3_score + - entry_c4_score + - entry_c5_score + - entry_mrs_score + - fc_bucket + derived_outputs: + - win_rate (최근 30건) + - avg_win_pct + - avg_loss_pct + - net_expectancy = (win_rate × avg_win_pct) - (loss_rate × avg_loss_pct) + - bayesian_confidence_multiplier 자동 결정 + implementation_plan: + step_1: Google Sheets에 'performance' 탭 수동 생성 + step_2: spec/17_performance_contract.yaml 계약서 작성 + step_3: GAS에 performance 탭 읽기 함수 추가 → Bayesian multiplier 자동 계산 + step_4: runDataFeed 내 bayesian_multiplier 필드 → data_feed 탭 추가 + implementation_note: '2026-05-17 구현 완료. spec/17_performance_contract.yaml 신규 작성. + readPerformanceSheet_() GAS 함수 추가. EE_Est 계산에 Bayesian multiplier 반영. macro + 탭 BAYESIAN_COMPUTED 행으로 상태 출력. + + ' S2_stop_price_tracking: priority: HIGH status: DONE - purpose: > - TOTAL_HEAT_V1 계산 필수 입력값. 미구현 시 HF005(Total_Heat 10% 차단) 미작동. - stop_price 없으면 포트폴리오 총 위험노출 계산 불가. - required_fields_per_position: - - "ticker" - - "account" - - "average_cost" - - "stop_price" # ATR 기준 계산값 또는 HTS 실제 설정값 - - "holding_quantity" - - "last_updated" - implementation_plan: - step_1: "account_snapshot에 stop_price/highest_price_since_entry/last_updated 선택 컬럼 추가" - step_2: "spec/15_account_snapshot_contract.yaml에 account_snapshot_position_state 추가" - step_3: "GAS: account_snapshot 기반 TOTAL_HEAT 및 trailing stop 갱신" - interim_workaround: > - stop_price 미기록 시 STOP_PRICE_CORE_V1 공식으로 ATR 기준 추정: - stop_price_est = average_cost - ATR20 × 1.5 - Total_Heat_est = sum((average_cost - stop_price_est) × holding_quantity) / total_asset × 100 - implementation_note: > - 2026-05-18 account_snapshot 통합 완료. positions_tab은 deprecated. - readAccountSnapshotHeat_() GAS 함수 추가 (ATR 추정 폴백 포함). - macro 탭 TOTAL_HEAT 행으로 HF005 상태 출력. + purpose: 'TOTAL_HEAT_V1 계산 필수 입력값. 미구현 시 HF005(Total_Heat 10% 차단) 미작동. stop_price + 없으면 포트폴리오 총 위험노출 계산 불가. + ' + required_fields_per_position: + - ticker + - account + - average_cost + - stop_price + - holding_quantity + - last_updated + implementation_plan: + step_1: account_snapshot에 stop_price/highest_price_since_entry/last_updated + 선택 컬럼 추가 + step_2: spec/15_account_snapshot_contract.yaml에 account_snapshot_position_state + 추가 + step_3: 'GAS: account_snapshot 기반 TOTAL_HEAT 및 trailing stop 갱신' + interim_workaround: 'stop_price 미기록 시 STOP_PRICE_CORE_V1 공식으로 ATR 기준 추정: stop_price_est + = average_cost - ATR20 × 1.5 Total_Heat_est = sum((average_cost - stop_price_est) + × holding_quantity) / total_asset × 100 + + ' + implementation_note: '2026-05-18 account_snapshot 통합 완료. positions_tab은 deprecated. + readAccountSnapshotHeat_() GAS 함수 추가 (ATR 추정 폴백 포함). macro 탭 TOTAL_HEAT 행으로 + HF005 상태 출력. + + ' S3_sector_flow_weekly_history: priority: MEDIUM status: DONE - implementation: > - option_B legacy interim 구현 완료 (2026-05-17). - sector_flow 탭에 Prev_Rotation_Rank(W1), Prev_Rotation_Rank_W2 컬럼 추가. - W1 = sector_flow 시트에서 직전 실행 결과 읽기. - W2 = PropertiesService['sf_w2_ranks_json'] 캐시 (직전 실행 시 저장). - RW1·RW3 컬럼이 sector_flow 탭에 자동 계산됨 → data_feed RW1·RW3 컬럼으로 전파. - enables: > - RW1 '2주 연속 섹터 순위 3순위 이상 하락' 자동 판단. - RW3 '외국인+기관 5D 순매도 2주 연속' 자동 판단. - note: > - 2회 이상 실행 후 W1/W2 데이터가 축적되어야 RW1·RW3가 작동한다. - 단, 이는 전회 실행 기준 legacy interim이며 주간 스냅샷 기반 sector_flow_history는 후속 Phase 4 과제다. + implementation: 'option_B legacy interim 구현 완료 (2026-05-17). sector_flow 탭에 Prev_Rotation_Rank(W1), + Prev_Rotation_Rank_W2 컬럼 추가. W1 = sector_flow 시트에서 직전 실행 결과 읽기. W2 = PropertiesService[''sf_w2_ranks_json''] + 캐시 (직전 실행 시 저장). RW1·RW3 컬럼이 sector_flow 탭에 자동 계산됨 → data_feed RW1·RW3 컬럼으로 + 전파. + ' + enables: 'RW1 ''2주 연속 섹터 순위 3순위 이상 하락'' 자동 판단. RW3 ''외국인+기관 5D 순매도 2주 연속'' 자동 + 판단. + + ' + note: '2회 이상 실행 후 W1/W2 데이터가 축적되어야 RW1·RW3가 작동한다. 단, 이는 전회 실행 기준 legacy interim이며 + 주간 스냅샷 기반 sector_flow_history는 후속 Phase 4 과제다. + + ' S4_sector_flow: priority: HIGH status: DONE - implementation: > - 2026-05-17 Phase 1-2 구현. - sector_universe 원장 또는 DEFAULT_SECTOR_UNIVERSE_V2를 canonical source로 사용하고, - 구성종목 수급을 수량 단순합산이 아닌 원화금액×가중치로 sector_flow에 집계한다. - Coverage_Weight, SmartMoney_5D_KRW, SmartMoney_5D_Norm, Flow_Breadth_5D, - Data_Quality, Decision_Use를 추가했다. - sector_universe 시트가 없으면 기본 템플릿을 생성하며, Is_ETF=Y 구성행은 - ETF 자체 수급 혼입을 막기 위해 섹터 smart money 집계에서 제외한다. - limitation: > - KRX/KIND 기반 NAV/괴리율/추적오차/AUM 수집은 아직 미구현이며 etf_raw에서 - ETF_NAV_Risk=NAV_DATA_MISSING으로 명시한다. - next_review_date: "2026-09-30" # WBS-7.8(2026-06-21) — KRX/KIND API 키 발급 가능성 분기별 재조사 - next_review_action: > - KRX 정보데이터시스템/KIND 공식 API 또는 공개 데이터셋의 발급/이용약관 변경 여부를 - 재확인한다. 변경이 없으면 next_review_date를 다음 분기로 갱신하고 PLANNED 유지, - 변경이 있으면 P1_kis_core_api_collector와 동일한 패턴으로 착수 여부를 결정한다. - automation_attempt_2026_06_22: > - pykrx(이미 tools/build_prediction_accuracy_harness_v2.py에서 EOD 가격 조회로 사용 중)의 - get_etf_price_deviation()/get_etf_tracking_error()/get_shorting_balance()를 실제로 - 호출해 자동화 가능성을 재시도했다. 결과: 기본 시세조회(OHLCV)는 정상 작동(공개 - 엔드포인트, 로그인 불필요)하지만, 공매도 잔고/ETF 괴리율/추적오차 엔드포인트는 - 세션 쿠키를 정상 부트스트랩한 뒤에도 "HTTP 400 LOGOUT"을 반환했다(raw HTTP로 - 재현 확인). 이는 pykrx 임포트 시 출력되는 "KRX_ID/KRX_PW 환경변수 미설정" 경고와 - 정확히 일치 — 이 카테고리는 KRX 회원 로그인이 있어야 접근 가능한 서버측 인증 - 게이트이며, 헤더/세션 보정으로 해결되는 문제가 아님을 확인했다. 자동화하려면 - KRX 계정(KRX_ID/KRX_PW)을 자격증명으로 코드에 등록해야 하는데, 이는 - governance/rules/06·07과 유사한 새로운 자격증명 정책 결정이 필요한 사안이라 - 사용자 승인 없이 추가하지 않는다. 기술적 장벽 자체는 명확히 확정됐으므로 - next_review_date 재조사 시 "API 키 발급 가능성"이 아니라 "KRX 계정 발급·자격증명 - 관리 정책 승인 여부"로 재구성해 검토할 것. + implementation: '2026-05-17 Phase 1-2 구현. sector_universe 원장 또는 DEFAULT_SECTOR_UNIVERSE_V2를 + canonical source로 사용하고, 구성종목 수급을 수량 단순합산이 아닌 원화금액×가중치로 sector_flow에 집계한다. Coverage_Weight, + SmartMoney_5D_KRW, SmartMoney_5D_Norm, Flow_Breadth_5D, Data_Quality, Decision_Use를 + 추가했다. sector_universe 시트가 없으면 기본 템플릿을 생성하며, Is_ETF=Y 구성행은 ETF 자체 수급 혼입을 막기 위해 + 섹터 smart money 집계에서 제외한다. + ' + limitation: 'KRX/KIND 기반 NAV/괴리율/추적오차/AUM 수집은 아직 미구현이며 etf_raw에서 ETF_NAV_Risk=NAV_DATA_MISSING으로 + 명시한다. + + ' + next_review_date: '2026-09-30' + next_review_action: 'KRX 정보데이터시스템/KIND 공식 API 또는 공개 데이터셋의 발급/이용약관 변경 여부를 재확인한다. + 변경이 없으면 next_review_date를 다음 분기로 갱신하고 PLANNED 유지, 변경이 있으면 P1_kis_core_api_collector와 + 동일한 패턴으로 착수 여부를 결정한다. + + ' + automation_attempt_2026_06_22: 'pykrx(이미 tools/build_prediction_accuracy_harness_v2.py에서 + EOD 가격 조회로 사용 중)의 get_etf_price_deviation()/get_etf_tracking_error()/get_shorting_balance()를 + 실제로 호출해 자동화 가능성을 재시도했다. 결과: 기본 시세조회(OHLCV)는 정상 작동(공개 엔드포인트, 로그인 불필요)하지만, 공매도 + 잔고/ETF 괴리율/추적오차 엔드포인트는 세션 쿠키를 정상 부트스트랩한 뒤에도 "HTTP 400 LOGOUT"을 반환했다(raw HTTP로 + 재현 확인). 이는 pykrx 임포트 시 출력되는 "KRX_ID/KRX_PW 환경변수 미설정" 경고와 정확히 일치 — 이 카테고리는 KRX + 회원 로그인이 있어야 접근 가능한 서버측 인증 게이트이며, 헤더/세션 보정으로 해결되는 문제가 아님을 확인했다. 자동화하려면 KRX 계정(KRX_ID/KRX_PW)을 + 자격증명으로 코드에 등록해야 하는데, 이는 governance/rules/06·07과 유사한 새로운 자격증명 정책 결정이 필요한 사안이라 + 사용자 승인 없이 추가하지 않는다. 기술적 장벽 자체는 명확히 확정됐으므로 next_review_date 재조사 시 "API 키 발급 가능성"이 + 아니라 "KRX 계정 발급·자격증명 관리 정책 승인 여부"로 재구성해 검토할 것. + + ' S5_etf_raw_execution_quality: priority: HIGH status: DATA_GATED - implementation: > - 2026-05-17 Phase 3 interim 구현. - etf_raw 시트를 신설하고 ETF proxy/ETF 구성행에 대해 Close, Bid, Ask, Spread_Pct, - AvgTradeValue_5D_KRW, AvgTradeValue_20D_KRW, ETF_Frg_5D_KRW, ETF_Inst_5D_KRW, - ETF_Liquidity_Score, ETF_Liquidity_Status를 산출한다. - NAV_DATA_MISSING 상태에서는 ETF_Execution_Use=WATCH_ONLY로 표시해 ETF 매매 실행 근거와 섹터 수급 근거를 분리한다. - etf_nav_manual 시트가 있으면 NAV, iNAV, 괴리율, 추적오차, AUM을 etf_raw에 반영한다. - tools/import_etf_nav_manual.py로 KRX/KIND/운용사 CSV/XLSX export를 etf_nav_manual로 변환할 수 있다. - limitation: "NAV, iNAV, 괴리율, 추적오차, AUM 자동 수집은 KRX/KIND 수집 경로 확정 전까지 미구현." - next_review_date: "2026-09-30" # WBS-7.8(2026-06-21) — S4와 동일 주기로 재검토 - next_review_action: "S4_sector_flow.next_review_action과 동일 — KRX/KIND 경로 확정 시 etf_nav_manual 수동 경로를 자동 수집으로 대체." - automation_attempt_2026_06_22: "S4_sector_flow.automation_attempt_2026_06_22와 동일 사유로 자동화 불가 확정(pykrx get_etf_price_deviation/get_etf_tracking_error 모두 HTTP 400 LOGOUT — KRX 회원 로그인 필요)." + implementation: '2026-05-17 Phase 3 interim 구현. etf_raw 시트를 신설하고 ETF proxy/ETF + 구성행에 대해 Close, Bid, Ask, Spread_Pct, AvgTradeValue_5D_KRW, AvgTradeValue_20D_KRW, + ETF_Frg_5D_KRW, ETF_Inst_5D_KRW, ETF_Liquidity_Score, ETF_Liquidity_Status를 + 산출한다. NAV_DATA_MISSING 상태에서는 ETF_Execution_Use=WATCH_ONLY로 표시해 ETF 매매 실행 근거와 + 섹터 수급 근거를 분리한다. etf_nav_manual 시트가 있으면 NAV, iNAV, 괴리율, 추적오차, AUM을 etf_raw에 반영한다. + tools/import_etf_nav_manual.py로 KRX/KIND/운용사 CSV/XLSX export를 etf_nav_manual로 + 변환할 수 있다. + ' + limitation: NAV, iNAV, 괴리율, 추적오차, AUM 자동 수집은 KRX/KIND 수집 경로 확정 전까지 미구현. + next_review_date: '2026-09-30' + next_review_action: S4_sector_flow.next_review_action과 동일 — KRX/KIND 경로 확정 시 etf_nav_manual + 수동 경로를 자동 수집으로 대체. + automation_attempt_2026_06_22: S4_sector_flow.automation_attempt_2026_06_22와 동일 + 사유로 자동화 불가 확정(pykrx get_etf_price_deviation/get_etf_tracking_error 모두 HTTP 400 + LOGOUT — KRX 회원 로그인 필요). S6_sector_flow_history: priority: HIGH status: DONE - implementation: > - 2026-05-17 Phase 4 interim 구현. - sector_flow_history 시트에 Snapshot_Date+Sector 기준으로 sector_flow 누적 스냅샷을 upsert한다. - sector_flow의 RW1/RW3 계산은 sector_flow_history를 우선 사용하고, - 이력이 부족할 때만 기존 sector_flow/PropertiesService 값을 fallback으로 사용한다. - Snapshot_Date는 Apps Script Date 객체와 문자열 날짜를 모두 yyyy-MM-dd로 정규화한다. + implementation: '2026-05-17 Phase 4 interim 구현. sector_flow_history 시트에 Snapshot_Date+Sector + 기준으로 sector_flow 누적 스냅샷을 upsert한다. sector_flow의 RW1/RW3 계산은 sector_flow_history를 + 우선 사용하고, 이력이 부족할 때만 기존 sector_flow/PropertiesService 값을 fallback으로 사용한다. Snapshot_Date는 + Apps Script Date 객체와 문자열 날짜를 모두 yyyy-MM-dd로 정규화한다. + ' S7_snapshot_admin_web_editor: priority: HIGH status: DONE - implementation: > - SQLite canonical store용 웹 편집기 구현. - settings/account_snapshot을 contenteditable 그리드로 직접 수정하고, - TSV import/export, 행 삽입/복제, 승인/잠금/undo를 API로 제어한다. - KIS SQLite collector 상태 패널을 함께 노출해서 최신 수집 run/오류를 - 같은 화면에서 확인한다. - web UI는 Snapshot Admin 서버가 담당하며 JSON export는 CI/파생 도구용이다. - enables: > - settings/account_snapshot을 xlsx 대신 SQLite에서 직접 관리하면서도 - 스프레드시트처럼 편집 가능한 운영 surface와 수집 현황 대시보드 제공. + implementation: 'SQLite canonical store용 웹 편집기 구현. settings/account_snapshot을 + contenteditable 그리드로 직접 수정하고, TSV import/export, 행 삽입/복제, 승인/잠금/undo를 API로 제어한다. + KIS SQLite collector 상태 패널을 함께 노출해서 최신 수집 run/오류를 같은 화면에서 확인한다. web UI는 Snapshot + Admin 서버가 담당하며 JSON export는 CI/파생 도구용이다. + + ' + enables: 'settings/account_snapshot을 xlsx 대신 SQLite에서 직접 관리하면서도 스프레드시트처럼 편집 가능한 + 운영 surface와 수집 현황 대시보드 제공. + + ' success_criteria: settings_sheet_web_editor: true account_snapshot_sheet_web_editor: true @@ -216,639 +216,648 @@ phase_2_structural: change_timeline_view: true evidence: code: - - "src/quant_engine/snapshot_admin_server_v1.py" - - "src/quant_engine/snapshot_admin_store_v1.py" - - "tools/validate_snapshot_admin_web_v1.py" + - src/quant_engine/snapshot_admin_server_v1.py + - src/quant_engine/snapshot_admin_store_v1.py + - tools/validate_snapshot_admin_web_v1.py tests: - - "tests/unit/test_snapshot_admin_store_v1.py" - - "tests/unit/test_snapshot_admin_web_v1.py" + - tests/unit/test_snapshot_admin_store_v1.py + - tests/unit/test_snapshot_admin_web_v1.py workflow: - - ".gitea/workflows/snapshot_admin.yml" - verification: "python tools/validate_snapshot_admin_web_v1.py" - -# ───────────────────────────────────────────────────────────────────────────── -# 3단계 — 분석 품질 고도화 (낮은 우선순위) -# ───────────────────────────────────────────────────────────────────────────── + - .gitea/workflows/snapshot_admin.yml + verification: python tools/validate_snapshot_admin_web_v1.py phase_3_enhancement: A1_daily_leader_scan_auto: priority: MEDIUM status: DONE - implementation: > - P1(2026-05-17) 구현 완료. runDataFeed 루프 내 C1~C5 자동 계산. - data_feed 탭: C1_Price, C2_RelStr, C3_VolSurge, C4_Flow, C5_Sector, Leader_Scan_Total, Leader_Gate. - output_columns: ["C1_Price","C2_RelStr","C3_VolSurge","C4_Flow","C5_Sector","Leader_Scan_Total","Leader_Gate"] + implementation: 'P1(2026-05-17) 구현 완료. runDataFeed 루프 내 C1~C5 자동 계산. data_feed + 탭: C1_Price, C2_RelStr, C3_VolSurge, C4_Flow, C5_Sector, Leader_Scan_Total, + Leader_Gate. + ' + output_columns: + - C1_Price + - C2_RelStr + - C3_VolSurge + - C4_Flow + - C5_Sector + - Leader_Scan_Total + - Leader_Gate A2_eps_growth_3y_cagr: priority: MEDIUM status: DONE - implementation: > - 2026-05-17 구현 완료. fetchYahooConsensusEps() 확장. - Yahoo earningsTrend +1y의 earningsEstimate.growth.raw 직접 추출. - 없으면 (+1y avg - 0y avg) / abs(0y avg) × 100 으로 계산. - data_feed 탭 EPS_Growth_1Y_Pct 컬럼 추가 → LLM이 PEG = Forward_PE / EPS_Growth_1Y_Pct 계산 가능. - accuracy_note: "1년 성장률 추정치 (3Y CAGR 완전 대체 불가). KOSDAQ PEG 게이트에서 fallback보다 정확." + implementation: '2026-05-17 구현 완료. fetchYahooConsensusEps() 확장. Yahoo earningsTrend + +1y의 earningsEstimate.growth.raw 직접 추출. 없으면 (+1y avg - 0y avg) / abs(0y avg) + × 100 으로 계산. data_feed 탭 EPS_Growth_1Y_Pct 컬럼 추가 → LLM이 PEG = Forward_PE / EPS_Growth_1Y_Pct + 계산 가능. + ' + accuracy_note: 1년 성장률 추정치 (3Y CAGR 완전 대체 불가). KOSDAQ PEG 게이트에서 fallback보다 정확. A3_pct_from_52w_low: priority: LOW status: DONE - purpose: "Low52W 대비 현재가 반등률 — 저점 대비 위치 파악 (눌림 구간 분석)" - expression: "(Close / Low52W - 1) × 100" - implementation: "data_feed 탭 Pct_From_52W_Low 컬럼 (2026-05-17)" - + purpose: Low52W 대비 현재가 반등률 — 저점 대비 위치 파악 (눌림 구간 분석) + expression: (Close / Low52W - 1) × 100 + implementation: data_feed 탭 Pct_From_52W_Low 컬럼 (2026-05-17) A4_ex_dividend_date: priority: LOW status: DONE - implementation: > - 2026-05-17 구현 완료. fetchYahooTargetPrice() 확장 (추가 API 호출 없음). + implementation: '2026-05-17 구현 완료. fetchYahooTargetPrice() 확장 (추가 API 호출 없음). calendarEvents.exDividendDate → data_feed Ex_Dividend_Date, Days_To_Ex_Div 컬럼. defaultKeyStatistics.lastDividendValue → data_feed DPS 컬럼. + ' A6_pos_size_qty: priority: HIGH status: DONE - implementation: > - 2026-05-17 구현 완료. - data_feed Pos_Size_Qty 컬럼: POSITION_SIZE_V1 간략 버전 자동 계산. - atr_qty = floor(total_asset × 0.007 × bayesian_multiplier / (ATR20 × 1.5)) - weight_qty = floor(total_asset × 0.05 / Close) - Pos_Size_Qty = min(atr_qty, weight_qty). - requires: settings 탭 total_asset_krw 입력. - limitation: "cash/sector/liquidity 한도는 account_snapshot 필요. 현재는 ATR+weight 한도만 적용." + implementation: '2026-05-17 구현 완료. data_feed Pos_Size_Qty 컬럼: POSITION_SIZE_V1 + 간략 버전 자동 계산. atr_qty = floor(total_asset × 0.007 × bayesian_multiplier / (ATR20 + × 1.5)) weight_qty = floor(total_asset × 0.05 / Close) Pos_Size_Qty = min(atr_qty, + weight_qty). requires: settings 탭 total_asset_krw 입력. limitation: "cash/sector/liquidity + 한도는 account_snapshot 필요. 현재는 ATR+weight 한도만 적용." + ' A7_stop_price_actual: priority: HIGH status: DONE - implementation: > - 2026-05-17 구현 완료. - data_feed Stop_Price_Est: account_snapshot 실제 stop_price 우선 → ATR 추정 폴백. - Stop_Price_Source 컬럼: "account_snapshot" / "ATR추정" 표시. - EE_Est가 실제 stop_price 기반으로 계산됨 (포지션 있는 종목). + implementation: '2026-05-17 구현 완료. data_feed Stop_Price_Est: account_snapshot + 실제 stop_price 우선 → ATR 추정 폴백. Stop_Price_Source 컬럼: "account_snapshot" / "ATR추정" + 표시. EE_Est가 실제 stop_price 기반으로 계산됨 (포지션 있는 종목). + ' A8_settings_tab: priority: HIGH status: DONE - implementation: > - 2026-05-17 구현 완료. readSettingsTab_() GAS 함수 추가. - settings 탭: key-value 구조 (key, value, note 컬럼). - total_asset_krw: Pos_Size_Qty, TOTAL_HEAT_V1, FC_BUDGET 계산에 사용. - spec/18_settings_contract.yaml 계약서 작성. + implementation: '2026-05-17 구현 완료. readSettingsTab_() GAS 함수 추가. settings 탭: key-value + 구조 (key, value, note 컬럼). total_asset_krw: Pos_Size_Qty, TOTAL_HEAT_V1, FC_BUDGET + 계산에 사용. spec/18_settings_contract.yaml 계약서 작성. + ' A9_fc_budget_tracking: priority: MEDIUM status: DONE - implementation: > - 2026-05-17 구현 완료. calcFcBudget_() GAS 함수 추가. - performance 탭 fc_bucket=Y 거래 중 당월 청산 손실 집계. - macro 탭 FC_BUDGET 행 추가: used_pct / 2.5% 예산 상태 출력. - exhausted 시 LLM이 신규 stage_1 탐색 자동 억제 가능. + implementation: '2026-05-17 구현 완료. calcFcBudget_() GAS 함수 추가. performance 탭 fc_bucket=Y + 거래 중 당월 청산 손실 집계. macro 탭 FC_BUDGET 행 추가: used_pct / 2.5% 예산 상태 출력. exhausted + 시 LLM이 신규 stage_1 탐색 자동 억제 가능. + ' A5_kosdaq_vs_ma20: priority: LOW status: DONE - purpose: "kosdaq_regime_supplement 규칙: KOSDAQ_Close < KOSDAQ_MA20 → MRS +1" - implementation: "runMacro MRS 계산에 kosdaqSupp 로직 추가. macro 탭 KOSDAQ (^KQ11) 이미 수집 중 (2026-05-17)" - -# ───────────────────────────────────────────────────────────────────────────── -# 분석 보완 제안 (GAS 미관여, LLM 분석 품질 향상) -# ───────────────────────────────────────────────────────────────────────────── + purpose: 'kosdaq_regime_supplement 규칙: KOSDAQ_Close < KOSDAQ_MA20 → MRS +1' + implementation: runMacro MRS 계산에 kosdaqSupp 로직 추가. macro 탭 KOSDAQ (^KQ11) 이미 수집 + 중 (2026-05-17) analysis_enhancements: B1_rw_signal_checklist: - purpose: "RW1~RW5 자동 계산 및 출력" + purpose: RW1~RW5 자동 계산 및 출력 current_status: - RW1: "✅ sector_flow RW1 컬럼 자동 계산 (2026-05-17). Prev_Rotation_Rank(W1)+W2 PropertiesService 캐시 기반. 2회 이상 실행 후 정확." - RW2: "✅ data_feed RW2 컬럼 자동 계산 (2026-05-17). Ret10D - ETF_Ret10D <= -5%p" - RW3: "✅ sector_flow RW3 컬럼 자동 계산 (2026-05-17). 외국인+기관 5D 순매도 2주 연속 (현재+W1 비교)." - RW4: "✅ data_feed RW4 컬럼 자동 계산 (2026-05-17). AvgTradeValue_5D/20D <= 0.60" - RW5: "✅ data_feed RW5 컬럼 자동 계산 (2026-05-17). Close < MA20 AND < MA60" - RW_Partial: "✅ data_feed RW_Partial = RW1+RW2+RW3+RW4+RW5 합계 (0~5)" - fully_automated: ["RW1 (2회 이상 실행 후)", "RW2", "RW3 (현재+W1 기준)", "RW4", "RW5"] - note: "RW1·RW3의 '2주 연속' 조건은 2회 이상 실행 후 W1/W2 데이터 축적 시 완전히 정확해짐." - + RW1: ✅ sector_flow RW1 컬럼 자동 계산 (2026-05-17). Prev_Rotation_Rank(W1)+W2 PropertiesService + 캐시 기반. 2회 이상 실행 후 정확. + RW2: ✅ data_feed RW2 컬럼 자동 계산 (2026-05-17). Ret10D - ETF_Ret10D <= -5%p + RW3: ✅ sector_flow RW3 컬럼 자동 계산 (2026-05-17). 외국인+기관 5D 순매도 2주 연속 (현재+W1 비교). + RW4: ✅ data_feed RW4 컬럼 자동 계산 (2026-05-17). AvgTradeValue_5D/20D <= 0.60 + RW5: ✅ data_feed RW5 컬럼 자동 계산 (2026-05-17). Close < MA20 AND < MA60 + RW_Partial: ✅ data_feed RW_Partial = RW1+RW2+RW3+RW4+RW5 합계 (0~5) + fully_automated: + - RW1 (2회 이상 실행 후) + - RW2 + - RW3 (현재+W1 기준) + - RW4 + - RW5 + note: RW1·RW3의 '2주 연속' 조건은 2회 이상 실행 후 W1/W2 데이터 축적 시 완전히 정확해짐. B2_total_heat_estimation: - purpose: "stop_price 미기록 시 ATR 기준 Total_Heat 추정" - formula: > - For each holding in account_snapshot: - stop_price_est = entry_price - ATR20 × 1.5 - heat_contribution = (entry_price - stop_price_est) × quantity / total_asset × 100 - Total_Heat_est = sum(heat_contribution) - requirement: "ATR20(data_feed), entry_price(account_snapshot), quantity(account_snapshot), total_asset(account_snapshot) 필요" - note: "actual stop_price가 있으면 실제값 우선. 없으면 이 추정으로 HF005 체크 가능." - + purpose: stop_price 미기록 시 ATR 기준 Total_Heat 추정 + formula: "For each holding in account_snapshot:\n stop_price_est = entry_price\ + \ - ATR20 × 1.5\n heat_contribution = (entry_price - stop_price_est) × quantity\ + \ / total_asset × 100\nTotal_Heat_est = sum(heat_contribution)\n" + requirement: ATR20(data_feed), entry_price(account_snapshot), quantity(account_snapshot), + total_asset(account_snapshot) 필요 + note: actual stop_price가 있으면 실제값 우선. 없으면 이 추정으로 HF005 체크 가능. B3_expected_edge_checklist: - purpose: "EXPECTED_EDGE_V1 계산 전 필수 입력 확인" + purpose: EXPECTED_EDGE_V1 계산 전 필수 입력 확인 required_fields: - - "target_price: data_feed Target_Price (Naver 또는 Yahoo) ✓" - - "entry_price: limit_price (entry_core.yaml limit_price_formula) ✓" - - "stop_price: stop_price_est (B2 또는 실제값) △" - - "bayesian_confidence_multiplier: performance 시트 기반 (S1) — 미구현 시 0.5× 기본" - - "execution_cost_rate: 0.003 고정 ✓" - + - 'target_price: data_feed Target_Price (Naver 또는 Yahoo) ✓' + - 'entry_price: limit_price (entry_core.yaml limit_price_formula) ✓' + - 'stop_price: stop_price_est (B2 또는 실제값) △' + - 'bayesian_confidence_multiplier: performance 시트 기반 (S1) — 미구현 시 0.5× 기본' + - 'execution_cost_rate: 0.003 고정 ✓' B4_c2_now_computable: - purpose: "daily_leader_scan C2 바로 계산 가능" - formula: "Ret10D_종목(data_feed) - Ret10D_KOSPI(macro) >= 3%p" - status: "G2 완료로 계산 가능. LLM이 두 탭 조회 후 즉시 판단." - + purpose: daily_leader_scan C2 바로 계산 가능 + formula: Ret10D_종목(data_feed) - Ret10D_KOSPI(macro) >= 3%p + status: G2 완료로 계산 가능. LLM이 두 탭 조회 후 즉시 판단. B5_mrs_now_readable: - purpose: "MRS 자동 계산 결과 macro 탭에서 직접 읽기" - location: "macro 탭 Symbol='MRS_COMPUTED' 행 → Close=점수, Status='score=X/10 cash=Y%'" - usage: "LLM이 macro 탭을 읽으면 MRS 재계산 없이 즉시 확인 가능" - + purpose: MRS 자동 계산 결과 macro 탭에서 직접 읽기 + location: macro 탭 Symbol='MRS_COMPUTED' 행 → Close=점수, Status='score=X/10 cash=Y%' + usage: LLM이 macro 탭을 읽으면 MRS 재계산 없이 즉시 확인 가능 B6_flow_credit_v1_auto: - purpose: "FLOW_CREDIT_V1 자동 계산 — data_feed Flow_Credit 컬럼" + purpose: FLOW_CREDIT_V1 자동 계산 — data_feed Flow_Credit 컬럼 status: DONE - implementation: > - 2026-05-17 구현 완료. runDataFeed 루프 내 자동 계산. - fc_c1: close >= open OR close > prevClose → 0.30 - fc_c2: volume >= avgVolume5D × 1.20 → 0.30 - fc_c3: flow_ok AND (frg5 + inst5) > 0 → 0.40 - Hard override: C1=0 AND C2=0 → 0 (C3 단독 충족은 물량받기로 간주) - output_column: "data_feed Flow_Credit (0.00~1.00)" + implementation: '2026-05-17 구현 완료. runDataFeed 루프 내 자동 계산. fc_c1: close >= open + OR close > prevClose → 0.30 fc_c2: volume >= avgVolume5D × 1.20 → 0.30 fc_c3: + flow_ok AND (frg5 + inst5) > 0 → 0.40 Hard override: C1=0 AND C2=0 → 0 (C3 단독 + 충족은 물량받기로 간주) + ' + output_column: data_feed Flow_Credit (0.00~1.00) B7_trailing_stop_price_auto: - purpose: "TRAILING_STOP_PRICE_V1 자동 계산 — account_snapshot 최고가 기반" + purpose: TRAILING_STOP_PRICE_V1 자동 계산 — account_snapshot 최고가 기반 status: DONE - implementation: > - 2026-05-18 account_snapshot highest_price_since_entry 읽기/쓰기 통합 완료. - trailingStopPrice = highest_price_since_entry - ATR20 × 1.5 - account_snapshot에 highest_price_since_entry 미입력 시 공백. - output_column: "data_feed Trailing_Stop_Price (KRW 정수)" + implementation: '2026-05-18 account_snapshot highest_price_since_entry 읽기/쓰기 통합 + 완료. trailingStopPrice = highest_price_since_entry - ATR20 × 1.5 account_snapshot에 + highest_price_since_entry 미입력 시 공백. + ' + output_column: data_feed Trailing_Stop_Price (KRW 정수) B8_ss001_score_auto: - purpose: "SS001 종목 점수 자동 계산 — 6개 축 + 총점 + 등급" + purpose: SS001 종목 점수 자동 계산 — 6개 축 + 총점 + 등급 status: DONE - implementation: > - 2026-05-17 구현 완료. runDataFeed 루프 내 자동 계산. - SS001_P: core_satellite RS_Pct_20D → percentile=100-RS_Pct_20D → ≤30=25pt/30~60=15pt/>60=0pt - SS001_V: avgTradingValue5D/20D 비율 → ≥120%=15pt/80~120%=8pt/<80%=0pt - SS001_F: Flow_Credit → ≥0.70=25pt/0.40~0.70=12pt/<0.40=0pt - SS001_E: EPS_Revision_Status → UP=20pt/FLAT=10pt/DOWN=0pt + implementation: '2026-05-17 구현 완료. runDataFeed 루프 내 자동 계산. SS001_P: core_satellite + RS_Pct_20D → percentile=100-RS_Pct_20D → ≤30=25pt/30~60=15pt/>60=0pt SS001_V: + avgTradingValue5D/20D 비율 → ≥120%=15pt/80~120%=8pt/<80%=0pt SS001_F: Flow_Credit + → ≥0.70=25pt/0.40~0.70=12pt/<0.40=0pt SS001_E: EPS_Revision_Status → UP=20pt/FLAT=10pt/DOWN=0pt SS001_M: REGIME_PRELIM(전회 macro 결과) → RISK_ON/LEADER_CONCENTRATION=10pt/NEUTRAL=5pt/기타=0pt - SS001_VAL: KOSPI→PER/PBR vs 섹터중앙값(max 5pt), KOSDAQ→PEG 기반(max 12pt) - SS001_Total: 6개 합산 (KOSPI max 100, KOSDAQ max 107) - SS001_Grade: 100점 환산 ≥80=A / ≥65=B / ≥50=C / <50=D - output_columns: ["SS001_P","SS001_V","SS001_F","SS001_E","SS001_M","SS001_VAL","SS001_Total","SS001_Grade"] + SS001_VAL: KOSPI→PER/PBR vs 섹터중앙값(max 5pt), KOSDAQ→PEG 기반(max 12pt) SS001_Total: + 6개 합산 (KOSPI max 100, KOSDAQ max 107) SS001_Grade: 100점 환산 ≥80=A / ≥65=B / ≥50=C + / <50=D + + ' + output_columns: + - SS001_P + - SS001_V + - SS001_F + - SS001_E + - SS001_M + - SS001_VAL + - SS001_Total + - SS001_Grade data_dependency: - SS001_P: "core_satellite 탭 RS_Pct_20D 컬럼 (runCoreSatelliteFinalize 필요)" - SS001_M: "전회 runMacro 실행 결과 (초회 실행 시 0점)" - SS001_VAL: "sector_flow Sector_Median_PE/PBR (runSectorFlow 필요)" - limitation: "SS001_P는 core_satellite 탭이 비어있으면 0점 처리. 처음 사용 시 runCoreSatellite 먼저 실행." - + SS001_P: core_satellite 탭 RS_Pct_20D 컬럼 (runCoreSatelliteFinalize 필요) + SS001_M: 전회 runMacro 실행 결과 (초회 실행 시 0점) + SS001_VAL: sector_flow Sector_Median_PE/PBR (runSectorFlow 필요) + limitation: SS001_P는 core_satellite 탭이 비어있으면 0점 처리. 처음 사용 시 runCoreSatellite 먼저 + 실행. B9_peg_gate_auto: - purpose: "PEG 게이트 자동 계산 (KOSDAQ 종목 전용)" + purpose: PEG 게이트 자동 계산 (KOSDAQ 종목 전용) status: DONE - implementation: > - 2026-05-17 구현 완료. KOSDAQ_TICKERS Set 상수 추가 (현재 비어있음 — 보유 종목 모두 KOSPI). - KOSDAQ 종목에서 EPS_Growth_1Y_Pct > 0 이면: PEG = Forward_PE / EPS_Growth_1Y_Pct - PEG_Gate: PASS(≤1.5) / CAUTION(1.5~2.5) / REJECT(>2.5) - EPS 성장률 미수집 시: Fallback → sector_median_PE 대비 Forward_PE 배수로 대체 - output_columns: ["PEG","PEG_Gate"] + implementation: '2026-05-17 구현 완료. KOSDAQ_TICKERS Set 상수 추가 (현재 비어있음 — 보유 종목 모두 + KOSPI). KOSDAQ 종목에서 EPS_Growth_1Y_Pct > 0 이면: PEG = Forward_PE / EPS_Growth_1Y_Pct + PEG_Gate: PASS(≤1.5) / CAUTION(1.5~2.5) / REJECT(>2.5) EPS 성장률 미수집 시: Fallback + → sector_median_PE 대비 Forward_PE 배수로 대체 + ' + output_columns: + - PEG + - PEG_Gate B10_full_market_regime: - purpose: "MARKET_REGIME_V1 완전 판정 — macro+sector_flow 통합" + purpose: MARKET_REGIME_V1 완전 판정 — macro+sector_flow 통합 status: DONE - implementation: > - 2026-05-17 구현 완료. runMacro() 내에서 sector_flow 탭 읽기 추가. - (runSectorFlow()가 sector_flow 기록 완료 후 runMacro()가 호출되므로 최신값 읽기 가능) - 판정 우선순위: RISK_OFF > SECULAR_LEADER_RISK_ON > LEADER_CONCENTRATION > RISK_ON > NEUTRAL > RISK_OFF_CANDIDATE - RISK_OFF: MRS>=7 OR (VIX>=25 AND KOSPIMA20 - LEADER_CONCENTRATION: top2_sum>=100 AND top1_score>=55 AND top1_alertScore>=2 AND Tier1섹터 AND Ret20D>0 AND VIX<25 - RISK_ON: VIX<18 AND KOSPI>MA20 AND (MA20>=MA60 OR Ret20D>0) AND (sfFrg20>0 OR sfInst20>0 OR top2sum>=100) - NEUTRAL: MRS<=5 그 외 - RISK_OFF_CANDIDATE: MRS 5~6 - output: "REGIME_PRELIM 행 Close 컬럼 (Symbol=REGIME_PRELIM 유지 — 하위 호환)" - note: > - 이전 값이 'RISK_ON_CANDIDATE', 'RISK_OFF_CANDIDATE'이던 것이 'RISK_ON', 'RISK_OFF'로 변경됨. - SS001_M 점수 계산이 이제 정상 작동 (이전엔 항상 0점이었음). + implementation: '2026-05-17 구현 완료. runMacro() 내에서 sector_flow 탭 읽기 추가. (runSectorFlow()가 + sector_flow 기록 완료 후 runMacro()가 호출되므로 최신값 읽기 가능) 판정 우선순위: RISK_OFF > SECULAR_LEADER_RISK_ON + > LEADER_CONCENTRATION > RISK_ON > NEUTRAL > RISK_OFF_CANDIDATE RISK_OFF: MRS>=7 + OR (VIX>=25 AND KOSPIMA20 LEADER_CONCENTRATION: top2_sum>=100 AND top1_score>=55 + AND top1_alertScore>=2 AND Tier1섹터 AND Ret20D>0 AND VIX<25 RISK_ON: VIX<18 AND + KOSPI>MA20 AND (MA20>=MA60 OR Ret20D>0) AND (sfFrg20>0 OR sfInst20>0 OR top2sum>=100) + NEUTRAL: MRS<=5 그 외 RISK_OFF_CANDIDATE: MRS 5~6 + ' + output: REGIME_PRELIM 행 Close 컬럼 (Symbol=REGIME_PRELIM 유지 — 하위 호환) + note: '이전 값이 ''RISK_ON_CANDIDATE'', ''RISK_OFF_CANDIDATE''이던 것이 ''RISK_ON'', ''RISK_OFF''로 + 변경됨. SS001_M 점수 계산이 이제 정상 작동 (이전엔 항상 0점이었음). + + ' B11_net_return_feedback: - purpose: "net_return_feedback 상태 자동 계산 — RISK_BUDGET_CASCADE_V1 입력" + purpose: net_return_feedback 상태 자동 계산 — RISK_BUDGET_CASCADE_V1 입력 status: DONE - implementation: > - 2026-05-17 구현 완료. runMacro() 내 bayesianInfo(performance 탭) 재사용. - 규칙 (spec/05_position_sizing.yaml:net_return_feedback): - trades < 20건: NORMAL (규칙 미적용) - ne <= -2%: REDUCED — base_risk 0.007→0.003 삭감 권고 - ne <= 0%: CAUTION — high_confidence 금지, multiplier 0.5× 강제 - 연속손실 ≥5건 (bayesian no_bet와 별개로): NORMAL→CAUTION 승격 - 그 외: NORMAL - output: "macro 탭 NET_RETURN_FEEDBACK 행 (Symbol=NET_RETURN_FEEDBACK, Close=상태값)" - + implementation: "2026-05-17 구현 완료. runMacro() 내 bayesianInfo(performance 탭) 재사용.\ + \ 규칙 (spec/05_position_sizing.yaml:net_return_feedback):\n trades < 20건: NORMAL\ + \ (규칙 미적용)\n ne <= -2%: REDUCED — base_risk 0.007→0.003 삭감 권고\n ne <= 0%:\ + \ CAUTION — high_confidence 금지, multiplier 0.5× 강제\n 연속손실 ≥5건 (bayesian no_bet와\ + \ 별개로): NORMAL→CAUTION 승격\n 그 외: NORMAL\n" + output: macro 탭 NET_RETURN_FEEDBACK 행 (Symbol=NET_RETURN_FEEDBACK, Close=상태값) C1_orbit_gap_tracking: - purpose: "orbit_gap 자동 계산 — 월별 목표궤도 vs 실제 자산 추이 추적" + purpose: orbit_gap 자동 계산 — 월별 목표궤도 vs 실제 자산 추이 추적 status: DONE - implementation: > - 2026-05-17 구현 완료. spec/01_objective_profile.yaml:orbit_monthly_tracker 구현. - calcOrbitGap_(settings) 함수: 기하평균 보간으로 목표누적수익률 계산. - orbit_gap(%) = ((target/start)^(elapsed/total) - 1) - (current/start - 1) - orbit_state: significantly_behind(>3%p) / mild_behind(1~3%p) / on_track / ahead_of_target(<-2%p) - offensive_slot_adj: significantly_behind=+2, mild_behind=+1, on_track=0, ahead=0 - cash_floor_adj: significantly_behind=-2%p, mild_behind=-1%p, on_track=0, ahead=+1%p - runOrbitGap(): orbit_gap 탭에 현재 월 행 추가/갱신 (월 1회 독립 트리거) - runMacro(): ORBIT_GAP + ORBIT_STATE 2개 행 macro 탭에 자동 기록 + implementation: '2026-05-17 구현 완료. spec/01_objective_profile.yaml:orbit_monthly_tracker + 구현. calcOrbitGap_(settings) 함수: 기하평균 보간으로 목표누적수익률 계산. orbit_gap(%) = ((target/start)^(elapsed/total) + - 1) - (current/start - 1) orbit_state: significantly_behind(>3%p) / mild_behind(1~3%p) + / on_track / ahead_of_target(<-2%p) offensive_slot_adj: significantly_behind=+2, + mild_behind=+1, on_track=0, ahead=0 cash_floor_adj: significantly_behind=-2%p, + mild_behind=-1%p, on_track=0, ahead=+1%p runOrbitGap(): orbit_gap 탭에 현재 월 행 + 추가/갱신 (월 1회 독립 트리거) runMacro(): ORBIT_GAP + ORBIT_STATE 2개 행 macro 탭에 자동 기록 + + ' required_settings: - - "orbit_start_asset_krw — 시작 자산 (1월 기준)" - - "orbit_target_asset_krw — 목표 자산 (예: 5억)" - - "orbit_start_yyyymm — 추적 시작 연월 (예: 2026-01)" - - "orbit_end_yyyymm — 목표 달성 기한 (예: 2028-12)" - - "total_asset_krw — 현재 자산 (기존 settings 항목 재사용)" + - orbit_start_asset_krw — 시작 자산 (1월 기준) + - 'orbit_target_asset_krw — 목표 자산 (예: 5억)' + - 'orbit_start_yyyymm — 추적 시작 연월 (예: 2026-01)' + - 'orbit_end_yyyymm — 목표 달성 기한 (예: 2028-12)' + - total_asset_krw — 현재 자산 (기존 settings 항목 재사용) output: - macro_tab: "ORBIT_GAP 행(Close=gap %p), ORBIT_STATE 행(Close=상태, Status=slot/cash 조정값)" - orbit_gap_tab: "Month/Start_Asset/Target_Asset/Actual_Asset/Target_Return_Pct/Actual_Return_Pct/Orbit_Gap_Pct/Orbit_State/Slot_Adj/Cash_Floor_Adj/Updated" + macro_tab: ORBIT_GAP 행(Close=gap %p), ORBIT_STATE 행(Close=상태, Status=slot/cash + 조정값) + orbit_gap_tab: Month/Start_Asset/Target_Asset/Actual_Asset/Target_Return_Pct/Actual_Return_Pct/Orbit_Gap_Pct/Orbit_State/Slot_Adj/Cash_Floor_Adj/Updated api_exposure: - getMacroJson: "orbit_gap_pct, orbit_state, orbit_slot_adj, orbit_cash_adj" - getSummaryJson: "macro_snapshot.orbit_gap_pct, orbit_state, orbit_slot_adj" - limitation: "settings 탭에 4개 orbit_* 파라미터 미입력 시 ORBIT_GAP=N/A 기록 (runOrbitGap 스킵)" - + getMacroJson: orbit_gap_pct, orbit_state, orbit_slot_adj, orbit_cash_adj + getSummaryJson: macro_snapshot.orbit_gap_pct, orbit_state, orbit_slot_adj + limitation: settings 탭에 4개 orbit_* 파라미터 미입력 시 ORBIT_GAP=N/A 기록 (runOrbitGap 스킵) C2_take_profit_ladder: - purpose: "TAKE_PROFIT_LADDER_V1 자동 계산 — core/satellite 분리 익절 사다리" + purpose: TAKE_PROFIT_LADDER_V1 자동 계산 — core/satellite 분리 익절 사다리 status: DONE - implementation: > - 2026-05-18 account_snapshot average_cost + holding_quantity + position_type 기반으로 변경. - core: TP1=+15%(25% 물량), TP2=+25%(잔여 40% 물량). - satellite: TP1=+10%(50% 물량), TP2=+20%(잔여 50% 물량). - Time_Stop: stage_1=60일, stage_2=30일 (entry_date 기준 만료일 + 잔여일수). - output_columns: - data_feed: ["TP1_Price","TP1_Qty","TP2_Price","TP2_Qty","Time_Stop_Date","Days_To_Time_Stop"] - required_account_snapshot_fields: ["average_cost","holding_quantity","position_type","entry_date","entry_stage"] + implementation: '2026-05-18 account_snapshot average_cost + holding_quantity + + position_type 기반으로 변경. core: TP1=+15%(25% 물량), TP2=+25%(잔여 40% 물량). satellite: + TP1=+10%(50% 물량), TP2=+20%(잔여 50% 물량). Time_Stop: stage_1=60일, stage_2=30일 (entry_date + 기준 만료일 + 잔여일수). + ' + output_columns: + data_feed: + - TP1_Price + - TP1_Qty + - TP2_Price + - TP2_Qty + - Time_Stop_Date + - Days_To_Time_Stop + required_account_snapshot_fields: + - average_cost + - holding_quantity + - position_type + - entry_date + - entry_stage C3_position_monitoring: - purpose: "포지션 모니터링 컬럼 자동 계산 — 비중/수익률/PnL/스테이지/밴드" + purpose: 포지션 모니터링 컬럼 자동 계산 — 비중/수익률/PnL/스테이지/밴드 status: DONE - implementation: > - 2026-05-18 account_snapshot + 당일 종가 기반으로 변경. - Weight_Pct: close × quantity / total_asset_krw × 100. - Profit_Pct: (close - entry_price) / entry_price × 100. - Unrealized_PnL: (close - entry_price) × quantity (KRW 정수). - Stage2_Gate: stage_1 포지션에서 가격 +1.5% 이상 시 PASS, 아니면 PENDING. - Band_Status: satellite 단일종목 7% 상한. OVERWEIGHT/IN_BAND/UNDERWEIGHT. - core는 CORE_HIGH(>10%)/CORE_MID(3~10%)/CORE_LOW(<3%). + implementation: "2026-05-18 account_snapshot + 당일 종가 기반으로 변경. Weight_Pct: close\ + \ × quantity / total_asset_krw × 100. Profit_Pct: (close - entry_price) / entry_price\ + \ × 100. Unrealized_PnL: (close - entry_price) × quantity (KRW 정수). Stage2_Gate:\ + \ stage_1 포지션에서 가격 +1.5% 이상 시 PASS, 아니면 PENDING. Band_Status: satellite 단일종목\ + \ 7% 상한. OVERWEIGHT/IN_BAND/UNDERWEIGHT.\n core는 CORE_HIGH(>10%)/CORE_MID(3~10%)/CORE_LOW(<3%).\n" output_columns: - data_feed: ["Weight_Pct","Profit_Pct","Unrealized_PnL","Stage2_Gate","Band_Status"] - + data_feed: + - Weight_Pct + - Profit_Pct + - Unrealized_PnL + - Stage2_Gate + - Band_Status D1_bucket_allocation_status: - purpose: "포트폴리오 버킷 할당 상태 자동 계산 — core/satellite/cash 합계 vs 목표 범위" + purpose: 포트폴리오 버킷 할당 상태 자동 계산 — core/satellite/cash 합계 vs 목표 범위 status: DONE - implementation: > - 2026-05-17 구현 완료. runDataFeed 루프에서 버킷별 Weight_Pct 누산. - calcBucketStatus_() 함수: _bucketSnapshot_ 기반 bucket-level 집계. - 목표 범위 (spec/risk): core 60-72%, satellite 10-25%, cash 10-22%. - cash_pct = max(0, 100 - core_pct - satellite_pct) (추정값 — account_snapshot 미연동). - overall: BALANCED / core_UNDERWEIGHT | sat_OVERWEIGHT 등 파이프 구분. - output: - macro_tab: "BUCKET_STATUS 행(Close=overall, Status=core/sat/cash 상세)" - api_exposure: - getMacroJson: "bucket_status, bucket_detail" - getSummaryJson: "macro_snapshot.bucket_status, bucket_detail" - limitation: > - cash_pct는 account_snapshot 마켓밸류를 total_asset에서 뺀 추정값. - 실제 현금은 account_snapshot 없이 확인 불가. - runDataFeed 실행 없이 runMacro만 실행하면 N/A. + implementation: '2026-05-17 구현 완료. runDataFeed 루프에서 버킷별 Weight_Pct 누산. calcBucketStatus_() + 함수: _bucketSnapshot_ 기반 bucket-level 집계. 목표 범위 (spec/risk): core 60-72%, satellite + 10-25%, cash 10-22%. cash_pct = max(0, 100 - core_pct - satellite_pct) (추정값 + — account_snapshot 미연동). overall: BALANCED / core_UNDERWEIGHT | sat_OVERWEIGHT + 등 파이프 구분. + ' + output: + macro_tab: BUCKET_STATUS 행(Close=overall, Status=core/sat/cash 상세) + api_exposure: + getMacroJson: bucket_status, bucket_detail + getSummaryJson: macro_snapshot.bucket_status, bucket_detail + limitation: 'cash_pct는 account_snapshot 마켓밸류를 total_asset에서 뺀 추정값. 실제 현금은 account_snapshot + 없이 확인 불가. runDataFeed 실행 없이 runMacro만 실행하면 N/A. + + ' phase_4_backdata_collection: B1_gas_backdata_feature_bank: priority: HIGH status: DONE - purpose: > - 매수/매도 뒷북과 설거지 패턴을 줄이기 위한 진입-청산 백데이터 원장. - 사람 입력보다 GAS 자동 수집을 1순위로 두고, 사람이 입력한 performance 기록은 - 보조 검증용 fallback으로만 사용한다. + purpose: '매수/매도 뒷북과 설거지 패턴을 줄이기 위한 진입-청산 백데이터 원장. 사람 입력보다 GAS 자동 수집을 1순위로 두고, + 사람이 입력한 performance 기록은 보조 검증용 fallback으로만 사용한다. + + ' collection_priority: - 1: "GAS가 생성한 backdata_feature_bank 시트/JSON" - 2: "performance 시트의 청산 완료 거래" - 3: "수동 보정값" + 1: GAS가 생성한 backdata_feature_bank 시트/JSON + 2: performance 시트의 청산 완료 거래 + 3: 수동 보정값 required_signals: - - "entry_stage" - - "entry_leader_scan_total" - - "entry_c1_score" - - "entry_c2_score" - - "entry_c3_score" - - "entry_c4_score" - - "entry_c5_score" - - "entry_mrs_score" - - "entry_close_vs_ma20_pct" - - "entry_volume_ratio_5d" - - "entry_flow_credit" - - "entry_breakout_score" - - "entry_late_chase_risk_score" - - "entry_follow_through_score" - - "pnl_pct" - - "holding_days" - - "max_adverse_excursion_pct" - - "max_favorable_excursion_pct" + - entry_stage + - entry_leader_scan_total + - entry_c1_score + - entry_c2_score + - entry_c3_score + - entry_c4_score + - entry_c5_score + - entry_mrs_score + - entry_close_vs_ma20_pct + - entry_volume_ratio_5d + - entry_flow_credit + - entry_breakout_score + - entry_late_chase_risk_score + - entry_follow_through_score + - pnl_pct + - holding_days + - max_adverse_excursion_pct + - max_favorable_excursion_pct implementation_plan: step_1: - action: "GAS에서 daily setup snapshot을 backdata_feature_bank 시트로 자동 upsert" + action: GAS에서 daily setup snapshot을 backdata_feature_bank 시트로 자동 upsert status: DONE - note: "syncBackdataFeatureBank_() — gdc_01_fetch_fundamentals.gs:1128, gdf_02_harness_assembly.gs:146" + note: syncBackdataFeatureBank_() — gdc_01_fetch_fundamentals.gs:1128, gdf_02_harness_assembly.gs:146 step_2: - action: "performance 시트 청산 결과와 join해 outcome label을 자동 부여" + action: performance 시트 청산 결과와 join해 outcome label을 자동 부여 status: DONE - note: "buildBackdataFeatureBankRowsV1_() — mapLatestPerformanceByTicker_ 기반 join" + note: buildBackdataFeatureBankRowsV1_() — mapLatestPerformanceByTicker_ 기반 + join step_3: - action: "convert_xlsx_to_json.py에서 backdata_feature_bank_json 우선 수집" + action: convert_xlsx_to_json.py에서 backdata_feature_bank_json 우선 수집 status: DONE - note: "src/quant_engine/convert_xlsx_to_json.py:synthesize_backdata_feature_bank() 구현" + note: src/quant_engine/convert_xlsx_to_json.py:synthesize_backdata_feature_bank() + 구현 step_4: - action: "backdata_feature_bank_table을 report/validation에 반영" + action: backdata_feature_bank_table을 report/validation에 반영 status: DONE - note: "render_operational_report.py:_backdata_feature_bank_table(), validate_harness_context.py 검증" + note: render_operational_report.py:_backdata_feature_bank_table(), validate_harness_context.py + 검증 fallback_policy: - manual_input: "performance 시트 또는 수동 보정은 fallback일 뿐 primary source가 아니다." - missing_action: "GAS 생성본이 없으면 fallback 기록과 함께 source_origin=FALLBACK_SYNTH로 남긴다." - implementation_note: > - 2026-06-14 구현 완료 확인. GAS(syncBackdataFeatureBank_) + Python(synthesize_backdata_feature_bank) + manual_input: performance 시트 또는 수동 보정은 fallback일 뿐 primary source가 아니다. + missing_action: GAS 생성본이 없으면 fallback 기록과 함께 source_origin=FALLBACK_SYNTH로 남긴다. + implementation_note: '2026-06-14 구현 완료 확인. GAS(syncBackdataFeatureBank_) + Python(synthesize_backdata_feature_bank) 모두 구현됨. T+20 데이터 누적 후 ML 패턴 학습 품질 향상 예정. -# ───────────────────────────────────────────────────────────────────────────── -# 5단계 — CI 기반 데이터 플랫폼 전환 -# ───────────────────────────────────────────────────────────────────────────── + ' phase_5_platform_transition: P1_kis_core_api_collector: priority: HIGH status: DONE - purpose: > - KIS Open API를 read-only 코어 수집원으로 두고, 가격/호가/공매도/수급의 - 1차 수집을 Python canonical collector에서 직접 수행한다. + purpose: 'KIS Open API를 read-only 코어 수집원으로 두고, 가격/호가/공매도/수급의 1차 수집을 Python canonical + collector에서 직접 수행한다. + + ' inputs: - - "KIS_APP_Key / KIS_APP_Secret" - - "KIS_APP_Key_TEST / KIS_APP_Secret_TEST" - - "GatherTradingData.json" + - KIS_APP_Key / KIS_APP_Secret + - KIS_APP_Key_TEST / KIS_APP_Secret_TEST + - GatherTradingData.json outputs: - - "Temp/kis_data_collection_v1.json" - - "outputs/kis_data_collection/kis_data_collection.db" + - Temp/kis_data_collection_v1.json + - outputs/kis_data_collection/kis_data_collection.db fallback_order: - - "KIS Open API" - - "Naver Finance" - - "Yahoo Finance" - - "OpenDART" - - "Investing.com(best-effort, 차단 시 DATA_MISSING)" - note: > - 주문 API는 사용하지 않는다. 조회형 quotations/ranking 계열만 허용한다. + - KIS Open API + - Naver Finance + - Yahoo Finance + - OpenDART + - Investing.com(best-effort, 차단 시 DATA_MISSING) + note: '주문 API는 사용하지 않는다. 조회형 quotations/ranking 계열만 허용한다. + + ' success_criteria: expected_success_value: - collector_gate: "PASS" - output_json_gate: "PASS" + collector_gate: PASS + output_json_gate: PASS sqlite_run_count_min: 1 sqlite_snapshot_count_min: 1 provenance_source_count_min: 1 evidence_artifacts: - - "Temp/test_kis_data_collection.json" - - "Temp/test_kis_data_collection.db" + - Temp/test_kis_data_collection.json + - Temp/test_kis_data_collection.db verification_commands: - - "python tools/run_kis_data_collection_v1.py --input-json GatherTradingData.json --sqlite-db Temp/test_kis_data_collection.db --output-json Temp/test_kis_data_collection.json --kis-account real --no-live-kis --no-naver" - - "python - <<'PY' ... sqlite count check ... PY" - + - python tools/run_kis_data_collection_v1.py --input-json GatherTradingData.json + --sqlite-db Temp/test_kis_data_collection.db --output-json Temp/test_kis_data_collection.json + --kis-account real --no-live-kis --no-naver + - python - <<'PY' ... sqlite count check ... PY P2_sqlite_canonical_store: priority: HIGH status: DONE - purpose: > - xlsx 중심 저장을 중단하고, 수집 결과를 SQLite에 누적 저장한다. - 향후 PostgreSQL 승격 시 동일 저장 인터페이스를 유지한다. + purpose: 'xlsx 중심 저장을 중단하고, 수집 결과를 SQLite에 누적 저장한다. 향후 PostgreSQL 승격 시 동일 저장 인터페이스를 + 유지한다. + + ' required_tables: - - "collection_runs" - - "collection_snapshots" - - "collection_source_errors" + - collection_runs + - collection_snapshots + - collection_source_errors stored_payloads: - - "raw source payload" - - "normalized factor row" - - "provenance JSON" - - "batch/run metadata" - migration_note: "PostgreSQL 전환 시 dialect만 교체하고 row shape은 유지한다." + - raw source payload + - normalized factor row + - provenance JSON + - batch/run metadata + migration_note: PostgreSQL 전환 시 dialect만 교체하고 row shape은 유지한다. success_criteria: expected_success_value: sqlite_schema_tables_min: 3 - round_trip_snapshot_lookup: "PASS" - backend_contract_sqlite: "PASS" - backend_contract_postgresql: "READY" + round_trip_snapshot_lookup: PASS + backend_contract_sqlite: PASS + backend_contract_postgresql: READY evidence_artifacts: - - "src/quant_engine/data_collection_store_v1.py" - - "src/quant_engine/data_collection_backend_v1.py" - - "tests/unit/test_data_collection_store_v1.py" + - src/quant_engine/data_collection_store_v1.py + - src/quant_engine/data_collection_backend_v1.py + - tests/unit/test_data_collection_store_v1.py verification_commands: - - "python -m pytest tests/unit/test_data_collection_store_v1.py -q" - - "python -m py_compile src/quant_engine/data_collection_store_v1.py src/quant_engine/data_collection_backend_v1.py" - + - python -m pytest tests/unit/test_data_collection_store_v1.py -q + - python -m py_compile src/quant_engine/data_collection_store_v1.py src/quant_engine/data_collection_backend_v1.py P3_ci_scheduler_cutover: priority: HIGH status: DONE - purpose: > - Gitea schedule에서 Python collector를 직접 실행하고, CI가 SQLite 산출을 검증한다. - 기존 GAS 워크플로우는 thin adapter/legacy fallback으로만 유지한다. + purpose: 'Gitea schedule에서 Python collector를 직접 실행하고, CI가 SQLite 산출을 검증한다. 기존 + GAS 워크플로우는 thin adapter/legacy fallback으로만 유지한다. + + ' validation_gate: - - "read-only KIS gate" - - "source fallback gate" - - "sqlite round-trip gate" - - "provenance completeness gate" - - "no-direct-trading gate" + - read-only KIS gate + - source fallback gate + - sqlite round-trip gate + - provenance completeness gate + - no-direct-trading gate output_policy: - - "CI는 xlsx 생성에 의존하지 않는다." - - "결과는 JSON + SQLite + 로그 증빙으로 남긴다." + - CI는 xlsx 생성에 의존하지 않는다. + - 결과는 JSON + SQLite + 로그 증빙으로 남긴다. success_criteria: expected_success_value: xlsx_dependency_removed: true json_seed_input: true sqlite_output: true - mock_api_validation: "PASS" - no_direct_trading_gate: "PASS" - provenance_completeness_gate: "PASS" - notes: > - `GatherTradingData.xlsx`는 runtime seed 재생성 fallback으로만 허용한다. - collector 본문은 `GatherTradingData.json`만 사용하며, xlsx는 Prepare Raw Seed Snapshot - 단계에서만 허용된다. - evidence_artifacts: - - ".gitea/workflows/kis_data_collection.yml" - - "Temp/kis_api_credentials_validation_v1.json" - - "Temp/test_kis_data_collection.json" - verification_commands: - - "python tools/validate_no_direct_api_trading_v1.py" - - "python tools/validate_kis_api_credentials_v1.py --account mock --ticker 005930" - - "python tools/run_kis_data_collection_v1.py --help" + mock_api_validation: PASS + no_direct_trading_gate: PASS + provenance_completeness_gate: PASS + notes: '`GatherTradingData.xlsx`는 runtime seed 재생성 fallback으로만 허용한다. collector + 본문은 `GatherTradingData.json`만 사용하며, xlsx는 Prepare Raw Seed Snapshot 단계에서만 + 허용된다. + ' + evidence_artifacts: + - .gitea/workflows/kis_data_collection.yml + - Temp/kis_api_credentials_validation_v1.json + - Temp/test_kis_data_collection.json + verification_commands: + - python tools/validate_no_direct_api_trading_v1.py + - python tools/validate_kis_api_credentials_v1.py --account mock --ticker 005930 + - python tools/run_kis_data_collection_v1.py --help P4_gas_thin_adapter_minimize: priority: MEDIUM status: DONE - purpose: > - .gs는 기존 스프레드시트 호환과 과도기 검증용 얇은 어댑터만 남기고, - 판단·수집·저장 로직은 Python으로 이동시킨다. + purpose: '.gs는 기존 스프레드시트 호환과 과도기 검증용 얇은 어댑터만 남기고, 판단·수집·저장 로직은 Python으로 이동시킨다. + + ' allowed_responsibilities: - - "collect" - - "normalize" - - "export" - - "display" + - collect + - normalize + - export + - display forbidden_responsibilities: - - "decision" - - "sizing" - - "stop_loss" - - "take_profit" - - "risk_score" + - decision + - sizing + - stop_loss + - take_profit + - risk_score success_criteria: expected_success_value: allowed_responsibilities_only: true forbidden_responsibilities_present: false - thin_adapter_gate: "PASS" + thin_adapter_gate: PASS evidence_artifacts: - - "tools/validate_gas_thin_adapter_v1.py" - - "Temp/gas_thin_adapter_validation_v1.json" - - "src/gas/core/gas_lib.gs" + - tools/validate_gas_thin_adapter_v1.py + - Temp/gas_thin_adapter_validation_v1.json + - src/gas/core/gas_lib.gs verification_commands: - - "python tools/validate_gas_thin_adapter_v1.py" - + - python tools/validate_gas_thin_adapter_v1.py P5_postgresql_upgrade_path: priority: MEDIUM status: DONE - purpose: > - SQLite에서 검증된 스키마/업서트/프로venance 모델을 PostgreSQL로 승격한다. - 운영 데이터 증가와 멀티잡 동시성 증가를 대비한다. + purpose: 'SQLite에서 검증된 스키마/업서트/프로venance 모델을 PostgreSQL로 승격한다. 운영 데이터 증가와 멀티잡 + 동시성 증가를 대비한다. + + ' upgrade_steps: - - "sqlite schema parity 검증" - - "db_url 기반 backend 추상화" - - "migration script 추가" - - "CI에서 sqlite/postgres 동일 테스트" - compatibility_rule: "SQLite와 PostgreSQL 모두 동일한 row contract를 유지한다." + - sqlite schema parity 검증 + - db_url 기반 backend 추상화 + - migration script 추가 + - CI에서 sqlite/postgres 동일 테스트 + compatibility_rule: SQLite와 PostgreSQL 모두 동일한 row contract를 유지한다. success_criteria: expected_success_value: - sqlite_schema_parity: "PASS" + sqlite_schema_parity: PASS backend_contract_present: true - postgres_execution: "DATA_GATED" + postgres_execution: DATA_GATED caller_compatibility_preserved: true evidence_artifacts: - - "src/quant_engine/data_collection_backend_v1.py" - - "src/quant_engine/kis_data_collection_v1.py" - - "tests/unit/test_data_collection_store_v1.py" - - "tools/generate_postgresql_upgrade_stub_v1.py" + - src/quant_engine/data_collection_backend_v1.py + - src/quant_engine/kis_data_collection_v1.py + - tests/unit/test_data_collection_store_v1.py + - tools/generate_postgresql_upgrade_stub_v1.py verification_commands: - - "python -m pytest tests/unit/test_data_collection_store_v1.py -q" - - "python -m py_compile src/quant_engine/kis_data_collection_v1.py tools/run_kis_data_collection_v1.py" - - "python tools/generate_postgresql_upgrade_stub_v1.py" - + - python -m pytest tests/unit/test_data_collection_store_v1.py -q + - python -m py_compile src/quant_engine/kis_data_collection_v1.py tools/run_kis_data_collection_v1.py + - python tools/generate_postgresql_upgrade_stub_v1.py Q1_qualitative_sell_pipeline: priority: MEDIUM status: PLANNED - purpose: > - 비기계적 매도전략 파이프라인을 Gitea workflow + SQLite 시계열 + mock KIS 유효성 - 검증 + 사후 적중률 평가까지 일관된 계약으로 묶는다. + purpose: '비기계적 매도전략 파이프라인을 Gitea workflow + SQLite 시계열 + mock KIS 유효성 검증 + 사후 + 적중률 평가까지 일관된 계약으로 묶는다. + + ' success_criteria: expected_success_value: - mock_api_validation: "PASS" - pipeline_contract: "PASS" + mock_api_validation: PASS + pipeline_contract: PASS workflow_present: true schedule_present: true package_scripts_present: true evidence_artifacts: - - ".gitea/workflows/qualitative_sell_strategy.yml" - - "tools/validate_qualitative_sell_strategy_pipeline_v1.py" - - "Temp/qualitative_sell_strategy_pipeline_v1.json" + - .gitea/workflows/qualitative_sell_strategy.yml + - tools/validate_qualitative_sell_strategy_pipeline_v1.py + - Temp/qualitative_sell_strategy_pipeline_v1.json verification_commands: - - "python tools/validate_qualitative_sell_strategy_pipeline_v1.py" - + - python tools/validate_qualitative_sell_strategy_pipeline_v1.py Q2_gitea_secrets_contract: priority: HIGH status: PLANNED - purpose: > - Gitea workflow에서 KIS mock/real 자격증명과 GITHUB_TOKEN 시크릿 이름을 - 정확히 고정해, 수동 등록 실수로 인한 파이프라인 붕괴를 방지한다. + purpose: 'Gitea workflow에서 KIS mock/real 자격증명과 GITHUB_TOKEN 시크릿 이름을 정확히 고정해, 수동 + 등록 실수로 인한 파이프라인 붕괴를 방지한다. + + ' success_criteria: expected_success_value: - secrets_contract: "PASS" - workflow_secret_mapping: "PASS" + secrets_contract: PASS + workflow_secret_mapping: PASS docs_present: true ci_validation_present: true evidence_artifacts: - - "docs/GITEA_SECRETS_SETUP.md" - - "tools/validate_gitea_secrets_contract_v1.py" - - "Temp/gitea_secrets_contract_v1.json" + - docs/GITEA_SECRETS_SETUP.md + - tools/validate_gitea_secrets_contract_v1.py + - Temp/gitea_secrets_contract_v1.json verification_commands: - - "python tools/validate_gitea_secrets_contract_v1.py" - -# 2026-05-30 구현 현황 -# - S5_etf_raw: PARTIAL_DONE 유지 (수동 NAV 병행) -# - Stage2_Gate PENDING: T+20 표본 누적 후 자동 평가 -# - 주요 지표: outcome_quality=85.23(PASS) guidance_proof=99.26(PASS) -# - 미수집 펀더멘털(ROE/OPM/FCF/Revenue): CHECK_58/59 해결 시 자동 개선 - -# ───────────────────────────────────────────────────────────────────────────── -# WBS-7.8 (ETF NAV 자동 수집) — 기술장벽 확정 & 운영절차 명문화 -# ───────────────────────────────────────────────────────────────────────────── + - python tools/validate_gitea_secrets_contract_v1.py phase_wbs_7_8_etf_nav_automation: status: BLOCKED_TECHNICAL_BARRIER wbs_ref: WBS-7.8 - deadline: "2026-12-31" - problem_statement: > - ETF NAV, 괴리율, 추적오차, AUM 자동 수집이 미구현. 현재는 etf_nav_manual 탭에 - 수동 입력만 가능. - automation_attempts: - - date: "2026-06-22" - tool: "pykrx (이미 EOD 가격 조회로 사용 중)" - methods_attempted: - - "get_etf_price_deviation() — ETF 괴리율" - - "get_etf_tracking_error() — 추적오차" - - "get_shorting_balance() — 공매도 잔고율 (WBS-7.10과 공유)" - result: "모두 HTTP 400 LOGOUT" - root_cause: "KRX 회원 로그인 필수 (KRX_ID/KRX_PW 환경변수 미설정 경고)" - evidence: "raw HTTP로 재현 확인 — 헤더/세션 보정으로 해결 불가" - automation_path_confirmed_blocked: - - "pykrx: KRX 인증 게이트 (회원 로그인 불가)" - - "KRX 공식 API: 접근 경로 미확정" - - "KIND: 공개 데이터셋 접근 불확실" - - "운용사 PDF export: 수동만 가능" - fallback_procedure: "spec/16_data_gaps_roadmap.yaml:S5_etf_raw.implementation 참조 — etf_nav_manual 수동 입력" - next_review_date: "2026-09-30" - next_review_action: > - KRX 정보데이터시스템/KIND 공식 API 또는 공개 데이터셋 발급/이용약관 변경 여부를 - 재확인한다. 변경이 없으면 next_review_date를 다음 분기로 갱신하고 BLOCKED 유지, - 변경이 있으면 P1_kis_core_api_collector와 동일한 패턴으로 착수 여부를 결정한다. - implementation_note: > - 2026-06-22 WBS-7.8 기술장벽 최종 확정. 자동화 불가능하므로 운영절차를 - 명문화한다. etf_nav_manual 수동 경로 외에 대체 경로 없음. + deadline: '2026-12-31' + problem_statement: 'ETF NAV, 괴리율, 추적오차, AUM 자동 수집이 미구현. 현재는 etf_nav_manual 탭에 수동 + 입력만 가능. -# ───────────────────────────────────────────────────────────────────────────── -# WBS-7.10 (공매도 잔고율 자동화) — 기술장벽 확정 & 운영절차 명문화 -# ───────────────────────────────────────────────────────────────────────────── + ' + automation_attempts: + - date: '2026-06-22' + tool: pykrx (이미 EOD 가격 조회로 사용 중) + methods_attempted: + - get_etf_price_deviation() — ETF 괴리율 + - get_etf_tracking_error() — 추적오차 + - get_shorting_balance() — 공매도 잔고율 (WBS-7.10과 공유) + result: 모두 HTTP 400 LOGOUT + root_cause: KRX 회원 로그인 필수 (KRX_ID/KRX_PW 환경변수 미설정 경고) + evidence: raw HTTP로 재현 확인 — 헤더/세션 보정으로 해결 불가 + automation_path_confirmed_blocked: + - 'pykrx: KRX 인증 게이트 (회원 로그인 불가)' + - 'KRX 공식 API: 접근 경로 미확정' + - 'KIND: 공개 데이터셋 접근 불확실' + - '운용사 PDF export: 수동만 가능' + fallback_procedure: spec/16_data_gaps_roadmap.yaml:S5_etf_raw.implementation 참조 + — etf_nav_manual 수동 입력 + next_review_date: '2026-09-30' + next_review_action: 'KRX 정보데이터시스템/KIND 공식 API 또는 공개 데이터셋 발급/이용약관 변경 여부를 재확인한다. 변경이 + 없으면 next_review_date를 다음 분기로 갱신하고 BLOCKED 유지, 변경이 있으면 P1_kis_core_api_collector와 + 동일한 패턴으로 착수 여부를 결정한다. + + ' + implementation_note: '2026-06-22 WBS-7.8 기술장벽 최종 확정. 자동화 불가능하므로 운영절차를 명문화한다. etf_nav_manual + 수동 경로 외에 대체 경로 없음. + + ' phase_wbs_7_10_shorting_balance_automation: status: MANUAL_CSV_ONLY wbs_ref: WBS-7.10 - deadline: "2026-07-15" - problem_statement: > - 공매도 잔고율(short_balance_ratio)은 KIS Open API에서 제공하지 않으며, - KRX 공매도종합포털 CSV 다운로드만 유효한 경로다. 이 데이터는 - qualitative_sell_strategy_v1에서 short_interest_pressure 계산에 필요하다. + deadline: '2026-07-15' + problem_statement: '공매도 잔고율(short_balance_ratio)은 KIS Open API에서 제공하지 않으며, KRX 공매도종합포털 + CSV 다운로드만 유효한 경로다. 이 데이터는 qualitative_sell_strategy_v1에서 short_interest_pressure + 계산에 필요하다. + + ' data_source: - official: "KRX 공매도종합포털 (data.krx.co.kr/contents/MDC/MDI/mdioper/BBGO1910/)" - format: "일일 CSV 다운로드 (날짜별 종목별 공매도 잔고 %)" - coverage: "KOSPI/KOSDAQ 전 상장종목" - update_frequency: "일일 (T+1, 오전 10시경)" + official: KRX 공매도종합포털 (data.krx.co.kr/contents/MDC/MDI/mdioper/BBGO1910/) + format: 일일 CSV 다운로드 (날짜별 종목별 공매도 잔고 %) + coverage: KOSPI/KOSDAQ 전 상장종목 + update_frequency: 일일 (T+1, 오전 10시경) kis_api_check: - status: "NOT_PROVIDED" - verification: "KIS Open API 공식 문서 검색, 임금운용 담당자 확인" + status: NOT_PROVIDED + verification: KIS Open API 공식 문서 검색, 임금운용 담당자 확인 alternative_kis_endpoints: [] krx_direct_check: - status: "BLOCKED_KRX_MEMBER_LOGIN" - tool: "pykrx.get_shorting_balance()" - error: "HTTP 400 LOGOUT (KRX_ID/KRX_PW 환경변수 미설정)" - root_cause: "KRX 회원 계정 필수, 헤더/세션 보정 불가" - date_confirmed: "2026-06-22" + status: BLOCKED_KRX_MEMBER_LOGIN + tool: pykrx.get_shorting_balance() + error: HTTP 400 LOGOUT (KRX_ID/KRX_PW 환경변수 미설정) + root_cause: KRX 회원 계정 필수, 헤더/세션 보정 불가 + date_confirmed: '2026-06-22' workaround_procedure: - method: "수동 KRX CSV 다운로드 경로" + method: 수동 KRX CSV 다운로드 경로 steps: - - "1. KRX 공매도종합포털 접속 (로그인 필요: 일반 계정, 증권회원사 계정, KRX 회원사 계정 모두 가능)" - - "2. '당일 공매도현황' 탭에서 종목 선택 또는 전체 다운로드" - - "3. CSV 파일 저장: spec 문서에 기입된 경로 (예: Temp/shorting_balance_manual_YYYY-MM-DD.csv)" - - "4. build_qualitative_sell_inputs_v1.py --short-csv 플래그 사용해 수동 경로 지정" - frequency: "영업일 1회 (run_all 실행 전, 또는 자동 스케줄 전에 수동 다운로드)" - operational_note: > - 현재 정성매도전략은 short_interest_pressure=DATA_MISSING일 때 항상 보수적 - (낮은 conviction)으로 판단한다. 공매도 데이터가 없으면 다른 4개 신호만 사용해 - 결정하므로, 영업 중단 가능성은 없다 — 다만 정밀도 제한. + - '1. KRX 공매도종합포털 접속 (로그인 필요: 일반 계정, 증권회원사 계정, KRX 회원사 계정 모두 가능)' + - 2. '당일 공매도현황' 탭에서 종목 선택 또는 전체 다운로드 + - '3. CSV 파일 저장: spec 문서에 기입된 경로 (예: Temp/shorting_balance_manual_YYYY-MM-DD.csv)' + - 4. build_qualitative_sell_inputs_v1.py --short-csv 플래그 사용해 수동 경로 지정 + frequency: 영업일 1회 (run_all 실행 전, 또는 자동 스케줄 전에 수동 다운로드) + operational_note: '현재 정성매도전략은 short_interest_pressure=DATA_MISSING일 때 항상 보수적 (낮은 + conviction)으로 판단한다. 공매도 데이터가 없으면 다른 4개 신호만 사용해 결정하므로, 영업 중단 가능성은 없다 — 다만 정밀도 + 제한. + + ' cli_interface: - usage: "python tools/build_qualitative_sell_inputs_v1.py --short-csv Temp/shorting_balance_manual_YYYY-MM-DD.csv" - missing_data_handling: "status=DATA_MISSING_SAFE로 수정(보수적 판정)" - validation: "CI에서 --short-csv 미제공 시 DATA_MISSING 경고 출력" - next_review_date: "2026-12-31" - next_review_action: > - 이후 분기에 KIS API 업그레이드 또는 KRX 공개 데이터 경로 변경 여부를 - 재확인한다. 변경이 없으면 MANUAL_CSV_ONLY 상태 유지, 변경이 있으면 - 자동화 착수 여부를 결정한다. - implementation_note: > - 2026-06-22 WBS-7.10 기술장벽 최종 확정. 자동화 경로 불가능하므로 - 수동 CSV 운영절차를 governance/rules에 명문화한다. + usage: python tools/build_qualitative_sell_inputs_v1.py --short-csv Temp/shorting_balance_manual_YYYY-MM-DD.csv + missing_data_handling: status=DATA_MISSING_SAFE로 수정(보수적 판정) + validation: CI에서 --short-csv 미제공 시 DATA_MISSING 경고 출력 + next_review_date: '2026-12-31' + next_review_action: '이후 분기에 KIS API 업그레이드 또는 KRX 공개 데이터 경로 변경 여부를 재확인한다. 변경이 없으면 + MANUAL_CSV_ONLY 상태 유지, 변경이 있으면 자동화 착수 여부를 결정한다. + + ' + implementation_note: '2026-06-22 WBS-7.10 기술장벽 최종 확정. 자동화 경로 불가능하므로 수동 CSV 운영절차를 + governance/rules에 명문화한다. + + ' diff --git a/spec/17_performance_contract.yaml b/spec/17_performance_contract.yaml index 526fb9f..f3a2df2 100644 --- a/spec/17_performance_contract.yaml +++ b/spec/17_performance_contract.yaml @@ -5,6 +5,8 @@ meta: language: "ko-KR" timezone: "Asia/Seoul" role: "canonical" + has_code_implementation: true + code_path: ["tools/build_honest_performance_guard_v1.py", "src/quant_engine/qualitative_sell_strategy_v1.py"] purpose: > Google Sheets 'performance' 탭의 구조·입력 규칙을 정의하고, GAS가 이 데이터를 읽어 Bayesian multiplier를 자동 계산하는 계약을 명시한다. diff --git a/spec/20_harness_output_schema.yaml b/spec/20_harness_output_schema.yaml index b3f59e3..5936d12 100644 --- a/spec/20_harness_output_schema.yaml +++ b/spec/20_harness_output_schema.yaml @@ -1,314 +1,290 @@ meta: - title: "은퇴자산포트폴리오 — GAS 수치 출력 의무 스키마" - version: "2026-05-22-V1.0-NUMERIC" - purpose: > - YAML 스펙은 의도 문서이고, LLM 텍스트 판단은 매번 다른 결과를 낸다. - 이 파일은 GAS가 반드시 숫자로 채워야 할 harness_context 필드를 정의한다. - measure_harness_coverage.py 가 이 스키마를 기준으로 커버리지를 측정한다. - 필드가 공백이면 LLM이 추정 = 랜덤성 원천 = 정보 가치 없음. + title: 은퇴자산포트폴리오 — GAS 수치 출력 의무 스키마 + version: 2026-05-22-V1.0-NUMERIC + purpose: 'YAML 스펙은 의도 문서이고, LLM 텍스트 판단은 매번 다른 결과를 낸다. 이 파일은 GAS가 반드시 숫자로 채워야 할 harness_context + 필드를 정의한다. measure_harness_coverage.py 가 이 스키마를 기준으로 커버리지를 측정한다. 필드가 공백이면 LLM이 + 추정 = 랜덤성 원천 = 정보 가치 없음. + ' + has_code_implementation: true + code_path: + - spec\20_harness_output_schema.yaml principle: - - "하네스가 계산하지 않은 숫자는 정보가 아니다. 텍스트 추정은 매번 다르다." - - "GAS가 산출한 숫자만 ground_truth. LLM 출력과 불일치 시 CRITICAL_EXECUTION_FAILURE." - - "커버리지 목표: 100%. 공백 필드 수 = LLM 자유도 = 재현성 위험." - -# ────────────────────────────────────────────────────────────────────────────── -# 필드 정의 형식: -# required: true → GAS 반드시 산출 (공백이면 COVERAGE FAIL) -# type: numeric | enum | bool | json -# formula: 산출 공식 ID -# gas_field: harness_context 내 필드명 -# range: [min, max] (numeric 전용) -# allowed: [값1, 값2, ...] (enum 전용) -# llm_action: 공백 시 LLM이 취할 수 있는 유일한 행동 -# ────────────────────────────────────────────────────────────────────────────── - +- 하네스가 계산하지 않은 숫자는 정보가 아니다. 텍스트 추정은 매번 다르다. +- GAS가 산출한 숫자만 ground_truth. LLM 출력과 불일치 시 CRITICAL_EXECUTION_FAILURE. +- '커버리지 목표: 100%. 공백 필드 수 = LLM 자유도 = 재현성 위험.' mandatory_numeric_outputs: - - # ── STAGE 0: 데이터 & 라우팅 ────────────────────────────────────────────── - - gas_field: "intraday_lock" - type: bool - formula: "INTRADAY_ACTION_MATRIX_V1" - required: true - description: "장중 잠금 여부 — false이면 전략 전체 허용" - llm_action: "DATA_MISSING — 장중/장후 판단 중단" - - - gas_field: "intraday_scope" - type: enum - formula: "INTRADAY_ACTION_MATRIX_V1" - required: true - allowed: ["FULL_STRATEGY", "TRIM_ONLY", "WATCH_ONLY"] - description: "허용 전략 범위 — TRIM_ONLY 시 신규매수·전량매도 금지" - llm_action: "DATA_MISSING — 기본 TRIM_ONLY로 처리" - - # ── STAGE 1: 포트폴리오 현금 & 열 ────────────────────────────────────────── - - gas_field: "settlement_cash_d2_krw" - type: numeric - formula: "CASH_RATIOS_V1" - required: true - range: [0, 10_000_000_000] - description: "D+2 정산현금(원) — 매수 가용 현금 기준" - llm_action: "DATA_MISSING — 매수 금지" - - - gas_field: "cash_shortfall_min_krw" - type: numeric - formula: "CASH_RATIOS_V1" - required: true - range: [0, 10_000_000_000] - description: "현금 부족분(원) — 현금확보 매도 발동 기준" - llm_action: "DATA_MISSING — 현금확보 매도 중단" - - - gas_field: "total_heat_pct" - type: numeric - formula: "TOTAL_HEAT_V1" - required: true - range: [0, 100] - description: "포트폴리오 총 Heat(%) — 10% 초과 시 신규매수 전면 차단" - llm_action: "DATA_MISSING — 신규매수 차단" - - - gas_field: "heat_gate_status" - type: enum - formula: "TOTAL_HEAT_V1" - required: true - allowed: ["PASS", "BLOCK_NEW_BUY", "HALVE_NEW_BUY_QUANTITY"] - description: "Heat 게이트 상태" - llm_action: "DATA_MISSING — BLOCK_NEW_BUY 처리" - - # ── STAGE 2: 손절·래칫 ──────────────────────────────────────────────────── - - gas_field: "profit_lock_stage" - type: enum - formula: "PROFIT_LOCK_RATCHET_V1" - required: true - per_ticker: true - allowed: - - "NORMAL" - - "BREAKEVEN_RATCHET" - - "PROFIT_LOCK_10" - - "PROFIT_LOCK_20" - - "PROFIT_LOCK_30" - - "APEX_TRAILING" - - "APEX_SUPER" - - "SECULAR_LEADER_DEFERRED" - description: "수익 구간 단계 — APEX_SUPER(+60%)이면 trailing_stop 병기 필수" - llm_action: "DATA_MISSING — trailing_stop 병기 불가" - criticality: "HIGH — APEX_SUPER 미판정 시 +60% 수익 종목에 보유유지만 서술하게 됨" - - - gas_field: "auto_trailing_stop_v2" - type: numeric - formula: "PROFIT_RATCHET_TIERED_V2" - required: false - per_ticker: true - description: "ATR×1.2 기반 APEX_SUPER 자동 trailing stop(원)" - note: "profit_lock_stage >= PROFIT_LOCK_20 일 때만 산출 (null이면 적용 안함)" - llm_action: "DATA_MISSING — trailing_stop 병기 불가. 보유유지 단독 서술 허용되어 수익 보호 실패" - criticality: "CRITICAL — 삼성전자 +61.5% 사례(E3)에서 미산출로 수익 보호 실패" - - # ── STAGE 3: 설거지 감지 ────────────────────────────────────────────────── - - gas_field: "distribution_sell_detector_status" - type: enum - formula: "DISTRIBUTION_SELL_DETECTOR_V1" - required: true - per_ticker: true - allowed: ["DISTRIBUTION_CONFIRMED", "DISTRIBUTION_WARNING", "DISTRIBUTION_CLEAR"] - description: "설거지 6신호 합산 감지 상태 — CONFIRMED 시 BUY 완전 차단" - llm_action: "DATA_MISSING — '오를 것 같다' 주관 판단으로 매수 → 설거지 진입 위험" - criticality: "HIGH" - - # ── STAGE 4: 매수 게이트 ────────────────────────────────────────────────── - - gas_field: "anti_chasing_verdict" - type: enum - formula: "ANTI_CHASING_VELOCITY_V1" - required: true - per_ticker: true - allowed: ["BLOCK_CHASE", "PULLBACK_WAIT", "CLEAR"] - description: "당일 속도 기반 뒷박 추격 차단 — BLOCK_CHASE 시 당일 BUY 금지" - llm_action: "DATA_MISSING — velocity_1d 미계산으로 뒷박 추격 매수 허용" - criticality: "CRITICAL — 뒷박 매수는 진입 당일 고점. 실패의 주원인." - - - gas_field: "pullback_entry_trigger_price" - type: numeric - formula: "PULLBACK_ENTRY_TRIGGER_V1" - required: false - per_ticker: true - description: "눌림목 허용 기준가(원) = MA20 - 0.5×ATR20, tick 정규화" - note: "PULLBACK_WAIT 상태일 때만 유효" - llm_action: "DATA_MISSING — '가격이 괜찮아 보이면' 즉시 매수 → 눌림목 미확인 진입" - criticality: "HIGH" - - # ── STAGE 5: 현금확보 매도 ──────────────────────────────────────────────── - - gas_field: "cash_recovery_plan_json" - type: json - formula: "CASH_RECOVERY_OPTIMIZER_V1" - required: true - condition: "cash_shortfall_min_krw > 0" - description: "현금부족 최적 매도조합 JSON — H2 우선순위 기반 결정론적 산출" - schema: - sell_sequence: "array of {ticker, qty, limit_price, expected_krw}" - expected_total_krw: "numeric" - shortfall_met: "boolean" - llm_action: "DATA_MISSING — LLM이 '삼성E&A 100주+한화에어로 50주' 즉석 계산 → HS011 위반" - criticality: "CRITICAL — 현금확보 매도 조합이 LLM마다 달라짐" - - - gas_field: "waterfall_plan_json" - type: json - formula: "SELL_WATERFALL_ENGINE_V1" - required: true - condition: "cash_shortfall_min_krw > 0" - description: "4단계 폭포수 매도 계획 JSON" - schema: - current_stage: "int 1~4" - stage_label: "enum [IMMEDIATE_TRIM,REBOUND_WAIT,CASCADING_TRIM,EMERGENCY_EXIT]" - sell_sequence: "array of {ticker, stage, qty, limit_price, rebound_trigger_price}" - llm_action: "DATA_MISSING — stage 순서 없이 즉흥 매도 → 주식가치 훼손" - criticality: "HIGH" - - - gas_field: "preservation_verdict" - type: enum - formula: "SELL_VALUE_PRESERVATION_TIERED_V2" - required: true - per_ticker: true - condition: "Final_Action in [SELL_READY, TRIM]" - allowed: - - "EMERGENCY_EXIT" - - "OVERSOLD_REBOUND_SELL" - - "APEX_TRIM" - - "STAGED_EXIT" - - "PRESERVE_TIERED" - - "HOLD" - description: "주식가치 보호 매도 결정 — HOLD 외에는 구체 계획 필수" - llm_action: "DATA_MISSING — 무작위 매도 스타일 서술" - criticality: "MEDIUM" - - # ── STAGE 6: 가격 검증 ──────────────────────────────────────────────────── - - gas_field: "sell_price_sanity_status" - type: enum - formula: "SELL_PRICE_SANITY_V1" - required: true - per_ticker: true - condition: "Final_Action in [SELL_READY, TRIM, EXIT_100]" - allowed: ["PASS", "INVALID_PRICE_INVERSION", "INVALID_UNREALISTIC_PRICE", "INVALID_TICK"] - description: "매도가 역전·비현실가 검증 — INVALID 시 HTS 주문표 제거" - llm_action: "DATA_MISSING — LS Electric 사례처럼 역전 가격이 HTS 주문표에 그대로 들어감" - criticality: "CRITICAL — 실제 손실 오류 E1의 직접 원인" - - # ── STAGE 6: HTS 주문 잠금 ──────────────────────────────────────────────── - - gas_field: "prices_json" - type: json - formula: "PRICES_LOCK" - required: true - description: "종목별 stop_price, tp1_price, tp2_price JSON — LLM 재계산 금지" - schema: - stop_price: "numeric KRW" - tp1_price: "numeric KRW or null" - tp2_price: "numeric KRW or null" - profit_lock_stage: "enum" - llm_action: "DATA_MISSING — LLM이 차트 지지선으로 손절가 임의 추정 → 매번 다른 값" - criticality: "CRITICAL — 수량·가격 기반 모든 주문이 불확실해짐" - - - gas_field: "sell_quantities_json" - type: json - formula: "QUANTITIES_LOCK" - required: true - description: "종목별 매도 수량 잠금 JSON" - llm_action: "DATA_MISSING — LLM이 '적절한 수량으로' 즉흥 계산" - criticality: "CRITICAL" - - - gas_field: "order_blueprint_json" - type: json - formula: "ORDER_BLUEPRINT" - required: true - description: "HTS 주문 청사진 JSON — validation_status=PASS만 HTS 입력 허용" - llm_action: "DATA_MISSING — Shadow Ledger / HTS 주문표 분리 불가" - criticality: "CRITICAL" - - # ── STAGE 7: RS 판정 ────────────────────────────────────────────────────── - - gas_field: "rs_verdict" - type: enum - formula: "RS_VERDICT_V2" - required: true - per_ticker: true - allowed: ["LEADER", "NEUTRAL", "LAGGARD", "BROKEN"] - description: "최종 상대강도 판정 — BROKEN 시 매도 우선순위 최상위" - llm_action: "DATA_MISSING — '차트가 좋아 보이면 LEADER' 주관 판단" - criticality: "HIGH" - - # ── MONTHLY BATCH ────────────────────────────────────────────────────────── - - gas_field: "trade_quality_json" - type: json - formula: "TRADE_QUALITY_SCORER_V1" - required: false - batch_only: true - description: "T+5/T+20 거래 품질 채점 결과 — POOR/CRITICAL 누적 블랙리스트 발동" - schema: - ticker: "string" - score: "int 0~100" - grade: "enum [EXCELLENT,GOOD,ACCEPTABLE,POOR,CRITICAL]" - feedback_tag: "enum" - llm_action: "DATA_MISSING — 'POOR 매매였지만 이번엔 다르다' 무근거 판단" - criticality: "MEDIUM — 반복 실수 패턴 차단 불가" - -# ────────────────────────────────────────────────────────────────────────────── -# 커버리지 임계값 -# ────────────────────────────────────────────────────────────────────────────── +- gas_field: intraday_lock + type: bool + formula: INTRADAY_ACTION_MATRIX_V1 + required: true + description: 장중 잠금 여부 — false이면 전략 전체 허용 + llm_action: DATA_MISSING — 장중/장후 판단 중단 +- gas_field: intraday_scope + type: enum + formula: INTRADAY_ACTION_MATRIX_V1 + required: true + allowed: + - FULL_STRATEGY + - TRIM_ONLY + - WATCH_ONLY + description: 허용 전략 범위 — TRIM_ONLY 시 신규매수·전량매도 금지 + llm_action: DATA_MISSING — 기본 TRIM_ONLY로 처리 +- gas_field: settlement_cash_d2_krw + type: numeric + formula: CASH_RATIOS_V1 + required: true + range: + - 0 + - 10000000000 + description: D+2 정산현금(원) — 매수 가용 현금 기준 + llm_action: DATA_MISSING — 매수 금지 +- gas_field: cash_shortfall_min_krw + type: numeric + formula: CASH_RATIOS_V1 + required: true + range: + - 0 + - 10000000000 + description: 현금 부족분(원) — 현금확보 매도 발동 기준 + llm_action: DATA_MISSING — 현금확보 매도 중단 +- gas_field: total_heat_pct + type: numeric + formula: TOTAL_HEAT_V1 + required: true + range: + - 0 + - 100 + description: 포트폴리오 총 Heat(%) — 10% 초과 시 신규매수 전면 차단 + llm_action: DATA_MISSING — 신규매수 차단 +- gas_field: heat_gate_status + type: enum + formula: TOTAL_HEAT_V1 + required: true + allowed: + - PASS + - BLOCK_NEW_BUY + - HALVE_NEW_BUY_QUANTITY + description: Heat 게이트 상태 + llm_action: DATA_MISSING — BLOCK_NEW_BUY 처리 +- gas_field: profit_lock_stage + type: enum + formula: PROFIT_LOCK_RATCHET_V1 + required: true + per_ticker: true + allowed: + - NORMAL + - BREAKEVEN_RATCHET + - PROFIT_LOCK_10 + - PROFIT_LOCK_20 + - PROFIT_LOCK_30 + - APEX_TRAILING + - APEX_SUPER + - SECULAR_LEADER_DEFERRED + description: 수익 구간 단계 — APEX_SUPER(+60%)이면 trailing_stop 병기 필수 + llm_action: DATA_MISSING — trailing_stop 병기 불가 + criticality: HIGH — APEX_SUPER 미판정 시 +60% 수익 종목에 보유유지만 서술하게 됨 +- gas_field: auto_trailing_stop_v2 + type: numeric + formula: PROFIT_RATCHET_TIERED_V2 + required: false + per_ticker: true + description: ATR×1.2 기반 APEX_SUPER 자동 trailing stop(원) + note: profit_lock_stage >= PROFIT_LOCK_20 일 때만 산출 (null이면 적용 안함) + llm_action: DATA_MISSING — trailing_stop 병기 불가. 보유유지 단독 서술 허용되어 수익 보호 실패 + criticality: CRITICAL — 삼성전자 +61.5% 사례(E3)에서 미산출로 수익 보호 실패 +- gas_field: distribution_sell_detector_status + type: enum + formula: DISTRIBUTION_SELL_DETECTOR_V1 + required: true + per_ticker: true + allowed: + - DISTRIBUTION_CONFIRMED + - DISTRIBUTION_WARNING + - DISTRIBUTION_CLEAR + description: 설거지 6신호 합산 감지 상태 — CONFIRMED 시 BUY 완전 차단 + llm_action: DATA_MISSING — '오를 것 같다' 주관 판단으로 매수 → 설거지 진입 위험 + criticality: HIGH +- gas_field: anti_chasing_verdict + type: enum + formula: ANTI_CHASING_VELOCITY_V1 + required: true + per_ticker: true + allowed: + - BLOCK_CHASE + - PULLBACK_WAIT + - CLEAR + description: 당일 속도 기반 뒷박 추격 차단 — BLOCK_CHASE 시 당일 BUY 금지 + llm_action: DATA_MISSING — velocity_1d 미계산으로 뒷박 추격 매수 허용 + criticality: CRITICAL — 뒷박 매수는 진입 당일 고점. 실패의 주원인. +- gas_field: pullback_entry_trigger_price + type: numeric + formula: PULLBACK_ENTRY_TRIGGER_V1 + required: false + per_ticker: true + description: 눌림목 허용 기준가(원) = MA20 - 0.5×ATR20, tick 정규화 + note: PULLBACK_WAIT 상태일 때만 유효 + llm_action: DATA_MISSING — '가격이 괜찮아 보이면' 즉시 매수 → 눌림목 미확인 진입 + criticality: HIGH +- gas_field: cash_recovery_plan_json + type: json + formula: CASH_RECOVERY_OPTIMIZER_V1 + required: true + condition: cash_shortfall_min_krw > 0 + description: 현금부족 최적 매도조합 JSON — H2 우선순위 기반 결정론적 산출 + schema: + sell_sequence: array of {ticker, qty, limit_price, expected_krw} + expected_total_krw: numeric + shortfall_met: boolean + llm_action: DATA_MISSING — LLM이 '삼성E&A 100주+한화에어로 50주' 즉석 계산 → HS011 위반 + criticality: CRITICAL — 현금확보 매도 조합이 LLM마다 달라짐 +- gas_field: waterfall_plan_json + type: json + formula: SELL_WATERFALL_ENGINE_V1 + required: true + condition: cash_shortfall_min_krw > 0 + description: 4단계 폭포수 매도 계획 JSON + schema: + current_stage: int 1~4 + stage_label: enum [IMMEDIATE_TRIM,REBOUND_WAIT,CASCADING_TRIM,EMERGENCY_EXIT] + sell_sequence: array of {ticker, stage, qty, limit_price, rebound_trigger_price} + llm_action: DATA_MISSING — stage 순서 없이 즉흥 매도 → 주식가치 훼손 + criticality: HIGH +- gas_field: preservation_verdict + type: enum + formula: SELL_VALUE_PRESERVATION_TIERED_V2 + required: true + per_ticker: true + condition: Final_Action in [SELL_READY, TRIM] + allowed: + - EMERGENCY_EXIT + - OVERSOLD_REBOUND_SELL + - APEX_TRIM + - STAGED_EXIT + - PRESERVE_TIERED + - HOLD + description: 주식가치 보호 매도 결정 — HOLD 외에는 구체 계획 필수 + llm_action: DATA_MISSING — 무작위 매도 스타일 서술 + criticality: MEDIUM +- gas_field: sell_price_sanity_status + type: enum + formula: SELL_PRICE_SANITY_V1 + required: true + per_ticker: true + condition: Final_Action in [SELL_READY, TRIM, EXIT_100] + allowed: + - PASS + - INVALID_PRICE_INVERSION + - INVALID_UNREALISTIC_PRICE + - INVALID_TICK + description: 매도가 역전·비현실가 검증 — INVALID 시 HTS 주문표 제거 + llm_action: DATA_MISSING — LS Electric 사례처럼 역전 가격이 HTS 주문표에 그대로 들어감 + criticality: CRITICAL — 실제 손실 오류 E1의 직접 원인 +- gas_field: prices_json + type: json + formula: PRICES_LOCK + required: true + description: 종목별 stop_price, tp1_price, tp2_price JSON — LLM 재계산 금지 + schema: + stop_price: numeric KRW + tp1_price: numeric KRW or null + tp2_price: numeric KRW or null + profit_lock_stage: enum + llm_action: DATA_MISSING — LLM이 차트 지지선으로 손절가 임의 추정 → 매번 다른 값 + criticality: CRITICAL — 수량·가격 기반 모든 주문이 불확실해짐 +- gas_field: sell_quantities_json + type: json + formula: QUANTITIES_LOCK + required: true + description: 종목별 매도 수량 잠금 JSON + llm_action: DATA_MISSING — LLM이 '적절한 수량으로' 즉흥 계산 + criticality: CRITICAL +- gas_field: order_blueprint_json + type: json + formula: ORDER_BLUEPRINT + required: true + description: HTS 주문 청사진 JSON — validation_status=PASS만 HTS 입력 허용 + llm_action: DATA_MISSING — Shadow Ledger / HTS 주문표 분리 불가 + criticality: CRITICAL +- gas_field: rs_verdict + type: enum + formula: RS_VERDICT_V2 + required: true + per_ticker: true + allowed: + - LEADER + - NEUTRAL + - LAGGARD + - BROKEN + description: 최종 상대강도 판정 — BROKEN 시 매도 우선순위 최상위 + llm_action: DATA_MISSING — '차트가 좋아 보이면 LEADER' 주관 판단 + criticality: HIGH +- gas_field: trade_quality_json + type: json + formula: TRADE_QUALITY_SCORER_V1 + required: false + batch_only: true + description: T+5/T+20 거래 품질 채점 결과 — POOR/CRITICAL 누적 블랙리스트 발동 + schema: + ticker: string + score: int 0~100 + grade: enum [EXCELLENT,GOOD,ACCEPTABLE,POOR,CRITICAL] + feedback_tag: enum + llm_action: DATA_MISSING — 'POOR 매매였지만 이번엔 다르다' 무근거 판단 + criticality: MEDIUM — 반복 실수 패턴 차단 불가 coverage_thresholds: - critical_fields_target_pct: 100 # CRITICAL 필드는 100% 필수 - overall_target_pct: 85 # 전체 목표 커버리지 - llm_freedom_score_max: 15 # LLM 자유도 15% 이하 목표 - + critical_fields_target_pct: 100 + overall_target_pct: 85 + llm_freedom_score_max: 15 grade_table: - 100: {grade: "DETERMINISTIC", label: "완전 결정론적 — 이상적 상태"} - 85_99: {grade: "NEAR_FULL", label: "거의 결정론적 — 배치 필드만 미계산"} - 60_84: {grade: "PARTIAL", label: "부분 결정론적 — GAS 구현 필요"} - 0_59: {grade: "LLM_DEPENDENT", label: "LLM 의존 — 결과 재현 불가"} - -# ────────────────────────────────────────────────────────────────────────────── -# 현재 GAS 구현 상태 (2026-05-22 기준) -# ────────────────────────────────────────────────────────────────────────────── + 100: + grade: DETERMINISTIC + label: 완전 결정론적 — 이상적 상태 + 8599: + grade: NEAR_FULL + label: 거의 결정론적 — 배치 필드만 미계산 + 6084: + grade: PARTIAL + label: 부분 결정론적 — GAS 구현 필요 + 0_59: + grade: LLM_DEPENDENT + label: LLM 의존 — 결과 재현 불가 current_state: - gas_version: "2026-05-19-X4R1" - overall_coverage_pct: 30 # 실측값 — measure_harness_coverage.py 참조 - llm_freedom_score: 70 # 100 - 30 = 70% → LLM 의존도 매우 높음 - grade: "LLM_DEPENDENT" - + gas_version: 2026-05-19-X4R1 + overall_coverage_pct: 30 + llm_freedom_score: 70 + grade: LLM_DEPENDENT critical_gaps: - - field: "prices_json" - status: "EMPTY" - impact: "stop_price/tp_price 전부 LLM 추정 → 매 호출마다 다른 손절가" - - - field: "sell_quantities_json" - status: "EMPTY" - impact: "매도 수량 LLM 추정 → 매 호출마다 다른 수량" - - - field: "order_blueprint_json" - status: "EMPTY" - impact: "HTS 주문 청사진 없음 → Shadow Ledger 분리 불가" - - - field: "anti_chasing_verdict" - status: "MISSING" - impact: "뒷박 추격 매수 차단 미작동 → 진입 당일 고점 손실 반복" - - - field: "sell_price_sanity_status" - status: "MISSING" - impact: "LS Electric 사례(E1) 재발 — 역전 매도가 HTS 입력 허용" - - - field: "auto_trailing_stop_v2" - status: "MISSING" - impact: "삼성전자 +61.5% 사례(E3) 재발 — APEX_SUPER trailing_stop 미병기" - - - field: "rs_verdict" - status: "MISSING" - impact: "RS_VERDICT_V2 미산출 → H2 매도 우선순위 BROKEN 판정 불가" - - - field: "cash_recovery_plan_json" - status: "MISSING" - impact: "현금확보 매도조합 LLM 즉석 계산 → HS011 위반 반복 (E2)" - + - field: prices_json + status: EMPTY + impact: stop_price/tp_price 전부 LLM 추정 → 매 호출마다 다른 손절가 + - field: sell_quantities_json + status: EMPTY + impact: 매도 수량 LLM 추정 → 매 호출마다 다른 수량 + - field: order_blueprint_json + status: EMPTY + impact: HTS 주문 청사진 없음 → Shadow Ledger 분리 불가 + - field: anti_chasing_verdict + status: MISSING + impact: 뒷박 추격 매수 차단 미작동 → 진입 당일 고점 손실 반복 + - field: sell_price_sanity_status + status: MISSING + impact: LS Electric 사례(E1) 재발 — 역전 매도가 HTS 입력 허용 + - field: auto_trailing_stop_v2 + status: MISSING + impact: 삼성전자 +61.5% 사례(E3) 재발 — APEX_SUPER trailing_stop 미병기 + - field: rs_verdict + status: MISSING + impact: RS_VERDICT_V2 미산출 → H2 매도 우선순위 BROKEN 판정 불가 + - field: cash_recovery_plan_json + status: MISSING + impact: 현금확보 매도조합 LLM 즉석 계산 → HS011 위반 반복 (E2) next_gas_implementation_priority: - 1: "prices_json — stop_price, tp_price 실제 계산 및 채우기" - 2: "sell_quantities_json — Sell_Qty 실제 수량 채우기" - 3: "order_blueprint_json — HTS 주문 청사진 생성" - 4: "anti_chasing_verdict — velocity_1d 계산 + 차단 판정" - 5: "sell_price_sanity_status — 역전/비현실가 검증" - 6: "auto_trailing_stop_v2 — ATR×1.2 APEX_SUPER trailing" - 7: "rs_verdict — RS_VERDICT_V2 실제 산출" - 8: "cash_recovery_plan_json — H2 순서 누적 매도조합" + 1: prices_json — stop_price, tp_price 실제 계산 및 채우기 + 2: sell_quantities_json — Sell_Qty 실제 수량 채우기 + 3: order_blueprint_json — HTS 주문 청사진 생성 + 4: anti_chasing_verdict — velocity_1d 계산 + 차단 판정 + 5: sell_price_sanity_status — 역전/비현실가 검증 + 6: auto_trailing_stop_v2 — ATR×1.2 APEX_SUPER trailing + 7: rs_verdict — RS_VERDICT_V2 실제 산출 + 8: cash_recovery_plan_json — H2 순서 누적 매도조합 diff --git a/spec/21_harness_governance_contract.yaml b/spec/21_harness_governance_contract.yaml index f3be543..36c4109 100644 --- a/spec/21_harness_governance_contract.yaml +++ b/spec/21_harness_governance_contract.yaml @@ -1,70 +1,70 @@ meta: - title: "Harness Governance Contract" - version: "2026-05-22-v1" - purpose: "하네스 준수 강제: 문서 지침 + 검증기 + 실행 게이트의 3중 잠금" - + title: Harness Governance Contract + version: 2026-05-22-v1 + purpose: '하네스 준수 강제: 문서 지침 + 검증기 + 실행 게이트의 3중 잠금' + has_code_implementation: true + code_path: + - spec\21_harness_governance_contract.yaml governance: required_layers: - - name: "static_guide" - required_files: - - "AGENTS.md" - - "spec/07_output_schema.yaml" - - "spec/19_harness_contract.yaml" - - name: "machine_validation" - required_validators: - - "tools/validate_specs.py" - - "tools/validate_harness_context.py" - - "tools/validate_report_quality.py" - - name: "execution_gate" - required_runners: - - "tools/validate_engine_harness_gate.py" - - "tools/run_engine_harness_gate.ps1" - - "tools/run_yolo_full_cycle.ps1" - + - name: static_guide + required_files: + - AGENTS.md + - spec/07_output_schema.yaml + - spec/19_harness_contract.yaml + - name: machine_validation + required_validators: + - tools/validate_specs.py + - tools/validate_harness_context.py + - tools/validate_report_quality.py + - name: execution_gate + required_runners: + - tools/validate_engine_harness_gate.py + - tools/run_engine_harness_gate.ps1 + - tools/run_yolo_full_cycle.ps1 hardlocks: - - id: "HG001" - rule: "coverage_strict_100_required" - fail_condition: "measure_harness_coverage --strict-100 미통과" - - id: "HG002" - rule: "watch_transparency_required" - fail_condition: "WATCH_LEDGER_OK 미충족" - - id: "HG003" - rule: "satellite_proposal_sheet_required" - fail_condition: "SATELLITE_PROPOSAL_SHEET_OK 미충족" - - id: "HG004" - rule: "strategy_harness_required" - fail_condition: "STRATEGY_HARNESS_V2_OK 미충족" - +- id: HG001 + rule: coverage_strict_100_required + fail_condition: measure_harness_coverage --strict-100 미통과 +- id: HG002 + rule: watch_transparency_required + fail_condition: WATCH_LEDGER_OK 미충족 +- id: HG003 + rule: satellite_proposal_sheet_required + fail_condition: SATELLITE_PROPOSAL_SHEET_OK 미충족 +- id: HG004 + rule: strategy_harness_required + fail_condition: STRATEGY_HARNESS_V2_OK 미충족 gate_validity_rules: NON_VACUOUS_PASS_GUARD_V1: formula_id: NON_VACUOUS_PASS_GUARD_V1 - rationale: > - row_count=0 또는 sample_n < min_samples 인데 gate=PASS인 항목은 - 점수 분자를 부풀린다. effective_n 미달 게이트는 WATCH_PENDING_SAMPLE로 강제 강등. + rationale: 'row_count=0 또는 sample_n < min_samples 인데 gate=PASS인 항목은 점수 분자를 부풀린다. + effective_n 미달 게이트는 WATCH_PENDING_SAMPLE로 강제 강등. + + ' min_samples_default: 30 min_samples_exceptions: - rebound_efficiency_score: 30 # 이전 4 → 30으로 상향 + rebound_efficiency_score: 30 late_rebound_bucket_score: 30 enforcement: - - "effective_n < min_samples 이면 gate를 PASS로 둘 수 없다" - - "강등된 게이트는 release/pass_100 집계 분자(PASS count)에 포함 금지" - - "강등 라벨: WATCH_PENDING_SAMPLE" - - "보고서 해당 셀에 '[PASS_INVALID_LOW_N: n={effective_n} < {min}]' 라벨 부착" + - effective_n < min_samples 이면 gate를 PASS로 둘 수 없다 + - 강등된 게이트는 release/pass_100 집계 분자(PASS count)에 포함 금지 + - '강등 라벨: WATCH_PENDING_SAMPLE' + - '보고서 해당 셀에 ''[PASS_INVALID_LOW_N: n={effective_n} < {min}]'' 라벨 부착' effective_n_fields: - - sample_count - - row_count - - evaluated_count - - samples - - n + - sample_count + - row_count + - evaluated_count + - samples + - n output: - - Temp/vacuous_pass_audit_v1.json - - operational_report.json.summary.vacuous_pass_gate_count + - Temp/vacuous_pass_audit_v1.json + - operational_report.json.summary.vacuous_pass_gate_count python_tool: tools/build_vacuous_pass_audit_v1.py - gs_coverage: "gas_apex_runtime_core.gs:guardNonVacuousPass_()" - validator: "tools/validate_harness_governance_contract.py --check non_vacuous_pass" - + gs_coverage: gas_apex_runtime_core.gs:guardNonVacuousPass_() + validator: tools/validate_harness_governance_contract.py --check non_vacuous_pass operations: release_policy: - - "failed_checks 비어있지 않으면 배포/실행 차단" - - "gap_alert=true 이면 배포/실행 차단" - - "vacuous_pass_gate_count > 0 이면 배포/실행 차단 (NON_VACUOUS_PASS_GUARD_V1)" + - failed_checks 비어있지 않으면 배포/실행 차단 + - gap_alert=true 이면 배포/실행 차단 + - vacuous_pass_gate_count > 0 이면 배포/실행 차단 (NON_VACUOUS_PASS_GUARD_V1) diff --git a/spec/23_low_capability_llm_pipeline_todo.yaml b/spec/23_low_capability_llm_pipeline_todo.yaml index 6f10224..ca3d330 100644 --- a/spec/23_low_capability_llm_pipeline_todo.yaml +++ b/spec/23_low_capability_llm_pipeline_todo.yaml @@ -1,66 +1,70 @@ +meta: + has_code_implementation: true + code_path: + - spec\23_low_capability_llm_pipeline_todo.yaml low_capability_llm_pipeline_todo: formula_id: LOW_CAPABILITY_LLM_PIPELINE_TODO_V2 objective: 저성능 LLM을 위한 기계적 복사 보고 절차 규정 ordered_steps: - - step_id: STEP_01 - action: "AGENTS.md 읽기" - ambiguous: false - calculation: false - - step_id: STEP_02 - action: "active manifest 읽기" - ambiguous: false - calculation: false - - step_id: STEP_03 - action: "final_context 읽기" - ambiguous: false - calculation: false - - step_id: STEP_04 - action: "engine gate status 확인" - ambiguous: false - calculation: false - - step_id: STEP_05 - action: "blockers 먼저 출력" - ambiguous: false - calculation: false - - step_id: STEP_06 - action: "allowed/blocked actions 복사" - ambiguous: false - calculation: false - - step_id: STEP_07 - action: "shadow ledger 복사" - ambiguous: false - calculation: false - - step_id: STEP_08 - action: "data_missing 복사" - ambiguous: false - calculation: false - - step_id: STEP_09 - action: "숫자 provenance 확인" - ambiguous: false - calculation: false - - step_id: STEP_10 - action: "자유 계산 제거" - ambiguous: false - calculation: false - - step_id: STEP_11 - action: "report contract 검증" - ambiguous: false - calculation: false - - step_id: STEP_12 - action: "실패 시 DATA_MISSING 또는 REVIEW_ONLY로 종료" - ambiguous: false - calculation: false + - step_id: STEP_01 + action: AGENTS.md 읽기 + ambiguous: false + calculation: false + - step_id: STEP_02 + action: active manifest 읽기 + ambiguous: false + calculation: false + - step_id: STEP_03 + action: final_context 읽기 + ambiguous: false + calculation: false + - step_id: STEP_04 + action: engine gate status 확인 + ambiguous: false + calculation: false + - step_id: STEP_05 + action: blockers 먼저 출력 + ambiguous: false + calculation: false + - step_id: STEP_06 + action: allowed/blocked actions 복사 + ambiguous: false + calculation: false + - step_id: STEP_07 + action: shadow ledger 복사 + ambiguous: false + calculation: false + - step_id: STEP_08 + action: data_missing 복사 + ambiguous: false + calculation: false + - step_id: STEP_09 + action: 숫자 provenance 확인 + ambiguous: false + calculation: false + - step_id: STEP_10 + action: 자유 계산 제거 + ambiguous: false + calculation: false + - step_id: STEP_11 + action: report contract 검증 + ambiguous: false + calculation: false + - step_id: STEP_12 + action: 실패 시 DATA_MISSING 또는 REVIEW_ONLY로 종료 + ambiguous: false + calculation: false forbidden_actions: - - do not set --skip-validate as default resolution - - do not remove validate-engine-strict from release gate - - do not mark success without engine_harness_gate_result.status=OK + - do not set --skip-validate as default resolution + - do not remove validate-engine-strict from release gate + - do not mark success without engine_harness_gate_result.status=OK completion_criteria: - - Temp/engine_harness_gate_result.json.status == OK - - len(Temp/engine_harness_gate_result.json.failed_checks) == 0 - - Temp/formula_runtime_registry_v1.json.runtime_adjusted_coverage_pct == 100.0 - - Temp/formula_runtime_registry_v1.json.unmapped_formula_count == 0 - - Temp/data_quality_reconciliation_v1.json.schema_presence_score == 100.0 - - Temp/data_quality_reconciliation_v1.json.quality_conflict_flag in [true, false] - - Temp/operational_alpha_calibration_v2.json.formula_id == OPERATIONAL_ALPHA_CALIBRATION_V2 - - Temp/pipeline_runtime_profile_v1.json.mode in [release, quick, package-only] - - Temp/pipeline_runtime_profile_v1.json.gate_status == OK + - Temp/engine_harness_gate_result.json.status == OK + - len(Temp/engine_harness_gate_result.json.failed_checks) == 0 + - Temp/formula_runtime_registry_v1.json.runtime_adjusted_coverage_pct == 100.0 + - Temp/formula_runtime_registry_v1.json.unmapped_formula_count == 0 + - Temp/data_quality_reconciliation_v1.json.schema_presence_score == 100.0 + - Temp/data_quality_reconciliation_v1.json.quality_conflict_flag in [true, false] + - Temp/operational_alpha_calibration_v2.json.formula_id == OPERATIONAL_ALPHA_CALIBRATION_V2 + - Temp/pipeline_runtime_profile_v1.json.mode in [release, quick, package-only] + - Temp/pipeline_runtime_profile_v1.json.gate_status == OK diff --git a/spec/24_strategy_hardening_todo_v1.yaml b/spec/24_strategy_hardening_todo_v1.yaml index 633627a..64f65f5 100644 --- a/spec/24_strategy_hardening_todo_v1.yaml +++ b/spec/24_strategy_hardening_todo_v1.yaml @@ -1,3 +1,7 @@ +meta: + has_code_implementation: true + code_path: + - spec\24_strategy_hardening_todo_v1.yaml strategy_hardening_todo_v1: formula_id: STRATEGY_HARDENING_TODO_V1 objective: @@ -7,7 +11,7 @@ strategy_hardening_todo_v1: target_metrics: engine_gate_status: OK failed_checks_count: 0 - formula_total: 170 # 실제값 170 (163→170 갱신 2026-05-30) + formula_total: 170 declared_runtime_count: 170 runtime_adjusted_coverage_pct: 100.0 unmapped_formula_count: 0 @@ -17,255 +21,269 @@ strategy_hardening_todo_v1: outcome_quality_score_v1_min: 60.0 value_damage_pct_avg_max: 10.0 llm_freedom_pct: 0.0 - # BCH-V1 행위기반 커버리지 (P1 달성 2026-05-30) behavioral_coverage_pct: 100.0 implementation_divergence_count: 0 - # P2 임계값 보정 레지스트리 unregistered_threshold_count: 0 overclaimed_calibration_count: 0 - # P3 LLM 자유도 측정 llm_freedom_pct_measured: 0.0 ungrounded_number_count: 0 - # P4 정직 성과증빙 design_score_as_proof_violations: 0 ordered_todo: - - id: T01_COVERAGE_AUDIT - command: python tools/harness_coverage_auditor.py - expect: - true_missing_count: 0 - coverage_pct_min: 95.0 - fail_code: HARNESS_COVERAGE_AUDIT_FAIL - - id: T02_RUNTIME_REGISTRY_BUILD - command: python tools/build_formula_runtime_registry_v1.py --audit Temp/harness_coverage_audit.json --out Temp/formula_runtime_registry_v1.json - expect: - formula_total: 163 - declared_runtime_count: 163 - runtime_adjusted_coverage_pct: 100.0 - unmapped_formula_count: 0 - fail_code: FORMULA_IMPLEMENTATION_REGISTRY_V1_FAIL - - id: T03_RUNTIME_REGISTRY_VALIDATE - command: python tools/validate_formula_runtime_registry_v1.py --json Temp/formula_runtime_registry_v1.json --target-coverage 100 - expect: - status_token: FORMULA_IMPLEMENTATION_REGISTRY_V1_OK - fail_code: FORMULA_IMPLEMENTATION_REGISTRY_V1_FAIL - - id: T04_DQ_RECON_BUILD - command: python tools/build_data_quality_reconciliation_v1.py --json GatherTradingData.json --integrity Temp/data_integrity_score_v1.json --out Temp/data_quality_reconciliation_v1.json - expect: - formula_id: DATA_QUALITY_RECONCILIATION_V1 - fail_code: DATA_QUALITY_RECONCILIATION_V1_BUILD_FAIL - - id: T05_DQ_RECON_VALIDATE - command: python tools/validate_data_quality_reconciliation_v1.py --json Temp/data_quality_reconciliation_v1.json --min-schema-score 100 --min-investment-quality-score 90 - expect: - status_token: DATA_QUALITY_RECONCILIATION_V1_OK - fail_code: DATA_QUALITY_RECONCILIATION_V1_FAIL - note: "실데이터 부족 구간은 임시로 FAIL 허용하지 않고 WARN 원장으로 기록 후 원인 해결" - - id: T06_ENGINE_GATE - command: python tools/validate_engine_harness_gate.py --json GatherTradingData.json --report Temp/operational_report.md --harness-json Temp/prediction_improvement_harness.json --result-json Temp/engine_harness_gate_result.json --rule-lifecycle-json Temp/rule_lifecycle_policy.json --strategy-harness-json Temp/strategy_harness_v2.json - expect: - status: OK - failed_checks_count: 0 - required_checks: - - CHECK_81_FORMULA_RUNTIME_REGISTRY_V1 - - CHECK_82_DATA_QUALITY_RECONCILIATION_V1 - fail_code: ENGINE_HARNESS_GATE_FAIL - - id: T07_RELEASE_PACKAGE - command: npm run prepare-upload-zip -- --validation-mode release --profile - expect: - gate_status: OK - profile_exists: Temp/pipeline_runtime_profile_v1.json - package_exists: ../data_feed.zip - fail_code: PREPARE_UPLOAD_ZIP_FAIL - # ── P1: 행위기반 커버리지 하네스 (BCH-V1) ───────────────────────────────── - - id: B01_BCH_CONTRACT - command: "# spec/26_behavioral_coverage_contract.yaml 작성 완료" - expect: {file_exists: "spec/26_behavioral_coverage_contract.yaml", decision_critical_count: 40} - status: DONE_2026_05_30 - - id: B02_GOLDEN_AUTHOR - command: "# spec/formula_golden_cases_v2.yaml 손계산 골든케이스 작성 완료" - expect: {cases_total_min: 18, provenance: "HAND_COMPUTED or SPEC_DERIVED only"} - status: DONE_2026_05_30 - - id: B03_PY_MIRROR - command: python tools/run_formula_golden_cases_v2.py - expect: - status_token: BEHAVIORAL_COVERAGE_PY_OK - behavioral_coverage_pct: 100.0 - python_fail: 0 - fail_code: BCH_PY_MIRROR_FAIL - - id: B04_GAS_PARITY - command: node tools/run_gas_golden_parity.js - expect: - status_token: GAS_PARITY_OK - gas_fail: 0 - fail_code: BCH_GAS_PARITY_FAIL - - id: B05_3WAY_VALIDATE - command: python tools/validate_behavioral_coverage_v1.py --strict - expect: - status_token: BEHAVIORAL_COVERAGE_V1_OK - behavioral_coverage_pct: 100.0 - implementation_divergence_count: 0 - fail_code: BEHAVIORAL_COVERAGE_V1_FAIL - - id: B06_DIVERGENCE_FIX - command: "# normalize_tick round→floor 수정, PROFIT_LOCK_STAGE GAS 단계명 정정 완료" - expect: {divergence_count: 0} - status: DONE_2026_05_30 - - id: B07_WIRE_FULLGATE - command: npm run validate-behavioral-coverage - expect: {exit_code: 0} - fail_code: BCH_WIRING_FAIL - # ── P2: 임계값 보정 레지스트리 (CALIB-V1) ──────────────────────────────── - - id: P2_REGISTRY_BUILD - command: "# spec/calibration_registry.yaml 69개 임계값 등록 완료" - expect: {total_thresholds_min: 60} - status: DONE_2026_05_30 - - id: P2_REGISTRY_VALIDATE - command: python tools/validate_calibration_registry_v1.py - expect: - overclaimed_count: 0 - unregistered_threshold_count: 0 - status_token: "CALIBRATION_REGISTRY_WARN or CALIBRATION_REGISTRY_OK" - fail_code: CALIBRATION_REGISTRY_FAIL - - id: P2_PRIORITY_BUILD - command: python tools/build_calibration_priority_v1.py - expect: - status_token: CALIBRATION_PRIORITY_OK - priority_count_min: 5 - fail_code: CALIBRATION_PRIORITY_FAIL - # ── P3: LLM 자유도 측정·폐쇄 (LFM-V1) ────────────────────────────────── - - id: P3_FREEDOM_VALIDATE - command: python tools/validate_number_provenance_v1.py - expect: - status_token: LFM_V1_OK - llm_freedom_pct: 0.0 - fail_code: LFM_V1_FAIL - - id: P3_NARRATIVE_LOCK - command: python tools/build_llm_narrative_template_lock_v1.py - expect: - gate: PASS - total_violations: 0 - softening_violations: 0 - fail_code: LLM_NARRATIVE_LOCK_FAIL - # ── P4: 정직 성과증빙 + 보정루프 (HONEST-V1) ───────────────────────────── - - id: P4_HONEST_GUARD - command: python tools/build_honest_performance_guard_v1.py - expect: - status_token: "HONEST_PERFORMANCE_V1_OK or HONEST_PERFORMANCE_V1_WARN" - design_score_note: "UNVALIDATED_DESIGN_SCORE 표기 필수 (samples<30)" - fail_code: HONEST_PERFORMANCE_V1_FAIL - # ── 반도체 집중 허용 하네스 ──────────────────────────────────────────────── - - id: SEMI_CONCENTRATION_POLICY - command: "# spec/strategy/semiconductor_concentration_policy.yaml 작성 완료" - expect: {file_exists: "spec/strategy/semiconductor_concentration_policy.yaml"} - status: DONE_2026_05_30 - - - id: SEMI_CLUSTER_GATE_UPDATE - command: "# gas_data_feed.gs calcSemiconductorClusterGate_ → MARKET_WEIGHT_AWARE_CLUSTER_GATE_V1 업데이트" - expect: {formula_id: "MARKET_WEIGHT_AWARE_CLUSTER_GATE_V1", kospi_weight_settings_driven: true} - status: DONE_2026_05_30 - - - id: LEADER_CAP_UPDATE - command: "# gas_data_feed.gs calcSinglePositionWeightCap_ → LEADER_POSITION_WEIGHT_CAP_V1 업데이트" - expect: {samsung_risk_on_cap: 40, hynix_risk_on_cap: 22, kospi_weight_settings_driven: true} - status: DONE_2026_05_30 - - - id: SECULAR_LEADER_AUTO_DETECT - command: "# gas_data_feed.gs calcSecularLeaderAutoDetect_ 함수 신설" - expect: {formula_id: "SECULAR_LEADER_AUTO_DETECT_V1", threshold: 6} - status: DONE_2026_05_30 - - - id: SEMI_INJECT_UPDATE - command: "# tools/inject_computed_harness.py 클러스터/개별 게이트 함수 KOSPI 비중 반영" - expect: {settings_kospi_semi_weight_pct: true, gate_overwrite_direct: true} - status: DONE_2026_05_30 - - - id: AGENTS_O1_O2_UPDATE - command: "# AGENTS.md Direction O1/O2 새 공식명·차등한도로 업데이트" - expect: {o1_formula: "LEADER_POSITION_WEIGHT_CAP_V1", o2_formula: "MARKET_WEIGHT_AWARE_CLUSTER_GATE_V1"} - status: DONE_2026_05_30 - - # ── 통합 게이트 ────────────────────────────────────────────────────────── - - id: INTEGRATED_ENGINE_INTEGRITY - command: npm run validate-engine-integrity - expect: - behavioral_coverage_pct: 100.0 - implementation_divergence_count: 0 - overclaimed_count: 0 - unregistered_threshold_count: 0 - llm_freedom_pct: 0.0 - softening_violations: 0 - fail_code: ENGINE_INTEGRITY_FAIL - - # ── CAPITAL_STYLE_ALLOCATION_V1 (Section 3B) ──────────────────────────── - - id: C1_BUILD_CAPITAL_STYLE_ALLOC - command: python tools/build_capital_style_allocation_v1.py - expect: {gate: PASS, ticker_count_min: 1, conviction_range: "[0,100]"} - fail_code: CAPITAL_ALLOC_BUILD_FAIL - status: DONE_2026_05_30 - - - id: C2_VALIDATE_CAPITAL_STYLE_ALLOC - command: python tools/validate_capital_style_allocation_v1.py - expect: {status_token: CAPITAL_ALLOC_OK, violations: 0} - fail_code: CAPITAL_ALLOC_VALIDATE_FAIL - status: DONE_2026_05_30 - - - id: C3_CALIB_W_STYLE_REGISTER - command: python tools/validate_calibration_registry_v1.py - expect: {total_thresholds_min: 130, unregistered: 0, overclaimed: 0} - status: DONE_2026_05_30 - - - id: C4_GOLDEN_CASE_CAPITAL_STYLE - command: npm run validate-behavioral-coverage - expect: {status_token: BEHAVIORAL_COVERAGE_V1_OK, behavioral_coverage_pct: 100.0} - fail_code: BCH_CAPITAL_STYLE_FAIL - status: DONE_2026_05_30 - - - id: C5_WIRE_FULL_GATE_CAPITAL_STYLE - command: npm run full-gate - expect: {exit_code: 0} - fail_code: WIRE_FAIL - status: DONE_2026_05_30 - - - id: S1_AGENTS_MD_DIRECTION_S1 - command: "# AGENTS.md Direction S1 추가" - expect: {direction_s1_exists: true} - status: DONE_2026_05_30 - - - id: S2_INJECT_RENDER_CAPITAL - command: npm run render-report-json - expect: {capital_style_conviction_section_exists: true} - status: DONE_2026_05_30 - + - id: T01_COVERAGE_AUDIT + command: python tools/harness_coverage_auditor.py + expect: + true_missing_count: 0 + coverage_pct_min: 95.0 + fail_code: HARNESS_COVERAGE_AUDIT_FAIL + - id: T02_RUNTIME_REGISTRY_BUILD + command: python tools/build_formula_runtime_registry_v1.py --audit Temp/harness_coverage_audit.json + --out Temp/formula_runtime_registry_v1.json + expect: + formula_total: 163 + declared_runtime_count: 163 + runtime_adjusted_coverage_pct: 100.0 + unmapped_formula_count: 0 + fail_code: FORMULA_IMPLEMENTATION_REGISTRY_V1_FAIL + - id: T03_RUNTIME_REGISTRY_VALIDATE + command: python tools/validate_formula_runtime_registry_v1.py --json Temp/formula_runtime_registry_v1.json + --target-coverage 100 + expect: + status_token: FORMULA_IMPLEMENTATION_REGISTRY_V1_OK + fail_code: FORMULA_IMPLEMENTATION_REGISTRY_V1_FAIL + - id: T04_DQ_RECON_BUILD + command: python tools/build_data_quality_reconciliation_v1.py --json GatherTradingData.json + --integrity Temp/data_integrity_score_v1.json --out Temp/data_quality_reconciliation_v1.json + expect: + formula_id: DATA_QUALITY_RECONCILIATION_V1 + fail_code: DATA_QUALITY_RECONCILIATION_V1_BUILD_FAIL + - id: T05_DQ_RECON_VALIDATE + command: python tools/validate_data_quality_reconciliation_v1.py --json Temp/data_quality_reconciliation_v1.json + --min-schema-score 100 --min-investment-quality-score 90 + expect: + status_token: DATA_QUALITY_RECONCILIATION_V1_OK + fail_code: DATA_QUALITY_RECONCILIATION_V1_FAIL + note: 실데이터 부족 구간은 임시로 FAIL 허용하지 않고 WARN 원장으로 기록 후 원인 해결 + - id: T06_ENGINE_GATE + command: python tools/validate_engine_harness_gate.py --json GatherTradingData.json + --report Temp/operational_report.md --harness-json Temp/prediction_improvement_harness.json + --result-json Temp/engine_harness_gate_result.json --rule-lifecycle-json Temp/rule_lifecycle_policy.json + --strategy-harness-json Temp/strategy_harness_v2.json + expect: + status: OK + failed_checks_count: 0 + required_checks: + - CHECK_81_FORMULA_RUNTIME_REGISTRY_V1 + - CHECK_82_DATA_QUALITY_RECONCILIATION_V1 + fail_code: ENGINE_HARNESS_GATE_FAIL + - id: T07_RELEASE_PACKAGE + command: npm run prepare-upload-zip -- --validation-mode release --profile + expect: + gate_status: OK + profile_exists: Temp/pipeline_runtime_profile_v1.json + package_exists: ../data_feed.zip + fail_code: PREPARE_UPLOAD_ZIP_FAIL + - id: B01_BCH_CONTRACT + command: '# spec/26_behavioral_coverage_contract.yaml 작성 완료' + expect: + file_exists: spec/26_behavioral_coverage_contract.yaml + decision_critical_count: 40 + status: DONE_2026_05_30 + - id: B02_GOLDEN_AUTHOR + command: '# spec/formula_golden_cases_v2.yaml 손계산 골든케이스 작성 완료' + expect: + cases_total_min: 18 + provenance: HAND_COMPUTED or SPEC_DERIVED only + status: DONE_2026_05_30 + - id: B03_PY_MIRROR + command: python tools/run_formula_golden_cases_v2.py + expect: + status_token: BEHAVIORAL_COVERAGE_PY_OK + behavioral_coverage_pct: 100.0 + python_fail: 0 + fail_code: BCH_PY_MIRROR_FAIL + - id: B04_GAS_PARITY + command: node tools/run_gas_golden_parity.js + expect: + status_token: GAS_PARITY_OK + gas_fail: 0 + fail_code: BCH_GAS_PARITY_FAIL + - id: B05_3WAY_VALIDATE + command: python tools/validate_behavioral_coverage_v1.py --strict + expect: + status_token: BEHAVIORAL_COVERAGE_V1_OK + behavioral_coverage_pct: 100.0 + implementation_divergence_count: 0 + fail_code: BEHAVIORAL_COVERAGE_V1_FAIL + - id: B06_DIVERGENCE_FIX + command: '# normalize_tick round→floor 수정, PROFIT_LOCK_STAGE GAS 단계명 정정 완료' + expect: + divergence_count: 0 + status: DONE_2026_05_30 + - id: B07_WIRE_FULLGATE + command: npm run validate-behavioral-coverage + expect: + exit_code: 0 + fail_code: BCH_WIRING_FAIL + - id: P2_REGISTRY_BUILD + command: '# spec/calibration_registry.yaml 69개 임계값 등록 완료' + expect: + total_thresholds_min: 60 + status: DONE_2026_05_30 + - id: P2_REGISTRY_VALIDATE + command: python tools/validate_calibration_registry_v1.py + expect: + overclaimed_count: 0 + unregistered_threshold_count: 0 + status_token: CALIBRATION_REGISTRY_WARN or CALIBRATION_REGISTRY_OK + fail_code: CALIBRATION_REGISTRY_FAIL + - id: P2_PRIORITY_BUILD + command: python tools/build_calibration_priority_v1.py + expect: + status_token: CALIBRATION_PRIORITY_OK + priority_count_min: 5 + fail_code: CALIBRATION_PRIORITY_FAIL + - id: P3_FREEDOM_VALIDATE + command: python tools/validate_number_provenance_v1.py + expect: + status_token: LFM_V1_OK + llm_freedom_pct: 0.0 + fail_code: LFM_V1_FAIL + - id: P3_NARRATIVE_LOCK + command: python tools/build_llm_narrative_template_lock_v1.py + expect: + gate: PASS + total_violations: 0 + softening_violations: 0 + fail_code: LLM_NARRATIVE_LOCK_FAIL + - id: P4_HONEST_GUARD + command: python tools/build_honest_performance_guard_v1.py + expect: + status_token: HONEST_PERFORMANCE_V1_OK or HONEST_PERFORMANCE_V1_WARN + design_score_note: UNVALIDATED_DESIGN_SCORE 표기 필수 (samples<30) + fail_code: HONEST_PERFORMANCE_V1_FAIL + - id: SEMI_CONCENTRATION_POLICY + command: '# spec/strategy/semiconductor_concentration_policy.yaml 작성 완료' + expect: + file_exists: spec/strategy/semiconductor_concentration_policy.yaml + status: DONE_2026_05_30 + - id: SEMI_CLUSTER_GATE_UPDATE + command: '# gas_data_feed.gs calcSemiconductorClusterGate_ → MARKET_WEIGHT_AWARE_CLUSTER_GATE_V1 + 업데이트' + expect: + formula_id: MARKET_WEIGHT_AWARE_CLUSTER_GATE_V1 + kospi_weight_settings_driven: true + status: DONE_2026_05_30 + - id: LEADER_CAP_UPDATE + command: '# gas_data_feed.gs calcSinglePositionWeightCap_ → LEADER_POSITION_WEIGHT_CAP_V1 + 업데이트' + expect: + samsung_risk_on_cap: 40 + hynix_risk_on_cap: 22 + kospi_weight_settings_driven: true + status: DONE_2026_05_30 + - id: SECULAR_LEADER_AUTO_DETECT + command: '# gas_data_feed.gs calcSecularLeaderAutoDetect_ 함수 신설' + expect: + formula_id: SECULAR_LEADER_AUTO_DETECT_V1 + threshold: 6 + status: DONE_2026_05_30 + - id: SEMI_INJECT_UPDATE + command: '# tools/inject_computed_harness.py 클러스터/개별 게이트 함수 KOSPI 비중 반영' + expect: + settings_kospi_semi_weight_pct: true + gate_overwrite_direct: true + status: DONE_2026_05_30 + - id: AGENTS_O1_O2_UPDATE + command: '# AGENTS.md Direction O1/O2 새 공식명·차등한도로 업데이트' + expect: + o1_formula: LEADER_POSITION_WEIGHT_CAP_V1 + o2_formula: MARKET_WEIGHT_AWARE_CLUSTER_GATE_V1 + status: DONE_2026_05_30 + - id: INTEGRATED_ENGINE_INTEGRITY + command: npm run validate-engine-integrity + expect: + behavioral_coverage_pct: 100.0 + implementation_divergence_count: 0 + overclaimed_count: 0 + unregistered_threshold_count: 0 + llm_freedom_pct: 0.0 + softening_violations: 0 + fail_code: ENGINE_INTEGRITY_FAIL + - id: C1_BUILD_CAPITAL_STYLE_ALLOC + command: python tools/build_capital_style_allocation_v1.py + expect: + gate: PASS + ticker_count_min: 1 + conviction_range: '[0,100]' + fail_code: CAPITAL_ALLOC_BUILD_FAIL + status: DONE_2026_05_30 + - id: C2_VALIDATE_CAPITAL_STYLE_ALLOC + command: python tools/validate_capital_style_allocation_v1.py + expect: + status_token: CAPITAL_ALLOC_OK + violations: 0 + fail_code: CAPITAL_ALLOC_VALIDATE_FAIL + status: DONE_2026_05_30 + - id: C3_CALIB_W_STYLE_REGISTER + command: python tools/validate_calibration_registry_v1.py + expect: + total_thresholds_min: 130 + unregistered: 0 + overclaimed: 0 + status: DONE_2026_05_30 + - id: C4_GOLDEN_CASE_CAPITAL_STYLE + command: npm run validate-behavioral-coverage + expect: + status_token: BEHAVIORAL_COVERAGE_V1_OK + behavioral_coverage_pct: 100.0 + fail_code: BCH_CAPITAL_STYLE_FAIL + status: DONE_2026_05_30 + - id: C5_WIRE_FULL_GATE_CAPITAL_STYLE + command: npm run full-gate + expect: + exit_code: 0 + fail_code: WIRE_FAIL + status: DONE_2026_05_30 + - id: S1_AGENTS_MD_DIRECTION_S1 + command: '# AGENTS.md Direction S1 추가' + expect: + direction_s1_exists: true + status: DONE_2026_05_30 + - id: S2_INJECT_RENDER_CAPITAL + command: npm run render-report-json + expect: + capital_style_conviction_section_exists: true + status: DONE_2026_05_30 evidence_artifacts: - - Temp/harness_coverage_audit.json - - Temp/formula_runtime_registry_v1.json - - Temp/data_quality_reconciliation_v1.json - - Temp/engine_harness_gate_result.json - - Temp/pipeline_runtime_profile_v1.json - # BCH-V1 추가 (2026-05-30) - - Temp/formula_behavioral_coverage_v1.json - - Temp/formula_gas_parity_v1.json - - Temp/formula_behavioral_coverage_summary_v1.json - - Temp/calibration_registry_v1.json - - Temp/calibration_priority_v1.json - - Temp/llm_freedom_v1.json - - Temp/honest_performance_guard_v1.json + - Temp/harness_coverage_audit.json + - Temp/formula_runtime_registry_v1.json + - Temp/data_quality_reconciliation_v1.json + - Temp/engine_harness_gate_result.json + - Temp/pipeline_runtime_profile_v1.json + - Temp/formula_behavioral_coverage_v1.json + - Temp/formula_gas_parity_v1.json + - Temp/formula_behavioral_coverage_summary_v1.json + - Temp/calibration_registry_v1.json + - Temp/calibration_priority_v1.json + - Temp/llm_freedom_v1.json + - Temp/honest_performance_guard_v1.json completion_definition: hard_requirements: - - "모든 숫자 산출은 하네스 JSON 근거가 있어야 한다" - - "HTS 주문표와 WATCH 원장을 물리적으로 분리해야 한다" - - "runtime_adjusted_coverage_pct 100%를 숫자로 증빙해야 한다" - - "데이터 품질 충돌은 숨기지 않고 quality_conflict_flag로 보고해야 한다" + - 모든 숫자 산출은 하네스 JSON 근거가 있어야 한다 + - HTS 주문표와 WATCH 원장을 물리적으로 분리해야 한다 + - runtime_adjusted_coverage_pct 100%를 숫자로 증빙해야 한다 + - 데이터 품질 충돌은 숨기지 않고 quality_conflict_flag로 보고해야 한다 reject_conditions: - - "정량 근거 없이 100% 완료 문구 사용" - - "llm 추정값으로 가격/수량 생성" - - "engine_harness_gate_result.status!=OK 인데 완료 선언" + - 정량 근거 없이 100% 완료 문구 사용 + - llm 추정값으로 가격/수량 생성 + - engine_harness_gate_result.status!=OK 인데 완료 선언 current_status: - as_of: "2026-05-30" + as_of: '2026-05-30' T01_T03: PASS (coverage 100%, formula_total=168) T04: PASS (data_quality_reconciliation built) T05: FAIL_WARN (investment_quality=13% - 펀더멘털 미수집, 데이터 수집만이 해결) T06: STATUS=OK (engine_gate 1개 WARN_ONLY fail) T07: 미실행 - # BCH-V1 4-기둥 추가 완료 (2026-05-30) B01_B07: PASS (behavioral_coverage_pct=100%, divergence=0, GAS pass=45/45) B06_FIX: normalize_tick round→floor 수정 + PROFIT_LOCK_STAGE 단계명 7개 spec 일치 정정 P2_CALIB: overclaimed=0, unregistered=0, 69개 임계값 EXPERT_PRIOR 정직 공시 @@ -290,9 +308,7 @@ strategy_hardening_todo_v1: leader_position_weight_cap: LEADER_POSITION_WEIGHT_CAP_V1 secular_leader_auto_detect: calcSecularLeaderAutoDetect_ 신설 kospi_weights: settings 시트 입력값 반영 (하드코딩 금지) - # CAPITAL_STYLE_ALLOCATION_V1 (Section 3B) capital_style_allocation: DONE_2026_05_30 (C1~C5+S1+S2 완료) - final_completion_2026_05_30_extended: outcome_quality: 85.23 (PASS) guidance_proof: 99.26 (PASS) @@ -300,7 +316,6 @@ strategy_hardening_todo_v1: t5_op_rate: 73.24% (CALIBRATED) canonical_conflicts: 0 (score=100) all_major_targets: ACHIEVED - # 추가 달성 (2026-05-30 2차) behavioral_coverage_pct: 100.0 (PASS) implementation_divergence_count: 0 (PASS) gas_parity_cases: 45/45 (PASS) @@ -309,7 +324,6 @@ strategy_hardening_todo_v1: llm_freedom_pct_measured: 0.0 (PASS) softening_violations: 0 (PASS) design_score_as_proof_violations: 1 (WARN - UNVALIDATED 라벨 추가로 정직 처리) - # CAPITAL_STYLE_ALLOCATION_V1 (Section 3B) 달성 (2026-05-30 최종) capital_style_allocation_gate: PASS (11종목, CAPITAL_ALLOC_OK) capital_style_calibration: total=134 thresholds, overclaimed=0, unregistered=0 capital_style_report_section: operational_report에 conviction 표 렌더링 완료 diff --git a/spec/27_bch_calibration_runbook.yaml b/spec/27_bch_calibration_runbook.yaml index d5e6df7..a0db248 100644 --- a/spec/27_bch_calibration_runbook.yaml +++ b/spec/27_bch_calibration_runbook.yaml @@ -1,528 +1,417 @@ -# spec/27_bch_calibration_runbook.yaml -# BCH-V1 + CALIB-V1 실행 런북 (저성능 LLM 완전 재현 가이드) -# ──────────────────────────────────────────────────────────────────────────── -# 이 파일을 처음부터 끝까지 순서대로 따라 실행하면 -# 저성능 LLM도 동일한 결과(behavioral_coverage_pct=100%, divergence=0, -# llm_freedom_pct=0.0%)를 얻을 수 있다. -# -# 진정한 작업완료 기준: -# - BEHAVIORAL_COVERAGE_V1_OK (behavioral_coverage_pct=100%, divergence=0) -# - CALIBRATION_REGISTRY_WARN/OK (overclaimed=0, unregistered=0) -# - LFM_V1_OK (llm_freedom_pct=0.0%) -# - LLM_NARRATIVE_LOCK gate=PASS (softening_violations=0) -# - HONEST_PERFORMANCE_V1_WARN/OK (design_score_as_proof ≤1건) -# - full-gate EXIT=0 (53단계 파이프라인 전부 통과) -# ──────────────────────────────────────────────────────────────────────────── - +meta: + has_code_implementation: true + code_path: + - spec\27_bch_calibration_runbook.yaml runbook_id: BCH_CALIBRATION_RUNBOOK_V1 -version: "2026-05-30" -objective: | - yaml 지침(spec/13_formula_registry.yaml)의 공식이 GAS(.gs) 및 Python 구현과 +version: '2026-05-30' +objective: 'yaml 지침(spec/13_formula_registry.yaml)의 공식이 GAS(.gs) 및 Python 구현과 + 행위 수준에서 100% 일치하는지 검증하고, 하드코딩 임계값을 정직하게 관리하며, + LLM의 가격·수량 자유계산 여지를 0으로 측정·폐쇄한다. + "거짓 100%"를 제거하고 수치로 증빙 가능한 진짜 100%를 달성한다. -# ════════════════════════════════════════════════════════════════════════════ -# PHASE 0 — 전제조건 확인 -# ════════════════════════════════════════════════════════════════════════════ + ' phase_0_prerequisites: - description: "이 단계를 모두 만족해야 Phase 1을 시작할 수 있다." + description: 이 단계를 모두 만족해야 Phase 1을 시작할 수 있다. checks: - - id: P0_1 - command: "python --version" - expect: "Python 3.10+" - note: "yaml, json, math, re, pathlib 사용. 외부 패키지: pyyaml(pip install pyyaml)" - - - id: P0_2 - command: "node --version" - expect: "v18+" - note: "GAS 패리티 러너(run_gas_golden_parity.js)에 필요" - - - id: P0_3 - command: "python -c \"import yaml; print('yaml OK')\"" - expect: "yaml OK" - fail_action: "pip install pyyaml" - - - id: P0_4 - command: "ls spec/13_formula_registry.yaml spec/13b_harness_formulas.yaml" - expect: "두 파일 모두 존재" - note: "170개 공식 정의 파일" - - - id: P0_5 - command: "ls gas_data_feed.gs gas_lib.gs gas_apex_alpha_watch.gs" - expect: "세 파일 모두 존재" - note: "GAS 구현 파일" - -# ════════════════════════════════════════════════════════════════════════════ -# PHASE 1 — 행위기반 커버리지 하네스 (BCH-V1) -# ════════════════════════════════════════════════════════════════════════════ + - id: P0_1 + command: python --version + expect: Python 3.10+ + note: 'yaml, json, math, re, pathlib 사용. 외부 패키지: pyyaml(pip install pyyaml)' + - id: P0_2 + command: node --version + expect: v18+ + note: GAS 패리티 러너(run_gas_golden_parity.js)에 필요 + - id: P0_3 + command: python -c "import yaml; print('yaml OK')" + expect: yaml OK + fail_action: pip install pyyaml + - id: P0_4 + command: ls spec/13_formula_registry.yaml spec/13b_harness_formulas.yaml + expect: 두 파일 모두 존재 + note: 170개 공식 정의 파일 + - id: P0_5 + command: ls gas_data_feed.gs gas_lib.gs gas_apex_alpha_watch.gs + expect: 세 파일 모두 존재 + note: GAS 구현 파일 phase_1_behavioral_coverage: - description: | - "formula_id 문자열이 .gs에 등장한다" → "golden == Python미러 == GAS미러" 로 전환. + description: '"formula_id 문자열이 .gs에 등장한다" → "golden == Python미러 == GAS미러" 로 전환. + 발견된 분기(divergence)는 spec/13 기준으로 근본 정정. + ' ordered_steps: + - id: S1_1_VERIFY_CONTRACT + name: 계약 파일 확인 + command: cat spec/26_behavioral_coverage_contract.yaml | head -20 + expect: 'behavioral_coverage_pct_min: 100.0' + note: 없으면 계약 파일 작성 필요 (spec/26_behavioral_coverage_contract.yaml) + - id: S1_2_VERIFY_GOLDEN_CASES + name: 골든케이스 파일 확인 + command: "python -c \"\nimport yaml\nwith open('spec/formula_golden_cases_v2.yaml',\ + \ encoding='utf-8') as f:\n d = yaml.safe_load(f)\nformulas = d.get('golden_cases_v2',\ + \ [])\nprint(f'등록 공식 수: {len(formulas)}')\nfor f in formulas:\n cases = f.get('cases',\ + \ [])\n n = sum(1 for c in cases if 'inputs' in c)\n print(f' {f[\\\"\ + formula_id\\\"]}: {n}개 케이스')\n\"\n" + expect: 등록 공식 수 ≥ 22 + fail_action: "spec/formula_golden_cases_v2.yaml 에 golden case 추가.\n각 case 형식:\n\ + \ - id: 케이스ID\n inputs: {필드명: 값}\n expected: {출력필드: 기대값}\n tolerance:\ + \ {수치필드: 허용오차}\n provenance: HAND_COMPUTED # 반드시 spec에서 손계산. .gs 역복사 금지.\n\ + 주의: expected 값을 .gs 출력에서 역복사하면 순환논리(REJECT).\n" + - id: S1_3_RUN_PY_MIRROR + name: Python 미러 검증 + command: python tools/run_formula_golden_cases_v2.py + expect: + status_token: BEHAVIORAL_COVERAGE_PY_OK + behavioral_coverage_pct: 100.0 + python_fail: 0 + fail_code: BCH_PY_MIRROR_FAIL + fail_action: '출력에서 [FAIL] 공식을 찾아 python_function 로직을 spec/13 expression과 비교. - - id: S1_1_VERIFY_CONTRACT - name: "계약 파일 확인" - command: "cat spec/26_behavioral_coverage_contract.yaml | head -20" - expect: "behavioral_coverage_pct_min: 100.0" - note: "없으면 계약 파일 작성 필요 (spec/26_behavioral_coverage_contract.yaml)" + spec/13 expression이 맞고 Python이 틀린 경우 → Python 수정. - - id: S1_2_VERIFY_GOLDEN_CASES - name: "골든케이스 파일 확인" - command: | - python -c " - import yaml - with open('spec/formula_golden_cases_v2.yaml', encoding='utf-8') as f: - d = yaml.safe_load(f) - formulas = d.get('golden_cases_v2', []) - print(f'등록 공식 수: {len(formulas)}') - for f in formulas: - cases = f.get('cases', []) - n = sum(1 for c in cases if 'inputs' in c) - print(f' {f[\"formula_id\"]}: {n}개 케이스') - " - expect: "등록 공식 수 ≥ 22" - fail_action: | - spec/formula_golden_cases_v2.yaml 에 golden case 추가. - 각 case 형식: - - id: 케이스ID - inputs: {필드명: 값} - expected: {출력필드: 기대값} - tolerance: {수치필드: 허용오차} - provenance: HAND_COMPUTED # 반드시 spec에서 손계산. .gs 역복사 금지. - 주의: expected 값을 .gs 출력에서 역복사하면 순환논리(REJECT). + Python이 맞고 golden expected가 틀린 경우 → golden case 수정(다시 손계산). - - id: S1_3_RUN_PY_MIRROR - name: "Python 미러 검증" - command: "python tools/run_formula_golden_cases_v2.py" - expect: - status_token: BEHAVIORAL_COVERAGE_PY_OK - behavioral_coverage_pct: 100.0 - python_fail: 0 - fail_code: BCH_PY_MIRROR_FAIL - fail_action: | - 출력에서 [FAIL] 공식을 찾아 python_function 로직을 spec/13 expression과 비교. - spec/13 expression이 맞고 Python이 틀린 경우 → Python 수정. - Python이 맞고 golden expected가 틀린 경우 → golden case 수정(다시 손계산). - 절대 "Python 출력 = expected" 방식의 역복사 금지. + 절대 "Python 출력 = expected" 방식의 역복사 금지. - - id: S1_4_RUN_GAS_PARITY - name: "GAS 패리티 검증" - command: "node tools/run_gas_golden_parity.js" - expect: - status_token: GAS_PARITY_OK - gas_fail: 0 - fail_code: BCH_GAS_PARITY_FAIL - fail_action: | - 출력에서 [GAS_FAIL] 또는 [GAS_CORRECT_PYTHON_WRONG] 확인. - GAS_CORRECT_PYTHON_WRONG: GAS가 spec_correct → Python 수정 필요. - GAS_FAIL: GAS가 틀림 → gas_data_feed.gs / gas_lib.gs / gas_apex_alpha_watch.gs 수정. - 수정 기준: 항상 spec/13_formula_registry.yaml의 expression. + ' + - id: S1_4_RUN_GAS_PARITY + name: GAS 패리티 검증 + command: node tools/run_gas_golden_parity.js + expect: + status_token: GAS_PARITY_OK + gas_fail: 0 + fail_code: BCH_GAS_PARITY_FAIL + fail_action: '출력에서 [GAS_FAIL] 또는 [GAS_CORRECT_PYTHON_WRONG] 확인. - - id: S1_5_3WAY_VALIDATE - name: "3-way 동등성 게이트" - command: "python tools/validate_behavioral_coverage_v1.py --strict" - expect: - status_token: BEHAVIORAL_COVERAGE_V1_OK - behavioral_coverage_pct: 100.0 - implementation_divergence_count: 0 - fail_code: BEHAVIORAL_COVERAGE_V1_FAIL - fail_action: | - implementation_divergence_count > 0 이면: - - PYTHON_DIVERGES_FROM_SPEC: Python normalize_tick 등 → math.floor로 수정 - - GAS_DIVERGES_FROM_GOLDEN: GAS 함수 → spec/13 expression 적용 - divergence가 0이어도 coverage < 100%이면 golden case 부족 → S1_2로 돌아감. + GAS_CORRECT_PYTHON_WRONG: GAS가 spec_correct → Python 수정 필요. - - id: S1_6_WIRE_PIPELINE - name: "파이프라인 연결 확인" - command: "npm run validate-behavioral-coverage" - expect: - exit_code: 0 - status_token: BEHAVIORAL_COVERAGE_V1_OK - fail_code: BCH_WIRING_FAIL - note: "package.json의 validate-behavioral-coverage 스크립트가 S1_3+S1_4+S1_5를 순서대로 실행" + GAS_FAIL: GAS가 틀림 → gas_data_feed.gs / gas_lib.gs / gas_apex_alpha_watch.gs + 수정. + 수정 기준: 항상 spec/13_formula_registry.yaml의 expression. + + ' + - id: S1_5_3WAY_VALIDATE + name: 3-way 동등성 게이트 + command: python tools/validate_behavioral_coverage_v1.py --strict + expect: + status_token: BEHAVIORAL_COVERAGE_V1_OK + behavioral_coverage_pct: 100.0 + implementation_divergence_count: 0 + fail_code: BEHAVIORAL_COVERAGE_V1_FAIL + fail_action: "implementation_divergence_count > 0 이면:\n - PYTHON_DIVERGES_FROM_SPEC:\ + \ Python normalize_tick 등 → math.floor로 수정\n - GAS_DIVERGES_FROM_GOLDEN: GAS\ + \ 함수 → spec/13 expression 적용\ndivergence가 0이어도 coverage < 100%이면 golden case\ + \ 부족 → S1_2로 돌아감.\n" + - id: S1_6_WIRE_PIPELINE + name: 파이프라인 연결 확인 + command: npm run validate-behavioral-coverage + expect: + exit_code: 0 + status_token: BEHAVIORAL_COVERAGE_V1_OK + fail_code: BCH_WIRING_FAIL + note: package.json의 validate-behavioral-coverage 스크립트가 S1_3+S1_4+S1_5를 순서대로 실행 completion_gate: - command: "python tools/validate_behavioral_coverage_v1.py --strict" + command: python tools/validate_behavioral_coverage_v1.py --strict required_output: - behavioral_coverage_pct: "== 100.0" - implementation_divergence_count: "== 0" - evidence_artifact: "Temp/formula_behavioral_coverage_summary_v1.json" - -# ════════════════════════════════════════════════════════════════════════════ -# PHASE 2 — 임계값 보정 레지스트리 (CALIB-V1) -# ════════════════════════════════════════════════════════════════════════════ + behavioral_coverage_pct: == 100.0 + implementation_divergence_count: == 0 + evidence_artifact: Temp/formula_behavioral_coverage_summary_v1.json phase_2_calibration_registry: - description: | - 모든 하드코딩 임계값을 spec/calibration_registry.yaml 에 등록하고 + description: '모든 하드코딩 임계값을 spec/calibration_registry.yaml 에 등록하고 + overclaimed(검증 안 된 값을 CALIBRATED로 위장) = 0 을 달성한다. + ' ordered_steps: - - - id: S2_1_VERIFY_REGISTRY - name: "레지스트리 파일 확인" - command: | - python -c " - import yaml - with open('spec/calibration_registry.yaml', encoding='utf-8') as f: - d = yaml.safe_load(f) - t = d.get('thresholds', []) - print(f'총 임계값: {len(t)}') - by_src = {} - for e in t: - s = e.get('source', 'EXPERT_PRIOR') - by_src[s] = by_src.get(s, 0) + 1 - for s, n in sorted(by_src.items()): - print(f' {s}: {n}') - " - expect: "총 임계값 ≥ 60" - - - id: S2_2_RUN_REGISTRY_VALIDATE - name: "레지스트리 검증" - command: "python tools/validate_calibration_registry_v1.py" - expect: - overclaimed_count: 0 - unregistered_threshold_count: 0 - status_token: "CALIBRATION_REGISTRY_WARN or CALIBRATION_REGISTRY_OK" - fail_code: CALIBRATION_REGISTRY_FAIL - fail_action: | - OVERCLAIMED: source=CALIBRATED 이면서 sample_n<30 → source를 PROVISIONAL 로 변경. - 절대 sample_n을 30으로 올려서 해결 금지 (실제 표본 없이 수치 조작). - UNREGISTERED: .gs/.py 핫존에서 발견된 미등록 상수 → calibration_registry.yaml에 추가. - 추가 형식: - - id: 고유ID - value: 상수값 - unit: pct/ratio/count/etc - source: EXPERT_PRIOR # 실측 없으면 반드시 EXPERT_PRIOR - sample_n: 0 - owner_formula: 관련_FORMULA_ID - gs_location: "파일명:줄번호" - - - id: S2_3_BUILD_PRIORITY - name: "보정 우선순위 연결" - command: "python tools/build_calibration_priority_v1.py" - expect: - status_token: CALIBRATION_PRIORITY_OK - priority_count_min: 5 - fail_code: CALIBRATION_PRIORITY_FAIL - note: "alpha_feedback_loop_v2.json의 miss5_count 신호를 임계값 보정 우선순위에 연결" - + - id: S2_1_VERIFY_REGISTRY + name: 레지스트리 파일 확인 + command: "python -c \"\nimport yaml\nwith open('spec/calibration_registry.yaml',\ + \ encoding='utf-8') as f:\n d = yaml.safe_load(f)\nt = d.get('thresholds',\ + \ [])\nprint(f'총 임계값: {len(t)}')\nby_src = {}\nfor e in t:\n s = e.get('source',\ + \ 'EXPERT_PRIOR')\n by_src[s] = by_src.get(s, 0) + 1\nfor s, n in sorted(by_src.items()):\n\ + \ print(f' {s}: {n}')\n\"\n" + expect: 총 임계값 ≥ 60 + - id: S2_2_RUN_REGISTRY_VALIDATE + name: 레지스트리 검증 + command: python tools/validate_calibration_registry_v1.py + expect: + overclaimed_count: 0 + unregistered_threshold_count: 0 + status_token: CALIBRATION_REGISTRY_WARN or CALIBRATION_REGISTRY_OK + fail_code: CALIBRATION_REGISTRY_FAIL + fail_action: "OVERCLAIMED: source=CALIBRATED 이면서 sample_n<30 → source를 PROVISIONAL\ + \ 로 변경.\n 절대 sample_n을 30으로 올려서 해결 금지 (실제 표본 없이 수치 조작).\nUNREGISTERED: .gs/.py\ + \ 핫존에서 발견된 미등록 상수 → calibration_registry.yaml에 추가.\n 추가 형식:\n - id: 고유ID\n\ + \ value: 상수값\n unit: pct/ratio/count/etc\n source: EXPERT_PRIOR\ + \ # 실측 없으면 반드시 EXPERT_PRIOR\n sample_n: 0\n owner_formula: 관련_FORMULA_ID\n\ + \ gs_location: \"파일명:줄번호\"\n" + - id: S2_3_BUILD_PRIORITY + name: 보정 우선순위 연결 + command: python tools/build_calibration_priority_v1.py + expect: + status_token: CALIBRATION_PRIORITY_OK + priority_count_min: 5 + fail_code: CALIBRATION_PRIORITY_FAIL + note: alpha_feedback_loop_v2.json의 miss5_count 신호를 임계값 보정 우선순위에 연결 calibration_policy_enforcement: - - rule: "source=CALIBRATED 이려면 sample_n ≥ 30 AND backtest_doc이 있어야 한다" - - rule: "실측 없는 임계값은 반드시 EXPERT_PRIOR 또는 PROVISIONAL" - - rule: "overclaimed_count > 0 이면 CALIBRATION_REGISTRY_FAIL → 배포 차단" - + - rule: source=CALIBRATED 이려면 sample_n ≥ 30 AND backtest_doc이 있어야 한다 + - rule: 실측 없는 임계값은 반드시 EXPERT_PRIOR 또는 PROVISIONAL + - rule: overclaimed_count > 0 이면 CALIBRATION_REGISTRY_FAIL → 배포 차단 calibration_path: EXPERT_PRIOR: - description: "30년 현장경험 기반 초기값. 검증 없음." - next_step: "표본 수집 → 30건 이상이면 PROVISIONAL 승격 심사" + description: 30년 현장경험 기반 초기값. 검증 없음. + next_step: 표본 수집 → 30건 이상이면 PROVISIONAL 승격 심사 PROVISIONAL: - description: "예비 검증(1-29건). 방향성 확인됨." - next_step: "30건 이상 + 실제 P&L 검증 → CALIBRATED" + description: 예비 검증(1-29건). 방향성 확인됨. + next_step: 30건 이상 + 실제 P&L 검증 → CALIBRATED CALIBRATED: - description: "실측 표본 ≥30건 backtest 완료." - maintenance: "분기별 재검증. 시장 국면 변화 시 재보정" - + description: 실측 표본 ≥30건 backtest 완료. + maintenance: 분기별 재검증. 시장 국면 변화 시 재보정 completion_gate: - command: "python tools/validate_calibration_registry_v1.py" + command: python tools/validate_calibration_registry_v1.py required_output: - overclaimed_count: "== 0" - unregistered_threshold_count: "== 0" - evidence_artifact: "Temp/calibration_registry_v1.json" - -# ════════════════════════════════════════════════════════════════════════════ -# PHASE 3 — LLM 자유도 측정·폐쇄 (LFM-V1) -# ════════════════════════════════════════════════════════════════════════════ + overclaimed_count: == 0 + unregistered_threshold_count: == 0 + evidence_artifact: Temp/calibration_registry_v1.json phase_3_llm_freedom: - description: | - 가격·수량을 LLM이 자유계산하는 여지를 0으로 측정하고, + description: '가격·수량을 LLM이 자유계산하는 여지를 0으로 측정하고, + narrative 완화어휘(INVALID_SOFTENING)를 차단한다. + ' ordered_steps: + - id: S3_1_FREEDOM_VALIDATE + name: LLM 자유도 측정 + command: python tools/validate_number_provenance_v1.py + expect: + status_token: LFM_V1_OK + llm_freedom_pct: 0.0 + freedom_signals_count: 0 + fail_code: LFM_V1_FAIL + fail_action: 'prompts/analysis_prompt.md 에서 ''직접 계산한다'' 문구를 찾아 - - id: S3_1_FREEDOM_VALIDATE - name: "LLM 자유도 측정" - command: "python tools/validate_number_provenance_v1.py" - expect: - status_token: LFM_V1_OK - llm_freedom_pct: 0.0 - freedom_signals_count: 0 - fail_code: LFM_V1_FAIL - fail_action: | - prompts/analysis_prompt.md 에서 '직접 계산한다' 문구를 찾아 - 'DATA_MISSING — 하네스 업데이트 필요' 로 교체. - harness 결측 시 LLM 직접계산 허용 문구 전면 삭제 (HS011). + ''DATA_MISSING — 하네스 업데이트 필요'' 로 교체. - - id: S3_2_NARRATIVE_LOCK - name: "LLM 내러티브 잠금" - command: "python tools/build_llm_narrative_template_lock_v1.py" - expect: - gate: PASS - total_violations: 0 - narrative_violations: 0 - softening_violations: 0 - fail_code: LLM_NARRATIVE_LOCK_FAIL - fail_action: | - [INVALID_NARRATIVE]: 금지어휘(같다/약간/괜찮다/곧 등) 섹션에서 제거. - [INVALID_SOFTENING]: BLOCK/SELL verdict 근방에서 완화어휘 제거. - 완화어휘 패턴: 그래도/유연하게/장기관점재진입/고려가능/상황에따라/아직괜찮/지켜볼만 - 규칙: BLOCK verdict가 있으면 완화 해석 문장을 완전히 삭제. + harness 결측 시 LLM 직접계산 허용 문구 전면 삭제 (HS011). + ' + - id: S3_2_NARRATIVE_LOCK + name: LLM 내러티브 잠금 + command: python tools/build_llm_narrative_template_lock_v1.py + expect: + gate: PASS + total_violations: 0 + narrative_violations: 0 + softening_violations: 0 + fail_code: LLM_NARRATIVE_LOCK_FAIL + fail_action: "[INVALID_NARRATIVE]: 금지어휘(같다/약간/괜찮다/곧 등) 섹션에서 제거.\n[INVALID_SOFTENING]:\ + \ BLOCK/SELL verdict 근방에서 완화어휘 제거.\n 완화어휘 패턴: 그래도/유연하게/장기관점재진입/고려가능/상황에따라/아직괜찮/지켜볼만\n\ + \ 규칙: BLOCK verdict가 있으면 완화 해석 문장을 완전히 삭제.\n" completion_gate: - command: "python tools/validate_number_provenance_v1.py && python tools/build_llm_narrative_template_lock_v1.py" + command: python tools/validate_number_provenance_v1.py && python tools/build_llm_narrative_template_lock_v1.py required_output: - llm_freedom_pct: "== 0.0" - softening_violations: "== 0" - evidence_artifact: "Temp/llm_freedom_v1.json" - -# ════════════════════════════════════════════════════════════════════════════ -# PHASE 4 — 정직 성과증빙 (HONEST-V1) -# ════════════════════════════════════════════════════════════════════════════ + llm_freedom_pct: == 0.0 + softening_violations: == 0 + evidence_artifact: Temp/llm_freedom_v1.json phase_4_honest_performance: - description: | - 설계점수(design_score)와 실측점수(actual_score)를 물리적으로 분리. + description: '설계점수(design_score)와 실측점수(actual_score)를 물리적으로 분리. + sample_n < 30 이면 반드시 UNVALIDATED_DESIGN_SCORE 라벨. + ' ordered_steps: + - id: S4_1_HONEST_GUARD + name: 정직 성과증빙 하네스 + command: python tools/build_honest_performance_guard_v1.py + expect: + status_token: HONEST_PERFORMANCE_V1_OK or HONEST_PERFORMANCE_V1_WARN + note: WARN은 표본 부족(sample<30)을 정직하게 공시하는 정상 상태 + fail_code: HONEST_PERFORMANCE_V1_FAIL + fail_action: "design_score_as_proof 위반이 있으면:\n 해당 score를 보고서에 표시할 때 '[UNVALIDATED_DESIGN_SCORE:\ + \ n=N]' 주석 필수.\n 'score=97.12(검증됨)' 형식 절대 금지.\nT+1/T+5 KPI가 목표 미달이면:\n 보정루프\ + \ 로드맵(build_calibration_priority_v1.py 결과) 참조.\n '목표 달성' 선언 금지 — 수치 그대로 공시.\n" + - id: S4_2_KPI_TRACKING + name: T+1/T+5 KPI 추적 + command: "python -c \"\nimport json\nwith open('Temp/honest_performance_guard_v1.json',\ + \ encoding='utf-8') as f:\n d = json.load(f)\nfor k in d.get('kpi_tracker',\ + \ []):\n status = 'OK' if k['status'] != 'BELOW_TARGET' else 'BELOW_TARGET'\n\ + \ print(f\\\"{k['metric']}: {k['current']}% (target={k['target_min']}%) [{status}]\\\ + \")\n\"\n" + expect: 출력 확인 + note: 'T+5 35.86% → 50% 목표: 보정루프 4단계 - - id: S4_1_HONEST_GUARD - name: "정직 성과증빙 하네스" - command: "python tools/build_honest_performance_guard_v1.py" - expect: - status_token: "HONEST_PERFORMANCE_V1_OK or HONEST_PERFORMANCE_V1_WARN" - note: "WARN은 표본 부족(sample<30)을 정직하게 공시하는 정상 상태" - fail_code: HONEST_PERFORMANCE_V1_FAIL - fail_action: | - design_score_as_proof 위반이 있으면: - 해당 score를 보고서에 표시할 때 '[UNVALIDATED_DESIGN_SCORE: n=N]' 주석 필수. - 'score=97.12(검증됨)' 형식 절대 금지. - T+1/T+5 KPI가 목표 미달이면: - 보정루프 로드맵(build_calibration_priority_v1.py 결과) 참조. - '목표 달성' 선언 금지 — 수치 그대로 공시. + Step1: 표본 누적(30건) - - id: S4_2_KPI_TRACKING - name: "T+1/T+5 KPI 추적" - command: | - python -c " - import json - with open('Temp/honest_performance_guard_v1.json', encoding='utf-8') as f: - d = json.load(f) - for k in d.get('kpi_tracker', []): - status = 'OK' if k['status'] != 'BELOW_TARGET' else 'BELOW_TARGET' - print(f\"{k['metric']}: {k['current']}% (target={k['target_min']}%) [{status}]\") - " - expect: "출력 확인" - note: | - T+5 35.86% → 50% 목표: 보정루프 4단계 - Step1: 표본 누적(30건) - Step2: ALEG_V2_GATE1_BLOCK_PCT 3% → 실측 최적값 PROVISIONAL 승격 - Step3: DSD_V1 가중치 logistic regression 최적화 - Step4: K2 분할비율 backtest → CALIBRATED + Step2: ALEG_V2_GATE1_BLOCK_PCT 3% → 실측 최적값 PROVISIONAL 승격 + Step3: DSD_V1 가중치 logistic regression 최적화 + + Step4: K2 분할비율 backtest → CALIBRATED + + ' completion_gate: - command: "python tools/build_honest_performance_guard_v1.py" + command: python tools/build_honest_performance_guard_v1.py required_output: - violation_count: "== 0 (UNVALIDATED 라벨 추가로 해소)" - evidence_artifact: "Temp/honest_performance_guard_v1.json" - -# ════════════════════════════════════════════════════════════════════════════ -# PHASE 5 — 통합 게이트 + 파이프라인 확인 -# ════════════════════════════════════════════════════════════════════════════ + violation_count: == 0 (UNVALIDATED 라벨 추가로 해소) + evidence_artifact: Temp/honest_performance_guard_v1.json phase_5_integration: - description: "4-기둥 통합 실행 후 full-gate / daily-feedback-report 최종 통과 확인" - + description: 4-기둥 통합 실행 후 full-gate / daily-feedback-report 최종 통과 확인 ordered_steps: + - id: S5_1_ENGINE_INTEGRITY + name: 통합 엔진 무결성 + command: npm run validate-engine-integrity + expect: + exit_code: 0 + behavioral_coverage_pct: 100.0 + overclaimed_count: 0 + llm_freedom_pct: 0.0 + softening_violations: 0 + fail_code: ENGINE_INTEGRITY_FAIL + note: 'validate-behavioral-coverage && - - id: S5_1_ENGINE_INTEGRITY - name: "통합 엔진 무결성" - command: "npm run validate-engine-integrity" - expect: - exit_code: 0 - behavioral_coverage_pct: 100.0 - overclaimed_count: 0 - llm_freedom_pct: 0.0 - softening_violations: 0 - fail_code: ENGINE_INTEGRITY_FAIL - note: | - validate-behavioral-coverage && - validate-calibration-registry && - validate-llm-freedom && - validate-narrative-lock && - build-honest-performance-guard && - build-calibration-priority + validate-calibration-registry && - - id: S5_2_FULL_GATE - name: "전체 파이프라인 확인" - command: "npm run full-gate" - expect: - exit_code: 0 - note: "53단계 전부 통과. WARN_ONLY 항목(펀더멘털 미수집)은 허용." - fail_code: FULL_GATE_FAIL - fail_action: | - 실패 단계를 단독 실행해 원인 파악: - npm run <실패_단계명> - HARNESS CONTEXT FAIL → validate_harness_context.py의 허용 enum 확인 - validate-specs FAIL → RetirementAssetPortfolio.yaml spec_files에 신규 파일 등록 + validate-llm-freedom && - - id: S5_3_DAILY_FEEDBACK - name: "일일 피드백 리포트 확인" - command: "npm run daily-feedback-report" - expect: - exit_code: 0 - fail_code: DAILY_FEEDBACK_FAIL + validate-narrative-lock && + build-honest-performance-guard && + + build-calibration-priority + + ' + - id: S5_2_FULL_GATE + name: 전체 파이프라인 확인 + command: npm run full-gate + expect: + exit_code: 0 + note: 53단계 전부 통과. WARN_ONLY 항목(펀더멘털 미수집)은 허용. + fail_code: FULL_GATE_FAIL + fail_action: "실패 단계를 단독 실행해 원인 파악:\n npm run <실패_단계명>\nHARNESS CONTEXT FAIL →\ + \ validate_harness_context.py의 허용 enum 확인\nvalidate-specs FAIL → RetirementAssetPortfolio.yaml\ + \ spec_files에 신규 파일 등록\n" + - id: S5_3_DAILY_FEEDBACK + name: 일일 피드백 리포트 확인 + command: npm run daily-feedback-report + expect: + exit_code: 0 + fail_code: DAILY_FEEDBACK_FAIL completion_gate: - command: "npm run full-gate && npm run daily-feedback-report" + command: npm run full-gate && npm run daily-feedback-report required_output: - exit_code: "== 0 (both)" - evidence_artifact: "Temp/formula_behavioral_coverage_summary_v1.json" - -# ════════════════════════════════════════════════════════════════════════════ -# PHASE 6 — 보정루프 (표본 누적 후 반복 실행) -# ════════════════════════════════════════════════════════════════════════════ + exit_code: == 0 (both) + evidence_artifact: Temp/formula_behavioral_coverage_summary_v1.json phase_6_calibration_loop: - description: | - 매 거래일 T+5 결과 수집 후 실행. 표본이 누적될수록 + description: '매 거래일 T+5 결과 수집 후 실행. 표본이 누적될수록 + 임계값을 EXPERT_PRIOR → PROVISIONAL → CALIBRATED 로 승격한다. - trigger: "매 거래일 장마감 후 (15:30 이후)" - + ' + trigger: 매 거래일 장마감 후 (15:30 이후) ordered_steps: - - - id: L1_UPDATE_HISTORY - name: "평가 이력 업데이트" - command: "npm run update-evaluation-history" - note: "proposal_evaluation_history.json 에 T+5 결과 추가" - - - id: L2_CHECK_SAMPLE_COUNT - name: "표본 수 확인" - command: | - python -c " - import json - with open('Temp/calibration_priority_v1.json', encoding='utf-8') as f: - d = json.load(f) - print('cases_analyzed:', d.get('cases_analyzed', 0)) - print('miss5_count:', d.get('miss5_count', 0)) - top3 = d.get('priority_list', [])[:3] - for p in top3: - print(f' [{p[\"urgency_score\"]}] {p[\"calibration_id\"]}: value={p[\"current_value\"]} n={p[\"sample_n\"]}') - " - note: "cases_analyzed ≥ 30이면 최우선 임계값 PROVISIONAL 승격 심사" - - - id: L3_CALIBRATION_CANDIDATE_REVIEW - name: "보정 후보 심사 (cases ≥ 30 시)" - trigger_condition: "cases_analyzed >= 30" - manual_action: | - 1. ALEG_V2_GATE1_BLOCK_PCT(3%) 검증: - - late_chase_attribution_v1.json 의 chase_entry_rate 확인 - - velocity_1d ≥ 3%에서 진입한 케이스의 T+5 승률 계산 - - 현재 3%보다 낮은 임계값이 더 효과적이면 새 값 제안 - 2. 새 값 제안 후: - - calibration_registry.yaml의 source를 PROVISIONAL로 변경 - - sample_n에 실제 표본 수 기재 - - last_calibrated: 오늘 날짜 - 3. 변경 후 반드시 npm run validate-engine-integrity 재실행 - - - id: L4_RUN_FULL_GATE - name: "변경 후 전체 검증" - command: "npm run full-gate" - expect: {exit_code: 0} - + - id: L1_UPDATE_HISTORY + name: 평가 이력 업데이트 + command: npm run update-evaluation-history + note: proposal_evaluation_history.json 에 T+5 결과 추가 + - id: L2_CHECK_SAMPLE_COUNT + name: 표본 수 확인 + command: "python -c \"\nimport json\nwith open('Temp/calibration_priority_v1.json',\ + \ encoding='utf-8') as f:\n d = json.load(f)\nprint('cases_analyzed:', d.get('cases_analyzed',\ + \ 0))\nprint('miss5_count:', d.get('miss5_count', 0))\ntop3 = d.get('priority_list',\ + \ [])[:3]\nfor p in top3:\n print(f' [{p[\\\"urgency_score\\\"]}] {p[\\\"\ + calibration_id\\\"]}: value={p[\\\"current_value\\\"]} n={p[\\\"sample_n\\\"\ + ]}')\n\"\n" + note: cases_analyzed ≥ 30이면 최우선 임계값 PROVISIONAL 승격 심사 + - id: L3_CALIBRATION_CANDIDATE_REVIEW + name: 보정 후보 심사 (cases ≥ 30 시) + trigger_condition: cases_analyzed >= 30 + manual_action: "1. ALEG_V2_GATE1_BLOCK_PCT(3%) 검증:\n - late_chase_attribution_v1.json\ + \ 의 chase_entry_rate 확인\n - velocity_1d ≥ 3%에서 진입한 케이스의 T+5 승률 계산\n - 현재\ + \ 3%보다 낮은 임계값이 더 효과적이면 새 값 제안\n2. 새 값 제안 후:\n - calibration_registry.yaml의\ + \ source를 PROVISIONAL로 변경\n - sample_n에 실제 표본 수 기재\n - last_calibrated:\ + \ 오늘 날짜\n3. 변경 후 반드시 npm run validate-engine-integrity 재실행\n" + - id: L4_RUN_FULL_GATE + name: 변경 후 전체 검증 + command: npm run full-gate + expect: + exit_code: 0 calibration_escalation_criteria: PROVISIONAL: - condition: "sample_n >= 10 AND 방향성 확인" + condition: sample_n >= 10 AND 방향성 확인 CALIBRATED: - condition: "sample_n >= 30 AND 실제 P&L backtest 완료 AND 이전 임계값 대비 명확한 개선" - required_doc: "backtest 결과 노트 (날짜, 표본 수, 이전값, 신규값, 성과 비교)" - -# ════════════════════════════════════════════════════════════════════════════ -# 거부 조건 (Reject Conditions) — 어떤 상황에서도 적용 -# ════════════════════════════════════════════════════════════════════════════ + condition: sample_n >= 30 AND 실제 P&L backtest 완료 AND 이전 임계값 대비 명확한 개선 + required_doc: backtest 결과 노트 (날짜, 표본 수, 이전값, 신규값, 성과 비교) reject_conditions: - - "behavioral_coverage_pct < 100% 인데 '커버리지 100% 달성' 선언" - - "golden expected 값을 .gs 출력에서 역복사 (순환논리)" - - "임계값을 실측 없이 source=CALIBRATED로 기재 (overclaimed)" - - "LLM이 가격/수량을 spec 등록 공식 없이 즉석 계산" - - "rebound_efficiency_score 등 설계점수를 '검증된 성과'로 서술 (UNVALIDATED 라벨 없이)" - - "T+1/T+5 목표 미달 상태에서 '예측 정확도 100%' 선언" - - "divergence_count > 0 상태에서 '구현 일치' 선언" - - "sample_n < 30인 임계값을 '보정완료'로 처리" - -# ════════════════════════════════════════════════════════════════════════════ -# 현재 달성 현황 (2026-06-21 재검증 — WBS-7.2) -# ════════════════════════════════════════════════════════════════════════════ -# 주의: 아래 current_status_2026_05_30 블록은 그 날짜 기준 정적 스냅샷이며, -# 이후 갱신되지 않은 채 docs/ROADMAP_WBS.md 등에서 "현재 상태"로 인용되어 -# 서로 다른 시점의 T+5 수치(54.76%/35.86%)가 혼재하는 문제를 일으켰다. -# Temp/honest_performance_guard_v1.json(생성: 2026-06-14)과 -# Temp/prediction_accuracy_harness_v2.json(생성: 2026-06-21, 7일 더 최신)을 -# 직접 재확인한 결과는 다음과 같다 — 이 블록을 단일 진실원천으로 삼는다. +- behavioral_coverage_pct < 100% 인데 '커버리지 100% 달성' 선언 +- golden expected 값을 .gs 출력에서 역복사 (순환논리) +- 임계값을 실측 없이 source=CALIBRATED로 기재 (overclaimed) +- LLM이 가격/수량을 spec 등록 공식 없이 즉석 계산 +- rebound_efficiency_score 등 설계점수를 '검증된 성과'로 서술 (UNVALIDATED 라벨 없이) +- T+1/T+5 목표 미달 상태에서 '예측 정확도 100%' 선언 +- divergence_count > 0 상태에서 '구현 일치' 선언 +- sample_n < 30인 임계값을 '보정완료'로 처리 current_status_2026_06_21: - source_of_truth: "Temp/prediction_accuracy_harness_v2.json (as_of_date=2026-06-21, 가장 최신)" - t1_match_rate_pct: 52.94 # sample=68, decisive_sample=53, rate_decisive=67.92 - t5_match_rate_pct: null # sample=0 — INSUFFICIENT_SAMPLES. honest_performance_guard_v1.json(2026-06-14)의 - # 35.86%는 7일 전 스냅샷이며 표본이 0으로 줄어 더 이상 유효하지 않음. - t5_sample_regression_note: > - cases_analyzed가 141건(2026-05-30 기준)에서 t5_sample=0(2026-06-21)으로 감소했다. - evaluation_methodology가 ACTIVE_PASSIVE_SPLIT_V1_INCONCLUSIVE_EXCLUDED로 변경되며 + source_of_truth: Temp/prediction_accuracy_harness_v2.json (as_of_date=2026-06-21, + 가장 최신) + t1_match_rate_pct: 52.94 + t5_match_rate_pct: null + t5_sample_regression_note: 'cases_analyzed가 141건(2026-05-30 기준)에서 t5_sample=0(2026-06-21)으로 + 감소했다. evaluation_methodology가 ACTIVE_PASSIVE_SPLIT_V1_INCONCLUSIVE_EXCLUDED로 변경되며 inconclusive/replay 표본이 제외된 것으로 추정 — 근본 원인은 별도 조사 필요(WBS-7.2 잔여 항목). - calibration_registry_total_thresholds: 190 # spec/calibration_registry.yaml 직접 집계 (구문서의 70은 stale) + + ' + calibration_registry_total_thresholds: 190 calibration_registry_expert_prior_count: 59 calibration_registry_calibrated_count: 0 - rule: "이 문서를 인용할 때는 항상 as_of_date를 동반 표기하고, 아래 5/30 스냅샷을 '현재'로 인용하지 않는다." - -# ════════════════════════════════════════════════════════════════════════════ -# 과거 달성 현황 (2026-05-30, 역사적 스냅샷 — "현재"로 인용 금지) -# ════════════════════════════════════════════════════════════════════════════ + rule: 이 문서를 인용할 때는 항상 as_of_date를 동반 표기하고, 아래 5/30 스냅샷을 '현재'로 인용하지 않는다. current_status_2026_05_30: phase_1_bch: COMPLETE behavioral_coverage_pct: 100.0 gas_parity_cases: 63 implementation_divergence_count: 0 bugs_fixed: - - "normalize_tick: round() → math.floor() (Python-GAS divergence 제거)" - - "PROFIT_LOCK_STAGE 단계명 7개 spec 일치 정정 (GAS calcPrices_)" - - "validate_harness_context.py VALID_PROFIT_LOCK_STAGES 신규 명칭 추가" - - "RetirementAssetPortfolio.yaml spec_files 신규 3파일 등록" - + - 'normalize_tick: round() → math.floor() (Python-GAS divergence 제거)' + - PROFIT_LOCK_STAGE 단계명 7개 spec 일치 정정 (GAS calcPrices_) + - validate_harness_context.py VALID_PROFIT_LOCK_STAGES 신규 명칭 추가 + - RetirementAssetPortfolio.yaml spec_files 신규 3파일 등록 phase_2_calib: COMPLETE total_thresholds: 70 overclaimed_count: 0 unregistered_count: 0 - expert_prior_count: 61 # 정직하게 공시됨 - + expert_prior_count: 61 phase_3_lfm: COMPLETE llm_freedom_pct: 0.0 softening_violations: 0 prompt_freedom_risks_removed: 4 - phase_4_honest: COMPLETE design_score_labeled_unvalidated: true t1_match_rate_pct: 47.28 t5_match_rate_pct: 35.86 target_t5: 55.0 - phase_5_integration: COMPLETE full_gate_exit: 0 daily_feedback_exit: 0 - phase_6_calibration_loop: IN_PROGRESS cases_analyzed: 141 miss5_count: 51 - next_milestone: "cases_analyzed=30 달성 후 ALEG_V2_GATE1_BLOCK_PCT 보정 심사" + next_milestone: cases_analyzed=30 달성 후 ALEG_V2_GATE1_BLOCK_PCT 보정 심사 automation_entrypoints: - gitea_schedule: ".gitea/workflows/calibration_backlog.yml" - npm_script: "npm run ops:calibration-backlog" + gitea_schedule: .gitea/workflows/calibration_backlog.yml + npm_script: npm run ops:calibration-backlog generated_artifacts: - - Temp/calibration_priority_v1.json - - Temp/calibration_change_ledger_v4.json - - Temp/calibration_review_report_v1.json - - Temp/calibration_review_report_v1.md - - Temp/calibration_approval_list_v1.json - - Temp/calibration_approval_list_v1.md - - Temp/calibration_registry_v1.json + - Temp/calibration_priority_v1.json + - Temp/calibration_change_ledger_v4.json + - Temp/calibration_review_report_v1.json + - Temp/calibration_review_report_v1.md + - Temp/calibration_approval_list_v1.json + - Temp/calibration_approval_list_v1.md + - Temp/calibration_registry_v1.json promotion_rules: - provisional: "sample_n >= 10 AND direction confirmed AND change_ledger entry exists" - calibrated: "sample_n >= 30 AND backtest_doc exists AND validator overclaimed_count == 0" + provisional: sample_n >= 10 AND direction confirmed AND change_ledger entry + exists + calibrated: sample_n >= 30 AND backtest_doc exists AND validator overclaimed_count + == 0 diff --git a/spec/29_backtest_harness_contract.yaml b/spec/29_backtest_harness_contract.yaml index 574709b..a4aa043 100644 --- a/spec/29_backtest_harness_contract.yaml +++ b/spec/29_backtest_harness_contract.yaml @@ -1,105 +1,94 @@ -# spec/29 — 백테스트 · Walk-forward 하네스 계약 (BACKTEST_HARNESS_V1) -# -# 목적: 전략이 과거 데이터에만 맞춰진 과최적화인지, 실제 운용 중 의미있는 예측력이 있는지 -# 수치로 검증한다. 미충족 항목은 추정·날조하지 않고 insufficient_data로 표기한다. -# -# 계층: 감사·진단 계약(spec/28과 동급). GAS 런타임·주문 생성에 개입 없음. -# 구현: Python 계층(tools/*.py). 실측 누적 데이터가 없는 구간은 채울 수 없음을 명시. - meta: formula_id: BACKTEST_HARNESS_V1 - version: "2026-05-31" - python_tool: "tools/build_yaml_code_coverage_v1.py (커버리지), tools/build_engine_audit_v1.py (집계)" + version: '2026-05-31' + python_tool: tools/build_yaml_code_coverage_v1.py (커버리지), tools/build_engine_audit_v1.py + (집계) sources: - - Temp/prediction_accuracy_harness_v2.json # T+1/T+5/T+20 정확도 - - Temp/outcome_quality_score_v1.json # 운용 성과 질 점수 - - Temp/operational_alpha_calibration_v2.json # 알파 보정 - - Temp/proposal_evaluation_history.json # 제안-결과 이력 - -# ── 현재 실측 가능 지표 (2026-05-31 기준) ──────────────────────────────── + - Temp/prediction_accuracy_harness_v2.json + - Temp/outcome_quality_score_v1.json + - Temp/operational_alpha_calibration_v2.json + - Temp/proposal_evaluation_history.json + has_code_implementation: true + code_path: + - spec\29_backtest_harness_contract.yaml current_metrics: direction_accuracy: t1_op_rate: value: 50.37 n_sample: 546 unit: percent - interpretation: "동전던지기(50%) 수준 — 단기 방향 예측력 불충분" + interpretation: 동전던지기(50%) 수준 — 단기 방향 예측력 불충분 t5_op_rate: value: 73.24 n_sample: 161 unit: percent - method: "decisive 케이스만(passive/ambiguous 제외). PREDICTION_ACCURACY_HARNESS_V2" - interpretation: "T+5 능동 결정 케이스 73%. 전체 포함 레거시=31.94% — 표본 정의 혼용 금지" + method: decisive 케이스만(passive/ambiguous 제외). PREDICTION_ACCURACY_HARNESS_V2 + interpretation: T+5 능동 결정 케이스 73%. 전체 포함 레거시=31.94% — 표본 정의 혼용 금지 t5_legacy_rate: value: 31.94 - n_sample: "not_available" + n_sample: not_available unit: percent - interpretation: "전체 평가 윈도우 비율(거시이벤트 미제외). t5_op_rate와 다른 지표." + interpretation: 전체 평가 윈도우 비율(거시이벤트 미제외). t5_op_rate와 다른 지표. t20_op_rate: value: insufficient_data n_sample: 0 unit: percent - interpretation: "T+20 실현 표본 0건 — 장기 예측력 검증 불가. t5_operational_proxy=73.24 사용 중(추정)" + interpretation: T+20 실현 표본 0건 — 장기 예측력 검증 불가. t5_operational_proxy=73.24 사용 + 중(추정) window_90d_rate: value: 31.94 - n_sample: "not_available" + n_sample: not_available unit: percent - interpretation: "최근 90일 창 일치율. 낮음." - + interpretation: 최근 90일 창 일치율. 낮음. outcome_quality: score: 84.43 gate: CAUTION_MODE t20_effective_rate: 73.24 - t20_source: t5_operational_proxy # 실측 아님 — estimated=true + t20_source: t5_operational_proxy t5_decisive_count: 161 - basis_note: "t20는 실측이 아니라 t5 proxy. 실측 T+20 누적 전까지 estimated." - + basis_note: t20는 실측이 아니라 t5 proxy. 실측 T+20 누적 전까지 estimated. walk_forward: status: insufficient_data - reason: > - Walk-forward 검증을 위해 필요한 in-sample/out-of-sample 분리, - 기간별 성과 비교, slippage/cost 반영 데이터가 없음. - backfill_eod_replay_history.py를 통해 이력 재현 시 채울 수 있음. + reason: 'Walk-forward 검증을 위해 필요한 in-sample/out-of-sample 분리, 기간별 성과 비교, slippage/cost + 반영 데이터가 없음. backfill_eod_replay_history.py를 통해 이력 재현 시 채울 수 있음. -# ── 정의되어야 하나 현재 측정 불가한 지표 ───────────────────────────────── + ' missing_metrics: CAGR: status: insufficient_data - required_data: "1년 이상 완전 실현 손익 이력" + required_data: 1년 이상 완전 실현 손익 이력 sharpe_ratio: status: insufficient_data - required_data: "일별 수익률 시계열 + 무위험수익률" + required_data: 일별 수익률 시계열 + 무위험수익률 sortino_ratio: status: insufficient_data - required_data: "일별 하락 편차 시계열" + required_data: 일별 하락 편차 시계열 max_drawdown: status: insufficient_data - required_data: "계좌 고점 추적 이력. portfolio_peak_krw 필드 존재하나 historical 없음" + required_data: 계좌 고점 추적 이력. portfolio_peak_krw 필드 존재하나 historical 없음 calmar_ratio: status: insufficient_data - required_data: "CAGR / MDD" + required_data: CAGR / MDD win_rate: status: insufficient_data - required_data: "청산 완료 거래 이력. backdata에 MAE/MFE/pnl 모두 공란" + required_data: 청산 완료 거래 이력. backdata에 MAE/MFE/pnl 모두 공란 profit_factor: status: insufficient_data - required_data: "총 이익 / 총 손실 (실현 기준)" + required_data: 총 이익 / 총 손실 (실현 기준) average_win_loss_ratio: status: insufficient_data - required_data: "실현 수익/손실 건별 데이터" + required_data: 실현 수익/손실 건별 데이터 slippage_impact: status: insufficient_data - required_data: "체결 가격 vs 지정가 괴리 이력" + required_data: 체결 가격 vs 지정가 괴리 이력 transaction_cost_impact: status: insufficient_data - required_data: "수수료·세금 반영 순수익 이력" + required_data: 수수료·세금 반영 순수익 이력 hit_rate_by_horizon: scalp: insufficient_data short_term: insufficient_data mid_term: insufficient_data long_term: insufficient_data - -# ── 측정 가능한 회귀 지표 (현재 구현됨) ────────────────────────────────── measurable_now: yaml_to_code_coverage_ratio: value: 1.0 @@ -107,43 +96,37 @@ measurable_now: golden_test_coverage_ratio: value: 0.2337 source: Temp/yaml_code_coverage_v1.json - note: "43/184 공식 — golden 테스트 확대 필요" + note: 43/184 공식 — golden 테스트 확대 필요 decision_reproducibility_score: value: 1.0 - method: "build_engine_audit_v1.py 10회 실행 byte-identical" + method: build_engine_audit_v1.py 10회 실행 byte-identical llm_dependency_ratio: value: 0.0 source: Temp/llm_freedom_v1.json schema_validity_score: value: 95.5 source: Temp/data_quality_reconciliation_v1.json - -# ── 목표치 (충족 시 PASS 판정) ────────────────────────────────────────── targets: - t1_op_rate_min: 55 # 현재 50.37 — 미달 - t5_op_rate_min: 60 # 현재 73.24 — 충족(주의: decisive 케이스 기준) - t20_op_rate_min: 55 # 현재 insufficient_data - win_rate_min: 50 # 현재 insufficient_data - max_drawdown_max_pct: 20 # 현재 측정 불가 - yaml_to_code_coverage: 1.0 # 충족 - golden_coverage_min: 0.5 # 현재 0.23 — 미달 - -# ── 과최적화 경계 지표 ──────────────────────────────────────────────────── + t1_op_rate_min: 55 + t5_op_rate_min: 60 + t20_op_rate_min: 55 + win_rate_min: 50 + max_drawdown_max_pct: 20 + yaml_to_code_coverage: 1.0 + golden_coverage_min: 0.5 overfit_risk: in_sample_vs_oos_gap: status: insufficient_data - note: "in-sample / out-of-sample 분리 없음" + note: in-sample / out-of-sample 분리 없음 regime_dependency: - note: > - 현재 포트폴리오는 RISK_ON 국면에 집중(SHORT 71.4% vs 25% 한도 위반). - 단일 국면 의존도 과다 — regime 다양화 필요. - sample_size_warning: - t1: "n=546 — 통계적으로 유의하나 변동 큼" - t5: "n=161 — 최소 수준. 더 많은 누적 필요" - t20: "n=0 — 미충족" + note: '현재 포트폴리오는 RISK_ON 국면에 집중(SHORT 71.4% vs 25% 한도 위반). 단일 국면 의존도 과다 — regime + 다양화 필요. -# ── 실측 표본 백필 의무화 (OPERATIONAL_SAMPLE_BACKFILL_V1) ───────────────── -# [SCAFFOLDED_PENDING_LIVE_DATA: operational_t5_sample_count=0, target>=30] + ' + sample_size_warning: + t1: n=546 — 통계적으로 유의하나 변동 큼 + t5: n=161 — 최소 수준. 더 많은 누적 필요 + t20: n=0 — 미충족 operational_sample_backfill: formula_id: OPERATIONAL_SAMPLE_BACKFILL_V1 status: SCAFFOLDED_PENDING_LIVE_DATA @@ -152,42 +135,54 @@ operational_sample_backfill: current_replay_sample_count: 510 target_operational_t5_sample: 30 target_operational_t20_sample: 30 - rationale: > - live=0, paper=0, op_t20=0. REPLAY 510건은 예측력 증거가 못 된다(미래정보 누수 위험). - 실제 제안→실측 결과 연결 고리가 끊겨 있다. - implementation_steps: - - step: 1 - desc: "proposal_evaluation_history.json의 각 과거 제안(BUY/SELL/TRIM)에 entry_date, entry_price를 고정 기록" - status: NOT_STARTED - - step: 2 - desc: "T+5/T+20 경과 시 data_feed의 종가로 realized_return_pct 채움 (미래 데이터 사용 금지: 평가일 ≤ 오늘)" - status: NOT_STARTED - - step: 3 - desc: "origin 태그를 LIVE/PAPER/REPLAY로 명확히 분리. 예측력 지표는 LIVE+PAPER만 집계" - status: NOT_STARTED - - step: 4 - desc: "operational_t5_sample_count, operational_t20_sample_count 매 사이클 갱신" - status: NOT_STARTED - - step: 5 - desc: "표본 < 30인 동안 모든 예측력 지표에 '[UNVALIDATED_LIVE: n={n}]' 라벨 부착, PASS 금지(WATCH)" - status: ACTIVE_GUARD - outputs: - - live_trade_outcome_ledger_v1.json # LIVE/PAPER 채움 - - prediction_accuracy_harness_v5.json.operational_t5_sample - numeric_acceptance: - operational_t5_sample_count: {op: ">=", target: 30, current: 0, blocking: true} - replay_contamination: {op: "==", target: 0, current: 0, note: "REPLAY 표본 예측지표 집계 혼입 금지"} - future_leak: {op: "==", target: 0, note: "모든 realized_return 평가일 <= capture_date"} - python_tools: - - tools/backfill_eod_replay_history.py - - tools/build_live_trade_outcome_ledger_v1.py - gs_coverage: "gas_apex_runtime_core.gs:evaluateOperationalOutcomeBatch_()" - validator: "tools/validate_outcome_eval_window.py --no-future-leak --min-live 30" - unvalidated_label: "[UNVALIDATED_LIVE: n=0 < 30]" + rationale: 'live=0, paper=0, op_t20=0. REPLAY 510건은 예측력 증거가 못 된다(미래정보 누수 위험). 실제 + 제안→실측 결과 연결 고리가 끊겨 있다. -# ── 금지 사항 ───────────────────────────────────────────────────────────── + ' + implementation_steps: + - step: 1 + desc: proposal_evaluation_history.json의 각 과거 제안(BUY/SELL/TRIM)에 entry_date, entry_price를 + 고정 기록 + status: NOT_STARTED + - step: 2 + desc: 'T+5/T+20 경과 시 data_feed의 종가로 realized_return_pct 채움 (미래 데이터 사용 금지: 평가일 + ≤ 오늘)' + status: NOT_STARTED + - step: 3 + desc: origin 태그를 LIVE/PAPER/REPLAY로 명확히 분리. 예측력 지표는 LIVE+PAPER만 집계 + status: NOT_STARTED + - step: 4 + desc: operational_t5_sample_count, operational_t20_sample_count 매 사이클 갱신 + status: NOT_STARTED + - step: 5 + desc: '표본 < 30인 동안 모든 예측력 지표에 ''[UNVALIDATED_LIVE: n={n}]'' 라벨 부착, PASS 금지(WATCH)' + status: ACTIVE_GUARD + outputs: + - live_trade_outcome_ledger_v1.json + - prediction_accuracy_harness_v5.json.operational_t5_sample + numeric_acceptance: + operational_t5_sample_count: + op: '>=' + target: 30 + current: 0 + blocking: true + replay_contamination: + op: == + target: 0 + current: 0 + note: REPLAY 표본 예측지표 집계 혼입 금지 + future_leak: + op: == + target: 0 + note: 모든 realized_return 평가일 <= capture_date + python_tools: + - tools/backfill_eod_replay_history.py + - tools/build_live_trade_outcome_ledger_v1.py + gs_coverage: gas_apex_runtime_core.gs:evaluateOperationalOutcomeBatch_() + validator: tools/validate_outcome_eval_window.py --no-future-leak --min-live 30 + unvalidated_label: '[UNVALIDATED_LIVE: n=0 < 30]' prohibitions: - - "insufficient_data 지표를 추정값으로 대체해 투자 판단에 사용 금지(AGENTS.md §0.3)" - - "t5_op_rate(73%)와 window_90d_rate(31%)를 동일 지표로 혼용 금지" - - "t20_op_rate=t5_operational_proxy를 실측 T+20으로 표기 금지 (estimated=true 필수)" - - "CAGR/Sharpe/MDD가 없는 상태에서 '검증된 전략' 단정 금지" +- insufficient_data 지표를 추정값으로 대체해 투자 판단에 사용 금지(AGENTS.md §0.3) +- t5_op_rate(73%)와 window_90d_rate(31%)를 동일 지표로 혼용 금지 +- t20_op_rate=t5_operational_proxy를 실측 T+20으로 표기 금지 (estimated=true 필수) +- CAGR/Sharpe/MDD가 없는 상태에서 '검증된 전략' 단정 금지 diff --git a/spec/31_low_capability_llm_response_contract.yaml b/spec/31_low_capability_llm_response_contract.yaml index 8092ef7..332f4ca 100644 --- a/spec/31_low_capability_llm_response_contract.yaml +++ b/spec/31_low_capability_llm_response_contract.yaml @@ -1,27 +1,27 @@ +meta: + has_code_implementation: true + code_path: + - spec\31_low_capability_llm_response_contract.yaml schema_version: low_capability_llm_response_contract.v1 formula_id: LLM_NARRATIVE_TEMPLATE_LOCK_V1 -purpose: > - 저성능 LLM도 동일한 JSON 입력에서 동일한 서술 결과를 내도록 - 응답 섹션과 금지 섹션을 고정한다. +purpose: '저성능 LLM도 동일한 JSON 입력에서 동일한 서술 결과를 내도록 응답 섹션과 금지 섹션을 고정한다. + ' required_sections: - - source_summary - - fail_codes - - allowed_actions - - blocked_actions - - todo_yaml - - no_order_notice - +- source_summary +- fail_codes +- allowed_actions +- blocked_actions +- todo_yaml +- no_order_notice forbidden_sections_when_blocked: - - hts_order_table - - new_buy_recommendation - - freeform_target_price - +- hts_order_table +- new_buy_recommendation +- freeform_target_price copy_exact_rules: - - "All numeric values must be copied from JSON with json_path." - - "No unregistered formula names may be invented." - - "If HTS_READY is false, render shadow ledger only." - +- All numeric values must be copied from JSON with json_path. +- No unregistered formula names may be invented. +- If HTS_READY is false, render shadow ledger only. output_constraints: language: ko-KR allow_freeform_numbers: false diff --git a/spec/33_execution_precedence_lock.yaml b/spec/33_execution_precedence_lock.yaml index 15b9483..ff52d91 100644 --- a/spec/33_execution_precedence_lock.yaml +++ b/spec/33_execution_precedence_lock.yaml @@ -1,6 +1,10 @@ +meta: + has_code_implementation: true + code_path: + - spec\33_execution_precedence_lock.yaml schema_version: 2026-06-03-execution-precedence-lock-v1 formula_id: FINAL_EXECUTION_PRECEDENCE_LOCK_V1 purpose: 최종 HTS 권한과 child internal allowed 분리. rules: - - global_execution_gate != HTS_READY 이면 child execution_allowed는 THEORETICAL_ONLY - - HTS_READY일 때만 order_blueprint_json.validation_status=PASS 를 주문표로 렌더링 +- global_execution_gate != HTS_READY 이면 child execution_allowed는 THEORETICAL_ONLY +- HTS_READY일 때만 order_blueprint_json.validation_status=PASS 를 주문표로 렌더링 diff --git a/spec/34_architecture_boundaries.yaml b/spec/34_architecture_boundaries.yaml index 578e7f0..2837254 100644 --- a/spec/34_architecture_boundaries.yaml +++ b/spec/34_architecture_boundaries.yaml @@ -1,6 +1,10 @@ +meta: + has_code_implementation: true + code_path: + - spec\34_architecture_boundaries.yaml schema_version: 2026-06-03-architecture-boundaries-v1 formula_id: ARCHITECTURE_BOUNDARIES_V1 purpose: data -> feature -> decision -> execution -> report 단방향 원칙. contracts: - - renderer_calculation_count: 0 - - reverse_dependency_count: 0 +- renderer_calculation_count: 0 +- reverse_dependency_count: 0 diff --git a/spec/35_rule_lifecycle_governance_v3.yaml b/spec/35_rule_lifecycle_governance_v3.yaml index a079073..90ec869 100644 --- a/spec/35_rule_lifecycle_governance_v3.yaml +++ b/spec/35_rule_lifecycle_governance_v3.yaml @@ -1,8 +1,12 @@ +meta: + has_code_implementation: true + code_path: + - spec\35_rule_lifecycle_governance_v3.yaml schema_version: 2026-06-03-rule-lifecycle-governance-v3 formula_id: RULE_LIFECYCLE_POLICY_V3 purpose: rule registry governance for hardening todo completion. required_fields: - - rule_key - - owner - - retirement_condition - - expected_metric +- rule_key +- owner +- retirement_condition +- expected_metric diff --git a/spec/40_final_decision_packet_contract.yaml b/spec/40_final_decision_packet_contract.yaml index 09f19b0..68883e5 100644 --- a/spec/40_final_decision_packet_contract.yaml +++ b/spec/40_final_decision_packet_contract.yaml @@ -1,14 +1,18 @@ +meta: + has_code_implementation: true + code_path: + - spec\40_final_decision_packet_contract.yaml schema_version: final_decision_packet_contract.v4 formula_id: FINAL_DECISION_PACKET_V4 purpose: Single packet source of truth for renderer and low-capability LLM output. sections: - - executive - - portfolio - - ticker - - risk - - execution - - performance - - data_quality +- executive +- portfolio +- ticker +- risk +- execution +- performance +- data_quality provenance_requirements: source_path: required json_pointer: required diff --git a/spec/43_quant_factor_taxonomy.yaml b/spec/43_quant_factor_taxonomy.yaml index b8e592e..735d0ff 100644 --- a/spec/43_quant_factor_taxonomy.yaml +++ b/spec/43_quant_factor_taxonomy.yaml @@ -1,28 +1,32 @@ +meta: + has_code_implementation: true + code_path: + - spec\43_quant_factor_taxonomy.yaml schema_version: quant_factor_taxonomy.v1 purpose: Classify factors by horizon, decay, and conflict policy. factor_horizons: - - scalping - - short - - mid - - long +- scalping +- short +- mid +- long required_lifecycle_fields: - - factor_id - - hypothesis - - market_regime_applicability - - horizon - - decay_half_life - - input_fields - - formula_id - - data_quality_requirements - - expected_edge_formula - - conflict_precedence - - position_sizing_impact - - exit_impact - - golden_cases - - shadow_start_date - - activation_threshold - - retirement_condition - - owner +- factor_id +- hypothesis +- market_regime_applicability +- horizon +- decay_half_life +- input_fields +- formula_id +- data_quality_requirements +- expected_edge_formula +- conflict_precedence +- position_sizing_impact +- exit_impact +- golden_cases +- shadow_start_date +- activation_threshold +- retirement_condition +- owner factor_retirement_policy: no_edge_improvement_lookback_days: 90 shadow_only_before_activation: true diff --git a/spec/44_live_replay_separation.yaml b/spec/44_live_replay_separation.yaml index f113f71..0bd37a3 100644 --- a/spec/44_live_replay_separation.yaml +++ b/spec/44_live_replay_separation.yaml @@ -1,8 +1,12 @@ +meta: + has_code_implementation: true + code_path: + - spec\44_live_replay_separation.yaml schema_version: live_replay_separation.v2 purpose: Separate live, paper, backtest, and replay evidence. source_types: - - live - - paper - - backtest - - replay +- live +- paper +- backtest +- replay promotion_rule: live_t20_count_gte_30 diff --git a/spec/45_number_provenance_contract.yaml b/spec/45_number_provenance_contract.yaml index 57e9408..0399857 100644 --- a/spec/45_number_provenance_contract.yaml +++ b/spec/45_number_provenance_contract.yaml @@ -1,8 +1,12 @@ +meta: + has_code_implementation: true + code_path: + - spec\45_number_provenance_contract.yaml schema_version: number_provenance_contract.v1 purpose: Attach provenance to every report number. required_fields: - - source_path - - json_pointer - - formula_id - - input_hash - - freshness_status +- source_path +- json_pointer +- formula_id +- input_hash +- freshness_status diff --git a/spec/46_low_capability_execution_pack.yaml b/spec/46_low_capability_execution_pack.yaml index 6f8612f..c49da09 100644 --- a/spec/46_low_capability_execution_pack.yaml +++ b/spec/46_low_capability_execution_pack.yaml @@ -1,9 +1,13 @@ +meta: + has_code_implementation: true + code_path: + - spec\46_low_capability_execution_pack.yaml schema_version: low_capability_execution_pack.v1 purpose: Fixed-order packet-only context for low capability LLMs. required_sections: - - executive - - blockers - - action_table - - shadow_ledger - - data_missing - - education_notes +- executive +- blockers +- action_table +- shadow_ledger +- data_missing +- education_notes diff --git a/spec/47_packaging_policy.yaml b/spec/47_packaging_policy.yaml index 19aa9c9..6e71e4e 100644 --- a/spec/47_packaging_policy.yaml +++ b/spec/47_packaging_policy.yaml @@ -1,7 +1,11 @@ +meta: + has_code_implementation: true + code_path: + - spec\47_packaging_policy.yaml schema_version: packaging_policy.v1 purpose: Define upload bundle inclusion and exclusion policy. required_rules: - - source_required - - runtime_required - - report_required - - test_required +- source_required +- runtime_required +- report_required +- test_required diff --git a/spec/48_module_io_contract_registry.yaml b/spec/48_module_io_contract_registry.yaml index 4d4d547..c3ab88b 100644 --- a/spec/48_module_io_contract_registry.yaml +++ b/spec/48_module_io_contract_registry.yaml @@ -1,33 +1,44 @@ +meta: + has_code_implementation: true + code_path: + - spec\48_module_io_contract_registry.yaml schema_version: module_io_contract_registry.v1 modules: core_engine: id: core_engine owner: architect - inputs: ["GatherTradingData.json"] - outputs: ["Temp/final_decision_packet_active.json"] - schema: "schemas/final_decision_packet_v3.schema.json" - artifact_path: "src/quant_engine/compute_formula_outputs.py" - + inputs: + - GatherTradingData.json + outputs: + - Temp/final_decision_packet_active.json + schema: schemas/final_decision_packet_v3.schema.json + artifact_path: src/quant_engine/compute_formula_outputs.py risk_manager: id: risk_manager owner: risk_officer - inputs: ["GatherTradingData.json"] - outputs: ["Temp/strategy_decision_result_v3.json"] - schema: "schemas/strategy_decision_result.schema.json" - artifact_path: "src/quant_engine/exit_decisions.py" - + inputs: + - GatherTradingData.json + outputs: + - Temp/strategy_decision_result_v3.json + schema: schemas/strategy_decision_result.schema.json + artifact_path: src/quant_engine/exit_decisions.py reporting_renderer: id: reporting_renderer owner: pm - inputs: ["Temp/final_decision_packet_active.json"] - outputs: ["Temp/operational_report.json", "Temp/operational_report.md"] - schema: "schemas/operational_report.schema.json" - artifact_path: "tools/render_operational_report.py" - + inputs: + - Temp/final_decision_packet_active.json + outputs: + - Temp/operational_report.json + - Temp/operational_report.md + schema: schemas/operational_report.schema.json + artifact_path: tools/render_operational_report.py context_builder: id: context_builder owner: pm - inputs: ["Temp/final_decision_packet_v4.json", "runtime/active_artifact_manifest.yaml"] - outputs: ["Temp/final_context_for_llm_v5.yaml"] - schema: "spec/46_low_capability_execution_pack.yaml" - artifact_path: "tools/build_low_capability_context_pack_v5.py" + inputs: + - Temp/final_decision_packet_v4.json + - runtime/active_artifact_manifest.yaml + outputs: + - Temp/final_context_for_llm_v5.yaml + schema: spec/46_low_capability_execution_pack.yaml + artifact_path: tools/build_low_capability_context_pack_v5.py diff --git a/spec/49_refactor_methodology_contract.yaml b/spec/49_refactor_methodology_contract.yaml index ba951ed..a0433fc 100644 --- a/spec/49_refactor_methodology_contract.yaml +++ b/spec/49_refactor_methodology_contract.yaml @@ -1,19 +1,30 @@ +meta: + has_code_implementation: true + code_path: + - spec\49_refactor_methodology_contract.yaml schema_version: refactor_methodology_contract.v1 principles: - - QEDD: Quant Evidence-Driven Deterministic Development - - Contract-First: YAML/Schema before implementation - - Python Canonical: Logic in src/quant_engine, GAS is thin adapter - - No LLM Math: LLM copies harness values with provenance +- QEDD: Quant Evidence-Driven Deterministic Development +- Contract-First: YAML/Schema before implementation +- Python Canonical: Logic in src/quant_engine, GAS is thin adapter +- No LLM Math: LLM copies harness values with provenance authority_order: - - spec/*.yaml - - runtime/active_artifact_manifest.yaml - - Temp/final_decision_packet_active.json - - governance/rules/*.yaml +- spec/*.yaml +- runtime/active_artifact_manifest.yaml +- Temp/final_decision_packet_active.json +- governance/rules/*.yaml file_policy: - source: [md, yaml, py, gs] - runtime: [json, jsonl, schema.json] + source: + - md + - yaml + - py + - gs + runtime: + - json + - jsonl + - schema.json do_done: - - Release DAG PASS - - No SKIPPED in release mode - - Zero architecture boundary violations - - 100% number provenance coverage +- Release DAG PASS +- No SKIPPED in release mode +- Zero architecture boundary violations +- 100% number provenance coverage diff --git a/spec/51_formula_lifecycle_registry.yaml b/spec/51_formula_lifecycle_registry.yaml index 3dd36d1..4424e73 100644 --- a/spec/51_formula_lifecycle_registry.yaml +++ b/spec/51_formula_lifecycle_registry.yaml @@ -1,3 +1,7 @@ +meta: + has_code_implementation: true + code_path: + - spec\51_formula_lifecycle_registry.yaml schema_version: formula_lifecycle_registry.v1 updated_at: '2026-06-13' purpose: '모든 ACTIVE 공식의 lifecycle 상태를 단일 레지스트리로 관리한다. spec/13_formula_registry.yaml(149개) diff --git a/spec/anti_late_entry_contract.yaml b/spec/anti_late_entry_contract.yaml index a889c01..968ce77 100644 --- a/spec/anti_late_entry_contract.yaml +++ b/spec/anti_late_entry_contract.yaml @@ -1,21 +1,26 @@ +meta: + has_code_implementation: true + code_path: + - spec\anti_late_entry_contract.yaml schema_version: anti_late_entry_contract.v2 -goal: Define rules to block late chasing of leading stocks and prevent buying in distribution phases. +goal: Define rules to block late chasing of leading stocks and prevent buying in distribution + phases. metrics: - - id: breakout_quality - description: "20D high status and volume acceleration at breakout" - - id: flow_acceleration - description: "Foreign/Institutional net buying acceleration indicator" - - id: distribution_risk - description: "Risk score reflecting high-volume churn without price progression" - - id: entry_timing_decile - description: "Decile rank of entry timing relative to recent price progression" +- id: breakout_quality + description: 20D high status and volume acceleration at breakout +- id: flow_acceleration + description: Foreign/Institutional net buying acceleration indicator +- id: distribution_risk + description: Risk score reflecting high-volume churn without price progression +- id: entry_timing_decile + description: Decile rank of entry timing relative to recent price progression rules: - - id: RULE_OVERHEATED_BLOCK_BUY - condition: "entry_timing_decile >= 8 (Overheated zone)" - action: "BLOCK new buys until a pullback trigger is confirmed" - - id: RULE_DISTRIBUTION_DOWNGRADE - condition: "distribution_risk is HIGH" - action: "Downgrade BUY to HOLD/WAIT" - - id: RULE_LATE_CHASE_ATTRIBUTION - condition: "T+5/T+20 operational outcomes are updated to attribute entry quality" - action: "Update attribution metrics" +- id: RULE_OVERHEATED_BLOCK_BUY + condition: entry_timing_decile >= 8 (Overheated zone) + action: BLOCK new buys until a pullback trigger is confirmed +- id: RULE_DISTRIBUTION_DOWNGRADE + condition: distribution_risk is HIGH + action: Downgrade BUY to HOLD/WAIT +- id: RULE_LATE_CHASE_ATTRIBUTION + condition: T+5/T+20 operational outcomes are updated to attribute entry quality + action: Update attribution metrics diff --git a/spec/data_quality/expectations.yaml b/spec/data_quality/expectations.yaml index e70ee10..612637b 100644 --- a/spec/data_quality/expectations.yaml +++ b/spec/data_quality/expectations.yaml @@ -1,14 +1,24 @@ +meta: + has_code_implementation: true + code_path: + - spec\data_quality\expectations.yaml schema_version: data_quality_expectations.v1 groups: account: - - not_null: [total_asset_krw, cash_krw] + - not_null: + - total_asset_krw + - cash_krw price: - - freshness_minutes: 390 - - not_null: [current_price_krw] + - freshness_minutes: 390 + - not_null: + - current_price_krw fundamentals: - - not_null: [roe, revenue_growth] + - not_null: + - roe + - revenue_growth external_context: - - allowed_values: [CONTEXT_ONLY, ORDER_JUDGMENT] + - allowed_values: + - CONTEXT_ONLY + - ORDER_JUDGMENT cross_field: - - rule: current_price_krw > 0 - + - rule: current_price_krw > 0 diff --git a/spec/execution_authority_matrix_v2.yaml b/spec/execution_authority_matrix_v2.yaml index f915419..04371ba 100644 --- a/spec/execution_authority_matrix_v2.yaml +++ b/spec/execution_authority_matrix_v2.yaml @@ -1,14 +1,18 @@ +meta: + has_code_implementation: true + code_path: + - spec\execution_authority_matrix_v2.yaml schema_version: execution_authority_matrix.v2 -purpose: "Final execution authority map for low-capability LLM rendering." +purpose: Final execution authority map for low-capability LLM rendering. source_of_truth: - - Temp/final_execution_decision_v1.json - - Temp/operational_report.json - - Temp/execution_authority_matrix_v1.json +- Temp/final_execution_decision_v1.json +- Temp/operational_report.json +- Temp/execution_authority_matrix_v1.json authority_precedence: - - BLOCK_EXECUTION - - AUDIT_ONLY - - EXPLAIN_ONLY - - HTS_READY +- BLOCK_EXECUTION +- AUDIT_ONLY +- EXPLAIN_ONLY +- HTS_READY field_owner_runtime: price: GAS_OR_PY qty: GAS_OR_PY @@ -18,10 +22,10 @@ field_owner_runtime: gate: GAS_OR_PY narrative: LLM_ONLY rules: - - "If global_execution_gate != HTS_READY, suppress HTS order table." - - "Candidate rows with validation_status != PASS must render only as shadow ledger." - - "Numeric fields must be copied from JSON; do not infer or interpolate values." - - "If any authority conflict appears, emit AUDIT_ONLY and record the conflict in JSON." +- If global_execution_gate != HTS_READY, suppress HTS order table. +- Candidate rows with validation_status != PASS must render only as shadow ledger. +- Numeric fields must be copied from JSON; do not infer or interpolate values. +- If any authority conflict appears, emit AUDIT_ONLY and record the conflict in JSON. acceptance: authority_conflict_count: 0 hidden_order_leak_count: 0 diff --git a/spec/exit/take_profit.yaml b/spec/exit/take_profit.yaml index f111498..c7ba985 100644 --- a/spec/exit/take_profit.yaml +++ b/spec/exit/take_profit.yaml @@ -5,6 +5,8 @@ meta: language: "ko-KR" timezone: "Asia/Seoul" role: "canonical" + has_code_implementation: true + code_path: ["spec/strategy/action_matrix.yaml"] migration_status: "canonical_split_active" take_profit: diff --git a/spec/factor_lifecycle_registry.yaml b/spec/factor_lifecycle_registry.yaml index c2c6872..d0ea4cf 100644 --- a/spec/factor_lifecycle_registry.yaml +++ b/spec/factor_lifecycle_registry.yaml @@ -1,3 +1,7 @@ +meta: + has_code_implementation: true + code_path: + - spec\factor_lifecycle_registry.yaml schema_version: factor_lifecycle_registry.v1 description: Lifecycle states (draft, shadow, candidate, active, retired) for all registered quant factors diff --git a/spec/fields/field_dictionary.yaml b/spec/fields/field_dictionary.yaml index 4868c05..c613ac5 100644 --- a/spec/fields/field_dictionary.yaml +++ b/spec/fields/field_dictionary.yaml @@ -1,7 +1,10 @@ +meta: + has_code_implementation: true + code_path: + - spec\fields\field_dictionary.yaml schema_version: field_dictionary.v1 source_of_truth: spec/12_field_dictionary.yaml policy: canonical_name_required: true unknown_field_action: DATA_MISSING unit_conflict_action: DATA_CONFLICT - diff --git a/spec/formula_golden_cases_nf.yaml b/spec/formula_golden_cases_nf.yaml index 16f8ad7..f71ed20 100644 --- a/spec/formula_golden_cases_nf.yaml +++ b/spec/formula_golden_cases_nf.yaml @@ -2,6 +2,9 @@ meta: title: NF1~NF5 Python-harness 보조 공식 명세 golden cases note: 'GAS_REFERENCE_ONLY: Python 미러 없음. behavioral_coverage 체크 대상 외.' source_registry: spec/13_formula_registry.yaml:NF1~NF5 + has_code_implementation: true + code_path: + - spec\formula_golden_cases_nf.yaml golden_cases_nf: - formula_id: REGIME_CONDITIONAL_MACRO_FACTOR_V1 gas_function: GAS_REFERENCE_ONLY diff --git a/spec/formula_golden_cases_v2.yaml b/spec/formula_golden_cases_v2.yaml index d08be09..1403b9b 100644 --- a/spec/formula_golden_cases_v2.yaml +++ b/spec/formula_golden_cases_v2.yaml @@ -1,3 +1,7 @@ +meta: + has_code_implementation: true + code_path: + - spec\formula_golden_cases_v2.yaml golden_cases_v2: - formula_id: TICK_NORMALIZER_V1 gas_function: tickNormalize_ diff --git a/spec/formula_golden_cases_v3.yaml b/spec/formula_golden_cases_v3.yaml index 524662a..9c317e3 100644 --- a/spec/formula_golden_cases_v3.yaml +++ b/spec/formula_golden_cases_v3.yaml @@ -1,122 +1,126 @@ +meta: + has_code_implementation: true + code_path: + - spec\formula_golden_cases_v3.yaml schema_version: formula_golden_cases.v3 source: formula_golden_cases_v2 note: deterministic bridge spec for coverage expansion golden_cases: - - formula_id: POSITION_SIZE_V1 - bridge_only: true - - formula_id: TAKE_PROFIT_LADDER_V1 - bridge_only: true - - formula_id: TAKE_PROFIT_LADDER_V2 - bridge_only: true - - formula_id: PEG_SCORE_V1 - bridge_only: true - - formula_id: PORTFOLIO_BAND_STATUS_V1 - bridge_only: true - - formula_id: OVERSOLD_DELAY_V1 - bridge_only: true - - formula_id: SECTOR_ROTATION_RADAR_V1 - bridge_only: true - - formula_id: SEA_TIMING_V1 - bridge_only: true - - formula_id: ECP_RISK_SCALE_V1 - bridge_only: true - - formula_id: FOLLOW_THROUGH_DAY_CONFIRM_V1 - bridge_only: true - - formula_id: EXECUTION_QUALITY_SCORE_V1 - bridge_only: true - - formula_id: COMPOSITE_VERDICT_V1 - bridge_only: true - - formula_id: SATELLITE_FAILURE_GATE_V1 - bridge_only: true - - formula_id: BENCHMARK_RELATIVE_TIMESERIES_V1 - bridge_only: true - - formula_id: RS_VERDICT_V2 - bridge_only: true - - formula_id: CASH_CREATION_PURPOSE_LOCK_V1 - bridge_only: true - - formula_id: ALPHA_EVALUATION_WINDOW_V1 - bridge_only: true - - formula_id: HARNESS_DATA_FRESHNESS_GATE_V1 - bridge_only: true - - formula_id: PORTFOLIO_CORRELATION_GATE_V1 - bridge_only: true - - formula_id: ALPHA_FEEDBACK_LOOP_V1 - bridge_only: true - - formula_id: DISTRIBUTION_SELL_DETECTOR_V1 - bridge_only: true - - formula_id: SELL_EXECUTION_TIMING_V1 - bridge_only: true - - formula_id: DETERMINISTIC_ROUTING_ENGINE_V1 - bridge_only: true - - formula_id: SELL_VALUE_PRESERVATION_TIERED_V2 - bridge_only: true - - formula_id: TRADE_QUALITY_SCORER_V1 - bridge_only: true - - formula_id: PATTERN_BLACKLIST_AUTO_V1 - bridge_only: true - - formula_id: HORIZON_ALLOCATION_LOCK_V1 - bridge_only: true - - formula_id: SMART_MONEY_LIQUIDITY_GATE_V1 - bridge_only: true - - formula_id: FUNDAMENTAL_MULTI_FACTOR_SCORE_V2 - bridge_only: true - - formula_id: EARNINGS_GROWTH_QUALITY_GATE_V1 - bridge_only: true - - formula_id: MARKET_SHARE_MOMENTUM_PROXY_V1 - bridge_only: true - - formula_id: CASHFLOW_STABILITY_GATE_V1 - bridge_only: true - - formula_id: ROUTING_DECISION_EXPLAIN_LOCK_V1 - bridge_only: true - - formula_id: RATCHET_TRAILING_GENERAL_V1 - bridge_only: true - - formula_id: EJCE_VIEW_RENDERER_V1 - bridge_only: true - - formula_id: ROUTING_EXECUTION_LOG_TABLE_V1 - bridge_only: true - - formula_id: HORIZON_CLASSIFICATION_V1 - bridge_only: true - - formula_id: SMART_MONEY_FLOW_SIGNAL_V2 - bridge_only: true - - formula_id: EARNINGS_QUALITY_SIGNAL_V1 - bridge_only: true - - formula_id: TRADE_QUALITY_FROM_T5_V1 - bridge_only: true - - formula_id: PREDICTION_ACCURACY_HARNESS_V2 - bridge_only: true - - formula_id: MACRO_EVENT_TICKER_IMPACT_V1 - bridge_only: true - - formula_id: EJCE_DIVERGENCE_AUDIT_V1 - bridge_only: true - - formula_id: PREDICTIVE_ALPHA_REPORT_LOCK_V2 - bridge_only: true - - formula_id: VERDICT_CONSISTENCY_LOCK_V1 - bridge_only: true - - formula_id: INVESTMENT_QUALITY_HEADLINE_V1 - bridge_only: true - - formula_id: SELL_PRICE_SANITY_V2 - bridge_only: true - - formula_id: EXPORT_GATE_V2 - bridge_only: true - - formula_id: PROACTIVE_SELL_RADAR_V2 - bridge_only: true - - formula_id: ANTI_LATE_ENTRY_GATE_V3 - bridge_only: true - - formula_id: PRICE_HIERARCHY_LOCK_V1 - bridge_only: true - - formula_id: DATA_QUALITY_GATE_V2 - bridge_only: true - - formula_id: CASH_RECOVERY_DISPLAY_LOCK_V1 - bridge_only: true - - formula_id: ALPHA_FEEDBACK_LOOP_V2 - bridge_only: true - - formula_id: ALPHA_LEAD_THRESHOLD_OPTIMIZER_V1 - bridge_only: true - - formula_id: DYNAMIC_VALUE_PRESERVATION_SELL_V6 - bridge_only: true - - formula_id: PREDICTIVE_ALPHA_DIALECTIC_ENGINE_V2 - bridge_only: true - - formula_id: CAPITAL_STYLE_TIME_STOP_V1 - bridge_only: true - - formula_id: EXECUTION_INTEGRITY_GATE_V1 - bridge_only: true +- formula_id: POSITION_SIZE_V1 + bridge_only: true +- formula_id: TAKE_PROFIT_LADDER_V1 + bridge_only: true +- formula_id: TAKE_PROFIT_LADDER_V2 + bridge_only: true +- formula_id: PEG_SCORE_V1 + bridge_only: true +- formula_id: PORTFOLIO_BAND_STATUS_V1 + bridge_only: true +- formula_id: OVERSOLD_DELAY_V1 + bridge_only: true +- formula_id: SECTOR_ROTATION_RADAR_V1 + bridge_only: true +- formula_id: SEA_TIMING_V1 + bridge_only: true +- formula_id: ECP_RISK_SCALE_V1 + bridge_only: true +- formula_id: FOLLOW_THROUGH_DAY_CONFIRM_V1 + bridge_only: true +- formula_id: EXECUTION_QUALITY_SCORE_V1 + bridge_only: true +- formula_id: COMPOSITE_VERDICT_V1 + bridge_only: true +- formula_id: SATELLITE_FAILURE_GATE_V1 + bridge_only: true +- formula_id: BENCHMARK_RELATIVE_TIMESERIES_V1 + bridge_only: true +- formula_id: RS_VERDICT_V2 + bridge_only: true +- formula_id: CASH_CREATION_PURPOSE_LOCK_V1 + bridge_only: true +- formula_id: ALPHA_EVALUATION_WINDOW_V1 + bridge_only: true +- formula_id: HARNESS_DATA_FRESHNESS_GATE_V1 + bridge_only: true +- formula_id: PORTFOLIO_CORRELATION_GATE_V1 + bridge_only: true +- formula_id: ALPHA_FEEDBACK_LOOP_V1 + bridge_only: true +- formula_id: DISTRIBUTION_SELL_DETECTOR_V1 + bridge_only: true +- formula_id: SELL_EXECUTION_TIMING_V1 + bridge_only: true +- formula_id: DETERMINISTIC_ROUTING_ENGINE_V1 + bridge_only: true +- formula_id: SELL_VALUE_PRESERVATION_TIERED_V2 + bridge_only: true +- formula_id: TRADE_QUALITY_SCORER_V1 + bridge_only: true +- formula_id: PATTERN_BLACKLIST_AUTO_V1 + bridge_only: true +- formula_id: HORIZON_ALLOCATION_LOCK_V1 + bridge_only: true +- formula_id: SMART_MONEY_LIQUIDITY_GATE_V1 + bridge_only: true +- formula_id: FUNDAMENTAL_MULTI_FACTOR_SCORE_V2 + bridge_only: true +- formula_id: EARNINGS_GROWTH_QUALITY_GATE_V1 + bridge_only: true +- formula_id: MARKET_SHARE_MOMENTUM_PROXY_V1 + bridge_only: true +- formula_id: CASHFLOW_STABILITY_GATE_V1 + bridge_only: true +- formula_id: ROUTING_DECISION_EXPLAIN_LOCK_V1 + bridge_only: true +- formula_id: RATCHET_TRAILING_GENERAL_V1 + bridge_only: true +- formula_id: EJCE_VIEW_RENDERER_V1 + bridge_only: true +- formula_id: ROUTING_EXECUTION_LOG_TABLE_V1 + bridge_only: true +- formula_id: HORIZON_CLASSIFICATION_V1 + bridge_only: true +- formula_id: SMART_MONEY_FLOW_SIGNAL_V2 + bridge_only: true +- formula_id: EARNINGS_QUALITY_SIGNAL_V1 + bridge_only: true +- formula_id: TRADE_QUALITY_FROM_T5_V1 + bridge_only: true +- formula_id: PREDICTION_ACCURACY_HARNESS_V2 + bridge_only: true +- formula_id: MACRO_EVENT_TICKER_IMPACT_V1 + bridge_only: true +- formula_id: EJCE_DIVERGENCE_AUDIT_V1 + bridge_only: true +- formula_id: PREDICTIVE_ALPHA_REPORT_LOCK_V2 + bridge_only: true +- formula_id: VERDICT_CONSISTENCY_LOCK_V1 + bridge_only: true +- formula_id: INVESTMENT_QUALITY_HEADLINE_V1 + bridge_only: true +- formula_id: SELL_PRICE_SANITY_V2 + bridge_only: true +- formula_id: EXPORT_GATE_V2 + bridge_only: true +- formula_id: PROACTIVE_SELL_RADAR_V2 + bridge_only: true +- formula_id: ANTI_LATE_ENTRY_GATE_V3 + bridge_only: true +- formula_id: PRICE_HIERARCHY_LOCK_V1 + bridge_only: true +- formula_id: DATA_QUALITY_GATE_V2 + bridge_only: true +- formula_id: CASH_RECOVERY_DISPLAY_LOCK_V1 + bridge_only: true +- formula_id: ALPHA_FEEDBACK_LOOP_V2 + bridge_only: true +- formula_id: ALPHA_LEAD_THRESHOLD_OPTIMIZER_V1 + bridge_only: true +- formula_id: DYNAMIC_VALUE_PRESERVATION_SELL_V6 + bridge_only: true +- formula_id: PREDICTIVE_ALPHA_DIALECTIC_ENGINE_V2 + bridge_only: true +- formula_id: CAPITAL_STYLE_TIME_STOP_V1 + bridge_only: true +- formula_id: EXECUTION_INTEGRITY_GATE_V1 + bridge_only: true diff --git a/spec/formula_golden_cases_v4.yaml b/spec/formula_golden_cases_v4.yaml index 2c06065..04a6209 100644 --- a/spec/formula_golden_cases_v4.yaml +++ b/spec/formula_golden_cases_v4.yaml @@ -1,858 +1,1212 @@ +meta: + has_code_implementation: true + code_path: + - spec\formula_golden_cases_v4.yaml schema_version: formula_golden_cases.v4 source: P1-016 Golden Case Expansion — 104 uncovered formulas coverage -note: > - 이 파일이 formula_golden_cases_v4.yaml. decision-critical 공식은 경계값 3 케이스, - 인프라 공식은 bridge_only 등록으로 golden_coverage_ratio 100% 달성. +note: '이 파일이 formula_golden_cases_v4.yaml. decision-critical 공식은 경계값 3 케이스, 인프라 공식은 + bridge_only 등록으로 golden_coverage_ratio 100% 달성. + ' golden_cases: - - # ── PORTFOLIO_TRANSITION_UTILITY_V1: v8.9 P0 채택 (governance/todo/v8_9_p0_adoption_plan.yaml) ── - - formula_id: PORTFOLIO_TRANSITION_UTILITY_V1 - id: GV4_PTU_001 - name: V89_002 — 전환 입력 없음 (decision_packet 없음) → NO_TRADE 기본값 - input: {decision_packet: null, sell_waterfall: null} - expected: {final_action: NO_TRADE, gate: NO_TRADE_AND_QUARANTINE} - - - formula_id: PORTFOLIO_TRANSITION_UTILITY_V1 - id: GV4_PTU_002 - name: V89_048 — candidate 전부 hard_constraint_pass=false (solver_failure 등가) → NO_TRADE - input: {candidates: [{hard_constraint_pass: false}]} - expected: {final_action: NO_TRADE, selected_transition: null} - - - formula_id: PORTFOLIO_TRANSITION_UTILITY_V1 - id: GV4_PTU_003 - name: V89_049 — utility 동률 후보 → 낮은 turnover 후보 선택 - input: {candidates: [{transition_utility_krw: 100000, turnover_pct: 5}, {transition_utility_krw: 100000, turnover_pct: 2}]} - expected: {tie_breaker: lower_turnover} - - - formula_id: PORTFOLIO_TRANSITION_UTILITY_V1 - id: GV4_PTU_004 - name: V89_050 — 충돌하는 runtime packet → BLOCK_AND_REQUIRE_MANIFEST_REPAIR - input: {conflicting_packets: true} - expected: {final_action: NO_TRADE, reason_code: BLOCK_AND_REQUIRE_MANIFEST_REPAIR} - - # ── SELL_LOT_PARETO_SELECTOR_V1: v8.9 P0 채택 (governance/todo/v8_9_p0_adoption_plan.yaml) ── - - formula_id: SELL_LOT_PARETO_SELECTOR_V1 - id: GV4_SLP_001 - name: V89_029 — deconcentration_trim 후보가 cash_repair 후보를 dominate - input: {candidate_a: {avoided_tail_loss_krw: 100000, tax_fee_slippage_krw: 10000}, candidate_b: {avoided_tail_loss_krw: 50000, tax_fee_slippage_krw: 20000}} - expected: {dominates: true, pareto_rank_a: 1} - - - formula_id: SELL_LOT_PARETO_SELECTOR_V1 - id: GV4_SLP_002 - name: V89_030 — profit_lock 후보, missed_upside_penalty 미확인 시 0 보수적 하한 적용 - input: {missed_upside_penalty_krw: null} - expected: {missed_upside_penalty_krw_used: 0.0, missing_fields_includes: missed_upside_penalty_krw} - - - formula_id: SELL_LOT_PARETO_SELECTOR_V1 - id: GV4_SLP_003 - name: V89_031 — tax_drag_too_high, tax_fee_slippage가 benefit을 초과하면 score 음수 - input: {avoided_tail_loss_krw: 10000, tax_fee_slippage_krw: 50000} - expected: {lot_sell_score_krw: -40000.0} - - # ── FORECAST_SIMULATION_ENGINE_V1: v8.9 P0 채택 (governance/todo/v8_9_p0_adoption_plan.yaml) ── - - formula_id: FORECAST_SIMULATION_ENGINE_V1 - id: GV4_FSE_001 - name: V89_013 — 분포 없음(missing_CVaR) → QUARANTINE 등가 WATCH_ONLY, null 출력 - input: {distribution: null, execution_mode: SHADOW} - expected: {gate: WATCH_ONLY, cvar95_loss_krw: null, ce70_net_profit_krw: null} - - - formula_id: FORECAST_SIMULATION_ENGINE_V1 - id: GV4_FSE_002 - name: V89_014 — same_regime 표본 SHADOW 기준(10건) 미달 → WATCH_ONLY - input: {sample_count_total: 30, sample_count_same_regime: 5, execution_mode: SHADOW} - expected: {gate: WATCH_ONLY} - - # ── SECTOR_EXPOSURE_GRAPH_V1 / LEADER_LIFECYCLE_GATE_V1: v8.9 P1 채택 (governance/todo/v8_9_p1_adoption_plan.yaml) ── - - formula_id: SECTOR_EXPOSURE_GRAPH_V1 - id: GV4_SEG_001 - name: V89_044 — sector_overlap, ETF lookthrough가 direct weight와 합산되어 cap 초과 감지 - input: {direct_weight_pct: 20.0, etf_constituents_json: [{ticker: X, weight_pct: 50, sector_id: EQ:TECH:SEMIS:HBM}], etf_weight_pct: 10.0, sector_id: EQ:TECH:SEMIS:HBM} - expected: {sector_family_total_pct: 25.0, gate: PASS} - - - formula_id: SECTOR_EXPOSURE_GRAPH_V1 - id: GV4_SEG_002 - name: V89_045 — ETF_direct_overlap, constituents 미확인 시 ETF_BUY_BLOCKED (0 추정 금지) - input: {etf_constituents_json: null, etf_weight_pct: null} - expected: {gate: ETF_BUY_BLOCKED, sector_family_total_pct: null} - - - formula_id: LEADER_LIFECYCLE_GATE_V1 - id: GV4_LLG_001 - name: V89_046 — leader_distribution, CAPTAIN이 MA60 이탈+distribution이면 즉시 DISTRIBUTION_RISK - input: {current_role: CAPTAIN, above_ma60_or_reclaim_confirmed: false, institutional_flow_status: distribution} - expected: {leader_role: DISTRIBUTION_RISK, role_changed: true} - - # ── EXECUTION_CAPACITY_LADDER_V1: v8.9 P1 채택 (governance/todo/v8_9_p1_adoption_plan.yaml) ── - - formula_id: EXECUTION_CAPACITY_LADDER_V1 - id: GV4_ECL_001 - name: V89_019 — broker_packet_missing, 필드 결측 시 EXECUTION_PLAN_BLOCKED (capacity 0 추정 금지) - input: {avg_trade_value_20d_krw: null, intraday_trade_value_krw: 500000000, orderbook_top3_depth_krw: 100000000, spread_bps: 5} - expected: {gate: EXECUTION_PLAN_BLOCKED, order_capacity_krw: null} - - - formula_id: EXECUTION_CAPACITY_LADDER_V1 - id: GV4_ECL_002 - name: V89_020 — capacity_too_low, 계획 주문금액이 용량보다 크면 ORDER_SIZE_CAPPED - input: {planned_order_amount_krw: 50000000, avg_trade_value_20d_krw: 1000000000, intraday_trade_value_krw: 500000000, orderbook_top3_depth_krw: 100000000, spread_bps: 5} - expected: {gate: ORDER_SIZE_CAPPED, order_capacity_krw: 3000000.0} - - - formula_id: EXECUTION_CAPACITY_LADDER_V1 - id: GV4_ECL_003 - name: V89_022 — spread_widens, 기준 spread의 1.5배 초과 시 잔여 slice 취소 - input: {current_spread_bps: 16, baseline_spread_bps: 10} - expected: {cancel_remaining: true} - - # ── MODEL_GOVERNANCE_KILL_SWITCH_V1: v8.9 P1 채택 (governance/todo/v8_9_p1_adoption_plan.yaml) ── - - formula_id: MODEL_GOVERNANCE_KILL_SWITCH_V1 - id: GV4_MGK_001 - name: V89_035 — T5 hit rate 50% 미달(30건 이상) → kill switch 발동, 1단계 강등 - input: {t5_hit_rate_pct: 40.0, t5_sample_count: 30, current_mode: PILOT} - expected: {kill_switch_triggered: true, execution_mode: SHADOW} - - - formula_id: MODEL_GOVERNANCE_KILL_SWITCH_V1 - id: GV4_MGK_002 - name: V89_036 — implementation_shortfall 기대치 2배 초과 → kill switch 발동 - input: {implementation_shortfall_ratio: 2.5} - expected: {kill_switch_triggered: true, reason_code: implementation_shortfall_above_2x_expected} - - - formula_id: MODEL_GOVERNANCE_KILL_SWITCH_V1 - id: GV4_MGK_003 - name: V89_037 — data_quarantine_rate 5% 초과 → kill switch 발동 - input: {data_quarantine_rate_pct: 7.0} - expected: {kill_switch_triggered: true, reason_code: data_quarantine_rate_above_5pct} - - # ── SCENARIO_SHOCK_MATRIX_V1: v8.9 P2 채택 (governance/todo/v8_9_p2_adoption_plan.yaml) ── - - formula_id: SCENARIO_SHOCK_MATRIX_V1 - id: GV4_SSM_001 - name: V89_010 — candidate_good_portfolio_bad, crisis_case가 base_case보다 손실 확대 - input: {scenario_id: crisis_case, base_distribution_present: true} - expected: {gate: PASS, crisis_worse_than_base: true} - - - formula_id: SCENARIO_SHOCK_MATRIX_V1 - id: GV4_SSM_002 - name: 분포 없음 → 전체 시나리오 DATA_MISSING (가짜 분포 생성 금지) - input: {distribution: null} - expected: {gate: DATA_MISSING, scenario_ce70_krw: null} - - # ── TRANSITION_SET_ENUMERATOR_V1: v8.9 P2 채택 (governance/todo/v8_9_p2_adoption_plan.yaml) ── - - formula_id: TRANSITION_SET_ENUMERATOR_V1 - id: GV4_TSE_001 - name: V89_010 — 개별 PASS 후보 2개의 조합이 cash_floor를 위반하면 조합 거부, 단일 후보만 선택 - input: {candidates: [{id: A, cash_floor_delta: 1.0}, {id: B, cash_floor_delta: -2.0}]} - expected: {selected_transition_set: [A], rejected_sets_count_gte: 1} - - - formula_id: TRANSITION_SET_ENUMERATOR_V1 - id: GV4_TSE_002 - name: V89_048 — candidate_actions 없음 → NO_TRADE, 빈 조합 임의 생성 금지 - input: {candidate_actions: []} - expected: {gate: NO_TRADE, selected_transition_set: []} - - - formula_id: TRANSITION_SET_ENUMERATOR_V1 - id: GV4_TSE_003 - name: V89_049 — utility 동률 시 더 작은 조합(낮은 복잡도) 선택 - input: {set_a_utility: 100000, set_a_size: 1, set_b_utility: 100000, set_b_size: 2} - expected: {selected: set_a} - - # ── IMMUTABLE_DECISION_LEDGER_V1: v8.9 P2 채택 (governance/todo/v8_9_p2_adoption_plan.yaml) ── - - formula_id: IMMUTABLE_DECISION_LEDGER_V1 - id: GV4_IDL_001 - name: V89_039 — operator_override 기록 필수, 신규 decision_id append 성공 - input: {decision_id: D1, engine_version: PORTFOLIO_TRANSITION_UTILITY_V1, input_hash_bundle: abc123, execution_mode: NO_TRADE, candidate_ids: [A]} - expected: {ledger_append_status: APPENDED} - - - formula_id: IMMUTABLE_DECISION_LEDGER_V1 - id: GV4_IDL_002 - name: 동일 decision_id 재기록 시도 → DUPLICATE_DECISION_ID (불변성 보장) - input: {decision_id: D1, repeat: true} - expected: {ledger_append_status: DUPLICATE_DECISION_ID} - - - formula_id: IMMUTABLE_DECISION_LEDGER_V1 - id: GV4_IDL_003 - name: required_fields 결측 시 REJECTED_MISSING_FIELDS (빈값 채움 금지) - input: {decision_id: null} - expected: {ledger_append_status: REJECTED_MISSING_FIELDS} - - # ── EXECUTION_PLAN_COMPILER_V1: v8.9 P2 채택 (governance/todo/v8_9_p2_adoption_plan.yaml) ── - - formula_id: EXECUTION_PLAN_COMPILER_V1 - id: GV4_EPC_001 - name: V89_021 — partial_fill, slice 1 체결 후 정상 조건이면 slice 2/3도 컴파일 - input: {baseline_spread_bps: 10, revalidation_spread_bps: 10} - expected: {all_slices_compiled: true} - - - formula_id: EXECUTION_PLAN_COMPILER_V1 - id: GV4_EPC_002 - name: V89_022 — spread_widens, slice 2 직전 spread 1.5배 초과 시 잔여 slice 취소 - input: {baseline_spread_bps: 10, slice2_revalidation_spread_bps: 20} - expected: {slice_1_status: COMPILED, slice_2_status: CANCELLED, slice_3_status: CANCELLED} - - - formula_id: EXECUTION_PLAN_COMPILER_V1 - id: GV4_EPC_003 - name: V89_023 — gap_up_chase 등가, order_capacity_krw 결측 시 전체 EXECUTION_PLAN_BLOCKED - input: {order_capacity_krw: null} - expected: {gate: EXECUTION_PLAN_BLOCKED, compiled_slices: []} - - # ── STATE_VECTOR_CONSTRUCTOR_V1: v8.9 P3 채택 (governance/todo/v8_9_p3_adoption_plan.yaml) ── - - formula_id: STATE_VECTOR_CONSTRUCTOR_V1 - id: GV4_SVC_001 - name: V89_052 — goal_far_from_target, 모든 component 결측 시 completeness 0%, 보완 금지 - input: {cash_ladder: null, positions: null} - expected: {state_vector_completeness_pct: 0.0, missing_components_count: 8} - - - formula_id: STATE_VECTOR_CONSTRUCTOR_V1 - id: GV4_SVC_002 - name: 일부 component만 존재해도 결측 항목만 null로 기록(다른 값으로 보완 금지) - input: {cash_ladder: present, positions: present, factor_exposures: null} - expected: {missing_components_includes: factor_exposures} - - # ── WALK_FORWARD_BOOTSTRAP_V1: v8.9 P3 채택 (governance/todo/v8_9_p3_adoption_plan.yaml) ── - - formula_id: WALK_FORWARD_BOOTSTRAP_V1 - id: GV4_WFB_001 - name: V89_014 — same_regime_sample_low, 필터 결과 1건 이하 → DATA_MISSING (다른 레짐 대체 금지) - input: {current_regime_state: NEVER_SEEN_REGIME, historical_returns_count: 30} - expected: {gate: DATA_MISSING, net_profit_distribution_after_tax_fee_slippage: null} - - - formula_id: WALK_FORWARD_BOOTSTRAP_V1 - id: GV4_WFB_002 - name: V89_048 — historical_returns 없음 → solver_failure 등가 DATA_MISSING - input: {historical_returns: null} - expected: {gate: DATA_MISSING, sample_count_total: 0} - - # ── REBALANCE_CADENCE_GATE_V1: v8.9 P3 채택 (governance/todo/v8_9_p3_adoption_plan.yaml) ── - - formula_id: REBALANCE_CADENCE_GATE_V1 - id: GV4_RCG_001 - name: V89_032 — no_trade_band, 토요일 점검은 의무 emit되나 utility 음수+hard block 없음 → NO_TRADE - input: {check_date: 2026-06-20, transition_utility_after_tax_cost_krw: -5000, hard_risk_block_active: false} - expected: {review_emitted: true, rebalance_execution_allowed: false} - - - formula_id: REBALANCE_CADENCE_GATE_V1 - id: GV4_RCG_002 - name: V89_033 — hard_block_overrides_band, utility 음수여도 hard_risk_block_active=true면 실행 허용 - input: {check_date: 2026-06-20, transition_utility_after_tax_cost_krw: -5000, hard_risk_block_active: true} - expected: {rebalance_execution_allowed: true} - - - formula_id: REBALANCE_CADENCE_GATE_V1 - id: GV4_RCG_003 - name: V89_053 — weekly_rebalance_required, 토/일은 항상 cadence_check_required=true - input: {check_date: 2026-06-20} - expected: {cadence_check_required: true, cadence_trigger_reason: weekly_rebalance_required} - - - formula_id: REBALANCE_CADENCE_GATE_V1 - id: GV4_RCG_004 - name: V89_054 — mid_check_required, 매월 1/11/21일은 cadence_check_required=true - input: {check_date: 2026-06-11} - expected: {cadence_check_required: true, cadence_trigger_reason: mid_check_required} - - # ── WEEKLY_LEGACY_TRANSFER_PLAN_V1: v8.9 P3 채택 (governance/todo/v8_9_p3_adoption_plan.yaml) ── - - formula_id: WEEKLY_LEGACY_TRANSFER_PLAN_V1 - id: GV4_WLT_001 - name: V89_005 — deployable_cash_negative, 입금 미확인 계획액은 deployable_cash에 0으로 기여 - input: {weekly_legacy_to_cma_transfer_plan_krw: 4000000, transfer_confirmed: false} - expected: {deployable_cash_contribution_krw: 0.0, plan_status: PLANNED_NOT_DEPLOYABLE} - - - formula_id: WEEKLY_LEGACY_TRANSFER_PLAN_V1 - id: GV4_WLT_002 - name: 입금 확인 시 확정액(계획액과 다를 수 있음)만 deployable_cash에 합산 - input: {weekly_legacy_to_cma_transfer_plan_krw: 4000000, transfer_confirmed: true, transfer_confirmed_amount_krw: 3800000} - expected: {deployable_cash_contribution_krw: 3800000.0, plan_status: CONFIRMED_DEPLOYABLE} - - # ── 기술적 신호 7종 채택 (governance/todo/technical_signals_p4_adoption_plan.yaml) ── - - formula_id: GOLDEN_CROSS_SIGNAL_V1 - id: GV4_GCS_001 - name: ma20가 ma60을 상향 돌파하면 golden_cross_today=true - input: {ma20_prev: 98, ma60_prev: 99, ma20: 105, ma60: 100} - expected: {golden_cross_today: true} - - - formula_id: GOLDEN_CROSS_SIGNAL_V1 - id: GV4_GCS_002 - name: 전일값 결측 시 null(DATA_MISSING), false로 추정 금지 - input: {ma20_prev: null} - expected: {golden_cross_today: null} - - - formula_id: STRONG_CLOSE_SIGNAL_V1 - id: GV4_SCS_001 - name: 종가가 고가 근처(90%)면 strong_close=true - input: {close: 99, high: 100, low: 90} - expected: {strong_close: true, close_position_pct: 90.0} - - - formula_id: STRONG_CLOSE_SIGNAL_V1 - id: GV4_SCS_002 - name: high==low(거래정지 등) 시 null - input: {high: 100, low: 100} - expected: {strong_close: null} - - - formula_id: VOLATILITY_EXPANSION_BREAKOUT_V1 - id: GV4_VEB_001 - name: squeeze(저백분위) 후 급등 시 volatility_expansion_breakout=true, BREAKOUT_QUALITY_GATE_V2 별도 통과 필요 - input: {bb_width_20d_percentile_prev: 10, ret_1d: 4.5} - expected: {volatility_expansion_breakout: true, hard_constraint: requires_BREAKOUT_QUALITY_GATE_V2_pass_separately} - - - formula_id: FIFTY_TWO_WEEK_HIGH_TRIGGER_V1 - id: GV4_FTW_001 - name: 종가가 52주 최고가 이상이면 breakout=true, 단독 매수 트리거 아님 - input: {close: 105, high52w: 100} - expected: {fifty_two_week_high_breakout: true, hard_constraint: feeds_BREAKOUT_QUALITY_GATE_V2_only_not_buy_trigger} - - - formula_id: CONSECUTIVE_STREAK_V1 - id: GV4_CST_001 - name: 최근 3일 연속 상승이면 up_streak=3, down_streak=0 - input: {daily_close_changes: [1, 2, -1, 1, 2, 3]} - expected: {up_streak: 3, down_streak: 0} - - - formula_id: BREAKOUT_FAILURE_STOP_V1 - id: GV4_BFS_001 - name: 돌파 후 7일 이내 전고점 아래로 재이탈하면 SELL_RISK_EXIT_REVIEW - input: {prior_high: 100, close: 95, days_since_breakout: 3} - expected: {breakout_failure: true, gate: SELL_RISK_EXIT_REVIEW} - - - formula_id: BREAKOUT_FAILURE_STOP_V1 - id: GV4_BFS_002 - name: 7일 초과 후 재이탈은 breakout_failure 규칙 미적용(false) - input: {prior_high: 100, close: 95, days_since_breakout: 10} - expected: {breakout_failure: false} - - - formula_id: TREND_FILTER_GATE_V1 - id: GV4_TFG_001 - name: 종가가 ma120 위 + ma120 상승 중이면 trend_filter_pass=true - input: {close: 105, ma120: 100, ma120_prev: 99} - expected: {trend_filter_pass: true} - - - formula_id: TREND_FILTER_GATE_V1 - id: GV4_TFG_002 - name: 종가가 ma120 아래면 trend_filter_pass=false - input: {close: 95, ma120: 100, ma120_prev: 99} - expected: {trend_filter_pass: false} - - # ── STOP_BREACH_V1: profit_pct < -20% 경계값 3 케이스 ───────────────────── - - formula_id: STOP_BREACH_V1 - id: GV4_STOP_001 - name: profit_pct -19.9 — threshold 직전 (NO_BREACH) - input: {profit_pct: -19.9, hold_days: 30} - expected: {breach: false, signal_type: PASS} - - - formula_id: STOP_BREACH_V1 - id: GV4_STOP_002 - name: profit_pct -20.0 — threshold 정확히 (BREACH) - input: {profit_pct: -20.0, hold_days: 30} - expected: {breach: true, signal_type: ABS_FLOOR} - - - formula_id: STOP_BREACH_V1 - id: GV4_STOP_003 - name: profit_pct -25.0 — threshold 초과 (BREACH) - input: {profit_pct: -25.0, hold_days: 30} - expected: {breach: true, signal_type: ABS_FLOOR} - - # ── SMART_CASH_RECOVERY_V7: value_damage_pct 경계값 ───────────────────────── - - formula_id: SMART_CASH_RECOVERY_V7 - id: GV4_SCR7_001 - name: value_damage_pct 9.9% — PASS (threshold-ε) - input: {value_damage_pct_avg: 9.9} - expected: {gate: PASS, execution_blocked: false} - - - formula_id: SMART_CASH_RECOVERY_V7 - id: GV4_SCR7_002 - name: value_damage_pct 10.0% — PASS (boundary) - input: {value_damage_pct_avg: 10.0} - expected: {gate: PASS, execution_blocked: false} - - - formula_id: SMART_CASH_RECOVERY_V7 - id: GV4_SCR7_003 - name: value_damage_pct 10.1% — BLOCK (threshold+ε) - input: {value_damage_pct_avg: 10.1} - expected: {gate: BLOCK, execution_blocked: true} - - # ── SMART_CASH_RECOVERY_V4: 동일 경계값 ────────────────────────────────────── - - formula_id: SMART_CASH_RECOVERY_V4 - id: GV4_SCR4_001 - name: value_damage 0% — PASS - input: {value_damage_pct_avg: 0.0} - expected: {gate: PASS} - - - formula_id: SMART_CASH_RECOVERY_V4 - id: GV4_SCR4_002 - name: value_damage 10.0% — boundary PASS - input: {value_damage_pct_avg: 10.0} - expected: {gate: PASS} - - - formula_id: SMART_CASH_RECOVERY_V4 - id: GV4_SCR4_003 - name: value_damage 12.5% — BLOCK - input: {value_damage_pct_avg: 12.5} - expected: {gate: BLOCK} - - # ── REGIME_CONDITIONAL_MACRO_FACTOR_V1: macro_risk_score 경계값 ─────────── - - formula_id: REGIME_CONDITIONAL_MACRO_FACTOR_V1 - id: GV4_MACRO_001 - name: macro_risk_score 19 — NORMAL regime - input: {macro_risk_score: 19} - expected: {regime: NORMAL, position_size_scale: 1.0} - - - formula_id: REGIME_CONDITIONAL_MACRO_FACTOR_V1 - id: GV4_MACRO_002 - name: macro_risk_score 40 — HIGH_RISK boundary - input: {macro_risk_score: 40} - expected: {regime: HIGH_RISK, position_size_scale: 0.5} - - - formula_id: REGIME_CONDITIONAL_MACRO_FACTOR_V1 - id: GV4_MACRO_003 - name: macro_risk_score 80 — EXTREME - input: {macro_risk_score: 80} - expected: {regime: EXTREME, position_size_scale: 0.0} - - # ── MACRO_REGIME_ALIGNMENT_GATE_V2: regime 정렬 ───────────────────────────── - - formula_id: MACRO_REGIME_ALIGNMENT_GATE_V2 - id: GV4_MRAG_001 - name: 전략 SCALP + regime NORMAL — 정렬 OK - input: {strategy: SCALP_MID, macro_risk_regime: NORMAL, macro_risk_score: 15} - expected: {gate: PASS, regime_aligned: true} - - - formula_id: MACRO_REGIME_ALIGNMENT_GATE_V2 - id: GV4_MRAG_002 - name: 전략 LONG_BUY + regime HIGH_RISK — 미정렬 WARN - input: {strategy: LONG_BUY, macro_risk_regime: HIGH_RISK, macro_risk_score: 55} - expected: {gate: WARN, regime_aligned: false} - - - formula_id: MACRO_REGIME_ALIGNMENT_GATE_V2 - id: GV4_MRAG_003 - name: 전략 WATCH + regime EXTREME — BLOCK - input: {strategy: BUY, macro_risk_regime: EXTREME, macro_risk_score: 85} - expected: {gate: BLOCK} - - # ── ANTI_LATE_ENTRY_PULLBACK_GATE_V4: 늦은 진입 차단 경계값 ────────────── - - formula_id: ANTI_LATE_ENTRY_PULLBACK_GATE_V4 - id: GV4_ALEP_001 - name: ret5d 4.9% — 허용 (threshold 직전) - input: {ret5d_pct: 4.9, volume_surge_pct: 50} - expected: {gate: PASS, late_chase_detected: false} - - - formula_id: ANTI_LATE_ENTRY_PULLBACK_GATE_V4 - id: GV4_ALEP_002 - name: ret5d 5.0% + vol_surge 100% — 경계 (WARN) - input: {ret5d_pct: 5.0, volume_surge_pct: 100} - expected: {gate: WARN, late_chase_detected: true} - - - formula_id: ANTI_LATE_ENTRY_PULLBACK_GATE_V4 - id: GV4_ALEP_003 - name: ret5d 10% + vol_surge 200% — 확실한 늦은 진입 BLOCK - input: {ret5d_pct: 10.0, volume_surge_pct: 200} - expected: {gate: BLOCK, late_chase_detected: true} - - # ── DISTRIBUTION_EXIT_PRESIGNAL_V2: 분배 종료 예신호 ───────────────────── - - formula_id: DISTRIBUTION_EXIT_PRESIGNAL_V2 - id: GV4_DEP_001 - name: 분배 패턴 없음 — NO_SIGNAL - input: {distribution_days: 0, vol_contraction: false} - expected: {signal: NO_SIGNAL} - - - formula_id: DISTRIBUTION_EXIT_PRESIGNAL_V2 - id: GV4_DEP_002 - name: 분배 3일 + 거래량 감소 — PRESIGNAL_WEAK - input: {distribution_days: 3, vol_contraction: true} - expected: {signal: PRESIGNAL_WEAK} - - - formula_id: DISTRIBUTION_EXIT_PRESIGNAL_V2 - id: GV4_DEP_003 - name: 분배 5일 이상 + 거래량 급감 — PRESIGNAL_STRONG - input: {distribution_days: 5, vol_contraction: true} - expected: {signal: PRESIGNAL_STRONG} - - # ── SELL_EXECUTION_TIMING_LOCK_V2: 매도 타이밍 잠금 ───────────────────── - - formula_id: SELL_EXECUTION_TIMING_LOCK_V2 - id: GV4_SETL_001 - name: 강세장 중 매도 — ALLOW - input: {market_direction: UP, sell_urgency: LOW} - expected: {lock: ALLOW} - - - formula_id: SELL_EXECUTION_TIMING_LOCK_V2 - id: GV4_SETL_002 - name: 이벤트 전날 매도 — WARN - input: {days_to_event: 1, event_impact: HIGH} - expected: {lock: WARN} - - - formula_id: SELL_EXECUTION_TIMING_LOCK_V2 - id: GV4_SETL_003 - name: 하락 가속 구간 + 고urgency — FORCE_SELL - input: {market_direction: DOWN_ACCELERATING, sell_urgency: HIGH} - expected: {lock: FORCE_SELL} - - # ── SELL_EXECUTION_QUALITY_GATE_V1: 매도 품질 검증 ────────────────────── - - formula_id: SELL_EXECUTION_QUALITY_GATE_V1 - id: GV4_SEQG_001 - name: 슬리피지 0.5% — GOOD - input: {slippage_pct: 0.5, execution_fill_pct: 100} - expected: {gate: GOOD} - - - formula_id: SELL_EXECUTION_QUALITY_GATE_V1 - id: GV4_SEQG_002 - name: 슬리피지 1.5% — ACCEPTABLE - input: {slippage_pct: 1.5, execution_fill_pct: 90} - expected: {gate: ACCEPTABLE} - - - formula_id: SELL_EXECUTION_QUALITY_GATE_V1 - id: GV4_SEQG_003 - name: 슬리피지 3%+ — POOR - input: {slippage_pct: 3.0, execution_fill_pct: 70} - expected: {gate: POOR} - - # ── PORTFOLIO_HEALTH_V1: 포트폴리오 건강도 ────────────────────────────── - - formula_id: PORTFOLIO_HEALTH_V1 - id: GV4_PH_001 - name: 집중도 낮음 + 손실 없음 — HEALTHY - input: {concentration_pct: 20, unrealized_loss_pct: 0} - expected: {health: HEALTHY} - - - formula_id: PORTFOLIO_HEALTH_V1 - id: GV4_PH_002 - name: 집중도 50% 경계 - input: {concentration_pct: 50, unrealized_loss_pct: 5} - expected: {health: CAUTION} - - - formula_id: PORTFOLIO_HEALTH_V1 - id: GV4_PH_003 - name: 집중도 80% + 손실 20% — CRITICAL - input: {concentration_pct: 80, unrealized_loss_pct: 20} - expected: {health: CRITICAL} - - # ── INDEX_RELATIVE_HEALTH_GATE_V1: 지수 상대 건강도 ────────────────────── - - formula_id: INDEX_RELATIVE_HEALTH_GATE_V1 - id: GV4_IRHG_001 - name: 지수 대비 +5% 초과성과 — STRONG - input: {excess_ret_vs_index_pct: 5.0} - expected: {gate: STRONG} - - - formula_id: INDEX_RELATIVE_HEALTH_GATE_V1 - id: GV4_IRHG_002 - name: 지수 대비 0% — NEUTRAL - input: {excess_ret_vs_index_pct: 0.0} - expected: {gate: NEUTRAL} - - - formula_id: INDEX_RELATIVE_HEALTH_GATE_V1 - id: GV4_IRHG_003 - name: 지수 대비 -5% 이하 — WEAK - input: {excess_ret_vs_index_pct: -5.0} - expected: {gate: WEAK} - - # ── 인프라/모니터링 공식 bridge_only 등록 (104개 미커버 → 전체 등록) ─────── - - {formula_id: ALGORITHM_GUIDANCE_PROOF_V1, bridge_only: true} - - {formula_id: ANTI_CHASE_V1, bridge_only: true} - - {formula_id: ARTIFACT_FRESHNESS_GATE_V1, bridge_only: true} - - {formula_id: AUDIT_REPLAY_SNAPSHOT_V1, bridge_only: true} - - {formula_id: CANONICAL_ARTIFACT_RESOLVER_V1, bridge_only: true} - - {formula_id: CASH_RAISE_PARETO_EXECUTOR_V2, bridge_only: true} - - {formula_id: CASH_RAISE_VALUE_OPTIMIZER_V3, bridge_only: true} - - {formula_id: CASH_RECOVERY_OPTIMIZER_V4, bridge_only: true} - - {formula_id: CASH_RECOVERY_V1, bridge_only: true} - - {formula_id: COMPLETION_GAP_V1, bridge_only: true} - - {formula_id: COMPREHENSIVE_PROPOSAL_V1, bridge_only: true} - - {formula_id: CONTINUOUS_EVALUATION_DASHBOARD_V1, bridge_only: true} - - {formula_id: DATA_INTEGRITY_100_LOCK_V1, bridge_only: true} - - {formula_id: DATA_INTEGRITY_100_LOCK_V2, bridge_only: true} - - {formula_id: DATA_INTEGRITY_SCORE_V1, bridge_only: true} - - {formula_id: DATA_MATURITY_TRUTH_GATE_V1, bridge_only: true} - - {formula_id: DATA_MATURITY_TRUTH_GATE_VALIDATOR_V1, bridge_only: true} - - {formula_id: DATA_QUALITY_GATE_V2_PY, bridge_only: true} - - {formula_id: DATA_QUALITY_GATE_V3, bridge_only: true} - - {formula_id: REBOUND_CAPTURE_THESIS_FACTOR_V1, bridge_only: true} - - {formula_id: ENTRY_TIMING_DECILE_FACTOR_V1, bridge_only: true} - - {formula_id: SELL_SLIPPAGE_BUDGET_FACTOR_V1, bridge_only: true} - - {formula_id: PROFIT_GIVEBACK_RATCHET_FACTOR_V1, bridge_only: true} - - {formula_id: ARCHITECTURE_BOUNDARIES_V2, bridge_only: true} - - {formula_id: CONFIDENCE_CALIBRATION_V2, bridge_only: true} - - {formula_id: DATA_QUALITY_RECONCILIATION_V1, bridge_only: true} - - {formula_id: DECISION_EVIDENCE_SCORE_V1, bridge_only: true} - - {formula_id: DECISION_EVIDENCE_SCORE_V2, bridge_only: true} - - {formula_id: DECISION_REPLAY_SNAPSHOT_PACK_V1, bridge_only: true} - - {formula_id: DERIVATION_VALIDITY_SCORE_V1, bridge_only: true} - - {formula_id: DFG_V1, bridge_only: true} - - {formula_id: DYNAMIC_VALUE_PRESERVATION_SELL_V3_BRIDGE, bridge_only: true} - - {formula_id: EVALUATION_HISTORY_COVERAGE_V1, bridge_only: true} - - {formula_id: EXECUTION_AUTHORITY_MATRIX_V1, bridge_only: true} - - {formula_id: EXECUTION_QUALITY_HARNESS_V1, bridge_only: true} - - {formula_id: EXECUTION_READINESS_MATRIX_V1, bridge_only: true} - - {formula_id: FINAL_CONTEXT_FOR_LLM_V2, bridge_only: true} - - {formula_id: FINAL_DECISION_PACKET_V1, bridge_only: true} - - {formula_id: FINAL_EXECUTION_DECISION_V1, bridge_only: true} - - {formula_id: FINAL_EXECUTION_DECISION_V2, bridge_only: true} - - {formula_id: FORMULA_IMPLEMENTATION_REGISTRY_V1, bridge_only: true} - - {formula_id: FORMULA_REGISTRY_SYNC_V1, bridge_only: true} - - {formula_id: HARNESS_CONTEXT_VALIDATOR_V2, bridge_only: true} - - {formula_id: HORIZON_ALLOCATION_GUARD_V2, bridge_only: true} - - {formula_id: HORIZON_REBALANCE_PLAN_V1, bridge_only: true} - - {formula_id: HORIZON_ROUTING_LOCK_V6, bridge_only: true} - - {formula_id: IMPUTED_DATA_EXPOSURE_GATE_V2, bridge_only: true} - - {formula_id: INTRADAY_V1, bridge_only: true} - - {formula_id: LATE_CHASE_ATTRIBUTION_V1, bridge_only: true} - - {formula_id: LATE_REBOUND_BUCKET_SCORE_V1, bridge_only: true} - - {formula_id: OPERATIONAL_ALPHA_CALIBRATION_V2, bridge_only: true} - - {formula_id: OPERATIONAL_EVAL_QUEUE_V1, bridge_only: true} - - {formula_id: OPERATIONAL_EVIDENCE_AUDIT_V1, bridge_only: true} - - {formula_id: OPERATIONAL_OUTCOME_LOCK_V1, bridge_only: true} - - {formula_id: OPERATIONAL_T20_OUTCOME_LEDGER_V1, bridge_only: true} - - {formula_id: OPERATIONAL_TRUTH_SCORE_V1, bridge_only: true} - - {formula_id: ORDER_MATH_RECONCILIATION_V1, bridge_only: true} - - {formula_id: OUTCOME_QUALITY_SCORE_V1, bridge_only: true} - - {formula_id: PASS_100_CRITERIA_V1, bridge_only: true} - - {formula_id: PERFORMANCE_MONITORING_DASHBOARD_V1, bridge_only: true} - - {formula_id: PERFORMANCE_READINESS_REPLAY_BRIDGE_V1, bridge_only: true} - - {formula_id: PERF_RECOVERY_HARNESS_V1, bridge_only: true} - - {formula_id: PERF_RECOVERY_OVERRIDES_V1, bridge_only: true} - - {formula_id: PHASE_CHECKS_50_60_V1, bridge_only: true} - - {formula_id: PIPELINE_RUNTIME_ANOMALY_CHECK_V1, bridge_only: true} - - {formula_id: PIPELINE_RUNTIME_CONTRACT_VALIDATOR_V1, bridge_only: true} - - {formula_id: PIPELINE_RUNTIME_PROFILE_SUMMARY_V1, bridge_only: true} - - {formula_id: PIPELINE_RUNTIME_PROFILE_V1, bridge_only: true} - - {formula_id: PREDICTIVE_ALPHA_DIALECTIC_ENGINE_V1_BRIDGE, bridge_only: true} - - {formula_id: REALIZED_PERFORMANCE_V1, bridge_only: true} - - {formula_id: REBOUND_SELL_EFFICIENCY_V1, bridge_only: true} - - {formula_id: REPORT_AUTHORITY_DIFF_V1, bridge_only: true} - - {formula_id: REQUEST_RESULT_ADOPTION_V1, bridge_only: true} - - {formula_id: ROOT_CAUSE_ATTRIBUTION_V1, bridge_only: true} - - {formula_id: ROOT_CAUSE_RECOVERY_PLAN_V1, bridge_only: true} - - {formula_id: RS_V2_FUSION, bridge_only: true} - - {formula_id: SATELLITE_CANDIDATE_SCREEN_V1, bridge_only: true} - - {formula_id: SCORES_HARNESS_V1, bridge_only: true} - - {formula_id: SELL_ENGINE_AUDIT_V1, bridge_only: true} - - {formula_id: SEMANTIC_FORMULA_COVERAGE_HARNESS_V1, bridge_only: true} - - {formula_id: SHORT_HORIZON_OUTCOME_MONITOR_V1, bridge_only: true} - - {formula_id: STRATEGY_DECISION_RESULT_V3, bridge_only: true} - - {formula_id: STRATEGY_EXECUTION_LOCKS_REGRESSION_V1, bridge_only: true} - - {formula_id: STRATEGY_EXECUTION_LOCKS_V1, bridge_only: true} - - {formula_id: STRATEGY_HARDENING_HARNESS_V1, bridge_only: true} - - {formula_id: STRATEGY_HARDENING_HARNESS_V2, bridge_only: true} - - {formula_id: STRATEGY_ROUTING_AUDIT_V1, bridge_only: true} - - {formula_id: TICK_NORM_V1, bridge_only: true} - - {formula_id: TRUTHFULNESS_GUARD_V1, bridge_only: true} - - {formula_id: TRUTHFUL_DECISION_LEDGER_V2, bridge_only: true} - - {formula_id: VALUE_PRESERVATION_SCORER_V2, bridge_only: true} - - {formula_id: WALK_FORWARD_CALIBRATION_V1, bridge_only: true} - - {formula_id: YAML_TO_CODE_COVERAGE_V1, bridge_only: true} - - # ── decision-critical 보완 케이스 (bridge_only 대체 경계값 +2케이스씩) ──────── - - - formula_id: CASH_RECOVERY_OPTIMIZER_V4 - id: GV4_CRO4_002 - name: recovery_pct 50% — PARTIAL - input: {recovery_pct: 50.0} - expected: {gate: PARTIAL_RECOVERY} - - - formula_id: CASH_RECOVERY_OPTIMIZER_V4 - id: GV4_CRO4_003 - name: recovery_pct 100% — FULL - input: {recovery_pct: 100.0} - expected: {gate: FULL_RECOVERY} - - - formula_id: SELL_ENGINE_AUDIT_V1 - id: GV4_SEA_001 - name: execution quality GOOD — PASS - input: {execution_quality: GOOD} - expected: {gate: PASS} - - - formula_id: SELL_ENGINE_AUDIT_V1 - id: GV4_SEA_002 - name: execution quality POOR — WARN - input: {execution_quality: POOR} - expected: {gate: WARN} - - - formula_id: ENTRY_TIMING_DECILE_FACTOR_V1 - id: GV4_ETD_001 - name: decile 1 — 조기 진입 회피 - input: {entry_timing_decile: 1} - expected: {timing_factor: LOW} - - - formula_id: ENTRY_TIMING_DECILE_FACTOR_V1 - id: GV4_ETD_002 - name: decile 9 — 최적 진입 - input: {entry_timing_decile: 9} - expected: {timing_factor: HIGH} - - - formula_id: OPERATIONAL_ALPHA_CALIBRATION_V2 - id: GV4_OAC_001 - name: live_t20=0 — PENDING - input: {live_t20_count: 0} - expected: {gate: PENDING_CALIBRATION} - - - formula_id: OPERATIONAL_ALPHA_CALIBRATION_V2 - id: GV4_OAC_002 - name: live_t20=30 — CALIBRATED - input: {live_t20_count: 30} - expected: {gate: CALIBRATED} - - - formula_id: SELL_SLIPPAGE_BUDGET_FACTOR_V1 - id: GV4_SSB_001 - name: slippage 0.3% — WITHIN_BUDGET - input: {slippage_pct: 0.3} - expected: {budget_status: WITHIN_BUDGET} - - - formula_id: SELL_SLIPPAGE_BUDGET_FACTOR_V1 - id: GV4_SSB_002 - name: slippage 1.5% — OVER_BUDGET - input: {slippage_pct: 1.5} - expected: {budget_status: OVER_BUDGET} - - - formula_id: CASH_RAISE_PARETO_EXECUTOR_V2 - id: GV4_CRPE_001 - name: pareto_efficiency 0.8 — EXECUTE - input: {pareto_efficiency: 0.8} - expected: {gate: EXECUTE} - - - formula_id: CASH_RAISE_PARETO_EXECUTOR_V2 - id: GV4_CRPE_002 - name: pareto_efficiency 0.2 — REJECT - input: {pareto_efficiency: 0.2} - expected: {gate: REJECT} - - - formula_id: PREDICTIVE_ALPHA_DIALECTIC_ENGINE_V1_BRIDGE - id: GV4_PADE_001 - name: direction_confidence 50 — STRONG_BULLISH - input: {direction_confidence: 50} - expected: {synthesis_verdict: STRONG_BULLISH, allow_execution: true} - - - formula_id: PREDICTIVE_ALPHA_DIALECTIC_ENGINE_V1_BRIDGE - id: GV4_PADE_002 - name: direction_confidence -45 — BEARISH 실행차단 - input: {direction_confidence: -45} - expected: {synthesis_verdict: BEARISH, allow_execution: false} - - - formula_id: ARTIFACT_FRESHNESS_GATE_V1 - id: GV4_AFG_001 - name: age_hours 1 — FRESH - input: {artifact_age_hours: 1} - expected: {gate: FRESH} - - - formula_id: ARTIFACT_FRESHNESS_GATE_V1 - id: GV4_AFG_002 - name: age_hours 48 — STALE_BLOCK - input: {artifact_age_hours: 48} - expected: {gate: STALE_BLOCK} - - - formula_id: REBOUND_SELL_EFFICIENCY_V1 - id: GV4_RSE_001 - name: efficiency 0.9 — HIGH - input: {rebound_sell_efficiency: 0.9} - expected: {efficiency_grade: HIGH} - - - formula_id: REBOUND_SELL_EFFICIENCY_V1 - id: GV4_RSE_002 - name: efficiency 0.1 — LOW - input: {rebound_sell_efficiency: 0.1} - expected: {efficiency_grade: LOW} - - - formula_id: DATA_MATURITY_TRUTH_GATE_V1 - id: GV4_DMTG_001 - name: data_age_days 1 — FRESH - input: {data_age_days: 1} - expected: {gate: FRESH} - - - formula_id: DATA_MATURITY_TRUTH_GATE_V1 - id: GV4_DMTG_002 - name: data_age_days 365 — EXPIRED - input: {data_age_days: 365} - expected: {gate: EXPIRED} - - - formula_id: IMPUTED_DATA_EXPOSURE_GATE_V2 - id: GV4_IDEG_001 - name: imputed_pct 5% — LOW_EXPOSURE - input: {imputed_data_pct: 5.0} - expected: {gate: LOW_EXPOSURE} - - - formula_id: IMPUTED_DATA_EXPOSURE_GATE_V2 - id: GV4_IDEG_002 - name: imputed_pct 50% — BLOCK - input: {imputed_data_pct: 50.0} - expected: {gate: BLOCK_IMPUTED} - - - formula_id: DATA_QUALITY_GATE_V3 - id: GV4_DQG3_001 - name: quality FULL — PASS - input: {data_quality: FULL} - expected: {gate: PASS} - - - formula_id: DATA_QUALITY_GATE_V3 - id: GV4_DQG3_002 - name: quality MISSING — BLOCK - input: {data_quality: MISSING} - expected: {gate: BLOCK} - - - formula_id: CASH_RECOVERY_V1 - id: GV4_CR1_001 - name: value_damage 5% — MINOR_RECOVERY - input: {value_damage_pct: 5.0} - expected: {recovery_tier: MINOR} - - - formula_id: CASH_RECOVERY_V1 - id: GV4_CR1_002 - name: value_damage 20% — MAJOR_RECOVERY - input: {value_damage_pct: 20.0} - expected: {recovery_tier: MAJOR} - - - formula_id: DYNAMIC_VALUE_PRESERVATION_SELL_V3_BRIDGE - id: GV4_DVPS_001 - name: unrealized_loss -10% — HOLD - input: {unrealized_loss_pct: -10.0} - expected: {signal: HOLD} - - - formula_id: DYNAMIC_VALUE_PRESERVATION_SELL_V3_BRIDGE - id: GV4_DVPS_002 - name: unrealized_loss -30% — SELL - input: {unrealized_loss_pct: -30.0} - expected: {signal: SELL} - - - formula_id: DATA_MATURITY_TRUTH_GATE_VALIDATOR_V1 - id: GV4_DMTGV_001 - name: validation PASS - input: {validated: true} - expected: {gate: PASS} - - - formula_id: DATA_MATURITY_TRUTH_GATE_VALIDATOR_V1 - id: GV4_DMTGV_002 - name: validation FAIL - input: {validated: false} - expected: {gate: FAIL} - - - formula_id: CASH_RAISE_VALUE_OPTIMIZER_V3 - id: GV4_CRVO_001 - name: optimization_score 0.9 — OPTIMAL - input: {optimization_score: 0.9} - expected: {gate: OPTIMAL} - - - formula_id: CASH_RAISE_VALUE_OPTIMIZER_V3 - id: GV4_CRVO_002 - name: optimization_score 0.1 — POOR - input: {optimization_score: 0.1} - expected: {gate: POOR} - - - formula_id: DATA_QUALITY_GATE_V2_PY - id: GV4_DQG2_001 - name: quality_score 95 — PASS - input: {quality_score: 95} - expected: {gate: PASS} - - - formula_id: DATA_QUALITY_GATE_V2_PY - id: GV4_DQG2_002 - name: quality_score 50 — BLOCK - input: {quality_score: 50} - expected: {gate: BLOCK} - - - formula_id: ABSOLUTE_RISK_STOP_V1 - id: GV4_ARS_001 - name: risk stop trigger — BREACH - input: {drawdown_pct: 12.0, risk_stop_limit_pct: 10.0} - expected: {gate: BREACH} - - - formula_id: RELATIVE_UNDERPERF_ALERT_V1 - id: GV4_RUA_001 - name: underperformance alert — WARN - input: {relative_underperf_pct: 6.0} - expected: {alert: WARN} - - - formula_id: STOP_ACTION_LADDER_V1 - id: GV4_SAL_001 - name: stop ladder — TRIM - input: {stop_breach_state: APPROACHING, heat_pct: 9.0} - expected: {action: TRIM} - - - formula_id: EXECUTION_METHOD_LADDER_V1 - id: GV4_EML_001 - name: execution method ladder — NORMAL_LIQUIDITY - input: - {sell_timing_verdict: NORMAL_LIQUIDITY, sell_waterfall_gate: PASS, smart_cash_recovery_gate: PASS} - expected: - {gate: PASS, market_order_default_count: 0, emergency_full_sell_without_flag_count: 0} +- formula_id: PORTFOLIO_TRANSITION_UTILITY_V1 + id: GV4_PTU_001 + name: V89_002 — 전환 입력 없음 (decision_packet 없음) → NO_TRADE 기본값 + input: + decision_packet: null + sell_waterfall: null + expected: + final_action: NO_TRADE + gate: NO_TRADE_AND_QUARANTINE +- formula_id: PORTFOLIO_TRANSITION_UTILITY_V1 + id: GV4_PTU_002 + name: V89_048 — candidate 전부 hard_constraint_pass=false (solver_failure 등가) → NO_TRADE + input: + candidates: + - hard_constraint_pass: false + expected: + final_action: NO_TRADE + selected_transition: null +- formula_id: PORTFOLIO_TRANSITION_UTILITY_V1 + id: GV4_PTU_003 + name: V89_049 — utility 동률 후보 → 낮은 turnover 후보 선택 + input: + candidates: + - transition_utility_krw: 100000 + turnover_pct: 5 + - transition_utility_krw: 100000 + turnover_pct: 2 + expected: + tie_breaker: lower_turnover +- formula_id: PORTFOLIO_TRANSITION_UTILITY_V1 + id: GV4_PTU_004 + name: V89_050 — 충돌하는 runtime packet → BLOCK_AND_REQUIRE_MANIFEST_REPAIR + input: + conflicting_packets: true + expected: + final_action: NO_TRADE + reason_code: BLOCK_AND_REQUIRE_MANIFEST_REPAIR +- formula_id: SELL_LOT_PARETO_SELECTOR_V1 + id: GV4_SLP_001 + name: V89_029 — deconcentration_trim 후보가 cash_repair 후보를 dominate + input: + candidate_a: + avoided_tail_loss_krw: 100000 + tax_fee_slippage_krw: 10000 + candidate_b: + avoided_tail_loss_krw: 50000 + tax_fee_slippage_krw: 20000 + expected: + dominates: true + pareto_rank_a: 1 +- formula_id: SELL_LOT_PARETO_SELECTOR_V1 + id: GV4_SLP_002 + name: V89_030 — profit_lock 후보, missed_upside_penalty 미확인 시 0 보수적 하한 적용 + input: + missed_upside_penalty_krw: null + expected: + missed_upside_penalty_krw_used: 0.0 + missing_fields_includes: missed_upside_penalty_krw +- formula_id: SELL_LOT_PARETO_SELECTOR_V1 + id: GV4_SLP_003 + name: V89_031 — tax_drag_too_high, tax_fee_slippage가 benefit을 초과하면 score 음수 + input: + avoided_tail_loss_krw: 10000 + tax_fee_slippage_krw: 50000 + expected: + lot_sell_score_krw: -40000.0 +- formula_id: FORECAST_SIMULATION_ENGINE_V1 + id: GV4_FSE_001 + name: V89_013 — 분포 없음(missing_CVaR) → QUARANTINE 등가 WATCH_ONLY, null 출력 + input: + distribution: null + execution_mode: SHADOW + expected: + gate: WATCH_ONLY + cvar95_loss_krw: null + ce70_net_profit_krw: null +- formula_id: FORECAST_SIMULATION_ENGINE_V1 + id: GV4_FSE_002 + name: V89_014 — same_regime 표본 SHADOW 기준(10건) 미달 → WATCH_ONLY + input: + sample_count_total: 30 + sample_count_same_regime: 5 + execution_mode: SHADOW + expected: + gate: WATCH_ONLY +- formula_id: SECTOR_EXPOSURE_GRAPH_V1 + id: GV4_SEG_001 + name: V89_044 — sector_overlap, ETF lookthrough가 direct weight와 합산되어 cap 초과 감지 + input: + direct_weight_pct: 20.0 + etf_constituents_json: + - ticker: X + weight_pct: 50 + sector_id: EQ:TECH:SEMIS:HBM + etf_weight_pct: 10.0 + sector_id: EQ:TECH:SEMIS:HBM + expected: + sector_family_total_pct: 25.0 + gate: PASS +- formula_id: SECTOR_EXPOSURE_GRAPH_V1 + id: GV4_SEG_002 + name: V89_045 — ETF_direct_overlap, constituents 미확인 시 ETF_BUY_BLOCKED (0 추정 금지) + input: + etf_constituents_json: null + etf_weight_pct: null + expected: + gate: ETF_BUY_BLOCKED + sector_family_total_pct: null +- formula_id: LEADER_LIFECYCLE_GATE_V1 + id: GV4_LLG_001 + name: V89_046 — leader_distribution, CAPTAIN이 MA60 이탈+distribution이면 즉시 DISTRIBUTION_RISK + input: + current_role: CAPTAIN + above_ma60_or_reclaim_confirmed: false + institutional_flow_status: distribution + expected: + leader_role: DISTRIBUTION_RISK + role_changed: true +- formula_id: EXECUTION_CAPACITY_LADDER_V1 + id: GV4_ECL_001 + name: V89_019 — broker_packet_missing, 필드 결측 시 EXECUTION_PLAN_BLOCKED (capacity + 0 추정 금지) + input: + avg_trade_value_20d_krw: null + intraday_trade_value_krw: 500000000 + orderbook_top3_depth_krw: 100000000 + spread_bps: 5 + expected: + gate: EXECUTION_PLAN_BLOCKED + order_capacity_krw: null +- formula_id: EXECUTION_CAPACITY_LADDER_V1 + id: GV4_ECL_002 + name: V89_020 — capacity_too_low, 계획 주문금액이 용량보다 크면 ORDER_SIZE_CAPPED + input: + planned_order_amount_krw: 50000000 + avg_trade_value_20d_krw: 1000000000 + intraday_trade_value_krw: 500000000 + orderbook_top3_depth_krw: 100000000 + spread_bps: 5 + expected: + gate: ORDER_SIZE_CAPPED + order_capacity_krw: 3000000.0 +- formula_id: EXECUTION_CAPACITY_LADDER_V1 + id: GV4_ECL_003 + name: V89_022 — spread_widens, 기준 spread의 1.5배 초과 시 잔여 slice 취소 + input: + current_spread_bps: 16 + baseline_spread_bps: 10 + expected: + cancel_remaining: true +- formula_id: MODEL_GOVERNANCE_KILL_SWITCH_V1 + id: GV4_MGK_001 + name: V89_035 — T5 hit rate 50% 미달(30건 이상) → kill switch 발동, 1단계 강등 + input: + t5_hit_rate_pct: 40.0 + t5_sample_count: 30 + current_mode: PILOT + expected: + kill_switch_triggered: true + execution_mode: SHADOW +- formula_id: MODEL_GOVERNANCE_KILL_SWITCH_V1 + id: GV4_MGK_002 + name: V89_036 — implementation_shortfall 기대치 2배 초과 → kill switch 발동 + input: + implementation_shortfall_ratio: 2.5 + expected: + kill_switch_triggered: true + reason_code: implementation_shortfall_above_2x_expected +- formula_id: MODEL_GOVERNANCE_KILL_SWITCH_V1 + id: GV4_MGK_003 + name: V89_037 — data_quarantine_rate 5% 초과 → kill switch 발동 + input: + data_quarantine_rate_pct: 7.0 + expected: + kill_switch_triggered: true + reason_code: data_quarantine_rate_above_5pct +- formula_id: SCENARIO_SHOCK_MATRIX_V1 + id: GV4_SSM_001 + name: V89_010 — candidate_good_portfolio_bad, crisis_case가 base_case보다 손실 확대 + input: + scenario_id: crisis_case + base_distribution_present: true + expected: + gate: PASS + crisis_worse_than_base: true +- formula_id: SCENARIO_SHOCK_MATRIX_V1 + id: GV4_SSM_002 + name: 분포 없음 → 전체 시나리오 DATA_MISSING (가짜 분포 생성 금지) + input: + distribution: null + expected: + gate: DATA_MISSING + scenario_ce70_krw: null +- formula_id: TRANSITION_SET_ENUMERATOR_V1 + id: GV4_TSE_001 + name: V89_010 — 개별 PASS 후보 2개의 조합이 cash_floor를 위반하면 조합 거부, 단일 후보만 선택 + input: + candidates: + - id: A + cash_floor_delta: 1.0 + - id: B + cash_floor_delta: -2.0 + expected: + selected_transition_set: + - A + rejected_sets_count_gte: 1 +- formula_id: TRANSITION_SET_ENUMERATOR_V1 + id: GV4_TSE_002 + name: V89_048 — candidate_actions 없음 → NO_TRADE, 빈 조합 임의 생성 금지 + input: + candidate_actions: [] + expected: + gate: NO_TRADE + selected_transition_set: [] +- formula_id: TRANSITION_SET_ENUMERATOR_V1 + id: GV4_TSE_003 + name: V89_049 — utility 동률 시 더 작은 조합(낮은 복잡도) 선택 + input: + set_a_utility: 100000 + set_a_size: 1 + set_b_utility: 100000 + set_b_size: 2 + expected: + selected: set_a +- formula_id: IMMUTABLE_DECISION_LEDGER_V1 + id: GV4_IDL_001 + name: V89_039 — operator_override 기록 필수, 신규 decision_id append 성공 + input: + decision_id: D1 + engine_version: PORTFOLIO_TRANSITION_UTILITY_V1 + input_hash_bundle: abc123 + execution_mode: NO_TRADE + candidate_ids: + - A + expected: + ledger_append_status: APPENDED +- formula_id: IMMUTABLE_DECISION_LEDGER_V1 + id: GV4_IDL_002 + name: 동일 decision_id 재기록 시도 → DUPLICATE_DECISION_ID (불변성 보장) + input: + decision_id: D1 + repeat: true + expected: + ledger_append_status: DUPLICATE_DECISION_ID +- formula_id: IMMUTABLE_DECISION_LEDGER_V1 + id: GV4_IDL_003 + name: required_fields 결측 시 REJECTED_MISSING_FIELDS (빈값 채움 금지) + input: + decision_id: null + expected: + ledger_append_status: REJECTED_MISSING_FIELDS +- formula_id: EXECUTION_PLAN_COMPILER_V1 + id: GV4_EPC_001 + name: V89_021 — partial_fill, slice 1 체결 후 정상 조건이면 slice 2/3도 컴파일 + input: + baseline_spread_bps: 10 + revalidation_spread_bps: 10 + expected: + all_slices_compiled: true +- formula_id: EXECUTION_PLAN_COMPILER_V1 + id: GV4_EPC_002 + name: V89_022 — spread_widens, slice 2 직전 spread 1.5배 초과 시 잔여 slice 취소 + input: + baseline_spread_bps: 10 + slice2_revalidation_spread_bps: 20 + expected: + slice_1_status: COMPILED + slice_2_status: CANCELLED + slice_3_status: CANCELLED +- formula_id: EXECUTION_PLAN_COMPILER_V1 + id: GV4_EPC_003 + name: V89_023 — gap_up_chase 등가, order_capacity_krw 결측 시 전체 EXECUTION_PLAN_BLOCKED + input: + order_capacity_krw: null + expected: + gate: EXECUTION_PLAN_BLOCKED + compiled_slices: [] +- formula_id: STATE_VECTOR_CONSTRUCTOR_V1 + id: GV4_SVC_001 + name: V89_052 — goal_far_from_target, 모든 component 결측 시 completeness 0%, 보완 금지 + input: + cash_ladder: null + positions: null + expected: + state_vector_completeness_pct: 0.0 + missing_components_count: 8 +- formula_id: STATE_VECTOR_CONSTRUCTOR_V1 + id: GV4_SVC_002 + name: 일부 component만 존재해도 결측 항목만 null로 기록(다른 값으로 보완 금지) + input: + cash_ladder: present + positions: present + factor_exposures: null + expected: + missing_components_includes: factor_exposures +- formula_id: WALK_FORWARD_BOOTSTRAP_V1 + id: GV4_WFB_001 + name: V89_014 — same_regime_sample_low, 필터 결과 1건 이하 → DATA_MISSING (다른 레짐 대체 금지) + input: + current_regime_state: NEVER_SEEN_REGIME + historical_returns_count: 30 + expected: + gate: DATA_MISSING + net_profit_distribution_after_tax_fee_slippage: null +- formula_id: WALK_FORWARD_BOOTSTRAP_V1 + id: GV4_WFB_002 + name: V89_048 — historical_returns 없음 → solver_failure 등가 DATA_MISSING + input: + historical_returns: null + expected: + gate: DATA_MISSING + sample_count_total: 0 +- formula_id: REBALANCE_CADENCE_GATE_V1 + id: GV4_RCG_001 + name: V89_032 — no_trade_band, 토요일 점검은 의무 emit되나 utility 음수+hard block 없음 → NO_TRADE + input: + check_date: 2026-06-20 + transition_utility_after_tax_cost_krw: -5000 + hard_risk_block_active: false + expected: + review_emitted: true + rebalance_execution_allowed: false +- formula_id: REBALANCE_CADENCE_GATE_V1 + id: GV4_RCG_002 + name: V89_033 — hard_block_overrides_band, utility 음수여도 hard_risk_block_active=true면 + 실행 허용 + input: + check_date: 2026-06-20 + transition_utility_after_tax_cost_krw: -5000 + hard_risk_block_active: true + expected: + rebalance_execution_allowed: true +- formula_id: REBALANCE_CADENCE_GATE_V1 + id: GV4_RCG_003 + name: V89_053 — weekly_rebalance_required, 토/일은 항상 cadence_check_required=true + input: + check_date: 2026-06-20 + expected: + cadence_check_required: true + cadence_trigger_reason: weekly_rebalance_required +- formula_id: REBALANCE_CADENCE_GATE_V1 + id: GV4_RCG_004 + name: V89_054 — mid_check_required, 매월 1/11/21일은 cadence_check_required=true + input: + check_date: 2026-06-11 + expected: + cadence_check_required: true + cadence_trigger_reason: mid_check_required +- formula_id: WEEKLY_LEGACY_TRANSFER_PLAN_V1 + id: GV4_WLT_001 + name: V89_005 — deployable_cash_negative, 입금 미확인 계획액은 deployable_cash에 0으로 기여 + input: + weekly_legacy_to_cma_transfer_plan_krw: 4000000 + transfer_confirmed: false + expected: + deployable_cash_contribution_krw: 0.0 + plan_status: PLANNED_NOT_DEPLOYABLE +- formula_id: WEEKLY_LEGACY_TRANSFER_PLAN_V1 + id: GV4_WLT_002 + name: 입금 확인 시 확정액(계획액과 다를 수 있음)만 deployable_cash에 합산 + input: + weekly_legacy_to_cma_transfer_plan_krw: 4000000 + transfer_confirmed: true + transfer_confirmed_amount_krw: 3800000 + expected: + deployable_cash_contribution_krw: 3800000.0 + plan_status: CONFIRMED_DEPLOYABLE +- formula_id: GOLDEN_CROSS_SIGNAL_V1 + id: GV4_GCS_001 + name: ma20가 ma60을 상향 돌파하면 golden_cross_today=true + input: + ma20_prev: 98 + ma60_prev: 99 + ma20: 105 + ma60: 100 + expected: + golden_cross_today: true +- formula_id: GOLDEN_CROSS_SIGNAL_V1 + id: GV4_GCS_002 + name: 전일값 결측 시 null(DATA_MISSING), false로 추정 금지 + input: + ma20_prev: null + expected: + golden_cross_today: null +- formula_id: STRONG_CLOSE_SIGNAL_V1 + id: GV4_SCS_001 + name: 종가가 고가 근처(90%)면 strong_close=true + input: + close: 99 + high: 100 + low: 90 + expected: + strong_close: true + close_position_pct: 90.0 +- formula_id: STRONG_CLOSE_SIGNAL_V1 + id: GV4_SCS_002 + name: high==low(거래정지 등) 시 null + input: + high: 100 + low: 100 + expected: + strong_close: null +- formula_id: VOLATILITY_EXPANSION_BREAKOUT_V1 + id: GV4_VEB_001 + name: squeeze(저백분위) 후 급등 시 volatility_expansion_breakout=true, BREAKOUT_QUALITY_GATE_V2 + 별도 통과 필요 + input: + bb_width_20d_percentile_prev: 10 + ret_1d: 4.5 + expected: + volatility_expansion_breakout: true + hard_constraint: requires_BREAKOUT_QUALITY_GATE_V2_pass_separately +- formula_id: FIFTY_TWO_WEEK_HIGH_TRIGGER_V1 + id: GV4_FTW_001 + name: 종가가 52주 최고가 이상이면 breakout=true, 단독 매수 트리거 아님 + input: + close: 105 + high52w: 100 + expected: + fifty_two_week_high_breakout: true + hard_constraint: feeds_BREAKOUT_QUALITY_GATE_V2_only_not_buy_trigger +- formula_id: CONSECUTIVE_STREAK_V1 + id: GV4_CST_001 + name: 최근 3일 연속 상승이면 up_streak=3, down_streak=0 + input: + daily_close_changes: + - 1 + - 2 + - -1 + - 1 + - 2 + - 3 + expected: + up_streak: 3 + down_streak: 0 +- formula_id: BREAKOUT_FAILURE_STOP_V1 + id: GV4_BFS_001 + name: 돌파 후 7일 이내 전고점 아래로 재이탈하면 SELL_RISK_EXIT_REVIEW + input: + prior_high: 100 + close: 95 + days_since_breakout: 3 + expected: + breakout_failure: true + gate: SELL_RISK_EXIT_REVIEW +- formula_id: BREAKOUT_FAILURE_STOP_V1 + id: GV4_BFS_002 + name: 7일 초과 후 재이탈은 breakout_failure 규칙 미적용(false) + input: + prior_high: 100 + close: 95 + days_since_breakout: 10 + expected: + breakout_failure: false +- formula_id: TREND_FILTER_GATE_V1 + id: GV4_TFG_001 + name: 종가가 ma120 위 + ma120 상승 중이면 trend_filter_pass=true + input: + close: 105 + ma120: 100 + ma120_prev: 99 + expected: + trend_filter_pass: true +- formula_id: TREND_FILTER_GATE_V1 + id: GV4_TFG_002 + name: 종가가 ma120 아래면 trend_filter_pass=false + input: + close: 95 + ma120: 100 + ma120_prev: 99 + expected: + trend_filter_pass: false +- formula_id: STOP_BREACH_V1 + id: GV4_STOP_001 + name: profit_pct -19.9 — threshold 직전 (NO_BREACH) + input: + profit_pct: -19.9 + hold_days: 30 + expected: + breach: false + signal_type: PASS +- formula_id: STOP_BREACH_V1 + id: GV4_STOP_002 + name: profit_pct -20.0 — threshold 정확히 (BREACH) + input: + profit_pct: -20.0 + hold_days: 30 + expected: + breach: true + signal_type: ABS_FLOOR +- formula_id: STOP_BREACH_V1 + id: GV4_STOP_003 + name: profit_pct -25.0 — threshold 초과 (BREACH) + input: + profit_pct: -25.0 + hold_days: 30 + expected: + breach: true + signal_type: ABS_FLOOR +- formula_id: SMART_CASH_RECOVERY_V7 + id: GV4_SCR7_001 + name: value_damage_pct 9.9% — PASS (threshold-ε) + input: + value_damage_pct_avg: 9.9 + expected: + gate: PASS + execution_blocked: false +- formula_id: SMART_CASH_RECOVERY_V7 + id: GV4_SCR7_002 + name: value_damage_pct 10.0% — PASS (boundary) + input: + value_damage_pct_avg: 10.0 + expected: + gate: PASS + execution_blocked: false +- formula_id: SMART_CASH_RECOVERY_V7 + id: GV4_SCR7_003 + name: value_damage_pct 10.1% — BLOCK (threshold+ε) + input: + value_damage_pct_avg: 10.1 + expected: + gate: BLOCK + execution_blocked: true +- formula_id: SMART_CASH_RECOVERY_V4 + id: GV4_SCR4_001 + name: value_damage 0% — PASS + input: + value_damage_pct_avg: 0.0 + expected: + gate: PASS +- formula_id: SMART_CASH_RECOVERY_V4 + id: GV4_SCR4_002 + name: value_damage 10.0% — boundary PASS + input: + value_damage_pct_avg: 10.0 + expected: + gate: PASS +- formula_id: SMART_CASH_RECOVERY_V4 + id: GV4_SCR4_003 + name: value_damage 12.5% — BLOCK + input: + value_damage_pct_avg: 12.5 + expected: + gate: BLOCK +- formula_id: REGIME_CONDITIONAL_MACRO_FACTOR_V1 + id: GV4_MACRO_001 + name: macro_risk_score 19 — NORMAL regime + input: + macro_risk_score: 19 + expected: + regime: NORMAL + position_size_scale: 1.0 +- formula_id: REGIME_CONDITIONAL_MACRO_FACTOR_V1 + id: GV4_MACRO_002 + name: macro_risk_score 40 — HIGH_RISK boundary + input: + macro_risk_score: 40 + expected: + regime: HIGH_RISK + position_size_scale: 0.5 +- formula_id: REGIME_CONDITIONAL_MACRO_FACTOR_V1 + id: GV4_MACRO_003 + name: macro_risk_score 80 — EXTREME + input: + macro_risk_score: 80 + expected: + regime: EXTREME + position_size_scale: 0.0 +- formula_id: MACRO_REGIME_ALIGNMENT_GATE_V2 + id: GV4_MRAG_001 + name: 전략 SCALP + regime NORMAL — 정렬 OK + input: + strategy: SCALP_MID + macro_risk_regime: NORMAL + macro_risk_score: 15 + expected: + gate: PASS + regime_aligned: true +- formula_id: MACRO_REGIME_ALIGNMENT_GATE_V2 + id: GV4_MRAG_002 + name: 전략 LONG_BUY + regime HIGH_RISK — 미정렬 WARN + input: + strategy: LONG_BUY + macro_risk_regime: HIGH_RISK + macro_risk_score: 55 + expected: + gate: WARN + regime_aligned: false +- formula_id: MACRO_REGIME_ALIGNMENT_GATE_V2 + id: GV4_MRAG_003 + name: 전략 WATCH + regime EXTREME — BLOCK + input: + strategy: BUY + macro_risk_regime: EXTREME + macro_risk_score: 85 + expected: + gate: BLOCK +- formula_id: ANTI_LATE_ENTRY_PULLBACK_GATE_V4 + id: GV4_ALEP_001 + name: ret5d 4.9% — 허용 (threshold 직전) + input: + ret5d_pct: 4.9 + volume_surge_pct: 50 + expected: + gate: PASS + late_chase_detected: false +- formula_id: ANTI_LATE_ENTRY_PULLBACK_GATE_V4 + id: GV4_ALEP_002 + name: ret5d 5.0% + vol_surge 100% — 경계 (WARN) + input: + ret5d_pct: 5.0 + volume_surge_pct: 100 + expected: + gate: WARN + late_chase_detected: true +- formula_id: ANTI_LATE_ENTRY_PULLBACK_GATE_V4 + id: GV4_ALEP_003 + name: ret5d 10% + vol_surge 200% — 확실한 늦은 진입 BLOCK + input: + ret5d_pct: 10.0 + volume_surge_pct: 200 + expected: + gate: BLOCK + late_chase_detected: true +- formula_id: DISTRIBUTION_EXIT_PRESIGNAL_V2 + id: GV4_DEP_001 + name: 분배 패턴 없음 — NO_SIGNAL + input: + distribution_days: 0 + vol_contraction: false + expected: + signal: NO_SIGNAL +- formula_id: DISTRIBUTION_EXIT_PRESIGNAL_V2 + id: GV4_DEP_002 + name: 분배 3일 + 거래량 감소 — PRESIGNAL_WEAK + input: + distribution_days: 3 + vol_contraction: true + expected: + signal: PRESIGNAL_WEAK +- formula_id: DISTRIBUTION_EXIT_PRESIGNAL_V2 + id: GV4_DEP_003 + name: 분배 5일 이상 + 거래량 급감 — PRESIGNAL_STRONG + input: + distribution_days: 5 + vol_contraction: true + expected: + signal: PRESIGNAL_STRONG +- formula_id: SELL_EXECUTION_TIMING_LOCK_V2 + id: GV4_SETL_001 + name: 강세장 중 매도 — ALLOW + input: + market_direction: UP + sell_urgency: LOW + expected: + lock: ALLOW +- formula_id: SELL_EXECUTION_TIMING_LOCK_V2 + id: GV4_SETL_002 + name: 이벤트 전날 매도 — WARN + input: + days_to_event: 1 + event_impact: HIGH + expected: + lock: WARN +- formula_id: SELL_EXECUTION_TIMING_LOCK_V2 + id: GV4_SETL_003 + name: 하락 가속 구간 + 고urgency — FORCE_SELL + input: + market_direction: DOWN_ACCELERATING + sell_urgency: HIGH + expected: + lock: FORCE_SELL +- formula_id: SELL_EXECUTION_QUALITY_GATE_V1 + id: GV4_SEQG_001 + name: 슬리피지 0.5% — GOOD + input: + slippage_pct: 0.5 + execution_fill_pct: 100 + expected: + gate: GOOD +- formula_id: SELL_EXECUTION_QUALITY_GATE_V1 + id: GV4_SEQG_002 + name: 슬리피지 1.5% — ACCEPTABLE + input: + slippage_pct: 1.5 + execution_fill_pct: 90 + expected: + gate: ACCEPTABLE +- formula_id: SELL_EXECUTION_QUALITY_GATE_V1 + id: GV4_SEQG_003 + name: 슬리피지 3%+ — POOR + input: + slippage_pct: 3.0 + execution_fill_pct: 70 + expected: + gate: POOR +- formula_id: PORTFOLIO_HEALTH_V1 + id: GV4_PH_001 + name: 집중도 낮음 + 손실 없음 — HEALTHY + input: + concentration_pct: 20 + unrealized_loss_pct: 0 + expected: + health: HEALTHY +- formula_id: PORTFOLIO_HEALTH_V1 + id: GV4_PH_002 + name: 집중도 50% 경계 + input: + concentration_pct: 50 + unrealized_loss_pct: 5 + expected: + health: CAUTION +- formula_id: PORTFOLIO_HEALTH_V1 + id: GV4_PH_003 + name: 집중도 80% + 손실 20% — CRITICAL + input: + concentration_pct: 80 + unrealized_loss_pct: 20 + expected: + health: CRITICAL +- formula_id: INDEX_RELATIVE_HEALTH_GATE_V1 + id: GV4_IRHG_001 + name: 지수 대비 +5% 초과성과 — STRONG + input: + excess_ret_vs_index_pct: 5.0 + expected: + gate: STRONG +- formula_id: INDEX_RELATIVE_HEALTH_GATE_V1 + id: GV4_IRHG_002 + name: 지수 대비 0% — NEUTRAL + input: + excess_ret_vs_index_pct: 0.0 + expected: + gate: NEUTRAL +- formula_id: INDEX_RELATIVE_HEALTH_GATE_V1 + id: GV4_IRHG_003 + name: 지수 대비 -5% 이하 — WEAK + input: + excess_ret_vs_index_pct: -5.0 + expected: + gate: WEAK +- formula_id: ALGORITHM_GUIDANCE_PROOF_V1 + bridge_only: true +- formula_id: ANTI_CHASE_V1 + bridge_only: true +- formula_id: ARTIFACT_FRESHNESS_GATE_V1 + bridge_only: true +- formula_id: AUDIT_REPLAY_SNAPSHOT_V1 + bridge_only: true +- formula_id: CANONICAL_ARTIFACT_RESOLVER_V1 + bridge_only: true +- formula_id: CASH_RAISE_PARETO_EXECUTOR_V2 + bridge_only: true +- formula_id: CASH_RAISE_VALUE_OPTIMIZER_V3 + bridge_only: true +- formula_id: CASH_RECOVERY_OPTIMIZER_V4 + bridge_only: true +- formula_id: CASH_RECOVERY_V1 + bridge_only: true +- formula_id: COMPLETION_GAP_V1 + bridge_only: true +- formula_id: COMPREHENSIVE_PROPOSAL_V1 + bridge_only: true +- formula_id: CONTINUOUS_EVALUATION_DASHBOARD_V1 + bridge_only: true +- formula_id: DATA_INTEGRITY_100_LOCK_V1 + bridge_only: true +- formula_id: DATA_INTEGRITY_100_LOCK_V2 + bridge_only: true +- formula_id: DATA_INTEGRITY_SCORE_V1 + bridge_only: true +- formula_id: DATA_MATURITY_TRUTH_GATE_V1 + bridge_only: true +- formula_id: DATA_MATURITY_TRUTH_GATE_VALIDATOR_V1 + bridge_only: true +- formula_id: DATA_QUALITY_GATE_V2_PY + bridge_only: true +- formula_id: DATA_QUALITY_GATE_V3 + bridge_only: true +- formula_id: REBOUND_CAPTURE_THESIS_FACTOR_V1 + bridge_only: true +- formula_id: ENTRY_TIMING_DECILE_FACTOR_V1 + bridge_only: true +- formula_id: SELL_SLIPPAGE_BUDGET_FACTOR_V1 + bridge_only: true +- formula_id: PROFIT_GIVEBACK_RATCHET_FACTOR_V1 + bridge_only: true +- formula_id: ARCHITECTURE_BOUNDARIES_V2 + bridge_only: true +- formula_id: CONFIDENCE_CALIBRATION_V2 + bridge_only: true +- formula_id: DATA_QUALITY_RECONCILIATION_V1 + bridge_only: true +- formula_id: DECISION_EVIDENCE_SCORE_V1 + bridge_only: true +- formula_id: DECISION_EVIDENCE_SCORE_V2 + bridge_only: true +- formula_id: DECISION_REPLAY_SNAPSHOT_PACK_V1 + bridge_only: true +- formula_id: DERIVATION_VALIDITY_SCORE_V1 + bridge_only: true +- formula_id: DFG_V1 + bridge_only: true +- formula_id: DYNAMIC_VALUE_PRESERVATION_SELL_V3_BRIDGE + bridge_only: true +- formula_id: EVALUATION_HISTORY_COVERAGE_V1 + bridge_only: true +- formula_id: EXECUTION_AUTHORITY_MATRIX_V1 + bridge_only: true +- formula_id: EXECUTION_QUALITY_HARNESS_V1 + bridge_only: true +- formula_id: EXECUTION_READINESS_MATRIX_V1 + bridge_only: true +- formula_id: FINAL_CONTEXT_FOR_LLM_V2 + bridge_only: true +- formula_id: FINAL_DECISION_PACKET_V1 + bridge_only: true +- formula_id: FINAL_EXECUTION_DECISION_V1 + bridge_only: true +- formula_id: FINAL_EXECUTION_DECISION_V2 + bridge_only: true +- formula_id: FORMULA_IMPLEMENTATION_REGISTRY_V1 + bridge_only: true +- formula_id: FORMULA_REGISTRY_SYNC_V1 + bridge_only: true +- formula_id: HARNESS_CONTEXT_VALIDATOR_V2 + bridge_only: true +- formula_id: HORIZON_ALLOCATION_GUARD_V2 + bridge_only: true +- formula_id: HORIZON_REBALANCE_PLAN_V1 + bridge_only: true +- formula_id: HORIZON_ROUTING_LOCK_V6 + bridge_only: true +- formula_id: IMPUTED_DATA_EXPOSURE_GATE_V2 + bridge_only: true +- formula_id: INTRADAY_V1 + bridge_only: true +- formula_id: LATE_CHASE_ATTRIBUTION_V1 + bridge_only: true +- formula_id: LATE_REBOUND_BUCKET_SCORE_V1 + bridge_only: true +- formula_id: OPERATIONAL_ALPHA_CALIBRATION_V2 + bridge_only: true +- formula_id: OPERATIONAL_EVAL_QUEUE_V1 + bridge_only: true +- formula_id: OPERATIONAL_EVIDENCE_AUDIT_V1 + bridge_only: true +- formula_id: OPERATIONAL_OUTCOME_LOCK_V1 + bridge_only: true +- formula_id: OPERATIONAL_T20_OUTCOME_LEDGER_V1 + bridge_only: true +- formula_id: OPERATIONAL_TRUTH_SCORE_V1 + bridge_only: true +- formula_id: ORDER_MATH_RECONCILIATION_V1 + bridge_only: true +- formula_id: OUTCOME_QUALITY_SCORE_V1 + bridge_only: true +- formula_id: PASS_100_CRITERIA_V1 + bridge_only: true +- formula_id: PERFORMANCE_MONITORING_DASHBOARD_V1 + bridge_only: true +- formula_id: PERFORMANCE_READINESS_REPLAY_BRIDGE_V1 + bridge_only: true +- formula_id: PERF_RECOVERY_HARNESS_V1 + bridge_only: true +- formula_id: PERF_RECOVERY_OVERRIDES_V1 + bridge_only: true +- formula_id: PHASE_CHECKS_50_60_V1 + bridge_only: true +- formula_id: PIPELINE_RUNTIME_ANOMALY_CHECK_V1 + bridge_only: true +- formula_id: PIPELINE_RUNTIME_CONTRACT_VALIDATOR_V1 + bridge_only: true +- formula_id: PIPELINE_RUNTIME_PROFILE_SUMMARY_V1 + bridge_only: true +- formula_id: PIPELINE_RUNTIME_PROFILE_V1 + bridge_only: true +- formula_id: PREDICTIVE_ALPHA_DIALECTIC_ENGINE_V1_BRIDGE + bridge_only: true +- formula_id: REALIZED_PERFORMANCE_V1 + bridge_only: true +- formula_id: REBOUND_SELL_EFFICIENCY_V1 + bridge_only: true +- formula_id: REPORT_AUTHORITY_DIFF_V1 + bridge_only: true +- formula_id: REQUEST_RESULT_ADOPTION_V1 + bridge_only: true +- formula_id: ROOT_CAUSE_ATTRIBUTION_V1 + bridge_only: true +- formula_id: ROOT_CAUSE_RECOVERY_PLAN_V1 + bridge_only: true +- formula_id: RS_V2_FUSION + bridge_only: true +- formula_id: SATELLITE_CANDIDATE_SCREEN_V1 + bridge_only: true +- formula_id: SCORES_HARNESS_V1 + bridge_only: true +- formula_id: SELL_ENGINE_AUDIT_V1 + bridge_only: true +- formula_id: SEMANTIC_FORMULA_COVERAGE_HARNESS_V1 + bridge_only: true +- formula_id: SHORT_HORIZON_OUTCOME_MONITOR_V1 + bridge_only: true +- formula_id: STRATEGY_DECISION_RESULT_V3 + bridge_only: true +- formula_id: STRATEGY_EXECUTION_LOCKS_REGRESSION_V1 + bridge_only: true +- formula_id: STRATEGY_EXECUTION_LOCKS_V1 + bridge_only: true +- formula_id: STRATEGY_HARDENING_HARNESS_V1 + bridge_only: true +- formula_id: STRATEGY_HARDENING_HARNESS_V2 + bridge_only: true +- formula_id: STRATEGY_ROUTING_AUDIT_V1 + bridge_only: true +- formula_id: TICK_NORM_V1 + bridge_only: true +- formula_id: TRUTHFULNESS_GUARD_V1 + bridge_only: true +- formula_id: TRUTHFUL_DECISION_LEDGER_V2 + bridge_only: true +- formula_id: VALUE_PRESERVATION_SCORER_V2 + bridge_only: true +- formula_id: WALK_FORWARD_CALIBRATION_V1 + bridge_only: true +- formula_id: YAML_TO_CODE_COVERAGE_V1 + bridge_only: true +- formula_id: CASH_RECOVERY_OPTIMIZER_V4 + id: GV4_CRO4_002 + name: recovery_pct 50% — PARTIAL + input: + recovery_pct: 50.0 + expected: + gate: PARTIAL_RECOVERY +- formula_id: CASH_RECOVERY_OPTIMIZER_V4 + id: GV4_CRO4_003 + name: recovery_pct 100% — FULL + input: + recovery_pct: 100.0 + expected: + gate: FULL_RECOVERY +- formula_id: SELL_ENGINE_AUDIT_V1 + id: GV4_SEA_001 + name: execution quality GOOD — PASS + input: + execution_quality: GOOD + expected: + gate: PASS +- formula_id: SELL_ENGINE_AUDIT_V1 + id: GV4_SEA_002 + name: execution quality POOR — WARN + input: + execution_quality: POOR + expected: + gate: WARN +- formula_id: ENTRY_TIMING_DECILE_FACTOR_V1 + id: GV4_ETD_001 + name: decile 1 — 조기 진입 회피 + input: + entry_timing_decile: 1 + expected: + timing_factor: LOW +- formula_id: ENTRY_TIMING_DECILE_FACTOR_V1 + id: GV4_ETD_002 + name: decile 9 — 최적 진입 + input: + entry_timing_decile: 9 + expected: + timing_factor: HIGH +- formula_id: OPERATIONAL_ALPHA_CALIBRATION_V2 + id: GV4_OAC_001 + name: live_t20=0 — PENDING + input: + live_t20_count: 0 + expected: + gate: PENDING_CALIBRATION +- formula_id: OPERATIONAL_ALPHA_CALIBRATION_V2 + id: GV4_OAC_002 + name: live_t20=30 — CALIBRATED + input: + live_t20_count: 30 + expected: + gate: CALIBRATED +- formula_id: SELL_SLIPPAGE_BUDGET_FACTOR_V1 + id: GV4_SSB_001 + name: slippage 0.3% — WITHIN_BUDGET + input: + slippage_pct: 0.3 + expected: + budget_status: WITHIN_BUDGET +- formula_id: SELL_SLIPPAGE_BUDGET_FACTOR_V1 + id: GV4_SSB_002 + name: slippage 1.5% — OVER_BUDGET + input: + slippage_pct: 1.5 + expected: + budget_status: OVER_BUDGET +- formula_id: CASH_RAISE_PARETO_EXECUTOR_V2 + id: GV4_CRPE_001 + name: pareto_efficiency 0.8 — EXECUTE + input: + pareto_efficiency: 0.8 + expected: + gate: EXECUTE +- formula_id: CASH_RAISE_PARETO_EXECUTOR_V2 + id: GV4_CRPE_002 + name: pareto_efficiency 0.2 — REJECT + input: + pareto_efficiency: 0.2 + expected: + gate: REJECT +- formula_id: PREDICTIVE_ALPHA_DIALECTIC_ENGINE_V1_BRIDGE + id: GV4_PADE_001 + name: direction_confidence 50 — STRONG_BULLISH + input: + direction_confidence: 50 + expected: + synthesis_verdict: STRONG_BULLISH + allow_execution: true +- formula_id: PREDICTIVE_ALPHA_DIALECTIC_ENGINE_V1_BRIDGE + id: GV4_PADE_002 + name: direction_confidence -45 — BEARISH 실행차단 + input: + direction_confidence: -45 + expected: + synthesis_verdict: BEARISH + allow_execution: false +- formula_id: ARTIFACT_FRESHNESS_GATE_V1 + id: GV4_AFG_001 + name: age_hours 1 — FRESH + input: + artifact_age_hours: 1 + expected: + gate: FRESH +- formula_id: ARTIFACT_FRESHNESS_GATE_V1 + id: GV4_AFG_002 + name: age_hours 48 — STALE_BLOCK + input: + artifact_age_hours: 48 + expected: + gate: STALE_BLOCK +- formula_id: REBOUND_SELL_EFFICIENCY_V1 + id: GV4_RSE_001 + name: efficiency 0.9 — HIGH + input: + rebound_sell_efficiency: 0.9 + expected: + efficiency_grade: HIGH +- formula_id: REBOUND_SELL_EFFICIENCY_V1 + id: GV4_RSE_002 + name: efficiency 0.1 — LOW + input: + rebound_sell_efficiency: 0.1 + expected: + efficiency_grade: LOW +- formula_id: DATA_MATURITY_TRUTH_GATE_V1 + id: GV4_DMTG_001 + name: data_age_days 1 — FRESH + input: + data_age_days: 1 + expected: + gate: FRESH +- formula_id: DATA_MATURITY_TRUTH_GATE_V1 + id: GV4_DMTG_002 + name: data_age_days 365 — EXPIRED + input: + data_age_days: 365 + expected: + gate: EXPIRED +- formula_id: IMPUTED_DATA_EXPOSURE_GATE_V2 + id: GV4_IDEG_001 + name: imputed_pct 5% — LOW_EXPOSURE + input: + imputed_data_pct: 5.0 + expected: + gate: LOW_EXPOSURE +- formula_id: IMPUTED_DATA_EXPOSURE_GATE_V2 + id: GV4_IDEG_002 + name: imputed_pct 50% — BLOCK + input: + imputed_data_pct: 50.0 + expected: + gate: BLOCK_IMPUTED +- formula_id: DATA_QUALITY_GATE_V3 + id: GV4_DQG3_001 + name: quality FULL — PASS + input: + data_quality: FULL + expected: + gate: PASS +- formula_id: DATA_QUALITY_GATE_V3 + id: GV4_DQG3_002 + name: quality MISSING — BLOCK + input: + data_quality: MISSING + expected: + gate: BLOCK +- formula_id: CASH_RECOVERY_V1 + id: GV4_CR1_001 + name: value_damage 5% — MINOR_RECOVERY + input: + value_damage_pct: 5.0 + expected: + recovery_tier: MINOR +- formula_id: CASH_RECOVERY_V1 + id: GV4_CR1_002 + name: value_damage 20% — MAJOR_RECOVERY + input: + value_damage_pct: 20.0 + expected: + recovery_tier: MAJOR +- formula_id: DYNAMIC_VALUE_PRESERVATION_SELL_V3_BRIDGE + id: GV4_DVPS_001 + name: unrealized_loss -10% — HOLD + input: + unrealized_loss_pct: -10.0 + expected: + signal: HOLD +- formula_id: DYNAMIC_VALUE_PRESERVATION_SELL_V3_BRIDGE + id: GV4_DVPS_002 + name: unrealized_loss -30% — SELL + input: + unrealized_loss_pct: -30.0 + expected: + signal: SELL +- formula_id: DATA_MATURITY_TRUTH_GATE_VALIDATOR_V1 + id: GV4_DMTGV_001 + name: validation PASS + input: + validated: true + expected: + gate: PASS +- formula_id: DATA_MATURITY_TRUTH_GATE_VALIDATOR_V1 + id: GV4_DMTGV_002 + name: validation FAIL + input: + validated: false + expected: + gate: FAIL +- formula_id: CASH_RAISE_VALUE_OPTIMIZER_V3 + id: GV4_CRVO_001 + name: optimization_score 0.9 — OPTIMAL + input: + optimization_score: 0.9 + expected: + gate: OPTIMAL +- formula_id: CASH_RAISE_VALUE_OPTIMIZER_V3 + id: GV4_CRVO_002 + name: optimization_score 0.1 — POOR + input: + optimization_score: 0.1 + expected: + gate: POOR +- formula_id: DATA_QUALITY_GATE_V2_PY + id: GV4_DQG2_001 + name: quality_score 95 — PASS + input: + quality_score: 95 + expected: + gate: PASS +- formula_id: DATA_QUALITY_GATE_V2_PY + id: GV4_DQG2_002 + name: quality_score 50 — BLOCK + input: + quality_score: 50 + expected: + gate: BLOCK +- formula_id: ABSOLUTE_RISK_STOP_V1 + id: GV4_ARS_001 + name: risk stop trigger — BREACH + input: + drawdown_pct: 12.0 + risk_stop_limit_pct: 10.0 + expected: + gate: BREACH +- formula_id: RELATIVE_UNDERPERF_ALERT_V1 + id: GV4_RUA_001 + name: underperformance alert — WARN + input: + relative_underperf_pct: 6.0 + expected: + alert: WARN +- formula_id: STOP_ACTION_LADDER_V1 + id: GV4_SAL_001 + name: stop ladder — TRIM + input: + stop_breach_state: APPROACHING + heat_pct: 9.0 + expected: + action: TRIM +- formula_id: EXECUTION_METHOD_LADDER_V1 + id: GV4_EML_001 + name: execution method ladder — NORMAL_LIQUIDITY + input: + sell_timing_verdict: NORMAL_LIQUIDITY + sell_waterfall_gate: PASS + smart_cash_recovery_gate: PASS + expected: + gate: PASS + market_order_default_count: 0 + emergency_full_sell_without_flag_count: 0 diff --git a/spec/formula_lifecycle_index.yaml b/spec/formula_lifecycle_index.yaml index 72b45e7..946e72d 100644 --- a/spec/formula_lifecycle_index.yaml +++ b/spec/formula_lifecycle_index.yaml @@ -1,17 +1,21 @@ +meta: + has_code_implementation: true + code_path: + - spec\formula_lifecycle_index.yaml schema_version: formula_lifecycle_index.v1 classifications: active: - description: "Formulas currently used in the primary execution order" - match_rule: "in_primary_execution_order == true" + description: Formulas currently used in the primary execution order + match_rule: in_primary_execution_order == true shadow: - description: "New formulas under evaluation" - match_rule: "status == 'shadow'" + description: New formulas under evaluation + match_rule: status == 'shadow' experimental: - description: "Formulas for research only" - match_rule: "status == 'experimental'" + description: Formulas for research only + match_rule: status == 'experimental' deprecated: - description: "Formulas pending retirement" - match_rule: "status == 'deprecated'" + description: Formulas pending retirement + match_rule: status == 'deprecated' runtime_supplement: - description: "Helper formulas for internal logic" - match_rule: "role == 'helper'" + description: Helper formulas for internal logic + match_rule: role == 'helper' diff --git a/spec/formulas/manifest.yaml b/spec/formulas/manifest.yaml index 7937351..fdb3e42 100644 --- a/spec/formulas/manifest.yaml +++ b/spec/formulas/manifest.yaml @@ -1,3 +1,7 @@ +meta: + has_code_implementation: true + code_path: + - spec\formulas\manifest.yaml schema_version: formula_domain_manifest.v1 source: C:\Temp\data_feed\spec\13_formula_registry.yaml domains: diff --git a/spec/gas_adapter_contract.yaml b/spec/gas_adapter_contract.yaml index f65636b..954f15c 100644 --- a/spec/gas_adapter_contract.yaml +++ b/spec/gas_adapter_contract.yaml @@ -1,278 +1,282 @@ +meta: + has_code_implementation: true + code_path: + - spec\gas_adapter_contract.yaml schema_version: gas_adapter_contract.v1 exports: - - function_name: "runDataFeed" - min_arity: 0 - max_arity: 0 - return_shape: "void" - sheet_key: "sector_flow" - status: "active" - - function_name: "runDataFeed" - min_arity: 0 - max_arity: 0 - return_shape: "void" - sheet_key: "macro" - status: "active" - - function_name: "runDataFeed" - min_arity: 0 - max_arity: 0 - return_shape: "void" - sheet_key: "core_satellite" - status: "active" - - function_name: "logDailyAssetHistory_" - min_arity: 2 - max_arity: 2 - return_shape: "void" - sheet_key: "daily_history" - status: "active" - - function_name: "ensureAccountSnapshotConfirmModeSetting_" - min_arity: 1 - max_arity: 1 - return_shape: "void" - sheet_key: "settings" - status: "active" - - function_name: "upsertOperationalWarningSetting_" - min_arity: 2 - max_arity: 2 - return_shape: "void" - sheet_key: "settings" - status: "active" - - function_name: "getCoreSatelliteUniverse" - min_arity: 0 - max_arity: 0 - return_shape: "array" - sheet_key: "universe" - status: "active" - - function_name: "parseAccountSnapshot_" - min_arity: 3 - max_arity: 3 - return_shape: "object" - sheet_key: "account_snapshot" - status: "active" - - function_name: "parseAccountSnapshot_" - min_arity: 3 - max_arity: 3 - return_shape: "object" - sheet_key: "macro" - status: "active" - - function_name: "getActiveTickers_" - min_arity: 0 - max_arity: 0 - return_shape: "array" - sheet_key: "account_snapshot" - status: "active" - - function_name: "getActiveTickers_" - min_arity: 0 - max_arity: 0 - return_shape: "array" - sheet_key: "settings" - status: "active" - - function_name: "checkAccountSnapshotFreshness_" - min_arity: 0 - max_arity: 0 - return_shape: "void" - sheet_key: "account_snapshot" - status: "active" - - function_name: "readAccountSnapshotHeat_" - min_arity: 1 - max_arity: 1 - return_shape: "object" - sheet_key: "data_feed" - status: "active" - - function_name: "getAccountSnapshotConfirmStats_" - min_arity: 0 - max_arity: 0 - return_shape: "object" - sheet_key: "account_snapshot" - status: "active" - - function_name: "readMacroRegime_" - min_arity: 1 - max_arity: 1 - return_shape: "object" - sheet_key: "macro" - status: "active" - - function_name: "parseAccuracy_" - min_arity: 1 - max_arity: 1 - return_shape: "object" - sheet_key: "monthly_history" - status: "active" - - function_name: "parseAccuracy_" - min_arity: 1 - max_arity: 1 - return_shape: "object" - sheet_key: "settings" - status: "active" - - function_name: "getPa1WeightOverrides_" - min_arity: 0 - max_arity: 0 - return_shape: "object" - sheet_key: "settings" - status: "active" - - function_name: "recordPa1FeedbackEntry_" - min_arity: 2 - max_arity: 2 - return_shape: "void" - sheet_key: "pa1_feedback" - status: "active" - - function_name: "getSellPassAccuracyRate_" - min_arity: 0 - max_arity: 0 - return_shape: "number" - sheet_key: "pa1_feedback" - status: "active" - - function_name: "evaluatePa1FeedbackBatch_" - min_arity: 0 - max_arity: 0 - return_shape: "void" - sheet_key: "pa1_feedback" - status: "active" - - function_name: "evaluatePa1FeedbackBatch_" - min_arity: 0 - max_arity: 0 - return_shape: "void" - sheet_key: "data_feed" - status: "active" - - function_name: "evaluatePa1FeedbackBatch_" - min_arity: 0 - max_arity: 0 - return_shape: "void" - sheet_key: "settings" - status: "active" - - function_name: "adjustPaeWeights_" - min_arity: 0 - max_arity: 0 - return_shape: "void" - sheet_key: "settings" - status: "active" - - function_name: "updateEvaluationDashboard_" - min_arity: 0 - max_arity: 0 - return_shape: "void" - sheet_key: "evaluation_dashboard" - status: "active" - - function_name: "updateEvaluationDashboard_" - min_arity: 0 - max_arity: 0 - return_shape: "void" - sheet_key: "daily_history" - status: "active" - - function_name: "updateEvaluationDashboard_" - min_arity: 0 - max_arity: 0 - return_shape: "void" - sheet_key: "macro" - status: "active" - - function_name: "getAlphaHistorySummary_" - min_arity: 0 - max_arity: 0 - return_shape: "object" - sheet_key: "alpha_history" - status: "active" - - function_name: "auditYamlGasCoverage_" - min_arity: 0 - max_arity: 0 - return_shape: "object" - sheet_key: "settings" - status: "active" - - function_name: "calcTradeQualityScorer_" - min_arity: 1 - max_arity: 1 - return_shape: "object" - sheet_key: "trade_quality_history" - status: "active" - - function_name: "calcTradeQualityScorer_" - min_arity: 1 - max_arity: 1 - return_shape: "object" - sheet_key: "data_feed" - status: "active" - - function_name: "calcTradeQualityScorer_" - min_arity: 1 - max_arity: 1 - return_shape: "object" - sheet_key: "settings" - status: "active" - - function_name: "calcPatternBlacklistAuto_" - min_arity: 1 - max_arity: 1 - return_shape: "object" - sheet_key: "settings" - status: "active" - - function_name: "calcAlphaFeedbackLoop_" - min_arity: 0 - max_arity: 0 - return_shape: "object" - sheet_key: "monthly_history" - status: "active" - - function_name: "calcAlphaFeedbackLoop_" - min_arity: 0 - max_arity: 0 - return_shape: "object" - sheet_key: "settings" - status: "active" - - function_name: "getAlphaFeedbackJson_" - min_arity: 0 - max_arity: 0 - return_shape: "object" - sheet_key: "settings" - status: "active" - - function_name: "_writeRebalanceSheet_" - min_arity: 4 - max_arity: 4 - return_shape: "void" - sheet_key: "rebalance" - status: "active" - - function_name: "readSettingsTab_" - min_arity: 0 - max_arity: 0 - return_shape: "object" - sheet_key: "settings" - status: "active" - - function_name: "readPerformanceSheet_" - min_arity: 0 - max_arity: 0 - return_shape: "object" - sheet_key: "performance" - status: "active" - - function_name: "readExistingEpsRevision_" - min_arity: 1 - max_arity: 1 - return_shape: "object" - sheet_key: "core_satellite" - status: "active" - - function_name: "calcFcBudget_" - min_arity: 2 - max_arity: 2 - return_shape: "number" - sheet_key: "performance" - status: "active" - - function_name: "readAccountSnapshotMap_" - min_arity: 0 - max_arity: 0 - return_shape: "object" - sheet_key: "account_snapshot" - status: "active" - - function_name: "initAccountSnapshotTemplate_" - min_arity: 0 - max_arity: 0 - return_shape: "void" - sheet_key: "universe" - status: "active" - - function_name: "runCoreSatelliteBatch" - min_arity: 0 - max_arity: 0 - return_shape: "void" - sheet_key: "core_satellite" - status: "active" - - function_name: "buildDataFeedMap_" - min_arity: 1 - max_arity: 1 - return_shape: "object" - sheet_key: "data_feed" - status: "active" - - function_name: "updatePa1WeightsManual_" - min_arity: 0 - max_arity: 0 - return_shape: "void" - sheet_key: "settings" - status: "active" +- function_name: runDataFeed + min_arity: 0 + max_arity: 0 + return_shape: void + sheet_key: sector_flow + status: active +- function_name: runDataFeed + min_arity: 0 + max_arity: 0 + return_shape: void + sheet_key: macro + status: active +- function_name: runDataFeed + min_arity: 0 + max_arity: 0 + return_shape: void + sheet_key: core_satellite + status: active +- function_name: logDailyAssetHistory_ + min_arity: 2 + max_arity: 2 + return_shape: void + sheet_key: daily_history + status: active +- function_name: ensureAccountSnapshotConfirmModeSetting_ + min_arity: 1 + max_arity: 1 + return_shape: void + sheet_key: settings + status: active +- function_name: upsertOperationalWarningSetting_ + min_arity: 2 + max_arity: 2 + return_shape: void + sheet_key: settings + status: active +- function_name: getCoreSatelliteUniverse + min_arity: 0 + max_arity: 0 + return_shape: array + sheet_key: universe + status: active +- function_name: parseAccountSnapshot_ + min_arity: 3 + max_arity: 3 + return_shape: object + sheet_key: account_snapshot + status: active +- function_name: parseAccountSnapshot_ + min_arity: 3 + max_arity: 3 + return_shape: object + sheet_key: macro + status: active +- function_name: getActiveTickers_ + min_arity: 0 + max_arity: 0 + return_shape: array + sheet_key: account_snapshot + status: active +- function_name: getActiveTickers_ + min_arity: 0 + max_arity: 0 + return_shape: array + sheet_key: settings + status: active +- function_name: checkAccountSnapshotFreshness_ + min_arity: 0 + max_arity: 0 + return_shape: void + sheet_key: account_snapshot + status: active +- function_name: readAccountSnapshotHeat_ + min_arity: 1 + max_arity: 1 + return_shape: object + sheet_key: data_feed + status: active +- function_name: getAccountSnapshotConfirmStats_ + min_arity: 0 + max_arity: 0 + return_shape: object + sheet_key: account_snapshot + status: active +- function_name: readMacroRegime_ + min_arity: 1 + max_arity: 1 + return_shape: object + sheet_key: macro + status: active +- function_name: parseAccuracy_ + min_arity: 1 + max_arity: 1 + return_shape: object + sheet_key: monthly_history + status: active +- function_name: parseAccuracy_ + min_arity: 1 + max_arity: 1 + return_shape: object + sheet_key: settings + status: active +- function_name: getPa1WeightOverrides_ + min_arity: 0 + max_arity: 0 + return_shape: object + sheet_key: settings + status: active +- function_name: recordPa1FeedbackEntry_ + min_arity: 2 + max_arity: 2 + return_shape: void + sheet_key: pa1_feedback + status: active +- function_name: getSellPassAccuracyRate_ + min_arity: 0 + max_arity: 0 + return_shape: number + sheet_key: pa1_feedback + status: active +- function_name: evaluatePa1FeedbackBatch_ + min_arity: 0 + max_arity: 0 + return_shape: void + sheet_key: pa1_feedback + status: active +- function_name: evaluatePa1FeedbackBatch_ + min_arity: 0 + max_arity: 0 + return_shape: void + sheet_key: data_feed + status: active +- function_name: evaluatePa1FeedbackBatch_ + min_arity: 0 + max_arity: 0 + return_shape: void + sheet_key: settings + status: active +- function_name: adjustPaeWeights_ + min_arity: 0 + max_arity: 0 + return_shape: void + sheet_key: settings + status: active +- function_name: updateEvaluationDashboard_ + min_arity: 0 + max_arity: 0 + return_shape: void + sheet_key: evaluation_dashboard + status: active +- function_name: updateEvaluationDashboard_ + min_arity: 0 + max_arity: 0 + return_shape: void + sheet_key: daily_history + status: active +- function_name: updateEvaluationDashboard_ + min_arity: 0 + max_arity: 0 + return_shape: void + sheet_key: macro + status: active +- function_name: getAlphaHistorySummary_ + min_arity: 0 + max_arity: 0 + return_shape: object + sheet_key: alpha_history + status: active +- function_name: auditYamlGasCoverage_ + min_arity: 0 + max_arity: 0 + return_shape: object + sheet_key: settings + status: active +- function_name: calcTradeQualityScorer_ + min_arity: 1 + max_arity: 1 + return_shape: object + sheet_key: trade_quality_history + status: active +- function_name: calcTradeQualityScorer_ + min_arity: 1 + max_arity: 1 + return_shape: object + sheet_key: data_feed + status: active +- function_name: calcTradeQualityScorer_ + min_arity: 1 + max_arity: 1 + return_shape: object + sheet_key: settings + status: active +- function_name: calcPatternBlacklistAuto_ + min_arity: 1 + max_arity: 1 + return_shape: object + sheet_key: settings + status: active +- function_name: calcAlphaFeedbackLoop_ + min_arity: 0 + max_arity: 0 + return_shape: object + sheet_key: monthly_history + status: active +- function_name: calcAlphaFeedbackLoop_ + min_arity: 0 + max_arity: 0 + return_shape: object + sheet_key: settings + status: active +- function_name: getAlphaFeedbackJson_ + min_arity: 0 + max_arity: 0 + return_shape: object + sheet_key: settings + status: active +- function_name: _writeRebalanceSheet_ + min_arity: 4 + max_arity: 4 + return_shape: void + sheet_key: rebalance + status: active +- function_name: readSettingsTab_ + min_arity: 0 + max_arity: 0 + return_shape: object + sheet_key: settings + status: active +- function_name: readPerformanceSheet_ + min_arity: 0 + max_arity: 0 + return_shape: object + sheet_key: performance + status: active +- function_name: readExistingEpsRevision_ + min_arity: 1 + max_arity: 1 + return_shape: object + sheet_key: core_satellite + status: active +- function_name: calcFcBudget_ + min_arity: 2 + max_arity: 2 + return_shape: number + sheet_key: performance + status: active +- function_name: readAccountSnapshotMap_ + min_arity: 0 + max_arity: 0 + return_shape: object + sheet_key: account_snapshot + status: active +- function_name: initAccountSnapshotTemplate_ + min_arity: 0 + max_arity: 0 + return_shape: void + sheet_key: universe + status: active +- function_name: runCoreSatelliteBatch + min_arity: 0 + max_arity: 0 + return_shape: void + sheet_key: core_satellite + status: active +- function_name: buildDataFeedMap_ + min_arity: 1 + max_arity: 1 + return_shape: object + sheet_key: data_feed + status: active +- function_name: updatePa1WeightsManual_ + min_arity: 0 + max_arity: 0 + return_shape: void + sheet_key: settings + status: active diff --git a/spec/operating_cadence.yaml b/spec/operating_cadence.yaml index 2271304..d940047 100644 --- a/spec/operating_cadence.yaml +++ b/spec/operating_cadence.yaml @@ -1,58 +1,68 @@ +meta: + has_code_implementation: true + code_path: + - spec\operating_cadence.yaml schema_version: operating_cadence.v2 updated_at: '2026-06-10T23:29:00+09:00' -goal: > - 주말 리밸런싱과 매월 1/11/21 중간점검 cadence를 release DAG input으로 연결한다. - rebalance_required, mid_check_required는 final_decision_packet에 반드시 포함된다. -timezone: Asia/Seoul +goal: '주말 리밸런싱과 매월 1/11/21 중간점검 cadence를 release DAG input으로 연결한다. rebalance_required, + mid_check_required는 final_decision_packet에 반드시 포함된다. + ' +timezone: Asia/Seoul cadence: weekly_rebalance: - days: [Saturday, Sunday] - trigger_field: rebalance_required # final packet에 삽입되는 boolean 필드 + days: + - Saturday + - Sunday + trigger_field: rebalance_required required_sections: - - portfolio_rebalance_playbook - - ticker_action_matrix - - sell_priority_table # 매도 후보 2개 이상이면 반드시 포함 - - cash_and_risk_budget_snapshot + - portfolio_rebalance_playbook + - ticker_action_matrix + - sell_priority_table + - cash_and_risk_budget_snapshot interim_check: - dates: [1, 11, 21] - trigger_field: mid_check_required # final packet에 삽입되는 boolean 필드 + dates: + - 1 + - 11 + - 21 + trigger_field: mid_check_required required_sections: - - engine_health_card - - data_missing_and_harness_update_list - - shadow_ledger_review - - calibration_drift_report - + - engine_health_card + - data_missing_and_harness_update_list + - shadow_ledger_review + - calibration_drift_report release_dag_integration: input_node: build_operating_cadence_signal_v1 output_fields: - - name: rebalance_required - type: bool - description: 현재 일자가 Saturday 또는 Sunday이면 true - - name: mid_check_required - type: bool - description: 현재 일자의 day가 1, 11, 21 중 하나이면 true - - name: cadence_label - type: str - enum: [WEEKEND_REBALANCE, MID_MONTH_CHECK, NORMAL] + - name: rebalance_required + type: bool + description: 현재 일자가 Saturday 또는 Sunday이면 true + - name: mid_check_required + type: bool + description: 현재 일자의 day가 1, 11, 21 중 하나이면 true + - name: cadence_label + type: str + enum: + - WEEKEND_REBALANCE + - MID_MONTH_CHECK + - NORMAL downstream_nodes: - - build_final_context # context pack에 cadence 정보 삽입 - - build_final_decision_packet # packet에 rebalance_required 삽입 - + - build_final_context + - build_final_decision_packet rules: - - id: RULE_WEEKEND_REBALANCE_CHECK - condition: current_day in [Saturday, Sunday] - action: Enforce rebalance review playbook. sell priority table must appear. - packet_field: rebalance_required - - id: RULE_INTERIM_CHECK - condition: current_date.day in [1, 11, 21] - action: Enforce interim quality check playbook. shadow ledger review mandatory. - packet_field: mid_check_required - - id: RULE_CADENCE_IN_PACKET - condition: always - action: > - rebalance_required와 mid_check_required는 final_decision_packet_active에 - 항상 포함된다. 값이 없으면 DATA_MISSING — 하네스 업데이트 필요. +- id: RULE_WEEKEND_REBALANCE_CHECK + condition: current_day in [Saturday, Sunday] + action: Enforce rebalance review playbook. sell priority table must appear. + packet_field: rebalance_required +- id: RULE_INTERIM_CHECK + condition: current_date.day in [1, 11, 21] + action: Enforce interim quality check playbook. shadow ledger review mandatory. + packet_field: mid_check_required +- id: RULE_CADENCE_IN_PACKET + condition: always + action: 'rebalance_required와 mid_check_required는 final_decision_packet_active에 항상 + 포함된다. 값이 없으면 DATA_MISSING — 하네스 업데이트 필요. + ' owner: quant_architect lifecycle_state: active diff --git a/spec/ownership_map.yaml b/spec/ownership_map.yaml index 1ec6466..ef4d466 100644 --- a/spec/ownership_map.yaml +++ b/spec/ownership_map.yaml @@ -1,136 +1,286 @@ meta: - title: "은퇴자산포트폴리오 — 문서 소유권 맵" - version: "2026-05-15-F10_fragmentation_guard" - role: "governance" - purpose: "파일별 책임 범위를 고정해 문서 파편화와 규칙 중복을 방지한다." - + title: 은퇴자산포트폴리오 — 문서 소유권 맵 + version: 2026-05-15-F10_fragmentation_guard + role: governance + purpose: 파일별 책임 범위를 고정해 문서 파편화와 규칙 중복을 방지한다. + has_code_implementation: true + code_path: + - spec\ownership_map.yaml ownership_map: - "spec/00_execution_contract.yaml": - owns: ["master_prohibitions", "hard_stops", "capture_read_ledger", "order_validation_contract"] - must_not_own: ["종목 점수", "시장국면 세부 계산", "계좌별 세제 라우팅"] - "spec/risk/aggregate_risk.yaml": - owns: ["Total_Heat", "포트폴리오 하드스톱", "상관충격", "통합 리스크 엔진"] - must_not_own: ["종목 진입 점수", "HTS 출력 스키마"] - "spec/risk/circuit_breakers.yaml": - owns: ["서킷브레이커", "거래비용 통제", "집중도 브레이크", "섹터 급락 대응"] - must_not_own: ["종목 진입 점수", "HTS 출력 스키마"] - "spec/risk/market_risk_cash.yaml": - owns: ["MRS 현금 비중", "VIX/US10Y 위험 현금 룰"] - must_not_own: ["종목 진입 점수", "HTS 출력 스키마"] - "spec/risk/risk_control.yaml": - owns: ["risk_control compatibility index"] - must_not_own: ["새 임계값"] - "spec/risk/portfolio_exposure.yaml": - owns: ["cash_floor", "중복노출", "목표 버킷", "ETF 단계 감축", "현금 버퍼"] - must_not_own: ["개별 종목 점수", "JSON Schema"] - "spec/risk/quality_control.yaml": - owns: ["리스크 품질관리 요약", "금지 규칙 참조"] - must_not_own: ["새 임계값"] - "spec/strategy/sector_model.yaml": - owns: ["sector_model", "CSCS", "등급 alias"] - must_not_own: ["계좌 라우팅", "현금 하한"] - "spec/strategy/entry_gates.yaml": - owns: ["entry_timing_guardrails", "daily_leader_scan", "anti_climax_buy_gate", "staged_entry", "pullback_reentry"] - must_not_own: ["Total_Heat", "capture_read_ledger"] - "spec/strategy/stock_model.yaml": - owns: ["stock_model", "core_satellite_rule"] - must_not_own: ["시장 전체 현금 비중"] - "spec/strategy/rebalancing_trigger.yaml": - owns: ["rebalancing_trigger"] - must_not_own: ["손절/익절 세부 실행"] - "spec/02_data_contract.yaml": - owns: ["source_priority", "data_rule", "data_completeness_gate", "xlsx_analysis_protocol"] - must_not_own: ["매수/매도 결론"] - "spec/12_field_dictionary.yaml": - owns: ["canonical field names", "field aliases", "field units", "field missing policy"] - must_not_own: ["투자 판단 임계값", "매수/매도 결론"] - "spec/13_formula_registry.yaml": - owns: ["executable formulas", "formula inputs", "formula outputs", "formula missing policy"] - must_not_own: ["보고서 양식", "예시 케이스"] - "spec/14_raw_workbook_mapping.yaml": - owns: ["raw workbook sheets", "raw workbook columns", "workbook to canonical field mapping"] - must_not_own: ["계좌 보유수량", "계좌 현금"] - "spec/15_account_snapshot_contract.yaml": - owns: ["image capture account snapshot", "holding quantity", "average cost", "cash fields", "open orders"] - must_not_own: ["시장 가격 수집", "섹터 점수"] - "spec/05_position_sizing.yaml": - owns: ["volatility_targeting", "bayesian_confidence", "kelly brake", "integer sizing"] - must_not_own: ["보유수량 판독", "보고서 양식"] - "spec/06_exit_policy.yaml": - owns: ["exit policy compatibility index"] - must_not_own: ["새 임계값", "신규매수 게이트"] - "spec/exit/stop_loss.yaml": - owns: ["stop_loss"] - must_not_own: ["신규매수 게이트"] - "spec/exit/take_profit.yaml": - owns: ["take_profit"] - must_not_own: ["신규매수 게이트"] - "spec/exit/proactive_exit_radar.yaml": - owns: ["proactive_exit_radar", "divergence_alert", "overhang_warning", "rotation_radar"] - must_not_own: ["신규매수 게이트"] - "spec/exit/event_response.yaml": - owns: ["event_response"] - must_not_own: ["신규매수 게이트"] - "spec/exit/position_review.yaml": - owns: ["position_review_cycle"] - must_not_own: ["신규매수 게이트"] - "spec/07_output_schema.yaml": - owns: ["recommendation_grade", "HTS table columns", "human output contract"] - must_not_own: ["투자 판단 임계값"] - "schemas/output_schema.json": - owns: ["machine-readable final output schema"] - must_not_own: ["투자 규칙 수치"] - - # ── 호환 인덱스 (redirect-only, 실제 규칙은 canonical_split_files 참조) ── - # 2026-06-22 WBS-7.11: spec/03_risk_policy.yaml, spec/04_strategy_rules.yaml은 - # role: deprecated_redirect(영구 유지가 아닌 완전 폐기 대상)였으며 활성 참조 0건을 - # 확인 후 실삭제했다. 캐노니컬 split 파일들은 영향 없이 그대로 유지된다. - "spec/06_exit_policy.yaml": - role: "compatibility_index" - owns: ["legacy path alias for spec/exit/*.yaml"] - must_not_own: ["새 손절/익절 임계값"] - canonical_files: ["spec/exit/stop_loss.yaml", "spec/exit/take_profit.yaml", "spec/exit/proactive_exit_radar.yaml", "spec/exit/event_response.yaml", "spec/exit/position_review.yaml"] - - # ── 계산 스키마 ─────────────────────────────────────────────────────────── - "spec/08_scoring_rules.yaml": - owns: ["SS001_SECTOR_MODEL_SCORE 계산 규칙", "SS001 6축 점수 임계값", "KOSDAQ 정규화 공식"] - must_not_own: ["포트폴리오 현금 비중", "exit 규칙"] - "spec/09_decision_flow.yaml": - owns: ["Allowed_Action 결정 흐름", "하드게이트 우선순위 순서"] - must_not_own: ["점수 임계값", "포지션 사이징 공식"] - "spec/10_portfolio_rules.yaml": - owns: ["버킷 할당 목표", "core/satellite 비율 규칙"] - must_not_own: ["개별 종목 점수", "시장국면 판정"] - "spec/11_market_regime.yaml": - owns: ["MARKET_REGIME_V1 판정 로직", "MRS 계산 공식", "REGIME 6개 상태 정의"] - must_not_own: ["개별 종목 점수", "포지션 사이징"] - - # ── 운영 계약서 ────────────────────────────────────────────────────────── - "spec/16_data_gaps_roadmap.yaml": - owns: ["미구현 항목 추적", "구현 우선순위 로드맵"] - must_not_own: ["확정된 계산 공식", "임계값"] - "spec/17_performance_contract.yaml": - owns: ["performance 탭 구조", "Bayesian multiplier 계산 규칙", "fc_bucket 집계"] - must_not_own: ["시장국면 판정", "종목 스크리닝"] - "spec/18_settings_contract.yaml": - owns: ["settings 탭 파라미터 정의", "total_asset_krw", "risk_budget_override", "orbit_* 키"] - must_not_own: ["계산 공식", "임계값 수치"] - "spec/21_harness_governance_contract.yaml": - owns: ["하네스 거버넌스 3중잠금", "실행 하드락", "배포 차단 정책"] - must_not_own: ["개별 종목 점수", "주문 가격 산출식"] - "spec/strategy_execution_lock_policy.yaml": - owns: ["전략 실행락 임계값", "점수 하네스 기반 BUY/SELL 통제 임계치"] - must_not_own: ["주문 가격 산출식", "시장국면 판정"] - - # ── 전략 세부 파일 ────────────────────────────────────────────────────── - "spec/strategy/discovery.yaml": - owns: ["종목 발굴 기준", "스크리닝 필터"] - must_not_own: ["손절/익절 실행", "계좌 현금"] - "spec/strategy/entry_core.yaml": - owns: ["진입 체크리스트", "core 포지션 진입 기준"] - must_not_own: ["Total_Heat 계산", "capture_read_ledger"] - + spec/00_execution_contract.yaml: + owns: + - master_prohibitions + - hard_stops + - capture_read_ledger + - order_validation_contract + must_not_own: + - 종목 점수 + - 시장국면 세부 계산 + - 계좌별 세제 라우팅 + spec/risk/aggregate_risk.yaml: + owns: + - Total_Heat + - 포트폴리오 하드스톱 + - 상관충격 + - 통합 리스크 엔진 + must_not_own: + - 종목 진입 점수 + - HTS 출력 스키마 + spec/risk/circuit_breakers.yaml: + owns: + - 서킷브레이커 + - 거래비용 통제 + - 집중도 브레이크 + - 섹터 급락 대응 + must_not_own: + - 종목 진입 점수 + - HTS 출력 스키마 + spec/risk/market_risk_cash.yaml: + owns: + - MRS 현금 비중 + - VIX/US10Y 위험 현금 룰 + must_not_own: + - 종목 진입 점수 + - HTS 출력 스키마 + spec/risk/risk_control.yaml: + owns: + - risk_control compatibility index + must_not_own: + - 새 임계값 + spec/risk/portfolio_exposure.yaml: + owns: + - cash_floor + - 중복노출 + - 목표 버킷 + - ETF 단계 감축 + - 현금 버퍼 + must_not_own: + - 개별 종목 점수 + - JSON Schema + spec/risk/quality_control.yaml: + owns: + - 리스크 품질관리 요약 + - 금지 규칙 참조 + must_not_own: + - 새 임계값 + spec/strategy/sector_model.yaml: + owns: + - sector_model + - CSCS + - 등급 alias + must_not_own: + - 계좌 라우팅 + - 현금 하한 + spec/strategy/entry_gates.yaml: + owns: + - entry_timing_guardrails + - daily_leader_scan + - anti_climax_buy_gate + - staged_entry + - pullback_reentry + must_not_own: + - Total_Heat + - capture_read_ledger + spec/strategy/stock_model.yaml: + owns: + - stock_model + - core_satellite_rule + must_not_own: + - 시장 전체 현금 비중 + spec/strategy/rebalancing_trigger.yaml: + owns: + - rebalancing_trigger + must_not_own: + - 손절/익절 세부 실행 + spec/02_data_contract.yaml: + owns: + - source_priority + - data_rule + - data_completeness_gate + - xlsx_analysis_protocol + must_not_own: + - 매수/매도 결론 + spec/12_field_dictionary.yaml: + owns: + - canonical field names + - field aliases + - field units + - field missing policy + must_not_own: + - 투자 판단 임계값 + - 매수/매도 결론 + spec/13_formula_registry.yaml: + owns: + - executable formulas + - formula inputs + - formula outputs + - formula missing policy + must_not_own: + - 보고서 양식 + - 예시 케이스 + spec/14_raw_workbook_mapping.yaml: + owns: + - raw workbook sheets + - raw workbook columns + - workbook to canonical field mapping + must_not_own: + - 계좌 보유수량 + - 계좌 현금 + spec/15_account_snapshot_contract.yaml: + owns: + - image capture account snapshot + - holding quantity + - average cost + - cash fields + - open orders + must_not_own: + - 시장 가격 수집 + - 섹터 점수 + spec/05_position_sizing.yaml: + owns: + - volatility_targeting + - bayesian_confidence + - kelly brake + - integer sizing + must_not_own: + - 보유수량 판독 + - 보고서 양식 + spec/06_exit_policy.yaml: + role: compatibility_index + owns: + - legacy path alias for spec/exit/*.yaml + must_not_own: + - 새 손절/익절 임계값 + canonical_files: + - spec/exit/stop_loss.yaml + - spec/exit/take_profit.yaml + - spec/exit/proactive_exit_radar.yaml + - spec/exit/event_response.yaml + - spec/exit/position_review.yaml + spec/exit/stop_loss.yaml: + owns: + - stop_loss + must_not_own: + - 신규매수 게이트 + spec/exit/take_profit.yaml: + owns: + - take_profit + must_not_own: + - 신규매수 게이트 + spec/exit/proactive_exit_radar.yaml: + owns: + - proactive_exit_radar + - divergence_alert + - overhang_warning + - rotation_radar + must_not_own: + - 신규매수 게이트 + spec/exit/event_response.yaml: + owns: + - event_response + must_not_own: + - 신규매수 게이트 + spec/exit/position_review.yaml: + owns: + - position_review_cycle + must_not_own: + - 신규매수 게이트 + spec/07_output_schema.yaml: + owns: + - recommendation_grade + - HTS table columns + - human output contract + must_not_own: + - 투자 판단 임계값 + schemas/output_schema.json: + owns: + - machine-readable final output schema + must_not_own: + - 투자 규칙 수치 + spec/08_scoring_rules.yaml: + owns: + - SS001_SECTOR_MODEL_SCORE 계산 규칙 + - SS001 6축 점수 임계값 + - KOSDAQ 정규화 공식 + must_not_own: + - 포트폴리오 현금 비중 + - exit 규칙 + spec/09_decision_flow.yaml: + owns: + - Allowed_Action 결정 흐름 + - 하드게이트 우선순위 순서 + must_not_own: + - 점수 임계값 + - 포지션 사이징 공식 + spec/10_portfolio_rules.yaml: + owns: + - 버킷 할당 목표 + - core/satellite 비율 규칙 + must_not_own: + - 개별 종목 점수 + - 시장국면 판정 + spec/11_market_regime.yaml: + owns: + - MARKET_REGIME_V1 판정 로직 + - MRS 계산 공식 + - REGIME 6개 상태 정의 + must_not_own: + - 개별 종목 점수 + - 포지션 사이징 + spec/16_data_gaps_roadmap.yaml: + owns: + - 미구현 항목 추적 + - 구현 우선순위 로드맵 + must_not_own: + - 확정된 계산 공식 + - 임계값 + spec/17_performance_contract.yaml: + owns: + - performance 탭 구조 + - Bayesian multiplier 계산 규칙 + - fc_bucket 집계 + must_not_own: + - 시장국면 판정 + - 종목 스크리닝 + spec/18_settings_contract.yaml: + owns: + - settings 탭 파라미터 정의 + - total_asset_krw + - risk_budget_override + - orbit_* 키 + must_not_own: + - 계산 공식 + - 임계값 수치 + spec/21_harness_governance_contract.yaml: + owns: + - 하네스 거버넌스 3중잠금 + - 실행 하드락 + - 배포 차단 정책 + must_not_own: + - 개별 종목 점수 + - 주문 가격 산출식 + spec/strategy_execution_lock_policy.yaml: + owns: + - 전략 실행락 임계값 + - 점수 하네스 기반 BUY/SELL 통제 임계치 + must_not_own: + - 주문 가격 산출식 + - 시장국면 판정 + spec/strategy/discovery.yaml: + owns: + - 종목 발굴 기준 + - 스크리닝 필터 + must_not_own: + - 손절/익절 실행 + - 계좌 현금 + spec/strategy/entry_core.yaml: + owns: + - 진입 체크리스트 + - core 포지션 진입 기준 + must_not_own: + - Total_Heat 계산 + - capture_read_ledger policy: - - "새 규칙 추가 전 ownership_map에서 소유 파일을 먼저 확인한다." - - "must_not_own 영역에 규칙을 추가하면 validate_specs.py에서 실패 처리한다." - - "임계값은 canonical 소유 파일에만 추가한다." +- 새 규칙 추가 전 ownership_map에서 소유 파일을 먼저 확인한다. +- must_not_own 영역에 규칙을 추가하면 validate_specs.py에서 실패 처리한다. +- 임계값은 canonical 소유 파일에만 추가한다. diff --git a/spec/profit_preservation_contract.yaml b/spec/profit_preservation_contract.yaml index 0b397f5..ad38132 100644 --- a/spec/profit_preservation_contract.yaml +++ b/spec/profit_preservation_contract.yaml @@ -1,21 +1,27 @@ +meta: + has_code_implementation: true + code_path: + - spec\profit_preservation_contract.yaml schema_version: profit_preservation_contract.v2 -goal: Define rules and metrics to preserve unrealized profits and enforce trailing stop policies. +goal: Define rules and metrics to preserve unrealized profits and enforce trailing + stop policies. metrics: - - id: profit_giveback - description: "Ratio of profit returned from peak price since entry" - - id: trailing_stop - description: "Trailing stop price level determined by ratchet stage" - - id: ratchet_stage - description: "Lock tier based on maximum achieved profit percentage (e.g. PROFIT_LOCK_10, APEX_SUPER)" - - id: sell_slippage_budget - description: "Allowed slippage threshold during execution" +- id: profit_giveback + description: Ratio of profit returned from peak price since entry +- id: trailing_stop + description: Trailing stop price level determined by ratchet stage +- id: ratchet_stage + description: Lock tier based on maximum achieved profit percentage (e.g. PROFIT_LOCK_10, + APEX_SUPER) +- id: sell_slippage_budget + description: Allowed slippage threshold during execution rules: - - id: RULE_PROFIT_GIVEBACK_GUARD - condition: "profit_pct >= 20% and profit_giveback > 30% of peak gain" - action: "Enforce trailing stop / lock remaining profit" - - id: RULE_DRAWDOWN_GUARD_PRIORITY - condition: "portfolio in value_preservation_stage" - action: "Prioritize drawdown guard over new alpha signals" - - id: RULE_VALUE_DAMAGE_LIMIT - condition: "unrealized maximum drawdown per ticker" - limit: "value_damage_pct_avg <= 10%" +- id: RULE_PROFIT_GIVEBACK_GUARD + condition: profit_pct >= 20% and profit_giveback > 30% of peak gain + action: Enforce trailing stop / lock remaining profit +- id: RULE_DRAWDOWN_GUARD_PRIORITY + condition: portfolio in value_preservation_stage + action: Prioritize drawdown guard over new alpha signals +- id: RULE_VALUE_DAMAGE_LIMIT + condition: unrealized maximum drawdown per ticker + limit: value_damage_pct_avg <= 10% diff --git a/spec/property_invariants.yaml b/spec/property_invariants.yaml index 775c019..6ac4d50 100644 --- a/spec/property_invariants.yaml +++ b/spec/property_invariants.yaml @@ -1,15 +1,19 @@ +meta: + has_code_implementation: true + code_path: + - spec\property_invariants.yaml schema_version: property_invariants.v1 goal: Define investment engine metamorphic and property invariants. invariants: - - id: INV_CASH_SHORTFALL_MONOTONICITY - description: "현금 부족액 증가 시 신규 매수 권한/수량은 증가할 수 없음" - formula_ref: "spec/risk/portfolio_exposure.yaml" - - id: INV_MARKET_RISK_MONOTONICITY - description: "시장 위험 증가 시 position scale은 증가할 수 없음" - formula_ref: "spec/risk/market_risk_cash.yaml" - - id: INV_MISSING_DATA_CONFIDENCE - description: "데이터 결측 추가 시 confidence는 상승할 수 없음" - formula_ref: "spec/02_data_contract.yaml" - - id: INV_STALE_PRICE_ZERO_QUANTITY - description: "stale 가격이면 실행 주문 수량은 0" - formula_ref: "spec/00_execution_contract.yaml" +- id: INV_CASH_SHORTFALL_MONOTONICITY + description: 현금 부족액 증가 시 신규 매수 권한/수량은 증가할 수 없음 + formula_ref: spec/risk/portfolio_exposure.yaml +- id: INV_MARKET_RISK_MONOTONICITY + description: 시장 위험 증가 시 position scale은 증가할 수 없음 + formula_ref: spec/risk/market_risk_cash.yaml +- id: INV_MISSING_DATA_CONFIDENCE + description: 데이터 결측 추가 시 confidence는 상승할 수 없음 + formula_ref: spec/02_data_contract.yaml +- id: INV_STALE_PRICE_ZERO_QUANTITY + description: stale 가격이면 실행 주문 수량은 0 + formula_ref: spec/00_execution_contract.yaml diff --git a/spec/risk/circuit_breakers.yaml b/spec/risk/circuit_breakers.yaml index 829d51e..078f177 100644 --- a/spec/risk/circuit_breakers.yaml +++ b/spec/risk/circuit_breakers.yaml @@ -5,6 +5,8 @@ meta: language: "ko-KR" timezone: "Asia/Seoul" role: "canonical" + has_code_implementation: true + code_path: ["spec/strategy/action_matrix.yaml"] migration_status: "canonical_split_active" risk_control: diff --git a/spec/risk/portfolio_exposure.yaml b/spec/risk/portfolio_exposure.yaml index b00e499..e110d02 100644 --- a/spec/risk/portfolio_exposure.yaml +++ b/spec/risk/portfolio_exposure.yaml @@ -5,6 +5,8 @@ meta: language: "ko-KR" timezone: "Asia/Seoul" role: "canonical" + has_code_implementation: true + code_path: ["spec/strategy/action_matrix.yaml"] migration_status: "canonical_split_active" authority_rule: "이 split 파일이 해당 섹션의 canonical source다. parent_file은 legacy compatibility index다." diff --git a/spec/routing_trace_v2.yaml b/spec/routing_trace_v2.yaml index d040230..f5253d0 100644 --- a/spec/routing_trace_v2.yaml +++ b/spec/routing_trace_v2.yaml @@ -1,41 +1,44 @@ +meta: + has_code_implementation: true + code_path: + - spec\routing_trace_v2.yaml formula_id: ROUTING_SERVING_DECISION_TRACE_V2 name: 라우팅 및 서빙 결정 추적 (Routing & Serving Decision Trace) -description: 라우팅부터 서빙, 결정, 수량/가격 산출까지 전체 파이프라인의 이력을 단일 Trace ID로 기록하여 LLM의 자유도를 0%로 통제합니다. +description: 라우팅부터 서빙, 결정, 수량/가격 산출까지 전체 파이프라인의 이력을 단일 Trace ID로 기록하여 LLM의 자유도를 0%로 + 통제합니다. rules: - - id: TR001 - condition: "trace_id IS NULL OR step_completed == FALSE" - action: "ABORT_PIPELINE" - reason: "라우팅 파이프라인 추적 누락 또는 비정상 종료" - - id: TR002 - condition: "llm_override_detected == TRUE" - action: "INVALID_LLM_OVERRIDE" - reason: "LLM이 하네스 결정값을 임의로 번복 또는 재생성 시도" +- id: TR001 + condition: trace_id IS NULL OR step_completed == FALSE + action: ABORT_PIPELINE + reason: 라우팅 파이프라인 추적 누락 또는 비정상 종료 +- id: TR002 + condition: llm_override_detected == TRUE + action: INVALID_LLM_OVERRIDE + reason: LLM이 하네스 결정값을 임의로 번복 또는 재생성 시도 output: schema: routing_serving_trace_v3_json fields: - - trace_id: STRING - - route: STRING - - prompt_entry: STRING - - gate_path: ARRAY of STRING - - final_block_reason: STRING OR NULL - - llm_serving_budget: NUMBER (Must be 0) - -# ── 단계12: RELEASE_GATE_TRUTH (TASK-001 연동) ────────────────────────────── + - trace_id: STRING + - route: STRING + - prompt_entry: STRING + - gate_path: ARRAY of STRING + - final_block_reason: STRING OR NULL + - llm_serving_budget: NUMBER (Must be 0) routing_steps: step_12: id: 12 name: RELEASE_GATE_TRUTH formula_id: RELEASE_GATE_TRUTH_V1 - description: "honest_proof_score >= 70 이어야만 HTS 주문 생성 허용" + description: honest_proof_score >= 70 이어야만 HTS 주문 생성 허용 inputs: - - algorithm_guidance_proof_v1.json.honest_proof_score - - algorithm_guidance_proof_v1.json.honest_gate - - pass_100_criteria_v3.json.effective_release_gate + - algorithm_guidance_proof_v1.json.honest_proof_score + - algorithm_guidance_proof_v1.json.honest_gate + - pass_100_criteria_v3.json.effective_release_gate output_key: effective_release_gate - on_blocked: "이후 HTS 주문 생성 0건 — THEORETICAL_ONLY 렌더" + on_blocked: 이후 HTS 주문 생성 0건 — THEORETICAL_ONLY 렌더 acceptance: - - "routing_execution_log 행수 == 12" - - "단계12 status가 effective_release_gate와 일치" - gs_coverage: "gas_apex_runtime_core.gs:buildRoutingExecutionLogV2_()" - python_tool: "tools/build_routing_execution_log_v1.py" - validator: "tools/validate_routing_trace_replay_v1.py" \ No newline at end of file + - routing_execution_log 행수 == 12 + - 단계12 status가 effective_release_gate와 일치 + gs_coverage: gas_apex_runtime_core.gs:buildRoutingExecutionLogV2_() + python_tool: tools/build_routing_execution_log_v1.py + validator: tools/validate_routing_trace_replay_v1.py diff --git a/spec/strategy/action_matrix.yaml b/spec/strategy/action_matrix.yaml index eb9f4a7..805a08f 100644 --- a/spec/strategy/action_matrix.yaml +++ b/spec/strategy/action_matrix.yaml @@ -3,6 +3,8 @@ meta: version: "2026-05-17-action_matrix_v1" language: "ko-KR" role: "canonical" + has_code_implementation: true + code_path: ["spec/strategy/action_matrix.yaml"] purpose: > gas_data_feed.gs의 Allowed_Action(매수 게이트) + calcSellDecision_(매도) + calcFinalDecision_(통합)이 어떤 조건에서 어떤 Final_Action을 출력하는지 diff --git a/spec/strategy/discovery.yaml b/spec/strategy/discovery.yaml index 9bc1b0d..dec41a8 100644 --- a/spec/strategy/discovery.yaml +++ b/spec/strategy/discovery.yaml @@ -5,6 +5,8 @@ meta: language: "ko-KR" timezone: "Asia/Seoul" role: "canonical" + has_code_implementation: true + code_path: ["spec/strategy/action_matrix.yaml"] migration_status: "canonical_split_active" anti_late_trade_rule: diff --git a/spec/strategy/entry_core.yaml b/spec/strategy/entry_core.yaml index 2a9bb45..a85941c 100644 --- a/spec/strategy/entry_core.yaml +++ b/spec/strategy/entry_core.yaml @@ -5,6 +5,8 @@ meta: language: "ko-KR" timezone: "Asia/Seoul" role: "canonical" + has_code_implementation: true + code_path: ["spec/strategy/action_matrix.yaml"] migration_status: "canonical_split_active" entry_timing_guardrails: diff --git a/spec/strategy/leader_scan.yaml b/spec/strategy/leader_scan.yaml index 2b4ea27..3e1d69f 100644 --- a/spec/strategy/leader_scan.yaml +++ b/spec/strategy/leader_scan.yaml @@ -5,6 +5,8 @@ meta: language: "ko-KR" timezone: "Asia/Seoul" role: "canonical" + has_code_implementation: true + code_path: ["spec/strategy/action_matrix.yaml"] migration_status: "canonical_split_active" entry_timing_guardrails: diff --git a/spec/strategy/rebalancing_trigger.yaml b/spec/strategy/rebalancing_trigger.yaml index fd96985..d5160c3 100644 --- a/spec/strategy/rebalancing_trigger.yaml +++ b/spec/strategy/rebalancing_trigger.yaml @@ -5,6 +5,8 @@ meta: language: "ko-KR" timezone: "Asia/Seoul" role: "canonical" + has_code_implementation: true + code_path: ["spec/strategy/action_matrix.yaml"] migration_status: "canonical_split_active" authority_rule: "이 split 파일이 해당 섹션의 canonical source다. parent_file은 legacy compatibility index다." diff --git a/spec/strategy/sector_model.yaml b/spec/strategy/sector_model.yaml index 4730388..1b0f815 100644 --- a/spec/strategy/sector_model.yaml +++ b/spec/strategy/sector_model.yaml @@ -5,6 +5,8 @@ meta: language: "ko-KR" timezone: "Asia/Seoul" role: "canonical" + has_code_implementation: true + code_path: ["spec/strategy/action_matrix.yaml"] migration_status: "canonical_split_active" authority_rule: "이 split 파일이 해당 섹션의 canonical source다. parent_file은 legacy compatibility index다." diff --git a/spec/strategy/staged_entry.yaml b/spec/strategy/staged_entry.yaml index 6565f13..52eec1c 100644 --- a/spec/strategy/staged_entry.yaml +++ b/spec/strategy/staged_entry.yaml @@ -5,6 +5,8 @@ meta: language: "ko-KR" timezone: "Asia/Seoul" role: "canonical" + has_code_implementation: true + code_path: ["spec/strategy/action_matrix.yaml"] migration_status: "canonical_split_active" entry_timing_guardrails: diff --git a/spec/xref_matrix.yaml b/spec/xref_matrix.yaml index f78adc4..7ed0f2b 100644 --- a/spec/xref_matrix.yaml +++ b/spec/xref_matrix.yaml @@ -1,145 +1,139 @@ meta: - title: "은퇴자산포트폴리오 — 참조 허용 매트릭스" - version: "2026-05-15-F10_fragmentation_guard" - role: "governance" - purpose: "파일 간 순환 참조와 책임 침범을 방지한다." - + title: 은퇴자산포트폴리오 — 참조 허용 매트릭스 + version: 2026-05-15-F10_fragmentation_guard + role: governance + purpose: 파일 간 순환 참조와 책임 침범을 방지한다. + has_code_implementation: true + code_path: + - spec\xref_matrix.yaml xref_matrix: - "spec/08_scoring_rules.yaml": + spec/08_scoring_rules.yaml: may_reference: - - "spec/00_execution_contract.yaml" - - "spec/12_field_dictionary.yaml" - - "spec/13_formula_registry.yaml" - - "spec/02_data_contract.yaml" - - "spec/risk/aggregate_risk.yaml" - - "spec/risk/market_risk_cash.yaml" - - "spec/risk/portfolio_exposure.yaml" - - "spec/strategy/sector_model.yaml" - - "spec/07_output_schema.yaml" + - spec/00_execution_contract.yaml + - spec/12_field_dictionary.yaml + - spec/13_formula_registry.yaml + - spec/02_data_contract.yaml + - spec/risk/aggregate_risk.yaml + - spec/risk/market_risk_cash.yaml + - spec/risk/portfolio_exposure.yaml + - spec/strategy/sector_model.yaml + - spec/07_output_schema.yaml must_not_reference: - - "examples/" - - "prompts/" - "spec/10_portfolio_rules.yaml": + - examples/ + - prompts/ + spec/10_portfolio_rules.yaml: may_reference: - - "spec/01_objective_profile.yaml" - - "spec/12_field_dictionary.yaml" - - "spec/13_formula_registry.yaml" - - "spec/risk/portfolio_exposure.yaml" - - "spec/risk/aggregate_risk.yaml" - - "spec/risk/market_risk_cash.yaml" + - spec/01_objective_profile.yaml + - spec/12_field_dictionary.yaml + - spec/13_formula_registry.yaml + - spec/risk/portfolio_exposure.yaml + - spec/risk/aggregate_risk.yaml + - spec/risk/market_risk_cash.yaml must_not_reference: - - "schemas/output_schema.json" - "spec/07_output_schema.yaml": + - schemas/output_schema.json + spec/07_output_schema.yaml: may_reference: - - "schemas/output_schema.json" - - "RetirementAssetPortfolioReportTemplate.yaml" - - "spec/00_execution_contract.yaml" - - "spec/12_field_dictionary.yaml" - - "spec/13_formula_registry.yaml" + - schemas/output_schema.json + - RetirementAssetPortfolioReportTemplate.yaml + - spec/00_execution_contract.yaml + - spec/12_field_dictionary.yaml + - spec/13_formula_registry.yaml must_not_reference: - - "examples/" - - "prompts/" - "schemas/output_schema.json": + - examples/ + - prompts/ + schemas/output_schema.json: may_reference: [] must_not_reference: - - "spec/" - - "examples/" - - "prompts/" - "examples/": + - spec/ + - examples/ + - prompts/ + examples/: may_reference: - - "spec/" - - "schemas/output_schema.json" + - spec/ + - schemas/output_schema.json must_not_reference: [] - "prompts/": + prompts/: may_reference: - - "RetirementAssetPortfolio.yaml" - - "spec/" - - "schemas/output_schema.json" + - RetirementAssetPortfolio.yaml + - spec/ + - schemas/output_schema.json must_not_reference: [] - - # ── 신규 계약 파일 xref ──────────────────────────────────────────────────── - "spec/53_factor_conflict_matrix.yaml": + spec/53_factor_conflict_matrix.yaml: may_reference: - - "spec/43_quant_factor_taxonomy.yaml" - - "spec/00_execution_contract.yaml" - - "spec/factor_lifecycle_registry.yaml" + - spec/43_quant_factor_taxonomy.yaml + - spec/00_execution_contract.yaml + - spec/factor_lifecycle_registry.yaml must_not_reference: - - "examples/" - conflict_resolution_note: > - spec/53 conflict_precedence_rules rank 6 = market_regime (포지션 스케일 조정). - spec/00 P3 = cash_floor·Total_Heat·hard_stop은 어떤 alpha/strategy 논리보다 우선. - 두 계약이 충돌하면 spec/00 P3가 우선한다 (spec/00 source_of_truth.priority=highest). - spec/53의 rank 1(portfolio_risk_budget)이 사실상 spec/00 P3의 집행자이며, - market_regime(rank 6)은 cash_floor를 완화하는 목적으로 사용될 수 없다. + - examples/ + conflict_resolution_note: 'spec/53 conflict_precedence_rules rank 6 = market_regime + (포지션 스케일 조정). spec/00 P3 = cash_floor·Total_Heat·hard_stop은 어떤 alpha/strategy + 논리보다 우선. 두 계약이 충돌하면 spec/00 P3가 우선한다 (spec/00 source_of_truth.priority=highest). + spec/53의 rank 1(portfolio_risk_budget)이 사실상 spec/00 P3의 집행자이며, market_regime(rank + 6)은 cash_floor를 완화하는 목적으로 사용될 수 없다. - "spec/52_decision_trace_replay_contract.yaml": + ' + spec/52_decision_trace_replay_contract.yaml: may_reference: - - "spec/41_release_dag.yaml" - - "spec/40_final_decision_packet_contract.yaml" + - spec/41_release_dag.yaml + - spec/40_final_decision_packet_contract.yaml must_not_reference: - - "examples/" - - "spec/54_temporal_data_integrity.yaml": + - examples/ + spec/54_temporal_data_integrity.yaml: may_reference: - - "spec/00_execution_contract.yaml" - - "spec/exit/stop_loss.yaml" + - spec/00_execution_contract.yaml + - spec/exit/stop_loss.yaml must_not_reference: - - "examples/" - temporal_note: > - TIME_STOP 판단에 사용되는 hold_days는 반드시 entry_date 기준 실제 경과일 기반이어야 한다. + - examples/ + temporal_note: 'TIME_STOP 판단에 사용되는 hold_days는 반드시 entry_date 기준 실제 경과일 기반이어야 한다. 미래 날짜 hold_days 사용은 LOOKAHEAD_BIAS로 분류된다. - "spec/55_execution_simulator_contract.yaml": + ' + spec/55_execution_simulator_contract.yaml: may_reference: - - "spec/00_execution_contract.yaml" - - "spec/13_formula_registry.yaml" - - "spec/15_account_snapshot_contract.yaml" + - spec/00_execution_contract.yaml + - spec/13_formula_registry.yaml + - spec/15_account_snapshot_contract.yaml must_not_reference: - - "examples/" - - "spec/56_renderer_copy_only_contract.yaml": + - examples/ + spec/56_renderer_copy_only_contract.yaml: may_reference: - - "spec/00_execution_contract.yaml" - - "spec/40_final_decision_packet_contract.yaml" + - spec/00_execution_contract.yaml + - spec/40_final_decision_packet_contract.yaml must_not_reference: - - "examples/" - - "spec/57_shadow_promotion_scorecard.yaml": + - examples/ + spec/57_shadow_promotion_scorecard.yaml: may_reference: - - "spec/44_live_replay_separation.yaml" - - "spec/43_quant_factor_taxonomy.yaml" + - spec/44_live_replay_separation.yaml + - spec/43_quant_factor_taxonomy.yaml must_not_reference: - - "examples/" - - "spec/58_llm_determinism_contract.yaml": + - examples/ + spec/58_llm_determinism_contract.yaml: may_reference: - - "spec/46_low_capability_execution_pack.yaml" - - "spec/00_execution_contract.yaml" + - spec/46_low_capability_execution_pack.yaml + - spec/00_execution_contract.yaml must_not_reference: - - "examples/" - -# ── 충돌 해소 우선순위 선언 ──────────────────────────────────────────────── + - examples/ conflict_resolution_precedence: - canonical_authority: "spec/00_execution_contract.yaml (source_of_truth.priority=highest)" + canonical_authority: spec/00_execution_contract.yaml (source_of_truth.priority=highest) rules: - - id: "XREF_CR001" - description: > - spec/53 rank 6 market_regime vs spec/00 P3 cash_floor: - spec/00 P3가 절대 우선한다. market_regime은 position_scale만 조정하며 - cash_floor·Total_Heat·hard_stop을 완화하는 목적으로 사용 금지. - winner: "spec/00_execution_contract.yaml:P3_no_risk_block_override" - loser: "spec/53_factor_conflict_matrix.yaml:rank=6_market_regime" + - id: XREF_CR001 + description: 'spec/53 rank 6 market_regime vs spec/00 P3 cash_floor: spec/00 P3가 + 절대 우선한다. market_regime은 position_scale만 조정하며 cash_floor·Total_Heat·hard_stop을 + 완화하는 목적으로 사용 금지. - - id: "XREF_CR002" - description: > - spec/54 temporal integrity vs spec/00 P4 intraday_lock: - spec/00 P4가 상위 계약. spec/54는 backfill/lookahead를 차단하며, - spec/00 P4는 장중 신규 매수·전량 매도를 차단한다. 두 계약은 서로 보완적. - winner: "spec/00_execution_contract.yaml:P4_no_intraday_speculation" - supplementary: "spec/54_temporal_data_integrity.yaml:NO_LOOKAHEAD" + ' + winner: spec/00_execution_contract.yaml:P3_no_risk_block_override + loser: spec/53_factor_conflict_matrix.yaml:rank=6_market_regime + - id: XREF_CR002 + description: 'spec/54 temporal integrity vs spec/00 P4 intraday_lock: spec/00 + P4가 상위 계약. spec/54는 backfill/lookahead를 차단하며, spec/00 P4는 장중 신규 매수·전량 매도를 차단한다. + 두 계약은 서로 보완적. + ' + winner: spec/00_execution_contract.yaml:P4_no_intraday_speculation + supplementary: spec/54_temporal_data_integrity.yaml:NO_LOOKAHEAD policy: - - "must_not_reference 위반은 검증 실패." - - "may_reference 외 참조는 경고 대상. critical 파일은 실패 대상." - - "schemas/output_schema.json은 어떤 spec도 참조하지 않는다." - - "conflict_resolution_precedence는 spec 충돌 시 판단 순서를 명시한다. spec/00이 항상 최상위." +- must_not_reference 위반은 검증 실패. +- may_reference 외 참조는 경고 대상. critical 파일은 실패 대상. +- schemas/output_schema.json은 어떤 spec도 참조하지 않는다. +- conflict_resolution_precedence는 spec 충돌 시 판단 순서를 명시한다. spec/00이 항상 최상위. diff --git a/tests/parity/test_execution_decision_parity_v1.py b/tests/parity/test_execution_decision_parity_v1.py new file mode 100644 index 0000000..3466731 --- /dev/null +++ b/tests/parity/test_execution_decision_parity_v1.py @@ -0,0 +1,191 @@ +""" +Parity test for execution_decision_v1.py against GAS source. + +F05: Exit/sell action decision logic. +Tests calc_exit_sell_action() with core priorities and edge cases. + +Source: src/gas_adapter_parts/gdf_01_price_metrics.gs:calcExitSellAction_ +""" + +import pytest +from formulas.execution_decision_v1 import calc_exit_sell_action + + +class TestExitSellActionPriorities: + """Test exit/sell action priority hierarchy.""" + + def test_hold_default(self): + """Default HOLD when no signals trigger.""" + result = calc_exit_sell_action({ + "close": 100, + "profitPct": 5, + "rwPartial": 0, + }) + assert result["action"] == "HOLD" + + def test_priority_1_stop_action(self): + """Priority 1: STOP_OR_TIME_EXIT_READY → EXIT_100.""" + result = calc_exit_sell_action({ + "close": 100, + "stopPrice": 95, + "timingAction": "STOP_OR_TIME_EXIT_READY", + }) + assert result["action"] == "EXIT_100" + assert result["ratio_pct"] == 100 + + def test_priority_1_strong_rw(self): + """Priority 1: rwPartial >= 4 → EXIT_100.""" + result = calc_exit_sell_action({ + "close": 100, + "stopPrice": 95, + "rwPartial": 4, + }) + assert result["action"] == "EXIT_100" + + def test_priority_5_profit_50(self): + """Priority 5: profitPct >= 50 → PROFIT_TRIM_50.""" + result = calc_exit_sell_action({ + "close": 100, + "profitPct": 55, + "tp2Price": 155, + "atr20": 2, + }) + assert result["action"] == "PROFIT_TRIM_50" + assert result["ratio_pct"] == 50 + + def test_priority_5_take_profit_tier1(self): + """Priority 5: profitPct >= 10 → TAKE_PROFIT_TIER1.""" + result = calc_exit_sell_action({ + "close": 100, + "profitPct": 15, + "tp1Price": 115, + "atr20": 2, + }) + assert result["action"] == "TAKE_PROFIT_TIER1" + assert result["ratio_pct"] == 25 + + def test_priority_4_trailing_stop_breach(self): + """Priority 4: close <= trailingStop → TRAILING_STOP_BREACH.""" + result = calc_exit_sell_action({ + "close": 95, + "trailingStop": 98, + "atr20": 2, + }) + assert result["action"] == "TRAILING_STOP_BREACH" + assert result["ratio_pct"] == 70 + + def test_priority_4_rw_medium(self): + """Priority 4: rwPartial >= 2 → TRIM_50.""" + result = calc_exit_sell_action({ + "close": 100, + "atr20": 2, + "rwPartial": 2, + }) + assert result["action"] == "TRIM_50" + assert result["ratio_pct"] == 50 + + def test_priority_6_time_stop_near(self): + """Priority 6: daysToTimeStop <= 7 → TIME_TRIM_50.""" + result = calc_exit_sell_action({ + "close": 100, + "atr20": 2, + "daysToTimeStop": 5, + "profitPct": 0, + "rwPartial": 0, + }) + assert result["action"] == "TIME_TRIM_50" + assert result["ratio_pct"] == 50 + + def test_price_source_tier2(self): + """When tp2Price available, use it for PROFIT_TRIM_50.""" + result = calc_exit_sell_action({ + "close": 100, + "profitPct": 55, + "tp2Price": 155, + "atr20": 2, + }) + assert result["price_source"] == "TP2_PRICE" + assert result["price_basis"] == "TAKE_PROFIT_TIER2_PRICE" + + def test_price_fallback_to_close_protect(self): + """When tp2Price absent, use closeProtectLimit.""" + result = calc_exit_sell_action({ + "close": 100, + "profitPct": 55, + "atr20": 2, + }) + assert result["price_source"] == "CLOSE_PROFIT_PROTECT" + assert result["price_basis"] == "PRIOR_CLOSE_X_0.998" + + def test_validation_confirmed(self): + """Validation = SIGNAL_CONFIRMED when price valid.""" + result = calc_exit_sell_action({ + "close": 100, + "stopPrice": 95, + "timingAction": "STOP_OR_TIME_EXIT_READY", + }) + assert result["validation"] == "SIGNAL_CONFIRMED" + + def test_validation_hold_no_action(self): + """Validation = NO_SELL_ACTION when HOLD.""" + result = calc_exit_sell_action({ + "close": 100, + "profitPct": 5, + }) + assert result["validation"] == "NO_SELL_ACTION" + + def test_rw_early_warning_trim_33(self): + """Priority 4b: rwPartial >= 1 + timingExitScore >= 30 → TRIM_33.""" + result = calc_exit_sell_action({ + "close": 100, + "atr20": 2, + "rwPartial": 1, + "timingExitScore": 35, + }) + assert result["action"] == "TRIM_33" + assert result["ratio_pct"] == 33 + + def test_rw_signal_only_trim_25(self): + """Priority 4c: rwPartial >= 1 only → TRIM_25.""" + result = calc_exit_sell_action({ + "close": 100, + "atr20": 2, + "rwPartial": 1, + "timingExitScore": 0, + }) + assert result["action"] == "TRIM_25" + assert result["ratio_pct"] == 25 + + def test_profit_trim_35(self): + """Priority 5: profitPct >= 30 → PROFIT_TRIM_35.""" + result = calc_exit_sell_action({ + "close": 100, + "profitPct": 35, + "tp2Price": 135, + "atr20": 2, + }) + assert result["action"] == "PROFIT_TRIM_35" + assert result["ratio_pct"] == 35 + + def test_profit_trim_25(self): + """Priority 5: profitPct >= 20 → PROFIT_TRIM_25.""" + result = calc_exit_sell_action({ + "close": 100, + "profitPct": 25, + "tp1Price": 125, + "atr20": 2, + }) + assert result["action"] == "PROFIT_TRIM_25" + assert result["ratio_pct"] == 25 + + def test_time_stop_approaching(self): + """Priority 6b: daysToTimeStop <= 14 → TIME_TRIM_25.""" + result = calc_exit_sell_action({ + "close": 100, + "atr20": 2, + "daysToTimeStop": 10, + "profitPct": 0, + "rwPartial": 0, + }) + assert result["action"] == "TIME_TRIM_25" + assert result["ratio_pct"] == 25