diff options
28 files changed, 8942 insertions, 6187 deletions
diff --git a/openbb_platform/core/openbb_core/provider/standard_models/mortgage_indices.py b/openbb_platform/core/openbb_core/provider/standard_models/mortgage_indices.py new file mode 100644 index 00000000000..bfba892bb2d --- /dev/null +++ b/openbb_platform/core/openbb_core/provider/standard_models/mortgage_indices.py @@ -0,0 +1,46 @@ +"""Mortgage Indices Standard Model.""" + +from datetime import ( + date as dateType, +) +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 +from openbb_core.provider.utils.descriptions import ( + DATA_DESCRIPTIONS, + QUERY_DESCRIPTIONS, +) + + +class MortgageIndicesQueryParams(QueryParams): + """Mortgage Indices Query.""" + + start_date: Optional[dateType] = Field( + default=None, + description=QUERY_DESCRIPTIONS.get("start_date", ""), + ) + end_date: Optional[dateType] = Field( + default=None, + description=QUERY_DESCRIPTIONS.get("end_date", ""), + ) + + +class MortgageIndicesData(Data): + """Mortgage Indices Data.""" + + date: dateType = Field(description=DATA_DESCRIPTIONS.get("date", "")) + symbol: Optional[str] = Field( + default=None, + description=DATA_DESCRIPTIONS.get("symbol", ""), + ) + name: Optional[str] = Field( + default=None, + description="Name of the index.", + ) + rate: float = Field( + description="Mortgage rate.", + json_schema_extra={"x-unit_measurement": "percent", "x-frontend_multiply": 100}, + ) diff --git a/openbb_platform/core/openbb_core/provider/standard_models/options_chains.py b/openbb_platform/core/openbb_core/provider/standard_models/options_chains.py index 6a23f687f5d..38aca52b57d 100644 --- a/openbb_platform/core/openbb_core/provider/standard_models/options_chains.py +++ b/openbb_platform/core/openbb_core/provider/standard_models/options_chains.py @@ -31,23 +31,29 @@ class OptionsChainsQueryParams(QueryParams): class OptionsChainsData(Data): """Options Chains Data.""" - symbol: Optional[str] = Field( - description=DATA_DESCRIPTIONS.get("symbol", "") - + " Here, it is the underlying symbol for the option.", + underlying_symbol: Optional[str] = Field( default=None, + description="Underlying symbol for the option.", + ) + underlying_price: Optional[float] = Field( + default=None, + description="Price of the underlying stock.", ) contract_symbol: str = Field(description="Contract symbol for the option.") eod_date: Optional[dateType] = Field( default=None, description="Date for which the options chains are returned." ) expiration: dateType = Field(description="Expiration date of the contract.") + dte: Optional[int] = Field( + default=None, description="Days to expiration of the contract." + ) strike: float = Field(description="Strike price of the contract.") option_type: str = Field(description="Call or Put.") open_interest: Optional[int] = Field( - default=None, description="Open interest on the contract." + default=0, description="Open interest on the contract." ) volume: Optional[int] = Field( - default=None, description=DATA_DESCRIPTIONS.get("volume", "") + default=0, description=DATA_DESCRIPTIONS.get("volume", "") ) theoretical_price: Optional[float] = Field( default=None, description="Theoretical value of the option." @@ -55,6 +61,13 @@ class OptionsChainsData(Data): last_trade_price: Optional[float] = Field( default=None, description="Last trade price of the option." ) + last_trade_size: Optional[int] = Field( + default=None, description="Last trade size of the option." + ) + last_trade_time: Optional[datetime] = Field( + default=None, + description="The timestamp of the last trade.", + ) tick: Optional[str] = Field( default=None, description="Whether the last tick was up or down in price." ) @@ -64,12 +77,26 @@ class OptionsChainsData(Data): bid_size: Optional[int] = Field( default=None, description="Bid size for the option." ) + bid_time: Optional[datetime] = Field( + default=None, + description="The timestamp of the bid price.", + ) + bid_exchange: Optional[str] = Field( + default=None, description="The exchange of the bid price." + ) ask: Optional[float] = Field( default=None, description="Current ask price for the option." ) ask_size: Optional[int] = Field( default=None, description="Ask size for the option." ) + ask_time: Optional[datetime] = Field( + default=None, + description="The timestamp of the ask price.", + ) + ask_exchange: Optional[str] = Field( + default=None, description="The exchange of the ask price." + ) mark: Optional[float] = Field( default=None, description="The mid-price between the latest bid and ask." ) @@ -138,7 +165,8 @@ class OptionsChainsData(Data): ) change_percent: Optional[float] = Field( default=None, - description="Change, in normalizezd percentage points, of the option.", + description="Change, in normalized percentage points, of the option.", + json_schema_extra={"x-unit_measurement": "percent", "x-frontend_multiply": 100}, ) implied_volatility: Optional[float] = Field( default=None, description="Implied volatility of the option." @@ -151,7 +179,7 @@ class OptionsChainsData(Data): @field_validator("expiration", mode="before", check_fields=False) @classmethod - def date_validate(cls, v): # pylint: disable=E0213 + def date_validate(cls, v): """Return the datetime object from the date string.""" if isinstance(v, datetime): return datetime.strftime(v, "%Y-%m-%d") diff --git a/openbb_platform/core/openbb_core/provider/standard_models/options_snapshots.py b/openbb_platform/core/openbb_core/provider/standard_models/options_snapshots.py new file mode 100644 index 00000000000..8c14af09ffd --- /dev/null +++ b/openbb_platform/core/openbb_core/provider/standard_models/options_snapshots.py @@ -0,0 +1,75 @@ +"""Options Snapshots Standard Model.""" + +from datetime import ( + date as dateType, + 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 +from openbb_core.provider.utils.descriptions import DATA_DESCRIPTIONS + + +class OptionsSnapshotsQueryParams(QueryParams): + """Options Snapshots Query.""" + + +class OptionsSnapshotsData(Data): + """Options Snapshots Data.""" + + underlying_symbol: str = Field(description="Ticker symbol of the underlying asset.") + contract_symbol: str = Field(description="Symbol of the options contract.") + expiration: dateType = Field(description="Expiration date of the options contract.") + dte: Optional[int] = Field( + default=None, + description="Number of days to expiration of the options contract.", + ) + strike: float = Field( + description="Strike price of the options contract.", + json_schema_extra={"x-unit_measurement": "currency"}, + ) + option_type: str = Field(description="The type of option.") + volume: Optional[int] = Field( + default=None, + description=DATA_DESCRIPTIONS.get("volume", ""), + ) + open_interest: Optional[int] = Field( + default=None, + description="Open interest at the time.", + ) + last_price: Optional[float] = Field( + default=None, + description="Last trade price at the time.", + json_schema_extra={"x-unit_measurement": "currency"}, + ) + last_size: Optional[int] = Field( + default=None, + description="Lot size of the last trade.", + ) + last_timestamp: Optional[datetime] = Field( + default=None, + description="Timestamp of the last price.", + ) + open: Optional[float] = Field( + default=None, + description=DATA_DESCRIPTIONS.get("open", ""), + json_schema_extra={"x-unit_measurement": "currency"}, + ) + high: Optional[float] = Field( + default=None, + description=DATA_DESCRIPTIONS.get("high", ""), + json_schema_extra={"x-unit_measurement": "currency"}, + ) + low: Optional[float] = Field( + default=None, + description=DATA_DESCRIPTIONS.get("low", ""), + json_schema_extra={"x-unit_measurement": "currency"}, + ) + close: Optional[float] = Field( + default=None, + description=DATA_DESCRIPTIONS.get("close", ""), + json_schema_extra={"x-unit_measurement": "currency"}, + ) diff --git a/openbb_platform/extensions/derivatives/integration/test_derivatives_api.py b/openbb_platform/extensions/derivatives/integration/test_derivatives_api.py index 210ab79190c..97e9a3551eb 100644 --- a/openbb_platform/extensions/derivatives/integration/test_derivatives_api.py +++ b/openbb_platform/extensions/derivatives/integration/test_derivatives_api.py @@ -24,7 +24,24 @@ def headers(): @parametrize( "params", [ - ({"provider": "intrinio", "symbol": "AAPL", "date": "2023-01-25"}), + ( + { + "provider": "intrinio", + "symbol": "AAPL", + "date": "2023-01-25", + "option_type": None, + "moneyness": "all", + "strike_gt": None, + "strike_lt": None, + "volume_gt": None, + "volume_lt": None, + "oi_gt": None, + "oi_lt": None, + "model": "black_scholes", + "show_extended_price": False, + "include_related_symbols": False, + } + ), ({"provider": "cboe", "symbol": "AAPL", "use_cache": False}), ({"provider": "tradier", "symbol": "AAPL"}), ({"provider": "yfinance", "symbol": "AAPL"}), @@ -125,3 +142,21 @@ def test_derivatives_futures_curve(params, headers): result = requests.get(url, headers=headers, timeout=60) assert isinstance(result, requests.Response) assert result.status_code == 200 + + +@parametrize( + "params", + [ + ({"provider": "intrinio", "date": None, "only_traded": True}), + ], +) +@pytest.mark.integration +def test_derivatives_options_snapshots(params, headers): + """Test the options snapshots endpoint.""" + 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/derivatives/options/snapshots?{query_str}" + result = requests.get(url, headers=headers, timeout=60) + assert isinstance(result, requests.Response) + assert result.status_code == 200 diff --git a/openbb_platform/extensions/derivatives/integration/test_derivatives_python.py b/openbb_platform/extensions/derivatives/integration/test_derivatives_python.py index 1bc0597855f..4e04039bc7a 100644 --- a/openbb_platform/extensions/derivatives/integration/test_derivatives_python.py +++ b/openbb_platform/extensions/derivatives/integration/test_derivatives_python.py @@ -20,7 +20,24 @@ def obb(pytestconfig): @parametrize( "params", [ - ({"provider": "intrinio", "symbol": "AAPL", "date": "2023-01-25"}), + ( + { + "provider": "intrinio", + "symbol": "AAPL", + "date": "2023-01-25", + "option_type": None, + "moneyness": "all", + "strike_gt": None, + "strike_lt": None, + "volume_gt": None, + "volume_lt": None, + "oi_gt": None, + "oi_lt": None, + "model": "black_scholes", + "show_extended_price": False, + "include_related_symbols": False, + } + ), ({"provider": "cboe", "symbol": "AAPL", "use_cache": False}), ({"provider": "tradier", "symbol": "AAPL"}), ({"provider": "yfinance", "symbol": "AAPL"}), @@ -109,3 +126,18 @@ def test_derivatives_futures_curve(params, obb): assert result assert isinstance(result, OBBject) assert len(result.results) > 0 + + +@parametrize( + "params", + [ + ({"provider": "intrinio", "date": None, "only_traded": True}), + ], +) +@pytest.mark.integration +def test_derivatives_options_snapshots(params, obb): + """Test the options snapshots endpoint.""" + result = obb.derivatives.options.snapshots(**params) + assert result + assert isinstance(result, OBBject) + assert len(result.results) > 0 diff --git a/openbb_platform/extensions/derivatives/openbb_derivatives/options/options_router.py b/openbb_platform/extensions/derivatives/openbb_derivatives/options/options_router.py index dbed2aa674d..bcdb00be4b7 100644 --- a/openbb_platform/extensions/derivatives/openbb_derivatives/options/options_router.py +++ b/openbb_platform/extensions/derivatives/openbb_derivatives/options/options_router.py @@ -54,3 +54,21 @@ async def unusual( ) -> OBBject: """Get the complete options chain for a ticker.""" return await OBBject.from_query(Query(**locals())) + + +@router.command( + model="OptionsSnapshots", + examples=[ + APIEx( + parameters={"provider": "intrinio"}, + ), + ], +) +async def snapshots( + cc: CommandContext, + provider_choices: ProviderChoices, + standard_params: StandardParams, + extra_params: ExtraParams, +) -> OBBject: + """Get a snapshot of the options market universe.""" + return await OBBject.from_query(Query(**locals())) diff --git a/openbb_platform/extensions/fixedincome/integration/test_fixedincome_api.py b/openbb_platform/extensions/fixedincome/integration/test_fixedincome_api.py index 1e9844767f3..521040398c2 100644 --- a/openbb_platform/extensions/fixedincome/integration/test_fixedincome_api.py +++ b/openbb_platform/extensions/fixedincome/integration/test_fixedincome_api.py @@ -694,3 +694,29 @@ def test_fixedincome_bond_indices(params, headers): result = requests.get(url, headers=headers, timeout=10) assert isinstance(result, requests.Response) assert result.status_code == 200 + + +@parametrize( + "params", + [ + { + "provider": "fred", + "index": "usda_30y,fha_30y", + "start_date": "2023-05-31", + "end_date": "2024-06-01", + "transform": None, + "frequency": None, + "aggregation_method": "avg", + }, + ], +) +@pytest.mark.integration +def test_fixedincome_mortgage_indices(params, headers): + """Test the mortgage indices endpoint.""" + 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/fixedincome/mortgage_indices?{query_str}" + result = requests.get(url, headers=headers, timeout=10) + assert isinstance(result, requests.Response) + assert result.status_code == 200 diff --git a/openbb_platform/extensions/fixedincome/integration/test_fixedincome_python.py b/openbb_platform/extensions/fixedincome/integration/test_fixedincome_python.py index 433b96a3d8f..6058c18ecc9 100644 --- a/openbb_platform/extensions/fixedincome/integration/test_fixedincome_python.py +++ b/openbb_platform/extensions/fixedincome/integration/test_fixedincome_python.py @@ -647,3 +647,28 @@ def test_fixedincome_bond_indices(params, obb): assert result assert isinstance(result, OBBject) assert len(result.results) > 0 + + +@parametrize( + "params", + [ + { + "provider": "fred", + "index": "usda_30y,fha_30y", + "start_date": "2023-05-31", + "end_date": "2024-06-01", + "transform": None, + "frequency": None, + "aggregation_method": "avg", + }, + ], +) +@pytest.mark.integration +def test_fixedincome_mortgage_indices(params, obb): + """Test the mortgage indices endpoint.""" + params = {p: v for p, v in params.items() if v} + + result = obb.fixedincome.mortgage_indices(**params) + assert result + assert isinstance(result, OBBject) + assert len(result.results) > 0 diff --git a/openbb_platform/extensions/fixedincome/openbb_fixedincome/fixedincome_router.py b/openbb_platform/extensions/fixedincome/openbb_fixedincome/fixedincome_router.py index fb346dd3cc3..f7d62a1b16b 100644 --- a/openbb_platform/extensions/fixedincome/openbb_fixedincome/fixedincome_router.py +++ b/openbb_platform/extensions/fixedincome/openbb_fixedincome/fixedincome_router.py @@ -81,3 +81,29 @@ async def bond_indices( ) -> OBBject: # type: ignore """Bond Indices.""" return await OBBject.from_query(Query(**locals())) + + +@router.command( + model="MortgageIndices", + examples=[ + APIEx( + description="The default state for FRED are the primary mortgage indices from Optimal Blue.", + parameters={"provider": "fred"}, + ), + APIEx( + description="Multiple indices can be requested.", + parameters={ + "index": "jumbo_30y,conforming_30y,conforming_15y", + "provider": "fred", + }, + ), + ], +) +async def mortgage_indices( + cc: CommandContext, + provider_choices: ProviderChoices, + standard_params: StandardParams, + extra_params: ExtraParams, +) -> OBBject: # type: ignore + """Mortgage Indices.""" + return await OBBject.from_query(Query(**locals())) diff --git a/openbb_platform/openbb/assets/reference.json b/openbb_platform/openbb/assets/reference.json index dc6cbd1d46d..4ef413a7eed 100644 --- a/openbb_platform/openbb/assets/reference.json +++ b/openbb_platform/openbb/assets/reference.json @@ -1213,6 +1213,101 @@ "default": null, "optional": true, "choices": null + }, + { + "name": "option_type", + "type": "Literal[None, Union[ForwardRef('call'), ForwardRef('put')]]", + "description": "The option type, call or put, 'None' is both (default).", + "default": null, + "optional": true, + "choices": [ + "call", + "put" + ] + }, + { + "name": "moneyness", + "type": "Literal['otm', 'itm', 'all']", + "description": "Return only contracts that are in or out of the money, default is 'all'. Parameter is ignored when a date is supplied.", + "default": "all", + "optional": true, + "choices": [ + "otm", + "itm", + "all" + ] + }, + { + "name": "strike_gt", + "type": "int", + "description": "Return options with a strike price greater than the given value. Parameter is ignored when a date is supplied.", + "default": null, + "optional": true, + "choices": null + }, + { + "name": "strike_lt", + "type": "int", + "description": "Return options with a strike price less than the given value. Parameter is ignored when a date is supplied.", + "default": null, + "optional": true, + "choices": null + }, + { + "name": "volume_gt", + "type": "int", + "description": "Return options with a volume greater than the given value. Parameter is ignored when a date is supplied.", + "default": null, + "optional": true, + "choices": null + }, + { + "name": "volume_lt", + "type": "int", + "description": "Return options with a volume less than the given value. Parameter is ignored when a date is supplied.", |