Série Algo Trading — De 100K au Million — Partie 10 sur 12

Production, Monitoring & Scale to 1M€

Infrastructure as Code complète, CI/CD, VM hardening, intrusion detection, lifecycle management automatisé, monitoring Discord sécurisé, et la route réaliste de 100K€ vers le million.

Docker + Nomad Hardening CI/CD Claude Code Security
Algo Trading — De 100K au Million10/12
IaCHardeningCI/CDLifecycleMonitoringRôle HumainRoad to 1M
Infrastructure as Code — Tout dans Git

Everything as Code — Le repo monolithique

L'intégralité du système de trading — infrastructure, données, stratégies, monitoring, secrets, déploiement — vit dans un seul dépôt Git. Rien n'est configuré manuellement. Tout est reproductible, auditable, et versionné.

Structure du repo

algo-million/
├── terraform/                    # Infrastructure provisioning
│   ├── main.tf                  # Hetzner VM + DNS + firewall
│   ├── tailscale.tf             # VPN mesh network
│   ├── variables.tf             # Vars (region, instance type)
│   ├── outputs.tf               # IPs, hostnames
│   └── terraform.tfvars.enc     # Vars chiffrées (SOPS/age)
├── nomad/                        # Orchestration de jobs
│   ├── trading-engine.nomad.hcl # Job principal (8 stratégies)
│   ├── data-pipeline.nomad.hcl  # Ingestion + feature engineering
│   ├── ibkr-gateway.nomad.hcl   # IB Gateway container
│   ├── monitoring.nomad.hcl     # Prometheus + Grafana
│   └── discord-bot.nomad.hcl    # Alertes Discord
├── consul/                       # Service discovery + KV store
│   ├── services.hcl             # Enregistrement des services
│   └── config/                  # Configurations par service
│       ├── trading.json         # Params runtime des stratégies
│       └── regime.json          # Thresholds des régimes
├── vault/                        # Secrets management
│   ├── policies/                # Policies Vault
│   │   ├── trading.hcl          # Accès IBKR credentials
│   │   └── discord.hcl          # Accès webhook Discord
│   └── secrets.env.enc          # Secrets chiffrés (age/SOPS)
├── docker/                       # Dockerfiles
│   ├── Dockerfile.trading       # Image trading engine
│   ├── Dockerfile.data          # Image data pipeline
│   ├── Dockerfile.ibkr          # IB Gateway + IBC
│   └── docker-compose.dev.yml   # Dev stack local
├── ansible/                      # Configuration management
│   ├── playbooks/
│   │   ├── harden.yml           # Hardening VM complet
│   │   ├── deploy.yml           # Déploiement Nomad/Consul/Vault
│   │   └── rotate-secrets.yml   # Rotation des secrets
│   └── roles/
│       ├── hardening/           # Rôle hardening (CIS Benchmark)
│       ├── tailscale/           # Installation Tailscale
│       └── monitoring/          # Prometheus + exporters
├── src/                          # Code Python des stratégies
│   ├── strategies/              # 8+ stratégies
│   ├── portfolio/               # Meta-allocateur, HRP, Kelly
│   ├── execution/               # OMS, TWAP, VWAP
│   ├── data/                    # Pipeline ingestion
│   ├── monitoring/              # Discord alerts, health checks
│   └── config/                  # Paramètres par stratégie
├── tests/                        # Tests unitaires + intégration
│   ├── unit/
│   ├── integration/
│   └── backtest/                # Tests de backtests
├── notebooks/                    # Recherche + validation
├── .github/
│   ├── workflows/
│   │   ├── ci.yml               # Tests + lint + security scan
│   │   ├── cd.yml               # Deploy to production
│   │   ├── backtest.yml         # Weekly backtest validation
│   │   └── security.yml         # SAST + dependency audit
│   └── CODEOWNERS               # Review obligatoire
├── scripts/
│   ├── bootstrap.sh             # Setup initial de la VM
│   └── disaster-recovery.sh     # Procédure de recovery
├── docs/                         # Documentation
│   ├── runbook.md               # Procédures opérationnelles
│   ├── incident-response.md     # Playbook incidents
│   └── strategies/              # Doc par stratégie
├── CLAUDE.md                     # Instructions pour Claude Code
└── Makefile                      # Commandes utilitaires

Terraform — Provisionner la VM

claude -p "Crée le fichier terraform/main.tf pour provisionner :
1. Un serveur Hetzner CX41 (4 vCPU, 16GB RAM, 160GB SSD) à Helsinki
2. Firewall: DENY ALL sauf ports Tailscale (41641/UDP) et ICMP
   → Pas de SSH public, pas de HTTP, RIEN sauf Tailscale
3. Volume attaché de 100GB pour les données historiques
4. DNS record A pour trading.mydomain.com
5. Cloud-init script qui:
   a. Met à jour le système (apt update && apt upgrade -y)
   b. Installe les dépendances (docker, nomad, consul, vault, tailscale)
   c. Configure le firewall UFW
   d. Exécute le bootstrap.sh

