Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BugFix] Chunk FMP Price Performance URL For Large Lists #6317

Merged
merged 6 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from typing import Optional

from pydantic import Field
from pydantic import Field, field_validator

from openbb_core.provider.abstract.data import Data
from openbb_core.provider.abstract.query_params import QueryParams
Expand All @@ -17,6 +17,12 @@ class EtfHoldingsQueryParams(QueryParams):

symbol: str = Field(description=QUERY_DESCRIPTIONS.get("symbol", "") + " (ETF)")

@field_validator("symbol")
@classmethod
def to_upper(cls, v: str) -> str:
"""Convert field to uppercase."""
return v.upper()


class EtfHoldingsData(Data):
"""ETF Holdings Data."""
Expand Down
8 changes: 8 additions & 0 deletions openbb_platform/extensions/etf/openbb_etf/etf_router.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""ETF Router."""

from openbb_core.app.deprecation import OpenBBDeprecationWarning
from openbb_core.app.model.command_context import CommandContext
from openbb_core.app.model.example import APIEx
from openbb_core.app.model.obbject import OBBject
Expand Down Expand Up @@ -172,6 +173,13 @@ async def holdings_date(

@router.command(
model="EtfHoldingsPerformance",
deprecated=True,
deprecation=OpenBBDeprecationWarning(
message="This endpoint is deprecated; pass a list of holdings symbols directly to"
+ " `/equity/price/performance` instead.",
since=(4, 1),
expected_removal=(4, 2),
),
examples=[APIEx(parameters={"symbol": "XLK", "provider": "fmp"})],
)
async def holdings_performance(
Expand Down
88 changes: 86 additions & 2 deletions openbb_platform/openbb/assets/reference.json
Original file line number Diff line number Diff line change
Expand Up @@ -5350,6 +5350,20 @@
"default": null,
"optional": true
},
{
"name": "smart_score_1m",
"type": "float",
"description": "A weighted average smart score over the last month.",
"default": null,
"optional": true
},
{
"name": "success_rate_1m",
"type": "float",
"description": "The percentage (normalized) of gain/loss ratings that resulted in a gain over the last month",
"default": null,
"optional": true
},
{
"name": "gain_count_3m",
"type": "int",
Expand Down Expand Up @@ -5378,6 +5392,20 @@
"default": null,
"optional": true
},
{
"name": "smart_score_3m",
"type": "float",
"description": "A weighted average smart score over the last 3 months.",
"default": null,
"optional": true
},
{
"name": "success_rate_3m",
"type": "float",
"description": "The percentage (normalized) of gain/loss ratings that resulted in a gain over the last 3 months",
"default": null,
"optional": true
},
{
"name": "gain_count_6m",
"type": "int",
Expand Down Expand Up @@ -5434,6 +5462,20 @@
"default": null,
"optional": true
},
{
"name": "smart_score_9m",
"type": "float",
"description": "A weighted average smart score over the last 9 months.",
"default": null,
"optional": true
},
{
"name": "success_rate_9m",
"type": "float",
"description": "The percentage (normalized) of gain/loss ratings that resulted in a gain over the last 9 months",
"default": null,
"optional": true
},
{
"name": "gain_count_1y",
"type": "int",
Expand Down Expand Up @@ -5462,6 +5504,20 @@
"default": null,
"optional": true
},
{
"name": "smart_score_1y",
"type": "float",
"description": "A weighted average smart score over the last 1 year.",
"default": null,
"optional": true
},
{
"name": "success_rate_1y",
"type": "float",
"description": "The percentage (normalized) of gain/loss ratings that resulted in a gain over the last 1 year",
"default": null,
"optional": true
},
{
"name": "gain_count_2y",
"type": "int",
Expand Down Expand Up @@ -5490,6 +5546,20 @@
"default": null,
"optional": true
},
{
"name": "smart_score_2y",
"type": "float",
"description": "A weighted average smart score over the last 3 years.",
"default": null,
"optional": true
},
{
"name": "success_rate_2y",
"type": "float",
"description": "The percentage (normalized) of gain/loss ratings that resulted in a gain over the last 2 years",
"default": null,
"optional": true
},
{
"name": "gain_count_3y",
"type": "int",
Expand Down Expand Up @@ -5517,6 +5587,20 @@
"description": "The standard deviation in percent (normalized) price difference in the analyst's ratings over the last 3 years",
"default": null,
"optional": true
},
{
"name": "smart_score_3y",
"type": "float",
"description": "A weighted average smart score over the last 3 years.",
"default": null,
"optional": true
},
{
"name": "success_rate_3y",
"type": "float",
"description": "The percentage (normalized) of gain/loss ratings that resulted in a gain over the last 3 years",
"default": null,
"optional": true
}
]
},
Expand Down Expand Up @@ -23216,8 +23300,8 @@
},
"/etf/holdings_performance": {
"deprecated": {
"flag": null,
"message": null
"flag": true,
"message": "This endpoint is deprecated; pass a list of holdings symbols directly to `/equity/price/performance` instead. Deprecated in OpenBB Platform V4.1 to be removed in V4.2."
},
"description": "Get the recent price performance of each ticker held in the ETF.",
"examples": "\nExamples\n--------\n\n```python\nfrom openbb import obb\nobb.etf.holdings_performance(symbol='XLK', provider='fmp')\n```\n\n",
Expand Down
24 changes: 24 additions & 0 deletions openbb_platform/openbb/package/equity_estimates.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ def analyst_search(
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)
smart_score_1m : Optional[float]
A weighted average smart score over the last month. (provider: benzinga)
success_rate_1m : Optional[float]
The percentage (normalized) of gain/loss ratings that resulted in a gain 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]
Expand All @@ -134,6 +138,10 @@ def analyst_search(
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)
smart_score_3m : Optional[float]
A weighted average smart score over the last 3 months. (provider: benzinga)
success_rate_3m : Optional[float]
The percentage (normalized) of gain/loss ratings that resulted in a gain 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]
Expand All @@ -150,6 +158,10 @@ def analyst_search(
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)
smart_score_9m : Optional[float]
A weighted average smart score over the last 9 months. (provider: benzinga)
success_rate_9m : Optional[float]
The percentage (normalized) of gain/loss ratings that resulted in a gain 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]
Expand All @@ -158,6 +170,10 @@ def analyst_search(
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)
smart_score_1y : Optional[float]
A weighted average smart score over the last 1 year. (provider: benzinga)
success_rate_1y : Optional[float]
The percentage (normalized) of gain/loss ratings that resulted in a gain 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]
Expand All @@ -166,6 +182,10 @@ def analyst_search(
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)
smart_score_2y : Optional[float]
A weighted average smart score over the last 3 years. (provider: benzinga)
success_rate_2y : Optional[float]
The percentage (normalized) of gain/loss ratings that resulted in a gain 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]
Expand All @@ -174,6 +194,10 @@ def analyst_search(
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)
smart_score_3y : Optional[float]
A weighted average smart score over the last 3 years. (provider: benzinga)
success_rate_3y : Optional[float]
The percentage (normalized) of gain/loss ratings that resulted in a gain over the last 3 years (provider: benzinga)

Examples
--------
Expand Down
15 changes: 14 additions & 1 deletion openbb_platform/openbb/package/etf.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

import datetime
from typing import List, Literal, Optional, Union
from warnings import simplefilter, warn

from openbb_core.app.deprecation import OpenBBDeprecationWarning
from openbb_core.app.model.custom_parameter import OpenBBCustomParameter
from openbb_core.app.model.obbject import OBBject
from openbb_core.app.static.container import Container
from openbb_core.app.static.utils.decorators import exception_handler, validate
from openbb_core.app.static.utils.filters import filter_inputs
from typing_extensions import Annotated
from typing_extensions import Annotated, deprecated


class ROUTER_etf(Container):
Expand Down Expand Up @@ -698,6 +700,10 @@ def holdings_date(

@exception_handler
@validate
@deprecated(
"This endpoint is deprecated; pass a list of holdings symbols directly to `/equity/price/performance` instead. Deprecated in OpenBB Platform V4.1 to be removed in V4.2.",
category=OpenBBDeprecationWarning,
)
def holdings_performance(
self,
symbol: Annotated[
Expand Down Expand Up @@ -782,6 +788,13 @@ def holdings_performance(
>>> obb.etf.holdings_performance(symbol='XLK', provider='fmp')
""" # noqa: E501

