Table des matières
nova-backtest
nova-backtest est une bibliothèque Python de backtesting de stratégies de trading crypto, publiée sur PyPI sous le nom novalabs-backtest (version 1.1.10 dans pyproject.toml). Elle télécharge les bougies historiques de Binance, Bybit, OKX, KuCoin, Huobi, MEXC, BTCEX et Oanda, applique une stratégie à de nombreuses paires à la fois et produit des statistiques. Ce dépôt est un fork archivé du projet NovaLabs ; les commits faits ici en avril 2023 renomment le dossier du paquet et mettent à jour le README. L’intérêt du code est sa façon de simuler les transactions sans boucle bougie par bougie.
1. Aperçu
Une stratégie est une sous-classe de BackTest (novalabs-backtest/utils/backtest.py) qui remplit trois méthodes sur un DataFrame pandas de bougies :
build_indicators(df)ajoute les colonnes d’indicateurs ;entry_strategy(df)fixeentry_signal(1 achat, −1 vente à découvert,NaNrien),take_profit,stop_lossetposition_sizesur la bougie du signal ;exit_strategy(df)fixeexit_signal(ouNaNpartout).
Le constructeur reçoit la plateforme, l’intervalle des bougies, les paires (une liste, "All pairs" ou "Random N"), la période, le capital de départ, le levier, le nombre maximal de positions ouvertes et la durée maximale de détention. Chaque position reçoit levier / max_pos du capital, et les frais maker de la plateforme viennent de FEES dans utils/constant.py (Binance 0,02 %, Bybit 0,01 %, OKX 0,015 %).
2. Cas d’utilisation
Bibliothèque Python qui télécharge les chandelles des plateformes crypto et teste une stratégie avec profits et drawdown.
- Télécharger l’historique
- Auteur de stratégiesAPI REST de plateforme
BackTest.get_historical_data (novalabs-backtest/utils/backtest.py) appelle le client de la plateforme et garde les données OHLCV dans database/<exchange>/hist_<pair>_<candle>.csv, à partir du 2019-01-01.
- Choisir une plateforme
- Auteur de stratégiesAPI REST de plateforme
clients() (novalabs-backtest/clients/clients.py) renvoie un client Binance, Bybit, OKX, Huobi, KuCoin, MEXC, Oanda ou BTCEX, chacun conforme à BackTestClientInterface.
- Définir entrées et sorties
- Auteur de stratégies
Une stratégie hérite de BackTest et remplit build_indicators, entry_strategy (entry_signal, take_profit, stop_loss, position_size) et exit_strategy (exit_signal).
- Lancer le backtest
- Auteur de stratégies
run_backtest simule les positions par paire avec les frais de la plateforme, un nombre maximal de positions et une durée de détention maximale, puis trace le profit cumulé.
- Enregistrer les statistiques
- Auteur de stratégies
L’exécution écrit results/<strategy>_pairs_stats.csv et results/<strategy>_overall_stats.json avec rendements, drawdown et chiffres par paire.
- Créer des indicateurs
- Auteur de stratégies
TechnicalIndicatorsCreation (novalabs-backtest/utils/indicators.py) ajoute décalages, ratios de clôture et niveaux de support ou de résistance à un DataFrame de chandelles.
2.1. Scénario : Tester une stratégie MACD sur des paires Binance
- Installer les dépendances de requirements.txt (la commande pip du README écrit le paquet novelabs-backtest).
- Hériter de BackTest avec exchange="binance", candle="1h", list_pairs=["BTCUSDT", "ETHUSDT"], un capital de départ, un levier et max_pos.
- Calculer l’histogramme MACD dans build_indicators et fixer entry_signal, take_profit et stop_loss dans entry_strategy.
- Appeler run_backtest() ; les paires absentes sont téléchargées dans database/binance/ la première fois.
- Lire le graphique de profit et les fichiers JSON et CSV écrits sous results/.
Fichiers consultésREADME.mdnovalabs-backtest/utils/backtest.pynovalabs-backtest/clients/clients.pynovalabs-backtest/clients/client_interface.pynovalabs-backtest/utils/indicators.pyrequirements.txt
3. Simulation d’une transaction
run_backtest traite chaque paire par opérations sur des colonnes entières, puis fusionne les paires.
flowchart TD
D["get_historical_data(paire) : bougies du client de la plateforme"] --> I["build_indicators"]
I --> E["entry_strategy : entry_signal, take_profit, stop_loss"]
E --> V["_verify_tp_sl : TP et SL du bon côté du prix"]
V --> P["_create_entry_prices_times : entrée à l’ouverture de la bougie SUIVANTE"]
P --> X["exit_strategy : exit_signal"]
X --> L["_create_closest_exit : anticipation sur i = 1 … N−1 bougies"]
L --> F["_create_all_exit_point : le plus tôt entre SL, TP, détention max et signal de sortie"]
F --> O["_create_position_df : retire les chevauchements sur une paire, prix de sortie, résultat et frais"]
O --> A["_all_pairs_real_positions : fusionne les paires, trie par sortie, retire ce qui dépasse max_pos"]
A --> S["_create_full_statistics + graphique Plotly"]
- Entrée. Un signal sur la bougie t est exécuté à l’ouverture de la bougie t + 1 : la stratégie ne peut pas négocier au cours de clôture qu’elle vient d’utiliser pour décider.
- Anticipation.
_create_closest_exitconvertit la durée maximale de détention en un nombre de bougies N et construit, pour chaque décalage i de 1 à N − 1, une colonne avec l’heure à laquelle la bougie t + i a touché le stop ou l’objectif. Pour un achat, le stop est touché quand le plus bas de cette bougie est au niveau du stop ou en dessous ; l’objectif ne compte que si le plus haut l’atteint et que le plus bas est resté au-dessus du stop. Quand une bougie touche les deux, la transaction est comptée comme stoppée : c’est la lecture prudente, puisqu’on ignore l’ordre des deux mouvements dans la bougie. Les ventes à découvert sont symétriques. - Sortie. L’heure de sortie est la plus tôt entre le stop le plus proche, l’objectif le plus proche, l’entrée plus la durée maximale, et la bougie qui suit un
exit_signalopposé. Stops et objectifs s’exécutent à leur propre prix ; les deux autres sorties à l’ouverture suivante. - Une transaction à la fois par paire. Les transactions dont l’entrée précède la sortie de la transaction précédente sur la même paire sont retirées.
- Résultat et frais. Sur un nominal de 100, la variation vaut
sens × (sortie − entrée) / entrée, et les frais100 × (2 + variation − frais) × frais: des frais à l’entrée, puis sur la valeur de sortie après les premiers frais. - Plafond du portefeuille. Les transactions de toutes les paires sont fusionnées et triées par heure de sortie ; celles qui s’ouvriraient alors que
max_pospositions sont déjà ouvertes sont supprimées, car un vrai compte n’aurait pas pu les prendre. La taille des positions vautlevier / max_pos × capital, avec en option une capitalisation (geometric_sizes).
Transaction détaillée. La stratégie d’exemple du README, MACD_HIST, achète quand l’histogramme du MACD devient positif et place l’objectif et le stop à tp_sl_delta = 0.05 de la clôture. Supposons que la bougie suivante ouvre à 100 et, pour simplifier, que la clôture du signal valait aussi 100 : l’objectif est à 105 et le stop à 95. La bougie t + 2 a un plus bas de 97 et un plus haut de 103 : rien ne se passe. La bougie t + 3 a un plus bas de 96 et un plus haut de 105,5 : le plus haut atteint l’objectif et le plus bas reste au-dessus du stop, la transaction sort donc à 105 sur cette bougie. La variation est de +5 % et les frais Binance de 0,02 % : sur un nominal de 100, les frais valent 100 × (2 + 0,05 − 0,0002) × 0,0002 = 0,041 et le résultat réalisé 5 − 0,041 = 4,959. Avec un levier de 2 et max_pos = 4, chaque position mobilise la moitié du capital. (Les valeurs des bougies sont illustratives ; les étapes et les formules sont celles du code.)
4. Démarrage
pip install novalabs-backtest
Le README écrit pip install novelabs-backtest, avec une coquille dans le nom du paquet. Une stratégie hérite ensuite de BackTest, implémente les trois méthodes et appelle run_backtest(), qui enregistre results/{stratégie}_pairs_stats.csv et results/{stratégie}_overall_stats.json. Certains clients de plateforme demandent des clés d’API passées par key, secret et passphrase.
5. Guide du dépôt
novalabs-backtest/utils/backtest.py: la classeBackTest(1 262 lignes) : données, sorties, positions, plafond du portefeuille, statistiques et graphiques.novalabs-backtest/clients/: un client par plateforme derrièreclient_interface.py, créé par la fabriqueclients().novalabs-backtest/utils/indicators.py,helpers.py,constant.py: indicateurs, conversions d’intervalles et frais.novalabs-backtest/data/: collecteurs Discord, Reddit, Telegram et carnet d’ordres.tests/: tests des clients (format, plus ancien horodatage, historique, informations des paires, heure du serveur, mises à jour) et des indicateurs..github/workflows/: tests, publication sur PyPI et génération de la documentation ;docs/est un site Sphinx.
6. Limites
- La boucle d’anticipation s’arrête à N − 1 bougies, une de moins que la durée maximale de détention, et son coût croît avec N : deux nouvelles colonnes par bougie de détention.
- Dans une même bougie, toucher à la fois le stop et l’objectif compte toujours comme un stop, même si le prix a pu atteindre l’objectif d’abord.
- Les frais utilisent le taux maker pour les deux jambes ; les ordres au marché, le financement et le glissement ne sont pas modélisés.
- L’exemple
MACD_HISTdu README lit des fichiers CSV locaux et n’hérite pas deBackTest: il ne montre pas la vraie API de la bibliothèque. - Le dépôt est archivé, le nom de dossier
novalabs-backtestcontient un trait d’union (impossible à importer tel quel depuis les sources) et la commande d’installation du README a une coquille. - Les badges du README pointent vers
Nova-DevTeam/nova-backtestet vers un badge de couverture dans un dépôt au nom différent (nove-backtest).
7. Sources
- Dépôt GitHub
- Paquet PyPI
novalabs-backtest novalabs-backtest/utils/backtest.pynovalabs-backtest/utils/constant.py- README
8. Pipeline CI/CD
3 workflows GitHub Actions, 3 tâches. Chaque boîte est une tâche ; les boîtes à double bord publient ou déploient, et les flèches suivent les dépendances needs.
Mermaid Déroulement du pipeline
flowchart LR
subgraph wf0["ReadTheDocs Build"]
direction LR
wf0_deploy[["deploy<br/>ubuntu-latest"]]
end
subgraph wf1["Publish Python 🐍 distributions 📦 to PyPI"]
direction LR
wf1_build_n_publish[["Build & publish nova-backtest 🐍<br/>ubuntu-latest"]]
end
subgraph wf2["Python Test and Build"]
direction LR
wf2_deploy["deploy<br/>ubuntu-latest"]
end
t0(["push · lancement manuel"])
t1(["demande de fusion"])
t2(["push · demande de fusion · lancement manuel"])
d0[("GitHub Pages")]
d1[("PyPI")]
t0 --> wf0_deploy
wf0_deploy -.-> d0
t1 --> wf1_build_n_publish
wf1_build_n_publish -.-> d1
t2 --> wf2_deploy
| Workflow | Déclencheurs | Tâches | Publie vers |
|---|---|---|---|
ReadTheDocs Build.github/workflows/make-docs.yml | push, lancement manuel |
| GitHub Pages |
Publish Python 🐍 distributions 📦 to PyPI.github/workflows/publish-to-pypi.yml | demande de fusion |
| PyPI |
Python Test and Build.github/workflows/run-test.yml | push, demande de fusion, lancement manuel |
| — |
Généré à partir du code au commit dda19e6.
9. Schéma de déploiement
Mermaid Schéma de déploiement
flowchart LR
repo[("Dépôt GitHub")]
ci[["GitHub Actions<br/>3 workflows"]]
image["Image Docker"]
pub_GitHub_Pages[("GitHub Pages")]
pub_PyPI[("PyPI")]
repo -->|"push ou demande de fusion"| ci
ci -->|"docker build"| image
ci -->|"publie"| pub_GitHub_Pages
ci -->|"publie"| pub_PyPI
10. Dépendances externes
14 paquets déclarés (14 à l’exécution, 0 pour le développement) dans pyproject.toml, requirements.txt.
Tableau des paquets 14
| Paquet | Version | Usage | Rôle | Registre |
|---|---|---|---|---|
pandas | ^2.0.0 | exécution | Analyse de données | pypi.org |
numpy | ^1.24.2 | exécution | Analyse de données | pypi.org |
pytz | ^2023.3 | exécution | World timezone definitions, modern and historical | pypi.org |
python-decouple | ^3.8 | exécution | Strict separation of settings from code. | pypi.org |
matplotlib | ^3.7.1 | exécution | Graphiques | pypi.org |
aiohttp | ^3.8.4 | exécution | Client HTTP | pypi.org |
asyncio | ^3.4.3 | exécution | Deprecated backport of asyncio; use the stdlib package instead | pypi.org |
psaw | ^0.1.0 | exécution | Pushshift.io API Wrapper for reddit.com public comment/submission search | pypi.org |
telethon | ^1.27.0 | exécution | Full-featured Telegram client library for Python 3 | pypi.org |
requests | ^2.28.2 | exécution | Client HTTP | pypi.org |
ta | ^0.10.2 | exécution | Données de marché et trading | pypi.org |
setuptools | — | exécution | Outils de build | pypi.org |
pytest | — | exécution | Tests | pypi.org |
typing | — | exécution | Typage | pypi.org |
11. Glossaire
Dépôt
Les fichiers source, la configuration et l’historique versionné d’un projet.
README
Le document d’entrée du dépôt, qui présente généralement son rôle et son installation.
Dépendance
Une bibliothèque, un outil ou un service nécessaire à la compilation ou à l’exécution d’un composant.
API
Une interface par laquelle des composants logiciels échangent des requêtes et des résultats. Une API n’utilise pas nécessairement HTTP.
HTTP
Un protocole de requête et réponse utilisé par les navigateurs et services web. Une requête comprend une méthode, un chemin, des en-têtes et parfois un corps.
Interface en ligne de commande
Une interface textuelle où les commandes et arguments choisissent les opérations. Les codes de retour permettent aux scripts de détecter un succès ou un échec.
Compilation
Les étapes qui transforment les sources et dépendances en programme exécutable ou en livrable distribuable.
Intégration continue
Des vérifications automatiques lors des changements de source, comme la compilation, les tests et l’analyse statique. Elles ne couvrent que ce qu’elles vérifient.
Mermaid
Un langage de diagrammes textuel. Les nœuds et liens décrivent un modèle ; le diagramme n’exécute pas le projet.
Fork
Un dépôt distinct dérivé d’un autre projet. Une modification du fork ne devient pas automatiquement une modification du projet amont.
12. Références
- antoinebou12. (2026, 5 novembre). nova-backtest. [Software repository] github.com.
- antoinebou12. (2026, 5 novembre). nova-backtest: README. [Repository documentation] github.com.
- antoinebou12. (2026, 5 novembre). novalabs-backtest/utils/backtest.py. [Source file] github.com.
- antoinebou12. (2026, 5 novembre). novalabs-backtest/utils/constant.py. [Source file] github.com.
- antoinebou12. (2026, 5 novembre). README.md. [Source file] github.com.
- Boucher, A. (2026, 23 octobre). nova-backtest : Des bougies historiques à la simulation. [Project article] antoineboucher.info.
Les sources sans date de publication indiquent la date de leur dernière vérification, le 5 novembre 2026. Les liens des fichiers conservent la révision inspectée lorsqu’elle est disponible.