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