1 Introduction Théorique : Le MEDAF (CAPM)

Modèle : Le Modèle d’Évaluation des Actifs Financiers (MEDAF, ou Capital Asset Pricing Model — CAPM) est le cadre de référence en finance de marché pour lier le rendement espéré d’un actif risqué à son exposition au risque systématique.

1.1 Formulation du Modèle

La relation fondamentale du CAPM s’écrit :

\[\boxed{E(R_i) - R_f \;=\; \alpha_i + \beta_i \,\bigl[E(R_m) - R_f\bigr] + \varepsilon_i}\]

où les termes sont définis comme suit :

Paramètre Notation Interprétation financière
Prime de risque de l’actif \(E(R_i) - R_f\) Rendement excédentaire attendu
Ordonnée à l’origine \(\alpha_i\) Alpha de Jensen — performance anormale
Coefficient de sensibilité \(\beta_i\) Exposition au risque systématique
Prime de marché \(E(R_m) - R_f\) Rendement excédentaire du marché
Terme d’erreur \(\varepsilon_i \sim \mathcal{N}(0,\sigma^2)\) Risque idiosyncratique non capturé

1.2 Hypothèses Structurelles

Le modèle repose sur les hypothèses classiques de la régression linéaire (Gauss-Markov) :

  1. Linéarité : \(E(Y \mid X) = \beta_0 + \beta_1 X\)
  2. Exogénéité stricte : \(E(\varepsilon_i \mid X) = 0\)
  3. Homoscédasticité : \(\text{Var}(\varepsilon_i) = \sigma^2 \; \forall i\)
  4. Absence d’autocorrélation : \(\text{Cov}(\varepsilon_i, \varepsilon_j) = 0, \; i \neq j\)
  5. Normalité : \(\varepsilon_i \sim \mathcal{N}(0, \sigma^2)\)

2 Données : Exploration et Description

2.1 Chargement et Visualisation

# Données : primes de risque de l'actif (y) vs. prime de marché (x)
x <- c(-2, -1.5, -0.5, 0, 0.5, 1, 1.5, 2, 2.5, 3)
y <- c(-3.1, -2, -0.8, 0.2, 0.9, 1.4, 2, 2.6, 3.1, 3.8)
n <- length(x)

df <- tibble(
  `Prime Marché (x)` = x,
  `Prime Actif (y)`  = y,
  Observation        = 1:n
)
df %>%
  kable(
    caption   = "Tableau 1 — Données de régression CAPM",
    align     = c("c", "c", "c"),
    digits    = 2,
    booktabs  = TRUE
  ) %>%
  kable_styling(
    bootstrap_options = c("striped", "hover", "condensed", "responsive"),
    full_width        = FALSE,
    position          = "center",
    font_size         = 13
  ) %>%
  row_spec(0, bold = TRUE, color = "white", background = "#0d3b66") %>%
  column_spec(1:2, bold = FALSE, color = "#1a1a2e")
Tableau 1 — Données de régression CAPM
Prime Marché (x) Prime Actif (y) Observation
-2.0 -3.1 1
-1.5 -2.0 2
-0.5 -0.8 3
0.0 0.2 4
0.5 0.9 5
1.0 1.4 6
1.5 2.0 7
2.0 2.6 8
2.5 3.1 9
3.0 3.8 10

2.2 Statistiques Descriptives

stats_df <- tibble(
  Statistique  = c("N", "Moyenne", "Médiane", "Écart-type", "Min", "Max", "Asymétrie"),
  `Prime Marché (x)` = c(
    n, mean(x), median(x), sd(x), min(x), max(x),
    (mean(x) - median(x)) / sd(x)
  ),
  `Prime Actif (y)` = c(
    n, mean(y), median(y), sd(y), min(y), max(y),
    (mean(y) - median(y)) / sd(y)
  )
)

stats_df %>%
  kable(
    caption  = "Tableau 2 — Statistiques descriptives",
    digits   = 4,
    booktabs = TRUE
  ) %>%
  kable_styling(
    bootstrap_options = c("striped", "hover", "condensed"),
    full_width        = FALSE,
    position          = "center",
    font_size         = 13
  ) %>%
  row_spec(0, bold = TRUE, color = "white", background = "#0d3b66")
