67 lines
1.9 KiB
Ruby
67 lines
1.9 KiB
Ruby
|
|
# frozen_string_literal: true
|
||
|
|
|
||
|
|
require "json"
|
||
|
|
require "net/http"
|
||
|
|
|
||
|
|
require "provider/adapters/adapter"
|
||
|
|
|
||
|
|
class Provider
|
||
|
|
module Adapters
|
||
|
|
# Banco Central do Brasil. Fetches daily PTAX closing exchange rates for 10
|
||
|
|
# currencies against the Brazilian real (BRL) via the PTAX OData API.
|
||
|
|
# The PTAX system only publishes these 10 currencies.
|
||
|
|
class BCB < Adapter
|
||
|
|
API_URL = "https://olinda.bcb.gov.br/olinda/servico/PTAX/versao/v1/odata/" \
|
||
|
|
"CotacaoMoedaPeriodo(moeda=@moeda,dataInicial=@dataInicial,dataFinalCotacao=@dataFinalCotacao)"
|
||
|
|
|
||
|
|
CURRENCIES = ["AUD", "CAD", "CHF", "DKK", "EUR", "GBP", "JPY", "NOK", "SEK", "USD"].freeze
|
||
|
|
|
||
|
|
def fetch(after: nil, upto: nil)
|
||
|
|
dataset = []
|
||
|
|
date_from = Date.parse(after.to_s)
|
||
|
|
date_upto = Date.parse((upto || Date.today).to_s)
|
||
|
|
|
||
|
|
CURRENCIES.each do |currency|
|
||
|
|
sleep(0.2)
|
||
|
|
dataset.concat(fetch_currency(currency, date_from, date_upto))
|
||
|
|
end
|
||
|
|
|
||
|
|
dataset
|
||
|
|
end
|
||
|
|
|
||
|
|
def parse(json, currency)
|
||
|
|
data = JSON.parse(json)
|
||
|
|
records = data["value"] || []
|
||
|
|
|
||
|
|
records.filter_map do |record|
|
||
|
|
rate = record["cotacaoVenda"]
|
||
|
|
next unless rate
|
||
|
|
next if rate.zero?
|
||
|
|
|
||
|
|
raw_date = record["dataHoraCotacao"].to_s.strip[0, 10]
|
||
|
|
next unless raw_date&.length == 10
|
||
|
|
|
||
|
|
date = Date.strptime(raw_date, "%Y-%m-%d")
|
||
|
|
{ date:, base: currency, quote: "BRL", rate: }
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
private
|
||
|
|
|
||
|
|
def fetch_currency(currency, date_from, date_upto)
|
||
|
|
query = [
|
||
|
|
"@moeda='#{currency}'",
|
||
|
|
"@dataInicial='#{date_from.strftime("%m-%d-%Y")}'",
|
||
|
|
"@dataFinalCotacao='#{date_upto.strftime("%m-%d-%Y")}'",
|
||
|
|
"$filter=tipoBoletim%20eq%20'Fechamento'",
|
||
|
|
"$format=json",
|
||
|
|
].join("&")
|
||
|
|
|
||
|
|
url = URI("#{API_URL}?#{query}")
|
||
|
|
response = Net::HTTP.get(url)
|
||
|
|
parse(response, currency)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|