Skip to Content
Projets de donnĂ©esSimulateur boursier 📈

Simulateur de marchĂ© boursier 📈

Par Nael Shiab

DerniĂšre mise Ă  jour le

Bienvenue dans ce nouveau projet ! Nous allons récupérer des données historiques du marché boursier et les utiliser pour estimer combien nous aurions gagné ou perdu en investissant dans des entreprises cotées en bourse.

Avant de commencer, assurez-vous d’avoir suivi la leçon Installation du chapitre 1, ainsi que les sections Fondamentaux de TypeScript et BĂątir avec TypeScript. Ce projet est conçu pour vous aider Ă  pratiquer tout ce que nous avons couvert jusqu’à prĂ©sent dans ce cours.

Vous voulez ĂȘtre prĂ©venu quand de nouvelles leçons sont publiĂ©es ? Abonnez-vous Ă  l'infolettre ✉ et donnez une ⭐ au cours sur GitHub pour me garder motivé ! Cliquez ici pour me contacter.

Quelle est la question ?

Il est toujours important d’identifier clairement la question Ă  laquelle nous voulons rĂ©pondre avant de plonger trop vite dans un ocĂ©an de donnĂ©es.

Aujourd’hui, notre question est :

  • Combien aurions-nous gagnĂ© ou perdu en investissant dans une entreprise cotĂ©e en bourse Ă  une date prĂ©cise ?

Pour y répondre, nous devons calculer la différence entre le montant initial et le montant final.

Nous pouvons également identifier trois variables qui influenceront le résultat :

  • L’entreprise choisie
  • Le montant initial investi
  • La date de l’investissement

Avec cela en tĂȘte, commençons !

Configuration

Créez un nouveau dossier vide sur votre ordinateur, ouvrez-le avec VS Code et créez-y un fichier nommé main.ts.

Tapez ce code dans main.ts et enregistrez le fichier :

main.ts
console.log("Hello!");

Configurons maintenant notre projet.

Créez un fichier package.json dans le dossier de votre projet avec ce contenu pour que VS Code sache que nous utiliserons la syntaxe moderne des modules TypeScript :

package.json
{ "type": "module" }

CrĂ©ez ensuite un fichier tsconfig.json dans le mĂȘme dossier pour que TypeScript vĂ©rifie notre code selon ces rĂšgles modernes de modules :

tsconfig.json
{ "compilerOptions": { "module": "nodenext", "types": ["node"], "allowImportingTsExtensions": true, "noEmit": true } }

La derniĂšre chose Ă  faire est d’installer les types de Node.js. Ouvrez le terminal (Command + J sur Mac ou Control + J sur Windows) et exĂ©cutez :

npm install --save-dev @types/node

Exécutez maintenant cette commande dans le terminal :

node --watch main.ts

Cette commande exécute notre code et le relance automatiquement chaque fois que nous enregistrons une modification, pour voir les résultats au fur et à mesure que nous travaillons.

VS Code montrant les fichiers de configuration du projet, l’installation des types de Node et main.ts exĂ©cutĂ© en mode surveillance.

Les données

Yahoo Finance

Pour notre simulateur, nous avons besoin des prix historiques du marchĂ© boursier. L’une des sources les plus courantes de donnĂ©es financiĂšres est Yahoo Finance .

Sur la page d’accueil , vous pouvez rechercher une entreprise cotĂ©e en bourse. Par exemple, recherchez Apple et cliquez sur le rĂ©sultat correspondant.

Une capture d'écran montrant le site Yahoo Finance.

Vous arriverez sur la page de l’action Apple. Ces donnĂ©es sont trĂšs intĂ©ressantes ! Mais comment pouvons-nous les rĂ©cupĂ©rer dans notre script ? đŸ€”

Une capture d'écran montrant le site Yahoo Finance.

Récupération des données

Ne vous inquiĂ©tez pas, j’ai créé une fonction juste pour cela !

