mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-28 13:01:38 +00:00
add Intrinio ETF Holdings (#6208)
This commit is contained in:
@@ -333,6 +333,12 @@ def test_etf_holdings_date(params, headers):
|
||||
"use_cache": False,
|
||||
}
|
||||
),
|
||||
(
|
||||
{
|
||||
"symbol": "DJIA",
|
||||
"provider": "intrinio",
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
|
||||
@@ -325,6 +325,12 @@ def test_etf_holdings_date(params, obb):
|
||||
"use_cache": False,
|
||||
}
|
||||
),
|
||||
(
|
||||
{
|
||||
"symbol": "DJIA",
|
||||
"provider": "intrinio",
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
|
||||
126
openbb_platform/openbb/assets/reference.json
vendored
126
openbb_platform/openbb/assets/reference.json
vendored
@@ -21582,7 +21582,7 @@
|
||||
},
|
||||
{
|
||||
"name": "provider",
|
||||
"type": "Literal['fmp', 'sec']",
|
||||
"type": "Literal['fmp', 'intrinio', 'sec']",
|
||||
"description": "The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default.",
|
||||
"default": "fmp",
|
||||
"optional": true
|
||||
@@ -21604,6 +21604,7 @@
|
||||
"optional": true
|
||||
}
|
||||
],
|
||||
"intrinio": [],
|
||||
"sec": [
|
||||
{
|
||||
"name": "date",
|
||||
@@ -21630,7 +21631,7 @@
|
||||
},
|
||||
{
|
||||
"name": "provider",
|
||||
"type": "Optional[Literal['fmp', 'sec']]",
|
||||
"type": "Optional[Literal['fmp', 'intrinio', 'sec']]",
|
||||
"description": "Provider name."
|
||||
},
|
||||
{
|
||||
@@ -21816,6 +21817,127 @@
|
||||
"optional": true
|
||||
}
|
||||
],
|
||||
"intrinio": [
|
||||
{
|
||||
"name": "security_type",
|
||||
"type": "str",
|
||||
"description": "The type of instrument for this holding. Examples(Bond='BOND', Equity='EQUI')",
|
||||
"default": null,
|
||||
"optional": true
|
||||
},
|
||||
{
|
||||
"name": "isin",
|
||||
"type": "str",
|
||||
"description": "The International Securities Identification Number.",
|
||||
"default": null,
|
||||
"optional": true
|
||||
},
|
||||
{
|
||||
"name": "ric",
|
||||
"type": "str",
|
||||
"description": "The Reuters Instrument Code.",
|
||||
"default": null,
|
||||
"optional": true
|
||||
},
|
||||
{
|
||||
"name": "sedol",
|
||||
"type": "str",
|
||||
"description": "The Stock Exchange Daily Official List.",
|
||||
"default": null,
|
||||
"optional": true
|
||||
},
|
||||
{
|
||||
"name": "share_class_figi",
|
||||
"type": "str",
|
||||
"description": "The OpenFIGI symbol for the holding.",
|
||||
"default": null,
|
||||
"optional": true
|
||||
},
|
||||
{
|
||||
"name": "country",
|
||||
"type": "str",
|
||||
"description": "The country or region of the holding.",
|
||||
"default": null,
|
||||
"optional": true
|
||||
},
|
||||
{
|
||||
"name": "maturity_date",
|
||||
"type": "date",
|
||||
"description": "The maturity date for the debt security, if available.",
|
||||
"default": null,
|
||||
"optional": true
|
||||
},
|
||||
{
|
||||
"name": "contract_expiry_date",
|
||||
"type": "date",
|
||||
"description": "Expiry date for the futures contract held, if available.",
|
||||
"default": null,
|
||||
"optional": true
|
||||
},
|
||||
{
|
||||
"name": "coupon",
|
||||
"type": "float",
|
||||
"description": "The coupon rate of the debt security, if available.",
|
||||
"default": null,
|
||||
"optional": true
|
||||
},
|
||||
{
|
||||
"name": "balance",
|
||||
"type": "Union[float, int]",
|
||||
"description": "The number of units of the security held, if available.",
|
||||
"default": null,
|
||||
"optional": true
|
||||
},
|
||||
{
|
||||
"name": "unit",
|
||||
"type": "str",
|
||||
"description": "The units of the 'balance' field.",
|
||||
"default": null,
|
||||
"optional": true
|
||||
},
|
||||
{
|
||||
"name": "units_per_share",
|
||||
"type": "float",
|
||||
"description": "Number of units of the security held per share outstanding of the ETF, if available.",
|
||||
"default": null,
|
||||
"optional": true
|
||||
},
|
||||
{
|
||||
"name": "face_value",
|
||||
"type": "float",
|
||||
"description": "The face value of the debt security, if available.",
|
||||
"default": null,
|
||||
"optional": true
|
||||
},
|
||||
{
|
||||
"name": "derivatives_value",
|
||||
"type": "float",
|
||||
"description": "The notional value of derivatives contracts held.",
|
||||
"default": null,
|
||||
"optional": true
|
||||
},
|
||||
{
|
||||
"name": "value",
|
||||
"type": "float",
|
||||
"description": "The market value of the holding, on the 'as_of' date.",
|
||||
"default": null,
|
||||
"optional": true
|
||||
},
|
||||
{
|
||||
"name": "weight",
|
||||
"type": "float",
|
||||
"description": "The weight of the holding, as a normalized percent.",
|
||||
"default": null,
|
||||
"optional": true
|
||||
},
|
||||
{
|
||||
"name": "updated",
|
||||
"type": "date",
|
||||
"description": "The 'as_of' date for the holding.",
|
||||
"default": null,
|
||||
"optional": true
|
||||
}
|
||||
],
|
||||
"sec": [
|
||||
{
|
||||
"name": "lei",
|
||||
|
||||
@@ -371,7 +371,7 @@ class ROUTER_etf(Container):
|
||||
str, OpenBBCustomParameter(description="Symbol to get data for. (ETF)")
|
||||
],
|
||||
provider: Annotated[
|
||||
Optional[Literal["fmp", "sec"]],
|
||||
Optional[Literal["fmp", "intrinio", "sec"]],
|
||||
OpenBBCustomParameter(
|
||||
description="The provider to use for the query, by default None.\n If None, the provider specified in defaults is selected or 'fmp' if there is\n no default."
|
||||
),
|
||||
@@ -384,7 +384,7 @@ class ROUTER_etf(Container):
|
||||
----------
|
||||
symbol : str
|
||||
Symbol to get data for. (ETF)
|
||||
provider : Optional[Literal['fmp', 'sec']]
|
||||
provider : Optional[Literal['fmp', 'intrinio', 'sec']]
|
||||
The provider to use for the query, by default None.
|
||||
If None, the provider specified in defaults is selected or 'fmp' if there is
|
||||
no default.
|
||||
@@ -401,7 +401,7 @@ class ROUTER_etf(Container):
|
||||
OBBject
|
||||
results : List[EtfHoldings]
|
||||
Serializable results.
|
||||
provider : Optional[Literal['fmp', 'sec']]
|
||||
provider : Optional[Literal['fmp', 'intrinio', 'sec']]
|
||||
Provider name.
|
||||
warnings : Optional[List[Warning_]]
|
||||
List of warnings.
|
||||
@@ -423,9 +423,10 @@ class ROUTER_etf(Container):
|
||||
cusip : Optional[str]
|
||||
The CUSIP of the holding. (provider: fmp, sec)
|
||||
isin : Optional[str]
|
||||
The ISIN of the holding. (provider: fmp, sec)
|
||||
The ISIN of the holding. (provider: fmp, intrinio, sec)
|
||||
balance : Optional[int]
|
||||
The balance of the holding, in shares or units. (provider: fmp);
|
||||
The number of units of the security held, if available. (provider: intrinio);
|
||||
The balance of the holding. (provider: sec)
|
||||
units : Optional[Union[str, float]]
|
||||
The type of units. (provider: fmp);
|
||||
@@ -433,9 +434,9 @@ class ROUTER_etf(Container):
|
||||
currency : Optional[str]
|
||||
The currency of the holding. (provider: fmp, sec)
|
||||
value : Optional[float]
|
||||
The value of the holding, in dollars. (provider: fmp, sec)
|
||||
The value of the holding, in dollars. (provider: fmp, intrinio, sec)
|
||||
weight : Optional[float]
|
||||
The weight of the holding, as a normalized percent. (provider: fmp);
|
||||
The weight of the holding, as a normalized percent. (provider: fmp, intrinio);
|
||||
The weight of the holding in ETF in %. (provider: sec)
|
||||
payoff_profile : Optional[str]
|
||||
The payoff profile of the holding. (provider: fmp, sec)
|
||||
@@ -444,7 +445,7 @@ class ROUTER_etf(Container):
|
||||
issuer_category : Optional[str]
|
||||
The issuer category of the holding. (provider: fmp, sec)
|
||||
country : Optional[str]
|
||||
The country of the holding. (provider: fmp, sec)
|
||||
The country of the holding. (provider: fmp, intrinio, sec)
|
||||
is_restricted : Optional[str]
|
||||
Whether the holding is restricted. (provider: fmp, sec)
|
||||
fair_value_level : Optional[int]
|
||||
@@ -460,7 +461,30 @@ class ROUTER_etf(Container):
|
||||
acceptance_datetime : Optional[str]
|
||||
The acceptance datetime of the filing. (provider: fmp)
|
||||
updated : Optional[Union[date, datetime]]
|
||||
The date the data was updated. (provider: fmp)
|
||||
The date the data was updated. (provider: fmp);
|
||||
The 'as_of' date for the holding. (provider: intrinio)
|
||||
security_type : Optional[str]
|
||||
The type of instrument for this holding. Examples(Bond='BOND', Equity='EQUI') (provider: intrinio)
|
||||
ric : Optional[str]
|
||||
The Reuters Instrument Code. (provider: intrinio)
|
||||
sedol : Optional[str]
|
||||
The Stock Exchange Daily Official List. (provider: intrinio)
|
||||
share_class_figi : Optional[str]
|
||||
The OpenFIGI symbol for the holding. (provider: intrinio)
|
||||
maturity_date : Optional[date]
|
||||
The maturity date for the debt security, if available. (provider: intrinio, sec)
|
||||
contract_expiry_date : Optional[date]
|
||||
Expiry date for the futures contract held, if available. (provider: intrinio)
|
||||
coupon : Optional[float]
|
||||
The coupon rate of the debt security, if available. (provider: intrinio)
|
||||
unit : Optional[str]
|
||||
The units of the 'balance' field. (provider: intrinio)
|
||||
units_per_share : Optional[float]
|
||||
Number of units of the security held per share outstanding of the ETF, if available. (provider: intrinio)
|
||||
face_value : Optional[float]
|
||||
The face value of the debt security, if available. (provider: intrinio)
|
||||
derivatives_value : Optional[float]
|
||||
The notional value of derivatives contracts held. (provider: intrinio)
|
||||
other_id : Optional[str]
|
||||
Internal identifier for the holding. (provider: sec)
|
||||
loan_value : Optional[float]
|
||||
@@ -469,8 +493,6 @@ class ROUTER_etf(Container):
|
||||
The issuer conditions of the holding. (provider: sec)
|
||||
asset_conditional : Optional[str]
|
||||
The asset conditions of the holding. (provider: sec)
|
||||
maturity_date : Optional[date]
|
||||
The maturity date of the debt security. (provider: sec)
|
||||
coupon_kind : Optional[str]
|
||||
The type of coupon for the debt security. (provider: sec)
|
||||
rate_type : Optional[str]
|
||||
@@ -591,7 +613,7 @@ class ROUTER_etf(Container):
|
||||
"provider": self._get_provider(
|
||||
provider,
|
||||
"/etf/holdings",
|
||||
("fmp", "sec"),
|
||||
("fmp", "intrinio", "sec"),
|
||||
)
|
||||
},
|
||||
standard_params={
|
||||
|
||||
@@ -11,6 +11,7 @@ from openbb_intrinio.models.equity_historical import IntrinioEquityHistoricalFet
|
||||
from openbb_intrinio.models.equity_info import IntrinioEquityInfoFetcher
|
||||
from openbb_intrinio.models.equity_quote import IntrinioEquityQuoteFetcher
|
||||
from openbb_intrinio.models.equity_search import IntrinioEquitySearchFetcher
|
||||
from openbb_intrinio.models.etf_holdings import IntrinioEtfHoldingsFetcher
|
||||
from openbb_intrinio.models.etf_info import IntrinioEtfInfoFetcher
|
||||
from openbb_intrinio.models.etf_price_performance import (
|
||||
IntrinioEtfPricePerformanceFetcher,
|
||||
@@ -60,6 +61,7 @@ intrinio_provider = Provider(
|
||||
"EquityQuote": IntrinioEquityQuoteFetcher,
|
||||
"EquitySearch": IntrinioEquitySearchFetcher,
|
||||
"EtfHistorical": IntrinioEquityHistoricalFetcher,
|
||||
"EtfHoldings": IntrinioEtfHoldingsFetcher,
|
||||
"EtfInfo": IntrinioEtfInfoFetcher,
|
||||
"EtfPricePerformance": IntrinioEtfPricePerformanceFetcher,
|
||||
"EtfSearch": IntrinioEtfSearchFetcher,
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
"""Intrinio ETF Holdings Model."""
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
|
||||
from datetime import date as dateType
|
||||
from typing import Any, Dict, List, Optional, Union
|
||||
|
||||
from openbb_core.provider.abstract.fetcher import Fetcher
|
||||
from openbb_core.provider.standard_models.etf_holdings import (
|
||||
EtfHoldingsData,
|
||||
EtfHoldingsQueryParams,
|
||||
)
|
||||
from openbb_core.provider.utils.helpers import (
|
||||
ClientResponse,
|
||||
ClientSession,
|
||||
amake_request,
|
||||
)
|
||||
from pydantic import Field, model_validator
|
||||
|
||||
|
||||
class IntrinioEtfHoldingsQueryParams(EtfHoldingsQueryParams):
|
||||
"""
|
||||
Intrinio ETF Holdings Query Params.
|
||||
|
||||
Source: https://docs.intrinio.com/documentation/web_api/get_etf_holdings_v2
|
||||
"""
|
||||
|
||||
|
||||
class IntrinioEtfHoldingsData(EtfHoldingsData):
|
||||
"""Intrinio ETF Holdings Data."""
|
||||
|
||||
__alias_dict__ = {
|
||||
"symbol": "ticker",
|
||||
"security_type": "type",
|
||||
"unit": "quantity_units",
|
||||
"face_value": "face",
|
||||
"balance": "quantity_held",
|
||||
"value": "market_value_held",
|
||||
"derivatives_value": "notional_value",
|
||||
"units_per_share": "quantity_per_share",
|
||||
"weight": "weighting",
|
||||
"updated": "as_of_date",
|
||||
"country": "location",
|
||||
"maturity_date": "maturity",
|
||||
}
|
||||
|
||||
name: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The common name for the holding.",
|
||||
)
|
||||
security_type: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The type of instrument for this holding. Examples(Bond='BOND', Equity='EQUI')",
|
||||
)
|
||||
isin: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The International Securities Identification Number.",
|
||||
)
|
||||
ric: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The Reuters Instrument Code.",
|
||||
)
|
||||
sedol: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The Stock Exchange Daily Official List.",
|
||||
)
|
||||
share_class_figi: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The OpenFIGI symbol for the holding.",
|
||||
)
|
||||
country: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The country or region of the holding.",
|
||||
)
|
||||
maturity_date: Optional[dateType] = Field(
|
||||
default=None,
|
||||
description="The maturity date for the debt security, if available.",
|
||||
)
|
||||
contract_expiry_date: Optional[dateType] = Field(
|
||||
default=None,
|
||||
description="Expiry date for the futures contract held, if available.",
|
||||
)
|
||||
coupon: Optional[float] = Field(
|
||||
default=None,
|
||||
description="The coupon rate of the debt security, if available.",
|
||||
)
|
||||
balance: Optional[Union[int, float]] = Field(
|
||||
default=None,
|
||||
description="The number of units of the security held, if available.",
|
||||
)
|
||||
unit: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The units of the 'balance' field.",
|
||||
)
|
||||
units_per_share: Optional[float] = Field(
|
||||
default=None,
|
||||
description="Number of units of the security held per share outstanding of the ETF, if available.",
|
||||
)
|
||||
face_value: Optional[float] = Field(
|
||||
default=None,
|
||||
description="The face value of the debt security, if available.",
|
||||
)
|
||||
derivatives_value: Optional[float] = Field(
|
||||
default=None,
|
||||
description="The notional value of derivatives contracts held.",
|
||||
)
|
||||
value: Optional[float] = Field(
|
||||
default=None,
|
||||
description="The market value of the holding, on the 'as_of' date.",
|
||||
)
|
||||
weight: Optional[float] = Field(
|
||||
default=None,
|
||||
description="The weight of the holding, as a normalized percent.",
|
||||
)
|
||||
updated: Optional[dateType] = Field(
|
||||
default=None,
|
||||
description="The 'as_of' date for the holding.",
|
||||
)
|
||||
|
||||
@model_validator(mode="before")
|
||||
@classmethod
|
||||
def replace_zero(cls, values):
|
||||
"""Check for zero values and replace with None."""
|
||||
return (
|
||||
{k: None if v == 0 else v for k, v in values.items()}
|
||||
if isinstance(values, dict)
|
||||
else values
|
||||
)
|
||||
|
||||
|
||||
class IntrinioEtfHoldingsFetcher(
|
||||
Fetcher[IntrinioEtfHoldingsQueryParams, List[IntrinioEtfHoldingsData]]
|
||||
):
|
||||
"""Intrinio ETF Holdings Fetcher."""
|
||||
|
||||
@staticmethod
|
||||
def transform_query(params: Dict[str, Any]) -> IntrinioEtfHoldingsQueryParams:
|
||||
"""Transform query."""
|
||||
return IntrinioEtfHoldingsQueryParams(**params)
|
||||
|
||||
@staticmethod
|
||||
async def aextract_data(
|
||||
query: IntrinioEtfHoldingsQueryParams,
|
||||
credentials: Optional[Dict[str, str]],
|
||||
**kwargs: Any,
|
||||
) -> List[Dict]:
|
||||
"""Return the raw data from the Intrinio endpoint."""
|
||||
|
||||
api_key = credentials.get("intrinio_api_key") if credentials else ""
|
||||
|
||||
symbol = query.symbol + ":US" if ":" not in query.symbol else query.symbol
|
||||
|
||||
URL = f"https://api-v2.intrinio.com/etfs/{symbol}/holdings?page_size=10000&api_key={api_key}"
|
||||
|
||||
data = []
|
||||
|
||||
async def response_callback(response: ClientResponse, session: ClientSession):
|
||||
"""Async response callback."""
|
||||
results = await response.json()
|
||||
|
||||
if results.get("error"): # type: ignore
|
||||
return results
|
||||
|
||||
if results.get("holdings") and len(results.get("holdings")) > 0: # type: ignore
|
||||
data.extend(results.get("holdings")) # type: ignore
|
||||
while results.get("next_page"): # type: ignore
|
||||
next_page = results["next_page"] # type: ignore
|
||||
next_url = f"{URL}&next_page={next_page}"
|
||||
results = await amake_request(next_url, session=session, **kwargs)
|
||||
if (
|
||||
"holdings" in results
|
||||
and len(results.get("holdings")) > 0 # type: ignore
|
||||
):
|
||||
data.extend(results.get("holdings")) # type: ignore
|
||||
return data
|
||||
|
||||
return await amake_request(URL, response_callback=response_callback, **kwargs) # type: ignore
|
||||
|
||||
@staticmethod
|
||||
def transform_data(
|
||||
query: IntrinioEtfHoldingsQueryParams,
|
||||
data: List[Dict],
|
||||
**kwargs: Any,
|
||||
) -> List[IntrinioEtfHoldingsData]:
|
||||
"""Transform data."""
|
||||
|
||||
if not data or isinstance(data, dict) and data.get("error"):
|
||||
if isinstance(data, list) and data == []:
|
||||
raise RuntimeError(
|
||||
str(
|
||||
f"No holdings were found for {query.symbol}, and the response from Intrinio was empty."
|
||||
)
|
||||
)
|
||||
raise RuntimeError(str(f"{data.get('message')} {query.symbol}: {data['error']}")) # type: ignore
|
||||
|
||||
results: List[IntrinioEtfHoldingsData] = []
|
||||
for d in sorted(data, key=lambda x: x["weighting"], reverse=True):
|
||||
# This field is deprecated and is dupilcated in the response.
|
||||
_ = d.pop("composite_figi", None)
|
||||
results.append(IntrinioEtfHoldingsData.model_validate(d))
|
||||
|
||||
return results
|
||||
@@ -0,0 +1,70 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- application/json
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Connection:
|
||||
- keep-alive
|
||||
method: GET
|
||||
uri: https://api-v2.intrinio.com/etfs/DJIA:US/holdings?api_key=MOCK_API_KEY&page_size=10000
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
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
|
||||
Dp6WX6//AwAA//8DAMc4QPyTNwAA
|
||||
headers:
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Thu, 14 Mar 2024 00:48:14 GMT
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
Vary:
|
||||
- Origin,Accept-Encoding
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -13,6 +13,7 @@ from openbb_intrinio.models.equity_historical import IntrinioEquityHistoricalFet
|
||||
from openbb_intrinio.models.equity_info import IntrinioEquityInfoFetcher
|
||||
from openbb_intrinio.models.equity_quote import IntrinioEquityQuoteFetcher
|
||||
from openbb_intrinio.models.equity_search import IntrinioEquitySearchFetcher
|
||||
from openbb_intrinio.models.etf_holdings import IntrinioEtfHoldingsFetcher
|
||||
from openbb_intrinio.models.etf_info import IntrinioEtfInfoFetcher
|
||||
from openbb_intrinio.models.etf_price_performance import (
|
||||
IntrinioEtfPricePerformanceFetcher,
|
||||
@@ -387,6 +388,15 @@ def test_intrinio_etf_info_fetcher(credentials=test_credentials):
|
||||
assert result is None
|
||||
|
||||
|
||||
@pytest.mark.record_http
|
||||
def test_intrinio_etf_holdings_fetcher(credentials=test_credentials):
|
||||
params = {"symbol": "DJIA"}
|
||||
|
||||
fetcher = IntrinioEtfHoldingsFetcher()
|
||||
result = fetcher.test(params, credentials)
|
||||
assert result is None
|
||||
|
||||
|
||||
@pytest.mark.record_http
|
||||
def test_intrinio_etf_price_performance_fetcher(credentials=test_credentials):
|
||||
params = {"symbol": "SPY:US"}
|
||||
|
||||
Reference in New Issue
Block a user