[Feature] Add EIA Daily Spot Prices Data via FRED (#6677)

* add EIA daily spot prices data via FRED

* line too long

* comment out the test skipped test

* fix test?

* delete commented out sections

* unused argument

* name things like Minh says

---------

Co-authored-by: Igor Radovanovic <74266147+IgorWounds@users.noreply.github.com>
This commit is contained in:
Danglewood
2024-10-03 12:47:44 -07:00
committed by GitHub
parent c786852080
commit b9de848bc3
17 changed files with 1273 additions and 518 deletions

View File

@@ -0,0 +1,52 @@
"""Commodity Spot Prices Standard Model."""
from datetime import (
date as dateType,
)
from typing import Optional
from pydantic import Field
from openbb_core.provider.abstract.data import Data
from openbb_core.provider.abstract.query_params import QueryParams
from openbb_core.provider.utils.descriptions import (
DATA_DESCRIPTIONS,
QUERY_DESCRIPTIONS,
)
class CommoditySpotPricesQueryParams(QueryParams):
"""Commodity Spot Prices Query."""
start_date: Optional[dateType] = Field(
default=None,
description=QUERY_DESCRIPTIONS.get("start_date", ""),
)
end_date: Optional[dateType] = Field(
default=None,
description=QUERY_DESCRIPTIONS.get("end_date", ""),
)
class CommoditySpotPricesData(Data):
"""Commodity Spot Prices Data."""
date: dateType = Field(
description=DATA_DESCRIPTIONS.get("date", ""),
)
symbol: Optional[str] = Field(
default=None,
description=DATA_DESCRIPTIONS.get("symbol", ""),
)
commodity: Optional[str] = Field(
default=None,
description="Commodity name.",
)
price: float = Field(
description="Price of the commodity.",
json_schema_extra={"x-unit_measurement": "currency"},
)
unit: Optional[str] = Field(
default=None,
description="Unit of the commodity price.",
)

View File

@@ -25,33 +25,24 @@ def headers():
[
(
{
"asset": "gold",
"commodity": "all",
"start_date": None,
"end_date": None,
"collapse": None,
"frequency": None,
"transform": None,
"provider": "nasdaq",
}
),
(
{
"asset": "silver",
"start_date": "1990-01-01",
"end_date": "2023-01-01",
"collapse": "monthly",
"transform": "diff",
"provider": "nasdaq",
"aggregation_method": None,
"provider": "fred",
}
),
],
)
@pytest.mark.integration
def test_commodity_lbma_fixing(params, headers):
"""Test the LBMA fixing endpoint."""
def test_commodity_price_spot(params, headers):
"""Test the commodity spot prices endpoint."""
params = {p: v for p, v in params.items() if v}
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/commodity/lbma_fixing?{query_str}"
url = f"http://0.0.0.0:8000/api/v1/commodity/price/spot?{query_str}"
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200

View File

