Preface

In financial markets, arbitrage is the practice of taking advantage of a price difference between two or more markets. It is a way to make a profit by simultaneously buying and selling an asset in different markets. This post will explore how to use graph theory to detect arbitrage opportunities using the Bellman-Ford algorithm.

What is Arbitrage?

Arbitrage occurs when a trader buys an asset in one market at a lower price and sells it in another market at a higher price, profiting from the price difference. In an efficient market, arbitrage opportunities are rare and quickly disappear as traders exploit them.

Graph Theory and Arbitrage Detection

In graph theory, we can represent different currencies or assets as vertices and the exchange rates as edges. A negative weight cycle in this graph indicates an arbitrage opportunity.

Why do we need to be careful with negative weights?

Negative weight edges can create negative weight cycles i.e. a cycle that will reduce the total path distance by coming back to the same point.

why-do-we-need-to-be-careful-with-negative-weights

Shortest path algorithms like Dijkstra's Algorithm that aren't able to detect such a cycle can give an incorrect result because they can go through a negative weight cycle and reduce the path length.

Bellman-Ford Algorithm

The Bellman-Ford algorithm is used to find the shortest paths from a single source vertex to all other vertices in a weighted graph. It can also detect negative weight cycles, which are key to identifying arbitrage opportunities.

How Bellman Ford's algorithm works

Bellman Ford algorithm works by overestimating the length of the path from the starting vertex to all other vertices. Then it iteratively relaxes those estimates by finding new paths that are shorter than the previously overestimated paths. By doing this repeatedly for all vertices, we can guarantee that the result is optimized.

bellman-fords-algorithm-step-1

bellman-fords-algorithm-step-2

bellman-fords-algorithm-step-3

bellman-fords-algorithm-step-4

bellman-fords-algorithm-step-5

bellman-fords-algorithm-step-6

Photo credit goes to programiz.com

Steps to Detect Arbitrage Using Graph Theory

  • Model the Market as a Graph: Represent currencies or assets as vertices and exchange rates as directed edges with weights.
  • Convert Exchange Rates to Logarithms: Use the negative logarithm of the exchange rates as edge weights to transform the problem into a shortest path problem.
  • Apply Bellman-Ford Algorithm for Arbitrage: Use the algorithm to detect negative weight cycles.
Example using Golang
bellman-fords-algorithm

Step 1: Define the Graph Structure

type Edge struct {
	from, to int
	weight   float64
}

type Graph struct {
	vertices int
	edges    []Edge
}

// NewGraph creates a new graph with a specified number of vertices
func NewGraph(vertices int) *Graph {
	return &Graph{vertices: vertices, edges: []Edge{}}
}

// AddEdge adds a directed edge with a weight (negative log of the rate) between two vertices
func (g *Graph) AddEdge(from, to int, rate float64) {
	weight := -math.Log(rate)
	g.edges = append(g.edges, Edge{from: from, to: to, weight: weight})
}

Step 2: Implement Bellman-Ford Algorithm

// DetectArbitrage uses the Bellman-Ford algorithm to detect negative weight cycles, which indicate arbitrage opportunities in trading.
func (g *Graph) DetectArbitrage(src int) bool {
	// Step 1: Initialize distances from the source to all other vertices as infinity, except the source itself.
	// This represents the initial assumption that all other currencies are infinitely far from the source currency.
	distances := make([]float64, g.vertices)
	for i := range distances {
		distances[i] = math.Inf(1)
	}
	distances[src] = 0

	// Step 2: Relax edges repeatedly.
	// Relaxing an edge means trying to improve the shortest known distance to a vertex by using an edge from another vertex.
	// If a shorter path is found, the distance to the vertex is updated.
	for i := 1; i < g.vertices; i++ {
		for _, edge := range g.edges {
			if distances[edge.from] != math.Inf(1) && distances[edge.from]+edge.weight < distances[edge.to] {
				distances[edge.to] = distances[edge.from] + edge.weight
			}
		}
	}

	// Step 3: Check for negative weight cycles.
	// After relaxing all edges, we do one more pass over all edges to see if we can still find a shorter path.
	// If we can, it means there is a negative weight cycle in the graph, indicating an arbitrage opportunity.
	for _, edge := range g.edges {
		if distances[edge.from] != math.Inf(1) && distances[edge.from]+edge.weight < distances[edge.to] {
			return true // Negative cycle detected, indicating an arbitrage opportunity
		}
	}

	// No negative cycles detected, hence no arbitrage opportunities.
	return false

Step 3: Example Usage

func main() {
	// A new graph is created with 4 vertices. Each vertex represents a different currency.
	graph := graph.NewGraph(4)

	// Representing exchange rates with negative logarithms. Exchange rates are converted to
	// negative logarithms to transform the problem into the shortest path problem.
	graph.AddEdge(0, 1, 0.5)  // USD to EUR
	graph.AddEdge(1, 2, 2.0)  // EUR to GBP
	graph.AddEdge(2, 3, 1.5)  // GBP to JPY
	graph.AddEdge(3, 0, 0.75) // JPY to USD

	// The method is called with source vertex 0, representing the starting currency (USD in this case).
	// currencyIndex: [USD": 0,"EUR": 1, "GBP": 2, "JPY": 3]
	if graph.DetectArbitrage(0) {
		slog.Info("Arbitrage opportunity detected!")
	} else {
		slog.Info("No arbitrage opportunity found.")
	}
}

For the full code, please visit gitHub repository, Trading Arbitrage Detector

Conclusion

By applying graph theory and the Bellman-Ford algorithm, we can efficiently identify arbitrage opportunities in financial markets. This method offers a systematic approach to uncovering profitable trades, illustrating the practical use of graph theory in real-world trading scenarios.

NOTE: I'm constantly delighted to receive feedback. Whether you spot an error, have a suggestion for improvement, or just want to share your thoughts, please don't hesitate to comment/reach out. I truly value connecting with readers!