Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,6 @@ build
*.node
.venv/
python/.venv/
.env
.env.local
__pycache__/
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- **Rust core:** `QuoteTransport` config option (`Config::quote_transport` / `Config::set_quote_transport`, env `LONGBRIDGE_QUOTE_TRANSPORT=ws|http`, default `WebSocket`). With `QuoteTransport::Http`, the 20 `QuoteContext` pull methods backed by the 19 WebSocket commands that have a REST equivalent (`static_info`, `quote`, `option_quote`, `warrant_quote`, `depth`, `brokers`, `participants`, `trades`, `intraday`, `candlesticks`, `history_candlesticks_by_offset`, `history_candlesticks_by_date`, `option_chain_expiry_date_list`, `warrant_issuers`, `warrant_list`, `trading_session`, `trading_days`, `capital_flow`, `capital_distribution`, `calc_indexes`) are served over `POST /quote/*` instead of the quote WebSocket, so a process that only pulls data never opens a WebSocket connection. Public method signatures and return types are unchanged: the gateway proto-JSON is decoded into the same protobuf messages as the WebSocket path (tolerating int64-as-string, omitted/`null` fields and camelCase keys) and the existing conversions are reused. Subscriptions, push events, `realtime_*`, `member_id` / `quote_level` / `quote_package_details` still use the WebSocket.
- **US overnight alignment:** the WebSocket only returns US overnight data when `Config::enable_overnight` is set, while REST always does. On the HTTP path (and only there) the SDK applies the WebSocket's rule for US equities: `quote().overnight_quote` is cleared, overnight `intraday` lines are dropped, and for `TradeSessions::All` candlestick queries overnight bars are dropped and count/range-capped windows are topped up with `POST /quote/history-candlesticks` offset queries (≤1000 bars per request, ≤8 extra requests; a failure in a top-up request fails the call). `trades` and `calc_indexes` are passed through unchanged.
- **Known differences:** HTTP errors are `Error::HttpClient(OpenApi { .. })` rather than `Error::WsClient(ResponseError { .. })` (`Error::openapi_error_code()` / `into_simple_error()` cover both, but a non-JSON gateway error surfaces as `HttpClientError::UnexpectedHttpResponse` with no code); the HTTP client retries `429` with back-off while the WebSocket does not; the REST gateway currently reports business errors (e.g. `301600`, `301607`) as `500`; during the US overnight session itself (20:00–04:00 New York) REST `quote` / `trades` values may reflect overnight trading that the WebSocket (without `enable_overnight`) does not report — not verified in this release.
- **C / C++ / Java / Node.js / Python:** the `QuoteTransport` enum and the corresponding config option are exposed in every binding layer.

## [5.2.0] - 2026-09-30