Nous allons installer ma librairie libre Journalism Finance  et utiliser la fonction getYahooFinanceData. Elle rĂ©cupĂšre les donnĂ©es de Yahoo Finance sous la forme d’une liste propre d’objets contenant des timestamps et des valeurs.

Mais attention : getYahooFinanceData utilise un point d’accĂšs non documentĂ© de Yahoo Finance et n’est ni affiliĂ©e Ă  Yahoo ni approuvĂ©e par Yahoo. Il en va de mĂȘme pour de nombreuses autres librairies libres que vous pourriez trouver pour rĂ©cupĂ©rer ce type de donnĂ©es. Avant de l’utiliser, consultez les conditions d’utilisation de Yahoo  et les restrictions du fournisseur de donnĂ©es  qui pourraient s’appliquer.

Pour l’instant, arrĂȘtons de surveiller et d’exĂ©cuter main.ts. Cliquez dans le terminal et appuyez sur CTRL + C. Installez ensuite la librairie en exĂ©cutant cette commande dans le terminal :

npm install @nshiab/journalism-finance

La dépendance figure maintenant dans package.json et est installée dans node_modules. npm met aussi à jour package-lock.json, qui enregistre les versions exactes des dépendances.

VS Code montrant Journalism Finance installée avec npm et listée dans package.json.

Nous allons d’abord recueillir les donnĂ©es, puis les utiliser. Pour garder le projet bien organisĂ©, nous placerons les fonctions utilitaires rĂ©utilisables dans leurs propres fichiers. CrĂ©ez un dossier helpers dans votre projet et ajoutez-y getData.ts. Cette fonction rĂ©cupĂ©rera les donnĂ©es d’une entreprise cotĂ©e en bourse.

Dans cette premiĂšre fonction utilitaire, nous importons getYahooFinanceData depuis @nshiab/journalism-finance, nous l’appelons avec les paramĂštres expliquĂ©s ci-dessous, puis nous retournons les donnĂ©es. getData attend un paramĂštre de type chaĂźne de caractĂšres, symbol. Comme la fonction est gĂ©nĂ©rale, nous pourrons la rĂ©utiliser pour n’importe quelle entreprise si nĂ©cessaire.

L’ajout de export default nous permet d’importer la fonction lĂ  oĂč nous en avons besoin, soit dans main.ts dans notre cas.

helpers/getData.ts
import { getYahooFinanceData } from "@nshiab/journalism-finance"; export default async function getData(symbol: string) { const dailyStockData = await getYahooFinanceData( symbol, new Date("1970-01-01"), new Date(), "adjclose", "1d", ); return dailyStockData; }

VS Code montrant helpers/getData.ts important getYahooFinanceData et retournant les données boursiÚres historiques.

Voici les arguments que nous passons Ă  getYahooFinanceData :

  • symbol est le symbole boursier. Nous utiliserons AAPL pour Apple.
  • Les deux dates dĂ©finissent la pĂ©riode. Nous commençons en 1970 et terminons aujourd’hui afin d’obtenir tous les prix disponibles.
  • "adjclose" sĂ©lectionne le prix ajustĂ© de clĂŽture. Celui-ci tient compte d’évĂ©nements comme les fractionnements d’actions et les dividendes, ce qui le rend utile pour estimer le rendement d’un investissement.
  • "1d" demande la valeur Ă  la fin de chaque journĂ©e.

Notez que getYahooFinanceData est asynchrone parce qu’elle rĂ©cupĂšre des donnĂ©es sur Internet. Nous utilisons le mot-clĂ© await pour nous assurer que toutes les donnĂ©es sont reçues avant de poursuivre l’exĂ©cution du script.

💡

En arriĂšre-plan, getYahooFinanceData rĂ©cupĂšre des donnĂ©es depuis une API de Yahoo Finance. Une API, ou Application Programming Interface, permet Ă  des programmes d’échanger des donnĂ©es.

Nous pouvons maintenant mettre à jour main.ts pour importer et appeler notre nouvelle fonction utilitaire, tout en gardant notre code bien organisé.

