Repository navigation
feat(tools): route US accounts' asset tools to US endpoints - #173
Merged
Merged
Conversation
The AP endpoints behind account_balance, stock_positions, cash_flow,
exchange_rate, fund_positions and margin_ratio are not deployed in the US
data center and fail with `code 12 internal server error` for US accounts.
- stock_positions: US accounts get the US asset overview (stock_list
symbols normalized) directly instead of calling the AP endpoint first,
which made the tool always fail for them.
- account_balance: US accounts use us_cash_and_buy_power
({buy_limit_info, cash_list[], margin_status}).
- cash_flow: US accounts use the paged US transaction history, walking
pages of 100 until a short page (at most 20 pages); the response flags
`truncated` with a note when the cap is hit.
- exchange_rate: US accounts use us_exchange_rates; bid/offer are dropped
when they equal average_rate, as on the AP path, and kept otherwise.
- fund_positions, margin_ratio: added to AP_ONLY_TOOLS, so US accounts no
longer see or call them.
AP behaviour is unchanged. Tool descriptions, zh-CN/zh-HK locales and the
stock_positions output schema describe the US shapes.
…drop before merge)
- stock_positions: US crypto_list entries now carry quantity, name and prices (the SDK used to drop them), and their bare pair code is qualified with its market (BTCUSD -> BTCUSD.BKKT) so symbol is fully qualified as in every other tool. The output schema and the tool descriptions list the crypto fields. - exchange_rate: describe universal_key as the account channel (e.g. us_lb_apex) and spec_key as the rate type (e.g. am, reference), as US prod returns them, and use those keys in the tests.
The US-region server instructions said tools with a US variant switch "for .US symbols", but account_balance, stock_positions, cash_flow, exchange_rate and order_detail take no symbol and return the US shape for every US account. Name those tools in the note, derived from the tool descriptions that say "US accounts get a US-specific variant", and keep the .US-symbol wording for the symbol-scoped variants.
…t tools
Both tools route every US account to the US order endpoint, which
returns {orders[]{id, ...}, total_count} instead of the AP shape, but
their descriptions only mentioned the US endpoint next to the us_*
params. Describe the US shape with the "US accounts get a US-specific
variant" marker so the generated US region note names them too.
…nd name AP-only alternatives - stock_positions: always emit the AP-required stock_info keys for US holdings (as "" when blank) so structured output matches the schema. - order_detail: attached_orders is omitted when empty, so it is no longer marked required in the output schema. - Validate every US golden (and the AP stock_positions/order_detail goldens) against the tool's output_schema. - today_orders: a US account's "today" starts at New York midnight (DST-aware via time-tz, already in the tree through the SDK). - history_orders: "excludes today" applies to AP accounts only. - AP-only tools rejected for US accounts name the US alternative, or say there is none and not to retry. - Drop the interim counter_id note from order descriptions; clarify the US-only cash_flow cap and Unknown direction.
…n AP-only alternatives - today_orders (US): the window now runs from 20:00 New York time on the previous calendar day (overnight session open) through 23:59:59 New York time today, DST-aware, so overnight orders no longer vanish at New York midnight while agents are told to check today_orders before resending. - history_orders (US): bare yyyy-mm-dd start_at/end_at are read as New York days so the range stitches with today_orders. - margin_ratio/operating rejections for US accounts now say there is no equivalent and name the partial account-level / key-metrics data. - Deliver the US alternative as the envelope hint instead of a data field that tool_error never emitted; test the delivered envelope. - Add a negative test for the output-schema validator.
…cutions its own range rules - Correct the history_orders comment: today_orders' US window opens at 20:00 ET the previous day, so it overlaps history_orders for yesterday's evening orders. Say so (and to dedupe by order_id) in the today_orders and history_orders descriptions (en/zh-CN/zh-HK). - Give history_executions its own HistoryExecutionsParam without us_page/us_limit, and read its bare dates in New York time for US accounts, matching history_orders. - Add history_range() to pick the date parser by region. - Route US history_executions to v1 /trade/execution/history; v3 /trade/execution/all fails in the US data center (code 12).
…ide unchanged - AP today_executions/history_executions render side exactly as before 0258250: "" for a today fill whose order is not in today's orders, "Unknown" for an unknown history side. - US fills use the same unresolved values instead of null. Sides missing after the range order query are looked up via /v1/us/orders/{id} (at most 20, 5 at a time); hitting the range query's page cap logs at warn. - A failed order query or detail lookup no longer fails the tool: it warns and leaves the side unresolved, still returning the fills. - Descriptions (en/zh-CN/zh-HK) point to order_detail(order_id) for an unresolved US side.
- When the unfiltered US order range query stops at the page cap, run one more range query filtered by the deduped symbols of the fills still unmatched (at most 50) before falling back to order detail lookups. The follow-up is sent directly to /v1/us/orders/query, since the SDK takes a single symbol; its failure is non-fatal. - today_executions with order_id on US skips the range query and resolves that order's side from its order detail. - Share one US order detail request between order_detail and side lookups. - Descriptions: an unresolved side means the order "could not be resolved". - Test the page-cap path, the symbol-filtered follow-up and its bound, and the by-order shortcut.
hogan-yuan
added a commit
to longbridge/openapi
that referenced
this pull request
Oct 23, 2026
## Why LBUS (US data-center) accounts can't read balances, cash flow or exchange rates through the SDK: the generic `/v1/asset/*` and `/v1/risk/margin-ratio` endpoints are AP-only. On US they return `code 12 internal server error`, because the gateway reports `unknown service PortfolioAsset` (the backend isn't deployed in US). This was found in the US UAT (items 3.3 / 4.3 / 5.4). ## What New `TradeContext` methods for US accounts (`dc_restrict(DcRegion::Us)`): | Method | Endpoint | |---|---| | `us_cash_and_buy_power(currency)` | `GET /v1/us/assets/cash-and-buy-power` | | `us_available_holding(opts)` | `GET /v1/us/assets/available-holding` | | `us_transaction_history(opts)` | `POST /v1/us/assets/transaction-history` | | `us_exchange_rates()` | `GET /v1/us/assets/exchange-rates` | - Response types follow the live `lb-portfolio-liberty` schemas (read via inner-gateway reflection). The exchange-rate response is a two-level map keyed by account channel (e.g. `us_lb_apex`) and rate type (`am` / `reference`). The SDK flattens it into `exchanges[]` and keeps both keys on each entry. - `fund_positions` and `margin_ratio` are now AP-only (`dc_restrict(DcRegion::Ap)`), so US accounts get a clear region error instead of `code 12`. US accounts have no fund holdings or margin-ratio data. - Bindings: Rust (async + blocking), Python (sync + async + `openapi.pyi`), Node.js (napi; `index.d.ts` regenerated with `@napi-rs/cli` 3.8.0), Java JNI layer. - Java classes and C/C++ are not included, following the precedent of the existing US methods (`us_asset_overview` etc.), which are not exposed there either. - CHANGELOG updated. ## Gateway All four routes are deployed to prod. `transaction-history` (559) and `exchange-rates` (558) are new. `available-holding` (440) now has `symbol2CounterID`, so callers pass `AAPL.US`. The routes are also bound to MCP scopes (`account.read` / `trade.read`) on the HK and US registries. ## Testing - `cargo test -p longbridge --lib`: 76 passed. Clippy shows no new warnings. Python and Node built locally, and the new methods were checked by importing them. - Against US prod with an LBUS API key: all four endpoints return data. The real responses deserialize into the new types. This caught a bug, fixed in `f8877d2ab`: the gateway returns both `symbol` and `counter_id`, so the earlier `counter_id` alias caused a duplicate-field error. ## Related - Go SDK: longbridge/openapi-go#135 - Docs: longbridge/developers#1297 - Consumers (draft until this is released): longbridge/longbridge-terminal#337, longbridge/longbridge-mcp#173 ## Updated after real-data review Checked against masked US prod responses (overview, cash-and-buy-power, available-holding, transaction-history, exchange-rates). The new types match. One gap fixed in cab7903: `USCryptoEntry` (used by `us_asset_overview`) kept only 5 of the fields prod returns for a crypto holding, so it had no `quantity`. It now has the same fields as `USStockEntry` (`quantity`, `market`, `name`, prices, `today_pl`, `position_side`, ...) in Rust, Python and Node.js. The `symbol` doc now says it is the bare pair code (`BTCUSD`), and the user-facing symbol is `<symbol>.<market>`. Also added a test using the prod response shapes (`current_page` as a number, `us_lb_apex`/`am`/`reference` keys, numeric-string timestamps). `cargo test -p longbridge --lib` passes (77 tests). `index.d.ts` was regenerated with `@napi-rs/cli@3.8.0`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
hogan-yuan
marked this pull request as ready for review
October 23, 2026 08:54
# Conflicts: # locales/zh-CN/tools.json # locales/zh-HK/tools.json # src/tools/mod.rs
Merged
hogan-yuan
added a commit
that referenced
this pull request
Oct 26, 2026
Cut **v0.15.0**. Bumps `0.14.0` → `0.15.0` (minor: new tools and output changes for Longbridge US accounts, listed below). ## Included since v0.14.0 - **Longbridge US accounts** (#173), built on longbridge SDK 5.3.0: - `account_balance`, `stock_positions`, `cash_flow`, `exchange_rate`, `today_orders`, `history_orders` and `order_detail` call the US asset and order APIs for US accounts and return the same shape as for AP accounts. - `today_executions` / `history_executions` work on US accounts; `side` is filled from the account's orders. - AP-only tools (`fund_positions`, `margin_ratio`, ...) are hidden for US accounts, and a direct call returns an error whose hint names the alternative. - **`fx_rate`** (#175): public ECB reference exchange rates via Frankfurter (latest, a past date, or a daily series), separate from Longbridge's account-conversion rates in `exchange_rate`. ## Behaviour changes for API clients - On US accounts, the tools above now return the AP shape instead of the raw US payloads; US-only fields stay alongside the AP keys. - `cash_flow` on US accounts returns a signed `balance` plus `direction`. - `today_orders` on US accounts covers the overnight session (from 20:00 ET the previous day); `history_orders` / `history_executions` read date-only bounds in New York time for US accounts. Only `Cargo.toml`, `Cargo.lock` and `server.json` change. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
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.
Why
For LBUS accounts,
stock_positions,account_balance,cash_flowandexchange_ratefail withcode 12, because they call AP-only endpoints (US UAT 5.2 / 5.4).stock_positionseven called the AP endpoint before the US overview supplement, so it never succeeded for US accounts.fund_positionsandmargin_ratiohave no US equivalent.What (US accounts only; AP behaviour unchanged)
stock_positionsus_asset_overviewonly (US fields at top level; output schema covers both shapes)account_balanceus_cash_and_buy_powercash_flowus_transaction_history, size 100, up to 20 pages,truncated+ note when cappedexchange_rateus_exchange_rates.bid/offerare dropped when equal toaveragefund_positions,margin_ratioAP_ONLY_TOOLS(hidden from and rejected for US accounts)Tool descriptions are updated in en / zh-CN / zh-HK.
The gateway routes are live in prod and bound to
account.read/trade.readon the HK and US scope registries.Testing
cargo +nightly fmt --check,cargo clippy --all-features --all-targets(0 warnings),cargo test(389 passed).Updated after real-data review
Checked against masked US prod responses. Changes in 9052862, with the SDK lock bumped to cab79039 in 592e1f6:
stock_positions(US):crypto_listentries now includequantity,nameand prices. Theirsymbolis qualified with the market (BTCUSDbecomesBTCUSD.BKKT). The output schema and the descriptions (en / zh-CN / zh-HK) list these fields.exchange_rate(US): the descriptions sayuniversal_keyis the account channel (e.g.us_lb_apex) andspec_keyis the rate type (e.g.am,reference). The tests use those keys.cargo +nightly fmt,cargo clippy --all-features --all-targets(0 warnings),cargo test(391 passed).🤖 Generated with Claude Code