Tableau 2 — Statistiques descriptives
Statistique Prime Marché (x) Prime Actif (y)
N 10.0000 10.0000
Moyenne 0.6500 0.8100
Médiane 0.7500 1.1500
Écart-type 1.6675 2.2437
Min -2.0000 -3.1000
Max 3.0000 3.8000
Asymétrie -0.0600 -0.1515

3 Modélisation et Estimation des Paramètres

3.1 Estimateurs des Moindres Carrés Ordinaires (MCO)

Les estimateurs MCO sont obtenus par minimisation de la somme des carrés des résidus :

\[\hat{\beta}_1 = \frac{\sum_{i=1}^{n}(x_i - \bar{x})(y_i - \bar{y})}{\sum_{i=1}^{n}(x_i - \bar{x})^2} = \frac{S_{xy}}{S_{xx}}\]

\[\hat{\beta}_0 = \bar{y} - \hat{\beta}_1 \bar{x}\]

# ── Calcul manuel des estimateurs MCO ────────────────────────────────
x_bar <- mean(x);  y_bar <- mean(y)
Sxx   <- sum((x - x_bar)^2)
Sxy   <- sum((x - x_bar) * (y - y_bar))
Syy   <- sum((y - y_bar)^2)

beta1_hat <- Sxy / Sxx                    # Bêta (pente)
beta0_hat <- y_bar - beta1_hat * x_bar   # Alpha (intercept)

cat(sprintf("α̂  (Intercept / Jensen Alpha) : %.6f\n", beta0_hat))
#> α̂  (Intercept / Jensen Alpha) : -0.061039
cat(sprintf("β̂  (Market Beta)              : %.6f\n", beta1_hat))
#> β̂  (Market Beta)              : 1.340060

3.2 Ajustement via lm() et Synthèse

model   <- lm(y ~ x)
tidy_m  <- tidy(model, conf.int = TRUE, conf.level = 0.95)
glance_m <- glance(model)
tidy_m %>%
  mutate(
    term      = c("α̂ (Intercept)", "β̂ (Market Beta)"),
    across(where(is.numeric), ~round(.x, 6))
  ) %>%
  rename(
    Paramètre   = term,
    Estimé      = estimate,
    `Ér. Std`   = std.error,
    `t-stat`    = statistic,
    `p-value`   = p.value,
    `IC 2.5%`   = conf.low,
    `IC 97.5%`  = conf.high
  ) %>%
  kable(
    caption  = "Tableau 3 — Estimateurs MCO et tests de Student",
    booktabs = TRUE
  ) %>%
  kable_styling(
    bootstrap_options = c("striped", "hover", "condensed"),
    full_width        = FALSE,
    font_size         = 13
  ) %>%
  row_spec(0, bold = TRUE, color = "white", background = "#0d3b66") %>%
  row_spec(2, bold = TRUE, background = "#eaf7ea")   # Bêta mis en évidence
Tableau 3 — Estimateurs MCO et tests de Student
Paramètre Estimé Ér. Std t-stat p-value IC 2.5% IC 97.5%
α̂ (Intercept)
-0.06103

4 Tests d’Hypothèses et Inférence Statistique

4.1 Test de Student — Significativité des Coefficients

Hypothèse : \(H_0 : \beta_j = 0\) contre \(H_1 : \beta_j \neq 0\). La statistique de test est : \[t_j = \frac{\hat{\beta}_j - 0}{\widehat{\text{se}}(\hat{\beta}_j)} \;\sim\; t_{n-2} \text{ sous } H_0\]

alpha_level <- 0.05
t_crit      <- qt(1 - alpha_level / 2, df = n - 2)

