feat: add --symbol/--all CLI to all training scripts for per-symbol pipeline
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
#!/usr/bin/env bash
|
||||
# 맥미니에서 전체 학습 파이프라인을 실행하고 LXC로 배포한다.
|
||||
# 사용법: bash scripts/train_and_deploy.sh [mlx|lgbm] [wf-splits]
|
||||
# 사용법: bash scripts/train_and_deploy.sh [mlx|lgbm] [--symbol TRXUSDT] [--all] [wf-splits]
|
||||
#
|
||||
# 예시:
|
||||
# bash scripts/train_and_deploy.sh # LightGBM + Walk-Forward 5폴드 (기본값)
|
||||
# bash scripts/train_and_deploy.sh mlx # MLX GPU 학습 + Walk-Forward 5폴드
|
||||
# bash scripts/train_and_deploy.sh lgbm 3 # LightGBM + Walk-Forward 3폴드
|
||||
# bash scripts/train_and_deploy.sh mlx 0 # MLX 학습만 (Walk-Forward 건너뜀)
|
||||
# bash scripts/train_and_deploy.sh lgbm 0 # LightGBM 학습만 (Walk-Forward 건너뜀)
|
||||
# bash scripts/train_and_deploy.sh # 전체 심볼 (SYMBOLS 환경변수) + LightGBM
|
||||
# bash scripts/train_and_deploy.sh --symbol TRXUSDT # TRXUSDT만 학습+배포
|
||||
# bash scripts/train_and_deploy.sh mlx --symbol TRXUSDT # MLX + TRXUSDT만
|
||||
# bash scripts/train_and_deploy.sh --all # 전체 심볼 순차 처리
|
||||
# bash scripts/train_and_deploy.sh lgbm 3 # 전체 심볼 + Walk-Forward 3폴드
|
||||
# bash scripts/train_and_deploy.sh mlx 0 # 전체 심볼 + MLX 학습만 (WF 건너뜀)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
@@ -26,77 +27,132 @@ else
|
||||
echo "경고: 가상환경을 찾을 수 없습니다 ($VENV_PATH). 시스템 Python을 사용합니다." >&2
|
||||
fi
|
||||
|
||||
BACKEND="${1:-lgbm}"
|
||||
WF_SPLITS="${2:-5}" # 두 번째 인자: Walk-Forward 폴드 수 (0이면 건너뜀)
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
mkdir -p data
|
||||
# ── 인자 파싱 ───────────────────────────────────────────────────────────────
|
||||
BACKEND="lgbm"
|
||||
WF_SPLITS="5"
|
||||
SYMBOL_ARG=""
|
||||
ALL_FLAG=false
|
||||
|
||||
PARQUET_FILE="data/combined_15m.parquet"
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--symbol)
|
||||
SYMBOL_ARG="$2"
|
||||
shift 2
|
||||
;;
|
||||
--all)
|
||||
ALL_FLAG=true
|
||||
shift
|
||||
;;
|
||||
mlx|lgbm)
|
||||
BACKEND="$1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
# 숫자면 WF_SPLITS로 처리
|
||||
if [[ "$1" =~ ^[0-9]+$ ]]; then
|
||||
WF_SPLITS="$1"
|
||||
fi
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "========================================"
|
||||
echo " 학습 파이프라인 시작: $(date '+%Y-%m-%d %H:%M:%S %Z')"
|
||||
echo "========================================"
|
||||
echo ""
|
||||
|
||||
echo "=== [1/3] 데이터 수집 (XRP + BTC + ETH 3심볼 + OI/펀딩비) ==="
|
||||
if [ ! -f "$PARQUET_FILE" ]; then
|
||||
echo " [최초 실행] 기존 데이터 없음 → 1년치(365일) 전체 수집 (--no-upsert)"
|
||||
FETCH_DAYS=365
|
||||
UPSERT_FLAG="--no-upsert"
|
||||
# ── 대상 심볼 결정 ──────────────────────────────────────────────────────────
|
||||
if [ -n "$SYMBOL_ARG" ]; then
|
||||
TARGETS=("$SYMBOL_ARG")
|
||||
else
|
||||
echo " [일반 실행] 기존 데이터 존재 → 35일치 Upsert (OI/펀딩비 0.0 구간 보충)"
|
||||
FETCH_DAYS=35
|
||||
UPSERT_FLAG=""
|
||||
# .env에서 SYMBOLS 로드 (없으면 XRPUSDT 기본값)
|
||||
TARGETS=($(python -c "from dotenv import load_dotenv; load_dotenv(); from src.config import Config; c=Config(); print(' '.join(c.symbols))"))
|
||||
fi
|
||||
|
||||
python scripts/fetch_history.py \
|
||||
--symbols XRPUSDT BTCUSDT ETHUSDT \
|
||||
--interval 15m \
|
||||
--days "$FETCH_DAYS" \
|
||||
$UPSERT_FLAG \
|
||||
--output "$PARQUET_FILE"
|
||||
|
||||
DECAY="${TIME_WEIGHT_DECAY:-2.0}"
|
||||
|
||||
echo ""
|
||||
echo "=== [1.5/3] OI 파생 피처 A/B 비교 ==="
|
||||
python scripts/train_model.py --compare --data "$PARQUET_FILE" --decay "$DECAY" || true
|
||||
|
||||
echo "========================================"
|
||||
echo " 학습 파이프라인 시작: $(date '+%Y-%m-%d %H:%M:%S %Z')"
|
||||
echo " 대상 심볼: ${TARGETS[*]}"
|
||||
echo " 백엔드: ${BACKEND}, WF 폴드: ${WF_SPLITS}"
|
||||
echo "========================================"
|
||||
echo ""
|
||||
echo "=== [2/3] 모델 학습 (26개 피처: XRP 13 + BTC/ETH 8 + OI/펀딩비 2 + OI파생 2 + ADX) ==="
|
||||
if [ "$BACKEND" = "mlx" ]; then
|
||||
echo " 백엔드: MLX (Apple Silicon GPU), decay=${DECAY}"
|
||||
python scripts/train_mlx_model.py --data data/combined_15m.parquet --decay "$DECAY"
|
||||
else
|
||||
echo " 백엔드: LightGBM (CPU), decay=${DECAY}"
|
||||
python scripts/train_model.py --data data/combined_15m.parquet --decay "$DECAY"
|
||||
fi
|
||||
|
||||
# Walk-Forward 검증 (WF_SPLITS > 0 인 경우)
|
||||
if [ "$WF_SPLITS" -gt 0 ] 2>/dev/null; then
|
||||
# ── 심볼별 파이프라인 ───────────────────────────────────────────────────────
|
||||
for SYM in "${TARGETS[@]}"; do
|
||||
SYM_LOWER=$(echo "$SYM" | tr '[:upper:]' '[:lower:]')
|
||||
mkdir -p "data/$SYM_LOWER" "models/$SYM_LOWER"
|
||||
|
||||
PARQUET_FILE="data/$SYM_LOWER/combined_15m.parquet"
|
||||
|
||||
echo ""
|
||||
echo "=== [2.5/3] Walk-Forward 검증 (${WF_SPLITS}폴드) ==="
|
||||
if [ "$BACKEND" = "mlx" ]; then
|
||||
python scripts/train_mlx_model.py \
|
||||
--data data/combined_15m.parquet \
|
||||
--decay "$DECAY" \
|
||||
--wf \
|
||||
--wf-splits "$WF_SPLITS"
|
||||
else
|
||||
python scripts/train_model.py \
|
||||
--data data/combined_15m.parquet \
|
||||
--decay "$DECAY" \
|
||||
--wf \
|
||||
--wf-splits "$WF_SPLITS"
|
||||
fi
|
||||
fi
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo " [$SYM] 파이프라인 시작"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
|
||||
echo ""
|
||||
echo "=== [3/3] LXC 배포 ==="
|
||||
bash scripts/deploy_model.sh "$BACKEND"
|
||||
# === [1/3] 데이터 수집 ===
|
||||
echo ""
|
||||
echo "=== [$SYM] [1/3] 데이터 수집 (+ BTC/ETH 상관관계 + OI/펀딩비) ==="
|
||||
if [ ! -f "$PARQUET_FILE" ]; then
|
||||
echo " [최초 실행] 기존 데이터 없음 → 1년치(365일) 전체 수집 (--no-upsert)"
|
||||
FETCH_DAYS=365
|
||||
UPSERT_FLAG="--no-upsert"
|
||||
else
|
||||
echo " [일반 실행] 기존 데이터 존재 → 35일치 Upsert (OI/펀딩비 0.0 구간 보충)"
|
||||
FETCH_DAYS=35
|
||||
UPSERT_FLAG=""
|
||||
fi
|
||||
|
||||
python scripts/fetch_history.py \
|
||||
--symbol "$SYM" \
|
||||
--interval 15m \
|
||||
--days "$FETCH_DAYS" \
|
||||
$UPSERT_FLAG
|
||||
|
||||
# === [1.5/3] OI 파생 피처 A/B 비교 ===
|
||||
echo ""
|
||||
echo "=== [$SYM] [1.5/3] OI 파생 피처 A/B 비교 ==="
|
||||
python scripts/train_model.py --compare --symbol "$SYM" --decay "$DECAY" || true
|
||||
|
||||
# === [2/3] 모델 학습 ===
|
||||
echo ""
|
||||
echo "=== [$SYM] [2/3] 모델 학습 ==="
|
||||
if [ "$BACKEND" = "mlx" ]; then
|
||||
echo " 백엔드: MLX (Apple Silicon GPU), decay=${DECAY}"
|
||||
python scripts/train_mlx_model.py --data "$PARQUET_FILE" --decay "$DECAY"
|
||||
else
|
||||
echo " 백엔드: LightGBM (CPU), decay=${DECAY}"
|
||||
python scripts/train_model.py --symbol "$SYM" --decay "$DECAY"
|
||||
fi
|
||||
|
||||
# Walk-Forward 검증 (WF_SPLITS > 0 인 경우)
|
||||
if [ "$WF_SPLITS" -gt 0 ] 2>/dev/null; then
|
||||
echo ""
|
||||
echo "=== [$SYM] [2.5/3] Walk-Forward 검증 (${WF_SPLITS}폴드) ==="
|
||||
if [ "$BACKEND" = "mlx" ]; then
|
||||
python scripts/train_mlx_model.py \
|
||||
--data "$PARQUET_FILE" \
|
||||
--decay "$DECAY" \
|
||||
--wf \
|
||||
--wf-splits "$WF_SPLITS"
|
||||
else
|
||||
python scripts/train_model.py \
|
||||
--symbol "$SYM" \
|
||||
--decay "$DECAY" \
|
||||
--wf \
|
||||
--wf-splits "$WF_SPLITS"
|
||||
fi
|
||||
fi
|
||||
|
||||
# === [3/3] 배포 ===
|
||||
echo ""
|
||||
echo "=== [$SYM] [3/3] LXC 배포 ==="
|
||||
bash scripts/deploy_model.sh "$BACKEND" --symbol "$SYM"
|
||||
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo " [$SYM] 파이프라인 완료"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "=== 전체 파이프라인 완료: $(date '+%Y-%m-%d %H:%M:%S %Z') ==="
|
||||
|
||||
Reference in New Issue
Block a user