Utilise le provider hcloud (Hetzner).
Les credentials sont dans vault (pas en clair dans le repo)."
claude -p "Crée terraform/tailscale.tf :
1. Provision un device Tailscale pour la VM trading
2. ACL: seul le device 'operator-laptop' peut se connecter à la VM
3. MagicDNS activé: trading.tail12345.ts.net
4. Exit node désactivé (la VM ne route pas le traffic)
5. SSH via Tailscale uniquement (tssh)

Le résultat: la VM est INVISIBLE sur Internet.
Seul votre laptop (via Tailscale) peut y accéder."

Docker — Containeriser chaque service

claude -p "Crée docker/Dockerfile.trading :
FROM python:3.12-slim

# Security: non-root user
RUN useradd -m -s /bin/bash trader
RUN apt-get update && apt-get install -y --no-install-recommends \
    gcc libffi-dev && rm -rf /var/lib/apt/lists/*

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY src/ ./src/
COPY config/ ./config/

# Security: read-only filesystem
USER trader
ENV PYTHONPATH=/app

# Health check
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
    CMD python -c 'from src.monitoring.health import check; check()'

ENTRYPOINT ['python', '-m', 'src.main']"
claude -p "Crée nomad/trading-engine.nomad.hcl :
job 'trading-engine' {
  datacenters = ['helsinki']
  type = 'service'

  group 'trading' {
    count = 1  # JAMAIS plus de 1 instance (risque de double-ordres)

    constraint {
      attribute = '\${meta.role}'
      value = 'trading'
    }

    # Restart policy: restart max 3x en 30min, puis alerte Discord
    restart {
      attempts = 3
      interval = '30m'
      delay = '30s'
      mode = 'fail'
    }

    task 'engine' {
      driver = 'docker'

      config {
        image = 'ghcr.io/myorg/trading-engine:latest'
        volumes = ['/data:/data:rw']
      }

      # Secrets via Vault
      vault {
        policies = ['trading']
      }

      template {
        data = <<-EOF
        IBKR_HOST={{ key 'trading/ibkr_host' }}
        IBKR_PORT={{ key 'trading/ibkr_port' }}
        DISCORD_WEBHOOK={{ with secret 'secret/discord' }}{{ .Data.data.webhook }}{{ end }}
        IBKR_USERNAME={{ with secret 'secret/ibkr' }}{{ .Data.data.username }}{{ end }}
        EOF
        destination = 'secrets/env'
        env = true
      }

      resources {
        cpu = 2000    # 2 vCPU
        memory = 8192 # 8GB RAM
      }
    }
  }
}"
VM Hardening — Sécuriser la forteresse

Hardening complet de la VM de production

La VM de trading gère votre argent réel. C'est une cible de haute valeur. Le hardening doit être paranoïaque mais automatisé — tout dans un playbook Ansible reproductible.

Stratégie de hardening en 7 couches

claude -p "Crée ansible/playbooks/harden.yml — Playbook de hardening complet:

# Couche 1: Réseau — Isolation totale
- Firewall UFW: DENY ALL incoming sauf Tailscale (41641/UDP)
- Pas de port SSH public (SSH via Tailscale uniquement: tssh trading)
- Pas de port HTTP/HTTPS ouvert (monitoring via Tailscale)
- iptables: bloquer tout traffic sortant sauf:
  * IBKR API (*.interactivebrokers.com:4001-4002)
  * Tailscale (100.64.0.0/10)
  * DNS (1.1.1.1:53, 8.8.8.8:53)
  * NTP (pool.ntp.org:123)
  * GitHub Container Registry (ghcr.io, pour les pulls Docker)
  * Discord webhook (discord.com:443, pour les alertes)
  * Yahoo Finance API (query1.finance.yahoo.com:443, pour les données)
- Fail2ban: même sur Tailscale, bannir après 3 tentatives SSH échouées

# Couche 2: OS — Minimiser la surface d'attaque
- Désinstaller tous les packages non essentiels (snap, avahi, cups, etc.)
- Désactiver IPv6 (pas utilisé, réduit la surface)
- Désactiver les services inutiles (bluetooth, printer, etc.)
- Kernel hardening: sysctl.conf
  net.ipv4.conf.all.rp_filter = 1
  net.ipv4.conf.default.accept_redirects = 0
  net.ipv4.conf.all.send_redirects = 0
  kernel.randomize_va_space = 2
  kernel.exec-shield = 1 (si disponible)
  fs.suid_dumpable = 0
- Limiter les capabilities Docker (no --privileged, drop ALL + add NET_BIND)

# Couche 3: Accès — Zero Trust
- SSH config: PermitRootLogin no, PasswordAuthentication no
- SSH keys only (Ed25519), rotées tous les 90 jours
- Sudo: require password + log toutes les commandes sudo
- PAM: limiter les tentatives de login
- Tailscale ACL: seul le device 'operator-laptop' autorisé
- MFA via Tailscale (device doit être approuvé dans le dashboard)

# Couche 4: Audit — Tout logger
- auditd: logger tous les accès fichiers sensibles
  -w /data -p rwxa -k data_access
  -w /etc/shadow -p rwxa -k auth
  -w /app/config -p rwxa -k config_change
  -a always,exit -F arch=b64 -S execve -k command_exec
- Journald: persist les logs (max 2GB, 90 jours)
- Logrotate pour les logs applicatifs

# Couche 5: Intrusion Detection
- AIDE (Advanced Intrusion Detection Environment):
  Baseline des fichiers système, vérification quotidienne
  Alerte Discord si un fichier système a changé
- rkhunter: scan hebdomadaire pour rootkits
- ClamAV: scan anti-malware hebdomadaire
- Processwatcher: alerter si un process inconnu est lancé
  → Script custom qui compare ps aux contre une whitelist

# Couche 6: Docker Security
- Docker rootless mode (pas de daemon root)
- Conteneurs en read-only filesystem (--read-only)
- Seccomp profile: default (bloque les syscalls dangereux)
- AppArmor profiles pour chaque conteneur
- Pas de --privileged, pas de --net=host
- Image scanning: Trivy dans le CI (bloquer si CVE critique)

# Couche 7: Secrets
- Vault pour tous les secrets (IBKR creds, Discord webhook, API keys)
- Secrets jamais en clair sur disque (tmpfs ou Vault agent)
- Rotation automatique des secrets tous les 30 jours
- Les conteneurs accèdent aux secrets via Vault agent sidecar
"

Détection d'ordres non autorisés

claude -p "Implémente un OrderAuditSystem dans src/monitoring/order_audit.py :

class OrderAuditSystem:
    '''Détecte les ordres et trades qui ne viennent pas de notre bot.

    Vérifié toutes les 5 minutes pendant les heures de marché:

    1. AUDIT DES ORDRES IBKR:
       - Fetch tous les ordres actifs via IBKR API
       - Comparer avec notre journal interne (orders.parquet)
       - Si un ordre existe chez IBKR mais PAS dans notre journal:
         → ALERTE CRITIQUE: ordre non autorisé détecté!
         → Logger: symbole, quantité, prix, heure, OrderID
         → ANNULER immédiatement l'ordre si possible
         → Alerte Discord dans le canal #security

    2. AUDIT DES POSITIONS:
       - Comparer positions IBKR vs positions internes
       - Si une position apparaît chez IBKR sans trade correspondant:
         → ALERTE CRITIQUE: position fantôme!
         → Possibles causes: accès non autorisé, bug, corporate action

    3. AUDIT DES SESSIONS TWS:
       - Vérifier le nombre de sessions TWS connectées
       - Notre bot = 1 session. Si sessions > 1:
         → ALERTE: session TWS supplémentaire détectée
         → Possible accès humain non autorisé ou 2ème instance du bot

    4. AUDIT DES API CALLS:
       - Logger toutes les requêtes API avec timestamp et IP source
       - Si une requête API vient d'une IP non-Tailscale:
         → ALERTE CRITIQUE: accès API depuis IP inconnue

    5. ALERTES:
       - Canal Discord dédié #security (webhook séparé)
       - Email de backup (via SES ou Mailgun)
       - Si 3+ alertes critiques en 1h: EMERGENCY SHUTDOWN (kill all)
    '''
"

Communication Discord sécurisée

claude -p "Implémente SecureDiscordBot dans src/monitoring/discord_secure.py :

class SecureDiscordBot:
    '''Bot Discord avec sécurité renforcée pour les alertes trading.

    Architecture:
    - Webhook (outbound only) pour les alertes → pas de surface d'attaque
    - Bot interactif (optionnel) sur un serveur Discord privé
    - Channel permissions: seul le rôle @operator peut lire #trading
    - Messages signés: chaque alerte contient un HMAC pour vérifier l'authenticité

    Channels:
    #trading    — Fills, P&L quotidien, rebalancement (normal)
    #alerts     — Warnings et erreurs (urgent)
    #security   — Ordres non autorisés, intrusion detection (critique)
    #research   — Backtest results, new signals, lifecycle transitions

    Rate limiting: max 60 messages/minute (éviter le spam en cas de bug)
    Retry: 3 tentatives avec exponential backoff si Discord est down

    Commandes interactives (si bot mode activé):
    !status    — État du système (positions, P&L, dernière exécution)
    !pause     — Pause le trading (requiert confirmation !pause CONFIRM)
    !resume    — Resume le trading
    !emergency — Liquidation de toutes les positions (requiert !emergency CONFIRM)
    !positions — Liste les positions actuelles
    !health    — Health check complet

    Sécurité des commandes:
    - Seul l'user Discord avec ID spécifié peut exécuter les commandes
    - Les commandes destructrices (pause, emergency) nécessitent confirmation
    - Cooldown de 30 secondes entre les commandes
    - Log de toutes les commandes exécutées
    '''
"
CI/CD — GitHub Actions pipeline

Pipeline CI/CD complet dans GitHub Actions

claude -p "Crée .github/workflows/ci.yml :

name: CI Pipeline
on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: { python-version: '3.12' }
      - run: pip install ruff mypy
      - run: ruff check src/
      - run: mypy src/ --strict

  test-unit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: { python-version: '3.12' }
      - run: pip install -r requirements.txt -r requirements-test.txt
      - run: pytest tests/unit/ -v --cov=src --cov-report=xml
      - uses: codecov/codecov-action@v4
        with: { token: secrets.CODECOV_TOKEN }

  test-integration:
    runs-on: ubuntu-latest
    needs: test-unit
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: { python-version: '3.12' }
      - run: pip install -r requirements.txt -r requirements-test.txt
      - run: pytest tests/integration/ -v --timeout=120

  security-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      # SAST: Bandit pour Python
      - run: pip install bandit && bandit -r src/ -f json -o bandit.json
      # Dependency audit: pip-audit
      - run: pip install pip-audit && pip-audit -r requirements.txt
      # Docker image scan: Trivy
      - uses: aquasecurity/trivy-action@master
        with:
          scan-type: 'fs'
          scan-ref: '.'
          severity: 'CRITICAL,HIGH'
          exit-code: '1'  # Fail si CVE critique
      # Secret scanning: detect-secrets
      - run: pip install detect-secrets && detect-secrets scan --baseline .secrets.baseline

  backtest-smoke:
    runs-on: ubuntu-latest
    needs: [test-unit, security-scan]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: { python-version: '3.12' }
      - run: pip install -r requirements.txt
      # Smoke test: backtest rapide (1 an) pour chaque stratégie
      - run: python -m tests.backtest.smoke_test --period=1y --fast
      # Vérifier que chaque stratégie a un Sharpe > 0 sur la dernière année
      - run: python -m tests.backtest.validate_sharpe --min-sharpe=0.0

  build-push:
    runs-on: ubuntu-latest
    needs: [test-integration, backtest-smoke, security-scan]
    if: github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v4
      - uses: docker/login-action@v3
        with: { registry: ghcr.io, username: github.actor, password: secrets.GITHUB_TOKEN }
      - uses: docker/build-push-action@v5
        with:
          context: .
          file: docker/Dockerfile.trading
          push: true
          tags: ghcr.io/myorg/trading-engine:latest,ghcr.io/myorg/trading-engine:sha-github.sha
"
claude -p "Crée .github/workflows/cd.yml :

name: CD Pipeline
on:
  workflow_run:
    workflows: ['CI Pipeline']
    types: [completed]
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    if: github.event.workflow_run.conclusion == 'success'
    steps:
      - uses: actions/checkout@v4

      # Connect to VM via Tailscale
      - uses: tailscale/github-action@v2
        with:
          oauth-client-id: secrets.TS_OAUTH_CLIENT_ID
          oauth-secret: secrets.TS_OAUTH_SECRET
          tags: tag:ci

      # Deploy via Nomad
      - name: Deploy trading engine
        run: |
          # Canary deployment: déployer avec 0 instances d'abord
          nomad job run -address=http://trading.tail.ts.net:4646 \
            -var='image_tag=sha-$GITHUB_SHA' \
            nomad/trading-engine.nomad.hcl

          # Health check: attendre 60s puis vérifier
          sleep 60
          HEALTH=$(curl -s http://trading.tail.ts.net:8080/health)
          if [ '$HEALTH' != 'ok' ]; then
            echo 'Health check failed, rolling back'
            nomad job revert trading-engine 0
            exit 1
          fi

      # Notify Discord
      - name: Notify success
        run: |
          curl -H 'Content-Type: application/json' \
            -d '{\"content\":\"✅ Deploy successful: trading-engine@sha-'$GITHUB_SHA'\"}' \
            secrets.DISCORD_DEPLOY_WEBHOOK
"
claude -p "Crée .github/workflows/security.yml :

name: Security Audit (Weekly)
on:
  schedule:
    - cron: '0 6 * * 1'  # Lundi 6h UTC

jobs:
  full-audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # 1. SAST complet (pas juste le smoke test du CI)
      - run: pip install bandit safety && bandit -r src/ -ll -ii

      # 2. Dependency vulnerabilities
      - run: pip install pip-audit && pip-audit -r requirements.txt --desc

      # 3. Docker image CVE scan (toutes sévérités)
      - uses: aquasecurity/trivy-action@master
        with:
          image-ref: 'ghcr.io/myorg/trading-engine:latest'
          severity: 'LOW,MEDIUM,HIGH,CRITICAL'

      # 4. Infrastructure scan (Terraform)
      - uses: aquasecurity/tfsec-action@v1.0.0

      # 5. Secret scanning
      - run: pip install detect-secrets trufflehog
      - run: trufflehog git file://. --only-verified

      # 6. Report to Discord
      - name: Report
        if: failure()
        run: |
          curl -H 'Content-Type: application/json' \
            -d '{\"content\":\"🔴 SECURITY AUDIT FAILED — Investigate immediately\"}' \
            secrets.DISCORD_SECURITY_WEBHOOK
"
claude -p "Crée .github/workflows/backtest.yml :

name: Weekly Backtest Validation
on:
  schedule:
    - cron: '0 8 * * 0'  # Dimanche 8h UTC

jobs:
  full-backtest:
    runs-on: ubuntu-latest
    timeout-minutes: 120
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: { python-version: '3.12' }
      - run: pip install -r requirements.txt

      # Backtest complet de chaque stratégie (5 ans)
      - run: python -m tests.backtest.full_validation --period=5y

      # Vérifier les critères de promotion/dégradation
      - run: python -m src.portfolio.lifecycle --check-all --output=lifecycle_report.json

      # Si une stratégie a dégradé: alerte
      - name: Check degradations
        run: |
          DEGRADED=$(jq '.degradations | length' lifecycle_report.json)
          if [ '$DEGRADED' -gt '0' ]; then
            curl -H 'Content-Type: application/json' \
              -d '{\"content\":\"⚠️ Backtest found degradation in '$DEGRADED' strategies. Review lifecycle_report.json\"}' \
              secrets.DISCORD_ALERTS_WEBHOOK
          fi
"
Lifecycle Management — Promotion et désactivation as code

Le lifecycle complet — De l'idée à la retraite, piloté par Claude Code

Le lifecycle d'une stratégie est entièrement codifié dans des fichiers YAML dans le repo. Chaque transition (promotion, dégradation, pause, retraite) est un commit Git avec une Pull Request et un review automatique.

Configuration d'une stratégie — YAML

claude -p "Crée la structure de configuration d'une stratégie:

# config/strategies/csm.yaml
strategy:
  name: CrossSectionMomentum
  id: csm
  version: 2.3.1
  category: momentum
  phase: PRODUCTION    # BACKTEST | PAPER | PILOT | RAMP_UP | PRODUCTION | PAUSED | RETIRED
  phase_since: 2026-01-15
  allocation:
    kelly_fraction: 0.5
    max_weight: 0.25
    min_weight: 0.02
    current_weight: 0.20

  # Critères de promotion (vérifiés par le lifecycle manager)
  promotion_criteria:
    paper_to_pilot:
      min_duration_days: 14
      max_tracking_error: 0.05
      min_sharpe: 0.5
    pilot_to_rampup:
      min_duration_days: 30
      min_sharpe_live: 0.5
      max_drawdown: -0.10
    rampup_to_production:
      min_duration_days: 30
      min_sharpe_live: 0.6
      max_drawdown: -0.12

  # Critères de dégradation (vérifiés quotidiennement)
  degradation_criteria:
    production_to_paused:
      rolling_sharpe_60d_below: 0.0
      max_dd_recent_vs_historical: 2.0  # Si DD > 2× le DD historique
    rampup_to_paused:
      max_drawdown: -0.12
      min_sharpe: 0.2
    paused_to_retired:
      max_pause_duration_days: 90

  # Emergency (vérifié en temps réel)
  emergency:
    max_drawdown: -0.20  # → PAUSE immédiate + alerte Discord

  # Paramètres de la stratégie
  params:
    lookback_months: 12
    skip_last_month: true
    n_positions: 30
    rebalance_frequency: monthly
    regions: [US, EU, APAC]
    quality_filter:
      min_roe: 0.05
      max_debt_equity: 3.0
      min_revenue_growth: -0.20

  # Métriques historiques (mises à jour automatiquement)
  metrics:
    sharpe_is: 1.35
    sharpe_oos: 1.12
    sharpe_live: 1.28
    max_dd_historical: -0.221
    max_dd_live: -0.085
    win_rate: 0.52
    avg_win_loss_ratio: 1.8
    total_trades: 847
    months_live: 14
    deflated_sharpe: 0.72
"

Le Lifecycle Manager — Le code qui décide

claude -p "Implémente le StrategyLifecycleManager complet dans src/portfolio/lifecycle.py :

import yaml
from datetime import datetime, timedelta
from pathlib import Path
from dataclasses import dataclass
from enum import Enum

class Phase(Enum):
    BACKTEST = 'BACKTEST'
    PAPER = 'PAPER'
    PILOT = 'PILOT'
    RAMP_UP = 'RAMP_UP'
    PRODUCTION = 'PRODUCTION'
    PAUSED = 'PAUSED'
    RETIRED = 'RETIRED'

@dataclass
class Transition:
    strategy_id: str
    from_phase: Phase
    to_phase: Phase
    reason: str
    metrics: dict
    timestamp: datetime
    requires_human_approval: bool

class StrategyLifecycleManager:
    '''Gère les transitions de phase pour toutes les stratégies.

    Méthodes principales:

    1. check_promotions() — Vérifié chaque dimanche 18h
       Pour chaque stratégie en PAPER/PILOT/RAMP_UP/PAUSED:
       - Lire config/strategies/{id}.yaml
       - Calculer les métriques live actuelles
       - Comparer aux promotion_criteria de la phase courante
       - Si tous les critères sont satisfaits → proposer la promotion
       - Les promotions PILOT→RAMP_UP et RAMP_UP→PRODUCTION nécessitent
         human_approval=True (revue humaine obligatoire)

    2. check_degradations() — Vérifié chaque jour 21h
       Pour chaque stratégie en PRODUCTION/RAMP_UP/PILOT:
       - Calculer rolling_sharpe_60d, max_dd_recent
       - Comparer aux degradation_criteria
       - Si critère de dégradation atteint → PAUSER automatiquement
       - Pas besoin d'approbation humaine (sécurité)

    3. emergency_check() — Vérifié en continu (every 5 min)
       Pour chaque stratégie active:
       - Si DD > emergency.max_drawdown → PAUSE immédiate
       - Alerte Discord #security
       - Log détaillé de la cause

    4. execute_transition(transition: Transition) — Applique la transition
       a. Mettre à jour config/strategies/{id}.yaml (phase, phase_since, metrics)
       b. Mettre à jour l'allocation dans le méta-allocateur
       c. Si promotion: augmenter le poids progressivement (pas d'un coup)
       d. Si dégradation: réduire le poids à 0 et clôturer les positions
       e. Créer un commit Git avec le diff du YAML
       f. Envoyer un résumé Discord

    5. generate_report() — Rapport hebdomadaire de toutes les transitions
       Format:
       ┌──────────────────────────────────────────┐
       │ 📊 LIFECYCLE REPORT — 2026-02-28         │
       │                                           │
       │ PRODUCTION (5): CSM ✓, TSMOM ✓, PEAD ✓, │
       │   RSI_Bounce ✓, Dual_Mom ✓               │
       │ RAMP_UP (1): Pairs_Trading (D+25)        │
       │ PILOT (1): Sector_Rot (D+18)             │
       │ PAPER (1): Bollinger_MR (D+5)            │
       │ PAUSED (0)                                │
       │ RETIRED (0)                               │
       │                                           │
       │ Transitions cette semaine:                │
       │ ✅ Pairs_Trading: PILOT → RAMP_UP        │
       │    Sharpe live: 0.68, DD: -4.2%          │
       │ ⚠️ Aucune dégradation                    │
       └──────────────────────────────────────────┘
    '''
"

Prompts Claude Code pour le lifecycle

Claude Code gère le lifecycle au quotidien

Créer une nouvelle stratégie :

claude -p "Crée une nouvelle stratégie 'VolumeBreakout':
1. Crée src/strategies/volume_breakout.py avec le squelette BaseStrategy
2. Crée config/strategies/volume_breakout.yaml avec phase=BACKTEST
3. Crée tests/unit/test_volume_breakout.py
4. Crée notebooks/research/volume_breakout_exploration.ipynb
5. Ajoute la stratégie au registry dans src/strategies/__init__.py
6. Exécute le backtest initial: pytest tests/backtest/test_volume_breakout.py
7. Si Sharpe OOS > 0.7 et DSR > 0.5: update le YAML à phase=PAPER
8. Commit: 'feat: add VolumeBreakout strategy (phase: BACKTEST)'"

Promouvoir une stratégie :

claude -p "Exécute la promotion review hebdomadaire:
1. Pour chaque stratégie en PAPER/PILOT/RAMP_UP:
   a. Calculer les métriques live (sharpe, DD, tracking error)
   b. Comparer aux critères dans config/strategies/{id}.yaml
   c. Si éligible: créer une PR avec le diff YAML
   d. Si requires_human_approval: ajouter le label 'needs-review'
2. Pour chaque stratégie en PAUSED > 90 jours:
   a. Proposer la transition vers RETIRED
3. Générer le rapport hebdomadaire et l'envoyer sur Discord #research
4. Commit: 'chore: lifecycle review 2026-02-28'"

Optimiser les paramètres :

claude -p "Optimise les paramètres de CSM strategy:
1. Lire config/strategies/csm.yaml pour les params actuels
2. Définir la grille de recherche:
   lookback_months: [6, 9, 12, 15, 18]
   n_positions: [20, 25, 30, 35, 40]
   skip_last_month: [true, false]
3. Walk-Forward avec 5 splits (4y IS, 1y OOS)
4. Critère: maximiser Calmar ratio OOS
5. Vérifier la sensibilité: le Sharpe ne doit pas varier >20% entre params voisins
6. Si meilleurs params trouvés ET robustes:
   a. Mettre à jour csm.yaml avec les nouveaux params
   b. Ajouter un commentaire: 'Optimized on 2026-02-28, prev Calmar=1.1, new Calmar=1.3'
   c. Commit: 'optimize: CSM params — Calmar 1.1 → 1.3'
7. Si pas d'amélioration: ne rien changer (log 'no improvement found')"

Data-driven désactivation :

claude -p "Analyse la stratégie TSMOM qui sous-performe depuis 2 mois:
1. Calculer les métriques rolling (30d, 60d, 90d): sharpe, DD, hit_rate
2. Comparer avec les métriques historiques (p-value du changement)
3. Identifier la cause probable:
   a. Changement de régime? (comparer avec regime_detector output)
   b. Corrélation avec les autres stratégies a changé?
   c. Univers d'ETF a changé (nouveaux listés, délistés)?
   d. Problème de data quality? (checker les gaps, les outliers)
4. Recommandation:
   - Si cause transitoire (régime): KEEP, réduire allocation de 30%
   - Si cause structurelle (alpha decay): PAUSE + investigation approfondie
   - Si cause technique (data): FIX la data, ne pas changer la stratégie
5. Rédiger un rapport dans docs/incidents/tsmom_underperformance_2026_02.md
6. Commit: 'investigate: TSMOM underperformance analysis'"
Monitoring — Le système nerveux

Monitoring à 3 niveaux — Infrastructure, Trading, Business

Niveau 1 — Infrastructure monitoring (Prometheus + Grafana)

claude -p "Configure le monitoring infrastructure:

Prometheus scrape targets:
- node_exporter (CPU, RAM, disque, réseau)
- docker_exporter (conteneurs, mémoire par conteneur)
- process_exporter (trading engine process)

Alertes infrastructure (AlertManager → Discord #alerts):
- CPU > 80% pendant 5 minutes
- RAM > 90%
- Disque > 85%
- Trading engine container restart
- IBKR Gateway déconnecté > 30s
- Nomad job failed/dead
- Network latency vers IBKR > 200ms

Grafana dashboards (accessibles via Tailscale uniquement):
1. System Overview: CPU, RAM, disque, réseau
2. Container Health: état de chaque conteneur, restarts, logs
3. IBKR Connection: latence, drops, reconnections
"

Niveau 2 — Trading monitoring

MétriqueFréquenceAlerte siCanal Discord
P&L quotidien21:30 UTCDD > -2% journalier#trading
P&L cumulé21:30 UTCDD > -10% depuis HWM#alerts
Positions ouvertesContinuPosition > 12% NAV#alerts
Nombre de positionsContinu> 40 ou < 8#alerts
Slippage moyenQuotidien> 10 bps (2× target)#trading
Fill rateQuotidien< 80%#alerts
Sharpe rolling 30dHebdo< 0#research
Corrélation inter-stratHebdoMax corr > 0.7 (risk concentration)#research
Turnover quotidienQuotidien> 15% NAV#trading
Cash levelContinu< 3% (trop peu de buffer)#alerts

Niveau 3 — Business monitoring

claude -p "Implémente le dashboard Discord hebdomadaire dans src/monitoring/weekly_report.py :

class WeeklyReport:
    '''Rapport hebdomadaire envoyé chaque dimanche 19h.

    Format Discord embed:
    ┌───────────────────────────────────────────────────┐
    │ 📊 WEEKLY REPORT — Semaine 9/2026                 │
    │                                                    │
    │ 💰 NAV: 142,350€ (+3,200€ / +2.3%)              │
    │ 📈 Cumul YTD: +18.5% (target: +37.7%)           │
    │ 📊 Sharpe 30d: 1.85                              │
    │ 📉 Max DD live: -4.2% (limit: -25%)             │
    │                                                    │
    │ STRATÉGIES:                                        │
    │  ✅ CSM: +1.8% (20.1% alloc)                     │
    │  ✅ TSMOM: +0.5% (15.8% alloc)                   │
    │  ✅ PEAD: +3.2% (14.5% alloc) ← earnings season  │
    │  ⚠️ IndRot: -0.3% (13.2% alloc) ← rotation late │
    │  ✅ RSI Bounce: +1.1% (7.8% alloc)               │
    │  ✅ Pairs: +0.2% (6.5% alloc)                    │
    │  ✅ Dual Mom: +0.8% (12.2% alloc) → equity mode  │
    │  ✅ Sector Rot: +0.4% (7.5% alloc)               │
    │  💵 Cash: 2.4%                                    │
    │                                                    │
    │ EXECUTION:                                         │
    │  Orders: 156 | Fill rate: 94.2% | Avg slip: 3.1bp │
    │  Best: NVDA +12.5% | Worst: SHOP -4.2%           │
    │                                                    │
    │ REGIME: Risk-On (VIX: 15.2, Credit: 3.5%)        │
    │ NEXT WEEK: FOMC Wed, AAPL/MSFT earnings Thu       │
    │                                                    │
    │ LIFECYCLE:                                         │
    │  Promotions: Pairs → RAMP_UP                      │
    │  Degradations: none                                │
    │  Pipeline: Bollinger_MR (PAPER D+12)              │
    └───────────────────────────────────────────────────┘
    '''
"
Le rôle de l'humain — Ce qu'on ne délègue JAMAIS

L'humain dans la boucle — La fenêtre de contrôle

Le système est quasi-autonome mais certaines décisions sont trop importantes pour être automatisées. L'humain a un rôle précis et limité.

Décisions exclusivement humaines (non automatisables)

DécisionFréquenceOutilPourquoi pas automatique
Approuver RAMP_UP → PRODUCTION~MensuelPR GitHubRisque capital significatif
Redémarrer après Emergency StopRareDiscord !resumeComprendre la cause avant
Augmenter le Kelly fraction~TrimestrielYAML + PRImpact direct sur le risque
Ajouter une nouvelle classe d'actifs~AnnuelCode reviewChangement architectural
Modifier les contraintes hard~SemestrielYAML + PRGarde-fous de sécurité
Décider de retirer un capitalVariableManuelDécision personnelle
Valider un backtest anomaliquement bonVariableReviewRisque d'overfitting

Le rituel hebdomadaire — 30 minutes le dimanche

Checklist du dimanche (19h-19h30)

  1. Lire le rapport hebdomadaire Discord (2 min)
  2. Vérifier les PRs lifecycle : promotions/dégradations proposées (5 min)
  3. Review les métriques de risque : DD, corrélations, concentration (3 min)
  4. Vérifier les alertes security : intrusion, ordres non autorisés (2 min)
  5. Lire les news macro de la semaine prochaine : FOMC, earnings, géopolitique (5 min)
  6. Décision : ajuster le risk budget ? (ex: réduire avant FOMC) (5 min)
  7. Valider ou annuler les transitions lifecycle (3 min)
  8. OK → Le système tourne pour 1 semaine de plus

Total : 30 minutes par semaine. Le reste est automatisé. C'est l'objectif : le minimum d'intervention humaine nécessaire pour garder le contrôle sans micro-manager.

Procédure d'urgence — Le bouton rouge

# Via Discord:
!emergency CONFIRM

# Ou via CLI (si Discord down):
tssh trading 'nomad job stop trading-engine && docker stop $(docker ps -q)'

# Ce qui se passe:
# 1. Toutes les positions sont liquidées au MARKET
# 2. Le trading engine est arrêté
# 3. Alerte email de backup envoyée
# 4. Le système NE PEUT PAS redémarrer sans !resume CONFIRM
# 5. Post-mortem obligatoire avant reprise
La route vers le million

Projection réaliste — 100K€ → 1M€

3 scénarios de projection

PériodeConservateur (25% CAGR)Base (38% CAGR)Optimiste (55% CAGR)
M0 (départ)100 000€100 000€100 000€
M6111 800€117 500€124 500€
M12125 000€138 000€155 000€
M18139 700€162 200€193 000€
M24 (2 ans)156 300€190 500€240 000€
M36 (3 ans)195 300€263 000€373 000€
M48 (4 ans)244 100€363 000€579 000€
M60 (5 ans)305 200€501 000€900 000€
M72 (6 ans)381 500€692 000€1 400 000€
M84 (7 ans)476 800€955 000€
Objectif 1M€~10 ans~7 ans~5.5 ans

Les catalyseurs qui accélèrent (ou ralentissent)

Accélérateurs

  • Ajout de nouvelles stratégies : Chaque stratégie décorrélée augmente le Sharpe combiné. Pipeline continu de recherche → 2-3 nouvelles stratégies/an
  • Apports de capital : Si vous ajoutez 2000€/mois, l'effet composé s'accélère massivement
  • Régimes favorables : Un bull run de 2-3 ans (comme 2020-2021) peut porter le CAGR à 50%+
  • Réduction du slippage : L'optimisation continue réduit les coûts de transaction → +0.5-1% CAGR
  • Confiance accrue : Après 12+ mois de track record, augmenter Kelly de 0.5 à 0.6 → +15% de croissance

Freineurs

  • Alpha decay : Les facteurs s'érodent avec le temps (crowding). La recherche continue est obligatoire.
  • Bear market prolongé : Un marché baissier de 2+ ans (2000-2002, 2008-2009) réduit le CAGR à 10-15%
  • Erreur humaine : Changer les règles pendant un drawdown est la cause #1 de destruction de valeur
  • Scaling effects : Au-delà de 500K€, le slippage augmente sur les mid/small-caps → réduire leur poids
  • Taxation : Les plus-values réduisent le rendement net. Privilégier un PEA/CTO avec enveloppe fiscale optimale

Le plan en 4 phases

PhaseCapitalDuréeFocusStratégies actives
🟡 Launch100K → 150K€12 moisValider le système live, ajuster4-5 (momentum + MR)
🟢 Ramp150K → 300K€18 moisAjouter des stratégies, optimiser6-8 (+ cross-asset)
🔵 Scale300K → 600K€24 moisScaling, gestion de la taille8-10 (+ nouvelles)
⚡ Cruise600K → 1M€+18 moisCompounding, préserver le capital10-12 (maturité)

La leçon finale

Ce que 30 ans d'expérience vous ont appris

Le trading algorithmique n'est pas un sprint, c'est un marathon d'ingénierie. Le code est un moyen, pas une fin. Ce qui fait la différence :

  • La discipline : Ne pas modifier les règles en plein drawdown. Faire confiance au processus.
  • La recherche continue : Allouer 20% de votre temps à la recherche de nouvelles stratégies. Le pipeline ne s'arrête jamais.
  • L'humilité : Aucune stratégie ne fonctionne éternellement. Accepter de RETIRER une stratégie qui a fait sa vie.
  • La patience composée : 38% CAGR semble lent par rapport à l'objectif de 216%. Mais c'est un rendement exceptionnel — top 0.1% des gérants mondiaux. Laissez les intérêts composés faire le travail.
  • L'automatisation : Claude Code écrit 90% du code. Vous validez 10%. Votre temps est pour la stratégie, pas l'implémentation.

Récapitulatif complet de la série

Les 10 parties en un coup d'œil

  • Part 1 — Infrastructure : VM Hetzner, IBKR, Python stack, Claude Code workflow
  • Part 2 — Data Pipeline : Ingestion multi-sources, feature engineering, qualité
  • Part 3 — Alpha Factors : 50+ facteurs, 6 familles, anti-overfitting
  • Part 4 — Portfolio : Kelly + HRP + risk budgeting + 4 niveaux de contraintes
  • Part 5 — Exécution : OMS, TWAP/VWAP, multi-marchés, slippage control
  • Part 6 — Momentum : CSM + TSMOM + PEAD + Industry Rotation (Sharpe combiné 1.62)
  • Part 7 — Mean Reversion : RSI Bounce + Pairs Trading (anti-crash, corrélation -0.15)
  • Part 8 — Cross-Asset : Dual Momentum + Sector Rotation + Tail Hedge (Calmar 4.44)
  • Part 9 — Régime ML : HMM, Gradient Boosting, allocation adaptative
  • Part 10 — Production : IaC, CI/CD, hardening, lifecycle, monitoring, road to 1M€

Résultat final : 8 stratégies en production, Sharpe 2.10, Max DD -8.5%, CAGR 37.7%, objectif 1M€ en ~7 ans.

Algo Trading — De 100K au Million10/12