Repository navigation
feat(trade): route asset commands to US APIs for US accounts - #337
Merged
Merged
Conversation
5.2.2 adds OrderStatus::DelayedNotReported (time-conditional orders being monitored); handle it in the TUI orders view as a pending, cancellable status.
…erge) Points the longbridge crate at a local checkout of the SDK branch feat/us-asset-apis, which adds the US cash/buying-power, available-holding, transaction-history and exchange-rate APIs. Drop this commit and bump the dependency once that SDK release is published.
…counts Add us_asset_overview, us_cash_and_buy_power, us_available_holding, us_transaction_history and us_exchange_rates to the TradeApi seam (and so to `serve` as trade.us_*). trade.account_balance, cash_flow, stock_positions, fund_positions and margin_ratio call AP endpoints that are not deployed in the US data center (they fail with code 12). A US session now gets a clear error that names the US counterpart where one exists, instead of a generic internal error; results keep their SDK shape rather than being silently answered in another one.
The AP asset endpoints (/v1/asset/account, /stock, /fund, /cashflow,
/exchange_rates, /v1/risk/margin-ratio) are not deployed in the US data
center, so these commands failed with code 12 for US accounts. Route them by
the session's data center; AP behaviour is unchanged.
- assets: cash per currency, buying power and margin status from
us_cash_and_buy_power.
- portfolio: US asset overview (stocks / options / crypto) plus
cash_and_buy_power, instead of account_balance + stock_positions.
- cash-flow: us_transaction_history over --start/--end, walking all pages.
- exchange-rate: us_exchange_rates, keeping the {exchanges: [...]} shape.
- fund-positions, margin-ratio: fail early with "not available for US
accounts" without calling the API.
Also show the symbol column of US positions from full_symbol / symbol (the
overview has no counter_id field, so it printed "-"), and update help text,
--schema descriptions and README for the changed commands.
…drop before merge)
- Crypto entries in the US asset overview carry the bare pair code (BTCUSD) plus market (BKKT): add the user-facing full_symbol (BTCUSD.BKKT), as stock entries have it, and print quantity, cost, last price and today's P&L in the crypto table now that the SDK keeps them. - exchange-rate: US accounts get one row per rate type (am, reference) for the same pair; show spec_key as a rate_type column so the rows are told apart, and describe universal_key / spec_key in --schema. - cash-flow: transaction symbol is already user-facing (BTCUSD.BKKT); drop the counter_id conversion.
On US accounts GET /v1/trade/order returns HTTP 500, and the CLI already reroutes `order` / `order <id>` to the US order APIs and refuses `order executions`. `serve` exposed neither US method, so a US session got an opaque upstream failure. Add us_query_orders and us_order_detail to the TradeApi seam (and so to serve as trade.us_query_orders / trade.us_order_detail). Mark today_orders, history_orders, order_detail, today_executions and history_executions AP-only, with errors naming the US method to call. Document the US mapping in the README and `serve -h`.
US accounts now print the same --format json keys, value formats and top-level shape as AP accounts for assets, positions, portfolio, cash-flow, exchange-rate, order (today / --history) and order detail. AP-only fields with no US source are omitted; US-only data stays as extra keys or under `us`. - orders: array rows keyed order_id/symbol/side/...; symbol taken from the response when the gateway sends it, else derived from counter_id; status uses the AP enum names; time_in_force/tag kept as us_time_in_force/us_tag. Order detail reads the raw body so counter_id survives. - cash-flow: flow_name/balance/time/description plus direction (amount sign, or quantity sign for zero-amount crypto transfers). - exchange-rate: one row per pair (reference, else am), numeric rates. - check --format json reports dc_region (ap / us). - AP JSON builders extracted unchanged and covered by golden tests; sanitized US golden tests for every command.
US cash-flow balance is now the signed transaction amount, as AP balances are, instead of its absolute value. Crypto transfers and fees keep balance 0; direction still comes from the amount sign, or the quantity sign when the amount is 0.
Symbol <-> counter ID conversion belongs to the gateway. US order, order detail and holding rows now use symbol / underlying_symbol / full_symbol from the response only; when a row has none, symbol is omitted and the raw counter_id (underlying_counter_id) is passed through instead of a CLI-derived symbol.
…reviews and return raw US order detail in serve
- serve trade.us_order_detail returns the untouched GET /v1/us/orders/{order_id} body; order IDs are validated (digits only) before going into the path
- cancel/replace previews on US read the raw detail and show symbol (or the raw counter_id, unconverted)
- --schema marks (US only) / (AP only) fields for order, order detail, assets, cash-flow, portfolio and positions; net_assets / total_asset are documented as absent without a net liquidation value
- US order paging note is printed only when orders remain past the requested page, and help/schema say it goes to stderr
- US order detail always emits stock_name, currency and executed_amount, as AP does
…, and stop deriving symbols - order executions and trade.today_executions/history_executions now work on US accounts (the execution APIs serve them with the AP shape) - US cancel/replace previews fail with the reason (invalid order ID, order not found) instead of issuing a confirmation code without the order - US preview summary and order detail --attached keep the raw counter_id when the response has no symbol; no counter_id-to-symbol derivation - note past-the-last-page US order pages; size pages by the returned rows - --schema: underlying_symbol/underlying_counter_id and US position extras; with_legend asserts every legend key is a field - help examples use all-digit order IDs; tests for is_us_order_id and the serve order_id param error
…ncel previews - order executions --history: US accounts read /v1/trade/execution/history (the SDK pages has_more); /v3/trade/execution/all answers HTTP 500 there. AP keeps the v3 paging loop. - US cancel/replace previews: report "not found" only for HTTP 404 or a missing/null/non-object order; other failures say "could not fetch order". - --execute on US accounts validates the order ID (digits only) before calling cancel/replace. - Pretty order detail --attached shows counter_id when no symbol is returned. - --schema: document top-level counter_id for order / order detail, add side and trade_done_at to order executions, and put the US_ORDER_LEGEND doc comment back on its item.
…rve execution sides - Side backfill trusts total_count only when positive (the SDK reports a missing total_count as 0); otherwise it stops at a short page. - Orders still unmatched after the range query are read from the order detail by order_id (at most 20, 4 at a time); failures only warn. - An unresolved US execution side is printed as "Unknown", as on AP, in JSON and table output; schema, help and READMEs say so. - Document that serve trade.today_executions / trade.history_executions stay raw (side "Unknown" on US) and should be joined with trade.us_query_orders or trade.us_order_detail by order_id. - README.zh-CN: add the US v1 execution history caveat.
Only a first-page order list failure is an error now; a later page failing prints a warning, stops paging and keeps the sides already found, so the order-detail fallback only reads the rest. Without total_count, a page ends the lookup only when shorter than both the requested limit and the previous page, so a server-capped page size does not stop paging early.
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 26, 2026 01:54
hogan-yuan
added a commit
that referenced
this pull request
Oct 26, 2026
Bump `0.30.0` → `0.31.0` for release. ## Included since v0.30.0 - **Longbridge US accounts** (#337): `assets`, `portfolio`, `positions`, `cash-flow`, `exchange-rate`, `order` (today and `--history`) and `order detail` call the US asset and order APIs for US accounts, built on longbridge SDK 5.3.0. Their `--format json` output keeps the AP keys and shape; US-only fields are marked `(US only)` in `--schema`, and `check --format json` reports `dc_region`. - **`order executions` on US accounts** (#337): history comes from `/v1/trade/execution/history`, which is not filtered by execution time and can lag across days; `side` is filled from the account's orders and shows `Unknown` when it can't be resolved. - **AP-only commands and `serve` methods** (#337): `fund-positions` and `margin-ratio` on a US account fail before sending a request and name the alternative; `serve` gains `trade.us_query_orders` and `trade.us_order_detail`. - **Safer US cancel / replace** (#337): the preview refuses to issue a confirmation code when the order can't be fetched, and US order ids must be digits. - **`rank --count`** (#336) is honored. Tag `v0.31.0` after merge to trigger the release build. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
hogan-yuan
added a commit
to longbridge/skills
that referenced
this pull request
Oct 26, 2026
…ount limits (#68) ## Why Found in the LBUS user acceptance test: - **5.4 "show my positions" failed for an LBUS account.** The base skill tells the model to always run `portfolio` for "my portfolio". On LBUS accounts the current CLI's `portfolio` calls AP-only endpoints and fails with `internal server error` (code 12). `positions` works. - **5.5 / 5.x: order confirmation is described wrong.** `references/order.md` was a stale capture of the old CLI help ("prompts for confirmation"). The CLI now previews by default and only acts when the same command is re-run with `--execute <CODE>`. `--execute` appeared nowhere in this repo. ## What - `longbridge-portfolio/references/order.md`: refreshed the captured `longbridge order --help` (CLI 0.30.0) and added the preview → confirm → `--execute <CODE>` flow, with "never execute before the user confirms". - `longbridge-portfolio/SKILL.md`: - The Auth section explains the dry-run default. - New "Longbridge US accounts" section: use `positions` for holdings, cash and buying power; fund positions, margin ratio and executions are not available for US accounts; fall back to `positions` if `portfolio` / `assets` / `cash-flow` fail on an older CLI. - Two new error-handling rows for the AP-only region error and the code 12 case. - `longbridge/SKILL.md`: one-line LBUS note next to the `portfolio` example. Follow-ups, not in this PR: - Once longbridge/longbridge-terminal#337 ships (US support for `portfolio`, `assets`, `cash-flow`, `exchange-rate`), the "older CLI" fallback note can be narrowed to a version. - Once longbridge/openapi#613 is released, add the new US SDK methods to `references/*-sdk/trade-context.md`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
hogan-yuan
added a commit
to longbridge/developers
that referenced
this pull request
Oct 26, 2026
…1297) ## Why LBUS users follow the asset docs and get `code 12`: the generic asset endpoints are AP-only, and the docs don't say so or point to the US endpoints (US UAT 3.3). ## What - New pages (en / zh-CN / zh-HK) under `trade/asset/`: Cash and Buying Power, Available Holding, Transaction History, Exchange Rates (US). The API reference (`openapi.yaml`) gets the 4 endpoints too. Examples are in Python, Python async, Node.js, Rust and Go. Java is not included because the Java SDK does not expose these methods yet. - An "AP accounts only" notice on Account Assets, Stock Positions, Fund Positions, Cash Flow, Margin Ratio and Exchange Rates, linking to the US equivalents. Fund positions and margin ratio are marked not available for US accounts. - Getting Started: US accounts are pointed to `us_asset_overview` / `us_cash_and_buy_power` for balances. SDK: longbridge/openapi#613. The endpoints are already live on the prod gateway. ## Testing - `autocorrect --lint` passes. `openapi.yaml` parses. The Node.js and Go examples type-check against the SDK branches. - The site build was not run here (`bun run build:canary` should be run before merge). ## Also in this PR Doc fixes from the LBUS UAT replies: - Order Details is marked AP-only and points US accounts to `us_order_detail`. Today Orders and History Orders recommend `us_query_orders` for US accounts (UAT 3.4). - Paper trading: the MCP prerequisites and the general FAQ say LBUS has no paper accounts, and tell users to test with the paper account's own credentials (UAT 3.6). - Error codes: added `403308` (scope not authorized), with the fix and the no-securities-account/no-permission case. The MCP troubleshooting section links to it (UAT 3.x / 5.5). - Getting Started: new OAuth scopes section (`watchlist`, `account.read`, `trade.read`, `trade.write`, and the production ids `4/6/10/11` from longbridge-mcp; other ids are treated as opaque) and a Sign Out section (delete the stored token file, or `longbridge auth logout`) (UAT 2.3). - CLI `order` / `grid`: replaced "prompts for confirmation" / `-y` / `--dry-run` with the actual preview + `--execute <CODE>` flow (UAT 5.5). - CLI `portfolio` / `assets` / `cash-flow` / `exchange-rate`: one-line note that LBUS should use `positions` for now, with US support coming in longbridge/longbridge-terminal#337 (UAT 4.3 / 5.4). 🤖 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
On LBUS accounts,
longbridge portfolioandassetsfail withcode 12 internal server error. In the US UAT (4.3 / 5.4), the trace showsGET /v1/asset/account→unknown service PortfolioAsset. The same happens forcash-flow,exchange-rate,fund-positions,margin-ratioand the matchingservemethods. The generic asset endpoints are AP-only, and onlypositionsalready branched to the US API.What (US accounts only; AP behaviour unchanged)
assetsus_cash_and_buy_power: buying power, cash per currency, margin statusportfolious_asset_overview+us_cash_and_buy_powercash-flowus_transaction_history, paging through all pagesexchange-rateus_exchange_ratesfund-positions,margin-ratioservetrade.us_*methods. AP-only methods return a clear error naming the US equivalentAlso:
positionstable.--schemaand READMEs.OrderStatus::DelayedNotReported.Not included: the TUI portfolio for US accounts, and using
us_available_holdingin the sell flow.Testing
cargo test: all pass. 13 new tests cover routing, no AP call on US, paging, JSON shape and serve errors.cargo clippy: the only new warnings are 5double_must_usefromasync_trait, the same as on every existing trait method.Updated after real-data review
Checked against masked US prod responses. Changes in 93af6fe, with the SDK lock bumped to cab79039 in b56b028:
positions/portfolio: crypto entries get afull_symbol(BTCUSD.BKKT) built from the baresymbolplusmarket, the same way stock entries already have one. The crypto table now shows Qty / Cost / Last / Today P&L, since the SDK now returns them.exchange-rate: a US account gets one row per rate type (am,reference) for the same pair. Arate_typecolumn (spec_key) now tells those rows apart, and--schemaexplainsuniversal_key(account channel, e.g.us_lb_apex) andspec_key(rate type).cash-flow: the transactionsymbolis already user-facing, so thecounter_idconversion was removed.cargo testpasses (915 unit tests, plus the integration tests).🤖 Generated with Claude Code