How to Load Historical Data in freqtrade (and Where to Get It)
freqtrade is one of the most popular open-source crypto trading bot frameworks. Its built-in data downloader is slow, rate-limited, and frequently breaks for assets with long histories. If you have ever tried to download 5 years of 1m BTC data through freqtrade and given up, this article is for you.
How freqtrade Stores Historical Data
user_data/data/binance/BTC_USDT-1m.json
user_data/data/binance/ETH_USDT-1h.json
The JSON format is a list of arrays: [timestamp_ms, open, high, low, close, volume].
Converting External Parquet Data to freqtrade Format
import polars as pl
import json
from pathlib import Path
df = pl.read_parquet("BTC_OHLCV_1h.parquet")
records = df.select([
(pl.col("candle_time").cast(pl.Int64) // 1_000_000).alias("ts"),
"open", "high", "low", "close", "volume"
]).rows()
out = Path("user_data/data/binance/BTC_USDT-1h.json")
out.parent.mkdir(parents=True, exist_ok=True)
out.write_text(json.dumps(records))
print(f"Written {len(records):,} candles")
Verifying the Data in freqtrade
freqtrade list-data --exchange binance --pairs BTC/USDT
Why Funding Rate Data Breaks freqtrade Backtests
A recurring issue (GitHub issues #11680, #12174) is funding rate data stopping updates. If your strategy uses funding rates as a signal, gaps in that data silently corrupt your backtest. Source funding rate data from a complete historical archive rather than live API pulls.
Summary
freqtrade’s built-in downloader is convenient for short histories but painful for multi-year backtests. Converting external Parquet datasets to freqtrade’s JSON format is a one-time script. Once the data is in user_data/data/, freqtrade’s backtesting engine works exactly as expected.