82 lines
2.1 KiB
Ruby
82 lines
2.1 KiB
Ruby
|
|
# frozen_string_literal: true
|
||
|
|
|
||
|
|
require "json"
|
||
|
|
require "net/http"
|
||
|
|
|
||
|
|
require "provider/adapters/adapter"
|
||
|
|
|
||
|
|
class Provider
|
||
|
|
module Adapters
|
||
|
|
# Banco Central de Chile. Fetches daily exchange rates for 8 currencies
|
||
|
|
# against the Chilean peso (CLP) via the BDE REST API. Requires registered
|
||
|
|
# credentials (email + password) passed as query parameters.
|
||
|
|
class BCCH < Adapter
|
||
|
|
API_URL = "https://si3.bcentral.cl/SieteRestWS/SieteRestWS.ashx"
|
||
|
|
|
||
|
|
# series_id => base currency (all quoted against CLP)
|
||
|
|
SERIES = {
|
||
|
|
"F073.TCO.PRE.Z.D" => "USD",
|
||
|
|
"F072.CLP.EUR.N.O.D" => "EUR",
|
||
|
|
"F072.CLP.GBP.N.O.D" => "GBP",
|
||
|
|
"F072.CLP.JPY.N.O.D" => "JPY",
|
||
|
|
"F072.CLP.CAD.N.O.D" => "CAD",
|
||
|
|
"F072.CLP.AUD.N.O.D" => "AUD",
|
||
|
|
"F072.CLP.CNY.N.O.D" => "CNY",
|
||
|
|
"F072.CLP.BRL.N.O.D" => "BRL",
|
||
|
|
}.freeze
|
||
|
|
|
||
|
|
class << self
|
||
|
|
def api_key = ENV["BCCH_USER"] || raise(Adapter::Unavailable, "no API key")
|
||
|
|
end
|
||
|
|
|
||
|
|
def fetch(after: nil, upto: nil)
|
||
|
|
dataset = []
|
||
|
|
params = {}
|
||
|
|
params[:firstdate] = after.to_s if after
|
||
|
|
params[:lastdate] = (upto || Date.today).to_s if after
|
||
|
|
|
||
|
|
SERIES.each do |series_id, base|
|
||
|
|
sleep(0.2)
|
||
|
|
dataset.concat(fetch_series(series_id, base, **params))
|
||
|
|
end
|
||
|
|
|
||
|
|
dataset
|
||
|
|
end
|
||
|
|
|
||
|
|
def parse(json, base)
|
||
|
|
data = JSON.parse(json)
|
||
|
|
observations = data.dig("Series", "Obs") || []
|
||
|
|
|
||
|
|
observations.filter_map do |obs|
|
||
|
|
next if obs["statusCode"] != "OK"
|
||
|
|
|
||
|
|
value = obs["value"]&.tr(",", "")
|
||
|
|
next unless value
|
||
|
|
|
||
|
|
rate = Float(value)
|
||
|
|
next if rate.zero?
|
||
|
|
|
||
|
|
date = Date.strptime(obs["indexDateString"], "%d-%m-%Y")
|
||
|
|
{ date:, base:, quote: "CLP", rate: }
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
private
|
||
|
|
|
||
|
|
def fetch_series(series_id, base, **params)
|
||
|
|
url = URI(API_URL)
|
||
|
|
url.query = URI.encode_www_form(
|
||
|
|
user: ENV["BCCH_USER"],
|
||
|
|
pass: ENV["BCCH_PASS"],
|
||
|
|
function: "GetSeries",
|
||
|
|
timeseries: series_id,
|
||
|
|
**params,
|
||
|
|
)
|
||
|
|
|
||
|
|
response = Net::HTTP.get(url)
|
||
|
|
parse(response, base)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|