Skip to content

Commit

Permalink
Add multi-ticker support to etf_countries (#5670)
Browse files Browse the repository at this point in the history
* add multi-ticker support to etf_countries

* remove commented-out lines

* normalized percent points

* percent -> percentage
  • Loading branch information
deeleeramone authored Nov 7, 2023
1 parent 88099d2 commit 8c965c4
Show file tree
Hide file tree
Showing 4 changed files with 215 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ def upper_symbol(cls, v: Union[str, List[str], Set[str]]):
class EtfCountriesData(Data):
"""ETF Countries Data."""

country: str = Field(description="The country of the exposure.")
weight: float = Field(
description="Exposure of the ETF to the country in normalized percentage points."
country: str = Field(
description="The country of the exposure. Corresponding values are normalized percentage points."
)
51 changes: 39 additions & 12 deletions openbb_platform/providers/fmp/openbb_fmp/models/etf_countries.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from typing import Any, Dict, List, Optional

import pandas as pd
from openbb_fmp.utils.helpers import create_url, get_data_many
from openbb_provider.abstract.fetcher import Fetcher
from openbb_provider.standard_models.etf_countries import (
Expand All @@ -17,8 +18,6 @@ class FMPEtfCountriesQueryParams(EtfCountriesQueryParams):
class FMPEtfCountriesData(EtfCountriesData):
"""FMP ETF Country Weighting Data."""

__alias_dict__ = {"weight": "weightPercentage"}


class FMPEtfCountriesFetcher(
Fetcher[
Expand All @@ -40,24 +39,52 @@ def extract_data(
**kwargs: Any,
) -> List[Dict]:
"""Return the raw data from the FMP endpoint."""

api_key = credentials.get("fmp_api_key") if credentials else ""
symbols = (
query.symbol.split(",") if "," in query.symbol else [query.symbol.upper()]
)
results = {}

url = create_url(
version=3,
endpoint=f"etf-country-weightings/{query.symbol.upper()}",
api_key=api_key,
for symbol in symbols:
data = {}
url = create_url(
version=3,
endpoint=f"etf-country-weightings/{symbol}",
api_key=api_key,
)
result = get_data_many(url, **kwargs)
df = pd.DataFrame(result).set_index("country")
if len(df) > 0:
for i in df.index:
data.update(
{
i: float(df.loc[i]["weightPercentage"].replace("%", ""))
* 0.01
}
)
results.update({symbol: data})

output = (
pd.DataFrame(results)
.transpose()
.reset_index()
.fillna(value=0)
.replace(0, None)
.rename(columns={"index": "symbol"})
).transpose()
output.columns = output.loc["symbol"].to_list()
output = output.drop("symbol", axis=0).sort_values(
by=output.columns[0], ascending=False
)

return get_data_many(url, **kwargs)
return (
output.reset_index().rename(columns={"index": "country"}).to_dict("records")
)

@staticmethod
def transform_data(
query: FMPEtfCountriesQueryParams, data: List[Dict], **kwargs: Any
) -> List[FMPEtfCountriesData]:
"""Return the transformed data."""
for d in data:
if d["weightPercentage"] is not None and d["weightPercentage"].endswith(
"%"
):
d["weightPercentage"] = float(d["weightPercentage"][:-1]) / 100
return [FMPEtfCountriesData.model_validate(d) for d in data]
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@ interactions:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
- gzip, deflate, br
Connection:
- keep-alive
method: GET
uri: https://financialmodelingprep.com/api/v3/etf-country-weightings/MISL?apikey=MOCK_API_KEY
uri: https://financialmodelingprep.com/api/v3/etf-country-weightings/VTI?apikey=MOCK_API_KEY
response:
body:
string: "[\n {\n \"country\": \"United States\",\n \"weightPercentage\":
\"98.35%\"\n },\n {\n \"country\": \"Other\",\n \"weightPercentage\":
\"1.65%\"\n }\n]"
string: !!binary |
H4sIAAAAAAAAA6XSTQuCQBAG4Hu/YlnoJqKG9nGrTkZUEJ2iw6SDCrnCOItZ9N9TusYYdNjTvPPw
srvnkVLP7iilk8oaplYvlD6ZgjFVRwbGWjufeYNFlvMBKUHDkGEfnEfuzB/rLvByvkp7zpEkwXOn
kQTEhDcwqUT4bhhKxLEp+IE0xHjuRGTWYCAFWQgCSVjamgluxQDiTSVkhVTa/3qsoS3BqLjur0R8
366MKG2QamxFQVrfYf89hltIxtbesbxWlrIfiNHlDcqTD93xAgAA
headers:
Access-Control-Allow-Credentials:
- 'true'
Expand All @@ -29,16 +31,178 @@ interactions:
- '3600'
Connection:
- keep-alive
Content-Length:
- '141'
Content-Encoding:
- gzip
Content-Type:
- application/json; charset=utf-8
Date:
- Wed, 01 Nov 2023 13:27:52 GMT
- Sun, 05 Nov 2023 05:15:21 GMT
ETag:
- W/"8d-2VmJo306+5EGW4NWPOj2rTFnMzA"
- W/"2f1-z5/4g/ulC3y6Aw5o83OT94EFKKU"
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:
- '*/*'
Accept-Encoding:
- gzip, deflate, br
Connection:
- keep-alive
method: GET
uri: https://financialmodelingprep.com/api/v3/etf-country-weightings/QQQ?apikey=MOCK_API_KEY
response:
body:
string: !!binary |
H4sIAAAAAAAAA4XPwQrCMAyA4fueIhS8jTI3nc6beFdBPImHsIa2MCp0KTLEd3djV8kOOSV8/Hlk
AJ9xAFT7SoHjoA6g7sEzGbgxMvUqn/dv8tbxlWJLgdHSdNjUulmpcf/N/0Mx2YSDRBR6KxIn5wPK
QC0CZ2JHscNgxFcKvd+JHRjQLIRsSkm4TB0yUK0l4Jh6jtj5hYqympHs+QNActKX3gEAAA==
headers:
Access-Control-Allow-Credentials:
- 'true'
Access-Control-Allow-Headers:
- X-Requested-With, content-type, auth-token, Authorization, stripe-signature,
APPS
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:
- Sun, 05 Nov 2023 05:15:21 GMT
ETag:
- W/"1de-u/Rt0fxDvduVLpiU+/1mhnLcZeE"
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:
- '*/*'
Accept-Encoding:
- gzip, deflate, br
Connection:
- keep-alive
method: GET
uri: https://financialmodelingprep.com/api/v3/etf-country-weightings/VOO?apikey=MOCK_API_KEY
response:
body:
string: !!binary |
H4sIAAAAAAAAA4XQPQvCQAwG4L2/Ihy4leOqpX6Mbi4qFCdxOHqhPagnpClFxf/uHV0lDpne5CHJ
NQN4xwJQzWMMTE+1A3UJntFBzZZxUPmcT+jbjs9IDQa2LabG7XqhYvrJfzIHwt4GJwGFrjYSceIO
SQKMrqT5evL8Qvq3htHlSmL2SPfRWZkoROKI6ZS0iPjRyJTiTwey2MuCWc5CdvsCtZKIl98BAAA=
headers:
Access-Control-Allow-Credentials:
- 'true'
Access-Control-Allow-Headers:
- X-Requested-With, content-type, auth-token, Authorization, stripe-signature,
APPS
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:
- Sun, 05 Nov 2023 05:15:22 GMT
ETag:
- W/"1df-OEmfqekeHOVvwG/zgq/j7mJKmsQ"
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:
- '*/*'
Accept-Encoding:
- gzip, deflate, br
Connection:
- keep-alive
method: GET
uri: https://financialmodelingprep.com/api/v3/etf-country-weightings/IWM?apikey=MOCK_API_KEY
response:
body:
string: !!binary |
H4sIAAAAAAAAA6XTTUvDQBAG4Ht/xbLQWwlJa9R6jNAS8aNQPImHaTIkgWQik100iv/dBPEm7woe
9rTLw7vz8bQw5mM6xtii9+J0tFfG5sotSWlX3zev3FS1O7AWLI4qnp/EUbpZ2un+c/Ur8SiN49Ic
HTkeELRNo80aSdc0diQmH+ZIkJoynSEpY+18SYhIovMEEQ+uZsUZtrAud71Q0WMhuUTCsZGKXnrl
AAJLsVOSIiQgIB+UuP1PhEzpvQkI8QWeDCHczjhap0i49W/cnXqvVSAHVDKqqaPAaMawGIfpK13g
KzEcrL1nlYHHgAFX7YY1LMCx2DcnpdYR3hEk3PO8Yn/Y9Z+eLJ6/ANaC2CnFBAAA
headers:
Access-Control-Allow-Credentials:
- 'true'
Access-Control-Allow-Headers:
- X-Requested-With, content-type, auth-token, Authorization, stripe-signature,
APPS
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:
- Sun, 05 Nov 2023 05:15:22 GMT
ETag:
- W/"4c5-b5x+LUJL2Tk17h5pypIQmPJe3ag"
Server:
- nginx/1.18.0 (Ubuntu)
Transfer-Encoding:
- chunked
Vary:
- Accept-Encoding
X-Frame-Options:
- SAMEORIGIN
X-Powered-By:
Expand Down
2 changes: 1 addition & 1 deletion openbb_platform/providers/fmp/tests/test_fmp_fetchers.py
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,7 @@ def test_fmp_price_performance_fetcher(credentials=test_credentials):

@pytest.mark.record_http
def test_fmp_etf_countries_fetcher(credentials=test_credentials):
params = {"symbol": "MISL"}
params = {"symbol": "VTI,QQQ,VOO,IWM"}

fetcher = FMPEtfCountriesFetcher()
result = fetcher.test(params, credentials)
Expand Down

0 comments on commit 8c965c4

Please sign in to comment.