# `Fred.Series`
[🔗](https://github.com/akoutmos/fred/blob/master/lib/fred/series.ex#L1)

Functions for the FRED Series endpoints.

Series are the core data type in FRED - each series is a time series of
economic observations (e.g., GDP, unemployment rate, CPI).

## Endpoints

  - `get/2` - [`/fred/series`](https://fred.stlouisfed.org/docs/api/fred/series.html) - Get series metadata
  - `categories/2` - [`/fred/series/categories`](https://fred.stlouisfed.org/docs/api/fred/series_categories.html) - Get categories for a series
  - `observations/2` - [`/fred/series/observations`](https://fred.stlouisfed.org/docs/api/fred/series_observations.html) - Get the actual data values
  - `release/2` - [`/fred/series/release`](https://fred.stlouisfed.org/docs/api/fred/series_release.html) - Get the release a series belongs to
  - `search/2` - [`/fred/series/search`](https://fred.stlouisfed.org/docs/api/fred/series_search.html) - Search for series by text
  - `search_tags/2` - [`/fred/series/search/tags`](https://fred.stlouisfed.org/docs/api/fred/series_search_tags.html) - Get tags for a search
  - `search_related_tags/2` - [`/fred/series/search/related_tags`](https://fred.stlouisfed.org/docs/api/fred/series_search_related_tags.html)
  - `tags/2` - [`/fred/series/tags`](https://fred.stlouisfed.org/docs/api/fred/series_tags.html) - Get tags for a series
  - `updates/1` - [`/fred/series/updates`](https://fred.stlouisfed.org/docs/api/fred/series_updates.html) - Get recently updated series
  - `vintage_dates/2` - [`/fred/series/vintagedates`](https://fred.stlouisfed.org/docs/api/fred/series_vintagedates.html) - Get revision dates

# `categories`

```elixir
@spec categories(series_id :: String.t(), opts :: keyword()) :: Fred.Client.response()
```

Get the categories for an economic data series.

## Options

  * `:realtime_end` (struct of type `Date`) - End of the real-time period.

* `:realtime_start` (struct of type `Date`) - Start of the real-time period.

## Examples

    iex> {:ok, categories} = Fred.Series.categories("UNRATE")
    iex> %{"categories" => [_ | _]} = categories

    iex> {:error, %Fred.Error{type: :option_error}} =
    ...>   Fred.Series.categories("UNRATE", realtime_start: "Bad Input")

# `get`

```elixir
@spec get(series_id :: String.t(), opts :: keyword()) :: Fred.Client.response()
```

Get an economic data series.

Returns metadata about a series including its title, frequency, units,
seasonal adjustment, and more.

## Options

  * `:realtime_end` (struct of type `Date`) - End of the real-time period.

* `:realtime_start` (struct of type `Date`) - Start of the real-time period.

## Examples

    iex> {:ok, series} = Fred.Series.get("GDP")
    iex> %{"seriess" => [_ | _]} = series

    iex> {:error, %Fred.Error{type: :option_error}} =
    ...>   Fred.Series.get("GDP", realtime_start: "Bad Input")

# `observations`

```elixir
@spec observations(series_id :: String.t(), opts :: keyword()) ::
  Fred.Client.response()
@spec observations(series_ids :: list() | String.t(), opts :: keyword()) ::
  {:ok, Explorer.DataFrame.t()} | {:error, term()}
```

Get the observations or data values for an economic data series.

This is the primary function for retrieving actual time series data from FRED.

## Options

  * `:aggregation_method` (`t:atom/0`) - How the data should be aggregated. Supported values are:
  - `:avg` - Average
  - `:sum` - Sum
  - `:eop` - End of period

* `:frequency` (`t:atom/0`) - Frequency filter. Supported values are:
  - `:d` - Daily
  - `:w` - Weekly
  - `:bw` - Biweekly
  - `:m` - Monthly
  - `:q` - Quarterly
  - `:sa` - Semiannual
  - `:a` - Annual
  - `:wef` - Weekly, Ending Friday
  - `:weth` - Weekly, Ending Thursday
  - `:wew` - Weekly, Ending Wednesday
  - `:wetu` - Weekly, Ending Tuesday
  - `:wem` - Weekly, Ending Monday
  - `:wesu` - Weekly, Ending Sunday
  - `:wesa` - Weekly, Ending Saturday
  - `:bwew` - Biweekly, Ending Wednesday
  - `:bwem` - Biweekly, Ending Monday

* `:limit` (`t:pos_integer/0`) - Max results (between 1-100000).

* `:observation_end` (struct of type `Date`) - End date for observations.

* `:observation_start` (struct of type `Date`) - Start date for observations.

* `:offset` (`t:pos_integer/0`) - Result offset.

* `:output_type` (`t:atom/0`) - Specifies how the real-time output is formated. Supported values are:
  - `:real_time_period` - Observations by real-time period.
  - `:all_vintage` - Observations by vintage date, all observations.
  - `:new_revised_vintage` - Observations by vintage date, new and revised observations only.
  - `:initial_release` - Observations, initial release only.

* `:realtime_end` (struct of type `Date`) - End of the real-time period.

* `:realtime_start` (struct of type `Date`) - Start of the real-time period.

* `:sort_order` (`t:atom/0`) - The sort order of the results. Supported values are:
  - `:asc`
  - `:desc`

* `:units` (`t:atom/0`) - Data value transformation. Supported values are:
  - `:lin` - Levels (no transformation, default)
  - `:chg` - Change
  - `:ch1` - Change from year ago
  - `:pch` - Percent change
  - `:pc1` - Percent change from year ago
  - `:pca` - Compounded annual rate of change
  - `:cch` - Continuously compounded rate of change
  - `:cca` - Continuously compounded annual rate of change
  - `:log` - Natural Log

* `:vintage_dates` (list of struct of type `Date`) - Dates for historical vintages

## Examples

    iex> {:ok, observations} = Fred.Series.observations("UNRATE")
    iex> %{"observations" => [_ | _]} = observations

    iex> {:ok, observations} =
    ...>   Fred.Series.observations("GDP",
    ...>     observation_start: ~D[2020-01-01],
    ...>     frequency: :q,
    ...>     units: :pch
    ...>   )
    iex> %{"observations" => [_ | _]} = observations

    iex> {:ok, observations} =
    ...>   Fred.Series.observations("GDP",
    ...>     vintage_dates: [~D[2015-01-01], ~D[2015-07-01]]
    ...>   )
    iex> %{"observations" => [_ | _]} = observations

    iex> {:error, %Fred.Error{type: :option_error}} =
    ...>   Fred.Series.observations("GDP", realtime_start: "Bad Input")

# `observations_as_data_frame`

Same as `observations/2` except this returns the observation data
inside of an `Explorer.DataFrame`. You can also pass in a list of
series ids and all of the series will be packaged into the
`Explorer.DataFrame`. Since series can all have different dates,
the union of all of the dates across all of the series will populate
the date column and series without data for that date will have a nil
value.

## Options

  * `:aggregation_method` (`t:atom/0`) - How the data should be aggregated. Supported values are:
  - `:avg` - Average
  - `:sum` - Sum
  - `:eop` - End of period

* `:frequency` (`t:atom/0`) - Frequency filter. Supported values are:
  - `:d` - Daily
  - `:w` - Weekly
  - `:bw` - Biweekly
  - `:m` - Monthly
  - `:q` - Quarterly
  - `:sa` - Semiannual
  - `:a` - Annual
  - `:wef` - Weekly, Ending Friday
  - `:weth` - Weekly, Ending Thursday
  - `:wew` - Weekly, Ending Wednesday
  - `:wetu` - Weekly, Ending Tuesday
  - `:wem` - Weekly, Ending Monday
  - `:wesu` - Weekly, Ending Sunday
  - `:wesa` - Weekly, Ending Saturday
  - `:bwew` - Biweekly, Ending Wednesday
  - `:bwem` - Biweekly, Ending Monday

* `:limit` (`t:pos_integer/0`) - Max results (between 1-100000).

* `:observation_end` (struct of type `Date`) - End date for observations.

* `:observation_start` (struct of type `Date`) - Start date for observations.

* `:offset` (`t:pos_integer/0`) - Result offset.

* `:output_type` (`t:atom/0`) - Specifies how the real-time output is formated. Supported values are:
  - `:real_time_period` - Observations by real-time period.
  - `:all_vintage` - Observations by vintage date, all observations.
  - `:new_revised_vintage` - Observations by vintage date, new and revised observations only.
  - `:initial_release` - Observations, initial release only.

* `:realtime_end` (struct of type `Date`) - End of the real-time period.

* `:realtime_start` (struct of type `Date`) - Start of the real-time period.

* `:sort_order` (`t:atom/0`) - The sort order of the results. Supported values are:
  - `:asc`
  - `:desc`

* `:units` (`t:atom/0`) - Data value transformation. Supported values are:
  - `:lin` - Levels (no transformation, default)
  - `:chg` - Change
  - `:ch1` - Change from year ago
  - `:pch` - Percent change
  - `:pc1` - Percent change from year ago
  - `:pca` - Compounded annual rate of change
  - `:cch` - Continuously compounded rate of change
  - `:cca` - Continuously compounded annual rate of change
  - `:log` - Natural Log

* `:vintage_dates` (list of struct of type `Date`) - Dates for historical vintages

## Examples

    iex> %Explorer.DataFrame{} = Fred.Series.observations_as_data_frame("GDP")

    iex> %Explorer.DataFrame{} =
    ...>   Fred.Series.observations_as_data_frame(["GDP", "UNRATE"],
    ...>     observation_start: ~D[2020-01-01],
    ...>     frequency: :q,
    ...>     units: :pch
    ...>   )

    iex> %Explorer.DataFrame{} =
    ...>   Fred.Series.observations_as_data_frame("GDP",
    ...>     vintage_dates: [~D[2015-01-01], ~D[2015-07-01]]
    ...>   )

    iex> {:error, %Fred.Error{type: :option_error}} =
    ...>   Fred.Series.observations_as_data_frame("GDP", realtime_start: "Bad Input")

# `release`

```elixir
@spec release(series_id :: String.t(), opts :: keyword()) :: Fred.Client.response()
```

Get the release for an economic data series.

## Options

  * `:realtime_end` (struct of type `Date`) - End of the real-time period.

* `:realtime_start` (struct of type `Date`) - Start of the real-time period.

## Examples

    iex> {:ok, release} = Fred.Series.release("GDP")
    iex> %{"releases" => [_ | _]} = release

    iex> {:error, %Fred.Error{type: :option_error}} =
    ...>   Fred.Series.release("GDP", realtime_start: "Bad Input")

# `search`

```elixir
@spec search(search_text :: String.t(), opts :: keyword()) :: Fred.Client.response()
```

Search for economic data series that match keywords.

## Options

  * `:exclude_tag_names` (list of `t:String.t/0`) - List of tag names to exclude.

* `:filter_value` (`t:String.t/0`) - The value of the filter_variable attribute to filter results by. This requires that the `:filter_variable` is also provided.

* `:filter_variable` (`t:atom/0`) - The attribute to filter results by. Supported values are:
  - `:frequency`
  - `:units`
  - `:seasonal_adjustment`

* `:limit` (`t:pos_integer/0`) - Max results (between 1-1000).

* `:offset` (`t:pos_integer/0`) - Result offset.

* `:order_by` (`t:atom/0`) - Order the results by the provided field. Supported values are:
  - `:search_rank`
  - `:series_id`
  - `:title`
  - `:units`
  - `:frequency`
  - `:seasonal_adjustment`
  - `:realtime_start`
  - `:realtime_end`
  - `:last_updated`
  - `:observation_start`
  - `:observation_end`
  - `:popularity`
  - `:group_popularit`

* `:realtime_end` (struct of type `Date`) - End of the real-time period.

* `:realtime_start` (struct of type `Date`) - Start of the real-time period.

* `:search_type` (`t:atom/0`) - Tag group filter. Supported values are:
  - `:full_text` - Searches title, units, frequency, and tags
  - `:series_id` - Substring search on series IDs

* `:sort_order` (`t:atom/0`) - The sort order of the results. Supported values are:
  - `:asc`
  - `:desc`

* `:tag_names` (list of `t:String.t/0`) - List of tag names to match.

## Examples

    iex> {:ok, series} = Fred.Series.search("UNRATE", search_type: :series_id)
    iex> %{"seriess" => [_ | _]} = series

    iex> {:ok, series} =
    ...>   Fred.Series.search("unemployment rate",
    ...>     order_by: :popularity,
    ...>     sort_order: :desc,
    ...>     limit: 10
    ...>   )
    iex> %{"seriess" => [_ | _]} = series

    iex> {:error, %Fred.Error{type: :option_error}} =
    ...>   Fred.Series.search("UNRATE", search_type: "Bad search type")

# `search_related_tags`

```elixir
@spec search_related_tags(
  search_text :: String.t(),
  tag_names :: String.t(),
  opts :: keyword()
) ::
  Fred.Client.response()
```

Get the related tags for a series search.

Returns tags assigned to series that match all tags in `:tag_names`
and the search text.

## Options

  * `:exclude_tag_names` (list of `t:String.t/0`) - List of tag names to exclude.

* `:limit` (`t:pos_integer/0`) - Max results (between 1-1000).

* `:offset` (`t:pos_integer/0`) - Result offset.

* `:order_by` (`t:atom/0`) - Order the results by the provided field. Supported values are:
  - `:series_count`
  - `:popularity`
  - `:created`
  - `:name`
  - `:group_id`

* `:realtime_end` (struct of type `Date`) - End of the real-time period.

* `:realtime_start` (struct of type `Date`) - Start of the real-time period.

* `:sort_order` (`t:atom/0`) - The sort order of the results. Supported values are:
  - `:asc`
  - `:desc`

* `:tag_group_id` (`t:atom/0`) - Tag group filter. Supported values are:
  - `:freq` - Frequency
  - `:gen` - General or Concept
  - `:geo` - Geography
  - `:geot` - Geography Type
  - `:rls` - Release
  - `:seas` - Seasonal Adjustment
  - `:src` - Source

* `:tag_search_text` (`t:String.t/0`) - Text to search tag names

## Examples

    iex> {:ok, tags} = Fred.Series.search_related_tags("mortgage rate", ["30-year", "frb"])
    iex> %{"tags" => [_ | _]} = tags

    iex> {:error, %Fred.Error{type: :option_error}} =
    ...>   Fred.Series.search_related_tags("monetary service index", ["30-year", "frb"], realtime_start: "Bad Input")

# `search_tags`

```elixir
@spec search_tags(search_text :: String.t(), opts :: keyword()) ::
  Fred.Client.response()
```

Get the tags for a series search.

Returns the FRED tags that are assigned to series matching the search text.

## Options

  * `:limit` (`t:pos_integer/0`) - Max results (between 1-1000).

* `:offset` (`t:pos_integer/0`) - Result offset.

* `:order_by` (`t:atom/0`) - Order the results by the provided field. Supported values are:
  - `:series_count`
  - `:popularity`
  - `:created`
  - `:name`
  - `:group_id`

* `:realtime_end` (struct of type `Date`) - End of the real-time period.

* `:realtime_start` (struct of type `Date`) - Start of the real-time period.

* `:sort_order` (`t:atom/0`) - The sort order of the results. Supported values are:
  - `:asc`
  - `:desc`

* `:tag_group_id` (`t:atom/0`) - Tag group filter. Supported values are:
  - `:freq` - Frequency
  - `:gen` - General or Concept
  - `:geo` - Geography
  - `:geot` - Geography Type
  - `:rls` - Release
  - `:seas` - Seasonal Adjustment
  - `:src` - Source

* `:tag_names` (list of `t:String.t/0`) - List of tag names to match.

* `:tag_search_text` (`t:String.t/0`) - Text to search tag names

## Examples

    iex> {:ok, tags} = Fred.Series.search_tags("monetary service index")
    iex> %{"tags" => [_ | _]} = tags

    iex> {:error, %Fred.Error{type: :option_error}} =
    ...>   Fred.Series.search_tags("monetary service index", realtime_start: "Bad Input")

# `tags`

```elixir
@spec tags(series_id :: String.t(), opts :: keyword()) :: Fred.Client.response()
```

Get the FRED tags for an economic data series.

## Options

  * `:order_by` (`t:atom/0`) - Order the results by the provided field. Supported values are:
  - `:series_count`
  - `:popularity`
  - `:created`
  - `:name`
  - `:group_id`

* `:realtime_end` (struct of type `Date`) - End of the real-time period.

* `:realtime_start` (struct of type `Date`) - Start of the real-time period.

* `:sort_order` (`t:atom/0`) - The sort order of the results. Supported values are:
  - `:asc`
  - `:desc`

## Examples

    iex> {:ok, tags} = Fred.Series.tags("UNRATE")
    iex> %{"tags" => [_ | _]} = tags

    iex> {:error, %Fred.Error{type: :option_error}} =
    ...>   Fred.Series.tags("UNRATE", realtime_start: "Bad Input")

# `updates`

```elixir
@spec updates(opts :: keyword()) :: Fred.Client.response()
```

Get economic data series sorted by when observations were updated on the FRED server.

Results are limited to series updated within the last two weeks.

## Options

  * `:end_time` (struct of type `NaiveDateTime`) - End time for filtering updates.

* `:filter_value` (`t:atom/0`) - Tag group filter. Supported values are:
  - `:macro`
  - `:regional`
  - `:all`

* `:limit` (`t:pos_integer/0`) - Max results (between 1-1000).

* `:offset` (`t:pos_integer/0`) - Result offset.

* `:realtime_end` (struct of type `Date`) - End of the real-time period.

* `:realtime_start` (struct of type `Date`) - Start of the real-time period.

* `:sort_order` (`t:atom/0`) - The sort order of the results. Supported values are:
  - `:asc`
  - `:desc`

* `:start_time` (struct of type `NaiveDateTime`) - Start time for filtering updates.

## Examples

    iex> {:ok, series} = Fred.Series.updates(limit: 20, filter_value: :macro)
    iex> %{"seriess" => [_ | _]} = series

    iex> {:error, %Fred.Error{type: :option_error}} =
    ...>   Fred.Series.updates(realtime_start: "Bad Input")

# `vintage_dates`

```elixir
@spec vintage_dates(series_id :: String.t(), opts :: keyword()) ::
  Fred.Client.response()
```

Get the dates in history when a series' data values were revised or new data
values were released.

Vintage dates are the release dates for a series excluding release dates when
the data for the series did not change.

## Options

  * `:limit` (`t:pos_integer/0`) - Max results (between 1-10000).

* `:offset` (`t:pos_integer/0`) - Result offset.

* `:realtime_end` (struct of type `Date`) - End of the real-time period.

* `:realtime_start` (struct of type `Date`) - Start of the real-time period.

* `:sort_order` (`t:atom/0`) - The sort order of the results. Supported values are:
  - `:asc`
  - `:desc`

## Examples

    iex> {:ok, vintage_dates} = Fred.Series.vintage_dates("GDP")
    iex> %{"vintage_dates" => [_ | _]} = vintage_dates

    iex> {:error, %Fred.Error{type: :option_error}} =
    ...>   Fred.Series.vintage_dates("GDP", realtime_start: "Bad Input")

---

*Consult [api-reference.md](api-reference.md) for complete listing*
