NĂ©gociation d'arbitrage (algorithme Bellman-Ford)



La négociation en bourse est généralement associée à des risques. Cela est absolument vrai pour la plupart des stratégies de trading. Le succÚs du commerce dans ces cas est déterminé uniquement par la capacité d'évaluer correctement les risques et de les gérer. Mais toutes les stratégies de trading ne le sont pas. Il existe des stratégies sans risque, qui incluent notamment l'arbitrage. Cet article explique ce qu'est l'arbitrage et comment l'implémenter en utilisant un algorithme de graphe classique tel que l'algorithme de Bellman-Ford.

Qu'est-ce que l'arbitrage?


L'arbitrage consiste en quelques transactions logiquement liĂ©es visant Ă  profiter de la diffĂ©rence de prix pour le mĂȘme actif ou des actifs connexes en mĂȘme temps sur diffĂ©rents marchĂ©s (arbitrage spatial), ou sur le mĂȘme marchĂ© Ă  diffĂ©rents moments dans le temps (arbitrage temporaire) .

À titre d'exemple simple, considĂ©rons l'arbitrage spatial. À New York et Ă  Londres, des accords peuvent ĂȘtre conclus pour acheter des dollars pour des euros et des euros pour des dollars. A New York, cela peut se faire au tarif de 4 dollars pour 3 euros, et Ă  Londres - au tarif de 5 dollars pour 3 euros. Cette diffĂ©rence de taux ouvre la possibilitĂ© d'un arbitrage spatial.



Avec 4 dollars, à New York, vous pouvez acheter 3 euros. AprÚs cela, à Londres, achetez pour ces 3 euros 5 dollars. Comme vous pouvez le voir, une séquence de transactions aussi simple apporte 1 dollar de profit pour 4 dollars investis. Par conséquent, s'il y a initialement 4 millions de dollars, le profit sera déjà de un million.

