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)