Release Notes¶
v1.4.26 · 2026-04-17¶
Broker channel IP pool fix (accounts may have been missing)
Since v1.4.8, broker TCP connections reused Platform IPs and relied on
the server to LOGIN_STATUS_REDIR us to the correct broker—but the
server doesn't always redirect, so some brokers could land on the wrong
server and get_acc_list would return too few or wrong accounts.
v1.4.26 aligns with C++ ChannelAddressManager: broker IP pools come
from commconfig guaranteed_ip_for_conn keyed by broker_id, so CMD
1001 login connects to the right broker directly and the account list
is complete again.
Other changes:
futucli accounttable expands from 3 columns to 8 (Acc ID / Card / Env / Broker / Type / Status / Role / Markets), aligned with the full TrdAcc proto.- 4 new MCP tools:
futu_get_history_kline(rehab control) /owner_plate(plate membership) /reference(related securities) /option_chain(expiry-grouped call/put). - 5 new futucli analysis commands:
capital-flow/capital-distribution/market-state/owner-plate/option-chain. - Trading bot tutorial adds a "5 minutes: zero to first order" starter section.
- Fixed: MCP trade tool
Protobuf decode failure(get_max_trd_qtys/get_history_orders/get_history_deals).
v1.4.25 · 2026-04-17¶
MCP + futucli trade/quote capability catch-up (aligned with official py-futu-api)
Benchmarked against FutunnOpen/py-futu-api (54 user-facing methods), this release adds 8 MCP tools + 6 futucli commands:
- MCP trade extensions:
futu_get_max_trd_qtys/order_fee/margin_ratio/history_orders/history_deals— LLM can now compute max position size / fee estimate / margin ratio / audit past fills before placing orders. - MCP analysis:
futu_get_capital_flow/capital_distribution/market_state— capital flow + market status analysis for LLM. - futucli order-write trio:
place-order/modify-order/cancel-order— shell-scriptable order placement (real env requires--confirm; default env = simulate for safety). - futucli history queries:
history-orders/history-deals/max-qtys— ops reconciliation + pre-order sizing.
Three-surface coverage: MCP 37% → 52%, futucli 26% → 37%,
REST remains at ~74%. Full matrix in
essentials/2026-04-17-1407-api-coverage-matrix.md.
Remaining gaps (option_chain / stock_filter / history_kline /
warrant / ipo_list / etc.) scheduled for v1.4.26.
v1.4.24 · 2026-04-17¶
Broker channel reconnect + runtime dynamic management
- Broker channel auto-reconnect: Platform channels have
reconnect-on-heartbeat-exit since v1.4.12, but per-broker channels
didn't — a broker disconnect left that broker "zombie" until opend
restart. v1.4.24 spawns a
reconnect watcherper broker that, on heartbeat exit, re-logs-in via CMD 1001 using the cachedbroker_client_sig/key(valid ~30 min), skipping HTTP auth. Exponential backoff 3-60s, 6 attempts before giving up (Platform reconnect will rebuild all brokers). - CMD 20177 runtime broker diff: when server pushes "valid broker
list changed," we now actually diff vs current
brokersmap: removed brokers get dropped from the map and TCP closed; added brokers emit WARN (can't auto-build due to one-shot auth_code — Platform reconnect or opend restart required).
Supporting change: new BrokerConnMeta cache stores each broker's
BrokerAuth + last TCP addr (post-redirect) for reconnect reuse.
v1.4.23 · 2026-04-17¶
Broker-change push handlers (aligned with C++ OnRecvBrokerChangePush / OnRecvValidBrokerListChangePush)
- CMD 20177
CidStatusChangePush: when the server pushes "your cid's valid broker list has changed" (triggered when user opens/closes a broker in the app), the client automatically re-fetches CMD 20176 GetValidBrokerList. Logs emit the newbroker_ids. - CMD 9429
BrokerChangePush: the legacy "main broker change" signal. C++ has deprecated the downstream reaction; we mirror the conservative behavior and only log.
Known limitation: receiving 20177 + re-fetching 20176 gets the new list, but we do not rebuild broker channels on the fly (newly-opened brokers won't auto-connect). Opend users rarely open new brokers at runtime; this is deferred until needed.
v1.4.22 · 2026-04-17¶
C++ alignment cleanup: forced_ip / svr_time offset / CMD 20176 / setup-only speedup
forced_ip_for_connsupport: CommConfig's "emergency forced IP" mechanism. Server pushes a single IP with expiry; client bypasses all fallback and uses it directly — meant for gradual rollout or server failover. Aligned with C++ParseForcedIpConfig.- svr_time offset correction: TOTP seed switched from "local time"
to "server time" (offset captured from auth response). CommConfig
requests no longer fail when local clock drifts > 30s; WARN emitted
on skew. Aligned with C++
INNBiz_SvrTime. - CMD 20176
GetValidBrokerListalignment: C++ deprecated the old 9419 main-broker protocol in favor of 20176 as broker validity source of truth. We now send 20176 after Platform login and diff the result against HTTP auth'sauth_code_list, warning on mismatch. --setup-only5-6x speedup: previously ran the entire initialization (~14s) before exiting. v1.4.22 returns immediately after auth succeeds — measured at 2.4s on-device. Much faster for systemd / Docker / cron first-launch setup.
v1.4.21 · 2026-04-17¶
4 login-path bugs caught during v1.4.20 on-device verification
- CMD 1321
conn_identify is invalid— overseas accounts fail to fetch ConnIP list:conn_identityfield was hardcoded to 1 (CN), so HK / US / SG / AU / JP accounts all got rejected. Now derived fromuser_attribution(HK=6 / US=2 / SG=3 / AU=4 / JP=5). - CommConfig
guaranteed_ip_for_connparse failure: v1.4.20 assumed the server always returns a "JSON-in-JSON string" for this field, but the server also returns arrays ornulldirectly for some accounts → parse failed withEOF while parsing. Now handles all three shapes gracefully. - remember-login wrongly fell back to password auth when server
requested SMS: server returning
code=20 require_device_verifyon expired cached credentials is a normal SMS flow, not an error. v1.4.20 treated it as error → fallback to password auth → two rapid authority requests hit server-side rate limit → got misleadingret_type=15. Fixed: remember-login path now also invokes the SMS handler. ret_type=15error hint no longer blames "device_id poisoning" uniformly: 15 has 3 distinct causes (poisoning / rate-limit / account-level state). The hint now walks users through them in order.
v1.4.20 · 2026-04-17¶
CommConfig dynamic IP pool — aligned with C++ FutuOpenD's official channel
- Platform IP pool gains a new top-priority layer: CommConfig. After
successful login, we actively call
/v2/conf/select_allonapi.futunn.com/api.moomoo.comand merge the server-pushed fresh IPs (guaranteed_ip_for_conn) to the front of the pool. This is the same channel C++ FutuOpenD uses — fresher than DNS, more authoritative than hardcoded lists. - Final IP priority chain: CommConfig (server-pushed) → DNS (public domain resolution) → Hardcoded (v1.4.11 baseline). Any layer failing falls back to the next — startup is never blocked.
- Periodic background refresh: opend spawns a background task that
re-fetches CommConfig on the
limit_timecadence returned by the server (clamped to 5 min – 2 h). Long-running instances automatically pick up fresh IPs without a restart; reconnects use the cached snapshot. - TOTP auth_token: 6-digit code generated via Google OTP SHA1 to
authenticate to the Futu API. Algorithm aligned with C++
GenGoogleOTPCode_SHA1and validated against RFC 6238 standard test vectors.
v1.4.19 · 2026-04-17¶
DNS-resolved IP pool + diagnostic messages + security hardening
- Platform IP pool gains DNS resolution: at startup we resolve the
six per-region domains (
hkconn.futunn.com,usconn.moomoo.com, etc.) and put the returned IPs in front of the connection pool. When Futu rotates server IPs, we pick them up automatically. The hardcoded IP list stays as fallback. Platform IP pool exhaustederror now includes firewall diagnosis: when every IP is unreachable, the log tells you "this is almost certainly an outbound firewall issue (port 9595 blocked)" with a reproducer command.- Login password in-memory protection:
AuthConfiggainsZeroizeOnDrop— heap memory is scrubbed on drop, shrinking the exposure window to core-dump / memory-dump attackers. - Dependency audit cleared: removed obsolete crates, upgraded
transitive deps;
cargo auditgoes from "1 CVE + 3 unmaintained warnings" to 0 blocking alerts.
v1.4.18 · 2026-04-17¶
Login password — secure storage
futucli set-login-pwd --account <ID>stores the password once in the OS keychain; subsequentfutu-opendlaunches no longer need--login-pwd. Nothing leaks tops aux, shell history, or config-file backups.- New
--login-pwd-file <path>— Docker secrets / systemdLoadCredentialfriendly. - Legacy
--login-pwdstill works but now prints a WARN prompting you to migrate.
v1.4.17 · 2026-04-17¶
device_id lifecycle overhaul + staged production deployment
~/.futu-opend-rs/now holds all credentials, so launching from different working directories no longer triggers repeated SMS verification.- New
--setup-only: run once in the foreground to complete SMS verification; subsequent systemd / Docker launches skip SMS. - New
--reset-device: one-shot cleanup when the server has locked your device_id. - Wrong SMS code → automatically rotate device_id and retry (up to 2 times). No more "one typo and you're stuck forever".
v1.4.11–v1.4.16 · 2026-04-17 (login-stability sprint)¶
8 releases in one day fixing the login pipeline. User-visible changes:
- Overseas accounts no longer hit CN IPs: IP pool now picked per account attribution (CN / HK / US / SG / AU / JP).
- Faster cold-start: 3 IPs are tried in parallel — the first one that handshakes wins. First-screen latency drops from "10-second timeout on the slow IP" to "~200ms RTT of the fastest IP".
- New
--platform <futunn|moomoo>: when the same phone number has independent accounts on both platforms, this flag disambiguates. - moomoo account login fixed: previously
--platform moomoo+ a phone number returned "account/password mismatch" (actually an internal header issue); fixed in v1.4.15. - Empty SMS code guard: background-mode runs used to read empty from stdin → submit empty code → device_id permanently locked. Now blocked.
- Multi-instance port conflict detection: running a futunn + moomoo instance side by side now warns about port collisions.
v1.4.10 · 2026-04-16¶
- Gateway connect timeout tightened from Linux's 127-second default to 10 seconds — fail fast.
- Auto-fallback to other IPs in the same pool when one is unreachable.
v1.4.8–v1.4.9 · 2026-04-16¶
Broker channel shipped
- Account list, positions, and orders now flow through a dedicated broker channel, matching the official Futu OpenD architecture.
- Supports 7 brokers: Futu HK / US / SG / AU / JP / MY / CA.
Earlier versions¶
v1.0–v1.4.7 changes were mostly internal refactors and protocol alignment with no impact on user-facing call conventions. If you are upgrading from an older version:
- Run
futu-opend --setup-onlyonce to initialize the v1.4.17+ credentials layout. - Consider migrating scripts from
--login-pwdtofutucli set-login-pwd(v1.4.18). - All other CLI flags remain compatible — no changes needed.
Feedback¶
Bug reports / feature requests: Contact