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