변경 사항 ---- - _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>
82 lines
2.8 KiB
Python
82 lines
2.8 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
전략 공통 리스크·슬롯 env_config 스냅샷 INSERT.
|
|
- 1회 매수금(슬롯): 300만 원 통일
|
|
- 1회 최대 손실(금액컷): 20만 원 통일
|
|
- SHORT(꼬리): ATR 익절 타이트 + 어깨 0.5%/0.3%
|
|
- UPDOW 총 운용 한도: 300만 원
|
|
|
|
실행:
|
|
cd ~/kis_bot && python3 -m kis_trader.scripts.apply_unified_risk_env
|
|
|
|
저장 위치 (2026-05 분리):
|
|
- 공통(API·MM·인프라): env_config
|
|
- 전략별: config_scalp / config_short / config_momentum / config_breakout / config_updow
|
|
최초 1회: python3 -m kis_trader.scripts.migrate_split_env_config
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
_ROOT = Path(__file__).resolve().parents[2]
|
|
if str(_ROOT) not in sys.path:
|
|
sys.path.insert(0, str(_ROOT))
|
|
|
|
from database import TradeDB # noqa: E402
|
|
|
|
PATCH = {
|
|
# ── 슬롯 300만 통일 ──
|
|
"SLOT_MONEY_DEFAULT": "3000000",
|
|
"MOMENTUM_SLOT_MONEY": "3000000",
|
|
"BREAKOUT_SLOT_MONEY": "3000000",
|
|
"UPDOW_SLOT_MONEY": "3000000",
|
|
# UPDOW: 이 금액 안에서만 동시 보유 (하락매수 총 한도)
|
|
"UPDOW_MAX_BUY_AMOUNT": "3000000",
|
|
"MAX_BUY_AMOUNT_PER_STOCK": "3000000",
|
|
# ── 금액 손실컷 20만 통일 (청산 엔진용, 포지션 축소 공식과 분리) ──
|
|
"MAX_LOSS_PER_TRADE_KRW": "200000",
|
|
"SCALP_MAX_LOSS_PER_TRADE_KRW": "200000",
|
|
"MOMENTUM_MAX_LOSS_PER_TRADE_KRW": "200000",
|
|
"BREAKOUT_MAX_LOSS_PER_TRADE_KRW": "200000",
|
|
"UPDOW_MAX_LOSS_PER_TRADE_KRW": "200000",
|
|
# ── SHORT: 작은 익절·어깨 우선 / ATR 익·손 상한 타이트 (0.2%/일 프로필) ──
|
|
"TARGET_ATR_MULTIPLIER_TAIL": "2.0",
|
|
"STOP_ATR_MULTIPLIER_TAIL": "1.5",
|
|
"TAIL_ATR_TP_MAX_PCT": "1.0",
|
|
"TAIL_ATR_TP_MIN_PCT": "0.3",
|
|
"TAIL_ATR_SL_MAX_PCT": "1.0",
|
|
"TAIL_ATR_SL_MIN_PCT": "0.5",
|
|
"SHOULDER_MIN_HIGH_PCT": "0.003",
|
|
"SHOULDER_CUT_PCT": "0.002",
|
|
# ── SHORT 진입 회복률 (HTS 조건검색 후보 → TRIGGER 완화) ──
|
|
"MIN_RECOVERY_RATIO_SHORT": "0.45",
|
|
"MAX_RECOVERY_RATIO_3M": "0.9",
|
|
# ── 익절 호가 지정가 (손절은 시장가 유지) ──
|
|
"SELL_USE_ORDERBOOK_ON_PROFIT": "true",
|
|
"SELL_ORDERBOOK_BID_LEVELS": "2",
|
|
"SELL_ORDERBOOK_DEPTH_MULT": "1.5",
|
|
}
|
|
|
|
|
|
def main() -> int:
|
|
db = TradeDB()
|
|
latest = db.get_latest_env()
|
|
base = dict((latest or {}).get("snapshot") or {})
|
|
if latest and latest.get("id"):
|
|
print(f"기존 env_config id={latest['id']} 복사 후 패치")
|
|
merged = {**base, **PATCH}
|
|
eid = db.insert_env_snapshot(merged)
|
|
db.close()
|
|
if not eid:
|
|
print("❌ insert_env_snapshot 실패")
|
|
return 1
|
|
print(f"✅ env_config 저장 완료 (id={eid})")
|
|
for k, v in PATCH.items():
|
|
print(f" {k} = {v}")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|