A comprehensive, high-performance Julia SDK for Binance Spot Trading APIs.
Binance.jl provides complete access to Binance's trading infrastructure:
- REST API for account management and trading operations
- WebSocket streams for real-time market data (JSON and high-performance SBE binary)
- WebSocket API for interactive real-time trading
- OrderBookManager for local order book with sub-millisecond access
- Recent Updates
- Features
- Installation
- Quick Start
- Documentation
- Examples
- Architecture
- Contributing
- License
Documentation-only release covering the Binance API notices dated 2026-10-27 and 2026-10-30. Includes BinanceFIX 0.6.1.
- REST/WebSocket API SBE schema
3:3will retire on 2026-11-09; the current production schema is3:5. This SDK's REST/WebSocket API clients use JSON, and its dedicated SBE market streams use the separate1:0schema. See schema versions and migration guidance. - Binance documented the existing FIX
ExpiryReason (25056)field.BinanceFIXalready parses it in text FIX and FIX SBE; see the field values and representations.
- Push signals and fills to your phone — the new
Notifiermodule forwards key events to an ntfy topic.NtfyLoggerwraps the global logger so any log at/above a configurable level, or any record taggedntfy=true, is pushed while console/file output stays unchanged. Configure it under[ntfy];install_ntfy_logger!/send_to_ntfyare exported. - Never blocks trading — sends are async and failure-tolerant (errors log once to stderr), and a local ntfy server is reached directly, bypassing the configured proxy.
- The feed no longer dies quietly — the SBE reconnect loop used to give up
permanently after
max_reconnect_attemptsfailures, leaving a strategy running on frozen data. Once a stream has delivered data at least once, drops are now retried forever at capped backoff;max_reconnect_attemptsonly bounds the initial connect so startup still fails fast on misconfiguration. sbe_force_reconnect!closes the live socket to force a re-dial, so an external freeze watchdog can break out of a half-open TUN/proxy connection thatread_idle_timeoutnever sees drop.
- SBE connects like it means it —
connect_sbe!now waits through the configured retries instead of bailing on the first handshake timeout; concurrent callers share one connection task, andsbe_close_allinterrupts retry backoff and rejects handshakes that land after closing. The default port moves to TLS 443 (9443 opt-in viaport=9443) for networks that disrupt it. - REST reads survive flaky links — GET requests retry transient TLS timeouts and truncated HTTP/2 responses up to three times, re-signing and re-reserving rate-limit capacity per attempt. Writes and permanent errors are sent once.
- Deferred time sync —
RESTClient(config; sync_time=false)plussynchronize_time!lets a process reuse an already-connected WebSocket API client's server time instead of a separate REST round trip. Constructors now also accept aBinanceConfigdirectly. - HTTP.jl 2.6.7 or newer is required for the transport-error classification.
REQUEST_WEIGHTnow counts weight, not requests — the limiter charged one unit per call, so 30convert/getQuoterequests (weight 200 each) registered as 30/6000 while the exchange had already charged the full 6000. Every endpoint's documented weight now lives inRateLimiter.jl, including the ones that vary with parameters (depthlimit, symbol counts,computeCommissionRates).- Order endpoints classified by method, not substring —
occursin("/api/v3/order", endpoint)treatedGET /api/v3/orderas an order placement, so 60 order-status queries exhausted the 50-per-10s order budget (blocking for ten seconds) while their real weight went unrecorded. Cost is now keyed on(method, path). - Weight settled against the response — the 2026-04-02 change makes order placement and cancellation free on success but still charged on failure. The limiter reserves the documented weight and releases it once the outcome is known.
- Usage reconciled from the server — REST responses'
X-MBX-USED-WEIGHT-*andX-MBX-ORDER-COUNT-*headers are now read. Previously a REST-only client never learned its real consumption: the server reported 697 used weight while the client's own tally was in single digits. - One limiter per credential —
REQUEST_WEIGHT/RAW_REQUESTSare per IP andORDERSper account, but each client built its own limiter, so a process running REST and WebSocket together believed it had two full budgets. - Cheaper window maintenance — expiry is a prefix removal (
popfirst!) rather than a fullfilter!rescan on every request, which cost 6.8 ms onceRAW_REQUESTSheld 300k entries. Server usage syncs as one aggregate charge instead of thousands of identically-dated entries. - 56 new rate-limit tests (398 → 454).
ListStatusMsg.symbolremoved — Binance dropped the top-levelSymbol (55)fromListStatus <N>in the QuickFIX order-entry schema and the API docs; the server had already stopped sending it. Useget_list_symbol(msg), which reads the symbol from the firstNoOrders(73) entry — every leg of an OCO/OTO/OTOCO list trades the same symbol. A gateway that still sends the legacy field can read it fromraw_fields[TAG_SYMBOL].- More robust group parsing — tag 55 previously served double duty as both
the top-level symbol and the
NoOrdersentry delimiter, told apart only by parser state. Dropping the top-level read removes the ambiguity, so the current and legacy message shapes now parse identically. - BinanceFIX 0.6.0; the
Binancepackage itself is unchanged.
- Replaced JSON3.jl and StructTypes.jl with JSON.jl 1.x — JSON3 is marked
[deprecated]upstream; JSON.jl 1.0 absorbed its design and moved struct mapping to StructUtils.jl. All 63StructTypesdeclarations are gone, replaced by field tags on the struct definitions themselves. - Faster typed parsing — filling a struct straight from the bytes is
3.7x faster and allocates 6.2x less than decode-then-convert (1000
myTrades: 0.76 ms / 546 KiB vs 2.83 ms / 3363 KiB).exchangeInfofor 100 symbols is 1.5x faster, 2.5x less memory. make_requestnow returns aJSON.Objectinstead of aJSON3.Object. Property access, symbol/string indexing,haskey,getandisa AbstractDictall behave the same, so pass-through call sites are unaffected. Code that testedisa JSON3.Objectshould testisa AbstractDict.- Clearer filter errors — an unrecognised
filterTyperaises anArgumentErrornaming the value instead of aFieldErrorabout an internal NamedTuple. Unknown filters still fail loudly rather than being dropped: silently losing aLOT_SIZEwould let an order violatestepSize. - 285 new deserialization tests (113 → 398), asserting every response type field by field in both the lazy and the materialized path.
- Fixed
depth()deserialization —OrderBookused the genericStructTypes.Struct()mapping, which cannot construct itsCustomStructPriceLevelelements; everydepth(ws_client, symbol)call raised aMethodError. It now provides explicitconstruct/lowermethods. - Error-safe retries — Signed REST requests are no longer replayed by the
HTTP client (a replay reuses the original
timestamp/signature, so it can land outsiderecvWindow, and amend/cancel would be re-sent against live orders). Rate-limit responses (429/418/403) are never retried on the transport level, since retrying them escalates a violation into an IP ban. - Single error path — Non-2xx responses now stay on the normal return path
(
status_exception = false), sohandle_erroris the only place that maps Binance error payloads to exceptions.401maps toUnauthorizedError.Retry-Afteris read throughHTTP.header(case-insensitive, canonicalized) and an unparseable value warns instead of throwing. - Credential safety — REST requests no longer follow redirects: HTTP.jl only
strips standard credential headers across origins, so
X-MBX-APIKEYwould otherwise be replayed to a redirect target. The API key is now aClientdefault header instead of being rebuilt per call. - Dead-connection detection — All WebSocket connections (market streams,
WebSocket API, SBE streams) set
read_idle_timeout, so a silently dropped TCP connection surfaces as a 1006 close and triggers a reconnect instead of blocking the reader forever. - Jittered reconnect backoff — Reconnect loops use exponential backoff with
jitter (
RateLimiter.backoff_delay) instead of a fixed delay, and every re-dial reserves a connection-limiter slot, so an exchange-side outage cannot exhaust the 300-connections-per-5-minutes budget in lockstep. - Proxy defaults — An empty
proxyinconfig.tomlnow means "use the standardHTTP_PROXY/HTTPS_PROXY/ALL_PROXY/NO_PROXYenvironment variables" (HTTP.jl's default) rather than forcing a direct connection. - Idle-connection control — Added
close_idle_connections!(rest_client)to drop pooled connections that intermediaries may have silently dropped, without closing the client. - Lower request latency — WebSocket API response waiting blocks on the
response channel instead of polling it every 50 ms, and REST JSON is parsed
straight from the response byte buffer without an intermediate
Stringcopy.
- Reusable HTTP client —
RESTClientnow owns a long-livedHTTP.Client/HTTP.Transport(HTTP.jl 2.x) instead of creating a fresh transport per request. TCP/TLS connections and ALPN HTTP/2 sessions are pooled and reused across calls, cutting latency for rate-limited trading loops. Proxy policy fromconfig.tomlis configured once on the transport. - Lifecycle management — Added
close(rest_client)/isopen(rest_client)to release idle connections; requests through a closed client raiseArgumentError(HTTP.jl closed-client poisoning).
- Immediate first connection — Fixed a rate-limiter control-flow bug that repeatedly reserved connection slots until the five-minute WebSocket limit was exhausted, making strategy startup appear to hang.
- Regression coverage — Added a test ensuring one connection attempt consumes exactly one limiter slot and returns immediately.
- SBE market-stream schema — Corrected the dedicated market-data decoder
from the WebSocket API schema ID
3to the officialspot_streamschema1:0, restoring Trade, best-bid/ask, and depth stream decoding.
- Exact order validation — Price and quantity filters accept decimal strings and fixed-point values without binary floating-point boundary errors.
- Thread-safe clients — REST caches, WebSocket request state,
subscriptions, callbacks, and
OrderBookManagerstate are synchronized; callbacks execute outside internal locks. - Safer SBE/FIX processing — Added strict framing and bounds validation, allocation-reduced integer codecs, supervised monitor tasks, and timeout handling that does not leave orphan readers.
- Configuration and API fixes — Corrected testnet endpoints, added the
exported
load_confighelper, restored missing root exports, and fixedREQUEST_WEIGHTrate-limit accounting. - BinanceFIX 0.5.0 — Includes the corresponding session, framing, concurrency, and encoder/decoder improvements. Julia 1.11+ is supported.
Complete version history: CHANGELOG.md
| Feature | Description |
|---|---|
| REST API | All Spot Account and Trading endpoints |
| WebSocket Streams | Real-time market data (ticker, kline, depth, trades) |
| SBE Streams | High-performance binary market data (60-70% less bandwidth) |
| WebSocket API | Interactive real-time trading with heartbeat |
| OrderBookManager | Local order book with < 1ms latency access |
| Convert API | Limit orders and quotes for token conversion |
| Authentication | Ed25519, RSA, and HMAC-SHA256 signature support |
| Rate Limiting | Automatic compliance with Binance limits |
| Error Handling | Comprehensive error types and recovery |
- General: Ping, Server Time, Exchange Info
- Market Data: Order Book, Trades (Recent/Historical/Aggregate), Klines, Tickers, Prices
- Spot Trading: Orders (Place/Cancel/Status), OCO Orders, Account Info, Order History, Rate Limits
- Strategy Helpers: Real-time trade strategy helpers with colored order book display
- Real-time Data: Tickers, Klines, Depth, Aggregate Trades
- All Market Symbols: Support for individual and combined streams
- Connection Management: Auto-reconnect with heartbeat, ping/pong handling
- Binary Encoding: 60-70% less bandwidth than JSON
- Complete Decoder: All 4 message types (Trade, BestBidAsk, Depth, DepthSnapshot)
- Low Latency: 30-50% lower latency vs JSON streams
- Convenience Functions: Subscribe/unsubscribe for all stream types
- Auto-Reconnect: Automatic reconnection with detailed error diagnostics
- Local Order Book: Continuously-synchronized with automatic WebSocket + REST sync
- Near-Zero Latency: < 1ms access (vs 20-100ms for REST/WebSocket)
- Deep Market: Up to 5000 price levels
- Built-in Analytics: VWAP calculation and depth imbalance analysis
- Auto-Recovery: Automatic reconnection and resynchronization
- Session Management: Logon, Status, Logout
- Trading Operations: Place/Cancel/Modify orders with full validation
- Order Lists: OCO/OTO/OTOCO support
- Account Queries: Balances, Orders, Execution Reports, Commission Rates
- Smart Order Routing: SOR orders for optimized execution
- User Data Streams: Real-time account updates
- Margin Account and Trading
- Futures API support
- Sub-account Management
- Advanced SAPI Endpoints (Savings, Mining, BLVT, BSwap, Fiat)
- Enhanced WebSocket User Data Event parsing
- Performance optimizations and benchmarks
using Pkg
Pkg.add("https://github.com/rzhli/Binance.jl.git")Create config.toml from the example:
cp config_example.toml config.tomlEdit with your credentials:
[api]
api_key = "YOUR_API_KEY"
secret_key = "YOUR_SECRET_KEY"
# For WebSocket API and SBE streams
signature_method = "ED25519"
private_key_path = "key/ed25519-private.pem"
private_key_pass = "YOUR_PASSWORD"
[connection]
testnet = false
# Leave empty to use the standard HTTP_PROXY / HTTPS_PROXY / ALL_PROXY / NO_PROXY
# environment variables; set explicitly to override them.
proxy = "" # e.g. "http://127.0.0.1:7890" or "socks5://127.0.0.1:7891"
[ntfy]
# Push trigger signals / order fills to an ntfy topic (set enabled = false to disable).
enabled = true
url = "http://127.0.0.1:2586" # local server is reached directly, bypassing proxy
token = "YOUR_NTFY_TOKEN"
topic = "Binance"
min_level = "Warn" # records tagged ntfy=true are forwarded regardless of levelSee config_example.toml for all options.
Load the configuration explicitly when needed:
config = load_config("config.toml")using Binance
# Create clients
rest_client = RESTClient()
stream_client = MarketDataStreamClient()
ws_client = WebSocketClient()
# Get market data
server_time = get_server_time(rest_client)
account = get_account_info(rest_client)
# Place order (use String or DecimalPrice for exact precision)
order = place_order(rest_client, "BTCUSDT", "BUY", "LIMIT";
quantity="0.001", price="60000.0", timeInForce="GTC")📖 More examples: examples/examples.jl
| Module | Description | Documentation |
|---|---|---|
| OrderBookManager | Local order book with < 1ms latency | docs/OrderBookManager.md |
| SBE Streams | High-performance binary market data | docs/SBE.md |
Decimal Precision:
# Use String or DecimalPrice for exact values (avoids floating-point errors)
quantity = "0.001"
price = DecimalPrice("60000.00")REST API:
rest_client = RESTClient()
server_time = get_server_time(rest_client)
account = get_account_info(rest_client)
order = place_order(rest_client, "BTCUSDT", "BUY", "LIMIT";
quantity="0.001", price="60000.0", timeInForce="GTC")
# RESTClient pools HTTP connections internally; release them when done
close_idle_connections!(rest_client) # drop idle pooled connections, stay usable
close(rest_client) # subsequent calls raise ArgumentError
isopen(rest_client) # false after closeREST GET requests make up to three attempts on transient transport failures
(including TLS timeouts and truncated HTTP/2 responses) or retryable server
errors. Each attempt signs a fresh timestamp and counts toward the rate limit.
Trading writes and authentication, validation, or rate-limit errors are not
automatically retried. Use get_account_info(rest_client; max_attempts=1) or
Binance.RESTAPI.make_request(...; max_attempts=1) to disable read retries for a call.
To synchronize through an already-connected WebSocket API client, defer REST time synchronization at construction:
rest_client = RESTClient("config.toml"; sync_time=false)
synchronize_time!(rest_client;
server_time_provider=() -> Binance.WebSocketAPI.time(ws_client).serverTime)
# synchronize_time!(rest_client) uses the REST time endpoint instead.WebSocket Market Streams:
stream_client = MarketDataStreamClient()
subscribe_ticker(stream_client, "BTCUSDT", data -> println(data))
subscribe_kline(stream_client, "BTCUSDT", "1h", data -> println(data))WebSocket API (Interactive Trading):
ws_client = WebSocketClient()
connect!(ws_client)
session_logon(ws_client)
place_order(ws_client, "BTCUSDT", "BUY", "LIMIT";
quantity="0.001", price="60000.0")SBE Streams (High Performance):
sbe_client = SBEStreamClient()
connect_sbe!(sbe_client)
sbe_subscribe_trade(sbe_client, "BTCUSDT", event -> println(event))
sbe_close_all(sbe_client)| File | Description |
|---|---|
examples/orderbook_basic.jl |
OrderBookManager basic usage |
examples/orderbook_advanced.jl |
Advanced OrderBookManager with analytics |
examples/sbe_stream_example.jl |
SBE binary streams usage |
examples/examples.jl |
General REST API, WebSocket streams examples |
The four files below drive a full trading strategy. They include the strategy/
directory, which is gitignored (personal trading strategies, not shipped with the
package), so a fresh clone will hit SystemError: opening file .../strategy/....
They are here to document the high-level entry points; every order-placing call is
commented out by default.
| File | Description |
|---|---|
test.jl |
All four client types, plus grid strategies driven by ticker and by depth |
single_run_test.jl |
run_single_orderbook_strategy / run_multi_orderbook_strategy, with technical analysis and support/resistance injection |
test_orderbook_strategy.jl |
Assembling an OrderBookManager by hand: own monitoring loop, own cleanup |
test_convert.jl |
Convert (flash-swap) strategies — no 5 USDT minimum notional |
Binance.jl/
├── src/
│ │
│ │ # Core Module
│ ├── Binance.jl # Main module with exports
│ │
│ │ # Configuration & Authentication
│ ├── Config.jl # Configuration management (TOML parsing)
│ ├── Signature.jl # Authentication (Ed25519, RSA, HMAC)
│ │
│ │ # REST API
│ ├── RESTAPI.jl # REST endpoints implementation
│ ├── Account.jl # Account-related utilities
│ ├── RateLimiter.jl # Rate limiting: per-endpoint weights + sliding window
│ │
│ │ # WebSocket Streams (JSON)
│ ├── MarketDataStreams.jl # WebSocket market data streams
│ ├── WebSocketAPI.jl # Interactive WebSocket API
│ ├── OrderBookManager.jl # Local order book management
│ │
│ │ # SBE Streams (Binary)
│ ├── SBEMarketDataStreams.jl # SBE market data streams
│ ├── SBEDecoder.jl # SBE binary message decoder
│ │
│ │ # Data Types & Utilities
│ ├── Types.jl # Data models and structs
│ ├── Events.jl # WebSocket event types
│ ├── Filters.jl # Order validation filters
│ └── Errors.jl # Custom error types
│
├── BinanceFIX/ # FIX Protocol SDK (sub-package)
│ ├── Project.toml
│ ├── src/
│ │ ├── BinanceFIX.jl # Main FIX module
│ │ ├── FIXAPI.jl # FIX session and order entry
│ │ ├── FIXConstants.jl # FIX field tags and constants
│ │ └── FIXSBEDecoder.jl # FIX SBE binary decoder
│ ├── test/ # FIX test suite
│ └── examples/ # FIX usage examples
│
├── docs/
│ ├── OrderBookManager.md # OrderBookManager documentation
│ └── SBE.md # SBE streams documentation
│
├── examples/
│ ├── orderbook_basic.jl # OrderBookManager basic usage
│ ├── orderbook_advanced.jl # OrderBookManager advanced features
│ ├── sbe_stream_example.jl # SBE streams usage example
│ └── examples.jl # General usage examples
│
├── config_example.toml # Configuration template
├── CHANGELOG.md # Version history
└── README.md # This file
- Enable 2FA on your Binance account
- Use IP whitelisting when possible
- Never commit
config.tomlor private keys to version control - Use testnet for development and testing
- Limit API permissions to only what you need
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/your-feature) - Add tests for new functionality
- Update documentation as needed
- Submit a pull request with clear description
This project is released under the MIT License. See LICENSE file for details.
This software is for educational and informational purposes only. Use at your own risk. Always test with small amounts and understand the risks involved in cryptocurrency trading.
- Issues: GitHub Issues
- Documentation: See docs/ directory