73 lines
2.2 KiB
Ruby
73 lines
2.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "json"
|
|
require "net/http"
|
|
|
|
require "provider/adapters/adapter"
|
|
|
|
class Provider
|
|
module Adapters
|
|
# Central Bank of the Republic of China (Taiwan). Publishes daily interbank
|
|
# spot rates for 15+ currencies against the US dollar. Rates are captured at
|
|
# 16:00 Taipei time (08:00 UTC). The API returns the full historical dataset
|
|
# (no server-side date filtering); client-side filtering is applied.
|
|
# Historical data available from 1993-01-05.
|
|
class CBC < Adapter
|
|
API_URL = "https://cpx.cbc.gov.tw/API/DataAPI/Get?FileName=BP01D01"
|
|
# Column index => [quote, base]
|
|
# Most rates are quoted as foreign currency per 1 USD (quote=X, base=USD).
|
|
# GBP, AUD, EUR are quoted as USD per 1 unit (quote=USD, base=X).
|
|
# Columns 15-17 (DEM, FRF, NLG) contain historical data pre-2002.
|
|
COLUMNS = {
|
|
1 => ["TWD", "USD"],
|
|
2 => ["JPY", "USD"],
|
|
3 => ["USD", "GBP"],
|
|
4 => ["HKD", "USD"],
|
|
5 => ["KRW", "USD"],
|
|
6 => ["CAD", "USD"],
|
|
7 => ["SGD", "USD"],
|
|
8 => ["CNY", "USD"],
|
|
9 => ["USD", "AUD"],
|
|
10 => ["IDR", "USD"],
|
|
11 => ["THB", "USD"],
|
|
12 => ["MYR", "USD"],
|
|
13 => ["PHP", "USD"],
|
|
14 => ["USD", "EUR"],
|
|
15 => ["DEM", "USD"],
|
|
16 => ["FRF", "USD"],
|
|
17 => ["NLG", "USD"],
|
|
18 => ["VND", "USD"],
|
|
}.freeze
|
|
|
|
def fetch(after: nil, upto: nil)
|
|
end_date = upto || Date.today
|
|
|
|
response = Net::HTTP.get(URI(API_URL))
|
|
data = JSON.parse(response)
|
|
rows = data.dig("data", "dataSets") || []
|
|
|
|
parse(rows, after, end_date)
|
|
end
|
|
|
|
def parse(rows, start_date = nil, end_date = nil)
|
|
rows.each_with_object([]) do |row, result|
|
|
next unless row.is_a?(Array) && row.length > 1
|
|
|
|
date = Date.strptime(row[0], "%Y%m%d")
|
|
next if start_date && date < start_date
|
|
next if end_date && date > end_date
|
|
|
|
COLUMNS.each do |index, (quote, base)|
|
|
value = row[index]
|
|
next if value.nil? || value == "-"
|
|
|
|
rate = Float(value)
|
|
next if rate.zero?
|
|
|
|
result << { date:, base:, quote:, rate: }
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|