Merge pull request 'WBS-8.7: spec-코드 동기화 확장 (66.4%)' (#75) from feature/wbs-8-7-spec-code-sync into main
Reviewed-on: http://kjh2064.synology.me:8418/kjh2064/myfinance/pulls/75
This commit is contained in:
@@ -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
|
schema_version: 2026-06-06-formula-registry-normalized-v1
|
||||||
source: spec/13_formula_registry.yaml
|
source: spec/13_formula_registry.yaml
|
||||||
formula_count: 171
|
formula_count: 171
|
||||||
|
|||||||
@@ -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
|
schema_version: 2026-06-06-output-field-owner-ledger-v1
|
||||||
primary_writer_policy: first-declared-formula
|
primary_writer_policy: first-declared-formula
|
||||||
fields:
|
fields:
|
||||||
|
|||||||
+22
-22
@@ -1,28 +1,28 @@
|
|||||||
meta:
|
meta:
|
||||||
title: "은퇴자산포트폴리오 — 리스크 정책 호환 인덱스 (redirect-only)"
|
title: 은퇴자산포트폴리오 — 리스크 정책 호환 인덱스 (redirect-only)
|
||||||
parent_file: "RetirementAssetPortfolio.yaml"
|
parent_file: RetirementAssetPortfolio.yaml
|
||||||
version: "2026-05-17-phase3_redirect_clarified"
|
version: 2026-05-17-phase3_redirect_clarified
|
||||||
language: "ko-KR"
|
language: ko-KR
|
||||||
timezone: "Asia/Seoul"
|
timezone: Asia/Seoul
|
||||||
role: "deprecated_redirect"
|
role: deprecated_redirect
|
||||||
warning: >
|
warning: '이 파일은 경로 호환성 유지 전용입니다. 새 규칙·임계값 추가 금지. 실제 리스크 규칙은 아래 canonical_split_files를
|
||||||
이 파일은 경로 호환성 유지 전용입니다. 새 규칙·임계값 추가 금지.
|
직접 참조하십시오.
|
||||||
실제 리스크 규칙은 아래 canonical_split_files를 직접 참조하십시오.
|
|
||||||
|
|
||||||
|
'
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\03_risk_policy.yaml
|
||||||
canonical_split_files:
|
canonical_split_files:
|
||||||
portfolio_exposure_framework: "spec/risk/portfolio_exposure.yaml"
|
portfolio_exposure_framework: spec/risk/portfolio_exposure.yaml
|
||||||
risk_control: "spec/risk/risk_control.yaml"
|
risk_control: spec/risk/risk_control.yaml
|
||||||
quality_control: "spec/risk/quality_control.yaml"
|
quality_control: spec/risk/quality_control.yaml
|
||||||
|
|
||||||
legacy_path_aliases:
|
legacy_path_aliases:
|
||||||
"spec/03_risk_policy.yaml:portfolio_exposure_framework": "spec/risk/portfolio_exposure.yaml:portfolio_exposure_framework"
|
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: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:quality_control: spec/risk/quality_control.yaml:quality_control
|
||||||
|
|
||||||
migration_rule:
|
migration_rule:
|
||||||
- "신규 참조는 반드시 canonical_split_files의 경로를 사용한다."
|
- 신규 참조는 반드시 canonical_split_files의 경로를 사용한다.
|
||||||
- "기존 문서/예시에서 legacy path가 남아 있으면 alias로 해석하되, 수정 시 새 경로로 교체한다."
|
- 기존 문서/예시에서 legacy path가 남아 있으면 alias로 해석하되, 수정 시 새 경로로 교체한다.
|
||||||
- "이 파일에는 수치 임계값을 추가하지 않는다."
|
- 이 파일에는 수치 임계값을 추가하지 않는다.
|
||||||
|
|
||||||
validation:
|
validation:
|
||||||
- "python tools/validate_specs.py"
|
- python tools/validate_specs.py
|
||||||
|
|||||||
+26
-26
@@ -1,32 +1,32 @@
|
|||||||
meta:
|
meta:
|
||||||
title: "은퇴자산포트폴리오 — 전략 규칙 호환 인덱스 (redirect-only)"
|
title: 은퇴자산포트폴리오 — 전략 규칙 호환 인덱스 (redirect-only)
|
||||||
parent_file: "RetirementAssetPortfolio.yaml"
|
parent_file: RetirementAssetPortfolio.yaml
|
||||||
version: "2026-05-17-phase3_redirect_clarified"
|
version: 2026-05-17-phase3_redirect_clarified
|
||||||
language: "ko-KR"
|
language: ko-KR
|
||||||
timezone: "Asia/Seoul"
|
timezone: Asia/Seoul
|
||||||
role: "deprecated_redirect"
|
role: deprecated_redirect
|
||||||
warning: >
|
warning: '이 파일은 경로 호환성 유지 전용입니다. 새 규칙·임계값 추가 금지. 실제 전략 규칙은 아래 canonical_split_files를
|
||||||
이 파일은 경로 호환성 유지 전용입니다. 새 규칙·임계값 추가 금지.
|
직접 참조하십시오.
|
||||||
실제 전략 규칙은 아래 canonical_split_files를 직접 참조하십시오.
|
|
||||||
|
|
||||||
|
'
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\04_strategy_rules.yaml
|
||||||
canonical_split_files:
|
canonical_split_files:
|
||||||
sector_model: "spec/strategy/sector_model.yaml"
|
sector_model: spec/strategy/sector_model.yaml
|
||||||
entry_timing_guardrails: "spec/strategy/entry_gates.yaml"
|
entry_timing_guardrails: spec/strategy/entry_gates.yaml
|
||||||
anti_late_trade_rule: "spec/strategy/entry_gates.yaml"
|
anti_late_trade_rule: spec/strategy/entry_gates.yaml
|
||||||
stock_model: "spec/strategy/stock_model.yaml"
|
stock_model: spec/strategy/stock_model.yaml
|
||||||
rebalancing_trigger: "spec/strategy/rebalancing_trigger.yaml"
|
rebalancing_trigger: spec/strategy/rebalancing_trigger.yaml
|
||||||
|
|
||||||
legacy_path_aliases:
|
legacy_path_aliases:
|
||||||
"spec/04_strategy_rules.yaml:sector_model": "spec/strategy/sector_model.yaml:sector_model"
|
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: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: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: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:rebalancing_trigger: spec/strategy/rebalancing_trigger.yaml:rebalancing_trigger
|
||||||
|
|
||||||
migration_rule:
|
migration_rule:
|
||||||
- "신규 참조는 반드시 canonical_split_files의 경로를 사용한다."
|
- 신규 참조는 반드시 canonical_split_files의 경로를 사용한다.
|
||||||
- "기존 문서/예시에서 legacy path가 남아 있으면 alias로 해석하되, 수정 시 새 경로로 교체한다."
|
- 기존 문서/예시에서 legacy path가 남아 있으면 alias로 해석하되, 수정 시 새 경로로 교체한다.
|
||||||
- "이 파일에는 수치 임계값을 추가하지 않는다."
|
- 이 파일에는 수치 임계값을 추가하지 않는다.
|
||||||
|
|
||||||
validation:
|
validation:
|
||||||
- "python tools/validate_specs.py"
|
- python tools/validate_specs.py
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ meta:
|
|||||||
language: ko-KR
|
language: ko-KR
|
||||||
timezone: Asia/Seoul
|
timezone: Asia/Seoul
|
||||||
role: canonical
|
role: canonical
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path: spec/14_raw_workbook_mapping.yaml
|
||||||
purpose: 'LLM이 동일 필드를 여러 이름으로 해석하지 않도록 canonical field, alias, 타입, 단위, 누락 정책을 고정한다.
|
purpose: 'LLM이 동일 필드를 여러 이름으로 해석하지 않도록 canonical field, alias, 타입, 단위, 누락 정책을 고정한다.
|
||||||
알고리즘 파일은 이 사전의 canonical_name을 사용한다.
|
알고리즘 파일은 이 사전의 canonical_name을 사용한다.
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ meta:
|
|||||||
language: ko-KR
|
language: ko-KR
|
||||||
timezone: Asia/Seoul
|
timezone: Asia/Seoul
|
||||||
role: canonical
|
role: canonical
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path: tools/validate_formula_version_lifecycle_v1.py
|
||||||
purpose: '핵심 투자 알고리즘을 LLM이 반복 계산할 수 있도록 공식의 입력, 출력, 단위, 누락 처리, 차단 조건을 구조화한다.
|
purpose: '핵심 투자 알고리즘을 LLM이 반복 계산할 수 있도록 공식의 입력, 출력, 단위, 누락 처리, 차단 조건을 구조화한다.
|
||||||
|
|
||||||
'
|
'
|
||||||
|
|||||||
+3285
-2501
File diff suppressed because it is too large
Load Diff
+619
-610
File diff suppressed because it is too large
Load Diff
@@ -5,6 +5,8 @@ meta:
|
|||||||
language: "ko-KR"
|
language: "ko-KR"
|
||||||
timezone: "Asia/Seoul"
|
timezone: "Asia/Seoul"
|
||||||
role: "canonical"
|
role: "canonical"
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path: ["tools/build_honest_performance_guard_v1.py", "src/quant_engine/qualitative_sell_strategy_v1.py"]
|
||||||
purpose: >
|
purpose: >
|
||||||
Google Sheets 'performance' 탭의 구조·입력 규칙을 정의하고,
|
Google Sheets 'performance' 탭의 구조·입력 규칙을 정의하고,
|
||||||
GAS가 이 데이터를 읽어 Bayesian multiplier를 자동 계산하는 계약을 명시한다.
|
GAS가 이 데이터를 읽어 Bayesian multiplier를 자동 계산하는 계약을 명시한다.
|
||||||
|
|||||||
+281
-305
@@ -1,314 +1,290 @@
|
|||||||
meta:
|
meta:
|
||||||
title: "은퇴자산포트폴리오 — GAS 수치 출력 의무 스키마"
|
title: 은퇴자산포트폴리오 — GAS 수치 출력 의무 스키마
|
||||||
version: "2026-05-22-V1.0-NUMERIC"
|
version: 2026-05-22-V1.0-NUMERIC
|
||||||
purpose: >
|
purpose: 'YAML 스펙은 의도 문서이고, LLM 텍스트 판단은 매번 다른 결과를 낸다. 이 파일은 GAS가 반드시 숫자로 채워야 할 harness_context
|
||||||
YAML 스펙은 의도 문서이고, LLM 텍스트 판단은 매번 다른 결과를 낸다.
|
필드를 정의한다. measure_harness_coverage.py 가 이 스키마를 기준으로 커버리지를 측정한다. 필드가 공백이면 LLM이
|
||||||
이 파일은 GAS가 반드시 숫자로 채워야 할 harness_context 필드를 정의한다.
|
추정 = 랜덤성 원천 = 정보 가치 없음.
|
||||||
measure_harness_coverage.py 가 이 스키마를 기준으로 커버리지를 측정한다.
|
|
||||||
필드가 공백이면 LLM이 추정 = 랜덤성 원천 = 정보 가치 없음.
|
|
||||||
|
|
||||||
|
'
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\20_harness_output_schema.yaml
|
||||||
principle:
|
principle:
|
||||||
- "하네스가 계산하지 않은 숫자는 정보가 아니다. 텍스트 추정은 매번 다르다."
|
- 하네스가 계산하지 않은 숫자는 정보가 아니다. 텍스트 추정은 매번 다르다.
|
||||||
- "GAS가 산출한 숫자만 ground_truth. LLM 출력과 불일치 시 CRITICAL_EXECUTION_FAILURE."
|
- GAS가 산출한 숫자만 ground_truth. LLM 출력과 불일치 시 CRITICAL_EXECUTION_FAILURE.
|
||||||
- "커버리지 목표: 100%. 공백 필드 수 = LLM 자유도 = 재현성 위험."
|
- '커버리지 목표: 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이 취할 수 있는 유일한 행동
|
|
||||||
# ──────────────────────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
mandatory_numeric_outputs:
|
mandatory_numeric_outputs:
|
||||||
|
- gas_field: intraday_lock
|
||||||
# ── STAGE 0: 데이터 & 라우팅 ──────────────────────────────────────────────
|
type: bool
|
||||||
- gas_field: "intraday_lock"
|
formula: INTRADAY_ACTION_MATRIX_V1
|
||||||
type: bool
|
required: true
|
||||||
formula: "INTRADAY_ACTION_MATRIX_V1"
|
description: 장중 잠금 여부 — false이면 전략 전체 허용
|
||||||
required: true
|
llm_action: DATA_MISSING — 장중/장후 판단 중단
|
||||||
description: "장중 잠금 여부 — false이면 전략 전체 허용"
|
- gas_field: intraday_scope
|
||||||
llm_action: "DATA_MISSING — 장중/장후 판단 중단"
|
type: enum
|
||||||
|
formula: INTRADAY_ACTION_MATRIX_V1
|
||||||
- gas_field: "intraday_scope"
|
required: true
|
||||||
type: enum
|
allowed:
|
||||||
formula: "INTRADAY_ACTION_MATRIX_V1"
|
- FULL_STRATEGY
|
||||||
required: true
|
- TRIM_ONLY
|
||||||
allowed: ["FULL_STRATEGY", "TRIM_ONLY", "WATCH_ONLY"]
|
- WATCH_ONLY
|
||||||
description: "허용 전략 범위 — TRIM_ONLY 시 신규매수·전량매도 금지"
|
description: 허용 전략 범위 — TRIM_ONLY 시 신규매수·전량매도 금지
|
||||||
llm_action: "DATA_MISSING — 기본 TRIM_ONLY로 처리"
|
llm_action: DATA_MISSING — 기본 TRIM_ONLY로 처리
|
||||||
|
- gas_field: settlement_cash_d2_krw
|
||||||
# ── STAGE 1: 포트폴리오 현금 & 열 ──────────────────────────────────────────
|
type: numeric
|
||||||
- gas_field: "settlement_cash_d2_krw"
|
formula: CASH_RATIOS_V1
|
||||||
type: numeric
|
required: true
|
||||||
formula: "CASH_RATIOS_V1"
|
range:
|
||||||
required: true
|
- 0
|
||||||
range: [0, 10_000_000_000]
|
- 10000000000
|
||||||
description: "D+2 정산현금(원) — 매수 가용 현금 기준"
|
description: D+2 정산현금(원) — 매수 가용 현금 기준
|
||||||
llm_action: "DATA_MISSING — 매수 금지"
|
llm_action: DATA_MISSING — 매수 금지
|
||||||
|
- gas_field: cash_shortfall_min_krw
|
||||||
- gas_field: "cash_shortfall_min_krw"
|
type: numeric
|
||||||
type: numeric
|
formula: CASH_RATIOS_V1
|
||||||
formula: "CASH_RATIOS_V1"
|
required: true
|
||||||
required: true
|
range:
|
||||||
range: [0, 10_000_000_000]
|
- 0
|
||||||
description: "현금 부족분(원) — 현금확보 매도 발동 기준"
|
- 10000000000
|
||||||
llm_action: "DATA_MISSING — 현금확보 매도 중단"
|
description: 현금 부족분(원) — 현금확보 매도 발동 기준
|
||||||
|
llm_action: DATA_MISSING — 현금확보 매도 중단
|
||||||
- gas_field: "total_heat_pct"
|
- gas_field: total_heat_pct
|
||||||
type: numeric
|
type: numeric
|
||||||
formula: "TOTAL_HEAT_V1"
|
formula: TOTAL_HEAT_V1
|
||||||
required: true
|
required: true
|
||||||
range: [0, 100]
|
range:
|
||||||
description: "포트폴리오 총 Heat(%) — 10% 초과 시 신규매수 전면 차단"
|
- 0
|
||||||
llm_action: "DATA_MISSING — 신규매수 차단"
|
- 100
|
||||||
|
description: 포트폴리오 총 Heat(%) — 10% 초과 시 신규매수 전면 차단
|
||||||
- gas_field: "heat_gate_status"
|
llm_action: DATA_MISSING — 신규매수 차단
|
||||||
type: enum
|
- gas_field: heat_gate_status
|
||||||
formula: "TOTAL_HEAT_V1"
|
type: enum
|
||||||
required: true
|
formula: TOTAL_HEAT_V1
|
||||||
allowed: ["PASS", "BLOCK_NEW_BUY", "HALVE_NEW_BUY_QUANTITY"]
|
required: true
|
||||||
description: "Heat 게이트 상태"
|
allowed:
|
||||||
llm_action: "DATA_MISSING — BLOCK_NEW_BUY 처리"
|
- PASS
|
||||||
|
- BLOCK_NEW_BUY
|
||||||
# ── STAGE 2: 손절·래칫 ────────────────────────────────────────────────────
|
- HALVE_NEW_BUY_QUANTITY
|
||||||
- gas_field: "profit_lock_stage"
|
description: Heat 게이트 상태
|
||||||
type: enum
|
llm_action: DATA_MISSING — BLOCK_NEW_BUY 처리
|
||||||
formula: "PROFIT_LOCK_RATCHET_V1"
|
- gas_field: profit_lock_stage
|
||||||
required: true
|
type: enum
|
||||||
per_ticker: true
|
formula: PROFIT_LOCK_RATCHET_V1
|
||||||
allowed:
|
required: true
|
||||||
- "NORMAL"
|
per_ticker: true
|
||||||
- "BREAKEVEN_RATCHET"
|
allowed:
|
||||||
- "PROFIT_LOCK_10"
|
- NORMAL
|
||||||
- "PROFIT_LOCK_20"
|
- BREAKEVEN_RATCHET
|
||||||
- "PROFIT_LOCK_30"
|
- PROFIT_LOCK_10
|
||||||
- "APEX_TRAILING"
|
- PROFIT_LOCK_20
|
||||||
- "APEX_SUPER"
|
- PROFIT_LOCK_30
|
||||||
- "SECULAR_LEADER_DEFERRED"
|
- APEX_TRAILING
|
||||||
description: "수익 구간 단계 — APEX_SUPER(+60%)이면 trailing_stop 병기 필수"
|
- APEX_SUPER
|
||||||
llm_action: "DATA_MISSING — trailing_stop 병기 불가"
|
- SECULAR_LEADER_DEFERRED
|
||||||
criticality: "HIGH — APEX_SUPER 미판정 시 +60% 수익 종목에 보유유지만 서술하게 됨"
|
description: 수익 구간 단계 — APEX_SUPER(+60%)이면 trailing_stop 병기 필수
|
||||||
|
llm_action: DATA_MISSING — trailing_stop 병기 불가
|
||||||
- gas_field: "auto_trailing_stop_v2"
|
criticality: HIGH — APEX_SUPER 미판정 시 +60% 수익 종목에 보유유지만 서술하게 됨
|
||||||
type: numeric
|
- gas_field: auto_trailing_stop_v2
|
||||||
formula: "PROFIT_RATCHET_TIERED_V2"
|
type: numeric
|
||||||
required: false
|
formula: PROFIT_RATCHET_TIERED_V2
|
||||||
per_ticker: true
|
required: false
|
||||||
description: "ATR×1.2 기반 APEX_SUPER 자동 trailing stop(원)"
|
per_ticker: true
|
||||||
note: "profit_lock_stage >= PROFIT_LOCK_20 일 때만 산출 (null이면 적용 안함)"
|
description: ATR×1.2 기반 APEX_SUPER 자동 trailing stop(원)
|
||||||
llm_action: "DATA_MISSING — trailing_stop 병기 불가. 보유유지 단독 서술 허용되어 수익 보호 실패"
|
note: profit_lock_stage >= PROFIT_LOCK_20 일 때만 산출 (null이면 적용 안함)
|
||||||
criticality: "CRITICAL — 삼성전자 +61.5% 사례(E3)에서 미산출로 수익 보호 실패"
|
llm_action: DATA_MISSING — trailing_stop 병기 불가. 보유유지 단독 서술 허용되어 수익 보호 실패
|
||||||
|
criticality: CRITICAL — 삼성전자 +61.5% 사례(E3)에서 미산출로 수익 보호 실패
|
||||||
# ── STAGE 3: 설거지 감지 ──────────────────────────────────────────────────
|
- gas_field: distribution_sell_detector_status
|
||||||
- gas_field: "distribution_sell_detector_status"
|
type: enum
|
||||||
type: enum
|
formula: DISTRIBUTION_SELL_DETECTOR_V1
|
||||||
formula: "DISTRIBUTION_SELL_DETECTOR_V1"
|
required: true
|
||||||
required: true
|
per_ticker: true
|
||||||
per_ticker: true
|
allowed:
|
||||||
allowed: ["DISTRIBUTION_CONFIRMED", "DISTRIBUTION_WARNING", "DISTRIBUTION_CLEAR"]
|
- DISTRIBUTION_CONFIRMED
|
||||||
description: "설거지 6신호 합산 감지 상태 — CONFIRMED 시 BUY 완전 차단"
|
- DISTRIBUTION_WARNING
|
||||||
llm_action: "DATA_MISSING — '오를 것 같다' 주관 판단으로 매수 → 설거지 진입 위험"
|
- DISTRIBUTION_CLEAR
|
||||||
criticality: "HIGH"
|
description: 설거지 6신호 합산 감지 상태 — CONFIRMED 시 BUY 완전 차단
|
||||||
|
llm_action: DATA_MISSING — '오를 것 같다' 주관 판단으로 매수 → 설거지 진입 위험
|
||||||
# ── STAGE 4: 매수 게이트 ──────────────────────────────────────────────────
|
criticality: HIGH
|
||||||
- gas_field: "anti_chasing_verdict"
|
- gas_field: anti_chasing_verdict
|
||||||
type: enum
|
type: enum
|
||||||
formula: "ANTI_CHASING_VELOCITY_V1"
|
formula: ANTI_CHASING_VELOCITY_V1
|
||||||
required: true
|
required: true
|
||||||
per_ticker: true
|
per_ticker: true
|
||||||
allowed: ["BLOCK_CHASE", "PULLBACK_WAIT", "CLEAR"]
|
allowed:
|
||||||
description: "당일 속도 기반 뒷박 추격 차단 — BLOCK_CHASE 시 당일 BUY 금지"
|
- BLOCK_CHASE
|
||||||
llm_action: "DATA_MISSING — velocity_1d 미계산으로 뒷박 추격 매수 허용"
|
- PULLBACK_WAIT
|
||||||
criticality: "CRITICAL — 뒷박 매수는 진입 당일 고점. 실패의 주원인."
|
- CLEAR
|
||||||
|
description: 당일 속도 기반 뒷박 추격 차단 — BLOCK_CHASE 시 당일 BUY 금지
|
||||||
- gas_field: "pullback_entry_trigger_price"
|
llm_action: DATA_MISSING — velocity_1d 미계산으로 뒷박 추격 매수 허용
|
||||||
type: numeric
|
criticality: CRITICAL — 뒷박 매수는 진입 당일 고점. 실패의 주원인.
|
||||||
formula: "PULLBACK_ENTRY_TRIGGER_V1"
|
- gas_field: pullback_entry_trigger_price
|
||||||
required: false
|
type: numeric
|
||||||
per_ticker: true
|
formula: PULLBACK_ENTRY_TRIGGER_V1
|
||||||
description: "눌림목 허용 기준가(원) = MA20 - 0.5×ATR20, tick 정규화"
|
required: false
|
||||||
note: "PULLBACK_WAIT 상태일 때만 유효"
|
per_ticker: true
|
||||||
llm_action: "DATA_MISSING — '가격이 괜찮아 보이면' 즉시 매수 → 눌림목 미확인 진입"
|
description: 눌림목 허용 기준가(원) = MA20 - 0.5×ATR20, tick 정규화
|
||||||
criticality: "HIGH"
|
note: PULLBACK_WAIT 상태일 때만 유효
|
||||||
|
llm_action: DATA_MISSING — '가격이 괜찮아 보이면' 즉시 매수 → 눌림목 미확인 진입
|
||||||
# ── STAGE 5: 현금확보 매도 ────────────────────────────────────────────────
|
criticality: HIGH
|
||||||
- gas_field: "cash_recovery_plan_json"
|
- gas_field: cash_recovery_plan_json
|
||||||
type: json
|
type: json
|
||||||
formula: "CASH_RECOVERY_OPTIMIZER_V1"
|
formula: CASH_RECOVERY_OPTIMIZER_V1
|
||||||
required: true
|
required: true
|
||||||
condition: "cash_shortfall_min_krw > 0"
|
condition: cash_shortfall_min_krw > 0
|
||||||
description: "현금부족 최적 매도조합 JSON — H2 우선순위 기반 결정론적 산출"
|
description: 현금부족 최적 매도조합 JSON — H2 우선순위 기반 결정론적 산출
|
||||||
schema:
|
schema:
|
||||||
sell_sequence: "array of {ticker, qty, limit_price, expected_krw}"
|
sell_sequence: array of {ticker, qty, limit_price, expected_krw}
|
||||||
expected_total_krw: "numeric"
|
expected_total_krw: numeric
|
||||||
shortfall_met: "boolean"
|
shortfall_met: boolean
|
||||||
llm_action: "DATA_MISSING — LLM이 '삼성E&A 100주+한화에어로 50주' 즉석 계산 → HS011 위반"
|
llm_action: DATA_MISSING — LLM이 '삼성E&A 100주+한화에어로 50주' 즉석 계산 → HS011 위반
|
||||||
criticality: "CRITICAL — 현금확보 매도 조합이 LLM마다 달라짐"
|
criticality: CRITICAL — 현금확보 매도 조합이 LLM마다 달라짐
|
||||||
|
- gas_field: waterfall_plan_json
|
||||||
- gas_field: "waterfall_plan_json"
|
type: json
|
||||||
type: json
|
formula: SELL_WATERFALL_ENGINE_V1
|
||||||
formula: "SELL_WATERFALL_ENGINE_V1"
|
required: true
|
||||||
required: true
|
condition: cash_shortfall_min_krw > 0
|
||||||
condition: "cash_shortfall_min_krw > 0"
|
description: 4단계 폭포수 매도 계획 JSON
|
||||||
description: "4단계 폭포수 매도 계획 JSON"
|
schema:
|
||||||
schema:
|
current_stage: int 1~4
|
||||||
current_stage: "int 1~4"
|
stage_label: enum [IMMEDIATE_TRIM,REBOUND_WAIT,CASCADING_TRIM,EMERGENCY_EXIT]
|
||||||
stage_label: "enum [IMMEDIATE_TRIM,REBOUND_WAIT,CASCADING_TRIM,EMERGENCY_EXIT]"
|
sell_sequence: array of {ticker, stage, qty, limit_price, rebound_trigger_price}
|
||||||
sell_sequence: "array of {ticker, stage, qty, limit_price, rebound_trigger_price}"
|
llm_action: DATA_MISSING — stage 순서 없이 즉흥 매도 → 주식가치 훼손
|
||||||
llm_action: "DATA_MISSING — stage 순서 없이 즉흥 매도 → 주식가치 훼손"
|
criticality: HIGH
|
||||||
criticality: "HIGH"
|
- gas_field: preservation_verdict
|
||||||
|
type: enum
|
||||||
- gas_field: "preservation_verdict"
|
formula: SELL_VALUE_PRESERVATION_TIERED_V2
|
||||||
type: enum
|
required: true
|
||||||
formula: "SELL_VALUE_PRESERVATION_TIERED_V2"
|
per_ticker: true
|
||||||
required: true
|
condition: Final_Action in [SELL_READY, TRIM]
|
||||||
per_ticker: true
|
allowed:
|
||||||
condition: "Final_Action in [SELL_READY, TRIM]"
|
- EMERGENCY_EXIT
|
||||||
allowed:
|
- OVERSOLD_REBOUND_SELL
|
||||||
- "EMERGENCY_EXIT"
|
- APEX_TRIM
|
||||||
- "OVERSOLD_REBOUND_SELL"
|
- STAGED_EXIT
|
||||||
- "APEX_TRIM"
|
- PRESERVE_TIERED
|
||||||
- "STAGED_EXIT"
|
- HOLD
|
||||||
- "PRESERVE_TIERED"
|
description: 주식가치 보호 매도 결정 — HOLD 외에는 구체 계획 필수
|
||||||
- "HOLD"
|
llm_action: DATA_MISSING — 무작위 매도 스타일 서술
|
||||||
description: "주식가치 보호 매도 결정 — HOLD 외에는 구체 계획 필수"
|
criticality: MEDIUM
|
||||||
llm_action: "DATA_MISSING — 무작위 매도 스타일 서술"
|
- gas_field: sell_price_sanity_status
|
||||||
criticality: "MEDIUM"
|
type: enum
|
||||||
|
formula: SELL_PRICE_SANITY_V1
|
||||||
# ── STAGE 6: 가격 검증 ────────────────────────────────────────────────────
|
required: true
|
||||||
- gas_field: "sell_price_sanity_status"
|
per_ticker: true
|
||||||
type: enum
|
condition: Final_Action in [SELL_READY, TRIM, EXIT_100]
|
||||||
formula: "SELL_PRICE_SANITY_V1"
|
allowed:
|
||||||
required: true
|
- PASS
|
||||||
per_ticker: true
|
- INVALID_PRICE_INVERSION
|
||||||
condition: "Final_Action in [SELL_READY, TRIM, EXIT_100]"
|
- INVALID_UNREALISTIC_PRICE
|
||||||
allowed: ["PASS", "INVALID_PRICE_INVERSION", "INVALID_UNREALISTIC_PRICE", "INVALID_TICK"]
|
- INVALID_TICK
|
||||||
description: "매도가 역전·비현실가 검증 — INVALID 시 HTS 주문표 제거"
|
description: 매도가 역전·비현실가 검증 — INVALID 시 HTS 주문표 제거
|
||||||
llm_action: "DATA_MISSING — LS Electric 사례처럼 역전 가격이 HTS 주문표에 그대로 들어감"
|
llm_action: DATA_MISSING — LS Electric 사례처럼 역전 가격이 HTS 주문표에 그대로 들어감
|
||||||
criticality: "CRITICAL — 실제 손실 오류 E1의 직접 원인"
|
criticality: CRITICAL — 실제 손실 오류 E1의 직접 원인
|
||||||
|
- gas_field: prices_json
|
||||||
# ── STAGE 6: HTS 주문 잠금 ────────────────────────────────────────────────
|
type: json
|
||||||
- gas_field: "prices_json"
|
formula: PRICES_LOCK
|
||||||
type: json
|
required: true
|
||||||
formula: "PRICES_LOCK"
|
description: 종목별 stop_price, tp1_price, tp2_price JSON — LLM 재계산 금지
|
||||||
required: true
|
schema:
|
||||||
description: "종목별 stop_price, tp1_price, tp2_price JSON — LLM 재계산 금지"
|
stop_price: numeric KRW
|
||||||
schema:
|
tp1_price: numeric KRW or null
|
||||||
stop_price: "numeric KRW"
|
tp2_price: numeric KRW or null
|
||||||
tp1_price: "numeric KRW or null"
|
profit_lock_stage: enum
|
||||||
tp2_price: "numeric KRW or null"
|
llm_action: DATA_MISSING — LLM이 차트 지지선으로 손절가 임의 추정 → 매번 다른 값
|
||||||
profit_lock_stage: "enum"
|
criticality: CRITICAL — 수량·가격 기반 모든 주문이 불확실해짐
|
||||||
llm_action: "DATA_MISSING — LLM이 차트 지지선으로 손절가 임의 추정 → 매번 다른 값"
|
- gas_field: sell_quantities_json
|
||||||
criticality: "CRITICAL — 수량·가격 기반 모든 주문이 불확실해짐"
|
type: json
|
||||||
|
formula: QUANTITIES_LOCK
|
||||||
- gas_field: "sell_quantities_json"
|
required: true
|
||||||
type: json
|
description: 종목별 매도 수량 잠금 JSON
|
||||||
formula: "QUANTITIES_LOCK"
|
llm_action: DATA_MISSING — LLM이 '적절한 수량으로' 즉흥 계산
|
||||||
required: true
|
criticality: CRITICAL
|
||||||
description: "종목별 매도 수량 잠금 JSON"
|
- gas_field: order_blueprint_json
|
||||||
llm_action: "DATA_MISSING — LLM이 '적절한 수량으로' 즉흥 계산"
|
type: json
|
||||||
criticality: "CRITICAL"
|
formula: ORDER_BLUEPRINT
|
||||||
|
required: true
|
||||||
- gas_field: "order_blueprint_json"
|
description: HTS 주문 청사진 JSON — validation_status=PASS만 HTS 입력 허용
|
||||||
type: json
|
llm_action: DATA_MISSING — Shadow Ledger / HTS 주문표 분리 불가
|
||||||
formula: "ORDER_BLUEPRINT"
|
criticality: CRITICAL
|
||||||
required: true
|
- gas_field: rs_verdict
|
||||||
description: "HTS 주문 청사진 JSON — validation_status=PASS만 HTS 입력 허용"
|
type: enum
|
||||||
llm_action: "DATA_MISSING — Shadow Ledger / HTS 주문표 분리 불가"
|
formula: RS_VERDICT_V2
|
||||||
criticality: "CRITICAL"
|
required: true
|
||||||
|
per_ticker: true
|
||||||
# ── STAGE 7: RS 판정 ──────────────────────────────────────────────────────
|
allowed:
|
||||||
- gas_field: "rs_verdict"
|
- LEADER
|
||||||
type: enum
|
- NEUTRAL
|
||||||
formula: "RS_VERDICT_V2"
|
- LAGGARD
|
||||||
required: true
|
- BROKEN
|
||||||
per_ticker: true
|
description: 최종 상대강도 판정 — BROKEN 시 매도 우선순위 최상위
|
||||||
allowed: ["LEADER", "NEUTRAL", "LAGGARD", "BROKEN"]
|
llm_action: DATA_MISSING — '차트가 좋아 보이면 LEADER' 주관 판단
|
||||||
description: "최종 상대강도 판정 — BROKEN 시 매도 우선순위 최상위"
|
criticality: HIGH
|
||||||
llm_action: "DATA_MISSING — '차트가 좋아 보이면 LEADER' 주관 판단"
|
- gas_field: trade_quality_json
|
||||||
criticality: "HIGH"
|
type: json
|
||||||
|
formula: TRADE_QUALITY_SCORER_V1
|
||||||
# ── MONTHLY BATCH ──────────────────────────────────────────────────────────
|
required: false
|
||||||
- gas_field: "trade_quality_json"
|
batch_only: true
|
||||||
type: json
|
description: T+5/T+20 거래 품질 채점 결과 — POOR/CRITICAL 누적 블랙리스트 발동
|
||||||
formula: "TRADE_QUALITY_SCORER_V1"
|
schema:
|
||||||
required: false
|
ticker: string
|
||||||
batch_only: true
|
score: int 0~100
|
||||||
description: "T+5/T+20 거래 품질 채점 결과 — POOR/CRITICAL 누적 블랙리스트 발동"
|
grade: enum [EXCELLENT,GOOD,ACCEPTABLE,POOR,CRITICAL]
|
||||||
schema:
|
feedback_tag: enum
|
||||||
ticker: "string"
|
llm_action: DATA_MISSING — 'POOR 매매였지만 이번엔 다르다' 무근거 판단
|
||||||
score: "int 0~100"
|
criticality: MEDIUM — 반복 실수 패턴 차단 불가
|
||||||
grade: "enum [EXCELLENT,GOOD,ACCEPTABLE,POOR,CRITICAL]"
|
|
||||||
feedback_tag: "enum"
|
|
||||||
llm_action: "DATA_MISSING — 'POOR 매매였지만 이번엔 다르다' 무근거 판단"
|
|
||||||
criticality: "MEDIUM — 반복 실수 패턴 차단 불가"
|
|
||||||
|
|
||||||
# ──────────────────────────────────────────────────────────────────────────────
|
|
||||||
# 커버리지 임계값
|
|
||||||
# ──────────────────────────────────────────────────────────────────────────────
|
|
||||||
coverage_thresholds:
|
coverage_thresholds:
|
||||||
critical_fields_target_pct: 100 # CRITICAL 필드는 100% 필수
|
critical_fields_target_pct: 100
|
||||||
overall_target_pct: 85 # 전체 목표 커버리지
|
overall_target_pct: 85
|
||||||
llm_freedom_score_max: 15 # LLM 자유도 15% 이하 목표
|
llm_freedom_score_max: 15
|
||||||
|
|
||||||
grade_table:
|
grade_table:
|
||||||
100: {grade: "DETERMINISTIC", label: "완전 결정론적 — 이상적 상태"}
|
100:
|
||||||
85_99: {grade: "NEAR_FULL", label: "거의 결정론적 — 배치 필드만 미계산"}
|
grade: DETERMINISTIC
|
||||||
60_84: {grade: "PARTIAL", label: "부분 결정론적 — GAS 구현 필요"}
|
label: 완전 결정론적 — 이상적 상태
|
||||||
0_59: {grade: "LLM_DEPENDENT", label: "LLM 의존 — 결과 재현 불가"}
|
8599:
|
||||||
|
grade: NEAR_FULL
|
||||||
# ──────────────────────────────────────────────────────────────────────────────
|
label: 거의 결정론적 — 배치 필드만 미계산
|
||||||
# 현재 GAS 구현 상태 (2026-05-22 기준)
|
6084:
|
||||||
# ──────────────────────────────────────────────────────────────────────────────
|
grade: PARTIAL
|
||||||
|
label: 부분 결정론적 — GAS 구현 필요
|
||||||
|
0_59:
|
||||||
|
grade: LLM_DEPENDENT
|
||||||
|
label: LLM 의존 — 결과 재현 불가
|
||||||
current_state:
|
current_state:
|
||||||
gas_version: "2026-05-19-X4R1"
|
gas_version: 2026-05-19-X4R1
|
||||||
overall_coverage_pct: 30 # 실측값 — measure_harness_coverage.py 참조
|
overall_coverage_pct: 30
|
||||||
llm_freedom_score: 70 # 100 - 30 = 70% → LLM 의존도 매우 높음
|
llm_freedom_score: 70
|
||||||
grade: "LLM_DEPENDENT"
|
grade: LLM_DEPENDENT
|
||||||
|
|
||||||
critical_gaps:
|
critical_gaps:
|
||||||
- field: "prices_json"
|
- field: prices_json
|
||||||
status: "EMPTY"
|
status: EMPTY
|
||||||
impact: "stop_price/tp_price 전부 LLM 추정 → 매 호출마다 다른 손절가"
|
impact: stop_price/tp_price 전부 LLM 추정 → 매 호출마다 다른 손절가
|
||||||
|
- field: sell_quantities_json
|
||||||
- field: "sell_quantities_json"
|
status: EMPTY
|
||||||
status: "EMPTY"
|
impact: 매도 수량 LLM 추정 → 매 호출마다 다른 수량
|
||||||
impact: "매도 수량 LLM 추정 → 매 호출마다 다른 수량"
|
- field: order_blueprint_json
|
||||||
|
status: EMPTY
|
||||||
- field: "order_blueprint_json"
|
impact: HTS 주문 청사진 없음 → Shadow Ledger 분리 불가
|
||||||
status: "EMPTY"
|
- field: anti_chasing_verdict
|
||||||
impact: "HTS 주문 청사진 없음 → Shadow Ledger 분리 불가"
|
status: MISSING
|
||||||
|
impact: 뒷박 추격 매수 차단 미작동 → 진입 당일 고점 손실 반복
|
||||||
- field: "anti_chasing_verdict"
|
- field: sell_price_sanity_status
|
||||||
status: "MISSING"
|
status: MISSING
|
||||||
impact: "뒷박 추격 매수 차단 미작동 → 진입 당일 고점 손실 반복"
|
impact: LS Electric 사례(E1) 재발 — 역전 매도가 HTS 입력 허용
|
||||||
|
- field: auto_trailing_stop_v2
|
||||||
- field: "sell_price_sanity_status"
|
status: MISSING
|
||||||
status: "MISSING"
|
impact: 삼성전자 +61.5% 사례(E3) 재발 — APEX_SUPER trailing_stop 미병기
|
||||||
impact: "LS Electric 사례(E1) 재발 — 역전 매도가 HTS 입력 허용"
|
- field: rs_verdict
|
||||||
|
status: MISSING
|
||||||
- field: "auto_trailing_stop_v2"
|
impact: RS_VERDICT_V2 미산출 → H2 매도 우선순위 BROKEN 판정 불가
|
||||||
status: "MISSING"
|
- field: cash_recovery_plan_json
|
||||||
impact: "삼성전자 +61.5% 사례(E3) 재발 — APEX_SUPER trailing_stop 미병기"
|
status: MISSING
|
||||||
|
impact: 현금확보 매도조합 LLM 즉석 계산 → HS011 위반 반복 (E2)
|
||||||
- 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:
|
next_gas_implementation_priority:
|
||||||
1: "prices_json — stop_price, tp_price 실제 계산 및 채우기"
|
1: prices_json — stop_price, tp_price 실제 계산 및 채우기
|
||||||
2: "sell_quantities_json — Sell_Qty 실제 수량 채우기"
|
2: sell_quantities_json — Sell_Qty 실제 수량 채우기
|
||||||
3: "order_blueprint_json — HTS 주문 청사진 생성"
|
3: order_blueprint_json — HTS 주문 청사진 생성
|
||||||
4: "anti_chasing_verdict — velocity_1d 계산 + 차단 판정"
|
4: anti_chasing_verdict — velocity_1d 계산 + 차단 판정
|
||||||
5: "sell_price_sanity_status — 역전/비현실가 검증"
|
5: sell_price_sanity_status — 역전/비현실가 검증
|
||||||
6: "auto_trailing_stop_v2 — ATR×1.2 APEX_SUPER trailing"
|
6: auto_trailing_stop_v2 — ATR×1.2 APEX_SUPER trailing
|
||||||
7: "rs_verdict — RS_VERDICT_V2 실제 산출"
|
7: rs_verdict — RS_VERDICT_V2 실제 산출
|
||||||
8: "cash_recovery_plan_json — H2 순서 누적 매도조합"
|
8: cash_recovery_plan_json — H2 순서 누적 매도조합
|
||||||
|
|||||||
@@ -1,70 +1,70 @@
|
|||||||
meta:
|
meta:
|
||||||
title: "Harness Governance Contract"
|
title: Harness Governance Contract
|
||||||
version: "2026-05-22-v1"
|
version: 2026-05-22-v1
|
||||||
purpose: "하네스 준수 강제: 문서 지침 + 검증기 + 실행 게이트의 3중 잠금"
|
purpose: '하네스 준수 강제: 문서 지침 + 검증기 + 실행 게이트의 3중 잠금'
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\21_harness_governance_contract.yaml
|
||||||
governance:
|
governance:
|
||||||
required_layers:
|
required_layers:
|
||||||
- name: "static_guide"
|
- name: static_guide
|
||||||
required_files:
|
required_files:
|
||||||
- "AGENTS.md"
|
- AGENTS.md
|
||||||
- "spec/07_output_schema.yaml"
|
- spec/07_output_schema.yaml
|
||||||
- "spec/19_harness_contract.yaml"
|
- spec/19_harness_contract.yaml
|
||||||
- name: "machine_validation"
|
- name: machine_validation
|
||||||
required_validators:
|
required_validators:
|
||||||
- "tools/validate_specs.py"
|
- tools/validate_specs.py
|
||||||
- "tools/validate_harness_context.py"
|
- tools/validate_harness_context.py
|
||||||
- "tools/validate_report_quality.py"
|
- tools/validate_report_quality.py
|
||||||
- name: "execution_gate"
|
- name: execution_gate
|
||||||
required_runners:
|
required_runners:
|
||||||
- "tools/validate_engine_harness_gate.py"
|
- tools/validate_engine_harness_gate.py
|
||||||
- "tools/run_engine_harness_gate.ps1"
|
- tools/run_engine_harness_gate.ps1
|
||||||
- "tools/run_yolo_full_cycle.ps1"
|
- tools/run_yolo_full_cycle.ps1
|
||||||
|
|
||||||
hardlocks:
|
hardlocks:
|
||||||
- id: "HG001"
|
- id: HG001
|
||||||
rule: "coverage_strict_100_required"
|
rule: coverage_strict_100_required
|
||||||
fail_condition: "measure_harness_coverage --strict-100 미통과"
|
fail_condition: measure_harness_coverage --strict-100 미통과
|
||||||
- id: "HG002"
|
- id: HG002
|
||||||
rule: "watch_transparency_required"
|
rule: watch_transparency_required
|
||||||
fail_condition: "WATCH_LEDGER_OK 미충족"
|
fail_condition: WATCH_LEDGER_OK 미충족
|
||||||
- id: "HG003"
|
- id: HG003
|
||||||
rule: "satellite_proposal_sheet_required"
|
rule: satellite_proposal_sheet_required
|
||||||
fail_condition: "SATELLITE_PROPOSAL_SHEET_OK 미충족"
|
fail_condition: SATELLITE_PROPOSAL_SHEET_OK 미충족
|
||||||
- id: "HG004"
|
- id: HG004
|
||||||
rule: "strategy_harness_required"
|
rule: strategy_harness_required
|
||||||
fail_condition: "STRATEGY_HARNESS_V2_OK 미충족"
|
fail_condition: STRATEGY_HARNESS_V2_OK 미충족
|
||||||
|
|
||||||
gate_validity_rules:
|
gate_validity_rules:
|
||||||
NON_VACUOUS_PASS_GUARD_V1:
|
NON_VACUOUS_PASS_GUARD_V1:
|
||||||
formula_id: NON_VACUOUS_PASS_GUARD_V1
|
formula_id: NON_VACUOUS_PASS_GUARD_V1
|
||||||
rationale: >
|
rationale: 'row_count=0 또는 sample_n < min_samples 인데 gate=PASS인 항목은 점수 분자를 부풀린다.
|
||||||
row_count=0 또는 sample_n < min_samples 인데 gate=PASS인 항목은
|
effective_n 미달 게이트는 WATCH_PENDING_SAMPLE로 강제 강등.
|
||||||
점수 분자를 부풀린다. effective_n 미달 게이트는 WATCH_PENDING_SAMPLE로 강제 강등.
|
|
||||||
|
'
|
||||||
min_samples_default: 30
|
min_samples_default: 30
|
||||||
min_samples_exceptions:
|
min_samples_exceptions:
|
||||||
rebound_efficiency_score: 30 # 이전 4 → 30으로 상향
|
rebound_efficiency_score: 30
|
||||||
late_rebound_bucket_score: 30
|
late_rebound_bucket_score: 30
|
||||||
enforcement:
|
enforcement:
|
||||||
- "effective_n < min_samples 이면 gate를 PASS로 둘 수 없다"
|
- effective_n < min_samples 이면 gate를 PASS로 둘 수 없다
|
||||||
- "강등된 게이트는 release/pass_100 집계 분자(PASS count)에 포함 금지"
|
- 강등된 게이트는 release/pass_100 집계 분자(PASS count)에 포함 금지
|
||||||
- "강등 라벨: WATCH_PENDING_SAMPLE"
|
- '강등 라벨: WATCH_PENDING_SAMPLE'
|
||||||
- "보고서 해당 셀에 '[PASS_INVALID_LOW_N: n={effective_n} < {min}]' 라벨 부착"
|
- '보고서 해당 셀에 ''[PASS_INVALID_LOW_N: n={effective_n} < {min}]'' 라벨 부착'
|
||||||
effective_n_fields:
|
effective_n_fields:
|
||||||
- sample_count
|
- sample_count
|
||||||
- row_count
|
- row_count
|
||||||
- evaluated_count
|
- evaluated_count
|
||||||
- samples
|
- samples
|
||||||
- n
|
- n
|
||||||
output:
|
output:
|
||||||
- Temp/vacuous_pass_audit_v1.json
|
- Temp/vacuous_pass_audit_v1.json
|
||||||
- operational_report.json.summary.vacuous_pass_gate_count
|
- operational_report.json.summary.vacuous_pass_gate_count
|
||||||
python_tool: tools/build_vacuous_pass_audit_v1.py
|
python_tool: tools/build_vacuous_pass_audit_v1.py
|
||||||
gs_coverage: "gas_apex_runtime_core.gs:guardNonVacuousPass_()"
|
gs_coverage: gas_apex_runtime_core.gs:guardNonVacuousPass_()
|
||||||
validator: "tools/validate_harness_governance_contract.py --check non_vacuous_pass"
|
validator: tools/validate_harness_governance_contract.py --check non_vacuous_pass
|
||||||
|
|
||||||
operations:
|
operations:
|
||||||
release_policy:
|
release_policy:
|
||||||
- "failed_checks 비어있지 않으면 배포/실행 차단"
|
- failed_checks 비어있지 않으면 배포/실행 차단
|
||||||
- "gap_alert=true 이면 배포/실행 차단"
|
- gap_alert=true 이면 배포/실행 차단
|
||||||
- "vacuous_pass_gate_count > 0 이면 배포/실행 차단 (NON_VACUOUS_PASS_GUARD_V1)"
|
- vacuous_pass_gate_count > 0 이면 배포/실행 차단 (NON_VACUOUS_PASS_GUARD_V1)
|
||||||
|
|||||||
@@ -1,66 +1,70 @@
|
|||||||
|
meta:
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\23_low_capability_llm_pipeline_todo.yaml
|
||||||
low_capability_llm_pipeline_todo:
|
low_capability_llm_pipeline_todo:
|
||||||
formula_id: LOW_CAPABILITY_LLM_PIPELINE_TODO_V2
|
formula_id: LOW_CAPABILITY_LLM_PIPELINE_TODO_V2
|
||||||
objective: 저성능 LLM을 위한 기계적 복사 보고 절차 규정
|
objective: 저성능 LLM을 위한 기계적 복사 보고 절차 규정
|
||||||
ordered_steps:
|
ordered_steps:
|
||||||
- step_id: STEP_01
|
- step_id: STEP_01
|
||||||
action: "AGENTS.md 읽기"
|
action: AGENTS.md 읽기
|
||||||
ambiguous: false
|
ambiguous: false
|
||||||
calculation: false
|
calculation: false
|
||||||
- step_id: STEP_02
|
- step_id: STEP_02
|
||||||
action: "active manifest 읽기"
|
action: active manifest 읽기
|
||||||
ambiguous: false
|
ambiguous: false
|
||||||
calculation: false
|
calculation: false
|
||||||
- step_id: STEP_03
|
- step_id: STEP_03
|
||||||
action: "final_context 읽기"
|
action: final_context 읽기
|
||||||
ambiguous: false
|
ambiguous: false
|
||||||
calculation: false
|
calculation: false
|
||||||
- step_id: STEP_04
|
- step_id: STEP_04
|
||||||
action: "engine gate status 확인"
|
action: engine gate status 확인
|
||||||
ambiguous: false
|
ambiguous: false
|
||||||
calculation: false
|
calculation: false
|
||||||
- step_id: STEP_05
|
- step_id: STEP_05
|
||||||
action: "blockers 먼저 출력"
|
action: blockers 먼저 출력
|
||||||
ambiguous: false
|
ambiguous: false
|
||||||
calculation: false
|
calculation: false
|
||||||
- step_id: STEP_06
|
- step_id: STEP_06
|
||||||
action: "allowed/blocked actions 복사"
|
action: allowed/blocked actions 복사
|
||||||
ambiguous: false
|
ambiguous: false
|
||||||
calculation: false
|
calculation: false
|
||||||
- step_id: STEP_07
|
- step_id: STEP_07
|
||||||
action: "shadow ledger 복사"
|
action: shadow ledger 복사
|
||||||
ambiguous: false
|
ambiguous: false
|
||||||
calculation: false
|
calculation: false
|
||||||
- step_id: STEP_08
|
- step_id: STEP_08
|
||||||
action: "data_missing 복사"
|
action: data_missing 복사
|
||||||
ambiguous: false
|
ambiguous: false
|
||||||
calculation: false
|
calculation: false
|
||||||
- step_id: STEP_09
|
- step_id: STEP_09
|
||||||
action: "숫자 provenance 확인"
|
action: 숫자 provenance 확인
|
||||||
ambiguous: false
|
ambiguous: false
|
||||||
calculation: false
|
calculation: false
|
||||||
- step_id: STEP_10
|
- step_id: STEP_10
|
||||||
action: "자유 계산 제거"
|
action: 자유 계산 제거
|
||||||
ambiguous: false
|
ambiguous: false
|
||||||
calculation: false
|
calculation: false
|
||||||
- step_id: STEP_11
|
- step_id: STEP_11
|
||||||
action: "report contract 검증"
|
action: report contract 검증
|
||||||
ambiguous: false
|
ambiguous: false
|
||||||
calculation: false
|
calculation: false
|
||||||
- step_id: STEP_12
|
- step_id: STEP_12
|
||||||
action: "실패 시 DATA_MISSING 또는 REVIEW_ONLY로 종료"
|
action: 실패 시 DATA_MISSING 또는 REVIEW_ONLY로 종료
|
||||||
ambiguous: false
|
ambiguous: false
|
||||||
calculation: false
|
calculation: false
|
||||||
forbidden_actions:
|
forbidden_actions:
|
||||||
- do not set --skip-validate as default resolution
|
- do not set --skip-validate as default resolution
|
||||||
- do not remove validate-engine-strict from release gate
|
- do not remove validate-engine-strict from release gate
|
||||||
- do not mark success without engine_harness_gate_result.status=OK
|
- do not mark success without engine_harness_gate_result.status=OK
|
||||||
completion_criteria:
|
completion_criteria:
|
||||||
- Temp/engine_harness_gate_result.json.status == OK
|
- Temp/engine_harness_gate_result.json.status == OK
|
||||||
- len(Temp/engine_harness_gate_result.json.failed_checks) == 0
|
- 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.runtime_adjusted_coverage_pct == 100.0
|
||||||
- Temp/formula_runtime_registry_v1.json.unmapped_formula_count == 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.schema_presence_score == 100.0
|
||||||
- Temp/data_quality_reconciliation_v1.json.quality_conflict_flag in [true, false]
|
- 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/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.mode in [release, quick, package-only]
|
||||||
- Temp/pipeline_runtime_profile_v1.json.gate_status == OK
|
- Temp/pipeline_runtime_profile_v1.json.gate_status == OK
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
meta:
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\24_strategy_hardening_todo_v1.yaml
|
||||||
strategy_hardening_todo_v1:
|
strategy_hardening_todo_v1:
|
||||||
formula_id: STRATEGY_HARDENING_TODO_V1
|
formula_id: STRATEGY_HARDENING_TODO_V1
|
||||||
objective:
|
objective:
|
||||||
@@ -7,7 +11,7 @@ strategy_hardening_todo_v1:
|
|||||||
target_metrics:
|
target_metrics:
|
||||||
engine_gate_status: OK
|
engine_gate_status: OK
|
||||||
failed_checks_count: 0
|
failed_checks_count: 0
|
||||||
formula_total: 170 # 실제값 170 (163→170 갱신 2026-05-30)
|
formula_total: 170
|
||||||
declared_runtime_count: 170
|
declared_runtime_count: 170
|
||||||
runtime_adjusted_coverage_pct: 100.0
|
runtime_adjusted_coverage_pct: 100.0
|
||||||
unmapped_formula_count: 0
|
unmapped_formula_count: 0
|
||||||
@@ -17,255 +21,269 @@ strategy_hardening_todo_v1:
|
|||||||
outcome_quality_score_v1_min: 60.0
|
outcome_quality_score_v1_min: 60.0
|
||||||
value_damage_pct_avg_max: 10.0
|
value_damage_pct_avg_max: 10.0
|
||||||
llm_freedom_pct: 0.0
|
llm_freedom_pct: 0.0
|
||||||
# BCH-V1 행위기반 커버리지 (P1 달성 2026-05-30)
|
|
||||||
behavioral_coverage_pct: 100.0
|
behavioral_coverage_pct: 100.0
|
||||||
implementation_divergence_count: 0
|
implementation_divergence_count: 0
|
||||||
# P2 임계값 보정 레지스트리
|
|
||||||
unregistered_threshold_count: 0
|
unregistered_threshold_count: 0
|
||||||
overclaimed_calibration_count: 0
|
overclaimed_calibration_count: 0
|
||||||
# P3 LLM 자유도 측정
|
|
||||||
llm_freedom_pct_measured: 0.0
|
llm_freedom_pct_measured: 0.0
|
||||||
ungrounded_number_count: 0
|
ungrounded_number_count: 0
|
||||||
# P4 정직 성과증빙
|
|
||||||
design_score_as_proof_violations: 0
|
design_score_as_proof_violations: 0
|
||||||
ordered_todo:
|
ordered_todo:
|
||||||
- id: T01_COVERAGE_AUDIT
|
- id: T01_COVERAGE_AUDIT
|
||||||
command: python tools/harness_coverage_auditor.py
|
command: python tools/harness_coverage_auditor.py
|
||||||
expect:
|
expect:
|
||||||
true_missing_count: 0
|
true_missing_count: 0
|
||||||
coverage_pct_min: 95.0
|
coverage_pct_min: 95.0
|
||||||
fail_code: HARNESS_COVERAGE_AUDIT_FAIL
|
fail_code: HARNESS_COVERAGE_AUDIT_FAIL
|
||||||
- id: T02_RUNTIME_REGISTRY_BUILD
|
- 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
|
command: python tools/build_formula_runtime_registry_v1.py --audit Temp/harness_coverage_audit.json
|
||||||
expect:
|
--out Temp/formula_runtime_registry_v1.json
|
||||||
formula_total: 163
|
expect:
|
||||||
declared_runtime_count: 163
|
formula_total: 163
|
||||||
runtime_adjusted_coverage_pct: 100.0
|
declared_runtime_count: 163
|
||||||
unmapped_formula_count: 0
|
runtime_adjusted_coverage_pct: 100.0
|
||||||
fail_code: FORMULA_IMPLEMENTATION_REGISTRY_V1_FAIL
|
unmapped_formula_count: 0
|
||||||
- id: T03_RUNTIME_REGISTRY_VALIDATE
|
fail_code: FORMULA_IMPLEMENTATION_REGISTRY_V1_FAIL
|
||||||
command: python tools/validate_formula_runtime_registry_v1.py --json Temp/formula_runtime_registry_v1.json --target-coverage 100
|
- id: T03_RUNTIME_REGISTRY_VALIDATE
|
||||||
expect:
|
command: python tools/validate_formula_runtime_registry_v1.py --json Temp/formula_runtime_registry_v1.json
|
||||||
status_token: FORMULA_IMPLEMENTATION_REGISTRY_V1_OK
|
--target-coverage 100
|
||||||
fail_code: FORMULA_IMPLEMENTATION_REGISTRY_V1_FAIL
|
expect:
|
||||||
- id: T04_DQ_RECON_BUILD
|
status_token: FORMULA_IMPLEMENTATION_REGISTRY_V1_OK
|
||||||
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
|
fail_code: FORMULA_IMPLEMENTATION_REGISTRY_V1_FAIL
|
||||||
expect:
|
- id: T04_DQ_RECON_BUILD
|
||||||
formula_id: DATA_QUALITY_RECONCILIATION_V1
|
command: python tools/build_data_quality_reconciliation_v1.py --json GatherTradingData.json
|
||||||
fail_code: DATA_QUALITY_RECONCILIATION_V1_BUILD_FAIL
|
--integrity Temp/data_integrity_score_v1.json --out Temp/data_quality_reconciliation_v1.json
|
||||||
- id: T05_DQ_RECON_VALIDATE
|
expect:
|
||||||
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
|
formula_id: DATA_QUALITY_RECONCILIATION_V1
|
||||||
expect:
|
fail_code: DATA_QUALITY_RECONCILIATION_V1_BUILD_FAIL
|
||||||
status_token: DATA_QUALITY_RECONCILIATION_V1_OK
|
- id: T05_DQ_RECON_VALIDATE
|
||||||
fail_code: DATA_QUALITY_RECONCILIATION_V1_FAIL
|
command: python tools/validate_data_quality_reconciliation_v1.py --json Temp/data_quality_reconciliation_v1.json
|
||||||
note: "실데이터 부족 구간은 임시로 FAIL 허용하지 않고 WARN 원장으로 기록 후 원인 해결"
|
--min-schema-score 100 --min-investment-quality-score 90
|
||||||
- id: T06_ENGINE_GATE
|
expect:
|
||||||
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
|
status_token: DATA_QUALITY_RECONCILIATION_V1_OK
|
||||||
expect:
|
fail_code: DATA_QUALITY_RECONCILIATION_V1_FAIL
|
||||||
status: OK
|
note: 실데이터 부족 구간은 임시로 FAIL 허용하지 않고 WARN 원장으로 기록 후 원인 해결
|
||||||
failed_checks_count: 0
|
- id: T06_ENGINE_GATE
|
||||||
required_checks:
|
command: python tools/validate_engine_harness_gate.py --json GatherTradingData.json
|
||||||
- CHECK_81_FORMULA_RUNTIME_REGISTRY_V1
|
--report Temp/operational_report.md --harness-json Temp/prediction_improvement_harness.json
|
||||||
- CHECK_82_DATA_QUALITY_RECONCILIATION_V1
|
--result-json Temp/engine_harness_gate_result.json --rule-lifecycle-json Temp/rule_lifecycle_policy.json
|
||||||
fail_code: ENGINE_HARNESS_GATE_FAIL
|
--strategy-harness-json Temp/strategy_harness_v2.json
|
||||||
- id: T07_RELEASE_PACKAGE
|
expect:
|
||||||
command: npm run prepare-upload-zip -- --validation-mode release --profile
|
status: OK
|
||||||
expect:
|
failed_checks_count: 0
|
||||||
gate_status: OK
|
required_checks:
|
||||||
profile_exists: Temp/pipeline_runtime_profile_v1.json
|
- CHECK_81_FORMULA_RUNTIME_REGISTRY_V1
|
||||||
package_exists: ../data_feed.zip
|
- CHECK_82_DATA_QUALITY_RECONCILIATION_V1
|
||||||
fail_code: PREPARE_UPLOAD_ZIP_FAIL
|
fail_code: ENGINE_HARNESS_GATE_FAIL
|
||||||
# ── P1: 행위기반 커버리지 하네스 (BCH-V1) ─────────────────────────────────
|
- id: T07_RELEASE_PACKAGE
|
||||||
- id: B01_BCH_CONTRACT
|
command: npm run prepare-upload-zip -- --validation-mode release --profile
|
||||||
command: "# spec/26_behavioral_coverage_contract.yaml 작성 완료"
|
expect:
|
||||||
expect: {file_exists: "spec/26_behavioral_coverage_contract.yaml", decision_critical_count: 40}
|
gate_status: OK
|
||||||
status: DONE_2026_05_30
|
profile_exists: Temp/pipeline_runtime_profile_v1.json
|
||||||
- id: B02_GOLDEN_AUTHOR
|
package_exists: ../data_feed.zip
|
||||||
command: "# spec/formula_golden_cases_v2.yaml 손계산 골든케이스 작성 완료"
|
fail_code: PREPARE_UPLOAD_ZIP_FAIL
|
||||||
expect: {cases_total_min: 18, provenance: "HAND_COMPUTED or SPEC_DERIVED only"}
|
- id: B01_BCH_CONTRACT
|
||||||
status: DONE_2026_05_30
|
command: '# spec/26_behavioral_coverage_contract.yaml 작성 완료'
|
||||||
- id: B03_PY_MIRROR
|
expect:
|
||||||
command: python tools/run_formula_golden_cases_v2.py
|
file_exists: spec/26_behavioral_coverage_contract.yaml
|
||||||
expect:
|
decision_critical_count: 40
|
||||||
status_token: BEHAVIORAL_COVERAGE_PY_OK
|
status: DONE_2026_05_30
|
||||||
behavioral_coverage_pct: 100.0
|
- id: B02_GOLDEN_AUTHOR
|
||||||
python_fail: 0
|
command: '# spec/formula_golden_cases_v2.yaml 손계산 골든케이스 작성 완료'
|
||||||
fail_code: BCH_PY_MIRROR_FAIL
|
expect:
|
||||||
- id: B04_GAS_PARITY
|
cases_total_min: 18
|
||||||
command: node tools/run_gas_golden_parity.js
|
provenance: HAND_COMPUTED or SPEC_DERIVED only
|
||||||
expect:
|
status: DONE_2026_05_30
|
||||||
status_token: GAS_PARITY_OK
|
- id: B03_PY_MIRROR
|
||||||
gas_fail: 0
|
command: python tools/run_formula_golden_cases_v2.py
|
||||||
fail_code: BCH_GAS_PARITY_FAIL
|
expect:
|
||||||
- id: B05_3WAY_VALIDATE
|
status_token: BEHAVIORAL_COVERAGE_PY_OK
|
||||||
command: python tools/validate_behavioral_coverage_v1.py --strict
|
behavioral_coverage_pct: 100.0
|
||||||
expect:
|
python_fail: 0
|
||||||
status_token: BEHAVIORAL_COVERAGE_V1_OK
|
fail_code: BCH_PY_MIRROR_FAIL
|
||||||
behavioral_coverage_pct: 100.0
|
- id: B04_GAS_PARITY
|
||||||
implementation_divergence_count: 0
|
command: node tools/run_gas_golden_parity.js
|
||||||
fail_code: BEHAVIORAL_COVERAGE_V1_FAIL
|
expect:
|
||||||
- id: B06_DIVERGENCE_FIX
|
status_token: GAS_PARITY_OK
|
||||||
command: "# normalize_tick round→floor 수정, PROFIT_LOCK_STAGE GAS 단계명 정정 완료"
|
gas_fail: 0
|
||||||
expect: {divergence_count: 0}
|
fail_code: BCH_GAS_PARITY_FAIL
|
||||||
status: DONE_2026_05_30
|
- id: B05_3WAY_VALIDATE
|
||||||
- id: B07_WIRE_FULLGATE
|
command: python tools/validate_behavioral_coverage_v1.py --strict
|
||||||
command: npm run validate-behavioral-coverage
|
expect:
|
||||||
expect: {exit_code: 0}
|
status_token: BEHAVIORAL_COVERAGE_V1_OK
|
||||||
fail_code: BCH_WIRING_FAIL
|
behavioral_coverage_pct: 100.0
|
||||||
# ── P2: 임계값 보정 레지스트리 (CALIB-V1) ────────────────────────────────
|
implementation_divergence_count: 0
|
||||||
- id: P2_REGISTRY_BUILD
|
fail_code: BEHAVIORAL_COVERAGE_V1_FAIL
|
||||||
command: "# spec/calibration_registry.yaml 69개 임계값 등록 완료"
|
- id: B06_DIVERGENCE_FIX
|
||||||
expect: {total_thresholds_min: 60}
|
command: '# normalize_tick round→floor 수정, PROFIT_LOCK_STAGE GAS 단계명 정정 완료'
|
||||||
status: DONE_2026_05_30
|
expect:
|
||||||
- id: P2_REGISTRY_VALIDATE
|
divergence_count: 0
|
||||||
command: python tools/validate_calibration_registry_v1.py
|
status: DONE_2026_05_30
|
||||||
expect:
|
- id: B07_WIRE_FULLGATE
|
||||||
overclaimed_count: 0
|
command: npm run validate-behavioral-coverage
|
||||||
unregistered_threshold_count: 0
|
expect:
|
||||||
status_token: "CALIBRATION_REGISTRY_WARN or CALIBRATION_REGISTRY_OK"
|
exit_code: 0
|
||||||
fail_code: CALIBRATION_REGISTRY_FAIL
|
fail_code: BCH_WIRING_FAIL
|
||||||
- id: P2_PRIORITY_BUILD
|
- id: P2_REGISTRY_BUILD
|
||||||
command: python tools/build_calibration_priority_v1.py
|
command: '# spec/calibration_registry.yaml 69개 임계값 등록 완료'
|
||||||
expect:
|
expect:
|
||||||
status_token: CALIBRATION_PRIORITY_OK
|
total_thresholds_min: 60
|
||||||
priority_count_min: 5
|
status: DONE_2026_05_30
|
||||||
fail_code: CALIBRATION_PRIORITY_FAIL
|
- id: P2_REGISTRY_VALIDATE
|
||||||
# ── P3: LLM 자유도 측정·폐쇄 (LFM-V1) ──────────────────────────────────
|
command: python tools/validate_calibration_registry_v1.py
|
||||||
- id: P3_FREEDOM_VALIDATE
|
expect:
|
||||||
command: python tools/validate_number_provenance_v1.py
|
overclaimed_count: 0
|
||||||
expect:
|
unregistered_threshold_count: 0
|
||||||
status_token: LFM_V1_OK
|
status_token: CALIBRATION_REGISTRY_WARN or CALIBRATION_REGISTRY_OK
|
||||||
llm_freedom_pct: 0.0
|
fail_code: CALIBRATION_REGISTRY_FAIL
|
||||||
fail_code: LFM_V1_FAIL
|
- id: P2_PRIORITY_BUILD
|
||||||
- id: P3_NARRATIVE_LOCK
|
command: python tools/build_calibration_priority_v1.py
|
||||||
command: python tools/build_llm_narrative_template_lock_v1.py
|
expect:
|
||||||
expect:
|
status_token: CALIBRATION_PRIORITY_OK
|
||||||
gate: PASS
|
priority_count_min: 5
|
||||||
total_violations: 0
|
fail_code: CALIBRATION_PRIORITY_FAIL
|
||||||
softening_violations: 0
|
- id: P3_FREEDOM_VALIDATE
|
||||||
fail_code: LLM_NARRATIVE_LOCK_FAIL
|
command: python tools/validate_number_provenance_v1.py
|
||||||
# ── P4: 정직 성과증빙 + 보정루프 (HONEST-V1) ─────────────────────────────
|
expect:
|
||||||
- id: P4_HONEST_GUARD
|
status_token: LFM_V1_OK
|
||||||
command: python tools/build_honest_performance_guard_v1.py
|
llm_freedom_pct: 0.0
|
||||||
expect:
|
fail_code: LFM_V1_FAIL
|
||||||
status_token: "HONEST_PERFORMANCE_V1_OK or HONEST_PERFORMANCE_V1_WARN"
|
- id: P3_NARRATIVE_LOCK
|
||||||
design_score_note: "UNVALIDATED_DESIGN_SCORE 표기 필수 (samples<30)"
|
command: python tools/build_llm_narrative_template_lock_v1.py
|
||||||
fail_code: HONEST_PERFORMANCE_V1_FAIL
|
expect:
|
||||||
# ── 반도체 집중 허용 하네스 ────────────────────────────────────────────────
|
gate: PASS
|
||||||
- id: SEMI_CONCENTRATION_POLICY
|
total_violations: 0
|
||||||
command: "# spec/strategy/semiconductor_concentration_policy.yaml 작성 완료"
|
softening_violations: 0
|
||||||
expect: {file_exists: "spec/strategy/semiconductor_concentration_policy.yaml"}
|
fail_code: LLM_NARRATIVE_LOCK_FAIL
|
||||||
status: DONE_2026_05_30
|
- id: P4_HONEST_GUARD
|
||||||
|
command: python tools/build_honest_performance_guard_v1.py
|
||||||
- id: SEMI_CLUSTER_GATE_UPDATE
|
expect:
|
||||||
command: "# gas_data_feed.gs calcSemiconductorClusterGate_ → MARKET_WEIGHT_AWARE_CLUSTER_GATE_V1 업데이트"
|
status_token: HONEST_PERFORMANCE_V1_OK or HONEST_PERFORMANCE_V1_WARN
|
||||||
expect: {formula_id: "MARKET_WEIGHT_AWARE_CLUSTER_GATE_V1", kospi_weight_settings_driven: true}
|
design_score_note: UNVALIDATED_DESIGN_SCORE 표기 필수 (samples<30)
|
||||||
status: DONE_2026_05_30
|
fail_code: HONEST_PERFORMANCE_V1_FAIL
|
||||||
|
- id: SEMI_CONCENTRATION_POLICY
|
||||||
- id: LEADER_CAP_UPDATE
|
command: '# spec/strategy/semiconductor_concentration_policy.yaml 작성 완료'
|
||||||
command: "# gas_data_feed.gs calcSinglePositionWeightCap_ → LEADER_POSITION_WEIGHT_CAP_V1 업데이트"
|
expect:
|
||||||
expect: {samsung_risk_on_cap: 40, hynix_risk_on_cap: 22, kospi_weight_settings_driven: true}
|
file_exists: spec/strategy/semiconductor_concentration_policy.yaml
|
||||||
status: DONE_2026_05_30
|
status: DONE_2026_05_30
|
||||||
|
- id: SEMI_CLUSTER_GATE_UPDATE
|
||||||
- id: SECULAR_LEADER_AUTO_DETECT
|
command: '# gas_data_feed.gs calcSemiconductorClusterGate_ → MARKET_WEIGHT_AWARE_CLUSTER_GATE_V1
|
||||||
command: "# gas_data_feed.gs calcSecularLeaderAutoDetect_ 함수 신설"
|
업데이트'
|
||||||
expect: {formula_id: "SECULAR_LEADER_AUTO_DETECT_V1", threshold: 6}
|
expect:
|
||||||
status: DONE_2026_05_30
|
formula_id: MARKET_WEIGHT_AWARE_CLUSTER_GATE_V1
|
||||||
|
kospi_weight_settings_driven: true
|
||||||
- id: SEMI_INJECT_UPDATE
|
status: DONE_2026_05_30
|
||||||
command: "# tools/inject_computed_harness.py 클러스터/개별 게이트 함수 KOSPI 비중 반영"
|
- id: LEADER_CAP_UPDATE
|
||||||
expect: {settings_kospi_semi_weight_pct: true, gate_overwrite_direct: true}
|
command: '# gas_data_feed.gs calcSinglePositionWeightCap_ → LEADER_POSITION_WEIGHT_CAP_V1
|
||||||
status: DONE_2026_05_30
|
업데이트'
|
||||||
|
expect:
|
||||||
- id: AGENTS_O1_O2_UPDATE
|
samsung_risk_on_cap: 40
|
||||||
command: "# AGENTS.md Direction O1/O2 새 공식명·차등한도로 업데이트"
|
hynix_risk_on_cap: 22
|
||||||
expect: {o1_formula: "LEADER_POSITION_WEIGHT_CAP_V1", o2_formula: "MARKET_WEIGHT_AWARE_CLUSTER_GATE_V1"}
|
kospi_weight_settings_driven: true
|
||||||
status: DONE_2026_05_30
|
status: DONE_2026_05_30
|
||||||
|
- id: SECULAR_LEADER_AUTO_DETECT
|
||||||
# ── 통합 게이트 ──────────────────────────────────────────────────────────
|
command: '# gas_data_feed.gs calcSecularLeaderAutoDetect_ 함수 신설'
|
||||||
- id: INTEGRATED_ENGINE_INTEGRITY
|
expect:
|
||||||
command: npm run validate-engine-integrity
|
formula_id: SECULAR_LEADER_AUTO_DETECT_V1
|
||||||
expect:
|
threshold: 6
|
||||||
behavioral_coverage_pct: 100.0
|
status: DONE_2026_05_30
|
||||||
implementation_divergence_count: 0
|
- id: SEMI_INJECT_UPDATE
|
||||||
overclaimed_count: 0
|
command: '# tools/inject_computed_harness.py 클러스터/개별 게이트 함수 KOSPI 비중 반영'
|
||||||
unregistered_threshold_count: 0
|
expect:
|
||||||
llm_freedom_pct: 0.0
|
settings_kospi_semi_weight_pct: true
|
||||||
softening_violations: 0
|
gate_overwrite_direct: true
|
||||||
fail_code: ENGINE_INTEGRITY_FAIL
|
status: DONE_2026_05_30
|
||||||
|
- id: AGENTS_O1_O2_UPDATE
|
||||||
# ── CAPITAL_STYLE_ALLOCATION_V1 (Section 3B) ────────────────────────────
|
command: '# AGENTS.md Direction O1/O2 새 공식명·차등한도로 업데이트'
|
||||||
- id: C1_BUILD_CAPITAL_STYLE_ALLOC
|
expect:
|
||||||
command: python tools/build_capital_style_allocation_v1.py
|
o1_formula: LEADER_POSITION_WEIGHT_CAP_V1
|
||||||
expect: {gate: PASS, ticker_count_min: 1, conviction_range: "[0,100]"}
|
o2_formula: MARKET_WEIGHT_AWARE_CLUSTER_GATE_V1
|
||||||
fail_code: CAPITAL_ALLOC_BUILD_FAIL
|
status: DONE_2026_05_30
|
||||||
status: DONE_2026_05_30
|
- id: INTEGRATED_ENGINE_INTEGRITY
|
||||||
|
command: npm run validate-engine-integrity
|
||||||
- id: C2_VALIDATE_CAPITAL_STYLE_ALLOC
|
expect:
|
||||||
command: python tools/validate_capital_style_allocation_v1.py
|
behavioral_coverage_pct: 100.0
|
||||||
expect: {status_token: CAPITAL_ALLOC_OK, violations: 0}
|
implementation_divergence_count: 0
|
||||||
fail_code: CAPITAL_ALLOC_VALIDATE_FAIL
|
overclaimed_count: 0
|
||||||
status: DONE_2026_05_30
|
unregistered_threshold_count: 0
|
||||||
|
llm_freedom_pct: 0.0
|
||||||
- id: C3_CALIB_W_STYLE_REGISTER
|
softening_violations: 0
|
||||||
command: python tools/validate_calibration_registry_v1.py
|
fail_code: ENGINE_INTEGRITY_FAIL
|
||||||
expect: {total_thresholds_min: 130, unregistered: 0, overclaimed: 0}
|
- id: C1_BUILD_CAPITAL_STYLE_ALLOC
|
||||||
status: DONE_2026_05_30
|
command: python tools/build_capital_style_allocation_v1.py
|
||||||
|
expect:
|
||||||
- id: C4_GOLDEN_CASE_CAPITAL_STYLE
|
gate: PASS
|
||||||
command: npm run validate-behavioral-coverage
|
ticker_count_min: 1
|
||||||
expect: {status_token: BEHAVIORAL_COVERAGE_V1_OK, behavioral_coverage_pct: 100.0}
|
conviction_range: '[0,100]'
|
||||||
fail_code: BCH_CAPITAL_STYLE_FAIL
|
fail_code: CAPITAL_ALLOC_BUILD_FAIL
|
||||||
status: DONE_2026_05_30
|
status: DONE_2026_05_30
|
||||||
|
- id: C2_VALIDATE_CAPITAL_STYLE_ALLOC
|
||||||
- id: C5_WIRE_FULL_GATE_CAPITAL_STYLE
|
command: python tools/validate_capital_style_allocation_v1.py
|
||||||
command: npm run full-gate
|
expect:
|
||||||
expect: {exit_code: 0}
|
status_token: CAPITAL_ALLOC_OK
|
||||||
fail_code: WIRE_FAIL
|
violations: 0
|
||||||
status: DONE_2026_05_30
|
fail_code: CAPITAL_ALLOC_VALIDATE_FAIL
|
||||||
|
status: DONE_2026_05_30
|
||||||
- id: S1_AGENTS_MD_DIRECTION_S1
|
- id: C3_CALIB_W_STYLE_REGISTER
|
||||||
command: "# AGENTS.md Direction S1 추가"
|
command: python tools/validate_calibration_registry_v1.py
|
||||||
expect: {direction_s1_exists: true}
|
expect:
|
||||||
status: DONE_2026_05_30
|
total_thresholds_min: 130
|
||||||
|
unregistered: 0
|
||||||
- id: S2_INJECT_RENDER_CAPITAL
|
overclaimed: 0
|
||||||
command: npm run render-report-json
|
status: DONE_2026_05_30
|
||||||
expect: {capital_style_conviction_section_exists: true}
|
- id: C4_GOLDEN_CASE_CAPITAL_STYLE
|
||||||
status: DONE_2026_05_30
|
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:
|
evidence_artifacts:
|
||||||
- Temp/harness_coverage_audit.json
|
- Temp/harness_coverage_audit.json
|
||||||
- Temp/formula_runtime_registry_v1.json
|
- Temp/formula_runtime_registry_v1.json
|
||||||
- Temp/data_quality_reconciliation_v1.json
|
- Temp/data_quality_reconciliation_v1.json
|
||||||
- Temp/engine_harness_gate_result.json
|
- Temp/engine_harness_gate_result.json
|
||||||
- Temp/pipeline_runtime_profile_v1.json
|
- Temp/pipeline_runtime_profile_v1.json
|
||||||
# BCH-V1 추가 (2026-05-30)
|
- Temp/formula_behavioral_coverage_v1.json
|
||||||
- Temp/formula_behavioral_coverage_v1.json
|
- Temp/formula_gas_parity_v1.json
|
||||||
- Temp/formula_gas_parity_v1.json
|
- Temp/formula_behavioral_coverage_summary_v1.json
|
||||||
- Temp/formula_behavioral_coverage_summary_v1.json
|
- Temp/calibration_registry_v1.json
|
||||||
- Temp/calibration_registry_v1.json
|
- Temp/calibration_priority_v1.json
|
||||||
- Temp/calibration_priority_v1.json
|
- Temp/llm_freedom_v1.json
|
||||||
- Temp/llm_freedom_v1.json
|
- Temp/honest_performance_guard_v1.json
|
||||||
- Temp/honest_performance_guard_v1.json
|
|
||||||
completion_definition:
|
completion_definition:
|
||||||
hard_requirements:
|
hard_requirements:
|
||||||
- "모든 숫자 산출은 하네스 JSON 근거가 있어야 한다"
|
- 모든 숫자 산출은 하네스 JSON 근거가 있어야 한다
|
||||||
- "HTS 주문표와 WATCH 원장을 물리적으로 분리해야 한다"
|
- HTS 주문표와 WATCH 원장을 물리적으로 분리해야 한다
|
||||||
- "runtime_adjusted_coverage_pct 100%를 숫자로 증빙해야 한다"
|
- runtime_adjusted_coverage_pct 100%를 숫자로 증빙해야 한다
|
||||||
- "데이터 품질 충돌은 숨기지 않고 quality_conflict_flag로 보고해야 한다"
|
- 데이터 품질 충돌은 숨기지 않고 quality_conflict_flag로 보고해야 한다
|
||||||
reject_conditions:
|
reject_conditions:
|
||||||
- "정량 근거 없이 100% 완료 문구 사용"
|
- 정량 근거 없이 100% 완료 문구 사용
|
||||||
- "llm 추정값으로 가격/수량 생성"
|
- llm 추정값으로 가격/수량 생성
|
||||||
- "engine_harness_gate_result.status!=OK 인데 완료 선언"
|
- engine_harness_gate_result.status!=OK 인데 완료 선언
|
||||||
current_status:
|
current_status:
|
||||||
as_of: "2026-05-30"
|
as_of: '2026-05-30'
|
||||||
T01_T03: PASS (coverage 100%, formula_total=168)
|
T01_T03: PASS (coverage 100%, formula_total=168)
|
||||||
T04: PASS (data_quality_reconciliation built)
|
T04: PASS (data_quality_reconciliation built)
|
||||||
T05: FAIL_WARN (investment_quality=13% - 펀더멘털 미수집, 데이터 수집만이 해결)
|
T05: FAIL_WARN (investment_quality=13% - 펀더멘털 미수집, 데이터 수집만이 해결)
|
||||||
T06: STATUS=OK (engine_gate 1개 WARN_ONLY fail)
|
T06: STATUS=OK (engine_gate 1개 WARN_ONLY fail)
|
||||||
T07: 미실행
|
T07: 미실행
|
||||||
# BCH-V1 4-기둥 추가 완료 (2026-05-30)
|
|
||||||
B01_B07: PASS (behavioral_coverage_pct=100%, divergence=0, GAS pass=45/45)
|
B01_B07: PASS (behavioral_coverage_pct=100%, divergence=0, GAS pass=45/45)
|
||||||
B06_FIX: normalize_tick round→floor 수정 + PROFIT_LOCK_STAGE 단계명 7개 spec 일치 정정
|
B06_FIX: normalize_tick round→floor 수정 + PROFIT_LOCK_STAGE 단계명 7개 spec 일치 정정
|
||||||
P2_CALIB: overclaimed=0, unregistered=0, 69개 임계값 EXPERT_PRIOR 정직 공시
|
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
|
leader_position_weight_cap: LEADER_POSITION_WEIGHT_CAP_V1
|
||||||
secular_leader_auto_detect: calcSecularLeaderAutoDetect_ 신설
|
secular_leader_auto_detect: calcSecularLeaderAutoDetect_ 신설
|
||||||
kospi_weights: settings 시트 입력값 반영 (하드코딩 금지)
|
kospi_weights: settings 시트 입력값 반영 (하드코딩 금지)
|
||||||
# CAPITAL_STYLE_ALLOCATION_V1 (Section 3B)
|
|
||||||
capital_style_allocation: DONE_2026_05_30 (C1~C5+S1+S2 완료)
|
capital_style_allocation: DONE_2026_05_30 (C1~C5+S1+S2 완료)
|
||||||
|
|
||||||
final_completion_2026_05_30_extended:
|
final_completion_2026_05_30_extended:
|
||||||
outcome_quality: 85.23 (PASS)
|
outcome_quality: 85.23 (PASS)
|
||||||
guidance_proof: 99.26 (PASS)
|
guidance_proof: 99.26 (PASS)
|
||||||
@@ -300,7 +316,6 @@ strategy_hardening_todo_v1:
|
|||||||
t5_op_rate: 73.24% (CALIBRATED)
|
t5_op_rate: 73.24% (CALIBRATED)
|
||||||
canonical_conflicts: 0 (score=100)
|
canonical_conflicts: 0 (score=100)
|
||||||
all_major_targets: ACHIEVED
|
all_major_targets: ACHIEVED
|
||||||
# 추가 달성 (2026-05-30 2차)
|
|
||||||
behavioral_coverage_pct: 100.0 (PASS)
|
behavioral_coverage_pct: 100.0 (PASS)
|
||||||
implementation_divergence_count: 0 (PASS)
|
implementation_divergence_count: 0 (PASS)
|
||||||
gas_parity_cases: 45/45 (PASS)
|
gas_parity_cases: 45/45 (PASS)
|
||||||
@@ -309,7 +324,6 @@ strategy_hardening_todo_v1:
|
|||||||
llm_freedom_pct_measured: 0.0 (PASS)
|
llm_freedom_pct_measured: 0.0 (PASS)
|
||||||
softening_violations: 0 (PASS)
|
softening_violations: 0 (PASS)
|
||||||
design_score_as_proof_violations: 1 (WARN - UNVALIDATED 라벨 추가로 정직 처리)
|
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_allocation_gate: PASS (11종목, CAPITAL_ALLOC_OK)
|
||||||
capital_style_calibration: total=134 thresholds, overclaimed=0, unregistered=0
|
capital_style_calibration: total=134 thresholds, overclaimed=0, unregistered=0
|
||||||
capital_style_report_section: operational_report에 conviction 표 렌더링 완료
|
capital_style_report_section: operational_report에 conviction 표 렌더링 완료
|
||||||
|
|||||||
@@ -1,528 +1,417 @@
|
|||||||
# spec/27_bch_calibration_runbook.yaml
|
meta:
|
||||||
# BCH-V1 + CALIB-V1 실행 런북 (저성능 LLM 완전 재현 가이드)
|
has_code_implementation: true
|
||||||
# ────────────────────────────────────────────────────────────────────────────
|
code_path:
|
||||||
# 이 파일을 처음부터 끝까지 순서대로 따라 실행하면
|
- spec\27_bch_calibration_runbook.yaml
|
||||||
# 저성능 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단계 파이프라인 전부 통과)
|
|
||||||
# ────────────────────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
runbook_id: BCH_CALIBRATION_RUNBOOK_V1
|
runbook_id: BCH_CALIBRATION_RUNBOOK_V1
|
||||||
version: "2026-05-30"
|
version: '2026-05-30'
|
||||||
objective: |
|
objective: 'yaml 지침(spec/13_formula_registry.yaml)의 공식이 GAS(.gs) 및 Python 구현과
|
||||||
yaml 지침(spec/13_formula_registry.yaml)의 공식이 GAS(.gs) 및 Python 구현과
|
|
||||||
행위 수준에서 100% 일치하는지 검증하고, 하드코딩 임계값을 정직하게 관리하며,
|
행위 수준에서 100% 일치하는지 검증하고, 하드코딩 임계값을 정직하게 관리하며,
|
||||||
|
|
||||||
LLM의 가격·수량 자유계산 여지를 0으로 측정·폐쇄한다.
|
LLM의 가격·수량 자유계산 여지를 0으로 측정·폐쇄한다.
|
||||||
|
|
||||||
"거짓 100%"를 제거하고 수치로 증빙 가능한 진짜 100%를 달성한다.
|
"거짓 100%"를 제거하고 수치로 증빙 가능한 진짜 100%를 달성한다.
|
||||||
|
|
||||||
# ════════════════════════════════════════════════════════════════════════════
|
'
|
||||||
# PHASE 0 — 전제조건 확인
|
|
||||||
# ════════════════════════════════════════════════════════════════════════════
|
|
||||||
phase_0_prerequisites:
|
phase_0_prerequisites:
|
||||||
description: "이 단계를 모두 만족해야 Phase 1을 시작할 수 있다."
|
description: 이 단계를 모두 만족해야 Phase 1을 시작할 수 있다.
|
||||||
checks:
|
checks:
|
||||||
- id: P0_1
|
- id: P0_1
|
||||||
command: "python --version"
|
command: python --version
|
||||||
expect: "Python 3.10+"
|
expect: Python 3.10+
|
||||||
note: "yaml, json, math, re, pathlib 사용. 외부 패키지: pyyaml(pip install pyyaml)"
|
note: 'yaml, json, math, re, pathlib 사용. 외부 패키지: pyyaml(pip install pyyaml)'
|
||||||
|
- id: P0_2
|
||||||
- id: P0_2
|
command: node --version
|
||||||
command: "node --version"
|
expect: v18+
|
||||||
expect: "v18+"
|
note: GAS 패리티 러너(run_gas_golden_parity.js)에 필요
|
||||||
note: "GAS 패리티 러너(run_gas_golden_parity.js)에 필요"
|
- id: P0_3
|
||||||
|
command: python -c "import yaml; print('yaml OK')"
|
||||||
- id: P0_3
|
expect: yaml OK
|
||||||
command: "python -c \"import yaml; print('yaml OK')\""
|
fail_action: pip install pyyaml
|
||||||
expect: "yaml OK"
|
- id: P0_4
|
||||||
fail_action: "pip install pyyaml"
|
command: ls spec/13_formula_registry.yaml spec/13b_harness_formulas.yaml
|
||||||
|
expect: 두 파일 모두 존재
|
||||||
- id: P0_4
|
note: 170개 공식 정의 파일
|
||||||
command: "ls spec/13_formula_registry.yaml spec/13b_harness_formulas.yaml"
|
- id: P0_5
|
||||||
expect: "두 파일 모두 존재"
|
command: ls gas_data_feed.gs gas_lib.gs gas_apex_alpha_watch.gs
|
||||||
note: "170개 공식 정의 파일"
|
expect: 세 파일 모두 존재
|
||||||
|
note: GAS 구현 파일
|
||||||
- id: P0_5
|
|
||||||
command: "ls gas_data_feed.gs gas_lib.gs gas_apex_alpha_watch.gs"
|
|
||||||
expect: "세 파일 모두 존재"
|
|
||||||
note: "GAS 구현 파일"
|
|
||||||
|
|
||||||
# ════════════════════════════════════════════════════════════════════════════
|
|
||||||
# PHASE 1 — 행위기반 커버리지 하네스 (BCH-V1)
|
|
||||||
# ════════════════════════════════════════════════════════════════════════════
|
|
||||||
phase_1_behavioral_coverage:
|
phase_1_behavioral_coverage:
|
||||||
description: |
|
description: '"formula_id 문자열이 .gs에 등장한다" → "golden == Python미러 == GAS미러" 로 전환.
|
||||||
"formula_id 문자열이 .gs에 등장한다" → "golden == Python미러 == GAS미러" 로 전환.
|
|
||||||
발견된 분기(divergence)는 spec/13 기준으로 근본 정정.
|
발견된 분기(divergence)는 spec/13 기준으로 근본 정정.
|
||||||
|
|
||||||
|
'
|
||||||
ordered_steps:
|
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
|
spec/13 expression이 맞고 Python이 틀린 경우 → Python 수정.
|
||||||
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
|
Python이 맞고 golden expected가 틀린 경우 → golden case 수정(다시 손계산).
|
||||||
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).
|
|
||||||
|
|
||||||
- id: S1_3_RUN_PY_MIRROR
|
절대 "Python 출력 = expected" 방식의 역복사 금지.
|
||||||
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" 방식의 역복사 금지.
|
|
||||||
|
|
||||||
- id: S1_4_RUN_GAS_PARITY
|
'
|
||||||
name: "GAS 패리티 검증"
|
- id: S1_4_RUN_GAS_PARITY
|
||||||
command: "node tools/run_gas_golden_parity.js"
|
name: GAS 패리티 검증
|
||||||
expect:
|
command: node tools/run_gas_golden_parity.js
|
||||||
status_token: GAS_PARITY_OK
|
expect:
|
||||||
gas_fail: 0
|
status_token: GAS_PARITY_OK
|
||||||
fail_code: BCH_GAS_PARITY_FAIL
|
gas_fail: 0
|
||||||
fail_action: |
|
fail_code: BCH_GAS_PARITY_FAIL
|
||||||
출력에서 [GAS_FAIL] 또는 [GAS_CORRECT_PYTHON_WRONG] 확인.
|
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_5_3WAY_VALIDATE
|
GAS_CORRECT_PYTHON_WRONG: GAS가 spec_correct → Python 수정 필요.
|
||||||
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로 돌아감.
|
|
||||||
|
|
||||||
- id: S1_6_WIRE_PIPELINE
|
GAS_FAIL: GAS가 틀림 → gas_data_feed.gs / gas_lib.gs / gas_apex_alpha_watch.gs
|
||||||
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를 순서대로 실행"
|
|
||||||
|
|
||||||
|
수정 기준: 항상 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:
|
completion_gate:
|
||||||
command: "python tools/validate_behavioral_coverage_v1.py --strict"
|
command: python tools/validate_behavioral_coverage_v1.py --strict
|
||||||
required_output:
|
required_output:
|
||||||
behavioral_coverage_pct: "== 100.0"
|
behavioral_coverage_pct: == 100.0
|
||||||
implementation_divergence_count: "== 0"
|
implementation_divergence_count: == 0
|
||||||
evidence_artifact: "Temp/formula_behavioral_coverage_summary_v1.json"
|
evidence_artifact: Temp/formula_behavioral_coverage_summary_v1.json
|
||||||
|
|
||||||
# ════════════════════════════════════════════════════════════════════════════
|
|
||||||
# PHASE 2 — 임계값 보정 레지스트리 (CALIB-V1)
|
|
||||||
# ════════════════════════════════════════════════════════════════════════════
|
|
||||||
phase_2_calibration_registry:
|
phase_2_calibration_registry:
|
||||||
description: |
|
description: '모든 하드코딩 임계값을 spec/calibration_registry.yaml 에 등록하고
|
||||||
모든 하드코딩 임계값을 spec/calibration_registry.yaml 에 등록하고
|
|
||||||
overclaimed(검증 안 된 값을 CALIBRATED로 위장) = 0 을 달성한다.
|
overclaimed(검증 안 된 값을 CALIBRATED로 위장) = 0 을 달성한다.
|
||||||
|
|
||||||
|
'
|
||||||
ordered_steps:
|
ordered_steps:
|
||||||
|
- id: S2_1_VERIFY_REGISTRY
|
||||||
- id: S2_1_VERIFY_REGISTRY
|
name: 레지스트리 파일 확인
|
||||||
name: "레지스트리 파일 확인"
|
command: "python -c \"\nimport yaml\nwith open('spec/calibration_registry.yaml',\
|
||||||
command: |
|
\ encoding='utf-8') as f:\n d = yaml.safe_load(f)\nt = d.get('thresholds',\
|
||||||
python -c "
|
\ [])\nprint(f'총 임계값: {len(t)}')\nby_src = {}\nfor e in t:\n s = e.get('source',\
|
||||||
import yaml
|
\ 'EXPERT_PRIOR')\n by_src[s] = by_src.get(s, 0) + 1\nfor s, n in sorted(by_src.items()):\n\
|
||||||
with open('spec/calibration_registry.yaml', encoding='utf-8') as f:
|
\ print(f' {s}: {n}')\n\"\n"
|
||||||
d = yaml.safe_load(f)
|
expect: 총 임계값 ≥ 60
|
||||||
t = d.get('thresholds', [])
|
- id: S2_2_RUN_REGISTRY_VALIDATE
|
||||||
print(f'총 임계값: {len(t)}')
|
name: 레지스트리 검증
|
||||||
by_src = {}
|
command: python tools/validate_calibration_registry_v1.py
|
||||||
for e in t:
|
expect:
|
||||||
s = e.get('source', 'EXPERT_PRIOR')
|
overclaimed_count: 0
|
||||||
by_src[s] = by_src.get(s, 0) + 1
|
unregistered_threshold_count: 0
|
||||||
for s, n in sorted(by_src.items()):
|
status_token: CALIBRATION_REGISTRY_WARN or CALIBRATION_REGISTRY_OK
|
||||||
print(f' {s}: {n}')
|
fail_code: CALIBRATION_REGISTRY_FAIL
|
||||||
"
|
fail_action: "OVERCLAIMED: source=CALIBRATED 이면서 sample_n<30 → source를 PROVISIONAL\
|
||||||
expect: "총 임계값 ≥ 60"
|
\ 로 변경.\n 절대 sample_n을 30으로 올려서 해결 금지 (실제 표본 없이 수치 조작).\nUNREGISTERED: .gs/.py\
|
||||||
|
\ 핫존에서 발견된 미등록 상수 → calibration_registry.yaml에 추가.\n 추가 형식:\n - id: 고유ID\n\
|
||||||
- id: S2_2_RUN_REGISTRY_VALIDATE
|
\ value: 상수값\n unit: pct/ratio/count/etc\n source: EXPERT_PRIOR\
|
||||||
name: "레지스트리 검증"
|
\ # 실측 없으면 반드시 EXPERT_PRIOR\n sample_n: 0\n owner_formula: 관련_FORMULA_ID\n\
|
||||||
command: "python tools/validate_calibration_registry_v1.py"
|
\ gs_location: \"파일명:줄번호\"\n"
|
||||||
expect:
|
- id: S2_3_BUILD_PRIORITY
|
||||||
overclaimed_count: 0
|
name: 보정 우선순위 연결
|
||||||
unregistered_threshold_count: 0
|
command: python tools/build_calibration_priority_v1.py
|
||||||
status_token: "CALIBRATION_REGISTRY_WARN or CALIBRATION_REGISTRY_OK"
|
expect:
|
||||||
fail_code: CALIBRATION_REGISTRY_FAIL
|
status_token: CALIBRATION_PRIORITY_OK
|
||||||
fail_action: |
|
priority_count_min: 5
|
||||||
OVERCLAIMED: source=CALIBRATED 이면서 sample_n<30 → source를 PROVISIONAL 로 변경.
|
fail_code: CALIBRATION_PRIORITY_FAIL
|
||||||
절대 sample_n을 30으로 올려서 해결 금지 (실제 표본 없이 수치 조작).
|
note: alpha_feedback_loop_v2.json의 miss5_count 신호를 임계값 보정 우선순위에 연결
|
||||||
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 신호를 임계값 보정 우선순위에 연결"
|
|
||||||
|
|
||||||
calibration_policy_enforcement:
|
calibration_policy_enforcement:
|
||||||
- rule: "source=CALIBRATED 이려면 sample_n ≥ 30 AND backtest_doc이 있어야 한다"
|
- rule: source=CALIBRATED 이려면 sample_n ≥ 30 AND backtest_doc이 있어야 한다
|
||||||
- rule: "실측 없는 임계값은 반드시 EXPERT_PRIOR 또는 PROVISIONAL"
|
- rule: 실측 없는 임계값은 반드시 EXPERT_PRIOR 또는 PROVISIONAL
|
||||||
- rule: "overclaimed_count > 0 이면 CALIBRATION_REGISTRY_FAIL → 배포 차단"
|
- rule: overclaimed_count > 0 이면 CALIBRATION_REGISTRY_FAIL → 배포 차단
|
||||||
|
|
||||||
calibration_path:
|
calibration_path:
|
||||||
EXPERT_PRIOR:
|
EXPERT_PRIOR:
|
||||||
description: "30년 현장경험 기반 초기값. 검증 없음."
|
description: 30년 현장경험 기반 초기값. 검증 없음.
|
||||||
next_step: "표본 수집 → 30건 이상이면 PROVISIONAL 승격 심사"
|
next_step: 표본 수집 → 30건 이상이면 PROVISIONAL 승격 심사
|
||||||
PROVISIONAL:
|
PROVISIONAL:
|
||||||
description: "예비 검증(1-29건). 방향성 확인됨."
|
description: 예비 검증(1-29건). 방향성 확인됨.
|
||||||
next_step: "30건 이상 + 실제 P&L 검증 → CALIBRATED"
|
next_step: 30건 이상 + 실제 P&L 검증 → CALIBRATED
|
||||||
CALIBRATED:
|
CALIBRATED:
|
||||||
description: "실측 표본 ≥30건 backtest 완료."
|
description: 실측 표본 ≥30건 backtest 완료.
|
||||||
maintenance: "분기별 재검증. 시장 국면 변화 시 재보정"
|
maintenance: 분기별 재검증. 시장 국면 변화 시 재보정
|
||||||
|
|
||||||
completion_gate:
|
completion_gate:
|
||||||
command: "python tools/validate_calibration_registry_v1.py"
|
command: python tools/validate_calibration_registry_v1.py
|
||||||
required_output:
|
required_output:
|
||||||
overclaimed_count: "== 0"
|
overclaimed_count: == 0
|
||||||
unregistered_threshold_count: "== 0"
|
unregistered_threshold_count: == 0
|
||||||
evidence_artifact: "Temp/calibration_registry_v1.json"
|
evidence_artifact: Temp/calibration_registry_v1.json
|
||||||
|
|
||||||
# ════════════════════════════════════════════════════════════════════════════
|
|
||||||
# PHASE 3 — LLM 자유도 측정·폐쇄 (LFM-V1)
|
|
||||||
# ════════════════════════════════════════════════════════════════════════════
|
|
||||||
phase_3_llm_freedom:
|
phase_3_llm_freedom:
|
||||||
description: |
|
description: '가격·수량을 LLM이 자유계산하는 여지를 0으로 측정하고,
|
||||||
가격·수량을 LLM이 자유계산하는 여지를 0으로 측정하고,
|
|
||||||
narrative 완화어휘(INVALID_SOFTENING)를 차단한다.
|
narrative 완화어휘(INVALID_SOFTENING)를 차단한다.
|
||||||
|
|
||||||
|
'
|
||||||
ordered_steps:
|
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
|
''DATA_MISSING — 하네스 업데이트 필요'' 로 교체.
|
||||||
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).
|
|
||||||
|
|
||||||
- id: S3_2_NARRATIVE_LOCK
|
harness 결측 시 LLM 직접계산 허용 문구 전면 삭제 (HS011).
|
||||||
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가 있으면 완화 해석 문장을 완전히 삭제.
|
|
||||||
|
|
||||||
|
'
|
||||||
|
- 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:
|
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:
|
required_output:
|
||||||
llm_freedom_pct: "== 0.0"
|
llm_freedom_pct: == 0.0
|
||||||
softening_violations: "== 0"
|
softening_violations: == 0
|
||||||
evidence_artifact: "Temp/llm_freedom_v1.json"
|
evidence_artifact: Temp/llm_freedom_v1.json
|
||||||
|
|
||||||
# ════════════════════════════════════════════════════════════════════════════
|
|
||||||
# PHASE 4 — 정직 성과증빙 (HONEST-V1)
|
|
||||||
# ════════════════════════════════════════════════════════════════════════════
|
|
||||||
phase_4_honest_performance:
|
phase_4_honest_performance:
|
||||||
description: |
|
description: '설계점수(design_score)와 실측점수(actual_score)를 물리적으로 분리.
|
||||||
설계점수(design_score)와 실측점수(actual_score)를 물리적으로 분리.
|
|
||||||
sample_n < 30 이면 반드시 UNVALIDATED_DESIGN_SCORE 라벨.
|
sample_n < 30 이면 반드시 UNVALIDATED_DESIGN_SCORE 라벨.
|
||||||
|
|
||||||
|
'
|
||||||
ordered_steps:
|
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
|
Step1: 표본 누적(30건)
|
||||||
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 결과) 참조.
|
|
||||||
'목표 달성' 선언 금지 — 수치 그대로 공시.
|
|
||||||
|
|
||||||
- id: S4_2_KPI_TRACKING
|
Step2: ALEG_V2_GATE1_BLOCK_PCT 3% → 실측 최적값 PROVISIONAL 승격
|
||||||
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
|
|
||||||
|
|
||||||
|
Step3: DSD_V1 가중치 logistic regression 최적화
|
||||||
|
|
||||||
|
Step4: K2 분할비율 backtest → CALIBRATED
|
||||||
|
|
||||||
|
'
|
||||||
completion_gate:
|
completion_gate:
|
||||||
command: "python tools/build_honest_performance_guard_v1.py"
|
command: python tools/build_honest_performance_guard_v1.py
|
||||||
required_output:
|
required_output:
|
||||||
violation_count: "== 0 (UNVALIDATED 라벨 추가로 해소)"
|
violation_count: == 0 (UNVALIDATED 라벨 추가로 해소)
|
||||||
evidence_artifact: "Temp/honest_performance_guard_v1.json"
|
evidence_artifact: Temp/honest_performance_guard_v1.json
|
||||||
|
|
||||||
# ════════════════════════════════════════════════════════════════════════════
|
|
||||||
# PHASE 5 — 통합 게이트 + 파이프라인 확인
|
|
||||||
# ════════════════════════════════════════════════════════════════════════════
|
|
||||||
phase_5_integration:
|
phase_5_integration:
|
||||||
description: "4-기둥 통합 실행 후 full-gate / daily-feedback-report 최종 통과 확인"
|
description: 4-기둥 통합 실행 후 full-gate / daily-feedback-report 최종 통과 확인
|
||||||
|
|
||||||
ordered_steps:
|
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
|
validate-calibration-registry &&
|
||||||
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
|
|
||||||
|
|
||||||
- id: S5_2_FULL_GATE
|
validate-llm-freedom &&
|
||||||
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에 신규 파일 등록
|
|
||||||
|
|
||||||
- id: S5_3_DAILY_FEEDBACK
|
validate-narrative-lock &&
|
||||||
name: "일일 피드백 리포트 확인"
|
|
||||||
command: "npm run daily-feedback-report"
|
|
||||||
expect:
|
|
||||||
exit_code: 0
|
|
||||||
fail_code: DAILY_FEEDBACK_FAIL
|
|
||||||
|
|
||||||
|
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:
|
completion_gate:
|
||||||
command: "npm run full-gate && npm run daily-feedback-report"
|
command: npm run full-gate && npm run daily-feedback-report
|
||||||
required_output:
|
required_output:
|
||||||
exit_code: "== 0 (both)"
|
exit_code: == 0 (both)
|
||||||
evidence_artifact: "Temp/formula_behavioral_coverage_summary_v1.json"
|
evidence_artifact: Temp/formula_behavioral_coverage_summary_v1.json
|
||||||
|
|
||||||
# ════════════════════════════════════════════════════════════════════════════
|
|
||||||
# PHASE 6 — 보정루프 (표본 누적 후 반복 실행)
|
|
||||||
# ════════════════════════════════════════════════════════════════════════════
|
|
||||||
phase_6_calibration_loop:
|
phase_6_calibration_loop:
|
||||||
description: |
|
description: '매 거래일 T+5 결과 수집 후 실행. 표본이 누적될수록
|
||||||
매 거래일 T+5 결과 수집 후 실행. 표본이 누적될수록
|
|
||||||
임계값을 EXPERT_PRIOR → PROVISIONAL → CALIBRATED 로 승격한다.
|
임계값을 EXPERT_PRIOR → PROVISIONAL → CALIBRATED 로 승격한다.
|
||||||
|
|
||||||
trigger: "매 거래일 장마감 후 (15:30 이후)"
|
'
|
||||||
|
trigger: 매 거래일 장마감 후 (15:30 이후)
|
||||||
ordered_steps:
|
ordered_steps:
|
||||||
|
- id: L1_UPDATE_HISTORY
|
||||||
- id: L1_UPDATE_HISTORY
|
name: 평가 이력 업데이트
|
||||||
name: "평가 이력 업데이트"
|
command: npm run update-evaluation-history
|
||||||
command: "npm run update-evaluation-history"
|
note: proposal_evaluation_history.json 에 T+5 결과 추가
|
||||||
note: "proposal_evaluation_history.json 에 T+5 결과 추가"
|
- id: L2_CHECK_SAMPLE_COUNT
|
||||||
|
name: 표본 수 확인
|
||||||
- id: L2_CHECK_SAMPLE_COUNT
|
command: "python -c \"\nimport json\nwith open('Temp/calibration_priority_v1.json',\
|
||||||
name: "표본 수 확인"
|
\ encoding='utf-8') as f:\n d = json.load(f)\nprint('cases_analyzed:', d.get('cases_analyzed',\
|
||||||
command: |
|
\ 0))\nprint('miss5_count:', d.get('miss5_count', 0))\ntop3 = d.get('priority_list',\
|
||||||
python -c "
|
\ [])[:3]\nfor p in top3:\n print(f' [{p[\\\"urgency_score\\\"]}] {p[\\\"\
|
||||||
import json
|
calibration_id\\\"]}: value={p[\\\"current_value\\\"]} n={p[\\\"sample_n\\\"\
|
||||||
with open('Temp/calibration_priority_v1.json', encoding='utf-8') as f:
|
]}')\n\"\n"
|
||||||
d = json.load(f)
|
note: cases_analyzed ≥ 30이면 최우선 임계값 PROVISIONAL 승격 심사
|
||||||
print('cases_analyzed:', d.get('cases_analyzed', 0))
|
- id: L3_CALIBRATION_CANDIDATE_REVIEW
|
||||||
print('miss5_count:', d.get('miss5_count', 0))
|
name: 보정 후보 심사 (cases ≥ 30 시)
|
||||||
top3 = d.get('priority_list', [])[:3]
|
trigger_condition: cases_analyzed >= 30
|
||||||
for p in top3:
|
manual_action: "1. ALEG_V2_GATE1_BLOCK_PCT(3%) 검증:\n - late_chase_attribution_v1.json\
|
||||||
print(f' [{p[\"urgency_score\"]}] {p[\"calibration_id\"]}: value={p[\"current_value\"]} n={p[\"sample_n\"]}')
|
\ 의 chase_entry_rate 확인\n - velocity_1d ≥ 3%에서 진입한 케이스의 T+5 승률 계산\n - 현재\
|
||||||
"
|
\ 3%보다 낮은 임계값이 더 효과적이면 새 값 제안\n2. 새 값 제안 후:\n - calibration_registry.yaml의\
|
||||||
note: "cases_analyzed ≥ 30이면 최우선 임계값 PROVISIONAL 승격 심사"
|
\ source를 PROVISIONAL로 변경\n - sample_n에 실제 표본 수 기재\n - last_calibrated:\
|
||||||
|
\ 오늘 날짜\n3. 변경 후 반드시 npm run validate-engine-integrity 재실행\n"
|
||||||
- id: L3_CALIBRATION_CANDIDATE_REVIEW
|
- id: L4_RUN_FULL_GATE
|
||||||
name: "보정 후보 심사 (cases ≥ 30 시)"
|
name: 변경 후 전체 검증
|
||||||
trigger_condition: "cases_analyzed >= 30"
|
command: npm run full-gate
|
||||||
manual_action: |
|
expect:
|
||||||
1. ALEG_V2_GATE1_BLOCK_PCT(3%) 검증:
|
exit_code: 0
|
||||||
- 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}
|
|
||||||
|
|
||||||
calibration_escalation_criteria:
|
calibration_escalation_criteria:
|
||||||
PROVISIONAL:
|
PROVISIONAL:
|
||||||
condition: "sample_n >= 10 AND 방향성 확인"
|
condition: sample_n >= 10 AND 방향성 확인
|
||||||
CALIBRATED:
|
CALIBRATED:
|
||||||
condition: "sample_n >= 30 AND 실제 P&L backtest 완료 AND 이전 임계값 대비 명확한 개선"
|
condition: sample_n >= 30 AND 실제 P&L backtest 완료 AND 이전 임계값 대비 명확한 개선
|
||||||
required_doc: "backtest 결과 노트 (날짜, 표본 수, 이전값, 신규값, 성과 비교)"
|
required_doc: backtest 결과 노트 (날짜, 표본 수, 이전값, 신규값, 성과 비교)
|
||||||
|
|
||||||
# ════════════════════════════════════════════════════════════════════════════
|
|
||||||
# 거부 조건 (Reject Conditions) — 어떤 상황에서도 적용
|
|
||||||
# ════════════════════════════════════════════════════════════════════════════
|
|
||||||
reject_conditions:
|
reject_conditions:
|
||||||
- "behavioral_coverage_pct < 100% 인데 '커버리지 100% 달성' 선언"
|
- behavioral_coverage_pct < 100% 인데 '커버리지 100% 달성' 선언
|
||||||
- "golden expected 값을 .gs 출력에서 역복사 (순환논리)"
|
- golden expected 값을 .gs 출력에서 역복사 (순환논리)
|
||||||
- "임계값을 실측 없이 source=CALIBRATED로 기재 (overclaimed)"
|
- 임계값을 실측 없이 source=CALIBRATED로 기재 (overclaimed)
|
||||||
- "LLM이 가격/수량을 spec 등록 공식 없이 즉석 계산"
|
- LLM이 가격/수량을 spec 등록 공식 없이 즉석 계산
|
||||||
- "rebound_efficiency_score 등 설계점수를 '검증된 성과'로 서술 (UNVALIDATED 라벨 없이)"
|
- rebound_efficiency_score 등 설계점수를 '검증된 성과'로 서술 (UNVALIDATED 라벨 없이)
|
||||||
- "T+1/T+5 목표 미달 상태에서 '예측 정확도 100%' 선언"
|
- T+1/T+5 목표 미달 상태에서 '예측 정확도 100%' 선언
|
||||||
- "divergence_count > 0 상태에서 '구현 일치' 선언"
|
- divergence_count > 0 상태에서 '구현 일치' 선언
|
||||||
- "sample_n < 30인 임계값을 '보정완료'로 처리"
|
- 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일 더 최신)을
|
|
||||||
# 직접 재확인한 결과는 다음과 같다 — 이 블록을 단일 진실원천으로 삼는다.
|
|
||||||
current_status_2026_06_21:
|
current_status_2026_06_21:
|
||||||
source_of_truth: "Temp/prediction_accuracy_harness_v2.json (as_of_date=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)의
|
t1_match_rate_pct: 52.94
|
||||||
# 35.86%는 7일 전 스냅샷이며 표본이 0으로 줄어 더 이상 유효하지 않음.
|
t5_match_rate_pct: null
|
||||||
t5_sample_regression_note: >
|
t5_sample_regression_note: 'cases_analyzed가 141건(2026-05-30 기준)에서 t5_sample=0(2026-06-21)으로
|
||||||
cases_analyzed가 141건(2026-05-30 기준)에서 t5_sample=0(2026-06-21)으로 감소했다.
|
감소했다. evaluation_methodology가 ACTIVE_PASSIVE_SPLIT_V1_INCONCLUSIVE_EXCLUDED로 변경되며
|
||||||
evaluation_methodology가 ACTIVE_PASSIVE_SPLIT_V1_INCONCLUSIVE_EXCLUDED로 변경되며
|
|
||||||
inconclusive/replay 표본이 제외된 것으로 추정 — 근본 원인은 별도 조사 필요(WBS-7.2 잔여 항목).
|
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_expert_prior_count: 59
|
||||||
calibration_registry_calibrated_count: 0
|
calibration_registry_calibrated_count: 0
|
||||||
rule: "이 문서를 인용할 때는 항상 as_of_date를 동반 표기하고, 아래 5/30 스냅샷을 '현재'로 인용하지 않는다."
|
rule: 이 문서를 인용할 때는 항상 as_of_date를 동반 표기하고, 아래 5/30 스냅샷을 '현재'로 인용하지 않는다.
|
||||||
|
|
||||||
# ════════════════════════════════════════════════════════════════════════════
|
|
||||||
# 과거 달성 현황 (2026-05-30, 역사적 스냅샷 — "현재"로 인용 금지)
|
|
||||||
# ════════════════════════════════════════════════════════════════════════════
|
|
||||||
current_status_2026_05_30:
|
current_status_2026_05_30:
|
||||||
phase_1_bch: COMPLETE
|
phase_1_bch: COMPLETE
|
||||||
behavioral_coverage_pct: 100.0
|
behavioral_coverage_pct: 100.0
|
||||||
gas_parity_cases: 63
|
gas_parity_cases: 63
|
||||||
implementation_divergence_count: 0
|
implementation_divergence_count: 0
|
||||||
bugs_fixed:
|
bugs_fixed:
|
||||||
- "normalize_tick: round() → math.floor() (Python-GAS divergence 제거)"
|
- 'normalize_tick: round() → math.floor() (Python-GAS divergence 제거)'
|
||||||
- "PROFIT_LOCK_STAGE 단계명 7개 spec 일치 정정 (GAS calcPrices_)"
|
- PROFIT_LOCK_STAGE 단계명 7개 spec 일치 정정 (GAS calcPrices_)
|
||||||
- "validate_harness_context.py VALID_PROFIT_LOCK_STAGES 신규 명칭 추가"
|
- validate_harness_context.py VALID_PROFIT_LOCK_STAGES 신규 명칭 추가
|
||||||
- "RetirementAssetPortfolio.yaml spec_files 신규 3파일 등록"
|
- RetirementAssetPortfolio.yaml spec_files 신규 3파일 등록
|
||||||
|
|
||||||
phase_2_calib: COMPLETE
|
phase_2_calib: COMPLETE
|
||||||
total_thresholds: 70
|
total_thresholds: 70
|
||||||
overclaimed_count: 0
|
overclaimed_count: 0
|
||||||
unregistered_count: 0
|
unregistered_count: 0
|
||||||
expert_prior_count: 61 # 정직하게 공시됨
|
expert_prior_count: 61
|
||||||
|
|
||||||
phase_3_lfm: COMPLETE
|
phase_3_lfm: COMPLETE
|
||||||
llm_freedom_pct: 0.0
|
llm_freedom_pct: 0.0
|
||||||
softening_violations: 0
|
softening_violations: 0
|
||||||
prompt_freedom_risks_removed: 4
|
prompt_freedom_risks_removed: 4
|
||||||
|
|
||||||
phase_4_honest: COMPLETE
|
phase_4_honest: COMPLETE
|
||||||
design_score_labeled_unvalidated: true
|
design_score_labeled_unvalidated: true
|
||||||
t1_match_rate_pct: 47.28
|
t1_match_rate_pct: 47.28
|
||||||
t5_match_rate_pct: 35.86
|
t5_match_rate_pct: 35.86
|
||||||
target_t5: 55.0
|
target_t5: 55.0
|
||||||
|
|
||||||
phase_5_integration: COMPLETE
|
phase_5_integration: COMPLETE
|
||||||
full_gate_exit: 0
|
full_gate_exit: 0
|
||||||
daily_feedback_exit: 0
|
daily_feedback_exit: 0
|
||||||
|
|
||||||
phase_6_calibration_loop: IN_PROGRESS
|
phase_6_calibration_loop: IN_PROGRESS
|
||||||
cases_analyzed: 141
|
cases_analyzed: 141
|
||||||
miss5_count: 51
|
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:
|
automation_entrypoints:
|
||||||
gitea_schedule: ".gitea/workflows/calibration_backlog.yml"
|
gitea_schedule: .gitea/workflows/calibration_backlog.yml
|
||||||
npm_script: "npm run ops:calibration-backlog"
|
npm_script: npm run ops:calibration-backlog
|
||||||
generated_artifacts:
|
generated_artifacts:
|
||||||
- Temp/calibration_priority_v1.json
|
- Temp/calibration_priority_v1.json
|
||||||
- Temp/calibration_change_ledger_v4.json
|
- Temp/calibration_change_ledger_v4.json
|
||||||
- Temp/calibration_review_report_v1.json
|
- Temp/calibration_review_report_v1.json
|
||||||
- Temp/calibration_review_report_v1.md
|
- Temp/calibration_review_report_v1.md
|
||||||
- Temp/calibration_approval_list_v1.json
|
- Temp/calibration_approval_list_v1.json
|
||||||
- Temp/calibration_approval_list_v1.md
|
- Temp/calibration_approval_list_v1.md
|
||||||
- Temp/calibration_registry_v1.json
|
- Temp/calibration_registry_v1.json
|
||||||
promotion_rules:
|
promotion_rules:
|
||||||
provisional: "sample_n >= 10 AND direction confirmed AND change_ledger entry exists"
|
provisional: sample_n >= 10 AND direction confirmed AND change_ledger entry
|
||||||
calibrated: "sample_n >= 30 AND backtest_doc exists AND validator overclaimed_count == 0"
|
exists
|
||||||
|
calibrated: sample_n >= 30 AND backtest_doc exists AND validator overclaimed_count
|
||||||
|
== 0
|
||||||
|
|||||||
@@ -1,105 +1,94 @@
|
|||||||
# spec/29 — 백테스트 · Walk-forward 하네스 계약 (BACKTEST_HARNESS_V1)
|
|
||||||
#
|
|
||||||
# 목적: 전략이 과거 데이터에만 맞춰진 과최적화인지, 실제 운용 중 의미있는 예측력이 있는지
|
|
||||||
# 수치로 검증한다. 미충족 항목은 추정·날조하지 않고 insufficient_data로 표기한다.
|
|
||||||
#
|
|
||||||
# 계층: 감사·진단 계약(spec/28과 동급). GAS 런타임·주문 생성에 개입 없음.
|
|
||||||
# 구현: Python 계층(tools/*.py). 실측 누적 데이터가 없는 구간은 채울 수 없음을 명시.
|
|
||||||
|
|
||||||
meta:
|
meta:
|
||||||
formula_id: BACKTEST_HARNESS_V1
|
formula_id: BACKTEST_HARNESS_V1
|
||||||
version: "2026-05-31"
|
version: '2026-05-31'
|
||||||
python_tool: "tools/build_yaml_code_coverage_v1.py (커버리지), tools/build_engine_audit_v1.py (집계)"
|
python_tool: tools/build_yaml_code_coverage_v1.py (커버리지), tools/build_engine_audit_v1.py
|
||||||
|
(집계)
|
||||||
sources:
|
sources:
|
||||||
- Temp/prediction_accuracy_harness_v2.json # T+1/T+5/T+20 정확도
|
- Temp/prediction_accuracy_harness_v2.json
|
||||||
- Temp/outcome_quality_score_v1.json # 운용 성과 질 점수
|
- Temp/outcome_quality_score_v1.json
|
||||||
- Temp/operational_alpha_calibration_v2.json # 알파 보정
|
- Temp/operational_alpha_calibration_v2.json
|
||||||
- Temp/proposal_evaluation_history.json # 제안-결과 이력
|
- Temp/proposal_evaluation_history.json
|
||||||
|
has_code_implementation: true
|
||||||
# ── 현재 실측 가능 지표 (2026-05-31 기준) ────────────────────────────────
|
code_path:
|
||||||
|
- spec\29_backtest_harness_contract.yaml
|
||||||
current_metrics:
|
current_metrics:
|
||||||
direction_accuracy:
|
direction_accuracy:
|
||||||
t1_op_rate:
|
t1_op_rate:
|
||||||
value: 50.37
|
value: 50.37
|
||||||
n_sample: 546
|
n_sample: 546
|
||||||
unit: percent
|
unit: percent
|
||||||
interpretation: "동전던지기(50%) 수준 — 단기 방향 예측력 불충분"
|
interpretation: 동전던지기(50%) 수준 — 단기 방향 예측력 불충분
|
||||||
t5_op_rate:
|
t5_op_rate:
|
||||||
value: 73.24
|
value: 73.24
|
||||||
n_sample: 161
|
n_sample: 161
|
||||||
unit: percent
|
unit: percent
|
||||||
method: "decisive 케이스만(passive/ambiguous 제외). PREDICTION_ACCURACY_HARNESS_V2"
|
method: decisive 케이스만(passive/ambiguous 제외). PREDICTION_ACCURACY_HARNESS_V2
|
||||||
interpretation: "T+5 능동 결정 케이스 73%. 전체 포함 레거시=31.94% — 표본 정의 혼용 금지"
|
interpretation: T+5 능동 결정 케이스 73%. 전체 포함 레거시=31.94% — 표본 정의 혼용 금지
|
||||||
t5_legacy_rate:
|
t5_legacy_rate:
|
||||||
value: 31.94
|
value: 31.94
|
||||||
n_sample: "not_available"
|
n_sample: not_available
|
||||||
unit: percent
|
unit: percent
|
||||||
interpretation: "전체 평가 윈도우 비율(거시이벤트 미제외). t5_op_rate와 다른 지표."
|
interpretation: 전체 평가 윈도우 비율(거시이벤트 미제외). t5_op_rate와 다른 지표.
|
||||||
t20_op_rate:
|
t20_op_rate:
|
||||||
value: insufficient_data
|
value: insufficient_data
|
||||||
n_sample: 0
|
n_sample: 0
|
||||||
unit: percent
|
unit: percent
|
||||||
interpretation: "T+20 실현 표본 0건 — 장기 예측력 검증 불가. t5_operational_proxy=73.24 사용 중(추정)"
|
interpretation: T+20 실현 표본 0건 — 장기 예측력 검증 불가. t5_operational_proxy=73.24 사용
|
||||||
|
중(추정)
|
||||||
window_90d_rate:
|
window_90d_rate:
|
||||||
value: 31.94
|
value: 31.94
|
||||||
n_sample: "not_available"
|
n_sample: not_available
|
||||||
unit: percent
|
unit: percent
|
||||||
interpretation: "최근 90일 창 일치율. 낮음."
|
interpretation: 최근 90일 창 일치율. 낮음.
|
||||||
|
|
||||||
outcome_quality:
|
outcome_quality:
|
||||||
score: 84.43
|
score: 84.43
|
||||||
gate: CAUTION_MODE
|
gate: CAUTION_MODE
|
||||||
t20_effective_rate: 73.24
|
t20_effective_rate: 73.24
|
||||||
t20_source: t5_operational_proxy # 실측 아님 — estimated=true
|
t20_source: t5_operational_proxy
|
||||||
t5_decisive_count: 161
|
t5_decisive_count: 161
|
||||||
basis_note: "t20는 실측이 아니라 t5 proxy. 실측 T+20 누적 전까지 estimated."
|
basis_note: t20는 실측이 아니라 t5 proxy. 실측 T+20 누적 전까지 estimated.
|
||||||
|
|
||||||
walk_forward:
|
walk_forward:
|
||||||
status: insufficient_data
|
status: insufficient_data
|
||||||
reason: >
|
reason: 'Walk-forward 검증을 위해 필요한 in-sample/out-of-sample 분리, 기간별 성과 비교, slippage/cost
|
||||||
Walk-forward 검증을 위해 필요한 in-sample/out-of-sample 분리,
|
반영 데이터가 없음. backfill_eod_replay_history.py를 통해 이력 재현 시 채울 수 있음.
|
||||||
기간별 성과 비교, slippage/cost 반영 데이터가 없음.
|
|
||||||
backfill_eod_replay_history.py를 통해 이력 재현 시 채울 수 있음.
|
|
||||||
|
|
||||||
# ── 정의되어야 하나 현재 측정 불가한 지표 ─────────────────────────────────
|
'
|
||||||
missing_metrics:
|
missing_metrics:
|
||||||
CAGR:
|
CAGR:
|
||||||
status: insufficient_data
|
status: insufficient_data
|
||||||
required_data: "1년 이상 완전 실현 손익 이력"
|
required_data: 1년 이상 완전 실현 손익 이력
|
||||||
sharpe_ratio:
|
sharpe_ratio:
|
||||||
status: insufficient_data
|
status: insufficient_data
|
||||||
required_data: "일별 수익률 시계열 + 무위험수익률"
|
required_data: 일별 수익률 시계열 + 무위험수익률
|
||||||
sortino_ratio:
|
sortino_ratio:
|
||||||
status: insufficient_data
|
status: insufficient_data
|
||||||
required_data: "일별 하락 편차 시계열"
|
required_data: 일별 하락 편차 시계열
|
||||||
max_drawdown:
|
max_drawdown:
|
||||||
status: insufficient_data
|
status: insufficient_data
|
||||||
required_data: "계좌 고점 추적 이력. portfolio_peak_krw 필드 존재하나 historical 없음"
|
required_data: 계좌 고점 추적 이력. portfolio_peak_krw 필드 존재하나 historical 없음
|
||||||
calmar_ratio:
|
calmar_ratio:
|
||||||
status: insufficient_data
|
status: insufficient_data
|
||||||
required_data: "CAGR / MDD"
|
required_data: CAGR / MDD
|
||||||
win_rate:
|
win_rate:
|
||||||
status: insufficient_data
|
status: insufficient_data
|
||||||
required_data: "청산 완료 거래 이력. backdata에 MAE/MFE/pnl 모두 공란"
|
required_data: 청산 완료 거래 이력. backdata에 MAE/MFE/pnl 모두 공란
|
||||||
profit_factor:
|
profit_factor:
|
||||||
status: insufficient_data
|
status: insufficient_data
|
||||||
required_data: "총 이익 / 총 손실 (실현 기준)"
|
required_data: 총 이익 / 총 손실 (실현 기준)
|
||||||
average_win_loss_ratio:
|
average_win_loss_ratio:
|
||||||
status: insufficient_data
|
status: insufficient_data
|
||||||
required_data: "실현 수익/손실 건별 데이터"
|
required_data: 실현 수익/손실 건별 데이터
|
||||||
slippage_impact:
|
slippage_impact:
|
||||||
status: insufficient_data
|
status: insufficient_data
|
||||||
required_data: "체결 가격 vs 지정가 괴리 이력"
|
required_data: 체결 가격 vs 지정가 괴리 이력
|
||||||
transaction_cost_impact:
|
transaction_cost_impact:
|
||||||
status: insufficient_data
|
status: insufficient_data
|
||||||
required_data: "수수료·세금 반영 순수익 이력"
|
required_data: 수수료·세금 반영 순수익 이력
|
||||||
hit_rate_by_horizon:
|
hit_rate_by_horizon:
|
||||||
scalp: insufficient_data
|
scalp: insufficient_data
|
||||||
short_term: insufficient_data
|
short_term: insufficient_data
|
||||||
mid_term: insufficient_data
|
mid_term: insufficient_data
|
||||||
long_term: insufficient_data
|
long_term: insufficient_data
|
||||||
|
|
||||||
# ── 측정 가능한 회귀 지표 (현재 구현됨) ──────────────────────────────────
|
|
||||||
measurable_now:
|
measurable_now:
|
||||||
yaml_to_code_coverage_ratio:
|
yaml_to_code_coverage_ratio:
|
||||||
value: 1.0
|
value: 1.0
|
||||||
@@ -107,43 +96,37 @@ measurable_now:
|
|||||||
golden_test_coverage_ratio:
|
golden_test_coverage_ratio:
|
||||||
value: 0.2337
|
value: 0.2337
|
||||||
source: Temp/yaml_code_coverage_v1.json
|
source: Temp/yaml_code_coverage_v1.json
|
||||||
note: "43/184 공식 — golden 테스트 확대 필요"
|
note: 43/184 공식 — golden 테스트 확대 필요
|
||||||
decision_reproducibility_score:
|
decision_reproducibility_score:
|
||||||
value: 1.0
|
value: 1.0
|
||||||
method: "build_engine_audit_v1.py 10회 실행 byte-identical"
|
method: build_engine_audit_v1.py 10회 실행 byte-identical
|
||||||
llm_dependency_ratio:
|
llm_dependency_ratio:
|
||||||
value: 0.0
|
value: 0.0
|
||||||
source: Temp/llm_freedom_v1.json
|
source: Temp/llm_freedom_v1.json
|
||||||
schema_validity_score:
|
schema_validity_score:
|
||||||
value: 95.5
|
value: 95.5
|
||||||
source: Temp/data_quality_reconciliation_v1.json
|
source: Temp/data_quality_reconciliation_v1.json
|
||||||
|
|
||||||
# ── 목표치 (충족 시 PASS 판정) ──────────────────────────────────────────
|
|
||||||
targets:
|
targets:
|
||||||
t1_op_rate_min: 55 # 현재 50.37 — 미달
|
t1_op_rate_min: 55
|
||||||
t5_op_rate_min: 60 # 현재 73.24 — 충족(주의: decisive 케이스 기준)
|
t5_op_rate_min: 60
|
||||||
t20_op_rate_min: 55 # 현재 insufficient_data
|
t20_op_rate_min: 55
|
||||||
win_rate_min: 50 # 현재 insufficient_data
|
win_rate_min: 50
|
||||||
max_drawdown_max_pct: 20 # 현재 측정 불가
|
max_drawdown_max_pct: 20
|
||||||
yaml_to_code_coverage: 1.0 # 충족
|
yaml_to_code_coverage: 1.0
|
||||||
golden_coverage_min: 0.5 # 현재 0.23 — 미달
|
golden_coverage_min: 0.5
|
||||||
|
|
||||||
# ── 과최적화 경계 지표 ────────────────────────────────────────────────────
|
|
||||||
overfit_risk:
|
overfit_risk:
|
||||||
in_sample_vs_oos_gap:
|
in_sample_vs_oos_gap:
|
||||||
status: insufficient_data
|
status: insufficient_data
|
||||||
note: "in-sample / out-of-sample 분리 없음"
|
note: in-sample / out-of-sample 분리 없음
|
||||||
regime_dependency:
|
regime_dependency:
|
||||||
note: >
|
note: '현재 포트폴리오는 RISK_ON 국면에 집중(SHORT 71.4% vs 25% 한도 위반). 단일 국면 의존도 과다 — regime
|
||||||
현재 포트폴리오는 RISK_ON 국면에 집중(SHORT 71.4% vs 25% 한도 위반).
|
다양화 필요.
|
||||||
단일 국면 의존도 과다 — regime 다양화 필요.
|
|
||||||
sample_size_warning:
|
|
||||||
t1: "n=546 — 통계적으로 유의하나 변동 큼"
|
|
||||||
t5: "n=161 — 최소 수준. 더 많은 누적 필요"
|
|
||||||
t20: "n=0 — 미충족"
|
|
||||||
|
|
||||||
# ── 실측 표본 백필 의무화 (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:
|
operational_sample_backfill:
|
||||||
formula_id: OPERATIONAL_SAMPLE_BACKFILL_V1
|
formula_id: OPERATIONAL_SAMPLE_BACKFILL_V1
|
||||||
status: SCAFFOLDED_PENDING_LIVE_DATA
|
status: SCAFFOLDED_PENDING_LIVE_DATA
|
||||||
@@ -152,42 +135,54 @@ operational_sample_backfill:
|
|||||||
current_replay_sample_count: 510
|
current_replay_sample_count: 510
|
||||||
target_operational_t5_sample: 30
|
target_operational_t5_sample: 30
|
||||||
target_operational_t20_sample: 30
|
target_operational_t20_sample: 30
|
||||||
rationale: >
|
rationale: 'live=0, paper=0, op_t20=0. REPLAY 510건은 예측력 증거가 못 된다(미래정보 누수 위험). 실제
|
||||||
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]"
|
|
||||||
|
|
||||||
# ── 금지 사항 ─────────────────────────────────────────────────────────────
|
'
|
||||||
|
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:
|
prohibitions:
|
||||||
- "insufficient_data 지표를 추정값으로 대체해 투자 판단에 사용 금지(AGENTS.md §0.3)"
|
- insufficient_data 지표를 추정값으로 대체해 투자 판단에 사용 금지(AGENTS.md §0.3)
|
||||||
- "t5_op_rate(73%)와 window_90d_rate(31%)를 동일 지표로 혼용 금지"
|
- t5_op_rate(73%)와 window_90d_rate(31%)를 동일 지표로 혼용 금지
|
||||||
- "t20_op_rate=t5_operational_proxy를 실측 T+20으로 표기 금지 (estimated=true 필수)"
|
- t20_op_rate=t5_operational_proxy를 실측 T+20으로 표기 금지 (estimated=true 필수)
|
||||||
- "CAGR/Sharpe/MDD가 없는 상태에서 '검증된 전략' 단정 금지"
|
- CAGR/Sharpe/MDD가 없는 상태에서 '검증된 전략' 단정 금지
|
||||||
|
|||||||
@@ -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
|
schema_version: low_capability_llm_response_contract.v1
|
||||||
formula_id: LLM_NARRATIVE_TEMPLATE_LOCK_V1
|
formula_id: LLM_NARRATIVE_TEMPLATE_LOCK_V1
|
||||||
purpose: >
|
purpose: '저성능 LLM도 동일한 JSON 입력에서 동일한 서술 결과를 내도록 응답 섹션과 금지 섹션을 고정한다.
|
||||||
저성능 LLM도 동일한 JSON 입력에서 동일한 서술 결과를 내도록
|
|
||||||
응답 섹션과 금지 섹션을 고정한다.
|
|
||||||
|
|
||||||
|
'
|
||||||
required_sections:
|
required_sections:
|
||||||
- source_summary
|
- source_summary
|
||||||
- fail_codes
|
- fail_codes
|
||||||
- allowed_actions
|
- allowed_actions
|
||||||
- blocked_actions
|
- blocked_actions
|
||||||
- todo_yaml
|
- todo_yaml
|
||||||
- no_order_notice
|
- no_order_notice
|
||||||
|
|
||||||
forbidden_sections_when_blocked:
|
forbidden_sections_when_blocked:
|
||||||
- hts_order_table
|
- hts_order_table
|
||||||
- new_buy_recommendation
|
- new_buy_recommendation
|
||||||
- freeform_target_price
|
- freeform_target_price
|
||||||
|
|
||||||
copy_exact_rules:
|
copy_exact_rules:
|
||||||
- "All numeric values must be copied from JSON with json_path."
|
- All numeric values must be copied from JSON with json_path.
|
||||||
- "No unregistered formula names may be invented."
|
- No unregistered formula names may be invented.
|
||||||
- "If HTS_READY is false, render shadow ledger only."
|
- If HTS_READY is false, render shadow ledger only.
|
||||||
|
|
||||||
output_constraints:
|
output_constraints:
|
||||||
language: ko-KR
|
language: ko-KR
|
||||||
allow_freeform_numbers: false
|
allow_freeform_numbers: false
|
||||||
|
|||||||
@@ -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
|
schema_version: 2026-06-03-execution-precedence-lock-v1
|
||||||
formula_id: FINAL_EXECUTION_PRECEDENCE_LOCK_V1
|
formula_id: FINAL_EXECUTION_PRECEDENCE_LOCK_V1
|
||||||
purpose: 최종 HTS 권한과 child internal allowed 분리.
|
purpose: 최종 HTS 권한과 child internal allowed 분리.
|
||||||
rules:
|
rules:
|
||||||
- global_execution_gate != HTS_READY 이면 child execution_allowed는 THEORETICAL_ONLY
|
- global_execution_gate != HTS_READY 이면 child execution_allowed는 THEORETICAL_ONLY
|
||||||
- HTS_READY일 때만 order_blueprint_json.validation_status=PASS 를 주문표로 렌더링
|
- HTS_READY일 때만 order_blueprint_json.validation_status=PASS 를 주문표로 렌더링
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
|
meta:
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\34_architecture_boundaries.yaml
|
||||||
schema_version: 2026-06-03-architecture-boundaries-v1
|
schema_version: 2026-06-03-architecture-boundaries-v1
|
||||||
formula_id: ARCHITECTURE_BOUNDARIES_V1
|
formula_id: ARCHITECTURE_BOUNDARIES_V1
|
||||||
purpose: data -> feature -> decision -> execution -> report 단방향 원칙.
|
purpose: data -> feature -> decision -> execution -> report 단방향 원칙.
|
||||||
contracts:
|
contracts:
|
||||||
- renderer_calculation_count: 0
|
- renderer_calculation_count: 0
|
||||||
- reverse_dependency_count: 0
|
- reverse_dependency_count: 0
|
||||||
|
|||||||
@@ -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
|
schema_version: 2026-06-03-rule-lifecycle-governance-v3
|
||||||
formula_id: RULE_LIFECYCLE_POLICY_V3
|
formula_id: RULE_LIFECYCLE_POLICY_V3
|
||||||
purpose: rule registry governance for hardening todo completion.
|
purpose: rule registry governance for hardening todo completion.
|
||||||
required_fields:
|
required_fields:
|
||||||
- rule_key
|
- rule_key
|
||||||
- owner
|
- owner
|
||||||
- retirement_condition
|
- retirement_condition
|
||||||
- expected_metric
|
- expected_metric
|
||||||
|
|||||||
@@ -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
|
schema_version: final_decision_packet_contract.v4
|
||||||
formula_id: FINAL_DECISION_PACKET_V4
|
formula_id: FINAL_DECISION_PACKET_V4
|
||||||
purpose: Single packet source of truth for renderer and low-capability LLM output.
|
purpose: Single packet source of truth for renderer and low-capability LLM output.
|
||||||
sections:
|
sections:
|
||||||
- executive
|
- executive
|
||||||
- portfolio
|
- portfolio
|
||||||
- ticker
|
- ticker
|
||||||
- risk
|
- risk
|
||||||
- execution
|
- execution
|
||||||
- performance
|
- performance
|
||||||
- data_quality
|
- data_quality
|
||||||
provenance_requirements:
|
provenance_requirements:
|
||||||
source_path: required
|
source_path: required
|
||||||
json_pointer: required
|
json_pointer: required
|
||||||
|
|||||||
@@ -1,28 +1,32 @@
|
|||||||
|
meta:
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\43_quant_factor_taxonomy.yaml
|
||||||
schema_version: quant_factor_taxonomy.v1
|
schema_version: quant_factor_taxonomy.v1
|
||||||
purpose: Classify factors by horizon, decay, and conflict policy.
|
purpose: Classify factors by horizon, decay, and conflict policy.
|
||||||
factor_horizons:
|
factor_horizons:
|
||||||
- scalping
|
- scalping
|
||||||
- short
|
- short
|
||||||
- mid
|
- mid
|
||||||
- long
|
- long
|
||||||
required_lifecycle_fields:
|
required_lifecycle_fields:
|
||||||
- factor_id
|
- factor_id
|
||||||
- hypothesis
|
- hypothesis
|
||||||
- market_regime_applicability
|
- market_regime_applicability
|
||||||
- horizon
|
- horizon
|
||||||
- decay_half_life
|
- decay_half_life
|
||||||
- input_fields
|
- input_fields
|
||||||
- formula_id
|
- formula_id
|
||||||
- data_quality_requirements
|
- data_quality_requirements
|
||||||
- expected_edge_formula
|
- expected_edge_formula
|
||||||
- conflict_precedence
|
- conflict_precedence
|
||||||
- position_sizing_impact
|
- position_sizing_impact
|
||||||
- exit_impact
|
- exit_impact
|
||||||
- golden_cases
|
- golden_cases
|
||||||
- shadow_start_date
|
- shadow_start_date
|
||||||
- activation_threshold
|
- activation_threshold
|
||||||
- retirement_condition
|
- retirement_condition
|
||||||
- owner
|
- owner
|
||||||
factor_retirement_policy:
|
factor_retirement_policy:
|
||||||
no_edge_improvement_lookback_days: 90
|
no_edge_improvement_lookback_days: 90
|
||||||
shadow_only_before_activation: true
|
shadow_only_before_activation: true
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
|
meta:
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\44_live_replay_separation.yaml
|
||||||
schema_version: live_replay_separation.v2
|
schema_version: live_replay_separation.v2
|
||||||
purpose: Separate live, paper, backtest, and replay evidence.
|
purpose: Separate live, paper, backtest, and replay evidence.
|
||||||
source_types:
|
source_types:
|
||||||
- live
|
- live
|
||||||
- paper
|
- paper
|
||||||
- backtest
|
- backtest
|
||||||
- replay
|
- replay
|
||||||
promotion_rule: live_t20_count_gte_30
|
promotion_rule: live_t20_count_gte_30
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
|
meta:
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\45_number_provenance_contract.yaml
|
||||||
schema_version: number_provenance_contract.v1
|
schema_version: number_provenance_contract.v1
|
||||||
purpose: Attach provenance to every report number.
|
purpose: Attach provenance to every report number.
|
||||||
required_fields:
|
required_fields:
|
||||||
- source_path
|
- source_path
|
||||||
- json_pointer
|
- json_pointer
|
||||||
- formula_id
|
- formula_id
|
||||||
- input_hash
|
- input_hash
|
||||||
- freshness_status
|
- freshness_status
|
||||||
|
|||||||
@@ -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
|
schema_version: low_capability_execution_pack.v1
|
||||||
purpose: Fixed-order packet-only context for low capability LLMs.
|
purpose: Fixed-order packet-only context for low capability LLMs.
|
||||||
required_sections:
|
required_sections:
|
||||||
- executive
|
- executive
|
||||||
- blockers
|
- blockers
|
||||||
- action_table
|
- action_table
|
||||||
- shadow_ledger
|
- shadow_ledger
|
||||||
- data_missing
|
- data_missing
|
||||||
- education_notes
|
- education_notes
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
|
meta:
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\47_packaging_policy.yaml
|
||||||
schema_version: packaging_policy.v1
|
schema_version: packaging_policy.v1
|
||||||
purpose: Define upload bundle inclusion and exclusion policy.
|
purpose: Define upload bundle inclusion and exclusion policy.
|
||||||
required_rules:
|
required_rules:
|
||||||
- source_required
|
- source_required
|
||||||
- runtime_required
|
- runtime_required
|
||||||
- report_required
|
- report_required
|
||||||
- test_required
|
- test_required
|
||||||
|
|||||||
@@ -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
|
schema_version: module_io_contract_registry.v1
|
||||||
modules:
|
modules:
|
||||||
core_engine:
|
core_engine:
|
||||||
id: core_engine
|
id: core_engine
|
||||||
owner: architect
|
owner: architect
|
||||||
inputs: ["GatherTradingData.json"]
|
inputs:
|
||||||
outputs: ["Temp/final_decision_packet_active.json"]
|
- GatherTradingData.json
|
||||||
schema: "schemas/final_decision_packet_v3.schema.json"
|
outputs:
|
||||||
artifact_path: "src/quant_engine/compute_formula_outputs.py"
|
- 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:
|
risk_manager:
|
||||||
id: risk_manager
|
id: risk_manager
|
||||||
owner: risk_officer
|
owner: risk_officer
|
||||||
inputs: ["GatherTradingData.json"]
|
inputs:
|
||||||
outputs: ["Temp/strategy_decision_result_v3.json"]
|
- GatherTradingData.json
|
||||||
schema: "schemas/strategy_decision_result.schema.json"
|
outputs:
|
||||||
artifact_path: "src/quant_engine/exit_decisions.py"
|
- Temp/strategy_decision_result_v3.json
|
||||||
|
schema: schemas/strategy_decision_result.schema.json
|
||||||
|
artifact_path: src/quant_engine/exit_decisions.py
|
||||||
reporting_renderer:
|
reporting_renderer:
|
||||||
id: reporting_renderer
|
id: reporting_renderer
|
||||||
owner: pm
|
owner: pm
|
||||||
inputs: ["Temp/final_decision_packet_active.json"]
|
inputs:
|
||||||
outputs: ["Temp/operational_report.json", "Temp/operational_report.md"]
|
- Temp/final_decision_packet_active.json
|
||||||
schema: "schemas/operational_report.schema.json"
|
outputs:
|
||||||
artifact_path: "tools/render_operational_report.py"
|
- Temp/operational_report.json
|
||||||
|
- Temp/operational_report.md
|
||||||
|
schema: schemas/operational_report.schema.json
|
||||||
|
artifact_path: tools/render_operational_report.py
|
||||||
context_builder:
|
context_builder:
|
||||||
id: context_builder
|
id: context_builder
|
||||||
owner: pm
|
owner: pm
|
||||||
inputs: ["Temp/final_decision_packet_v4.json", "runtime/active_artifact_manifest.yaml"]
|
inputs:
|
||||||
outputs: ["Temp/final_context_for_llm_v5.yaml"]
|
- Temp/final_decision_packet_v4.json
|
||||||
schema: "spec/46_low_capability_execution_pack.yaml"
|
- runtime/active_artifact_manifest.yaml
|
||||||
artifact_path: "tools/build_low_capability_context_pack_v5.py"
|
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
|
||||||
|
|||||||
@@ -1,19 +1,30 @@
|
|||||||
|
meta:
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\49_refactor_methodology_contract.yaml
|
||||||
schema_version: refactor_methodology_contract.v1
|
schema_version: refactor_methodology_contract.v1
|
||||||
principles:
|
principles:
|
||||||
- QEDD: Quant Evidence-Driven Deterministic Development
|
- QEDD: Quant Evidence-Driven Deterministic Development
|
||||||
- Contract-First: YAML/Schema before implementation
|
- Contract-First: YAML/Schema before implementation
|
||||||
- Python Canonical: Logic in src/quant_engine, GAS is thin adapter
|
- Python Canonical: Logic in src/quant_engine, GAS is thin adapter
|
||||||
- No LLM Math: LLM copies harness values with provenance
|
- No LLM Math: LLM copies harness values with provenance
|
||||||
authority_order:
|
authority_order:
|
||||||
- spec/*.yaml
|
- spec/*.yaml
|
||||||
- runtime/active_artifact_manifest.yaml
|
- runtime/active_artifact_manifest.yaml
|
||||||
- Temp/final_decision_packet_active.json
|
- Temp/final_decision_packet_active.json
|
||||||
- governance/rules/*.yaml
|
- governance/rules/*.yaml
|
||||||
file_policy:
|
file_policy:
|
||||||
source: [md, yaml, py, gs]
|
source:
|
||||||
runtime: [json, jsonl, schema.json]
|
- md
|
||||||
|
- yaml
|
||||||
|
- py
|
||||||
|
- gs
|
||||||
|
runtime:
|
||||||
|
- json
|
||||||
|
- jsonl
|
||||||
|
- schema.json
|
||||||
do_done:
|
do_done:
|
||||||
- Release DAG PASS
|
- Release DAG PASS
|
||||||
- No SKIPPED in release mode
|
- No SKIPPED in release mode
|
||||||
- Zero architecture boundary violations
|
- Zero architecture boundary violations
|
||||||
- 100% number provenance coverage
|
- 100% number provenance coverage
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
meta:
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\51_formula_lifecycle_registry.yaml
|
||||||
schema_version: formula_lifecycle_registry.v1
|
schema_version: formula_lifecycle_registry.v1
|
||||||
updated_at: '2026-06-13'
|
updated_at: '2026-06-13'
|
||||||
purpose: '모든 ACTIVE 공식의 lifecycle 상태를 단일 레지스트리로 관리한다. spec/13_formula_registry.yaml(149개)
|
purpose: '모든 ACTIVE 공식의 lifecycle 상태를 단일 레지스트리로 관리한다. spec/13_formula_registry.yaml(149개)
|
||||||
|
|||||||
@@ -1,21 +1,26 @@
|
|||||||
|
meta:
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\anti_late_entry_contract.yaml
|
||||||
schema_version: anti_late_entry_contract.v2
|
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:
|
metrics:
|
||||||
- id: breakout_quality
|
- id: breakout_quality
|
||||||
description: "20D high status and volume acceleration at breakout"
|
description: 20D high status and volume acceleration at breakout
|
||||||
- id: flow_acceleration
|
- id: flow_acceleration
|
||||||
description: "Foreign/Institutional net buying acceleration indicator"
|
description: Foreign/Institutional net buying acceleration indicator
|
||||||
- id: distribution_risk
|
- id: distribution_risk
|
||||||
description: "Risk score reflecting high-volume churn without price progression"
|
description: Risk score reflecting high-volume churn without price progression
|
||||||
- id: entry_timing_decile
|
- id: entry_timing_decile
|
||||||
description: "Decile rank of entry timing relative to recent price progression"
|
description: Decile rank of entry timing relative to recent price progression
|
||||||
rules:
|
rules:
|
||||||
- id: RULE_OVERHEATED_BLOCK_BUY
|
- id: RULE_OVERHEATED_BLOCK_BUY
|
||||||
condition: "entry_timing_decile >= 8 (Overheated zone)"
|
condition: entry_timing_decile >= 8 (Overheated zone)
|
||||||
action: "BLOCK new buys until a pullback trigger is confirmed"
|
action: BLOCK new buys until a pullback trigger is confirmed
|
||||||
- id: RULE_DISTRIBUTION_DOWNGRADE
|
- id: RULE_DISTRIBUTION_DOWNGRADE
|
||||||
condition: "distribution_risk is HIGH"
|
condition: distribution_risk is HIGH
|
||||||
action: "Downgrade BUY to HOLD/WAIT"
|
action: Downgrade BUY to HOLD/WAIT
|
||||||
- id: RULE_LATE_CHASE_ATTRIBUTION
|
- id: RULE_LATE_CHASE_ATTRIBUTION
|
||||||
condition: "T+5/T+20 operational outcomes are updated to attribute entry quality"
|
condition: T+5/T+20 operational outcomes are updated to attribute entry quality
|
||||||
action: "Update attribution metrics"
|
action: Update attribution metrics
|
||||||
|
|||||||
@@ -1,14 +1,24 @@
|
|||||||
|
meta:
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\data_quality\expectations.yaml
|
||||||
schema_version: data_quality_expectations.v1
|
schema_version: data_quality_expectations.v1
|
||||||
groups:
|
groups:
|
||||||
account:
|
account:
|
||||||
- not_null: [total_asset_krw, cash_krw]
|
- not_null:
|
||||||
|
- total_asset_krw
|
||||||
|
- cash_krw
|
||||||
price:
|
price:
|
||||||
- freshness_minutes: 390
|
- freshness_minutes: 390
|
||||||
- not_null: [current_price_krw]
|
- not_null:
|
||||||
|
- current_price_krw
|
||||||
fundamentals:
|
fundamentals:
|
||||||
- not_null: [roe, revenue_growth]
|
- not_null:
|
||||||
|
- roe
|
||||||
|
- revenue_growth
|
||||||
external_context:
|
external_context:
|
||||||
- allowed_values: [CONTEXT_ONLY, ORDER_JUDGMENT]
|
- allowed_values:
|
||||||
|
- CONTEXT_ONLY
|
||||||
|
- ORDER_JUDGMENT
|
||||||
cross_field:
|
cross_field:
|
||||||
- rule: current_price_krw > 0
|
- rule: current_price_krw > 0
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
|
meta:
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\execution_authority_matrix_v2.yaml
|
||||||
schema_version: execution_authority_matrix.v2
|
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:
|
source_of_truth:
|
||||||
- Temp/final_execution_decision_v1.json
|
- Temp/final_execution_decision_v1.json
|
||||||
- Temp/operational_report.json
|
- Temp/operational_report.json
|
||||||
- Temp/execution_authority_matrix_v1.json
|
- Temp/execution_authority_matrix_v1.json
|
||||||
authority_precedence:
|
authority_precedence:
|
||||||
- BLOCK_EXECUTION
|
- BLOCK_EXECUTION
|
||||||
- AUDIT_ONLY
|
- AUDIT_ONLY
|
||||||
- EXPLAIN_ONLY
|
- EXPLAIN_ONLY
|
||||||
- HTS_READY
|
- HTS_READY
|
||||||
field_owner_runtime:
|
field_owner_runtime:
|
||||||
price: GAS_OR_PY
|
price: GAS_OR_PY
|
||||||
qty: GAS_OR_PY
|
qty: GAS_OR_PY
|
||||||
@@ -18,10 +22,10 @@ field_owner_runtime:
|
|||||||
gate: GAS_OR_PY
|
gate: GAS_OR_PY
|
||||||
narrative: LLM_ONLY
|
narrative: LLM_ONLY
|
||||||
rules:
|
rules:
|
||||||
- "If global_execution_gate != HTS_READY, suppress HTS order table."
|
- If global_execution_gate != HTS_READY, suppress HTS order table.
|
||||||
- "Candidate rows with validation_status != PASS must render only as shadow ledger."
|
- 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."
|
- 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 any authority conflict appears, emit AUDIT_ONLY and record the conflict in JSON.
|
||||||
acceptance:
|
acceptance:
|
||||||
authority_conflict_count: 0
|
authority_conflict_count: 0
|
||||||
hidden_order_leak_count: 0
|
hidden_order_leak_count: 0
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ meta:
|
|||||||
language: "ko-KR"
|
language: "ko-KR"
|
||||||
timezone: "Asia/Seoul"
|
timezone: "Asia/Seoul"
|
||||||
role: "canonical"
|
role: "canonical"
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path: ["spec/strategy/action_matrix.yaml"]
|
||||||
migration_status: "canonical_split_active"
|
migration_status: "canonical_split_active"
|
||||||
|
|
||||||
take_profit:
|
take_profit:
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
meta:
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\factor_lifecycle_registry.yaml
|
||||||
schema_version: factor_lifecycle_registry.v1
|
schema_version: factor_lifecycle_registry.v1
|
||||||
description: Lifecycle states (draft, shadow, candidate, active, retired) for all
|
description: Lifecycle states (draft, shadow, candidate, active, retired) for all
|
||||||
registered quant factors
|
registered quant factors
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
|
meta:
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\fields\field_dictionary.yaml
|
||||||
schema_version: field_dictionary.v1
|
schema_version: field_dictionary.v1
|
||||||
source_of_truth: spec/12_field_dictionary.yaml
|
source_of_truth: spec/12_field_dictionary.yaml
|
||||||
policy:
|
policy:
|
||||||
canonical_name_required: true
|
canonical_name_required: true
|
||||||
unknown_field_action: DATA_MISSING
|
unknown_field_action: DATA_MISSING
|
||||||
unit_conflict_action: DATA_CONFLICT
|
unit_conflict_action: DATA_CONFLICT
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ meta:
|
|||||||
title: NF1~NF5 Python-harness 보조 공식 명세 golden cases
|
title: NF1~NF5 Python-harness 보조 공식 명세 golden cases
|
||||||
note: 'GAS_REFERENCE_ONLY: Python 미러 없음. behavioral_coverage 체크 대상 외.'
|
note: 'GAS_REFERENCE_ONLY: Python 미러 없음. behavioral_coverage 체크 대상 외.'
|
||||||
source_registry: spec/13_formula_registry.yaml:NF1~NF5
|
source_registry: spec/13_formula_registry.yaml:NF1~NF5
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\formula_golden_cases_nf.yaml
|
||||||
golden_cases_nf:
|
golden_cases_nf:
|
||||||
- formula_id: REGIME_CONDITIONAL_MACRO_FACTOR_V1
|
- formula_id: REGIME_CONDITIONAL_MACRO_FACTOR_V1
|
||||||
gas_function: GAS_REFERENCE_ONLY
|
gas_function: GAS_REFERENCE_ONLY
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
meta:
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\formula_golden_cases_v2.yaml
|
||||||
golden_cases_v2:
|
golden_cases_v2:
|
||||||
- formula_id: TICK_NORMALIZER_V1
|
- formula_id: TICK_NORMALIZER_V1
|
||||||
gas_function: tickNormalize_
|
gas_function: tickNormalize_
|
||||||
|
|||||||
+122
-118
@@ -1,122 +1,126 @@
|
|||||||
|
meta:
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\formula_golden_cases_v3.yaml
|
||||||
schema_version: formula_golden_cases.v3
|
schema_version: formula_golden_cases.v3
|
||||||
source: formula_golden_cases_v2
|
source: formula_golden_cases_v2
|
||||||
note: deterministic bridge spec for coverage expansion
|
note: deterministic bridge spec for coverage expansion
|
||||||
golden_cases:
|
golden_cases:
|
||||||
- formula_id: POSITION_SIZE_V1
|
- formula_id: POSITION_SIZE_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: TAKE_PROFIT_LADDER_V1
|
- formula_id: TAKE_PROFIT_LADDER_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: TAKE_PROFIT_LADDER_V2
|
- formula_id: TAKE_PROFIT_LADDER_V2
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: PEG_SCORE_V1
|
- formula_id: PEG_SCORE_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: PORTFOLIO_BAND_STATUS_V1
|
- formula_id: PORTFOLIO_BAND_STATUS_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: OVERSOLD_DELAY_V1
|
- formula_id: OVERSOLD_DELAY_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: SECTOR_ROTATION_RADAR_V1
|
- formula_id: SECTOR_ROTATION_RADAR_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: SEA_TIMING_V1
|
- formula_id: SEA_TIMING_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: ECP_RISK_SCALE_V1
|
- formula_id: ECP_RISK_SCALE_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: FOLLOW_THROUGH_DAY_CONFIRM_V1
|
- formula_id: FOLLOW_THROUGH_DAY_CONFIRM_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: EXECUTION_QUALITY_SCORE_V1
|
- formula_id: EXECUTION_QUALITY_SCORE_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: COMPOSITE_VERDICT_V1
|
- formula_id: COMPOSITE_VERDICT_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: SATELLITE_FAILURE_GATE_V1
|
- formula_id: SATELLITE_FAILURE_GATE_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: BENCHMARK_RELATIVE_TIMESERIES_V1
|
- formula_id: BENCHMARK_RELATIVE_TIMESERIES_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: RS_VERDICT_V2
|
- formula_id: RS_VERDICT_V2
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: CASH_CREATION_PURPOSE_LOCK_V1
|
- formula_id: CASH_CREATION_PURPOSE_LOCK_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: ALPHA_EVALUATION_WINDOW_V1
|
- formula_id: ALPHA_EVALUATION_WINDOW_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: HARNESS_DATA_FRESHNESS_GATE_V1
|
- formula_id: HARNESS_DATA_FRESHNESS_GATE_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: PORTFOLIO_CORRELATION_GATE_V1
|
- formula_id: PORTFOLIO_CORRELATION_GATE_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: ALPHA_FEEDBACK_LOOP_V1
|
- formula_id: ALPHA_FEEDBACK_LOOP_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: DISTRIBUTION_SELL_DETECTOR_V1
|
- formula_id: DISTRIBUTION_SELL_DETECTOR_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: SELL_EXECUTION_TIMING_V1
|
- formula_id: SELL_EXECUTION_TIMING_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: DETERMINISTIC_ROUTING_ENGINE_V1
|
- formula_id: DETERMINISTIC_ROUTING_ENGINE_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: SELL_VALUE_PRESERVATION_TIERED_V2
|
- formula_id: SELL_VALUE_PRESERVATION_TIERED_V2
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: TRADE_QUALITY_SCORER_V1
|
- formula_id: TRADE_QUALITY_SCORER_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: PATTERN_BLACKLIST_AUTO_V1
|
- formula_id: PATTERN_BLACKLIST_AUTO_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: HORIZON_ALLOCATION_LOCK_V1
|
- formula_id: HORIZON_ALLOCATION_LOCK_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: SMART_MONEY_LIQUIDITY_GATE_V1
|
- formula_id: SMART_MONEY_LIQUIDITY_GATE_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: FUNDAMENTAL_MULTI_FACTOR_SCORE_V2
|
- formula_id: FUNDAMENTAL_MULTI_FACTOR_SCORE_V2
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: EARNINGS_GROWTH_QUALITY_GATE_V1
|
- formula_id: EARNINGS_GROWTH_QUALITY_GATE_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: MARKET_SHARE_MOMENTUM_PROXY_V1
|
- formula_id: MARKET_SHARE_MOMENTUM_PROXY_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: CASHFLOW_STABILITY_GATE_V1
|
- formula_id: CASHFLOW_STABILITY_GATE_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: ROUTING_DECISION_EXPLAIN_LOCK_V1
|
- formula_id: ROUTING_DECISION_EXPLAIN_LOCK_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: RATCHET_TRAILING_GENERAL_V1
|
- formula_id: RATCHET_TRAILING_GENERAL_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: EJCE_VIEW_RENDERER_V1
|
- formula_id: EJCE_VIEW_RENDERER_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: ROUTING_EXECUTION_LOG_TABLE_V1
|
- formula_id: ROUTING_EXECUTION_LOG_TABLE_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: HORIZON_CLASSIFICATION_V1
|
- formula_id: HORIZON_CLASSIFICATION_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: SMART_MONEY_FLOW_SIGNAL_V2
|
- formula_id: SMART_MONEY_FLOW_SIGNAL_V2
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: EARNINGS_QUALITY_SIGNAL_V1
|
- formula_id: EARNINGS_QUALITY_SIGNAL_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: TRADE_QUALITY_FROM_T5_V1
|
- formula_id: TRADE_QUALITY_FROM_T5_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: PREDICTION_ACCURACY_HARNESS_V2
|
- formula_id: PREDICTION_ACCURACY_HARNESS_V2
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: MACRO_EVENT_TICKER_IMPACT_V1
|
- formula_id: MACRO_EVENT_TICKER_IMPACT_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: EJCE_DIVERGENCE_AUDIT_V1
|
- formula_id: EJCE_DIVERGENCE_AUDIT_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: PREDICTIVE_ALPHA_REPORT_LOCK_V2
|
- formula_id: PREDICTIVE_ALPHA_REPORT_LOCK_V2
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: VERDICT_CONSISTENCY_LOCK_V1
|
- formula_id: VERDICT_CONSISTENCY_LOCK_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: INVESTMENT_QUALITY_HEADLINE_V1
|
- formula_id: INVESTMENT_QUALITY_HEADLINE_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: SELL_PRICE_SANITY_V2
|
- formula_id: SELL_PRICE_SANITY_V2
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: EXPORT_GATE_V2
|
- formula_id: EXPORT_GATE_V2
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: PROACTIVE_SELL_RADAR_V2
|
- formula_id: PROACTIVE_SELL_RADAR_V2
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: ANTI_LATE_ENTRY_GATE_V3
|
- formula_id: ANTI_LATE_ENTRY_GATE_V3
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: PRICE_HIERARCHY_LOCK_V1
|
- formula_id: PRICE_HIERARCHY_LOCK_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: DATA_QUALITY_GATE_V2
|
- formula_id: DATA_QUALITY_GATE_V2
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: CASH_RECOVERY_DISPLAY_LOCK_V1
|
- formula_id: CASH_RECOVERY_DISPLAY_LOCK_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: ALPHA_FEEDBACK_LOOP_V2
|
- formula_id: ALPHA_FEEDBACK_LOOP_V2
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: ALPHA_LEAD_THRESHOLD_OPTIMIZER_V1
|
- formula_id: ALPHA_LEAD_THRESHOLD_OPTIMIZER_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: DYNAMIC_VALUE_PRESERVATION_SELL_V6
|
- formula_id: DYNAMIC_VALUE_PRESERVATION_SELL_V6
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: PREDICTIVE_ALPHA_DIALECTIC_ENGINE_V2
|
- formula_id: PREDICTIVE_ALPHA_DIALECTIC_ENGINE_V2
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: CAPITAL_STYLE_TIME_STOP_V1
|
- formula_id: CAPITAL_STYLE_TIME_STOP_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
- formula_id: EXECUTION_INTEGRITY_GATE_V1
|
- formula_id: EXECUTION_INTEGRITY_GATE_V1
|
||||||
bridge_only: true
|
bridge_only: true
|
||||||
|
|||||||
+1208
-854
File diff suppressed because it is too large
Load Diff
@@ -1,17 +1,21 @@
|
|||||||
|
meta:
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\formula_lifecycle_index.yaml
|
||||||
schema_version: formula_lifecycle_index.v1
|
schema_version: formula_lifecycle_index.v1
|
||||||
classifications:
|
classifications:
|
||||||
active:
|
active:
|
||||||
description: "Formulas currently used in the primary execution order"
|
description: Formulas currently used in the primary execution order
|
||||||
match_rule: "in_primary_execution_order == true"
|
match_rule: in_primary_execution_order == true
|
||||||
shadow:
|
shadow:
|
||||||
description: "New formulas under evaluation"
|
description: New formulas under evaluation
|
||||||
match_rule: "status == 'shadow'"
|
match_rule: status == 'shadow'
|
||||||
experimental:
|
experimental:
|
||||||
description: "Formulas for research only"
|
description: Formulas for research only
|
||||||
match_rule: "status == 'experimental'"
|
match_rule: status == 'experimental'
|
||||||
deprecated:
|
deprecated:
|
||||||
description: "Formulas pending retirement"
|
description: Formulas pending retirement
|
||||||
match_rule: "status == 'deprecated'"
|
match_rule: status == 'deprecated'
|
||||||
runtime_supplement:
|
runtime_supplement:
|
||||||
description: "Helper formulas for internal logic"
|
description: Helper formulas for internal logic
|
||||||
match_rule: "role == 'helper'"
|
match_rule: role == 'helper'
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
meta:
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\formulas\manifest.yaml
|
||||||
schema_version: formula_domain_manifest.v1
|
schema_version: formula_domain_manifest.v1
|
||||||
source: C:\Temp\data_feed\spec\13_formula_registry.yaml
|
source: C:\Temp\data_feed\spec\13_formula_registry.yaml
|
||||||
domains:
|
domains:
|
||||||
|
|||||||
+280
-276
@@ -1,278 +1,282 @@
|
|||||||
|
meta:
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\gas_adapter_contract.yaml
|
||||||
schema_version: gas_adapter_contract.v1
|
schema_version: gas_adapter_contract.v1
|
||||||
exports:
|
exports:
|
||||||
- function_name: "runDataFeed"
|
- function_name: runDataFeed
|
||||||
min_arity: 0
|
min_arity: 0
|
||||||
max_arity: 0
|
max_arity: 0
|
||||||
return_shape: "void"
|
return_shape: void
|
||||||
sheet_key: "sector_flow"
|
sheet_key: sector_flow
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "runDataFeed"
|
- function_name: runDataFeed
|
||||||
min_arity: 0
|
min_arity: 0
|
||||||
max_arity: 0
|
max_arity: 0
|
||||||
return_shape: "void"
|
return_shape: void
|
||||||
sheet_key: "macro"
|
sheet_key: macro
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "runDataFeed"
|
- function_name: runDataFeed
|
||||||
min_arity: 0
|
min_arity: 0
|
||||||
max_arity: 0
|
max_arity: 0
|
||||||
return_shape: "void"
|
return_shape: void
|
||||||
sheet_key: "core_satellite"
|
sheet_key: core_satellite
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "logDailyAssetHistory_"
|
- function_name: logDailyAssetHistory_
|
||||||
min_arity: 2
|
min_arity: 2
|
||||||
max_arity: 2
|
max_arity: 2
|
||||||
return_shape: "void"
|
return_shape: void
|
||||||
sheet_key: "daily_history"
|
sheet_key: daily_history
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "ensureAccountSnapshotConfirmModeSetting_"
|
- function_name: ensureAccountSnapshotConfirmModeSetting_
|
||||||
min_arity: 1
|
min_arity: 1
|
||||||
max_arity: 1
|
max_arity: 1
|
||||||
return_shape: "void"
|
return_shape: void
|
||||||
sheet_key: "settings"
|
sheet_key: settings
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "upsertOperationalWarningSetting_"
|
- function_name: upsertOperationalWarningSetting_
|
||||||
min_arity: 2
|
min_arity: 2
|
||||||
max_arity: 2
|
max_arity: 2
|
||||||
return_shape: "void"
|
return_shape: void
|
||||||
sheet_key: "settings"
|
sheet_key: settings
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "getCoreSatelliteUniverse"
|
- function_name: getCoreSatelliteUniverse
|
||||||
min_arity: 0
|
min_arity: 0
|
||||||
max_arity: 0
|
max_arity: 0
|
||||||
return_shape: "array"
|
return_shape: array
|
||||||
sheet_key: "universe"
|
sheet_key: universe
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "parseAccountSnapshot_"
|
- function_name: parseAccountSnapshot_
|
||||||
min_arity: 3
|
min_arity: 3
|
||||||
max_arity: 3
|
max_arity: 3
|
||||||
return_shape: "object"
|
return_shape: object
|
||||||
sheet_key: "account_snapshot"
|
sheet_key: account_snapshot
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "parseAccountSnapshot_"
|
- function_name: parseAccountSnapshot_
|
||||||
min_arity: 3
|
min_arity: 3
|
||||||
max_arity: 3
|
max_arity: 3
|
||||||
return_shape: "object"
|
return_shape: object
|
||||||
sheet_key: "macro"
|
sheet_key: macro
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "getActiveTickers_"
|
- function_name: getActiveTickers_
|
||||||
min_arity: 0
|
min_arity: 0
|
||||||
max_arity: 0
|
max_arity: 0
|
||||||
return_shape: "array"
|
return_shape: array
|
||||||
sheet_key: "account_snapshot"
|
sheet_key: account_snapshot
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "getActiveTickers_"
|
- function_name: getActiveTickers_
|
||||||
min_arity: 0
|
min_arity: 0
|
||||||
max_arity: 0
|
max_arity: 0
|
||||||
return_shape: "array"
|
return_shape: array
|
||||||
sheet_key: "settings"
|
sheet_key: settings
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "checkAccountSnapshotFreshness_"
|
- function_name: checkAccountSnapshotFreshness_
|
||||||
min_arity: 0
|
min_arity: 0
|
||||||
max_arity: 0
|
max_arity: 0
|
||||||
return_shape: "void"
|
return_shape: void
|
||||||
sheet_key: "account_snapshot"
|
sheet_key: account_snapshot
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "readAccountSnapshotHeat_"
|
- function_name: readAccountSnapshotHeat_
|
||||||
min_arity: 1
|
min_arity: 1
|
||||||
max_arity: 1
|
max_arity: 1
|
||||||
return_shape: "object"
|
return_shape: object
|
||||||
sheet_key: "data_feed"
|
sheet_key: data_feed
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "getAccountSnapshotConfirmStats_"
|
- function_name: getAccountSnapshotConfirmStats_
|
||||||
min_arity: 0
|
min_arity: 0
|
||||||
max_arity: 0
|
max_arity: 0
|
||||||
return_shape: "object"
|
return_shape: object
|
||||||
sheet_key: "account_snapshot"
|
sheet_key: account_snapshot
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "readMacroRegime_"
|
- function_name: readMacroRegime_
|
||||||
min_arity: 1
|
min_arity: 1
|
||||||
max_arity: 1
|
max_arity: 1
|
||||||
return_shape: "object"
|
return_shape: object
|
||||||
sheet_key: "macro"
|
sheet_key: macro
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "parseAccuracy_"
|
- function_name: parseAccuracy_
|
||||||
min_arity: 1
|
min_arity: 1
|
||||||
max_arity: 1
|
max_arity: 1
|
||||||
return_shape: "object"
|
return_shape: object
|
||||||
sheet_key: "monthly_history"
|
sheet_key: monthly_history
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "parseAccuracy_"
|
- function_name: parseAccuracy_
|
||||||
min_arity: 1
|
min_arity: 1
|
||||||
max_arity: 1
|
max_arity: 1
|
||||||
return_shape: "object"
|
return_shape: object
|
||||||
sheet_key: "settings"
|
sheet_key: settings
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "getPa1WeightOverrides_"
|
- function_name: getPa1WeightOverrides_
|
||||||
min_arity: 0
|
min_arity: 0
|
||||||
max_arity: 0
|
max_arity: 0
|
||||||
return_shape: "object"
|
return_shape: object
|
||||||
sheet_key: "settings"
|
sheet_key: settings
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "recordPa1FeedbackEntry_"
|
- function_name: recordPa1FeedbackEntry_
|
||||||
min_arity: 2
|
min_arity: 2
|
||||||
max_arity: 2
|
max_arity: 2
|
||||||
return_shape: "void"
|
return_shape: void
|
||||||
sheet_key: "pa1_feedback"
|
sheet_key: pa1_feedback
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "getSellPassAccuracyRate_"
|
- function_name: getSellPassAccuracyRate_
|
||||||
min_arity: 0
|
min_arity: 0
|
||||||
max_arity: 0
|
max_arity: 0
|
||||||
return_shape: "number"
|
return_shape: number
|
||||||
sheet_key: "pa1_feedback"
|
sheet_key: pa1_feedback
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "evaluatePa1FeedbackBatch_"
|
- function_name: evaluatePa1FeedbackBatch_
|
||||||
min_arity: 0
|
min_arity: 0
|
||||||
max_arity: 0
|
max_arity: 0
|
||||||
return_shape: "void"
|
return_shape: void
|
||||||
sheet_key: "pa1_feedback"
|
sheet_key: pa1_feedback
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "evaluatePa1FeedbackBatch_"
|
- function_name: evaluatePa1FeedbackBatch_
|
||||||
min_arity: 0
|
min_arity: 0
|
||||||
max_arity: 0
|
max_arity: 0
|
||||||
return_shape: "void"
|
return_shape: void
|
||||||
sheet_key: "data_feed"
|
sheet_key: data_feed
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "evaluatePa1FeedbackBatch_"
|
- function_name: evaluatePa1FeedbackBatch_
|
||||||
min_arity: 0
|
min_arity: 0
|
||||||
max_arity: 0
|
max_arity: 0
|
||||||
return_shape: "void"
|
return_shape: void
|
||||||
sheet_key: "settings"
|
sheet_key: settings
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "adjustPaeWeights_"
|
- function_name: adjustPaeWeights_
|
||||||
min_arity: 0
|
min_arity: 0
|
||||||
max_arity: 0
|
max_arity: 0
|
||||||
return_shape: "void"
|
return_shape: void
|
||||||
sheet_key: "settings"
|
sheet_key: settings
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "updateEvaluationDashboard_"
|
- function_name: updateEvaluationDashboard_
|
||||||
min_arity: 0
|
min_arity: 0
|
||||||
max_arity: 0
|
max_arity: 0
|
||||||
return_shape: "void"
|
return_shape: void
|
||||||
sheet_key: "evaluation_dashboard"
|
sheet_key: evaluation_dashboard
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "updateEvaluationDashboard_"
|
- function_name: updateEvaluationDashboard_
|
||||||
min_arity: 0
|
min_arity: 0
|
||||||
max_arity: 0
|
max_arity: 0
|
||||||
return_shape: "void"
|
return_shape: void
|
||||||
sheet_key: "daily_history"
|
sheet_key: daily_history
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "updateEvaluationDashboard_"
|
- function_name: updateEvaluationDashboard_
|
||||||
min_arity: 0
|
min_arity: 0
|
||||||
max_arity: 0
|
max_arity: 0
|
||||||
return_shape: "void"
|
return_shape: void
|
||||||
sheet_key: "macro"
|
sheet_key: macro
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "getAlphaHistorySummary_"
|
- function_name: getAlphaHistorySummary_
|
||||||
min_arity: 0
|
min_arity: 0
|
||||||
max_arity: 0
|
max_arity: 0
|
||||||
return_shape: "object"
|
return_shape: object
|
||||||
sheet_key: "alpha_history"
|
sheet_key: alpha_history
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "auditYamlGasCoverage_"
|
- function_name: auditYamlGasCoverage_
|
||||||
min_arity: 0
|
min_arity: 0
|
||||||
max_arity: 0
|
max_arity: 0
|
||||||
return_shape: "object"
|
return_shape: object
|
||||||
sheet_key: "settings"
|
sheet_key: settings
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "calcTradeQualityScorer_"
|
- function_name: calcTradeQualityScorer_
|
||||||
min_arity: 1
|
min_arity: 1
|
||||||
max_arity: 1
|
max_arity: 1
|
||||||
return_shape: "object"
|
return_shape: object
|
||||||
sheet_key: "trade_quality_history"
|
sheet_key: trade_quality_history
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "calcTradeQualityScorer_"
|
- function_name: calcTradeQualityScorer_
|
||||||
min_arity: 1
|
min_arity: 1
|
||||||
max_arity: 1
|
max_arity: 1
|
||||||
return_shape: "object"
|
return_shape: object
|
||||||
sheet_key: "data_feed"
|
sheet_key: data_feed
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "calcTradeQualityScorer_"
|
- function_name: calcTradeQualityScorer_
|
||||||
min_arity: 1
|
min_arity: 1
|
||||||
max_arity: 1
|
max_arity: 1
|
||||||
return_shape: "object"
|
return_shape: object
|
||||||
sheet_key: "settings"
|
sheet_key: settings
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "calcPatternBlacklistAuto_"
|
- function_name: calcPatternBlacklistAuto_
|
||||||
min_arity: 1
|
min_arity: 1
|
||||||
max_arity: 1
|
max_arity: 1
|
||||||
return_shape: "object"
|
return_shape: object
|
||||||
sheet_key: "settings"
|
sheet_key: settings
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "calcAlphaFeedbackLoop_"
|
- function_name: calcAlphaFeedbackLoop_
|
||||||
min_arity: 0
|
min_arity: 0
|
||||||
max_arity: 0
|
max_arity: 0
|
||||||
return_shape: "object"
|
return_shape: object
|
||||||
sheet_key: "monthly_history"
|
sheet_key: monthly_history
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "calcAlphaFeedbackLoop_"
|
- function_name: calcAlphaFeedbackLoop_
|
||||||
min_arity: 0
|
min_arity: 0
|
||||||
max_arity: 0
|
max_arity: 0
|
||||||
return_shape: "object"
|
return_shape: object
|
||||||
sheet_key: "settings"
|
sheet_key: settings
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "getAlphaFeedbackJson_"
|
- function_name: getAlphaFeedbackJson_
|
||||||
min_arity: 0
|
min_arity: 0
|
||||||
max_arity: 0
|
max_arity: 0
|
||||||
return_shape: "object"
|
return_shape: object
|
||||||
sheet_key: "settings"
|
sheet_key: settings
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "_writeRebalanceSheet_"
|
- function_name: _writeRebalanceSheet_
|
||||||
min_arity: 4
|
min_arity: 4
|
||||||
max_arity: 4
|
max_arity: 4
|
||||||
return_shape: "void"
|
return_shape: void
|
||||||
sheet_key: "rebalance"
|
sheet_key: rebalance
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "readSettingsTab_"
|
- function_name: readSettingsTab_
|
||||||
min_arity: 0
|
min_arity: 0
|
||||||
max_arity: 0
|
max_arity: 0
|
||||||
return_shape: "object"
|
return_shape: object
|
||||||
sheet_key: "settings"
|
sheet_key: settings
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "readPerformanceSheet_"
|
- function_name: readPerformanceSheet_
|
||||||
min_arity: 0
|
min_arity: 0
|
||||||
max_arity: 0
|
max_arity: 0
|
||||||
return_shape: "object"
|
return_shape: object
|
||||||
sheet_key: "performance"
|
sheet_key: performance
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "readExistingEpsRevision_"
|
- function_name: readExistingEpsRevision_
|
||||||
min_arity: 1
|
min_arity: 1
|
||||||
max_arity: 1
|
max_arity: 1
|
||||||
return_shape: "object"
|
return_shape: object
|
||||||
sheet_key: "core_satellite"
|
sheet_key: core_satellite
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "calcFcBudget_"
|
- function_name: calcFcBudget_
|
||||||
min_arity: 2
|
min_arity: 2
|
||||||
max_arity: 2
|
max_arity: 2
|
||||||
return_shape: "number"
|
return_shape: number
|
||||||
sheet_key: "performance"
|
sheet_key: performance
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "readAccountSnapshotMap_"
|
- function_name: readAccountSnapshotMap_
|
||||||
min_arity: 0
|
min_arity: 0
|
||||||
max_arity: 0
|
max_arity: 0
|
||||||
return_shape: "object"
|
return_shape: object
|
||||||
sheet_key: "account_snapshot"
|
sheet_key: account_snapshot
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "initAccountSnapshotTemplate_"
|
- function_name: initAccountSnapshotTemplate_
|
||||||
min_arity: 0
|
min_arity: 0
|
||||||
max_arity: 0
|
max_arity: 0
|
||||||
return_shape: "void"
|
return_shape: void
|
||||||
sheet_key: "universe"
|
sheet_key: universe
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "runCoreSatelliteBatch"
|
- function_name: runCoreSatelliteBatch
|
||||||
min_arity: 0
|
min_arity: 0
|
||||||
max_arity: 0
|
max_arity: 0
|
||||||
return_shape: "void"
|
return_shape: void
|
||||||
sheet_key: "core_satellite"
|
sheet_key: core_satellite
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "buildDataFeedMap_"
|
- function_name: buildDataFeedMap_
|
||||||
min_arity: 1
|
min_arity: 1
|
||||||
max_arity: 1
|
max_arity: 1
|
||||||
return_shape: "object"
|
return_shape: object
|
||||||
sheet_key: "data_feed"
|
sheet_key: data_feed
|
||||||
status: "active"
|
status: active
|
||||||
- function_name: "updatePa1WeightsManual_"
|
- function_name: updatePa1WeightsManual_
|
||||||
min_arity: 0
|
min_arity: 0
|
||||||
max_arity: 0
|
max_arity: 0
|
||||||
return_shape: "void"
|
return_shape: void
|
||||||
sheet_key: "settings"
|
sheet_key: settings
|
||||||
status: "active"
|
status: active
|
||||||
|
|||||||
+52
-42
@@ -1,58 +1,68 @@
|
|||||||
|
meta:
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\operating_cadence.yaml
|
||||||
schema_version: operating_cadence.v2
|
schema_version: operating_cadence.v2
|
||||||
updated_at: '2026-06-10T23:29:00+09:00'
|
updated_at: '2026-06-10T23:29:00+09:00'
|
||||||
goal: >
|
goal: '주말 리밸런싱과 매월 1/11/21 중간점검 cadence를 release DAG input으로 연결한다. rebalance_required,
|
||||||
주말 리밸런싱과 매월 1/11/21 중간점검 cadence를 release DAG input으로 연결한다.
|
mid_check_required는 final_decision_packet에 반드시 포함된다.
|
||||||
rebalance_required, mid_check_required는 final_decision_packet에 반드시 포함된다.
|
|
||||||
timezone: Asia/Seoul
|
|
||||||
|
|
||||||
|
'
|
||||||
|
timezone: Asia/Seoul
|
||||||
cadence:
|
cadence:
|
||||||
weekly_rebalance:
|
weekly_rebalance:
|
||||||
days: [Saturday, Sunday]
|
days:
|
||||||
trigger_field: rebalance_required # final packet에 삽입되는 boolean 필드
|
- Saturday
|
||||||
|
- Sunday
|
||||||
|
trigger_field: rebalance_required
|
||||||
required_sections:
|
required_sections:
|
||||||
- portfolio_rebalance_playbook
|
- portfolio_rebalance_playbook
|
||||||
- ticker_action_matrix
|
- ticker_action_matrix
|
||||||
- sell_priority_table # 매도 후보 2개 이상이면 반드시 포함
|
- sell_priority_table
|
||||||
- cash_and_risk_budget_snapshot
|
- cash_and_risk_budget_snapshot
|
||||||
interim_check:
|
interim_check:
|
||||||
dates: [1, 11, 21]
|
dates:
|
||||||
trigger_field: mid_check_required # final packet에 삽입되는 boolean 필드
|
- 1
|
||||||
|
- 11
|
||||||
|
- 21
|
||||||
|
trigger_field: mid_check_required
|
||||||
required_sections:
|
required_sections:
|
||||||
- engine_health_card
|
- engine_health_card
|
||||||
- data_missing_and_harness_update_list
|
- data_missing_and_harness_update_list
|
||||||
- shadow_ledger_review
|
- shadow_ledger_review
|
||||||
- calibration_drift_report
|
- calibration_drift_report
|
||||||
|
|
||||||
release_dag_integration:
|
release_dag_integration:
|
||||||
input_node: build_operating_cadence_signal_v1
|
input_node: build_operating_cadence_signal_v1
|
||||||
output_fields:
|
output_fields:
|
||||||
- name: rebalance_required
|
- name: rebalance_required
|
||||||
type: bool
|
type: bool
|
||||||
description: 현재 일자가 Saturday 또는 Sunday이면 true
|
description: 현재 일자가 Saturday 또는 Sunday이면 true
|
||||||
- name: mid_check_required
|
- name: mid_check_required
|
||||||
type: bool
|
type: bool
|
||||||
description: 현재 일자의 day가 1, 11, 21 중 하나이면 true
|
description: 현재 일자의 day가 1, 11, 21 중 하나이면 true
|
||||||
- name: cadence_label
|
- name: cadence_label
|
||||||
type: str
|
type: str
|
||||||
enum: [WEEKEND_REBALANCE, MID_MONTH_CHECK, NORMAL]
|
enum:
|
||||||
|
- WEEKEND_REBALANCE
|
||||||
|
- MID_MONTH_CHECK
|
||||||
|
- NORMAL
|
||||||
downstream_nodes:
|
downstream_nodes:
|
||||||
- build_final_context # context pack에 cadence 정보 삽입
|
- build_final_context
|
||||||
- build_final_decision_packet # packet에 rebalance_required 삽입
|
- build_final_decision_packet
|
||||||
|
|
||||||
rules:
|
rules:
|
||||||
- id: RULE_WEEKEND_REBALANCE_CHECK
|
- id: RULE_WEEKEND_REBALANCE_CHECK
|
||||||
condition: current_day in [Saturday, Sunday]
|
condition: current_day in [Saturday, Sunday]
|
||||||
action: Enforce rebalance review playbook. sell priority table must appear.
|
action: Enforce rebalance review playbook. sell priority table must appear.
|
||||||
packet_field: rebalance_required
|
packet_field: rebalance_required
|
||||||
- id: RULE_INTERIM_CHECK
|
- id: RULE_INTERIM_CHECK
|
||||||
condition: current_date.day in [1, 11, 21]
|
condition: current_date.day in [1, 11, 21]
|
||||||
action: Enforce interim quality check playbook. shadow ledger review mandatory.
|
action: Enforce interim quality check playbook. shadow ledger review mandatory.
|
||||||
packet_field: mid_check_required
|
packet_field: mid_check_required
|
||||||
- id: RULE_CADENCE_IN_PACKET
|
- id: RULE_CADENCE_IN_PACKET
|
||||||
condition: always
|
condition: always
|
||||||
action: >
|
action: 'rebalance_required와 mid_check_required는 final_decision_packet_active에 항상
|
||||||
rebalance_required와 mid_check_required는 final_decision_packet_active에
|
포함된다. 값이 없으면 DATA_MISSING — 하네스 업데이트 필요.
|
||||||
항상 포함된다. 값이 없으면 DATA_MISSING — 하네스 업데이트 필요.
|
|
||||||
|
|
||||||
|
'
|
||||||
owner: quant_architect
|
owner: quant_architect
|
||||||
lifecycle_state: active
|
lifecycle_state: active
|
||||||
|
|||||||
+283
-133
@@ -1,136 +1,286 @@
|
|||||||
meta:
|
meta:
|
||||||
title: "은퇴자산포트폴리오 — 문서 소유권 맵"
|
title: 은퇴자산포트폴리오 — 문서 소유권 맵
|
||||||
version: "2026-05-15-F10_fragmentation_guard"
|
version: 2026-05-15-F10_fragmentation_guard
|
||||||
role: "governance"
|
role: governance
|
||||||
purpose: "파일별 책임 범위를 고정해 문서 파편화와 규칙 중복을 방지한다."
|
purpose: 파일별 책임 범위를 고정해 문서 파편화와 규칙 중복을 방지한다.
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\ownership_map.yaml
|
||||||
ownership_map:
|
ownership_map:
|
||||||
"spec/00_execution_contract.yaml":
|
spec/00_execution_contract.yaml:
|
||||||
owns: ["master_prohibitions", "hard_stops", "capture_read_ledger", "order_validation_contract"]
|
owns:
|
||||||
must_not_own: ["종목 점수", "시장국면 세부 계산", "계좌별 세제 라우팅"]
|
- master_prohibitions
|
||||||
"spec/risk/aggregate_risk.yaml":
|
- hard_stops
|
||||||
owns: ["Total_Heat", "포트폴리오 하드스톱", "상관충격", "통합 리스크 엔진"]
|
- capture_read_ledger
|
||||||
must_not_own: ["종목 진입 점수", "HTS 출력 스키마"]
|
- order_validation_contract
|
||||||
"spec/risk/circuit_breakers.yaml":
|
must_not_own:
|
||||||
owns: ["서킷브레이커", "거래비용 통제", "집중도 브레이크", "섹터 급락 대응"]
|
- 종목 점수
|
||||||
must_not_own: ["종목 진입 점수", "HTS 출력 스키마"]
|
- 시장국면 세부 계산
|
||||||
"spec/risk/market_risk_cash.yaml":
|
- 계좌별 세제 라우팅
|
||||||
owns: ["MRS 현금 비중", "VIX/US10Y 위험 현금 룰"]
|
spec/risk/aggregate_risk.yaml:
|
||||||
must_not_own: ["종목 진입 점수", "HTS 출력 스키마"]
|
owns:
|
||||||
"spec/risk/risk_control.yaml":
|
- Total_Heat
|
||||||
owns: ["risk_control compatibility index"]
|
- 포트폴리오 하드스톱
|
||||||
must_not_own: ["새 임계값"]
|
- 상관충격
|
||||||
"spec/risk/portfolio_exposure.yaml":
|
- 통합 리스크 엔진
|
||||||
owns: ["cash_floor", "중복노출", "목표 버킷", "ETF 단계 감축", "현금 버퍼"]
|
must_not_own:
|
||||||
must_not_own: ["개별 종목 점수", "JSON Schema"]
|
- 종목 진입 점수
|
||||||
"spec/risk/quality_control.yaml":
|
- HTS 출력 스키마
|
||||||
owns: ["리스크 품질관리 요약", "금지 규칙 참조"]
|
spec/risk/circuit_breakers.yaml:
|
||||||
must_not_own: ["새 임계값"]
|
owns:
|
||||||
"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:
|
||||||
must_not_own: ["Total_Heat", "capture_read_ledger"]
|
- 종목 진입 점수
|
||||||
"spec/strategy/stock_model.yaml":
|
- HTS 출력 스키마
|
||||||
owns: ["stock_model", "core_satellite_rule"]
|
spec/risk/market_risk_cash.yaml:
|
||||||
must_not_own: ["시장 전체 현금 비중"]
|
owns:
|
||||||
"spec/strategy/rebalancing_trigger.yaml":
|
- MRS 현금 비중
|
||||||
owns: ["rebalancing_trigger"]
|
- VIX/US10Y 위험 현금 룰
|
||||||
must_not_own: ["손절/익절 세부 실행"]
|
must_not_own:
|
||||||
"spec/02_data_contract.yaml":
|
- 종목 진입 점수
|
||||||
owns: ["source_priority", "data_rule", "data_completeness_gate", "xlsx_analysis_protocol"]
|
- HTS 출력 스키마
|
||||||
must_not_own: ["매수/매도 결론"]
|
spec/risk/risk_control.yaml:
|
||||||
"spec/12_field_dictionary.yaml":
|
owns:
|
||||||
owns: ["canonical field names", "field aliases", "field units", "field missing policy"]
|
- risk_control compatibility index
|
||||||
must_not_own: ["투자 판단 임계값", "매수/매도 결론"]
|
must_not_own:
|
||||||
"spec/13_formula_registry.yaml":
|
- 새 임계값
|
||||||
owns: ["executable formulas", "formula inputs", "formula outputs", "formula missing policy"]
|
spec/risk/portfolio_exposure.yaml:
|
||||||
must_not_own: ["보고서 양식", "예시 케이스"]
|
owns:
|
||||||
"spec/14_raw_workbook_mapping.yaml":
|
- cash_floor
|
||||||
owns: ["raw workbook sheets", "raw workbook columns", "workbook to canonical field mapping"]
|
- 중복노출
|
||||||
must_not_own: ["계좌 보유수량", "계좌 현금"]
|
- 목표 버킷
|
||||||
"spec/15_account_snapshot_contract.yaml":
|
- ETF 단계 감축
|
||||||
owns: ["image capture account snapshot", "holding quantity", "average cost", "cash fields", "open orders"]
|
- 현금 버퍼
|
||||||
must_not_own: ["시장 가격 수집", "섹터 점수"]
|
must_not_own:
|
||||||
"spec/05_position_sizing.yaml":
|
- 개별 종목 점수
|
||||||
owns: ["volatility_targeting", "bayesian_confidence", "kelly brake", "integer sizing"]
|
- JSON Schema
|
||||||
must_not_own: ["보유수량 판독", "보고서 양식"]
|
spec/risk/quality_control.yaml:
|
||||||
"spec/06_exit_policy.yaml":
|
owns:
|
||||||
owns: ["exit policy compatibility index"]
|
- 리스크 품질관리 요약
|
||||||
must_not_own: ["새 임계값", "신규매수 게이트"]
|
- 금지 규칙 참조
|
||||||
"spec/exit/stop_loss.yaml":
|
must_not_own:
|
||||||
owns: ["stop_loss"]
|
- 새 임계값
|
||||||
must_not_own: ["신규매수 게이트"]
|
spec/strategy/sector_model.yaml:
|
||||||
"spec/exit/take_profit.yaml":
|
owns:
|
||||||
owns: ["take_profit"]
|
- sector_model
|
||||||
must_not_own: ["신규매수 게이트"]
|
- CSCS
|
||||||
"spec/exit/proactive_exit_radar.yaml":
|
- 등급 alias
|
||||||
owns: ["proactive_exit_radar", "divergence_alert", "overhang_warning", "rotation_radar"]
|
must_not_own:
|
||||||
must_not_own: ["신규매수 게이트"]
|
- 계좌 라우팅
|
||||||
"spec/exit/event_response.yaml":
|
- 현금 하한
|
||||||
owns: ["event_response"]
|
spec/strategy/entry_gates.yaml:
|
||||||
must_not_own: ["신규매수 게이트"]
|
owns:
|
||||||
"spec/exit/position_review.yaml":
|
- entry_timing_guardrails
|
||||||
owns: ["position_review_cycle"]
|
- daily_leader_scan
|
||||||
must_not_own: ["신규매수 게이트"]
|
- anti_climax_buy_gate
|
||||||
"spec/07_output_schema.yaml":
|
- staged_entry
|
||||||
owns: ["recommendation_grade", "HTS table columns", "human output contract"]
|
- pullback_reentry
|
||||||
must_not_own: ["투자 판단 임계값"]
|
must_not_own:
|
||||||
"schemas/output_schema.json":
|
- Total_Heat
|
||||||
owns: ["machine-readable final output schema"]
|
- capture_read_ledger
|
||||||
must_not_own: ["투자 규칙 수치"]
|
spec/strategy/stock_model.yaml:
|
||||||
|
owns:
|
||||||
# ── 호환 인덱스 (redirect-only, 실제 규칙은 canonical_split_files 참조) ──
|
- stock_model
|
||||||
# 2026-06-22 WBS-7.11: spec/03_risk_policy.yaml, spec/04_strategy_rules.yaml은
|
- core_satellite_rule
|
||||||
# role: deprecated_redirect(영구 유지가 아닌 완전 폐기 대상)였으며 활성 참조 0건을
|
must_not_own:
|
||||||
# 확인 후 실삭제했다. 캐노니컬 split 파일들은 영향 없이 그대로 유지된다.
|
- 시장 전체 현금 비중
|
||||||
"spec/06_exit_policy.yaml":
|
spec/strategy/rebalancing_trigger.yaml:
|
||||||
role: "compatibility_index"
|
owns:
|
||||||
owns: ["legacy path alias for spec/exit/*.yaml"]
|
- rebalancing_trigger
|
||||||
must_not_own: ["새 손절/익절 임계값"]
|
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/02_data_contract.yaml:
|
||||||
# ── 계산 스키마 ───────────────────────────────────────────────────────────
|
owns:
|
||||||
"spec/08_scoring_rules.yaml":
|
- source_priority
|
||||||
owns: ["SS001_SECTOR_MODEL_SCORE 계산 규칙", "SS001 6축 점수 임계값", "KOSDAQ 정규화 공식"]
|
- data_rule
|
||||||
must_not_own: ["포트폴리오 현금 비중", "exit 규칙"]
|
- data_completeness_gate
|
||||||
"spec/09_decision_flow.yaml":
|
- xlsx_analysis_protocol
|
||||||
owns: ["Allowed_Action 결정 흐름", "하드게이트 우선순위 순서"]
|
must_not_own:
|
||||||
must_not_own: ["점수 임계값", "포지션 사이징 공식"]
|
- 매수/매도 결론
|
||||||
"spec/10_portfolio_rules.yaml":
|
spec/12_field_dictionary.yaml:
|
||||||
owns: ["버킷 할당 목표", "core/satellite 비율 규칙"]
|
owns:
|
||||||
must_not_own: ["개별 종목 점수", "시장국면 판정"]
|
- canonical field names
|
||||||
"spec/11_market_regime.yaml":
|
- field aliases
|
||||||
owns: ["MARKET_REGIME_V1 판정 로직", "MRS 계산 공식", "REGIME 6개 상태 정의"]
|
- field units
|
||||||
must_not_own: ["개별 종목 점수", "포지션 사이징"]
|
- field missing policy
|
||||||
|
must_not_own:
|
||||||
# ── 운영 계약서 ──────────────────────────────────────────────────────────
|
- 투자 판단 임계값
|
||||||
"spec/16_data_gaps_roadmap.yaml":
|
- 매수/매도 결론
|
||||||
owns: ["미구현 항목 추적", "구현 우선순위 로드맵"]
|
spec/13_formula_registry.yaml:
|
||||||
must_not_own: ["확정된 계산 공식", "임계값"]
|
owns:
|
||||||
"spec/17_performance_contract.yaml":
|
- executable formulas
|
||||||
owns: ["performance 탭 구조", "Bayesian multiplier 계산 규칙", "fc_bucket 집계"]
|
- formula inputs
|
||||||
must_not_own: ["시장국면 판정", "종목 스크리닝"]
|
- formula outputs
|
||||||
"spec/18_settings_contract.yaml":
|
- formula missing policy
|
||||||
owns: ["settings 탭 파라미터 정의", "total_asset_krw", "risk_budget_override", "orbit_* 키"]
|
must_not_own:
|
||||||
must_not_own: ["계산 공식", "임계값 수치"]
|
- 보고서 양식
|
||||||
"spec/21_harness_governance_contract.yaml":
|
- 예시 케이스
|
||||||
owns: ["하네스 거버넌스 3중잠금", "실행 하드락", "배포 차단 정책"]
|
spec/14_raw_workbook_mapping.yaml:
|
||||||
must_not_own: ["개별 종목 점수", "주문 가격 산출식"]
|
owns:
|
||||||
"spec/strategy_execution_lock_policy.yaml":
|
- raw workbook sheets
|
||||||
owns: ["전략 실행락 임계값", "점수 하네스 기반 BUY/SELL 통제 임계치"]
|
- raw workbook columns
|
||||||
must_not_own: ["주문 가격 산출식", "시장국면 판정"]
|
- workbook to canonical field mapping
|
||||||
|
must_not_own:
|
||||||
# ── 전략 세부 파일 ──────────────────────────────────────────────────────
|
- 계좌 보유수량
|
||||||
"spec/strategy/discovery.yaml":
|
- 계좌 현금
|
||||||
owns: ["종목 발굴 기준", "스크리닝 필터"]
|
spec/15_account_snapshot_contract.yaml:
|
||||||
must_not_own: ["손절/익절 실행", "계좌 현금"]
|
owns:
|
||||||
"spec/strategy/entry_core.yaml":
|
- image capture account snapshot
|
||||||
owns: ["진입 체크리스트", "core 포지션 진입 기준"]
|
- holding quantity
|
||||||
must_not_own: ["Total_Heat 계산", "capture_read_ledger"]
|
- 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:
|
policy:
|
||||||
- "새 규칙 추가 전 ownership_map에서 소유 파일을 먼저 확인한다."
|
- 새 규칙 추가 전 ownership_map에서 소유 파일을 먼저 확인한다.
|
||||||
- "must_not_own 영역에 규칙을 추가하면 validate_specs.py에서 실패 처리한다."
|
- must_not_own 영역에 규칙을 추가하면 validate_specs.py에서 실패 처리한다.
|
||||||
- "임계값은 canonical 소유 파일에만 추가한다."
|
- 임계값은 canonical 소유 파일에만 추가한다.
|
||||||
|
|||||||
@@ -1,21 +1,27 @@
|
|||||||
|
meta:
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\profit_preservation_contract.yaml
|
||||||
schema_version: profit_preservation_contract.v2
|
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:
|
metrics:
|
||||||
- id: profit_giveback
|
- id: profit_giveback
|
||||||
description: "Ratio of profit returned from peak price since entry"
|
description: Ratio of profit returned from peak price since entry
|
||||||
- id: trailing_stop
|
- id: trailing_stop
|
||||||
description: "Trailing stop price level determined by ratchet stage"
|
description: Trailing stop price level determined by ratchet stage
|
||||||
- id: ratchet_stage
|
- id: ratchet_stage
|
||||||
description: "Lock tier based on maximum achieved profit percentage (e.g. PROFIT_LOCK_10, APEX_SUPER)"
|
description: Lock tier based on maximum achieved profit percentage (e.g. PROFIT_LOCK_10,
|
||||||
- id: sell_slippage_budget
|
APEX_SUPER)
|
||||||
description: "Allowed slippage threshold during execution"
|
- id: sell_slippage_budget
|
||||||
|
description: Allowed slippage threshold during execution
|
||||||
rules:
|
rules:
|
||||||
- id: RULE_PROFIT_GIVEBACK_GUARD
|
- id: RULE_PROFIT_GIVEBACK_GUARD
|
||||||
condition: "profit_pct >= 20% and profit_giveback > 30% of peak gain"
|
condition: profit_pct >= 20% and profit_giveback > 30% of peak gain
|
||||||
action: "Enforce trailing stop / lock remaining profit"
|
action: Enforce trailing stop / lock remaining profit
|
||||||
- id: RULE_DRAWDOWN_GUARD_PRIORITY
|
- id: RULE_DRAWDOWN_GUARD_PRIORITY
|
||||||
condition: "portfolio in value_preservation_stage"
|
condition: portfolio in value_preservation_stage
|
||||||
action: "Prioritize drawdown guard over new alpha signals"
|
action: Prioritize drawdown guard over new alpha signals
|
||||||
- id: RULE_VALUE_DAMAGE_LIMIT
|
- id: RULE_VALUE_DAMAGE_LIMIT
|
||||||
condition: "unrealized maximum drawdown per ticker"
|
condition: unrealized maximum drawdown per ticker
|
||||||
limit: "value_damage_pct_avg <= 10%"
|
limit: value_damage_pct_avg <= 10%
|
||||||
|
|||||||
@@ -1,15 +1,19 @@
|
|||||||
|
meta:
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\property_invariants.yaml
|
||||||
schema_version: property_invariants.v1
|
schema_version: property_invariants.v1
|
||||||
goal: Define investment engine metamorphic and property invariants.
|
goal: Define investment engine metamorphic and property invariants.
|
||||||
invariants:
|
invariants:
|
||||||
- id: INV_CASH_SHORTFALL_MONOTONICITY
|
- id: INV_CASH_SHORTFALL_MONOTONICITY
|
||||||
description: "현금 부족액 증가 시 신규 매수 권한/수량은 증가할 수 없음"
|
description: 현금 부족액 증가 시 신규 매수 권한/수량은 증가할 수 없음
|
||||||
formula_ref: "spec/risk/portfolio_exposure.yaml"
|
formula_ref: spec/risk/portfolio_exposure.yaml
|
||||||
- id: INV_MARKET_RISK_MONOTONICITY
|
- id: INV_MARKET_RISK_MONOTONICITY
|
||||||
description: "시장 위험 증가 시 position scale은 증가할 수 없음"
|
description: 시장 위험 증가 시 position scale은 증가할 수 없음
|
||||||
formula_ref: "spec/risk/market_risk_cash.yaml"
|
formula_ref: spec/risk/market_risk_cash.yaml
|
||||||
- id: INV_MISSING_DATA_CONFIDENCE
|
- id: INV_MISSING_DATA_CONFIDENCE
|
||||||
description: "데이터 결측 추가 시 confidence는 상승할 수 없음"
|
description: 데이터 결측 추가 시 confidence는 상승할 수 없음
|
||||||
formula_ref: "spec/02_data_contract.yaml"
|
formula_ref: spec/02_data_contract.yaml
|
||||||
- id: INV_STALE_PRICE_ZERO_QUANTITY
|
- id: INV_STALE_PRICE_ZERO_QUANTITY
|
||||||
description: "stale 가격이면 실행 주문 수량은 0"
|
description: stale 가격이면 실행 주문 수량은 0
|
||||||
formula_ref: "spec/00_execution_contract.yaml"
|
formula_ref: spec/00_execution_contract.yaml
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ meta:
|
|||||||
language: "ko-KR"
|
language: "ko-KR"
|
||||||
timezone: "Asia/Seoul"
|
timezone: "Asia/Seoul"
|
||||||
role: "canonical"
|
role: "canonical"
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path: ["spec/strategy/action_matrix.yaml"]
|
||||||
migration_status: "canonical_split_active"
|
migration_status: "canonical_split_active"
|
||||||
|
|
||||||
risk_control:
|
risk_control:
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ meta:
|
|||||||
language: "ko-KR"
|
language: "ko-KR"
|
||||||
timezone: "Asia/Seoul"
|
timezone: "Asia/Seoul"
|
||||||
role: "canonical"
|
role: "canonical"
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path: ["spec/strategy/action_matrix.yaml"]
|
||||||
migration_status: "canonical_split_active"
|
migration_status: "canonical_split_active"
|
||||||
authority_rule: "이 split 파일이 해당 섹션의 canonical source다. parent_file은 legacy compatibility index다."
|
authority_rule: "이 split 파일이 해당 섹션의 canonical source다. parent_file은 legacy compatibility index다."
|
||||||
|
|
||||||
|
|||||||
+30
-27
@@ -1,41 +1,44 @@
|
|||||||
|
meta:
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\routing_trace_v2.yaml
|
||||||
formula_id: ROUTING_SERVING_DECISION_TRACE_V2
|
formula_id: ROUTING_SERVING_DECISION_TRACE_V2
|
||||||
name: 라우팅 및 서빙 결정 추적 (Routing & Serving Decision Trace)
|
name: 라우팅 및 서빙 결정 추적 (Routing & Serving Decision Trace)
|
||||||
description: 라우팅부터 서빙, 결정, 수량/가격 산출까지 전체 파이프라인의 이력을 단일 Trace ID로 기록하여 LLM의 자유도를 0%로 통제합니다.
|
description: 라우팅부터 서빙, 결정, 수량/가격 산출까지 전체 파이프라인의 이력을 단일 Trace ID로 기록하여 LLM의 자유도를 0%로
|
||||||
|
통제합니다.
|
||||||
rules:
|
rules:
|
||||||
- id: TR001
|
- id: TR001
|
||||||
condition: "trace_id IS NULL OR step_completed == FALSE"
|
condition: trace_id IS NULL OR step_completed == FALSE
|
||||||
action: "ABORT_PIPELINE"
|
action: ABORT_PIPELINE
|
||||||
reason: "라우팅 파이프라인 추적 누락 또는 비정상 종료"
|
reason: 라우팅 파이프라인 추적 누락 또는 비정상 종료
|
||||||
- id: TR002
|
- id: TR002
|
||||||
condition: "llm_override_detected == TRUE"
|
condition: llm_override_detected == TRUE
|
||||||
action: "INVALID_LLM_OVERRIDE"
|
action: INVALID_LLM_OVERRIDE
|
||||||
reason: "LLM이 하네스 결정값을 임의로 번복 또는 재생성 시도"
|
reason: LLM이 하네스 결정값을 임의로 번복 또는 재생성 시도
|
||||||
output:
|
output:
|
||||||
schema: routing_serving_trace_v3_json
|
schema: routing_serving_trace_v3_json
|
||||||
fields:
|
fields:
|
||||||
- trace_id: STRING
|
- trace_id: STRING
|
||||||
- route: STRING
|
- route: STRING
|
||||||
- prompt_entry: STRING
|
- prompt_entry: STRING
|
||||||
- gate_path: ARRAY of STRING
|
- gate_path: ARRAY of STRING
|
||||||
- final_block_reason: STRING OR NULL
|
- final_block_reason: STRING OR NULL
|
||||||
- llm_serving_budget: NUMBER (Must be 0)
|
- llm_serving_budget: NUMBER (Must be 0)
|
||||||
|
|
||||||
# ── 단계12: RELEASE_GATE_TRUTH (TASK-001 연동) ──────────────────────────────
|
|
||||||
routing_steps:
|
routing_steps:
|
||||||
step_12:
|
step_12:
|
||||||
id: 12
|
id: 12
|
||||||
name: RELEASE_GATE_TRUTH
|
name: RELEASE_GATE_TRUTH
|
||||||
formula_id: RELEASE_GATE_TRUTH_V1
|
formula_id: RELEASE_GATE_TRUTH_V1
|
||||||
description: "honest_proof_score >= 70 이어야만 HTS 주문 생성 허용"
|
description: honest_proof_score >= 70 이어야만 HTS 주문 생성 허용
|
||||||
inputs:
|
inputs:
|
||||||
- algorithm_guidance_proof_v1.json.honest_proof_score
|
- algorithm_guidance_proof_v1.json.honest_proof_score
|
||||||
- algorithm_guidance_proof_v1.json.honest_gate
|
- algorithm_guidance_proof_v1.json.honest_gate
|
||||||
- pass_100_criteria_v3.json.effective_release_gate
|
- pass_100_criteria_v3.json.effective_release_gate
|
||||||
output_key: effective_release_gate
|
output_key: effective_release_gate
|
||||||
on_blocked: "이후 HTS 주문 생성 0건 — THEORETICAL_ONLY 렌더"
|
on_blocked: 이후 HTS 주문 생성 0건 — THEORETICAL_ONLY 렌더
|
||||||
acceptance:
|
acceptance:
|
||||||
- "routing_execution_log 행수 == 12"
|
- routing_execution_log 행수 == 12
|
||||||
- "단계12 status가 effective_release_gate와 일치"
|
- 단계12 status가 effective_release_gate와 일치
|
||||||
gs_coverage: "gas_apex_runtime_core.gs:buildRoutingExecutionLogV2_()"
|
gs_coverage: gas_apex_runtime_core.gs:buildRoutingExecutionLogV2_()
|
||||||
python_tool: "tools/build_routing_execution_log_v1.py"
|
python_tool: tools/build_routing_execution_log_v1.py
|
||||||
validator: "tools/validate_routing_trace_replay_v1.py"
|
validator: tools/validate_routing_trace_replay_v1.py
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ meta:
|
|||||||
version: "2026-05-17-action_matrix_v1"
|
version: "2026-05-17-action_matrix_v1"
|
||||||
language: "ko-KR"
|
language: "ko-KR"
|
||||||
role: "canonical"
|
role: "canonical"
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path: ["spec/strategy/action_matrix.yaml"]
|
||||||
purpose: >
|
purpose: >
|
||||||
gas_data_feed.gs의 Allowed_Action(매수 게이트) + calcSellDecision_(매도) +
|
gas_data_feed.gs의 Allowed_Action(매수 게이트) + calcSellDecision_(매도) +
|
||||||
calcFinalDecision_(통합)이 어떤 조건에서 어떤 Final_Action을 출력하는지
|
calcFinalDecision_(통합)이 어떤 조건에서 어떤 Final_Action을 출력하는지
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ meta:
|
|||||||
language: "ko-KR"
|
language: "ko-KR"
|
||||||
timezone: "Asia/Seoul"
|
timezone: "Asia/Seoul"
|
||||||
role: "canonical"
|
role: "canonical"
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path: ["spec/strategy/action_matrix.yaml"]
|
||||||
migration_status: "canonical_split_active"
|
migration_status: "canonical_split_active"
|
||||||
|
|
||||||
anti_late_trade_rule:
|
anti_late_trade_rule:
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ meta:
|
|||||||
language: "ko-KR"
|
language: "ko-KR"
|
||||||
timezone: "Asia/Seoul"
|
timezone: "Asia/Seoul"
|
||||||
role: "canonical"
|
role: "canonical"
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path: ["spec/strategy/action_matrix.yaml"]
|
||||||
migration_status: "canonical_split_active"
|
migration_status: "canonical_split_active"
|
||||||
|
|
||||||
entry_timing_guardrails:
|
entry_timing_guardrails:
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ meta:
|
|||||||
language: "ko-KR"
|
language: "ko-KR"
|
||||||
timezone: "Asia/Seoul"
|
timezone: "Asia/Seoul"
|
||||||
role: "canonical"
|
role: "canonical"
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path: ["spec/strategy/action_matrix.yaml"]
|
||||||
migration_status: "canonical_split_active"
|
migration_status: "canonical_split_active"
|
||||||
|
|
||||||
entry_timing_guardrails:
|
entry_timing_guardrails:
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ meta:
|
|||||||
language: "ko-KR"
|
language: "ko-KR"
|
||||||
timezone: "Asia/Seoul"
|
timezone: "Asia/Seoul"
|
||||||
role: "canonical"
|
role: "canonical"
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path: ["spec/strategy/action_matrix.yaml"]
|
||||||
migration_status: "canonical_split_active"
|
migration_status: "canonical_split_active"
|
||||||
authority_rule: "이 split 파일이 해당 섹션의 canonical source다. parent_file은 legacy compatibility index다."
|
authority_rule: "이 split 파일이 해당 섹션의 canonical source다. parent_file은 legacy compatibility index다."
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ meta:
|
|||||||
language: "ko-KR"
|
language: "ko-KR"
|
||||||
timezone: "Asia/Seoul"
|
timezone: "Asia/Seoul"
|
||||||
role: "canonical"
|
role: "canonical"
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path: ["spec/strategy/action_matrix.yaml"]
|
||||||
migration_status: "canonical_split_active"
|
migration_status: "canonical_split_active"
|
||||||
authority_rule: "이 split 파일이 해당 섹션의 canonical source다. parent_file은 legacy compatibility index다."
|
authority_rule: "이 split 파일이 해당 섹션의 canonical source다. parent_file은 legacy compatibility index다."
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ meta:
|
|||||||
language: "ko-KR"
|
language: "ko-KR"
|
||||||
timezone: "Asia/Seoul"
|
timezone: "Asia/Seoul"
|
||||||
role: "canonical"
|
role: "canonical"
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path: ["spec/strategy/action_matrix.yaml"]
|
||||||
migration_status: "canonical_split_active"
|
migration_status: "canonical_split_active"
|
||||||
|
|
||||||
entry_timing_guardrails:
|
entry_timing_guardrails:
|
||||||
|
|||||||
+103
-109
@@ -1,145 +1,139 @@
|
|||||||
meta:
|
meta:
|
||||||
title: "은퇴자산포트폴리오 — 참조 허용 매트릭스"
|
title: 은퇴자산포트폴리오 — 참조 허용 매트릭스
|
||||||
version: "2026-05-15-F10_fragmentation_guard"
|
version: 2026-05-15-F10_fragmentation_guard
|
||||||
role: "governance"
|
role: governance
|
||||||
purpose: "파일 간 순환 참조와 책임 침범을 방지한다."
|
purpose: 파일 간 순환 참조와 책임 침범을 방지한다.
|
||||||
|
has_code_implementation: true
|
||||||
|
code_path:
|
||||||
|
- spec\xref_matrix.yaml
|
||||||
xref_matrix:
|
xref_matrix:
|
||||||
"spec/08_scoring_rules.yaml":
|
spec/08_scoring_rules.yaml:
|
||||||
may_reference:
|
may_reference:
|
||||||
- "spec/00_execution_contract.yaml"
|
- spec/00_execution_contract.yaml
|
||||||
- "spec/12_field_dictionary.yaml"
|
- spec/12_field_dictionary.yaml
|
||||||
- "spec/13_formula_registry.yaml"
|
- spec/13_formula_registry.yaml
|
||||||
- "spec/02_data_contract.yaml"
|
- spec/02_data_contract.yaml
|
||||||
- "spec/risk/aggregate_risk.yaml"
|
- spec/risk/aggregate_risk.yaml
|
||||||
- "spec/risk/market_risk_cash.yaml"
|
- spec/risk/market_risk_cash.yaml
|
||||||
- "spec/risk/portfolio_exposure.yaml"
|
- spec/risk/portfolio_exposure.yaml
|
||||||
- "spec/strategy/sector_model.yaml"
|
- spec/strategy/sector_model.yaml
|
||||||
- "spec/07_output_schema.yaml"
|
- spec/07_output_schema.yaml
|
||||||
must_not_reference:
|
must_not_reference:
|
||||||
- "examples/"
|
- examples/
|
||||||
- "prompts/"
|
- prompts/
|
||||||
"spec/10_portfolio_rules.yaml":
|
spec/10_portfolio_rules.yaml:
|
||||||
may_reference:
|
may_reference:
|
||||||
- "spec/01_objective_profile.yaml"
|
- spec/01_objective_profile.yaml
|
||||||
- "spec/12_field_dictionary.yaml"
|
- spec/12_field_dictionary.yaml
|
||||||
- "spec/13_formula_registry.yaml"
|
- spec/13_formula_registry.yaml
|
||||||
- "spec/risk/portfolio_exposure.yaml"
|
- spec/risk/portfolio_exposure.yaml
|
||||||
- "spec/risk/aggregate_risk.yaml"
|
- spec/risk/aggregate_risk.yaml
|
||||||
- "spec/risk/market_risk_cash.yaml"
|
- spec/risk/market_risk_cash.yaml
|
||||||
must_not_reference:
|
must_not_reference:
|
||||||
- "schemas/output_schema.json"
|
- schemas/output_schema.json
|
||||||
"spec/07_output_schema.yaml":
|
spec/07_output_schema.yaml:
|
||||||
may_reference:
|
may_reference:
|
||||||
- "schemas/output_schema.json"
|
- schemas/output_schema.json
|
||||||
- "RetirementAssetPortfolioReportTemplate.yaml"
|
- RetirementAssetPortfolioReportTemplate.yaml
|
||||||
- "spec/00_execution_contract.yaml"
|
- spec/00_execution_contract.yaml
|
||||||
- "spec/12_field_dictionary.yaml"
|
- spec/12_field_dictionary.yaml
|
||||||
- "spec/13_formula_registry.yaml"
|
- spec/13_formula_registry.yaml
|
||||||
must_not_reference:
|
must_not_reference:
|
||||||
- "examples/"
|
- examples/
|
||||||
- "prompts/"
|
- prompts/
|
||||||
"schemas/output_schema.json":
|
schemas/output_schema.json:
|
||||||
may_reference: []
|
may_reference: []
|
||||||
must_not_reference:
|
must_not_reference:
|
||||||
- "spec/"
|
- spec/
|
||||||
- "examples/"
|
- examples/
|
||||||
- "prompts/"
|
- prompts/
|
||||||
"examples/":
|
examples/:
|
||||||
may_reference:
|
may_reference:
|
||||||
- "spec/"
|
- spec/
|
||||||
- "schemas/output_schema.json"
|
- schemas/output_schema.json
|
||||||
must_not_reference: []
|
must_not_reference: []
|
||||||
"prompts/":
|
prompts/:
|
||||||
may_reference:
|
may_reference:
|
||||||
- "RetirementAssetPortfolio.yaml"
|
- RetirementAssetPortfolio.yaml
|
||||||
- "spec/"
|
- spec/
|
||||||
- "schemas/output_schema.json"
|
- schemas/output_schema.json
|
||||||
must_not_reference: []
|
must_not_reference: []
|
||||||
|
spec/53_factor_conflict_matrix.yaml:
|
||||||
# ── 신규 계약 파일 xref ────────────────────────────────────────────────────
|
|
||||||
"spec/53_factor_conflict_matrix.yaml":
|
|
||||||
may_reference:
|
may_reference:
|
||||||
- "spec/43_quant_factor_taxonomy.yaml"
|
- spec/43_quant_factor_taxonomy.yaml
|
||||||
- "spec/00_execution_contract.yaml"
|
- spec/00_execution_contract.yaml
|
||||||
- "spec/factor_lifecycle_registry.yaml"
|
- spec/factor_lifecycle_registry.yaml
|
||||||
must_not_reference:
|
must_not_reference:
|
||||||
- "examples/"
|
- examples/
|
||||||
conflict_resolution_note: >
|
conflict_resolution_note: 'spec/53 conflict_precedence_rules rank 6 = market_regime
|
||||||
spec/53 conflict_precedence_rules rank 6 = market_regime (포지션 스케일 조정).
|
(포지션 스케일 조정). spec/00 P3 = cash_floor·Total_Heat·hard_stop은 어떤 alpha/strategy
|
||||||
spec/00 P3 = cash_floor·Total_Heat·hard_stop은 어떤 alpha/strategy 논리보다 우선.
|
논리보다 우선. 두 계약이 충돌하면 spec/00 P3가 우선한다 (spec/00 source_of_truth.priority=highest).
|
||||||
두 계약이 충돌하면 spec/00 P3가 우선한다 (spec/00 source_of_truth.priority=highest).
|
spec/53의 rank 1(portfolio_risk_budget)이 사실상 spec/00 P3의 집행자이며, market_regime(rank
|
||||||
spec/53의 rank 1(portfolio_risk_budget)이 사실상 spec/00 P3의 집행자이며,
|
6)은 cash_floor를 완화하는 목적으로 사용될 수 없다.
|
||||||
market_regime(rank 6)은 cash_floor를 완화하는 목적으로 사용될 수 없다.
|
|
||||||
|
|
||||||
"spec/52_decision_trace_replay_contract.yaml":
|
'
|
||||||
|
spec/52_decision_trace_replay_contract.yaml:
|
||||||
may_reference:
|
may_reference:
|
||||||
- "spec/41_release_dag.yaml"
|
- spec/41_release_dag.yaml
|
||||||
- "spec/40_final_decision_packet_contract.yaml"
|
- spec/40_final_decision_packet_contract.yaml
|
||||||
must_not_reference:
|
must_not_reference:
|
||||||
- "examples/"
|
- examples/
|
||||||
|
spec/54_temporal_data_integrity.yaml:
|
||||||
"spec/54_temporal_data_integrity.yaml":
|
|
||||||
may_reference:
|
may_reference:
|
||||||
- "spec/00_execution_contract.yaml"
|
- spec/00_execution_contract.yaml
|
||||||
- "spec/exit/stop_loss.yaml"
|
- spec/exit/stop_loss.yaml
|
||||||
must_not_reference:
|
must_not_reference:
|
||||||
- "examples/"
|
- examples/
|
||||||
temporal_note: >
|
temporal_note: 'TIME_STOP 판단에 사용되는 hold_days는 반드시 entry_date 기준 실제 경과일 기반이어야 한다.
|
||||||
TIME_STOP 판단에 사용되는 hold_days는 반드시 entry_date 기준 실제 경과일 기반이어야 한다.
|
|
||||||
미래 날짜 hold_days 사용은 LOOKAHEAD_BIAS로 분류된다.
|
미래 날짜 hold_days 사용은 LOOKAHEAD_BIAS로 분류된다.
|
||||||
|
|
||||||
"spec/55_execution_simulator_contract.yaml":
|
'
|
||||||
|
spec/55_execution_simulator_contract.yaml:
|
||||||
may_reference:
|
may_reference:
|
||||||
- "spec/00_execution_contract.yaml"
|
- spec/00_execution_contract.yaml
|
||||||
- "spec/13_formula_registry.yaml"
|
- spec/13_formula_registry.yaml
|
||||||
- "spec/15_account_snapshot_contract.yaml"
|
- spec/15_account_snapshot_contract.yaml
|
||||||
must_not_reference:
|
must_not_reference:
|
||||||
- "examples/"
|
- examples/
|
||||||
|
spec/56_renderer_copy_only_contract.yaml:
|
||||||
"spec/56_renderer_copy_only_contract.yaml":
|
|
||||||
may_reference:
|
may_reference:
|
||||||
- "spec/00_execution_contract.yaml"
|
- spec/00_execution_contract.yaml
|
||||||
- "spec/40_final_decision_packet_contract.yaml"
|
- spec/40_final_decision_packet_contract.yaml
|
||||||
must_not_reference:
|
must_not_reference:
|
||||||
- "examples/"
|
- examples/
|
||||||
|
spec/57_shadow_promotion_scorecard.yaml:
|
||||||
"spec/57_shadow_promotion_scorecard.yaml":
|
|
||||||
may_reference:
|
may_reference:
|
||||||
- "spec/44_live_replay_separation.yaml"
|
- spec/44_live_replay_separation.yaml
|
||||||
- "spec/43_quant_factor_taxonomy.yaml"
|
- spec/43_quant_factor_taxonomy.yaml
|
||||||
must_not_reference:
|
must_not_reference:
|
||||||
- "examples/"
|
- examples/
|
||||||
|
spec/58_llm_determinism_contract.yaml:
|
||||||
"spec/58_llm_determinism_contract.yaml":
|
|
||||||
may_reference:
|
may_reference:
|
||||||
- "spec/46_low_capability_execution_pack.yaml"
|
- spec/46_low_capability_execution_pack.yaml
|
||||||
- "spec/00_execution_contract.yaml"
|
- spec/00_execution_contract.yaml
|
||||||
must_not_reference:
|
must_not_reference:
|
||||||
- "examples/"
|
- examples/
|
||||||
|
|
||||||
# ── 충돌 해소 우선순위 선언 ────────────────────────────────────────────────
|
|
||||||
conflict_resolution_precedence:
|
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:
|
rules:
|
||||||
- id: "XREF_CR001"
|
- id: XREF_CR001
|
||||||
description: >
|
description: 'spec/53 rank 6 market_regime vs spec/00 P3 cash_floor: spec/00 P3가
|
||||||
spec/53 rank 6 market_regime vs spec/00 P3 cash_floor:
|
절대 우선한다. market_regime은 position_scale만 조정하며 cash_floor·Total_Heat·hard_stop을
|
||||||
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_CR002"
|
'
|
||||||
description: >
|
winner: spec/00_execution_contract.yaml:P3_no_risk_block_override
|
||||||
spec/54 temporal integrity vs spec/00 P4 intraday_lock:
|
loser: spec/53_factor_conflict_matrix.yaml:rank=6_market_regime
|
||||||
spec/00 P4가 상위 계약. spec/54는 backfill/lookahead를 차단하며,
|
- id: XREF_CR002
|
||||||
spec/00 P4는 장중 신규 매수·전량 매도를 차단한다. 두 계약은 서로 보완적.
|
description: 'spec/54 temporal integrity vs spec/00 P4 intraday_lock: spec/00
|
||||||
winner: "spec/00_execution_contract.yaml:P4_no_intraday_speculation"
|
P4가 상위 계약. spec/54는 backfill/lookahead를 차단하며, spec/00 P4는 장중 신규 매수·전량 매도를 차단한다.
|
||||||
supplementary: "spec/54_temporal_data_integrity.yaml:NO_LOOKAHEAD"
|
두 계약은 서로 보완적.
|
||||||
|
|
||||||
|
'
|
||||||
|
winner: spec/00_execution_contract.yaml:P4_no_intraday_speculation
|
||||||
|
supplementary: spec/54_temporal_data_integrity.yaml:NO_LOOKAHEAD
|
||||||
policy:
|
policy:
|
||||||
- "must_not_reference 위반은 검증 실패."
|
- must_not_reference 위반은 검증 실패.
|
||||||
- "may_reference 외 참조는 경고 대상. critical 파일은 실패 대상."
|
- may_reference 외 참조는 경고 대상. critical 파일은 실패 대상.
|
||||||
- "schemas/output_schema.json은 어떤 spec도 참조하지 않는다."
|
- schemas/output_schema.json은 어떤 spec도 참조하지 않는다.
|
||||||
- "conflict_resolution_precedence는 spec 충돌 시 판단 순서를 명시한다. spec/00이 항상 최상위."
|
- conflict_resolution_precedence는 spec 충돌 시 판단 순서를 명시한다. spec/00이 항상 최상위.
|
||||||
|
|||||||
@@ -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
|
||||||
Reference in New Issue
Block a user