mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-27 12:40:35 +00:00
[Enhancement] Add analyst_search to the Equity/Estimates Router (#6088)
* standardize price_target * add analyst search * black * more black * ruff * linter, test parmas * last missing param * get rid of convert to upper * ruff * pylint
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
"""Analyst Search Standard Model."""
|
||||
|
||||
from datetime import (
|
||||
datetime,
|
||||
)
|
||||
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
|
||||
|
||||
|
||||
class AnalystSearchQueryParams(QueryParams):
|
||||
"""Analyst Search Query."""
|
||||
|
||||
analyst_name: Optional[str] = Field(
|
||||
default=None,
|
||||
description="A comma separated list of analyst names to bring back."
|
||||
+ " Omitting will bring back all available analysts.",
|
||||
)
|
||||
firm_name: Optional[str] = Field(
|
||||
default=None,
|
||||
description="A comma separated list of firm names to bring back."
|
||||
+ " Omitting will bring back all available firms.",
|
||||
)
|
||||
|
||||
|
||||
class AnalystSearchData(Data):
|
||||
"""Analyst Search data."""
|
||||
|
||||
last_updated: Optional[datetime] = Field(
|
||||
default=None,
|
||||
description="Date of the last update.",
|
||||
)
|
||||
firm_name: Optional[str] = Field(
|
||||
default=None,
|
||||
description="Firm name of the analyst.",
|
||||
)
|
||||
name_first: Optional[str] = Field(
|
||||
default=None,
|
||||
description="Analyst first name.",
|
||||
)
|
||||
name_last: Optional[str] = Field(
|
||||
default=None,
|
||||
description="Analyst last name.",
|
||||
)
|
||||
name_full: str = Field(
|
||||
description="Analyst full name.",
|
||||
)
|
||||
@@ -1,7 +1,11 @@
|
||||
"""Price Target Standard Model."""
|
||||
|
||||
from datetime import datetime
|
||||
from typing import List, Optional, Set, Union
|
||||
from datetime import (
|
||||
date as dateType,
|
||||
datetime,
|
||||
time,
|
||||
)
|
||||
from typing import Optional, Union
|
||||
|
||||
from pydantic import Field, NonNegativeInt, field_validator
|
||||
|
||||
@@ -16,49 +20,67 @@ from openbb_core.provider.utils.descriptions import (
|
||||
class PriceTargetQueryParams(QueryParams):
|
||||
"""Price Target Query."""
|
||||
|
||||
symbol: str = Field(description=QUERY_DESCRIPTIONS.get("symbol", ""))
|
||||
symbol: Optional[str] = Field(
|
||||
default=None, description=QUERY_DESCRIPTIONS.get("symbol", "")
|
||||
)
|
||||
limit: NonNegativeInt = Field(
|
||||
default=100, description=QUERY_DESCRIPTIONS.get("limit", "")
|
||||
default=200, description=QUERY_DESCRIPTIONS.get("limit", "")
|
||||
)
|
||||
|
||||
@field_validator("symbol", mode="before", check_fields=False)
|
||||
@classmethod
|
||||
def upper_symbol(cls, v: str) -> str:
|
||||
def upper_symbol(cls, v: str):
|
||||
"""Convert symbol to uppercase."""
|
||||
return v.upper()
|
||||
return v.upper() if v else None
|
||||
|
||||
|
||||
class PriceTargetData(Data):
|
||||
"""Price Target Data."""
|
||||
|
||||
symbol: str = Field(description=DATA_DESCRIPTIONS.get("symbol", ""))
|
||||
published_date: datetime = Field(description="Published date of the price target.")
|
||||
news_url: Optional[str] = Field(
|
||||
default=None, description="News URL of the price target."
|
||||
published_date: Union[dateType, datetime] = Field(
|
||||
description="Published date of the price target."
|
||||
)
|
||||
news_title: Optional[str] = Field(
|
||||
default=None, description="News title of the price target."
|
||||
published_time: Optional[time] = Field(
|
||||
default=None, description="Time of the original rating, UTC."
|
||||
)
|
||||
symbol: str = Field(description=DATA_DESCRIPTIONS.get("symbol", ""))
|
||||
exchange: Optional[str] = Field(
|
||||
default=None, description="Exchange where the company is traded."
|
||||
)
|
||||
company_name: Optional[str] = Field(
|
||||
default=None, description="Name of company that is the subject of rating."
|
||||
)
|
||||
analyst_name: Optional[str] = Field(default=None, description="Analyst name.")
|
||||
analyst_company: Optional[str] = Field(default=None, description="Analyst company.")
|
||||
price_target: Optional[float] = Field(default=None, description="Price target.")
|
||||
analyst_firm: Optional[str] = Field(
|
||||
default=None,
|
||||
description="Name of the analyst firm that published the price target.",
|
||||
)
|
||||
currency: Optional[str] = Field(
|
||||
default=None, description="Currency the data is denominated in."
|
||||
)
|
||||
price_target: Optional[float] = Field(
|
||||
default=None, description="The current price target."
|
||||
)
|
||||
adj_price_target: Optional[float] = Field(
|
||||
default=None, description="Adjusted price target."
|
||||
default=None,
|
||||
description="Adjusted price target for splits and stock dividends.",
|
||||
)
|
||||
price_target_previous: Optional[float] = Field(
|
||||
default=None, description="Previous price target."
|
||||
)
|
||||
previous_adj_price_target: Optional[float] = Field(
|
||||
default=None, description="Previous adjusted price target."
|
||||
)
|
||||
price_when_posted: Optional[float] = Field(
|
||||
default=None, description="Price when posted."
|
||||
)
|
||||
news_publisher: Optional[str] = Field(
|
||||
default=None, description="News publisher of the price target."
|
||||
rating_current: Optional[str] = Field(
|
||||
default=None, description="The analyst's rating for the company."
|
||||
)
|
||||
news_base_url: Optional[str] = Field(
|
||||
default=None, description="News base URL of the price target."
|
||||
rating_previous: Optional[str] = Field(
|
||||
default=None, description="Previous analyst rating for the company."
|
||||
)
|
||||
action: Optional[str] = Field(
|
||||
default=None,
|
||||
description="Description of the change in rating from firm's last rating.",
|
||||
)
|
||||
|
||||
@field_validator("symbol", mode="before", check_fields=False)
|
||||
@classmethod
|
||||
def upper_symbol(cls, v: Union[str, List[str], Set[str]]):
|
||||
"""Convert symbol to uppercase."""
|
||||
if isinstance(v, str):
|
||||
return v.upper()
|
||||
return ",".join([symbol.upper() for symbol in list(v)])
|
||||
|
||||
@@ -627,7 +627,7 @@ def test_equity_ownership_major_holders(params, headers):
|
||||
@parametrize(
|
||||
"params",
|
||||
[
|
||||
({"symbol": "AAPL", "limit": 10, "provider": "fmp"}),
|
||||
({"symbol": "AAPL", "limit": 10, "provider": "fmp", "with_grade": True}),
|
||||
({"symbol": "AAPL", "provider": "finviz"}),
|
||||
(
|
||||
{
|
||||
@@ -637,13 +637,14 @@ def test_equity_ownership_major_holders(params, headers):
|
||||
# optional provider params
|
||||
"fields": None,
|
||||
"date": None,
|
||||
"date_from": None,
|
||||
"date_to": None,
|
||||
"start_date": None,
|
||||
"end_date": None,
|
||||
"importance": None,
|
||||
"updated": None,
|
||||
"action": None,
|
||||
"analyst": None,
|
||||
"firm": None,
|
||||
"analyst_ids": None,
|
||||
"firm_ids": None,
|
||||
"page": 0,
|
||||
}
|
||||
),
|
||||
],
|
||||
@@ -659,6 +660,34 @@ def test_equity_estimates_price_target(params, headers):
|
||||
assert result.status_code == 200
|
||||
|
||||
|
||||
@parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"limit": 10,
|
||||
"provider": "benzinga",
|
||||
# optional provider params
|
||||
"fields": None,
|
||||
"analyst_ids": None,
|
||||
"firm_ids": None,
|
||||
"firm_name": "Barclays",
|
||||
"analyst_name": None,
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_equity_estimates_analyst_search(params, headers):
|
||||
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/equity/estimates/analyst_search?{query_str}"
|
||||
result = requests.get(url, headers=headers, timeout=10)
|
||||
assert isinstance(result, requests.Response)
|
||||
assert result.status_code == 200
|
||||
|
||||
|
||||
@parametrize(
|
||||
"params",
|
||||
[
|
||||
|
||||
@@ -586,7 +586,7 @@ def test_equity_ownership_major_holders(params, obb):
|
||||
@parametrize(
|
||||
"params",
|
||||
[
|
||||
({"symbol": "AAPL", "limit": 10, "provider": "fmp"}),
|
||||
({"symbol": "AAPL", "limit": 10, "provider": "fmp", "with_grade": True}),
|
||||
(
|
||||
{
|
||||
"symbol": "AAPL",
|
||||
@@ -595,13 +595,14 @@ def test_equity_ownership_major_holders(params, obb):
|
||||
# optional provider params
|
||||
"fields": None,
|
||||
"date": None,
|
||||
"date_from": None,
|
||||
"date_to": None,
|
||||
"start_date": None,
|
||||
"end_date": None,
|
||||
"importance": None,
|
||||
"updated": None,
|
||||
"action": None,
|
||||
"analyst": None,
|
||||
"firm": None,
|
||||
"analyst_ids": None,
|
||||
"firm_ids": None,
|
||||
"page": 0,
|
||||
}
|
||||
),
|
||||
({"symbol": "AAPL", "provider": "finviz"}),
|
||||
@@ -615,6 +616,31 @@ def test_equity_estimates_price_target(params, obb):
|
||||
assert result.results is not None
|
||||
|
||||
|
||||
@parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"limit": 10,
|
||||
"provider": "benzinga",
|
||||
# optional provider params
|
||||
"fields": None,
|
||||
"analyst_ids": None,
|
||||
"firm_ids": None,
|
||||
"firm_name": "Barclays",
|
||||
"analyst_name": None,
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_equity_estimates_analyst_search(params, obb):
|
||||
result = obb.equity.estimates.analyst_search(**params)
|
||||
assert result
|
||||
assert isinstance(result, OBBject)
|
||||
assert result.results is not None
|
||||
|
||||
|
||||
@parametrize(
|
||||
"params",
|
||||
[
|
||||
|
||||
@@ -15,34 +15,69 @@ router = Router(prefix="/estimates")
|
||||
# pylint: disable=unused-argument
|
||||
|
||||
|
||||
@router.command(model="PriceTarget")
|
||||
@router.command(
|
||||
model="PriceTarget",
|
||||
exclude_auto_examples=True,
|
||||
examples=[
|
||||
'obb.equity.estimates.price_target(start_date="2020-01-01", end_date="2024-02-16",limit=10, symbol="msft", provider="benzinga",action="downgrades").to_df()' # noqa: E501 pylint: disable=line-too-long
|
||||
],
|
||||
)
|
||||
async def price_target(
|
||||
cc: CommandContext,
|
||||
provider_choices: ProviderChoices,
|
||||
standard_params: StandardParams,
|
||||
extra_params: ExtraParams,
|
||||
) -> OBBject:
|
||||
"""Price Target. Price target data."""
|
||||
"""Analyst price targets by company."""
|
||||
return await OBBject.from_query(Query(**locals()))
|
||||
|
||||
|
||||
@router.command(model="AnalystEstimates")
|
||||
@router.command(
|
||||
model="AnalystEstimates",
|
||||
exclude_auto_examples=True,
|
||||
examples=[
|
||||
'obb.equity.estimates.historical("AAPL", period="quarter", provider="fmp").to_df()',
|
||||
],
|
||||
)
|
||||
async def historical(
|
||||
cc: CommandContext,
|
||||
provider_choices: ProviderChoices,
|
||||
standard_params: StandardParams,
|
||||
extra_params: ExtraParams,
|
||||
) -> OBBject:
|
||||
"""Historical Analyst Estimates. Analyst stock recommendations."""
|
||||
"""Historical analyst estimates for earnings and revenue."""
|
||||
return await OBBject.from_query(Query(**locals()))
|
||||
|
||||
|
||||
@router.command(model="PriceTargetConsensus")
|
||||
@router.command(
|
||||
model="PriceTargetConsensus",
|
||||
exclude_auto_examples=True,
|
||||
examples=[
|
||||
'obb.equity.estimates.consensus("AAPL,MSFT", provider="yfinance").to_df()'
|
||||
],
|
||||
)
|
||||
async def consensus(
|
||||
cc: CommandContext,
|
||||
provider_choices: ProviderChoices,
|
||||
standard_params: StandardParams,
|
||||
extra_params: ExtraParams,
|
||||
) -> OBBject:
|
||||
"""Price Target Consensus. Price target consensus data."""
|
||||
"""Consensus price target and recommendation."""
|
||||
return await OBBject.from_query(Query(**locals()))
|
||||
|
||||
|
||||
@router.command(
|
||||
model="AnalystSearch",
|
||||
exclude_auto_examples=True,
|
||||
examples=[
|
||||
'obb.equity.estimates.analyst_search(firm_name="Wedbush", provider="benzinga").to_df()',
|
||||
],
|
||||
)
|
||||
async def analyst_search(
|
||||
cc: CommandContext,
|
||||
provider_choices: ProviderChoices,
|
||||
standard_params: StandardParams,
|
||||
extra_params: ExtraParams,
|
||||
) -> OBBject:
|
||||
"""Search for specific analysts and get their forecast track record."""
|
||||
return await OBBject.from_query(Query(**locals()))
|
||||
|
||||
@@ -12,6 +12,7 @@ from typing_extensions import Annotated
|
||||
|
||||
class ROUTER_equity_estimates(Container):
|
||||
"""/equity/estimates
|
||||
analyst_search
|
||||
consensus
|
||||
historical
|
||||
price_target
|
||||
@@ -20,6 +21,176 @@ class ROUTER_equity_estimates(Container):
|
||||
def __repr__(self) -> str:
|
||||
return self.__doc__ or ""
|
||||
|
||||
@validate
|
||||
def analyst_search(
|
||||
self,
|
||||
analyst_name: Annotated[
|
||||
Optional[str],
|
||||
OpenBBCustomParameter(
|
||||
description="A comma separated list of analyst names to bring back. Omitting will bring back all available analysts."
|
||||
),
|
||||
] = None,
|
||||
firm_name: Annotated[
|
||||
Optional[str],
|
||||
OpenBBCustomParameter(
|
||||
description="A comma separated list of firm names to bring back. Omitting will bring back all available firms."
|
||||
),
|
||||
] = None,
|
||||
provider: Optional[Literal["benzinga"]] = None,
|
||||
**kwargs
|
||||
) -> OBBject:
|
||||
"""Search for specific analysts and get their forecast track record.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
analyst_name : Optional[str]
|
||||
A comma separated list of analyst names to bring back. Omitting will bring back all available analysts.
|
||||
firm_name : Optional[str]
|
||||
A comma separated list of firm names to bring back. Omitting will bring back all available firms.
|
||||
provider : Optional[Literal['benzinga']]
|
||||
The provider to use for the query, by default None.
|
||||
If None, the provider specified in defaults is selected or 'benzinga' if there is
|
||||
no default.
|
||||
analyst_ids : Optional[Union[str, List[str]]]
|
||||
A comma separated list of analyst IDs to bring back. (provider: benzinga)
|
||||
firm_ids : Optional[Union[str, List[str]]]
|
||||
A comma separated list of firm IDs to bring back. (provider: benzinga)
|
||||
limit : Optional[int]
|
||||
Number of results returned. Limit 1000. (provider: benzinga)
|
||||
page : Optional[int]
|
||||
Page offset. For optimization, performance and technical reasons, page offsets are limited from 0 - 100000. Limit the query results by other parameters such as date. (provider: benzinga)
|
||||
fields : Optional[Union[str, List[str]]]
|
||||
Comma-separated list of fields to include in the response. See https://docs.benzinga.io/benzinga-apis/calendar/get-ratings to learn about the available fields. (provider: benzinga)
|
||||
|
||||
Returns
|
||||
-------
|
||||
OBBject
|
||||
results : List[AnalystSearch]
|
||||
Serializable results.
|
||||
provider : Optional[Literal['benzinga']]
|
||||
Provider name.
|
||||
warnings : Optional[List[Warning_]]
|
||||
List of warnings.
|
||||
chart : Optional[Chart]
|
||||
Chart object.
|
||||
extra: Dict[str, Any]
|
||||
Extra info.
|
||||
|
||||
AnalystSearch
|
||||
-------------
|
||||
last_updated : Optional[datetime]
|
||||
Date of the last update.
|
||||
firm_name : Optional[str]
|
||||
Firm name of the analyst.
|
||||
name_first : Optional[str]
|
||||
Analyst first name.
|
||||
name_last : Optional[str]
|
||||
Analyst last name.
|
||||
name_full : str
|
||||
Analyst full name.
|
||||
analyst_id : Optional[str]
|
||||
ID of the analyst. (provider: benzinga)
|
||||
firm_id : Optional[str]
|
||||
ID of the analyst firm. (provider: benzinga)
|
||||
smart_score : Optional[float]
|
||||
A weighted average of the total_ratings_percentile, overall_avg_return_percentile, and overall_success_rate (provider: benzinga)
|
||||
overall_success_rate : Optional[float]
|
||||
The percentage (normalized) of gain/loss ratings that resulted in a gain overall. (provider: benzinga)
|
||||
overall_avg_return_percentile : Optional[float]
|
||||
The percentile (normalized) of this analyst's overall average return per rating in comparison to other analysts' overall average returns per rating. (provider: benzinga)
|
||||
total_ratings_percentile : Optional[float]
|
||||
The percentile (normalized) of this analyst's total number of ratings in comparison to the total number of ratings published by all other analysts (provider: benzinga)
|
||||
total_ratings : Optional[int]
|
||||
Number of recommendations made by this analyst. (provider: benzinga)
|
||||
overall_gain_count : Optional[int]
|
||||
The number of ratings that have gained value since the date of recommendation (provider: benzinga)
|
||||
overall_loss_count : Optional[int]
|
||||
The number of ratings that have lost value since the date of recommendation (provider: benzinga)
|
||||
overall_average_return : Optional[float]
|
||||
The average percent (normalized) price difference per rating since the date of recommendation (provider: benzinga)
|
||||
overall_std_dev : Optional[float]
|
||||
The standard deviation in percent (normalized) price difference in the analyst's ratings since the date of recommendation (provider: benzinga)
|
||||
gain_count_1m : Optional[int]
|
||||
The number of ratings that have gained value over the last month (provider: benzinga)
|
||||
loss_count_1m : Optional[int]
|
||||
The number of ratings that have lost value over the last month (provider: benzinga)
|
||||
average_return_1m : Optional[float]
|
||||
The average percent (normalized) price difference per rating over the last month (provider: benzinga)
|
||||
std_dev_1m : Optional[float]
|
||||
The standard deviation in percent (normalized) price difference in the analyst's ratings over the last month (provider: benzinga)
|
||||
gain_count_3m : Optional[int]
|
||||
The number of ratings that have gained value over the last 3 months (provider: benzinga)
|
||||
loss_count_3m : Optional[int]
|
||||
The number of ratings that have lost value over the last 3 months (provider: benzinga)
|
||||
average_return_3m : Optional[float]
|
||||
The average percent (normalized) price difference per rating over the last 3 months (provider: benzinga)
|
||||
std_dev_3m : Optional[float]
|
||||
The standard deviation in percent (normalized) price difference in the analyst's ratings over the last 3 months (provider: benzinga)
|
||||
gain_count_6m : Optional[int]
|
||||
The number of ratings that have gained value over the last 6 months (provider: benzinga)
|
||||
loss_count_6m : Optional[int]
|
||||
The number of ratings that have lost value over the last 6 months (provider: benzinga)
|
||||
average_return_6m : Optional[float]
|
||||
The average percent (normalized) price difference per rating over the last 6 months (provider: benzinga)
|
||||
std_dev_6m : Optional[float]
|
||||
The standard deviation in percent (normalized) price difference in the analyst's ratings over the last 6 months (provider: benzinga)
|
||||
gain_count_9m : Optional[int]
|
||||
The number of ratings that have gained value over the last 9 months (provider: benzinga)
|
||||
loss_count_9m : Optional[int]
|
||||
The number of ratings that have lost value over the last 9 months (provider: benzinga)
|
||||
average_return_9m : Optional[float]
|
||||
The average percent (normalized) price difference per rating over the last 9 months (provider: benzinga)
|
||||
std_dev_9m : Optional[float]
|
||||
The standard deviation in percent (normalized) price difference in the analyst's ratings over the last 9 months (provider: benzinga)
|
||||
gain_count_1y : Optional[int]
|
||||
The number of ratings that have gained value over the last 1 year (provider: benzinga)
|
||||
loss_count_1y : Optional[int]
|
||||
The number of ratings that have lost value over the last 1 year (provider: benzinga)
|
||||
average_return_1y : Optional[float]
|
||||
The average percent (normalized) price difference per rating over the last 1 year (provider: benzinga)
|
||||
std_dev_1y : Optional[float]
|
||||
The standard deviation in percent (normalized) price difference in the analyst's ratings over the last 1 year (provider: benzinga)
|
||||
gain_count_2y : Optional[int]
|
||||
The number of ratings that have gained value over the last 2 years (provider: benzinga)
|
||||
loss_count_2y : Optional[int]
|
||||
The number of ratings that have lost value over the last 2 years (provider: benzinga)
|
||||
average_return_2y : Optional[float]
|
||||
The average percent (normalized) price difference per rating over the last 2 years (provider: benzinga)
|
||||
std_dev_2y : Optional[float]
|
||||
The standard deviation in percent (normalized) price difference in the analyst's ratings over the last 2 years (provider: benzinga)
|
||||
gain_count_3y : Optional[int]
|
||||
The number of ratings that have gained value over the last 3 years (provider: benzinga)
|
||||
loss_count_3y : Optional[int]
|
||||
The number of ratings that have lost value over the last 3 years (provider: benzinga)
|
||||
average_return_3y : Optional[float]
|
||||
The average percent (normalized) price difference per rating over the last 3 years (provider: benzinga)
|
||||
std_dev_3y : Optional[float]
|
||||
The standard deviation in percent (normalized) price difference in the analyst's ratings over the last 3 years (provider: benzinga)
|
||||
|
||||
Example
|
||||
-------
|
||||
>>> from openbb import obb
|
||||
>>> obb.equity.estimates.analyst_search(firm_name="Wedbush", provider="benzinga").to_df()
|
||||
""" # noqa: E501
|
||||
|
||||
return self._run(
|
||||
"/equity/estimates/analyst_search",
|
||||
**filter_inputs(
|
||||
provider_choices={
|
||||
"provider": self._get_provider(
|
||||
provider,
|
||||
"/equity/estimates/analyst_search",
|
||||
("benzinga",),
|
||||
)
|
||||
},
|
||||
standard_params={
|
||||
"analyst_name": analyst_name,
|
||||
"firm_name": firm_name,
|
||||
},
|
||||
extra_params=kwargs,
|
||||
)
|
||||
)
|
||||
|
||||
@validate
|
||||
def consensus(
|
||||
self,
|
||||
@@ -32,7 +203,7 @@ class ROUTER_equity_estimates(Container):
|
||||
provider: Optional[Literal["fmp", "yfinance"]] = None,
|
||||
**kwargs
|
||||
) -> OBBject:
|
||||
"""Price Target Consensus. Price target consensus data.
|
||||
"""Consensus price target and recommendation.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
@@ -83,7 +254,7 @@ class ROUTER_equity_estimates(Container):
|
||||
Example
|
||||
-------
|
||||
>>> from openbb import obb
|
||||
>>> obb.equity.estimates.consensus(symbol="AAPL")
|
||||
>>> obb.equity.estimates.consensus("AAPL,MSFT", provider="yfinance").to_df()
|
||||
""" # noqa: E501
|
||||
|
||||
return self._run(
|
||||
@@ -121,7 +292,7 @@ class ROUTER_equity_estimates(Container):
|
||||
provider: Optional[Literal["fmp"]] = None,
|
||||
**kwargs
|
||||
) -> OBBject:
|
||||
"""Historical Analyst Estimates. Analyst stock recommendations.
|
||||
"""Historical analyst estimates for earnings and revenue.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
@@ -200,7 +371,7 @@ class ROUTER_equity_estimates(Container):
|
||||
Example
|
||||
-------
|
||||
>>> from openbb import obb
|
||||
>>> obb.equity.estimates.historical(symbol="AAPL", period="annual", limit=30)
|
||||
>>> obb.equity.estimates.historical("AAPL", period="quarter", provider="fmp").to_df()
|
||||
""" # noqa: E501
|
||||
|
||||
return self._run(
|
||||
@@ -226,23 +397,23 @@ class ROUTER_equity_estimates(Container):
|
||||
def price_target(
|
||||
self,
|
||||
symbol: Annotated[
|
||||
Union[str, List[str]],
|
||||
Union[str, None, List[str]],
|
||||
OpenBBCustomParameter(
|
||||
description="Symbol to get data for. Multiple items allowed: benzinga."
|
||||
),
|
||||
],
|
||||
] = None,
|
||||
limit: Annotated[
|
||||
int,
|
||||
OpenBBCustomParameter(description="The number of data entries to return."),
|
||||
] = 100,
|
||||
] = 200,
|
||||
provider: Optional[Literal["benzinga", "fmp"]] = None,
|
||||
**kwargs
|
||||
) -> OBBject:
|
||||
"""Price Target. Price target data.
|
||||
"""Analyst price targets by company.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
symbol : Union[str, List[str]]
|
||||
symbol : Union[str, None, List[str]]
|
||||
Symbol to get data for. Multiple items allowed: benzinga.
|
||||
limit : int
|
||||
The number of data entries to return.
|
||||
@@ -250,24 +421,26 @@ class ROUTER_equity_estimates(Container):
|
||||
The provider to use for the query, by default None.
|
||||
If None, the provider specified in defaults is selected or 'benzinga' if there is
|
||||
no default.
|
||||
fields : Optional[str]
|
||||
Comma-separated list of fields to include in the response. See https://docs.benzinga.io/benzinga-apis/calendar/get-ratings to learn about the available fields. (provider: benzinga)
|
||||
date : Optional[str]
|
||||
page : Optional[int]
|
||||
Page offset. For optimization, performance and technical reasons, page offsets are limited from 0 - 100000. Limit the query results by other parameters such as date. Used in conjunction with the limit and date parameters. (provider: benzinga)
|
||||
date : Optional[datetime.date]
|
||||
Date for calendar data, shorthand for date_from and date_to. (provider: benzinga)
|
||||
date_from : Optional[str]
|
||||
Date to query from point in time. (provider: benzinga)
|
||||
date_to : Optional[str]
|
||||
Date to query to point in time. (provider: benzinga)
|
||||
start_date : Optional[datetime.date]
|
||||
Start date of the data, in YYYY-MM-DD format. (provider: benzinga)
|
||||
end_date : Optional[datetime.date]
|
||||
End date of the data, in YYYY-MM-DD format. (provider: benzinga)
|
||||
updated : Optional[Union[datetime.date, int]]
|
||||
Records last Updated Unix timestamp (UTC). This will force the sort order to be Greater Than or Equal to the timestamp indicated. The date can be a date string or a Unix timestamp. The date string must be in the format of YYYY-MM-DD. (provider: benzinga)
|
||||
importance : Optional[int]
|
||||
Importance level to filter by. (provider: benzinga)
|
||||
updated : Optional[int]
|
||||
Records last updated Unix timestamp (UTC). (provider: benzinga)
|
||||
action : Optional[Literal['Downgrades', 'Maintains', 'Reinstates', 'Reiterates', 'Upgrades', 'Assumes', 'Initiates Coverage On', 'Terminates Coverage On', 'Removes', 'Suspends', 'Firm Dissolved']]
|
||||
Importance level to filter by. Uses Greater Than or Equal To the importance indicated (provider: benzinga)
|
||||
action : Optional[Literal['downgrades', 'maintains', 'reinstates', 'reiterates', 'upgrades', 'assumes', 'initiates', 'terminates', 'removes', 'suspends', 'firm_dissolved']]
|
||||
Filter by a specific action_company. (provider: benzinga)
|
||||
analyst : Optional[str]
|
||||
Comma-separated list of analyst (person) IDs. (provider: benzinga)
|
||||
firm : Optional[str]
|
||||
Comma-separated list of analyst firm IDs. (provider: benzinga)
|
||||
analyst_ids : Optional[Union[str, List[str]]]
|
||||
Comma-separated list of analyst (person) IDs. Omitting will bring back all available analysts. (provider: benzinga)
|
||||
firm_ids : Optional[Union[str, List[str]]]
|
||||
Comma-separated list of firm IDs. (provider: benzinga)
|
||||
fields : Optional[Union[str, List[str]]]
|
||||
Comma-separated list of fields to include in the response. See https://docs.benzinga.io/benzinga-apis/calendar/get-ratings to learn about the available fields. (provider: benzinga)
|
||||
with_grade : bool
|
||||
Include upgrades and downgrades in the response. (provider: fmp)
|
||||
|
||||
@@ -287,75 +460,67 @@ class ROUTER_equity_estimates(Container):
|
||||
|
||||
PriceTarget
|
||||
-----------
|
||||
published_date : Union[date, datetime]
|
||||
Published date of the price target.
|
||||
published_time : Optional[datetime.time]
|
||||
Time of the original rating, UTC.
|
||||
symbol : str
|
||||
Symbol representing the entity requested in the data.
|
||||
published_date : datetime
|
||||
Published date of the price target.
|
||||
news_url : Optional[str]
|
||||
News URL of the price target.
|
||||
news_title : Optional[str]
|
||||
News title of the price target.
|
||||
exchange : Optional[str]
|
||||
Exchange where the company is traded.
|
||||
company_name : Optional[str]
|
||||
Name of company that is the subject of rating.
|
||||
analyst_name : Optional[str]
|
||||
Analyst name.
|
||||
analyst_company : Optional[str]
|
||||
Analyst company.
|
||||
analyst_firm : Optional[str]
|
||||
Name of the analyst firm that published the price target.
|
||||
currency : Optional[str]
|
||||
Currency the data is denominated in.
|
||||
price_target : Optional[float]
|
||||
Price target.
|
||||
The current price target.
|
||||
adj_price_target : Optional[float]
|
||||
Adjusted price target.
|
||||
Adjusted price target for splits and stock dividends.
|
||||
price_target_previous : Optional[float]
|
||||
Previous price target.
|
||||
previous_adj_price_target : Optional[float]
|
||||
Previous adjusted price target.
|
||||
price_when_posted : Optional[float]
|
||||
Price when posted.
|
||||
news_publisher : Optional[str]
|
||||
News publisher of the price target.
|
||||
news_base_url : Optional[str]
|
||||
News base URL of the price target.
|
||||
action_company : Optional[Literal['Downgrades', 'Maintains', 'Reinstates', 'Reiterates', 'Upgrades', 'Assumes', 'Initiates Coverage On', 'Terminates Coverage On', 'Removes', 'Suspends', 'Firm Dissolved', '']]
|
||||
Description of the change in rating from firm's last rating.Note that all of these terms are precisely defined. (provider: benzinga)
|
||||
action_pt : Optional[Literal['Announces', 'Maintains', 'Lowers', 'Raises', 'Removes', 'Adjusts', '']]
|
||||
rating_current : Optional[str]
|
||||
The analyst's rating for the company.
|
||||
rating_previous : Optional[str]
|
||||
Previous analyst rating for the company.
|
||||
action : Optional[str]
|
||||
Description of the change in rating from firm's last rating.
|
||||
action_change : Optional[Literal['Announces', 'Maintains', 'Lowers', 'Raises', 'Removes', 'Adjusts']]
|
||||
Description of the change in price target from firm's last price target. (provider: benzinga)
|
||||
adjusted_pt_prior : Optional[str]
|
||||
Analyst's prior price target, adjusted to account for stock splits and stock dividends. If none are applicable, the pt_prior value is used. (provider: benzinga)
|
||||
analyst_id : Optional[str]
|
||||
Id of the analyst. (provider: benzinga)
|
||||
currency : Optional[str]
|
||||
Currency the data is denominated in. (provider: benzinga)
|
||||
exchange : Optional[str]
|
||||
Exchange of the price target. (provider: benzinga)
|
||||
id : Optional[str]
|
||||
Unique ID of this entry. (provider: benzinga)
|
||||
importance : Optional[Literal[0, 1, 2, 3, 4, 5]]
|
||||
Subjective Basis of How Important Event is to Market. 5 = High (provider: benzinga)
|
||||
notes : Optional[str]
|
||||
Notes of the price target. (provider: benzinga)
|
||||
pt_prior : Optional[str]
|
||||
Analyst's prior price target. (provider: benzinga)
|
||||
rating_current : Optional[str]
|
||||
The analyst's rating for the company. (provider: benzinga)
|
||||
rating_prior : Optional[str]
|
||||
Prior analyst rating for the company. (provider: benzinga)
|
||||
ratings_accuracy : Optional[str]
|
||||
Ratings accuracy of the price target. (provider: benzinga)
|
||||
time : Optional[str]
|
||||
Last updated timestamp, UTC. (provider: benzinga)
|
||||
updated : Optional[int]
|
||||
Last updated timestamp, UTC. (provider: benzinga)
|
||||
url : Optional[str]
|
||||
analyst_id : Optional[str]
|
||||
Id of the analyst. (provider: benzinga)
|
||||
url_news : Optional[str]
|
||||
URL for analyst ratings news articles for this ticker on Benzinga.com. (provider: benzinga)
|
||||
url_analyst : Optional[str]
|
||||
URL for analyst ratings page for this ticker on Benzinga.com. (provider: benzinga)
|
||||
url_calendar : Optional[str]
|
||||
URL for analyst ratings page for this ticker on Benzinga.com. (provider: benzinga)
|
||||
name : Optional[str]
|
||||
Name of company that is subject of rating. (provider: benzinga)
|
||||
new_grade : Optional[str]
|
||||
New grade (provider: fmp)
|
||||
previous_grade : Optional[str]
|
||||
Previous grade (provider: fmp)
|
||||
grading_company : Optional[str]
|
||||
Grading company (provider: fmp)
|
||||
id : Optional[str]
|
||||
Unique ID of this entry. (provider: benzinga)
|
||||
last_updated : Optional[datetime]
|
||||
Last updated timestamp, UTC. (provider: benzinga)
|
||||
news_url : Optional[str]
|
||||
News URL of the price target. (provider: fmp)
|
||||
news_title : Optional[str]
|
||||
News title of the price target. (provider: fmp)
|
||||
news_publisher : Optional[str]
|
||||
News publisher of the price target. (provider: fmp)
|
||||
news_base_url : Optional[str]
|
||||
News base URL of the price target. (provider: fmp)
|
||||
|
||||
Example
|
||||
-------
|
||||
>>> from openbb import obb
|
||||
>>> obb.equity.estimates.price_target(symbol="AAPL", limit=100)
|
||||
>>> obb.equity.estimates.price_target(start_date="2020-01-01", end_date="2024-02-16",limit=10, symbol="msft", provider="benzinga",action="downgrades").to_df()
|
||||
""" # noqa: E501
|
||||
|
||||
return self._run(
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
"equity_discovery_undervalued_growth": "/equity/discovery/undervalued_growth",
|
||||
"equity_discovery_undervalued_large_caps": "/equity/discovery/undervalued_large_caps",
|
||||
"equity_estimates": "/equity/estimates",
|
||||
"equity_estimates_analyst_search": "/equity/estimates/analyst_search",
|
||||
"equity_estimates_consensus": "/equity/estimates/consensus",
|
||||
"equity_estimates_historical": "/equity/estimates/historical",
|
||||
"equity_estimates_price_target": "/equity/estimates/price_target",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"""Benzinga provider module."""
|
||||
|
||||
from openbb_benzinga.models.analyst_search import BenzingaAnalystSearchFetcher
|
||||
from openbb_benzinga.models.company_news import BenzingaCompanyNewsFetcher
|
||||
from openbb_benzinga.models.price_target import BenzingaPriceTargetFetcher
|
||||
from openbb_benzinga.models.world_news import BenzingaWorldNewsFetcher
|
||||
@@ -12,6 +13,7 @@ benzinga_provider = Provider(
|
||||
focused on information that moves the market.""",
|
||||
credentials=["api_key"],
|
||||
fetcher_dict={
|
||||
"AnalystSearch": BenzingaAnalystSearchFetcher,
|
||||
"CompanyNews": BenzingaCompanyNewsFetcher,
|
||||
"WorldNews": BenzingaWorldNewsFetcher,
|
||||
"PriceTarget": BenzingaPriceTargetFetcher,
|
||||
|
||||
@@ -0,0 +1,393 @@
|
||||
"""Benzinga Analyst Search Model."""
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, List, Optional, Union
|
||||
|
||||
from openbb_core.provider.abstract.fetcher import Fetcher
|
||||
from openbb_core.provider.standard_models.analyst_search import (
|
||||
AnalystSearchData,
|
||||
AnalystSearchQueryParams,
|
||||
)
|
||||
from openbb_core.provider.utils.errors import EmptyDataError
|
||||
from openbb_core.provider.utils.helpers import amake_request, get_querystring
|
||||
from pydantic import Field, field_validator, model_validator
|
||||
from pytz import UTC
|
||||
|
||||
|
||||
class BenzingaAnalystSearchQueryParams(AnalystSearchQueryParams):
|
||||
"""Benzinga Analyst Search Query.
|
||||
|
||||
Source: https://docs.benzinga.io/benzinga-apis/calendar/get-analysts
|
||||
"""
|
||||
|
||||
__alias_dict__ = {
|
||||
"analyst_ids": "id",
|
||||
"firm_ids": "firm",
|
||||
"limit": "pageSize",
|
||||
}
|
||||
|
||||
analyst_ids: Optional[Union[str, List[str]]] = Field(
|
||||
default=None,
|
||||
description="A comma separated list of analyst IDs to bring back.",
|
||||
)
|
||||
firm_ids: Optional[Union[str, List[str]]] = Field(
|
||||
default=None,
|
||||
description="A comma separated list of firm IDs to bring back.",
|
||||
)
|
||||
limit: Optional[int] = Field(
|
||||
default=100,
|
||||
description="Number of results returned. Limit 1000.",
|
||||
)
|
||||
page: Optional[int] = Field(
|
||||
default=0,
|
||||
description="Page offset. For optimization,"
|
||||
+ " performance and technical reasons, page offsets"
|
||||
+ " are limited from 0 - 100000."
|
||||
+ " Limit the query results by other parameters such as date.",
|
||||
)
|
||||
fields: Optional[Union[List[str], str]] = Field(
|
||||
default=None,
|
||||
description="Comma-separated list of fields to include in the response."
|
||||
" See https://docs.benzinga.io/benzinga-apis/calendar/get-ratings to learn about the available fields.",
|
||||
)
|
||||
|
||||
@field_validator(
|
||||
"fields", "firm_ids", "analyst_ids", mode="before", check_fields=False
|
||||
)
|
||||
@classmethod
|
||||
def convert_list(cls, v: Union[str, List[str]]):
|
||||
"""Convert a List[str] to a string list."""
|
||||
if isinstance(v, str):
|
||||
return v.upper()
|
||||
return ",".join([symbol.upper() for symbol in list(v)])
|
||||
|
||||
@field_validator(
|
||||
"analyst_ids",
|
||||
"firm_ids",
|
||||
"analyst_name",
|
||||
"firm_name",
|
||||
mode="before",
|
||||
check_fields=False,
|
||||
)
|
||||
@classmethod
|
||||
def validate_list(cls, v: Union[str, List[str], None]):
|
||||
"""Validate list."""
|
||||
if isinstance(v, str):
|
||||
return v
|
||||
return ",".join(v) if v else None
|
||||
|
||||
|
||||
class BenzingaAnalystSearchData(AnalystSearchData):
|
||||
"""Benzinga Analyst Search Data."""
|
||||
|
||||
__alias_dict__ = {
|
||||
"analyst_id": "id",
|
||||
"last_updated": "updated",
|
||||
}
|
||||
analyst_id: Optional[str] = Field(
|
||||
default=None,
|
||||
description="ID of the analyst.",
|
||||
)
|
||||
firm_id: Optional[str] = Field(
|
||||
default=None,
|
||||
description="ID of the analyst firm.",
|
||||
)
|
||||
smart_score: Optional[float] = Field(
|
||||
default=None,
|
||||
description="A weighted average of the total_ratings_percentile,"
|
||||
+ " overall_avg_return_percentile, and overall_success_rate",
|
||||
)
|
||||
overall_success_rate: Optional[float] = Field(
|
||||
default=None,
|
||||
description="The percentage (normalized) of gain/loss ratings that resulted in a gain overall.",
|
||||
json_schema_extra={"unit_measurement": "percent", "frontend_multiply": 100},
|
||||
)
|
||||
overall_avg_return_percentile: Optional[float] = Field(
|
||||
default=None,
|
||||
description="The percentile (normalized) of this analyst's overall average"
|
||||
+ " return per rating in comparison to other analysts' overall average returns per rating.",
|
||||
json_schema_extra={"unit_measurement": "percent", "frontend_multiply": 100},
|
||||
)
|
||||
total_ratings_percentile: Optional[float] = Field(
|
||||
default=None,
|
||||
description="The percentile (normalized) of this analyst's total number of ratings"
|
||||
+ " in comparison to the total number of ratings published by all other analysts",
|
||||
json_schema_extra={"unit_measurement": "percent", "frontend_multiply": 100},
|
||||
)
|
||||
total_ratings: Optional[int] = Field(
|
||||
default=None,
|
||||
description="Number of recommendations made by this analyst.",
|
||||
)
|
||||
overall_gain_count: Optional[int] = Field(
|
||||
default=None,
|
||||
description="The number of ratings that have gained value since the date of recommendation",
|
||||
)
|
||||
overall_loss_count: Optional[int] = Field(
|
||||
default=None,
|
||||
description="The number of ratings that have lost value since the date of recommendation",
|
||||
)
|
||||
overall_average_return: Optional[float] = Field(
|
||||
default=None,
|
||||
description="The average percent (normalized) price difference per rating since the date of recommendation",
|
||||
json_schema_extra={"unit_measurement": "percent", "frontend_multiply": 100},
|
||||
)
|
||||
overall_std_dev: Optional[float] = Field(
|
||||
default=None,
|
||||
description="The standard deviation in percent (normalized) price difference in the"
|
||||
+ " analyst's ratings since the date of recommendation",
|
||||
json_schema_extra={"unit_measurement": "percent", "frontend_multiply": 100},
|
||||
alias="overall_stdev",
|
||||
)
|
||||
gain_count_1m: Optional[int] = Field(
|
||||
default=None,
|
||||
description="The number of ratings that have gained value over the last month",
|
||||
alias="1m_gain_count",
|
||||
)
|
||||
loss_count_1m: Optional[int] = Field(
|
||||
default=None,
|
||||
description="The number of ratings that have lost value over the last month",
|
||||
alias="1m_loss_count",
|
||||
)
|
||||
average_return_1m: Optional[float] = Field(
|
||||
default=None,
|
||||
description="The average percent (normalized) price difference per rating over the last month",
|
||||
json_schema_extra={"unit_measurement": "percent", "frontend_multiply": 100},
|
||||
alias="1m_average_return",
|
||||
)
|
||||
std_dev_1m: Optional[float] = Field(
|
||||
default=None,
|
||||
description="The standard deviation in percent (normalized) price difference in the"
|
||||
+ " analyst's ratings over the last month",
|
||||
json_schema_extra={"unit_measurement": "percent", "frontend_multiply": 100},
|
||||
alias="1m_stdev",
|
||||
)
|
||||
gain_count_3m: Optional[int] = Field(
|
||||
default=None,
|
||||
description="The number of ratings that have gained value over the last 3 months",
|
||||
alias="3m_gain_count",
|
||||
)
|
||||
loss_count_3m: Optional[int] = Field(
|
||||
default=None,
|
||||
description="The number of ratings that have lost value over the last 3 months",
|
||||
alias="3m_loss_count",
|
||||
)
|
||||
average_return_3m: Optional[float] = Field(
|
||||
default=None,
|
||||
description="The average percent (normalized) price difference per rating over"
|
||||
+ " the last 3 months",
|
||||
json_schema_extra={"unit_measurement": "percent", "frontend_multiply": 100},
|
||||
alias="3m_average_return",
|
||||
)
|
||||
std_dev_3m: Optional[float] = Field(
|
||||
default=None,
|
||||
description="The standard deviation in percent (normalized) price difference in the"
|
||||
+ " analyst's ratings over the last 3 months",
|
||||
json_schema_extra={"unit_measurement": "percent", "frontend_multiply": 100},
|
||||
alias="3m_stdev",
|
||||
)
|
||||
gain_count_6m: Optional[int] = Field(
|
||||
default=None,
|
||||
description="The number of ratings that have gained value over the last 6 months",
|
||||
alias="6m_gain_count",
|
||||
)
|
||||
loss_count_6m: Optional[int] = Field(
|
||||
default=None,
|
||||
description="The number of ratings that have lost value over the last 6 months",
|
||||
alias="6m_loss_count",
|
||||
)
|
||||
average_return_6m: Optional[float] = Field(
|
||||
default=None,
|
||||
description="The average percent (normalized) price difference per rating over"
|
||||
+ " the last 6 months",
|
||||
json_schema_extra={"unit_measurement": "percent", "frontend_multiply": 100},
|
||||
alias="6m_average_return",
|
||||
)
|
||||
std_dev_6m: Optional[float] = Field(
|
||||
default=None,
|
||||
description="The standard deviation in percent (normalized) price difference in the"
|
||||
+ " analyst's ratings over the last 6 months",
|
||||
json_schema_extra={"unit_measurement": "percent", "frontend_multiply": 100},
|
||||
alias="6m_stdev",
|
||||
)
|
||||
gain_count_9m: Optional[int] = Field(
|
||||
default=None,
|
||||
description="The number of ratings that have gained value over the last 9 months",
|
||||
alias="9m_gain_count",
|
||||
)
|
||||
loss_count_9m: Optional[int] = Field(
|
||||
default=None,
|
||||
description="The number of ratings that have lost value over the last 9 months",
|
||||
alias="9m_loss_count",
|
||||
)
|
||||
average_return_9m: Optional[float] = Field(
|
||||
default=None,
|
||||
description="The average percent (normalized) price difference per rating over"
|
||||
+ " the last 9 months",
|
||||
json_schema_extra={"unit_measurement": "percent", "frontend_multiply": 100},
|
||||
alias="9m_average_return",
|
||||
)
|
||||
std_dev_9m: Optional[float] = Field(
|
||||
default=None,
|
||||
description="The standard deviation in percent (normalized) price difference in the"
|
||||
+ " analyst's ratings over the last 9 months",
|
||||
json_schema_extra={"unit_measurement": "percent", "frontend_multiply": 100},
|
||||
alias="9m_stdev",
|
||||
)
|
||||
gain_count_1y: Optional[int] = Field(
|
||||
default=None,
|
||||
description="The number of ratings that have gained value over the last 1 year",
|
||||
alias="1y_gain_count",
|
||||
)
|
||||
loss_count_1y: Optional[int] = Field(
|
||||
default=None,
|
||||
description="The number of ratings that have lost value over the last 1 year",
|
||||
alias="1y_loss_count",
|
||||
)
|
||||
average_return_1y: Optional[float] = Field(
|
||||
default=None,
|
||||
description="The average percent (normalized) price difference per rating over"
|
||||
+ " the last 1 year",
|
||||
json_schema_extra={"unit_measurement": "percent", "frontend_multiply": 100},
|
||||
alias="1y_average_return",
|
||||
)
|
||||
std_dev_1y: Optional[float] = Field(
|
||||
default=None,
|
||||
description="The standard deviation in percent (normalized) price difference in the"
|
||||
+ " analyst's ratings over the last 1 year",
|
||||
json_schema_extra={"unit_measurement": "percent", "frontend_multiply": 100},
|
||||
alias="1y_stdev",
|
||||
)
|
||||
gain_count_2y: Optional[int] = Field(
|
||||
default=None,
|
||||
description="The number of ratings that have gained value over the last 2 years",
|
||||
alias="2y_gain_count",
|
||||
)
|
||||
loss_count_2y: Optional[int] = Field(
|
||||
default=None,
|
||||
description="The number of ratings that have lost value over the last 2 years",
|
||||
alias="2y_loss_count",
|
||||
)
|
||||
average_return_2y: Optional[float] = Field(
|
||||
default=None,
|
||||
description="The average percent (normalized) price difference per rating over"
|
||||
+ " the last 2 years",
|
||||
json_schema_extra={"unit_measurement": "percent", "frontend_multiply": 100},
|
||||
alias="2y_average_return",
|
||||
)
|
||||
std_dev_2y: Optional[float] = Field(
|
||||
default=None,
|
||||
description="The standard deviation in percent (normalized) price difference in the"
|
||||
+ " analyst's ratings over the last 2 years",
|
||||
json_schema_extra={"unit_measurement": "percent", "frontend_multiply": 100},
|
||||
alias="2y_stdev",
|
||||
)
|
||||
gain_count_3y: Optional[int] = Field(
|
||||
default=None,
|
||||
description="The number of ratings that have gained value over the last 3 years",
|
||||
alias="3y_gain_count",
|
||||
)
|
||||
loss_count_3y: Optional[int] = Field(
|
||||
default=None,
|
||||
description="The number of ratings that have lost value over the last 3 years",
|
||||
alias="3y_loss_count",
|
||||
)
|
||||
average_return_3y: Optional[float] = Field(
|
||||
default=None,
|
||||
description="The average percent (normalized) price difference per rating over"
|
||||
+ " the last 3 years",
|
||||
json_schema_extra={"unit_measurement": "percent", "frontend_multiply": 100},
|
||||
alias="3y_average_return",
|
||||
)
|
||||
std_dev_3y: Optional[float] = Field(
|
||||
default=None,
|
||||
description="The standard deviation in percent (normalized) price difference in the"
|
||||
+ " analyst's ratings over the last 3 years",
|
||||
json_schema_extra={"unit_measurement": "percent", "frontend_multiply": 100},
|
||||
alias="3y_stdev",
|
||||
)
|
||||
|
||||
@field_validator("last_updated", mode="before", check_fields=False)
|
||||
@classmethod
|
||||
def validate_date(cls, v):
|
||||
if v:
|
||||
dt = datetime.fromtimestamp(v, UTC)
|
||||
return dt.date() if dt.time() == dt.min.time() else dt
|
||||
return v
|
||||
|
||||
@model_validator(mode="before")
|
||||
@classmethod
|
||||
def replace_empty_strings(cls, values):
|
||||
"""Check for empty strings and replace with None."""
|
||||
return (
|
||||
{k: None if v == "" else v for k, v in values.items()}
|
||||
if isinstance(values, dict)
|
||||
else values
|
||||
)
|
||||
|
||||
@model_validator(mode="before")
|
||||
@classmethod
|
||||
def normalize_percent(cls, values):
|
||||
"""Normalize percent values."""
|
||||
contains = ["return", "percentile", "stdev", "rate"]
|
||||
for key in values:
|
||||
if any(x in key for x in contains):
|
||||
values[key] = (
|
||||
float(values[key]) / 100
|
||||
if values[key] != "" or values[key] is not None
|
||||
else None
|
||||
)
|
||||
return values
|
||||
|
||||
|
||||
class BenzingaAnalystSearchFetcher(
|
||||
Fetcher[BenzingaAnalystSearchQueryParams, List[BenzingaAnalystSearchData]]
|
||||
):
|
||||
"""Benzinga Analyst Search Fetcher."""
|
||||
|
||||
@staticmethod
|
||||
def transform_query(params: Dict[str, Any]) -> BenzingaAnalystSearchQueryParams:
|
||||
"""Transform query params."""
|
||||
return BenzingaAnalystSearchQueryParams(**params)
|
||||
|
||||
@staticmethod
|
||||
async def aextract_data(
|
||||
query: BenzingaAnalystSearchQueryParams,
|
||||
credentials: Optional[Dict[str, str]],
|
||||
**kwargs: Any,
|
||||
) -> List[Dict]:
|
||||
"""Extract the raw data."""
|
||||
|
||||
token = credentials.get("benzinga_api_key") if credentials else ""
|
||||
querystring = get_querystring(query.model_dump(), [])
|
||||
url = f"https://api.benzinga.com/api/v2.1/calendar/ratings/analysts?{querystring}&token={token}"
|
||||
response = await amake_request(url, **kwargs)
|
||||
|
||||
if not response:
|
||||
raise EmptyDataError()
|
||||
|
||||
return response.get("analyst_ratings_analyst") # type: ignore
|
||||
|
||||
@staticmethod
|
||||
def transform_data(
|
||||
query: BenzingaAnalystSearchQueryParams,
|
||||
data: List[Dict],
|
||||
**kwargs: Any,
|
||||
) -> List[BenzingaAnalystSearchData]:
|
||||
"""Transform the data."""
|
||||
results: List[BenzingaAnalystSearchData] = []
|
||||
for item in data:
|
||||
if item.get("firm_id"):
|
||||
result = {
|
||||
"updated": item.get("updated", None),
|
||||
"firm_id": item.get("firm_id", None),
|
||||
"firm_name": item.get("firm_name", None),
|
||||
"id": item.get("id", None),
|
||||
"name_first": item.get("name_first", None),
|
||||
"name_full": item.get("name_full", None),
|
||||
"name_last": item.get("name_last", None),
|
||||
**item["ratings_accuracy"],
|
||||
}
|
||||
results.append(BenzingaAnalystSearchData.model_validate(result))
|
||||
return results
|
||||
@@ -1,17 +1,39 @@
|
||||
"""Benzinga Price Target Model."""
|
||||
|
||||
import math
|
||||
from copy import deepcopy
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, List, Literal, Optional
|
||||
# pylint: disable=unused-argument
|
||||
|
||||
from datetime import (
|
||||
date as dateType,
|
||||
datetime,
|
||||
time,
|
||||
timezone,
|
||||
)
|
||||
from typing import Any, Dict, List, Literal, Optional, Union
|
||||
|
||||
from openbb_core.provider.abstract.fetcher import Fetcher
|
||||
from openbb_core.provider.standard_models.price_target import (
|
||||
PriceTargetData,
|
||||
PriceTargetQueryParams,
|
||||
)
|
||||
from openbb_core.provider.utils.descriptions import QUERY_DESCRIPTIONS
|
||||
from openbb_core.provider.utils.errors import EmptyDataError
|
||||
from openbb_core.provider.utils.helpers import amake_requests, get_querystring
|
||||
from pydantic import Field, PrivateAttr, field_validator, model_validator
|
||||
from pydantic import Field, field_validator, model_validator
|
||||
from pytz import UTC
|
||||
|
||||
COVERAGE_DICT = {
|
||||
"downgrades": "Downgrades",
|
||||
"maintains": "Maintains",
|
||||
"reinstates": "Reinstates",
|
||||
"reiterates": "Reiterates",
|
||||
"upgrades": "Upgrades",
|
||||
"assumes": "Assumes",
|
||||
"initiates": "Initiates Coverage On",
|
||||
"terminates": "Terminates Coverage On",
|
||||
"removes": "Removes",
|
||||
"suspends": "Suspends",
|
||||
"firm_dissolved": "Firm Dissolved",
|
||||
}
|
||||
|
||||
|
||||
class BenzingaPriceTargetQueryParams(PriceTargetQueryParams):
|
||||
@@ -21,38 +43,131 @@ class BenzingaPriceTargetQueryParams(PriceTargetQueryParams):
|
||||
"""
|
||||
|
||||
__alias_dict__ = {
|
||||
"limit": "pageSize",
|
||||
"limit": "pagesize",
|
||||
"symbol": "parameters[tickers]",
|
||||
}
|
||||
__json_schema_extra__ = {"symbol": ["multiple_items_allowed"]}
|
||||
|
||||
fields: Optional[str] = Field(
|
||||
page: Optional[int] = Field(
|
||||
default=0,
|
||||
description="Page offset. For optimization, performance and technical reasons,"
|
||||
+ " page offsets are limited from 0 - 100000. Limit the query results by other parameters such as date."
|
||||
+ " Used in conjunction with the limit and date parameters.",
|
||||
)
|
||||
date: Optional[dateType] = Field(
|
||||
default=None,
|
||||
description="Date for calendar data, shorthand for date_from and date_to.",
|
||||
alias="parameters[date]",
|
||||
)
|
||||
start_date: Optional[dateType] = Field(
|
||||
default=None,
|
||||
description=QUERY_DESCRIPTIONS.get("start_date", ""),
|
||||
alias="parameters[date_from]",
|
||||
)
|
||||
end_date: Optional[dateType] = Field(
|
||||
default=None,
|
||||
description=QUERY_DESCRIPTIONS.get("end_date", ""),
|
||||
alias="parameters[date_to]",
|
||||
)
|
||||
updated: Optional[Union[dateType, int]] = Field(
|
||||
default=None,
|
||||
description="Records last Updated Unix timestamp (UTC)."
|
||||
+ " This will force the sort order to be Greater Than or Equal to the timestamp indicated."
|
||||
+ " The date can be a date string or a Unix timestamp."
|
||||
+ " The date string must be in the format of YYYY-MM-DD.",
|
||||
alias="parameters[updated]",
|
||||
)
|
||||
importance: Optional[int] = Field(
|
||||
default=None,
|
||||
description="Importance level to filter by."
|
||||
+ " Uses Greater Than or Equal To the importance indicated",
|
||||
alias="parameters[importance]",
|
||||
)
|
||||
action: Union[
|
||||
None,
|
||||
Literal[
|
||||
"downgrades",
|
||||
"maintains",
|
||||
"reinstates",
|
||||
"reiterates",
|
||||
"upgrades",
|
||||
"assumes",
|
||||
"initiates",
|
||||
"terminates",
|
||||
"removes",
|
||||
"suspends",
|
||||
"firm_dissolved",
|
||||
],
|
||||
] = Field(
|
||||
default=None,
|
||||
description="Filter by a specific action_company.",
|
||||
alias="parameters[action]",
|
||||
)
|
||||
analyst_ids: Optional[Union[List[str], str]] = Field(
|
||||
default=None,
|
||||
description="Comma-separated list of analyst (person) IDs."
|
||||
+ " Omitting will bring back all available analysts.",
|
||||
alias="parameters[analyst_id]",
|
||||
)
|
||||
firm_ids: Optional[Union[List[str], str]] = Field(
|
||||
default=None,
|
||||
description="Comma-separated list of firm IDs.",
|
||||
alias="parameters[firm_id]",
|
||||
)
|
||||
fields: Optional[Union[List[str], str]] = Field(
|
||||
default=None,
|
||||
description="Comma-separated list of fields to include in the response."
|
||||
" See https://docs.benzinga.io/benzinga-apis/calendar/get-ratings to learn about the available fields.",
|
||||
)
|
||||
date: Optional[str] = Field(
|
||||
default=None,
|
||||
description="Date for calendar data, shorthand for date_from and date_to.",
|
||||
is_parameters=True,
|
||||
|
||||
@field_validator("action", mode="after", check_fields=False)
|
||||
@classmethod
|
||||
def convert_action(cls, v):
|
||||
"""Convert to the action string."""
|
||||
return COVERAGE_DICT[v] if v else None
|
||||
|
||||
@field_validator("updated", mode="after", check_fields=False)
|
||||
@classmethod
|
||||
def date_validate(cls, v):
|
||||
"""Convert the the dates to a standard format."""
|
||||
if isinstance(v, datetime):
|
||||
v = v.replace(tzinfo=timezone.utc)
|
||||
return int(v.timestamp())
|
||||
if isinstance(v, dateType):
|
||||
v = datetime.combine(v, time(), tzinfo=timezone.utc)
|
||||
return int(v.timestamp())
|
||||
return None
|
||||
|
||||
@field_validator(
|
||||
"fields", "firm_ids", "analyst_ids", mode="before", check_fields=False
|
||||
)
|
||||
date_from: Optional[str] = Field(
|
||||
default=None,
|
||||
description="Date to query from point in time.",
|
||||
is_parameters=True,
|
||||
)
|
||||
date_to: Optional[str] = Field(
|
||||
default=None, description="Date to query to point in time.", is_parameters=True
|
||||
)
|
||||
importance: Optional[int] = Field(
|
||||
default=None, description="Importance level to filter by.", is_parameters=True
|
||||
)
|
||||
updated: Optional[int] = Field(
|
||||
default=None,
|
||||
description="Records last updated Unix timestamp (UTC).",
|
||||
is_parameters=True,
|
||||
)
|
||||
action: Optional[
|
||||
@classmethod
|
||||
def convert_list(cls, v: Union[str, List[str]]):
|
||||
"""Convert a List[str] to a string list."""
|
||||
if isinstance(v, str):
|
||||
return v
|
||||
return ",".join(v) if v else None
|
||||
|
||||
|
||||
class BenzingaPriceTargetData(PriceTargetData):
|
||||
"""Benzinga Price Target Data."""
|
||||
|
||||
__alias_dict__ = {
|
||||
"symbol": "ticker",
|
||||
"published_date": "date",
|
||||
"adj_price_target": "adjusted_pt_current",
|
||||
"price_target": "pt_current",
|
||||
"price_target_previous": "pt_prior",
|
||||
"previous_adj_price_target": "adjusted_pt_prior",
|
||||
"published_time": "time",
|
||||
"analyst_firm": "analyst",
|
||||
"company_name": "name",
|
||||
"rating_previous": "rating_prior",
|
||||
"url_analyst": "url",
|
||||
}
|
||||
|
||||
action: Union[
|
||||
None,
|
||||
Literal[
|
||||
"Downgrades",
|
||||
"Maintains",
|
||||
@@ -65,147 +180,62 @@ class BenzingaPriceTargetQueryParams(PriceTargetQueryParams):
|
||||
"Removes",
|
||||
"Suspends",
|
||||
"Firm Dissolved",
|
||||
]
|
||||
],
|
||||
] = Field(
|
||||
default=None,
|
||||
description="Filter by a specific action_company.",
|
||||
is_parameters=True,
|
||||
)
|
||||
analyst: Optional[str] = Field(
|
||||
default=None, description="Comma-separated list of analyst (person) IDs."
|
||||
)
|
||||
firm: Optional[str] = Field(
|
||||
default=None, description="Comma-separated list of analyst firm IDs."
|
||||
)
|
||||
_parameters: Dict[str, Any] = PrivateAttr(default_factory=dict)
|
||||
|
||||
@model_validator(mode="after")
|
||||
@classmethod
|
||||
def assemble_parameters(
|
||||
cls, values: "BenzingaPriceTargetQueryParams"
|
||||
) -> "BenzingaPriceTargetQueryParams":
|
||||
"""Assemble the parameters private attribute."""
|
||||
model_fields = values.model_fields
|
||||
|
||||
for field in deepcopy(values):
|
||||
key, value = field
|
||||
field_info = model_fields[key]
|
||||
if field_info.json_schema_extra and field_info.json_schema_extra.get(
|
||||
"is_parameters", False
|
||||
):
|
||||
if value:
|
||||
# add to parameters
|
||||
# pylint: disable=protected-access
|
||||
values._parameters[f"parameters[{key}]"] = value
|
||||
# remove from values
|
||||
delattr(values, key)
|
||||
|
||||
return values
|
||||
|
||||
|
||||
class BenzingaPriceTargetData(PriceTargetData):
|
||||
"""Benzinga Price Target Data."""
|
||||
|
||||
__alias_dict__ = {
|
||||
"symbol": "ticker",
|
||||
"published_date": "date",
|
||||
"news_url": "url_news",
|
||||
"adj_price_target": "adjusted_pt_current",
|
||||
"price_target": "pt_current",
|
||||
}
|
||||
|
||||
action_company: Literal[
|
||||
"Downgrades",
|
||||
"Maintains",
|
||||
"Reinstates",
|
||||
"Reiterates",
|
||||
"Upgrades",
|
||||
"Assumes",
|
||||
"Initiates Coverage On",
|
||||
"Terminates Coverage On",
|
||||
"Removes",
|
||||
"Suspends",
|
||||
"Firm Dissolved",
|
||||
"",
|
||||
] = Field(
|
||||
default="",
|
||||
description="Description of the change in rating from firm's last rating."
|
||||
"Note that all of these terms are precisely defined.",
|
||||
alias="action_company",
|
||||
)
|
||||
action_pt: Literal[
|
||||
"Announces", "Maintains", "Lowers", "Raises", "Removes", "Adjusts", ""
|
||||
action_change: Union[
|
||||
None,
|
||||
Literal["Announces", "Maintains", "Lowers", "Raises", "Removes", "Adjusts"],
|
||||
] = Field(
|
||||
default="",
|
||||
description="Description of the change in price target from firm's last price target.",
|
||||
)
|
||||
adjusted_pt_prior: Optional[str] = Field(
|
||||
default=None,
|
||||
description="Analyst's prior price target, adjusted to account for stock splits and stock dividends."
|
||||
" If none are applicable, the pt_prior value is used.",
|
||||
description="Description of the change in price target from firm's last price target.",
|
||||
alias="action_pt",
|
||||
)
|
||||
analyst_id: Optional[str] = Field(default=None, description="Id of the analyst.")
|
||||
currency: Optional[str] = Field(
|
||||
default=None, description="Currency the data is denominated in."
|
||||
)
|
||||
exchange: Optional[str] = Field(
|
||||
default=None, description="Exchange of the price target."
|
||||
)
|
||||
id: Optional[str] = Field(default=None, description="Unique ID of this entry.")
|
||||
importance: Optional[Literal[0, 1, 2, 3, 4, 5]] = Field(
|
||||
importance: Union[None, Literal[0, 1, 2, 3, 4, 5]] = Field(
|
||||
default=None,
|
||||
description="Subjective Basis of How Important Event is to Market. 5 = High",
|
||||
)
|
||||
notes: Optional[str] = Field(default=None, description="Notes of the price target.")
|
||||
pt_prior: Optional[str] = Field(
|
||||
default=None, description="Analyst's prior price target."
|
||||
analyst_id: Optional[str] = Field(default=None, description="Id of the analyst.")
|
||||
url_news: Optional[str] = Field(
|
||||
default=None,
|
||||
description="URL for analyst ratings news articles for this ticker on Benzinga.com.",
|
||||
)
|
||||
rating_current: Optional[str] = Field(
|
||||
default=None, description="The analyst's rating for the company."
|
||||
)
|
||||
rating_prior: Optional[str] = Field(
|
||||
default=None, description="Prior analyst rating for the company."
|
||||
)
|
||||
ratings_accuracy: Optional[str] = Field(
|
||||
default=None, description="Ratings accuracy of the price target."
|
||||
)
|
||||
time: Optional[str] = Field(
|
||||
default=None, description="Last updated timestamp, UTC."
|
||||
)
|
||||
updated: Optional[int] = Field(
|
||||
default=None, description="Last updated timestamp, UTC."
|
||||
)
|
||||
url: str = Field(
|
||||
url_analyst: Optional[str] = Field(
|
||||
default=None,
|
||||
description="URL for analyst ratings page for this ticker on Benzinga.com.",
|
||||
)
|
||||
url_calendar: Optional[str] = Field(
|
||||
id: Optional[str] = Field(default=None, description="Unique ID of this entry.")
|
||||
last_updated: Optional[datetime] = Field(
|
||||
default=None,
|
||||
description="URL for analyst ratings page for this ticker on Benzinga.com.",
|
||||
)
|
||||
name: Optional[str] = Field(
|
||||
default=None, description="Name of company that is subject of rating."
|
||||
description="Last updated timestamp, UTC.",
|
||||
alias="updated",
|
||||
)
|
||||
|
||||
@field_validator("published_date", mode="before", check_fields=False)
|
||||
@classmethod
|
||||
def parse_date(cls, v: str) -> datetime:
|
||||
"""Parse the date field."""
|
||||
if v:
|
||||
v = datetime.strptime(v, "%Y-%m-%d")
|
||||
def parse_date(cls, v: str):
|
||||
"""Parse the publisihed_date."""
|
||||
return datetime.strptime(v, "%Y-%m-%d").date() if v else None
|
||||
|
||||
@field_validator("last_updated", mode="before", check_fields=False)
|
||||
@classmethod
|
||||
def validate_date(cls, v):
|
||||
"""Convert the Unix timestamp to a datetime object."""
|
||||
if v:
|
||||
dt = datetime.fromtimestamp(v, UTC)
|
||||
return dt.date() if dt.time() == dt.min.time() else dt
|
||||
return v
|
||||
|
||||
@field_validator("adj_price_target", mode="before", check_fields=False)
|
||||
@model_validator(mode="before")
|
||||
@classmethod
|
||||
def parse_adj_price_target(cls, v: str) -> float:
|
||||
"""Parse the adj_price_target field."""
|
||||
return float(v) if v else 0.0
|
||||
|
||||
@field_validator("price_target", mode="before", check_fields=False)
|
||||
@classmethod
|
||||
def parse_price_target(cls, v: str) -> float:
|
||||
"""Parse the price_target field."""
|
||||
return float(v) if v else 0.0
|
||||
def replace_empty_strings(cls, values):
|
||||
"""Check for empty strings and replace with None."""
|
||||
return {k: None if v == "" else v for k, v in values.items()}
|
||||
|
||||
|
||||
class BenzingaPriceTargetFetcher(
|
||||
@@ -226,34 +256,31 @@ class BenzingaPriceTargetFetcher(
|
||||
query: BenzingaPriceTargetQueryParams,
|
||||
credentials: Optional[Dict[str, str]],
|
||||
**kwargs: Any,
|
||||
) -> Dict:
|
||||
) -> List[Dict]:
|
||||
"""Return the raw data from the Benzinga endpoint."""
|
||||
token = credentials.get("benzinga_api_key") if credentials else ""
|
||||
|
||||
base_url = "https://api.benzinga.com/api/v2.1/calendar/ratings"
|
||||
full_query = {
|
||||
**query.model_dump(by_alias=True),
|
||||
**query._parameters, # pylint: disable=protected-access
|
||||
}
|
||||
querystring = get_querystring(full_query, exclude=[])
|
||||
querystring = get_querystring(query.model_dump(by_alias=True), [])
|
||||
|
||||
pages = math.ceil(query.limit / 100) if query.limit else 1
|
||||
url = f"{base_url}?{querystring}&token={token}"
|
||||
data = await amake_requests(url, **kwargs)
|
||||
|
||||
urls = [
|
||||
f"{base_url}?{querystring}&page={page}&token={token}"
|
||||
for page in range(pages)
|
||||
]
|
||||
if not data:
|
||||
raise EmptyDataError()
|
||||
|
||||
data = await amake_requests(urls, **kwargs)
|
||||
return data[0].get("ratings")
|
||||
|
||||
return data[: query.limit]
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
@staticmethod
|
||||
def transform_data(
|
||||
query: BenzingaPriceTargetQueryParams,
|
||||
data: Dict,
|
||||
data: List[Dict],
|
||||
**kwargs: Any,
|
||||
) -> List[BenzingaPriceTargetData]:
|
||||
"""Return the transformed data."""
|
||||
return [BenzingaPriceTargetData.model_validate(d) for d in data[0]["ratings"]]
|
||||
results: List[BenzingaPriceTargetData] = []
|
||||
# Remove duplicated field with a URL
|
||||
for item in data:
|
||||
item.pop("url_calendar", None)
|
||||
results.append(BenzingaPriceTargetData.model_validate(item))
|
||||
return results
|
||||
|
||||
@@ -0,0 +1,282 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- application/json
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Connection:
|
||||
- keep-alive
|
||||
method: GET
|
||||
uri: https://api.benzinga.com/api/v2.1/calendar/ratings/analysts?firm_name=Barclays&page=0&pageSize=100&token=MOCK_TOKEN
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
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
|
||||
headers:
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json; charset=utf-8
|
||||
Date:
|
||||
- Fri, 16 Feb 2024 20:32:34 GMT
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
Vary:
|
||||
- Accept-Encoding
|
||||
Via:
|
||||
- kong/2.4.1, 1.1 9adef5b1c5fc9ca80d6f4f8d19e103a2.cloudfront.net (CloudFront)
|
||||
X-Amz-Cf-Id:
|
||||
- wzPB7RswTYmBQtCmdpuOoCBrs9caz6DluhsLZXglRNPo13Tc9phzyA==
|
||||
X-Amz-Cf-Pop:
|
||||
- SEA19-C3
|
||||
X-Bz-Request-Id:
|
||||
- bBEB7mxrS7rediVwPHqUVe
|
||||
X-Cache:
|
||||
- Miss from cloudfront
|
||||
X-Kong-Proxy-Latency:
|
||||
- '0'
|
||||
X-Kong-Upstream-Latency:
|
||||
- '35'
|
||||
X-Powered-By:
|
||||
- Athlon 64 X2
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -9,108 +9,191 @@ interactions:
|
||||
Connection:
|
||||
- keep-alive
|
||||
method: GET
|
||||
uri: https://api.benzinga.com/api/v2.1/calendar/ratings?page=0&pageSize=100¶meters%5Btickers%5D=AAPL&token=MOCK_TOKEN
|
||||
uri: https://api.benzinga.com/api/v2.1/calendar/ratings?page=0&pagesize=200¶meters%5Btickers%5D=AAPL&token=MOCK_TOKEN
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
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
|
||||
AwAA//8WFqvx7vUBAA==
|
||||
headers:
|
||||
Connection:
|
||||
- keep-alive
|
||||
@@ -119,25 +202,25 @@ interactions:
|
||||
Content-Type:
|
||||
- application/json; charset=utf-8
|
||||
Date:
|
||||
- Fri, 12 Jan 2024 10:16:49 GMT
|
||||
- Fri, 16 Feb 2024 19:52:20 GMT
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
Vary:
|
||||
- Accept-Encoding
|
||||
Via:
|
||||
- kong/2.4.1, 1.1 56d84f665e9029878cb3adcd83a21026.cloudfront.net (CloudFront)
|
||||
- kong/2.4.1, 1.1 0906d4887f6625f4a4467d8d4fd268d2.cloudfront.net (CloudFront)
|
||||
X-Amz-Cf-Id:
|
||||
- u7IyZpkTSODX4-a_LDLxUQJI4E_R06BB8oFSA40IJHC7YxXml3QJuw==
|
||||
- FHckqBx4BKNJXwvRb3EbbAcqCMXmvOJY4btI-H_zsgzrYwfmLk2VEQ==
|
||||
X-Amz-Cf-Pop:
|
||||
- LIS50-P1
|
||||
- SEA19-C3
|
||||
X-Bz-Request-Id:
|
||||
- DSIshnOBTn5TzNsr70peza
|
||||
- w44XRYJcNVDLtWZCdKXWlD
|
||||
X-Cache:
|
||||
- Miss from cloudfront
|
||||
X-Kong-Proxy-Latency:
|
||||
- '0'
|
||||
X-Kong-Upstream-Latency:
|
||||
- '16'
|
||||
- '43'
|
||||
X-Powered-By:
|
||||
- Athlon 64 X2
|
||||
status:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import pytest
|
||||
from openbb_benzinga.models.analyst_search import BenzingaAnalystSearchFetcher
|
||||
from openbb_benzinga.models.company_news import BenzingaCompanyNewsFetcher
|
||||
from openbb_benzinga.models.price_target import BenzingaPriceTargetFetcher
|
||||
from openbb_benzinga.models.world_news import BenzingaWorldNewsFetcher
|
||||
@@ -44,3 +45,12 @@ def test_benzinga_price_target_fetcher(credentials=test_credentials):
|
||||
fetcher = BenzingaPriceTargetFetcher()
|
||||
result = fetcher.test(params, credentials)
|
||||
assert result is None
|
||||
|
||||
|
||||
@pytest.mark.record_http
|
||||
def test_benzinga_analyst_search_fetcher(credentials=test_credentials):
|
||||
params = {"firm_name": "Barclays"}
|
||||
|
||||
fetcher = BenzingaAnalystSearchFetcher()
|
||||
result = fetcher.test(params, credentials)
|
||||
assert result is None
|
||||
|
||||
@@ -23,6 +23,8 @@ class FMPEquityProfileQueryParams(EquityInfoQueryParams):
|
||||
Source: https://site.financialmodelingprep.com/developer/docs/companies-key-stats-free-api/
|
||||
"""
|
||||
|
||||
__json_schema_extra__ = {"symbol": ["multiple_items_allowed"]}
|
||||
|
||||
|
||||
class FMPEquityProfileData(EquityInfoData):
|
||||
"""FMP Equity Profile Data."""
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
"""FMP Equity Ownership Model."""
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
@@ -27,15 +29,31 @@ class FMPPriceTargetQueryParams(PriceTargetQueryParams):
|
||||
class FMPPriceTargetData(PriceTargetData):
|
||||
"""FMP Price Target Data."""
|
||||
|
||||
__alias_dict__ = {"news_url": "newsURL", "news_base_url": "newsBaseURL"}
|
||||
__alias_dict__ = {
|
||||
"analyst_firm": "gradingCompany",
|
||||
"rating_current": "newGrade",
|
||||
"rating_previous": "previousGrade",
|
||||
"news_title": "newsTitle",
|
||||
"url_news": "newsURL",
|
||||
"url_base": "newsBaseURL",
|
||||
}
|
||||
|
||||
new_grade: Optional[str] = Field(description="New grade", default=None)
|
||||
previous_grade: Optional[str] = Field(description="Previous grade", default=None)
|
||||
grading_company: Optional[str] = Field(description="Grading company", default=None)
|
||||
news_url: Optional[str] = Field(
|
||||
default=None, description="News URL of the price target."
|
||||
)
|
||||
news_title: Optional[str] = Field(
|
||||
default=None, description="News title of the price target."
|
||||
)
|
||||
news_publisher: Optional[str] = Field(
|
||||
default=None, description="News publisher of the price target."
|
||||
)
|
||||
news_base_url: Optional[str] = Field(
|
||||
default=None, description="News base URL of the price target."
|
||||
)
|
||||
|
||||
@field_validator("published_date", mode="before", check_fields=False)
|
||||
def fiscal_date_ending_validate(cls, v: str): # pylint: disable=E0213
|
||||
"""Return the fiscal date ending as a datetime object."""
|
||||
def validate_date(cls, v: str): # pylint: disable=E0213
|
||||
"""Validate the published date."""
|
||||
v = v.replace("\n", "")
|
||||
return datetime.strptime(v, "%Y-%m-%dT%H:%M:%S.%fZ") # type: ignore
|
||||
|
||||
@@ -53,7 +71,6 @@ class FMPPriceTargetFetcher(
|
||||
"""Transform the query params."""
|
||||
return FMPPriceTargetQueryParams(**params)
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
@staticmethod
|
||||
async def aextract_data(
|
||||
query: FMPPriceTargetQueryParams,
|
||||
@@ -71,11 +88,16 @@ class FMPPriceTargetFetcher(
|
||||
|
||||
return await get_data_urls(urls)
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
@staticmethod
|
||||
def transform_data(
|
||||
query: FMPPriceTargetQueryParams, data: List[Dict], **kwargs: Any
|
||||
) -> List[FMPPriceTargetData]:
|
||||
"""Return the transformed data."""
|
||||
data = data[: query.limit]
|
||||
return [FMPPriceTargetData.model_validate(d) for d in data]
|
||||
results: List[FMPPriceTargetData] = []
|
||||
for item in data:
|
||||
new_item = {
|
||||
k if k != "analystCompany" else "analyst_firm": v
|
||||
for k, v in item.items()
|
||||
}
|
||||
results.append(FMPPriceTargetData.model_validate(new_item))
|
||||
return results
|
||||
|
||||
Reference in New Issue
Block a user