Dukascopy tick downloader and candle/tick exporter for backtesting workflows.
Project description
tradedesk-dukascopy
Dukascopy tick downloader and candle exporter for use in backtesting your trading strategies.
This tool downloads raw tick data from Dukascopy, converts it into clean, deterministic CSV candle files, and writes a metadata sidecar describing exactly how the data was produced.
It is designed to be run once per dataset, not repeatedly during backtests.
Quick start
Install:
pip install tradedesk-dukascopy
Export 5-minute candles for EURUSD:
tradedesk-dc-export --symbol EURUSD \
--from 2025-01-01 --to 2025-01-31 \
--out data \
--cache-dir /paperclip/tradedesk/marketdata \
--price-divisor 1000 \
--workers 1
This produces:
data/
EURUSD_5MIN.csv
EURUSD_5MIN.csv.meta.json
You can now point your backtest engine at the CSV file directly.
Price scaling (--price-divisor)
Dukascopy tick prices are stored as integers or scaled values depending on the instrument.
This tool applies price scaling once, at export time, using --price-divisor.
Examples:
| Instrument | Typical divisor |
|---|---|
| EURUSD | 1000 |
| USDJPY | 100000 |
| Indices | 1 or 10 |
If unsure, use probe mode:
tradedesk-dc-export --symbol GBPSEK \
--from 2025-07-01 --to 2025-07-01 \
--probe
Probe mode prints sample ticks at different divisors without writing files.
GBPSEK: detected tick price format = int
GBPSEK @ 2025-07-01T00:00:00+00:00 (int): first 10 ticks
first tick raw: 2025-07-01T00:00:00.326000+00:00 bid_i 1297675 ask_i 1298619 vol 1.149999976158142
divisor 1: bid 1297675.000000 ask 1298619.000000
divisor 10: bid 129767.500000 ask 129861.900000
divisor 100: bid 12976.750000 ask 12986.190000
divisor 1000: bid 1297.675000 ask 1298.619000
divisor 10000: bid 129.767500 ask 129.861900
divisor 100000: bid 12.976750 ask 12.986190
using --price-divisor 1.0:
2025-07-01T00:00:00.326000+00:00 bid 1297675.0 ask 1298619.0 bid_vol 1.149999976158142
2025-07-01T00:00:01.128000+00:00 bid 1297800.0 ask 1298661.0 bid_vol 0.9200000166893005
2025-07-01T00:00:01.329000+00:00 bid 1297796.0 ask 1298621.0 bid_vol 0.9200000166893005
2025-07-01T00:00:03.335000+00:00 bid 1297796.0 ask 1298591.0 bid_vol 0.9200000166893005
2025-07-01T00:00:03.737000+00:00 bid 1297842.0 ask 1298695.0 bid_vol 1.149999976158142
2025-07-01T00:00:05.340000+00:00 bid 1297850.0 ask 1298655.0 bid_vol 0.9200000166893005
2025-07-01T00:00:06.542000+00:00 bid 1297862.0 ask 1298709.0 bid_vol 0.9200000166893005
2025-07-01T00:00:08.546000+00:00 bid 1297874.0 ask 1298709.0 bid_vol 0.9200000166893005
2025-07-01T00:00:10.556000+00:00 bid 1297877.0 ask 1298724.0 bid_vol 0.9200000166893005
2025-07-01T00:00:12.562000+00:00 bid 1297839.0 ask 1298684.0 bid_vol 1.149999976158142
Intended workflow
This tool is intended to be used as a data preparation step, not as part of your backtest runtime loop:
- Download and export historical data once
- Commit or archive the output CSV + metadata if applicable
- Run fast, deterministic backtests against local files
Output files and --cache-dir
When run, the tool will fetch new or missing raw data files from Dukascopy for the instrument(s) and periods that you specify. These are always compressed, hourly files. Once fetched, the files are converted to CSV format tick files and aggregated into daily files. When all 24 hour periods are available and the daily CSV file is written to the cache, the raw native files are discarded.
Dukascopy downloads are notoriously slow and unreliable due to rate limiting and limited resources available for their service. This tool has multiple strategies to address and work around those limitations, including retaining the raw files until a full daily file of CSV data can be written. Re-running the same tradedesk-dc-export is both safe and efficient - it will only attempt to fill in gaps and will finish very quickly where downloads or conversions are already cached.
For this to work well though, you should treat the cache directory as a permanent, not a transient store of local market data that can be added to over time. Best practice is to always specify a --cache-dir that points to your common market data trove wherever you use the tool from.
Concurrency and Dukascopy reliability
Each symbol export uses up to four downloader threads internally. --workers
controls how many symbols are exported concurrently, so the total request
concurrency can grow quickly.
Dukascopy becomes unreliable when too many requests are in flight. If you want
to stay near the safest limit of four concurrent download threads, keep
--workers 1. Re-running the same command is idempotent and is the intended way
to fill cache gaps caused by failed hours.
Resampled CSV using --out
If you --resample files to an --out location, the resulting output CSV file contains OHLCV candles with timestamps in UTC (ISO-8601):
timestamp,open,high,low,close,volume
2025-01-01T00:00:00+00:00,1.10342,1.10361,1.10311,1.10355,1234.0
- Timestamps are always UTC
- Prices are floats after applying the price divisor
- Volume is derived from tick volume
Metadata sidecar (.meta.json)
Every CSV is accompanied by a metadata file describing how it was generated:
{
"data_type": "candles",
"generated_at": "2026-03-06T16:58:50.397630Z",
"params": {
"date_from": "2026-01-05",
"date_to": "2026-01-06",
"price_side": "bid",
"resample": "15MIN"
},
"price_divisor": 10.0,
"schema_version": "1",
"source": "dukascopy",
"symbol": "GBPUSD",
"timestamp_format": "iso8601_utc"
}
This ensures datasets are self-describing and reproducible, even months later.
--out and --resample are optional but must always be used together if specified. If you choose to run the tool with neither, this will create the source tick files only in the --cache-dir but generate no output resampled candle files. You may wish to do this if you want to point your backtest directly at the cache, you're using dynamic resampling from the tick data as part of your backtest, or you are just building up some local market data for use later.
Requirements
- Python 3.11+
- Internet access to Dukascopy datafeed
License
Licensed under the Apache License, Version 2.0. See: https://www.apache.org/licenses/LICENSE-2.0
Copyright 2026 Radius Red Ltd.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tradedesk_dukascopy-0.4.0.tar.gz.
File metadata
- Download URL: tradedesk_dukascopy-0.4.0.tar.gz
- Upload date:
- Size: 226.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
336db67a790414d801d35bdbf5e83e474169692012dc5f931aa8f63490278313
|
|
| MD5 |
ba5fbece415987f33cd6c772eabb15f9
|
|
| BLAKE2b-256 |
1c65a65e0e40f7ffb76a0869d1da7dc475ebd78c770435f32247b7337ddfc13c
|
Provenance
The following attestation bundles were made for tradedesk_dukascopy-0.4.0.tar.gz:
Publisher:
publish.yml on radiusred/tradedesk-dukascopy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tradedesk_dukascopy-0.4.0.tar.gz -
Subject digest:
336db67a790414d801d35bdbf5e83e474169692012dc5f931aa8f63490278313 - Sigstore transparency entry: 1279860165
- Sigstore integration time:
-
Permalink:
radiusred/tradedesk-dukascopy@12e5f27062cdf49d759caa76c4b2d1ac37e2c6b9 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/radiusred
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@12e5f27062cdf49d759caa76c4b2d1ac37e2c6b9 -
Trigger Event:
release
-
Statement type:
File details
Details for the file tradedesk_dukascopy-0.4.0-py3-none-any.whl.
File metadata
- Download URL: tradedesk_dukascopy-0.4.0-py3-none-any.whl
- Upload date:
- Size: 28.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ebd20c1f8544e606e4510a3cde255eff3f25c818dd1fc0a386b51126b75d242c
|
|
| MD5 |
acbc1030dc676a8cba7d300425461e53
|
|
| BLAKE2b-256 |
9c3711daefcc438c42801d4d4889bb08812736b8c9f09f1b3d0a9a32bb734217
|
Provenance
The following attestation bundles were made for tradedesk_dukascopy-0.4.0-py3-none-any.whl:
Publisher:
publish.yml on radiusred/tradedesk-dukascopy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tradedesk_dukascopy-0.4.0-py3-none-any.whl -
Subject digest:
ebd20c1f8544e606e4510a3cde255eff3f25c818dd1fc0a386b51126b75d242c - Sigstore transparency entry: 1279860191
- Sigstore integration time:
-
Permalink:
radiusred/tradedesk-dukascopy@12e5f27062cdf49d759caa76c4b2d1ac37e2c6b9 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/radiusred
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@12e5f27062cdf49d759caa76c4b2d1ac37e2c6b9 -
Trigger Event:
release
-
Statement type: