[BugFix] FMP - Fix missing exchange choices in equity.screener (#7008)

* add exchange choices to __json_schema_extra__

* unused-import

* unused-argument, not import

---------

Co-authored-by: James Maslek <jmaslek11@gmail.com>
This commit is contained in:
Danglewood
2025-01-27 09:16:35 -08:00
committed by GitHub
parent 163c8db273
commit c5e60a2a6e
8 changed files with 446 additions and 35 deletions

View File

@@ -1434,7 +1434,7 @@
},
{
"name": "counter_currencies",
"type": "Union[List[str], str]",
"type": "Union[str, List[str]]",
"description": "An optional list of counter currency symbols to filter for. None returns all.",
"default": null,
"optional": true,
@@ -2006,9 +2006,17 @@
"optional": false,
"choices": null
},
{
"name": "contract_size",
"type": "List[Union[int, float]]",
"description": "Number of underlying units per contract.",
"default": "",
"optional": true,
"choices": null
},
{
"name": "open_interest",
"type": "List[int]",
"type": "List[Union[int, float]]",
"description": "Open interest on the contract.",
"default": "",
"optional": true,
@@ -2016,7 +2024,7 @@
},
{
"name": "volume",
"type": "List[int]",
"type": "List[Union[int, float]]",
"description": "The trading volume.",
"default": "",
"optional": true,
@@ -2040,7 +2048,7 @@
},
{
"name": "last_trade_size",
"type": "List[int]",
"type": "List[Union[int, float]]",
"description": "Last trade size of the option.",
"default": "",
"optional": true,
@@ -2072,7 +2080,7 @@
},
{
"name": "bid_size",
"type": "List[int]",
"type": "List[Union[int, float]]",
"description": "Bid size for the option.",
"default": "",
"optional": true,
@@ -2104,7 +2112,7 @@
},
{
"name": "ask_size",
"type": "List[int]",
"type": "List[Union[int, float]]",
"description": "Ask size for the option.",
"default": "",
"optional": true,
@@ -2216,7 +2224,7 @@
},
{
"name": "close_size",
"type": "List[int]",
"type": "List[Union[int, float]]",
"description": "The closing trade size for the option that day.",
"default": "",
"optional": true,
@@ -2240,7 +2248,7 @@
},
{
"name": "close_bid_size",
"type": "List[int]",
"type": "List[Union[int, float]]",
"description": "The closing bid size for the option that day.",
"default": "",
"optional": true,
@@ -2264,7 +2272,7 @@
},
{
"name": "close_ask_size",
"type": "List[int]",
"type": "List[Union[int, float]]",
"description": "The closing ask size for the option that day.",
"default": "",
"optional": true,
@@ -12190,7 +12198,7 @@
},
{
"name": "analyst_ids",
"type": "Union[Union[List[str], str], List[Union[List[str], str]]]",
"type": "Union[Union[str, List[str]], List[Union[str, List[str]]]]",
"description": "Comma-separated list of analyst (person) IDs. Omitting will bring back all available analysts. Multiple items allowed for provider(s): benzinga.",
"default": null,
"optional": true,
@@ -12198,7 +12206,7 @@
},
{
"name": "firm_ids",
"type": "Union[Union[List[str], str], List[Union[List[str], str]]]",
"type": "Union[Union[str, List[str]], List[Union[str, List[str]]]]",
"description": "Comma-separated list of firm IDs. Multiple items allowed for provider(s): benzinga.",
"default": null,
"optional": true,
@@ -12206,7 +12214,7 @@
},
{
"name": "fields",
"type": "Union[Union[List[str], str], List[Union[List[str], str]]]",
"type": "Union[Union[str, List[str]], List[Union[str, List[str]]]]",
"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. Multiple items allowed for provider(s): benzinga.",
"default": null,
"optional": true,
@@ -30341,11 +30349,26 @@
},
{
"name": "sector",
"type": "Literal['consumer_cyclical', 'energy', 'technology', 'industrials', 'financial_services', 'basic_materials', 'communication_services', 'consumer_defensive', 'healthcare', 'real_estate', 'utilities', 'industrial_goods', 'financial', 'services', 'conglomerates']",
"type": "Literal['consumer_cyclical', 'energy', 'technology', 'industrials', 'financial_services', 'basic_materials', 'communication_services', 'consumer_defensive', 'healthcare', 'real_estate', 'utilities', 'industrial_goods', 'financial', 'services']",
"description": "Filter by sector.",
"default": null,
"optional": true,
"choices": null
"choices": [
"consumer_cyclical",
"energy",
"technology",
"industrials",
"financial_services",
"basic_materials",
"communication_services",
"consumer_defensive",
"healthcare",
"real_estate",
"utilities",
"industrial_goods",
"financial",
"services"
]
},
{
"name": "industry",
@@ -30369,7 +30392,64 @@
"description": "Filter by exchange.",
"default": null,
"optional": true,
"choices": null
"choices": [
"amex",
"ams",
"ase",
"asx",
"ath",
"bme",
"bru",
"bud",
"bue",
"cai",
"cnq",
"cph",
"dfm",
"doh",
"etf",
"euronext",
"hel",
"hkse",
"ice",
"iob",
"ist",
"jkt",
"jnb",
"jpx",
"kls",
"koe",
"ksc",
"kuw",
"lse",
"mex",
"mutual_fund",
"nasdaq",
"neo",
"nse",
"nyse",
"nze",
"osl",
"otc",
"pnk",
"pra",
"ris",
"sao",
"sau",
"set",
"sgo",
"shh",
"shz",
"six",
"sto",
"tai",
"tlv",
"tsx",
"two",
"vie",
"wse",
"xetra"
]
},
{
"name": "limit",
@@ -31673,7 +31753,64 @@
"description": "The market to fetch data for.",
"default": "nasdaq",
"optional": true,
"choices": null
"choices": [
"amex",
"ams",
"ase",
"asx",
"ath",
"bme",
"bru",
"bud",
"bue",
"cai",
"cnq",
"cph",
"dfm",
"doh",
"etf",
"euronext",
"hel",
"hkse",
"ice",
"iob",
"ist",
"jkt",
"jnb",
"jpx",
"kls",
"koe",
"ksc",
"kuw",
"lse",
"mex",
"mutual_fund",
"nasdaq",
"neo",
"nse",
"nyse",
"nze",
"osl",
"otc",
"pnk",
"pra",
"ris",
"sao",
"sau",
"set",
"sgo",
"shh",
"shz",
"six",
"sto",
"tai",
"tlv",
"tsx",
"two",
"vie",
"wse",
"xetra"
]
}
],
"intrinio": [
@@ -32267,7 +32404,14 @@
"description": "The exchange code the ETF trades on.",
"default": null,
"optional": true,
"choices": null
"choices": [
"AMEX",
"NYSE",
"NASDAQ",
"ETF",
"TSX",
"EURONEXT"
]
},
{
"name": "is_active",
@@ -41109,8 +41253,8 @@
"name": "source",
"type": "str",
"description": "Source of the news article",
"default": "",
"optional": false,
"default": null,
"optional": true,
"choices": null
}
]