tidy_m %>%
  mutate(
    Paramètre   = c("α̂", "β̂"),
    `t critique (α=5%)` = round(t_crit, 4),
    Décision    = ifelse(abs(statistic) > t_crit,
                         "✅ Rejet H₀ — Significatif",
                         "❌ Non rejet H₀"),
    `p-value`   = round(p.value, 6),
    across(c(estimate, statistic), ~round(.x, 6))
  ) %>%
  select(Paramètre, estimate, statistic, `t critique (α=5%)`, `p-value`, Décision) %>%
  rename(Estimé = estimate, `t-stat` = statistic) %>%
  kable(caption = "Tableau 4 — Test de Student (bilatéral, α = 5%)", booktabs = TRUE) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE,
                font_size = 13) %>%
  row_spec(0, bold = TRUE, color = "white", background = "#0d3b66")
Tableau 4 — Test de Student (bilatéral, α = 5%)
Paramètre Estimé t-stat t critique (α=5%) p-value Décision
α̂
-0.06103

4.2 Analyse de la Variance (ANOVA)

La décomposition de la variance totale s’écrit :

\[\underbrace{SCT}_{=\,S_{yy}} \;=\; \underbrace{SCE}_{\hat{\beta}_1^2 \cdot S_{xx}} \;+\; \underbrace{SCR}_{SCT - SCE}\]

anova_obj <- anova(model)

SCE   <- beta1_hat^2 * Sxx
SCR   <- Syy - SCE
SCT   <- Syy
MSE   <- SCE / 1
MSR   <- SCR / (n - 2)
F_stat <- MSE / MSR
p_F   <- pf(F_stat, 1, n - 2, lower.tail = FALSE)

anova_df <- tibble(
  Source          = c("Régression (SCE)", "Résidus (SCR)", "Total (SCT)"),
  `Degrés Liberté` = c(1L, n - 2L, n - 1L),
  `Somme Carrés`  = round(c(SCE, SCR, SCT), 6),
  `Carré Moyen`   = round(c(MSE, MSR, NA), 6),
  `F-stat`        = c(round(F_stat, 4), NA, NA),
  `p-value`       = c(format(p_F, scientific = TRUE, digits = 4), NA, NA)
)

anova_df %>%
  kable(caption = "Tableau 5 — Table ANOVA de la régression", booktabs = TRUE,
        na.rm = TRUE) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE,
                font_size = 13) %>%
  row_spec(0, bold = TRUE, color = "white", background = "#0d3b66") %>%
  row_spec(3, bold = TRUE, background = "#eef2f7")
Tableau 5 — Table ANOVA de la régression
Source Degrés Liberté Somme Carrés Carré Moyen F-stat p-value
Régression (SCE) 1 44.93891 44.938910 971.4161 1.221e-09
Résidus (SCR) 8 0.37009 0.046261 NA NA
Total (SCT) 9 45.30900 NA NA NA

4.3 Coefficient de Détermination \(R^2\)

R2       <- SCE / SCT
R2_adj   <- 1 - (SCR / (n - 2)) / (SCT / (n - 1))
sigma_hat <- sqrt(SCR / (n - 2))

tibble(
  Métrique        = c("R²", "R² ajusté", "σ̂ (Erreur std résiduelle)"),
  Valeur          = round(c(R2, R2_adj, sigma_hat), 6),
  Interprétation  = c(
    paste0(round(R2 * 100, 2), "% de la variance de y expliquée par x"),
    "Penalisé par le nombre de paramètres",
    "Dispersion moyenne des résidus autour de la droite"
  )
) %>%
  kable(caption = "Tableau 6 — Qualité d'ajustement du modèle", booktabs = TRUE) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE,
                font_size = 13) %>%
  row_spec(0, bold = TRUE, color = "white", background = "#0d3b66") %>%
  row_spec(1, bold = TRUE, background = "#eaf7ea")
Tableau 6 — Qualité d’ajustement du modèle
Métrique Valeur Interprétation
0.991832 99.18% de la variance de y expliquée par x
R² ajusté 0.990811 Penalisé par le nombre de paramètres
σ̂ (Erreur std résiduelle)
0.21508

Interprétation : Un \(R^2 = 0.9918\) signifie que 99.18% de la variance du rendement excédentaire de l’actif est expliquée par la prime de risque de marché. Ce niveau élevé confirme la robustesse du modèle CAPM sur cet échantillon.


