Si tu fais tourner plusieurs bots Freqtrade sur Hyperliquid, tu as forcément déjà vu ce message :
freqtrade.exchange.common - WARNING - _async_get_candle_history() returned exception: "Could not fetch historical candle (OHLCV) data for pair BTC/USDC:USDC due to RateLimitExceeded."Le fameux HTTP 429 — Too Many Requests. Ton bot freeze pendant quelques secondes, rate un signal, loupe un DCA, ou pire : ne détecte pas qu'un exit vient de se remplir. Et plus tu ajoutes de bots, plus ça empire.
C'est le problème n°1 de tous ceux qui essaient de scaler du trading algorithmique sur Hyperliquid avec Freqtrade. Jusqu'à aujourd'hui, les seules "solutions" étaient des rustines : augmenter le process_throttle_secs, baisser le nombre de paires, ou payer un VPN pour multiplier les IPs. Aucune ne résout le problème de fond.
Aujourd'hui je vais te présenter ftcache et ftpairlist — deux systèmes de cache partagé que je viens d'ajouter à mon fork de Freqtrade. Avec eux, 100 bots sur la même machine consomment à peine plus de rate limit qu'un seul bot.
Ce n'est pas de la théorie. C'est ce que je fais tourner en production aujourd'hui.

🤔 Comprendre le problème : pourquoi Freqtrade spamme l'API
Pour comprendre la solution, il faut d'abord comprendre pourquoi Freqtrade fait autant d'appels API.
Ce que fait un bot à chaque cycle
Toutes les X secondes (défini par process_throttle_secs), chaque bot Freqtrade exécute sa boucle de trading — la méthode process(). Voici ce qu'elle fait, étape par étape :

Avec 60 paires, un seul cycle fait donc ~65 appels API. Si ton process_throttle_secs est à 5 secondes, ça fait ~780 appels par minute pour un seul bot.
Le rate limit d'Hyperliquid
Hyperliquid autorise 1 200 requêtes par minute par adresse IP (20 req/s). C'est généreux pour un seul bot. Mais dès que tu en lances un deuxième, tu approches dangereusement de la limite. Au troisième, c'est le 429 festival 🎉
Et la situation empire avec les pairlists dynamiques : les filtres comme VolumePairList, TrendRegularityFilter ou VolatilityFilter ont besoin de télécharger des centaines de bougies historiques pour calculer leurs métriques. Sur un refresh de pairlist (toutes les 30 min par défaut), 5 bots × 60 paires × OHLCV = 300 appels d'un coup. Bonjour le spike.
Ce que les gens essaient (et pourquoi ça ne marche pas vraiment)

Le vrai problème, c'est que chaque bot fait exactement les mêmes appels API que tous les autres — mêmes paires, mêmes bougies, mêmes tickers. 10 bots qui tradent BTC/USDC en 15m téléchargent les mêmes bougies BTC 10 fois. C'est du pur gaspillage.
🧠 La solution : ftcache — un daemon de cache OHLCV partagé
ftcache est un processus daemon qui tourne sur ta machine et centralise TOUS les appels API de TOUS tes bots. Au lieu que chaque bot parle directement à l'exchange, ils parlent au daemon, qui se charge de mutualiser et de dédupliquer les appels.
Architecture en 30 secondes
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Bot 1 │ │ Bot 2 │ │ Bot N │ ← tes bots Freqtrade
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
└──────┬─────┴────────────┘
│ Unix socket (local, ~0 latence)
┌─────▼─────┐
│ ftcache │ ← 1 seul daemon, 1 seul rate limiter
│ daemon │
└─────┬─────┘
│ HTTPS (1 seul flux d'appels)
┌─────▼─────┐
│ Hyperliquid│
│ API │
└───────────┘
Concrètement :
Le premier bot qui démarre lance automatiquement le daemon ftcache (pas besoin de le lancer manuellement).
Chaque bot se connecte au daemon via un Unix socket local — pas de réseau, pas de latence réseau, pas de config supplémentaire.
Quand un bot demande les bougies de BTC/USDC 15m, le daemon vérifie si elles sont déjà en cache. Si oui, il les renvoie instantanément. Si non, il les fetch une seule fois et les distribue à tous les bots qui les demandent.
Le daemon gère un token bucket centralisé — un seul rate limiter pour tous les bots, au lieu d'un par bot.
Ce qui est caché (partagé entre bots)

Ce qui n'est PAS caché (appels directs à l'exchange)

