| name | longbridge-statement-tax |
| description | Use when computing realized P&L, dividends, interest, or tax due from a Longbridge (長橋證券) account — for individual income tax on foreign income (个税 境外所得), CRS reporting, accounting, or broker P&L reconciliation. Pulls the official monthly statements via the Longbridge CLI and reconstructs the figures the statement does not provide. Companion to the Futu statement skill. |
Longbridge Statement Tax
Overview
Longbridge (長橋證券) has an official command-line tool (longbridge, see
https://open.longbridge.com/zh-CN/docs/cli/). This skill calls longbridge statement to
fetch the monthly statements as JSON and turns them into tax-ready CSVs.
Like most brokers, Longbridge statements have no "已实现盈亏" (realized P&L) section,
so realized P&L is reconstructed here (average-cost) from stock_trades, seeded with
the prior-December closing holdings (equity_holdings.cost_price) so positions carried
into the year are costed correctly. Cash dividends live in corps (corporate actions);
financing interest is in interests — a cost you paid, not income.
This is the companion to futu-statement-skill (the other broker). Combine the two
brokers' 已实现盈亏 for the final 财产转让所得 (capital-gains) tax.
When to Use
- Computing 个税 境外所得: realized capital gains + dividends, kept separate
- CRS / annual account reconciliation
- "How much did I make/lose on Longbridge last year, and how much was dividends?"
Prerequisite: the official Longbridge CLI
This skill shells out to longbridge — it never handles your credentials. If the CLI
is missing, the script offers to install it for you (asks for confirmation first), then
offers to run longbridge auth login — both steps require your y/N confirmation, and it
falls back to printing manual steps if you decline or run non-interactively. Manual setup:
brew install --cask longbridge/tap/longbridge-terminal
curl -sSL https://open.longbridge.com/longbridge/longbridge-terminal/install | sh
scoop install https://open.longbridge.com/longbridge/longbridge-terminal/longbridge.json
longbridge auth login
longbridge statement --type monthly --format json
If a CLI call fails with an auth error, the script tells you to run longbridge auth login.
Docs: https://open.longbridge.com/zh-CN/docs/cli/ . Python 3.10+. (Note: this uses the CLI,
not the Longbridge MCP.)
Quick Start
python3 longbridge_tax.py --year 2025
Output lands in out/<year>/ by default (e.g. out/2025/); -o DIR overrides the base and
the year is always auto-nested under it. The Longbridge account number is not retrievable
from the API or the statements — it is known only at CLI login time (the assets/portfolio
commands don't carry it, and bank-cards shows your external bank accounts, not the brokerage
account). So the script does not label output by account, and you must never guess one — a
wrong guess (e.g. from memory) silently mislabels someone's tax data. The CLI has no account
selector either: it uses whichever account the token is bound to, so just make sure the CLI is
logged into the account you mean. Only if you genuinely run multiple accounts do you need
to separate them — then pass a distinct -o per account yourself (e.g. -o out_acctA) and
switch CLI logins between runs.
--rate (optional) is the HKD→RMB year-end 中间价 shorthand. For multi-currency statements,
pass one --fx-rate CCY=RATE per currency, e.g. --fx-rate HKD=0.90322 --fx-rate USD=7.10.
Amounts are grouped by currency first; RMB/tax columns are filled only when that currency
has a matching rate.
For --year 2025, if no rate is passed, the script uses the 2025-12-31 PBOC/CFETS central
parity defaults: HKD=0.90322, USD=7.0288. Explicit --rate / --fx-rate values override
the built-in defaults.
--on-negative-position {flag,exclude,short} controls how negative/short positions are
handled (default flag) — see Negative positions below; treat a flag run that reports
negative positions as needing user confirmation, not a final answer.
| Output (utf-8-sig) | Contents |
|---|
longbridge_<YEAR>_成交明细.csv | stock / option / fund trades; 清算金额 already net of fees |
longbridge_<YEAR>_股息利息现金流.csv | dividends (corps), financing interest, withdrawals |
longbridge_<YEAR>_已实现盈亏_按标的.csv | realized P&L per instrument (average-cost) |
longbridge_<YEAR>_账户净值.csv | per-month asset total (cross-check) |
longbridge_<YEAR>_税务汇总.csv | tax summary by currency: gains / dividends / interest + tax due |
The script prints realized total, dividends and interest so you can sanity-check.
Negative positions — STOP and confirm with the user
A Longbridge cash account cannot really short, so when the reconstruction drives an
instrument to a negative position, it almost always means missing cost basis, not a
genuine short — e.g. shares transferred in (转入), a sell recorded before its buy, or the
prior-December cost_price was N/A and got skipped. By default the script computes it as a
symmetric short, includes it in the totals, and warns.
When you (Claude) run the script and see NEGATIVE_POSITION on stderr (or a ⚠ 负持仓
note in 已实现盈亏_按标的.csv), do NOT silently accept the default number. Surface it and
let the user choose the口径 before reporting any tax figure:
- 补成本基础重跑(最准 / recommended) — the instrument is real but its opening cost is
missing. Find the correct carried-in cost (prior-year purchase price / transfer-in cost)
and re-run so the basis is seeded correctly. This is the only option that yields a correct
realized number.
- 先排除待核对 — re-run with
--on-negative-position=exclude; the flagged instrument is
dropped from the totals and 税务汇总 so a data gap doesn't pollute the tax figure, and it's
listed separately for manual handling.
- 确认是做空 — only if the user confirms it is a genuine short, re-run with
--on-negative-position=short to include it without the warning.
Explain which instruments are affected and roughly how much they move the total, then re-run
with the chosen flag (and corrected opening data for option 1). Never report a tax number from
a flag run that still has unresolved negative positions without telling the user.
How it works
longbridge statement --type monthly --start-date <YEAR-1>-12-01 --limit 14 → file keys
for the 12 months plus the prior December (for opening cost basis).
longbridge statement export --file-key <k> → each month's full JSON.
- Reconstruct realized P&L (average-cost, long + short) from
stock_trades, seeded from the
prior-Dec equity_holdings and from IPO allotments (account_balance_changes lines with
biz_code LIPOALDR — 打新中签 shares arrive here with their cost, not as a stock_trades buy).
Within a trade date, buys are processed before sells (statements carry no intraday time), so a
same-day round-trip isn't mistaken for a short. Realized accrues only when a trade reduces the
open position, so positions still open at year-end (long or short) contribute 0. A genuinely
negative position is flagged (a cash account can't really short — usually missing cost basis)
instead of booking the whole sale as profit. Dividends from corps; interest from interests.
Statement sections used
| Section | Holds | Use for |
|---|
stock_trades | each trade (clear_amount = net of fees, signed) | realized P&L, fees |
equity_holdings | per-holding cost_price, quantities (incl. prior-Dec) | opening cost basis |
corps | corporate actions / cash dividends | dividend income |
interests | monthly financing interest (total negative = paid) | interest cost |
account_balance_changes | cash movements (withdrawals, etc.) + IPO allotment debits (biz_code LIPOALDR) | cash-flow view; IPO 打新 cost basis |
asset | month-end asset total | NAV cross-check |
fund_trades | money-market fund subscribe/redeem | shown; excluded from realized |
Critical Gotchas
- No realized-P&L section — reconstruct from
stock_trades (average-cost). Seed the
opening basis from the prior-December statement, or gains on positions bought last
year are overstated.
clear_amount is already net of fees (signed: BUY < 0, SELL > 0). Per-trade fee =
|clear_amount| − trade_amount.
- Dividends are in
corps, not a "dividend" line. (In some years corps is empty —
then there were no cash dividends.)
interests is a cost you paid (financing/margin interest), not income.
- Money-market funds (
fund_trades) are accumulating cash-management vehicles; they
appear in 成交明细 but are excluded from the realized-P&L headline (gain is small and
the statement gives no fund cost basis). Note it if material.
- Capital-gains tax must be combined across accounts. This skill is Longbridge-only;
its 税务汇总 shows the standalone figure. Net it against your other brokers (e.g. Futu)
within
财产转让所得 before computing the final capital-gains tax.
- Currencies are not interchangeable. Keep USD/HKD/etc. in separate buckets for
average cost, realized P&L, dividends, interest, and RMB conversion. Use
--fx-rate
for every currency that needs tax/RMB output. Note that cash-dividend lines (in corps
or as dividend-flagged account_balance_changes) often arrive with a blank currency
field, carrying the market only in the remark/symbol (e.g. Cash Dividend 700.HK); the
script recovers it via settle_ccy() (@CCY tag or CODE.MARKET suffix) so the dividend
is still taxed under HKD/USD rather than dropping into an unknown-currency bucket.
- Default FX rates are year-scoped. 2025 has built-in PBOC/CFETS 2025-12-31 defaults
for HKD and USD. Other years need explicit rates until their defaults are added.
- IPO-allotted shares (打新中签) have no buy in
stock_trades. Their cost basis is the
IPO Allotted Amount(Dr) line in account_balance_changes (biz_code LIPOALDR); the script
seeds it automatically. Without it, selling allotted shares would look like a zero-cost short
and massively overstate the gain (it once flipped a real +HKD 10k profit into a fake loss).
Tax note (个税 境外所得)
Convert each currency to RMB at the year-end 人民币汇率中间价 (--rate for HKD, repeated
--fx-rate CCY=RATE for other currencies). 财产转让所得 (capital gains,
20%) nets gains/losses within the same market across accounts; 利息股息红利所得
(dividends, flat 20%) is taxed standalone with no deductions. Confirm netting scope,
foreign-tax credit, fund-income classification, and FX 口径 with a tax advisor.