ZhuLinsen/daily_stock_analysis · error · FutuPortfolioError
无法确认证券类型的 Futu 持仓: {codes}
Error message
无法确认证券类型的 Futu 持仓: {codes} What it means
After classification, every position code must have been seen in a get_stock_basicinfo response row (classified_codes). Codes that were sent for classification but never appeared in any response row — neither classified as STOCK, nor as a known non-stock type, nor skipped as unknown — cause this hard failure. The loader treats 'asked but got no answer' as unsafe: it cannot decide whether the position is a analyzable stock, so it refuses rather than guessing.
Source
Thrown at src/brokers/futu/portfolio.py:437
except Exception as exc: # noqa: BLE001 - translate SDK/network errors for CLI callers
raise FutuPortfolioError(f"查询 Futu 持仓证券类型失败: {exc}") from exc
finally:
_safe_close(context)
missing_codes = [
code
for codes in grouped.values()
for code in codes
if code not in classified_codes
]
if unsupported_codes:
logger.warning(
"已跳过 %d 个当前分析流程不支持的 Futu 持仓: %s",
len(unsupported_codes),
", ".join(unsupported_codes),
)
if missing_codes:
raise FutuPortfolioError(
"无法确认证券类型的 Futu 持仓: " + ", ".join(missing_codes)
)
result: List[str] = []
conversion_failures: List[str] = []
for futu_code in position_codes:
if futu_code not in stock_codes:
continue
analysis_code = _to_analysis_code(futu_code)
if not analysis_code:
conversion_failures.append(futu_code)
continue
if analysis_code not in result:
result.append(analysis_code)
if conversion_failures:
raise FutuPortfolioError(
"无法转换已确认的 Futu 正股代码到当前分析格式: "
+ ", ".join(conversion_failures)View on GitHub (pinned to 5159bd72e8)
Solutions
- Read the code list in the message; those symbols were silently dropped by futu's basicinfo API.
- Verify each symbol in Futu OpenD / moomoo — often they are halted, pre-IPO, or non-standard symbols.
- Close or exclude those positions (or that account via FUTU_ACC_ID) if they are not analyzable stocks.
- Report to maintainers if the symbols are ordinary liquid stocks — that indicates a normalization bug between request and response codes.
Defensive patterns
Strategy: try-catch
Try / catch
try:
analysis_codes = classify_futu_positions(position_codes)
except FutuPortfolioError as exc:
if "无法确认证券类型" in str(exc):
unclassified = str(exc).split(":", 1)[1]
logger.warning("futu silently dropped: %s", unclassified)
raise Prevention
- Treat silently-dropped codes as actionable: check halted/pre-IPO symbols in the account
- Exclude unclassifiable accounts via FUTU_ACC_ID when they are not analysis targets
- Report reproducible drops on liquid symbols as a normalization bug
When it happens
Trigger: get_stock_basicinfo silently omitting codes from its response (futu does this for codes it cannot resolve), so the code is not in classified_codes. Duplicates across batches, casing mismatches after .strip().upper() normalization, or codes the API drops without error also trigger it. The full offending list is embedded in the message.
Common situations: Portfolio containing symbols futu cannot classify (new IPOs, halted symbols, market-specific quirks); response row 'code' formatting differing from the request's normalized form.
Related errors
- Futu 非零持仓返回了无效证券代码
- Futu 非零持仓返回了空证券代码
- Futu 非零持仓返回了无效证券代码: {code}
- 查询 Futu 真实持仓失败: {exc}
- 查询 Futu 持仓证券类型失败({prefix}): {data}
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/98f6219c56a20969.
Report an issue: GitHub.