View File

@@ -329,6 +329,71 @@ class ROUTER_equity(Container):
},
standard_params={},
extra_params=kwargs,
info={
"market": {
"fmp": {
"multiple_items_allowed": False,
"choices": [
"amex",
"ams",
"ase",
"asx",
"ath",
"bme",
"bru",
"bud",
"bue",
"cai",
"cnq",
"cph",
"dfm",
"doh",
"etf",
"euronext",
"hel",
"hkse",
"ice",
"iob",
"ist",
"jkt",
"jnb",
"jpx",
"kls",
"koe",
"ksc",
"kuw",
"lse",
"mex",
"mutual_fund",
"nasdaq",
"neo",
"nse",
"nyse",
"nze",
"osl",
"otc",
"pnk",
"pra",
"ris",
"sao",
"sau",
"set",
"sgo",
"shh",
"shz",
"six",
"sto",
"tai",
"tlv",
"tsx",
"two",
"vie",
"wse",
"xetra",
],
}
}
},
)
)
@@ -588,7 +653,7 @@ class ROUTER_equity(Container):
If true, returns only ETFs. (provider: fmp)
is_active : Optional[bool]
If false, returns only inactive tickers. (provider: fmp)
sector : Optional[Union[Literal['consumer_cyclical', 'energy', 'technology', 'industrials', 'financial_services', 'basic_materials', 'communication_services', 'consumer_defensive', 'healthcare', 'real_estate', 'utilities', 'industrial_goods', 'financial', 'services', 'conglomerates'], Literal['basic_materials', 'communication_services', 'consumer_cyclical', 'consumer_defensive', 'energy', 'financial_services', 'healthcare', 'industrials', 'real_estate', 'technology', 'utilities']]]
sector : Optional[Union[Literal['consumer_cyclical', 'energy', 'technology', 'industrials', 'financial_services', 'basic_materials', 'communication_services', 'consumer_defensive', 'healthcare', 'real_estate', 'utilities', 'industrial_goods', 'financial', 'services'], Literal['basic_materials', 'communication_services', 'consumer_cyclical', 'consumer_defensive', 'energy', 'financial_services', 'healthcare', 'industrials', 'real_estate', 'technology', 'utilities']]]
Filter by sector. (provider: fmp, yfinance)
industry : Optional[str]
Filter by industry. (provider: fmp, yfinance)
@@ -704,6 +769,25 @@ class ROUTER_equity(Container):
extra_params=kwargs,
info={
"sector": {
"fmp": {
"multiple_items_allowed": False,
"choices": [
"consumer_cyclical",
"energy",
"technology",
"industrials",
"financial_services",
"basic_materials",
"communication_services",
"consumer_defensive",
"healthcare",
"real_estate",
"utilities",
"industrial_goods",
"financial",
"services",
],
},
"yfinance": {
"multiple_items_allowed": False,
"choices": [
@@ -719,7 +803,7 @@ class ROUTER_equity(Container):
"technology",
"utilities",
],
}
},
},
"industry": {
"yfinance": {
@@ -937,6 +1021,67 @@ class ROUTER_equity(Container):
}
},
"exchange": {
"fmp": {
"multiple_items_allowed": False,
"choices": [
"amex",
"ams",
"ase",
"asx",
"ath",
"bme",
"bru",
"bud",
"bue",
"cai",
"cnq",
"cph",
"dfm",
"doh",
"etf",
"euronext",
"hel",
"hkse",
"ice",
"iob",
"ist",
"jkt",
"jnb",
"jpx",
"kls",
"koe",
"ksc",
"kuw",
"lse",
"mex",
"mutual_fund",
"nasdaq",
"neo",
"nse",
"nyse",
"nze",
"osl",
"otc",
"pnk",
"pra",
"ris",
"sao",
"sau",
"set",
"sgo",
"shh",
"shz",
"six",
"sto",
"tai",
"tlv",
"tsx",
"two",
"vie",
"wse",
"xetra",
],
},
"yfinance": {
"multiple_items_allowed": False,
"choices": [
@@ -1017,7 +1162,7 @@ class ROUTER_equity(Container):
"vse",
"wse",
],
}
},
},
},
)

