{"record":{"id":"87717f6f2a325f17","repo":"microsoft/qlib","slug":"unexpected-order-direction-direction","errorCode":null,"errorMessage":"Unexpected order direction: {direction}","messagePattern":"Unexpected order direction: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"qlib/rl/order_execution/simulator_simple.py","lineNumber":357,"sourceCode":"        return pd.concat([df, other_df], axis=0)\n\n\ndef price_advantage(\n    exec_price: float_or_ndarray,\n    baseline_price: float,\n    direction: OrderDir | int,\n) -> float_or_ndarray:\n    if baseline_price == 0:  # something is wrong with data. Should be nan here\n        if isinstance(exec_price, float):\n            return 0.0\n        else:\n            return np.zeros_like(exec_price)\n    if direction == OrderDir.BUY:\n        res = (1 - exec_price / baseline_price) * 10000\n    elif direction == OrderDir.SELL:\n        res = (exec_price / baseline_price - 1) * 10000\n    else:\n        raise ValueError(f\"Unexpected order direction: {direction}\")\n    res_wo_nan: np.ndarray = np.nan_to_num(res, nan=0.0)\n    if res_wo_nan.size == 1:\n        return res_wo_nan.item()\n    else:\n        return cast(float_or_ndarray, res_wo_nan)\n","sourceCodeStart":339,"sourceCodeEnd":363,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/rl/order_execution/simulator_simple.py#L339-L363","documentation":"ValueError from `calculate_trade_value`-style PAW/baseline-bps computation in qlib/rl/order_execution/simulator_simple.py:357. The `direction` argument must equal `OrderDir.BUY` or `OrderDir.SELL`; anything else (2, -1, None, a raw string) hits the else branch.","triggerScenarios":"Passing `direction` as an unvalidated int from user code or serialized data (e.g. 2 from a mislabeled dataset), or passing None because an order object's direction field was never set. Note `OrderDir` is an IntEnum, so plain 0/1 also work but 2/-1 fail.","commonSituations":"Loading order lists from CSV/database where direction is stored as arbitrary ints; refactors that pass the whole `Order` object instead of `order.direction`; downstream code assuming SELL=-1.","solutions":["Pass `order.direction` (an `OrderDir` member) rather than a raw int or string.","Sanitize external direction data: map {1,'buy','B'}->OrderDir.BUY, {0/2? no, 2 is invalid}, {0,'sell','S'}->OrderDir.SELL per your data convention, and reject everything else at load time.","If you defined a custom direction enum, convert with `OrderDir(direction)` inside a try/except ValueError to fail with a clear message."],"exampleFix":"// before\nres = calculate_trade_value(price, baseline, row[\"side\"])  # side is 'B'/'S' string\n// after\nfrom qlib.rl.order_execution.simulator_simple import OrderDir  # or qlib.utils.enum\ndir_map = {\"B\": OrderDir.BUY, \"S\": OrderDir.SELL}\nres = calculate_trade_value(price, baseline, dir_map[row[\"side\"]])","handlingStrategy":"type-guard","validationCode":"from qlib.utils.enum import OrderDir  # IntEnum: BUY=0, SELL=1\nassert direction in (OrderDir.BUY, OrderDir.SELL, 0, 1), f\"bad direction {direction!r}\"","typeGuard":"from qlib.utils.enum import OrderDir\n\ndef is_valid_direction(d) -> bool:\n    return d in (OrderDir.BUY, OrderDir.SELL)","tryCatchPattern":"try:\n    value = calculate_trade_value(p, b, direction)\nexcept ValueError as e:\n    if \"Unexpected order direction\" in str(e):\n        raise ValueError(f\"bad direction {direction!r} in trade record\") from e\n    raise","preventionTips":["Convert direction to OrderDir at the data-loading boundary.","Never pass strings or arbitrary ints to trade-value helpers.","Add a schema check on order dataframes (direction values in {0,1})."],"tags":["rl","order-execution","enum","validation"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}