negotiated-structure.risk.lock-vs-float — arbitrage blocage vs flottant
Objectif
Ce module calcule explicitement le coût de la certitude pour un contrat
d'électricité de gros : combien coûte la décision de bloquer le prix (contrat
fixe) par rapport à laisser le prix suivre le marché (contrat indexé ou
partiellement indexé) ?
Il remplace l'heuristique implicite de sélection de durée (appétit au risque ×
pente de marché) par une **comparaison de coûts sur trois scénarios de prix
versionnés**, avec la prime de blocage rendue explicite dans la sortie.
---
Scénarios de prix
Trois scénarios équipondérés (1/3 chacun) :
| Scénario | Multiplicateur | Prix CAL Y+1 |
|----------|---------------|--------------|
| Central | ×1,00 | Prix observé |
| Haussier | ×1,15 | +15 % |
| Baissier | ×0,85 | −15 % |
Hypothèse de volatilité : ±15 % annualisé pour les contrats à terme
baseload français (CAL Y+1). Cette hypothèse s'appuie sur les données
historiques EPEX SPOT (2019–2024, plage constatée 12–18 %) et sur le rapport
CRE « État et perspectives du marché de l'électricité » (2024). Elle est
documentée dans le code source et doit être revue chaque année.
---
Trois structures comparées par scénario
Pour chaque scénario, le module calcule le coût de la composante énergie
(€/MWh) de trois structures :
Ce prix est invariant d'un scénario à l'autre : c'est précisément la
définition du blocage. Les hausses ou baisses de marché postérieures ne
modifient pas ce que l'acheteur paiera.
fixed_pct / cal_y1_pct / spot_pct
issue de l'optimiseur (spec-2bis#5). La part fixe reste au prix central ;
la part indexée suit le scénario.
---
Prime de blocage
La prime de blocage (champ lock_premium_eur_mwh) est définie comme :
```
prime = coût_fixe_central − espérance(coût_indexé)
```
Avec des scénarios symétriques équipondérés ±15 % :
```
E[indexé] = (central + haussier + baissier) / 3
= CAL × (1,0 + 1,15 + 0,85) / 3
= CAL × 1,0
= coût_fixe_central
```
→ La prime est nulle (≈ 0) par construction. C'est une sortie correcte et
intentionnelle. Bloquer le prix n'apporte pas d'économies en espérance ;
sa valeur est la réduction de variance, mesurée par le champ spread_eur_mwh.
Ce résultat est affiché tel quel — il n'est pas artificiellement positivisé.
---
Fraction recommandée à bloquer
Le champ recommended_lock_fraction (0–1) est calculé par une règle
déterministe à partir de l'appétit au risque et de l'amplitude du spread :
| Appétit au risque | Fraction de base |
|-------------------|-----------------|
| fixe | 1,00 |
| mixte | 0,70 |
| indexe | 0,30 |
| opportuniste | 0,00 |
Si le spread dépasse 20 €/MWh (risque de prix élevé), la fraction est majorée
de 0,10 (plafond à 1,0).
---
Composantes non-énergie
TURPE, accise, CSPE, CEE, capacité et frais fixes sont **invariants selon le
scénario**. Ils contribuent au champ expected_cost_eur_mwh (coût total estimé
toutes composantes confondues), mais n'affectent pas spread_eur_mwh ni
lock_premium_eur_mwh, qui mesurent la sensibilité aux scénarios de la
composante énergie uniquement.
---
Périmètre
Ce module est un calcul autonome, pur et synchrone : entrées → résultat, sans
I/O. Il ne recâble pas optimize() ni pickTerm() — l'intégration dans le
parcours complet est prévue par spec-2bis#18 (moteur de tarification des offres).