import streamlit as st import pandas as pd import yfinance as yf import plotly.express as px import os from datetime import datetime, timedelta # ✅ Ceci doit être le premier appel Streamlit st.set_page_config(layout="wide", page_title="📈 Euronext Growth - Analyse Interactive") # --- Constantes #CACHE_FILE = "cac40_data.json" CACHE_FILE = os.path.join("/tmp", "euronext_growth_data.json") CACHE_DURATION_HOURS = 1 #TICKERS = [ # "ALNEV.PA", "ALSRS.PA", "ALNOV.PA", "ALTD.PA", "ALTBG.PA", "ALBOO.PA", "ALNRG.PA", "ALHG.PA", # "ALSPW.PA", "ALCBI.PA", "ALTAO.PA", "ALARF.PA", "ALADO.PA", "ALAFY.PA", "ALAGP.PA", "ALGR.PA", # "ALCHI.PA" #] TICKERS = [ "ALNEV.PA", "ALSRS.PA", "ALNOV.PA", "ALTD.PA", "ALTBG.PA", "ALBOO.PA", "ALNRG.PA", "ALHG.PA", "ALSPW.PA", "ALCBI.PA", "ALTAO.PA", "ALARF.PA", "ALADO.PA" ] # --- Fonctions cache / data def is_cache_valid(path, duration_hours): if not os.path.exists(path): return False mtime = datetime.fromtimestamp(os.path.getmtime(path)) return datetime.now() - mtime < timedelta(hours=duration_hours) def load_cached_data(path): return pd.read_json(path) def save_data_to_cache(df, path): df.to_json(path, orient="records", indent=2) def fetch_cac40_data(): data = [] for ticker in TICKERS: stock = yf.Ticker(ticker) info = stock.info try: data.append({ "Name": info.get("shortName", ticker), "Price Change (%)": round(info.get("regularMarketChangePercent", 0), 2), "Volume": info.get("regularMarketVolume", 0), "Nb shares": info.get("sharesOutstanding", 0), "Price": round(info.get("regularMarketPrice", 0), 2), "Sector": info.get("industry", "N/A"), "Effectif": info.get("fullTimeEmployees", 0) }) except: continue return pd.DataFrame(data) def get_data(): if is_cache_valid(CACHE_FILE, CACHE_DURATION_HOURS): return load_cached_data(CACHE_FILE) else: df = fetch_cac40_data() save_data_to_cache(df, CACHE_FILE) return df # --- Streamlit UI st.title("📈 Euronext Growth : Capitalisations, secteurs et variations en un coup d'œil") st.markdown("Affichage des sociétés du CAC 40 avec variation de prix et capitalisation boursière.") df = get_data() df["Market Cap (B eur)"] = round(df["Nb shares"] * df["Price"] / 1e9, 2) df["return_ratio_text_info"] = df["Price Change (%)"].apply(lambda x: f"{x:+.2f}") df["Root"] = "📊 Euronext Growth" fig = px.treemap( df, path=["Root", "Sector", "Name"], values="Market Cap (B eur)", color="Price Change (%)", color_continuous_scale=px.colors.diverging.RdYlGn, color_continuous_midpoint=0, custom_data=[ "Price", "return_ratio_text_info", "Volume", "Nb shares", "Market Cap (B eur)", "Sector", "Effectif" ], width=1200, height=700 ) fig.update_traces( root_color="#f0f0f0", textposition="middle center", texttemplate="%{label}
%{customdata[1]}%", hovertemplate="%{label}
" + "Secteur : %{customdata[5]}
" + "Cours : %{customdata[0]:.2f} €
" + "Variation : %{customdata[1]}%
" + "Volume : %{customdata[2]:,}
" + "Capitalisation : %{customdata[4]:.2f} Mds €
" + "Effectif : %{customdata[6]:,}" ) st.plotly_chart(fig, use_container_width=True)