Last observation: 14 sept. 2026 (N = 456)
First observation: 8 janv. 1985 (N = 81)
Last data update: 15 sept. 2026, 06:31
Last compile: 15 sept. 2026, 06:45
stocks_FRA réunit l’historique quotidien (OHLCV, source investing.com) de 749 actions de la place de Paris, dont les plus anciennes remontent à 1985.
Cours rebasés à 100 début 2000, échelle logarithmique : une même pente = une même performance annualisée. L’écart entre le luxe (LVMH, Hermès, Kering) et le reste de la cote résume deux décennies de Bourse parisienne.
sel <- tribble(
~symbol, ~lab,
"LVMH", "LVMH", "HRMS", "Hermès", "OREP", "L'Oréal",
"PRTP", "Kering", "AIRP", "Air Liquide", "SGEF", "Vinci",
"SASY", "Sanofi", "TOTF", "TotalEnergies","BNPP", "BNP Paribas")
stocks_FRA |>
inner_join(sel, by = "symbol") |>
deglitch() |>
filter(Date >= as.Date("2000-01-01")) |>
group_by(lab) |> arrange(Date) |>
mutate(y = 100 * Close / first(Close)) |> ungroup() |>
line_named("Cours rebasé (base 100 = janv. 2000)")
Rendement annualisé (hors dividendes) des valeurs cotées depuis 2010 — annualisé pour comparer sur un même axe des multiplications par 200 et des quasi-faillites (Rallye, Casino, EuropaCorp…).
tr <- total_return(stocks_FRA, "2010-01-01") |>
left_join(stocks_FRA_var |> select(symbol, name), by = "symbol") |>
mutate(name = coalesce(name, symbol),
yrs = pmax(as.numeric(to - from) / 365.25, 1),
cagr = ifelse(ret <= -0.999, -1, (1 + ret)^(1 / yrs) - 1)) |>
filter(!is.na(cagr))
bind_rows(slice_max(tr, cagr, n = 18), slice_min(tr, cagr, n = 18)) |>
mutate(name = fct_reorder(name, cagr),
col = ifelse(cagr >= 0, "#2ca02c", "#d62728")) |>
ggplot(aes(cagr, name, fill = col)) +
geom_col(width = 0.72) +
geom_vline(xintercept = 0, colour = "grey40") +
geom_text(aes(label = scales::percent(cagr, accuracy = 1),
hjust = ifelse(cagr >= 0, -0.2, 1.2)),
size = 2.7, colour = "grey30") +
scale_fill_identity() +
scale_x_continuous(labels = scales::percent,
expand = expansion(mult = c(0.14, 0.14))) +
theme_minimal() + xlab("Rendement annualisé depuis 2010") + ylab("")
Indice CAC 40 (hors dividendes), échelle logarithmique depuis 1988.
indices_FRA |>
filter(symbol == "FCHI", !is.na(Close), Close > 0) |>
ggplot(aes(Date, Close)) +
geom_line(colour = "#1f77b4", linewidth = 0.5) +
scale_x_date(breaks = seq(1985, 2100, 5) |> paste0("-01-01") |> as.Date(),
labels = date_format("%Y")) +
scale_y_log10(breaks = c(1000, 2000, 3000, 4000, 5000, 6000, 8000)) +
theme_minimal() + xlab("") + ylab("CAC 40 (points, échelle log)")
Pour chaque valeur cotée depuis au moins 2005, rendement annualisé et bêta (sensibilité au CAC 40), estimés sur les variations mensuelles. La droite pointillée est l’ajustement linéaire — la « Security Market Line » empirique.
mkt <- indices_FRA |> filter(symbol == "FCHI") |>
mutate(ym = floor_date(Date, "month")) |>
group_by(ym) |> slice_max(Date, n = 1) |> ungroup() |>
transmute(ym, mkt = Close)
monthly <- stocks_FRA |>
deglitch() |>
transmute(symbol, Date, px = Close) |>
filter(!is.na(px), px > 0) |>
mutate(ym = floor_date(Date, "month")) |>
group_by(symbol, ym) |> slice_max(Date, n = 1) |> ungroup() |>
left_join(mkt, by = "ym") |>
filter(!is.na(mkt)) |>
arrange(symbol, ym) |>
group_by(symbol) |>
mutate(r = px / lag(px) - 1, rm = mkt / lag(mkt) - 1) |>
filter(!is.na(r), !is.na(rm)) |>
filter(n() >= 240, min(ym) <= as.Date("2005-01-01")) |>
summarise(beta = cov(r, rm) / var(rm),
ann = (1 + mean(r))^12 - 1, .groups = "drop") |>
left_join(stocks_FRA_var |> select(symbol, name), by = "symbol") |>
mutate(name = coalesce(name, symbol)) |>
filter(beta > 0, beta < 2.5, ann > -0.3, ann < 0.5)
big <- c("LVMH", "HRMS", "OREP", "SASY", "TOTF", "AIRP", "SCHN", "BNPP", "AXAF",
"SGEF", "PRTP", "SAF", "AIR", "RENA", "SGEF", "STM", "MICP", "DANO",
"ORAN", "PUBP", "LEGD", "CAPP", "TCFP", "PERP", "CARR", "VIE", "DAST",
"SOGN", "ACAP", "EDEN", "ML")
lab <- monthly |> filter(symbol %in% big)
ggplot(monthly, aes(beta, ann)) +
geom_hline(yintercept = 0, colour = "grey80") +
geom_smooth(method = "lm", formula = y ~ x, linetype = 2,
colour = "#d62728", se = FALSE) +
geom_point(colour = "grey72", size = 1.4) +
geom_point(data = lab, colour = "#1f77b4", size = 2.2) +
ggrepel::geom_text_repel(data = lab, aes(label = name), size = 3,
colour = "grey20", segment.colour = "grey75",
max.overlaps = 20, min.segment.length = 0) +
scale_y_continuous(labels = scales::percent) +
theme_minimal() +
xlab("Bêta (sensibilité au CAC 40)") +
ylab("Rendement annualisé (variations mensuelles)")