@@ -20,32 +20,23 @@ def obb(pytestconfig): # pylint: disable=inconsistent-return-statements
[
(
{
"asset": "gold",
"commodity": "all",
"start_date": None,
"end_date": None,
"collapse": None,
"frequency": None,
"transform": None,
"provider": "nasdaq",
}
),
(
{
"asset": "silver",
"start_date": "1990-01-01",
"end_date": "2023-01-01",
"collapse": "monthly",
"transform": "diff",
"provider": "nasdaq",
"aggregation_method": None,
"provider": "fred",
}
),
],
)
@pytest.mark.integration
def test_commodity_lbma_fixing(params, obb):
"""Test the LBMA fixing endpoint."""
def test_commodity_price_spot(params, obb):
"""Test the commodity spot prices endpoint."""
params = {p: v for p, v in params.items() if v}
result = obb.commodity.lbma_fixing(**params)
result = obb.commodity.price.spot(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0

View File

@@ -1,5 +1,8 @@
"""The Commodity router."""
# pylint: disable=unused-argument,unused-import
# flake8: noqa: F401
from openbb_core.app.model.command_context import CommandContext
from openbb_core.app.model.example import APIEx
from openbb_core.app.model.obbject import OBBject
@@ -11,32 +14,9 @@ from openbb_core.app.provider_interface import (
from openbb_core.app.query import Query
from openbb_core.app.router import Router
from openbb_commodity.price.price_router import router as price_router
router = Router(prefix="", description="Commodity market data.")
# pylint: disable=unused-argument
@router.command(
model="LbmaFixing",
examples=[
APIEx(parameters={"provider": "nasdaq"}),
APIEx(
description="Get the daily LBMA fixing prices for silver in 2023.",
parameters={
"asset": "silver",
"start_date": "2023-01-01",
"end_date": "2023-12-31",
"transform": "rdiff",
"collapse": "monthly",
"provider": "nasdaq",
},
),
],
)
async def lbma_fixing(
cc: CommandContext,
provider_choices: ProviderChoices,
standard_params: StandardParams,
extra_params: ExtraParams,
) -> OBBject:
"""Daily LBMA Fixing Prices in USD/EUR/GBP."""
return await OBBject.from_query(Query(**locals()))
router.include_router(price_router)

View File

@@ -0,0 +1 @@
"""Commodity Price."""

View File

@@ -0,0 +1,33 @@
"""Price Router."""
# pylint: disable=unused-argument
from openbb_core.app.model.command_context import CommandContext
from openbb_core.app.model.example import APIEx
from openbb_core.app.model.obbject import OBBject
from openbb_core.app.provider_interface import (
ExtraParams,
ProviderChoices,
StandardParams,
)
from openbb_core.app.query import Query
from openbb_core.app.router import Router
router = Router(prefix="/price")
@router.command(
model="CommoditySpotPrices",
examples=[
APIEx(parameters={"provider": "fred"}),
APIEx(parameters={"provider": "fred", "commodity": "wti"}),
],
)
async def spot(
cc: CommandContext,
provider_choices: ProviderChoices,
standard_params: StandardParams,
extra_params: ExtraParams,
) -> OBBject:
"""Commodity Spot Prices."""
return await OBBject.from_query(Query(**locals()))

View File

@@ -39,6 +39,185 @@
}
},
"paths": {
"/commodity/price/spot": {
"deprecated": {
"flag": null,
"message": null
},
"description": "Commodity Spot Prices.",
"examples": "\nExamples\n--------\n\n```python\nfrom openbb import obb\nobb.commodity.price.spot(provider='fred')\nobb.commodity.price.spot(provider='fred', commodity=wti)\n```\n\n",
"parameters": {
"standard": [
{
"name": "start_date",
"type": "Union[date, str]",
"description": "Start date of the data, in YYYY-MM-DD format.",
"default": null,
"optional": true,
"choices": null
},
{
"name": "end_date",
"type": "Union[date, str]",
"description": "End date of the data, in YYYY-MM-DD format.",
"default": null,
"optional": true,
"choices": null
}
],
"fred": [
{
"name": "commodity",
"type": "Literal['wti', 'brent', 'natural_gas', 'jet_fuel', 'propane', 'heating_oil', 'diesel_gulf_coast', 'diesel_ny_harbor', 'diesel_la', 'gasoline_ny_harbor', 'gasoline_gulf_coast', 'rbob', 'all']",
"description": "Commodity name associated with the EIA spot price commodity data, default is 'all'.",
"default": "all",
"optional": true,
"choices": [
"wti",
"brent",
"natural_gas",
"jet_fuel",
"propane",
"heating_oil",
"diesel_gulf_coast",
"diesel_ny_harbor",
"diesel_la",
"gasoline_ny_harbor",
"gasoline_gulf_coast",
"rbob",
"all"
]
},
{
"name": "frequency",
"type": "Literal['a', 'q', 'm', 'w', 'd', 'wef', 'weth', 'wew', 'wetu', 'wem', 'wesu', 'wesa', 'bwew', 'bwem']",
"description": "Frequency aggregation to convert high frequency data to lower frequency.\n None = No change\n a = Annual\n q = Quarterly\n m = Monthly\n w = Weekly\n d = Daily\n wef = Weekly, Ending Friday\n weth = Weekly, Ending Thursday\n wew = Weekly, Ending Wednesday\n wetu = Weekly, Ending Tuesday\n wem = Weekly, Ending Monday\n wesu = Weekly, Ending Sunday\n wesa = Weekly, Ending Saturday\n bwew = Biweekly, Ending Wednesday\n bwem = Biweekly, Ending Monday",
"default": null,
"optional": true,
"choices": [
"a",
"q",
"m",
"w",
"d",
"wef",
"weth",
"wew",
"wetu",
"wem",
"wesu",
"wesa",
"bwew",
"bwem"
]
},
{
"name": "aggregation_method",
"type": "Literal['avg', 'sum', 'eop']",
"description": "A key that indicates the aggregation method used for frequency aggregation.\n This parameter has no affect if the frequency parameter is not set.\n avg = Average\n sum = Sum\n eop = End of Period",
"default": "eop",
"optional": true,
"choices": [
"avg",
"sum",
"eop"
]
},
{
"name": "transform",
"type": "Literal['chg', 'ch1', 'pch', 'pc1', 'pca', 'cch', 'cca', 'log']",
"description": "Transformation type\n None = No transformation\n chg = Change\n ch1 = Change from Year Ago\n pch = Percent Change\n pc1 = Percent Change from Year Ago\n pca = Compounded Annual Rate of Change\n cch = Continuously Compounded Rate of Change\n cca = Continuously Compounded Annual Rate of Change\n log = Natural Log",
"default": null,
"optional": true,
"choices": [
"chg",
"ch1",
"pch",
"pc1",
"pca",
"cch",
"cca",
"log"
]
}
]
},
"returns": {
"OBBject": [
{
"name": "results",
"type": "List[CommoditySpotPrices]",
"description": "Serializable results."
},
{
"name": "provider",
"type": "Optional[Literal['fred']]",
"description": "Provider name."
},
{
"name": "warnings",
"type": "Optional[List[Warning_]]",
"description": "List of warnings."
},
{
"name": "chart",
"type": "Optional[Chart]",
"description": "Chart object."
},
{
"name": "extra",
"type": "Dict[str, Any]",
"description": "Extra info."
}
]
},
"data": {
"standard": [
{
"name": "date",
"type": "Union[date, str]",
"description": "The date of the data.",
"default": "",
"optional": false,
"choices": null
},
{
"name": "symbol",
"type": "str",
"description": "Symbol representing the entity requested in the data.",
"default": null,
"optional": true,
"choices": null
},
{
"name": "commodity",
"type": "str",
"description": "Commodity name.",
"default": null,
"optional": true,
"choices": null
},
{
"name": "price",
"type": "float",
"description": "Price of the commodity.",
"default": "",
"optional": false,
"choices": null
},
{
"name": "unit",
"type": "str",
"description": "Unit of the commodity price.",
"default": null,
"optional": true,
"choices": null
}
],
"fred": []
},
"model": "CommoditySpotPrices"
},
"/crypto/price/historical": {
"deprecated": {
"flag": null,
@@ -5668,7 +5847,7 @@
{
"name": "frequency",
"type": "Literal['a', 'q', 'm', 'w', 'd', 'wef', 'weth', 'wew', 'wetu', 'wem', 'wesu', 'wesa', 'bwew', 'bwem']",
"description": "Frequency aggregation to convert high frequency data to lower frequency.\n \n None = No change\n \n a = Annual\n \n q = Quarterly\n \n m = Monthly\n \n w = Weekly\n \n d = Daily\n \n wef = Weekly, Ending Friday\n \n weth = Weekly, Ending Thursday\n \n wew = Weekly, Ending Wednesday\n \n wetu = Weekly, Ending Tuesday\n \n wem = Weekly, Ending Monday\n \n wesu = Weekly, Ending Sunday\n \n wesa = Weekly, Ending Saturday\n \n bwew = Biweekly, Ending Wednesday\n \n bwem = Biweekly, Ending Monday",
"description": "Frequency aggregation to convert high frequency data to lower frequency.\n None = No change\n a = Annual\n q = Quarterly\n m = Monthly\n w = Weekly\n d = Daily\n wef = Weekly, Ending Friday\n weth = Weekly, Ending Thursday\n wew = Weekly, Ending Wednesday\n wetu = Weekly, Ending Tuesday\n wem = Weekly, Ending Monday\n wesu = Weekly, Ending Sunday\n wesa = Weekly, Ending Saturday\n bwew = Biweekly, Ending Wednesday\n bwem = Biweekly, Ending Monday",
"default": null,
"optional": true,
"choices": [
@@ -5691,7 +5870,7 @@
{
"name": "aggregation_method",
"type": "Literal['avg', 'sum', 'eop']",
"description": "A key that indicates the aggregation method used for frequency aggregation.\n This parameter has no affect if the frequency parameter is not set.\n \n avg = Average\n \n sum = Sum\n \n eop = End of Period",
"description": "A key that indicates the aggregation method used for frequency aggregation.\n This parameter has no affect if the frequency parameter is not set.\n avg = Average\n sum = Sum\n eop = End of Period",
"default": "eop",
"optional": true,
"choices": [
@@ -5703,7 +5882,7 @@
{
"name": "transform",
"type": "Literal['chg', 'ch1', 'pch', 'pc1', 'pca', 'cch', 'cca', 'log']",
"description": "Transformation type\n \n None = No transformation\n \n chg = Change\n \n ch1 = Change from Year Ago\n \n pch = Percent Change\n \n pc1 = Percent Change from Year Ago\n \n pca = Compounded Annual Rate of Change\n \n cch = Continuously Compounded Rate of Change\n \n cca = Continuously Compounded Annual Rate of Change\n \n log = Natural Log",
"description": "Transformation type\n None = No transformation\n chg = Change\n ch1 = Change from Year Ago\n pch = Percent Change\n pc1 = Percent Change from Year Ago\n pca = Compounded Annual Rate of Change\n cch = Continuously Compounded Rate of Change\n cca = Continuously Compounded Annual Rate of Change\n log = Natural Log",
"default": null,
"optional": true,
"choices": [
@@ -38700,6 +38879,9 @@
}
},
"routers": {
"/commodity": {
"description": "Commodity market data."
},
"/crypto": {
"description": "Cryptocurrency market data."
},

View File

@@ -8,6 +8,7 @@ class Extensions(Container):
# fmt: off
"""
Routers:
/commodity
/crypto
/currency
/derivatives
@@ -52,6 +53,13 @@ Extensions:
def __repr__(self) -> str:
return self.__doc__ or ""
@property
def commodity(self):
# pylint: disable=import-outside-toplevel
from . import commodity
return commodity.ROUTER_commodity(command_runner=self._command_runner)
@property
def crypto(self):
# pylint: disable=import-outside-toplevel

View File

@@ -0,0 +1,22 @@
### THIS FILE IS AUTO-GENERATED. DO NOT EDIT. ###
from openbb_core.app.static.container import Container
class ROUTER_commodity(Container):
"""/commodity
/price
"""
def __repr__(self) -> str:
return self.__doc__ or ""
@property
def price(self):
# pylint: disable=import-outside-toplevel
from . import commodity_price
return commodity_price.ROUTER_commodity_price(
command_runner=self._command_runner
)

805
openbb_platform/poetry.lock generated vendored

File diff suppressed because it is too large Load Diff

View File

@@ -5,6 +5,7 @@ from openbb_fred.models.ameribor import FredAmeriborFetcher
from openbb_fred.models.balance_of_payments import FredBalanceOfPaymentsFetcher
from openbb_fred.models.bond_indices import FredBondIndicesFetcher
from openbb_fred.models.commercial_paper import FREDCommercialPaperFetcher
from openbb_fred.models.commodity_spot_prices import FredCommoditySpotPricesFetcher
from openbb_fred.models.consumer_price_index import FREDConsumerPriceIndexFetcher
from openbb_fred.models.dwpcr_rates import FREDDiscountWindowPrimaryCreditRateFetcher
from openbb_fred.models.ecb_interest_rates import (
@@ -66,6 +67,7 @@ Research division of the Federal Reserve Bank of St. Louis that has more than
fetcher_dict={
"BalanceOfPayments": FredBalanceOfPaymentsFetcher,
"BondIndices": FredBondIndicesFetcher,
"CommoditySpotPrices": FredCommoditySpotPricesFetcher,
"ConsumerPriceIndex": FREDConsumerPriceIndexFetcher,
"USYieldCurve": FREDUSYieldCurveFetcher,
"SOFR": FREDSOFRFetcher,

View File

@@ -0,0 +1,249 @@
"""FRED Commodity Spot Prices Model."""
# pylint: disable=unused-argument
from typing import Any, Literal, Optional
from openbb_core.app.model.abstract.error import OpenBBError
from openbb_core.provider.abstract.annotated_result import AnnotatedResult
from openbb_core.provider.abstract.fetcher import Fetcher
from openbb_core.provider.standard_models.commodity_spot_prices import (
CommoditySpotPricesData,
CommoditySpotPricesQueryParams,
)
from openbb_core.provider.utils.errors import EmptyDataError
from pydantic import Field
SERIES_MAP = {
"wti": "DCOILWTICO",
"brent": "DCOILBRENTEU",
"natural_gas": "DHHNGSP",
"jet_fuel": "DJFUELUSGULF",
"propane": "DPROPANEMBTX",
"heating_oil": "DHOILNYH",
"diesel_gulf_coast": "DDFUELUSGULF",
"diesel_ny_harbor": "DDFUELNYH",
"diesel_la": "DDFUELLA",
"gasoline_ny_harbor": "DGASNYH",
"gasoline_gulf_coast": "DGASUSGULF",
"rbob": "DRGASLA",
"all": "DCOILWTICO,DCOILBRENTEU,DHHNGSP,DJFUELUSGULF,"
"DPROPANEMBTX,DHOILNYH,DDFUELUSGULF,DDFUELNYH,"
"DDFUELLA,DGASNYH,DGASUSGULF,DRGASLA",
}
class FredCommoditySpotPricesQueryParams(CommoditySpotPricesQueryParams):
"""FRED Commodity Spot Prices Query Params."""
__json_schema_extra__ = {
"commodity": {"multiple_items_allowed": False, "choices": list(SERIES_MAP)},
"frequency": {
"multiple_items_allowed": False,
"choices": [
"a",
"q",
"m",
"w",
"d",
"wef",
"weth",
"wew",
"wetu",
"wem",
"wesu",
"wesa",
"bwew",
"bwem",
],
},
"aggregation_method": {
"multiple_items_allowed": False,
"choices": ["avg", "sum", "eop"],
},
"transform": {
"multiple_items_allowed": False,
"choices": [
"chg",
"ch1",
"pch",
"pc1",
"pca",
"cch",
"cca",
"log",
],
},
}
commodity: Literal[
"wti",
"brent",
"natural_gas",
"jet_fuel",
"propane",
"heating_oil",
"diesel_gulf_coast",
"diesel_ny_harbor",
"diesel_la",
"gasoline_ny_harbor",
"gasoline_gulf_coast",
"rbob",
"all",
] = Field(
default="all",
description="Commodity name associated with the EIA spot price commodity data, default is 'all'.",
)
frequency: Optional[
Literal[
"a",
"q",
"m",
"w",
"d",
"wef",
"weth",
"wew",
"wetu",
"wem",
"wesu",
"wesa",
"bwew",
"bwem",
]
] = Field(
default=None,
description="""Frequency aggregation to convert high frequency data to lower frequency.
None = No change
a = Annual
q = Quarterly
m = Monthly
w = Weekly
d = Daily
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
""",
)
aggregation_method: Literal["avg", "sum", "eop"] = Field(
default="eop",
description="""A key that indicates the aggregation method used for frequency aggregation.
This parameter has no affect if the frequency parameter is not set.
avg = Average
sum = Sum
eop = End of Period
""",
)
transform: Optional[
Literal["chg", "ch1", "pch", "pc1", "pca", "cch", "cca", "log"]
] = Field(
default=None,
description="""Transformation type
None = No transformation
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
""",
)
class FredCommoditySpotPricesData(CommoditySpotPricesData):
"""FRED Commodity Spot Prices Data."""
class FredCommoditySpotPricesFetcher(
Fetcher[FredCommoditySpotPricesQueryParams, list[FredCommoditySpotPricesData]]
):
"""FRED Commodity Spot Prices Fetcher."""
@staticmethod
def transform_query(params: dict[str, Any]) -> FredCommoditySpotPricesQueryParams:
"""Transform query."""
return FredCommoditySpotPricesQueryParams(**params)
@staticmethod
async def aextract_data(
query: FredCommoditySpotPricesQueryParams,
credentials: Optional[dict[str, str]],
**kwargs: Any,
) -> dict:
"""Extract the data from the FRED API."""
# pylint: disable=import-outside-toplevel
from datetime import datetime, timedelta # noqa
from openbb_fred.models.series import FredSeriesFetcher
symbols = SERIES_MAP[query.commodity]
series_query = {
"symbol": symbols,
"start_date": (
query.start_date
if query.start_date is not None
else (datetime.now() - timedelta(weeks=156)).date()
),
"end_date": (
query.end_date if query.end_date is not None else datetime.now().date()
),
"frequency": query.frequency,
"aggregation_method": query.aggregation_method,
"transform": query.transform,
}
try:
results = await FredSeriesFetcher.fetch_data(series_query, credentials)
return {
"result": results.result,
"metadata": results.metadata,
}
except Exception as e:
raise OpenBBError(f"Failed to fetch data from FRED API: {e}") from e
@staticmethod
def transform_data(
query: FredCommoditySpotPricesQueryParams, data: dict, **kwargs: Any
) -> AnnotatedResult[list[FredCommoditySpotPricesData]]:
"""Transform the data."""
# pylint: disable=import-outside-toplevel
from pandas import DataFrame
results = data.get("result", [])
if not results:
raise EmptyDataError("The request was returned with no data.")
metadata = data.get("metadata", {})
title_map = {k: v.get("title") for k, v in metadata.items()}
units_map = {k: v.get("units") for k, v in metadata.items()}
df = DataFrame([d.model_dump() for d in results])
df = (
df.melt(
id_vars="date",
value_vars=[d for d in df.columns if d != "date"],
value_name="price",
var_name="symbol",
)
.dropna()
.sort_values(by="date")
)
df = df.reset_index(drop=True)
df.loc[:, "commodity"] = df.symbol.map(title_map)
df.loc[:, "unit"] = df.symbol.map(units_map)
records = df.to_dict(orient="records")
return AnnotatedResult(
result=[FredCommoditySpotPricesData.model_validate(r) for r in records],
metadata=metadata,
)

View File

@@ -24,7 +24,45 @@ class FredSeriesQueryParams(SeriesQueryParams):
"end_date": "observation_end",
"transform": "units",
}
__json_schema_extra__ = {"symbol": {"multiple_items_allowed": True}}
__json_schema_extra__ = {
"symbol": {"multiple_items_allowed": True},
"frequency": {
"multiple_items_allowed": False,
"choices": [
"a",
"q",
"m",
"w",
"d",
"wef",
"weth",
"wew",
"wetu",
"wem",
"wesu",
"wesa",
"bwew",
"bwem",
],
},
"aggregation_method": {
"multiple_items_allowed": False,
"choices": ["avg", "sum", "eop"],
},
"transform": {
"multiple_items_allowed": False,
"choices": [
"chg",
"ch1",
"pch",
"pc1",
"pca",
"cch",
"cca",
"log",
],
},
}
frequency: Optional[
Literal[
@@ -46,69 +84,47 @@ class FredSeriesQueryParams(SeriesQueryParams):
] = Field(
default=None,
description="""Frequency aggregation to convert high frequency data to lower frequency.
\n None = No change
\n a = Annual
\n q = Quarterly
\n m = Monthly
\n w = Weekly
\n d = Daily
\n wef = Weekly, Ending Friday
\n weth = Weekly, Ending Thursday
\n wew = Weekly, Ending Wednesday
\n wetu = Weekly, Ending Tuesday
\n wem = Weekly, Ending Monday
\n wesu = Weekly, Ending Sunday
\n wesa = Weekly, Ending Saturday
\n bwew = Biweekly, Ending Wednesday
\n bwem = Biweekly, Ending Monday
None = No change
a = Annual
q = Quarterly
m = Monthly
w = Weekly
d = Daily
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
""",
json_schema_extra={
"choices": [
"a",
"q",
"m",
"w",
"d",
"wef",
"weth",
"wew",
"wetu",
"wem",
"wesu",
"wesa",
"bwew",
"bwem",
]
},
)
aggregation_method: Optional[Literal["avg", "sum", "eop"]] = Field(
default="eop",
description="""A key that indicates the aggregation method used for frequency aggregation.
This parameter has no affect if the frequency parameter is not set.
\n avg = Average
\n sum = Sum
\n eop = End of Period
avg = Average
sum = Sum
eop = End of Period
""",
json_schema_extra={"choices": ["avg", "sum", "eop"]},
)
transform: Optional[
Literal["chg", "ch1", "pch", "pc1", "pca", "cch", "cca", "log"]
] = Field(
default=None,
description="""Transformation type
\n None = No transformation
\n chg = Change
\n ch1 = Change from Year Ago
\n pch = Percent Change
\n pc1 = Percent Change from Year Ago
\n pca = Compounded Annual Rate of Change
\n cch = Continuously Compounded Rate of Change
\n cca = Continuously Compounded Annual Rate of Change
\n log = Natural Log
None = No transformation
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
""",
json_schema_extra={
"choices": ["chg", "ch1", "pch", "pc1", "pca", "cch", "cca", "log"]
},
)
limit: int = Field(description=QUERY_DESCRIPTIONS.get("limit", ""), default=100000)

View File

@@ -0,0 +1,114 @@
interactions:
- request:
body: null
headers:
Accept:
- application/json
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
method: GET
uri: https://api.stlouisfed.org/fred/series/observations?aggregation_method=eop&api_key=MOCK_API_KEY&file_type=json&limit=100000&observation_end=2024-07-10&observation_start=2024-07-01&series_id=DHHNGSP
response:
body:
string: !!binary |
H4sIAAAAAAAEA6pWKkpNzCnJzE2NLy5JLCpRslIyMjAy0TWw1DW0UNJByKbmpaDL5ScVpxaVJZZk
5uehaTbXNTBU0lFCVoCs31zX0EBJR6k0L7OkWMlKKSczD6S4tKSgtCS+pLIgVcnKUEcpLTMnFcpT
yirOByspSkktik+qVLJCMTolsSRVSUepOL+oJD4fpETJSimxOFlJRyk5vzSvRMnKQkcpPy2tOLVE
ycpARyknMzezRMnK0AAEUBxZrGQVTUmAgB0CC0BoGJQl5pSmgkJOz8hQqVaHmsYbKekoIYw3MKOy
8caoxhtR2XgTJOP1qGy2KZLZRnoG1HY6KGMgAp7a0WqJ4ngTKjsenPMQjgfMRKk2thYA+CTarwUE
AAA=
headers:
Cache-Control:
- max-age=0, no-cache
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Length:
- '287'
Content-Type:
- application/json; charset=UTF-8
Date:
- Wed, 18 Sep 2024 20:45:15 GMT
Expires:
- Wed, 18 Sep 2024 20:45:15 GMT
Last-Modified:
- Wed, 18 Sep 2024 17:31:01 GMT
Pragma:
- no-cache
Server:
- Apache
Set-Cookie:
- cookiesession1=678A3E1F3E4DC09007890C31D5BEF27D;Expires=Thu, 18 Sep 2025 20:45:15
GMT;Path=/;Secure;HttpOnly
- ak_bmsc=E097556194BD6EBE95EBC9BFD47E6028~000000000000000000000000000000~YAAQi03bF7wfUeCRAQAAntLhBhkWXUUyu3D1NHcXN2HwQb+AuwSjQA2/LmrGXxn3cka4F9ld4nAHIAgzgptVAAFRM3NJ5+OXAAosFGsz8CX4y9Toe05ZO5+ZljjrKCsGF7zV0pRqLcj3f9Jrnu+4kEtI2s21Tyj+AHnRKt5ciKiFpltHhRtdH0lpJLpzgufFa47ymLgPJoT0+lBwdoT+shaCiHVQkhxq7oD92OKP9C2fe1Mhvmcf3cX8lh+bFwmUmoY1bX6iqV5eGvMlL7NC4I4DZU3iK/ihgdNFIgxMpx61goe4N0RBFE3clHZQMs6O443qGhpPwHCGoZufxbcs/dIur5YqJCPw8qeS+xiRZZ2YIy2Shb9/b7WCJSDYuksL;
Domain=.stlouisfed.org; Path=/; Expires=Wed, 18 Sep 2024 22:45:15 GMT; Max-Age=7200
Strict-Transport-Security:
- max-age=86400
Vary:
- Accept-Encoding
status:
code: 200
message: OK
- request:
body: null
headers:
Accept:
- application/json
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
Cookie:
- ak_bmsc=E097556194BD6EBE95EBC9BFD47E6028~000000000000000000000000000000~YAAQi03bF7wfUeCRAQAAntLhBhkWXUUyu3D1NHcXN2HwQb+AuwSjQA2/LmrGXxn3cka4F9ld4nAHIAgzgptVAAFRM3NJ5+OXAAosFGsz8CX4y9Toe05ZO5+ZljjrKCsGF7zV0pRqLcj3f9Jrnu+4kEtI2s21Tyj+AHnRKt5ciKiFpltHhRtdH0lpJLpzgufFa47ymLgPJoT0+lBwdoT+shaCiHVQkhxq7oD92OKP9C2fe1Mhvmcf3cX8lh+bFwmUmoY1bX6iqV5eGvMlL7NC4I4DZU3iK/ihgdNFIgxMpx61goe4N0RBFE3clHZQMs6O443qGhpPwHCGoZufxbcs/dIur5YqJCPw8qeS+xiRZZ2YIy2Shb9/b7WCJSDYuksL;
cookiesession1=678A3E1F3E4DC09007890C31D5BEF27D
method: GET
uri: https://api.stlouisfed.org/fred/series?api_key=MOCK_API_KEY&file_type=json&series_id=DHHNGSP
response:
body:
string: !!binary |
H4sIAAAAAAAEA6pWKkpNzCnJzE2NLy5JLCpRslIyMjAy0TWw1DW0UNJByKbmpaDLFacWZaYWFytZ
RVcrZYJkXTw8/NyDA5C1kWxoSWZJTqqSlZJHal5RpYJHaZKCX2JJaVFijoJ7YrFCcEF+iUJAUWZy
qpKOUn5ScWpRWWJJZn4e3PGGlpbmugaGugbmaArQ3A+STitKLSxNzUuuVLJScknMzKlU0lGCi8UX
Z+SDg8NFSUepNC+zpBikKj8nJ7GoWKEgtUjBNzMnJzM/T8EpJBSmAq5HRSEAokIPKl2cmlicn5eY
E5+YklVaXJKbmgcKab/8EoVgqExOpYIjWC41RUlHCYt6uOF+wY5KOko5icUl8aUFKYklqaCgR0Sa
gqGRlbGhFSgMTJV0lAryC0pzEosySyqVrMxMdJTy8ktSQV7xzS9KVcjMS8svygWHoEJiUn5piUJJ
RmaxAiRiFZIT8xSSUhXS8kvzUhQSSxQySkoKrGL0Y/TLy8v1UjMT9dLzy2L0U/ISy2L089Jj9EOS
clxS04pBHMDiC4oy49NKS+JLknJSUtOM9BKLC5RqY2sBaKVzPW8CAAA=
headers:
Cache-Control:
- max-age=0, no-cache
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Length:
- '440'
Content-Type:
- application/json; charset=UTF-8
Date:
- Wed, 18 Sep 2024 20:45:15 GMT
Expires:
- Wed, 18 Sep 2024 20:45:15 GMT
Last-Modified:
- Wed, 18 Sep 2024 17:31:01 GMT
Pragma:
- no-cache
Server:
- Apache
Set-Cookie:
- ak_bmsc=E097556194BD6EBE95EBC9BFD47E6028~000000000000000000000000000000~YAAQi03bFxEgUeCRAQAAVdPhBhmCP//g04q0JLFpVCOfSiSr2N74GguAwHhujjvb7O/dN1n3dR31nJhY3gS+m5FATlv2TbEUs7XiWjtjejZo1LQwMiNJbJlBr4GN3lSaeuEJXUaM7NahM00mJDav1AlksVdioFDsK8qUuL9ACV38J8Xv4gFPAo0Uzzma0te6fplKsT5Fk2AihQx1skpu1rtsAIPjBKz1jK2Zq5dDnMYw6xLGtBxSZ5zWlcNYMIxurirPDIMAvqWXybhf1Gu7+oOoctoLC8RXaW2/9hjF1UQr5PXcvXWUF4GQDC5eziHACFnNwmDpTJc6qTkT8WQDpCrjYPc2xQrUaJsxiPM+cUS3HuxEDmRKRj2sdM9r9XYYb0uVhPPi3aphsihV1v2boA==;
Domain=.stlouisfed.org; Path=/; Expires=Wed, 18 Sep 2024 22:45:15 GMT; Max-Age=7200
- bm_sv=62B1FC612346E802F558E479E19FAB44~YAAQi03bFxIgUeCRAQAAVdPhBhnHWQJ4jBA1ptR9N8x94P1AWgu887s7dp+uanShkebuaR10e1ml4OJ1wRh83u+PZG0Yt0jpN8O8SFT+YmtV06EtTRZQy9L7GvJBPR5Fhjq0AR/r1z267ijptbxFdFFH3x4803D3X+Ug8s5U9dbkGEJ9KhtVqpSn+5dxGpvkQMCzg1zJx3ngp/7QzeotmKb41h413tZQAFa7QgSPgdHCB3vehmVK3JCvF6suejJIl7axDg==~1;
Domain=.stlouisfed.org; Path=/; Expires=Wed, 18 Sep 2024 22:45:15 GMT; Max-Age=7200;
Secure
Strict-Transport-Security:
- max-age=86400
Vary:
- Accept-Encoding
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,103 @@
interactions:
- request:
body: null
headers:
Accept:
- application/json
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
method: GET
uri: https://api.stlouisfed.org/fred/series/observations?aggregation_method=eop&api_key=MOCK_API_KEY&file_type=json&limit=100000&observation_end=2024-07-10&observation_start=2024-07-01&series_id=DHHNGSP
response:
body:
string: !!binary |
H4sIAAAAAAAEA6pWKkpNzCnJzE2NLy5JLCpRslIyMjAy0TWw1DW0UNJByKbmpaDL5ScVpxaVJZZk
5uehaTbXNTBU0lFCVoCs31zX0EBJR6k0L7OkWMlKKSczD6S4tKSgtCS+pLIgVcnKUEcpLTMnFcpT
yirOByspSkktik+qVLJCMTolsSRVSUepOL+oJD4fpETJSimxOFlJRyk5vzSvRMnKQkcpPy2tOLVE
ycpARyknMzezRMnK0AAEUBxZrGQVTUmAgB0CC0BoGJQl5pSmgkJOz8hQqVaHmsYbKekoIYw3MKOy
8caoxhtR2XgTJOP1qGy2KZLZRnoG1HY6KGMgAp7a0WqJ4ngTKjsenPMQjgfMRKk2thYA+CTarwUE
AAA=
headers:
Cache-Control:
- max-age=0, no-cache
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Length:
- '287'
Content-Type:
- application/json; charset=UTF-8
Date:
- Wed, 18 Sep 2024 20:31:30 GMT
Expires:
- Wed, 18 Sep 2024 20:31:30 GMT
Last-Modified:
- Wed, 18 Sep 2024 17:31:01 GMT
Pragma:
- no-cache
Server:
- Apache
Strict-Transport-Security:
- max-age=86400
Vary:
- Accept-Encoding
status:
code: 200
message: OK
- request:
body: null
headers:
Accept:
- application/json
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
method: GET
uri: https://api.stlouisfed.org/fred/series?api_key=MOCK_API_KEY&file_type=json&series_id=DHHNGSP
response:
body:
string: !!binary |
H4sIAAAAAAAEA6pWKkpNzCnJzE2NLy5JLCpRslIyMjAy0TWw1DW0UNJByKbmpaDLFacWZaYWFytZ
RVcrZYJkXTw8/NyDA5C1kWxoSWZJTqqSlZJHal5RpYJHaZKCX2JJaVFijoJ7YrFCcEF+iUJAUWZy
qpKOUn5ScWpRWWJJZn4e3PGGlpbmugaGugbmaArQ3A+STitKLSxNzUuuVLJScknMzKlU0lGCi8UX
Z+SDg8NFSUepNC+zpBikKj8nJ7GoWKEgtUjBNzMnJzM/T8EpJBSmAq5HRSEAokIPKl2cmlicn5eY
E5+YklVaXJKbmgcKab/8EoVgqExOpYIjWC41RUlHCYt6uOF+wY5KOko5icUl8aUFKYklqaCgR0Sa
gqGRlbGhFSgMTJV0lAryC0pzEosySyqVrMxMdJTy8ktSQV7xzS9KVcjMS8svygWHoEJiUn5piUJJ
RmaxAiRiFZIT8xSSUhXS8kvzUhQSSxQySkoKrGL0Y/TLy8v1UjMT9dLzy2L0U/ISy2L089Jj9EOS
clxS04pBHMDiC4oy49NKS+JLknJSUtOM9BKLC5RqY2sBaKVzPW8CAAA=
headers:
Cache-Control:
- max-age=0, no-cache
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Length:
- '440'
Content-Type:
- application/json; charset=UTF-8
Date:
- Wed, 18 Sep 2024 20:31:30 GMT
Expires:
- Wed, 18 Sep 2024 20:31:30 GMT
Last-Modified:
- Wed, 18 Sep 2024 17:31:01 GMT
Pragma:
- no-cache
Server:
- Apache
Set-Cookie:
- ak_bmsc=1FF7C50F81F03BCC5D72BDAA0849EEB2~000000000000000000000000000000~YAAQb/TVFxwfM3iRAQAAVjvVBhmIJR9H+TxkN5BZr8YWEQyS3JUG0tA7CiOfn9AcMnEUjiRYud8zpR4frzIgaF6Wf8vzlrA+G+Ojy9E/I3Cli9x25TBJtlfzlCyehUz0A7bW3htZky9ld7e9cbczJbMDFJWnM+IeV152BF9qaqStp77OeAEJvzTTuUcet/9oXFZd6Xv1GPch7gg1VRV9AQX9Jco0bAc9rh1oy0hmtVsdknVwMbrIWY62xX6XSLlEtrYSX/zfo3TUl1uR1Wr5KbOTKvL3kq5bHx8N1x5UYYE29MgQzX9c5q0jMG4a6N8RGNORA/TVKHYzdkf5VrEOVJS0Auhacoxbv/csxBcwiQnqKCHVAdR7Pjv0ealc8y5C;
Domain=.stlouisfed.org; Path=/; Expires=Wed, 18 Sep 2024 22:31:30 GMT; Max-Age=7200
Strict-Transport-Security:
- max-age=86400
Vary:
- Accept-Encoding
status:
code: 200
message: OK
version: 1

View File

@@ -8,6 +8,7 @@ from openbb_fred.models.ameribor import FredAmeriborFetcher
from openbb_fred.models.balance_of_payments import FredBalanceOfPaymentsFetcher
from openbb_fred.models.bond_indices import FredBondIndicesFetcher
from openbb_fred.models.commercial_paper import FREDCommercialPaperFetcher
from openbb_fred.models.commodity_spot_prices import FredCommoditySpotPricesFetcher
from openbb_fred.models.consumer_price_index import FREDConsumerPriceIndexFetcher
from openbb_fred.models.dwpcr_rates import FREDDiscountWindowPrimaryCreditRateFetcher
from openbb_fred.models.ecb_interest_rates import (
@@ -533,3 +534,17 @@ def test_fred_tips_yields_fetcher(credentials=test_credentials):
fetcher = FredTipsYieldsFetcher()
result = fetcher.test(params, credentials)
assert result is None
@pytest.mark.record_http
def test_fred_commodity_spot_prices_fetcher(credentials=test_credentials):
"""Test FRED Commodity Spot Prices."""
params = {
"start_date": datetime.date(2024, 7, 1),
"end_date": datetime.date(2024, 7, 10),
"commodity": "natural_gas",
}
fetcher = FredCommoditySpotPricesFetcher()
result = fetcher.test(params, credentials)
assert result is None

View File

@@ -10,7 +10,8 @@ from openbb_nasdaq.models.economic_calendar import NasdaqEconomicCalendarFetcher
from openbb_nasdaq.models.equity_screener import NasdaqEquityScreenerFetcher
from openbb_nasdaq.models.equity_search import NasdaqEquitySearchFetcher
from openbb_nasdaq.models.historical_dividends import NasdaqHistoricalDividendsFetcher
from openbb_nasdaq.models.lbma_fixing import NasdaqLbmaFixingFetcher
# from openbb_nasdaq.models.lbma_fixing import NasdaqLbmaFixingFetcher
from openbb_nasdaq.models.sp500_multiples import NasdaqSP500MultiplesFetcher
from openbb_nasdaq.models.top_retail import NasdaqTopRetailFetcher
@@ -31,7 +32,7 @@ unmatched technology, insights and markets expertise.""",
"EquitySearch": NasdaqEquitySearchFetcher,
"EquityScreener": NasdaqEquityScreenerFetcher,
"HistoricalDividends": NasdaqHistoricalDividendsFetcher,
"LbmaFixing": NasdaqLbmaFixingFetcher,
# "LbmaFixing": NasdaqLbmaFixingFetcher, TODO: Replace or Remove.
"SP500Multiples": NasdaqSP500MultiplesFetcher,
"TopRetail": NasdaqTopRetailFetcher,
},