À la ligne 3, nous crĂ©ons la variable symbol et lui attribuons le symbole boursier d’Apple, AAPL. Nous passons cette variable Ă  getData, qui attend un paramĂštre symbol. LĂ  encore, nous utilisons await pour nous assurer de recevoir toutes les donnĂ©es avant de continuer. À la ligne 6, nous affichons les dix premiers rĂ©sultats sous forme de tableau.

main.ts
import getData from "./helpers/getData.ts"; const symbol = "AAPL"; const dailyStockData = await getData(symbol); console.table(dailyStockData.slice(0, 10));

VS Code montrant main.ts important getData, demandant les données AAPL et affichant les dix premiÚres lignes avec console.table.

Mais avant d’exĂ©cuter ce code, nous devons nous occuper d’une derniĂšre chose.

Mise en cache

Si nous exécutions main.ts maintenant, les données seraient récupérées à nouveau chaque fois que le code est exécuté.

Nous ne voulons pas surcharger les serveurs de Yahoo avec nos requĂȘtes. Nous devons respecter leur infrastructure. Nous ne voulons pas non plus ĂȘtre mis sur une liste noire
 đŸ«Ł Mettons donc les donnĂ©es en cache.

L’idĂ©e est assez simple. La premiĂšre fois que nous rĂ©cupĂ©rons les donnĂ©es, nous les Ă©crivons dans un fichier. Ensuite, chaque fois que le code s’exĂ©cute Ă  nouveau, si le fichier existe, ce qui sera le cas, nous l’utilisons au lieu de rĂ©cupĂ©rer les donnĂ©es une nouvelle fois.

Créez un dossier data dans votre projet pour les données mises en cache.

VS Code montrant le nouveau dossier data Ă  cĂŽtĂ© de helpers et main.ts, prĂȘt Ă  stocker les donnĂ©es boursiĂšres en cache.

Nous allons maintenant mettre Ă  jour getData pour vĂ©rifier si un fichier mis en cache existe. Pour cela, nous utilisons existsSync() du module node:fs, qui retourne true si le fichier existe et false sinon. Nous pouvons ensuite utiliser des branches if et else pour lire les donnĂ©es depuis le fichier s’il existe, ou rĂ©cupĂ©rer de nouvelles donnĂ©es s’il n’existe pas.

helpers/getData.ts
import { getYahooFinanceData } from "@nshiab/journalism-finance"; import { existsSync } from "node:fs"; import { readFile, writeFile } from "node:fs/promises"; export default async function getData(symbol: string) { const path = `./data/${symbol}.json`; let dailyStockData; if (existsSync(path)) { console.log(`=> Cached data found at ${path}. Reading it...`); dailyStockData = JSON.parse(await readFile(path, "utf8")); } else { console.log("=> No cached data found. Fetching it from Yahoo Finance..."); dailyStockData = await getYahooFinanceData( symbol, new Date("1970-01-01"), new Date(), "adjclose", "1d", ); console.log(`=> Data fetched. Writing it to ${path} for the next run...`); await writeFile(path, JSON.stringify(dailyStockData)); } return dailyStockData; }

Voici ce qui se passe lorsque vous exécutez ce code :

  • path contient le symbole boursier pour que chaque entreprise ait son propre fichier cache.
  • existsSync() vĂ©rifie si le fichier existe. Si oui, readFile(path, "utf8") le lit comme du texte et JSON.parse() reconstitue la liste.
  • Sinon, nous rĂ©cupĂ©rons les prix, convertissons la liste en JSON et l’enregistrons avec writeFile().
  • Enfin, la fonction retourne les donnĂ©es, quelle que soit leur source.

Exécutez maintenant main.ts et surveillez les changements :

node --watch main.ts

La premiĂšre fois, le fichier cache n’existe pas. Le bloc else rĂ©cupĂšre les donnĂ©es et Ă©crit AAPL.json dans data.

VS Code montrant la premiĂšre exĂ©cution rĂ©cupĂ©rant les donnĂ©es boursiĂšres d’Apple, les enregistrant dans data/AAPL.json et affichant les premiĂšres lignes dans le terminal.

