frankfurter/lib/provider/adapters/bcb.rb

67 lines
1.9 KiB
Ruby
Raw Normal View History

2026-05-21 01:38:14 -06:00
# 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