💡 Ces appels non-cachés passent quand même par le rate limiter centralisé du daemon. Donc même les ordres sont coordonnés — pas de collision entre bots.
La magie du coalescing (déduplications en vol)
C'est la feature la plus puissante de ftcache. Imagine :
Bot 1 demande les bougies BTC/USDC 15m au daemon
Le daemon lance le fetch vers Hyperliquid
Pendant que le fetch est en cours (200ms de latence réseau), Bot 2, Bot 3, Bot 4 demandent les mêmes bougies
Au lieu de lancer 3 fetches supplémentaires, le daemon attache les 3 demandes à la requête déjà en vol
Quand la réponse arrive, elle est distribuée aux 4 bots en même temps
Résultat : 4 bots servis, 1 seul appel API consommé.
Ce coalescing est géré par un RequestCoordinator qui aligne les demandes par chunks temporels. Même si les bots ont des décalages de quelques secondes dans leur cycle, les demandes qui couvrent la même plage de bougies sont fusionnées.
Le système de priorités
Tous les appels ne se valent pas. ftcache utilise un token bucket à 4 niveaux de priorité :

En cas de congestion, tes ordres réels passent toujours en premier. Les bots en dry-run ou en warmup attendent. Et à priorité égale, les bots avec le plus de capital déployé sont servis en premier.
Persistance sur disque
Les bougies OHLCV sont persistées au format Feather (format binaire colonnaire ultra-rapide) dans ~/.freqtrade/ftcache/. Si le daemon redémarre, il recharge les bougies depuis le disque au lieu de tout re-télécharger. Résultat : redémarrage en quelques secondes, pas en quelques minutes.
📋 ftpairlist — le cache partagé pour les filtres de pairlist
ftcache résout le problème des bougies et des tickers. Mais il y a un autre gros consommateur d'API : les filtres de pairlist.
Quand tu utilises TrendRegularityFilter, VolatilityFilter, ou VolumePairList avec un lookback de 7 jours, chaque bot doit télécharger des centaines de bougies historiques pour calculer le R², la volatilité, ou le volume moyen de chaque paire. Avec 5 bots et 60 paires, ça fait des centaines d'appels dupliqués à chaque refresh de pairlist.
ftpairlist est un deuxième daemon léger qui cache les résultats des filtres de pairlist. Son principe :
Bot 1 calcule le R² de BTC/USDC pour le TrendRegularityFilter → résultat stocké dans le daemon avec un TTL
Bot 2, 3, 4 demandent le même R² → réponse instantanée depuis le cache, aucun appel API
Quand le TTL expire, un seul bot recalcule → les autres récupèrent le résultat frais
La clé de cache est (nom_du_filtre, hash_des_paramètres, paire). Si tu changes la config du filtre (par exemple le lookback_period), le cache est automatiquement invalidé. Pas de risque de données périmées.
💡 Sur un setup avec 5 bots et 60 paires, le refresh de pairlist passe de 5 × 60 = 300 appels OHLCV à 1 × 60 = 60 appels. Et avec ftcache en plus, même ces 60 appels sont mutualisés.
📊 Comparaison chiffrée : avant/après
Prenons un setup concret : 5 bots DCA mean-reversion, 60 paires chacun, throttle 15s, timeframe 15m.

