💶 Euro Exchange Rates History
Mix.install([
{:briefly, "~> 0.4.1"},
{:req, "~> 0.3.10"},
{:kino_explorer, "~> 0.1.8"},
{:kino_vega_lite, "~> 0.1.9"}
])
Fetch historic exchange data from European Central Bank
alias Explorer.DataFrame, as: D
alias Explorer.Series, as: S
alias VegaLite, as: V
path = Briefly.create!()
"https://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist.zip"
|> Req.get!()
|> then(&(&1.body |> hd() |> elem(1)))
|> then(&File.write!(path, &1))
history = D.from_csv!(path, header: true, parse_dates: true, null_character: "N/A")
currencies =
history
|> D.dtypes()
|> Map.keys()
|> Kernel.--(["Date"])
|> Enum.sort()
|> Enum.map(&{&1, &1})
currency =
"Currency"
|> Kino.Input.select(currencies, default: "USD")
|> Kino.render()
|> Kino.Input.read()
from_to =
"Exchange"
|> Kino.Input.select([
{"from", "Currency to EUR"},
{"to", "EUR to Currency"}
])
|> Kino.render()
|> Kino.Input.read()
time_filter =
"Show"
|> Kino.Input.select(
[
{"all", "All"},
{"1825", "Last 5 years"},
{"730", "Last 2 years"},
{"365", "Last 1 year"},
{"ytd", "Year to date"},
{"90", "Last 90 days"},
{"60", "Last 60 days"},
{"30", "Last 30 days"},
{"15", "Last 15 days"},
{"7", "Last 7 days"}
],
default: "all"
)
|> Kino.render()
|> Kino.Input.read()
df =
history
|> D.select(["Date", currency])
|> D.rename(%{currency => "to"})
|> D.mutate_with(fn entry ->
case entry["to"] do
nil -> []
to -> [from: S.divide(1, to)]
end
end)
|> D.select(["Date", from_to])
|> D.rename(%{"Date" => "date", from_to => "value"})
df =
case time_filter do
"all" ->
df
"ytd" ->
cut = %Date{Date.utc_today() | month: 1, day: 1}
D.filter_with(df, &S.greater(&1["date"], cut))
days ->
cut = Date.add(Date.utc_today(), -1 * String.to_integer(days))
D.filter_with(df, &S.greater(&1["date"], cut))
end
:ok
label =
case from_to do
"from" -> "1 #{currency} to EUR"
"to" -> "1 EUR to #{currency}"
end
V.new(
width: 750,
height: 400,
title: ["date", label]
)
|> V.data_from_values(df, only: ["date", "value"])
|> V.mark(:point, tooltip: true)
|> V.encode_field(:x, "date",
title: "date",
type: :temporal
)
|> V.encode_field(:y, "value",
title: label,
type: :quantitative
)