변경 사항 ---- - _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>
106 lines
3.1 KiB
Python
106 lines
3.1 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
env_config → env_config(공통) + config_{전략} 분리 마이그레이션.
|
|
|
|
1) config_scalp / config_short / config_momentum / config_breakout / config_updow 테이블 생성·컬럼 보강
|
|
2) 기존 env_config 최신 행 + env_config_ext 값을 테이블별로 INSERT
|
|
3) 공통 키만 env_config 에 새 스냅샷 INSERT
|
|
|
|
실행:
|
|
cd ~/kis_bot && 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 config_schema import CONFIG_TABLE_NAMES, classify_config_key # noqa: E402
|
|
from database import ( # noqa: E402
|
|
CONFIG_TABLE_KEYS,
|
|
ENV_CONFIG_KEYS,
|
|
TradeDB,
|
|
)
|
|
|
|
|
|
def _load_legacy_flat(db: TradeDB) -> dict:
|
|
"""기존 fat env_config 1행 + env_config_ext."""
|
|
flat = {}
|
|
try:
|
|
row = db.conn.execute(
|
|
"SELECT * FROM env_config ORDER BY id DESC LIMIT 1"
|
|
).fetchone()
|
|
if row:
|
|
rk = row.keys() if hasattr(row, "keys") else []
|
|
for k in ENV_CONFIG_KEYS:
|
|
if k in rk and row[k] is not None and str(row[k]).strip() != "":
|
|
flat[k] = str(row[k])
|
|
except Exception as e:
|
|
print(f"legacy env_config 읽기 실패: {e}")
|
|
try:
|
|
ext = db.conn.execute(
|
|
"SELECT env_key, env_value FROM env_config_ext"
|
|
).fetchall()
|
|
for er in ext or []:
|
|
ek = er["env_key"] if isinstance(er, dict) else er[0]
|
|
ev = er["env_value"] if isinstance(er, dict) else er[1]
|
|
if ek:
|
|
flat[str(ek)] = "" if ev is None else str(ev)
|
|
except Exception:
|
|
pass
|
|
return flat
|
|
|
|
|
|
def main() -> int:
|
|
db = TradeDB()
|
|
db._migrate_config_table_columns()
|
|
|
|
flat = _load_legacy_flat(db)
|
|
if not flat:
|
|
merged = db.get_merged_env_snapshot()
|
|
if merged:
|
|
flat = dict(merged)
|
|
if not flat:
|
|
print("❌ 마이그레이션할 env 데이터 없음")
|
|
db.close()
|
|
return 1
|
|
|
|
print(f"소스 키 {len(flat)}개 → 테이블별 INSERT")
|
|
eid = db.insert_env_snapshot(flat)
|
|
if not eid:
|
|
print("❌ insert_env_snapshot 실패")
|
|
db.close()
|
|
return 1
|
|
|
|
snap = db.get_merged_env_snapshot()
|
|
print(f"\n✅ 완료 env_config id={eid}")
|
|
print(f"병합 snapshot 키 수: {len(snap)}")
|
|
for tbl in CONFIG_TABLE_NAMES:
|
|
n = len(CONFIG_TABLE_KEYS.get(tbl, ()))
|
|
filled = sum(1 for k in CONFIG_TABLE_KEYS.get(tbl, ()) if snap.get(k))
|
|
print(f" {tbl}: 컬럼 {n} / 값 있음 {filled}")
|
|
|
|
checks = [
|
|
"KIS_APP_KEY_REAL",
|
|
"SCALP_STOP_LOSS_PCT",
|
|
"TAIL_ATR_TP_MAX_PCT",
|
|
"SHOULDER_MIN_HIGH_PCT",
|
|
"MOMENTUM_SLOT_MONEY",
|
|
"UPDOW_MAX_BUY_AMOUNT",
|
|
"SELL_USE_ORDERBOOK_ON_PROFIT",
|
|
]
|
|
print("\n검증:")
|
|
for k in checks:
|
|
tbl = classify_config_key(k)
|
|
print(f" {k} [{tbl}] = {snap.get(k, '(없음)')}")
|
|
|
|
db.close()
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|