ci/docs/sdk: drop lx-trading-cpp + sdk/cpp refs

Follow-up to 09c17ec which deleted the orphaned C++ trees.
Workflows + docs + sdk/Makefile still referenced them.

  .github/workflows/sdk-ci.yml     delete test-cpp job + drop from integration-check.needs
  .github/workflows/sdk-release.yml delete build-cpp job + drop from generate-checksums.needs
  sdk/Makefile                     delete build-cpp + test-cpp targets, clean ref
  sdk/README.md                    repoint cpp row to ~/work/luxcpp/dex/sdk/trading-cpp/
  docs/content/docs/sdk/cpp/       delete (sdk source moved; doc to be re-authored from luxcpp)

Also fixes the stale amm_gpu.go docstring (kernel moved to
~/work/luxcpp/metal/src/shaders/dex/, driver stays in dex/gpu/metal/).
This commit is contained in:
2026-05-21 14:29:39 -07:00
parent 09c17ec533
commit b3cd216951
10 changed files with 7 additions and 2308 deletions
+1 -33
View File
@@ -161,42 +161,10 @@ jobs:
- name: Build release
run: cargo build --release
# C++ SDK Tests
test-cpp:
name: C++ SDK
runs-on: ubuntu-latest
defaults:
run:
working-directory: sdk/lx-trading-cpp
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y cmake build-essential libssl-dev libcurl4-openssl-dev
- name: Configure CMake
run: |
mkdir -p build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DLX_TRADING_BUILD_TESTS=ON
- name: Build
run: |
cd build
make -j$(nproc)
- name: Run tests
run: |
cd build
./lx_trading_tests
# Integration test (all SDKs must pass)
integration-check:
name: Integration Check
needs: [test-go, test-typescript, test-python, test-rust, test-cpp]
needs: [test-go, test-typescript, test-python, test-rust]
runs-on: ubuntu-latest
steps:
- name: All SDK tests passed
+1 -65
View File
@@ -290,74 +290,10 @@ jobs:
sdk/lx-trading-core/lx-trading-rust-*.tar.gz
sdk/lx-trading-core/lx-trading-rust-*.zip
# Build C++ SDK
build-cpp:
name: C++ SDK (${{ matrix.os }})
needs: [validate-version, create-release]
strategy:
matrix:
include:
- os: lux-amd64
platform: linux-amd64
- os: macos-13
platform: darwin-amd64
- os: macos-14
platform: darwin-arm64
- os: windows-latest
platform: windows-amd64
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Install dependencies (Linux)
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install -y cmake build-essential libssl-dev libcurl4-openssl-dev
- name: Install dependencies (macOS)
if: startsWith(matrix.os, 'macos')
run: |
brew install cmake openssl curl
- name: Configure and Build
working-directory: sdk/lx-trading-cpp
shell: bash
run: |
mkdir -p build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DLX_TRADING_BUILD_TESTS=OFF
cmake --build . --config Release -j
- name: Package
working-directory: sdk/lx-trading-cpp
shell: bash
run: |
mkdir -p dist/lib dist/include
cp -r include/* dist/include/
if [ "${{ matrix.os }}" = "windows-latest" ]; then
cp build/Release/*.lib dist/lib/ 2>/dev/null || cp build/*.lib dist/lib/ 2>/dev/null || true
cp build/Release/*.dll dist/lib/ 2>/dev/null || cp build/*.dll dist/lib/ 2>/dev/null || true
cd dist && 7z a ../lx-trading-cpp-${{ matrix.platform }}.zip *
else
cp build/*.a dist/lib/ 2>/dev/null || true
cp build/*.so dist/lib/ 2>/dev/null || true
cp build/*.dylib dist/lib/ 2>/dev/null || true
tar -czf lx-trading-cpp-${{ matrix.platform }}.tar.gz -C dist .
fi
- name: Upload Release Asset
uses: softprops/action-gh-release@v2
with:
tag_name: sdk-v${{ needs.validate-version.outputs.version }}
files: |
sdk/lx-trading-cpp/lx-trading-cpp-*.tar.gz
sdk/lx-trading-cpp/lx-trading-cpp-*.zip
# Generate checksums
generate-checksums:
name: Generate Checksums
needs: [validate-version, build-go, build-typescript, build-python, build-rust, build-cpp]
needs: [validate-version, build-go, build-typescript, build-python, build-rust]
runs-on: ubuntu-latest
steps:
- name: Download all artifacts
-569
View File
@@ -1,569 +0,0 @@
---
title: Client
description: Connection management, SSL/TLS configuration, and reconnection strategies for the C++ SDK
---
# Client
The `Client` class manages WebSocket connections to LX, handling authentication, connection pooling, automatic reconnection, and request/response correlation.
## Connection Architecture
```
+--------------------------------------------------+
| Client |
| +--------------------------------------------+ |
| | Connection Pool | |
| | +--------+ +--------+ +--------+ | |
| | | Conn 0 | | Conn 1 | | Conn 2 | ... | |
| | +--------+ +--------+ +--------+ | |
| +--------------------------------------------+ |
| | Request Router (Round-Robin) | |
| +--------------------------------------------+ |
| | Response Correlator (Lock-Free) | |
| +--------------------------------------------+
+--------------------------------------------------+
```
## Basic Usage
### Creating a Client
```cpp
#include <lxdex/client.hpp>
using namespace lxdex;
// Simple construction
Client client("wss://api.lux.network/ws");
// With options
Client client({
.endpoints = {
"wss://api.lux.network/ws",
"wss://api2.lux.network/ws" // Failover
},
.api_key = "your-api-key",
.api_secret = "your-api-secret"
});
```
### Connection Lifecycle
```cpp
#include <lxdex/client.hpp>
#include <iostream>
int main() {
using namespace lxdex;
Client client({
.endpoints = {"wss://api.lux.network/ws"},
.api_key = std::getenv("LX_API_KEY")
});
// Register lifecycle callbacks
client.on_connect([](const ConnectionInfo& info) {
std::cout << "Connected to " << info.endpoint
<< " (latency: " << info.latency_us << "us)\n";
});
client.on_disconnect([](const DisconnectReason& reason) {
std::cout << "Disconnected: " << reason.message << '\n';
});
client.on_error([](const Error& error) {
std::cerr << "Error: " << error.message << '\n';
});
// Connect with timeout
auto result = client.connect(std::chrono::seconds{10});
if (!result) {
std::cerr << "Connection failed: " << result.error() << '\n';
return 1;
}
// Client is now connected and authenticated
std::cout << "Session ID: " << client.session_id() << '\n';
// Graceful shutdown
client.disconnect();
return 0;
}
```
## Client Configuration
### Full Configuration Options
```cpp
struct ClientConfig {
// Network
std::vector<std::string> endpoints;
std::string api_key;
std::string api_secret;
std::optional<std::string> proxy_url;
// Connection pool
std::size_t pool_size = 4;
bool use_kernel_bypass = false; // io_uring/DPDK
// Timeouts
std::chrono::milliseconds connect_timeout{5000};
std::chrono::milliseconds request_timeout{1000};
std::chrono::milliseconds heartbeat_interval{30000};
// SSL/TLS
TlsConfig tls;
// Reconnection
ReconnectConfig reconnect;
// Memory
std::size_t write_buffer_size = 64 * 1024;
std::size_t read_buffer_size = 64 * 1024;
// Threading
std::size_t io_threads = 1;
std::optional<std::vector<int>> cpu_affinity;
};
```
### TLS Configuration
```cpp
struct TlsConfig {
bool verify_peer = true;
bool verify_host = true;
std::string ca_cert_path; // CA certificate file
std::string client_cert_path; // Client certificate (mTLS)
std::string client_key_path; // Client private key (mTLS)
std::string cipher_list; // OpenSSL cipher string
TlsVersion min_version = TlsVersion::TLS_1_3;
};
// Example: Production TLS setup
Client client({
.endpoints = {"wss://api.lux.network/ws"},
.tls = {
.verify_peer = true,
.verify_host = true,
.ca_cert_path = "/etc/ssl/certs/ca-certificates.crt",
.min_version = TlsVersion::TLS_1_3
}
});
// Example: Mutual TLS (mTLS)
Client client({
.endpoints = {"wss://secure.lux.network/ws"},
.tls = {
.verify_peer = true,
.ca_cert_path = "/path/to/ca.pem",
.client_cert_path = "/path/to/client.pem",
.client_key_path = "/path/to/client.key"
}
});
```
### Reconnection Strategy
```cpp
struct ReconnectConfig {
bool enabled = true;
std::size_t max_attempts = 10;
std::chrono::milliseconds initial_delay{100};
std::chrono::milliseconds max_delay{30000};
double backoff_multiplier = 2.0;
bool jitter = true; // Randomize delays
};
// Example: Aggressive reconnection for HFT
Client client({
.endpoints = {"wss://api.lux.network/ws"},
.reconnect = {
.enabled = true,
.max_attempts = 100,
.initial_delay = std::chrono::milliseconds{10},
.max_delay = std::chrono::milliseconds{1000},
.backoff_multiplier = 1.5
}
});
// Example: Fail-fast for latency-critical paths
Client client({
.reconnect = {.enabled = false} // Fail immediately
});
```
## Connection Pool
The client maintains a pool of connections for load distribution and redundancy.
### Pool Configuration
```cpp
Client client({
.endpoints = {
"wss://api.lux.network/ws",
"wss://api2.lux.network/ws"
},
.pool_size = 8, // 8 connections per endpoint
});
// Query pool status
auto status = client.pool_status();
std::cout << "Active connections: " << status.active << '\n';
std::cout << "Pending requests: " << status.pending_requests << '\n';
```
### Connection Selection
```cpp
// Default: Round-robin
client.set_connection_strategy(ConnectionStrategy::RoundRobin);
// Latency-based: Route to fastest connection
client.set_connection_strategy(ConnectionStrategy::LowestLatency);
// Affinity: Sticky sessions per symbol
client.set_connection_strategy(ConnectionStrategy::SymbolAffinity);
```
## Authentication
### API Key Authentication
```cpp
Client client({
.endpoints = {"wss://api.lux.network/ws"},
.api_key = "pk_live_...",
.api_secret = "sk_live_..."
});
// Authentication happens automatically on connect
client.connect();
```
### JWT Authentication
```cpp
Client client({
.endpoints = {"wss://api.lux.network/ws"}
});
// Set JWT token (can be refreshed)
client.set_auth_token("eyJhbGciOiJIUzI1NiIs...");
// Refresh token before expiry
client.on_token_expiring([&client](std::chrono::seconds remaining) {
if (remaining < std::chrono::seconds{60}) {
auto new_token = refresh_token(); // Your refresh logic
client.set_auth_token(new_token);
}
});
```
### Signature-Based Authentication (HFT)
```cpp
#include <lxdex/auth/signer.hpp>
// Create Ed25519 signer
auto signer = Signer::from_private_key("/path/to/private.key");
Client client({
.endpoints = {"wss://api.lux.network/ws"},
.signer = std::move(signer)
});
// Each request is automatically signed
// Signature: Ed25519(timestamp || nonce || body)
```
## Request/Response
### Synchronous Requests
```cpp
// Blocking call with timeout
auto result = client.request(
"lx_getOrderBook",
{{"symbol", "BTC-USD"}, {"depth", 10}},
std::chrono::milliseconds{100}
);
if (result) {
auto& book = *result;
std::cout << "Best bid: " << book["bids"][0]["price"] << '\n';
}
```
### Asynchronous Requests
```cpp
// Future-based
auto future = client.request_async(
"lx_placeOrder",
{{"symbol", "BTC-USD"}, {"side", "buy"}, {"price", 50000}}
);
// Non-blocking check
if (future.wait_for(std::chrono::microseconds{10}) == std::future_status::ready) {
auto result = future.get();
// Process...
}
```
### Callback-Based (Zero Allocation)
```cpp
// Pre-allocate response buffer
alignas(64) std::array<char, 4096> buffer;
client.request_callback(
"lx_getOrder",
{{"orderId", order_id}},
[&buffer](std::span<const char> response) {
// Response arrives here on I/O thread
// Zero-copy: response points directly to network buffer
std::memcpy(buffer.data(), response.data(), response.size());
}
);
```
## Subscriptions
### Market Data Streams
```cpp
// Order book subscription
auto sub = client.subscribe("orderbook", {{"symbol", "BTC-USD"}},
[](const json& update) {
// Called on I/O thread
}
);
// Unsubscribe
sub.cancel();
// Or use RAII
{
auto sub = client.subscribe(...);
// Auto-unsubscribe when sub goes out of scope
}
```
### Multiple Subscriptions
```cpp
// Subscribe to multiple symbols
client.subscribe_batch({
{"orderbook", {{"symbol", "BTC-USD"}}},
{"orderbook", {{"symbol", "ETH-USD"}}},
{"trades", {{"symbol", "BTC-USD"}}}
}, [](const std::string& channel, const json& data) {
if (channel == "orderbook") {
// Handle order book
} else if (channel == "trades") {
// Handle trades
}
});
```
## Error Handling
### Error Types
```cpp
enum class ErrorCode {
// Connection errors
ConnectionFailed,
ConnectionLost,
ConnectionTimeout,
TlsError,
// Authentication errors
AuthenticationFailed,
InvalidCredentials,
TokenExpired,
// Request errors
InvalidRequest,
MethodNotFound,
RateLimited,
InsufficientBalance,
// Internal errors
InternalError,
Timeout
};
struct Error {
ErrorCode code;
std::string message;
std::optional<int> rpc_code;
std::chrono::system_clock::time_point timestamp;
};
```
### Error Handling Patterns
```cpp
// Using std::expected (C++23)
auto result = client.place_order(order);
if (!result) {
handle_error(result.error());
return;
}
auto& placed_order = *result;
// Exception mode (opt-in)
client.enable_exceptions(true);
try {
auto order = client.place_order_throwing(order);
} catch (const lxdex::ConnectionError& e) {
// Handle connection issues
} catch (const lxdex::RateLimitError& e) {
std::this_thread::sleep_for(e.retry_after);
}
```
## Metrics and Monitoring
```cpp
// Get connection metrics
auto metrics = client.metrics();
std::cout << "Messages sent: " << metrics.messages_sent << '\n';
std::cout << "Messages received: " << metrics.messages_received << '\n';
std::cout << "Bytes sent: " << metrics.bytes_sent << '\n';
std::cout << "Bytes received: " << metrics.bytes_received << '\n';
std::cout << "Latency p50: " << metrics.latency_p50_us << "us\n";
std::cout << "Latency p99: " << metrics.latency_p99_us << "us\n";
std::cout << "Reconnections: " << metrics.reconnection_count << '\n';
// Reset metrics
client.reset_metrics();
// Prometheus export
std::cout << client.metrics_prometheus();
```
## RAII and Lifetime
```cpp
class TradingEngine {
lxdex::Client client_;
std::unique_ptr<lxdex::Subscription> book_sub_;
public:
TradingEngine(const Config& cfg)
: client_({
.endpoints = {cfg.endpoint},
.api_key = cfg.api_key
})
{
client_.connect();
book_sub_ = std::make_unique<lxdex::Subscription>(
client_.subscribe("orderbook", {{"symbol", "BTC-USD"}},
[this](const json& update) { on_book_update(update); }
)
);
}
~TradingEngine() {
// RAII: Subscriptions auto-cancel, connections auto-close
// Explicit shutdown for graceful disconnect
client_.disconnect();
}
private:
void on_book_update(const json& update);
};
```
## Thread Safety
| Method | Thread Safety |
|--------|---------------|
| `connect()` | Call from single thread |
| `disconnect()` | Call from single thread |
| `request()` | Thread-safe |
| `request_async()` | Thread-safe |
| `subscribe()` | Thread-safe |
| `metrics()` | Thread-safe (atomic reads) |
| Callbacks | Invoked on I/O thread |
## Best Practices
1. **Reuse clients**: Create once, use for application lifetime
2. **Use connection pool**: Set `pool_size` based on request volume
3. **Handle reconnection**: Always register `on_disconnect` callback
4. **Prefer async**: Use `request_async` for non-blocking operations
5. **Pin I/O threads**: Set `cpu_affinity` for deterministic latency
6. **Monitor metrics**: Track latency and error rates
## Example: Production Client Setup
```cpp
#include <lxdex/client.hpp>
#include <csignal>
#include <atomic>
std::atomic<bool> running{true};
void signal_handler(int) {
running.store(false, std::memory_order_release);
}
int main() {
std::signal(SIGINT, signal_handler);
std::signal(SIGTERM, signal_handler);
using namespace lxdex;
Client client({
.endpoints = {
"wss://api.lux.network/ws",
"wss://api2.lux.network/ws"
},
.api_key = std::getenv("LX_API_KEY"),
.api_secret = std::getenv("LX_API_SECRET"),
.pool_size = 4,
.tls = {
.verify_peer = true,
.min_version = TlsVersion::TLS_1_3
},
.reconnect = {
.enabled = true,
.max_attempts = 50
},
.io_threads = 2,
.cpu_affinity = {0, 1}
});
client.on_connect([](const ConnectionInfo& info) {
spdlog::info("Connected to {} ({}us)", info.endpoint, info.latency_us);
});
client.on_disconnect([](const DisconnectReason& reason) {
spdlog::warn("Disconnected: {}", reason.message);
});
if (auto result = client.connect(); !result) {
spdlog::error("Failed to connect: {}", result.error().message);
return 1;
}
// Main loop
while (running.load(std::memory_order_acquire)) {
// Trading logic...
std::this_thread::sleep_for(std::chrono::milliseconds{1});
}
spdlog::info("Shutting down...");
client.disconnect();
return 0;
}
```
-378
View File
@@ -1,378 +0,0 @@
---
title: C++ SDK
description: High-performance C++ SDK for LX - HFT-grade trading with sub-microsecond latency
---
# C++ SDK
> **Specification**: [LP-9002 DEX API & RPC](https://github.com/luxfi/LPs/blob/main/LPs/lp-9002-dex-api-rpc-specification.md) | **Source**: [luxfi/dex-cpp](https://github.com/luxfi/dex/tree/main/sdk/cpp)
The LX C++ SDK is designed for high-frequency trading (HFT) applications requiring sub-microsecond latency and deterministic performance. Built with modern C++20 features, lock-free data structures, and zero-copy networking.
## Features
| Feature | Description |
|---------|-------------|
| **Sub-microsecond latency** | 597ns order placement, lock-free hot paths |
| **Zero-copy networking** | io_uring on Linux, kqueue on macOS |
| **Lock-free order book** | Wait-free reads, obstruction-free writes |
| **SIMD price matching** | AVX-512/NEON vectorized comparisons |
| **Memory pools** | Pre-allocated arenas, no heap allocation on hot path |
| **Header-only option** | Single `lxdex.hpp` for rapid integration |
## Requirements
- **Compiler**: GCC 12+, Clang 15+, or MSVC 19.35+
- **C++ Standard**: C++20 (C++17 compatibility mode available)
- **CMake**: 3.21+
- **Dependencies**: OpenSSL 3.0+, Boost 1.83+ (optional)
## Installation
### vcpkg (Recommended)
```bash
# Add LX overlay
vcpkg add overlay-port https://github.com/luxfi/vcpkg-registry
# Install the SDK
vcpkg install lxdex-cpp
```
### CMake FetchContent
```cmake
include(FetchContent)
FetchContent_Declare(
lxdex
GIT_REPOSITORY https://github.com/luxfi/dex.git
GIT_TAG v1.0.0
SOURCE_SUBDIR sdk/cpp
)
FetchContent_MakeAvailable(lxdex)
target_link_libraries(your_app PRIVATE lxdex::lxdex)
```
### Header-Only Mode
```cpp
#define LXDEX_HEADER_ONLY
#include <lxdex/lxdex.hpp>
```
### Manual Build
```bash
git clone https://github.com/luxfi/dex.git
cd dex/sdk/cpp
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release \
-DLXDEX_BUILD_TESTS=ON \
-DLXDEX_BUILD_BENCHMARKS=ON \
..
cmake --build . -j$(nproc)
sudo cmake --install .
```
## CMakeLists.txt Examples
### Minimal Project
```cmake
cmake_minimum_required(VERSION 3.21)
project(my_trading_bot LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(lxdex REQUIRED)
add_executable(trading_bot main.cpp)
target_link_libraries(trading_bot PRIVATE lxdex::lxdex)
```
### HFT Production Build
```cmake
cmake_minimum_required(VERSION 3.21)
project(hft_engine LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# HFT-grade compiler flags
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -march=native -mtune=native -flto=auto")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-rtti -fno-exceptions")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -ffast-math -funroll-loops")
# Link-time optimization
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE ON)
# Prefer static linking for deterministic deployment
set(BUILD_SHARED_LIBS OFF)
find_package(lxdex REQUIRED)
find_package(OpenSSL REQUIRED)
add_executable(hft_engine
src/main.cpp
src/strategy.cpp
src/risk.cpp
)
target_link_libraries(hft_engine PRIVATE
lxdex::lxdex
lxdex::lockfree
OpenSSL::SSL
OpenSSL::Crypto
)
# CPU affinity and huge pages support
target_compile_definitions(hft_engine PRIVATE
LXDEX_USE_HUGE_PAGES
LXDEX_CPU_AFFINITY
LXDEX_DISABLE_LOGGING # No logging on hot path
)
```
### vcpkg Integration
Create `vcpkg.json` in your project root:
```json
{
"name": "my-trading-app",
"version": "1.0.0",
"dependencies": [
"lxdex-cpp",
"openssl",
{
"name": "boost-lockfree",
"features": ["spsc-queue"]
}
],
"builtin-baseline": "2024.01.12"
}
```
Then in CMakeLists.txt:
```cmake
cmake_minimum_required(VERSION 3.21)
# vcpkg toolchain (before project())
if(DEFINED ENV{VCPKG_ROOT})
set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake")
endif()
project(my_trading_app LANGUAGES CXX)
find_package(lxdex CONFIG REQUIRED)
target_link_libraries(my_app PRIVATE lxdex::lxdex)
```
## Quick Start
### Connect and Place Order
```cpp
#include <lxdex/client.hpp>
#include <lxdex/order.hpp>
#include <iostream>
int main() {
using namespace lxdex;
// Create client with connection pool
Client client({
.endpoints = {"wss://api.lux.network/ws"},
.api_key = std::getenv("LX_API_KEY"),
.pool_size = 4,
.use_kernel_bypass = true // DPDK/io_uring
});
// Connect with timeout
if (auto result = client.connect(std::chrono::seconds{5}); !result) {
std::cerr << "Connection failed: " << result.error() << '\n';
return 1;
}
// Place limit order (non-blocking)
auto order_future = client.place_order({
.symbol = "BTC-USD",
.side = Side::Buy,
.type = OrderType::Limit,
.price = Price{50000'00}, // Fixed-point: $50,000.00
.quantity = Quantity{1'00000000}, // 1.0 BTC (8 decimals)
.time_in_force = TimeInForce::GTC
});
// Non-blocking check
if (order_future.wait_for(std::chrono::microseconds{100}) == std::future_status::ready) {
auto order = order_future.get();
std::cout << "Order ID: " << order.id << '\n';
}
return 0;
}
```
### Subscribe to Market Data
```cpp
#include <lxdex/client.hpp>
#include <lxdex/orderbook.hpp>
int main() {
using namespace lxdex;
Client client({"wss://api.lux.network/ws"});
client.connect();
// Lock-free order book subscription
client.subscribe_orderbook("BTC-USD", [](const OrderBook& book) {
// Called on dedicated I/O thread - keep fast!
auto [bid, ask] = book.best_bid_ask();
if (bid && ask) {
auto spread = ask->price - bid->price;
// Process spread...
}
});
// Keep running
std::this_thread::sleep_for(std::chrono::hours{24});
}
```
## Architecture Overview
```
+--------------------------------------------------+
| Application |
+--------------------------------------------------+
| Client | OrderBook | TradeHandler |
+--------------------------------------------------+
| Connection Pool (io_uring) |
+--------------------------------------------------+
| Lock-Free | Memory | SIMD |
| Queues | Pools | Price Match |
+--------------------------------------------------+
| OpenSSL / BoringSSL |
+--------------------------------------------------+
```
## SDK Components
| Component | Header | Description |
|-----------|--------|-------------|
| `Client` | `<lxdex/client.hpp>` | Connection management, request/response |
| `OrderBook` | `<lxdex/orderbook.hpp>` | Lock-free order book with SIMD matching |
| `Order` | `<lxdex/order.hpp>` | Order types, builders, validation |
| `Trade` | `<lxdex/trade.hpp>` | Trade events, callbacks |
| `Pool` | `<lxdex/memory/pool.hpp>` | Memory pools, arenas |
| `Lockfree` | `<lxdex/lockfree/spsc.hpp>` | SPSC/MPSC queues |
## Configuration Options
### Compile-Time Options
```cmake
# Enable/disable features
option(LXDEX_HEADER_ONLY "Header-only mode" OFF)
option(LXDEX_USE_BOOST "Use Boost.Asio instead of standalone" OFF)
option(LXDEX_USE_IOURING "Use io_uring (Linux 5.1+)" ON)
option(LXDEX_USE_SIMD "Enable SIMD optimizations" ON)
option(LXDEX_BUILD_TESTS "Build unit tests" OFF)
option(LXDEX_BUILD_BENCHMARKS "Build benchmarks" OFF)
```
### Runtime Configuration
```cpp
lxdex::Config config{
.network = {
.connect_timeout_ms = 5000,
.read_timeout_ms = 1000,
.write_buffer_size = 64 * 1024,
.read_buffer_size = 64 * 1024,
.tcp_nodelay = true,
.tcp_quickack = true,
.so_busy_poll = 50, // microseconds
},
.memory = {
.use_huge_pages = true,
.arena_size = 1024 * 1024, // 1MB
.order_pool_size = 100000,
},
.threading = {
.io_threads = 2,
.cpu_affinity = {0, 1}, // Pin to cores 0,1
.realtime_priority = true,
}
};
Client client(config);
```
## Benchmarks
Measured on AMD EPYC 7763, single-threaded, kernel bypass enabled:
| Operation | Latency (p50) | Latency (p99) | Throughput |
|-----------|---------------|---------------|------------|
| Order Place | 597ns | 1.2us | 1.67M/s |
| Order Cancel | 312ns | 890ns | 3.2M/s |
| Book Update | 89ns | 210ns | 11.2M/s |
| Trade Callback | 45ns | 120ns | 22.2M/s |
## Thread Safety
- **Client**: Thread-safe, uses internal connection pool
- **OrderBook**: Lock-free reads, single-writer updates
- **Order**: Immutable after construction
- **Callbacks**: Invoked on dedicated I/O threads
See [Threading Guide](/docs/sdk/cpp/threading) for detailed concurrency patterns.
## Error Handling
The SDK uses `std::expected` (C++23) or a backport for C++20:
```cpp
auto result = client.place_order(order);
if (result) {
std::cout << "Order ID: " << result->id << '\n';
} else {
switch (result.error().code) {
case ErrorCode::InsufficientBalance:
// Handle...
break;
case ErrorCode::RateLimited:
// Backoff...
break;
default:
std::cerr << result.error().message << '\n';
}
}
```
## Next Steps
- [Client Guide](/docs/sdk/cpp/client) - Connection management and SSL/TLS
- [Orders Guide](/docs/sdk/cpp/orders) - Order operations and types
- [OrderBook Guide](/docs/sdk/cpp/orderbook) - Lock-free data structures
- [Memory Guide](/docs/sdk/cpp/memory) - RAII and memory pools
- [Threading Guide](/docs/sdk/cpp/threading) - Concurrency patterns
- [Performance Guide](/docs/sdk/cpp/performance) - Low-latency optimization
## Support
- **GitHub Issues**: [luxfi/dex/issues](https://github.com/luxfi/dex/issues)
- **Discord**: [discord.gg/luxfi](https://discord.gg/luxfi) `#cpp-sdk`
- **API Status**: [status.lux.network](https://status.lux.network)
-9
View File
@@ -1,9 +0,0 @@
{
"title": "C++ SDK",
"pages": [
"index",
"client",
"orders",
"orderbook"
]
}
-587
View File
@@ -1,587 +0,0 @@
---
title: OrderBook
description: Lock-free order book data structures, SIMD price matching, and real-time updates
---
# OrderBook
The `OrderBook` class provides a lock-free, cache-optimized representation of market depth with wait-free reads and obstruction-free writes, designed for HFT applications requiring sub-microsecond access.
## Architecture
```
+----------------------------------------------------------+
| OrderBook |
| +------------------------+ +------------------------+ |
| | Bid Side | | Ask Side | |
| | (Sorted Descending) | | (Sorted Ascending) | |
| | +------------------+ | | +------------------+ | |
| | | Level 0 (Best) | | | | Level 0 (Best) | | |
| | | Price: 50000.00 | | | | Price: 50000.01 | | |
| | | Qty: 10.5 | | | | Qty: 8.2 | | |
| | | Orders: 15 | | | | Orders: 12 | | |
| | +------------------+ | | +------------------+ | |
| | | Level 1 | | | | Level 1 | | |
| | | Price: 49999.99 | | | | Price: 50000.02 | | |
| | +------------------+ | | +------------------+ | |
| | | ... | | | | ... | | |
| +------------------------+ +------------------------+ |
+----------------------------------------------------------+
```
## Basic Usage
### Creating an OrderBook
```cpp
#include <lxdex/orderbook.hpp>
using namespace lxdex;
// Create order book with default capacity
OrderBook book("BTC-USD");
// Create with specified depth
OrderBook book("BTC-USD", {
.max_levels = 1000,
.use_simd = true,
.cache_aligned = true
});
```
### Subscribing to Order Book Updates
```cpp
Client client({.endpoints = {"wss://api.lux.network/ws"}});
client.connect();
// Subscribe with callback
client.subscribe_orderbook("BTC-USD", [](const OrderBook& book) {
// Called on I/O thread with lock-free read access
auto [bid, ask] = book.best_bid_ask();
if (bid && ask) {
auto spread = ask->price - bid->price;
auto mid = (bid->price + ask->price) / 2;
std::cout << "Spread: " << spread.to_string()
<< " Mid: " << mid.to_string() << '\n';
}
});
```
### Accessing Book Data
```cpp
// Best bid/ask (O(1))
auto [bid, ask] = book.best_bid_ask();
// Specific level (O(1))
auto level = book.bid_level(5); // 5th best bid
// All bids/asks (O(n))
for (const auto& level : book.bids()) {
std::cout << level.price.to_string() << " x "
<< level.quantity.to_string() << '\n';
}
// Top N levels
auto top_bids = book.top_bids(10);
auto top_asks = book.top_asks(10);
```
## Price Level Structure
```cpp
namespace lxdex {
struct PriceLevel {
Price price;
Quantity quantity;
uint32_t order_count;
Timestamp last_update;
// Calculated fields
[[nodiscard]] Price notional() const noexcept {
return price * quantity;
}
};
// Cache-line aligned for performance
static_assert(sizeof(PriceLevel) <= 64);
static_assert(alignof(PriceLevel) == 64);
} // namespace lxdex
```
## Lock-Free Implementation
### Wait-Free Reads
```cpp
// Multiple reader threads can access simultaneously
// No locks, no contention, deterministic latency
std::thread reader1([&book] {
while (running) {
auto bid = book.best_bid(); // Wait-free O(1)
process_bid(bid);
}
});
std::thread reader2([&book] {
while (running) {
auto spread = book.spread(); // Wait-free O(1)
process_spread(spread);
}
});
```
### Obstruction-Free Writes
```cpp
// Single writer thread applies updates
// Uses atomic compare-and-swap for consistency
void apply_update(OrderBook& book, const BookUpdate& update) {
switch (update.type) {
case UpdateType::Set:
book.set_level(update.side, update.price, update.quantity);
break;
case UpdateType::Delete:
book.delete_level(update.side, update.price);
break;
}
}
```
### Memory Ordering
```cpp
// SeqLock pattern for consistent snapshots
class OrderBook {
mutable std::atomic<uint64_t> sequence_{0};
std::array<PriceLevel, MAX_LEVELS> bids_;
std::array<PriceLevel, MAX_LEVELS> asks_;
public:
// Reader: retry until consistent read
std::optional<PriceLevel> best_bid() const noexcept {
PriceLevel level;
uint64_t seq1, seq2;
do {
seq1 = sequence_.load(std::memory_order_acquire);
if (seq1 & 1) continue; // Write in progress
level = bids_[0]; // Read
std::atomic_thread_fence(std::memory_order_acquire);
seq2 = sequence_.load(std::memory_order_relaxed);
} while (seq1 != seq2);
if (level.quantity.raw() == 0) return std::nullopt;
return level;
}
// Writer: increment sequence before and after
void set_level(Side side, Price price, Quantity qty) noexcept {
sequence_.fetch_add(1, std::memory_order_release); // Odd = writing
std::atomic_thread_fence(std::memory_order_release);
// Perform update...
std::atomic_thread_fence(std::memory_order_release);
sequence_.fetch_add(1, std::memory_order_release); // Even = done
}
};
```
## SIMD Price Matching
### AVX-512 Implementation
```cpp
#include <lxdex/simd/avx512.hpp>
// Find price level using SIMD (8 prices per comparison)
std::optional<size_t> find_price_level_avx512(
const std::array<int64_t, 1024>& prices,
int64_t target_price,
size_t count
) {
__m512i target = _mm512_set1_epi64(target_price);
for (size_t i = 0; i < count; i += 8) {
__m512i prices_vec = _mm512_load_epi64(&prices[i]);
__mmask8 mask = _mm512_cmpeq_epi64_mask(prices_vec, target);
if (mask != 0) {
return i + __builtin_ctz(mask);
}
}
return std::nullopt;
}
```
### NEON Implementation (ARM)
```cpp
#include <lxdex/simd/neon.hpp>
// Find price level using NEON (2 prices per comparison)
std::optional<size_t> find_price_level_neon(
const std::array<int64_t, 1024>& prices,
int64_t target_price,
size_t count
) {
int64x2_t target = vdupq_n_s64(target_price);
for (size_t i = 0; i < count; i += 2) {
int64x2_t prices_vec = vld1q_s64(&prices[i]);
uint64x2_t cmp = vceqq_s64(prices_vec, target);
if (vgetq_lane_u64(cmp, 0)) return i;
if (vgetq_lane_u64(cmp, 1)) return i + 1;
}
return std::nullopt;
}
```
### Automatic Dispatch
```cpp
// Runtime SIMD detection
OrderBook book("BTC-USD", {
.use_simd = true, // Auto-detect best SIMD
.simd_hint = SimdHint::Auto // Or: AVX512, AVX2, NEON, Scalar
});
// Manual dispatch
#if defined(__AVX512F__)
auto idx = find_price_level_avx512(prices, target, count);
#elif defined(__AVX2__)
auto idx = find_price_level_avx2(prices, target, count);
#elif defined(__ARM_NEON)
auto idx = find_price_level_neon(prices, target, count);
#else
auto idx = find_price_level_scalar(prices, target, count);
#endif
```
## Book Snapshots
### Full Snapshot
```cpp
// Get immutable snapshot (copy)
auto snapshot = book.snapshot();
// Process snapshot on different thread
std::thread processor([snapshot = std::move(snapshot)] {
for (const auto& level : snapshot.bids()) {
analyze_level(level);
}
});
```
### Incremental Updates
```cpp
// Subscribe to incremental updates
client.subscribe_orderbook_incremental("BTC-USD",
// Snapshot callback (called first)
[&book](const OrderBookSnapshot& snap) {
book.apply_snapshot(snap);
},
// Delta callback (called for each update)
[&book](const OrderBookDelta& delta) {
book.apply_delta(delta);
}
);
```
### Delta Structure
```cpp
struct OrderBookDelta {
std::string symbol;
uint64_t sequence;
Timestamp timestamp;
struct Change {
Side side;
Price price;
Quantity quantity; // 0 = delete level
};
std::vector<Change> changes;
};
// Apply delta
void OrderBook::apply_delta(const OrderBookDelta& delta) {
if (delta.sequence != expected_sequence_) {
// Gap detected - request full snapshot
return;
}
for (const auto& change : delta.changes) {
if (change.quantity.raw() == 0) {
delete_level(change.side, change.price);
} else {
set_level(change.side, change.price, change.quantity);
}
}
++expected_sequence_;
}
```
## Market Metrics
### Spread and Mid-Price
```cpp
// Spread (O(1))
auto spread = book.spread();
std::cout << "Spread: " << spread.to_string() << '\n';
// Mid-price (O(1))
auto mid = book.mid_price();
std::cout << "Mid: " << mid.to_string() << '\n';
// Weighted mid-price (O(1))
auto wmid = book.weighted_mid_price();
std::cout << "Weighted Mid: " << wmid.to_string() << '\n';
```
### Market Depth
```cpp
// Total quantity at price levels
auto bid_depth = book.bid_depth(10); // Sum of top 10 bid levels
auto ask_depth = book.ask_depth(10);
// Cumulative depth up to price
auto depth_to_price = book.cumulative_depth_to_price(
Side::Bid,
Price::from_string("49000.00")
);
// Depth required to move price by X%
auto depth_to_move = book.depth_to_move_price(
Side::Ask,
0.01 // 1%
);
```
### Order Book Imbalance
```cpp
// Imbalance ratio: (bid_qty - ask_qty) / (bid_qty + ask_qty)
auto imbalance = book.imbalance(5); // Top 5 levels
// Returns: [-1.0, 1.0], positive = more bids
// Volume-weighted imbalance
auto vwap_imbalance = book.vwap_imbalance(5);
```
## Order Book Views
### Aggregated View
```cpp
// Aggregate by price bucket
auto aggregated = book.aggregate(Price::from_string("10.00")); // $10 buckets
for (const auto& [price_bucket, total_qty] : aggregated.bids()) {
std::cout << price_bucket.to_string() << " : "
<< total_qty.to_string() << '\n';
}
```
### Filtered View
```cpp
// Filter by minimum quantity
auto large_orders = book.filter([](const PriceLevel& level) {
return level.quantity >= Quantity::from_string("10.0");
});
// Filter by price range
auto range_view = book.price_range(
Price::from_string("49000.00"),
Price::from_string("51000.00")
);
```
## Cache-Friendly Design
### Memory Layout
```cpp
// Cache-line aligned price levels
struct alignas(64) PriceLevel {
int64_t price; // 8 bytes
int64_t quantity; // 8 bytes
uint32_t orders; // 4 bytes
uint32_t flags; // 4 bytes
int64_t timestamp; // 8 bytes
char padding[32]; // Pad to 64 bytes
};
// Contiguous storage for cache efficiency
class OrderBook {
// Hot data (accessed every tick)
alignas(64) std::array<PriceLevel, 16> hot_bids_;
alignas(64) std::array<PriceLevel, 16> hot_asks_;
// Warm data (accessed occasionally)
alignas(64) std::vector<PriceLevel> bids_;
alignas(64) std::vector<PriceLevel> asks_;
};
```
### Prefetching
```cpp
// Manual prefetch for known access patterns
void OrderBook::prefetch_top_levels() const noexcept {
// Prefetch best bid/ask into L1 cache
__builtin_prefetch(&hot_bids_[0], 0, 3); // Read, high locality
__builtin_prefetch(&hot_asks_[0], 0, 3);
// Prefetch next levels into L2 cache
__builtin_prefetch(&hot_bids_[1], 0, 2);
__builtin_prefetch(&hot_asks_[1], 0, 2);
}
// Use before accessing book
book.prefetch_top_levels();
auto [bid, ask] = book.best_bid_ask();
```
## Benchmarks
### Microbenchmarks
```cpp
#include <benchmark/benchmark.h>
#include <lxdex/orderbook.hpp>
static void BM_BestBidAsk(benchmark::State& state) {
lxdex::OrderBook book("BTC-USD");
// Setup book with 1000 levels...
for (auto _ : state) {
auto [bid, ask] = book.best_bid_ask();
benchmark::DoNotOptimize(bid);
benchmark::DoNotOptimize(ask);
}
}
BENCHMARK(BM_BestBidAsk);
static void BM_ApplyDelta(benchmark::State& state) {
lxdex::OrderBook book("BTC-USD");
lxdex::OrderBookDelta delta{/* ... */};
for (auto _ : state) {
book.apply_delta(delta);
}
}
BENCHMARK(BM_ApplyDelta);
BENCHMARK_MAIN();
```
### Performance Numbers
| Operation | Latency (p50) | Latency (p99) | Notes |
|-----------|---------------|---------------|-------|
| `best_bid_ask()` | 12ns | 45ns | Lock-free |
| `spread()` | 15ns | 50ns | Lock-free |
| `mid_price()` | 18ns | 55ns | Lock-free |
| `top_bids(10)` | 89ns | 210ns | Copy 10 levels |
| `apply_delta()` | 45ns | 120ns | Single update |
| `find_price_simd()` | 8ns | 25ns | AVX-512, 1000 levels |
## Thread Safety Summary
| Operation | Read Thread | Write Thread |
|-----------|-------------|--------------|
| `best_bid()` | Wait-free | - |
| `best_ask()` | Wait-free | - |
| `spread()` | Wait-free | - |
| `bids()` | Wait-free | - |
| `asks()` | Wait-free | - |
| `snapshot()` | Wait-free | - |
| `set_level()` | - | Single writer |
| `delete_level()` | - | Single writer |
| `apply_delta()` | - | Single writer |
## Example: Market Making
```cpp
#include <lxdex/client.hpp>
#include <lxdex/orderbook.hpp>
class MarketMaker {
Client& client_;
OrderBook book_;
Price spread_target_{100000}; // 0.001 in fixed-point
Quantity quote_size_{1'00000000}; // 1.0
public:
MarketMaker(Client& client, std::string_view symbol)
: client_(client), book_(symbol) {}
void on_book_update(const OrderBook& book) {
book_ = book; // Lock-free copy
requote();
}
void requote() {
auto mid = book_.mid_price();
if (!mid) return;
Price bid_price = *mid - spread_target_ / 2;
Price ask_price = *mid + spread_target_ / 2;
// Cancel existing orders
client_.cancel_all_orders();
// Place new quotes
client_.place_order(OrderBuilder()
.symbol(book_.symbol())
.side(Side::Buy)
.type(OrderType::Limit)
.price(bid_price)
.quantity(quote_size_)
.build());
client_.place_order(OrderBuilder()
.symbol(book_.symbol())
.side(Side::Sell)
.type(OrderType::Limit)
.price(ask_price)
.quantity(quote_size_)
.build());
}
};
int main() {
Client client({.endpoints = {"wss://api.lux.network/ws"}});
client.connect();
MarketMaker mm(client, "BTC-USD");
client.subscribe_orderbook("BTC-USD", [&mm](const OrderBook& book) {
mm.on_book_update(book);
});
// Run forever
std::this_thread::sleep_for(std::chrono::hours{24 * 365});
}
```
-647
View File
@@ -1,647 +0,0 @@
---
title: Orders
description: Order types, placement, cancellation, and management with C++17/20 examples
---
# Orders
The order subsystem provides type-safe order construction, validation, and lifecycle management with zero-copy serialization for HFT applications.
## Order Types
### Supported Order Types
| Type | Enum | Description |
|------|------|-------------|
| Limit | `OrderType::Limit` | Execute at specified price or better |
| Market | `OrderType::Market` | Execute immediately at best available price |
| Stop | `OrderType::Stop` | Trigger market order when price reaches stop |
| Stop Limit | `OrderType::StopLimit` | Trigger limit order when price reaches stop |
| Iceberg | `OrderType::Iceberg` | Hidden quantity with visible portion |
| Peg | `OrderType::Peg` | Track best bid/ask with offset |
### Order Structure
```cpp
#include <lxdex/order.hpp>
namespace lxdex {
struct Order {
OrderId id; // Server-assigned
std::string symbol; // "BTC-USD"
Side side; // Buy/Sell
OrderType type; // Limit/Market/Stop/...
Price price; // Fixed-point price
Quantity quantity; // Fixed-point quantity
Quantity filled_quantity; // Amount filled
TimeInForce time_in_force; // GTC/IOC/FOK/DAY
OrderStatus status; // Pending/Active/Filled/...
Timestamp created_at;
Timestamp updated_at;
// Optional fields
std::optional<Price> stop_price;
std::optional<Quantity> visible_quantity; // Iceberg
std::optional<Price> peg_offset; // Peg orders
std::optional<std::string> client_order_id;
};
enum class Side : uint8_t { Buy = 0, Sell = 1 };
enum class OrderType : uint8_t {
Limit = 0,
Market = 1,
Stop = 2,
StopLimit = 3,
Iceberg = 4,
Peg = 5
};
enum class TimeInForce : uint8_t {
GTC = 0, // Good Till Cancelled
IOC = 1, // Immediate Or Cancel
FOK = 2, // Fill Or Kill
DAY = 3 // Day Order
};
enum class OrderStatus : uint8_t {
Pending = 0,
Active = 1,
PartiallyFilled = 2,
Filled = 3,
Cancelled = 4,
Rejected = 5,
Expired = 6
};
} // namespace lxdex
```
## Fixed-Point Arithmetic
Prices and quantities use fixed-point representation to avoid floating-point errors.
```cpp
#include <lxdex/types.hpp>
// Price: 8 decimal places (satoshi precision)
// Quantity: 8 decimal places
// Construction from integer (raw value)
Price price{50000'00000000}; // $50,000.00
// Construction from double (lossy, use with care)
Price price = Price::from_double(50000.00);
// Construction from string (exact)
Price price = Price::from_string("50000.00");
// Arithmetic
Price spread = ask - bid;
Quantity total = quantity * Price{2};
// Comparison
if (bid >= Price{49000'00000000}) {
// ...
}
// Output
std::cout << price.to_string() << '\n'; // "50000.00000000"
std::cout << price.to_double() << '\n'; // 50000.0
```
## Order Builder Pattern
### Basic Order Builder
```cpp
#include <lxdex/order.hpp>
using namespace lxdex;
// Limit buy order
auto order = OrderBuilder()
.symbol("BTC-USD")
.side(Side::Buy)
.type(OrderType::Limit)
.price(Price::from_string("50000.00"))
.quantity(Quantity::from_string("1.5"))
.time_in_force(TimeInForce::GTC)
.build();
// Market sell order
auto market_order = OrderBuilder()
.symbol("ETH-USD")
.side(Side::Sell)
.type(OrderType::Market)
.quantity(Quantity::from_string("10.0"))
.build();
```
### Advanced Order Builder
```cpp
// Stop-limit order
auto stop_limit = OrderBuilder()
.symbol("BTC-USD")
.side(Side::Sell)
.type(OrderType::StopLimit)
.price(Price::from_string("48000.00")) // Limit price
.stop_price(Price::from_string("49000.00")) // Trigger price
.quantity(Quantity::from_string("0.5"))
.time_in_force(TimeInForce::GTC)
.build();
// Iceberg order (hidden quantity)
auto iceberg = OrderBuilder()
.symbol("BTC-USD")
.side(Side::Buy)
.type(OrderType::Iceberg)
.price(Price::from_string("50000.00"))
.quantity(Quantity::from_string("100.0")) // Total quantity
.visible_quantity(Quantity::from_string("1.0")) // Shown in book
.time_in_force(TimeInForce::GTC)
.build();
// Peg order (tracks best bid/ask)
auto peg = OrderBuilder()
.symbol("BTC-USD")
.side(Side::Buy)
.type(OrderType::Peg)
.peg_offset(Price::from_string("-0.01")) // 1 cent below best ask
.quantity(Quantity::from_string("5.0"))
.build();
```
### Compile-Time Validation
```cpp
// Using C++20 concepts for compile-time validation
template<typename T>
concept ValidOrder = requires(T t) {
{ t.symbol } -> std::convertible_to<std::string_view>;
{ t.side } -> std::same_as<Side&>;
{ t.quantity } -> std::same_as<Quantity&>;
requires t.quantity.raw() > 0;
};
// Builder with validation
auto order = OrderBuilder()
.symbol("BTC-USD")
.side(Side::Buy)
.type(OrderType::Limit)
.price(Price::from_string("50000.00"))
.quantity(Quantity::from_string("1.0"))
.validate() // Throws if invalid
.build();
```
## Placing Orders
### Synchronous Placement
```cpp
#include <lxdex/client.hpp>
#include <lxdex/order.hpp>
Client client({.endpoints = {"wss://api.lux.network/ws"}});
client.connect();
// Place order (blocking)
auto result = client.place_order(
OrderBuilder()
.symbol("BTC-USD")
.side(Side::Buy)
.type(OrderType::Limit)
.price(Price::from_string("50000.00"))
.quantity(Quantity::from_string("1.0"))
.build()
);
if (result) {
std::cout << "Order placed: " << result->id << '\n';
std::cout << "Status: " << to_string(result->status) << '\n';
} else {
std::cerr << "Error: " << result.error().message << '\n';
}
```
### Asynchronous Placement
```cpp
// Future-based async
auto future = client.place_order_async(order);
// Do other work...
// Check result
if (future.wait_for(std::chrono::microseconds{100}) == std::future_status::ready) {
auto result = future.get();
// Process...
}
```
### Callback-Based (Lowest Latency)
```cpp
// Zero-allocation callback
client.place_order_callback(order, [](std::expected<Order, Error> result) {
// Called on I/O thread - keep fast!
if (result) {
// Order confirmed
}
});
```
### Batch Order Placement
```cpp
std::vector<Order> orders;
orders.reserve(100);
for (int i = 0; i < 100; ++i) {
orders.push_back(
OrderBuilder()
.symbol("BTC-USD")
.side(Side::Buy)
.type(OrderType::Limit)
.price(Price{50000'00000000 - i * 100000000}) // Price ladder
.quantity(Quantity{1'00000000})
.build()
);
}
// Place all orders in single request
auto results = client.place_orders_batch(orders);
for (std::size_t i = 0; i < results.size(); ++i) {
if (results[i]) {
std::cout << "Order " << i << " placed: " << results[i]->id << '\n';
} else {
std::cerr << "Order " << i << " failed: " << results[i].error().message << '\n';
}
}
```
## Cancelling Orders
### Cancel Single Order
```cpp
// By order ID
auto result = client.cancel_order(order_id);
if (result) {
std::cout << "Order cancelled\n";
}
// Cancel with expected state (optimistic)
auto result = client.cancel_order(order_id, OrderStatus::Active);
```
### Cancel Multiple Orders
```cpp
// Cancel specific orders
std::vector<OrderId> order_ids = {id1, id2, id3};
auto results = client.cancel_orders(order_ids);
// Cancel all orders for symbol
auto results = client.cancel_all_orders("BTC-USD");
// Cancel all orders
auto results = client.cancel_all_orders();
```
### Cancel-Replace (Atomic Modify)
```cpp
// Atomically cancel and place new order
auto result = client.cancel_replace(
existing_order_id,
OrderBuilder()
.symbol("BTC-USD")
.side(Side::Buy)
.type(OrderType::Limit)
.price(Price::from_string("49999.00")) // New price
.quantity(Quantity::from_string("1.0"))
.build()
);
if (result) {
std::cout << "Order modified: " << result->id << '\n';
}
```
## Order Queries
### Get Single Order
```cpp
auto result = client.get_order(order_id);
if (result) {
const auto& order = *result;
std::cout << "Symbol: " << order.symbol << '\n';
std::cout << "Status: " << to_string(order.status) << '\n';
std::cout << "Filled: " << order.filled_quantity.to_string()
<< " / " << order.quantity.to_string() << '\n';
}
```
### Get Open Orders
```cpp
// All open orders
auto orders = client.get_open_orders();
// Open orders for symbol
auto orders = client.get_open_orders("BTC-USD");
// With pagination
auto orders = client.get_open_orders({
.symbol = "BTC-USD",
.limit = 100,
.offset = 0
});
```
### Get Order History
```cpp
auto orders = client.get_order_history({
.symbol = "BTC-USD",
.start_time = std::chrono::system_clock::now() - std::chrono::hours{24},
.end_time = std::chrono::system_clock::now(),
.status = {OrderStatus::Filled, OrderStatus::Cancelled},
.limit = 1000
});
```
## Order Updates (Real-Time)
### Subscribe to Order Updates
```cpp
client.subscribe_orders([](const OrderUpdate& update) {
std::cout << "Order " << update.order_id
<< " " << to_string(update.event_type) << '\n';
switch (update.event_type) {
case OrderEventType::Created:
// New order acknowledged
break;
case OrderEventType::PartialFill:
std::cout << " Filled: " << update.fill_quantity.to_string()
<< " @ " << update.fill_price.to_string() << '\n';
break;
case OrderEventType::Filled:
// Order completely filled
break;
case OrderEventType::Cancelled:
// Order cancelled
break;
case OrderEventType::Rejected:
std::cerr << " Reason: " << update.reject_reason << '\n';
break;
}
});
```
### Order Update Structure
```cpp
struct OrderUpdate {
OrderId order_id;
std::string symbol;
OrderEventType event_type;
OrderStatus status;
Quantity filled_quantity; // This fill
Price fill_price; // This fill price
Quantity cumulative_quantity; // Total filled
Timestamp timestamp;
std::optional<std::string> reject_reason;
std::optional<TradeId> trade_id;
};
enum class OrderEventType : uint8_t {
Created,
PartialFill,
Filled,
Cancelled,
Rejected,
Expired,
Modified
};
```
## C++20 Coroutines
```cpp
#include <lxdex/client.hpp>
#include <lxdex/coro.hpp>
lxdex::Task<void> trading_loop(lxdex::Client& client) {
// Place order
auto order = co_await client.place_order_coro(
OrderBuilder()
.symbol("BTC-USD")
.side(Side::Buy)
.type(OrderType::Limit)
.price(Price::from_string("50000.00"))
.quantity(Quantity::from_string("1.0"))
.build()
);
if (!order) {
std::cerr << "Order failed: " << order.error().message << '\n';
co_return;
}
std::cout << "Order placed: " << order->id << '\n';
// Wait for fill
while (order->status != OrderStatus::Filled) {
co_await lxdex::sleep(std::chrono::milliseconds{10});
order = co_await client.get_order_coro(order->id);
}
std::cout << "Order filled!\n";
}
int main() {
lxdex::Client client({.endpoints = {"wss://api.lux.network/ws"}});
client.connect();
// Run coroutine
lxdex::sync_wait(trading_loop(client));
}
```
## C++17 Compatibility
```cpp
#include <lxdex/order.hpp>
// C++17: Use optional and variant instead of expected
#include <optional>
#include <variant>
// Place order returns variant<Order, Error>
auto result = client.place_order(order);
if (auto* placed = std::get_if<Order>(&result)) {
std::cout << "Order placed: " << placed->id << '\n';
} else if (auto* error = std::get_if<Error>(&result)) {
std::cerr << "Error: " << error->message << '\n';
}
// Or use visitor
std::visit(overloaded{
[](const Order& order) {
std::cout << "Order: " << order.id << '\n';
},
[](const Error& error) {
std::cerr << "Error: " << error.message << '\n';
}
}, result);
```
## Order Validation
### Client-Side Validation
```cpp
#include <lxdex/validation.hpp>
auto order = OrderBuilder()
.symbol("BTC-USD")
.side(Side::Buy)
.type(OrderType::Limit)
.price(Price::from_string("50000.00"))
.quantity(Quantity::from_string("1.0"))
.build();
// Validate before sending
auto validation = validate_order(order);
if (!validation.is_valid()) {
for (const auto& error : validation.errors()) {
std::cerr << error << '\n';
}
return;
}
client.place_order(order);
```
### Validation Rules
| Rule | Description |
|------|-------------|
| `SymbolExists` | Symbol must be valid trading pair |
| `PriceRange` | Price within min/max for symbol |
| `QuantityRange` | Quantity within min/max for symbol |
| `TickSize` | Price must be multiple of tick size |
| `LotSize` | Quantity must be multiple of lot size |
| `NotionalValue` | Order value >= minimum notional |
## Performance Tips
### Pre-Allocated Order Pool
```cpp
#include <lxdex/memory/pool.hpp>
// Pre-allocate order pool
lxdex::ObjectPool<Order> order_pool(10000);
// Get order from pool (no heap allocation)
auto* order = order_pool.acquire();
*order = OrderBuilder()
.symbol("BTC-USD")
.side(Side::Buy)
.type(OrderType::Limit)
.price(Price{50000'00000000})
.quantity(Quantity{1'00000000})
.build();
client.place_order(*order);
// Return to pool
order_pool.release(order);
```
### Zero-Copy Order Submission
```cpp
// Direct wire format construction
alignas(64) std::array<char, 256> buffer;
auto size = serialize_order_wire(buffer.data(), buffer.size(),
"BTC-USD",
Side::Buy,
OrderType::Limit,
50000'00000000, // Price
1'00000000 // Quantity
);
client.send_raw(std::span{buffer.data(), size});
```
### Latency Measurement
```cpp
auto start = std::chrono::steady_clock::now();
auto result = client.place_order(order);
auto end = std::chrono::steady_clock::now();
auto latency = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start);
std::cout << "Order latency: " << latency.count() << "ns\n";
```
## Error Handling
### Order Rejection Reasons
| Code | Reason | Description |
|------|--------|-------------|
| `INSUFFICIENT_BALANCE` | Not enough funds | Deposit more or reduce size |
| `PRICE_OUT_OF_RANGE` | Price too far from market | Adjust price closer to market |
| `QUANTITY_TOO_SMALL` | Below minimum size | Increase quantity |
| `RATE_LIMIT_EXCEEDED` | Too many requests | Implement backoff |
| `MARKET_CLOSED` | Trading halted | Wait for market open |
| `SELF_TRADE` | Would match own order | Adjust price or cancel existing |
### Retry Logic
```cpp
template<typename F>
auto retry_with_backoff(F&& func, int max_retries = 3) {
using ResultType = std::invoke_result_t<F>;
for (int attempt = 0; attempt < max_retries; ++attempt) {
auto result = func();
if (result) {
return result;
}
if (result.error().code == ErrorCode::RateLimited) {
auto delay = std::chrono::milliseconds{100 * (1 << attempt)};
std::this_thread::sleep_for(delay);
continue;
}
// Non-retryable error
return result;
}
return ResultType{std::unexpected{Error{ErrorCode::Timeout, "Max retries exceeded"}}};
}
// Usage
auto result = retry_with_backoff([&] {
return client.place_order(order);
});
```
+3 -3
View File
@@ -7,9 +7,9 @@ package lx
// GPU-accelerated batch xy=k AMM evaluation via Metal.
//
// The Metal kernel and Objective-C++ driver live in luxcpp/dex/gpu/metal:
// kernel: amm_xyk.metal -> built by cmake into amm_xyk.metallib
// driver: amm_xyk_driver.{h,mm} -> built into libamm_xyk_metal.a
// The Metal kernel lives in luxcpp/metal (one-home-per-backend policy):
// kernel: ~/work/luxcpp/metal/src/shaders/dex/amm_xyk.metal
// driver: ~/work/luxcpp/dex/gpu/metal/amm_xyk_driver.{h,mm}
//
// One-time build:
// cmake -S ~/work/luxcpp/dex -B ~/work/luxcpp/dex/build && \
+1 -16
View File
@@ -59,17 +59,11 @@ build-rust: ## Build Rust SDK
@echo "$(BLUE)Building Rust SDK...$(NC)"
cd lx-trading-core && cargo build --release
build-cpp: ## Build C++ SDK
@echo "$(BLUE)Building C++ SDK...$(NC)"
cd lx-trading-cpp && mkdir -p build && cd build && \
cmake .. -DCMAKE_BUILD_TYPE=Release && \
make -j$(NPROC)
#------------------------------------------------------------------------------
# Test targets
#------------------------------------------------------------------------------
test: test-go test-ts test-py test-rust test-cpp ## Run all SDK tests
test: test-go test-ts test-py test-rust ## Run all SDK tests
@echo ""
@echo "$(GREEN)═══════════════════════════════════════════════════════════$(NC)"
@echo "$(GREEN) All SDK tests completed$(NC)"
@@ -103,14 +97,6 @@ test-rust: ## Run Rust SDK tests
@echo "$(BLUE)═══════════════════════════════════════════════════════════$(NC)"
cd lx-trading-core && cargo test --all-features
test-cpp: ## Run C++ SDK tests
@echo ""
@echo "$(BLUE)═══════════════════════════════════════════════════════════$(NC)"
@echo "$(BLUE) Running C++ SDK tests$(NC)"
@echo "$(BLUE)═══════════════════════════════════════════════════════════$(NC)"
cd lx-trading-cpp/build && ./lx_trading_tests 2>/dev/null || \
(cd ../.. && $(MAKE) build-cpp && cd lx-trading-cpp/build && ./lx_trading_tests)
#------------------------------------------------------------------------------
# Lint & Format
#------------------------------------------------------------------------------
@@ -161,7 +147,6 @@ clean: ## Clean all build artifacts
rm -rf lx-trading-ts/dist lx-trading-ts/node_modules
rm -rf lx-trading-py/dist lx-trading-py/build lx-trading-py/*.egg-info
rm -rf lx-trading-core/target
rm -rf lx-trading-cpp/build
@echo "$(GREEN)Clean complete$(NC)"
#------------------------------------------------------------------------------
+1 -1
View File
@@ -15,7 +15,7 @@ LX Trading SDK provides a unified interface for trading across:
| Language | Package | Directory | Throughput |
|----------|---------|-----------|------------|
| Rust | `lx-trading` | `lx-trading-core/` | 5M+ msgs/sec |
| C++ | `lx-trading` | `lx-trading-cpp/` | 10M+ msgs/sec |
| C++ | `lx-trading` | `~/work/luxcpp/dex/sdk/trading-cpp/` | 10M+ msgs/sec |
| Go | `github.com/luxfi/trading` | `lx-trading-go/` | 1M+ msgs/sec |
| TypeScript | `@luxfi/trading` | `lx-trading-ts/` | 100K+ msgs/sec |
| Python | `lx-trading` | `lx-trading-py/` | 50K+ msgs/sec |