From 152bf40a4cc4119811694fd2668bfe35c4ba37a7 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 6 Sep 2026 19:57:51 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20NameError(json)=20=EC=A6=89=EC=8B=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20+=20=ED=8C=8C=EC=BC=80=EC=9D=B4=20?= =?UTF-8?q?=EB=A1=9C=EB=8D=94=20=EC=97=94=EC=A7=84=20=EA=B2=8C=EC=9D=B4?= =?UTF-8?q?=ED=8A=B8=20=EB=B6=84=EB=A6=AC=20(A=EC=95=88)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NameError 수정 (내 직전 커밋 56b254b 회귀 버그) - optuna_scalping/breakout/momentum: 함수 내부의 중복 import json 제거. Python 스코프 규칙: 함수 안에 import 가 있으면 컴파일러가 그 이름을 로컬 변수로 취급 → if False 경로 진입 시 objective/후단에서 UnboundLocalError. 파일 상단 import json 을 그대로 사용. 파케이 초고속 로더: 엔진 선택과 분리 (A안 · 사용자 승인) - breakout_tick_loader.py:277: BACKTEST_USE_RUST=='1' 게이트 제거. 파케이 파일 존재하면 무조건 Rust I/O 로드 → Python/Rust 어느 엔진이든 초고속. 실패 시 자동 DB 폴백(기존 try/except 유지). - 정합성 안전: 파케이 = ws_ticks 필터 없는 스냅샷 → DB 로드와 동일. 300건 문제와 무관. 웹 재시작 200. 다음 옵투나 Python 라디오 실행이 이 커밋으로 정상 진행 가능. Co-authored-by: Cursor --- kis_trader/backtest/breakout_tick_loader.py | 13 ++++++++----- kis_trader/backtest/optuna_breakout.py | 2 +- kis_trader/backtest/optuna_momentum.py | 2 +- kis_trader/backtest/optuna_scalping.py | 3 ++- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/kis_trader/backtest/breakout_tick_loader.py b/kis_trader/backtest/breakout_tick_loader.py index 1d074bf..22c71a8 100644 --- a/kis_trader/backtest/breakout_tick_loader.py +++ b/kis_trader/backtest/breakout_tick_loader.py @@ -274,20 +274,23 @@ def load_common_ticks_by_code( try: import os import time - if os.environ.get("BACKTEST_USE_RUST") == "1" and os.path.exists(pq_path): + # 2026-09-06: 파케이 초고속 로드는 엔진(BACKTEST_USE_RUST) 과 별개. + # I/O 최적화일 뿐 → Python/Rust 어느 엔진이든 사용 가능. 파일 없거나 실패면 DB 폴백. + # 근거: 사용자 승인 A안 (docs/rust_engine_parity_port_plan.md). + if os.path.exists(pq_path): import kis_rust_core _st = time.time() - + codes_list = list(codes) if codes else None tick_source = os.environ.get("TICK_SOURCE", "").strip() or None - + res = kis_rust_core.load_parquet_ticks_fast( pq_path, chunk_s_val, chunk_e_val, codes_list, tick_source ) - + _local_out.update(res["data"]) _n = res["count"] - + _et = time.time() logger.info(f"⚡ [Rust Parquet 초고속 로드] day={day_str} rows={_n} (Rust I/O + PyDict: {_et - _st:.3f}s)") return chunk_s_val, chunk_e_val, _local_out, _n diff --git a/kis_trader/backtest/optuna_breakout.py b/kis_trader/backtest/optuna_breakout.py index 094a06e..46ca1f6 100644 --- a/kis_trader/backtest/optuna_breakout.py +++ b/kis_trader/backtest/optuna_breakout.py @@ -436,7 +436,7 @@ def run_breakout_optuna( rust_session_id = f"optuna_break_{uuid.uuid4().hex[:8]}" try: import kis_rust_core - import json + # json 은 파일 상단 import. 함수 안 재import 시 UnboundLocalError (scalping 과 동일). candles_json = json.dumps(ctx.codes_candles) kis_rust_core.init_backtest_session_json( rust_session_id, diff --git a/kis_trader/backtest/optuna_momentum.py b/kis_trader/backtest/optuna_momentum.py index 269880f..6061eee 100644 --- a/kis_trader/backtest/optuna_momentum.py +++ b/kis_trader/backtest/optuna_momentum.py @@ -489,7 +489,7 @@ def run_momentum_optuna( rust_session_id = f"optuna_mome_{uuid.uuid4().hex[:8]}" try: import kis_rust_core - import json + # json 은 파일 상단 import. 함수 안 재import 시 UnboundLocalError (scalping 과 동일). candles_json = json.dumps(ctx.codes_candles) kis_rust_core.init_backtest_session_json( rust_session_id, diff --git a/kis_trader/backtest/optuna_scalping.py b/kis_trader/backtest/optuna_scalping.py index 2e90b76..0793376 100644 --- a/kis_trader/backtest/optuna_scalping.py +++ b/kis_trader/backtest/optuna_scalping.py @@ -424,7 +424,8 @@ def run_scalp_optuna( rust_session_id = f"optuna_scalp_{uuid.uuid4().hex[:8]}" try: import kis_rust_core - import json + # json 은 파일 상단에서 이미 import. 함수 안 재import 하면 Python 이 + # json 을 로컬 변수로 취급 → if False 경로에서 UnboundLocalError. candles_json = json.dumps(ctx.codes_candles) kis_rust_core.init_backtest_session_json( rust_session_id,