DecInfer-03-Utility-Money : Utilite de l’Argent et Aversion au Risque

Serie : Programmation Probabiliste avec Infer.NET (3/10)
Duree estimee : 45 minutes
Prerequis : Notebook 14 (Axiomes de l’utilite)


Objectifs

  • Comprendre le Paradoxe de Saint-Petersbourg
  • Maitriser les fonctions d’utilite CARA et CRRA
  • Calculer les coefficients d’aversion au risque (Arrow-Pratt)
  • Appliquer la dominance stochastique

1. Le Paradoxe de Saint-Petersbourg

Enonce (Nicolas Bernoulli, 1713)

Une piece equilibree est lancee jusqu’a obtenir Face. Si Face apparait au lancer n, vous gagnez 2^n euros. Combien paieriez-vous pour jouer ?

Calcul de la valeur esperee

\[E[\text{gain}] = \sum_{n=1}^{\infty} P(\text{Face au tour } n) \times 2^n = \sum_{n=1}^{\infty} \frac{1}{2^n} \times 2^n = \sum_{n=1}^{\infty} 1 = \infty\]

La valeur esperee est infinie, pourtant personne ne paierait plus de quelques dizaines d’euros pour jouer !

Pourquoi la valeur esperee echoue ici ?

Ce paradoxe revele une faille fondamentale de la maximisation de la valeur esperee :

  1. Les grands gains sont trop rares : La probabilite de gagner 2^20 (1M EUR) est de 1 sur un million. Psychologiquement, on ignore ces événements.

  2. L’utilite marginale decroit : Passer de 0 a 1000 EUR change votre vie. Passer de 1M a 1.001M EUR ? Negligeable.

  3. Limites pratiques : Aucun casino n’a de richesse infinie pour payer les gains.

Resolution de Bernoulli (1738)

Daniel Bernoulli proposa que les individus maximisent l’utilite esperee, pas la valeur esperee, avec une utilite logarithmique :

\[U(x) = \ln(x)\]

\[E[U(\text{gain})] = \sum_{n=1}^{\infty} \frac{1}{2^n} \ln(2^n) = \ln(2) \sum_{n=1}^{\infty} \frac{n}{2^n} = 2\ln(2) \approx 1.39\]

Equivalent certain : e^1.39 EUR = 4 EUR.

Cette resolution a fonde la théorie moderne de la decision et l’economie comportementale.


Preparation de l’environnement

Avant de simuler le paradoxe, nous chargeons Infer.NET. Ce framework sera utilise plus loin pour l’inference bayesienne du profil de risque.

// Installation Infer.NET
#r "nuget: Microsoft.ML.Probabilistic"
#r "nuget: Microsoft.ML.Probabilistic.Compiler"

using Microsoft.ML.Probabilistic;
using Microsoft.ML.Probabilistic.Distributions;
using Microsoft.ML.Probabilistic.Models;
using Microsoft.ML.Probabilistic.Algorithms;

Console.WriteLine("Infer.NET charge !");
Installed Packages
  • Microsoft.ML.Probabilistic, 0.4.2504.701
  • Microsoft.ML.Probabilistic.Compiler, 0.4.2504.701
Infer.NET charge !

Chargement des utilitaires de visualisation des graphes de facteurs.

// Chargement du helper pour les visualisations de factor graphs
#load "../../Infer/FactorGraphHelper.cs"

// NOTE: Les visualisations Plotly ont ete remplacees par des sorties console
// pour assurer la compatibilite avec toutes les versions de .NET Interactive.
// Les calculs et resultats restent identiques.

Console.WriteLine("FactorGraphHelper charge !");
Console.WriteLine("Note : Les graphiques ont ete remplaces par des tableaux console.");
FactorGraphHelper charge !
Note : Les graphiques ont ete remplaces par des tableaux console.

Simulation du paradoxe

Verifions empiriquement les predictions de Bernoulli avec une simulation Monte Carlo. Le code ci-dessous :

  1. Simule 100 000 parties du jeu de Saint-Petersbourg
  2. Calcule le gain moyen (valeur esperee empirique)
  3. Calcule l’utilite moyenne avec U(x) = ln(x)
  4. Determine l’equivalent certain exp(E[U])
// Simulation du Paradoxe de Saint-Petersbourg

double SimulerJeu(Random rng)
{
    int n = 1;
    while (rng.NextDouble() < 0.5) // Pile
        n++;
    return Math.Pow(2, n);
}

// Simulation Monte Carlo
var rng = new Random(42);
int N = 100000;
double sommeGains = 0;
double sommeUtilite = 0; // U(x) = ln(x)

for (int i = 0; i < N; i++)
{
    double gain = SimulerJeu(rng);
    sommeGains += gain;
    sommeUtilite += Math.Log(gain);
}

double gainMoyen = sommeGains / N;
double utiliteMoyenne = sommeUtilite / N;
double equivalentCertain = Math.Exp(utiliteMoyenne);

Console.WriteLine($"Simulation sur {N:N0} parties :");
Console.WriteLine($"  Gain moyen (valeur esperee empirique) : {gainMoyen:N0} EUR");
Console.WriteLine($"  Utilite moyenne E[ln(gain)] : {utiliteMoyenne:F3}");
Console.WriteLine($"  Equivalent certain exp(E[U]) : {equivalentCertain:F1} EUR");
Console.WriteLine();
Console.WriteLine("=> La valeur esperee croit avec N, mais l'equivalent certain reste borne.");
Simulation sur 100 000 parties :
  Gain moyen (valeur esperee empirique) : 21 EUR
  Utilite moyenne E[ln(gain)] : 1,386
  Equivalent certain exp(E[U]) : 4,0 EUR

=> La valeur esperee croit avec N, mais l'equivalent certain reste borne.

Interpretation des résultats de simulation

Le tableau ci-dessus illustre parfaitement le paradoxe :

Mesure Valeur Signification
Gain moyen empirique ~21 EUR Croit indefiniment avec N (theoriquement infini)
Utilite moyenne E[ln(gain)] ~1.39 Converge vers 2*ln(2) = 1.386
Equivalent certain ~4 EUR Montant que l’agent accepterait a coup sur

Point cle : Malgre une valeur esperee “infinie”, un agent rationnel avec utilite logarithmique ne paierait que 4 EUR pour jouer. C’est la resolution du paradoxe par Bernoulli.

La simulation confirme la théorie : - Le gain moyen fluctue enormement (peut atteindre des millions avec des simulations plus longues) - L’equivalent certain reste stable autour de 4 EUR, quelle que soit la taille de l’echantillon

// Analyse du Paradoxe de Saint-Petersbourg
// Evolution du gain moyen et de l'equivalent certain en fonction du nombre de simulations

var taillesEchantillon = new List<int>();
var gainsMoyens = new List<double>();
var equivalentsCertains = new List<double>();

var rngViz = new Random(123);
double sommeGainsViz = 0;
double sommeUtiliteViz = 0;

int[] checkpoints = { 100, 500, 1000, 2000, 5000, 10000, 20000, 50000, 100000 };
int checkpoint_idx = 0;

for (int i = 1; i <= 100000; i++)
{
    double gain = SimulerJeu(rngViz);
    sommeGainsViz += gain;
    sommeUtiliteViz += Math.Log(gain);
    
    if (checkpoint_idx < checkpoints.Length && i == checkpoints[checkpoint_idx])
    {
        taillesEchantillon.Add(i);
        gainsMoyens.Add(sommeGainsViz / i);
        equivalentsCertains.Add(Math.Exp(sommeUtiliteViz / i));
        checkpoint_idx++;
    }
}

// Affichage sous forme de tableau
Console.WriteLine("Evolution du Paradoxe de Saint-Petersbourg :");
Console.WriteLine();
Console.WriteLine("Simulations | Gain moyen (EUR) | Equiv. certain (EUR) | CE theorique");
Console.WriteLine("------------|------------------|---------------------|-------------");
for (int i = 0; i < taillesEchantillon.Count; i++)
{
    Console.WriteLine($"{taillesEchantillon[i],11:N0} | {gainsMoyens[i],16:F1} | {equivalentsCertains[i],19:F2} | 4.00");
}

Console.WriteLine();
Console.WriteLine("Observation : Le gain moyen fluctue (peut croitre indefiniment),");
Console.WriteLine("tandis que l'equivalent certain converge vers ~4 EUR.");
Evolution du Paradoxe de Saint-Petersbourg :

Simulations | Gain moyen (EUR) | Equiv. certain (EUR) | CE theorique
------------|------------------|---------------------|-------------
        100 |              8,8 |                4,79 | 4.00
        500 |             91,2 |                4,19 | 4.00
      1 000 |             50,4 |                4,11 | 4.00
      2 000 |             31,1 |                4,06 | 4.00
      5 000 |             25,5 |                4,04 | 4.00
     10 000 |             21,6 |                4,07 | 4.00
     20 000 |             20,7 |                4,04 | 4.00
     50 000 |             17,9 |                4,00 | 4.00
    100 000 |             18,3 |                4,01 | 4.00

Observation : Le gain moyen fluctue (peut croitre indefiniment),
tandis que l'equivalent certain converge vers ~4 EUR.

Lecture du tableau : deux suites, deux destins — c’est le paradoxe qui se dissout