Tu passes de 108% du rate limit (impossible sans erreurs) à 6.7%. Et ce ratio ne change presque pas en ajoutant des bots — parce que la charge API non-cachée est quasi-constante. Que tu aies 5 bots ou 50, les bougies sont fetchées une seule fois.
Et avec 100 bots ?
100 bots DCA avec ftcache, la charge non-cachée = ordres uniquement. Avec MOT 3 par bot et 15% des bots qui ont un signal par cycle, on parle de ~50 appels ordre/minute. Les bougies et tickers restent à ~60-80 appels. Total : ~130 appels/minute sur un budget de 1 200. Soit 11% de charge.
C'est ça la puissance du cache centralisé : l'ajout d'un bot supplémentaire ne coûte quasiment rien en API. Le coût marginal est uniquement en CPU et RAM côté serveur.
⚙️ Comment l'activer
C'est la meilleure partie : il n'y a rien à configurer. ftcache est activé par défaut dans le fork.
# 1. Clone le fork (si pas déjà fait)
git clone https://github.com/titouannwtt/freqtrade-fork.git
cd freqtrade-fork
# 2. Installe
./setup.sh -i
# 3. Lance tes bots normalement
./launch_bot.sh ma_config_bot1.json
./launch_bot.sh ma_config_bot2.json
./launch_bot.sh ma_config_bot3.json
# ... autant que tu veux
Le premier bot qui démarre lance automatiquement le daemon ftcache. Les suivants s'y connectent via Unix socket. Aucune config réseau, aucun port à ouvrir, aucun fichier à modifier.
Si tu viens de Freqtrade upstream
Deux choses à faire :
Supprime les
ccxt_config.rateLimitetenableRateLimitde tes configs — ils sont ignorés par ftcache et génèrent un warning au démarrage. Le rate limiting est désormais centralisé dans le daemon.Tu peux baisser ton
process_throttle_secsà 15s sans risque de 429 — la charge API ne dépend plus du nombre de bots. (Avant, avec 5 bots, il fallait monter à 30-60s pour éviter les 429.)
// ❌ Avant (Freqtrade upstream, 5 bots)
"process_throttle_secs": 30, // obligé de ralentir
"ccxt_config": { "rateLimit": 500 } // rustine ccxt
// ✅ Après (freqtrade-fork avec ftcache)
"process_throttle_secs": 15, // throttle basé sur la stratégie, pas sur l'API
// pas de ccxt_config.rateLimit — géré par ftcache
Désactiver ftcache (si besoin)
Pour les backtests et hyperopts, ftcache se désactive automatiquement — les backtests lisent les fichiers de data locaux, pas besoin de cache réseau. Aucune interférence.
Si tu veux le désactiver manuellement en live (peu probable, mais possible) :
"shared_ohlcv_cache": {
"enabled": false
}
🛡️ Limites et honnêteté
Parce qu'on est Freqtrade France et qu'on ne vend pas du rêve, voici ce que ftcache ne fait pas :
Il ne résout pas les problèmes de CPU/RAM. 100 bots, c'est 100 processus Python. Chacun consomme 100-300 Mo de RAM et un peu de CPU. Sur un VPS à 2 Go de RAM, tu ne lanceras pas 50 bots. L'API n'est plus le bottleneck, c'est le serveur qui le devient.
Il ne cache pas les ordres. Placer un ordre, c'est un effet de bord — ça ne peut pas être caché. Si 50 bots passent chacun 5 ordres par minute, ça fait 250 appels/min non-cachables. C'est le nouveau plafond théorique.
Il ne remplace pas une bonne stratégie. 100 bots qui perdent de l'argent, ça perd 100 fois plus vite 😅
C'est du code en production, pas un prototype. Mais c'est ma production à moi. Je fais tourner ça depuis plusieurs semaines sans problème, mais ton setup peut différer du mien. Comme toujours : dry-run d'abord.
C'est spécifique au fork. ftcache n'existe pas dans Freqtrade upstream. Si tu utilises la version officielle, tu n'as pas cette fonctionnalité — tu es limité aux rustines décrites plus haut.
🔧 Détails techniques pour les curieux
Si tu veux comprendre comment ça marche sous le capot (ou si tu veux contribuer au code) :
Stack technique
Communication : Unix socket (
/tmp/ftcache-{uid}.sock) — latence ~0ms, pas de réseauProtocole : JSON newline-delimited (un objet JSON par ligne) — simple, debuggable
Rate limiter : Token bucket avec 4 niveaux de priorité et burst configurable
Persistance : format Feather (Apache Arrow) dans
~/.freqtrade/ftcache/, flush toutes les 30sCoalescing :
RequestCoordinatoravecasyncio.Futurepour dédupliquer les requêtes en volAutostart : le daemon est spawné automatiquement par le premier bot, les suivants se connectent
Budget rate limit par exchange
Le daemon est configuré pour rester sous le rate limit officiel avec une marge de sécurité :
La marge de 50% est intentionnelle : elle absorbe les pics (refresh pairlist, burst de DCA) et laisse de la place pour les appels non-cachés (ordres). Si le daemon détecte un 429 malgré tout, il réduit automatiquement son budget (adaptive backoff).
Code source
Tout est dans le repo : github.com/titouannwtt/freqtrade-fork
freqtrade/ohlcv_cache/— daemon, client, mixin, coordinator, store, persistencefreqtrade/pairlist_cache/— daemon, client pour les filtres de pairlist
🤔 FAQ — Questions fréquentes
Est-ce que ça marche avec d'autres exchanges que Hyperliquid ?
Oui. Le daemon supporte tous les exchanges supportés par Freqtrade (via ccxt). Les budgets rate limit sont configurés par exchange. Mais c'est sur Hyperliquid que le gain est le plus flagrant parce que c'est un DEX avec un rate limit relativement bas et aucune notion de sous-comptes API.
Est-ce que ça modifie le comportement de ma stratégie ?
Non. Les bougies, tickers et positions sont identiques — le cache ne modifie rien. Ta stratégie reçoit exactement les mêmes données qu'elle recevrait sans ftcache. La seule différence : les données arrivent depuis le cache local au lieu de l'exchange, donc plus vite.
Et si le daemon crash ?
Les bots détectent la déconnexion et tentent de relancer le daemon automatiquement. Pendant la reconnexion (~2s), les bots continuent de fonctionner avec les données en mémoire. Pas de trade perdu.
Comment je vois que ça marche ?
Au démarrage du bot, tu verras dans les logs :
ftcache | connected to daemon (pid 12345, 3 peers)"3 peers" = 3 autres bots connectés au même daemon. Tu peux aussi vérifier que le daemon tourne :
ls /tmp/ftcache-*.sockEst-ce compatible avec le mode Producer-Consumer de Freqtrade ?
Oui, les deux sont complémentaires. Le Producer-Consumer partage les signaux de trading (entry/exit). ftcache partage les données de marché (bougies, tickers, positions). Tu peux utiliser les deux ensemble.
📌 En résumé
Si tu fais tourner plusieurs bots Freqtrade sur Hyperliquid :
Le problème : chaque bot fait les mêmes appels API que tous les autres. 5 bots = 5× la charge. Le rate limit explose dès le 3ème bot.
La solution : ftcache centralise tous les appels dans un daemon partagé. Les bougies, tickers et positions sont fetchés une seule fois et distribués à tous les bots.
Le résultat : 5 bots consomment ~7% du rate limit. 100 bots ~11%. Tu peux scaler ton setup sans jamais revoir un 429.
Comment l'avoir : utilise freqtrade-fork, c'est activé par défaut.
C'est une des raisons pour lesquelles j'ai créé ce fork — les problèmes que j'ai rencontrés en faisant tourner une douzaine de bots en production, je les ai corrigés directement dans le code. Si tu veux en savoir plus sur le fork et ses autres fonctionnalités, j'en ai fait une présentation complète ici.
Et comme promis dans ce post de présentation : je mets tout sur le fork public au fur et à mesure. ftcache et ftpairlist sont les premiers gros morceaux. La suite arrive.
☕ Si ce post t'a été utile, tu peux me soutenir ici : https://buymeacoffee.com/freqtrade_france
⚠️ Je ne suis pas conseiller financier. Ce contenu reflète mon expérience personnelle et mon approche du trading algorithmique. Les performances passées ne préjugent pas des performances futures. Il existe d'autres méthodes tout aussi valables.
