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
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **All SDKs:** document that `SubmitMultiLegOrderLeg.ratio_quantity` must be a positive number. A leg's direction comes from the `strategy` plus the order `side`, not from the sign of the ratio; the server rejects a negative or zero ratio with `602001` (`value does not match regex pattern "^([1-9]\\d*(\\.\\d+)?)$"`). Doc comments only — no behaviour or type changes
- **All SDKs:** `FundamentalContext.executive` (`GET /v1/quote/company-professionals`) sent its security in a `symbol` query parameter, but the endpoint expects the plural `symbols` (it takes a comma-separated list). The server silently ignored the unknown parameter and answered with an empty group (`total: 0`, no `symbol`, a `forward_url` missing the security id), so the call appeared to succeed while returning nothing. Verified live against `700.HK` and `AAPL.US`
- **All SDKs:** every optional response field now tolerates an explicit JSON `null`. `#[serde(default)]` alone only covers a *missing* key, so a server that sent `null` for any of ~700 optional fields aborted the whole response with `deserialize response body error: invalid type: null`. All `#[serde(default)]` response fields across every module (quote, trade, fundamental, market, dca, alert, sharelist, portfolio, calendar, content, screener, agent) now map `null` to the field's default value. First observed live as `institution_rating_detail` `"target"/"evaluate": null` (symbols without analyst coverage) and `us_company_dividends` `"recent_dividends": null` (no trailing dividends). No field types changed, so the language bindings are unaffected

### Added

- **All languages:** `MultiLegStrategy` gains `CalendarCallSpread` (`7`) and `CalendarPutSpread` (`8`) — calendar (horizontal) spreads, accepted by `TradeContext.submit_multileg` and reported back on the `multi_leg` field of order queries and the order-changed push. Both are appended after `Strangle`, so the discriminants of the existing variants are unchanged. Added across Rust, C, C++, Java, Node.js, and Python. Documented in longbridge/developers#1251
- **Rust:** `Signal.status` is now a `SignalStatus` enum (pending / active / deleted / ai-failed / filtered-by-manual / ai-submit-failed), `SignalsResponse.total` is `i32` to match the wire contract, and the `risk_level` / `display_control` fields were dropped — neither is part of the API contract nor served in production
- **Rust:** `SignalContext.security_facts` now returns a typed `SecurityFact` instead of raw JSON — fact id / type / direction, the securities it is about, the factors behind it (with their anomaly test and groups), the data sources, and the natural-language `nl_info`. Adds the `FactType` and `FactDirection` enums, and `FactNlInfo::summary_tags()` / `invest_anal_tags()` / `eli_explain_tags()` for the `{tag, value}` entries the API carries as JSON inside a string
- **Rust:** add `SignalContext` — strategy signals and the catalyst facts behind them. `signals` (`GET /v1/signals`) queries signals with symbol / strategy / catalyst / time-range filters and paging; `signal` (`GET /v1/signals/{signal_id}`) returns one signal including the full strategy analysis in `json_data`; `security_facts` (`GET /v1/facts/security_facts`) lists a security's fact (catalyst) events. Bindings for the other languages are not wired up yet
- **All languages:** add `TradeContext.submit_multileg` (`POST /v1/trade/order/multileg`) — submit a multi-leg option combination order (vertical spreads, straddles, strangles, collars, etc.) whose legs are placed together as a single strategy order. Takes `side`, `order_type`, `submitted_quantity`, `strategy` (`MultiLegStrategy`), a list of legs (`symbol` + `ratio_quantity`), and optional `submitted_price` / `remark` / `client_request_id`; returns the existing `SubmitOrderResponse`
- **All languages:** order queries and the order push now expose multi-leg strategy information. `Order` (from `today_orders` / `history_orders`), `OrderDetail` (from `order_detail`), and the `PushOrderChanged` order-changed event gain an optional `multi_leg` field (`MultiLegInfo`) — present only for multi-leg option combination orders — carrying the `strategy`, `strategy_name`, `multileg_id`, `code`, and the combination `legs` (each with `symbol`, `side`, `position`, `ratio_quantity`, `strike_price`, `expire_date`, and `contract_direction`). Adds the `MultiLegStrategy`, `MultiLegPosition`, and `ContractDirection` enums
- **All languages:** add grid-trading support via a standalone `GridContext` — submit / replace / cancel / suspend / restart grid orders, list orders (paged and by IDs), fetch order detail and trigger history, submit the strategy risk-disclosure questionnaire, and query the security (symbol) info (`symbol_info` → `GridSymbolInfo`: name, last price, lot sizes, price-step rules, channel/authorization) needed to build a grid order. Available in the Rust, Python, Node.js, Java, and C/C++ bindings
- **All languages:** `Execution` gains a `side` field (`OrderSide`) — the buy/sell direction of the fill, now returned by the `today_executions`, `history_executions`, and `all_executions` responses

### Fixed

