Packages

Download and stream historical price data for variety of financial instruments (Forex, Commodities and Indices) from Dukascopy Bank SA.

Current section

Files

Jump to
dukascopy lib mix tasks dukascopy.gen.instruments.ex
Raw

lib/mix/tasks/dukascopy.gen.instruments.ex

defmodule Mix.Tasks.Dukascopy.Gen.Instruments do
@moduledoc """
Downloads Dukascopy instrument data and saves it to priv/instruments.json
Fetches instrument data directly from Dukascopy API and saves it as JSON.
Usage:
mix dukascopy.gen.instruments
"""
use Mix.Task
@shortdoc "Downloads instruments data from Dukascopy API"
@dukascopy_api_url "https://freeserv.dukascopy.com/2.0/index.php?path=common%2Finstruments&jsonp=_callbacks_._2n9mtpe0f"
@impl Mix.Task
def run(_args) do
Mix.Task.run("app.start")
output_file = "priv/instruments.json"
# Ensure priv directory exists
File.mkdir_p!("priv")
IO.puts("Fetching instrument data from Dukascopy API...")
json_data = fetch_instruments()
IO.puts("Saving to #{output_file}...")
File.write!(output_file, Jason.encode!(json_data, pretty: true))
IO.puts("✓ Downloaded #{output_file}")
end
defp fetch_instruments do
headers = [
{"User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"},
{"Accept", "*/*"},
{"Referer", "https://freeserv.dukascopy.com/"}
]
case Req.get(@dukascopy_api_url, headers: headers) do
{:ok, response} ->
response.body
|> strip_jsonp()
|> Jason.decode!()
{:error, reason} ->
raise "Failed to fetch instruments from Dukascopy: #{inspect(reason)}"
end
end
defp strip_jsonp(body) do
# Remove JSONP wrapper: _callbacks_._1m9mtpe0f({...})
body
|> String.replace(~r/^[^(]+\(/, "")
|> String.replace(~r/\)[^)]*$/, "")
end
end