Accéder au contenu principal

Tutoriel sur le trading algorithmique en R

Dans ce tutoriel R, vous ferez du web scraping, appellerez une API finance et utiliserez un htmlwidget pour créer un graphique de série temporelle interactif afin de tester une stratégie simple de trading algorithmique.
Actualisé 19 sept. 2026  · 15 min lire

Explorer avec l’IA

ChatGPTClaudePerplexity

Dans cet article, je vous montre comment utiliser R pour récupérer la liste des actions proposées sur loyal3, télécharger des historiques depuis Yahoo, puis appliquer une stratégie simple de trading algorithmique. Au passage, vous verrez du web scraping, l’appel d’une API finance et l’utilisation d’un htmlwidget pour créer un graphique de série temporelle interactif.

Dans ce billet, un « algo de trading » est défini comme un ensemble de règles déclenchant des ordres d’achat ou de vente, plutôt qu’un modèle prédictif ou une prévision de série temporelle. C’est la forme la plus simple d’algorithme de trading, mais si vous souhaitez aller plus loin en finance avec R, je vous recommande le cours de DataCamp sur la modélisation d’une stratégie de trading quantitative en R.

Contexte

En 2015, j’ai commencé à investir un peu via loyal3. Leur service est atypique et constitue un excellent point de départ pour débuter en Bourse. Plutôt que de facturer les opérations aux investisseurs, loyal3 fait payer les entreprises pour être listées sur leur plateforme. L’idée est que les personnes qui apprécient le service d’une entreprise achèteront aussi l’action et deviendront ainsi des ambassadeurs de la marque. Autre atout : vous pouvez acheter des fractions d’actions. Vous pouvez donc entrer sur l’action Amazon à 800 $ avec seulement 10 $, puis racheter une fraction de 10 $ chaque fois que vous avez un peu de cash en fin de mois. Bien sûr, il y a des frictions : vous tradez par fenêtres et votre portefeuille est limité à ~70 actions, mais loyal3 reste une façon ludique et peu coûteuse d’explorer l’investissement en actions. Vous pouvez « avoir de la peau dans le jeu » pour à peine 10 $ !

Pour être transparent, je possède des comptes d’épargne retraite et d’investissement classiques, mais j’aime l’interface épurée de l’appli loyal3 et l’absence de frais. Je consulte plus souvent mon petit portefeuille loyal3 que mes fonds communs, simplement parce qu’il est facile et amusant de suivre la performance des titres que j’ai choisis moi‑même.

trading algorithmique R
Les actions disponibles sur www.loyal3.com

Préparer votre espace de travail

Pour commencer, chargez les bibliothèques dans votre environnement. J’utilise quasiment toujours rvest pour le web scraping aujourd’hui. D’autres packages existent, comme RSelenium, mais j’apprécie la simplicité d’exécution de rvest.

Le deuxième package, pbapply, est optionnel : il ajoute simplement une barre de progression aux fonctions apply. Comme vous pouvez aspirer des centaines de pages, une barre de progression aide à estimer le temps restant.

Ensuite, TTR est un package que je viens d’explorer. Il sert à construire des « règles de trading technique ». Même si vous allez découvrir un algo simple ici, TTR permet des calculs plus sophistiqués et mérite d’être appris.

La bibliothèque dygraphs est un wrapper d’une librairie JavaScript de charting rapide et open source. C’est l’un des htmlwidgets qui rendent les graphiques R dynamiques et intégrés à une page HTML plutôt qu’en image statique. Enfin, le package lubridate facilite la manipulation des dates.

library(rvest)
library(pbapply)
library(TTR)
library(dygraphs)
library(lubridate)

Collecte des données

Toutes les actions loyal3 sont listées sur une seule page. Avant de pouvoir récupérer les cours quotidiens individuels pour construire votre algorithme, vous devez d’abord collecter tous les tickers disponibles. Déclarez d’abord stock.list comme une chaîne d’URL. Utilisez ensuite read_html() pour que votre session R ouvre une session Internet et récupère tout le HTML de la page sous forme d’ensemble de nœuds XML. La page CSS comporte un sélecteur d’ID « .company-name ». Utilisez‑le en paramètre de html_nodes() pour ne sélectionner que les données XML associées à ce nœud. Enfin, html_text() permet d’extraire les valeurs textuelles des noms d’entreprises.

