Aller au contenu
Riadh Mnasri
← Retour au blog
4 min de lecture

SA-CCR pas à pas : implémenter la formule réglementaire

SA-CCR (Standardised Approach for Counterparty Credit Risk) a remplacé la méthode CEM dans Bâle III pour une raison précise : CEM traitait un swap de taux à trois mois et un swap à vingt-neuf ans avec la même grille de facteurs grossière. SA-CCR sensibilise le calcul à la maturité réelle et à la direction du risque, au prix d'une formule nettement plus dense. Cet article implémente cette formule pas à pas, pour un cas simplifié : un seul trade, une seule classe d'actifs. Les tables de facteurs superviseurs complètes et l'agrégation multi-classes suivent la même logique, mais alourdiraient l'exemple sans rien ajouter à la compréhension.

La formule de tête#

EAD = alpha × (RC + PFE)

alpha est fixé par le régulateur à 1,4, un multiplicateur forfaitaire qui n'a rien à voir avec le trade lui-même. Tout le travail se trouve dans les deux autres termes.

RC : le coût de remplacement#

RC répond à une question simple : si la contrepartie fait défaut aujourd'hui, combien coûte-t-il de refaire le même trade sur le marché ? Pour un trade non collatéralisé :

typescript
function replacementCost(marketValue: number): number {
  return Math.max(marketValue, 0);
}

Le Math.max(..., 0) n'est pas cosmétique : une exposition négative ne réduit pas le risque de contrepartie en dessous de zéro, elle signifie simplement que c'est vous qui devez de l'argent à la contrepartie, pas l'inverse. Pour un trade collatéralisé, RC se réduit du montant net de collatéral détenu, avec un plancher qui dépend des seuils contractuels (threshold, minimum transfer amount) définis dans l'accord de collatéralisation : ce niveau de détail suit la même logique, mais dépend d'un contrat par contrat, donc omis ici volontairement.

PFE : l'exposition future potentielle#

PFE mesure combien l'exposition pourrait augmenter avant la prochaine date de marge. Elle se construit en trois étapes.

1. L'AddOn par trade#

typescript
type Trade = {
  notional: number;
  maturityYears: number;
  supervisoryFactor: number; // ex. 0.005 pour un IRS (0,5%)
  delta: number; // +1 long, -1 short, pour les positions non linéaires
};
 
function maturityFactor(maturityYears: number): number {
  return Math.sqrt(Math.min(maturityYears, 1));
}
 
function addOn(trade: Trade): number {
  const mf = maturityFactor(trade.maturityYears);
  return trade.notional * trade.supervisoryFactor * mf * trade.delta;
}

Le facteur de maturité plafonne l'effet du temps à un an : un trade de dix ans et un trade de trois ans obtiennent le même MF, parce qu'au-delà d'un an l'incertitude sur l'exposition future ne croît plus proportionnellement au temps restant dans le modèle SA-CCR. Un trade de six mois, lui, obtient un MF réduit (sqrt(0.5) ≈ 0,71), ce qui reflète une fenêtre de risque plus courte.

2. L'agrégation en AddOn de classe d'actifs#

Dans le cas réel, plusieurs trades de la même classe d'actifs (taux, change, crédit) s'agrègent avec des paramètres de corrélation superviseurs, pas une simple somme. Pour un seul trade, l'AddOn agrégé se réduit à l'AddOn du trade lui-même.

3. Le multiplicateur#

typescript
function pfeMultiplier(marketValue: number, collateral: number, addOnAggregate: number): number {
  const floor = 0.05;
  const excess = marketValue - collateral;
  if (excess >= 0) return 1;
  return Math.max(
    floor,
    floor + (1 - floor) * Math.exp(excess / (2 * (1 - floor) * addOnAggregate)),
  );
}
 
function potentialFutureExposure(addOnAggregate: number, multiplier: number): number {
  return multiplier * addOnAggregate;
}

Le multiplicateur reconnaît que du collatéral en excès réduit le risque futur, mais jamais en dessous d'un plancher de 5 % de l'AddOn : même sur-collatéralisé, un netting set garde une exposition future potentielle non nulle, parce que le collatéral d'aujourd'hui n'est pas une garantie sur le collatéral de demain.

Assembler les trois morceaux#

typescript
function calculateEAD(trade: Trade, marketValue: number, collateral: number): number {
  const alpha = 1.4;
  const rc = replacementCost(marketValue - collateral);
  const trAddOn = addOn(trade);
  const multiplier = pfeMultiplier(marketValue, collateral, trAddOn);
  const pfe = potentialFutureExposure(trAddOn, multiplier);
  return alpha * (rc + pfe);
}

Ce que cette implémentation ne couvre pas#

Ce code traite un trade isolé dans une classe d'actifs. Une implémentation de production doit gérer l'agrégation à travers plusieurs hedging sets avec des corrélations superviseurs par classe d'actifs, les règles spécifiques aux trades non linéaires (delta calculé par un modèle d'options, pas fixé à ±1), et les seuils contractuels de collatéralisation propres à chaque accord CSA. Ce n'est pas un détail à ajouter plus tard, c'est la majorité de la complexité réelle d'un moteur SA-CCR en production. L'objectif ici n'est pas de fournir un moteur complet, c'est de rendre lisible la structure que ces règles plus complexes viennent ensuite peupler : deux nombres, RC et PFE, un multiplicateur régulateur, et une formule qui tient sur une ligne une fois qu'on sait ce que chaque terme représente vraiment.