From 1e617cff8c70096ff9a7d407dc8533068ed1b90b Mon Sep 17 00:00:00 2001 From: James Maslek Date: Thu, 16 Nov 2023 14:32:05 -0500 Subject: [PATCH 1/3] Rename the fmp search -> screener --- .../equity/openbb_equity/equity_router.py | 11 +++++ .../standard_models/equity_screener.py | 28 ++++++++++++ .../providers/fmp/openbb_fmp/__init__.py | 4 +- .../{equity_search.py => equity_screener.py} | 43 ++++++++----------- ... => test_fmp_equity_screener_fetcher.yaml} | 0 .../providers/fmp/tests/test_fmp_fetchers.py | 6 +-- 6 files changed, 61 insertions(+), 31 deletions(-) create mode 100644 openbb_platform/platform/provider/openbb_provider/standard_models/equity_screener.py rename openbb_platform/providers/fmp/openbb_fmp/models/{equity_search.py => equity_screener.py} (82%) rename openbb_platform/providers/fmp/tests/record/http/test_fmp_fetchers/{test_fmp_equity_search_fetcher.yaml => test_fmp_equity_screener_fetcher.yaml} (100%) diff --git a/openbb_platform/extensions/equity/openbb_equity/equity_router.py b/openbb_platform/extensions/equity/openbb_equity/equity_router.py index 289baef0011a..911efc2aa475 100644 --- a/openbb_platform/extensions/equity/openbb_equity/equity_router.py +++ b/openbb_platform/extensions/equity/openbb_equity/equity_router.py @@ -46,6 +46,17 @@ def search( return OBBject(results=Query(**locals()).execute()) +@router.command(model="EquityScreener") +def screener( + cc: CommandContext, + provider_choices: ProviderChoices, + standard_params: StandardParams, + extra_params: ExtraParams, +) -> OBBject[BaseModel]: + """Equity Screen. Screen for companies meeting various criteria.""" + return OBBject(results=Query(**locals()).execute()) + + @router.command(model="EquityInfo") def profile( cc: CommandContext, diff --git a/openbb_platform/platform/provider/openbb_provider/standard_models/equity_screener.py b/openbb_platform/platform/provider/openbb_provider/standard_models/equity_screener.py new file mode 100644 index 000000000000..b2f28abb60e8 --- /dev/null +++ b/openbb_platform/platform/provider/openbb_provider/standard_models/equity_screener.py @@ -0,0 +1,28 @@ +"""Equity Screener data model.""" + +from typing import List, Set, Union + +from pydantic import Field, field_validator + +from openbb_provider.abstract.data import Data +from openbb_provider.abstract.query_params import QueryParams +from openbb_provider.utils.descriptions import DATA_DESCRIPTIONS + + +class EquityScreenerQueryParams(QueryParams): + """Company Screener Query Params.""" + + +class EquityScreenerData(Data): + """Company Screener Data.""" + + symbol: str = Field(description=DATA_DESCRIPTIONS.get("symbol", "")) + name: str = Field(description="Name of the company.") + + @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)]) diff --git a/openbb_platform/providers/fmp/openbb_fmp/__init__.py b/openbb_platform/providers/fmp/openbb_fmp/__init__.py index 7bd847530d75..402a8c25e1d1 100644 --- a/openbb_platform/providers/fmp/openbb_fmp/__init__.py +++ b/openbb_platform/providers/fmp/openbb_fmp/__init__.py @@ -22,7 +22,7 @@ from openbb_fmp.models.equity_ownership import FMPEquityOwnershipFetcher from openbb_fmp.models.equity_peers import FMPEquityPeersFetcher from openbb_fmp.models.equity_quote import FMPEquityQuoteFetcher -from openbb_fmp.models.equity_search import FMPEquitySearchFetcher +from openbb_fmp.models.equity_screener import FMPEquityScreenerFetcher from openbb_fmp.models.equity_valuation_multiples import ( FMPEquityValuationMultiplesFetcher, ) @@ -90,7 +90,7 @@ "EquityOwnership": FMPEquityOwnershipFetcher, "EquityPeers": FMPEquityPeersFetcher, "EquityQuote": FMPEquityQuoteFetcher, - "EquitySearch": FMPEquitySearchFetcher, + "EquityScreener": FMPEquityScreenerFetcher, "EquityValuationMultiples": FMPEquityValuationMultiplesFetcher, "EtfCountries": FMPEtfCountriesFetcher, "EtfHoldings": FMPEtfHoldingsFetcher, diff --git a/openbb_platform/providers/fmp/openbb_fmp/models/equity_search.py b/openbb_platform/providers/fmp/openbb_fmp/models/equity_screener.py similarity index 82% rename from openbb_platform/providers/fmp/openbb_fmp/models/equity_search.py rename to openbb_platform/providers/fmp/openbb_fmp/models/equity_screener.py index 2e09bde15e5c..bd54e6499a4d 100644 --- a/openbb_platform/providers/fmp/openbb_fmp/models/equity_search.py +++ b/openbb_platform/providers/fmp/openbb_fmp/models/equity_screener.py @@ -1,4 +1,4 @@ -"""FMP Equity Search fetcher.""" +"""FMP Equity Screener fetcher.""" from typing import Any, Dict, List, Literal, Optional @@ -6,15 +6,15 @@ from openbb_fmp.utils.definitions import EXCHANGES, SECTORS from openbb_fmp.utils.helpers import create_url, get_data from openbb_provider.abstract.fetcher import Fetcher -from openbb_provider.standard_models.equity_search import ( - EquitySearchData, - EquitySearchQueryParams, +from openbb_provider.standard_models.equity_screener import ( + EquityScreenerData, + EquityScreenerQueryParams, ) from pydantic import Field -class FMPEquitySearchQueryParams(EquitySearchQueryParams): - """FMP Equity Search Query Params.""" +class FMPEquityScreenerQueryParams(EquityScreenerQueryParams): + """FMP Equity Screener Query Params.""" __alias_dict__ = { "mktcap_min": "marketCapMoreThan", @@ -91,8 +91,8 @@ class FMPEquitySearchQueryParams(EquitySearchQueryParams): ) -class FMPEquitySearchData(EquitySearchData): - """FMP Equity Search Data.""" +class FMPEquityScreenerData(EquityScreenerData): + """FMP Equity Screener Data.""" __alias_dict__ = { "name": "companyName", @@ -141,22 +141,22 @@ class FMPEquitySearchData(EquitySearchData): ) -class FMPEquitySearchFetcher( +class FMPEquityScreenerFetcher( Fetcher[ - FMPEquitySearchQueryParams, - List[FMPEquitySearchData], + FMPEquityScreenerQueryParams, + List[FMPEquityScreenerData], ] ): """Transform the query, extract and transform the data from the FMP endpoints.""" @staticmethod - def transform_query(params: Dict[str, Any]) -> FMPEquitySearchQueryParams: + def transform_query(params: Dict[str, Any]) -> FMPEquityScreenerQueryParams: """Transform the query.""" - return FMPEquitySearchQueryParams(**params) + return FMPEquityScreenerQueryParams(**params) @staticmethod def extract_data( - query: FMPEquitySearchQueryParams, + query: FMPEquityScreenerQueryParams, credentials: Optional[Dict[str, str]], **kwargs: Any, ) -> List[Dict]: @@ -173,8 +173,8 @@ def extract_data( @staticmethod def transform_data( - query: FMPEquitySearchQueryParams, data: List[Dict], **kwargs: Any - ) -> List[FMPEquitySearchData]: + query: FMPEquityScreenerQueryParams, data: List[Dict], **kwargs: Any + ) -> List[FMPEquityScreenerData]: """Return the transformed data.""" results = pd.DataFrame(data) if len(results) == 0: @@ -184,21 +184,12 @@ def transform_data( results["sector"].str.contains(query.industry, case=False) | results["industry"].str.contains(query.industry, case=False) ] - if query.query: - results = results[ - results["companyName"].str.contains(query.query, case=False) - | results["exchangeShortName"].str.contains(query.query, case=False) - | results["exchange"].str.contains(query.query, case=False) - | results["sector"].str.contains(query.query, case=False) - | results["industry"].str.contains(query.query, case=False) - | results["country"].str.contains(query.query, case=False) - ] results["companyName"] = results["companyName"].fillna("-").replace("-", "") for col in results: if results[col].dtype in ("int", "float"): results[col] = results[col].fillna(0).replace(0, None) return [ - FMPEquitySearchData.model_validate(d) + FMPEquityScreenerData.model_validate(d) for d in results.sort_values(by="marketCap", ascending=False).to_dict( "records" ) diff --git a/openbb_platform/providers/fmp/tests/record/http/test_fmp_fetchers/test_fmp_equity_search_fetcher.yaml b/openbb_platform/providers/fmp/tests/record/http/test_fmp_fetchers/test_fmp_equity_screener_fetcher.yaml similarity index 100% rename from openbb_platform/providers/fmp/tests/record/http/test_fmp_fetchers/test_fmp_equity_search_fetcher.yaml rename to openbb_platform/providers/fmp/tests/record/http/test_fmp_fetchers/test_fmp_equity_screener_fetcher.yaml diff --git a/openbb_platform/providers/fmp/tests/test_fmp_fetchers.py b/openbb_platform/providers/fmp/tests/test_fmp_fetchers.py index 74f5b7e9984f..bddbb964e063 100644 --- a/openbb_platform/providers/fmp/tests/test_fmp_fetchers.py +++ b/openbb_platform/providers/fmp/tests/test_fmp_fetchers.py @@ -25,7 +25,7 @@ from openbb_fmp.models.equity_ownership import FMPEquityOwnershipFetcher from openbb_fmp.models.equity_peers import FMPEquityPeersFetcher from openbb_fmp.models.equity_quote import FMPEquityQuoteFetcher -from openbb_fmp.models.equity_search import FMPEquitySearchFetcher +from openbb_fmp.models.equity_screener import FMPEquityScreenerFetcher from openbb_fmp.models.equity_valuation_multiples import ( FMPEquityValuationMultiplesFetcher, ) @@ -464,10 +464,10 @@ def test_fmp_equity_quote_fetcher(credentials=test_credentials): @pytest.mark.record_http -def test_fmp_equity_search_fetcher(credentials=test_credentials): +def test_fmp_equity_screener_fetcher(credentials=test_credentials): params = {"query": "midstream", "sector": "Energy", "beta_max": 0.5} - fetcher = FMPEquitySearchFetcher() + fetcher = FMPEquityScreenerFetcher() result = fetcher.test(params, credentials) assert result is None From 187b5bb3df56a4039d9d27ce0b01b5d96632f1ab Mon Sep 17 00:00:00 2001 From: James Maslek Date: Thu, 16 Nov 2023 14:42:59 -0500 Subject: [PATCH 2/3] misses some --- .../equity/integration/test_equity_api.py | 39 +++++++++++++++++++ .../equity/integration/test_equity_python.py | 36 +++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/openbb_platform/extensions/equity/integration/test_equity_api.py b/openbb_platform/extensions/equity/integration/test_equity_api.py index 0dd07d267c56..462c2ae5d7c6 100644 --- a/openbb_platform/extensions/equity/integration/test_equity_api.py +++ b/openbb_platform/extensions/equity/integration/test_equity_api.py @@ -969,6 +969,45 @@ def test_equity_search(params, headers): assert result.status_code == 200 +@pytest.mark.parametrize( + "params", + [ + ( + { + "query": "residential", + "industry": "REIT", + "sector": "Real Estate", + "mktcap_min": None, + "mktcap_max": None, + "price_min": None, + "price_max": None, + "volume_min": None, + "volume_max": None, + "dividend_min": None, + "dividend_max": None, + "is_active": True, + "is_etf": False, + "beta_min": None, + "beta_max": None, + "country": "US", + "exchange": "nyse", + "limit": None, + "provider": "fmp", + } + ), + ], +) +@pytest.mark.integration +def test_equity_screener(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/screener?{query_str}" + result = requests.get(url, headers=headers, timeout=10) + assert isinstance(result, requests.Response) + assert result.status_code == 200 + + @pytest.mark.parametrize( "params", [ diff --git a/openbb_platform/extensions/equity/integration/test_equity_python.py b/openbb_platform/extensions/equity/integration/test_equity_python.py index 9e87c93f8d52..8a08a81c1dae 100644 --- a/openbb_platform/extensions/equity/integration/test_equity_python.py +++ b/openbb_platform/extensions/equity/integration/test_equity_python.py @@ -897,6 +897,42 @@ def test_equity_search(params, obb): assert len(result.results) > 0 +@pytest.mark.parametrize( + "params", + [ + ( + { + "query": "residential", + "industry": "REIT", + "sector": "Real Estate", + "mktcap_min": None, + "mktcap_max": None, + "price_min": None, + "price_max": None, + "volume_min": None, + "volume_max": None, + "dividend_min": None, + "dividend_max": None, + "is_active": True, + "is_etf": False, + "beta_min": None, + "beta_max": None, + "country": "US", + "exchange": "nyse", + "limit": None, + "provider": "fmp", + } + ), + ], +) +@pytest.mark.integration +def test_equity_screener(params, obb): + result = obb.equity.screener(**params) + assert result + assert isinstance(result, OBBject) + assert len(result.results) > 0 + + @pytest.mark.parametrize( "params", [ From e0a4c24346802f02894b49fc38202c7d647fa658 Mon Sep 17 00:00:00 2001 From: James Maslek Date: Thu, 16 Nov 2023 14:48:39 -0500 Subject: [PATCH 3/3] i cant copy paste --- openbb_platform/extensions/equity/integration/test_equity_api.py | 1 - .../extensions/equity/integration/test_equity_python.py | 1 - 2 files changed, 2 deletions(-) diff --git a/openbb_platform/extensions/equity/integration/test_equity_api.py b/openbb_platform/extensions/equity/integration/test_equity_api.py index 462c2ae5d7c6..6c968e2d8ea5 100644 --- a/openbb_platform/extensions/equity/integration/test_equity_api.py +++ b/openbb_platform/extensions/equity/integration/test_equity_api.py @@ -974,7 +974,6 @@ def test_equity_search(params, headers): [ ( { - "query": "residential", "industry": "REIT", "sector": "Real Estate", "mktcap_min": None, diff --git a/openbb_platform/extensions/equity/integration/test_equity_python.py b/openbb_platform/extensions/equity/integration/test_equity_python.py index 8a08a81c1dae..f485fe1c193a 100644 --- a/openbb_platform/extensions/equity/integration/test_equity_python.py +++ b/openbb_platform/extensions/equity/integration/test_equity_python.py @@ -902,7 +902,6 @@ def test_equity_search(params, obb): [ ( { - "query": "residential", "industry": "REIT", "sector": "Real Estate", "mktcap_min": None,