Download free forex tick data for backtesting
Download free historical forex tick data and 1-minute candles as CSV for backtesting, for EUR/USD, gold and hundreds of other currency pairs.
Backtesting a forex strategy needs clean historical data: every tick with its bid and ask price, or candles at the timeframe your strategy trades on. dukascopy-node downloads both for free, as CSV files you can load into Python, R, Excel or your own backtester. This guide builds a typical dataset for EUR/USD.
1. Choose a currency pair
Section titled “1. Choose a currency pair”Every pair has an id that you pass with -i in the CLI or instrument in Node.js: eurusd, gbpusd, usdjpy, or xauusd for gold. Browse the forex majors, crosses and metals. Each instrument page shows how far back its data goes for every timeframe.
2. Download tick data
Section titled “2. Download tick data”Ticks are every price change, with the best bid and ask price at that moment. They are the most detailed data you can backtest on, and the right choice when spreads or execution timing matter:
npx dukascopy-node -i eurusd -from 2020-03-30 -to 2020-03-31 -t tick -f csv -vimport { getHistoricalRates } from 'dukascopy-node';
const ticks = await getHistoricalRates({ instrument: 'eurusd', dates: { from: '2020-03-30', to: '2020-03-31' }, timeframe: 'tick', format: 'csv'});The CLI saves the result to download/eurusd-tick-2020-03-30-2020-03-31.csv:
timestamp,askPrice,bidPrice,askVolume,bidVolume1585526400104,1.11369,1.11361,0.75,0.751585526400256,1.11371,1.11361,0.94,1.5Timestamps are Unix milliseconds in UTC, and volumes are in millions of units.
Tip
Tick data is large: a month of one pair can take hundreds of megabytes. Start with a day, check the output, then extend the range. See large downloads.
3. Or download 1-minute candles
Section titled “3. Or download 1-minute candles”Many strategies trade on bars rather than ticks, and candles are much smaller. Pick the timeframe your strategy uses: s1 (one second), m1, m5, m15, m30, h1, h4, d1 or mn1. A year of 1-minute EUR/USD candles:
npx dukascopy-node -i eurusd -from 2023-01-01 -to 2024-01-01 -t m1 -f csv -vconst candles = await getHistoricalRates({ instrument: 'eurusd', dates: { from: '2023-01-01', to: '2024-01-01' }, timeframe: 'm1', format: 'csv'});The file, download/eurusd-m1-bid-2023-01-01-2024-01-01.csv, starts with the header timestamp,open,high,low,close,volume. Candles use bid prices by default. Add -p ask (priceType: 'ask' in Node.js) for ask candles, or download both if your backtest models the spread.
4. Load the data into your backtest
Section titled “4. Load the data into your backtest”The CSV works with any tool. In Python with pandas:
import pandas as pd
df = pd.read_csv('download/eurusd-m1-bid-2023-01-01-2024-01-01.csv')df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms', utc=True)df = df.set_index('timestamp')For a spreadsheet, write readable dates instead of Unix timestamps with --date-format "YYYY-MM-DD HH:mm:ss", and convert them to your time zone with --time-zone. See date formats and time zones.
In Node.js you can skip the file: use format: 'array' or format: 'json' and pass the data straight to your backtesting code. See output formats.
Check the data before you trust a backtest
Section titled “Check the data before you trust a backtest”- Weekends have no data. The forex market closes from Friday evening to Sunday evening (UTC), so there are no ticks or candles for those hours, and holidays can be quiet too. That is expected, not a gap to fill.
- Each pair starts at a different date, and finer timeframes often start later than daily candles. Check the instrument page before choosing a start date. A range that starts earlier begins at the first available data.
- Bid and ask differ. Ticks include both prices. For candles, choose
bidorask, or download both to model the spread. - Timestamps are UTC unless you convert them, which matters for strategies built around trading sessions.
- Make long downloads resilient. Add
--retries 3to retry failed requests, and--cacheso that extending the range later does not download the same data again. See errors and empty data and using the cache.