- **All languages:** the AI Agent streamed conversation no longer errors mid-run when the server sends an explicit `"outputs": null`. `WorkflowFinishedPayload.outputs`, `NodeToolUseFinishedPayload.outputs`, and `SubagentFinishedPayload.outputs` were annotated `#[serde(default)]`, which only covers a *missing* key, not an explicit `null` — so a `workflow_finished` / `node_tool_use_finished` / `subagent_finished` event carrying `null` outputs failed to deserialize and aborted the whole event stream (`invalid type: null, expected struct WorkflowOutputs`). These fields now map `null` to the type's default
- **All languages:** likewise, list-typed fields on the streamed AI Agent event payloads no longer error on an explicit `null` (`invalid type: null, expected a sequence`). `tip_chips` (on the node / subagent / agent-tool `*_started` payloads), `WorkflowFinishedPayload.process_data`, and `SubagentStartedPayload.tools` were `#[serde(default)]`, which does not accept an explicit `null`; they now deserialize `null` to an empty list
- **All languages:** clarified that `CompanyOverview.employees` is typed as a **string** (not an integer) across all SDK languages — the Longbridge API returns this field as a JSON string (e.g. `"10000"`). Doc comments have been updated to make this explicit and prevent downstream tools from incorrectly treating the value as an integer
Expand Down
8 changes: 8 additions & 0 deletions c/csrc/include/longbridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -1343,6 +1343,14 @@ typedef enum CMultiLegStrategy {
* Strangle
*/
MultiLegStrategyStrangle,
/**
* Calendar call spread
*/
MultiLegStrategyCalendarCallSpread,
/**
* Calendar put spread
*/
MultiLegStrategyCalendarPutSpread,
} CMultiLegStrategy;

/**
Expand Down
6 changes: 6 additions & 0 deletions c/src/trade_context/enum_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,12 @@ pub enum CMultiLegStrategy {
/// Strangle
#[c(remote = "Strangle")]
MultiLegStrategyStrangle,
/// Calendar call spread
#[c(remote = "CalendarCallSpread")]
MultiLegStrategyCalendarCallSpread,
/// Calendar put spread
#[c(remote = "CalendarPutSpread")]
MultiLegStrategyCalendarPutSpread,
}

/// Multi-leg position direction
Expand Down
4 changes: 4 additions & 0 deletions cpp/include/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1697,6 +1697,10 @@ enum class MultiLegStrategy
Straddle,
/// Strangle
Strangle,
/// Calendar call spread
CalendarCallSpread,
/// Calendar put spread
CalendarPutSpread,
};

/// Multi-leg position direction
Expand Down
8 changes: 8 additions & 0 deletions cpp/src/convert.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1532,6 +1532,10 @@ convert(CMultiLegStrategy strategy)
return MultiLegStrategy::Straddle;
case MultiLegStrategyStrangle:
return MultiLegStrategy::Strangle;
case MultiLegStrategyCalendarCallSpread:
return MultiLegStrategy::CalendarCallSpread;
case MultiLegStrategyCalendarPutSpread:
return MultiLegStrategy::CalendarPutSpread;
default:
return MultiLegStrategy::Unknown;
}
Expand All @@ -1557,6 +1561,10 @@ convert(MultiLegStrategy strategy)
return MultiLegStrategyStraddle;
case MultiLegStrategy::Strangle:
return MultiLegStrategyStrangle;
case MultiLegStrategy::CalendarCallSpread:
return MultiLegStrategyCalendarCallSpread;
case MultiLegStrategy::CalendarPutSpread:
return MultiLegStrategyCalendarPutSpread;
default:
return MultiLegStrategyUnknown;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,8 @@ public enum MultiLegStrategy {
Straddle,
/** Strangle */
Strangle,
/** Calendar call spread */
CalendarCallSpread,
/** Calendar put spread */
CalendarPutSpread,
}
4 changes: 3 additions & 1 deletion java/src/types/enum_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,9 @@ impl_java_enum!(
VerticalPutSpread,
Collar,
Straddle,
Strangle
Strangle,
CalendarCallSpread,
CalendarPutSpread
]
);

Expand Down
6 changes: 5 additions & 1 deletion nodejs/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6026,7 +6026,11 @@ export declare const enum MultiLegStrategy {
/** Straddle */
Straddle = 6,
/** Strangle */
Strangle = 7
Strangle = 7,
/** Calendar call spread */
CalendarCallSpread = 8,
/** Calendar put spread */
CalendarPutSpread = 9
}

/** Options for listing topics created by the current authenticated user */
Expand Down
4 changes: 4 additions & 0 deletions nodejs/src/trade/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,10 @@ pub enum MultiLegStrategy {
Straddle,
/// Strangle
Strangle,
/// Calendar call spread
CalendarCallSpread,
/// Calendar put spread
CalendarPutSpread,
}

/// Multi-leg position direction
Expand Down
10 changes: 10 additions & 0 deletions python/pysrc/longbridge/openapi.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -6358,6 +6358,16 @@ class MultiLegStrategy:
Strangle
"""

class CalendarCallSpread(MultiLegStrategy):
"""
Calendar call spread
"""

class CalendarPutSpread(MultiLegStrategy):
"""
Calendar put spread
"""

class MultiLegPosition:
"""
Multi-leg position direction
Expand Down
4 changes: 4 additions & 0 deletions python/src/trade/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,10 @@ pub(crate) enum MultiLegStrategy {
Straddle,
/// Strangle
Strangle,
/// Calendar call spread
CalendarCallSpread,
/// Calendar put spread
CalendarPutSpread,
}

/// Multi-leg position direction
Expand Down
6 changes: 6 additions & 0 deletions rust/src/trade/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,12 @@ pub enum MultiLegStrategy {
/// Strangle
#[strum(to_string = "Strangle", serialize = "6")]
Strangle,
/// Calendar call spread
#[strum(to_string = "CalendarCallSpread", serialize = "7")]
CalendarCallSpread,
/// Calendar put spread
#[strum(to_string = "CalendarPutSpread", serialize = "8")]
CalendarPutSpread,
}

/// Multi-leg position direction
Expand Down
Loading