microsoft/qlib · error · ValueError
Get Unexpected arguments {kwargs}
Error message
Get Unexpected arguments {kwargs} What it means
The Exchange constructor accepts only one extra keyword beyond its named parameters: 'trade_unit', which it pops from kwargs. After that pop, any remaining entry in kwargs is a typo'd or unsupported parameter, and the constructor raises ValueError listing the leftovers. This is a fail-fast guard against silently ignored misspelled arguments.
Source
Thrown at qlib/backtest/exchange.py:137
$close is for calculating the total value at end of each day.
Optional fields:
$volume is only necessary when we limit the trade amount or calculate
PA(vwap) indicator
$vwap is only necessary when we use the $vwap price as the deal price
$factor is for rounding to the trading unit
limit_sell will be set to False by default (False indicates we can sell
this target on this day).
limit_buy will be set to False by default (False indicates we can buy
this target on this day).
index: MultipleIndex(instrument, pd.Datetime)
"""
self.freq = freq
self.start_time = start_time
self.end_time = end_time
self.trade_unit = kwargs.pop("trade_unit", C.trade_unit)
if len(kwargs) > 0:
raise ValueError(f"Get Unexpected arguments {kwargs}")
if limit_threshold is None:
limit_threshold = C.limit_threshold
if deal_price is None:
deal_price = C.deal_price
# we have some verbose information here. So logging is enabled
self.logger = get_module_logger("online operator")
# TODO: the quote, trade_dates, codes are not necessary.
# It is just for performance consideration.
self.limit_type = self._get_limit_type(limit_threshold)
if limit_threshold is None:
if C.region in [REG_CN, REG_TW]:
self.logger.warning(f"limit_threshold not set. The stocks hit the limit may be bought/sold")
elif self.limit_type == self.LT_FLT and abs(cast(float, limit_threshold)) > 0.1:
if C.region in [REG_CN, REG_TW]:
self.logger.warning(f"limit_threshold may not be set to a reasonable value")View on GitHub (pinned to 79633dd950)
Solutions
- Inspect the error message: the {kwargs} dict names exactly which keys are unrecognized; fix or remove those keys
- If building Exchange from a config dict, filter keys against the constructor signature (inspect.signature) before the call
- Check the current Exchange.__init__ signature in your installed qlib version for renamed parameters (e.g. trade_unit is the only accepted extra kwarg)
Example fix
# before exch = Exchange(freq='day', trade_units=100) # 'trade_units' -> ValueError # after exch = Exchange(freq='day', trade_unit=100)
Defensive patterns
Strategy: validation
Validate before calling
import inspect
sig = inspect.signature(Exchange.__init__)
allowed = set(sig.parameters) | {'trade_unit'}
unknown = {k for k in cfg if k not in allowed and k != 'self'}
assert not unknown, f"Unknown Exchange kwargs: {unknown}"
exch = Exchange(**cfg) Prevention
- Diff config keys against Exchange.__init__ signature after every qlib upgrade
- Never blind-forward user config dicts into Exchange(**cfg)
When it happens
Trigger: Instantiating Exchange(...) with unknown keywords, e.g. Exchange(volume_threshold=...) when it is a named param misspelled, or passing removed/renamed options like Exchange(trade_units=100) or dealer-style kwargs; also forwarding **config dicts that contain stale keys.
Common situations: Version upgrades where Exchange parameters were renamed or removed; config files (yaml/json) whose keys are dumped into Exchange(**cfg); copy-pasted example code from an older qlib README.
Related errors
- This type of input {rtype} is not supported
- direction {direction} is not supported!
- weight_position is {}, weight_position is not in the range o
- {limit[0]} is not supported
- This type of input is not supported
AI-assisted analysis of microsoft/qlib@79633dd950 (2026-08-15).
Data as JSON: /api/errors/429b44deb73203e9.
Report an issue: GitHub.