stock.list<-'https://www.loyal3.com/stocks'
stocks<-read_html(stock.list)
stocks.names<-html_nodes(stocks,'.company-name')
stocks.names<-html_text(stocks.names)

Pour examiner les actions disponibles sur loyal3, affichez l’objet stocks.names dans votre console. Il renvoie les noms des entreprises sous forme de vecteur de texte.

stocks.names 

Pour rechercher les cours, vous devez d’abord récupérer le symbole (ticker). Sur le site loyal3, vous pouvez cliquer sur la tuile d’une entreprise pour ouvrir une page contenant le ticker et d’autres informations.

Avec html_nodes() appliqué à stocks, vous extrayez tous les nœuds marqués « a ». En HTML, la balise <a> définit un lien hypertexte vers une autre page. Dans cette balise, « href » correspond à l’URL exacte. Ainsi, html_attr() extrait l’URL de TOUS les liens de la page si vous passez « href ».

Après inspection manuelle, j’ai constaté que les 54e à 123e liens de la page correspondent aux pages entreprises dont j’ai besoin pour aspirer le ticker. La dernière ligne utilise paste0() pour concaténer l’URL de base ’http://www.loyal3.com` avec les pages spécifiques, comme « /WALMART ». Par exemple, http://www.loyal3.com/WALMART :

loyal.links<-html_nodes(stocks, "a")
loyal.links<-html_attr(loyal.links, "href")
stock.links<-paste0('http://www.loyal3.com',loyal.links[54:123])

Sur chaque page entreprise, on trouve une description, un dernier cours de clôture et le ticker. Toutes les pages sont structurées de la même manière, donc la fonction personnalisée get.ticker() peut extraire le symbole.

Dans la page d’une entreprise, il y a un tableau nommé « ticker-price ». La fonction va sur la page, identifie le tableau, puis en extrait le texte avec html_text(). Enfin, grâce à sub() et l’expression régulière ^([[:alpha:]]*).* avec \\1, on ne conserve que les caractères alphabétiques. Résultat : tous les caractères spéciaux (comme $) et numériques (comme le cours) sont supprimés. Au fil de la lecture des ~70 pages, la fonction ne retient que le ticker.

 get.ticker<-function(url){
  x<-read_html(url)
  x<-html_node(x,'.ticker-price')
  x<-html_text(x)
  x<-sub("^([[:alpha:]]*).*", "\\1", x)
  return(x)
  } 
page loyal3 pour l’action Alibaba
La page loyal3 d’Alibaba, où le tableau contenant le ticker de l’action, BABA, se trouve sous le texte en gras

Armé de votre fonction, utilisez pblapply() pour l’appliquer à chacun des stock.links correspondant aux pages entreprises. L’objet résultant, stock.tickers, est une liste de tickers, chaque élément correspondant à une entreprise.

stock.tickers<-pblapply(stock.links,get.ticker)

Une façon d’aplatir une liste d’éléments est d’utiliser do.call(). Ici, vous appliquez rbind pour empiler chaque élément en un seul vecteur. Enfin, vous créez un data frame avec le symbole et le nom de l’entreprise.

stock.ticks<-do.call(rbind,stock.tickers)
stock.ticks<-data.frame(symbol=stock.ticks,name=stocks.names)

Pour rester cohérent dans votre analyse, vous pouvez limiter l’historique récupéré pour chaque action. La fonction Sys.Data() stocke une date en année, mois, jour. Utiliser des années en entier est un moyen de soustraire une période précise à l’objet start.date.

start.date<-Sys.Date()
end.date<-Sys.Date()-years(3)

Pour interroger Yahoo Finance, l’objet date doit être converti en chaîne simple sans tirets. La fonction de substitution globale gsub() sur start.date et end.date convertit la classe et enlève les tirets simultanément. Dans gsub(), passez le motif à rechercher, puis la chaîne de remplacement. Ici, le remplacement est une chaîne vide entre guillemets. Le dernier paramètre est l’objet auquel appliquer gsub().

start.date<-gsub('-','', start.date)
end.date<-gsub('-','', end.date)

La fonction getYahooData() du package TTR accepte un symbole et des dates de début et de fin. Elle renvoie un data frame de série temporelle. Chaque ligne est une date et les colonnes incluent les prix « Open », « High », « Low » et « Close ». Comme vous interrogez plusieurs entreprises, utilisez lapply() ou pblapply(). Passez le vecteur de symboles, puis la fonction getYahooData(), puis les dates. Les objets date sont recyclés à chaque application de getYahooData() à un symbole.

 stocks.ts<-pblapply(stock.ticks$symbol,getYahooData,end.date, start.date)

