변경 사항 ---- - _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>
63 lines
2.7 KiB
Python
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 저장")
|