Grab is a high-performance, real-time cryptocurrency arbitrage detection engine written in modern C++20. It establishes concurrent secure WebSocket connections to the Binance live market data stream, builds an dynamic directed asset-exchange graph, and implements graph-theoretic cycle detection algorithms to find profitable triangular and multi-hop arbitrage opportunities.
By transforming live exchange rates into logarithmic weights, the engine models the multiplicative compounding of sequential trades as an additive path-finding problem, making it possible to locate profitable loops instantly using a customized Bellman-Ford negative-cycle detection algorithm.
-
Real-time Live Streaming: Connects directly to Binance's API via secure WebSockets using
Boost.Asio,Boost.Beast, andOpenSSL(TLS 1.3). - Asynchronous Multi-Threaded Engine: Utilizes asynchronous network I/O powered by a thread pool and synchronized via Boost.Asio strands to update exchange rates in a highly thread-safe, lock-free manner.
- Graph-Theoretic Arbitrage Search: Represents trading pairs as a dynamic directed graph. Logarithmic edge weights ($-\ln(\text{price})$) enable efficient detection of profitable loops using negative-weight cycle detection.
-
Automatic Session Management:
- Complies with Binance's strict API requirements by maintaining automated heartbeat ping-pong frames.
- Implements 24-hour connection cycling to prevent forceful server-side disconnects.
- Handles unexpected network disruption with automated reconnect logic and exponential backoff.
-
Live Consolidation Matrix: Dynamic tracking of 14 mainstream cryptocurrency assets (
USDT,USDC,BTC,ETH,BNB,ADA,SOL,XRP,TRX,LINK,BCH,SUI,AVAX,HBAR) in a synchronized cross-rate matrix. -
Modern C++20 Architecture: Leverages standard-compliant techniques, RAII smart pointers, precise type-safety, and compiler optimizations (
-O3,-march=native, Link-Time Optimization).
In standard trading, triangular or cyclic arbitrage is found when starting with an asset
Mathematically, for a cycle of exchange rates
Multiplying floating-point rates in real-time is computationally inefficient for large-scale path-finding. We can convert this multiplicative problem into an additive one by applying the natural logarithm (
Using log identities, this simplifies to:
Multiplying the entire inequality by
By defining the edge weight
The profit condition translates directly to:
This is the exact definition of a negative-weight cycle! The engine builds a directed graph where:
-
Vertices are assets (e.g.
BTC,ETH,USDT). - Edges represent available trading pairs.
-
Edge Weights are set to
$-\ln(\text{price})$ . For direct trades (buying$B$ with$A$ ), we use the ask price. For inverse trades (selling$B$ for$A$ ), we use the inverse of the bid price ($1 / \text{bid}$ ).
The Bellman-Ford algorithm is then executed over the graph. Since a negative cycle represents an infinite loop of negative weight, any detected cycle corresponds directly to a compounding arbitrage loop.
[ USDT ]
/ ^
/ \ (1/Bid, converted to -ln)
v \
[ BTC ] ------> [ ETH ]
(Ask, converted to -ln)
grab/
├── cmake/ # Custom CMake find modules (Boost, OpenSSL, nlohmann_json)
├── docs/ # Architectural and component design documents
│ ├── Connection.md # Secure WebSocket Client detail & state machines
│ └── Ticker.md # Stream-specific Ticker subscription wrapper
├── src/ # Source Directory
│ ├── main.cpp # App entrypoint, WebSocket orchestrator, and metrics console
│ ├── connection.hpp/.cpp # Secure multi-stream TLS WebSocket client using Boost.Beast
│ ├── ticker.hpp/.cpp # High-level ticker subscription wrapper
│ ├── algorithms/
│ │ └── bellman-ford.cpp # Reference DFS cyclic & min-weight algorithm helper
│ └── graph/
│ ├── graph.hpp/.cpp # Core directed graph, adjacency matrix, & Bellman-Ford cycle-finder
│ └── graph-bf.hpp # Alternative minimum cycle finder with depth-first searches
├── test/ # Unit and integration test suites
├── CMakeLists.txt # Top-level CMake configuration
├── CMakePresets.json # Compilation presets (Release/Debug using Ninja)
└── README.md # Project documentation
To compile the codebase, ensure you have the following dependencies installed on your system:
- C++ Compiler: GCC 10+ or Clang 11+ (C++20 support required)
- Build System: CMake 3.31+ and Ninja (recommended)
- Libraries:
- Boost 1.71.0+ (specifically system, thread, and header-only Beast/Asio)
- OpenSSL 3.0.0+ (needed for secure WebSocket TLS connections)
- nlohmann-json 3.7.3+ (modern JSON parser)
On Debian/Ubuntu-based systems, you can install the main prerequisites via:
sudo apt-get update
sudo apt-get install -y build-essential cmake ninja-build libboost-all-dev libssl-dev nlohmann-json3-devThis project leverages standard CMake Presets to simplify configure and build steps across various environments.
-
Configure the Project (using the
grabpreset):cmake --preset grab
-
Build the Engine:
cmake --build --preset grab
Upon successful compilation, the compiled executable will be located in the binary directory under:
.builds/grab/bin/Grab
Simply execute the compiled binary to start monitoring the market in real-time.
./.builds/grab/bin/GrabWhen running, the application will:
- Initialize the 14 vertices of the price graph.
- Establish separate parallel TLS WebSockets multiplexing data streams for all active trading pairs.
- Keep updating the consolidated
$14 \times 14$ bid/ask price matrix in real-time. - Scan the graph every 5 seconds to prevent rate limits and display detailed logs if an arbitrage opportunity exceeding the commission threshold (e.g.,
$0.1%$ per leg) is found.
*** ARBITRAGE OPPORTUNITY DETECTED ***
Path: USDT -> BTC -> ETH -> USDT
Prices: 95420.50000 -> 0.0614500 -> 5863.20000
Calculated Profit: 0.5420%
Estimated Profit (Net of Fees): 0.2420%
Opportunities found: 12
Max profit: 1.1042%
Accumulated profit: 5.4312%
*****************************************
The networking engine. It manages a raw TCP socket, handles SSL handshake negotiations with Binance's server via OpenSSL, and upgrades the session into an active RFC 6455 WebSocket.
- Auto-Reconnection: Re-establishes broken networks using configurable exponential backoff strategies.
- Ping/Pong Heartbeats: Regularly digests WebSocket ping frames sent by Binance and answers back with pONGs, maintaining connection longevity.
- 24-Hour Cycle: Explicitly schedules teardown and reinstantiation timers to conform with Binance’s strict connection age constraints.
Acts as a logical consumer wrapper for stream subscriptions.
- Multiplexes stream endpoints (e.g.,
<pair>@ticker) under a shared secure Connection to decrease connection overhead. - Connects data signals to targeted lambda callbacks, isolating business logic from low-level frame decoding.
The main data structures. Maps symbols to discrete indexes, computes direct/indirect edges dynamically, and performs cycle searches.
-
find_negative_cycle_bellman_ford(): Relaxes all$E$ edges up to$V-1$ times. In the$V$ -th iteration, if a further relaxation occurs, a negative cycle is traced back and reconstructed using a predecessor traversal list. -
calculate_arbitrage_profit(): Back-calculates cumulative compounded percentage yield over paths to ensure the math checks out perfectly before emitting signals.
This project is licensed under the MIT License. Feel free to use, modify, and distribute it for private or commercial purposes.