Introduction au pricing d`option en finance

Transcription

Introduction au pricing d`option en finance
Introduction au pricing d’option en finance
Olivier Pironneau
Cours d’informatique Scientifique
1
Modélisation du prix d’un actif financier
Les actions, obligations et autres produits financiers cotés en bourse ont des
prix fluctuants établis en fonction de l’offre et de la demande.
En finance, on confond le nom du produit et son prix. Ainsi St désigne
le prix d’un actif financier, par exemple l’action Renault, à l’instant t.
S’il n’y avait pas d’aléas dans les marchés on aurait St+δt = St (1 + µδt) où µ
est la tendance de l’actif, à la hausse (µ > 0) ou à la baisse (µ < 0). Cette
relation exprime simplement que si l’action Renault par exemple qui vaut au1
) = 90.3$
jourd’hui 90$ monte de 4% en un an alors elle vaudra 90(1 + 0.04 12
dans un mois.
Lorsque le taux d’intérêt bancaire vaut r il est raisonnable de penser que
µ = r, car si µ > r il serait plus avantageux d’acheter ce produit financier
que de prêter au taux r, et inversement, personne ne garderait le produit si
µ < r. Mais le marché n’étant pas entièrement prévisible, on écrit
St+δt = St (1 + rδt + σ(Wt+δt − Wt ))
où Wt est un processus aléatoire brownien et σ est un coefficient numérique
appelé la “volatilité”.
Pour la suite, nous n’utiliserons qu’une seule propriété de W :
√
Wt+δt − Wt = δt N (0, 1)
1
où N (0, 1) est le processus gaussien centré en zéro et de variance unité1
Là encore la modélisation est très simple et dit simplement que la partie
aléatoire est d’autant plus grande que le pas de temps δt est grand et que la
volatilité est grande.
Ainsi pour prédire la valeur de l’actif S le lendemain, le modèle a un paramètre,
σ, ajusté chaque jour sur les données de la veille.
Pour prédire la valeur due S dans un an il faut répéter le processus 365 fois.
1.1
Programmation
La génération d’un nombre aléatoire gaussien va se faire par la procédure
gauss() ci-dessous. Celle-ci repose sur l’utilisation de la fonction système
random() qui rend un entier aléatoire compris entre 0 et un grand nombre
RAND MAX (nombre prédéfini dont la valeur dépend de la précision arithmétique
de l’ordinateur).
Ainsi chaque fois l’instruction x = random() retourne une valeur différente
pour x.
Notez que (1+random())/double(1+RAND MAX) est un nombre quelconque entre 0 et 1 avec une probabilité uniforme.
On démontre que si x et y sont deux
q nombres aléatoires de probabilité uniforme entre 0 et 1 alors cos(2πx) −2 log(y) est un nombre aléatoire sur
R := (−∞, +∞) avec une distribution de probabilité gaussienne centrée en
0 et de variance 1.
On obtient donc le programme suivant:
#include <iostream>
//
pour les entrees sorties
#include <cmath>
//
pour les fonctions, cos, log...
#include <vector>
//
pour les vecteurs de la STL
#include <fstream>
//
pour la gestion des fichiers
using namespace std;
//
pour donner un sens a cout...
const
double two_pi =2*M_PI; //
constante de la lib cmath
1
On rappelle qu’une variable aléatoire est gaussienne N (µ, σ) si la probabilité qu’elle
appartienne à (x, x + dx) est (2πσ 2 )−1/2 exp(−(x − µ)2 /(2σ 2 ))dx. Remarquez que si x est
N (0, 1), ax est N (0, a).
2
double gauss()
{
double x= double(1.+random())/double(1.+RAND_MAX);
double y= double(1.+random())/double(1.+RAND_MAX);
return sqrt( -2 *log(x) )*cos(two_pi*y);
}
void EDOstoch(vector<double> &S,
double S0,
int M,
double sigma,
double r )
{
//
historique de S, valeur initiale de S, nb de
jours, vol et taux
const double dt=1./M, sdt =sigma*sqrt(dt);
S[0]= S0;
for(int i=1;i<M;i++)
S[i]= S[i-1]*( 1 + r*dt + gauss()*sdt );
}
int main()
{
const double sigma=0.2, r=0.1;
//
volatilite, taux
const int M=365;
double So;
vector<double> S(M);
//
prix de l’actif chaque jour
cout<<"Entrer la valeur de So ";
cin >>So;
EDOstoch(S,So,M,sigma,r);
cout <<"Valeur de S apres un an "<<S[M-1]<<endl;
//
ecriture des valeurs intermediaires dans un fichier
//
pour visualiser le resultat utiliser gnuplot: plot
"result.dat" w l
ofstream ff("result.dat");
for(int i=0;i<M;i++)
ff<<S[i]<<endl;
return 0;
}
Remarque 1 Pour obtenir un entier aléatoire, random() utilise l’overflow. Par
exemple sur une machine 64 bits, si s est un entier plus grand que 232 le résultat
de s∗s étant supérieur à 264 −1, il ne tient pas dans le registre du multiplicateur de
la machine, il y a overflow et la machine produit n’importe quoi quand on calcule
s ∗ s. Le nombre s utilisé dans random() s’appelle en anglais seed. Le résultat de
random() est utilisé comme seed pour l’appel suivant de random(). Par défaut au
début, s est toujours le même; donc si on exécute plusieurs fois ce programme on
3
obtiendra toujours les même valeurs. Pour obtenir des valeurs différentes à chaque
exécution, ce qui est légitime puisque random() est censé générer des nombres
aléatoires, il faut changer seed en rajoutant au début dans le main():
srand(time(NULL));
La fonction srand ne rend rien mais initialise seed à un entier calculé à partir de
l’horloge. Deux exécutions à deux temps différents donneront donc deux résultats
différents.
160
"result.dat"
155
150
145
140
135
130
125
120
115
0
50
100
150
200
250
300
Figure 1: Une réalisation de St sur un an.
4
350
400
2
Pricing d’option
Une option sur un actif financier est un contrat d’achat ou de vente de l’actif
à un prix donné à une date future. Ce contrat est anonyme, il peut donc être
revendu et le problème à résoudre est celui de la détermination de son prix.
Prenons un exemple concret: une banque possède un actif qui vaut aujourd’hui S0 = 100$; elle souhaite se couvrir contre les fluctuations du marché
et pour cela elle fait savoir qu’elle est prête à payer un tiers un prix P0 (dollars, euros...) une obligation conditionnelle d’achat de l’action dans un an à
105$.
L’obligation est conditionnelle dans le sens où celui qui à reçu les P0 est forcé
d’acheter l’action si la banque le souhaite mais il ne peut forcer la banque
à vendre. Le contrat est nominatif dans le sens que le tiers s’est engagé et
qu’il doit donc être localisable sur la période (0,T).
On dit alors que la banque a émis une option put P sur S de strike K=105$
et de maturité T=1 an.
• Le premier problème est de déterminer une valeur raisonnable pour P0 ?
• La banque peut ensuite vouloir vendre l’actif à une date ultérieure mais
comment établir un prix raisonnable pour ce put?
Notez que ce put n’a de sens que si l’on possède aussi l’actif (on dit le
sous-jacent) sur lequel il est basé; cependant on peut toujours l’acheter plus
tard sur le marché, c’est pourquoi cette option peut avoir une vie autonome
indépendamment du sous-jacent (mais toujours avec le même tiers contractant).
Modélisation: Si le marché est fluide, il est raisonnable de supposer que le
prix Pt de P à une date t > 0 est l’espérance du profit que le propriétaire de
St et Pt fera à la date T , escompté en t, soit
Pt = e−r(T −t) E(K − ST )+
où f + (s) = max(f (s), 0) et E désigne
l’espérance au sens de la théorie des
R
probabilités, c’est à dire l’intégrale R (K − s)+ ρ(s)ds , lorsqu’une densité de
5
probabilité ρ() existe pour ST .
En effet si dans un an l’option est cotée en bourse à ST , le profit à la vente
est K − ST si K > ST et zéro sinon. Or n$ au temps t vaudront ner(T −t) à
la date T (exprimée en portion d’année) car ils peuvent être placés au taux r.
Lorsque dt est petit, on introduit la notation: dSt = (St+dt − St ); alors
le problème s’écrit:
dSt = St (rdt + σdWt ), St=0 = S0 donné
Pt = e−r(T −t) E(K − ST )+
(1)
C’est le modèle de Black et Scholes.
Programmation: Il suffit de faire générer par le programme N réalisations
Sn de ST et de faire
−1
e−r(T −t) NX
Pt =
(K − Sn )+
N
n=0
D’où le programme suivant:
#include <iostream>
#include <cmath>
#include <fstream>
#include <cassert>
using namespace std;
const
double two_pi =2*M_PI;
double gauss();
double
{
EDOstoch(double S0,
int M, double sigma, double r )
const double dt=1./M, sdt =sigma*sqrt(dt);
double S= S0;
for(int i=1;i<M;i++)
S *= (1.+gauss()*sdt+r*dt);
return S;
}
6
int main()
{
const double r=0.1, sig=0.2, K=140, S0=120, t=12;
double option = 0;
int T=365, N=50000;
for(int I=0;I<N;I++){
double aux = K-EDOstoch(S0,365,sig,r);
if(aux<0) aux=0;
option +=aux/N;
}
cout <<"L’option apres "<<t<<" jours vaut "
<< option*exp(-r*(T-t)/365) <<endl;
return 0;
}
L’exécution de ce programme produit
Valeur de l’option apres 12 jours 13.6185
2.1
L’équation aux dérivées partielles de Black & Scholes
On démontre2 grâce au calcul de Itô que (1) est équivalent à
Pt = u(T − t, St )
où u(x, t) est la solution de
∂u
∂u σ 2 x2 ∂ 2 u
−
−
rx
+ ru = 0 dans R+ × (0, T ), u(x, 0) = (K − x)+
∂t
2 ∂x2
∂x
Remarque 2 Notez que cette EDP contient implicitement des conditions aux
limites en 0 et +∞.
• En x = 0, l’EDP donne ∂t u+ru = 0, u(0, 0) = K, donc u(0, t) = Ke−rt .
• Si on suppose que u est dans L2 (R+ ) alors limx→+∞ u(x, t) = 0.
Exercice 1 Montrer que l’EDP peut aussi s’écrire sous forme divergentielle
∂u
∂ σ 2 x2 ∂u
∂u
−
(
) − βx
+ ru = 0 dans R+ × (0, T ), u(x, 0) = (K − x)+
∂t ∂x 2 ∂x
∂x
avec β = r − σ 2 − xσ ∂σ
.
∂x
2
Paul Wilmott, Sam Howison, and Jeff Dewynne. The mathematics of financial derivatives. Cambridge University Press, Cambridge, 1995. A student introduction.
7
3
Option panier sur 2 sous-jacents
Prenons maintenant l’exemple d’une banque qui pour minimiser encore les
risques combine une action Renault avec une action Peugeot avec l’idée que
si l’une baisse, l’autre montera et que la somme des deux est plus stable que
chacune séparée. Soient St1 , St2 les prix de ces deux actions. On prend le
modèle suivant
dSt1 = St1 (rdt + dWt1 + dWt2 )
dSt2 = St2 (rdt + dWt2 + dWt1 )
(2)
Comme précédemment Wt1 , Wt2 sont deux processus gaussiens mais tels que
E(dW 1 )2 = dtσ12 , E(dW 2 )2 = dtσ22 , E(dWt1 dWt2 ) = dtqσ1 σ2
Notez que si q = 0 on obtient le modèle précédent pour chacun des actifs et
donc q mesure la corrélation entre les deux actifs.
Un option put construite sur la somme S 1 + S 2 pour un strike K et une
maturité T aura donc comme prix l’espérance du bénéfice escompté, soit
Pt = e−r(T −t) E(K − ST1 − ST2 )+
Equation aux dérivées partielles : Dès qu’une quantité déterministe dépend
de la solution d’une équation différentielle stochastique, le calcul de Itô
s’applique. Ici, il donne
Pt = u(T − t, St1 , St2 ) où u est la solution de
∂2u
∂u
∂u
∂u σ12 x2 ∂ 2 u σ22 y 2 ∂ 2 u
−
−
−
qσ
σ
xy
− rx
− ry
+ ru = 0
1
2
2
2
∂t
2 ∂x
2 ∂y
∂x∂y
∂x
∂y
u(x, 0) = (K − x − y)+
(3)
4
Calcul d’une courbe d’option par Monte-Carlo
#include <iostream>
8
#include <cmath>
#include <fstream>
using namespace std;
const
double two_pi =2*M_PI;
class PriceMC{
public:
double r,sigma,K,T,S0;
//
taux, vol, strike,
matur,actif
double t, u;
//
valeur de l’option au temps t
double gauss();
double EDOstoch(int M);
double getPutPrice(int N, int M);
PriceMC(double r1, double sigma1, double K1, double T1,
double S01)
: r(r1),sigma(sigma1), K(K1), T(T1), S0(S01){ }
};
//
/////////////////////// implementation /////////////////
double PriceMC::gauss(){
double x= double(1.+random())/double(1.+RAND_MAX);
double y= double(1.+random())/double(1.+RAND_MAX);
return sqrt( -2 *log(x) )*cos(two_pi*y);
}
double
PriceMC::EDOstoch(int M){
const double dt=T/M, sdt =sigma*sqrt(dt);
double S= S0;
for(int i=1;i<M;i++)
S *= (1+r*dt+gauss()*sdt);
return S;
}
double PriceMC::getPutPrice(int N, int M){
double option = 0;
for(int n=0;n<N;n++){
double aux=K-EDOstoch(M);
if(aux<0) aux=0;
option += aux/N;
}
return option*exp(-r*(T-t));
}
//
//////////// end class PriceMC //////////////////////
int main(){
srandom(time(NULL));
PriceMC p(0.01,0.2,140,1,100);
9
//
r, sigma, K,T,S0
p.t = 0.;
p.u = p.getPutPrice(5000,100);//
nb trials, nb time steps
cout <<"Valeur de l’option apres "<<p.t<<" jours "<< p.u <<endl;
//
gnuplot pour S0->p.u: plot "option.dat" using 1:2 w l
ofstream ff("option.dat");
for(p.S0=0; p.S0<250; p.S0+=10){
p.u =p.getPutPrice(50000,100);
cout<<p.S0<<"\t"<<p.u<<endl;
ff<<p.S0<<"\t"<<p.u<<endl;
}
return 0;
}
140
"option.dat" using 1:2
120
100
80
60
40
20
0
0
50
100
150
200
250
Figure 2: Résultat du programme ci-dessus pour le calcul d’un put.
10
5
5.1
Annexe: deux arguments pour justifier l’EDP
Le cas déterministe
Lorsque σ = 0 le problème n’est pas stochastique et se réduit à
dSt = St rdt, S(t0 ) = S0 ,
P0 = e−r(T −t0 ) (K − ST )+
Ici c’est volontairement que nous ne prenons pas t0 = 0. La solution de ce
problème est
St = er(t−t0 ) S0 ,
P0 = e−r(T −t0 ) (K − er(T −t0 ) S0 )+
On en déduit que
∂P0
= re−r(T −t0 ) (K − er(T −t0 ) S0 )+ + e−r(T −t0 ) 1(K−er(T −t0 ) S0 )+ S0 rer(T −t0 )
∂t0
∂P0
= −e−r(T −t0 ) 1(K−er(T −t0 ) S0 )+ er(T −t0 )
(4)
∂S0
et donc que
∂P0
∂P0
= rPt − rS0
∂t0
∂S0
qui est l’EDP de Black-Scholes dans le cas σ = 0.
5.2
Le calcul de Itô
Soit Xt un processus verifiant dXt = µdt + σdWt et f (Xt , t) à valeurs réelles
fonction des statisitiques de Xt et non pas des valeurs (réalisations de) Xt ,
alors
∂f
∂ 2f σ2
∂f
dt +
µdt +
dt
df =
∂t
∂X
∂X 2 2
Autrement dit, il faut pousser le développement de Taylor justqu’a l’ordre
2 pour
√ avoir tous les termes d’ordre 1 a cause du fait que dWt est d’ordre
O( t).
11