### Added
Expand Down
1 change: 1 addition & 0 deletions c/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ setx LONGBRIDGE_ACCESS_TOKEN "Access Token get from user center"
| LONGBRIDGE_TRADE_WS_URL | Trade websocket endpoint url (Default: `wss://openapi-trade.longbridge.com/v2`) |
| LONGBRIDGE_ENABLE_OVERNIGHT | Enable overnight quote, `true` or `false` (Default: `false`) |
| LONGBRIDGE_PUSH_CANDLESTICK_MODE | `realtime` or `confirmed` (Default: `realtime`) |
| LONGBRIDGE_QUOTE_TRANSPORT | Transport for quote pull APIs, `ws` or `http` (Default: `ws`) |
| LONGBRIDGE_PRINT_QUOTE_PACKAGES | Print quote packages when connected, `true` or `false` (Default: `true`) |
| LONGBRIDGE_LOG_PATH | Set the path of the log files (Default: `no logs`) |
| LONGBRIDGE_PAPERTRADING | Enable paper trading mode, `true` or `false` (Default: `false`). See [Paper Trading](#paper-trading). |
Expand Down
1 change: 1 addition & 0 deletions c/cbindgen.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ cpp_compat = true
"CHttpResult" = "lb_http_result_t"
"CLanguage" = "lb_language_t"
"CPushCandlestickMode" = "lb_push_candlestick_mode_t"
"CQuoteTransport" = "lb_quote_transport_t"
"CMarket" = "lb_market_t"
"CDecimal" = "lb_decimal_t"
"CAsyncCallback" = "lb_async_callback_t"
Expand Down
44 changes: 37 additions & 7 deletions c/csrc/include/longbridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,22 @@ typedef enum lb_push_candlestick_mode_t {
PushCandlestickMode_Confirmed,
} lb_push_candlestick_mode_t;

/**
* Transport used by the quote pull APIs
*/
typedef enum lb_quote_transport_t {
/**
* Send pull requests over the quote WebSocket connection (default)
*/
QuoteTransport_WebSocket,
/**
* Send pull requests over HTTP (`POST /quote/...`) where the API has a
* REST equivalent, falling back to the WebSocket for the rest. Using
* only HTTP-backed APIs never opens a WebSocket connection.
*/
QuoteTransport_Http,
} lb_quote_transport_t;

/**
* DCA investment frequency
*/
Expand Down Expand Up @@ -14318,9 +14334,10 @@ void lb_calendar_context_finance_calendar(const struct lb_calendar_context_t *ct
* Optional environment variables are read automatically:
* `LONGBRIDGE_HTTP_URL`, `LONGBRIDGE_LANGUAGE`, `LONGBRIDGE_QUOTE_WS_URL`,
* `LONGBRIDGE_TRADE_WS_URL`, `LONGBRIDGE_ENABLE_OVERNIGHT`,
* `LONGBRIDGE_PUSH_CANDLESTICK_MODE`, `LONGBRIDGE_PRINT_QUOTE_PACKAGES`,
* `LONGBRIDGE_LOG_PATH`. Use the corresponding `lb_config_set_*` functions
* to override any of these values after construction.
* `LONGBRIDGE_PUSH_CANDLESTICK_MODE`, `LONGBRIDGE_QUOTE_TRANSPORT`,
* `LONGBRIDGE_PRINT_QUOTE_PACKAGES`, `LONGBRIDGE_LOG_PATH`. Use the
* corresponding `lb_config_set_*` functions to override any of these values
* after construction.
*
* @param app_key App key
* @param app_secret App secret
Expand All @@ -14339,7 +14356,8 @@ struct lb_config_t *lb_config_from_apikey(const char *app_key,
* `LONGBRIDGE_ACCESS_TOKEN`, `LONGBRIDGE_HTTP_URL`, `LONGBRIDGE_QUOTE_WS_URL`,
* `LONGBRIDGE_TRADE_WS_URL`, `LONGBRIDGE_LANGUAGE`,
* `LONGBRIDGE_ENABLE_OVERNIGHT`, `LONGBRIDGE_PUSH_CANDLESTICK_MODE`,
* `LONGBRIDGE_PRINT_QUOTE_PACKAGES`, `LONGBRIDGE_LOG_PATH`
* `LONGBRIDGE_QUOTE_TRANSPORT`, `LONGBRIDGE_PRINT_QUOTE_PACKAGES`,
* `LONGBRIDGE_LOG_PATH`
*/
struct lb_config_t *lb_config_from_apikey_env(struct lb_error_t **error);

Expand All @@ -14349,9 +14367,10 @@ struct lb_config_t *lb_config_from_apikey_env(struct lb_error_t **error);
* Optional environment variables are read automatically:
* `LONGBRIDGE_HTTP_URL`, `LONGBRIDGE_LANGUAGE`, `LONGBRIDGE_QUOTE_WS_URL`,
* `LONGBRIDGE_TRADE_WS_URL`, `LONGBRIDGE_ENABLE_OVERNIGHT`,
* `LONGBRIDGE_PUSH_CANDLESTICK_MODE`, `LONGBRIDGE_PRINT_QUOTE_PACKAGES`,
* `LONGBRIDGE_LOG_PATH`. Use the corresponding `lb_config_set_*` functions
* to override any of these values after construction.
* `LONGBRIDGE_PUSH_CANDLESTICK_MODE`, `LONGBRIDGE_QUOTE_TRANSPORT`,
* `LONGBRIDGE_PRINT_QUOTE_PACKAGES`, `LONGBRIDGE_LOG_PATH`. Use the
* corresponding `lb_config_set_*` functions to override any of these values
* after construction.
*
* Does **not** take ownership of `oauth`. The caller must free `oauth` with
* `lb_oauth_free` after this call returns.
Expand Down Expand Up @@ -14408,6 +14427,17 @@ void lb_config_enable_overnight(struct lb_config_t *config);
void lb_config_set_push_candlestick_mode(struct lb_config_t *config,
enum lb_push_candlestick_mode_t mode);

/**
* Set the transport used by the quote pull APIs
*
* Default: `QuoteTransport_WebSocket` (or `LONGBRIDGE_QUOTE_TRANSPORT` =
* `ws` / `http`)
*
* @param config Config object
* @param transport Quote transport
*/
void lb_config_set_quote_transport(struct lb_config_t *config, enum lb_quote_transport_t transport);

/**
* Disable printing of quote packages on connection
*
Expand Down
34 changes: 26 additions & 8 deletions c/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{
async_call::{CAsyncCallback, execute_async},
error::{CError, set_error},
oauth::COAuth,
types::{CLanguage, CPushCandlestickMode, CString},
types::{CLanguage, CPushCandlestickMode, CQuoteTransport, CString},
};

/// Configuration options for Longbridge SDK
Expand All @@ -22,9 +22,10 @@ pub struct CConfig(pub(crate) Config);
/// Optional environment variables are read automatically:
/// `LONGBRIDGE_HTTP_URL`, `LONGBRIDGE_LANGUAGE`, `LONGBRIDGE_QUOTE_WS_URL`,
/// `LONGBRIDGE_TRADE_WS_URL`, `LONGBRIDGE_ENABLE_OVERNIGHT`,
/// `LONGBRIDGE_PUSH_CANDLESTICK_MODE`, `LONGBRIDGE_PRINT_QUOTE_PACKAGES`,
/// `LONGBRIDGE_LOG_PATH`. Use the corresponding `lb_config_set_*` functions
/// to override any of these values after construction.
/// `LONGBRIDGE_PUSH_CANDLESTICK_MODE`, `LONGBRIDGE_QUOTE_TRANSPORT`,
/// `LONGBRIDGE_PRINT_QUOTE_PACKAGES`, `LONGBRIDGE_LOG_PATH`. Use the
/// corresponding `lb_config_set_*` functions to override any of these values
/// after construction.
///
/// @param app_key App key
/// @param app_secret App secret
Expand Down Expand Up @@ -54,7 +55,8 @@ pub unsafe extern "C" fn lb_config_from_apikey(
/// `LONGBRIDGE_ACCESS_TOKEN`, `LONGBRIDGE_HTTP_URL`, `LONGBRIDGE_QUOTE_WS_URL`,
/// `LONGBRIDGE_TRADE_WS_URL`, `LONGBRIDGE_LANGUAGE`,
/// `LONGBRIDGE_ENABLE_OVERNIGHT`, `LONGBRIDGE_PUSH_CANDLESTICK_MODE`,
/// `LONGBRIDGE_PRINT_QUOTE_PACKAGES`, `LONGBRIDGE_LOG_PATH`
/// `LONGBRIDGE_QUOTE_TRANSPORT`, `LONGBRIDGE_PRINT_QUOTE_PACKAGES`,
/// `LONGBRIDGE_LOG_PATH`
#[unsafe(no_mangle)]
pub unsafe extern "C" fn lb_config_from_apikey_env(error: *mut *mut CError) -> *mut CConfig {
match Config::from_apikey_env() {
Expand All @@ -74,9 +76,10 @@ pub unsafe extern "C" fn lb_config_from_apikey_env(error: *mut *mut CError) -> *
/// Optional environment variables are read automatically:
/// `LONGBRIDGE_HTTP_URL`, `LONGBRIDGE_LANGUAGE`, `LONGBRIDGE_QUOTE_WS_URL`,
/// `LONGBRIDGE_TRADE_WS_URL`, `LONGBRIDGE_ENABLE_OVERNIGHT`,
/// `LONGBRIDGE_PUSH_CANDLESTICK_MODE`, `LONGBRIDGE_PRINT_QUOTE_PACKAGES`,
/// `LONGBRIDGE_LOG_PATH`. Use the corresponding `lb_config_set_*` functions
/// to override any of these values after construction.
/// `LONGBRIDGE_PUSH_CANDLESTICK_MODE`, `LONGBRIDGE_QUOTE_TRANSPORT`,
/// `LONGBRIDGE_PRINT_QUOTE_PACKAGES`, `LONGBRIDGE_LOG_PATH`. Use the
/// corresponding `lb_config_set_*` functions to override any of these values
/// after construction.
///
/// Does **not** take ownership of `oauth`. The caller must free `oauth` with
/// `lb_oauth_free` after this call returns.
Expand Down Expand Up @@ -163,6 +166,21 @@ pub unsafe extern "C" fn lb_config_set_push_candlestick_mode(
(*config).0.set_push_candlestick_mode(mode.into());
}

/// Set the transport used by the quote pull APIs
///
/// Default: `QuoteTransport_WebSocket` (or `LONGBRIDGE_QUOTE_TRANSPORT` =
/// `ws` / `http`)
///
/// @param config Config object
/// @param transport Quote transport
#[unsafe(no_mangle)]
pub unsafe extern "C" fn lb_config_set_quote_transport(
config: *mut CConfig,
transport: CQuoteTransport,
) {
(*config).0.set_quote_transport(transport.into());
}

/// Disable printing of quote packages on connection
///
/// @param config Config object
Expand Down
2 changes: 2 additions & 0 deletions c/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ mod language;
mod market;
mod option;
mod push_candlestick_mode;
mod quote_transport;
mod string;

use std::{ffi::CStr, os::raw::c_char};
Expand All @@ -18,6 +19,7 @@ pub(crate) use language::CLanguage;
pub(crate) use market::CMarket;
pub(crate) use option::COption;
pub(crate) use push_candlestick_mode::CPushCandlestickMode;
pub(crate) use quote_transport::CQuoteTransport;
pub(crate) use string::CString;

pub(crate) trait ToFFI {
Expand Down
17 changes: 17 additions & 0 deletions c/src/types/quote_transport.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use longbridge_c_macros::CEnum;

/// Transport used by the quote pull APIs
#[derive(Debug, Copy, Clone, Eq, PartialEq, CEnum)]
#[c(remote = "longbridge::QuoteTransport")]
#[allow(clippy::enum_variant_names, non_camel_case_types)]
#[repr(C)]
pub enum CQuoteTransport {
/// Send pull requests over the quote WebSocket connection (default)
#[c(remote = "WebSocket")]
QuoteTransport_WebSocket,
/// Send pull requests over HTTP (`POST /quote/...`) where the API has a
/// REST equivalent, falling back to the WebSocket for the rest. Using
/// only HTTP-backed APIs never opens a WebSocket connection.
#[c(remote = "Http")]
QuoteTransport_Http,
}
1 change: 1 addition & 0 deletions cpp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ setx LONGBRIDGE_ACCESS_TOKEN "Access Token get from user center"
| LONGBRIDGE_TRADE_WS_URL | Trade websocket endpoint url (Default: `wss://openapi-trade.longbridge.com/v2`) |
| LONGBRIDGE_ENABLE_OVERNIGHT | Enable overnight quote, `true` or `false` (Default: `false`) |
| LONGBRIDGE_PUSH_CANDLESTICK_MODE | `realtime` or `confirmed` (Default: `realtime`) |
| LONGBRIDGE_QUOTE_TRANSPORT | Transport for quote pull APIs, `ws` or `http` (Default: `ws`) |
| LONGBRIDGE_PRINT_QUOTE_PACKAGES | Print quote packages when connected, `true` or `false` (Default: `true`) |
| LONGBRIDGE_LOG_PATH | Set the path of the log files (Default: `no logs`) |
| LONGBRIDGE_PAPERTRADING | Enable paper trading mode, `true` or `false` (Default: `false`). See [Paper Trading](#paper-trading). |
Expand Down
15 changes: 12 additions & 3 deletions cpp/include/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ class Config
/// Optional environment variables are read automatically:
/// `LONGBRIDGE_HTTP_URL`, `LONGBRIDGE_LANGUAGE`, `LONGBRIDGE_QUOTE_WS_URL`,
/// `LONGBRIDGE_TRADE_WS_URL`, `LONGBRIDGE_ENABLE_OVERNIGHT`,
/// `LONGBRIDGE_PUSH_CANDLESTICK_MODE`, `LONGBRIDGE_PRINT_QUOTE_PACKAGES`,
/// `LONGBRIDGE_PUSH_CANDLESTICK_MODE`, `LONGBRIDGE_QUOTE_TRANSPORT`,
/// `LONGBRIDGE_PRINT_QUOTE_PACKAGES`,
/// `LONGBRIDGE_LOG_PATH`. Use the chainable `set_*` methods to override any
/// of these values.
///
Expand All @@ -48,7 +49,8 @@ class Config
/// Variables: `LONGBRIDGE_APP_KEY`, `LONGBRIDGE_APP_SECRET`,
/// `LONGBRIDGE_ACCESS_TOKEN`, `LONGBRIDGE_HTTP_URL`, `LONGBRIDGE_QUOTE_WS_URL`,
/// `LONGBRIDGE_TRADE_WS_URL`, `LONGBRIDGE_LANGUAGE`, `LONGBRIDGE_ENABLE_OVERNIGHT`,
/// `LONGBRIDGE_PUSH_CANDLESTICK_MODE`, `LONGBRIDGE_PRINT_QUOTE_PACKAGES`,
/// `LONGBRIDGE_PUSH_CANDLESTICK_MODE`, `LONGBRIDGE_QUOTE_TRANSPORT`,
/// `LONGBRIDGE_PRINT_QUOTE_PACKAGES`,
/// `LONGBRIDGE_LOG_PATH`
static Config from_apikey_env(Status& status);

Expand All @@ -57,7 +59,8 @@ class Config
/// Optional environment variables are read automatically:
/// `LONGBRIDGE_HTTP_URL`, `LONGBRIDGE_LANGUAGE`, `LONGBRIDGE_QUOTE_WS_URL`,
/// `LONGBRIDGE_TRADE_WS_URL`, `LONGBRIDGE_ENABLE_OVERNIGHT`,
/// `LONGBRIDGE_PUSH_CANDLESTICK_MODE`, `LONGBRIDGE_PRINT_QUOTE_PACKAGES`,
/// `LONGBRIDGE_PUSH_CANDLESTICK_MODE`, `LONGBRIDGE_QUOTE_TRANSPORT`,
/// `LONGBRIDGE_PRINT_QUOTE_PACKAGES`,
/// `LONGBRIDGE_LOG_PATH`. Use the chainable `set_*` methods to override any
/// of these values.
///
Expand Down Expand Up @@ -96,6 +99,12 @@ class Config
/// Set the push candlestick mode
Config& set_push_candlestick_mode(PushCandlestickMode mode);

/// Set the transport used by the quote pull APIs
///
/// Default: `QuoteTransport::WebSocket` (or `LONGBRIDGE_QUOTE_TRANSPORT` =
/// `ws` / `http`)
Config& set_quote_transport(QuoteTransport transport);

/// Disable printing of quote packages on connection
Config& disable_print_quote_packages();

Expand Down
11 changes: 11 additions & 0 deletions cpp/include/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,17 @@ enum class PushCandlestickMode
Confirmed,
};

/// Transport used by the quote pull APIs
enum class QuoteTransport
{
/// Send pull requests over the quote WebSocket connection (default)
WebSocket,
/// Send pull requests over HTTP (`POST /quote/*`) where the API has a REST
/// equivalent, falling back to the WebSocket for the rest. Using only
/// HTTP-backed APIs never opens a WebSocket connection.
Http,
};

/// Market
enum class Market
{
Expand Down
7 changes: 7 additions & 0 deletions cpp/src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,13 @@ Config::set_push_candlestick_mode(PushCandlestickMode mode)
return *this;
}

Config&
Config::set_quote_transport(QuoteTransport transport)
{
lb_config_set_quote_transport(config_, convert::convert(transport));
return *this;
}

Config&
Config::disable_print_quote_packages()
{
Expand Down
13 changes: 13 additions & 0 deletions cpp/src/convert.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,19 @@ convert(PushCandlestickMode mode)
}
}

inline lb_quote_transport_t
convert(QuoteTransport transport)
{
switch (transport) {
case QuoteTransport::WebSocket:
return QuoteTransport_WebSocket;
case QuoteTransport::Http:
return QuoteTransport_Http;
default:
throw std::invalid_argument("unreachable");
}
}

inline Market
convert(lb_market_t market)
{
Expand Down
1 change: 1 addition & 0 deletions examples/rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ members = [
"subscribe_candlesticks",
"http_client",
"grid_trading",
"quote_http_compare",
]
9 changes: 9 additions & 0 deletions examples/rust/quote_http_compare/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "quote_http_compare"
version = "0.1.0"
edition.workspace = true

[dependencies]
longbridge = { path = "../../../rust" }
tokio = { version = "1.19", features = ["rt-multi-thread", "macros"] }
time = { version = "0.3", features = ["macros"] }
Loading
Loading