All notable changes to this project are documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
0.3.0 - 2026-10-04
Changed
protox2.0.9 → 2.1.0, withlib/longbridge/_protos.exregenerated — protox 2.1.0 raises its generator version to 2, so the pre-generated modules were rebuilt against it. Same 98 modules; the file shrinks from 27,584 to 23,965 lines. Decoding changes callers can observe: a known field number carrying an unexpected wire type is now kept as an unknown field instead of being parsed with the field's expected parser (matching the reference Go and Rust implementations), and a map entry whose key or value sub-field uses an unsupported wire type now raises%Protox.DecodingError{}instead ofCaseClauseError.%Protox.EncodingError{}is also returned for more invalid field values, so callers matching the exact exception struct insideProtox.encode/1's{:error, exception}tuple may see a different type. Measured locally against v0.2.1 on this SDK's own message types (scripts/bench_proto.exs, three runs per tree, identical per-workload checksums): encoding is 13–23% faster with 29–37% fewer reductions, and decoding is 37–39% faster with 60–70% fewer reductions and 31–46% less allocation. Method and raw numbers are in the v0.3.0 benchmark report.
Fixed
TradeContext.start_link/2no longer makes a network call ininit/1— it previously fetched the WebSocket one-time password there, so a single transient connect timeout (Mint/Finch:timeoutafter ~5s) failedinit/1and took the caller's supervision tree down with it.Longbridge.WSConnectionfetches its own OTP during its own init and keeps returning{:ok, _}with a scheduled reconnect when that fetch fails — the pathQuoteContextalready used.skip_connection: trueperforms no network call either, and the internalstate.ws_configfield is gone (state.http_configholds the original config).
Security
mint1.9.3 → 1.11.0 andfinch0.23.0 → 0.24.0 — mint 1.11.0 fixes three vulnerabilities in the HTTP client the SDK's REST transport uses (unbounded HTTP/2 header-list allocation, unbounded HTTP/2 frame buffering, and HTTP/1 chunked-framing divergence). finch 0.24.0 is the release that closes the stale-connection window mint 1.11 exposes, so the two move together.
0.2.1
Fixed
- Reconnect after an idle timeout no longer uses a stale OTP — the
one-time password was previously written over
config.token, so reconnects reused the spent OTP and failed auth (status 5), and the follow-up token refresh failed with 401 as well. The OTP now lives in a separatesocket_tokenfield and is re-derived on every connect. order_typeatoms map to the Longbridge enum names (:lo→"LO",:elo→"ELO",:market→"MO", ...) instead of being camelized, so typed order submission sends the correct wire values.- HTTP POST/PUT requests send
Content-Type: application/json— the server ignored JSON bodies without the header, breaking order placement and other write endpoints. order_changedpush events are decoded from the real server format (topicprivate,event/datawrapper) —on_order_changedcallbacks now receive the order payload itself.- Stopping a
TradeContextorQuoteContextalso stops its WebSocket connection — previously the connection kept reconnecting in the background after the context process exited.
0.2.0
Added
Longbridge.QuoteContext.candlesticks_paginated/3— fetch up to N K-line bars across multiplecandlesticks/3calls. Deduplicates by timestamp to avoid infinite loops when the API returns the same recent bars on every call (e.g. paper-trading accounts where the historical window is unavailable), and returns candles sorted oldest-first. Rate-limited by the SDK's connection-level throttle.
Fixed
mix credo --strictFunctionArityfinding —Longbridge.QuoteContext.paginate/9took 9 parameters, exceeding the max-8 limit and causing the strict Credo run to exit with rc=8. The two loop-state arguments (acc,seen) have been collapsed into a singlestatemap, dropping the arity to 8. Public API is unchanged.- README
Longbridge.TradeContext.cancel_order/2example — the install/quickstart snippet destructured the return as:ok; the function's@specreturns{:ok, map()}. The snippet now pattern- matches the actual tuple shape.
0.1.2
Changed
- Pre-generated protobuf modules —
lib/longbridge/_protos.exnow ships the compiled output ofmix protox.generateinstead of usinguse Protox, files: [...]. Downstream consumers no longer needprotocinstalled to compile the SDK.protocis only required for maintainers regenerating the modules after a.protochange (runmix gen_protos). Theprotos/source files are kept in the package so consumers can inspect the schema. - Removed the
protocbuild-time requirement from the README installation instructions (no longer needed thanks to pre-generated modules).
0.1.1
Changed
- Dropped the
jasondependency in favor of the built-inJSONmodule (Elixir 1.20+). All encode/decode call sites inlib/andtest/now useJSON.encode!/1/JSON.decode/1.jasonremains only as a transitive dependency ofreqandex_doc. - Removed the redundant License section from the README; the MIT LICENSE file now ships with the package and is linked via the badge.
0.1.0 — Initial beta release
Initial public beta. The SDK implements the Longbridge OpenAPI binary protocol over WebSocket for the quote and trade endpoints, plus 8 HTTP-backed context modules for alerts, asset, calendar, content, DCA, fundamental, market, portfolio, screener, sharelist, and quote-HTTP endpoints.
The SDK is feature-complete against the upstream protocol for the pinned
longbridge/openapi-protobufs@gen/go/v0.7.0 protobuf definitions.
Added
Longbridge.QuoteContextrealtime push-data cache —realtime_quote/2,realtime_depth/2,realtime_brokers/2,realtime_trades/3, andreset_realtime_cache/1. Mirrors the in-memory store pattern from the upstream Rust/Go SDKs, backed by an ETS table owned by the context.Longbridge.QuoteContext.RealtimeStore— internal GenServer that owns the:longbridge_quote_realtimeETS table.Longbridge.QuoteHTTPContext.filings/2— regulatory filings for a symbol (e.g. SEC 10-K, 10-Q). MirrorsFilingsfrom upstream.Longbridge.QuoteHTTPContext.symbol_to_counter_ids/2— HTTP-only batch symbol → counter_id lookup. For local-first resolution with embedded directory + cache, useLongbridge.Symbol.resolve_counter_ids/2.Longbridge.OAuth.InMemoryTokenStorage— in-memory implementation of theLongbridge.OAuth.TokenStoragebehaviour for tests and ephemeral CLI sessions. Mirrors the v4.2.0 in-memory storage patterns from upstream.Longbridge.TradeContextHTTP 401 auto-refresh + retry — all HTTP calls (order_detail,today_orders,submit_order, etc.) automatically retry once on a401 Unauthorizedresponse after refreshing the access token viaConfig.refresh_access_token/2.Longbridge.OAuth.load_token/2:refresh_skewoption — refresh tokens proactively when within:refresh_skewseconds of expiry. Default0(only refresh after expiry).Longbridge.OAuth.load_token/2error wrapping — refresh failures are now wrapped as{:error, {:refresh_failed, reason}}(network/parse errors) or{:error, {:refresh_token_revoked, error, data}}(server rejected, user must re-authorize). Previously these were indistinguishable from "no token file" errors.
Changed
Longbridge.QuoteHTTPContext.option_volumepaths renamed —GET /v1/quote/option-volume→/v1/quote/option-volume-statsand/v1/quote/option-volume-daily→/v1/quote/option-volume-stats/daily. Params renamedstart_date/end_date→start/end. Response shapes updated. Mirrors upstream renaming.Longbridge.TradeContext.estimate_max_purchase_quantity/2endpoint corrected —POST /v1/trade/estimate→GET /v1/trade/estimate/buy_limitwith query params (matches upstream).Longbridge.TradeContext.replace_orderandcancel_orderHTTP methods corrected — both were usingPOST /v1/trade/order/{replace,cancel}which don't exist. Now usePUT /v1/trade/orderandDELETE /v1/trade/order?order_id=...matching upstream.
Endpoints
- QuoteContext (28 methods) — static_info, quote, option_quote,
warrant_quote, depth, brokers, participant_broker_ids, trades, intraday,
candlesticks, history_candlesticks_by_offset, history_candlesticks_by_date,
option_chain_date, option_chain_strike_info, warrant_issuer_info,
warrant_list, calc_index, capital_flow_intraday, capital_flow_distribution,
market_trade_period, market_trade_day, subscription, subscribe, unsubscribe,
user_quote_profile, typed push callbacks
(
set_on_quote/depth/brokers/trades) - TradeContext (16 methods) — submit_order, replace_order, cancel_order, history_orders, today_orders, history_executions, today_executions, order_detail, account_balance, cash_flow, fund_positions, stock_positions, margin_ratio, estimate_max_purchase_quantity, subscribe/unsubscribe (push)
- QuoteHTTPContext (15 methods) — short_positions, option_volume, option_volume_daily, security_list, watchlist_groups CRUD + update_pinned, market_temperature, history_market_temperature, short_trades
- Other HTTP contexts — AlertContext, AssetContext, CalendarContext, ContentContext, DCAContext, FundamentalContext, MarketContext, PortfolioContext, ScreenerContext, SharelistContext
Transport
- WebSocket transport via Mint + Finch (binary protocol with custom 11/10/5-byte header layouts, gzip-compressed response bodies)
- HTTP transport via Finch for REST endpoints (HMAC-SHA256 signed)
- Pluggable OAuth token storage (
Longbridge.OAuth.TokenStoragebehaviour) with defaultLongbridge.OAuth.FileTokenStorage
Test coverage
- 642 tests pass, 0 credo, 0 dialyzer, 0 ex_dna, 0 reach.
- Total coverage: 90.8% (above 89% threshold).
Longbridge.TradeContext: 95.9%.Longbridge.QuoteContext.RealtimeStore: 100%.