Automatiser une watchlist quotidienne : un script planifié qui récupère les données, calcule les signaux et rédige un rapport, et les pièges des clés d'API et des limites de requêtes
Transformez le code d'un notebook en un script robuste en ligne de commande, avec configuration, journalisation, nouvelles tentatives avec temporisation croissante, gestion sûre des clés d'API et planificateur, et produisez un fichier de rapport quotidien.
Ce que vous allez apprendre
- Comment restructurer des cellules de notebook en un script doté de fonctions, d'un point d'entrée
main()et d'un fichier de configuration. - Comment garder les clés d'API hors du code et gérer les limites de requêtes par l'attente et une temporisation exponentielle (exponential back-off).
- Comment rédiger un rapport utile à 07:30 du matin : un tableau classé, quelques alertes et un horodatage.
- Comment planifier le script avec cron ou le Planificateur de tâches de Windows, et quoi journaliser pour que les échecs silencieux ne passent pas inaperçus.
Explication
Un notebook sert à explorer ; un script répète la même tâche chaque jour sans que vous ayez à le surveiller. Les indicateurs (leçon 6) et la logique des signaux (leçons 7 et 8) restent les mêmes ; tout ce qui les entoure change.
Structure du script
Découpez le travail en fonctions ayant chacune une seule tâche : load_config(), fetch(ticker), compute_signals(df), build_report(rows) et main(). La garde if __name__ == '__main__': main() vous permet d'exécuter le fichier tout en important ses fonctions dans des tests. Conservez la watchlist, les paramètres et le dossier de sortie dans config.yaml ou config.json, afin de pouvoir les modifier sans toucher au code.
Clés d'API et secrets
N'écrivez jamais une clé dans le code source ou dans un notebook que vous pourriez partager ou versionner dans Git. Lisez-la depuis une variable d'environnement ou un fichier .env avec os.environ['DATA_API_KEY'] (le paquet python-dotenv charge le fichier .env), et inscrivez .env dans .gitignore. Traitez la clé comme un mot de passe et renouvelez-la si elle fuite.
Limites de requêtes, nouvelles tentatives et temporisation
Une limite de requêtes (rate limit) est le nombre maximal de requêtes qu'un fournisseur autorise par minute ou par jour ; la dépasser renvoie une erreur HTTP 429 ou, pire, des données vides sans erreur. Cadencez la boucle avec time.sleep(60 / max_per_minute). En cas d'échec temporaire (429, 500, délais dépassés), réessayez avec une temporisation exponentielle : attendez 1 s, 2 s, 4 s, 8 s, puis abandonnez et journalisez le ticker comme manquant. Ne réessayez jamais dans une boucle serrée ; c'est ainsi que des clés se font bannir.
def fetch_with_retry(ticker, tries=4, base=1.0):for n in range(tries):try:return fetch(ticker)except TransientError as e:wait = base * 2 ** nlog.warning('%s : %s, nouvel essai dans %.0f s', ticker, e, wait)time.sleep(wait)log.error('%s : abandon', ticker)return None
Mettez en cache les téléchargements bruts (data/raw/TICKER_YYYY-MM-DD.parquet) : une seconde exécution le même jour lit le fichier au lieu de consommer du quota, et vous conservez une trace de ce que le script a vu.
Validation avant les signaux
Les données arrivent défectueuses plus souvent que vous ne le pensez : une dernière barre manquante, une date périmée, une clôture à 0, un split non ajusté. Vérifiez que la dernière date correspond à la date de bourse attendue, que les 20 dernières lignes ne contiennent aucun NaN et que le rendement absolu du jour reste sous un seuil de vraisemblance, par exemple 50 %. Les échecs sont consignés dans une section « problèmes de données » du rapport au lieu de produire un signal d'achat sur une cotation erronée.
Le rapport
Écrivez un fichier Markdown ou HTML contenant l'horodatage de l'exécution et la date des données, un tableau trié selon votre classement (par exemple la distance à la SMA sur 50 jours en unités d'ATR), les nouveaux signaux depuis la veille (comparés au fichier de signaux enregistré la veille) et les problèmes de données. Enregistrez-le sous reports/watchlist_2026-10-30.md pour conserver l'historique ; des graphiques par ticker signalé (leçon 10) sont facultatifs.
Planification et journalisation
Sous Linux et macOS, cron exécute des commandes selon un horaire : 30 6 * * 1-5 /path/venv/bin/python /path/watchlist.py >> /path/logs/cron.log 2>&1 s'exécute à 06:30 les jours ouvrés ; sous Windows, le Planificateur de tâches fait la même chose via une boîte de dialogue. Utilisez le chemin complet du Python de l'environnement virtuel (leçon 1), car les planificateurs n'activent pas les environnements. Journalisez dans un fichier avec le module logging : démarrage, tickers récupérés, signaux trouvés, fin. L'absence d'entrée pour aujourd'hui signifie que le planificateur a échoué. Les ordinateurs se mettent en veille, les réseaux tombent, les points d'accès changent ; un script que vous ne vérifiez pas n'est pas de l'automatisation.
Exemple commenté
Exemple hypothétique : une watchlist de 40 actions européennes et américaines, une offre de données gratuite limitée à 5 requêtes par minute et 500 par jour (chiffres inventés ; vérifiez les conditions actuelles de votre fournisseur).
- Cadence. 40 tickers à 5 par minute = 40 / 5 = 8 minutes au minimum. Le script attend 12 secondes entre les appels. Une planification à 06:30 signifie que les données sont prêtes vers 06:40.
- Quota. Une exécution consomme 40 des 500 appels quotidiens (880 par mois sur 22 jours de bourse). Un bug qui relancerait le script toutes les 10 minutes brûlerait 240 appels par heure et atteindrait le plafond en deux heures environ ; un cache sur disque élimine ce risque.
- Temporisation. Deux tickers renvoient une erreur HTTP 429 au premier essai. Les nouvelles tentatives après 1, 2 et 4 secondes réussissent au deuxième essai ; dans le pire des cas, le temps supplémentaire est de 1 + 2 + 4 + 8 = 15 secondes par ticker, l'exécution se termine donc toujours dans le budget de 10 minutes.
- Rapport. Règle : « la clôture croise à la hausse la SMA sur 50 jours avec un RSI(14) inférieur à 60 ». Le fichier de la veille comptait 3 signaux actifs ; l'exécution du jour en trouve 5, dont 2 nouveaux. Le rapport liste d'abord les 2 nouvelles valeurs, puis les 3 qui se poursuivent, et 1 ticker sous « problèmes de données » parce que sa dernière barre date de deux jours.
Exclu : rien de tout cela ne dit si le signal est rentable ; cela rend seulement la préparation quotidienne fiable et reproductible.
Erreur fréquente
Exercice pratique
Sur papier : votre fournisseur autorise 30 requêtes par minute et 2,000 par jour. Vous voulez exécuter une watchlist de 150 tickers une fois à 06:00 et actualiser 20 tickers prioritaires toutes les 30 minutes entre 09:00 et 17:30 (CET). (a) Quel délai minimal entre les appels respecte la limite par minute ? (b) Combien d'appels une journée complète consomme-t-elle ? Est-ce dans le quota quotidien ? (c) L'exécution de 06:00 indique 150 tickers récupérés, mais tous les signaux sont identiques à ceux de la veille. Citez deux vérifications qui vous diraient si les données sont fraîches.
Afficher la solution
(a) 60 / 30 = 2 secondes entre les appels (prenez 2.1 s par sécurité).
(b) Exécution du matin : 150 appels. En journée : de 09:00 à 17:30, il y a 8.5 heures = 17 créneaux d'une demi-heure, plus le créneau de 09:00 lui-même = 18 actualisations × 20 tickers = 360 appels. Total de 510 appels, bien en deçà de 2,000. Même avec une nouvelle tentative complète pour chaque appel (1,020), le quota tient.
(c) Vérifiez que la dernière date d'index de chaque DataFrame correspond au jour de bourse précédent attendu (en tenant compte des jours fériés boursiers), et comparez une empreinte (hash) ou la dernière clôture du téléchargement du jour avec le fichier mis en cache la veille ; si les 150 dernières clôtures sont identiques à celles de la veille, le fournisseur a servi des données périmées.
Limites : les quotas, les points d'accès et les règles des offres gratuites changent ; les chiffres donnés ici sont illustratifs et vous devez lire la documentation actuelle de votre fournisseur.
Points clés à retenir
- Les scripts ont besoin de fonctions, d'un fichier de configuration, d'une garde
main()et d'une journalisation ; les notebooks, non. - Conservez les clés dans des variables d'environnement ou dans
.env; cadencez les requêtes selon la limite et réessayez avec une temporisation exponentielle, puis abandonnez et journalisez. - Validez les dates et le nombre de lignes avant de calculer les signaux ; mettez en cache les téléchargements bruts.
- Planifiez avec cron ou le Planificateur de tâches en utilisant le chemin complet du Python de l'environnement virtuel, et consultez le journal chaque jour.
Étape suivante
La leçon 13 assemble le tout en un projet complet de notebook de recherche, des données au rapport, et le passe en revue avec une liste de contrôle contre le biais d'anticipation et le surapprentissage.
Auto-évaluation
Répondez aux questions, puis vérifiez vos réponses. Vous pouvez recommencer autant de fois que vous le souhaitez.
Auto-évaluation automatique pour vos propres révisions. Vos réponses sont vérifiées dans votre navigateur ; nous ne les voyons pas et ne les évaluons pas. Ce n'est ni un examen ni une qualification.
Votre progression
« Terminée » signifie seulement que vous avez marqué la leçon comme lue. Ce n'est pas un test de votre compréhension. La progression et les notes sont enregistrées uniquement dans ce navigateur, sur cet appareil — pas dans un compte.