ZhuLinsen/daily_stock_analysis · error · FutuPortfolioError

无法转换已确认的 Futu 正股代码到当前分析格式: {codes}

Error message

无法转换已确认的 Futu 正股代码到当前分析格式: {codes}

What it means

Final conversion step failure: a position code was confirmed as SecurityType.STOCK by futu, but the local mapping _to_analysis_code(futu_code) returned falsy — the loader knows no analysis-format equivalent (e.g. the analysis system's market prefix convention) for that confirmed stock code. Failing loudly here guarantees the analysis universe matches the real portfolio instead of silently omitting real holdings.

Source

Thrown at src/brokers/futu/portfolio.py:453

        )
    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)
        )
    return result


def load_futu_stock_codes() -> List[str]:
    """Return deduplicated analysis codes from all selected REAL Futu accounts.

    Only explicitly ACTIVE REAL accounts and Futu ``SecurityType.STOCK`` LONG
    positions with non-zero quantity are kept. ``FUTU_ACC_ID`` can select one
    account; otherwise NORMAL and MASTER accounts are merged. ``MASTER`` is an
    account role, while read-only describes this integration's query-only API
    calls. Firm discovery uses the SDK's ``SecurityFirm.NONE`` auto-detection
    unless ``FUTU_SECURITY_FIRM`` is explicitly set. Position data is always
    refreshed. Symbol conversion is limited to A/HK/US stocks; holdings from
    other Futu markets are logged with their codes and skipped.
    """

View on GitHub (pinned to 5159bd72e8)

Solutions

  1. Check the listed codes' market prefix; unsupported markets need either an exclusion rule or a mapping added to _to_analysis_code in src/brokers/futu/portfolio.py.
  2. If the market is genuinely out of scope for the analysis flow, exclude those positions/account rather than extending the mapping ad hoc.
  3. Add a regression test with the failing futu code once mapped.
Defensive patterns

Strategy: try-catch

Try / catch

try:
    result = classify_futu_positions(position_codes)
except FutuPortfolioError as exc:
    logger.error("unmapped futu stock codes: %s", exc)
    raise

Prevention

When it happens

Trigger: A futu market prefix/symbol combo that _to_analysis_code has no mapping rule for, e.g. a market the analysis system doesn't support (some A-share/futures/UK codes) but which futu classifies as STOCK. The failing futu codes are listed in the message.

Common situations: Account holding stocks on markets added by futu but not yet mapped in the analyzer (e.g. SG, JP, AU exchanges); new futu code formats after SDK upgrades.

Related errors


AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15). Data as JSON: /api/errors/dee50811b18e0e44. Report an issue: GitHub.