All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Rust:
market::TradeStatusmodels/v1/quote/market-statustrade status codes, including engine-compatible normalization and display helpers. - C++:
market::TradeStatusmodels/v1/quote/market-statustrade status codes, with status-code conversion, normalization, display helpers, and typedMarketTimeItemstatus fields.
- All languages: corrected market trade status documentation and aligned
market::TradeStatuswith the status definition table, including code2001and the123/1009/1010display names.
- All languages:
macroeconomic_indicatorsgainskeywordparameter for fuzzy name filtering - All languages:
macroeconomicswitches toGET /v2/quote/macrodata/{id}, defaults tosort=desc
MacroeconomicIndicator.name/.describe:MultiLanguageText→stringMacroeconomic.unit/.unit_prefix:MultiLanguageText→string
- All languages:
FundamentalContextgainsmacroeconomic_indicators(country, offset, limit)— list macroeconomic indicators viaGET /v1/quote/macrodata; filter by country (MacroeconomicCountry::HongKong / China / UnitedStates / EuroZone / Japan / Singapore); response includescount(total matching) - All languages:
FundamentalContextgainsmacroeconomic(indicator_code, start_date, end_date, offset, limit)— historical data for a specific indicator viaGET /v1/quote/macrodata/{indicator_code};start_date/end_dateaccept"YYYY-MM-DD"strings; response includescount(total data points) - New types:
MultiLanguageText,MacroeconomicCountry,MacroeconomicImportance,MacroeconomicIndicator,MacroeconomicIndicatorListResponse,Macroeconomic,MacroeconomicResponse
MacroeconomicIndicator.describe/name/MacroeconomicResponse.info: handlenullresponses from API without deserializing error
- All languages:
FundamentalContextgainsetf_asset_allocation(symbol)— queriesGET /v1/quote/etf-asset-allocationfor ETF asset allocation grouped by element type (Holdings/Regional/AssetClass/Industry); returnsAssetAllocationResponsewith report date, position ratios, localized names, and per-holding detail - Rust: new public
longbridge::countermodule —symbol_to_counter_id,index_symbol_to_counter_id,counter_id_to_symbol, andis_etf, backed by the embedded ETF + index + warrant directory, so downstream consumers (CLI / MCP) no longer need their own copies - Rust:
QuoteContextgainssymbol_to_counter_ids(symbols)(batch conversion viaPOST /v1/quote/symbol-to-counter-ids) andresolve_counter_ids(symbols)(local-first resolution with remote fallback) — remotely resolved entries are persisted to~/.longbridge/cache/counter-ids.csv(one counter_id per line, override the directory withLONGBRIDGE_CACHE_DIR) and consulted by subsequentcounterlookups, so symbols missing from the embedded directory (e.g. newly listed ETFs) resolve correctly after the first query
symbol_to_counter_idnow also consults the embedded index and warrant directories — e.g.HSI.HK→IX/HK/HSI,10005.HK→WT/HK/10005; leading zeros are stripped from numeric.HKcodes (00700.HK→ST/HK/700, A-share codes are kept verbatim)
- Refreshed the embedded US ETF list (4574 → 7250 entries, from the instrument-management export) and added index (648) + warrant (17693) directories — newer ETFs (e.g.
DRAM.US) were resolved toST/...instead ofETF/...counter IDs, breaking ETF-specific APIs such asetf_asset_allocation
- All languages:
CalendarEventsResponsenow exposesnext_datecursor — callers can pass it asstart(with the sameend) to fetch the next page of/v1/quote/finance_calendarresults - All languages:
CalendarEventInfo.symbolnow returns standard symbol format (e.g.CRM.US) instead of rawcounter_idformat (e.g.ST/US/CRM)
ScreenerContext: screener endpoints migrated to/v1/quote/ai/screener/*;screener_recommend_strategies/screener_user_strategiesnow accept amarketparameter;screener_searchaccepts typedScreenerConditionobjects (Mode B) instead of raw strings
OperatingFinancial: renamedcounter_id→symbol(convertsST/US/AAPL→AAPL.US)
- 19 new APIs:
FundamentalContext+9,QuoteContext+1 (short_trades),MarketContext+3, newScreenerContext+5 — see PR #526, #527 - Rust:
OAuthBuildergainsTokenStoragetrait for custom token persistence
short_positionsunified for HK+US; typed structs with RFC 3339 timestampstop_movers,rank_list,valuation_comparison: typed structs,counter_id→ symbol, RFC 3339 timestamps
stock_events→top_movers;StockEventsResponse→TopMoversResponsehk_short_positionsremoved; useshort_positions(symbol, count)ShortPositionsResponse,ShortTradesResponse,TopMoversResponse,RankListResponse,ValuationComparisonResponsechanged from raw JSON to typed structs
- All languages (Rust, Python, Node.js, Java, C, C++):
AlertContext::enable()andAlertContext::disable()have been replaced by a singleAlertContext::update(item, enabled)method. Pass theAlertItemfromlist()directly —enabled = trueenables,enabled = falsedisables. This fixesinvalid frequency/invalid indicator idAPI errors caused by the old methods sending incomplete fields.
- All languages (Rust, Python, Node.js, Java, C, C++): Seven new context types covering all major data APIs:
FundamentalContext— financial reports, analyst ratings, dividends, EPS forecasts, consensus estimates, valuation (PE/PB/PS), industry valuation, company overview, executives, shareholders, fund holders, corporate actions, investor relations, operating reports, buyback data, stock ratings.MarketContext— market status, broker holding (top/detail/daily), A/H premium (klines/intraday), trade statistics, market anomalies, index constituents.CalendarContext— finance calendar (earnings, dividends, splits, IPOs, macro data, market closures, meetings, mergers).PortfolioContext— exchange rates, P&L analysis (summary/detail/by-market/flows).AlertContext— price alert management (list/add/delete/enable/disable).DCAContext— dollar-cost-averaging plan management (list/create/update/pause/resume/stop/history/stats/check-support/calc-date/set-reminder).SharelistContext— community sharelist management (list/detail/popular/create/delete/add-securities/remove-securities/sort-securities).
- All languages:
QuoteContextgainsshort_positions,option_volume,option_volume_daily, andupdate_pinned. - All languages:
ContentContextgainstopic_detail,list_topic_replies, andcreate_topic_reply. - Rust:
Config::header(key, value)builder method for injecting custom HTTP/WebSocket headers. - All languages (Rust, Python, Node.js, Java, C, C++): Restore
Config::refresh_access_token(andrefresh_access_token_blockingin Rust). Refreshes the access token via the Longbridge token-refresh API. Only available with Legacy API Key authentication (Config::from_apikey); not supported in OAuth 2.0 mode.
- All languages: Method parameters now use typed enums instead of raw integers:
DCAFrequency,DCAStatus,AlertCondition,AlertFrequency,CalendarCategory,FinancialReportKind,FinancialReportPeriod,BrokerHoldingPeriod,AhPremiumPeriod. - All languages: Response struct fields are typed enums where applicable:
DcaPlan.status/invest_frequency/market,MarketTimeItem.market,FlowItem.direction,ProfitSummaryInfo.asset_type,InstitutionRatingSummary.recommend. - All languages: All SDK responses are fully typed structs — no method returns a raw JSON string.
- All languages: Monetary/numeric fields use
Decimal/Option<Decimal>(Rust) orBigDecimal(Java). Non-parseable values such as""or"--"deserialize asNone/null.
- Rust: Fix incorrect cache expiry checks in
QuoteContext.
- All bindings:
ContentContextadds two new methods (Rust, Go, C, C++, Java, Python, Node.js):my_topics(opts)— get topics created by the current authenticated user, with optional page/size/topic_type filtering.create_topic(opts)— create a new topic; returns the topic ID (String) on success.
- All bindings: New types
OwnedTopic,MyTopicsOptions, andCreateTopicOptionsto support the above methods. - Python: Added type stubs (
openapi.pyi) forContentContext,AsyncContentContext,OwnedTopic,TopicReply,TopicAuthor, andTopicImage.
- C++:
create_topiccallback now correctly yieldsstd::string(topic ID) instead ofOwnedTopic.
- All bindings:
QuoteContext::new/TradeContext::new/ContentContext::neware now synchronous and infallible — no moreawait,.get(), or callback at construction time. The WebSocket connection is established lazily on first use. - All bindings:
member_id,quote_level, andquote_package_detailsare now async methods (were previously sync fields/properties). - Rust: A single global Tokio runtime is shared across all SDK components; per-binding runtimes removed.
- Reduced connection latency by ~1.3 s by fixing a geo-probe cache issue and a WebSocket rate-limiter initialisation bug.
- Quote: trading days are now loaded lazily on first use instead of eagerly at connect time.
- OAuth token refresh now triggers at 5 minutes before expiry instead of only after expiry, preventing a blocking refresh on the first API call.
- CN region detection updated to use a new probe endpoint.
- Rust: Fix copy-paste field mapping bugs in
TryFrom<quote::FilterWarrant> for WarrantInfowherestrike_price,itm_otm,implied_volatility,delta,effective_leverage,conversion_ratio, andbalance_pointwere incorrectly mapped tolast_done. (#485)
- Migrate OAuth base URL from
openapi.longbridgeapp.comtoopenapi.longbridge.com. - Migrate CN endpoint URLs from
longportapp.cntolongbridge.cn. - Change OAuth token storage path from
~/.longbridge-openapi/to~/.longbridge/openapi/. - Update all README docs to use
openapi.longbridge.comfor OAuth registration endpoints. - Update proto submodule with latest upstream changes (URL migration in proto comments).
- All bindings: New
ContentContext(Rust, C, C++, Java, Python, Node.js) with two methods:topics(symbol)— get discussion topics for a security.news(symbol)— get news list for a security.
- Quote API:
QuoteContext.filings(symbol)— get regulatory filings for a security. Available in all bindings (Rust, C, C++, Java, Python, Node.js). - MCP server: Expose
news,topics, andfilingsas MCP tools.
- Python: Fix
str()on enum fields (e.g.CashFlow.direction,Subscription,OptionDirection) causing a hang/deadlock by registering previously missing types in the quote and trade modules. (#476)
-
OAuth 2.0 authentication for all language bindings (Rust, C, C++, Java, Python, Node.js). Use
OAuthBuilderto run the browser flow; pass the resultingOAuthhandle toConfig::from_oauth(). Tokens are persisted under~/.longbridge/openapi/tokens/<client_id>and reused; the browser is only opened when no valid token exists. -
Python — async callbacks:
AsyncQuoteContextandAsyncTradeContextaccept async callbacks forset_on_quote,set_on_depth,set_on_brokers,set_on_trades,set_on_candlestick, andset_on_order_changed. If a callback returns a coroutine, the SDK schedules it on the asyncio loop. Sync callbacks still work as before. -
Python —
loop_parameter:AsyncQuoteContext.create()andAsyncTradeContext.create()take an optionalloop_argument. When using async callbacks, passloop_=asyncio.get_running_loop()so the SDK can schedule coroutines withasyncio.run_coroutine_threadsafe. Omitloop_when using only sync callbacks.
- Rust:
Config::new→Config::from_apikey,Config::from_env→Config::from_apikey_env; removedConfig::refresh_access_tokenandConfig::refresh_access_token_blocking. - C/C++:
lb_config_new→lb_config_from_apikey,lb_config_from_env→lb_config_from_apikey_env, removedlb_config_refresh_access_token;lb_http_client_new→lb_http_client_from_apikey,lb_http_client_from_env→lb_http_client_from_apikey_env. - Java:
Config.fromEnv()→Config.fromApikeyEnv(), removedConfig.refreshAccessToken(). - Python:
Config.from_env()→Config.from_apikey_env(), removedConfig.refresh_access_token();HttpClient.from_env()→HttpClient.from_apikey_env(). - Node.js:
Config.fromEnv()→Config.fromApikeyEnv().
- python: add asyncio support for quote, trade, and HTTP client; existing sync API unchanged.
- rust: fix incorrect field mapping in
WarrantInfofor warrant filter API.
- java-sdk: fix
limit_depth_levelandtrigger_countbeing correctly passed and read asIntegerin submit/replace order options and order detail.
- add
limit_depth_level,trigger_count,monitor_pricetoOrderDetail, 'Order' types. - add support specify
limit_depth_level,trigger_count,monitor_pricewhen placing order.
- add
US_VIXmarket definition. - python: add support Python
3.14.
- fix candlesticks (K-line) might be generated incorrectly in certain situations.
- fix parsing
OrderDetailmay fail in certain situations.
- add
SecurityBoard.SPXIndexandSecurityBoard.VIXIndex.
- add
ErrorKindenum to represent error kinds.
- fix candlesticks (K-line) might be generated incorrectly in certain situations.
- fix #298
- add
trade_sessionfor query all session intraday. - add
Market.Crypto. - fix subscription index K-line.
- python: fix unable to import SecurityBoard
- A connection limit exceeded error occurred while creating an OTP.
- fix: subscribe candlesticks with
Period::Day.
- add
AccountBalance.frozen_transaction_fees - fix(nodejs): correct condition for disabling quote package printing #230
- fix: Add missing types register #226
- java-sdk: rename
QuoteContext.securityListtoQuoteContext.getSecurityList - java-sdk: add
QuoteContext.getMarketTemperatureandQuoteContext.getHistoryMarketTemperaturemethods
- fix #213
- fix #212
- add support extended hours candlesticks
- add market temperature api
- add support use environment variable
LONGBRIDGE_LANGUAGEto set the response language - java-sdk: add
QuoteContext.getCapitalDistributionmethod - fix #208
- add
log_pathfield toConfig
- add support for more candlesticks periods
- add PushQuote.current_volume, PushQuote.current_turnover
- Add
PushCandlestick.is_confirmedfield.
- Update candlesticks rule.
- Add Serialize/Deserialize to response types.
- Add
LONGBRIDGE_PRINT_QUOTE_PACKAGESenvironment variable to enable printing the opened quote packages when connected to the server, default istrue.
- Changed the
timeparameter ofQuote.history_candlesticks_by_offsetmethod to be optional.
- [python] Change
TradeStatus.SuspendTradetoTradeStatus.Suspendin pyi.
- Returns the most recent historical candlesticks after subscribing to the candlesticks.
- Print the opened quote packages when connected to the server.
- Add
EstimateMaxPurchaseQuantityOptions.fractional_sharesfield, sets totrueto get the maximum fractional share buying power. - The quantity type in the trading API has changed from
inttoDecimal.
- make Depth.price to optional type