Files
kis_bot/kis_trader/backtest/param_search_cli_common.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

111 lines
3.6 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
kis_trader/backtest/param_search_cli_common.py — 포트폴리오 파라서치 공통 CLI
=============================================================================
꼬리·스캘핑·모멘텀·돌파는 동일한 run 옵션 패턴을 쓴다 (하락매수 UPDOW 제외).
예시 (전략 파일만 바꿈):
python3 kis_trader/backtest/param_search_momentum.py \\
--start 2026-05-01 --end 2026-05-31 \\
--slot-money 200000 --max-stocks 20 --total-budget 2000000 \\
--time-start 830 --time-end 1530 \\
--mode fast
"""
from __future__ import annotations
import argparse
from typing import Any, Dict, Optional
# 파라서치 공통 필터 기본값 (정렬은 각 스크립트 total_pnl 유지)
MIN_WIN_RATE_DEFAULT = 40.0
MIN_PF_DEFAULT = 1.0
def combo_passes_search_filters(
*,
win_rate: float,
pf: float,
min_win_rate: float,
min_pf: float,
) -> bool:
"""승률·PF 하한 — 워커·머지 단계 공통."""
if float(win_rate) < float(min_win_rate):
return False
if float(pf) < float(min_pf):
return False
return True
def add_search_filter_cli_args(parser: argparse.ArgumentParser) -> None:
"""승률·PF 하한 CLI (--min_win_rate, --min_pf)."""
parser.add_argument(
"--min_win_rate",
default=MIN_WIN_RATE_DEFAULT,
type=float,
help="승률 하한(%%). 기본 40",
)
parser.add_argument(
"--min_pf",
default=MIN_PF_DEFAULT,
type=float,
help="Profit Factor 하한 (총익/|총손|). 기본 1.0",
)
def add_portfolio_cli_args(parser: argparse.ArgumentParser) -> None:
"""1회투자·동시보유·총한도·매매시간 — tail/scalp/momentum/breakout 공통."""
parser.add_argument(
"--time-start", type=int, default=None, dest="time_start",
help="매수 시작 HHMM (미지정 시 DB·전략 기본값)",
)
parser.add_argument(
"--time-end", type=int, default=None, dest="time_end",
help="매수 종료 HHMM (미지정 시 DB·전략 기본값)",
)
parser.add_argument(
"--slot-money", type=float, default=None, dest="slot_money",
help="1회투자금(원). 미지정 시 DB 전략별 SLOT_*",
)
parser.add_argument(
"--max-stocks", type=int, default=None, dest="max_stocks",
help="동시보유 종목 수. 미지정 시 DB 전략 MAX_*_STOCKS",
)
parser.add_argument(
"--total-budget", type=float, default=None, dest="total_budget",
help="총 운용한도(원). 0/미지정 시 동시×1회투자",
)
def apply_session_to_fixed(
fixed: Dict[str, Any],
*,
time_start_hm: Optional[int] = None,
time_end_hm: Optional[int] = None,
) -> None:
"""CLI 매매시간 → 백테 base fixed dict (in-place)."""
if time_start_hm is not None:
fixed["time_start_hm"] = int(time_start_hm)
if time_end_hm is not None:
fixed["time_end_hm"] = int(time_end_hm)
def search_json_meta(
portfolio: Dict[str, Any],
fixed: Dict[str, Any],
) -> Dict[str, Any]:
"""JSON 저장·--apply meta — 포트폴리오 + 매매시간."""
return {
"slot_money": portfolio.get("slot_money"),
"max_stocks": portfolio.get("max_stocks"),
"total_budget_krw": portfolio.get("total_budget_krw"),
"time_start_hm": fixed.get("time_start_hm"),
"time_end_hm": fixed.get("time_end_hm"),
"portfolio": dict(portfolio),
}
def format_session_hm(fixed: Dict[str, Any]) -> str:
ts = int(fixed.get("time_start_hm") or 930)
te = int(fixed.get("time_end_hm") or 1530)
return f"{ts:04d}-{te:04d}"