Forex (Forex v0.2.1)
View SourceForex
is a simple Elixir library that serves as a wrapper to the
foreign exchange reference rates provided by the European Central Bank.
Usage Information
The reference rates are usually updated at around 16:00 CET every working day, except on TARGET closing days.
They are based on the daily concertation procedure between central banks across Europe, which normally takes place around 14:10 CET. The reference rates are published for information purposes only. Using the rates for transaction purposes is strongly discouraged.
Source: European Central Bank
Motivation
Even though there are other libraries in the Elixir ecosystem that provide
similar functionality (example: ex_money
), Forex
was created with the intent
of providing access to currency exchange rates for projects that want to self-host
the data and not rely on third-party paid services in a simple and straightforward
manner. No API keys, no authentication, no rate limits, just a simple Elixir library
that fetches the data from the European Central Bank and caches it for later use.
Options
:base
- The base currency to convert the rates to. The default currency base is:eur
.:format
- The format of the rate value. Supported values are:decimal
and:string
. The default is:decimal
.:round
- The number of decimal places to round the rate value to. The default is5
.:symbols
- A list of currency codes (atoms or strings) to filter the rates by. The default isnil
, which means all available currencies will be returned.:keys
- The format of the keys in the rate map. Supported values are:strings
and:atoms
. The default is:atoms
.:use_cache
- A boolean value to enable or disable the cache. To enable the cache check the usage section docs for detailed instructions. The default istrue
.:feed_fn
- Anmfa
tuple that can be used to fetch the exchange rates from a custom feed. This option is mostly used for testing purposes. The default isnil
, which means the default feed will be used.
Usage
By default the base
currency is the Euro (EUR), the same as the European Central Bank,
but you can change the base currency by passing the base
option to the relevant functions.
To fetch the latest exchange rates, you can use the latest_rates/1
function:
iex> Forex.latest_rates()
{:ok,
%{
base: :eur,
date: ~D[2025-03-12],
rates: %{
usd: Decimal.new("1.1234"),
jpy: Decimal.new("120.1234"),
...
zar: Decimal.new("24.1442")
}}
}
To fetch the exchange rates for the last ninety days, you can use the last_ninety_days_rates/1
function:
iex> Forex.last_ninety_days_rates()
{:ok,
[
%{
date: ~D[2025-03-12],
base: :eur,
rates: %{
usd: Decimal.new("1.1234"),
jpy: Decimal.new("120.1234"),
...
zar: Decimal.new("24.1442")
}
},
...
]}
To fetch the historic exchange rates (for any working day since 4 January 1999),
you can use the historic_rates/1
function:
iex> Forex.historic_rates()
{:ok,
[
%{
date: ~D[2025-03-12],
base: :eur,
rates: %{
usd: Decimal.new("1.1234"),
jpy: Decimal.new("120.1234"),
...
zar: Decimal.new("24.1442")
}
},
...
]}
To fetch the exchange rates for a specific date, you can use the get_historic_rate/2
function:
iex> Forex.get_historic_rate(~D[2025-02-25])
{:ok,
[
%{
date: ~D[2025-03-12],
base: :eur,
rates: %{
usd: Decimal.new("1.1234"),
jpy: Decimal.new("120.1234"),
...
zar: Decimal.new("24.1442")
}
},
...
]}
To fetch the exchange rates between two dates, you can use the get_historic_rates_between/3
function:
iex> Forex.get_historic_rates_between(~D[2025-02-25], ~D[2025-02-28])
{:ok,
[
%{
date: ~D[2025-03-12],
base: :eur,
rates: %{
usd: Decimal.new("1.1234"),
jpy: Decimal.new("120.1234"),
...
zar: Decimal.new("24.1442")
}
},
...
]}
To convert an amount from one currency to another, you can use the exchange/4
function:
iex> Forex.exchange(100, "USD", "EUR")
{:ok, Decimal.new("91.86100")}
iex> Forex.exchange(420, :eur, :gbp)
{:ok, Decimal.new("353.12760")}
To list all available currencies from the European Central Bank,
you can use the available_currencies/1
function:
iex> Forex.available_currencies()
[:try, :eur, :aud, :bgn, :brl, ...]
Summary
Types
The currency code is a three-letter code that represents a currency, in accordance with the ISO 4217 standard. It can be either a string or an atom.
A currency rate, represented as a map with the currency code as the key and the rate as the value. The rate can be either a Decimal or a string.
Functions
Return a list of all available currencies ISO 4217 codes.
Return a list of all available currencies in the format
%{currency_code() => currency_name()}
.
Useful for input forms, selects, etc.
Exchange a given amount from one currency to another. It will use the cached exchange rates from the European Central Bank (ECB) or fetch the latest rates if the cache is disabled.
Same as exchange/3
, but raises an error if the request fails.
Get the currency information for the given ISO code.
Get the currency information for the given ISO code.
Like get_currency/1
, but raises an error if the currency is not found.
Get a specific date from the historic exchange rates feed.
It returns either an {:ok, rate()}
if the rate was successfully
retrieved or an {:error, reasons}
if the rate was not found.
Same as get_historic_rate/2
, but raises an error if the request fails.
Get exchange rates between two dates from the historic exchange rates feed.
Same as get_historic_rates_between/3
, but raises an error if the request fails.
Fetch the historic exchange rates feed from the European Central Bank (ECB) for any working day since 4 January 1999.
Same as historic_rates/1
, but raises an error if the request fails.
Returns the configured JSON encoding library for Forex.
The default is the Jason
library.
Fetch the exchange rates for the last ninety days from the European Central Bank (ECB).
Same as last_ninety_days_rates/1
, but raises an error if the request fails.
Last updated date of the exchange rates feed. Lists the last date the exchange rates were updated from the cache.
Fetch the latest exchange rates from the European Central Bank (ECB).
Same as latest_rates/1
, but raises an error if the request fails.
Return a list of all available currencies.
Validate and return the options for the Forex module functions, using default values if the options are not provided.
Types
The currency code is a three-letter code that represents a currency, in accordance with the ISO 4217 standard. It can be either a string or an atom.
@type rate() :: %{required(currency_code()) => Decimal.t() | String.t()}
A currency rate, represented as a map with the currency code as the key and the rate as the value. The rate can be either a Decimal or a string.
Functions
Return a list of all available currencies ISO 4217 codes.
Return a list of all available currencies in the format
%{currency_code() => currency_name()}
.
Useful for input forms, selects, etc.
@spec exchange(number() | Decimal.t(), currency_code(), currency_code(), keyword()) :: {:ok, Decimal.t()} | {:error, term()}
Exchange a given amount from one currency to another. It will use the cached exchange rates from the European Central Bank (ECB) or fetch the latest rates if the cache is disabled.
Options
:format
- The format of the rate value. Supported values are:decimal
and:string
. The default is:decimal
.:round
- The number of decimal places to round the rate value to. The default is4
.
Examples
iex> Forex.exchange(100, "USD", "EUR")
{:ok, Decimal.new("91.86100")}
iex> Forex.exchange(420, :eur, :gbp, format: :string)
{:ok, "353.12760"}
iex> Forex.exchange(123, :gbp, :usd, format: :string, round: 1)
{:ok, "159.3"}
Same as exchange/3
, but raises an error if the request fails.
Get the currency information for the given ISO code.
Get the currency information for the given ISO code.
Like get_currency/1
, but raises an error if the currency is not found.
Get a specific date from the historic exchange rates feed.
It returns either an {:ok, rate()}
if the rate was successfully
retrieved or an {:error, reasons}
if the rate was not found.
Arguments
date
- The date to get the rate for.date
is either aDate.new()
struct or a string in the ISO 8601 format.opts
- Same options aslatest_rates/1
.
Same as get_historic_rate/2
, but raises an error if the request fails.
@spec get_historic_rates_between(maybe_date(), maybe_date(), keyword()) :: {:ok, [rate()]} | {:error, term()}
Get exchange rates between two dates from the historic exchange rates feed.
Returns a list of exchange rates for each working day between the start and end date.
Arguments
start_date
- Start date (Date, ISO 8601 string, or {year, month, day} tuple)end_date
- End date (Date, ISO 8601 string, or {year, month, day} tuple)opts
- Same options aslatest_rates/1
Return Value
Returns {:ok, [%{date: Date.t(), base: atom(), rates: map()}]}
where each list item
represents rates for one day.
Examples
iex> Forex.get_historic_rates_between("2023-01-01", "2023-01-05")
{:ok, [
%{date: ~D[2023-01-02], base: :eur, rates: %{usd: Decimal.new("1.0678", ...}},
%{date: ~D[2023-01-03], base: :eur, rates: %{usd: Decimal.new("1.0545", ...}},
%{date: ~D[2023-01-04], base: :eur, rates: %{usd: Decimal.new("1.0599", ...}},
%{date: ~D[2023-01-05], base: :eur, rates: %{usd: Decimal.new("1.0556", ...}}
]}
Same as get_historic_rates_between/3
, but raises an error if the request fails.
Fetch the historic exchange rates feed from the European Central Bank (ECB) for any working day since 4 January 1999.
By default, the historic rates are not automatically fetched when using the Fetcher (scheduler) module, since the whole file is returned this avoids excessive memory usage when caching the results if not needed. To fetch and cache the historic rates, you need to manually call this function.
Same options as latest_rates/1
.
Same as historic_rates/1
, but raises an error if the request fails.
Returns the configured JSON encoding library for Forex.
The default is the Jason
library.
The JSON library must implement the encode/1
function.
The JSON library is only required when using the mix tasks to export the exchange rates to a JSON file, otherwise this setting can be ignored.
To customize the JSON library, including the following
in your config/config.exs
:
config :forex, :json_library, AlternativeJsonLibrary
The library must implement the encode_to_iodata!/2
function.
Fetch the exchange rates for the last ninety days from the European Central Bank (ECB).
Note that rates are only available on working days.
Arguments
Same options as latest_rates/1
.
Same as last_ninety_days_rates/1
, but raises an error if the request fails.
@spec last_updated() :: Keyword.t() | nil
Last updated date of the exchange rates feed. Lists the last date the exchange rates were updated from the cache.
Example:
iex> Forex.last_updated()
[
latest_rates: ~U[2024-11-23 18:19:38.974337Z],
historic_rates: ~U[2024-11-23 18:27:07.391035Z],
last_ninety_days_rates: ~U[2024-11-23 18:19:39.111818Z],
]
Fetch the latest exchange rates from the European Central Bank (ECB).
Return Value
Returns {:ok, %{base: atom(), date: Date.t(), rates: map()}}
on success where:
base
is the base currency codedate
is the reference daterates
is a map of currency codes to rate values
Arguments
opts
- Options::format
- Format of rates (:decimal
or:string
, default::decimal
):base
- Base currency (default:EUR
):symbols
- List of currency codes to include:keys
- Key format in rates map (:atoms
or:strings
):use_cache
- Whether to use cached rates (default:true
)
Examples
{:ok, %{base: :eur, date: ~D[2025-03-12], rates: %{usd: Decimal.new("1.1234"), jpy: Decimal.new("120.1234"), ...}}}
Same as latest_rates/1
, but raises an error if the request fails.
Return a list of all available currencies.
Validate and return the options for the Forex module functions, using default values if the options are not provided.
Options
:base
- The base currency to convert rates to (default::eur
):format
- Format of rate values (:decimal
or:string
, default::decimal
):round
- Decimal places for rounding (default:5
):symbols
- Currency codes to include (default:nil
for all currencies):keys
- Map key format (:atoms
or:strings
, default::atoms
):use_cache
- Whether to use cached rates (default:true
):feed_fn
- Optional custom feed function as{module, function, args}
(default:nil
)