Aller au contenu
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.

Bibliothèque PythonForkArchivéAlgorithme
PythonpandasNumPyPlotlyPoetrypytestSphinx
  • Mis à jour

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) fixe entry_signal (1 achat, −1 vente à découvert, NaN rien), take_profit, stop_loss et position_size sur la bougie du signal ;
  • exit_strategy(df) fixe exit_signal (ou NaN partout).

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.

Diagramme de cas d’utilisation de nova-backtest : Télécharger l’historique; Choisir une plateforme; Définir entrées et sorties; Lancer le backtest; Enregistrer les statistiques; Créer des indicateursnova-backtestTélécharger l’historiqueChoisir une plateformeDéfinir entrées et sortiesLancer le backtestEnregistrer les statistiquesCréer des indicateursAuteur de stratégies«système»API REST de plateforme
Acteurs à gauche (personnes) et à droite (systèmes externes) ; chaque ovale est un cas d’utilisation appuyé par les fichiers cités ci-dessous.
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

  1. Installer les dépendances de requirements.txt (la commande pip du README écrit le paquet novelabs-backtest).
  2. Hériter de BackTest avec exchange="binance", candle="1h", list_pairs=["BTCUSDT", "ETHUSDT"], un capital de départ, un levier et max_pos.
  3. Calculer l’histogramme MACD dans build_indicators et fixer entry_signal, take_profit et stop_loss dans entry_strategy.
  4. Appeler run_backtest() ; les paires absentes sont téléchargées dans database/binance/ la première fois.
  5. 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"]
  1. 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.
  2. Anticipation. _create_closest_exit convertit 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.
  3. 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_signal opposé. Stops et objectifs s’exécutent à leur propre prix ; les deux autres sorties à l’ouverture suivante.
  4. 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.
  5. Résultat et frais. Sur un nominal de 100, la variation vaut sens × (sortie − entrée) / entrée, et les frais 100 × (2 + variation − frais) × frais : des frais à l’entrée, puis sur la valeur de sortie après les premiers frais.
  6. 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_pos positions sont déjà ouvertes sont supprimées, car un vrai compte n’aurait pas pu les prendre. La taille des positions vaut levier / 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 classe BackTest (1 262 lignes) : données, sorties, positions, plafond du portefeuille, statistiques et graphiques.
  • novalabs-backtest/clients/ : un client par plateforme derrière client_interface.py, créé par la fabrique clients().
  • 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_HIST du README lit des fichiers CSV locaux et n’hérite pas de BackTest : il ne montre pas la vraie API de la bibliothèque.
  • Le dépôt est archivé, le nom de dossier novalabs-backtest contient 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-backtest et vers un badge de couverture dans un dépôt au nom différent (nove-backtest).

7. Sources

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
Workflows, déclencheurs, tâches et cibles
WorkflowDéclencheursTâchesPublie vers
ReadTheDocs Build
.github/workflows/make-docs.yml
push, lancement manuel
  • deploy ubuntu-latest
    actions/checkout · Set up Python · Install dependencies · Build Docs · Deploy
GitHub Pages
Publish Python 🐍 distributions 📦 to PyPI
.github/workflows/publish-to-pypi.yml
demande de fusion
  • Build & publish nova-backtest 🐍 ubuntu-latest
    actions/checkout · Set up Python 3.8 · Install setuptools · Build a binary wheel and a source tarball · Publish distribution 📦 to PyPI
PyPI
Python Test and Build
.github/workflows/run-test.yml
push, demande de fusion, lancement manuel
  • deploy ubuntu-latest
    actions/checkout · Set up Python · Install dependencies · Export Environment Variables · Run Tests · Build package
—

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
Dépendances externes
PaquetVersionUsageRôleRegistre
pandas^2.0.0exécutionAnalyse de donnéespypi.org
numpy^1.24.2exécutionAnalyse de donnéespypi.org
pytz^2023.3exécutionWorld timezone definitions, modern and historicalpypi.org
python-decouple^3.8exécutionStrict separation of settings from code.pypi.org
matplotlib^3.7.1exécutionGraphiquespypi.org
aiohttp^3.8.4exécutionClient HTTPpypi.org
asyncio^3.4.3exécutionDeprecated backport of asyncio; use the stdlib package insteadpypi.org
psaw^0.1.0exécutionPushshift.io API Wrapper for reddit.com public comment/submission searchpypi.org
telethon^1.27.0exécutionFull-featured Telegram client library for Python 3pypi.org
requests^2.28.2exécutionClient HTTPpypi.org
ta^0.10.2exécutionDonnées de marché et tradingpypi.org
setuptools—exécutionOutils de buildpypi.org
pytest—exécutionTestspypi.org
typing—exécutionTypagepypi.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

  1. antoinebou12. (2026, 5 novembre). nova-backtest. [Software repository] github.com.
  2. antoinebou12. (2026, 5 novembre). nova-backtest: README. [Repository documentation] github.com.
  3. antoinebou12. (2026, 5 novembre). novalabs-backtest/utils/backtest.py. [Source file] github.com.
  4. antoinebou12. (2026, 5 novembre). novalabs-backtest/utils/constant.py. [Source file] github.com.
  5. antoinebou12. (2026, 5 novembre). README.md. [Source file] github.com.
  6. 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.