param — 실행 전에 정한 값
train_days=750, step_days=60, lgbm.learning_rate=0.05처럼 내가 고른 조건. 문자열로 저장되고 한 번 쓰면 바꿀 수 없다.
experiment tracking실험 추적runwalk-forwardholdout연구·백테스트 스크립트는 이미 성실하게 파일을 남긴다. 실행마다 타임스탬프가 붙은 폴더가 생기고 그 안에 예측·요약·리포트가 들어간다.
artifacts/├── research/│ ├── features_nxt_day_202608.parquet # 피처 캐시│ └── nxt_daily_o2n_20260830_120331/│ ├── predictions.parquet│ ├── summary.csv│ ├── daily_net_returns.csv│ └── report.html├── backtest/│ └── 20260830_120951_backtest/│ └── summary.json · trades.csv · equity.csv · report.html└── optuna.db # trial별 파라미터와 목적값이 구조는 산출물 보관에는 충분하다. 막히는 건 그다음이다.
| 하고 싶은 일 | 폴더만 있을 때 |
|---|---|
| 지난달 돌린 것 중 holdout Sharpe가 가장 높았던 조건 찾기 | 폴더를 하나씩 열어 summary.csv를 읽어야 한다 |
step_days를 60에서 120으로 바꾼 효과만 보기 | 어느 폴더가 어떤 step_days였는지 폴더 이름에 없다 |
| 튜닝 trial 30개의 파라미터-성능 관계 보기 | optuna.db에는 목적값 하나뿐, 나머지 지표는 사라진다 |
| 이 결과가 어떤 코드 버전에서 나왔는지 확인 | 커밋 해시가 어디에도 없다 |
| 백테스트와 walk-forward 결과를 같은 표에서 비교 | 파일 형식(summary.json · summary.csv)부터 다르다 |
공통점은 하나다. 파일은 “그때 무엇이 나왔는가”를 남기지만 “그때 무엇을 정했는가”를 남기지 않는다. 조건이 코드 안 기본값과 CLI 인자에 흩어져 있으니, 폴더를 아무리 잘 정리해도 조건별 비교가 안 된다.
MLflow Tracking은 실행 하나를 run으로 잘라 네 가지를 함께 저장한다. 셋은 구조화된 값이고 하나는 파일이다.
param — 실행 전에 정한 값
train_days=750, step_days=60, lgbm.learning_rate=0.05처럼 내가 고른 조건. 문자열로 저장되고 한 번 쓰면 바꿀 수 없다.
metric — 실행이 만든 수치
sharpe_net, holdout_mdd, hit_rate처럼 실행 결과로 나온 숫자. 나중에 조건 검색의 좌변이 된다.
tag — 분류·메모
phase=tune, study=nxt_daily_o2n처럼 런을 묶고 거르는 문자열. 나중에 추가·수정할 수 있다.
artifact — 산출물 파일
report.html, predictions.parquet처럼 값으로 못 담는 것. 원본은 여전히 artifacts/ 폴더에 있고 사본이 run에 붙는다.
이렇게 저장하면 아까의 질문이 전부 조건식이 된다.
import mlflow
best = mlflow.search_runs( experiment_names=["research/tune_o2n"], filter_string="params.step_days = '120' and metrics.holdout_sharpe_net > 0.8", order_by=["metrics.holdout_sharpe_net DESC"],)MLflow를 “MLOps 전체”로 이해하면 이 레포에서 쓸 자리를 잘못 잡는다. 지금 sshim-trader가 이미 다른 도구로 잘 하고 있는 일이 있고, MLflow는 거기 끼어들지 않는다.
artifacts/optuna.db가
study 상태를 이어 간다. MLflow는 그 trial의 결과를 받아 적을 뿐 탐색에 개입하지 않는다.sharpe_net을 어떻게 계산하는지는
sshim_trader/research/evaluate.py가 정한다. MLflow는 숫자를 검증하지 않는다.mlflow는 pyproject.toml의 dev group에 있다. 매매 봇은
MLflow 없이 동작해야 한다.sshim_trader/utils/tracking.py의 log_run()은 전체를 try로 감싸고 실패하면 경고만 남긴다.
except Exception: logger.warning("MLflow 기록 실패 (런 산출물 자체는 무관)", exc_info=True) return None이 선택은 지켜야 할 계약이다. 파일 산출물이 원본이고 MLflow는 그 위의 색인 계층이므로, 트래킹이 깨져도 연구는 계속돼야 한다. 이 덱에서 무엇을 추가로 기록할지 고를 때도 같은 기준을 쓴다 — MLflow에만 존재하는 정보가 늘수록 이 계약이 약해진다.
거꾸로 말하면 지금 log_run()이 놓치는 것도 분명하다. mlflow.db가 지워지면 어떤 파라미터로 무엇이
나왔는지는 완전히 사라진다. 파라미터를 파일에도 남기는 문제는 10장에서 다룬다.