Projet de mathématique financi`ere Programmation DLL de
Transcription
Projet de mathématique financi`ere Programmation DLL de
Le 24 mai 2005 Projet de mathématique financière Programmation DLL de deux fonctions financières consommatrices de temps Par : Arthur Pham Yoan Renard Bou Ly Wu I.I.E Institut d’Informatique d’Entreprise 2004 - 2005 Projet MAF - DLL 1 Introduction On entends souvent parler de DLL, pour Dynamic Link Library, qui sont apparus avec les premières versions de Windows. Pour rester simple, une DLL est une collection de fonctions qui est chargée dynamiquement à l’exécution d’une application. Une DLL ne contient de fonction main, mais de 3 fonctions Entry, LibMain, Exit. Une DLL est généralement écrite en C/C++, apportant rapidité et efficacité, tout en apportant de la modularité au code. Ainsi pour notre projet, la DLL de pricing pourrait être utilisée très simplement depuis un autre environnement qu’Excel. De plus, il est préférable d’avoir plusieurs DLLs qui se chargent quand l’application en a besoin plutot que d’avoir un énorme exécutable qui occupe une grande quantité mémoire. Parmi les inconvénients des DLLS, on peut citer le problème de la gestion des versions des DLLs, et du déboggage. Notre projet de voir concrètement les gains, principalement en terme de temps, qu’on pouvait espérer sur le calcul d’option par monte carlo et sur le calcul d’option par arbre disjoint. Projet MAF - DLL 1 1.1 2 Réaliser une DLL sous Microsoft Visual C++ et l’utiliser avec Microsoft Excel Création d’une DLL Les outils nécessaires à la réalisation de la DLL sont : Visual C++ 6.0 et Microsoft Excel. Présentation de la méthode Étape 1 Démarrer Microsoft Visual C++ 6.0 et fermer tous les espaces de travail existants (si certains sont ouverts). Étape 2 Cliquer sur (File | New), choisir Win32 Dynamic Link Library parmi les projets proposés et sélectionner dans la zone de saisie Location le répertoire dans lequel votre projet sera créé. Appeler votre projet DllExample. Voir le diagramme ci-dessous : Étape 3 Cliquer sur OK. Dans la boı̂te de dialogue suivante il vous sera demandé le type de DLL que vous souhaitez créer. Choisir alors la seconde option c’est-à-dire : A simple DLL project. Comme indiqué sur le diagramme suivant, cliquer alors sur Finish puis OK. Projet MAF - DLL 3 Étape 4 Vous pourrez alors voir les classe créées dans l’onglet class view. Voir la figure ci-après. Cliquer sur le symbole (+) pour explorer les classes et cliquer à nouveau sur le symbole (+) du dossier principal pour voir l’objet DllMain comme indiqué sur la capture en bas à droite. Projet MAF - DLL 4 Étape 5 Double cliquer sur l’objet DllMain pour en obtenir le code source dans le workspace sur la droite. Vous devrez obtenir le listing suivant : 1 2 3 4 5 6 7 8 9 10 // DllExample . cpp : Defines the entry point for the DLL application . // # include " stdafx . h " BOOL APIENTRY DllMain ( HANDLE hModule , DWORD ul_reason_for_call , LPVOID lpReserved ) { return TRUE ; } Étape 6 Ajouter les lignes suivantes de telle sorte que votre code ressemble au code présenté ci-après : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 // DllExample . cpp : Defines the entry point for the DLL application . // # include " stdafx . h " BOOL APIENTRY DllMain ( HANDLE hModule , DWORD ul_reason_for_call , LPVOID lpReserved ) { return TRUE ; } __declspec ( dllexport ) double __stdcall Multiply ( double first , double second ) { return ( first * second ); } Étape 7 Maintenant choisir (File | New) et choisir le type Text File. Nommer le fichier DllExample.def comme indiqué : Projet MAF - DLL 5 Étape 8 Maintenant choisir l’onglet fie view et ajouter les quelques lignes qui suivent. Après sauver le fichier qui doit ressembler au listing suivant : 1 2 3 4 5 6 ; DllExample . def LIBRARY " DllExample " DESCRIPTION ’ DllExample Windows Dynamic Link Library ’ EXPORTS ; Explicit exports can go here Multiply Étape 9 Vous pouvez alors construire votre DLL en cliquant sur l’icône build. Normalement vous devriez voir apparaı̂tre en bas de la fenêtre dans laquelle figure le code le message : DllExample.dll - 0 error(s), 0 warning(s) La partie concernant la création de la DLL est maintenant terminée. Nous allons maintenant lier la DLL créée à l’application Excel de Microsoft. Projet MAF - DLL 1.2 6 Utilisation de la DLL sous Excel La première étape va consister à déplacer la DLL créée dans un dossier de l’application Excel, ou l’application sera en mesure de trouver le fichier DLL. Une possibilité est de placer la DLL dans le répertoire C:\Program Files\Microsoft Office\Office Trouver la localisation exacte de ce répertoire et copiiez y la nouvelle DLL que vous venez de créer. Étape 1 Ouvrir maintenant Excel et choisir (Tools | Macro | Visual Basic Editor) ou juste appuyer sur les touches Alt+F11 afin d’ouvrir l’éditeur Visual Basic. Étape 2 Insérer un nouveau module (Insert | module). Entrer le code suivant dans cette fenêtre. Remarque, ne pas appuyer sur la touche ENTER avant la fin de chaque déclaration. Si vous devez appuyer sur ENTER avant la fin d’une déclaration taper ensuite un tiret bas (” ”) afin d’indiquer la suite de votre déclaration. 1 2 Declare Function Multiply Lib " DllExample . DLL " ( ByVal First As Double , ByVal Second As Double ) As Double 3 4 Sub addins () 5 6 End Sub Étape 3 Dans l’éditeur Visual Basic sélectionner (Run | Run Sub / User Form). Il vous sera demandé de saisir le nom d’une Macro. Taper alors MyDLLExample puis appuyer sur Create. Vous venez d’enregistrer votre fonction et elle est maintenant disponible sur votre feuille de travail (worksheet). Elle sera accessible depuis (Insert | Function | User defined) dans la feuille de travail. Sauver le code dans l’éditeur Visual Basic (File | Save Book 1). Saisir MyExample et sélectionner le type Microsoft Excel Add-in. Étape 4 Revenir sur la page de travail Microsoft Excel et sélectionner alors : (Tools | Addins). Cliquer sur browse et sélectionner le fichier MyDLLExample . Assurez vous que le fichier soit bien sélectionné et cliquez alors sur OK. Étape 5 Pour terminer, tester votre fonction sous Excel comme vous auriez testé n’importe quelle autre fonction. Projet MAF - DLL 7 Cette méthode est exactement, étape après étape celle que nous avons suivi pour développer notre calcul de la loi inverse, la seule différence bien entendue étant le code de la fonction à partir de laquelle nous calculons l’inverse de la loi normale centrée réduite. Nous allons maintenant présenter l’algorithme que nous avons adopté pour calculer plus rapidement qu’Excel l’inverse de la loi normale. 2 2.1 Calcul d’option par la méthode de Monté Carlo Présentation On appelle méthode de Monte-Carlo toute méthode visant à calculer une valeur numérique, et utilisant des procédés aléatoires, c’est-à-dire des techniques probabilistes. Cette méthode peut être utilisée dans l’évaluation du prix des options par la méthode présentée ci-après : En prenant S = 100, σ = 20% pa, µ = 25% pa, r = 10% pa, T = 1 year, K = 95 C = e−rT [max(ST − K, 0)] = e−0.1 [max(ST − 95, 0)] On génère un grand nombre de cours à l’échéance ST issus d’une loi lognormale et on mesure la moyenne. √ σ2 ST = S0 exp[r − T + σε T ] avec ε ∼ Φ(0, 1) 2 0.1 − 0.22 i + 0.2εi S1 = 100 exp 2 avec les i tirés dans la loi normale standard Cependant, cette méthode de calcul exige dans le cadre de notre expérience l’inversion de la loi normale centrée réduite. Ce calcul bien que pouvant être exécuté sous Excel requiert une durée dont l’augmentation en fonction du nombre de valeurs est plus que considérable ; en effet suivant la machine sur laquelle est exécutée le programma cette valeur peut varier entre 15 et 30 secondes c’est-à-dire une éternité à l’échelle informatique. Nous avons donc tenté de réduire cette valeur au maximum, en implantant nous-mêmes une DLL, qui réalise elle-même le calcul de l’inverse de la loi normale centrée réduite. Après avoir présenté la méthode pour construire une DLL exécutable depuis le programme Microsoft Excel, nous détaillerons l’algorithme que nous avons utilisé pour inverser la loi normale centrée réduite et les résultats obtenus. 2.2 Algorithme du calcul de l’inverse de la loi Normale centrée réduite L’algorithme que nous avons implanté permet d’inverser la fonction de répartition de la loi normale centrée réduite avec une erreur relative dont la valeur absolue est inférieure à 1, 15.10−9 . 2.2.1 Présentation de l’algorithme −1 L’algorithme utilise le faitque si F (p) est la fonction inverse de la loi normale centrée 1 est une fonction impaire. L’algorithme utilise deux réduite, alors G−1 (p) = F −1 p + 2 Projet MAF - DLL 8 algorithmes de recherche de minimums distincts : une approximation des rationnels est utilisée pour la région centrale de la courbe, et un autre algorithme est utilisé pour les queues de fonction. La région centrale est déterminée de la manière suivante : pour p ∈ [0.0242, 0.97575]. Pour cette région le premier algorithme est utilisé directement. Pour les queues de la fonction de répartition, c’est-à-dire lorsque p < 0.02425 ou lorsque p > 1 − 0.02425 = 0.97575, l’argument est d’abord modifié par le biais d’une transformation non linéaire, avant que le premier algorithme ne lui soit appliquée. 2.2.2 Qualité de l’algorithme Pour expliquer en quelques mots la qualité de l’algorithme, la valeur absolue de l’erreur est inférieure à 1, 15.10−9 sur l’ensemble de la région. Par la suite, supposons que p soit la probabilité (l’argument de l’algorithme), et x le quantile correspondant (la sortie désirée de l’algorithme), et xapprox la valeur approximative de x retournée par l’algorithme. La valeur retour de l’algorithme, xapprox , a une erreur relative par rapport à la vraie xapprox − x . Cette erreur relative a une valeur absolue qui valeur donnée par la formule : x est inférieure à 1, 15.10−9 dès lors que x > −38. Ce qui se produit pour des valeurs de x 6 −38 n’est pas vraiment un problème. Premièrement, la probabilité d’avoir une valeur aléatoire de loi normale centrée réduite inférieure à −38 est approximativement de 2.885428351.10−316 . Pour des raisons pratiques, on considérera que cette probabilité est nulle - des événements avec une probabilité d’apparition si faible ne surviennent pas. Deuxièmement, en supposant que nous utilisons la double précision arithmétique IEEE, qui est disponible sur la plupart des ordinateurs de nos jours, les nombres inférieurs à 2−1022 (approximativement 2, 225073859.10−308 ) sont appelés anormaux. De tels nombres, peuvent certes être représentés mais pas avec une précision parfaite. Personne ne peut alors s’attendre à une erreur relative de l’ordre de 1, 15.10−9 pour la valeur de retour pour des valeurs d’entrée inférieures à −38 juste parce que la valeur d’entrée de la fonction ne peut pas être représentée avec autant de précision. 2.3 Implémentation du calcul d’option par la méthode de Monté Carlo Nous avons calculé sous excel le cash flow du call pour 10000 nombres aléatoire uniforme. Pour cela, nous procédons successivement par étape : – Génération d’un nombre aléatoire uniforme entre 0 et 1 – Calcul du nombre d’écart type de ε : loi normale inverse du nombre généré précédemment 0, 22 – Calcul du rendement généré : 0, 1 − + 0, 2ε 2 0, 22 – Calcul du rendement exponentiel : exp 0, 1 − + 0, 2ε) 2 0, 22 i – Calcul de l’action généré : S1 = 100 ∗ exp 0, 1 − + 0, 2ε) 2 Projet MAF - DLL 9 – Calcul du cash flow du call : e−0,1 [max(ST − 95, 0)] Nous pouvons constater à ce niveau là que la génération d’un seul cash flow est quasi instantané mais pour 10000 valeurs, Excel prend environ 5 à 10 secondes avant d’afficher le résultat. Quelques essais ont suffit pour montré que ce qui est la plus consommatrice de temps est la fonction d’inversion de la loi normale (NOMINV) sous Excel. Ne savant pas comment cette fonction a été implémenté dans le logiciel, une première approche afin de gagner du temps est de diminuer le temps nécessaire pour effectuer ce calcul sans pour autant perdre en précision. Nous avons donc été amené à implémenter la loi normale inverse de façon optimale en DLL dans un premier temps puis tester les mêmes calculs sous Excel. Les résultats sont surprenants : le calcul des 10000 cash flow qui avaient prit cinq à dix secondes avec uniquement les fonctions d’Excel prennent maintenant moins d’une seconde avec la DLL. Dans un deuxième temps, nous avons implanté entièrement la fonction calculant le cash flow à partir d’un nombre aléatoire uniforme. En appelant cette fonction à partir d’Excel, nous pouvons encore constater une légère réduction du temps de calculs. Nous allons maintenant voire plus précisément les temps de calculs d’un nombre N d’appels à la fonction. 2.4 2.4.1 Résultats en terme de temps Résultats A l’aide d’une fonction de mesure de temps en Visual Basic dont nous avons écrite, nous avons mesuré le temps mis pour exécuter un certain nombre d’appel à la fonction sous excel puis sous Visual Basic en utilisant les fonctions d’Excel : notamment la fonction d’inversion de la loi normale. Nombre d’appel DLL Excel 0 0.031010 0.41878 10 0.039111 5.660217 100 0.105600 40.863015 1000 0.746184 401.331175 5000 3.726731 2023.466778 10000 7.432230 4725.081260 20000 15.330719 8098.695505 30000 22.229020 12242.263472 Projet MAF - DLL 10 Nous pouvons ainsi voir le gain de temps assez impressionnant en exécutant un grand nombre d’appel à la fonction à partir de la DLL. Ce qui prenait entre 10 et 15 secondes sous Excel prend moins d’une seconde avec la DLL. 3 Calcul du prix de l’option de liquidité d’un future Dans l’optique de comparer à nouveau les temps d’exécution des programmes en utilisant ou non des DLL, et aux vues des résultats encourageants que nous avions obtenu dans l’étape précédente, nous avons réimplanter le code C++ réalisant le calcul du prix de liquidité d’un future. Après avoir présenté la méthode pour réaliser le programme utilisant une DLL sous VC++ nous présenterons les résultats que nous avons obtenu. 3.1 Réaliser une DLL appelée par un programme C++ Ce chapitre montre comment créer une DLL Win32. Les DLL simples, ou encore ”Regular DLLs” suivant le terme consacré s’exécutent dans le même espace mémoire que les client qui font appel à ces DLLs, cependant elles présentent l’avantage non négligeable de gérer elles mêmes les données, inutile donc de s’inquiéter au sujet des pointeurs, ou de la gestion des données. 3.1.1 Première étape, l’objet Win32 DLL Nous allons commencer par implanter les fichiers source pour le projet, que nous nommerons Win32DLL. 1. Démarrer Visual C++ Studio 2. Fermer tout Workspace ou tout fichier qui serait encore ouvert 3. Sélectionner New du menu Fichier 4. Sélectionner le projet : Win32 Dynamic-Link Library 5. Donner au projet un nom évocateur par exemple, Win32DLL, s’assurer de la place choisie sur le disque dur et cliquer sur OK. Projet MAF - DLL 11 6. Sélectionner l’option A simple DLL project 7. Cliquer sur Finish puis OK. Nous allons maintenant réaliser le fichier header de déclaration des classes et des fonctions de notre projet que nous allons nommerons : DLLCode.h. Sélectionner New dans le menu Fichier puis, C/C++ Header File et donner au fichier le nom DLLCode.h. cliquer alors sur OK. Dans le cadre de notre projet, le fichier HEADER contient le code suivant : 1 2 /* File name : DLLCode . h 3 4 5 6 7 8 Ce fichier contient toutes les déclarations et les interfaces des objets de ce projet . Il comporte la Definition d une structure , et celle d une classe . Suivant le m^ e me schéma , ce fichier HEADER pourrait Aussi contenir la déclaration de fonction . 9 10 11 Remarque : Nous utilisons le m^ e me fichier HEADER pour compiler les fichiers . DLL et . exe ( l application ). 12 13 14 15 16 17 18 19 20 21 Ce fichier HEADER definit une macro qui exporte les objets DLL cible si nous construisons un fichier DLL ou qui importe les fichiers DLL nécessaires à une application si cette derniere necessite l utilisation de la DLL . Si nous definissons DLLDIR_EX ( une instruction pour le pre processeur ) alors la macro pour le pre processeur DLLDIR devient une instruction d export du code , sinon cela devient une instruction d importation . */ 22 23 24 25 26 27 # ifdef DLLDIR_EX # define DLLDIR # else # define DLLDIR # endif __declspec ( dllexport ) __declspec ( dllimport ) 28 29 30 31 32 33 struct sbloc { int size ; // taille du bloc int type ; // 0 si le bloc est à recopier , 1 si il est à calculer }; 34 35 36 37 38 39 40 41 42 43 44 45 46 class DLLDIR Hedge_manager { public : sbloc ** hed_schem ; int * nb_bloc ; Hedge_manager (); // Constructeur de la classe virtual ~ Hedge_manager (); // Destructeur de la classe void hed_schem_init (); void hed_affich (); int hed_steps ; }; Projet MAF - DLL 12 Sauvegarder et fermer ce fichier HEADER. Maintenant nous allons créer le fichier qui implémente ce HEADER afin de générer la DLL, nous le nommerons DLLCode.cpp. Sélectionner New dans le menu Fichier, puis sélectionner C++ Source File et nommer le alors DLLCode. Cliquer sur OK. Pour des raisons d’efficacité nous n’avons pas recopié le code source implémentant le fichier HEADER car celui-ci était assez volumineux. Synthétiquement, ce fichier est organisé comme un fichier C++ commun mis à part quelques singularités que nous allons souligner. Nous présentons un petit morceau de code à titre d’exemple : 1 2 3 # include " Stdafx . h " # include " DLLCode . h " # include < iostream > 4 5 using namespace std ; En dessous de ces lignes doit figurer le code implantant un fichier cpp? commun Si nous voulons accéder aux fonctions de la DLL nous devons les exporter. Quand la DLL est construite, elle construit également un autre objet appelé une librairie appelée export library. Cet objet contient toutes les informations nécessaires pour lier dynamiquement la DLL au moment de l’exécution d’un programme. Lorsque l’on exporte une fonction ou une classe, le nom ainsi que la position de la fonction sont stockées dans l’objet export library. La fonction qui utilise la DLL doit donc se lier à l’export library pour accéder aux objets stockés dans la DLL. Pour créer l’objet DLL export Library, sélectionner Settings... le menu Project. Puis choisir l’onglet C/C++. Insérer, DLLDIR_EX dans la zone texte de définition du pré processeur. Cliquer sur OK. Cela évitera les messages d’erreurs du compilateur. Cliquer sur le bouton pour construire le projet build. Félicitations, nous avons terminer de construire une application du type Win32 DLL et sa librairie d’export. 3.1.2 Construction d’un client pour la DLL Il s’agit du plus simple et su plus courant dans client DLL. Sa flexibilité provient de sa librairie d’export. Il faut maintenant construire une application Win32 de type console, faisant partie du projet DLLClient1. Dans cette application la DLL est chargée au moment du lancement de l’application. 1. 2. 3. 4. Fermer tout fichier ou tout espace de travail qui pourrait être ouvert Sélectionner New dans le menu Fichier Sélectionner Win32 Console Application Dans la zone de texte du nom du projet, saisir un nom évocateur, dans notre cas DLLClient1 , puis cliquer sur Suivant. 5. Sélectionner An empty project puis cliquer sur Finish puis OK Nous allons maintenant coder le client de la DLL. Dans le menu cliquer sur New, puis C/C++ Source File. Dans la zone texte du nom du projet lui donner comme nom DLLClient1 puis appuyer sur la touche ENTER. Comme le fichier C++ implémentant le fichier HEADER, par souci d’efficacité nous n’avons pas recopié l’intégralité du code qui s’apparente à celui d’un programme C++ commun, en revanche nous allons souligner les différences : Projet MAF - DLL 13 Les premières lignes du fichier doivent être les suivantes : 1 2 3 4 5 # include < iostream > # include < conio .h > # include < windows .h > # include " DLLCode . h " # pragma comment ( lib , " W32DLL . lib " ) 6 7 using namespace std ; Sauvegarder et fermer cette source C++, minimiser la fenêtre de application VC++ Studio. Il faut alors copier quelques fichiers du projet Win32DLL précédent dans le fichier du projet DLLClient1 : – W32DLL\Debug\W32DLL.DLL – W32DLL\Debug\W32DLL.lib – W32DLL\DLLCode.h Maximiser la fenêtre de l’application VC++, puis cliquer sur l’icône pour construire le projet. Puis sur le bouton ! pour exécuter le projet. Avec cette méthode la DLL est chargée au lancement. Le système d’exploitation, cherche la DLL dans les répertoires suivants : – Le répertoire du system Windows – Le répertoire Windows – Le répertoire dans lequel est situé l’application 3.2 Résultats Nous n’avons malheureusement pas pu observer d’amélioration dans les temps d’exécution du programme. Projet MAF - DLL 14 Conclusion En définitive, dans le calcul d’option par Monte Carlo, on a constaté une très nette amélioration du comportement du calcul du pricing d’option sur un ordinateur AMD XP 2500+, 512 meg RAM, Windows XP. La DLL a permis de garder le temps de réponse de l’application raisonnable malgré le nombre important de données à traiter. D’une manière générale, le temps de réponse d’une application à un utilisateur se doit de ne pas dépasser quelques secondes, et la DLL (plutôt que de programmer directement en VBA) pour Excel s’avère une bonne solution. Par ailleurs, la transformation d’un grand exécutable (écrit en C++) en un petit exécutable qui appelle des DLLs (écrites en C++), n’apporte que très peu par rapport au gain en temps, par contre, il apporte une meilleure gestion de la mémoire si les DLLs contiennent de nombreuses lignes de code. En bref, on peut dire que passer au stade de la DLL est avantageux quand on a déjà du code qui fonctionne, afin d’optimiser soit le temps, soit la gestion mémoire. Projet MAF - DLL 1 2 // ProjetMAF . cpp : Defines the entry point for the DLL application . // 3 4 5 6 7 8 # include # include # include # include # include " stdafx . h " < stdio .h > < stdlib .h > < math .h > < time .h > # define # define # define # define # define # define A1 A2 A3 A4 A5 A6 ( -3.969683028665376 e +01) 2.209460984245205 e +02 ( -2.759285104469687 e +02) 1.383577518672690 e +02 ( -3.066479806614716 e +01) 2.506628277459239 e +00 # define # define # define # define # define B1 B2 B3 B4 B5 ( -5.447609879822406 e +01) 1.615858368580409 e +02 ( -1.556989798598866 e +02) 6.680131188771972 e +01 ( -1.328068155288572 e +01) # define # define # define # define # define # define C1 C2 C3 C4 C5 C6 ( -7.784894002430293 e -03) ( -3.223964580411365 e -01) ( -2.400758277161838 e +00) ( -2.549732539343734 e +00) 4.374664141464968 e +00 2.938163982698783 e +00 # define # define # define # define D1 D2 D3 D4 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 7.784695709041462 e -03 3.224671290700398 e -01 2.445134137142996 e +00 3.754408661907416 e +00 34 35 36 37 # define P_LOW 0.02425 /* P_high = 1 - p_low */ # define P_HIGH 0.97575 38 39 40 41 42 43 44 45 46 47 BOOL APIENTRY DllMain ( HANDLE hModule , DWORD ul_reason_for_call , LPVOID lpReserved ) { srand ( ( unsigned ) time ( NULL ) ); return TRUE ; } 48 49 // declaration des fonctions 50 51 52 53 54 55 56 57 // Fonction générant un nombre aléatoire entre 0 et 1 double genere ( void ) { return ( double ) rand ()/ RAND_MAX ; } 15 Projet MAF - DLL 16 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 // Fonction calculant la loi normale inverse // d ’ un nombre p compris entre 0 et 1 __declspec ( dllexport ) double __stdcall stdnormal_inv ( double p ) { double x ; double q , r ; if ((0 < p ) && ( p < P_LOW )){ q = sqrt ( -2* log ( p )); x = ((((( C1 * q + C2 )* q + C3 )* q + C4 )* q + C5 )* q + C6 ) / (((( D1 * q + D2 )* q + D3 )* q + D4 )* q +1); } else { if (( P_LOW <= p ) && ( p <= P_HIGH )){ q = p - 0.5; r = q*q; x = ((((( A1 * r + A2 )* r + A3 )* r + A4 )* r + A5 )* r + A6 )* q /((((( B1 * r + B2 )* r + B3 )* r + B4 )* r + B5 )* r +1); } else { if (( P_HIGH < p )&&( p < 1)){ q = sqrt ( -2* log (1 - p )); x = -((((( C1 * q + C2 )* q + C3 )* q + C4 )* q + C5 )* q + C6 ) / (((( D1 * q + D2 )* q + D3 )* q + D4 )* q +1); } } } 85 86 87 return x ; } 88 89 90 91 92 93 94 95 96 97 98 99 // Fonction calculant la valeur d ’ un cash flow // avec un nombre entre 0 et 1 en argument __declspec ( dllexport ) double __stdcall cash_flow ( double u ) { double x , max , actionGen ; actionGen = 100 * exp ((0.1 - pow (0.2 ,2)/2) + 0.2* stdnormal_inv ( u ) ); max = ( actionGen -95 >0) ? actionGen -95 : 0; x = exp ( -0.1) * max ; return x ; } 100 101 102 103 104 105 106 107 108 109 110 111 // Fonction calculant le pricing par la méthode de monte carlo __declspec ( dllexport ) double __stdcall pricing ( double a ) { double x , max , actionGen ; double u = genere (); actionGen = 100 * exp ((0.1 - pow (0.2 ,2)/2) + 0.2* stdnormal_inv ( u ) ); max = ( actionGen -95 >0) ? actionGen -95 : 0; x = exp ( -0.1) * max ; return x ; } Sous Excel : 1 Projet MAF - DLL 2 3 4 5 6 17 ’ ========= Declarations ======= Private Type LARGE_INTEGER lowpart As Long highpart As Long End Type 7 8 9 10 11 Private Declare Function Query P e r f o r m a n c e C o u n t e r Lib " kernel32 " ( lpPerformanceCount As LARGE_INTEGER ) As Long Private Declare Function Qu ery P e r f o r m a n c e F r e q u e n c y Lib " kernel32 " ( lpFrequency As LARGE_INTEGER ) As Long 12 13 ’ =========== SUBS ========= 14 15 16 17 18 19 Public Function PricingExcel () As Double Dim x As Double Dim u As Double Dim ActionGen As Double Dim maxi As Double 20 21 22 23 24 25 26 27 u = Rnd () ActionGen = 100 * Exp ((0.1 - Application . WorksheetFunction . Power (0.2 , 2) / 2) + 0.2 * Application . WorksheetFunction . NormInv (u , 0 , 1)) If ( ActionGen - 95 > 0) Then maxi = ActionGen - 95 Else maxi = 0 x = Exp ( -0.1) * maxi PricingExcel = x End Function 28 29 30 31 32 33 34 35 Public Function TimePricingDLL ( NbAppels As Integer ) As String Dim curStart As LARGE_INTEGER Dim curEnd As LARGE_INTEGER Dim curFreq As LARGE_INTEGER Dim fResult As Double Dim sText As String Dim TmpCalc As Double 36 37 38 Q u e r y P e r f or man ceF req uen cy curFreq Q u e r y P e r f ormanceCounter curStart ’ relevé du " top par secondes " ’ relevé d ’ un top ( début de mesure ) 39 40 41 42 For i = 0 To NbAppels TmpCalc = pricing (0) Next i 43 44 WaitMicroSeconde 20 45 46 Q u e r y P e r f ormanceCounter curEnd ’ relevé d ’ un autre top ( fin de mesure ) 47 48 49 50 51 52 ’ conversion du résultat inter - top en millisecondes fResult = 1000 * ( CDbl ( curEnd . lowpart ) - CDbl ( curStart . lowpart )) / CDbl ( curFreq . lowpart ) ’ formattage pour l ’ affichage TimePricingDLL = Format ( fResult , " #0.000000 " ) & " ms " 53 54 End Function 55 56 57 58 Public Function TimePricingExcel ( NbAppels As Integer ) As String Dim curStart As LARGE_INTEGER Projet MAF - DLL 59 60 61 62 63 Dim Dim Dim Dim Dim 18 curEnd As LARGE_INTEGER curFreq As LARGE_INTEGER fResult As Double sText As String TmpCalc As Double 64 65 66 Q u e r y P e r f or man ceF req uen cy curFreq Q u e r y P e r f ormanceCounter curStart ’ relevé du " top par secondes " ’ relevé d ’ un top ( début de mesure ) 67 68 69 70 For i = 0 To NbAppels TmpCalc = PricingExcel () Next i 71 72 WaitMicroSeconde 20 73 74 Q u e r y P e r f ormanceCounter curEnd ’ relevé d ’ un autre top ( fin de mesure ) 75 76 77 78 79 80 ’ conversion du résultat inter - top en millisecondes fResult = 1000 * ( CDbl ( curEnd . lowpart ) - CDbl ( curStart . lowpart )) / CDbl ( curFreq . lowpart ) ’ formattage pour l ’ affichage TimePricingExcel = Format ( fResult , " #0.000000 " ) & " ms " 81 82 End Function 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 Public Sub WaitMicroSeconde ( Duree As Long ) ’ attend " duree " microsecondes . ’ Des test montre que c ’ est = Duree + ou - x microsecondes ...! Dim curStart As LARGE_INTEGER Dim curEnd As LARGE_INTEGER Dim curFreq As LARGE_INTEGER Dim WaitTop As Long Q u e r y P e r f or man ceF req uen cy curFreq Q u e r y P e r f ormanceCounter curStart WaitTop = curStart . lowpart + Int ( Duree * 3.38) Do Q u e r yPerformanceCounter curEnd Loop Until curEnd . lowpart >= WaitTop 98 99 End Sub