ZhuLinsen/daily_stock_analysis · error · FutuPortfolioError
查询 Futu 真实账户失败: {data}
Error message
查询 Futu 真实账户失败: {data} What it means
FutuPortfolioError raised in _discover_real_accounts (src/brokers/futu/portfolio.py:182) when OpenSecTradeContext.get_acc_list() returns ret != RET_OK. In the Futu SDK convention (ret, data), a non-zero ret means the request failed and 'data' carries the error string; that string is embedded in this exception.
Source
Thrown at src/brokers/futu/portfolio.py:182
def _discover_real_accounts(api: _FutuApi, host: str, port: int) -> List[_FutuAccount]:
"""Discover explicitly ACTIVE NORMAL or MASTER REAL accounts."""
accounts: List[_FutuAccount] = []
seen_ids = set()
requested_acc_id = _configured_account_id()
security_firm = _configured_security_firm(api)
context = None
try:
context = api.OpenSecTradeContext(
host=host,
port=port,
filter_trdmarket=api.TrdMarket.NONE,
security_firm=security_firm,
)
ret, data = context.get_acc_list()
if ret != api.RET_OK:
raise FutuPortfolioError(f"查询 Futu 真实账户失败: {data}")
for row in _iter_rows(data, "Futu 账户查询"):
if _enum_text(row.get("trd_env")) != "REAL":
continue
if _enum_text(row.get("acc_status")) != "ACTIVE":
continue
if _enum_text(row.get("acc_role")) not in _SUPPORTED_ACCOUNT_ROLES:
continue
raw_acc_id = row.get("acc_id")
try:
acc_id = int(raw_acc_id)
exact_integer = isinstance(raw_acc_id, str) or bool(
raw_acc_id == acc_id
)
except (TypeError, ValueError, OverflowError) as exc:
raise FutuPortfolioError(
"Futu 账户查询返回了无效账户 ID"
) from exc
if isinstance(raw_acc_id, bool) or not exact_integer or acc_id <= 0:View on GitHub (pinned to 5159bd72e8)
Solutions
- Confirm OpenD is running and reachable: nc -vz <host> 11111 (or telnet), and check the OpenD UI/log for login state.
- Read the embedded '{data}' text — the SDK's error string usually names the exact cause (connect failure, not logged in, no permission).
- Verify OpenD is logged into the Futu account with trading enabled, and that its version is compatible with futu-api==10.8.6808.
- Match FUTU_SECURITY_FIRM to the actual account or leave it at NONE for auto-detection.
Example fix
# before: assume success
ret, data = ctx.get_acc_list()
# after: fail fast with the SDK's reason surfaced
ret, data = ctx.get_acc_list()
if ret != RET_OK:
raise RuntimeError(f"get_acc_list failed: {data}") Defensive patterns
Strategy: retry
Validate before calling
import socket
def opend_reachable(host: str, port: int, timeout: float = 2.0) -> bool:
try:
with socket.create_connection((host, port), timeout=timeout):
return True
except OSError:
return False Try / catch
from src.brokers.futu.portfolio import FutuPortfolioError
try:
accounts = discover(api, host, port)
except FutuPortfolioError as exc:
if '查询 Futu 真实账户失败' in str(exc):
log.error('OpenD get_acc_list failed: %s', exc)
# inspect message: login/permission vs connectivity before retrying
raise Prevention
- Health-check OpenD connectivity (socket probe on host:port) before broker calls.
- Keep OpenD logged in and trading-enabled; monitor its session state.
- Match OpenD and futu-api versions per Futu's compatibility matrix.
When it happens
Trigger: OpenD gateway not running or unreachable at FUTU_OPEND_HOST:PORT; OpenD logged out of the Futu account; the connected OpenD has no trading (SecTrade) capability enabled; invalid security_firm for the connection; OpenD version too old for the pinned SDK.
Common situations: OpenD not started on the deployment machine; firewall blocking the port in Docker/remote setups; OpenD session expired and needs re-login; FUTU_SECURITY_FIRM mismatched with the actual logged-in broker.
Related errors
- 查询 Futu 真实账户失败: {exc}
- 查询 Futu 真实持仓失败: {data}
- futu-api==10.8.6808 的网络层仅支持 IPv4;FUTU_OPEND_HOST 当前为 {host!r
- 未找到状态为 ACTIVE 的 Futu REAL 普通或 MASTER 证券账户
- 查询 Futu 真实持仓失败: {exc}
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/0aedac9719a432a7.
Report an issue: GitHub.