Pour faciliter la navigation dans la liste retournée, stocks.ts, vous pouvez nommer ses éléments. Avec names sur l’objet stocks.ts, affectez comme noms le vecteur initial $symbol.

names(stocks.ts)<-stock.ticks$symbol

Avec de grandes listes, j’aime inspecter l’objet résultant pour vérifier que tout correspond à mes attentes. Maintenant que les éléments sont nommés, vous pouvez les référencer directement. Dans cet exemple, vous examinez les 6 premières lignes pour AMC Entertainment Holdings (AMC). En utilisant head() sur la liste en référant $AMC, vous obtenez un extrait de la série temporelle pour ce titre :

head(stocks.ts$AMC)

Examiner les données boursières

Quand j’écoute les commentateurs financiers, ils se réfèrent souvent aux graphiques. Malgré le trading à haute fréquence et la gestion active pratiqués ailleurs, beaucoup de petits investisseurs utilisent encore les graphiques pour se faire une idée. L’objet de série temporelle peut être rapidement affiché avec plot. Passez la liste en pointant l’élément nommé, par exemple $AMC, puis la colonne à afficher, ici $Close.

plot(stocks.ts$AMZN$Close)
graphique des actions

Ce tracé est statique et peu engageant.

Utilisons une librairie JavaScript pour créer un graphique exploratoire. Dans l’extrait ci‑dessous, vous remarquerez l’opérateur « %>% » ou pipe. Il permet d’écrire un code concis : il transmet un objet à la fonction suivante sans réécrire son nom, contrairement aux exemples précédents.

Ici, vous créez un dygraph pour l’action Twitter, $TWTR, et la colonne à tracer, $Close. Dans dygraph, main ajoute un titre entre guillemets. Grâce au « %>% », l’objet est passé à dyRangeSelector(). Vous pouvez définir une plage de dates par défaut avec c(). L’objet HTML obtenu est une série temporelle dynamique du titre Twitter, avec un sélecteur de dates en bas.

Pensez à changer le ticker dans la liste stocks.ts et le titre du graphique pour afficher une autre action.

dygraph(stocks.ts$TWTR$Close, main = "TWTR Stock Price") %>%
  dyRangeSelector(dateWindow = c("2013-12-18", "2016-12-30"))

dygraph de base pour l’action Twitter
Un dygraph de base pour l’action Twitter

Une stratégie simple : le suivi de tendance

Les traders haute fréquence et hedge funds utilisent des modèles sophistiqués et des approches par règles pour exécuter leurs ordres. Pour en savoir plus, je vous suggère de visiter www.quantopian.com pour des approches avancées. Pour des méthodes plus simples, commencez par cette page sur www.Investopedia.com.

Dans le code ci‑dessous, vous allez visualiser une stratégie de momentum simple. L’idée : calculer les moyennes mobiles à 200 jours et 50 jours du cours d’une action. Les jours où la moyenne à 50 jours est au‑dessus de celle à 200 jours, vous achetez ou conservez votre position. Lorsque la 200 jours dépasse la 50 jours, vous vendez. Cette stratégie est dite de suivi de tendance. La relation positive ou négative entre ces deux moyennes mobiles traduit le momentum du titre.

Le package TTR propose SMA() pour calculer une moyenne mobile simple. Dans l’exemple, vous affichez les 6 premières valeurs des moyennes mobiles 200 et 50 jours de Twitter. SMA() prend la série temporelle d’un titre et une colonne spécifique comme Close (vecteur des cours de clôture de TWTR). Le second paramètre est un entier représentant le nombre d’observations de la moyenne mobile. Sans head(), SMA() renvoie toutes les valeurs.

head(SMA(stocks.ts$TWTR$Close, 200))
head(SMA(stocks.ts$TWTR$Close, 50))

Maintenant que vous avez examiné la fonction de moyenne mobile, il faut l’appliquer aux ~70 actions. stocks.ts est une liste de 70 data frames contenant les données de chaque titre. La quatrième colonne de chaque data frame correspond au cours de clôture que nous allons utiliser pour les moyennes mobiles.

