{"record":{"id":"cf5ea9148289a03b","repo":"HKUDS/Vibe-Trading","slug":"binance-usd-m-shadow-account-requires-one-way-posi","errorCode":null,"errorMessage":"Binance USD-M Shadow Account requires one-way position mode","messagePattern":"Binance USD-M Shadow Account requires one-way position mode","errorType":"exception","errorClass":"UsdMObservationError","httpStatus":null,"severity":"error","filePath":"agent/src/trading/connectors/binance/usdm.py","lineNumber":292,"sourceCode":"        ),\n        (\n            account[\"margin_balance\"],\n            account[\"wallet_balance\"] + account[\"total_unrealized_pnl\"],\n        ),\n    )\n    if any(not close_enough(reported, derived) for reported, derived in comparisons):\n        raise UsdMObservationError(\"Binance USD-M account totals are incoherent\")\n\n\ndef _mapping_rows(value: Any, name: str) -> list[Mapping[str, Any]]:\n    if not isinstance(value, list) or any(not isinstance(row, Mapping) for row in value):\n        raise UsdMObservationError(f\"Binance USD-M {name} payload is invalid\")\n    return value\n\n\ndef _require_one_way(rows: list[Mapping[str, Any]]) -> None:\n    if any(str(row.get(\"positionSide\") or \"\").upper() != \"BOTH\" for row in rows):\n        raise UsdMObservationError(\"Binance USD-M Shadow Account requires one-way position mode\")\n\n\ndef _active_by_symbol(rows: list[Mapping[str, Any]], source: str) -> dict[str, Mapping[str, Any]]:\n    active: dict[str, Mapping[str, Any]] = {}\n    for row in rows:\n        quantity = _number(row.get(\"positionAmt\"), \"positionAmt\")\n        if quantity == 0:\n            continue\n        symbol = str(row.get(\"symbol\") or \"\").upper()\n        _canonical_symbol(symbol)\n        if symbol in active:\n            raise UsdMObservationError(f\"duplicate {source} position symbol\")\n        active[symbol] = row\n    return active\n\n\ndef _canonical_symbol(symbol: str) -> str:\n    if not symbol.endswith(\"USDT\") or len(symbol) <= 4 or not symbol.isalnum():","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/trading/connectors/binance/usdm.py#L274-L310","documentation":"Raised by _require_one_way when any position row has positionSide != 'BOTH' (case-insensitive). Binance Hedge Mode sets positionSide to LONG or SHORT per side; this connector's Shadow Accounting only supports One-way Mode where a symbol has a single position with positionSide BOTH. The account must be switched to one-way mode on the exchange before the connector can read it.","triggerScenarios":"The Binance futures account has Position Mode set to Hedge Side (dual-side); positionRisk rows then carry positionSide='LONG'/'SHORT' and _join_positions raises on the first such row.","commonSituations":"Account was switched to Hedge Mode manually on the Binance UI or via POST /fapi/v1/positionSide/dual to run another strategy; existing open hedge-mode positions block switching back; CI fixtures written for hedge mode.","solutions":["Close all open positions and open orders, then switch to One-way Mode (Binance UI or POST /fapi/v1/positionSide/dual with dualSidePosition=false)","Remove conflicting strategies/bots that require hedge mode from this account","Update test fixtures so positionSide is 'BOTH' or absent (row.get defaults to '')... ensure it is literally BOTH"],"exampleFix":"# before\n{\"symbol\": \"BTCUSDT\", \"positionAmt\": \"1\", \"positionSide\": \"LONG\"}\n# after\n{\"symbol\": \"BTCUSDT\", \"positionAmt\": \"1\", \"positionSide\": \"BOTH\"}","handlingStrategy":"validation","validationCode":"def is_one_way(position_rows: list[dict]) -> bool:\n    return all(str(r.get(\"positionSide\") or \"\").upper() == \"BOTH\" for r in position_rows)\n\nif not is_one_way(rows):\n    raise RuntimeError(\"account is in hedge mode; switch to one-way\")","typeGuard":null,"tryCatchPattern":"try:\n    obs = connector.read_account_observation(...)\nexcept UsdMObservationError as exc:\n    if \"one-way position mode\" in str(exc):\n        notify_operator(\"switch Binance account to one-way mode and restart\")\n    raise","preventionTips":["Verify dualSidePosition=false via GET /fapi/v1/positionSide/dual before starting","Don't share the API account with hedge-mode bots","Set position mode during account provisioning, not at runtime"],"tags":["binance","usdm","position-mode","hedge-mode","configuration"],"backgroundTag":"exchange-position-mode-conflict","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}