Dukascopy
Download and stream historical price data for variety of financial instruments (Forex, Commodities and Indices) from Dukascopy Bank SA.
Install / Use
npx skills add theorycraft-trading/dukascopyInstalls into whichever agent you are using.
README
Dukascopy
Dukascopy is a TheoryCraft extension for downloading and streaming historical market data from Dukascopy Bank SA.
Access free historical tick and bar data for 1600+ instruments including Forex, Stocks, Crypto, Commodities, Bonds, ETFs, and Indices.
For tutorials and guides, see the user documentation:
- https://theorycraft-trading.com/docs/guides/dukascopy/
⚠️ Development Status
This library is under active development and the API is subject to frequent changes.
Breaking changes may occur between releases as we refine the interface and add new features.
Installation
Add dukascopy to your list of dependencies in mix.exs:
def deps do
[
{:dukascopy, github: "theorycraft-trading/dukascopy"}
]
end
CLI Usage
Install the CLI:
mix escript.install github theorycraft-trading/dukascopy
Download Data
# Download daily EUR/USD data
dukascopy download -i EUR/USD --from 2024-01-01 --to 2024-12-31
# Download 5-minute bars in JSON format
dukascopy download -i EUR/USD -t m5 --from 2024-01-01 -f json
# Download with caching enabled
dukascopy download -i AAPL.US/USD -t h1 --from 2024-01-01 --cache
# Download tick data
dukascopy download -i EUR/USD -t tick --from 2024-01-01 --to 2024-01-02
Search Instruments
# Search for instruments
dukascopy search EUR
dukascopy search AAPL
dukascopy search xau
CLI Options
Usage:
dukascopy download -i INSTRUMENT --from DATE [options]
dukascopy search <query>
Required:
-i, --instrument Trading instrument (e.g., EUR/USD, AAPL.US/USD)
--from Start date (YYYY-MM-DD)
Options:
--to End date (YYYY-MM-DD or 'now') [default: now]
-t, --timeframe Timeframe: tick, m1, m5, m15, m30, h1, h4, D, W, M [default: D]
-p, --price-type Price type: bid, ask, mid [default: bid]
-f, --format Output format: csv, json, ndjson, none [default: csv]
-o, --output Output directory [default: ./download]
--cache Enable file caching [default: false]
--proxy Proxy URL (http://[user:pass@]host:port or socks5://host:port)
--continue-on-error Continue on fetch errors (WARNING: may cause data gaps)
-h, --help Show help message
Elixir API
Search Instruments
alias Dukascopy.Instruments
# Get all instruments
Instruments.all()
# => ["EUR/USD", "GBP/USD", "AAPL.US/USD", "BTC/USD", ...]
# Filter by category
Instruments.forex_majors() # => ["AUD/USD", "EUR/USD", "GBP/USD", ...]
Instruments.forex_crosses() # => ["AUD/CAD", "EUR/GBP", ...]
Instruments.metals() # => ["XAU/USD", "XAG/USD", ...]
Instruments.stocks() # => ["AAPL.US/USD", "TSLA.US/USD", ...]
Instruments.indices() # => ["USA30.IDX/USD", "USATECH.IDX/USD", ...]
Instruments.commodities() # => ["BRENT.CMD/USD", "COPPER.CMD/USD", ...]
Instruments.agriculturals() # => ["COCOA.CMD/USD", "COFFEE.CMD/USX", ...]
Instruments.crypto() # => ["BTC/USD", "ETH/USD", ...]
# Search instruments by name
Instruments.search("eur")
# => ["EUR/USD", "EUR/GBP", "EUR/JPY", ...]
DataFeed (TheoryCraft Integration)
Use Dukascopy.DataFeed with TheoryCraft's MarketSource to build trading pipelines:
alias TheoryCraft.MarketSource
# Build a pipeline with Dukascopy data
opts = [
instrument: "EUR/USD",
granularity: :tick,
from: ~D[2024-01-01],
to: ~D[2024-01-31]
]
market =
%MarketSource{}
|> MarketSource.add_data({Dukascopy.DataFeed, opts}, name: "EURUSD")
|> MarketSource.resample("m5", name: "EURUSD_m5")
|> MarketSource.resample("h1", name: "EURUSD_h1")
# Stream events through the pipeline
for event <- MarketSource.stream(market) do
IO.inspect(event)
end
Available granularities: :tick, :minute, :hour, :day
Streaming API
Use Dukascopy.stream/3 for aggregated data with automatic resampling:
# Stream raw ticks
Dukascopy.stream("EUR/USD", :tick, from: ~D[2024-01-01], to: ~D[2024-01-02])
|> Enum.take(1000)
# Stream 5-minute bars
Dukascopy.stream("EUR/USD", "m5", from: ~D[2024-01-01], to: ~D[2024-01-31])
|> Enum.to_list()
# Stream hourly bars with options
Dukascopy.stream("EUR/USD", "h1",
from: ~D[2024-01-01],
to: ~D[2024-12-31],
price_type: :mid,
timezone: "America/New_York"
)
|> Enum.to_list()
# Stream daily bars with caching
Dukascopy.stream("EUR/USD", "D",
date_range: Date.range(~D[2020-01-01], ~D[2024-01-01]),
use_cache: true
)
|> Enum.to_list()
# Stream weekly bars
Dukascopy.stream("EUR/USD", "W",
from: ~D[2024-01-01],
to: ~D[2024-12-31],
market_open: ~T[17:00:00],
weekly_open: :sunday
)
|> Enum.to_list()
Supported timeframes (strings or atoms):
:tick- Raw tick datat<N>- N ticks per bar (e.g.,t5,t100)s<N>- N-second bars (e.g.,s30)m<N>- N-minute bars (e.g.,m1,m5,m15)h<N>- N-hour bars (e.g.,h1,h4)D<N>- N-day bars (e.g.,D,D3)W<N>- N-week bars (e.g.,W)M<N>- N-month bars (e.g.,M)
Instruments
| Category | Count | Examples | |----------|-------|----------| | Forex Majors | 7 | EUR/USD, GBP/USD, USD/JPY | | Forex Crosses | 290+ | EUR/GBP, AUD/NZD, GBP/JPY | | Metals | 50+ | XAU/USD, XAG/USD, XPT/USD | | Stocks | 1000+ | AAPL.US/USD, TSLA.US/USD | | Indices | 21 | USA30.IDX/USD, USATECH.IDX/USD | | Commodities | 10+ | BRENT.CMD/USD, COPPER.CMD/USD | | Agriculturals | 6 | COCOA.CMD/USD, COFFEE.CMD/USX | | Crypto | 33 | BTC/USD, ETH/USD |
Development
# Run tests (excludes network tests by default)
mix test
# Run tests including network tests
mix test --include network
# Run CI checks (credo + tests)
mix ci
# Update instrument metadata from Dukascopy API
mix dukascopy.gen.instruments
License
Copyright (C) 2025 TheoryCraft Trading
Licensed under the Apache License, Version 2.0. See LICENSE for details.
Related Skills
node-connect
385.5kDiagnose OpenClaw Android, iOS, or macOS node pairing, QR/setup code, route, auth, and connection failures.
blender-python-addon
40.5kBlender Python add-on rules for operators, panels, properties, registration, testing, and API-safe scripting
flutter-development-guidelines-cursorrules-prompt-file
40.5kCursor rules for Flutter development with MVVM architecture, Riverpod state management, Material widgets, and Dart style guidelines.
commit-push-pr
140.6kCommit, push, and open a PR
