feat(fund): add FundContext for the mutual-fund channel - #124
Merged
Merged
Conversation
hogan-yuan
added a commit
that referenced
this pull request
Sep 28, 2026
Cut **v0.28.0** — closes out the `[Unreleased]` CHANGELOG section as `[v0.28.0] - 2026-09-28`. ## Included since v0.27.0 - **Grid trading** (`grid.GridContext`); `SubmitStrategyQuestionnaire` endpoint removed - **Removed all symbol↔counter_id conversions** (port longbridge/openapi #562) — endpoints send/receive the user symbol directly; `counter` package removed - **Multi-leg option orders** — `TradeContext.SubmitMultiLeg` + `MultiLegInfo` on orders/push (#575, #589, #590) - **Option chain onto the HTTP endpoint** (#588, **breaking**) — `StrikePriceInfo` → `OptionChainContract`; see gateway note below - **FinanceCalendar pagination** (#597, **breaking**) — `count`/`offset`/`next` + `CalendarPageDirection` - **HistoryExecutions pages through all `has_more`** (#591) - **SignalContext** — `Signals` / `Signal` / `SecurityFacts` (#577, #578) - **Type refinements** — `Execution.Side`, typed `AlertValueMap`, typed `RankCategories`, `CorpActionLive.Status` string, `IndustryPeersResponse.Top` optional, `WarrantStatusUnknown`, Greek doc refresh (#586) - Ratings temporarily disabled; `TopMovers.NextParams` string; portfolio flows timestamp ##⚠️ Gateway dependency (#588) `QuoteContext.OptionChainInfoByDate` now calls `GET /v1/gemini/option/option_chain_list`. That endpoint must be deployed on the target gateway. Verified live for this release: **available on staging, not yet on production** (returns `404 api not found` there until deployed). Called out prominently at the top of the v0.28.0 CHANGELOG entry. ## Verification Read-only endpoints exercised live against staging + production (report with per-endpoint request/response params): every change verified on at least one environment — see internal report. `go build ./...` and package tests pass. ## Not included `#123` (DelayedNotReported) and `#124` (fund) remain open for a later release. ## After merge Tag `v0.28.0` on the merge commit and push (Go modules resolve by tag).
Pure-Go HTTP bindings for the fund channel (28 methods), mirroring the grid package: catalog & market data, user fund positions, and fund orders/trading. Paths mirror the Rust core (`/v1/fund/*`, `/v1/asset/funds/*`); the fund identifier is `symbol`. Server-defined "any" JSON fields are surfaced as `json.RawMessage`, unix-second timestamps as `int64`, numeric-string fields as `string`.
The fund backend returns many int64 fields as JSON strings (created_at, last_update_time, recent_trading_day, id, …). Add a jsontypes.Int64 type whose UnmarshalJSON accepts a number, a quoted numeric string, null, or empty string (→0), and switch the affected response fields to it, so Nav/NavHistory/Orders/ Positions no longer fail to deserialize. Also fix the three batch-backed endpoints — latest NAV, daily performance and held-fund performance — to send the identifier as a one-element JSON array in a counter_ids query parameter (via withCounterIDs) instead of the scalar counter_id, matching the backend contract.
Align with the Rust core making these optional: the backend returns FundDetail.asset_allocation, FundTrend.contrast_performances, FundPositionDetail.detail_values and FundOrderDetail.order as null for many funds. Change them from value to pointer types (nil = null) so callers can distinguish null from an empty object, matching the other SDK layers' optional modeling. (Go already tolerated null by zero-valuing, so this is a representation/parity change, not a crash fix.)
hogan-yuan
force-pushed
the
feat/fund
branch
from
September 28, 2026 08:18
6dac27f to
e83ec4d
Compare
Fund endpoints are counter_id-only (request and response). Rename the remaining request-side symbol fields: ValidateFundOrder/SubmitFundOrder body Symbol -> CounterID (json counter_id), and GetFundOrders filter Symbols -> CounterIDs (orders query key symbol -> counter_id, backend-verified).
The fund entry was stale text from the first commit and still described the
pre-refactor design: it listed `{symbol}` path segments, claimed the
identifier is passed as `symbol`, and said numeric-string fields are kept as
`string`. All three contradict the shipped code, which identifies funds by
`counter_id` (query param, fixed sub-paths), sends batch endpoints a
`counter_ids` JSON array, uses the string-tolerant `jsontypes.Int64` for the
27 int64 fields, and pointer-izes the four nullable nested objects. Rewrite the
block to match and call out that funds are the deliberate exception to the
release-wide symbol migration.
The fund position identifier was the ISIN in a field named Symbol, which can't be used with the fund channel (no ISIN->counter_id conversion). Expose the full CounterID instead (ISIN is its last /-separated segment). The wire type reads counter_id and still accepts the legacy symbol key during transition.
hogan-yuan
added a commit
to longbridge/openapi
that referenced
this pull request
Sep 30, 2026
…598) ## Summary New `FundContext` for the Hong Kong mutual-fund channel — **28 endpoints** (catalog & market data, user positions, orders & trading) — across all six SDK layers: Rust core (async + blocking), C, C++, Java, Node.js, Python. ## Design notes - **`counter_id`-only, request and response** (e.g. `UT/FD/HK0000384492`); no `symbol` field. It contains `/`, so it's passed as a `counter_id` query param (fixed sub-paths like `/v1/fund/funds/detail`), never a path segment. Batch endpoints (`nav`, `performance`, `position_performance`) use a one-element `counter_ids` JSON array. - **Nullable nested objects** (`asset_allocation`, `contrast_performances`, `detail_values`, `order`) are optional/nullable in every layer; **int64** fields accept a JSON number or a quoted string. - Node.js / Python expose the position type as **`FundHoldingPosition`** to avoid a clash with the trade channel's `FundPosition`; C uses the `lb_*_t` naming convention like every other channel. ## Related Go: longbridge/openapi-go#124 · CLI: longbridge/longbridge-terminal#327 · MCP: longbridge/longbridge-mcp#161 · Docs (CLI only; excluded from SDK/API reference by the counter_id policy): longbridge/developers#1269
Merged
hogan-yuan
added a commit
that referenced
this pull request
Sep 30, 2026
Cut **v0.29.0** — closes out the `[Unreleased]` CHANGELOG section as `[v0.29.0] - 2026-09-30`. ## Included since v0.28.0 - **Added — Mutual-fund channel** (`fund.FundContext`, #124): 28 methods mirroring the Rust core — catalog & market data, user positions, and orders/trading. Funds are identified by `counter_id` (contains `/`, sent as a query parameter; `Performance` / `Nav` / `PositionPerformance` use a one-element `counter_ids` JSON array), the deliberate exception to the release-wide symbol migration. - **Breaking — `trade.FundPosition`** (#124): the fund identifier field is renamed `Symbol` → `CounterID`, matching the Rust core and the fund channel. It now holds the full fund `counter_id` (e.g. `UT/FD/HK0000384492`); the ISIN is its last `/`-separated segment. The wire type reads the new `counter_id` key and still accepts the legacy `symbol` key during the transition. ## Changelog housekeeping The `fund.FundContext` **Added** block was moved out of `[v0.28.0]` into `[v0.29.0]`: the fund package shipped in #124 **after** the v0.28.0 tag, so the v0.28.0 tag never contained it. `grid` / `signal` / multi-leg stay in `[v0.28.0]` (they were in that tag). > #124 is technically breaking (`FundPosition` field rename); released as minor per maintainer decision, consistent with v0.28.0.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a pure-Go
fundpackage withFundContext(28 methods) for themutual-fund channel, mirroring the Rust core field-for-field. Method groups:
catalog & market data, user fund positions, and orders/trading.
Design notes
counter_id-only, request and response — funds are identified bycounter_id(e.g.UT/FD/HK0000384492), the deliberate exception to therelease-wide symbol migration. Single-fund endpoints pass
counter_idas aquery param (fixed sub-paths like
/v1/fund/funds/detail); the order filtercarries repeated
counter_id. Nosymbolanywhere in the fund package.Performance,Nav,PositionPerformance) send aone-element JSON array in a
counter_idsquery param (withCounterIDs).jsontypes.Int64— a string-tolerant int64 type is applied to the 27int64 wire fields; the backend may send them as a number or a quoted string
(empty/null → 0).
FundDetail.AssetAllocation,FundTrend.ContrastPerformances,FundPositionDetail.DetailValues,FundOrderDetail.Order) are pointers sonulldeserializes cleanly.json.RawMessage.Verification
go build ./...,go vet ./fund/..., andgofmt -l fund/all clean.Related
Core + C/C++/Java/Node.js/Python: longbridge/openapi#598 · CLI: longbridge/longbridge-terminal#327 · MCP: longbridge/longbridge-mcp#161 · Docs: longbridge/developers#1269