Blog de développement

K-Bis et Avis de Situation INSEE

Dernière Modification le :
2000-01-01

...

Historique CAC40: ABC-Bourse

J'ai acheté un historique sur ABC Bourse en prenant le format le plus proche de .CSV classique: Télécharger → Après paiement, on obtiens un ZIP (CotationsMS.zip). On y trouve un fichier indicesfr.asc. Il suffit de changer l'extension en .csv et de nettoyer un peu avec le génial QuickSilver QSV.

 
"c:\...\qsv.exe" behead --flexible   "E:\...\indicesfr.csv"  |  "c:\...\qsv.exe"  select 1-6 -n -o "E:\...\indicesfr_beheaded_selected.csv"
"C:\...\qsv.exe" partition 1 --drop -n --filename "{}.csv" "E:\...\Par_Indice" "E:\...\indicesfr_beheaded_selected.csv"
"c:\...\qsv.exe"  select 1 -n "E:\...\indicesfr_beheaded_selected.csv"  |  "c:\...\qsv.exe"  sort 1 -n --unique -o "E:\...\code_ABC.csv"

Dans un pipe, on coupe les headers, la colonne volumes, et on partitionne pour récupérer les fichiers par indice. Chaque indice est réferencé par son code ABC (ou ISIN?) Pour faire la table code <--> ticker (par exemple FR0003500008 <--> PX1, sachant que PX1, c'est le CAC40...), on fait un petit script pour lancer la recherche sur ABC Bourse et récupérer le ticker. J'ai mis la table dans le ZIP de ressources.

base_search_url = "https://www.abcbourse.com/marches/symbol_retrieve/"
base_cotation_url = "https://www.abcbourse.com/cotation/"
search_url = f"{base_search_url}{code}"
headers = {'User-Agent': ('Mozilla/5.0 (Windows NT 10.0; Win64; x64) ' 'AppleWebKit/537.36 (KHTML, like Gecko) ' 'Chrome/58.0.3029.110 Safari/537.3')}
try:
    response = requests.get(search_url, headers=headers, allow_redirects=True)
    if response.status_code == 200:
        final_url = response.url
        if final_url.startswith(base_cotation_url):
            ticker = final_url[len(base_cotation_url):]
            return ticker
        else:
            # Redirection vers une page d'erreur ou inattendue
            return None

Ce fichier donne l'historique de 1969 (reconstruit, car PX1 CAC40 n'existait pas encore) jusqu'au jour de l'achat. Voici un exemple au tournant du siècle:


991228,5901.41,5901.41,5801.18,5827.08
991229,5856.10,5879.82,5814.80,5837.75
991230,5882.63,5979.54,5858.29,5958.32
000103,6024.38,6102.12,5901.77,5917.37
000104,5922.23,5925.07,5657.20,5672.02
000105,5521.83,5589.50,5461.59,5479.70

Le 19 des années 19XX et le 20 des années 20XX a été tronqué: on le remet et l'historique journalier pèse 500 k. Le dossier est nommé PX1 (à la différence du dossier glissant Euronext)

Historique CAC40, récent, glissant: Euronext

Pour les valeurs récents et mises à jours, on utilise la série historique (courte, 2 ans, gratuite) d'Euronext: En mode manuel, on va sur la page d'Euronext Télécharger →. Elle offre des choix de format : MS Excel (.xls), .csv, .txt, de séparateur décimal (point ou virgule), de date (dd/mm/yy ou mm/dd/yy) Le téléchargement est fait par une ressource AJAX dont la syntaxe est :

https://live.euronext.com/en/ajax/AwlHistoricalPrice/getFullDownloadAjax/FR0003500008-XPAR?format=csv&decimal_separator=.&date_form=d%2Fm%2FY&op=

On intègre une fonction de téléchargement dans un script quotidien de mise à jour des annuaires...


