- Drain signal queue eventfd (fds[0]) after each pop attempt.
Without this, the eventfd counter stays >0 forever after the first
signal, causing poll() to return immediately every iteration (100% CPU).
- Fix strncpy truncation warnings in fill_handler.c (use memcpy+nullterm)
- Fix write/read return value warnings in fill_handler.c, log.c
- Fix misleading indentation in http_client.c (add line breaks after if)
- Add concurrent_slots config (fused_engine section, default 1)
- Create executor_shared_t with shared in_flight table + queue mutex for multi-thread
- Move in_flight state from executor_thread_t to executor_shared_t (cross-thread isolation)
- event_executor_thread: per-thread entry point, N threads created in main.c
- Add fundsIncrement to trading_pair_t, triangle_t, signal_leg_t (fetch from KuCoin API)
- Use funds_increment for rounding market buy quote_cost (evaluate.c) and increment floor (executor.c)
- Fix leg 0: remove double-counted apply_fee_hold (evaluate already accounts via ff)
- Remove executor/ and common/ Python directories (dead code after C migration)
- Remove src/http_server.c/.h (was for Python executor, generates warnings)
- Remove dead config keys: socket_path, executor_socket_path, send_signals, rest_host, rest_port
- Remove dead UDS code in events.c/h (send_signal_to_executor, unix_* functions)
- Fix fee hold on leg 0 buys (apply_fee_hold to prevent Balance insufficient)
- Fix PnL leg0_in to use fills[0][4] instead of wrong currency field
- Fix REST keepalive warmup currency (use initial_capital[0] instead of hardcoded USDT)
- Add balance wait between legs via /account/balance WS + eventfd wake
- Fix all strncpy truncation warnings in config.c, symbols_api.c, ws_client.c
Replace the Python executor with direct C execution in a dedicated
executor thread. Removes UDS JSON serialization, Python async
overhead, and the 2+ms pipeline gap between signal creation and
order fire.
New components:
- src/rest_client.c/h: Keepalive HTTPS, HMAC-SHA256 signing,
order_place, order_test, Content-Length response parsing
- src/fill_handler.c/h: SPSC ring buffer for WS match events,
hot thread -> executor thread fill dispatch
- src/executor.c/h: execute_triangle() cascade, fee hold
reduction, increment floor, paper mode simulation, PnL,
concurrency isolation, reporting
Modified:
- src/ws_client.c: Subscribe to tradeOrdersV2 + account.balance,
dispatch orderChange match events to fill SPSC, private token
fetch via bullet-private, token cleared on reconnect
- src/http_client.c: Added https_post_auth() for signed POST
- src/events.c: Cold thread replaced with executor thread
(poll on wake_fd + fill_fd, direct execution)
- config.yaml.example: initial_capital moved to fused_engine,
added cooldown_seconds, kcs_discount_active
Removed:
- src/kucoin_sign.c/h (redundant with http_client.c helpers)
executor/executor.py:
- Replace unauthenticated /api/v1/time warmup with authenticated /api/v1/accounts
- Keepalive interval 15s -> 30s, uses authenticated warmup_session
- After sell leg, override filled_volume with latest balance from WS (net of fee)
executor/kucoin_api.py:
- Add warmup_session() method for GET /api/v1/accounts (authenticated)
- Pre-heats TCP/TLS connection pool to reduce first-order latency
executor/ws_client.py:
- Add latest_balance() method to expose WS balance cache
src/events.c:
- Always include book tops in signal (remove !sig->live gate)
- Only serialize top bid/ask level (not all 5)
Two-process architecture: a C17 fused engine (WebSocket order book
mirror, triangle enumeration, real-time profitability evaluation)
communicating via Unix domain socket to a Python 3 executor (order
placement with paper/live trading modes, REST control API).
Targets KuCoin spot market.