# Triangular Arbitrage Bot Real-time triangular arbitrage detection and execution for KuCoin Spot. Single C binary — WebSocket book feeds, triangle evaluation, and order placement in one process. ## Architecture Monolithic single-process design using three pthreads: | Thread | Role | |---|---| | **Hot thread** | WebSocket I/O via epoll, order book maintenance, book update dispatch to evaluator | | **Evaluator** (embedded in hot thread) | Triangle profitability evaluation on every book update, pushes signals to SPSC queue | | **Executor thread(s)** | Pops signals from queue, places 3-leg HF market orders via KuCoin REST API, waits for fills via WebSocket, optional balance-wait between legs | ``` [KuCoin WS] ──▶ Hot Thread ──▶ Evaluator ──▶ SPSC Queue ──▶ Executor Thread(s) │ | Order Book KuCoin REST ``` The evaluator runs **in-process** on every book update (no cooldown). The executor does **not** re-evaluate — it trusts the signal as valid at emission time. ## Status | Component | Status | |---|---| | WebSocket client (level2/top5 depth) | Complete — multi-connection, reconnect, private balance/orderChange channels | | Order book store | Complete — bid/ask cache with sequence tracking | | Triangle enumeration | Complete — builder pattern from /api/v2/symbols | | Profitability evaluation | Complete — paper-trade simulation cascade matching executor | | SPSC signal queue | Complete — lock-free ring buffer + eventfd wakeup | | Order execution | Complete — HF market orders, fill event wait, balance wait | | Fill channel | Complete — eventfd-based cross-thread fill delivery | | Concurrent execution | Optional — configurable `concurrent_slots` (default 1) | | Fee table | Complete — fetched from /api/v1/base-fee, pair-specific lookup | | Balance wait | Optional — configurable `balance_wait_enabled` | ## Prerequisites - C compiler (gcc/clang), CMake 3.22+, OpenSSL, libyaml, pthreads ## Building ```bash mkdir -p build && cd build cmake ../src -DCMAKE_BUILD_TYPE=Release make -j$(nproc) ``` Binary at `build/fused_engine`. ## Configuration Edit `config.yaml` (see `config.yaml.example`): | Key | Description | |---|---| | `live_mode` | `false` = paper trades (test endpoint), `true` = real orders | | `signal_threshold_bps` | Minimum predicted bps to fire a signal (default: 2) | | `hold_currencies` | Currencies held as capital; triangles must start/end in one of these | | `excluded_currencies` | Currencies to exclude from triangle enumeration | | `kcs_discount_active` | Whether KCS fee discount applies | | `balance_wait_enabled` | Wait for WS balance settlement between live legs (default: false) | | `concurrent_slots` | Number of executor threads (default: 1, max 16) | | `initial_capital` | Map of currency to max quote per signal | | `kucoin_api_key/secret/passphrase` | KuCoin API credentials | ## Running ```bash ./build/fused_engine ``` Fetches fee table and symbol list, connects to KuCoin WebSocket, subscribes to order books, enumerates triangles, evaluates on every book update, and executes signals via REST. ## Project Structure ``` tri_arb/ ├── src/ # C source │ ├── main.c # Entry point, thread spawn │ ├── ws_client.c/h # KuCoin WebSocket client (TLS, epoll, book/balance/order frames) │ ├── book.c/h # Order book store (top-5 bid/ask) │ ├── symbols_api.c/h # Symbol discovery, triangle enumeration │ ├── triangle.c/h # Triangle set, leg, signal types │ ├── evaluate.c/h # Triangle evaluation and signal dispatch │ ├── executor.c/h # Signal execution, REST order placement, fill+balance wait │ ├── events.c/h # Event loops (hot thread + executor thread(s)) │ ├── fill_handler.c/h # Cross-thread fill event channel (SPSC ring + eventfd) │ ├── rest_client.c/h # KuCoin REST API client (signed requests, keepalive) │ ├── http_client.c/h # One-shot HTTPS requests (token fetch, fee table) │ ├── queue.c/h # SPSC lock-free queue (evaluator to executor) │ ├── config.c/h # YAML config parser │ ├── hash.c/h # Hash table │ ├── cJSON.c/h # JSON parser │ ├── log.c/h # Logging │ └── CMakeLists.txt ├── build/ # Build output ├── config.yaml # Runtime config (gitignored) ├── config.yaml.example # Config template └── scripts/ # Deployment scripts ```