summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanglewood <85772166+deeleeramone@users.noreply.github.com>2024-05-14 21:18:35 -0700
committerDanglewood <85772166+deeleeramone@users.noreply.github.com>2024-05-14 21:18:35 -0700
commit887204b120949f2f7f09e8fad8f3f1ef4202af19 (patch)
tree1c7bfb1299874e356accd52e32fe8ad266a79f56
parentb711bd8eff341c26e4e88efd90ae39df7606d160 (diff)
fmp yield curve
-rw-r--r--openbb_platform/providers/fmp/openbb_fmp/__init__.py3
-rw-r--r--openbb_platform/providers/fmp/openbb_fmp/models/yield_curve.py126
-rw-r--r--openbb_platform/providers/fmp/tests/record/http/test_fmp_fetchers/test_fmp_yield_curve_fetcher.yaml276
-rw-r--r--openbb_platform/providers/fmp/tests/test_fmp_fetchers.py11
4 files changed, 416 insertions, 0 deletions
diff --git a/openbb_platform/providers/fmp/openbb_fmp/__init__.py b/openbb_platform/providers/fmp/openbb_fmp/__init__.py
index 01f9a5019e5..d10dfdd2353 100644
--- a/openbb_platform/providers/fmp/openbb_fmp/__init__.py
+++ b/openbb_platform/providers/fmp/openbb_fmp/__init__.py
@@ -63,6 +63,8 @@ from openbb_fmp.models.risk_premium import FMPRiskPremiumFetcher
from openbb_fmp.models.share_statistics import FMPShareStatisticsFetcher
from openbb_fmp.models.treasury_rates import FMPTreasuryRatesFetcher
from openbb_fmp.models.world_news import FMPWorldNewsFetcher
+from openbb_fmp.models.yield_curve import FMPYieldCurveFetcher
+
fmp_provider = Provider(
name="fmp",
@@ -134,6 +136,7 @@ stock market information (news, currencies, and stock prices).""",
"TreasuryRates": FMPTreasuryRatesFetcher,
"WorldNews": FMPWorldNewsFetcher,
"EtfHistorical": FMPEquityHistoricalFetcher,
+ "YieldCurve": FMPYieldCurveFetcher,
},
repr_name="Financial Modeling Prep (FMP)",
v3_credentials=["API_KEY_FINANCIALMODELINGPREP"],
diff --git a/openbb_platform/providers/fmp/openbb_fmp/models/yield_curve.py b/openbb_platform/providers/fmp/openbb_fmp/models/yield_curve.py
new file mode 100644
index 00000000000..8e2e3d8f245
--- /dev/null
+++ b/openbb_platform/providers/fmp/openbb_fmp/models/yield_curve.py
@@ -0,0 +1,126 @@
+"""FMP Yield Curve Model."""
+
+# pylint: disable=unused-argument
+
+from datetime import datetime, timedelta
+from typing import Any, Dict, List, Optional
+
+from openbb_core.provider.abstract.fetcher import Fetcher
+from openbb_core.provider.standard_models.yield_curve import (
+ YieldCurveData,
+ YieldCurveQueryParams,
+)
+from openbb_core.provider.utils.errors import EmptyDataError
+from openbb_core.provider.utils.helpers import amake_requests
+from pandas import Categorical, DataFrame, DatetimeIndex
+
+maturity_dict = {
+ "month1": "month_1",
+ "month2": "month_2",
+ "month3": "month_3",
+ "month6": "month_6",
+ "year1": "year_1",
+ "year2": "year_2",
+ "year3": "year_3",
+ "year5": "year_5",
+ "year7": "year_7",
+ "year10": "year_10",
+ "year20": "year_20",
+ "year30": "year_30",
+}
+
+
+class FMPYieldCurveQueryParams(YieldCurveQueryParams):
+ """FMP Yield Curve Query.
+
+ Source: https://site.financialmodelingprep.com/developer/docs/treasury-rates-api/
+ """
+
+ __json_schema_extra__ = {"date": {"multiple_items_allowed": True}}
+
+
+class FMPYieldCurveData(YieldCurveData):
+ """FMP Yield Curve Data."""
+
+
+class FMPYieldCurveFetcher(
+ Fetcher[
+ FMPYieldCurveQueryParams,
+ List[FMPYieldCurveData],
+ ]
+):
+ """FMP Yield Curve Fetcher."""
+
+ @staticmethod
+ def transform_query(params: Dict[str, Any]) -> FMPYieldCurveQueryParams:
+ """Transform the query params."""
+ transformed_params = params
+ if not transformed_params.get("date"):
+ transformed_params["date"] = datetime.now().strftime("%Y-%m-%d")
+ return FMPYieldCurveQueryParams(**transformed_params)
+
+ @staticmethod
+ async def aextract_data(
+ query: FMPYieldCurveQueryParams,
+ credentials: Optional[Dict[str, str]],
+ **kwargs: Any,
+ ) -> List[Dict]:
+ """Return the raw data from the FMP endpoint."""
+ api_key = credentials.get("fmp_api_key") if credentials else ""
+
+ def generate_url(date):
+ """Generate URL for a small window between each date."""
+ date = datetime.strptime(date, "%Y-%m-%d")
+ from_date = (date - timedelta(days=3)).strftime("%Y-%m-%d")
+ to_date = (date + timedelta(days=3)).strftime("%Y-%m-%d")
+ url = (
+ "https://financialmodelingprep.com/api/v4/treasury?"
+ + f"from={from_date}&to={to_date}&apikey={api_key}"
+ )
+ return url
+
+ dates = query.date.split(",")
+ urls = [generate_url(date) for date in dates]
+
+ return await amake_requests(urls, **kwargs)
+
+ @staticmethod
+ def transform_data(
+ query: FMPYieldCurveQueryParams, data: List[Dict], **kwargs: Any
+ ) -> List[FMPYieldCurveData]:
+ """Return the transformed data."""
+ if not data:
+ raise EmptyDataError("The request was returned empty.")
+ df = DataFrame(data).set_index("date")
+ dates = query.date.split(",") if query.date else [df.index.max()]
+ df.index = DatetimeIndex(df.index)
+ dates_list = DatetimeIndex(dates)
+ df = df.rename(columns=maturity_dict)
+ df.columns.name = "maturity"
+
+ # Find the nearest date in the DataFrame to each date in dates_list
+ nearest_dates = [df.index.asof(date) for date in dates_list]
+
+ # Filter for only the nearest dates
+ df = df[df.index.isin(nearest_dates)]
+
+ df = df.fillna("N/A").replace("N/A", None)
+
+ # Flatten the DataFrame
+ flattened_data = df.reset_index().melt(
+ id_vars="date", var_name="maturity", value_name="rate"
+ )
+ flattened_data = flattened_data.sort_values("date")
+ flattened_data["maturity"] = Categorical(
+ flattened_data["maturity"],
+ categories=list(maturity_dict.values()),
+ ordered=True,
+ )
+ flattened_data["rate"] = flattened_data["rate"].astype(float) / 100
+ flattened_data = flattened_data.sort_values(
+ by=["date", "maturity"]
+ ).reset_index(drop=True)
+ flattened_data.loc[:, "date"] = flattened_data["date"].dt.strftime("%Y-%m-%d")
+ records = flattened_data.to_dict(orient="records")
+
+ return [FMPYieldCurveData.model_validate(d) for d in records]
diff --git a/openbb_platform/providers/fmp/tests/record/http/test_fmp_fetchers/test_fmp_yield_curve_fetcher.yaml b/openbb_platform/providers/fmp/tests/record/http/test_fmp_fetchers/test_fmp_yield_curve_fetcher.yaml
new file mode 100644
index 00000000000..9bf46d6f9f5
--- /dev/null
+++ b/openbb_platform/providers/fmp/tests/record/http/test_fmp_fetchers/test_fmp_yield_curve_fetcher.yaml
@@ -0,0 +1,276 @@
+interactions:
+- request:
+ body: null
+ headers:
+ Accept:
+ - application/json
+ Accept-Encoding:
+ - gzip, deflate
+ Connection:
+ - keep-alive
+ method: GET
+ uri: https://financialmodelingprep.com/api/v4/treasury?apikey=MOCK_API_KEY&from=2020-05-11&to=2020-05-17
+ response:
+ body:
+ string: !!binary |
+ H4sIAAAAAAAAA62UywrCMBBF9/2K0HUrmTz68FfERcGCGxWkGxH/3ZpM4IbGNoiLbk7Sm+Z0Zg6F
+ EM/5EaI8DdNY7kWppJK1tDV1ZeVXLrfrdKZ5Te4IkfIoYtozjazxzDJ7jMOd01pAnNYB8mHKALIO
+ adzVOmQxi6Rjrcb8D6P4TO2ZMTN6VSsubMKF7JcyYsYyVJ4MRCyjWcigHhDLIEBehsFdLKNBjSxD
+ 4pksQ6stGSZTRqow/ulCAfmuAkslqEjUhUQWVGyZ0JktkhCR2SH/ExGFr5REoj+03RKhMkXkmsA7
+ 0hJxWvSp3kRCBV6SVeC/Di6wZcKsQIvBRbflgnLbI7c/fpaRGJz4IsuI4lcGZ1R3PDhdhxTHN0O6
+ YwdHBgAA
+ headers:
+ Access-Control-Allow-Credentials:
+ - 'true'
+ Access-Control-Allow-Headers:
+ - X-Requested-With, content-type, auth-token, Authorization, stripe-signature,
+ APPS, publicauthkey, privateauthkey
+ Access-Control-Allow-Methods:
+ - GET, POST, OPTIONS
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Max-Age:
+ - '3600'
+ Connection:
+ - keep-alive
+ Content-Encoding:
+ - gzip
+ Content-Type:
+ - application/json; charset=utf-8
+ Date:
+ - Wed, 15 May 2024 04:17:01 GMT
+ Etag:
+ - W/"647-LydzNMvIZhxt85QadA8Kg/rKyC0"
+ Server:
+ - nginx/1.18.0 (Ubuntu)
+ Transfer-Encoding:
+ - chunked
+ Vary:
+ - Accept-Encoding
+ X-Frame-Options:
+ - SAMEORIGIN
+ X-Powered-By:
+ - Express
+ status:
+ code: 200
+ message: OK
+- request:
+ body: null
+ headers:
+ Accept:
+ - application/json
+ Accept-Encoding:
+ - gzip, deflate
+ Connection:
+ - keep-alive
+ method: GET
+ uri: https://financialmodelingprep.com/api/v4/treasury?apikey=MOCK_API_KEY&from=2023-05-11&to=2023-05-17
+ response:
+ body:
+ string: !!binary |
+ H4sIAAAAAAAAA4WUu27DMAxF93yF4Tkx9KbUXyk6BGiALm2BIktR9N9jiwx6WRHx4OXIpsjjKz0f
+ pulnfaZpfj1fL/PTNAcX4snlk6/zkVfePz+ub35dy0tuyEJnISCLnUWPrDCrwr4v5y8u5wKgrVpa
+ QgK0FYtLQ5Q7Kg0QMSIs75hlrO/6BmrPyO81v6Lf4wMZZMkYXbgyugiKiYt/KtLSRhVeddobRYVs
+ IiOiEYmJjHaCTF2wPrNa90wUy0RFxt03xURFRFa0nj8XFQfgak712lulMRYZjYkMpVpk4JePZNCe
+ jGzIKAmZyCBkIsM4Iyr9LINwgMC9YvpZhko/y0g4EctIVjIMF8YRqWnPRTBc0HBfrH/XcqHOErvw
+ YzBINcu94kjiAt8SF4hoROJCKQv3EIwyaPeUeENGVT9cZBiXp0LiwsjFoKKOscg4EKuIYyyicXVG
+ LHZXYeSC4qbi8HIDJk0/oEoGAAA=
+ headers:
+ Access-Control-Allow-Credentials:
+ - 'true'
+ Access-Control-Allow-Headers:
+ - X-Requested-With, content-type, auth-token, Authorization, stripe-signature,
+ APPS, publicauthkey, privateauthkey
+ Access-Control-Allow-Methods:
+ - GET, POST, OPTIONS
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Max-Age:
+ - '3600'
+ Connection:
+ - keep-alive
+ Content-Encoding:
+ - gzip
+ Content-Type:
+ - application/json; charset=utf-8
+ Date:
+ - Wed, 15 May 2024 04:17:01 GMT
+ Etag:
+ - W/"64a-qQ86HxIoIDU3JJj3ypPqfnNTl40"
+ Server:
+ - nginx/1.18.0 (Ubuntu)
+ Transfer-Encoding:
+ - chunked
+ Vary:
+ - Accept-Encoding
+ X-Frame-Options:
+ - SAMEORIGIN
+ X-Powered-By:
+ - Express
+ status:
+ code: 200
+ message: OK
+- request:
+ body: null
+ headers:
+ Accept:
+ - application/json
+ Accept-Encoding:
+ - gzip, deflate
+ Connection:
+ - keep-alive
+ method: GET
+ uri: https://financialmodelingprep.com/api/v4/treasury?apikey=MOCK_API_KEY&from=2022-05-11&to=2022-05-17
+ response:
+ body:
+ string: !!binary |
+ H4sIAAAAAAAAA42UzWrDMBAG73kK4XNi9GNprb5K6SHQQC9toeRSSt89tnZVvq0UO4dcJpFgJ7N6
+ Phjzs3yMGV7P18vwZAZvvT/ZeHLzcORv3j8/rm9u+c6OMSHzhc0RWViYG21Algr7O/t9OX+t1/nR
+ IfIFpRlQKGieAEVGGRAVlB1eb9uf+ZWF0eNtgZmlBf0eN2RQR0ZyyDZkKGkigx6RQThTaEdiGRkP
+ rjIC3s0mMmoVEwHPiQm3ayL1TEzINkwQMjGB/websCiHTcQ2C4qAJAucnFpfNYuejE4Vec9F6LlQ
+ M7ILysjur8jUVmFRj6xIWwW1VfRWBI3VMHDw6sJ3wthz4R/cEFJ+QmG5syHT/y6cDl26UA2zC5xI
+ XKAx6UK9RtKFci3PRetiz4TrPZyqgA0TypiYUPvMJtTDxlW0JtTY96tQoqUKPFlNYD11ReIq4/By
+ AxjfFZ5IBgAA
+ headers:
+ Access-Control-Allow-Credentials:
+ - 'true'
+ Access-Control-Allow-Headers:
+ - X-Requested-With, content-type, auth-token, Authorization, stripe-signature,
+ APPS, publicauthkey, privateauthkey
+ Access-Control-Allow-Methods:
+ - GET, POST, OPTIONS
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Max-Age:
+ - '3600'
+ Connection:
+ - keep-alive
+ Content-Encoding:
+ - gzip
+ Content-Type:
+ - application/json; charset=utf-8
+ Date:
+ - Wed, 15 May 2024 04:17:01 GMT
+ Etag:
+ - W/"648-twHy7YLcgra10np90L3C4D2swpw"
+ Server:
+ - nginx/1.18.0 (Ubuntu)
+ Transfer-Encoding:
+ - chunked
+ Vary:
+ - Accept-Encoding
+ X-Frame-Options:
+ - SAMEORIGIN
+ X-Powered-By:
+ - Express
+ status:
+ code: 200
+ message: OK
+- request:
+ body: null
+ headers:
+ Accept:
+ - application/json
+ Accept-Encoding:
+ - gzip, deflate
+ Connection:
+ - keep-alive
+ method: GET
+ uri: https://financialmodelingprep.com/api/v4/treasury?apikey=MOCK_API_KEY&from=2021-05-11&to=2021-05-17
+ response:
+ body:
+ string: !!binary |
+ H4sIAAAAAAAAA62Uyw6CMBBF935FwxpIZ8rTXzEuSCRxoyaGjTH+u0CH5FYaHsKCzSkztKd3OB2U
+ erePUsGlaurgqALWTJFOIyqC0K7cHvfmSu2aRsAdiDUhM5YxsswyI+xVV0+yKANkuxEi28wkgNIe
+ FdgrbxHFXGJ73bMMK7ljHHOOH7DM5C36hBMm8l1N4La2mkBkTTieV4rI5kQkYxE/555w4bCtqcBC
+ ccGAJlKBlYOM1CMjnZNhdk2FxwTuapUJTyoI24sJx7SYKDwmyjkTvDQWzsHXjcgyGfiWyMCgiwyn
+ vcjAqAwykImMZM4FLXWxdET+doFXLi5GKpz7HlT4fheYMmdCDucv9UoTokQGAAA=
+ headers:
+ Access-Control-Allow-Credentials:
+ - 'true'
+ Access-Control-Allow-Headers:
+ - X-Requested-With, content-type, auth-token, Authorization, stripe-signature,
+ APPS, publicauthkey, privateauthkey
+ Access-Control-Allow-Methods:
+ - GET, POST, OPTIONS
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Max-Age:
+ - '3600'
+ Connection:
+ - keep-alive
+ Content-Encoding:
+ - gzip
+ Content-Type:
+ - application/json; charset=utf-8
+ Date:
+ - Wed, 15 May 2024 04:17:01 GMT
+ Etag:
+ - W/"644-FBvvp3deUZ1C1r7lKBqDjdjmSI4"
+ Server:
+ - nginx/1.18.0 (Ubuntu)
+ Transfer-Encoding:
+ - chunked
+ Vary:
+ - Accept-Encoding
+ X-Frame-Options:
+ - SAMEORIGIN
+ X-Powered-By:
+ - Express
+ status:
+ code: 200
+ message: OK
+- request:
+ body: null
+ headers:
+ Accept:
+ - application/json
+ Accept-Encoding:
+ - gzip, deflate
+ Connection:
+ - keep-alive
+ method: GET
+ uri: https://financialmodelingprep.com/api/v4/treasury?apikey=MOCK_API_KEY&from=2024-05-11&to=2024-05-17
+ response:
+ body:
+ string: !!binary |
+ H4sIAAAAAAAAA6XQTQrCMBCG4X1PEbJuS35mJq1XERcFC25UkG5EvLtpJsInBUFcdPNkOk3ffWPM
+ Iz/G2OO0zHZnbHCBOsedJ9vqyfl6WU4+n3HPSKEQJbSoRmiiFqvd5+mm27wArduoHzxQLCQBiAsR
+ vpiUGNe7rQU1GfEDajxmerZfWsQ/WnzM/dQCr19b4JS2wKGaAn/xnWLYpkgYtqaQuKZoDi/SxMk5
+ GQIAAA==
+ headers:
+ Access-Control-Allow-Credentials:
+ - 'true'
+ Access-Control-Allow-Headers:
+ - X-Requested-With, content-type, auth-token, Authorization, stripe-signature,
+ APPS, publicauthkey, privateauthkey
+ Access-Control-Allow-Methods:
+ - GET, POST, OPTIONS
+ Access-Control-Allow-Origin:
+ - '*'
+ Access-Control-Max-Age:
+ - '3600'
+ Connection:
+ - keep-alive
+ Content-Encoding:
+ - gzip
+ Content-Type:
+ - application/json; charset=utf-8
+ Date:
+ - Wed, 15 May 2024 04:17:01 GMT
+ Etag:
+ - W/"219-AzGShdXa56qJWPx5KMZ5NeNIBjI"
+ Server:
+ - nginx/1.18.0 (Ubuntu)
+ Transfer-Encoding:
+ - chunked
+ Vary:
+ - Accept-Encoding
+ X-Frame-Options:
+ - SAMEORIGIN
+ X-Powered-By:
+ - Express
+ status:
+ code: 200
+ message: OK
+version: 1
diff --git a/openbb_platform/providers/fmp/tests/test_fmp_fetchers.py b/openbb_platform/providers/fmp/tests/test_fmp_fetchers.py
index b740b6e8050..de3c82ef7c5 100644
--- a/openbb_platform/providers/fmp/tests/test_fmp_fetchers.py
+++ b/openbb_platform/providers/fmp/tests/test_fmp_fetchers.py
@@ -70,6 +70,7 @@ from openbb_fmp.models.risk_premium import FMPRiskPremiumFetcher
from openbb_fmp.models.share_statistics import FMPShareStatisticsFetcher
from openbb_fmp.models.treasury_rates import FMPTreasuryRatesFetcher
from openbb_fmp.models.world_news import FMPWorldNewsFetcher
+from openbb_fmp.models.yield_curve import FMPYieldCurveFetcher
test_credentials = UserService().default_user_settings.credentials.model_dump(
mode="json"
@@ -746,3 +747,13 @@ def test_fmp_equity_forward_eps_fetcher(credentials=test_credentials):
fetcher = FMPForwardEpsEstimatesFetcher()
result = fetcher.test(params, credentials)
assert result is None
+
+
+@pytest.mark.record_http
+def test_fmp_yield_curve_fetcher(credentials=test_credentials):
+ """Test FMP Yield Curve Fetcher."""
+ params = {"date": "2024-05-14,2023-05-14,2022-05-14,2021-05-14,2020-05-14"}
+
+ fetcher = FMPYieldCurveFetcher()
+ result = fetcher.test(params, credentials)
+ assert result is None