Qlib's US Region Does Not Make Commission Per Share
An open Qlib question asks how to model US trading costs when the commission is charged per share. The example already sets trade_unit to one and passes a small number as open_cost. Those settings look close to a per-share fee, but they describe two different things.
The useful first check is the unit of each input. trade_unit controls the permitted order increment. open_cost and close_cost are rates applied to trade value. Changing the region can set US defaults, but it cannot change that fee equation.
Trace the actual fee path
The Qlib region configuration sets the US trade unit to one and removes the China A-share price-limit threshold. So initialize the provider with the US region:
from qlib.constant import REG_US
qlib.init(provider_uri="path/to/us_data", region=REG_US)
Then inspect the Exchange implementation. The relevant path is short:
trade_val = order.deal_amount * trade_price
trade_cost = max(trade_val * cost_ratio, self.min_cost)
For a buy, cost_ratio includes open_cost; for a sell it includes close_cost. The fee therefore changes with the trade price when the share count stays fixed. A true per-share commission would stay the same in that comparison, until a minimum fee takes over. Setting trade_unit=1 does not alter this calculation.
A four-case fixture before changing code
This is the test matrix I would freeze for a custom fee rule. It specifies relationships, not a claimed result from a run.
| Case | Input held fixed | Change | Expected distinction |
|---|---|---|---|
| Same shares | Share count | Use two different trade prices | A per-share fee stays equal; a value-rate fee changes. |
| Same trade value | Total notional | Use different share counts | A value-rate fee stays equal; a per-share fee changes. |
| Minimum floor | Share count and price | Choose an order below the declared minimum | The configured minimum wins under either model. |
| Cash boundary | Available cash and target order | Put cash just inside and outside the fee-inclusive limit | Fill quantity and charged fee follow one consistent rule. |
The last case matters because the Exchange uses the fee when it clips a buy to available cash. Replacing only the final reported trade_cost would make the report look right while the simulated fill quantity still follows the old rate-based calculation. A custom exchange needs one fee policy for both cash admission and the resulting trade record.
What this check proves
It answers the configuration question in the issue: region=REG_US selects US defaults, while the built-in open_cost and close_cost remain percentages of trade value with a minimum. The four cases above are proposed acceptance tests for a per-share extension. I reviewed the current source path; I have not run a custom Exchange or measured a strategy result here. Broker-specific schedules, taxes, rebates and partial fills need their own explicit rules before a backtest can claim to represent them.