5 Visualisation : Droite de Régression

5.1 Graphique Interactif (plotly)

y_hat  <- fitted(model)
resids <- residuals(model)

p_gg <- ggplot(df, aes(x = `Prime Marché (x)`, y = `Prime Actif (y)`)) +
  geom_point(
    aes(text = paste0(
      "Obs. ", Observation, "<br>",
      "x = ", `Prime Marché (x)`, "<br>",
      "y = ", `Prime Actif (y)`, "<br>",
      "ŷ = ", round(y_hat, 3), "<br>",
      "ε = ", round(resids, 3)
    )),
    size = 3.5, colour = "#e63946", shape = 19
  ) +
  geom_smooth(
    method  = "lm", formula = y ~ x,
    se      = TRUE, colour  = "#0d3b66",
    fill    = "#a8c8e8", alpha = 0.25, linewidth = 1.1
  ) +
  geom_hline(yintercept = 0, linetype = "dashed", colour = "#6c757d", linewidth = 0.5) +
  geom_vline(xintercept = 0, linetype = "dashed", colour = "#6c757d", linewidth = 0.5) +
  annotate(
    "label",
    x     = min(x) + 0.3,
    y     = max(y) - 0.3,
    label = sprintf("ŷ = %.4f + %.4f·x\nR² = %.4f", beta0_hat, beta1_hat, R2),
    size  = 3.5, colour = "#0d3b66", fill = "white",
    label.padding = unit(0.4, "lines"), label.r = unit(0.3, "lines"),
    hjust = 0, fontface = "italic"
  ) +
  labs(
    title    = "Droite de Régression MCO — Modèle CAPM",
    subtitle = sprintf("α̂ = %.4f  |  β̂ = %.4f  |  R² = %.4f", beta0_hat, beta1_hat, R2),
    x        = "Prime de Risque de Marché  (Rm − Rf)",
    y        = "Prime de Risque de l'Actif  (Ri − Rf)",
    caption  = "Source : Données de l'exercice — MCO estimé sous R"
  ) +
  theme_minimal(base_size = 13) +
  theme(
    plot.title    = element_text(face = "bold", colour = "#0d3b66", size = 14),
    plot.subtitle = element_text(colour = "#457b9d", size = 11),
    plot.caption  = element_text(colour = "#6c757d", size = 9),
    panel.grid.minor = element_blank()
  )

ggplotly(p_gg, tooltip = "text") %>%
  layout(
    font = list(family = "IBM Plex Sans"),
    hoverlabel = list(
      bgcolor   = "#0d3b66",
      font      = list(color = "white", size = 12)
    )
  )

6 Validation des Hypothèses : Analyse des Résidus

6.1 Distribution des Résidus

aug_df <- augment(model) %>%
  mutate(obs = 1:n)

p1 <- ggplot(aug_df, aes(x = .fitted, y = .resid)) +
  geom_hline(yintercept = 0, linetype = "dashed", colour = "#e63946") +
  geom_point(colour = "#0d3b66", size = 3) +
  geom_smooth(se = FALSE, colour = "#457b9d", linewidth = 0.8, method = "loess", formula = y~x) +
  labs(title = "Résidus vs. Valeurs ajustées", x = "ŷ", y = "Résidus") +
  theme_minimal(base_size = 12) +
  theme(plot.title = element_text(face = "bold", colour = "#0d3b66"))

p2 <- ggplot(aug_df, aes(sample = .resid)) +
  stat_qq(colour = "#0d3b66", size = 2.5) +
  stat_qq_line(colour = "#e63946", linewidth = 1) +
  labs(title = "Q-Q Plot des Résidus", x = "Quantiles théoriques", y = "Quantiles observés") +
  theme_minimal(base_size = 12) +
  theme(plot.title = element_text(face = "bold", colour = "#0d3b66"))

gridExtra::grid.arrange(p1, p2, ncol = 2)

6.2 Tests Formels

# Normalité — Shapiro-Wilk & Anderson-Darling
sw_test <- shapiro.test(residuals(model))
ad_test <- nortest::ad.test(residuals(model))