La colonne « Gain moyen » est instable de bout en bout : 8,8 puis 91,2 puis 50,4 EUR en descendant les tailles de simulation, sans tendance stable — la moyenne empirique d’une loterie à queue lourde ne converge pas à vitesse utile ; un tirage rare à 2^20 EUR déplace à lui seul la moyenne de milliers de parties. La colonne « Equiv. certain » fait l’inverse : 4,79 → 4,19 → … → 4,01, resserrée autour de la valeur théorique 4 EUR = 2^2 dès 100 parties. C’est la résolution du paradoxe en acte : sous l’utilité logarithmique, la série géométrique des utilités converge (Σ 2⁻ᵏ = 2), quand la série des gains diverge. L’espérance monétaire de la loterie est infinie — aucun prix « juste » au sens de l’espérance n’existe — mais son espérance d’utilité est finie, et l’équivalent certain de 4 EUR est le seul prix qu’un agent log-utilitaire acceptera de payer. La leçon générale dépasse la curiosité historique : modéliser les gains (et non leur utilité) conduit à valoriser des queues de distribution impossibles à acheter. C’est le cœur de la section 2 qui suit : pourquoi une même richesse n’a pas la même valeur selon celui qui la possède.

2. Utilite Marginale Decroissante

Le principe fondamental

L’utilite d’un euro supplementaire depend de la richesse actuelle :

  • Pour un etudiant, 100 EUR = enorme différence
  • Pour un milliardaire, 100 EUR = negligeable

Mathematiquement : U’’(x) < 0 (utilite concave)

Consequences

  1. Aversion au risque : U(E[X]) > E[U(X)] (inegalite de Jensen)
  2. Prime de risque : L’agent accepte moins que la valeur esperee pour eviter le risque
  3. Equivalent certain : Montant certain equivalent a une loterie

Demonstration numérique

Le code suivant calcule l’utilite et l’utilite marginale pour différentes fonctions classiques (racine carree et logarithme) a différents niveaux de richesse.

// Illustration de l'utilite marginale decroissante

Func<double, double> U_sqrt = x => Math.Sqrt(x);      // Racine carree
Func<double, double> U_log = x => Math.Log(x + 1);    // Logarithmique
Func<double, double> U_linear = x => x / 1000.0;      // Lineaire (neutre)

Console.WriteLine("Utilite marginale pour differentes richesses :");
Console.WriteLine();
Console.WriteLine("Richesse  | U_sqrt(x) | U'_sqrt(x) | U_log(x) | U'_log(x)");
Console.WriteLine("----------|-----------|------------|----------|----------");

foreach (double x in new[] { 100.0, 1000.0, 10000.0, 100000.0 })
{
    double u_sqrt = U_sqrt(x);
    double up_sqrt = 0.5 / Math.Sqrt(x);  // Derivee de sqrt
    double u_log = U_log(x);
    double up_log = 1.0 / (x + 1);        // Derivee de log
    
    Console.WriteLine($"{x,9:N0} | {u_sqrt,9:F2} | {up_sqrt,10:F6} | {u_log,8:F3} | {up_log,8:F6}");
}

Console.WriteLine();
Console.WriteLine("=> L'utilite marginale (U'(x)) decroit quand la richesse augmente.");
Utilite marginale pour differentes richesses :

Richesse  | U_sqrt(x) | U'_sqrt(x) | U_log(x) | U'_log(x)
----------|-----------|------------|----------|----------
      100 |     10,00 |   0,050000 |    4,615 | 0,009901
    1 000 |     31,62 |   0,015811 |    6,909 | 0,000999
   10 000 |    100,00 |   0,005000 |    9,210 | 0,000100
  100 000 |    316,23 |   0,001581 |   11,513 | 0,000010

=> L'utilite marginale (U'(x)) decroit quand la richesse augmente.

Interpretation des résultats — l’utilité marginale décroît

Les résultats numériques demontrent le principe fondamental :

Richesse U’_sqrt (derivee) Facteur de reduction
100 EUR 0.0500 Reference
1 000 EUR 0.0158 /3.2
10 000 EUR 0.0050 /10
100 000 EUR 0.0016 /31.6

Interpretation economique : Quand la richesse est multipliee par 10, l’utilite marginale est divisee par environ 3.16 pour la fonction racine carree, et par 10 pour la fonction logarithmique.

Cette propriete explique pourquoi : - Les riches investissent dans des actifs plus risques (1000 EUR de perte leur fait moins “mal”) - Les pauvres achetent des assurances couteuses (100 EUR de perte leur fait plus “mal”)

3. Fonctions d’Utilite Classiques

Les economistes utilisent deux familles de fonctions d’utilite, chacune avec des proprietes distinctes qui les rendent appropriees pour différents contextes.

CARA : Constant Absolute Risk Aversion

\[U(x) = -e^{-ax}\]

  • Paramètre a : coefficient d’aversion au risque absolu
  • Propriete : la prime de risque ne depend pas de la richesse initiale

Quand utiliser CARA ? Quand les enjeux sont petits par rapport a la richesse totale (decisions quotidiennes, paris modestes). Un milliardaire et un etudiant auraient la même prime de risque pour un pari de 100 EUR - ce qui est peu realiste pour de grands enjeux.

CRRA : Constant Relative Risk Aversion

\[U(x) = \begin{cases} \frac{x^{1-\rho}}{1-\rho} & \text{si } \rho \neq 1 \\ \ln(x) & \text{si } \rho = 1 \end{cases}\]

  • Paramètre ρ (rho) : coefficient d’aversion au risque relatif
  • Propriete : la prime de risque en proportion de la richesse est constante

Quand utiliser CRRA ? Pour les decisions d’investissement a long terme, les choix de carriere, ou tout enjeu proportionnel a la richesse. Un milliardaire risque 10% de sa fortune avec la même reluctance qu’un etudiant risque 10% de la sienne.

Comparaison intuitive

Aspect CARA CRRA
Prime de risque Fixe en euros Fixe en % de richesse
Riche vs pauvre Même attitude en absolu Même attitude en relatif
Usage typique Assurance, petits paris Investissement, grandes decisions
Comportement empirique Moins realiste Plus proche de la realite

Valeurs typiques de rho

rho Interpretation Exemple
0 Neutre au risque (lineaire) Trader haute frequence
0.5 Faible aversion Investisseur agressif
1 Logarithmique (Bernoulli) Investisseur equilibre
2-4 Valeurs empiriques typiques Menage moyen
> 10 Très averse (rare) Investisseur ultra-conservateur

Les études empiriques suggerent rho = 2-3 pour la population générale.

Implementation et demonstration

Le code suivant implemente les fonctions CARA et CRRA, puis illustre l’impact du paramètre rho sur l’evaluation d’une loterie simple.

// Implementation des fonctions CARA et CRRA (defini ici pour etre disponible dans les cellules suivantes)

public static class UtilityFunctions
{
    // CARA : U(x) = -exp(-a*x)
    public static double CARA(double x, double a)
    {
        return -Math.Exp(-a * x);
    }
    
    // CRRA : U(x) = x^(1-rho) / (1-rho)  ou  ln(x) si rho=1
    public static double CRRA(double x, double rho)
    {
        if (x <= 0) return double.NegativeInfinity;
        if (Math.Abs(rho - 1) < 1e-10)
            return Math.Log(x);
        return Math.Pow(x, 1 - rho) / (1 - rho);
    }
}

// Demonstration des fonctions d'utilite CRRA pour differents rho

var richesses = new[] { 1000.0, 5000.0, 10000.0, 15000.0, 20000.0 };
var rhos = new[] { 0.0, 0.5, 1.0, 2.0, 4.0 };

Console.WriteLine("Fonctions d'utilite CRRA : Concavite croissante avec rho");
Console.WriteLine();
Console.WriteLine("Richesse  | rho=0.0   | rho=0.5   | rho=1.0   | rho=2.0   | rho=4.0");
Console.WriteLine("----------|-----------|-----------|-----------|-----------|----------");

foreach (var x in richesses)
{
    Console.Write($"{x,9:N0} |");
    foreach (var rho in rhos)
    {
        double u = UtilityFunctions.CRRA(x, rho);
        // Normaliser pour affichage
        double uNorm = rho == 0 ? u/10000 : rho < 1 ? u/100 : rho == 1 ? u/5 : u*10;
        Console.Write($" {uNorm,9:F3} |");
    }
    Console.WriteLine();
}

Console.WriteLine();
Console.WriteLine("Observation : Plus rho est eleve, plus la courbe est concave,");
Console.WriteLine("ce qui traduit une plus forte aversion au risque (utilite marginale decroissante).");
Fonctions d'utilite CRRA : Concavite croissante avec rho

Richesse  | rho=0.0   | rho=0.5   | rho=1.0   | rho=2.0   | rho=4.0
----------|-----------|-----------|-----------|-----------|----------
    1 000 |     0,100 |     0,632 |     1,382 |    -0,010 |    -0,000 |
    5 000 |     0,500 |     1,414 |     1,703 |    -0,002 |    -0,000 |
   10 000 |     1,000 |     2,000 |     1,842 |    -0,001 |    -0,000 |
   15 000 |     1,500 |     2,449 |     1,923 |    -0,001 |    -0,000 |
   20 000 |     2,000 |     2,828 |     1,981 |    -0,001 |    -0,000 |

