RiskPremium

Measuring the market risk premium
Log | Files | Refs

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