변경 사항 ---- - _test_kiwoom_condition_list.py: 키움 웹소켓 조건검색 '목록조회' 기능을 단독으로 테스트하는 스크립트 추가 - _test_kiwoom_condition_realtime.py: 'momentum' 조건식을 실시간으로 등록하고 초기 매칭 종목 리스트 및 실시간 편입/이탈을 수신하는 테스트 스크립트 추가 - _verify_columnar_bitid.py, _verify_shared_e2e_breakout.py, _verify_shared_e2e.py: 공유 메모리 및 dict 간의 데이터 일관성을 검증하는 테스트 추가 영향 ---- - 신규 테스트 스크립트 추가로 키움 웹소켓 API의 기능 검증 및 안정성을 높임 - 기존 기능에 대한 영향 없음 Co-authored-by: Cursor <cursoragent@cursor.com>
47 lines
1.8 KiB
Python
47 lines
1.8 KiB
Python
#!/usr/bin/env python3
|
||
"""웹 /api/backtest/momentum 스모크 — Flask test_client (서버 불필요)."""
|
||
import json
|
||
import sys
|
||
|
||
sys.path.insert(0, "/home/hoon/kis_bot")
|
||
|
||
from backtest_web import app # noqa: E402
|
||
|
||
QS = {
|
||
"start": "2026-06-01",
|
||
"end": "2026-06-14",
|
||
"universe": "sim",
|
||
"pattern_breakout": "1",
|
||
"pattern_pullback": "1",
|
||
"chase_lookback_min": "10",
|
||
"pullback_lookback_min": "15",
|
||
"pullback_min_pct": "0.3",
|
||
"pullback_max_pct": "3.0",
|
||
"use_ema_filter": "1",
|
||
"use_rsi_max_filter": "0",
|
||
"use_high_chase_filter": "0",
|
||
"use_daily_range_filter": "0",
|
||
"mom_max_from_open_pct": "999",
|
||
"mom_min_from_open_pct": "-999",
|
||
}
|
||
|
||
with app.test_client() as c:
|
||
r = c.get("/api/backtest/momentum", query_string=QS)
|
||
print("HTTP", r.status_code)
|
||
d = r.get_json(silent=True) or {}
|
||
if d.get("error"):
|
||
print("ERROR:", d["error"])
|
||
sys.exit(1)
|
||
s = d.get("summary") or {}
|
||
p = d.get("params") or {}
|
||
print("--- V2 스모크 (6/1~14, universe=sim) ---")
|
||
print(f"패턴: 돌파={p.get('pattern_breakout')} 눌림={p.get('pattern_pullback')} chase={p.get('chase_lookback_min')}분")
|
||
print(f"RSI≥{p.get('mom_rsi_min')} vol×{p.get('mom_vol_mult')} EMA={p.get('use_ema_filter')} ({p.get('ema_fast_period')}/{p.get('ema_slow_period')})")
|
||
print(f"거래: {s.get('total_trades')}건 | 승률 {s.get('win_rate')}% | PF {s.get('profit_factor')}")
|
||
print(f"총손익: {s.get('total_pnl'):+,}원 | MDD {s.get('max_drawdown'):,}원 | 평균보유 {s.get('avg_hold_min')}분")
|
||
print(f"종목수: {p.get('codes_analyzed')} | 슬롯 {p.get('max_stocks')} × {p.get('slot_money'):,.0f}원")
|
||
reasons = d.get("reasons") or {}
|
||
if reasons:
|
||
top = sorted(reasons.items(), key=lambda x: -x[1])[:8]
|
||
print("청산사유:", ", ".join(f"{k}={v}" for k, v in top))
|