ee3e799de1
주요 변경: - tools/build_rebalance_engine_v1.py: REBALANCE_ENGINE_V1 신규 * account_snapshot 직접 합산(_build_snap_position_map) → 소수주 분리 행 병합 * 레짐 소스 macro.REGIME_PRELIM 최우선 (GAS 와 동일) - src/gas_adapter_parts/gdf_06_rebalance.gs: runRebalanceSheet_() 신규 * Logger.log / getSpreadsheet_() 로 run_all 연동 수정 - src/gas_adapter_parts/gdc_01_fetch_fundamentals.gs * _mergePositionRecord_(): 소수주 중복 행 합산 신규 * parseInt → parseFloat (qty, availQty) - src/gas_adapter_parts/gdf_01_price_metrics.gs * 미보유 종목 SELL_READY → WATCH_EXIT_SIGNAL - spec/41_release_dag.yaml: build_rebalance_sheet 노드 추가 (step_count 63) - spec/51_formula_lifecycle_registry.yaml: REBALANCE_ENGINE_V1 등록 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
125 lines
7.4 KiB
YAML
125 lines
7.4 KiB
YAML
# spec/28 — 대체데이터 노출 게이트 계약 (IMPUTED_DATA_EXPOSURE_GATE_V1)
|
||
#
|
||
# 목적: 거버넌스/truth 점수(schema_presence, investment_quality, confidence_cap_basis)는
|
||
# 높지만 그 분모가 "스키마 존재율"에 치우쳐 실질 입력의 대체(imputed)·합성·PENDING을
|
||
# 가릴 수 있다. 이 게이트는 실질 데이터 커버리지를 결정론적으로 측정해 정직 신뢰도 캡을
|
||
# 재산출하고, 대체데이터 감지 시 장기·펀더멘털 단정을 차단한다.
|
||
#
|
||
# 위치: ENGINE_AUDIT_V1 감사 산출물(Temp/engine_audit_v1.json) 전용.
|
||
# GAS 런타임/HTS 주문 판단에는 개입하지 않는다(감사·진단 계층).
|
||
# 우선순위: 리스크 정책(spec/03) 하위. 본 계약은 감사 가시성 계약이며 주문을 생성하지 않는다.
|
||
|
||
meta:
|
||
formula_id: IMPUTED_DATA_EXPOSURE_GATE_V1
|
||
audit_id: ENGINE_AUDIT_V1
|
||
version: "2026-05-31_ENGINE_AUDIT_V1"
|
||
python_tool: tools/build_engine_audit_v1.py
|
||
validator_tool: tools/validate_engine_audit_v1.py
|
||
canonical_ref: spec/13b_harness_formulas.yaml:IMPUTED_DATA_EXPOSURE_GATE_V1
|
||
llm_role: explanation_only # 게이트 산출값은 LLM 재계산·완화 금지
|
||
|
||
# ── 실질 데이터 도메인 (가중치 합 = 1.0) ───────────────────────────────
|
||
domains:
|
||
fundamental_core:
|
||
weight: 0.30
|
||
coverage_source: "fundamental_multifactor_v3.json:rows[non-ETF].breakdown{roe,opm,ocf,fcf}"
|
||
coverage_formula: "present_core_factors / (4 × non_etf_ticker_count)"
|
||
note: ROE/OPM/OCF/FCF 결측(PARTIAL)이면 coverage↓. 장기·펀더멘털 우위 판단의 핵심.
|
||
realized_outcome:
|
||
weight: 0.30
|
||
coverage_source: "prediction_accuracy_harness_v2.json:{t1_sample,t5_sample,t20_sample}"
|
||
coverage_formula: "windows_with_sample / 3"
|
||
note: T+20 실현 표본 0건이면 장기 예측 미검증.
|
||
trade_quality:
|
||
weight: 0.15
|
||
coverage_source: "data_quality_gate_v2_py.json:category_scores.trade_quality"
|
||
coverage_formula: "score/100 (PENDING → 0)"
|
||
pattern:
|
||
weight: 0.10
|
||
coverage_source: "data_quality_gate_v2_py.json:category_scores.pattern"
|
||
coverage_formula: "score/100 (PENDING → 0)"
|
||
alpha_eval:
|
||
weight: 0.15
|
||
coverage_source: "data_quality_gate_v2_py.json:category_scores.alpha_eval"
|
||
coverage_formula: "score/100 (PENDING → 0)"
|
||
|
||
# ── 산식 ────────────────────────────────────────────────────────────────
|
||
formulas:
|
||
weighted_coverage: "Σ(domain.weight × domain.coverage)"
|
||
imputed_field_ratio: "1 − weighted_coverage"
|
||
imputed_domain_ratio: "count(domain.coverage < 0.5) / domain_count"
|
||
fundamental_core_factor_coverage: "domains.fundamental_core.coverage"
|
||
surrogate_outcome_ratio: "1 − domains.realized_outcome.coverage"
|
||
# 시스템 자체 캡 공식 재사용, 분모만 정직 커버리지로 교체
|
||
effective_confidence_honest: "raw_confidence_cap_basis × (0.4 + 0.6 × weighted_coverage)"
|
||
confidence_cap_inflation_gap: "raw_confidence_cap_basis − effective_confidence_honest"
|
||
|
||
# ── 임계값 ──────────────────────────────────────────────────────────────
|
||
thresholds:
|
||
block_ratio: 0.50 # imputed_field_ratio ≥ 0.50 → IMPUTED_DATA_BLOCK
|
||
warn_ratio: 0.25 # ≥ 0.25 → IMPUTED_DATA_WARN
|
||
fund_factor_min_coverage: 0.50 # 미만이면 fundamental_claim_allowed=false
|
||
render_skew_pct: 10.0 # 렌더 보고서 값 vs 권위 JSON 차이 임계(%)
|
||
|
||
# ── 게이트 출력 계약 ────────────────────────────────────────────────────
|
||
output:
|
||
target: Temp/engine_audit_v1.json
|
||
block: imputed_data_exposure
|
||
fields:
|
||
- gate_status # PASS | IMPUTED_DATA_WARN | IMPUTED_DATA_BLOCK
|
||
- imputed_field_ratio
|
||
- imputed_domain_ratio
|
||
- weighted_coverage
|
||
- domain_coverage
|
||
- fundamental_core_factor_coverage
|
||
- fundamental_missing_ratio
|
||
- surrogate_outcome_ratio
|
||
- raw_confidence_cap_basis
|
||
- effective_confidence_honest
|
||
- confidence_cap_inflation_gap
|
||
- long_horizon_allowed # t20_sample>0 AND fundamental_core_factor_coverage≥0.5
|
||
- fundamental_claim_allowed # fundamental_core_factor_coverage≥0.5
|
||
- report_render_skew # 렌더 보고서 vs 권위 JSON 불일치 감지
|
||
- exposure_reasons
|
||
|
||
# ── 마스킹 금지 규칙 (RAW_VS_ADJUSTED_DISCLOSURE_V1) ─────────────────────
|
||
masking_rules:
|
||
RAW_VS_ADJUSTED_DISCLOSURE_V1:
|
||
formula_id: RAW_VS_ADJUSTED_DISCLOSURE_V1
|
||
rationale: >
|
||
raw_value_damage=15.7%가 adjusted=0.0%로 가려진 채 게이트에 들어가면
|
||
가치훼손 캡(10%)이 무력화된다.
|
||
enforcement:
|
||
- "게이트 입력(value_damage_cap 등)은 항상 raw_* 값을 사용한다. adjusted_*는 게이트 입력 금지"
|
||
- "보고서 표에 adjusted를 표시할 경우 같은 행/셀에 raw를 의무 병기: 'raw 15.7% / adj 0.0%'"
|
||
- "raw 병기 없는 adjusted 단독 표시 1건당 masked_metric_without_raw_count += 1"
|
||
detection:
|
||
fields_to_check:
|
||
- {raw: raw_value_damage_pct_avg, adjusted: adjusted_value_damage_pct_avg,
|
||
source: smart_cash_recovery_v8.json}
|
||
- {raw: raw_value_damage_pct, adjusted: adjusted_value_damage_pct,
|
||
source: value_preservation_scorer_v2.json}
|
||
output_metric: operational_report.json.summary.masked_metric_without_raw_count
|
||
acceptance: "masked_metric_without_raw_count == 0"
|
||
python_tool: tools/build_value_preservation_scorer_v2.py
|
||
gs_coverage: "gas_lib.gs:formatRawAdjustedPair_()"
|
||
validator: "tools/validate_value_damage_reconciliation_v1.py --raw-required"
|
||
|
||
# ── 금지 사항 ───────────────────────────────────────────────────────────
|
||
prohibitions:
|
||
- "LLM이 gate_status / effective_confidence_honest / coverage 를 재계산·완화하는 것 금지(HS011)"
|
||
- "fundamental_claim_allowed=false 인데 펀더멘털·장기 우위를 단정하는 서술 금지"
|
||
- "long_horizon_allowed=false 인데 POSITION(장기) 신규 진입을 정당화하는 서술 금지"
|
||
- "report_render_skew.skew_detected=true 를 무시하고 렌더 보고서 값을 권위값으로 인용 금지"
|
||
|
||
# ── 검증 (validate_engine_audit_v1.py) ─────────────────────────────────
|
||
validation:
|
||
default_mode: "산출물 무결성(스키마·불변식·산식 재현). 엔진 status=failed 여도 PASS 가능."
|
||
strict_mode: "추가로 final_verdict.status == passed 요구 → 미달 시 비0 종료."
|
||
invariants:
|
||
- "fundamental_core_factor_coverage < fund_factor_min_coverage → fundamental_claim_allowed == false"
|
||
- "imputed_field_ratio ≥ block_ratio → gate_status == IMPUTED_DATA_BLOCK"
|
||
- "decision.decision_source == rule_engine"
|
||
- "llm_control.final_decision_from_llm == false AND llm_generated_decision_field_count == 0"
|
||
- "weighted_coverage / imputed_field_ratio / effective_confidence_honest 재계산 일치(±오차)"
|