def telecharger_csv_euronext_historique():
    url = "https://live.euronext.com/en/ajax/AwlHistoricalPrice/getFullDownloadAjax/FR0003500008-XPAR?format=csv&decimal_separator=.&date_form=d%2Fm%2FY&op="
    datestamp = date_aujourd_hui # Date seulement, sans heure
    nom_fichier = f"CAC40_historical_price_{datestamp}.csv"
    chemin_fichier = os.path.join(dossier_csv_euronext_raw, nom_fichier)
    # Vérifier si le fichier de destination existe déjà
    if os.path.exists(chemin_fichier):
        log_and_print(f"Fichier déjà existant, téléchargement ignoré : {chemin_fichier}")
        return
        
    else:
        try:
            log_and_print(f"CSV historique CAC40 à télécharger sous '{chemin_fichier}'.")
            response = session.get(url, timeout=(10, 60))
            response.raise_for_status()
            with open(chemin_fichier, 'wb') as fichier:
                fichier.write(response.content)
            #log_and_print(f"Page pour {identifier_name} : {identifier_value} téléchargée avec succès sous '{chemin_fichier}'.")
        except requests.exceptions.Timeout:
            log_and_print(f"Timeout lors du téléchargement pour {url}. Tentative avec cURL.")
            telecharger_un_fichier_avec_curl(url, chemin_fichier)
        except requests.exceptions.HTTPError as http_err:
            log_and_print(f"Erreur HTTP lors du téléchargement pour {url} : {http_err}. Tentative avec cURL.")
            telecharger_un_fichier_avec_curl(url, chemin_fichier)
        except requests.exceptions.RequestException as err:
            log_and_print(f"Erreur lors du téléchargement pour {url} : {err}. Tentative avec cURL.")
            telecharger_un_fichier_avec_curl(url, chemin_fichier)
        except Exception as e:
            log_and_print(f"Erreur inattendue lors du téléchargement pour {url} : {e}. Tentative avec cURL.")
            telecharger_page_with_curl(base_url, identifier_name, identifier_value, chemin_fichier)

Le fichier téléchargé depuis Euronext a des entêtes à retirer. Les colonnes "Last" et "Close" sont redondantes; "Number of Trades" et "Turnover" ne nous intéressent pas dans un premier temps.


Historical Data								
From 17/01/2025 to 23/01/2023								
FR0003500008								
Date	Open	High	Low	Last	Close	Number of Shares	Number of Trades	Turnover
17/01/2025	7685.04	7732.32	7667.85	7709.75	7709.75	'0	'0	'0
16/01/2025	7591.35	7634.74	7567.67	7634.74	7634.74	'0	'0	'4599038405
15/01/2025	7447.39	7514.91	7415.52	7474.59	7474.59	'0	'0	'4382236287
14/01/2025	7481.95	7499.77	7423.49	7423.67	7423.67	'0	'0	'3485910251
13/01/2025	7409.56	7424.51	7353.05	7408.64	7408.64	'0	'0	'2795280068
10/01/2025	7495.21	7521.22	7417.59	7431.04	7431.04	'0	'0	'3285496659

Par un script en mode lecture du texte ligne à ligne, on nettoie, on met la date au format ISO simplifié (YYYYMMDD) on change le nom de "CAC40_historical_price_" en "CAC40_historique_prix.csv". Le cumulatif est constitué en ajoutant les nouvelles lignes à un fichier historique total (ce qui oblige à une gestion des dates) et/ou avec un fichier Year-to-date (ex. 2025) qui pèsera 20k. Je mets les années 2023, 2024, etc. dans le ZIP de ressources.

https://polygon.io/landing/historical-intraday-stock-data?utm_term=historical%20trading%20data&utm_campaign=Stocks+-+INT-+DynamicPages&utm_source=adwords&utm_medium=ppc&hsa_acc=4299129556&hsa_cam=13075782420&hsa_grp=175202528807&hsa_ad=724077607817&hsa_src=g&hsa_tgt=kwd-365568505877&hsa_kw=historical%20trading%20data&hsa_mt=p&hsa_net=adwords&hsa_ver=3&gad_source=1&gclid=CjwKCAiAyJS7BhBiEiwAyS9uNWS48esAhCplKNVaqRUahSib_-8Z0RIMPWUPyF9wKyQucmCMMKjFzRoCZgcQAvD_BwE

Investing.com offre une alternative, mais il faut être inscrit:
https://fr.investing.com/indices/france-40-historical-data

Ce wrapper python
https://github.com/ig-python/trading-ig
indique que: Using the IG APIs you can get live and historical data, automate your trades, or create apps

https://live.euronext.com/en/ajax/related-instruments-block-content/indices/FR0003500008-XPAR/indices2

Ressources alternatives

https://www.kaggle.com/datasets/bryanb/cac40-stocks-dataset

https://www.kaggle.com/datasets/pavankrishnanarne/global-stock-market-2008-present

>

Historiques Intraday CAC40 et ses valeurs

Bien sûr on a tout cela à lécran avec ProRealTime (je suis abonné avec en outre l'option temps réel), mais pour travailler en Python, autant avoir une série bien clean. J'ai acheté celle d'ABC-Bourse: Intraday historique et pris l'abonnement pour le recevoir quotiennement.

Da

XXX

XXX

La.

Le

XXX

					    
XXX