freqtrade/freqtrade · error · OperationalException
No exchange object found.
Error message
No exchange object found.
What it means
download_all_data_for_training() must enumerate tradable markets via the exchange object attached to DataProvider. dp._exchange is None when the DataProvider was created without a live exchange connection (e.g. pure backtest context), and the helper raises OperationalException because pair discovery is impossible.
Source
Thrown at freqtrade/freqai/utils.py:34
from freqtrade.freqai.data_drawer import FreqaiDataDrawer
from freqtrade.freqai.data_kitchen import FreqaiDataKitchen
from freqtrade.plugins.pairlist.pairlist_helpers import dynamic_expand_pairlist
logger = logging.getLogger(__name__)
def download_all_data_for_training(dp: DataProvider, config: Config) -> None:
"""
Called only once upon start of bot to download the necessary data for
populating indicators and training the model.
:param timerange: TimeRange = The full data timerange for populating the indicators
and training the model.
:param dp: DataProvider instance attached to the strategy
"""
if dp._exchange is None:
raise OperationalException("No exchange object found.")
markets = [
p
for p in dp._exchange.get_markets(
tradable_only=True, active_only=not config.get("include_inactive")
).keys()
]
all_pairs = dynamic_expand_pairlist(config, markets)
timerange = get_required_data_timerange(config)
new_pairs_days = int((timerange.stopts - timerange.startts) / 86400)
refresh_backtest_ohlcv_data(
dp._exchange,
pairs=all_pairs,
timeframes=config["freqai"]["feature_parameters"].get("include_timeframes"),
datadir=config["datadir"],View on GitHub (pinned to 1c8edfe4d1)
Solutions
- Ensure the config contains a valid 'exchange' section (name, pair_whitelist, etc.) — copy from config_examples and pass it with -c
- Run the official entry point: freqtrade download-data --freqaimodel <model> --config <config with freqai + exchange>
- When calling programmatically, construct DataProvider with a real Exchange instance (dp = DataProvider(config, exchange)) before calling the helper
Example fix
# before (script) dp = DataProvider(config, None) # no exchange download_all_data_for_training(dp, config) # after exchange = ExchangeResolver.load_exchange(config, validate=True) dp = DataProvider(config, exchange) download_all_data_for_training(dp, config)
Defensive patterns
Strategy: validation
Validate before calling
# Programmatic guard before downloading freqAI training data
assert dp._exchange is not None, (
'DataProvider has no exchange - load one via ExchangeResolver first') Type guard
def dataprovider_has_exchange(dp) -> bool:
return getattr(dp, '_exchange', None) is not None Prevention
- Always include a valid 'exchange' block in configs used for freqAI data downloads
- Construct DataProvider(config, exchange) with a real Exchange in scripts
When it happens
Trigger: Calling freqtrade freqai commands that lead to download_all_data_for_training() (e.g. download-data with --freqaimodel, or start-up data preparation) with a config whose exchange section is missing or not instantiated; or invoking the utility programmatically with a DataProvider built with exchange=None.
Common situations: Config lacks the 'exchange' block or has an empty name; running data download utilities from a script with a DataProvider meant for backtesting; exchange initialization failed earlier and the error surfaces here first.
Related errors
- Using analyze-per-epoch parameter is not supported with a Fr
- Main timeframe of {main_tf} must be smaller or equal to Freq
- Using timerange parameter is not supported with --freqai-bac
- Using --freqai-backtest-live-models parameter is only suppor
- Please pass --timerange if you intend to use FreqAI for back
AI-assisted analysis of freqtrade/freqtrade@1c8edfe4d1 (2026-08-15).
Data as JSON: /api/errors/95445e755950c7ca.
Report an issue: GitHub.