Skip to main content
scripts/retrain.py is the single command for triggering a retrain. It runs locally with GPU-first and CPU fallback. Signal and position models are always trained together to prevent feature-count mismatches.
Developer/operator lane only. Regular users should run onboarding, select profile 1-5, pull approved model revisions from R2, and run trading.

Usage

# Standard retrain (cached data)
python scripts/retrain.py

# Fetch fresh data from MT5 API before training
python scripts/retrain.py --refresh

# Include SHAP analysis after training
python scripts/retrain.py --shap

# Tune with more Optuna trials (local)
python scripts/retrain.py --trials 100

# Warm-start from existing model weights (faster, experimental)
python scripts/retrain.py --warmstart

CLI flags

FlagDefaultDescription
--refreshfalseFetch fresh BTCUSD M15 candles from MT5 API before training
--shapfalseRun SHAP analysis after training and write shap_summary.json
--localfalseDeprecated compatibility flag (training is already local-only)
--trials N50Optuna trials for local hyperparameter tuning
--warmstartfalseWarm-start from existing weights (skips --no-warmstart)

Backend priority

1. Local GPU   -- auto-detected CUDA or AMD ROCm
2. Local CPU   -- fallback, uses all cores (n_jobs=-1)

What gets trained

Both signal and position models are always trained in the same run:
  • models/ensemble_rf.pkl, ensemble_xgb.pkl, ensemble_lgb.pkl — signal models
  • models/ensemble_scaler.pkl — feature scaler (shared)
  • models/position_rf.pkl, position_xgb.pkl, position_lgb.pkl — position models
  • models/position_scaler.pkl — position feature scaler
  • models/model_compat.json — written after every successful unified train
Never train only the signal model or only the position model separately. They share a scaler. Training one separately produces a scaler mismatch that crashes inference.

After retraining

# 1. Verify model compat
python3 -c "
import json
mc = json.load(open('models/model_compat.json'))
ml = json.load(open('ml_config.json'))
assert mc['feature_count'] == len(ml['features']), 'MISMATCH'
print('OK --', mc['feature_count'], 'features, trained', mc.get('trained_at','?')[:10])
"

# 2. OOS backtest
python backtest_config.py \
  --balance 500 --no-swap --leverage 500 \
  --spread 16.95 --oos-only --no-chart

# 3. Push to R2
python ml/r2_hub.py --push

# 4. Smoke test
python trading.py --dry

Notes

--local is kept only for backward compatibility with older scripts and docs.