Skip to content
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Breaking changes

- **All SDKs:** `QuoteContext.option_chain_info_by_date` moves off quote socket business command `21` onto the plain HTTP endpoint `GET /v1/gemini/option/option_chain_list` (longbridge/developers#1244), and its return type changes shape. The paired `StrikePriceInfo` (`price` + `call_symbol` + `put_symbol` + `standard`) is **removed** in favour of a flat, one-entry-per-contract `OptionChainContract` (`symbol`, `expiry_date`, `strike_price`, `direction`, `option_type`, `standard_attr`, `days_to_expiry`). Calls and puts are no longer paired by strike, so a strike listed on one side only now yields a single entry instead of an entry with an empty `call_symbol`/`put_symbol`, and callers must filter on `direction` where they used to read the two symbol fields. Two new enums come with it: `OptionExpiryCycleType` (`Unknown` / `Monthly` / `Weekly` / `Quarterly`) for the special expiration cycle — the server's empty `option_type` means a standard monthly option — and `OptionStandardAttr` (`Unknown` / `Normal` / `Old`) marking the legacy contracts left over from a corporate action (e.g. `BABA2261218C10000.US`); both fall back to `Unknown` for an unrecognized server value. The method also gains a `standard_only` parameter that filters those legacy contracts out server-side (positional `bool` in Rust incl. blocking, C, C++ and Java; optional `standardOnly?: boolean` in Node.js; `standard_only: bool = False` in Python) — it is omitted from the query string when false, which the endpoint treats as "return everything". The 30-minute client-side cache of the chain is gone, matching the other HTTP quote endpoints. New types per layer: C `lb_option_chain_contract_t` / `lb_option_expiry_cycle_type_t` / `lb_option_standard_attr_t` (`lb_strike_price_info_t` removed, and `lb_quote_context_option_chain_info_by_date` gains a `bool standard_only` argument before the callback), C++ `quote::OptionChainContract` / `OptionExpiryCycleType` / `OptionStandardAttr`, Java `com.longbridge.quote.OptionChainContract` / `OptionExpiryCycleType` / `OptionStandardAttr` (`StrikePriceInfo` deleted, and `getOptionChainInfoByDate` becomes `getOptionChainInfoByDate(String, LocalDate, boolean)`), Node.js `OptionChainContract` / `OptionExpiryCycleType` / `OptionStandardAttr`, and Python the same three (incl. the `openapi.pyi` stub). `QuoteContext.option_chain_expiry_date_list` is **unchanged** and still uses socket command `20`: the new endpoint requires `expiry_date`, so it cannot enumerate expiry dates, and the gateway path for the replacement expiry-date-list endpoint is not settled upstream yet
- **All SDKs:** removed `GridContext.submit_strategy_questionnaire` (`POST /v1/record/questionnaire`) and its `SubmitStrategyQuestionnaireOptions` type. The endpoint has been retired; the strategy risk-disclosure record is no longer submitted through the OpenAPI SDK. Removed across Rust (incl. blocking), C, C++, Java, Node.js, and Python bindings

### Fixed
Expand Down
6 changes: 4 additions & 2 deletions c/cbindgen.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ cpp_compat = true
"CTradeStatus" = "lb_trade_status_t"
"CTradeDirection" = "lb_trade_direction_t"
"COptionDirection" = "lb_option_direction_t"
"COptionExpiryCycleType" = "lb_option_expiry_cycle_type_t"
"COptionStandardAttr" = "lb_option_standard_attr_t"
"COptionType" = "lb_option_type_t"
"CWarrantType" = "lb_warrant_type_t"
"CAdjustType" = "lb_adjust_type_t"
Expand Down Expand Up @@ -52,7 +54,7 @@ cpp_compat = true
"CSecurityBrokers" = "lb_security_brokers_t"
"CParticipantInfo" = "lb_participant_info_t"
"CIntradayLine" = "lb_intraday_line_t"
"CStrikePriceInfo" = "lb_strike_price_info_t"
"COptionChainContract" = "lb_option_chain_contract_t"
"CIssuerInfo" = "lb_issuer_info_t"
"CTradingSessionInfo" = "lb_trading_session_info_t"
"CMarketTradingSession" = "lb_market_trading_session_t"
Expand Down Expand Up @@ -413,7 +415,7 @@ include = [
"CSecurityBrokers",
"CParticipantInfo",
"CIntradayLine",
"CStrikePriceInfo",
"COptionChainContract",
"CIssuerInfo",
"CTradingSessionInfo",
"CMarketTradingSession",
Expand Down
86 changes: 75 additions & 11 deletions c/csrc/include/longbridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -1633,6 +1633,47 @@ typedef enum lb_option_direction_t {
OptionDirectionCall,
} lb_option_direction_t;

/**
* Special expiration cycle of an option contract
*/
typedef enum lb_option_expiry_cycle_type_t {
/**
* Unknown
*/
OptionExpiryCycleTypeUnknown,
/**
* Standard monthly option
*/
OptionExpiryCycleTypeMonthly,
/**
* Weekly option, expires weekly
*/
OptionExpiryCycleTypeWeekly,
/**
* Quarterly option, expires quarterly
*/
OptionExpiryCycleTypeQuarterly,
} lb_option_expiry_cycle_type_t;

/**
* Whether an option contract is a legacy contract left over from a corporate
* action
*/
typedef enum lb_option_standard_attr_t {
/**
* Unknown
*/
OptionStandardAttrUnknown,
/**
* A normal, active contract
*/
OptionStandardAttrNormal,
/**
* A legacy contract produced by a corporate action
*/
OptionStandardAttrOld,
} lb_option_standard_attr_t;

/**
* Cash flow direction
*/
Expand Down Expand Up @@ -5028,26 +5069,40 @@ typedef struct lb_intraday_line_t {
} lb_intraday_line_t;

/**
* Strike price info
* A single option contract of an option chain
*/
typedef struct lb_strike_price_info_t {
typedef struct lb_option_chain_contract_t {
/**
* Option contract code, in `ticker.region` format
*/
const char *symbol;
/**
* Expiry date, in US Eastern time
*/
struct lb_date_t expiry_date;
/**
* Strike price
*/
const struct lb_decimal_t *price;
const struct lb_decimal_t *strike_price;
/**
* Contract direction
*/
enum lb_option_direction_t direction;
/**
* Security code of call option
* Special expiration cycle of the contract
*/
const char *call_symbol;
enum lb_option_expiry_cycle_type_t option_type;
/**
* Security code of put option
* Whether the contract is a legacy contract left over from a corporate
* action
*/
const char *put_symbol;
enum lb_option_standard_attr_t standard_attr;
/**
* Is standard
* Number of days remaining until the option expires, `0` on the expiry
* day and negative once expired
*/
bool standard;
} lb_strike_price_info_t;
int32_t days_to_expiry;
} lb_option_chain_contract_t;

/**
* Issuer info
Expand Down Expand Up @@ -13319,11 +13374,20 @@ void lb_quote_context_option_chain_expiry_date_list(const struct lb_quote_contex
void *userdata);

/**
* Get option chain info by date
* Get the option contract list of an underlying security for a given expiry
* date
*
* Every contract is an independent entry: calls and puts are not paired, so a
* strike price that is listed on one side only yields a single entry.
*
* `standard_only` filters out the legacy contracts produced by corporate
* actions. `true` returns standard contracts only; `false` returns everything,
* including the contracts carrying `OptionStandardAttrOld`.
*/
void lb_quote_context_option_chain_info_by_date(const struct lb_quote_context_t *ctx,
const char *symbol,
const struct lb_date_t *expiry_date,
bool standard_only,
lb_async_callback_t callback,
void *userdata);

Expand Down
27 changes: 18 additions & 9 deletions c/src/quote_context/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ use crate::{
CCandlestickOwned, CCapitalDistributionResponseOwned, CCapitalFlowLineOwned,
CCreateWatchlistGroup, CFilingItemOwned, CHistoryMarketTemperatureResponseOwned,
CIntradayLineOwned, CIssuerInfoOwned, CMarketTemperatureOwned, CMarketTradingDaysOwned,
CMarketTradingSessionOwned, COptionQuoteOwned, CParticipantInfoOwned, CPushBrokers,
CPushBrokersOwned, CPushCandlestick, CPushCandlestickOwned, CPushDepth,
CPushDepthOwned, CPushQuote, CPushQuoteOwned, CPushTrades, CPushTradesOwned,
CQuotePackageDetailOwned, CRealtimeQuoteOwned, CSecurityBrokersOwned,
CSecurityCalcIndexOwned, CSecurityDepthOwned, CSecurityOwned, CSecurityQuoteOwned,
CSecurityStaticInfoOwned, CStrikePriceInfoOwned, CSubscriptionOwned, CTradeOwned,
CMarketTradingSessionOwned, COptionChainContractOwned, COptionQuoteOwned,
CParticipantInfoOwned, CPushBrokers, CPushBrokersOwned, CPushCandlestick,
CPushCandlestickOwned, CPushDepth, CPushDepthOwned, CPushQuote, CPushQuoteOwned,
CPushTrades, CPushTradesOwned, CQuotePackageDetailOwned, CRealtimeQuoteOwned,
CSecurityBrokersOwned, CSecurityCalcIndexOwned, CSecurityDepthOwned, CSecurityOwned,
CSecurityQuoteOwned, CSecurityStaticInfoOwned, CSubscriptionOwned, CTradeOwned,
CUpdateWatchlistGroup, CWarrantInfoOwned, CWarrantQuoteOwned, CWatchlistGroupOwned,
LB_WATCHLIST_GROUP_NAME, LB_WATCHLIST_GROUP_SECURITIES,
},
Expand Down Expand Up @@ -725,21 +725,30 @@ pub unsafe extern "C" fn lb_quote_context_option_chain_expiry_date_list(
});
}

