ZhuLinsen/daily_stock_analysis · error · FutuPortfolioError
查询 Futu 持仓证券类型失败({prefix}): {data}
Error message
查询 Futu 持仓证券类型失败({prefix}): {data} What it means
Raised during the security-type classification step: after grouping position codes by market prefix, the loader batches codes (in _STATIC_INFO_BATCH_SIZE chunks) into context.get_stock_basicinfo(market, stock_type=STOCK, code_list=batch). If the futu API returns ret != RET_OK (the SDK's non-exception failure mode), the error is raised with the market prefix and the raw data payload futu returned (usually an error string).
Source
Thrown at src/brokers/futu/portfolio.py:404
stock_codes = set()
classified_codes = set()
context = None
try:
context = api.OpenQuoteContext(host=host, port=port)
for prefix, codes in grouped.items():
market = getattr(api.Market, prefix, None)
if market is None:
unsupported_codes.extend(codes)
continue
for start in range(0, len(codes), _STATIC_INFO_BATCH_SIZE):
batch = codes[start : start + _STATIC_INFO_BATCH_SIZE]
ret, data = context.get_stock_basicinfo(
market,
stock_type=api.SecurityType.STOCK,
code_list=batch,
)
if ret != api.RET_OK:
raise FutuPortfolioError(
f"查询 Futu 持仓证券类型失败({prefix}): {data}"
)
for row in _iter_rows(data, "Futu 证券类型查询"):
code = str(row.get("code", "") or "").strip().upper()
if not code:
continue
stock_type = _enum_text(row.get("stock_type"))
if stock_type in _UNKNOWN_SECURITY_TYPES:
continue
classified_codes.add(code)
if stock_type == "STOCK":
stock_codes.add(code)
except FutuPortfolioError:
raise
except Exception as exc: # noqa: BLE001 - translate SDK/network errors for CLI callers
raise FutuPortfolioError(f"查询 Futu 持仓证券类型失败: {exc}") from exc
finally:
_safe_close(context)View on GitHub (pinned to 5159bd72e8)
Solutions
- Inspect the {data} payload — it contains futu's own error string which pinpoints the cause (invalid code, frequency limit, permission).
- If a specific code is rejected, exclude that position/account or handle it as unsupported instead of STOCK.
- Check market permissions for the account in Futu OpenD (e.g. US market data/quote rights).
- Restart/re-auth FutuOpenD and retry; if persistent, reduce portfolio size to isolate the failing batch.
Defensive patterns
Strategy: try-catch
Try / catch
try:
stock_codes = classify_futu_positions(position_codes)
except FutuPortfolioError as exc:
logger.error("basicinfo failed: %s", exc) # message embeds prefix + futu error text
raise Prevention
- Verify market permissions for all markets held in the account
- Keep portfolios/batches within futu code_list limits
- Read the embedded {data} payload — it is futu's own error string and names the root cause
When it happens
Trigger: get_stock_basicinfo returning RET_ERROR for a batch, e.g. too many codes requested, an invalid code slipped into code_list, market temporarily unavailable, rate limiting, or OpenD protocol errors. The message embeds which prefix (SH/HK/US...) failed and futu's own error text in data.
Common situations: Large portfolios where a batch hits futu's code_list limits; one malformed code poisoning the whole batch; FutuOpenD not subscribed/logged in for that market; API quota exceeded.
Related errors
- Futu 非零持仓返回了无效证券代码
- Futu 非零持仓返回了空证券代码
- Futu 非零持仓返回了无效证券代码: {code}
- 查询 Futu 真实持仓失败: {exc}
- 查询 Futu 持仓证券类型失败: {exc}
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/f4abcfe21adba926.
Report an issue: GitHub.