Lorsque les taux de change (nous ne considĂ©rons pas l'Ă©cart) pour la mĂȘme paire de devises diffĂšrent, la sĂ©quence des transactions requises pour mettre en Ɠuvre la stratĂ©gie d'arbitrage est trĂšs simple. Si le taux de change pour une paire de devises est fixe, mais que plusieurs paires de devises sont nĂ©gociĂ©es en parallĂšle, l'arbitrage est Ă©galement possible, mais la sĂ©quence des transactions sera dĂ©jĂ  non triviale. Par exemple, vous pouvez acheter 4 euros pour 5 dollars, 3 livres pour 4 euros, puis 6 dollars pour 3 livres. Le profit d'une telle sĂ©quence de transactions sera de 1 $ pour chaque 5 dollars investis.



Des centaines de paires de devises peuvent ĂȘtre Ă©changĂ©es en bourse et les taux de change changent constamment. Il est dĂ©jĂ  impossible de comprendre quelle sĂ©quence de transactions apportera des bĂ©nĂ©fices sans une solution algorithmique.

Transition vers le problĂšme algorithmique


Imaginez des transactions de change potentielles sous une forme algorithmique, Ă  savoir sous la forme d'un graphique. Les sommets de ce graphique reprĂ©sentent les devises et les bords sont des transactions potentielles. La longueur de la nervure correspond au taux de change auquel la transaction peut ĂȘtre conclue.


La question suivante est de savoir comment trouver une sĂ©quence de transactions dans une telle colonne qui apportera des bĂ©nĂ©fices. Évidemment, puisqu'au dĂ©but de la sĂ©quence et Ă  la fin il doit s'agir de la mĂȘme monnaie, la sĂ©quence doit correspondre au cycle du graphe donnĂ©. Ensuite, vous devez dĂ©terminer comment le taux de change entre les deux devises est calculĂ©, si elles ne sont pas Ă©changĂ©es directement, mais via une certaine troisiĂšme devise (ou un nombre arbitraire d'opĂ©rations intermĂ©diaires). Tout ici est Ă©galement assez simple. Un tel taux de change sera calculĂ© comme le produit des taux de change des transactions intermĂ©diaires. Une sĂ©quence de transactions rentable devient si ce produit prend une valeur infĂ©rieure Ă  un. En d'autres termes, si une unitĂ© monĂ©taire peut ĂȘtre achetĂ©e moins qu'une unitĂ© de la mĂȘme monnaie.


Les algorithmes de graphe classiques sont mal adaptĂ©s pour travailler avec des produits de longueurs d'arĂȘte. Ces algorithmes visent principalement Ă  trouver un chemin dĂ©fini comme la somme de ces longueurs. Cependant, pour contourner cette limitation, il existe un moyen mathĂ©matique de passer d'un produit Ă  une somme. De cette façon, c'est le logarithme. Si le produit apparaĂźt sous le logarithme, alors un tel logarithme peut ĂȘtre converti en la somme des logarithmes. Sur le cĂŽtĂ© droit de cette Ă©quation, le nombre souhaitĂ© est infĂ©rieur Ă  un, ce qui signifie que le logarithme de ce nombre doit ĂȘtre infĂ©rieur Ă  zĂ©ro.




Une telle astuce mathĂ©matique simple vous permet de passer de la recherche d'un cycle dont le produit des longueurs d'arĂȘtes est infĂ©rieur Ă  un Ă  la recherche d'un cycle dont la somme des longueurs d'arĂȘtes est infĂ©rieure Ă  zĂ©ro. Une telle tĂąche semble dĂ©jĂ  plus rĂ©soluble par les algorithmes de graphes classiques, et plus prĂ©cisĂ©ment l'algorithme de Bellman-Ford.

Bellman - Algorithme Ford


L'algorithme Bellman-Ford est généralement utilisé pour trouver la distance d'un sommet donné à tous les autres sommets d'un graphique, mais sa modification permet de trouver des cycles de longueur négative.

L'opĂ©ration de base de cet algorithme est la relaxation des bords. L'essence de cette opĂ©ration est la suivante. Supposons qu'il y ait un borda→b, ainsi que les valeurs prĂ©liminaires des distances aux pics prĂ©cĂ©demment calculĂ©es sont connues aet b. Pour effectuer une relaxation des bords, il est nĂ©cessaire de calculer la distance par rapport au sommet.bsi le chemin passait par le haut aet cĂŽtes a→b. Cette distance est calculĂ©e comme la somme de la distance jusqu'au sommet.a et longueurs de cĂŽtes a→b. De plus, si cette distance est infĂ©rieure Ă  la distance prĂ©liminaire actuelleaalors c'est la distance Ă  aCorrespond et prend une nouvelle valeur, juste calculĂ©e.

Le reste de l'algorithme est Ă©galement simple. NĂ©cessaireN fois (NEst le nombre de sommets du graphique) contourner la liste des arĂȘtes, en appliquant une opĂ©ration de relaxation pour chaque tour. La complexitĂ© de l'algorithme est obtenueN∗M (OĂč N- le nombre de sommets, et M- nombre de cĂŽtes). Pour un graphique sans cycles nĂ©gatifs, une relaxation supplĂ©mentaire des bords n'entraĂźnera pas de changement de la distance aux sommets. En mĂȘme temps, pour un graphique contenant un cycle nĂ©gatif, la relaxation rĂ©duira la distance aux sommets et aprĂšsNdĂ©tours. Cette propriĂ©tĂ© peut ĂȘtre utilisĂ©e pour trouver le cycle souhaitĂ©.

La petite implémentation suivante de l'algorithme décrit ci-dessus sur Kotlin devrait aider ceux qui sont plus familiers avec le tri du code.

fun findNegativeCycle(nodes: Int, edges: Array<Edge>, source: Int): List<Int>? {
    // Initialize distances and prev arrays. All distances but the distance to
    // the source node are infinite, distance to the source node is zero.
    val distances = DoubleArray(nodes) { if (it == source) 0.0 else INFINITY }
    val prev = IntArray(nodes) { -1 }

    // Relax all edges N times where N is the number of nodes.
    repeat(nodes) {
        edges.forEach { it.relax(distances, prev) }
    }

    // Try to relax at least one more edge. If it's possible memorize the node,
    // otherwise return from the method.
    val firstRelaxedEdge = edges.firstOrNull { it.relax(distances, prev) }
    var node = firstRelaxedEdge?.to ?: return null

    // Step back N times where N is the number of nodes. As a result, the node will
    // be in the loop for sure.
    repeat(nodes) {
        node = prev[node]
    }

    // Recover the loop by the node that is inside it and prev links.
    val lastNode = node
    return buildList {
        do {
            add(node)
            node = prev[node]
        } while (node != lastNode)

        reverse()
    }
}

// Edge DTO with implemented relaxation operation.
data class Edge(val from: Int, val to: Int, val length: Double) {

    fun relax(distances: DoubleArray, prev: IntArray): Boolean {
        if (distances[from] + length >= distances[to]) {
            return false
        }

        distances[to] = distances[from] + length
        prev[to] = from
        return true
    }
}

Examinons un exemple avec un petit graphique, qui comprend un cycle de longueur négative. Pour que l'algorithme fonctionne, il est nécessaire que chaque sommet maintienne la distance connue actuelle à celui-ci, ainsi qu'un lien vers son sommet précédent. La référence au sommet précédent dans ce cas est déterminée par la relaxation réussie de la cÎte. Si l'opération de relaxation a réussi et que la distance au sommet a été mise à jour, le lien vers le sommet précédent de ce sommet est également mis à jour et prend la valeur du sommet source du bord donné.

Donc, vous devez d'abord initialiser les sommets en définissant la distance à tous les sommets sauf l'infini égal initial. Pour le sommet initial, une distance de zéro est définie.


Le premier tour de toutes les cĂŽtes suit et leur relaxation est effectuĂ©e. Presque toute la relaxation ne donne aucun rĂ©sultat, sauf la relaxation des cĂŽtesa→b. La relaxation de cette cĂŽte vous permet de mettre Ă  jour la distance Ă b.


Ceci est suivi par le deuxiĂšme tour de tous les bords du graphique et la relaxation correspondante. Cette fois, le rĂ©sultat est une relaxation des cĂŽtes.b→c, et b→d. Les distances aux sommets sont mises Ă  jour.c et d. Il est Ă  noter ici que le rĂ©sultat dĂ©pend de l'ordre dans lequel les bords sont traversĂ©s.


Au troisiĂšme tour de cĂŽtes, il est possible de dĂ©tendre avec succĂšs dĂ©jĂ  trois cĂŽtes, Ă  savoir les cĂŽtes →d, d→e, d→b. Dans ce cas, lorsque les cĂŽtes sont dĂ©tendues→d et d→bdistances dĂ©jĂ  enregistrĂ©es det b, ainsi que les liens correspondants vers les sommets prĂ©cĂ©dents.


Au quatriĂšme tour, les opĂ©rations de relaxation des cĂŽtes sont terminĂ©es avec succĂšs. b→cet b→a. Dans ce cas, les valeurs dĂ©jĂ  enregistrĂ©es des distances aux pics sont Ă  nouveau mises Ă  jour.a et c, ainsi que les liens correspondants vers les sommets prĂ©cĂ©dents.


Le cinquiĂšme tour est le dernier. Les cĂŽtes se dĂ©tendent pendant cette promenade→d, d→b, d→e. Ici, vous pouvez voir que la prĂ©sence d'un cycle de longueur nĂ©gative apporte dĂ©jĂ  certains ajustements aux valeurs des distances aux pics.


AprĂšs cette tournĂ©e, si le graphique ne contenait pas de cycle de longueur nĂ©gative, l'algorithme serait terminĂ©, car la relaxation de n'importe quel bord n'aurait apportĂ© aucun changement. Cependant, pour ce graphique, du fait de la prĂ©sence d'un cycle de longueur nĂ©gative, on peut encore trouver une arĂȘte dont la relaxation mettra Ă  jour la distance Ă  l'un des sommets.


On retrouve un bord dont la relaxation met Ă  jour la distance jusqu'au sommet. Cela confirme la prĂ©sence d'un cycle de longueur nĂ©gative. Vous devez maintenant trouver ce cycle lui-mĂȘme. Il est important que le sommet, dont la distance est maintenant mise Ă  jour, puisse ĂȘtre Ă  la fois Ă  l'intĂ©rieur et Ă  l'extĂ©rieur du cycle. Dans l'exemple, c'est le hauteet elle est hors cycle. Ensuite, vous devez vous rĂ©fĂ©rer aux liens vers les sommets prĂ©cĂ©dents, qui ont Ă©tĂ© soigneusement mis Ă  jour Ă  toutes les Ă©tapes de l'algorithme. Pour ĂȘtre assurĂ© d'entrer dans le cycle, vous devez prendre du reculNpics en utilisant ces liens.

Dans cet exemple, les transitions seront les suivantes:e→d→c→b→d→c. Donc le sommet est situĂ©c, qui est garanti de se situer dans un cycle de longueur nĂ©gative.


De plus, une question de technologie. Pour retourner le cycle souhaité, vous devez réitérer en utilisant les liens vers les sommets précédents jusqu'à ce que le sommet se rencontre à nouveauc. Cela signifie que le cycle est terminé. Il ne reste plus qu'à inverser l'ordre, puisque l'itération a été inversée lors des itérations sur les liens vers les sommets précédents.

L'algorithme ci-dessus suppose la prĂ©sence d'un sommet initial Ă  partir duquel les distances sont calculĂ©es. La prĂ©sence d'un tel sommet n'est pas nĂ©cessaire pour que l'algorithme fonctionne, mais il a Ă©tĂ© introduit dans une plus large mesure pour correspondre Ă  l'algorithme Bellman-Ford d'origine. Si le sujet d'intĂ©rĂȘt est un cycle de longueur nĂ©gative, alors nous pouvons supposer que tous les sommets d'un graphe donnĂ© sont initiaux. En d'autres termes, la distance Ă  tous les sommets est initialement nulle.

Conclusion


L'utilisation de l'algorithme Bellman-Ford dans le problĂšme de la nĂ©gociation d'arbitrage est un excellent exemple de la façon dont les algorithmes classiques peuvent rĂ©soudre de vrais problĂšmes commerciaux, en particulier dans le domaine financier. ComplexitĂ© asymptotique de l'algorithme, Ă©gale Ă N3pour un graphe entiĂšrement connectĂ©, il peut s'avĂ©rer assez volumineux. Il faut vraiment s'en souvenir. Cependant, dans de nombreux cas, comme l'Ă©change de devises, cette complexitĂ© ne crĂ©e aucun problĂšme en raison du nombre relativement faible de nƓuds dans le graphique.

Source: https://habr.com/ru/post/undefined/


All Articles