# Homoscédasticité — Breusch-Pagan
bp_test <- lmtest::bptest(model)

tibble(
  Test           = c("Shapiro-Wilk (Normalité)",
                     "Anderson-Darling (Normalité)",
                     "Breusch-Pagan (Homoscédasticité)"),
  `Statistique`  = round(c(sw_test$statistic, ad_test$statistic, bp_test$statistic), 6),
  `p-value`      = round(c(sw_test$p.value, ad_test$p.value, bp_test$p.value), 6),
  Décision       = ifelse(
    c(sw_test$p.value, ad_test$p.value, bp_test$p.value) > 0.05,
    "✅ H₀ non rejetée — Hypothèse validée",
    "⚠️  H₀ rejetée — Violation potentielle"
  )
) %>%
  kable(caption = "Tableau 7 — Tests de validation des hypothèses MCO", booktabs = TRUE) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE,
                font_size = 13) %>%
  row_spec(0, bold = TRUE, color = "white", background = "#0d3b66")
Tableau 7 — Tests de validation des hypothèses MCO
Test Statistique p-value Décision
Shapiro-Wilk (Normalité) 0.975863 0.939258 ✅ H₀ non rejetée — Hypothèse validée |
Anderson-Darling (Normalité) 0.143110 0.953569 ✅ H₀ non rejetée — Hypothèse validée |
Breusch-Pagan (Homoscédasticité) 1.869208 0.171566 ✅ H₀ non rejetée — Hypothèse validée |

Note méthodologique : Avec \(n = 10\) observations, la puissance des tests formels est limitée. L’analyse graphique (Q-Q plot, résidus vs. ajustés) est complémentaire et souvent plus informative sur de petits échantillons.


7 Conclusion : Interprétation Financière

7.1 Résultats Finaux

tibble(
  Paramètre     = c("α̂ — Jensen Alpha", "β̂ — Market Beta", "R²", "R² ajusté", "σ̂"),
  Valeur        = round(c(beta0_hat, beta1_hat, R2, R2_adj, sigma_hat), 6),
  `Interprétation Financière` = c(
    "Performance anormale quasi-nulle → cohérent avec CAPM en équilibre",
    "Pour +1% de prime de marché, l'actif génère +β̂% de prime",
    paste0(round(R2*100,2), "% de la variance expliquée par le risque systématique"),
    "Qualité d'ajustement corrigée du biais d'estimation",
    "Volatilité résiduelle (risque idiosyncratique non capturé)"
  )
) %>%
  kable(caption = "Tableau 8 — Synthèse des résultats et interprétations", booktabs = TRUE) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE,
                font_size = 13) %>%
  row_spec(0, bold = TRUE, color = "white", background = "#0d3b66") %>%
  row_spec(2, bold = TRUE, background = "#eaf7ea")
Tableau 8 — Synthèse des résultats et interprétations
Paramètre Valeur Interprétation Financière
α̂ — Jensen Alpha
-0.06103

7.2 Interprétation du Bêta

Classification de l’actif selon le Bêta estimé (\(\hat{\beta} = 1.3401\)) :

  • \(\hat{\beta} > 1\) → Actif agressif (amplifie les mouvements du marché) : volatilité supérieure au marché, adapté aux phases haussières.
  • \(\hat{\beta} \approx 1\) → Actif neutre : suit fidèlement l’indice de référence.
  • \(0 < \hat{\beta} < 1\) → Actif défensif : atténue les fluctuations, privilégié en phase de repli.
  • \(\hat{\beta} < 0\) → Actif contra-cyclique : couverture naturelle contre le risque de marché.

Pour cet exercice : \(\hat{\beta} = 1.3401\), ce qui classe l’actif comme agressif — amplificateur de risque systématique. Le \(\hat{\alpha} \approx -0.061\) est statistiquement non significatif (\(p > 0.05\)), confirmant l’hypothèse d’efficience des marchés en l’absence d’alpha positif persistant.


Rapport généré sous R Markdown · FST Errachidia, Finance & Actuariat · 2026