View File

@@ -1371,6 +1371,21 @@ class ROUTER_etf(Container):
"query": query,
},
extra_params=kwargs,
info={
"exchange": {
"fmp": {
"multiple_items_allowed": False,
"choices": [
"AMEX",
"NYSE",
"NASDAQ",
"ETF",
"TSX",
"EURONEXT",
],
}
}
},
)
)

View File

@@ -10,7 +10,6 @@ from openbb_core.provider.standard_models.earnings_call_transcript import (
EarningsCallTranscriptData,
EarningsCallTranscriptQueryParams,
)
from openbb_core.provider.utils.helpers import amake_requests
from pydantic import field_validator
@@ -56,6 +55,9 @@ class FMPEarningsCallTranscriptFetcher(
**kwargs: Any,
) -> List[Dict]:
"""Return the raw data from the FMP endpoint."""
# pylint: disable=import-outside-toplevel
from openbb_fmp.utils.helpers import get_data
api_key = credentials.get("fmp_api_key") if credentials else ""
symbols = query.symbol.split(",")
years = query.year.split(",") if isinstance(query.year, str) else [query.year]
@@ -68,12 +70,14 @@ class FMPEarningsCallTranscriptFetcher(
)
return url
urls: List = []
results: list = []
for symbol in symbols:
for year in years:
urls.append(generate_url(symbol, year))
response = await get_data(generate_url(symbol, year), **kwargs)
if isinstance(response, list):
results.extend(response)
return await amake_requests(urls, **kwargs) # type: ignore
return results
@staticmethod
def transform_data(

View File

@@ -10,7 +10,7 @@ from openbb_core.provider.standard_models.equity_screener import (
EquityScreenerQueryParams,
)
from openbb_core.provider.utils.errors import EmptyDataError
from openbb_fmp.utils.definitions import EXCHANGES, SECTORS
from openbb_fmp.utils.definitions import EXCHANGES, SECTORS, Exchanges, Sectors
from pydantic import Field
@@ -32,6 +32,17 @@ class FMPEquityScreenerQueryParams(EquityScreenerQueryParams):
"is_etf": "isEtf",
}
__json_schema_extra__ = {
"exchange": {
"multiple_items_allowed": False,
"choices": EXCHANGES,
},
"sector": {
"multiple_items_allowed": False,
"choices": SECTORS,
},
}
mktcap_min: Optional[int] = Field(
default=None, description="Filter by market cap greater than this value."
)
@@ -79,12 +90,12 @@ class FMPEquityScreenerQueryParams(EquityScreenerQueryParams):
default=True,
description="If false, returns only inactive tickers.",
)
sector: Optional[SECTORS] = Field(default=None, description="Filter by sector.")
sector: Optional[Sectors] = Field(default=None, description="Filter by sector.")
industry: Optional[str] = Field(default=None, description="Filter by industry.")
country: Optional[str] = Field(
default=None, description="Filter by country, as a two-letter country code."
)
exchange: Optional[EXCHANGES] = Field(
exchange: Optional[Exchanges] = Field(
default=None, description="Filter by exchange."
)
limit: Optional[int] = Field(
@@ -179,6 +190,7 @@ class FMPEquityScreenerFetcher(
query=_query,
exclude=["query", "is_symbol", "industry"],
).replace(" ", "%20")
return await get_data(url, **kwargs) # type: ignore
@staticmethod

View File

@@ -1,5 +1,7 @@
"""FMP ETF Search Model."""
# pylint: disable=unused-argument
from typing import Any, Dict, List, Literal, Optional
from openbb_core.provider.abstract.fetcher import Fetcher
@@ -13,6 +15,13 @@ from pydantic import Field
class FMPEtfSearchQueryParams(EtfSearchQueryParams):
"""FMP ETF Search Query."""
__json_schema_extra__ = {
"exchange": {
"multiple_items_allowed": False,
"choices": ["AMEX", "NYSE", "NASDAQ", "ETF", "TSX", "EURONEXT"],
}
}
exchange: Optional[Literal["AMEX", "NYSE", "NASDAQ", "ETF", "TSX", "EURONEXT"]] = (
Field(
description="The exchange code the ETF trades on.",

View File

@@ -17,7 +17,7 @@ from openbb_core.provider.standard_models.market_snapshots import (
MarketSnapshotsQueryParams,
)
from openbb_core.provider.utils.helpers import safe_fromtimestamp
from openbb_fmp.utils.definitions import EXCHANGES
from openbb_fmp.utils.definitions import EXCHANGES, Exchanges
from openbb_fmp.utils.helpers import get_data
from pydantic import Field, field_validator
@@ -28,7 +28,14 @@ class FMPMarketSnapshotsQueryParams(MarketSnapshotsQueryParams):
Source: https://site.financialmodelingprep.com/developer/docs#exchange-prices-quote
"""
market: EXCHANGES = Field(
__json_schema_extra__ = {
"market": {
"multiple_items_allowed": False,
"choices": EXCHANGES,
}
}
market: Exchanges = Field(
description="The market to fetch data for.", default="nasdaq"
)
@@ -151,7 +158,7 @@ class FMPMarketSnapshotsData(MarketSnapshotsData):
@classmethod
def validate_empty_strings(cls, v):
"""Validate the name."""
return v if v and v != " " and v != "''" else None
return v if v and v not in (" ", "''") else None
class FMPMarketSnapshotsFetcher(

View File

@@ -2,7 +2,7 @@
from typing import Literal
SECTORS = Literal[
Sectors = Literal[
"consumer_cyclical",
"energy",
"technology",
@@ -17,10 +17,85 @@ SECTORS = Literal[
"industrial_goods",
"financial",
"services",
"conglomerates",
]
EXCHANGES = Literal[
SECTORS = [
"consumer_cyclical",
"energy",
"technology",
"industrials",
"financial_services",
"basic_materials",
"communication_services",
"consumer_defensive",
"healthcare",
"real_estate",
"utilities",
"industrial_goods",
"financial",
"services",
]
EXCHANGES = [
"amex",
"ams",
"ase",
"asx",
"ath",
"bme",
"bru",
"bud",
"bue",
"cai",
"cnq",
"cph",
"dfm",
"doh",
"etf",
"euronext",
"hel",
"hkse",
"ice",
"iob",
"ist",
"jkt",
"jnb",
"jpx",
"kls",
"koe",
"ksc",
"kuw",
"lse",
"mex",
"mutual_fund",
"nasdaq",
"neo",
"nse",
"nyse",
"nze",
"osl",
"otc",
"pnk",
"pra",
"ris",
"sao",
"sau",
"set",
"sgo",
"shh",
"shz",
"six",
"sto",
"tai",
"tlv",
"tsx",
"two",
"vie",
"wse",
"xetra",
]
Exchanges = Literal[
"amex",
"ams",
"ase",