Achats/ventes en bourse - IGI00 - Michel Couprie NOTE:LessectionsA,B,C,D,Efontpartiedel énoncédonnéauxétudiants,lessections suivantes contiennent des indications ou des solutions. A. Le problème Une société spécialisée en informatique financière est chargée d évaluer les opérateurs de marché (traders). Pour cela elle dispose, sur un certain nombre n de jours passés, de la valeur de certaines actions (on considèrera seulement une action dans la suite). On note T(i) la valeur de l action au jour i, 1 i n. On suppose ainsi, pour simplifier, que la valeur de l action ne change pas durant un jour. La période de temps considérée peut varier selon la précision voulue (heure, minute, seconde...). Si cette action a été achetée au jour i et revendue au jour j, avec 1 i j n, le profit réalisé est égal à T(j) T(i). On cherche à évaluer le profit maximal qui aurait pu être réalisté, en une seule opération d achat/vente, durant cette même période. On pourra alors comparer ce profit avec celui effectivement réalisé par un trader sur la même période, et ainsi évaluer ses performances. Par exemple, considérons le tableau suivant retraçant une petite partie de l historique de notre action : i 1 7 8 T(i) 7 1 Quelles sont les dates d achat et de vente permettant d obtenir le profit maximal? La société disposant d un très grand nombre de données, il est utile de disposer d un algorithme efficace pour évaluer le profit maximal pour n importe quelle période. B. Un algorithme naïf Proposer un algorithme naïf pour résoudre ce problème. Quelle est sa complexité de calcul? 1
C. Un algorithme en O(nlogn) Proposer un algorithme pour résoudre ce problème, basé sur le principe diviser pour régner, et dont la complexité de calcul est en O(nlogn) (on supposera pour simplifier que n est une puissance de ). D. Un algorithme en O(n) Proposer un algorithme pour résoudre ce problème, basé sur le principe diviser pour régner, et dont la complexité de calcul est en O(n). E. Un autre algorithme en O(n) Proposer un second algorithme pour résoudre ce problème, dont la complexité de calcul est en O(n), effectuant un seul balayage du tableau T. A. Indications et solutions Une expression graphique (courbe de l évolution du cours de l action) des données du problème peut aider. On peut noter que la condition i j (la date d achat précède celle de la vente) est essentielle, sans celle-ci la solution serait triviale et reviendrait à trouver le min et le max du tableau. B. Algorithme naïf 1 Algorithme 1 : TraderNaif Données : T[],n Résultat : p max,a,v p max = 0; a = 1; v = 1; pour i de 1 à n faire pour j de i+1 à n faire si T[j] T[i] > p max alors p max = T[j] T[i]; a = i; v = j;
Sa complexité est en O(n ). C. Algorithme basé sur diviser pour régner en O(nlogn) Comme on le sait, la méthode diviser pour régner consiste à résoudre le problème en trois phases : diviser les données en paquets appliquer la méthode de résolution à chacun des paquets, combiner les résultats des résolutions partielles. On applique cette méthode récursivement, sauf quand la taille des données devient trop petite, auquel cas la solution est triviale. L algorithme suivant ne marche pas mais constitue une tentative intéressante car correcte dans sa structure : 1 7 Algorithme : TraderLogLinF Données : T[],i,j Résultat : a,v,p si j = i alors a = i; v = j; p = 0; sinon TraderLogLinF(T,i, i+j,a 1,v 1,p 1 ); TraderLogLinF(T, i+j +1,j,a,v,p ); p = p 1 ; v = v 1 ; a = a 1 ; si p > p alors p = p ; v = v ; a = a ; si T[v ] T[a 1 ] > p alors p = T[v ] T[a 1 ]; v = v ; a = a 1 ; Le problème vient du dernier cas (v,a 1 ), en effet ces positions ne correspondent pas forcément au max et au min, respectivement, des deux sous-tableaux. Pour corriger cela, une première idée est d appeler une fonction argmax et une fonction argmin qui calculent respectivement l indice du max et celui du min d un tableau :
Algorithme : TraderLogLin Données : T[],i,j Résultat : a,v,p 1 si j = i alors a = i; v = j; p = 0; sinon TraderLogLin(T,i, i+j,a 1,v 1,p 1 ); TraderLogLin(T, i+j +1,j,a,v,p ); m = argmin(t[i,..., i+j ]); M = argmax(t[ i+j +1,...,j]); 7 p = p 1 ; v = v 1 ; a = a 1 ; 8 si p > p alors p = p ; v = v ; a = a ; 9 si T[M] T[m] > p alors p = T[M] T[m]; v = M ; a = m; Évaluons la complexité de cet algorithme. Si C(n) est le coût de calcul pour des données de taille n, on peut exprimer C(n) par l équation de récurrence suivante : C(n) = C( n )+bn+c, C(1) = 1 (1) Pour résoudre cette équation, on supposera tout d abord que n = k (autrement dit k = log n). Développons la partie de droite de l équation : C( k ) = C( k 1 )+b k +c = [C( k )+b k 1 +c]+b k +c = [[C( k )+b k +c]+b k 1 +c]+b k +c =... = k +1+kb k +c[ k 1 + k +...+1] = n+1+bnlog n+cn d où une complexité en O(nlogn). D. Algorithme basé sur diviser pour régner en O(n) Pour obtenir une complexité moindre, on peut essayer d éliminer les calculs de argmin et de argmax de la recombinaison en les incluant dans le calcul récursif. Pour cela, on rajoute deux paramètres de sortie m et M :
1 7 8 9 Algorithme : TraderLin Données : T[],i,j Résultat : a,v,m,m,p si j = i alors a = i; v = i; m = i; M = i; sinon TraderLin(T,i, i+j,a 1,v 1,m 1,M 1,p 1 ); TraderLin(T, i+j +1,j,a,v,m,M,p ); si T[m 1 ] T[m ] alors m = m 1 ; sinon m = m ; si T[M 1 ] T[M ] alors M = M 1 ; sinon M = M ; p = p 1 ; v = v 1 ; a = a 1 ; si p > p alors p = p ; v = v ; a = a ; si T[M ] T[m 1 ] > p alors p = T[M ] T[m 1 ]; v = M ; a = m 1 ; Cette fois-ci, l équation de récurrence est la suivante : C(n) = C( n )+c, C(1) = 1 () En la résolvant de manière similaire à la précédente, on obtient : C(n) = n+1+cn d où une complexité en O(n). C. Algorithme linéaire en un balayage Enfin, voici un autre algorithme linéaire en un seul balayage du tableau T. Comme dans les algorithmes précédents, a représente la date d achat et v la date de vente trouvées, permettant de réaliser le profit maximum. On utilise de plus les variables suivantes : i représente la dernière date d achat envisagée, j représente la dernière date de vente envisagée, p est le profit correspondant aux dates i et j, p max est le profit maximum trouvé jusqu ici (correspondant aux dates a et v).
1 Algorithme : TraderScan Données : T[],n Résultat : a,v a = 1; v = 1; i = 1; p = 0; p max = 0; pour j de à n faire si T[j] > T[i] alors p = T[j] T[i]; si p > p max alors p max = p; a = i; v = j; si T[j] < T[i] alors i = j; p = 0;