Rust-backed Python bindings for low-latency cross-exchange crypto trading.
Project description
dcex - DEX & CEX trading library
Important: No default broker tags are set. You may manually specify a broker tag within function arguments if needed.
Forked from krex, a simplified version of the ccxt Python library.
Originally created and maintained by the same contributor, this fork continues active development, building upon the original foundation with enhanced design, unified DEX + CEX support, and fixes for previously unresolved issues.
A high-performance and lightweight Python and Rust library for interacting with cryptocurrency exchanges. dcex offers Python clients backed by a Rust core, plus direct Rust APIs for low-level HTTP, WebSocket, signing, and exchange integrations.
Scope note: dcex focuses on market data, account queries, trading/order APIs, and market/user-data streams. External withdrawal creation endpoints are not currently wrapped, and options support is limited to exchange-specific APIs rather than the unified Product Table Manager.
Installation
Python:
pip install dcex
or use uv to manage the project:
uv add dcex
Rust:
cargo add dcex
or add it manually:
[dependencies]
dcex = "0.1.0"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
Quick Start
Python Synchronous Usage
import dcex
client = dcex.binance()
klines = client.get_klines(product_symbol="BTC-USDT-SWAP", interval="1m")
print(klines)
Python Asynchronous Usage
import os
import asyncio
import dcex.async_support as dcex
from dotenv import load_dotenv
load_dotenv()
BINANCE_API_KEY = os.getenv("BINANCE_API_KEY")
BINANCE_API_SECRET = os.getenv("BINANCE_API_SECRET")
async def main():
client = await dcex.binance(
api_key=BINANCE_API_KEY,
api_secret=BINANCE_API_SECRET
)
try:
result = await client.get_income_history()
print(result)
finally:
await client.close()
if __name__ == "__main__":
asyncio.run(main())
Rust Usage
use std::time::Duration;
use dcex::exchanges::binance::{BinanceClient, BinanceMarket};
use dcex::http::HttpMethod;
#[tokio::main]
async fn main() -> dcex::Result<()> {
let client = BinanceClient::new(None, None, Duration::from_secs(10))?;
let response = client
.request_raw(
HttpMethod::Get,
BinanceMarket::Spot,
"/api/v3/time",
Vec::new(),
false,
)
.await?;
println!("{}", response.text()?);
Ok(())
}
Supported Exchanges
| Exchange | HTTP Sync | HTTP Async | WS Public | WS Private |
|---|---|---|---|---|
| Binance | Yes | Yes | Yes | Yes |
| Bybit | Yes | Yes | Yes | Yes |
| OKX | Yes | Yes | Yes | Yes |
| Bitget | Yes | Yes | Yes | Yes |
| Kraken | Yes | Yes | Yes | Yes |
| MEXC | Yes | Yes | Yes | Yes |
| BitMart | Yes | Yes | Yes | Yes |
| BitMEX | Yes | Yes | Yes | Yes |
| Gate.io | Yes | Yes | Yes | Yes |
| BingX | Yes | Yes | Yes | Yes |
| KuCoin | Yes | Yes | Yes | Yes |
| Hyperliquid | Yes | Yes | No | No |
| Lighter | Yes | Yes | No | No |
| Backpack | Yes | Yes | No | No |
| Aster | Yes | Yes | No | No |
WS private support currently covers authenticated user-data streams. Order placement and cancellation remain on HTTP clients.
Key Features
- Product Table Manager for unifying trading instruments across exchanges
- HTTP clients with consistent sync and async interfaces where available
- Native Rust core for exchange HTTP, WebSocket, signing, serialization, and response validation
- WebSocket public streams for Binance, BingX, Bybit, OKX, Bitget, Kraken, KuCoin, MEXC, BitMart, BitMEX, and Gate.io, with authenticated user-data streams for Binance, BingX, Bybit, OKX, Bitget, Kraken, KuCoin, MEXC, BitMart, BitMEX, and Gate.io
- Direct Rust crate (
dcex) for applications that do not need the Python layer - Opt-in live test suites for public, private, stateful, and generated-report endpoints
What is Product Table Manager (PTM)?
PTM is a utility that standardizes and unifies trading instrument metadata across different exchanges, making cross-exchange strategy development easier.
It is a table that contains the following columns:
| Column | Description |
|---|---|
| exchange | The exchange name |
| product_symbol | The symbol we use to identify the product, it will be the same in different exchanges. For example, BTC-USDT-SWAP is the same product in Binance and Bybit, which named BTCUSDT in Binance and BTC-USDT-SWAP in OKX. |
| exchange_symbol | The symbol that the exchange actually uses |
| product_type | The normalized product type used by dcex, e.g. spot, swap, futures |
| exchange_type | The exchange-specific product type, e.g. spot, linear, inverse, perpetual, delivery |
| base_currency | The base currency, e.g. BTC |
| quote_currency | The quote currency, e.g. USDT |
| price_precision | The price precision, e.g. 0.000001 |
| size_precision | The size precision, e.g. 0.000001 |
| min_size | The minimum size, e.g. 0.000001 |
| min_notional | The minimum notional, e.g. 0.000001 |
| size_per_contract | The size per contract. Sometimes 1 contract is not the same as 1 unit in exchanges like OKX. |
Options are not currently included in the unified PTM output. Some exchange-specific clients expose option-related parameters or market endpoints, but options are not normalized across exchanges.
How to use Product Table Manager?
In most cases, dcex handles product-symbol mapping internally. If you have a specific use case, you can use ptm to get the information you need.
from dcex.utils.common import Common
from dcex.product_table.manager import ProductTableManager
ptm = ProductTableManager.get_instance(Common.BINANCE)
product_symbol = ptm.get_product_symbol(
exchange=Common.BINANCE,
exchange_symbol="BTCUSDT",
product_type="swap",
)
print(product_symbol)
rows = ptm.rows()
ptm.write_csv("binance_product_table.csv")
Contributing
Contributions are welcome through GitHub issues and pull requests. Run the default test suite before opening a pull request.
Testing
The default test suite is offline and does not require exchange API keys or network access:
uv run pytest
Live, private, stateful, and generated-report tests use the pytest markers
configured in pyproject.toml. These tests are opt-in because they can require
network access, exchange credentials, or account state.
Examples
Python examples are under examples/sync and examples/async. Rust examples
are under crates/dcex/examples. See examples/README.md
for the example conventions.
Benchmarking
Local CPU-bound benchmarks isolate Lighter signing and hashing hot paths. The
baseline is the PyPI dcex==0.21.2 native Python implementation, fixed at
1.00x. Rust-backed Python is PyPI dcex==0.22.0, and Rust native is the
crates.io dcex==0.1.0 crate. The benchmark records package source and version
so the comparison stays reproducible after this branch is merged into main.
Recorded sample (uv run python scripts/benchmark_core_local.py --iterations 50 --warmup 5 --python-baseline-version 0.21.2 --pyo3-version 0.22.0 --rust-crate-version 0.1.0, 2026-06-20):
Baseline: PyPI dcex==0.21.2 native Python implementation = 1.00x.
Rust-backed Python: PyPI dcex==0.22.0; Rust native: crates.io dcex==0.1.0.
| Operation | Rust-backed Python | Rust native |
|---|---|---|
| Cryptographic hash | 77.68x | 103.58x |
| Schnorr signature | 532.71x | 695.91x |
| Transaction payload signing | 319.56x | 556.76x |
Public HTTP benchmarks install the same PyPI packages and compile a temporary
Cargo benchmark against crates.io dcex==0.1.0. Treat those results as an
end-to-end latency check, not as the primary evidence for CPU-bound signing
speed, because exchange latency and local network conditions dominate the
measurement.
| Layer | Command | Output |
|---|---|---|
| Local CPU-bound release artifacts | uv run python scripts/benchmark_core_local.py --iterations 50 --warmup 5 --python-baseline-version 0.21.2 --pyo3-version 0.22.0 --rust-crate-version 0.1.0 |
Speedup table |
| Public HTTP release artifacts | uv run python scripts/benchmark_public_http.py --iterations 20 --python-baseline-version 0.21.2 --pyo3-version 0.22.0 --rust-crate-version 0.1.0 |
Markdown table |
| Optional local CPU-bound CSV output | uv run python scripts/benchmark_core_local.py --csv benchmark_core.csv |
Ignored local CSV file |
| Optional public HTTP CSV output | uv run python scripts/benchmark_public_http.py --csv benchmark_public.csv |
Ignored local CSV file |
The Python benchmark scripts install PyPI packages into temporary target
directories with uv pip install --target, then compile the Rust benchmark
harness against the requested crates.io package version. They do not mutate the
current environment. Use --python-baseline-version, --pyo3-version, and
--rust-crate-version when you need to compare against other published
artifacts.
Release Publishing
The release workflow detects Conventional Commit changes on main and plans
Python and Rust releases independently. A bumped Python release builds wheels
and publishes the Python package to PyPI. If no Python version bump is
detected, PyPI is not updated.
The Rust crate has an independent version in crates/dcex/Cargo.toml and is
published from rust-v* tags. For example, rust-v0.1.0 publishes crate
version 0.1.0 to crates.io and creates a separate GitHub Release.
The crates/dcex-python package is an internal PyO3 build crate and is not
published to crates.io; the Python package version is managed only in
pyproject.toml.
License
This project is licensed under the MIT License.
Support
- Issues: Report bugs and request features on GitHub Issues.
- Discussions: Discuss ideas and share your thoughts on GitHub Discussions.
Disclaimer
Cryptocurrency trading involves significant risk. This library is provided as-is without any warranty. Users are responsible for their own trading decisions and risk management.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dcex-0.23.0.tar.gz.
File metadata
- Download URL: dcex-0.23.0.tar.gz
- Upload date:
- Size: 461.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7501011332625828d1a8fdc274e8f214c6a9dcc130c08844d838a93c282d821b
|
|
| MD5 |
db4b9c1bf3d3d1821055abb4d19ec31a
|
|
| BLAKE2b-256 |
46a3787ff3065f31650659c85949f282fc41e2823af7f081a8d046b8dd54459f
|
File details
Details for the file dcex-0.23.0-cp312-cp312-win_amd64.whl.
File metadata
- Download URL: dcex-0.23.0-cp312-cp312-win_amd64.whl
- Upload date:
- Size: 10.1 MB
- Tags: CPython 3.12, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
80c6f981d5dcaadbace65c1279ffd9a7ee02730089ef37e6ba91356174f74d90
|
|
| MD5 |
b71233deeba878958f10f502ae1b8a49
|
|
| BLAKE2b-256 |
e765fb254a72a9c63a7a20500bdb907e41cdf328144c1fd4a17f476756022e38
|
File details
Details for the file dcex-0.23.0-cp312-cp312-manylinux_2_34_x86_64.whl.
File metadata
- Download URL: dcex-0.23.0-cp312-cp312-manylinux_2_34_x86_64.whl
- Upload date:
- Size: 9.8 MB
- Tags: CPython 3.12, manylinux: glibc 2.34+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
27854f471e5f1fe85689b35282cb4fedf4de1aa7a2879da560514d3891f368aa
|
|
| MD5 |
5c99cbb7643c0b788f1f61396a1fdd82
|
|
| BLAKE2b-256 |
1c288dfa7238ea28e7bcfc0403b7fd9475eac0355e0146d762ce6a77923defc8
|
File details
Details for the file dcex-0.23.0-cp312-cp312-macosx_11_0_arm64.whl.
File metadata
- Download URL: dcex-0.23.0-cp312-cp312-macosx_11_0_arm64.whl
- Upload date:
- Size: 9.2 MB
- Tags: CPython 3.12, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1db928c883eacf90a2b01be1d135c0c12c0e4a79694387f8d8fa81174cf759b9
|
|
| MD5 |
cbc4679638eccc5bf736906723201469
|
|
| BLAKE2b-256 |
050a4fad7b9b2c878e182529bd87370f2fcb54a41050ccb059bf6ff76b48596c
|