💡

Vous vous demandez ce que signifie timestamp ? Cet Ă©norme nombre correspond au nombre de millisecondes Ă©coulĂ©es depuis le 1er janvier 1970. C’est ainsi que JavaScript suit les dates et les heures en arriĂšre-plan. Ici, la librairie nous fournit directement le timestamp plutĂŽt qu’une date, mais comme nous le verrons, JavaScript permet de passer facilement des dates aux timestamps et vice versa.

ExĂ©cutez de nouveau main.ts en l’enregistrant (CMD + S sur Mac ou CTRL + S sur PC). Cette fois, la condition est remplie, car Node.js trouve AAPL.json. Le bloc if est exĂ©cutĂ©, tandis que tout ce qui se trouve sous else est ignorĂ©. Nous n’avons pas besoin de rĂ©cupĂ©rer les donnĂ©es Ă  nouveau. Nous les lisons plutĂŽt depuis notre fichier local. C’est plus rapide et cela Ă©vite d’importuner les serveurs de Yahoo avec une autre requĂȘte.

VS Code montrant une exĂ©cution suivante lisant les donnĂ©es boursiĂšres d’Apple en cache dans data/AAPL.json et les affichant dans le terminal.

Vous pouvez conserver des donnĂ©es en cache pour plusieurs entreprises. Par exemple, remplacez AAPL dans la variable symbol par GOOG pour obtenir les prix historiques de l’action d’Alphabet, anciennement Google, puis exĂ©cutez le code.

main.ts
import getData from "./helpers/getData.ts"; const symbol = "GOOG"; const dailyStockData = await getData(symbol); console.table(dailyStockData.slice(0, 10));

Vous verrez qu’un autre fichier, GOOG.json, est créé dans data.

VS Code montrant les données boursiÚres GOOG récupérées depuis Yahoo Finance, enregistrées dans data/GOOG.json et affichées dans le terminal.

Si vous revenez à AAPL, les données sont toujours là. Plus besoin de les récupérer à nouveau !

Et si vous voulez des prix plus récents, supprimez simplement les fichiers dans data et exécutez votre code de nouveau. Facile !

main.ts
import getData from "./helpers/getData.ts"; const symbol = "AAPL"; const dailyStockData = await getData(symbol); console.table(dailyStockData.slice(0, 10));

VS Code montrant le retour au symbole AAPL et la lecture des donnĂ©es boursiĂšres d’Apple depuis le cache existant.

💡

Ici, nous utilisons la mise en cache pour éviter de solliciter trop souvent les serveurs de Yahoo. Mais la mise en cache est aussi trÚs couramment utilisée pour améliorer les performances. Lire un fichier local est beaucoup plus rapide que de récupérer des données sur Internet. Par exemple, un script peut effectuer des calculs complexes qui prennent beaucoup de temps. Au lieu de les répéter à chaque exécution du script, vous pouvez mettre les résultats en cache et les lire directement lors des exécutions suivantes.

Calcul des rendements

Nous avons maintenant tout ce qu’il nous faut pour calculer les rendements !

Créons une autre fonction, calculateFinalAmount, dans helpers. Cette fonction aura besoin de trois paramÚtres :

  • Le montant investi, amount, qui doit ĂȘtre un number
  • La date de l’investissement, startDate, qui est une Date
  • Les donnĂ©es dailyStockData retournĂ©es par getYahooFinanceData, soit une liste d’objets associant un timestamp Ă  une value
helpers/calculateFinalAmount.ts
export default function calculateFinalAmount( amount: number, startDate: Date, dailyStockData: { timestamp: number; value: number }[], ) { console.log("=> Calculating final amount..."); const filteredDailyStockData = dailyStockData.filter((dailyData) => dailyData.timestamp >= startDate.getTime() ); const initialValue = filteredDailyStockData[0].value; const finalValue = filteredDailyStockData[filteredDailyStockData.length - 1] .value; const rateOfReturn = (finalValue - initialValue) / initialValue; return amount + amount * rateOfReturn; }

