fix(정합성): Python 라디오인데 Rust 로 도는 원흉 제거 + web_jobs env 오타 정정
증상: Python 엔진 라디오를 눌러도 Rust 만큼 빠르고 매매 건수가 완전 다름 (380건 등).
잡 JSON 에는 use_rust=False 로 저장됐지만 실제 엔진은 Rust.
근본원인 (룰 19 딥다이브):
1. optuna_web_jobs.py:3759 [완전 반대 오타] (2026-09-06 4dbb138 안티그래비티 커밋에서 유입)
`if use_rust: env['BACKTEST_USE_RUST'] = '0'`
→ Rust 라디오 = '0' (Python) / Python 라디오 = 세팅 안 함 (부모 env 상속)
2. optuna_scalping/breakout/momentum/param_search_optuna: BACKTEST_USE_RUST env 무관하게
무조건 kis_rust_core.init_backtest_session_json() 초기화 + combo['_rust_session_id'] 세팅
→ scalping/breakout/momentum/tail_backtest_common 이 _rust_session_id 존재만으로 Rust 실행
→ env 오타가 아니어도 어차피 항상 Rust 로 돌던 진짜 원흉
수정 (B안):
- optuna_web_jobs.py:3759: `env['BACKTEST_USE_RUST'] = '1' if use_rust else '0'` (항상 명시)
- optuna_scalping/breakout/momentum/param_search_optuna: BACKTEST_USE_RUST=='1' 인 경우에만
init_backtest_session_json 호출 + combo['_rust_session_id'] 세팅
- Python 경로에서는 rust_session_id=None, combo 에도 없음 → 순수 Python 엔진
- clear_rust_session 도 세션 있을 때만 호출 (param_search_optuna)
env 하나가 진리 소스 (룰 29):
- optuna_web_jobs 가 env 를 명시 세팅 → 서브프로세스 상속
- 각 optuna_* 는 env 만 보고 Rust/Python 분기
- 부모 env 오염 방지
실매 스모크: logs/test_live_execution_validation_20260906_195008.log → 최종: 통과
웹 재시작 200. 다음 옵투나 실행부터 Python 라디오는 실제로 Python 엔진.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -510,22 +510,30 @@ def run_tail_optuna(
|
||||
bind_study_trials(study, n_trials=n_trials, log=logger)
|
||||
n_trials = clamp_optimize_n_trials(study, n_trials, log=logger)
|
||||
|
||||
import uuid
|
||||
rust_session_id = f"optuna_tail_{uuid.uuid4().hex[:8]}"
|
||||
try:
|
||||
from kis_trader.engine.tail_engine import init_rust_session, clear_rust_session
|
||||
init_rust_session(rust_session_id, ctx.candles_by_code, ctx.ticks_by_code)
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to init_rust_session: {e}")
|
||||
# 2026-09-06 (docs/rust_engine_parity_port_plan.md · 룰 29): env 게이트로 Rust 세션 초기화 제한.
|
||||
_use_rust_env = os.environ.get("BACKTEST_USE_RUST") == "1"
|
||||
rust_session_id: Optional[str] = None
|
||||
if _use_rust_env:
|
||||
import uuid
|
||||
rust_session_id = f"optuna_tail_{uuid.uuid4().hex[:8]}"
|
||||
try:
|
||||
from kis_trader.engine.tail_engine import init_rust_session, clear_rust_session # noqa: F401
|
||||
init_rust_session(rust_session_id, ctx.candles_by_code, ctx.ticks_by_code)
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to init_rust_session: {e}")
|
||||
rust_session_id = None
|
||||
else:
|
||||
logger.info("🐍 [Python 엔진] Rust 세션 미초기화 (BACKTEST_USE_RUST != 1)")
|
||||
|
||||
def objective(trial: optuna.Trial) -> float:
|
||||
if ctx.mode == "tpe":
|
||||
combo = suggest_tail_params_tpe(trial, entry_mode=ctx.tpe_entry_mode)
|
||||
else:
|
||||
combo = suggest_tail_params(trial, ctx.mode)
|
||||
|
||||
# Rust 세션 ID를 파라미터에 넘겨서 하위에서 사용할 수 있게 함
|
||||
combo["_rust_session_id"] = rust_session_id
|
||||
|
||||
# Rust 세션이 없으면 세팅하지 않음 (Python 경로)
|
||||
if rust_session_id is not None:
|
||||
combo["_rust_session_id"] = rust_session_id
|
||||
result = evaluate_tail_param_combo(
|
||||
combo,
|
||||
base_params=ctx.base_params,
|
||||
@@ -748,11 +756,13 @@ def run_tail_optuna(
|
||||
finally:
|
||||
# mode_combo 실측이 ticks 공유뷰를 쓰므로 optimize 직후 unlink 금지
|
||||
release_shared_tick_store(ctx, log=logger)
|
||||
try:
|
||||
from kis_trader.engine.tail_engine import clear_rust_session
|
||||
clear_rust_session(rust_session_id)
|
||||
except Exception as e:
|
||||
pass
|
||||
# rust_session_id 는 use_rust=True 로 초기화된 경우에만 clear 필요
|
||||
if rust_session_id is not None:
|
||||
try:
|
||||
from kis_trader.engine.tail_engine import clear_rust_session
|
||||
clear_rust_session(rust_session_id)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def apply_best_trial(study: optuna.Study, ctx: TailSearchContext) -> bool:
|
||||
|
||||
Reference in New Issue
Block a user