Projet Courbe de Taux Estimation de la courbe zéro coupon spline
Transcription
Projet Courbe de Taux Estimation de la courbe zéro coupon spline
Projet Courbe de Taux Estimation de la courbe zéro coupon spline polynomiaux Daniel Herlemont 18 octobre 2007 Table des matières 1 Introduction et rappels 1.1 Bon et taux zéro-coupon . . . . 1.2 Calibration de la courbe de taux 1.3 Méthodes indirectes . . . . . . . 1.4 Splines cubiques . . . . . . . . . . . . . . . . . zéro-coupon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Description des données 3 A réaliser 3.1 Lecture des fichiers . . . . . . . 3.2 Splines cubiques . . . . . . . . . 3.3 La fonction d’évaluation du prix 3.4 Calcul de la fonction d’erreur de 3.5 Optimisation . . . . . . . . . . 3.6 Moindres carrés généralisés . . . 3.7 Splines exponentielles . . . . . . 2 2 2 3 4 5 . . . . . . . . . . . . . . . . . . . . . . . . minimisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 6 7 8 9 10 13 14 4 Nelson Siegel 14 5 References 15 [1] TRUE 1 1 INTRODUCTION ET RAPPELS 1 Introduction et rappels L’objectif du projet est de reconstituer la courbe des taux zéro coupon par la méthode des splines cubiques. nota : les modélisations sont largement inspirées du livre ”Produit de taux et d’Intérêts” de Martellini and Priaulet (1999) [?]. 1.1 Bon et taux zéro-coupon La construction d’une structure par terme des taux d’intérêt fait le plus souvent référence à la notion de bon zéro-coupon. Un bon zéro-coupon de maturité m, noté B(t, m) correspond à la valeur aujourd’hui (en t) d’un euro payé dans m périodes, sans paiements intermédiaires. Le rendement implicite associé à ce bon représente le taux d’intérêt, noté y(t, m) d’un bon zéro-coupon. Une relation simple lie le bon à son taux, ce qui permet de travailler indifféremment sur l’un ou l’autre. Cette relation prend deux formes selon qu’elle est écrite en temps discret : 1 (1 + yd (t, m))m (1) yd (t, m) = B(t, m)−1/m − 1 (2) B(t, m) = e−myc (t,m) (3) B(t, m) = ou en continu : 1 log B(t, m) (4) m A un instant donné, la structure par terme des taux d’intérêt se définit comme la valeur prise par y(t, m) pour différentes valeurs de la maturité m. yc (t, m) = − 1.2 Calibration de la courbe de taux zéro-coupon La calibration de la courbe zéro coupon consiste a reconstruire la courbe des taux à partir de données observées sur le marché. Cette reconstitution est rendue nécessaire par le fait qu’il n’existe pas suffisamment d’obligations zéro-coupon (strips) cotées sur le marché. Par conséquent, il n’est pas possible d’obtenir les taux zéro-coupon pour un continuum de maturités. En outre, les obligations zéro-coupon ont souvent une moindre liquidité que les obligations à coupons. Daniel Herlemont 2 1 INTRODUCTION ET RAPPELS Il est important de faire une sélection rigoureuse des titres qui servent à la reconstitution. Il faut éliminer : les titres qui présentent des clauses optionnelles car la présence d’options rend le prix de ces titres non homogènes avec ceux qui n’en contiennent pas, les titres qui présentent des erreurs de prix. Typiquement dues à des erreurs de saisie, les titres qui sont soit illiquides, soit surliquides, et présentent donc des prix qui ne sont pas dans le marché. Il ne faut pas tracer la courbe des taux sur des segments de maturité où l’on ne dispose pas de titres. Par exemple, ne pas tracer la courbe sur le segment (20-30 ans) si l’on ne dispose pas de titres de maturités supérieures à 20 ans dans le panier. Il existe plusieurs méthodes de reconstitution (cf. cours) : – Méthode théorique directe et bootstrapping – Différents types d’interpolation (linéraire, cubiques) – Méthodes indirectes : modèle de Nelson et Siegel, splines cubiques et exponentielles Dans ce projet, nous nous intéresserons essentiellement aux méthodes les plus utilisées en pratique, à savoir les méthodes indirectes et particulièrement les ”splines cubiques”. 1.3 Méthodes indirectes Ce sont les méthodes les plus utilisées en pratique. Le principe est le suivant : pour un panier d’obligations à coupons, il s’agit de minimiser l’écart au carré entre les prix de marché et les prix reconstitués à l’aide d’une forme a priori spécifiée des taux zéro-coupon ou de la fonction d’actualisation. Soit un panier constitué de n titres. On note à la date t : – Pj prix de marché du j-ème titre – P̂j le prix théorique du j-ème titre – Fsj flux futur du j-ème titre tombant à la date s (s > t), en général Fsj sera constitué d’un coupon annuel et du principal à l’échéance. Les méthodes indirectes consistent à approcher les facteurs d’actualisation B(t, s) par une fonction f (s − t; β) dépendant de paramètres β à estimer. X X P̂j = Fsj B(t, s) = Fsj f (s; β) (5) s=s1 ,...sn s=s1 ,...sn avec s1 , ...sn le dates des flux futurs Fs1 , ...Fsn , typiquement on aura Fsi = Coupon pour i = 1, n − 1 et Fsn = Coupon + P rincipal. On cherchera les paramètres β qui minimisent l’erreur quadratique moyenne entre les prix observés et les prix calculés : n 1X (P̂j − Pj )2 min β n j=1 Daniel Herlemont (6) 3 1 INTRODUCTION ET RAPPELS La courbe des taux a en général une forme assez régulière et présentant peu de changement de convexité, on peut donc penser à l’approcher par des fonctions simples telles que polynômes, exponentielles de polynômes, etc... Nous l’approcherons par des splines cubiques. 1.4 Splines cubiques Plusieurs formes fonctionnelles de f ont été proposées. Nous retiendrons ici celle qui consiste à ajuster des splines (des polynômes de degré trois ou quatre) sur des plages de maturité choisies. Le ”raccord” entre les différentes plages s’effectue sous la contrainte de continuité et de double dérivabilité aux points de raccord. Par exemple, la fonction d’actualisation f (s) sensée représenter le prix du zéro coupon f (s) = B(0, s) sera définie par 3 splines cubiques : f0 (s) = d0 + c0 s + b0 s2 + a0 s3 pour s ∈ [0, 5] f1 (s) = d1 + c1 s + b1 s2 + a1 s3 pour s ∈ [5, 10] f2 (s) = d2 + c2 s + b2 s2 + a2 s3 pour s ∈ [10, 20] (7) (8) (9) sous la contrainte de continuité et double dérivabilité aux points de raccord de maturité 5 ans et 10 ans. f 0(i) (5) = f 1(i) (5) f 1(i) (10) = f 2(i) (10) (10) (11) avec f (i) représentant la dérivée d’ordre i (pour i=0, il s’agit de la fonction elle-même). Enfin, on imposera la contrainte évidente d’un facteur d’actualisation égal à 1 pour la maturité 0 : f0 (0) = 1 (12) Nous avons donc 12 inconnues (a0 , b0 , c0 , d0 , a1 , b1 , c1 , d1 , a2 , b2 , c2 , d2 ) et 7 contraintes (6+ 1), soit 5 degrés de liberté. d0 = 1 par la contrainte 1. Ensuite, on peut écrire les fonctions sous la forme suivante : f0 (s) = 1 + c0 s + b0 s2 + a0 s3 pour s ∈ [0, 5] f1 (s) = f0 (s) + (a1 − a0 )(s − 5)3 pour s ∈ [5, 10] f2 (s) = f1 (s) + (a2 − a1 )(s − 10)3 pour s ∈ [10, 20] Daniel Herlemont (13) (14) (15) 4 2 DESCRIPTION DES DONNÉES A l’évidence cette écriture vérifie les contraintes de continuité et double dérivabilité aux points de raccord (à vérfier, voir plus loin). Les inconnues sont c0 , b0 , a0 , a1 , a2 , au nombre de 5. La fonctionnelle peut encore s’écrire sous la forme condensée suivante : f (s) = 1 + c0 s + b0 s2 + a0 s3 + (a1 − a0 )(s − 5)3+ + (a2 − a1 )(s − 10)3+ (16) avec la notation (s − θ)3+ = max(s − θ, 0)3 . On peut généraliser à un nombre quelconque de raccords. Soient κi , pour i = 1, m, les points de raccord en ordre croissant (dans le cas précédent, on avait m = 2, κ1 = 5 et κ2 = 10). La fonction générale est alors : 2 3 f (s) = 1 + c0 s + b0 s + a0 s + m X (ai − ai−1 )(s − κi )3+ (17) i=1 Le nombre d’inconnues c0 , b0 , a0 , a1 ..., am est donc égal au nombre de noeuds plus 3. Nous avons ramené le problème de minimisation sous contrainte à un problème de minimisation quadratique sans contrainte. Commentaires : Le choix des points de raccord est une question centrale. le marché suggère l’utilisation de points charnières correspondant, par exemple, aux maturité à 1 an, 3 ans, 5 ans, 10 et 30 ans. 2 Description des données Le données utilisées sont des obligations cotées sur le marché français au 28 novembre 1995. On cherche à reconstruire la courbe des taux zéro-coupon issue du marché de la dette de l’Etat français. Les titres sélectionnés font partie des BTF (bon à taux fixe), BTAN (bon à taux annuel normalisé) et OAT (obligation assimilable du trésor) cotés sur le marché. L’ensemble du spectre des maturités est couvert (de 1 à 17 ans). Deux paniers d’obligations sont retenus : Le premier panier, dit de ”minimisation”, compte 25 valeurs et sert directement à l’obtention de la courbe. Il est disponible à l’adresse : http://www.yats.com/data/bonds/ rates-fr-minimisation.txt Le second panier, dit de ”vérification”, ne compte que 10 titres : il permet de s’assurer que la courbe est fidèlement reconstituée, y compris pour des obligations situées en dehors du premier panier. http://www.yats.com/data/bonds/rates-fr-validation.txt Les fichiers ont des formats identiques, chaque ligne correspond à une obligation d’état, les champs sont séparés par des tabulations et correspondent à : Daniel Herlemont 5 3 A RÉALISER – – – – 3 un libellé du titre (BTF, BTAN, OAT) l’échéance le coupon (la valeur faciale étant de 100) le prix du marché A réaliser 3.1 Lecture des fichiers Ecricre une fonction C pour lire les fichiers de données, sous la forme suivante : /** lecture d'un fichier d'obligations IN: filename: nom du fichier coupon: le tabelau des coupons price: tableau des prix maturity: tableau des maturité, en années OUT: n: nombre d'obligations (et donne aussi le nb d'éléments des tableaux) */ void readfile(char *filename, float coupon[], float price[], float maturity[], int *count) { // .. a faire } On rangera les données dans des tableaux (sur-dimensionnés), on notera également le nombre d’éléments des tableaux, dans des variables : // ensemble de minimisation float m_coupon[100]; float m_price[100]; float m_maturity[100]; int m_count; // ensemble de validation float v_coupon[100]; float v_price[100]; Daniel Herlemont 6 3 A RÉALISER float v_maturity[100]; int v_count; Les variables ”price”, ”coupon”, ”maturity” contiennent les prix, les coupons, les maturités en nombre d’années entre la date de cotation le 28 Novembre 1995 et la date de maturité de l’obligation. On utilisera la fonction de la manière suivante : readfile("c:/data/bonds/rates-fr-minimisation.txt" ,m_coupon,m_price,m_maturity,&m_count); readfile("c:/data/bonds/rates-fr-validation.txt" ,v_coupon,v_price,v_maturity,&v_count); Utiliser les fonctions de calcul sur les dates vues dans le TP précédent. en cas de difficultés, on pourra télécharger le fichier http://www.yats.com/data/bonds/rates-fr-declarations. h contenant les déclarations des variables globales du type ”price”, ”coupon”, ”maturity”, puis inclure ce fichier : #include "rates-fr-declarations.h" 3.2 Splines cubiques Représenter une fonction spline par une fonction en langage C. Pour cela, on définira les variables suivantes : // le nombre de points de raccord int nknots; // les coefficients c_0,b_0,a_0, ... a_m float coef[100]; /** fonction spline generale. params: IN: coef rangés dans l'ordre c_0,b_0, a_0,a_1,a_2, ... ncoef: nb d'elements dans coef knot: les points de raccords nknot: le nombre de raccords, doit etre egal à coef-3 OUT: resultat de la fonction */ Daniel Herlemont 7 3 A RÉALISER float spline(float s, float coef[], int ncoef, float knot[], int nknot) { ... a faire } On testera la fonction de la manière suivante : // test fonction spline. float knot[]={1,10}; float coef[]={-3e-02,-2e-03,-2.5e-04,2.3e-04,-2.3e-05}; printf("%f %f %f %f %f\n" ,spline(0.5,coef,5,knot,2) ,spline(1,coef,5,knot,2) ,spline(2,coef,5,knot,2) ,spline(5,coef,5,knot,2) ,spline(12,coef,5,knot,2) ); // resultat attendu //0.984469 0.967750 0.930480 0.799470 0.556856 3.3 La fonction d’évaluation du prix Ecrire la fonction d’évaluation du prix d’une obligation à l’aide de la fonction spline, sous la forme : /** fonction d'évaluation d'une obligation. coupon: coupon annuel T : maturite coef: coefficient des splines c0,b0,a0,a1,...am ncoef: nb d'elements de coef knot: les points de raccord nknot: nb de points (avec la relation nknot=ncoef-3) evaluation du prix. */ float spline_bond_price(float coupon, float T, float coef[], int ncoef, float knot[], int nknot) Daniel Herlemont 8 3 A RÉALISER { ... a faire } Tester la fonction : printf("spline_bond_price test %f %f %f\n" ,spline_bond_price(9.5,5.5,coef,ncoef,knot,nknot) ,spline_bond_price(8.5,1.1,coef,ncoef,knot,nknot) ,spline_bond_price(8.125,3.5,coef,ncoef,knot,nknot) ); //resultats attendus = 105.445198 112.823029 123.365555 3.4 Calcul de la fonction d’erreur de minimisation Calculer l’erreur quadratique moyenne d’approximation : n ERQM = 1X j (P̂ − P j )2 n j=1 (18) avec P j le prix (coté) de l’obligation j et P̂ j le prix approché à l’aide de la fonction spline. Erreur que l’on cherchera donc à minimiser. La fonction C aura la forme suivante: /* erreur quadratique moyenne de l'approximation. pour un ensemble d'obligations de nbonds, en donnant les coupons, les maturité, les prix cotés ainsi que le parametres des splines pour calculer les prix approchés. prix approchés */ float mean_square_error(int nbonds ,float coupon[], float maturity[], float price[] ,float coef[], int ncoef,float knot[], int nknot) { ... a faire } Daniel Herlemont 9 3 A RÉALISER // test printf("test erreur quadratique moyenne"); float x=mean_square_error(m_count,m_coupon,m_maturity,m_price ,coef,ncoef,knot,nknot); printf("resultat attendu=%f\n",x); // resultat attendu = 107.717995 3.5 Optimisation Nous recherchons ici les coefficients des splines cubiques qui minimisent l’erreur quadratique moyenne. Le problème peut se ramener à celui d’une optimisation quadratique, du même type qu’une régression. Ces méthodes seront étudiées ultérieurement. En attendant, nous utiliserons un simple optimiseur multidimensionnel et sans contrainte : hooke (Nonlinear Optimization using the algorithm of Hooke and Jeeves, 1994). Cet optimiseur ne fait pas d’hypothèses trop contraignantes sur les fonctions qui peuvent être différentiables ou non. On pourra télécharger les fichiers à partir de http://www.yats.com/downloads. Récupérer les fichiers hooke.c et hooke.h. On pourra lire les commentaires du fichier hooke.c ainsi que consulter un exemple d’utilisation en téléchargeant hooke-test.c Compiler à l’aide de la commande : gcc -c hooke.c // ce qui genere le fichier hooke.o Pour utiliser cet optimiseur, on fera un include du .h dans les codes sources qui l’utilisent : #include "hooke.h" Puis lors de la compilation, on ajoutera hooke.o à la ligne de commande : gcc monprogramme.c hooke.o Tester le programme hooke avec une fonction à plusieurs variables dont on connaı̂t le résultat de la minimisation. On commencera par la fonction très simple : f(x,y)=(x-1)2+(y-1)2 avec la solution évidente (x,y)=(1,1) #include <stdio.h> Daniel Herlemont 10 3 A RÉALISER #include <math.h> #include "hooke.h" float f(float x[], int nx){ return (pow((x[0]-1),2)+pow((x[1]-1),2)); } int main(){ float xInit[]={0,0}; // vecteur initial float xRes[2]; // vecteur resultat int nx=2; // dimension int i; hooke(f,nx,xInit,xRes,0.8,1e-6,1000); for(i=0;i<2;i++){ printf("xRes[%d]=%lf\n",i,xRes[i]); } // resultat attendu 1 1 } Puis sur une fonction un peu plus complexe : la fonction de Rosenbrock : f(x,y)=100 (y-x2)2+(1-x)2 dont le minimum est atteint pour x = 1 et y = 1 On utilisera ce programme pour rechercher les coefficients des splines qui minimisent l’erreur quadratique, sous la forme suivante : /* fonction à optimiser. @params IN x: coef des splines dans l'ordre c0,b0,a0,a1,...am nvars: le nombre d'elements de x @returns l'erreur quadratique. */ float func(float x[], int nvars) { } Cette fonction est ensuite passée en paramètre dans l’optimiseur, de la manière suivante // optimisation Daniel Herlemont 11 3 A RÉALISER float rho=0.7; // paramètre de convergence hooke // plus rho est proche de 1 et moins plus l'optimisation est lente // mais plus précise. float epsilon=1e-8; int itermax=5000; // nb d'iterations max int iter = hooke(func,ncoef, coef, coef, rho, epsilon, itermax); if (iter>=itermax) error("too many iterations"); printf("*****************************************\n"); printf("resultats de l'optimisation, nb iterations=%i\n",iter); printf("raccords: nknot=%i knots=",nknot); for (i = 0; i < nknot; i++) printf("%f ", knot[i]); printf("\n"); printf("coef spline: "); for (i = 0; i < ncoef; i++) printf("%f ", coef[i]); printf("\n"); // recalculer l'erreur quadratique de minimisation // on utilise le resultat de l'optimisation comme coefs. x=mean_square_error(m_count,m_coupon,m_maturity,m_price ,coef,ncoef,knot,nknot); printf("erreur quadratique apres optimisation=%f\n",x); printf("ecart type=%f\n",sqrt(x)); x=mean_square_error(v_count,v_coupon,v_maturity,v_price ,coef,ncoef,knot,nknot); printf("erreur quadratique de validation=%f\n",x); printf("ecart type=%f\n",sqrt(x)); L’erreur est bien plus faible que dans le cas précédent. Cependant l’écart reste encore trop grand. On pourra ajouter des splines à d’autres points de raccord judicieusement choisis. Refaire l’optimisation en utilisant 5 splines avec le points de raccord à 1 ans, 3 ans, 7 ans, et 10 ans. Commenter. Résultats attendus (les résultats peuvent varier légèrement d'une machine à une autre) Daniel Herlemont 12 3 A RÉALISER ***************************************** resultats de l'optimisation, nb iterations=51 raccords: nknot=2 knots=1.000000 10.000000 coef spline: -0.032434 -0.002876 -0.000166 0.000227 -0.000004 erreur quadratique apres optimisation=3.638351 ecart type=1.907446 erreur quadratique de validation=1.408044 ecart type=1.186610 ***************************************** resultats de l'optimisation, nb iterations=51 raccords: nknot=4 knots=1.000000 3.000000 7.000000 10.000000 coef spline: -0.051563 0.009567 -0.001742 -0.001846 0.000790 -0.000025 -0.000000 erreur quadratique apres optimisation=3.662073 ecart type=1.913654 erreur quadratique de validation=1.717703 ecart type=1.310612 On constate donc que l’erreur sur l’ensemble de minimisation est réduite. Mais l’erreur sur l’ensemble de validation augmente ... Expliquer pourquoi l’erreur de validation se détériore lorsqu’on augmente le nombre de splines. 3.6 Moindres carrés généralisés Dans le programme d’optimisation, on considère implicitement que toutes les erreurs sont comparables (autrement dit la variance est constante). Or on constate un plus grande imprécision sur les taux longs terme que sur les taux court terme. Afin d’augmenter la qualité de reconstitution, Vasicek et Fond (1982) ont proposé de surpondérer les titres courts terme par un facteur ωj2 2 Dj2 (t)P j dP j 2 = (19) ωj = drj (t) (1 + rj (t))2 Ou rj (t) et Dj (t) sont respectivement le taux de rendement actuariel et la duration de l’obligation j à la date t. On cherche alors a minimiser !2 X Pj − P̂j (20) ωj j=1,n Daniel Herlemont 13 4 NELSON SIEGEL Ce choix est motivé par le fait que plus une obligation est long terme, plus l’estimation est difficile ; l’obligation de durée 15 ans nécessite la connaissance de 15 taux zéro coupon. D’autre choix sont possible et on pourra prendre ωj2 = Tj2 (21) avec Tj la maturité de l’obligation j. A faire effectuer l’optimisation avec ωj = Tj 3.7 Splines exponentielles Vasiceck et Fong (1982) ont introduit les splines exponentielles, plus à même de modéliser les taux zéro coupon sous la forme fi (s) = di + ci e−us + bi e−2us + ai e−3us (22) pour la spline sur le segment i. Les mêmes contraintes s’appliquent que dans le cas polynomial, pour obtenir la régularité de la courbe. Les splines exponentielles requièrent une étape supplémentaire : l’estimation du paramètre u que l’on peut considéré comme le taux pour une maturité infini u = lim f (s) (23) s→∞ A faire Effectuer les mêmes opération d’optimisation et de validation. Au préalable, on fixera u en utilisant les résultats des splines polynomiaux 4 Nelson Siegel L’un des défauts de la méthode précédente tient au fait que les coefficients n’ont pas d’interprétation financière. Le modèle de Nelson Siegel apporte une réponse partielle a ce problème, sous la modélisation suivante : X X P̂j = Fsj f (s) = Fsj f (s; β) (24) s=s1 ,...sn s=s1 ,...sn avec s s s f (s) = β0 + β1 exp(− ) + +β2 exp(− ) τ τ τ – β0 : facteur de niveau ; il s’agit du taux long. – β1 : facteur de rotation ; il s’agit de l’écart entre le taux court et le taux long Daniel Herlemont (25) 14 – β2 : facteur de courbure – τ : paramètre d’échelle destiné à rester fixe au cours du temps Cette méthode a été adoptée par la banque de France. A faire – estimer les paramètres en utilisant le panier d’estimation, – évaluer la qualité de l’estimation à l’aide du panier de validation, – comparer à la méthode des splines. 5 References [1] MARTELLINI & PRIAULET. ”Produits de taux d’intérêt”. Economica, Paris, 1999. Daniel Herlemont 15