Voici ce qui se passe lorsque nous appelons cette fonction :

  • La ligne 6 indique dans le terminal que la fonction est appelĂ©e.
  • Les lignes 8 Ă  10 conservent uniquement les donnĂ©es Ă  partir de la date de l’investissement.
  • La ligne 12 rĂ©cupĂšre la valeur initiale de l’action.
  • Les lignes 13 et 14 rĂ©cupĂšrent sa valeur la plus rĂ©cente.
  • La ligne 15 calcule le taux de rendement, qui peut ĂȘtre positif ou nĂ©gatif.
  • La ligne 17 calcule le montant final : le montant initial auquel s’ajoute le montant multipliĂ© par le taux de rendement.

Si nous exécutons notre code maintenant, rien ne se produira. Nous devons encore appeler notre nouvelle fonction dans main.ts.

Nous importons d’abord calculateFinalAmount. Ensuite, nous crĂ©ons les variables amount et startDate, puis nous les passons Ă  la fonction avec dailyStockData. Enfin, nous stockons son rĂ©sultat dans une nouvelle variable nommĂ©e finalAmount.

main.ts
import getData from "./helpers/getData.ts"; import calculateFinalAmount from "./helpers/calculateFinalAmount.ts"; const symbol = "AAPL"; const amount = 1000; const startDate = new Date("2020-01-01"); const dailyStockData = await getData(symbol); const finalAmount = calculateFinalAmount(amount, startDate, dailyStockData); console.log(finalAmount);

Et voici le rĂ©sultat ! Ça fonctionne ! Vous auriez environ 4 764 $ aujourd’hui, en octobre 2026, si vous aviez investi 1 000 $ dans Apple en janvier 2020.

VS Code montrant main.ts appelant calculateFinalAmount et le montant final de l’investissement dans le terminal.

Affichage du résultat

Créons une fonction pour afficher le résultat plus clairement.

Dans helpers, créez une fonction appelée logResult.

Pour rendre le message plus facile Ă  lire, nous formatons startDate avec .toLocaleDateString("en-US"). "en-US" est ce que nous appelons une locale. Elle prĂ©cise que la date doit ĂȘtre formatĂ©e en anglais pour les États-Unis, mais vous pouvez utiliser la locale de votre choix, comme "fr-CA" pour le français au Canada. Nous arrondissons Ă©galement finalAmount avec Math.round().

Nous prĂ©cisons timeZone: "UTC" parce qu’une date sans heure comme "2020-01-01" est interprĂ©tĂ©e en UTC. La date affichĂ©e reste ainsi identique quel que soit votre fuseau horaire.

helpers/logResult.ts
export default function logResult( amount: number, symbol: string, startDate: Date, finalAmount: number, ) { const formattedDate = startDate.toLocaleDateString("en-US", { timeZone: "UTC" }); const roundedAmount = Math.round(finalAmount); console.log( `\nIf you had invested $${amount} in ${symbol} on ${formattedDate}, you would have $${roundedAmount} today.\n`, ); }

Nous pouvons maintenant utiliser cette fonction dans main.ts.

main.ts
import getData from "./helpers/getData.ts"; import calculateFinalAmount from "./helpers/calculateFinalAmount.ts"; import logResult from "./helpers/logResult.ts"; const symbol = "AAPL"; const amount = 1000; const startDate = new Date("2020-01-01"); const dailyStockData = await getData(symbol); const finalAmount = calculateFinalAmount(amount, startDate, dailyStockData); logResult(amount, symbol, startDate, finalAmount);

VS Code montrant main.ts appelant logResult et le rĂ©sultat formatĂ© de l’investissement de 4 764 $ dans le terminal.

Magnifique, n’est-ce pas ? 😍

Un instant


Tout fonctionne bien avec une startDate en janvier 2020
 Mais que se passerait-il si la date de dĂ©but Ă©tait en 1970, avant l’entrĂ©e en bourse d’Apple ?

