782fe74578
사용자 제시 10개 고전 기술전략(골든크로스/모멘텀/52주신고가/연속상승하락/이격도/돌파실패/ 강한종가/변동성확장/평균회귀/추세필터)을 기존 엔진과 대조한 갭분석 결과: - 이미 구현됨: 모멘텀(VELOCITY_V1/RS_MOMENTUM_V1), 이격도·평균회귀(MEAN_REVERSION_GATE_V1) - 신규 채택 7개: GOLDEN_CROSS_SIGNAL_V1, STRONG_CLOSE_SIGNAL_V1, VOLATILITY_EXPANSION_BREAKOUT_V1, FIFTY_TWO_WEEK_HIGH_TRIGGER_V1, CONSECUTIVE_STREAK_V1, BREAKOUT_FAILURE_STOP_V1, TREND_FILTER_GATE_V1 AGENTS.md 하드룰(추격매수 방지, anti-late-entry gate 필수통과)에 따라 BUY 방향 신호 전부를 STRATEGY_SCORING의 보조신호로만 편입 — BREAKOUT_QUALITY_GATE_V2/FOLLOW_THROUGH_DAY_CONFIRM_V1/ ANTI_LATE_ENTRY_GATE_V2 게이트 체인을 우회하는 독립 BUY 트리거로는 사용하지 않음. 검증: validate_specs/validate_golden_coverage_100(100%)/validate_calibration_registry_v1/ validate_schema_model_generation_v1/validate_agents_shrink_v1 전부 PASS. golden test 22/22 PASS. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
54 lines
1.9 KiB
Python
54 lines
1.9 KiB
Python
#!/usr/bin/env python3
|
|
"""VOLATILITY_EXPANSION_BREAKOUT_V1 — spec/formulas/domains/entry.yaml.
|
|
|
|
This signal does NOT authorize a buy by itself -- callers must separately confirm
|
|
BREAKOUT_QUALITY_GATE_V2 != BLOCKED_LATE_CHASE. governance/todo/technical_signals_p4_adoption_plan.yaml P4-3.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
DEFAULT_OUT = ROOT / "Temp" / "volatility_expansion_breakout_v1.json"
|
|
|
|
SQUEEZE_PERCENTILE_THRESHOLD = 20.0
|
|
EXPANSION_RET_THRESHOLD_PCT = 3.0
|
|
|
|
|
|
def squeeze_detected(bb_width_20d_percentile: float | None) -> bool | None:
|
|
if bb_width_20d_percentile is None:
|
|
return None
|
|
return bb_width_20d_percentile <= SQUEEZE_PERCENTILE_THRESHOLD
|
|
|
|
|
|
def evaluate(squeeze_detected_previous_day: bool | None, ret_1d: float | None) -> bool | None:
|
|
if squeeze_detected_previous_day is None or ret_1d is None:
|
|
return None
|
|
return squeeze_detected_previous_day and ret_1d >= EXPANSION_RET_THRESHOLD_PCT
|
|
|
|
|
|
def main() -> int:
|
|
ap = argparse.ArgumentParser()
|
|
ap.add_argument("--bb-width-20d-percentile-prev", type=float, default=None)
|
|
ap.add_argument("--ret-1d", type=float, default=None)
|
|
ap.add_argument("--out", default=str(DEFAULT_OUT))
|
|
args = ap.parse_args()
|
|
|
|
prev_squeeze = squeeze_detected(args.bb_width_20d_percentile_prev)
|
|
result = {
|
|
"formula_id": "VOLATILITY_EXPANSION_BREAKOUT_V1",
|
|
"squeeze_detected_previous_day": prev_squeeze,
|
|
"volatility_expansion_breakout": evaluate(prev_squeeze, args.ret_1d),
|
|
"hard_constraint": "requires_BREAKOUT_QUALITY_GATE_V2_pass_separately",
|
|
}
|
|
out = Path(args.out)
|
|
out.write_text(json.dumps(result, ensure_ascii=False, indent=2), encoding="utf-8")
|
|
print(json.dumps(result, ensure_ascii=False, indent=2))
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|