{"record":{"id":"af32b7b619e382a6","repo":"ZhuLinsen/daily_stock_analysis","slug":"futu-acc-id-id-opend","errorCode":null,"errorMessage":"FUTU_ACC_ID 未匹配到可用的真实证券账户；请检查账户 ID、券商和 OpenD 登录状态。","messagePattern":"FUTU_ACC_ID 未匹配到可用的真实证券账户；请检查账户 ID、券商和 OpenD 登录状态。","errorType":"exception","errorClass":"FutuPortfolioError","httpStatus":null,"severity":"error","filePath":"src/brokers/futu/portfolio.py","lineNumber":222,"sourceCode":"            returned_firm_name = _enum_text(row.get(\"security_firm\"))\n            returned_firm = getattr(\n                api.SecurityFirm,\n                returned_firm_name,\n                security_firm,\n            )\n            seen_ids.add(acc_id)\n            accounts.append(_FutuAccount(acc_id=acc_id, security_firm=returned_firm))\n    except FutuPortfolioError:\n        raise\n    except Exception as exc:  # noqa: BLE001 - translate SDK/network failures\n        raise FutuPortfolioError(f\"查询 Futu 真实账户失败: {exc}\") from exc\n    finally:\n        _safe_close(context)\n\n    if requested_acc_id is not None:\n        accounts = [account for account in accounts if account.acc_id == requested_acc_id]\n        if not accounts:\n            raise FutuPortfolioError(\n                \"FUTU_ACC_ID 未匹配到可用的真实证券账户；请检查账户 ID、券商和 OpenD 登录状态。\"\n            )\n\n    if not accounts:\n        raise FutuPortfolioError(\n            \"未找到状态为 ACTIVE 的 Futu REAL 普通或 MASTER 证券账户\"\n        )\n    return accounts\n\n\ndef _load_position_codes(\n    api: _FutuApi,\n    host: str,\n    port: int,\n    accounts: Iterable[_FutuAccount],\n) -> List[str]:\n    \"\"\"Load deduplicated non-zero LONG position codes from selected accounts.\"\"\"\n","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/ZhuLinsen/daily_stock_analysis/blob/5159bd72e8373d215492dff122acc9d389e219c9/src/brokers/futu/portfolio.py#L204-L240","documentation":"FutuPortfolioError raised in _discover_real_accounts (src/brokers/futu/portfolio.py:222) when FUTU_ACC_ID is configured but, after filtering discovered ACTIVE REAL accounts, none matches the configured ID. Discovery succeeded — the account list simply does not contain that ID (wrong ID, different broker firm, or the account is not in ACTIVE REAL state in OpenD).","triggerScenarios":"FUTU_ACC_ID points to a SIMULATE account (filtered out because trd_env != REAL); the ID belongs to a different security firm than the one OpenD logged into; typo in the ID; the account exists but its acc_status is not ACTIVE; paper-trading IDs used against a real-account filter.","commonSituations":"Users copying the account number from Futu moomoo app (display number) instead of the OpenD acc_id; accounts under a second broker not logged into OpenD; account frozen/pending so status != ACTIVE.","solutions":["Unset FUTU_ACC_ID temporarily and let discovery log the available ACTIVE REAL accounts; copy the exact acc_id from that list.","Confirm OpenD is logged into the broker that owns the account and the account status is ACTIVE in OpenD's UI.","If you intended paper trading, note this source only supports REAL environments — SIMULATE accounts are filtered by design.","Fix typos: the ID must be the plain positive integer acc_id."],"exampleFix":"# before (.env)\nFUTU_ACC_ID=3865276   # app display number\n\n# after — discover first, then pin\n# 1) comment out FUTU_ACC_ID, run once, read logged acc_id values\n# 2) FUTU_ACC_ID=<exact acc_id from get_acc_list>","handlingStrategy":"validation","validationCode":"def acc_id_exists(acc_id: int, discovered) -> bool:\n    return any(a.acc_id == acc_id for a in discovered)","typeGuard":null,"tryCatchPattern":"from src.brokers.futu.portfolio import FutuPortfolioError\ntry:\n    accounts = discover(api, host, port, requested_acc_id=acc_id)\nexcept FutuPortfolioError as exc:\n    if '未匹配到可用的真实证券账户' in str(exc):\n        all_accounts = discover(api, host, port)  # unset filter, inspect ids\n        log.error('configured %s; available: %s', acc_id, [a.acc_id for a in all_accounts])\n    raise","preventionTips":["Run discovery once without FUTU_ACC_ID to learn valid IDs, then pin.","Use the OpenD acc_id, not the app's display account number.","Remember this source filters to ACTIVE REAL NORMAL/MASTER accounts only."],"tags":["futu","configuration","account-matching"],"backgroundTag":null,"analyzedSha":"5159bd72e8373d215492dff122acc9d389e219c9","analyzedAt":"2026-08-15T01:59:36.292Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}