C’est impossible ! Notre code devrait avertir la personne qui l’utilise.

Remplacez startDate par "1950-01-01" pour faire un test
 Le code retourne un montant, alors qu’il devrait dĂ©clencher une erreur ! đŸ˜±

VS Code montrant une date d’investissement en 1950 et un rĂ©sultat impossible avant l’entrĂ©e en bourse d’Apple.

Écrasons ce bogue ! 🐛

Nous pouvons mettre Ă  jour calculateFinalAmount, qui reçoit dĂ©jĂ  startDate et dailyStockData. Les lignes que nous ajoutons ci-dessous comparent la date de l’investissement au premier prix disponible. Si la date de l’investissement est antĂ©rieure, la fonction dĂ©clenche une erreur accompagnĂ©e d’un message.

helpers/calculateFinalAmount.ts
export default function calculateFinalAmount( amount: number, startDate: Date, dailyStockData: { timestamp: number; value: number }[], ) { console.log("=> Calculating final amount..."); if (startDate.getTime() < dailyStockData[0].timestamp) { throw new Error( "The company was not public at that time. Please choose a later date.", ); } const filteredDailyStockData = dailyStockData.filter((dailyData) => dailyData.timestamp >= startDate.getTime() ); const initialValue = filteredDailyStockData[0].value; const finalValue = filteredDailyStockData[filteredDailyStockData.length - 1] .value; const rateOfReturn = (finalValue - initialValue) / initialValue; return amount + amount * rateOfReturn; }

VS Code montrant calculateFinalAmount dĂ©clenchant une erreur lorsque la date d’investissement prĂ©cĂšde l’entrĂ©e en bourse de l’entreprise.

💡

DĂ©clencher une erreur arrĂȘte le script et fournit, espĂ©rons-le, un message utile. L’erreur indique Ă©galement son origine. Dans la capture d’écran ci-dessus, calculateFinalAmount.ts:9:15 dĂ©signe la ligne 9 et le caractĂšre 15 de ce fichier. Dans VS Code, faites CMD + clic sur cette rĂ©fĂ©rence pour accĂ©der directement Ă  l’erreur, ce qui est trĂšs pratique pour dĂ©boguer.

C’est mieux. Nous ne retournerons plus de rĂ©sultats impossibles ! Vous pouvez maintenant essayer diffĂ©rentes valeurs pour startDate en toute sĂ©curitĂ©.

Mais sommes-nous complĂštement Ă  l’abri ? Que se passe-t-il si vous fournissez une date dans le futur ? đŸ€” Essayez de trouver un moyen de dĂ©clencher une autre erreur dans ce cas. Voici un indice : Date.now() vous donne la date et l’heure actuelles sous la forme d’un nombre de millisecondes.

Conclusion

FĂ©licitations ! Vous avez appris beaucoup de choses dans ce projet. Nous avons utilisĂ© une librairie pour rĂ©cupĂ©rer des donnĂ©es propres, nous les avons mises en cache localement et nous avons calculĂ© le rendement d’un montant investi Ă  une date prĂ©cise. Ce n’est pas rien !

Vous pouvez maintenant continuer Ă  expĂ©rimenter avec ce script. Recherchez d’autres entreprises sur le site de Yahoo et copiez-collez leurs symboles. Essayez diffĂ©rents montants et diffĂ©rentes dates d’investissement !

Vous pouvez aussi modifier le code pour ajouter d’autres fonctionnalitĂ©s. Voici quelques idĂ©es :

  • Comparer les rendements de plusieurs entreprises
  • Investir dans plusieurs entreprises Ă  la fois
  • Acheter et vendre des actions Ă  diffĂ©rentes dates

Amusez-vous ! 💃đŸ•ș

Vous avez aimé ? Vous voulez ĂȘtre prĂ©venu quand de nouvelles leçons sont publiĂ©es ? Abonnez-vous Ă  l'infolettre ✉ et donnez une ⭐ au cours sur GitHub pour me garder motivé ! Contactez-moi si vous avez des questions.