Observation : Plus rho est eleve, plus la courbe est concave,
ce qui traduit une plus forte aversion au risque (utilite marginale decroissante).

Application des fonctions d’utilite CARA et CRRA a une loterie concrete.

// Demonstration avec une loterie : 50% de 200, 50% de 0
double[] outcomes = { 200, 0 };
double[] probs = { 0.5, 0.5 };

Console.WriteLine("Loterie : [50%: 200, 50%: 0]");
Console.WriteLine("Valeur esperee : 100 EUR");

foreach (double rho in new[] { 0.0, 0.5, 1.0, 2.0, 4.0 })
{
    // Calcul EU avec CRRA
    double EU = 0;
    for (int i = 0; i < outcomes.Length; i++)
    {
        double u = outcomes[i] > 0 ? UtilityFunctions.CRRA(outcomes[i], rho) : UtilityFunctions.CRRA(0.01, rho);
        EU += probs[i] * u;
    }
    
    // Equivalent certain : inverser CRRA
    double CE;
    if (Math.Abs(rho - 1) < 1e-10)
        CE = Math.Exp(EU);
    else
        CE = Math.Pow(EU * (1 - rho), 1.0 / (1 - rho));
    
    double primeRisque = 100 - CE; // EV - CE
    
    Console.WriteLine($"rho = {rho:F1} : EU = {EU,8:F3}, CE = {CE,6:F1} EUR, Prime de risque = {primeRisque,5:F1} EUR");
}
Loterie : [50%: 200, 50%: 0]
Valeur esperee : 100 EUR
rho = 0,0 : EU =  100,005, CE =  100,0 EUR, Prime de risque =  -0,0 EUR
rho = 0,5 : EU =   14,242, CE =   50,7 EUR, Prime de risque =  49,3 EUR
rho = 1,0 : EU =    0,347, CE =    1,4 EUR, Prime de risque =  98,6 EUR
rho = 2,0 : EU =  -50,002, CE =    0,0 EUR, Prime de risque = 100,0 EUR
rho = 4,0 : EU = -166666,667, CE =    0,0 EUR, Prime de risque = 100,0 EUR

Interpretation des résultats CRRA

Le tableau montre comment l’aversion au risque (paramètre rho) affecte la valorisation d’une loterie :

rho Equivalent Certain Prime de Risque Interpretation
0.0 100 EUR 0 EUR Neutre : accepte la valeur esperee
0.5 50.7 EUR 49.3 EUR Legerement averse
1.0 1.4 EUR 98.6 EUR Très averse (log)
2.0+ ~0 EUR ~100 EUR Extremement averse

Attention au cas rho >= 1 : La loterie inclut un outcome de 0 EUR. Pour rho >= 1, U(0) = -infini (logarithme ou puissance negative de 0). Le code utilise U(0.01) comme approximation, ce qui explique les valeurs extremes.

Conclusion pratique : Pour les valeurs typiques rho in [0.5, 2], la prime de risque varie enormement. C’est pourquoi l’elicitation de préférences (mesurer rho experimentalement) est cruciale en finance comportementale.

4. Coefficients d’Aversion au Risque (Arrow-Pratt)

Kenneth Arrow et John Pratt ont formalise des mesures qui permettent de quantifier et comparer l’aversion au risque entre agents et contextes.

Aversion Absolue au Risque (ARA)

