docs: update README to reflect single-binary architecture and current config

This commit is contained in:
nicolas 2026-05-28 20:50:03 -03:00
parent 6005b5ca88
commit f2c50b37ea
1 changed files with 58 additions and 63 deletions

113
README.md
View File

@ -1,37 +1,47 @@
# Triangular Arbitrage Bot
Real-time triangular arbitrage detection and execution for centralized crypto exchanges. Currently supports **KuCoin**.
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
Two-process design communicating via Unix domain sockets:
Monolithic single-process design using three pthreads:
| Process | Role |
| Thread | Role |
|---|---|
| `fused_engine` | C binary combining Feed Handler, Order Book, and Opportunity Engine. KuCoin WebSocket subscriber, order book mirror, triangle enumeration, live opportunity evaluation. Emits signals to executor. |
| `executor` | Consumes signals from `fused_engine`, places 3-leg KuCoin REST orders. Fire-and-forget: no re-evaluation, no queue, drop if busy. |
| **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] ──▶ [fused_engine] ──────────────────── Unix socket ──▶ [executor]
Triangle Evaluator
[KuCoin WS] ──▶ Hot Thread ──▶ Evaluator ──▶ SPSC Queue ──▶ Executor Thread(s)
|
Order Book KuCoin REST
```
`fused_engine` evaluates triangles on live book updates and emits signals to the executor. The executor does **not** re-evaluate books — it trusts the signal as valid at emission time and places orders directly via KuCoin REST API.
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 |
|---|---|
| `fused_engine` | Complete — WebSocket subscription, order book mirror, triangle enumeration, top-level profitability evaluation with chained `max_volume`, signal dispatch via Unix socket |
| `executor` | Complete — Signal consumption via Unix socket, paper-mode order validation via `/api/v1/hf/orders/test`, deterministic fill simulation, REST control API |
| 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, pthread
- Python 3.11+ (for executor only)
- C compiler (gcc/clang), CMake 3.22+, OpenSSL, libyaml, pthreads
## Building fused_engine
## Building
```bash
mkdir -p build && cd build
@ -43,67 +53,52 @@ Binary at `build/fused_engine`.
## Configuration
Edit `config.yaml`:
Edit `config.yaml` (see `config.yaml.example`):
- `hold_currencies` — currencies held as capital. Only triangles starting and ending in one of these are evaluated (default: `["USDT", "USDC", "USD1"]`)
- `excluded_currencies` — currencies to exclude from triangle enumeration
- `signal_threshold_bps` — minimum net profit in basis points to fire a signal (default: `0.2`)
- `cooldown_ms` — minimum milliseconds between opportunity notifications for the same triangle (default: `1000`)
- `api.key` / `api.secret` / `api.passphrase` — KuCoin API credentials
| 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
**Startup order:** `executor``fused_engine`
### 1. Start the executor
```bash
source .venv/bin/activate
python3 -m executor
```
Creates the Unix socket at `/tmp/executor.sock` and listens for signals.
### 2. Start fused_engine
```bash
./build/fused_engine
```
Fetches all KuCoin pairs, enumerates triangles, subscribes to WebSocket order books, evaluates triangles on every book update, and dispatches signals to the executor via Unix socket.
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 for fused_engine
│ ├── main.c # Entry point
│ ├── ws_client.c/h # KuCoin WebSocket client (TLS, masked frames)
│ ├── book.c/h # Order book store
├── 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 management
│ ├── evaluate.c/h # Triangle evaluation & signal construction
│ ├── events.c/h # Event loop, Unix socket client to executor
│ ├── queue.c/h # SPSC lock-free queue (hot → cold thread)
│ ├── 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
│ ├── http_client.c/h # KuCoin REST API client (HMAC signing)
│ ├── hash.c/h # Hash table
│ ├── cJSON.c/h # JSON parser
│ ├── jsmn.h # Minimal JSON tokenizer (header-only, unused)
│ ├── log.c/h # Logging
│ └── CMakeLists.txt
├── executor/ # Triangular Arbitrage Executor (Python)
│ ├── __main__.py
│ ├── executor.py
│ ├── kucoin_api.py
│ ├── rest_api.py
│ ├── socket_server.py
│ └── config.py
├── common/ # Shared Python utilities
│ ├── config.py
│ └── log.py
├── build/ # Build output (not committed)
├── scripts/
│ └── install.sh
├── config.yaml
└── config.yaml.example
├── build/ # Build output
├── config.yaml # Runtime config (gitignored)
├── config.yaml.example # Config template
└── scripts/ # Deployment scripts
```