59 KiB
59 KiB
In [13]:
# ── 1.1 Upload du ZIP AHAD QUANT ──────────────────────────────────────────────
from google.colab import files
import os, zipfile, shutil
print('📁 Sélectionne le fichier ahad_quant_v32_FINAL_updated_v4.zip ...')
uploaded = files.upload()
zip_name = list(uploaded.keys())[0]
print(f'\n✅ Reçu : {zip_name} ({os.path.getsize(zip_name)/1024/1024:.1f} MB)')
# Extraire dans /content/ahad_quant
os.makedirs('/content/ahad_quant', exist_ok=True)
with zipfile.ZipFile(zip_name, 'r') as z:
z.extractall('/content/ahad_quant')
# Trouver le dossier extrait
subdirs = [d for d in os.listdir('/content/ahad_quant') if os.path.isdir(f'/content/ahad_quant/{d}')]
PROJECT_DIR = f'/content/ahad_quant/{subdirs[0]}'
print(f'📂 Projet extrait dans : {PROJECT_DIR}')
os.chdir(PROJECT_DIR)
print('✅ Répertoire de travail configuré')📁 Sélectionne le fichier ahad_quant_v32_FINAL_updated_v4.zip ...
Upload widget is only available when the cell has been executed in the
current browser session. Please rerun this cell to enable.
Saving ahad_quant_v32_CLEAN.zip to ahad_quant_v32_CLEAN.zip ✅ Reçu : ahad_quant_v32_CLEAN.zip (0.2 MB) 📂 Projet extrait dans : /content/ahad_quant/ahad_quant_v32_fixed ✅ Répertoire de travail configuré
In [14]:
# ── 1.2 Installation des dépendances ─────────────────────────────────────────
print('📦 Installation des packages...')
# Packages standards depuis PyPI
!pip install -q lightgbm xgboost scikit-learn optuna yfinance stable-baselines3[extra] gymnasium shimmy python-dotenv
# Torch GPU (CUDA 11.8) depuis l'index PyTorch dédié
!pip install -q torch torchvision --index-url https://download.pytorch.org/whl/cu118
print('\n✅ Packages installés')📦 Installation des packages... ✅ Packages installés
In [16]:
# ── 1.3 Configuration GPU + variables d'environnement ────────────────────────
import torch, os
GPU_OK = torch.cuda.is_available()
if GPU_OK:
gpu_name = torch.cuda.get_device_name(0)
gpu_mem = torch.cuda.get_device_properties(0).total_memory / 1024**3
print(f'✅ GPU détecté : {gpu_name} ({gpu_mem:.1f} GB)')
else:
print('⚠️ Pas de GPU — entraînement plus lent (CPU). Active le GPU dans Runtime → Modifier le type de Runtime.')
# Variables d'env pour AHAD QUANT
os.environ.update({
'DATA_SOURCE' : 'yfinance', # source données (gratuit)
'EXCHANGE' : 'paper', # pas de broker réel
'PAPER_MODE' : 'true',
'PAPER_INITIAL_BALANCE' : '10000',
# Mémoire : RAM SYSTÈME Colab (~12 Gi), indépendante de la VRAM du GPU
'MAX_SEQ_PER_PAIR' : '4000',
# Batch size TFT/TGRU — GPU peut prendre 512, CPU limité
'AHAD_QUANT_BATCH_SIZE' : '512' if GPU_OK else '128',
'AHAD_QUANT_MAX_EPOCHS' : '20' if GPU_OK else '10',
})
print('\n📋 Config active :')
for k in ['DATA_SOURCE','PAPER_MODE','MAX_SEQ_PER_PAIR','AHAD_QUANT_BATCH_SIZE','AHAD_QUANT_MAX_EPOCHS']:
print(f' {k} = {os.environ[k]}')✅ GPU détecté : Tesla T4 (14.6 GB) 📋 Config active : DATA_SOURCE = yfinance PAPER_MODE = true MAX_SEQ_PER_PAIR = 4000 AHAD_QUANT_BATCH_SIZE = 512 AHAD_QUANT_MAX_EPOCHS = 20
In [17]:
# ── 1.4 (Optionnel) Montage Google Drive pour sauvegarde auto ────────────────
USE_DRIVE = True # ← Mettre False si tu ne veux pas utiliser Drive
DRIVE_SAVE_DIR = None
if USE_DRIVE:
from google.colab import drive
drive.mount('/content/drive')
DRIVE_SAVE_DIR = '/content/drive/MyDrive/AhadQuant_Models'
os.makedirs(DRIVE_SAVE_DIR, exist_ok=True)
print(f'✅ Drive monté — sauvegarde dans : {DRIVE_SAVE_DIR}')
else:
print('ℹ️ Drive désactivé — les modèles seront téléchargés en fin de notebook')Drive already mounted at /content/drive; to attempt to forcibly remount, call drive.mount("/content/drive", force_remount=True).
✅ Drive monté — sauvegarde dans : /content/drive/MyDrive/AhadQuant_Models
In [18]:
# ── 2.1 Download 730 jours de données 1h pour les 25 paires ─────────────────
import subprocess, sys
print('📡 Téléchargement des données historiques Forex (Yahoo Finance)...')
print(' 25 paires × 730 jours × 1h ≈ 17 000 bougies/paire\n')
result = subprocess.run(
[sys.executable, 'download_data.py'],
capture_output=False,
text=True
)
if result.returncode == 0:
data_files = [f for f in os.listdir('data') if f.endswith('.json')] if os.path.exists('data') else []
print(f'\n✅ Données téléchargées : {len(data_files)} fichiers dans data/')
else:
print(f'\n❌ Erreur download (code {result.returncode})')📡 Téléchargement des données historiques Forex (Yahoo Finance)... 25 paires × 730 jours × 1h ≈ 17 000 bougies/paire ✅ Données téléchargées : 25 fichiers dans data/
In [19]:
# ── 3.1 Entraînement du pipeline ML complet (version diagnostic) ────────────
import subprocess, sys, time, os
print('🧠 Lancement entraînement ML...')
print(' LightGBM + XGBoost + RF + TFT + TransformerGRU + Meta-learner\n')
t0 = time.time()
with open('train_log.txt', 'w') as logfile:
proc = subprocess.Popen(
[sys.executable, '-u', 'train.py'],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
bufsize=1,
)
for line in proc.stdout:
print(line, end='')
logfile.write(line)
logfile.flush()
proc.wait()
elapsed = (time.time() - t0) / 60
if proc.returncode == 0:
print(f'\n✅ Entraînement ML terminé en {elapsed:.1f} min')
else:
print(f'\n❌ Échec entraînement ML (code {proc.returncode}) — {elapsed:.1f} min')
print('\n--- Dernières lignes du log ---')
with open('train_log.txt') as f:
lines = f.readlines()
print(''.join(lines[-40:]))🧠 Lancement entraînement ML...
LightGBM + XGBoost + RF + TFT + TransformerGRU + Meta-learner
[DL] PyTorch 2.11.0+cu128 detected — TFT + TGRU enabled
=================================================================
AHAD QUANT — Ensemble Training Pipeline (V5)
LightGBM + XGBoost + RF + TFT + TransformerGRU + Meta-learner
=================================================================
[0/7] Données disponibles : 25 fichiers dans data/
[1/7] Loading data and building tabular features...
✅ EURUSD — 17,222 samples (719 jours)
✅ GBPUSD — 17,223 samples (719 jours)
✅ USDJPY — 17,109 samples (714 jours)
✅ USDCHF — 17,163 samples (716 jours)
✅ AUDUSD — 17,321 samples (723 jours)
✅ NZDUSD — 17,314 samples (723 jours)
✅ USDCAD — 17,326 samples (723 jours)
✅ EURGBP — 17,248 samples (720 jours)
✅ EURJPY — 17,234 samples (719 jours)
✅ EURCAD — 17,249 samples (720 jours)
✅ EURCHF — 17,233 samples (719 jours)
✅ EURAUD — 17,247 samples (720 jours)
✅ EURNZD — 17,240 samples (720 jours)
✅ GBPJPY — 17,233 samples (719 jours)
✅ GBPCAD — 17,313 samples (723 jours)
✅ GBPCHF — 17,230 samples (719 jours)
✅ GBPAUD — 17,309 samples (723 jours)
✅ AUDCAD — 17,318 samples (723 jours)
✅ AUDNZD — 17,315 samples (723 jours)
✅ AUDJPY — 17,234 samples (719 jours)
✅ AUDCHF — 17,283 samples (722 jours)
✅ CADJPY — 17,237 samples (720 jours)
✅ CHFJPY — 17,221 samples (719 jours)
✅ NZDJPY — 17,230 samples (719 jours)
✅ NZDCAD — 17,309 samples (723 jours)
Total: 431,361 samples | 62 features | 50.40% long labels
[1b/7] Building sequence dataset (SEQ_LEN=168)...
→ sampled 4,000 / 17,051 sequences (RAM cap)
[EURUSD ] 4,000 sequences
→ sampled 4,000 / 17,052 sequences (RAM cap)
[GBPUSD ] 4,000 sequences
→ sampled 4,000 / 16,938 sequences (RAM cap)
[USDJPY ] 4,000 sequences
→ sampled 4,000 / 16,992 sequences (RAM cap)
[USDCHF ] 4,000 sequences
→ sampled 4,000 / 17,150 sequences (RAM cap)
[AUDUSD ] 4,000 sequences
→ sampled 4,000 / 17,143 sequences (RAM cap)
[NZDUSD ] 4,000 sequences
→ sampled 4,000 / 17,155 sequences (RAM cap)
[USDCAD ] 4,000 sequences
→ sampled 4,000 / 17,077 sequences (RAM cap)
[EURGBP ] 4,000 sequences
→ sampled 4,000 / 17,063 sequences (RAM cap)
[EURJPY ] 4,000 sequences
→ sampled 4,000 / 17,078 sequences (RAM cap)
[EURCAD ] 4,000 sequences
→ sampled 4,000 / 17,062 sequences (RAM cap)
[EURCHF ] 4,000 sequences
→ sampled 4,000 / 17,076 sequences (RAM cap)
[EURAUD ] 4,000 sequences
→ sampled 4,000 / 17,069 sequences (RAM cap)
[EURNZD ] 4,000 sequences
→ sampled 4,000 / 17,062 sequences (RAM cap)
[GBPJPY ] 4,000 sequences
→ sampled 4,000 / 17,142 sequences (RAM cap)
[GBPCAD ] 4,000 sequences
→ sampled 4,000 / 17,059 sequences (RAM cap)
[GBPCHF ] 4,000 sequences
→ sampled 4,000 / 17,138 sequences (RAM cap)
[GBPAUD ] 4,000 sequences
→ sampled 4,000 / 17,147 sequences (RAM cap)
[AUDCAD ] 4,000 sequences
→ sampled 4,000 / 17,144 sequences (RAM cap)
[AUDNZD ] 4,000 sequences
→ sampled 4,000 / 17,063 sequences (RAM cap)
[AUDJPY ] 4,000 sequences
→ sampled 4,000 / 17,112 sequences (RAM cap)
[AUDCHF ] 4,000 sequences
→ sampled 4,000 / 17,066 sequences (RAM cap)
[CADJPY ] 4,000 sequences
→ sampled 4,000 / 17,050 sequences (RAM cap)
[CHFJPY ] 4,000 sequences
→ sampled 4,000 / 17,059 sequences (RAM cap)
[NZDJPY ] 4,000 sequences
→ sampled 4,000 / 17,138 sequences (RAM cap)
[NZDCAD ] 4,000 sequences
Total : 100,000 sequences | shape X_seq=(100000, 168, 62) | 50.00% long labels
Sequence samples : 100,000 | shape: (100000, 168, 62)
Seq splits: train=70,000 | val=15,000 | test=15,000
[2/7] Walk-forward cross-validation (tabular)...
Walk-forward CV (4 windows):
Training until validation scores don't improve for 30 rounds
Did not meet early stopping. Best iteration is:
[500] valid_0's binary_logloss: 0.537108
Window 1: train=215,680 test=53,920 acc=0.7102
Training until validation scores don't improve for 30 rounds
Did not meet early stopping. Best iteration is:
[500] valid_0's binary_logloss: 0.536396
Window 2: train=269,600 test=53,920 acc=0.7090
Training until validation scores don't improve for 30 rounds
Did not meet early stopping. Best iteration is:
[500] valid_0's binary_logloss: 0.529891
Window 3: train=323,520 test=53,920 acc=0.7125
Training until validation scores don't improve for 30 rounds
Did not meet early stopping. Best iteration is:
[500] valid_0's binary_logloss: 0.530677
Window 4: train=377,440 test=53,920 acc=0.7138
CV accuracy: 0.7114 ± 0.0019
Tabular splits: train=301,952 | val=64,704 | test=64,705
[3/7] Hyperparameter search (30 Optuna trials)...
Training until validation scores don't improve for 30 rounds
Early stopping, best iteration is:
[306] valid_0's binary_logloss: 0.531696
Training until validation scores don't improve for 30 rounds
Early stopping, best iteration is:
[256] valid_0's binary_logloss: 0.536046
Training until validation scores don't improve for 30 rounds
Did not meet early stopping. Best iteration is:
[1000] valid_0's binary_logloss: 0.531071
Training until validation scores don't improve for 30 rounds
Early stopping, best iteration is:
[176] valid_0's binary_logloss: 0.534405
Training until validation scores don't improve for 30 rounds
Early stopping, best iteration is:
[320] valid_0's binary_logloss: 0.532699
Training until validation scores don't improve for 30 rounds
Did not meet early stopping. Best iteration is:
[1000] valid_0's binary_logloss: 0.529014
Training until validation scores don't improve for 30 rounds
Did not meet early stopping. Best iteration is:
[1000] valid_0's binary_logloss: 0.533946
Training until validation scores don't improve for 30 rounds
Did not meet early stopping. Best iteration is:
[997] valid_0's binary_logloss: 0.531701
Training until validation scores don't improve for 30 rounds
Early stopping, best iteration is:
[540] valid_0's binary_logloss: 0.535239
Training until validation scores don't improve for 30 rounds
Early stopping, best iteration is:
[519] valid_0's binary_logloss: 0.530513
Training until validation scores don't improve for 30 rounds
Did not meet early stopping. Best iteration is:
[996] valid_0's binary_logloss: 0.530435
Training until validation scores don't improve for 30 rounds
Early stopping, best iteration is:
[725] valid_0's binary_logloss: 0.529296
Training until validation scores don't improve for 30 rounds
Did not meet early stopping. Best iteration is:
[998] valid_0's binary_logloss: 0.528426
Training until validation scores don't improve for 30 rounds
Did not meet early stopping. Best iteration is:
[987] valid_0's binary_logloss: 0.529308
Training until validation scores don't improve for 30 rounds
Did not meet early stopping. Best iteration is:
[998] valid_0's binary_logloss: 0.528884
Training until validation scores don't improve for 30 rounds
Did not meet early stopping. Best iteration is:
[1000] valid_0's binary_logloss: 0.529866
Training until validation scores don't improve for 30 rounds
Early stopping, best iteration is:
[815] valid_0's binary_logloss: 0.528147
Training until validation scores don't improve for 30 rounds
Early stopping, best iteration is:
[469] valid_0's binary_logloss: 0.530574
Training until validation scores don't improve for 30 rounds
Did not meet early stopping. Best iteration is:
[1000] valid_0's binary_logloss: 0.532568
Training until validation scores don't improve for 30 rounds
Early stopping, best iteration is:
[897] valid_0's binary_logloss: 0.528453
Training until validation scores don't improve for 30 rounds
Did not meet early stopping. Best iteration is:
[1000] valid_0's binary_logloss: 0.528905
Training until validation scores don't improve for 30 rounds
Early stopping, best iteration is:
[695] valid_0's binary_logloss: 0.529934
Training until validation scores don't improve for 30 rounds
Early stopping, best iteration is:
[833] valid_0's binary_logloss: 0.529049
Training until validation scores don't improve for 30 rounds
Did not meet early stopping. Best iteration is:
[1000] valid_0's binary_logloss: 0.52851
Training until validation scores don't improve for 30 rounds
Early stopping, best iteration is:
[761] valid_0's binary_logloss: 0.531103
Training until validation scores don't improve for 30 rounds
Did not meet early stopping. Best iteration is:
[1000] valid_0's binary_logloss: 0.529707
Training until validation scores don't improve for 30 rounds
Did not meet early stopping. Best iteration is:
[1000] valid_0's binary_logloss: 0.531528
Training until validation scores don't improve for 30 rounds
Did not meet early stopping. Best iteration is:
[1000] valid_0's binary_logloss: 0.529486
Training until validation scores don't improve for 30 rounds
Did not meet early stopping. Best iteration is:
[1000] valid_0's binary_logloss: 0.532756
Training until validation scores don't improve for 30 rounds
Early stopping, best iteration is:
[310] valid_0's binary_logloss: 0.531737
Best LightGBM accuracy (Optuna): 0.7147
[4/7] Training tabular base models (LightGBM + XGBoost + RF)...
Training LightGBM...
Training until validation scores don't improve for 50 rounds
[200] valid_0's binary_logloss: 0.537594
[400] valid_0's binary_logloss: 0.532418
[600] valid_0's binary_logloss: 0.530308
[800] valid_0's binary_logloss: 0.529119
[1000] valid_0's binary_logloss: 0.528434
Early stopping, best iteration is:
[1018] valid_0's binary_logloss: 0.528387
Training XGBoost...
Training RandomForest...
[4b/7] Training Deep Learning models (TFT + TransformerGRU)...
Training Temporal Fusion Transformer...
[TFT] device=cuda | train=70,000 val=15,000 samples
[TFT] parameters: 669,305
/content/ahad_quant/ahad_quant_v32_fixed/tft_model.py:280: FutureWarning: `torch.cuda.amp.GradScaler(args...)` is deprecated. Please use `torch.amp.GradScaler('cuda', args...)` instead.
scaler_amp = torch.cuda.amp.GradScaler(enabled=torch.cuda.is_available())
/content/ahad_quant/ahad_quant_v32_fixed/tft_model.py:297: FutureWarning: `torch.cuda.amp.autocast(args...)` is deprecated. Please use `torch.amp.autocast('cuda', args...)` instead.
with torch.cuda.amp.autocast(enabled=torch.cuda.is_available()):
[TFT] epoch 1/30 train=0.6950 val=0.6942 val_acc=0.5015 (82s)
[TFT] epoch 2/30 train=0.6936 val=0.6953 val_acc=0.5015 (163s)
[TFT] epoch 3/30 train=0.6935 val=0.6931 val_acc=0.5053 (243s)
[TFT] epoch 4/30 train=0.6934 val=0.6935 val_acc=0.5007 (324s)
[TFT] epoch 5/30 train=0.6931 val=0.6934 val_acc=0.5003 (405s)
[TFT] epoch 6/30 train=0.6934 val=0.6940 val_acc=0.5033 (486s)
[TFT] epoch 7/30 train=0.6932 val=0.6936 val_acc=0.5002 (566s)
[TFT] epoch 8/30 train=0.6929 val=0.6938 val_acc=0.5059 (647s)
[TFT] epoch 9/30 train=0.6926 val=0.6932 val_acc=0.5073 (728s)
[TFT] early stopping at epoch 9
[TFT] training complete — best val_loss=0.6931
Training TransformerGRU...
[TGRU] device=cuda | train=70,000 val=15,000 samples
[TGRU] parameters: 588,033
/content/ahad_quant/ahad_quant_v32_fixed/transformer_gru_model.py:275: FutureWarning: `torch.cuda.amp.GradScaler(args...)` is deprecated. Please use `torch.amp.GradScaler('cuda', args...)` instead.
scaler_amp = torch.cuda.amp.GradScaler(enabled=torch.cuda.is_available())
/content/ahad_quant/ahad_quant_v32_fixed/transformer_gru_model.py:292: FutureWarning: `torch.cuda.amp.autocast(args...)` is deprecated. Please use `torch.amp.autocast('cuda', args...)` instead.
with torch.cuda.amp.autocast(enabled=torch.cuda.is_available()):
[TGRU] epoch 1/30 train=0.6419 val=0.5863 val_acc=0.6751 (32s)
[TGRU] epoch 2/30 train=0.5910 val=0.5618 val_acc=0.6897 (64s)
[TGRU] epoch 3/30 train=0.5722 val=0.5608 val_acc=0.6885 (96s)
[TGRU] epoch 4/30 train=0.5620 val=0.5450 val_acc=0.7002 (128s)
[TGRU] epoch 5/30 train=0.5493 val=0.5325 val_acc=0.7067 (160s)
[TGRU] epoch 6/30 train=0.5413 val=0.5278 val_acc=0.7097 (192s)
[TGRU] epoch 7/30 train=0.5334 val=0.5214 val_acc=0.7157 (224s)
[TGRU] epoch 8/30 train=0.5262 val=0.5349 val_acc=0.7007 (255s)
[TGRU] epoch 9/30 train=0.5193 val=0.5043 val_acc=0.7247 (287s)
[TGRU] epoch 10/30 train=0.5138 val=0.4947 val_acc=0.7262 (319s)
[TGRU] epoch 11/30 train=0.5041 val=0.4924 val_acc=0.7249 (351s)
[TGRU] epoch 12/30 train=0.4999 val=0.4847 val_acc=0.7306 (383s)
[TGRU] epoch 13/30 train=0.4940 val=0.4821 val_acc=0.7277 (415s)
[TGRU] epoch 14/30 train=0.4866 val=0.4807 val_acc=0.7303 (447s)
[TGRU] epoch 15/30 train=0.4838 val=0.4750 val_acc=0.7301 (479s)
[TGRU] epoch 16/30 train=0.4791 val=0.4762 val_acc=0.7289 (511s)
[TGRU] epoch 17/30 train=0.4743 val=0.4713 val_acc=0.7335 (543s)
[TGRU] epoch 18/30 train=0.4716 val=0.4662 val_acc=0.7378 (575s)
[TGRU] epoch 19/30 train=0.4677 val=0.4707 val_acc=0.7357 (606s)
[TGRU] epoch 20/30 train=0.4647 val=0.4677 val_acc=0.7347 (639s)
[TGRU] epoch 21/30 train=0.4622 val=0.4695 val_acc=0.7347 (670s)
[TGRU] epoch 22/30 train=0.4592 val=0.4632 val_acc=0.7383 (702s)
[TGRU] epoch 23/30 train=0.4566 val=0.4646 val_acc=0.7373 (734s)
[TGRU] epoch 24/30 train=0.4544 val=0.4650 val_acc=0.7395 (766s)
[TGRU] epoch 25/30 train=0.4532 val=0.4667 val_acc=0.7361 (798s)
[TGRU] epoch 26/30 train=0.4521 val=0.4632 val_acc=0.7394 (830s)
[TGRU] epoch 27/30 train=0.4504 val=0.4662 val_acc=0.7381 (862s)
[TGRU] epoch 28/30 train=0.4497 val=0.4646 val_acc=0.7389 (894s)
[TGRU] epoch 29/30 train=0.4478 val=0.4644 val_acc=0.7387 (926s)
[TGRU] epoch 30/30 train=0.4488 val=0.4646 val_acc=0.7397 (958s)
[TGRU] training complete — best val_loss=0.4632
❌ Échec entraînement ML (code -9) — 88.7 min
--- Dernières lignes du log ---
[TFT] training complete — best val_loss=0.6931
Training TransformerGRU...
[TGRU] device=cuda | train=70,000 val=15,000 samples
[TGRU] parameters: 588,033
/content/ahad_quant/ahad_quant_v32_fixed/transformer_gru_model.py:275: FutureWarning: `torch.cuda.amp.GradScaler(args...)` is deprecated. Please use `torch.amp.GradScaler('cuda', args...)` instead.
scaler_amp = torch.cuda.amp.GradScaler(enabled=torch.cuda.is_available())
/content/ahad_quant/ahad_quant_v32_fixed/transformer_gru_model.py:292: FutureWarning: `torch.cuda.amp.autocast(args...)` is deprecated. Please use `torch.amp.autocast('cuda', args...)` instead.
with torch.cuda.amp.autocast(enabled=torch.cuda.is_available()):
[TGRU] epoch 1/30 train=0.6419 val=0.5863 val_acc=0.6751 (32s)
[TGRU] epoch 2/30 train=0.5910 val=0.5618 val_acc=0.6897 (64s)
[TGRU] epoch 3/30 train=0.5722 val=0.5608 val_acc=0.6885 (96s)
[TGRU] epoch 4/30 train=0.5620 val=0.5450 val_acc=0.7002 (128s)
[TGRU] epoch 5/30 train=0.5493 val=0.5325 val_acc=0.7067 (160s)
[TGRU] epoch 6/30 train=0.5413 val=0.5278 val_acc=0.7097 (192s)
[TGRU] epoch 7/30 train=0.5334 val=0.5214 val_acc=0.7157 (224s)
[TGRU] epoch 8/30 train=0.5262 val=0.5349 val_acc=0.7007 (255s)
[TGRU] epoch 9/30 train=0.5193 val=0.5043 val_acc=0.7247 (287s)
[TGRU] epoch 10/30 train=0.5138 val=0.4947 val_acc=0.7262 (319s)
[TGRU] epoch 11/30 train=0.5041 val=0.4924 val_acc=0.7249 (351s)
[TGRU] epoch 12/30 train=0.4999 val=0.4847 val_acc=0.7306 (383s)
[TGRU] epoch 13/30 train=0.4940 val=0.4821 val_acc=0.7277 (415s)
[TGRU] epoch 14/30 train=0.4866 val=0.4807 val_acc=0.7303 (447s)
[TGRU] epoch 15/30 train=0.4838 val=0.4750 val_acc=0.7301 (479s)
[TGRU] epoch 16/30 train=0.4791 val=0.4762 val_acc=0.7289 (511s)
[TGRU] epoch 17/30 train=0.4743 val=0.4713 val_acc=0.7335 (543s)
[TGRU] epoch 18/30 train=0.4716 val=0.4662 val_acc=0.7378 (575s)
[TGRU] epoch 19/30 train=0.4677 val=0.4707 val_acc=0.7357 (606s)
[TGRU] epoch 20/30 train=0.4647 val=0.4677 val_acc=0.7347 (639s)
[TGRU] epoch 21/30 train=0.4622 val=0.4695 val_acc=0.7347 (670s)
[TGRU] epoch 22/30 train=0.4592 val=0.4632 val_acc=0.7383 (702s)
[TGRU] epoch 23/30 train=0.4566 val=0.4646 val_acc=0.7373 (734s)
[TGRU] epoch 24/30 train=0.4544 val=0.4650 val_acc=0.7395 (766s)
[TGRU] epoch 25/30 train=0.4532 val=0.4667 val_acc=0.7361 (798s)
[TGRU] epoch 26/30 train=0.4521 val=0.4632 val_acc=0.7394 (830s)
[TGRU] epoch 27/30 train=0.4504 val=0.4662 val_acc=0.7381 (862s)
[TGRU] epoch 28/30 train=0.4497 val=0.4646 val_acc=0.7389 (894s)
[TGRU] epoch 29/30 train=0.4478 val=0.4644 val_acc=0.7387 (926s)
[TGRU] epoch 30/30 train=0.4488 val=0.4646 val_acc=0.7397 (958s)
[TGRU] training complete — best val_loss=0.4632
In [ ]:
import os, shutil
if os.path.exists('model_ensemble.pkl'):
print(f"model_ensemble.pkl : {os.path.getsize('model_ensemble.pkl')/1024/1024:.1f} MB")
if DRIVE_SAVE_DIR:
shutil.copy('model_ensemble.pkl', f'{DRIVE_SAVE_DIR}/model_ensemble.pkl')
print(f"💾 Sauvegardé sur Drive : {DRIVE_SAVE_DIR}/model_ensemble.pkl")
else:
print("⚠️ model_ensemble.pkl non trouvé")In [ ]:
# ── 3.2 Résultats ML (backtest rapide) ───────────────────────────────────────
import json
# Lire les résultats de l'entraînement
results_files = ['last_retrain.json', 'backtest_results.json']
for rf in results_files:
if os.path.exists(rf):
with open(rf) as f:
data = json.load(f)
print(f'\n📊 {rf}:')
for k, v in list(data.items())[:15]:
print(f' {k}: {v}')In [ ]:
# ── 4.1 Vérification pré-RL ──────────────────────────────────────────────────
import os, json
print('🔍 Vérification des prérequis RL...')
checks = {
'model_ensemble.pkl' : 'Modèle ML',
'data/' : 'Données Forex',
}
ok = True
for path, label in checks.items():
exists = os.path.exists(path)
print(f' {"✅" if exists else "❌"} {label} ({path})')
if not exists:
ok = False
if ok:
print('\n✅ Tous les prérequis sont présents — tu peux lancer l\'entraînement RL')
else:
print('\n❌ Lance d\'abord les étapes 2 et 3 !')
# Config RL
RL_STEPS = 1_000_000 # ← Modifier ici si besoin (500k = rapide, 2M = meilleure qualité)
print(f'\n⚙️ Steps RL configurés : {RL_STEPS:,}')
print(f' Durée estimée : ~{RL_STEPS/60000:.0f} min (GPU T4)')In [ ]:
# ── 4.2 Entraînement RL PPO ──────────────────────────────────────────────────
# ⚠️ En cas de reprise après déconnexion : changer --steps en 0 et garder --resume
import subprocess, sys, time, os, shutil
RESUME = os.path.exists('rl_progress.json') and os.path.getsize('rl_progress.json') > 5
if RESUME:
with open('rl_progress.json') as f:
prog = json.load(f)
done = prog.get('steps_done', 0)
total = prog.get('total_steps', RL_STEPS)
print(f'♻️ Reprise détectée : {done:,} / {total:,} steps déjà effectués')
resume_flag = ['--resume']
else:
print('🆕 Nouvel entraînement RL')
resume_flag = []
print(f'\n🎮 Lancement PPO ({RL_STEPS:,} steps)...')
print(' Checkpoints sauvegardés toutes les 50k steps dans rl_checkpoints/')
print(' Durée estimée : 45-90 min (GPU T4)\n')
t0 = time.time()
result = subprocess.run(
[sys.executable, 'rl_train.py', '--steps', str(RL_STEPS)] + resume_flag,
capture_output=False,
text=True
)
elapsed = (time.time() - t0) / 60
if result.returncode == 0:
print(f'\n✅ Entraînement RL terminé en {elapsed:.1f} min')
for f in ['rl_agent.zip', 'rl_scaler.pkl']:
if os.path.exists(f):
print(f' {f} : {os.path.getsize(f)/1024:.0f} KB')
# Sauvegarde Drive
if DRIVE_SAVE_DIR:
for f in ['rl_agent.zip', 'rl_scaler.pkl']:
if os.path.exists(f):
shutil.copy(f, f'{DRIVE_SAVE_DIR}/{f}')
# Sauvegarder aussi les checkpoints
if os.path.exists('rl_checkpoints'):
shutil.copytree('rl_checkpoints', f'{DRIVE_SAVE_DIR}/rl_checkpoints', dirs_exist_ok=True)
print(f' 💾 Sauvegardé sur Drive : {DRIVE_SAVE_DIR}/')
else:
print(f'\n❌ Échec RL (code {result.returncode}) — {elapsed:.1f} min')
print(' ➡️ Relance cette cellule avec --resume pour reprendre')In [ ]:
# ── 5.1 Export ahad_quant_unified.zip ─────────────────────────────────────────
import subprocess, sys, os, shutil
print('📦 Export du modèle unifié...')
result = subprocess.run(
[sys.executable, 'export_unified.py'],
capture_output=False,
text=True
)
if result.returncode == 0 and os.path.exists('ahad_quant_unified.zip'):
size_mb = os.path.getsize('ahad_quant_unified.zip') / 1024 / 1024
print(f'✅ ahad_quant_unified.zip créé ({size_mb:.1f} MB)')
if DRIVE_SAVE_DIR:
shutil.copy('ahad_quant_unified.zip', f'{DRIVE_SAVE_DIR}/ahad_quant_unified.zip')
print(f'💾 Sauvegardé sur Drive : {DRIVE_SAVE_DIR}/ahad_quant_unified.zip')
else:
print('❌ Export échoué')In [ ]:
# ── 5.2 Créer un bundle complet avec tous les modèles ────────────────────────
import zipfile, os, datetime, shutil
timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M')
bundle_name = f'ahad_quant_trained_{timestamp}.zip'
FILES_TO_BUNDLE = [
'ahad_quant_unified.zip', # modèle unifié complet
'model_ensemble.pkl', # modèle ML ensemble
'rl_agent.zip', # agent RL PPO
'rl_scaler.pkl', # scaler RL
'backtest_results.json', # résultats backtest
'last_retrain.json', # méta-infos entraînement
]
print(f'📦 Création du bundle {bundle_name}...')
with zipfile.ZipFile(bundle_name, 'w', zipfile.ZIP_DEFLATED) as zf:
for f in FILES_TO_BUNDLE:
if os.path.exists(f):
zf.write(f)
print(f' + {f} ({os.path.getsize(f)/1024:.0f} KB)')
else:
print(f' ⚠️ {f} — non trouvé, ignoré')
# Ajouter les checkpoints RL
if os.path.exists('rl_checkpoints'):
for root, dirs, files in os.walk('rl_checkpoints'):
for file in files:
fp = os.path.join(root, file)
zf.write(fp)
print(f' + rl_checkpoints/ ({len(os.listdir("rl_checkpoints"))} fichiers)')
size_mb = os.path.getsize(bundle_name) / 1024 / 1024
print(f'\n✅ Bundle créé : {bundle_name} ({size_mb:.1f} MB)')
if DRIVE_SAVE_DIR:
shutil.copy(bundle_name, f'{DRIVE_SAVE_DIR}/{bundle_name}')
print(f'💾 Sauvegardé sur Drive : {DRIVE_SAVE_DIR}/{bundle_name}')In [ ]:
# ── 5.3 Téléchargement direct depuis Colab ───────────────────────────────────
from google.colab import files
import os
# Choisir ce qu'on veut télécharger
TO_DOWNLOAD = [
bundle_name, # bundle complet (recommandé)
# 'ahad_quant_unified.zip', # ou juste le modèle unifié
]
for f in TO_DOWNLOAD:
if os.path.exists(f):
size_mb = os.path.getsize(f) / 1024 / 1024
print(f'⬇️ Téléchargement de {f} ({size_mb:.1f} MB)...')
files.download(f)
else:
print(f'⚠️ {f} non trouvé')
print('\n✅ Terminé ! Place les fichiers .pkl et .zip dans ton dossier ahad_quant_v32_fixed/ sur ta machine.')In [ ]:
# ── REPRISE RAPIDE (après déconnexion pendant le RL) ─────────────────────────
# 1. Monte Drive
from google.colab import drive
drive.mount('/content/drive')
# 2. Réinstalle les packages
!pip install -q lightgbm xgboost scikit-learn optuna yfinance stable-baselines3[extra] gymnasium shimmy python-dotenv torch --index-url https://download.pytorch.org/whl/cu118
# 3. Remonte le projet depuis Drive
import os, shutil, json
DRIVE_SAVE_DIR = '/content/drive/MyDrive/AhadQuant_Models'
PROJECT_DIR = '/content/ahad_quant_resume'
os.makedirs(PROJECT_DIR, exist_ok=True)
# Copie le ZIP du projet depuis Drive (si tu l'avais mis là)
# OU remonte le ZIP original depuis upload
# from google.colab import files
# uploaded = files.upload() # ← décommente si besoin
# 4. Copie les modèles existants depuis Drive
for f in ['model_ensemble.pkl', 'rl_agent.zip', 'rl_scaler.pkl', 'rl_progress.json']:
src = f'{DRIVE_SAVE_DIR}/{f}'
if os.path.exists(src):
shutil.copy(src, f'{PROJECT_DIR}/{f}')
print(f'✅ Restauré : {f}')
if os.path.exists(f'{DRIVE_SAVE_DIR}/rl_checkpoints'):
shutil.copytree(f'{DRIVE_SAVE_DIR}/rl_checkpoints', f'{PROJECT_DIR}/rl_checkpoints', dirs_exist_ok=True)
print('✅ Restauré : rl_checkpoints/')
# 5. Affiche la progression
prog_file = f'{PROJECT_DIR}/rl_progress.json'
if os.path.exists(prog_file):
with open(prog_file) as f:
prog = json.load(f)
steps_done = prog.get('steps_done', 0)
total = prog.get('total_steps', 1_000_000)
pct = steps_done / total * 100
print(f'\n📊 Progression RL : {steps_done:,} / {total:,} steps ({pct:.1f}%)')
print('➡️ Maintenant exécute la cellule 4.2 — la reprise sera détectée automatiquement')In [8]:
!free -htotal used free shared buff/cache available Mem: 12Gi 1.1Gi 10Gi 2.0Mi 785Mi 11Gi Swap: 0B 0B 0B