Files
kis_bot/compare_web_cli_momentum.py
Hwang 61c72a8a4c feat(tests): 신규 키움 웹소켓 조건검색 및 실시간 조건검색 테스트 추가
변경 사항
----
- _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>
2026-07-06 01:27:00 +09:00

63 lines
2.7 KiB
Python

#!/usr/bin/env python3
"""웹 API vs diag_momentum_backtest CLI 동일조건 비교 (1위 · 5일 · 필터OFF)."""
import json, urllib.parse, urllib.request, time, sys
START, END = "2026-06-22", "2026-06-26"
# 1위 파라미터 (search_momentum_fast_20260627_015211.json rank=1)
QS = {
"start": START, "end": END,
"sl_pct": "1.5", "tp_pct": "2.0", "tp_max_pct": "2.0",
"slot_money": "300000", "slots": "20", "total_budget_krw": "6000000",
"cooldown_min": "1", "shoulder_min_high": "0.5", "shoulder_cut_pct": "0.15",
"trail_pct": "0.5", "trail_arm_pct": "0", "max_hold_bars": "0",
"ratchet_tiers": "0.5:0.1,1.0:0.3",
"time_start": "830", "time_end": "1530", "max_daily": "10",
"high_chase_thr": "0.99", "max_daily_chg": "50", "min_price": "1000",
"max_loss_krw": "200000", "min_margin": "0.2",
"use_defense_filters": "1",
"ob_filter": "0", "pg_filter": "0",
"max_spread_pct": "0.45",
"use_high_chase_filter": "0", "use_daily_range_filter": "0",
"use_ema_filter": "0", "use_rsi_max_filter": "0",
"pattern_breakout": "1", "pattern_pullback": "0",
"chase_lookback_min": "8", "pullback_lookback_min": "10",
"pullback_min_pct": "0.3", "pullback_max_pct": "3.0",
"setup_vol_max_mult": "0.8", "setup_bear_bars_min": "1",
"ema_fast_period": "9", "ema_slow_period": "21",
"mom_rsi_min": "50", "mom_rsi_max": "80",
"mom_vol_mult": "3", "mom_vol_win": "5",
"mom_time_end": "1220",
"mom_max_from_open_pct": "30", "mom_min_from_open_pct": "-999",
"universe": "history",
}
url = "http://127.0.0.1:5050/api/backtest/momentum?" + urllib.parse.urlencode(QS)
print(f"🌐 웹 API 호출: {START}~{END} 필터OFF ...")
t0 = time.time()
try:
with urllib.request.urlopen(url, timeout=300) as r:
d = json.loads(r.read().decode())
except Exception as e:
print(f"❌ 웹 API 실패: {e}")
sys.exit(1)
el = time.time() - t0
s = d.get("summary") or {}
print(f"🌐 웹 API ({el:.0f}초): 손익 {s.get('total_pnl',0):+,.0f}원 | "
f"승률 {s.get('win_rate',0):.1f}% | 거래 {s.get('total_trades',0)} | "
f"PF {s.get('profit_factor',0):.2f}")
daily = {}
for t in d.get("trades") or []:
day = str(t.get("buy_time") or t.get("entry_time") or "")[:8]
x = daily.setdefault(day, [0, 0.0])
x[0] += 1
x[1] += float(t.get("pnl") or 0)
for day in sorted(daily):
n, p = daily[day]
print(f" {day}: {n:3d}거래 {p:+,.0f}")
skip = (d.get("summary") or {}).get("skip_stats") or {}
if skip:
print(f" skip_stats: {skip}")
with open("logs/compare_web_api.json", "w", encoding="utf-8") as f:
json.dump({"summary": s, "daily": daily, "elapsed_sec": el}, f, ensure_ascii=False, indent=2)
print(" → logs/compare_web_api.json 저장")