\[r(x) = -\frac{U''(x)}{U'(x)}\]

Interpretation economique : r(x) mesure combien l’agent est averse au risque pour des enjeux en valeur absolue (euros).

  • r(x) eleve → forte aversion pour des paris de X euros
  • r(x) decroissant (DARA) → plus riche = moins averse en absolu (comportement realiste)

Aversion Relative au Risque (RRA)

\[R(x) = x \cdot r(x) = -\frac{x \cdot U''(x)}{U'(x)}\]

Interpretation economique : R(x) mesure l’aversion au risque pour des enjeux proportionnels (% de richesse).

  • R(x) = 2 signifie que l’agent a la même aversion a risquer 10% de sa richesse, qu’il ait 1000 EUR ou 1M EUR.
  • R(x) constant (CRRA) est empiriquement observe chez la plupart des investisseurs.

Proprietes des fonctions classiques

Fonction ARA r(x) RRA R(x) Comportement
CARA : U = -e^(-ax) a (constante) ax (croissante) Même aversion en EUR quelle que soit richesse
CRRA : U = x^(1-ρ)/(1-ρ) ρ/x (decroissante) ρ (constante) Même aversion en % quelle que soit richesse
Log : U = ln(x) 1/x 1 Cas particulier CRRA avec ρ=1

Application pratique

Pour estimer l’ARA ou RRA d’un agent, on observe ses choix face a des loteries calibrees, puis on ajuste la fonction d’utilite qui explique ces choix. C’est la base de l’elicitation de préférences en finance comportementale.

// Calcul des coefficients Arrow-Pratt

public static class ArrowPratt
{
    // ARA pour CRRA : r(x) = rho / x
    public static double ARA_CRRA(double x, double rho) => rho / x;
    
    // RRA pour CRRA : R(x) = rho (constante)
    public static double RRA_CRRA(double rho) => rho;
    
    // ARA pour CARA : r(x) = a (constante)
    public static double ARA_CARA(double a) => a;
    
    // RRA pour CARA : R(x) = a*x (croissante)
    public static double RRA_CARA(double x, double a) => a * x;
}

// Comparaison CARA vs CRRA
double rho = 2.0;  // CRRA
double a = 0.001;  // CARA (ajuste pour comportement similaire autour de 1000)

Console.WriteLine("Comparaison CARA (a=0.001) vs CRRA (rho=2)\n");
Console.WriteLine("Richesse x | ARA_CARA | ARA_CRRA | RRA_CARA | RRA_CRRA");
Console.WriteLine("-----------|----------|----------|----------|----------");

foreach (double x in new[] { 100.0, 1000.0, 10000.0, 100000.0 })
{
    Console.WriteLine($"{x,10:N0} | {ArrowPratt.ARA_CARA(a),8:F4} | {ArrowPratt.ARA_CRRA(x, rho),8:F4} | {ArrowPratt.RRA_CARA(x, a),8:F1} | {ArrowPratt.RRA_CRRA(rho),8:F1}");
}

Console.WriteLine();
Console.WriteLine("=> CARA : meme aversion absolue quelle que soit la richesse");
Console.WriteLine("=> CRRA : meme aversion relative (proportionnelle) quelle que soit la richesse");
Comparaison CARA (a=0.001) vs CRRA (rho=2)

Richesse x | ARA_CARA | ARA_CRRA | RRA_CARA | RRA_CRRA
-----------|----------|----------|----------|----------
       100 |   0,0010 |   0,0200 |      0,1 |      2,0
     1 000 |   0,0010 |   0,0020 |      1,0 |      2,0
    10 000 |   0,0010 |   0,0002 |     10,0 |      2,0
   100 000 |   0,0010 |   0,0000 |    100,0 |      2,0

=> CARA : meme aversion absolue quelle que soit la richesse
=> CRRA : meme aversion relative (proportionnelle) quelle que soit la richesse

Interpretation des coefficients Arrow-Pratt

Le tableau compare les comportements CARA vs CRRA pour différents niveaux de richesse :

Richesse ARA_CARA ARA_CRRA RRA_CARA RRA_CRRA
100 EUR 0.0010 0.0200 0.1 2.0
1 000 EUR 0.0010 0.0020 1.0 2.0
10 000 EUR 0.0010 0.0002 10.0 2.0
100 000 EUR 0.0010 0.0000 100.0 2.0

Observations cles :

  • CARA : ARA constante (0.001), mais RRA croit avec la richesse
  • CRRA : ARA decroit avec la richesse, mais RRA constante (2.0)

Implication pratique : Avec CARA, un pauvre et un milliardaire exigent la même prime de risque en euros. Avec CRRA, ils exigent la même prime en pourcentage de leur richesse. CRRA est plus realiste pour les grandes decisions financieres.

Exercice 1 : Dominance stochastique et sélection de portefeuille

Objectif : Utilisez la dominance stochastique pour eliminer des investissements domines sans connaitre la fonction d’utilite exacte.

Contexte : Quatre fonds d’investissement sont disponibles, chacun avec une distribution de rendement différente. Avant de choisir, vous devez verifier si certains fonds sont domines stochastiquement.

Étapes : 1. Definissez les 4 fonds avec leurs distributions discretes de rendement 2. Verifiez la dominance de premier ordre (FSD) entre chaque paire de fonds 3. Identifiez les fonds non-domines (frontiere efficace) 4. Verifiez la dominance de second ordre (SSD) entre les fonds restants

Indices : - Indice 1 : Pour FSD, comparez les CDFs : F_A domine F_B si F_A(x) <= F_B(x) pour tout x - Indice 2 : Utilisez la classe DiscreteLottery définie precedemment et sa méthode CDF() - Indice 3 : Pour SSD, comparez les integrales des CDFs : integrale(F_A) <= integrale(F_B) pour tout x - Étape 2 : Comparez toutes les 6 paires possibles parmi 4 fonds

// Exercice : Dominance stochastique et selection de portefeuille

// Quatre fonds avec distributions discretes de rendement annuel (%)
// Fonds A : "Conservateur" - [30%: 2%, 40%: 4%, 30%: 6%]
// Fonds B : "Equilibre"    - [20%: 0%, 30%: 5%, 30%: 10%, 20%: 15%]
// Fonds C : "Agressif"     - [10%: -5%, 20%: 0%, 30%: 10%, 25%: 20%, 15%: 30%]
// Fonds D : "Tres risque"  - [25%: -10%, 25%: 5%, 25%: 20%, 25%: 35%]

// TODO 1 : Creer les 4 loteries avec DiscreteLottery
// Indice : var fondsA = new DiscreteLottery("Conservateur", 
//           new[] { 2.0, 4.0, 6.0 }, new[] { 0.3, 0.4, 0.3 });

// TODO 2 : Verifier FSD entre chaque paire (6 comparaisons)
// Indice : pour chaque seuil x, verifier que CDF_A(x) <= CDF_B(x)
// Si vrai pour tout x, A domine B au 1er ordre

// TODO 3 : Identifier les fonds non-domines
// Indice : un fonds est non-dominé s'il n'est domine par aucun autre fonds

// TODO 4 : Parmi les non-domines, verifier la SSD
// Indice : SSD verifie que la somme cumulee des CDFs est plus petite

Console.WriteLine("Exercice a completer : dominance stochastique et selection de portefeuille");
Exercice a completer : dominance stochastique et selection de portefeuille

5. Equivalent Certain et Prime de Risque

Definitions

Pour une loterie L avec valeur esperee E[L] :

  • Equivalent certain (CE) : Montant x tel que U(x) = E[U(L)]
  • Prime de risque (RP) : RP = E[L] - CE

Interpretation

  • RP > 0 : Agent averse au risque (prefere moins mais certain)
  • RP = 0 : Agent neutre au risque
  • RP < 0 : Agent amateur de risque (rare)
// Calcul de l'equivalent certain et prime de risque avec Infer.NET

// Loterie modelisee : investissement incertain
// 60% de gagner 50%, 40% de perdre 30%

double richesseInitiale = 10000;
double[] multipliers = { 1.5, 0.7 };  // +50% ou -30%
double[] probabilities = { 0.6, 0.4 };

// Valeur esperee
double EV = richesseInitiale * (probabilities[0] * multipliers[0] + probabilities[1] * multipliers[1]);

Console.WriteLine($"Richesse initiale : {richesseInitiale:N0} EUR");
Console.WriteLine($"Loterie : 60% -> {richesseInitiale * multipliers[0]:N0}, 40% -> {richesseInitiale * multipliers[1]:N0}");
Console.WriteLine($"Valeur esperee : {EV:N0} EUR\n");

// Calcul pour differents niveaux d'aversion
foreach (double rho in new[] { 0.5, 1.0, 2.0, 3.0 })
{
    // E[U]
    double EU = 0;
    for (int i = 0; i < multipliers.Length; i++)
    {
        double outcome = richesseInitiale * multipliers[i];
        EU += probabilities[i] * UtilityFunctions.CRRA(outcome, rho);
    }
    
    // Equivalent certain (inverser CRRA)
    double CE;
    if (Math.Abs(rho - 1) < 1e-10)
        CE = Math.Exp(EU);
    else
        CE = Math.Pow(EU * (1 - rho), 1.0 / (1 - rho));
    
    double primeRisque = EV - CE;
    double primeRelative = primeRisque / richesseInitiale * 100;
    
    Console.WriteLine($"rho = {rho:F1} : CE = {CE:N0} EUR, Prime = {primeRisque:N0} EUR ({primeRelative:F1}% de richesse)");
}
Richesse initiale : 10 000 EUR
Loterie : 60% -> 15 000, 40% -> 7 000
Valeur esperee : 11 800 EUR

rho = 0,5 : CE = 11 439 EUR, Prime = 361 EUR (3,6% de richesse)
rho = 1,0 : CE = 11 058 EUR, Prime = 742 EUR (7,4% de richesse)
rho = 2,0 : CE = 10 294 EUR, Prime = 1 506 EUR (15,1% de richesse)
rho = 3,0 : CE = 9 609 EUR, Prime = 2 191 EUR (21,9% de richesse)

Lecture : la prime de risque croît avec l’aversion — et avec quoi au juste ?

Sur la même loterie (espérance 11 800 EUR depuis une richesse de 10 000 EUR), la prime exigée passe de 361 EUR (ρ=0,5) à 1 506 EUR (ρ=2) puis 2 191 EUR (ρ=3). La prime relative suit : 3,6 % → 15,1 % → 21,9 % de la richesse. L’ordre de grandeur économiquement significatif est le second : un agent « typique » (ρ=2, valeur médiane des études empiriques) refuse cette loterie à moins de recevoir un sixième de sa richesse en compensation — c’est le genre de chiffre qui explique pourquoi l’assurance prospère. Notez la mécanique : la loterie ne change pas d’une ligne à l’autre, seul ρ change ; toute la prime est fabriquée par la concavité de l’utilité, qui écrase les gains hauts plus fort à mesure que ρ monte.

// Analyse de la prime de risque en fonction de rho

var rhoRange = new[] { 0.1, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0 };

Console.WriteLine("Impact de l'aversion au risque sur la prime de risque");
Console.WriteLine($"Loterie : 60% -> {richesseInitiale * 1.5:N0} EUR, 40% -> {richesseInitiale * 0.7:N0} EUR");
Console.WriteLine($"Valeur esperee : {EV:N0} EUR");

Console.WriteLine(" rho  | Equiv. Certain | Prime Risque | Prime Relative");
Console.WriteLine("------|----------------|--------------|---------------");

foreach (double rhoVal in rhoRange)
{
    double EU = 0;
    for (int i = 0; i < multipliers.Length; i++)
    {
        double outcome = richesseInitiale * multipliers[i];
        EU += probabilities[i] * UtilityFunctions.CRRA(outcome, rhoVal);
    }
    
    double CE;
    if (Math.Abs(rhoVal - 1) < 1e-10)
        CE = Math.Exp(EU);
    else
        CE = Math.Pow(EU * (1 - rhoVal), 1.0 / (1 - rhoVal));
    
    double primeRisque = EV - CE;
    double primeRelative = primeRisque / richesseInitiale * 100;
    
    Console.WriteLine($"{rhoVal,5:F1} | {CE,14:N0} | {primeRisque,12:N0} | {primeRelative,13:F1}%");
}

Console.WriteLine();
Console.WriteLine("=> Un agent neutre (rho~0) exige une prime quasi-nulle");
Console.WriteLine("=> Un agent typique (rho=2) exige ~1500 EUR de prime (15% de richesse)");
Impact de l'aversion au risque sur la prime de risque
Loterie : 60% -> 15 000 EUR, 40% -> 7 000 EUR
Valeur esperee : 11 800 EUR
 rho  | Equiv. Certain | Prime Risque | Prime Relative
------|----------------|--------------|---------------
  0,1 |         11 730 |           70 |           0,7%
  0,5 |         11 439 |          361 |           3,6%
  1,0 |         11 058 |          742 |           7,4%
  1,5 |         10 672 |        1 128 |          11,3%
  2,0 |         10 294 |        1 506 |          15,1%
  2,5 |          9 937 |        1 863 |          18,6%
  3,0 |          9 609 |        2 191 |          21,9%
  3,5 |          9 317 |        2 483 |          24,8%
  4,0 |          9 062 |        2 738 |          27,4%

=> Un agent neutre (rho~0) exige une prime quasi-nulle
=> Un agent typique (rho=2) exige ~1500 EUR de prime (15% de richesse)

Lecture du balayage : une relation quasi linéaire, lue en prime relative

Le tableau fait varier ρ de 0,1 à 4 : la prime passe de 70 EUR à 2 738 EUR, presque proportionnellement (×39 pour ×40 de ρ — la relation est proche de la linéarité sur cette plage, car la prime relative monte de 0,7 % à 27,4 % de façon régulière). Les deux bornes encadrent les profils réels : ρ≈0,1 est quasi-neutre au risque (l’agent paie à peine pour éliminer le risque), ρ=4 est un profil très averse qui sacrifie plus d’un quart de sa richesse pour la certitude. La zone utile pour calibrer un décideur réel se lit dans la littérature empirique entre 1 et 3 — c’est là que le prochain exemple guide situera « votre » profil.

Definition des loteries et dominance stochastique.

// Definition de la classe DiscreteLottery et des loteries A, B
// (necessaire pour la verification de dominance stochastique)

public class DiscreteLottery
{
    public double[] Outcomes { get; }
    public double[] Probs { get; }
    public string Name { get; }
    
    public DiscreteLottery(string name, double[] outcomes, double[] probs)
    {
        Name = name;
        Outcomes = outcomes;
        Probs = probs;
    }
    
    public double CDF(double x)
    {
        double sum = 0;
        for (int i = 0; i < Outcomes.Length; i++)
            if (Outcomes[i] <= x)
                sum += Probs[i];
        return sum;
    }
    
    public double ExpectedValue() => Outcomes.Zip(Probs, (o, p) => o * p).Sum();
}

// Loterie A : 50% de 100, 50% de 200 (meilleure)
// Loterie B : 50% de 50, 50% de 200 (dominee)
var A = new DiscreteLottery("A", new[] { 100.0, 200.0 }, new[] { 0.5, 0.5 });
var B = new DiscreteLottery("B", new[] { 50.0, 200.0 }, new[] { 0.5, 0.5 });

Console.WriteLine("Loteries definies pour l'analyse de dominance stochastique :");
Console.WriteLine($"  Loterie A : [50%: 100, 50%: 200], E[A] = {A.ExpectedValue()}");
Console.WriteLine($"  Loterie B : [50%: 50, 50%: 200], E[B] = {B.ExpectedValue()}");
Console.WriteLine();

// Analyse des CDFs
Console.WriteLine("Comparaison des CDFs (dominance 1er ordre si F_A(x) <= F_B(x) pour tout x) :");
Console.WriteLine("   x  | F_A(x) | F_B(x) | A<=B?");
Console.WriteLine("------|--------|--------|------");

bool FSD_AdomB = true;
foreach (double x in new[] { 25.0, 50.0, 75.0, 100.0, 150.0, 200.0 })
{
    double fa = A.CDF(x);
    double fb = B.CDF(x);
    bool ok = fa <= fb;
    if (!ok) FSD_AdomB = false;
    Console.WriteLine($"{x,5} | {fa,6:F2} | {fb,6:F2} | {(ok ? "Oui" : "NON")}");
}

Console.WriteLine();
Console.WriteLine(FSD_AdomB 
    ? "=> A domine B au 1er ordre (tout le monde prefere A)" 
    : "=> Pas de dominance au 1er ordre");
Loteries definies pour l'analyse de dominance stochastique :
  Loterie A : [50%: 100, 50%: 200], E[A] = 150
  Loterie B : [50%: 50, 50%: 200], E[B] = 125

Comparaison des CDFs (dominance 1er ordre si F_A(x) <= F_B(x) pour tout x) :
   x  | F_A(x) | F_B(x) | A<=B?
------|--------|--------|------
   25 |   0,00 |   0,00 | Oui
   50 |   0,00 |   0,50 | Oui
   75 |   0,00 |   0,50 | Oui
  100 |   0,50 |   0,50 | Oui
  150 |   0,50 |   0,50 | Oui
  200 |   1,00 |   1,00 | Oui

=> A domine B au 1er ordre (tout le monde prefere A)

Interpretation des résultats — la prime de risque croît avec rho

Le tableau montre l’impact de l’aversion au risque sur l’equivalent certain et la prime de risque :

rho Equivalent Certain Prime de Risque Prime Relative
0.5 11 439 EUR 361 EUR 3.6%
1.0 11 058 EUR 742 EUR 7.4%
2.0 10 294 EUR 1 506 EUR 15.1%
3.0 9 609 EUR 2 191 EUR 21.9%

Observation cle : Pour cette loterie (60% de +50%, 40% de -30%), même un agent moderement averse (rho=2) exige une prime de 15% de sa richesse pour accepter le risque.

Applications pratiques : - En assurance : la prime de risque justifie le cout d’une couverture - En investissement : determine le rendement minimal exige pour un actif risque - En negociation : evalue combien un individu est pret a payer pour eliminer l’incertitude


6. Dominance Stochastique

La dominance stochastique permet de comparer des loteries sans connaitre la fonction d’utilite de l’agent.

Dominance de premier ordre (FSD)

Loterie A domine B au premier ordre si : \(F_A(x) \leq F_B(x)\) pour tout x.

Interpretation : Tout agent rationnel (quelle que soit son aversion au risque) prefere A a B.

Dominance de second ordre (SSD)

A domine B au second ordre si l’integrale des CDF satisfait une condition similaire.

Interpretation : Tout agent averse au risque prefere A a B.

// Note: DiscreteLottery et les loteries A, B ont ete definis dans la cellule precedente
// Cette cellule est conservee pour compatibilite mais le code principal est au-dessus

Console.WriteLine("Rappel des loteries definies :");
Console.WriteLine($"  Loterie A : E[A] = {A.ExpectedValue()} EUR");
Console.WriteLine($"  Loterie B : E[B] = {B.ExpectedValue()} EUR");
Console.WriteLine();
Console.WriteLine("La dominance stochastique du 1er ordre a ete verifiee ci-dessus.");
Rappel des loteries definies :
  Loterie A : E[A] = 150 EUR
  Loterie B : E[B] = 125 EUR

La dominance stochastique du 1er ordre a ete verifiee ci-dessus.

Interpretation des résultats de dominance

Le tableau des CDF confirme que A domine B au premier ordre :

Seuil x F_A(x) F_B(x) Interpretation
50 EUR 0.00 0.50 A n’a jamais de perte severe, B oui
100 EUR 0.50 0.50 Même probabilite d’etre sous 100
200 EUR 1.00 1.00 Les deux atteignent 200 max

Consequence pratique : Puisque A domine B au premier ordre, tout agent rationnel (averse, neutre ou amateur de risque) devrait preferer A. C’est un critere de decision universel qui ne depend pas de la fonction d’utilite.

Applications de la dominance stochastique : - Sélection de portefeuille : Eliminer les actifs domines avant toute optimisation - Comparaison de politiques : Choisir entre deux interventions sans connaitre les préférences exactes - Tests A/B : Valider qu’une version domine l’autre pour tous les utilisateurs

// Definition des fonctions et variables pour le choix d'investissement
// (definies ici pour etre disponibles dans les cellules suivantes)

double capital = 100000;

// Fonction pour echantillonner une distribution normale (Box-Muller)
double SampleNormal(Random r, double mean, double std)
{
    double u1 = r.NextDouble();
    double u2 = r.NextDouble();
    double z = Math.Sqrt(-2 * Math.Log(u1)) * Math.Cos(2 * Math.PI * u2);
    return mean + std * z;
}

// Analyse du choix d'investissement selon l'aversion au risque
Console.WriteLine("Choix d'investissement optimal selon l'aversion au risque (rho)");
Console.WriteLine($"Capital initial : {capital:N0} EUR");

Console.WriteLine("Options disponibles :");
Console.WriteLine("  A: Livret A (3% certain)");
Console.WriteLine("  B: Fonds modere (8% +/- 10%)");
Console.WriteLine("  C: Actions agressives (12% +/- 25%)");
Console.WriteLine();

var rhoValues = new[] { 0.2, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 5.0 };
Console.WriteLine(" rho  | EU(A)     | EU(B)     | EU(C)     | Choix optimal");
Console.WriteLine("------|-----------|-----------|-----------|---------------");

foreach (double r in rhoValues)
{
    double eu_a = UtilityFunctions.CRRA(capital * 1.03, r);
    
    double sum_b = 0, sum_c = 0;
    var rngInv = new Random(42);
    for (int i = 0; i < 2000; i++)
    {
        double wB = capital * (1 + SampleNormal(rngInv, 0.08, 0.10));
        double wC = capital * (1 + SampleNormal(rngInv, 0.12, 0.25));
        sum_b += wB > 0 ? UtilityFunctions.CRRA(wB, r) : UtilityFunctions.CRRA(1, r);
        sum_c += wC > 0 ? UtilityFunctions.CRRA(wC, r) : UtilityFunctions.CRRA(1, r);
    }
    double eu_b = sum_b / 2000;
    double eu_c = sum_c / 2000;
    
    string choix = eu_a >= eu_b && eu_a >= eu_c ? "A (Livret)" : 
                   eu_b >= eu_c ? "B (Fonds)" : "C (Actions)";
    
    Console.WriteLine($"{r,5:F1} | {eu_a,9:F4} | {eu_b,9:F4} | {eu_c,9:F4} | {choix}");
}

Console.WriteLine();
Console.WriteLine("=> Faible rho : prefere C (rendement max)");
Console.WriteLine("=> Rho eleve : prefere B (compromis risque/rendement)");
Choix d'investissement optimal selon l'aversion au risque (rho)
Capital initial : 100 000 EUR
Options disponibles :
  A: Livret A (3% certain)
  B: Fonds modere (8% +/- 10%)
  C: Actions agressives (12% +/- 25%)

 rho  | EU(A)     | EU(B)     | EU(C)     | Choix optimal
------|-----------|-----------|-----------|---------------
  0,2 | 12799,1106 | 13316,8378 | 13607,5834 | C (Actions)
  0,5 |  641,8723 |  657,5376 |  664,2666 | C (Actions)
  1,0 |   11,5425 |   11,5885 |   11,5970 | C (Actions)
  1,5 |   -0,0062 |   -0,0061 |   -0,0061 | B (Fonds)
  2,0 |   -0,0000 |   -0,0000 |   -0,0000 | B (Fonds)
  3,0 |   -0,0000 |   -0,0000 |   -0,0000 | B (Fonds)
  4,0 |   -0,0000 |   -0,0000 |   -0,0000 | B (Fonds)
  5,0 |   -0,0000 |   -0,0000 |   -0,0000 | B (Fonds)

=> Faible rho : prefere C (rendement max)
=> Rho eleve : prefere B (compromis risque/rendement)

Lecture : le basculement C → B, et une précaution de lecture du tableau

La colonne « Choix optimal » raconte l’histoire : à faible aversion (ρ ≤ 1), l’agent prend C (actions, 12 % ± 25 %) ; dès ρ = 1,5, il replie sur B (fonds, 8 % ± 10 %). L’option A (livret, 3 % certain) n’est jamais choisie : elle est dominée — B offre un rendement espéré supérieur avec un risque que même les agents les plus averses du tableau acceptent de porter.

Précaution de lecture, importante : les colonnes E[U] ne se comparent pas entre lignes. Chaque ρ définit une fonction d’utilité différente, à une transformation monotone près — les valeurs d’une même ligne (A vs B vs C pour un ρ fixé) sont comparables, mais « 641,87 à ρ=0,5 » contre « 11,54 à ρ=1 » ne veut rien dire. C’est pourquoi l’affichage à haute aversion montre des E[U] tous arrondis à −0,0000 : ce sont des ordres de grandeur numériquement écrasés, sans contenu économique — seule la ligne « Choix » transporte l’information, et c’est elle qu’il faut lire.

7. Application : Choix d’Investissement

Scénario

Vous avez 100 000 EUR a investir. Trois options :

Option Description Distribution
Livret A Sans risque 3% certain
Fonds B Modere N(8%, 10%)
Actions C Agressif N(12%, 25%)
// Decision d'investissement avec Infer.NET
// Note: capital et SampleNormal ont ete definis dans la cellule precedente

// Rendements (en proportion)
var rendementA = 0.03; // Certain
var rendementB_mean = 0.08;
var rendementB_std = 0.10;
var rendementC_mean = 0.12;
var rendementC_std = 0.25;

// Simulation Monte Carlo pour comparer
var rng = new Random(42);
int N = 10000;

double rho = 2.0; // Aversion au risque typique

double EU_A = UtilityFunctions.CRRA(capital * (1 + rendementA), rho);

double sumU_B = 0, sumU_C = 0;
for (int i = 0; i < N; i++)
{
    double rB = SampleNormal(rng, rendementB_mean, rendementB_std);
    double rC = SampleNormal(rng, rendementC_mean, rendementC_std);
    
    double wealthB = capital * (1 + rB);
    double wealthC = capital * (1 + rC);
    
    // Eviter les valeurs negatives (faillite)
    sumU_B += wealthB > 0 ? UtilityFunctions.CRRA(wealthB, rho) : UtilityFunctions.CRRA(1, rho);
    sumU_C += wealthC > 0 ? UtilityFunctions.CRRA(wealthC, rho) : UtilityFunctions.CRRA(1, rho);
}

double EU_B = sumU_B / N;
double EU_C = sumU_C / N;

Console.WriteLine($"Comparaison des investissements (rho = {rho}, capital = {capital:N0} EUR) :");
Console.WriteLine($"Option A (Livret, 3% certain)    : E[U] = {EU_A:F4}");
Console.WriteLine($"Option B (Fonds, 8% +/- 10%)     : E[U] = {EU_B:F4}");
Console.WriteLine($"Option C (Actions, 12% +/- 25%)  : E[U] = {EU_C:F4}");
Console.WriteLine();

var best = new[] { ("A", EU_A), ("B", EU_B), ("C", EU_C) }.OrderByDescending(x => x.Item2).First();
Console.WriteLine($"Decision optimale pour rho={rho} : Option {best.Item1}");
Comparaison des investissements (rho = 2, capital = 100 000 EUR) :
Option A (Livret, 3% certain)    : E[U] = -0,0000
Option B (Fonds, 8% +/- 10%)     : E[U] = -0,0000
Option C (Actions, 12% +/- 25%)  : E[U] = -0,0000

Decision optimale pour rho=2 : Option B

Impact du coefficient d’aversion au risque sur la decision d’investissement.

// Impact du coefficient d'aversion au risque sur la decision

Console.WriteLine("Decision optimale selon l'aversion au risque :\n");
Console.WriteLine(" rho  | E[U_A]   | E[U_B]   | E[U_C]   | Choix");
Console.WriteLine("------|----------|----------|----------|------");

foreach (double r in new[] { 0.5, 1.0, 2.0, 3.0, 5.0 })
{
    double eu_a = UtilityFunctions.CRRA(capital * 1.03, r);
    
    double sum_b = 0, sum_c = 0;
    var rng2 = new Random(42);
    for (int i = 0; i < 5000; i++)
    {
        double wB = capital * (1 + SampleNormal(rng2, 0.08, 0.10));
        double wC = capital * (1 + SampleNormal(rng2, 0.12, 0.25));
        sum_b += wB > 0 ? UtilityFunctions.CRRA(wB, r) : UtilityFunctions.CRRA(1, r);
        sum_c += wC > 0 ? UtilityFunctions.CRRA(wC, r) : UtilityFunctions.CRRA(1, r);
    }
    double eu_b = sum_b / 5000;
    double eu_c = sum_c / 5000;
    
    string choix = eu_a >= eu_b && eu_a >= eu_c ? "A" : (eu_b >= eu_c ? "B" : "C");
    Console.WriteLine($"{r,5:F1} | {eu_a,8:F4} | {eu_b,8:F4} | {eu_c,8:F4} | {choix}");
}

Console.WriteLine();
Console.WriteLine("=> Plus l'aversion au risque augmente, plus les options securisees sont preferees.");
Decision optimale selon l'aversion au risque :

 rho  | E[U_A]   | E[U_B]   | E[U_C]   | Choix
------|----------|----------|----------|------
  0,5 | 641,8723 | 657,4616 | 665,6975 | C
  1,0 |  11,5425 |  11,5883 |  11,6011 | C
  2,0 |  -0,0000 |  -0,0000 |  -0,0000 | B
  3,0 |  -0,0000 |  -0,0000 |  -0,0000 | B
  5,0 |  -0,0000 |  -0,0000 |  -0,0000 | B

=> Plus l'aversion au risque augmente, plus les options securisees sont preferees.

Interpretation des résultats d’investissement

Le tableau montre comment l’aversion au risque determine le choix optimal :

rho Choix Optimal Interpretation
0.5 C (Actions) Faible aversion : maximise le rendement espere
1.0 C (Actions) Logarithmique : encore attiré par le rendement
2.0-5.0 B (Fonds) Aversion typique : compromis rendement/risque

Point cle : Les valeurs E[U] proches de 0 pour rho >= 2 sont dues a la forme de la fonction CRRA qui devient très petite pour de grandes richesses divisees par (1-rho) negatif.

Enseignements pratiques : 1. Aucune dominance stochastique entre B et C : le choix depend vraiment de rho 2. Le Livret A n’est jamais optimal pour ces paramètres (rendement trop faible) 3. La volatilite de C (25%) penalise fortement les agents averses

Cette simulation illustre pourquoi les conseillers financiers commencent par evaluer le profil de risque du client avant de recommander des placements.

8. Exemple guide : Votre Profil de Risque

Enonce

En utilisant les fonctions CARA et CRRA définies dans ce notebook, determinez votre profil de risque personnel a partir d’une serie de choix entre loteries et montants certains.

Méthode

  1. Pour chaque loterie proposee, indiquez votre equivalent certain (le montant certain qui vous rendrait indifferent)
  2. Calculez le coefficient d’aversion au risque implied par chaque choix
  3. Verifiez la coherence de vos reponses (les coefficients devraient etre stables)

Code pour explorer

// Calibration de votre rho

double W0 = 10000;
double W_gain = 20000;
double W_perte = 5000;

// Votre probabilite d'indifference (ajustez !)
double p_indifference = 0.55; // <- Modifiez : a partir de quelle proba acceptez-vous ?

// U(W0) = p * U(W_gain) + (1-p) * U(W_perte)
// Pour CRRA, trouvons rho tel que cette equation soit satisfaite

double FindRho(double p, double w0, double wGain, double wLoss)
{
    // Recherche binaire
    double rhoMin = 0.01, rhoMax = 10.0;
    
    for (int i = 0; i < 50; i++)
    {
        double rho = (rhoMin + rhoMax) / 2;
        
        double U0 = UtilityFunctions.CRRA(w0, rho);
        double UGain = UtilityFunctions.CRRA(wGain, rho);
        double ULoss = UtilityFunctions.CRRA(wLoss, rho);
        double EU_loterie = p * UGain + (1 - p) * ULoss;
        
        if (EU_loterie > U0)
            rhoMin = rho; // Agent accepte => augmenter rho pour qu'il refuse
        else
            rhoMax = rho;
    }
    return (rhoMin + rhoMax) / 2;
}

double votre_rho = FindRho(p_indifference, W0, W_gain, W_perte);

Console.WriteLine($"Votre probabilite d'indifference : {p_indifference:P0}");
Console.WriteLine($"Votre coefficient d'aversion au risque estime : rho = {votre_rho:F2}");
Console.WriteLine();

if (votre_rho < 0.5)
    Console.WriteLine("Profil : Faible aversion au risque (investisseur agressif)");
else if (votre_rho < 1.5)
    Console.WriteLine("Profil : Aversion moderee (investisseur equilibre)");
else if (votre_rho < 3.0)
    Console.WriteLine("Profil : Aversion significative (investisseur prudent)");
else
    Console.WriteLine("Profil : Forte aversion au risque (investisseur tres conservateur)");
Votre probabilite d'indifference : 55 %
Votre coefficient d'aversion au risque estime : rho = 1,29

Profil : Aversion moderee (investisseur equilibre)

Lecture : votre ρ révélé par un seul prix d’indifférence

La calibration demande une seule réponse : à quelle probabilité de gain êtes-vous indifférent entre une loterie et sa contrepartie certaine ? De ce prix d’indifférence (55 % ici), le modèle inverse la fonction d’utilité et rend ρ = 1,29 — un profil modérément averse. C’est le même mouvement que l’exemple guide précédent, mais dans l’autre sens : au lieu de calculer les préférences depuis ρ, on infère ρ depuis une préférence déclarée. Ce renversement (préférences → paramètres) est exactement ce que la section suivante automatisera avec Infer.NET : observer des choix répétés plutôt qu’un unique aveu, et en déduire une distribution sur le profil entier.

9. Inference Bayesienne de l’Aversion au Risque avec Infer.NET

Motivation

Jusqu’ici, nous avons determine rho par introspection (méthode des equivalents certains). Mais Infer.NET permet d’inferer le profil de risque d’un agent a partir de ses choix observes !

Approche

  1. Modeliser la probabilite de choisir l’option risquee comme une variable Beta
  2. Observer les choix de l’agent face a des loteries binaires
  3. Inferer le posterior sur la propension au risque

Un agent qui choisit souvent l’option risquee a une probabilite de risque elevee (faible aversion), et inversement.

// Inference Bayesienne du profil de risque avec Infer.NET

// Scenario : Un decideur a fait 10 choix entre option sure et option risquee
// 1 = a choisi l'option risquee, 0 = a choisi l'option sure
int[] choixObserves = { 0, 0, 1, 0, 1, 0, 0, 0, 1, 0 }; // 3/10 risques = averse

// Modele : probabilite de choisir l'option risquee
// Prior Beta(2,2) = non-informatif centre sur 0.5
Variable<double> probRisque = Variable.Beta(2, 2).Named("probRisque");

// Observations : chaque choix est un tirage Bernoulli
Range choixRange = new Range(choixObserves.Length).Named("choixRange");
VariableArray<bool> choix = Variable.Array<bool>(choixRange).Named("choix");
choix[choixRange] = Variable.Bernoulli(probRisque).ForEach(choixRange);

// Observations
choix.ObservedValue = choixObserves.Select(c => c == 1).ToArray();

// Inference
InferenceEngine engineRisk = new InferenceEngine();
engineRisk.Compiler.CompilerChoice = Microsoft.ML.Probabilistic.Compiler.CompilerChoice.Roslyn;

Beta posteriorProbRisque = engineRisk.Infer<Beta>(probRisque);

Console.WriteLine("=== Inference Bayesienne du Profil de Risque ===\n");
Console.WriteLine($"Choix observes : {string.Join(", ", choixObserves.Select(c => c == 1 ? "Risque" : "Sur"))}");
Console.WriteLine($"Taux empirique de choix risques : {choixObserves.Average():P0}\n");

Console.WriteLine($"Prior : Beta(2,2) => P(risque) moyenne = 0.50");
Console.WriteLine($"Posterior : {posteriorProbRisque}");
Console.WriteLine($"           => P(risque) moyenne = {posteriorProbRisque.GetMean():F3}");

// Calcul de l'intervalle de credibilite 95% par approximation normale
double alpha_post = posteriorProbRisque.TrueCount;
double beta_post = posteriorProbRisque.FalseCount;
double mean_post = posteriorProbRisque.GetMean();
double var_post = (alpha_post * beta_post) / (Math.Pow(alpha_post + beta_post, 2) * (alpha_post + beta_post + 1));
double std_post = Math.Sqrt(var_post);
double ci_low = Math.Max(0, mean_post - 1.96 * std_post);
double ci_high = Math.Min(1, mean_post + 1.96 * std_post);
Console.WriteLine($"           => Intervalle 95% (approx) : [{ci_low:F2}, {ci_high:F2}]");
Console.WriteLine();

// Interpretation du profil
double probMoy = posteriorProbRisque.GetMean();
if (probMoy < 0.3)
    Console.WriteLine("=> Profil AVERSE au risque (choisit rarement l'option risquee)");
else if (probMoy < 0.5)
    Console.WriteLine("=> Profil MODEREMENT AVERSE au risque");
else if (probMoy < 0.7)
    Console.WriteLine("=> Profil NEUTRE ou legerement amateur de risque");
else
    Console.WriteLine("=> Profil AMATEUR DE RISQUE (choisit souvent l'option risquee)");

Console.WriteLine();
Console.WriteLine("=> Infer.NET permet d'inferer le profil de risque IMPLICITE d'un decideur !");
Console.WriteLine("   Cette approche est utilisee en finance comportementale et en UX.");
Compiling model...done.
=== Inference Bayesienne du Profil de Risque ===

Choix observes : Sur, Sur, Risque, Sur, Risque, Sur, Sur, Sur, Risque, Sur
Taux empirique de choix risques : 30 %

Prior : Beta(2,2) => P(risque) moyenne = 0.50
Posterior : Beta(5,9)[mean=0,3571]
           => P(risque) moyenne = 0,357
           => Intervalle 95% (approx) : [0,11, 0,60]

=> Profil MODEREMENT AVERSE au risque

=> Infer.NET permet d'inferer le profil de risque IMPLICITE d'un decideur !
   Cette approche est utilisee en finance comportementale et en UX.

Interpretation de l’inference bayesienne

Le modèle Infer.NET a mis a jour nos croyances sur la propension au risque de l’agent :

Mesure Prior Posterior Interpretation
Distribution Beta(2,2) Beta(5,9) Mise a jour bayesienne
Moyenne 0.50 ~0.36 Tendance averse confirmee
Intervalle 95% [0.09, 0.91] [0.11, 0.60] Incertitude reduite

Formule de mise a jour : Avec un prior Beta(alpha, beta) et n observations dont k succes (choix risques) : \[\text{Posterior} = \text{Beta}(\alpha + k, \beta + n - k)\]

Ici : Beta(2+3, 2+7) = Beta(5, 9) avec 3 choix risques sur 10.

Applications pratiques de cette approche :

  1. Finance comportementale : Inferer le profil de risque implicite d’un client a partir de son historique de decisions
  2. A/B testing : Determiner si un utilisateur prefere les options sures ou risquees dans une interface
  3. Economie experimentale : Analyser les choix des sujets dans des expériences de laboratoire
  4. Recommandation de produits : Personnaliser les offres selon le profil de risque infere

Avantages de l’approche bayesienne : - Integre l’incertitude (intervalle credible, pas juste une estimation ponctuelle) - Permet d’incorporer des connaissances prealables (prior informatif) - Converge vers le vrai paramètre avec plus d’observations - Fournit une distribution complete, pas seulement une moyenne

// Visualisation du Factor Graph pour l'inference du profil de risque

// Recreer le modele et l'engine pour generer le factor graph
int[] choixData = { 0, 0, 1, 0, 1, 0, 0, 0, 1, 0 };

Variable<double> probRisqueFG = Variable.Beta(2, 2).Named("probRisque");
Range choixRangeFG = new Range(choixData.Length).Named("choixRange");
VariableArray<bool> choixFG = Variable.Array<bool>(choixRangeFG).Named("choix");
choixFG[choixRangeFG] = Variable.Bernoulli(probRisqueFG).ForEach(choixRangeFG);
choixFG.ObservedValue = choixData.Select(c => c == 1).ToArray();

var engineFG = new InferenceEngine();
engineFG.Compiler.CompilerChoice = Microsoft.ML.Probabilistic.Compiler.CompilerChoice.Roslyn;
engineFG.ShowFactorGraph = true;

try
{
    var _ = engineFG.Infer<Beta>(probRisqueFG);
    FactorGraphHelper.GetLatestFactorGraphHtml(700).DisplayAs("text/html");
    
    Console.WriteLine("Le factor graph montre :");
    Console.WriteLine("  - probRisque : variable latente Beta (cercle)");
    Console.WriteLine("  - choix[i] : observations Bernoulli conditionnees sur probRisque");
    Console.WriteLine("  - Le facteur Bernoulli connecte probRisque a chaque observation");
}
catch (Exception ex)
{
    Console.WriteLine("Factor graph non genere (Graphviz requis).");
    Console.WriteLine($"Erreur : {ex.Message}");
}
Compiling model...done.
Model_09_23_26_09_15_41_16.svg
Model node0 Beta(2,2)[mean=0,5] node1 Random node0->node1 dist node2 probRisque node1->node2 node3 Bernoulli node2->node3 probTrue node4 choix[choixRange] node3->node4
Le factor graph montre :
  - probRisque : variable latente Beta (cercle)
  - choix[i] : observations Bernoulli conditionnees sur probRisque
  - Le facteur Bernoulli connecte probRisque a chaque observation

Comparaison visuelle des distributions Prior et Posterior.

// Visualisation de la distribution Beta : Prior vs Posterior
// Affichage sous forme de tableau plutot que graphique

// Fonction de densite Beta
double BetaPDF(double x, double alpha, double beta)
{
    if (x <= 0 || x >= 1) return 0;
    double logB = Microsoft.ML.Probabilistic.Math.MMath.GammaLn(alpha) 
                + Microsoft.ML.Probabilistic.Math.MMath.GammaLn(beta) 
                - Microsoft.ML.Probabilistic.Math.MMath.GammaLn(alpha + beta);
    return Math.Exp((alpha - 1) * Math.Log(x) + (beta - 1) * Math.Log(1 - x) - logB);
}

Console.WriteLine("Distribution Beta : Prior vs Posterior");
Console.WriteLine();
Console.WriteLine("   P(risque) | Prior Beta(2,2) | Posterior Beta(5,9)");
Console.WriteLine("-------------|-----------------|--------------------");

foreach (double x in new[] { 0.1, 0.2, 0.3, 0.36, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9 })
{
    double prior = BetaPDF(x, 2, 2);
    double posterior = BetaPDF(x, 5, 9);
    string marker = Math.Abs(x - 0.36) < 0.02 ? " <- Moyenne posterior" : 
                    Math.Abs(x - 0.5) < 0.02 ? " <- Moyenne prior" : "";
    Console.WriteLine($"        {x:F2} | {prior,15:F4} | {posterior,18:F4}{marker}");
}

Console.WriteLine();
Console.WriteLine("Interpretation :");
Console.WriteLine("  - Prior Beta(2,2) : distribution uniforme centree sur 0.5");
Console.WriteLine("  - Posterior Beta(5,9) : apres 3 choix risques sur 10, decale vers 0.36");
Console.WriteLine("  - La distribution posterior est plus concentree (moins d'incertitude)");
Console.WriteLine();
Console.WriteLine("=> L'agent choisit rarement l'option risquee, confirmant un profil averse.");
Distribution Beta : Prior vs Posterior

   P(risque) | Prior Beta(2,2) | Posterior Beta(5,9)
-------------|-----------------|--------------------
        0,10 |          0,5400 |             0,2770
        0,20 |          0,9600 |             1,7274
        0,30 |          1,2600 |             3,0048
        0,36 |          1,3824 |             3,0423 <- Moyenne posterior
        0,40 |          1,4400 |             2,7669
        0,50 |          1,5000 |             1,5710 <- Moyenne prior
        0,60 |          1,4400 |             0,5466
        0,70 |          1,2600 |             0,1014
        0,80 |          0,9600 |             0,0067
        0,90 |          0,5400 |             0,0000

Interpretation :
  - Prior Beta(2,2) : distribution uniforme centree sur 0.5
  - Posterior Beta(5,9) : apres 3 choix risques sur 10, decale vers 0.36
  - La distribution posterior est plus concentree (moins d'incertitude)

=> L'agent choisit rarement l'option risquee, confirmant un profil averse.

Lecture : la conjugaison Beta-Bernoulli rend le posterior lisible sans calcul

Le posterior Beta(5,9) se lit directement depuis le prior Beta(2,2) et les données : α = 2 + 3 choix risqués, β = 2 + 7 choix sûrs — la famille Beta est conjuguée à la Bernoulli, les observations s’ajoutent aux hyperparamètres. Trois lectures dans la table : la masse du posterior s’est décalée de 0,50 vers 0,36 (l’agent évite le risque plus qu’à moitié) ; la distribution est plus concentrée (le pic monte, les queues tombent — dix observations ont réduit l’incertitude) ; et l’intervalle à 95 % [0,11 ; 0,60] reste large — avec peu de données, le profil n’est qu’estimé, pas connu. C’est la contribution propre d’Infer.NET ici : la réponse n’est pas « ρ = x » mais une distribution sur le comportement, dont on peut propager l’incertitude dans toute décision aval.

Exercice 2 : Portfolio avec Contraintes de Risque (VaR/CVaR)

Soumis par Jean-Francois De Greling (Gr02) - Implementation Python

L’etudiant a realise une traduction complete en Python du modèle de portfolio avec optimisation sous contrainte CVaR. Le code est dans exercice_portfolio.py et couvre : - Modelisation gaussienne des 3 actifs (Obligataire, Actions, Immobilier) - Calcul analytique VaR/CVaR a 95% - Optimisation scipy SLSQP sous contrainte CVaR < 5% - Recherche par grille discrete (bonus)

Résultat : l’optimum alloue ~15% Obligataire, ~30% Actions, ~55% Immobilier pour un rendement de ~5.5% avec CVaR exactement a la limite de 5%.

// Exercice : Portfolio avec contraintes de risque (VaR/CVaR) via Infer.NET

// Parametres des actifs
// Actif 1 : Obligataire (rendement moyen 3%, ecart-type 2%)
// Actif 2 : Actions (rendement moyen 8%, ecart-type 15%)
// Actif 3 : Immobilier (rendement moyen 5%, ecart-type 8%)

// TODO 1 : Creer les variables Infer.NET pour chaque actif
// Hint : Variable.GaussianFromMeanAndVariance(moyenne, variance)
//        Attention : variance = (ecart-type)^2

// TODO 2 : Definir les poids du portfolio (ex: 40% obligataire, 40% actions, 20% immobilier)
// Les poids doivent sommer a 1

// TODO 3 : Creer la variable du rendement du portfolio
// Hint : En Infer.NET pour des Gaussiennes, la somme ponderee est aussi une Gaussienne

// TODO 4 : Inferer la distribution du portfolio

// TODO 5 : Calculer VaR et CVaR a 95%
// Pour N(mu, sigma) : VaR_95 = -(mu - 1.645 * sigma)  [perte, donc signe negatif]

// Pour CVaR : phi(z) = densite normale standard en z = 1.645

// TODO 6 : Afficher les resultats et verifier la contrainte CVaR < 5%

// TODO 7 (BONUS) : Tester d'autres allocations et trouver l'optimum
// Indice : un portefeuille 100% obligataire respecte la contrainte mais a un faible rendement
//          un portefeuille 100% actions la viole probablement
//          l'optimum se trouve entre les deux

Console.WriteLine("A implementer : modelisation Infer.NET, calcul VaR/CVaR, optimisation des poids.");
A implementer : modelisation Infer.NET, calcul VaR/CVaR, optimisation des poids.

Exercice 3 : Comparaison de fonctions d’utilite pour l’investissement

En utilisant le même framework de 3 actifs (Obligataire/Actions/Immobilier), comparez les decisions d’investissement sous différentes fonctions d’utilite.

Objectifs

  1. Implementer 3 fonctions d’utilite : lineaire, CARA et CRRA
  2. Pour chaque fonction, calculer l’utilite esperee de 5 allocations
  3. Identifier l’allocation preferee selon chaque fonction
  4. Analyser l’impact de l’aversion au risque sur le choix
// Exercice : Fonctions d'utilite et decisions d'investissement

// Parametres des actifs (memes que l'exemple guide)
// Obligataire: mu=3%, sigma=2%  |  Actions: mu=8%, sigma=15%  |  Immobilier: mu=5%, sigma=8%

// TODO 1 : Definir les 3 fonctions d'utilite
// - Lineaire : U(x) = x
// - CARA (exponentielle) : U(x) = 1 - exp(-alpha * x), alpha = aversion au risque
// - CRRA (puissance) : U(x) = x^(1-gamma) / (1-gamma), gamma = coefficient de risque relatif
// Indice: pour CRRA, gamma=1 correspond a U(x) = ln(x)


// TODO 2 : Definir 5 allocations a tester
// Indice: incluez au moins un portefeuille conservateur, un agressif, et un equilibre


// TODO 3 : Pour chaque allocation, calculer mu_p et sigma_p du portefeuille
// Puis calculer E[U(R_p)] par simulation Monte Carlo (1000 tirages)
// Indice: R_p ~ N(mu_p, sigma_p^2), tirez des echantillons et moyennez U(r)


// TODO 4 : Afficher un tableau comparatif
// | Allocation | E[U] lineaire | E[U] CARA (alpha=2) | E[U] CRRA (gamma=3) | Rang |


// Question : L'investisseur CRRA avec gamma=3 fait-il le meme choix que l'investisseur CARA ?
// Pourquoi ?

Console.WriteLine("A implementer : comparaison des fonctions d'utilite.");
A implementer : comparaison des fonctions d'utilite.

10. Resume et Navigation

Concepts cles

Concept Description
Paradoxe de St-Petersbourg Montre que la valeur esperee ne suffit pas
Utilite marginale decroissante U’’(x) < 0, fondement de l’aversion au risque
CARA Aversion absolue constante, U = -e^(-ax)
CRRA Aversion relative constante, U = x^(1-rho)/(1-rho)
Coefficients Arrow-Pratt r(x) absolu, R(x) relatif
Equivalent certain CE tel que U(CE) = E[U(L)]
Dominance stochastique Comparaison sans connaitre U exactement

Pour aller plus loin

Si vous voulez… Consultez…
Decisions multi-critères DecInfer-04-Multi-Attribute
Reseaux de decision DecInfer-05-Decision-Networks
Valeur de l’information DecInfer-06-Value-Information

References

  • Arrow (1965) : Aspects of the Theory of Risk Bearing
  • Pratt (1964) : Risk Aversion in the Small and in the Large
  • Bernoulli (1738) : Specimen Theoriae Novae de Mensura Sortis
Retour au sommet