# frozen_string_literal: true require "json" require "net/http" require "provider/adapters/adapter" class Provider module Adapters # Central Bank of the Republic of Turkey. # Uses EVDS3 bulk API with buying (A) and selling (S) rates in TRY. # Each currency's mid-market rate is derived from the average of buy/sell. # Requires TCMB_API_KEY environment variable. class TCMB < Adapter EVDS_URL = "https://evds3.tcmb.gov.tr/igmevdsms-dis" # Buy/sell rates in TRY for each currency. Hardcoded because the EVDS3 catalog API doesn't expose # a clean list and the series rarely change. # Browse: https://evds3.tcmb.gov.tr > Exchange Rates > Indicative Exchange Rates CURRENCIES = [ "AED", "AUD", "AZN", "CAD", "CHF", "CNY", "DKK", "EUR", "GBP", "JPY", "KRW", "KWD", "KZT", "NOK", "PKR", "QAR", "RON", "RUB", "SAR", "SEK", "USD", ].freeze SERIES = CURRENCIES.flat_map do |c| [["#{c}_BUY", "TP.DK.#{c}.A.YTL"], ["#{c}_SELL", "TP.DK.#{c}.S.YTL"]] end.to_h.freeze COLUMNS = SERIES.to_h { |code, series| [series.tr(".", "_"), code] }.freeze class << self def api_key = ENV["TCMB_API_KEY"] || raise(Adapter::Unavailable, "no API key") def backfill_range = 730 end def fetch(after: nil, upto: nil) start_date = after || Date.new(2012, 1, 2) end_date = upto || Date.today url = URI("#{EVDS_URL}/series=#{SERIES.values.join("-")}" \ "&startDate=#{start_date.strftime("%d-%m-%Y")}" \ "&endDate=#{end_date.strftime("%d-%m-%Y")}" \ "&type=json&frequency=1") response = Net::HTTP.get(url, "key" => self.class.api_key) data = JSON.parse(response) items = data["items"] || [] items.flat_map do |item| date = Date.strptime(item["Tarih"], "%d-%m-%Y") raw = {} COLUMNS.each do |column, code| value = item[column] next if value.nil? raw[code] = Float(value) end # Mid of buying and selling for each currency → X→TRY rate # JPY is quoted per 100 units in TCMB data (confirmed via series metadata) CURRENCIES.filter_map do |currency| buy = raw["#{currency}_BUY"] sell = raw["#{currency}_SELL"] next unless buy && sell rate = (buy + sell) / 2 rate /= 100.0 if currency == "JPY" { date:, base: currency, quote: "TRY", rate: rate.round(4) } end end end end end end