FredUtils.jl (2464B)
1 # src/FredUtils.jl 2 module FredUtils 3 4 using HTTP, JSON, DataFrames, Dates 5 6 export fred_series_info, fred_observations 7 8 const FRED_BASE = "https://api.stlouisfed.org/fred" 9 10 function _api_key() 11 key = get(ENV, "FRED_API_KEY", "") 12 if isempty(key) 13 envfile = joinpath(@__DIR__, "..", ".env") 14 if isfile(envfile) 15 for line in eachline(envfile) 16 m = match(r"^FRED_API_KEY\s*=\s*(.+)$", line) 17 if m !== nothing 18 key = strip(m.captures[1]) 19 break 20 end 21 end 22 end 23 end 24 isempty(key) && error("Set FRED_API_KEY environment variable or add it to .env") 25 return key 26 end 27 28 """ 29 fred_series_info(series_id) -> NamedTuple 30 31 Return metadata for a FRED series: title, frequency, units, seasonal_adjustment, 32 observation_start, observation_end. 33 """ 34 function fred_series_info(series_id::AbstractString) 35 url = "$FRED_BASE/series?series_id=$series_id&api_key=$(_api_key())&file_type=json" 36 resp = HTTP.get(url) 37 data = JSON.parse(String(resp.body)) 38 s = data["seriess"][1] 39 return ( 40 id = s["id"], 41 title = s["title"], 42 frequency = s["frequency"], 43 units = s["units"], 44 seasonal_adjustment = s["seasonal_adjustment"], 45 observation_start = Date(s["observation_start"]), 46 observation_end = Date(s["observation_end"]), 47 ) 48 end 49 50 """ 51 fred_observations(series_id; start_date, end_date) -> DataFrame 52 53 Download observations for a FRED series. Returns DataFrame with columns `date::Date` 54 and `value::Union{Float64,Missing}`. 55 """ 56 function fred_observations(series_id::AbstractString; 57 start_date::Date = Date(1947,1,1), 58 end_date::Date = Date(2026,12,31)) 59 url = string(FRED_BASE, "/series/observations?series_id=", series_id, 60 "&api_key=", _api_key(), 61 "&file_type=json", 62 "&observation_start=", start_date, 63 "&observation_end=", end_date) 64 resp = HTTP.get(url) 65 data = JSON.parse(String(resp.body)) 66 obs_list = data["observations"] 67 n = length(obs_list) 68 dates = Vector{Date}(undef, n) 69 values = Vector{Union{Float64,Missing}}(undef, n) 70 for (i, obs) in enumerate(obs_list) 71 dates[i] = Date(obs["date"]) 72 v = obs["value"] 73 values[i] = v == "." ? missing : parse(Float64, v) 74 end 75 return DataFrame(date = dates, value = values) 76 end 77 78 end # module