/// Get option chain info by date
/// Get the option contract list of an underlying security for a given expiry
/// date
///
/// Every contract is an independent entry: calls and puts are not paired, so a
/// strike price that is listed on one side only yields a single entry.
///
/// `standard_only` filters out the legacy contracts produced by corporate
/// actions. `true` returns standard contracts only; `false` returns everything,
/// including the contracts carrying `OptionStandardAttrOld`.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn lb_quote_context_option_chain_info_by_date(
ctx: *const CQuoteContext,
symbol: *const c_char,
expiry_date: *const CDate,
standard_only: bool,
callback: CAsyncCallback,
userdata: *mut c_void,
) {
let ctx_inner = (*ctx).ctx.clone();
let symbol = cstr_to_rust(symbol);
let expiry_date = (*expiry_date).into();
execute_async(callback, ctx, userdata, async move {
let rows: CVec<CStrikePriceInfoOwned> = ctx_inner
.option_chain_info_by_date(symbol, expiry_date)
let rows: CVec<COptionChainContractOwned> = ctx_inner
.option_chain_info_by_date(symbol, expiry_date, standard_only)
.await?
.into();
Ok(rows)
Expand Down
38 changes: 38 additions & 0 deletions c/src/quote_context/enum_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,44 @@ pub enum COptionDirection {
OptionDirectionCall,
}

/// Special expiration cycle of an option contract
#[derive(Debug, Copy, Clone, Eq, PartialEq, CEnum)]
#[c(remote = "longbridge::quote::OptionExpiryCycleType")]
#[allow(clippy::enum_variant_names)]
#[repr(C)]
pub enum COptionExpiryCycleType {
/// Unknown
#[c(remote = "Unknown")]
OptionExpiryCycleTypeUnknown,
/// Standard monthly option
#[c(remote = "Monthly")]
OptionExpiryCycleTypeMonthly,
/// Weekly option, expires weekly
#[c(remote = "Weekly")]
OptionExpiryCycleTypeWeekly,
/// Quarterly option, expires quarterly
#[c(remote = "Quarterly")]
OptionExpiryCycleTypeQuarterly,
}

/// Whether an option contract is a legacy contract left over from a corporate
/// action
#[derive(Debug, Copy, Clone, Eq, PartialEq, CEnum)]
#[c(remote = "longbridge::quote::OptionStandardAttr")]
#[allow(clippy::enum_variant_names)]
#[repr(C)]
pub enum COptionStandardAttr {
/// Unknown
#[c(remote = "Unknown")]
OptionStandardAttrUnknown,
/// A normal, active contract
#[c(remote = "Normal")]
OptionStandardAttrNormal,
/// A legacy contract produced by a corporate action
#[c(remote = "Old")]
OptionStandardAttrOld,
}

/// Warrant type
#[derive(Debug, Copy, Clone, Eq, PartialEq, CEnum)]
#[c(remote = "longbridge::quote::WarrantType")]
Expand Down
Loading
Loading