La fonction personnalisée mov.avgs() prend un data frame de titre et calcule ses moyennes mobiles. La première ligne sélectionne les cours de clôture via l’index [,4] pour créer stock.close. Ensuite, la fonction utilise ifelse pour vérifier le nombre de lignes. Si nrow est inférieur à (2*260), la fonction crée un data frame de moyennes mobiles rempli de « NA ».

J’ai choisi ce seuil car il y a environ 250 séances par an : on vérifie ainsi que la série couvre ~2 ans ou plus. Loyal3 peut parfois accéder à des IPO : si le titre est récent, il n’y aura pas assez d’historique pour une moyenne à 200 jours. En revanche, si nrow est supérieur à 2*260, la fonction renvoie un data frame avec les données d’origine et deux nouvelles colonnes pour les moyennes 200 et 50 jours. Avec colnames, je nomme les colonnes. Enfin, complete.cases sert à vérifier la présence de valeurs dans la colonne 200 jours : les lignes incomplètes sont supprimées.

mov.avgs<-function(stock.df){
  stock.close<-stock.df[,4]
  ifelse((nrow(stock.df)<(2*260)),
         x<-data.frame(stock.df, 'NA', 'NA'),
         x<-data.frame(stock.df, SMA(stock.close, 200), SMA(stock.close, 50)))
  colnames(x)<-c(names(stock.df), 'sma_200','sma_50')
  x<-x[complete.cases(x$sma_200),]
  return(x)
  }

Avec cette fonction mov.avgs(), utilisez pblapply() pour ajouter les calculs de moyennes mobiles à chacun des 70 data frames.

stocks.ts<-pblapply(stocks.ts, mov.avgs)

Utilisez le code ci‑dessous pour visualiser les moyennes mobiles d’un titre avec dygraph. À nouveau, le code enchaîne les fonctions avec « %>% ». dygraph() reçoit le data frame stocks.ts$FOX. On indexe par nom de colonnes avec c('sma_200','sma_50'). Cet objet est transmis à dySeries() dans les 2 lignes suivantes. Vous pouvez référencer une colonne par son nom : dySeries() trace une ligne pour « sma_50 » et « sma_200 ». L’objet est encore transmis à dyRangeSelector() pour ajuster la hauteur du sélecteur. Enfin, j’ajoute des zones ombrées pour indiquer les périodes d’achat/conservation, et celles où il aurait fallu vendre ou rester à l’écart selon votre position.

dygraph(stocks.ts$FOX[,c('sma_200','sma_50')],main = 'FOX Moving Averages') %>%
  dySeries('sma_50', label = 'sma 50') %>%
  dySeries('sma_200', label = 'sma 200') %>%
  dyRangeSelector(height = 30) %>%
  dyShading(from = '2016-4-28', to = '2016-7-27', color = '#CCEBD6') %>%
  dyShading(from = '2016-7-28', to = '2016-12-30', color = '#FFE6E6')

Voici le résultat final sous forme de série temporelle interactive.

moyennes mobiles de FOX
Les moyennes mobiles de FOX avec zones ombrées pour achat/conservation versus vente

Conclusion

En tant qu’aspirant trader algorithmique, vous n’avez pas besoin de tracer les 70 actions. L’objectif est plutôt d’exécuter le code chaque jour et d’ajouter un moyen programmatique d’identifier les titres qui respectent la règle : « acheter si la moyenne mobile 50 jours est au‑dessus de la 200 jours ». En regardant le graphique, la zone verte correspond à une période d’achat/conservation de l’action FOX. La zone rouge indique le moment de vendre vos titres et de rester à l’écart.

Comme le graphique est interactif, vous pouvez redimensionner la vue avec le curseur. Selon cette approche d’algo simple, c’est peut‑être le bon moment pour acheter FOX ! Le 30 décembre 2016, la moyenne à 50 jours est passée de 0,01 $ au‑dessus de la 200 jours.

action FOX
Zoom sur la période de l’action FOX

Bien sûr, n’oubliez pas que tout investissement peut perdre de la valeur. Pour en savoir plus sur la finance et le trading algorithmique, consultez les cours de DataCamp ici.

Découvrez aussi notre tutoriel Basic Programming Skills in R.

Sujets
R
Science des données

En savoir plus sur R

Cours

Introduction à R

4 h
3.1M
Maîtrisez les bases de l’analyse de données en R et pratiquez les vecteurs, listes et data frames avec des données réelles.
Afficher les détailsRight Arrow
Commencer Le Cours
Voir plusRight Arrow