simplefilter("always", DeprecationWarning)
warn(
"This endpoint is deprecated; pass a list of holdings symbols directly to `/equity/price/performance` instead. Deprecated in OpenBB Platform V4.1 to be removed in V4.2.",
category=DeprecationWarning,
stacklevel=2,
)

return self._run(
"/etf/holdings_performance",
**filter_inputs(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ def normalize_percent(cls, v):
def replace_empty(cls, v):
"""Replace empty strings and 0s with None."""
if isinstance(v, str):
return v if v not in ("", "0") else None
return v if v not in ("", "0", "-") else None
if isinstance(v, (float, int)):
return v if v and v not in (0.0, 0) else None
return v if v else None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ async def aextract_data(
# Split into chunks of 500
chunks = [holdings_list[i : i + 500] for i in range(0, len(holdings_list), 500)]
# Get price performance for the holdings
holdings_performance: list = []
holdings_performance: List[Dict] = []
for holding_chunk in chunks:
holdings_str = (
",".join(holding_chunk) if len(holding_chunk) > 1 else holding_chunk[0]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
RecentPerformanceData,
RecentPerformanceQueryParams,
)
from openbb_fmp.utils.helpers import create_url, get_data_many
from openbb_fmp.utils.helpers import create_url, get_data_urls
from pydantic import Field, model_validator


Expand Down Expand Up @@ -71,14 +71,23 @@ async def aextract_data(
) -> List[Dict]:
"""Return the raw data from the FMP endpoint."""
api_key = credentials.get("fmp_api_key") if credentials else ""

url = create_url(
version=3,
endpoint=f"stock-price-change/{query.symbol}",
api_key=api_key,
exclude=["symbol"],
)
return await get_data_many(url, **kwargs)
symbols = query.symbol.upper().split(",")
symbols = list(dict.fromkeys(symbols))
chunk_size = 200
chunks = [
symbols[i : i + chunk_size] for i in range(0, len(symbols), chunk_size)
]
urls = [
create_url(
version=3,
endpoint=f"stock-price-change/{','.join(chunk)}",
api_key=api_key,
exclude=["symbol"],
)
for chunk in chunks
]
data = await get_data_urls(urls, **kwargs)
return data

@staticmethod
def transform_data(
Expand All @@ -88,7 +97,8 @@ def transform_data(
) -> List[FMPPricePerformanceData]:
"""Return the transformed data."""

symbols = query.symbol.split(",")
symbols = query.symbol.upper().split(",")
symbols = list(dict.fromkeys(symbols))
if len(data) != len(symbols):
data_symbols = [d["symbol"] for d in data]
missing_symbols = [
Expand Down
Loading
Loading