#!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" RUNTIME_DIR="$REPO_ROOT/runtime" LOG_FILE="$RUNTIME_DIR/lstm_retrain.log" LOCK_FILE="$RUNTIME_DIR/lstm_retrain.lock" mkdir -p "$RUNTIME_DIR" log() { printf '[%s] %s\n' "$(date -Is)" "$*" | tee -a "$LOG_FILE" } if command -v flock >/dev/null 2>&1; then exec 9>"$LOCK_FILE" if ! flock -n 9; then log "Another LSTM retrain is already running; skipping." exit 0 fi else LOCK_DIR="$LOCK_FILE.d" if ! mkdir "$LOCK_DIR" 2>/dev/null; then log "Another LSTM retrain is already running; skipping." exit 0 fi trap 'rmdir "$LOCK_DIR"' EXIT fi if [[ -x "$REPO_ROOT/.venv/bin/python" ]]; then PYTHON="$REPO_ROOT/.venv/bin/python" elif command -v python3 >/dev/null 2>&1; then PYTHON="$(command -v python3)" elif command -v python >/dev/null 2>&1; then PYTHON="$(command -v python)" else log "ERROR: Python was not found." exit 1 fi SYMBOLS="${LSTM_RETRAIN_SYMBOLS:-}" LIMIT="${LSTM_RETRAIN_LIMIT:-1000}" LOOKBACKS="${LSTM_RETRAIN_LOOKBACKS:-16,32}" UNITS="${LSTM_RETRAIN_UNITS:-4,6}" RIDGES="${LSTM_RETRAIN_RIDGES:-0.001}" INTERVAL="${LSTM_RETRAIN_INTERVAL:-}" ENV_FILE="${LSTM_RETRAIN_ENV:-}" if [[ -z "$ENV_FILE" && -f "$REPO_ROOT/.env" ]]; then ENV_FILE="$REPO_ROOT/.env" fi args=( "tools/train_lstm_forecaster.py" "--limit" "$LIMIT" "--lookbacks" "$LOOKBACKS" "--units" "$UNITS" "--ridges" "$RIDGES" ) if [[ -n "$SYMBOLS" ]]; then args+=("--symbols" "$SYMBOLS"); fi if [[ -n "$INTERVAL" ]]; then args+=("--interval" "$INTERVAL"); fi if [[ -n "$ENV_FILE" ]]; then args+=("--env" "$ENV_FILE"); fi cd "$REPO_ROOT" log "Starting LSTM retrain: $PYTHON -u ${args[*]}" "$PYTHON" -u "${args[@]}" 2>&1 | tee -a "$LOG_FILE" log "Finished LSTM retrain."