{"record":{"id":"7b70965d4a1c46d0","repo":"microsoft/qlib","slug":"trade-account-and-position-can-only-choose-one","errorCode":null,"errorMessage":"trade_account and position can only choose one","messagePattern":"trade_account and position can only choose one","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"qlib/backtest/exchange.py","lineNumber":445,"sourceCode":"    ) -> Tuple[float, float, float]:\n        \"\"\"\n        Deal order when the actual transaction\n        the results section in `Order` will be changed.\n        :param order:  Deal the order.\n        :param trade_account: Trade account to be updated after dealing the order.\n        :param position: position to be updated after dealing the order.\n        :param dealt_order_amount: the dealt order amount dict with the format of {stock_id: float}\n        :return: trade_val, trade_cost, trade_price\n        \"\"\"\n        # check order first.\n        if not self.check_order(order):\n            order.deal_amount = 0.0\n            # using np.nan instead of None to make it more convenient to show the value in format string\n            self.logger.debug(f\"Order failed due to trading limitation: {order}\")\n            return 0.0, 0.0, np.nan\n\n        if trade_account is not None and position is not None:\n            raise ValueError(\"trade_account and position can only choose one\")\n\n        # NOTE: order will be changed in this function\n        trade_price, trade_val, trade_cost = self._calc_trade_info_by_order(\n            order,\n            trade_account.current_position if trade_account else position,\n            dealt_order_amount,\n        )\n        if trade_val > 1e-5:\n            # If the order can only be deal 0 value. Nothing to be updated\n            # Otherwise, it will result in\n            # 1) some stock with 0 value in the position\n            # 2) `trade_unit` of trade_cost will be lost in user account\n            if trade_account:\n                trade_account.update_order(order=order, trade_val=trade_val, cost=trade_cost, trade_price=trade_price)\n            elif position:\n                position.update_order(order=order, trade_val=trade_val, cost=trade_cost, trade_price=trade_price)\n\n        return trade_val, trade_cost, trade_price","sourceCodeStart":427,"sourceCodeEnd":463,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/backtest/exchange.py#L427-L463","documentation":"Exchange.deal_order accepts the post-trade position state through exactly one channel: either a trade_account (whose current_position is used) or a bare position object. Supplying both is ambiguous, so it raises ValueError immediately after the order check. The parameters exist to support both account-based and standalone-position workflows, never both at once.","triggerScenarios":"exch.deal_order(order, trade_account=account, position=pos); typical when a caller has an account and also passes the account's position defensively.","commonSituations":"Wrapper code or tutorials that pass every optional argument; refactors where position was kept for compatibility while trade_account was introduced.","solutions":["Pass only trade_account when trading within an account: exch.deal_order(order, trade_account=account)","Or pass only position for standalone simulation: exch.deal_order(order, position=pos)","If unsure, prefer trade_account in normal backtests; use position only for lightweight custom simulations"],"exampleFix":"# before\nval, cost, price = exch.deal_order(order, trade_account=account, position=account.current_position)\n# after\nval, cost, price = exch.deal_order(order, trade_account=account)","handlingStrategy":"validation","validationCode":"assert (trade_account is None) != (position is None), 'pass exactly one of trade_account/position'\nexch.deal_order(order, trade_account=trade_account, position=position)","typeGuard":"def deal_order_args_ok(trade_account, position) -> bool:\n    return (trade_account is None) != (position is None)","tryCatchPattern":null,"preventionTips":["In account-based backtests pass only trade_account","Treat the two parameters as mutually exclusive in wrapper signatures"],"tags":["qlib","exchange","deal-order","mutually-exclusive"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}