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.
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é.
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
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."
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
}
}
}
}"
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.
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
"
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)
'''
"
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
'''
"
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
"
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.
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
"
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 │
└──────────────────────────────────────────┘
'''
"
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'"
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
"
| Métrique | Fréquence | Alerte si | Canal Discord |
|---|---|---|---|
| P&L quotidien | 21:30 UTC | DD > -2% journalier | #trading |
| P&L cumulé | 21:30 UTC | DD > -10% depuis HWM | #alerts |
| Positions ouvertes | Continu | Position > 12% NAV | #alerts |
| Nombre de positions | Continu | > 40 ou < 8 | #alerts |
| Slippage moyen | Quotidien | > 10 bps (2× target) | #trading |
| Fill rate | Quotidien | < 80% | #alerts |
| Sharpe rolling 30d | Hebdo | < 0 | #research |
| Corrélation inter-strat | Hebdo | Max corr > 0.7 (risk concentration) | #research |
| Turnover quotidien | Quotidien | > 15% NAV | #trading |
| Cash level | Continu | < 3% (trop peu de buffer) | #alerts |
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 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écision | Fréquence | Outil | Pourquoi pas automatique |
|---|---|---|---|
| Approuver RAMP_UP → PRODUCTION | ~Mensuel | PR GitHub | Risque capital significatif |
| Redémarrer après Emergency Stop | Rare | Discord !resume | Comprendre la cause avant |
| Augmenter le Kelly fraction | ~Trimestriel | YAML + PR | Impact direct sur le risque |
| Ajouter une nouvelle classe d'actifs | ~Annuel | Code review | Changement architectural |
| Modifier les contraintes hard | ~Semestriel | YAML + PR | Garde-fous de sécurité |
| Décider de retirer un capital | Variable | Manuel | Décision personnelle |
| Valider un backtest anomaliquement bon | Variable | Review | Risque d'overfitting |
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.
# 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
| Période | Conservateur (25% CAGR) | Base (38% CAGR) | Optimiste (55% CAGR) |
|---|---|---|---|
| M0 (départ) | 100 000€ | 100 000€ | 100 000€ |
| M6 | 111 800€ | 117 500€ | 124 500€ |
| M12 | 125 000€ | 138 000€ | 155 000€ |
| M18 | 139 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 |
| Phase | Capital | Durée | Focus | Stratégies actives |
|---|---|---|---|---|
| 🟡 Launch | 100K → 150K€ | 12 mois | Valider le système live, ajuster | 4-5 (momentum + MR) |
| 🟢 Ramp | 150K → 300K€ | 18 mois | Ajouter des stratégies, optimiser | 6-8 (+ cross-asset) |
| 🔵 Scale | 300K → 600K€ | 24 mois | Scaling, gestion de la taille | 8-10 (+ nouvelles) |
| ⚡ Cruise | 600K → 1M€+ | 18 mois | Compounding, préserver le capital | 10-12 (maturité) |
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 :
Résultat final : 8 stratégies en production, Sharpe 2.10, Max DD -8.5%, CAGR 37.7%, objectif 1M€ en ~7 ans.