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

  • protox 2.0.9 → 2.1.0, with lib/longbridge/_protos.ex regenerated — 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 of CaseClauseError. %Protox.EncodingError{} is also returned for more invalid field values, so callers matching the exact exception struct inside Protox.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/2 no longer makes a network call in init/1 — it previously fetched the WebSocket one-time password there, so a single transient connect timeout (Mint/Finch :timeout after ~5s) failed init/1 and took the caller's supervision tree down with it. Longbridge.WSConnection fetches its own OTP during its own init and keeps returning {:ok, _} with a scheduled reconnect when that fetch fails — the path QuoteContext already used. skip_connection: true performs no network call either, and the internal state.ws_config field is gone (state.http_config holds the original config).

Security

  • mint 1.9.3 → 1.11.0 and finch 0.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 separate socket_token field and is re-derived on every connect.
  • order_type atoms 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_changed push events are decoded from the real server format (topic private, event/data wrapper) — on_order_changed callbacks now receive the order payload itself.
  • Stopping a TradeContext or QuoteContext also 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 multiple candlesticks/3 calls. 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 --strict FunctionArity finding — Longbridge.QuoteContext.paginate/9 took 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 single state map, dropping the arity to 8. Public API is unchanged.
  • README Longbridge.TradeContext.cancel_order/2 example — the install/quickstart snippet destructured the return as :ok; the function's @spec returns {:ok, map()}. The snippet now pattern- matches the actual tuple shape.

0.1.2

Changed

  • Pre-generated protobuf modules — lib/longbridge/_protos.ex now ships the compiled output of mix protox.generate instead of using use Protox, files: [...]. Downstream consumers no longer need protoc installed to compile the SDK. protoc is only required for maintainers regenerating the modules after a .proto change (run mix gen_protos). The protos/ source files are kept in the package so consumers can inspect the schema.
  • Removed the protoc build-time requirement from the README installation instructions (no longer needed thanks to pre-generated modules).

0.1.1

Changed

  • Dropped the jason dependency in favor of the built-in JSON module (Elixir 1.20+). All encode/decode call sites in lib/ and test/ now use JSON.encode!/1 / JSON.decode/1. jason remains only as a transitive dependency of req and ex_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

Changed

  • Longbridge.QuoteHTTPContext.option_volume paths renamed — GET /v1/quote/option-volume → /v1/quote/option-volume-stats and /v1/quote/option-volume-daily → /v1/quote/option-volume-stats/daily. Params renamed start_date/end_date → start/end. Response shapes updated. Mirrors upstream renaming.
  • Longbridge.TradeContext.estimate_max_purchase_quantity/2 endpoint corrected — POST /v1/trade/estimate → GET /v1/trade/estimate/buy_limit with query params (matches upstream).
  • Longbridge.TradeContext.replace_order and cancel_order HTTP methods corrected — both were using POST /v1/trade/order/{replace,cancel} which don't exist. Now use PUT /v1/trade/order and DELETE /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

Test coverage