diff options
author | Danglewood <85772166+deeleeramone@users.noreply.github.com> | 2024-08-03 16:52:48 -0700 |
---|---|---|
committer | Danglewood <85772166+deeleeramone@users.noreply.github.com> | 2024-08-03 16:52:48 -0700 |
commit | 0e5b5079f82fa9317475048f89cdb61bd60849cf (patch) | |
tree | 4d4c72809efd2252171aaf2071918f212e341a14 | |
parent | 242e2e47129b7611d077e1b9a102fab28873296c (diff) | |
parent | 804a67f24fa890153f811130fb3549a0b1544486 (diff) |
Merge branch 'develop' of https://github.com/OpenBB-finance/OpenBB into feature/openbb-store
40 files changed, 55797 insertions, 21700 deletions
diff --git a/openbb_platform/core/openbb_core/app/model/obbject.py b/openbb_platform/core/openbb_core/app/model/obbject.py index 48dabce4f75..2b10fac38cb 100644 --- a/openbb_platform/core/openbb_core/app/model/obbject.py +++ b/openbb_platform/core/openbb_core/app/model/obbject.py @@ -84,17 +84,54 @@ class OBBject(Tagged, Generic[T]): return f"{self.__class__.__name__}\n\n" + "\n".join(items) def to_df( - self, index: Optional[Union[str, None]] = "date", sort_by: Optional[str] = None + self, + index: Optional[Union[str, None]] = "date", + sort_by: Optional[str] = None, + ascending: Optional[bool] = None, ) -> "DataFrame": - """Alias for `to_dataframe`.""" - return self.to_dataframe(index=index, sort_by=sort_by) + """Alias for `to_dataframe`. + + Supports converting creating Pandas DataFrames from the following + serializable data formats: + + - List[BaseModel] + - List[Dict] + - List[List] + - List[str] + - List[int] + - List[float] + - Dict[str, Dict] + - Dict[str, List] + - Dict[str, BaseModel] + + Other supported formats: + - str + + Parameters + ---------- + index : Optional[str] + Column name to use as index. + sort_by : Optional[str] + Column name to sort by. + ascending: Optional[bool] + Sort by ascending for each column specified in `sort_by`. + + Returns + ------- + DataFrame + Pandas DataFrame. + """ + return self.to_dataframe(index=index, sort_by=sort_by, ascending=ascending) def to_dataframe( - self, index: Optional[Union[str, None]] = "date", sort_by: Optional[str] = None + self, + index: Optional[Union[str, None]] = "date", + sort_by: Optional[str] = None, + ascending: Optional[bool] = None, ) -> "DataFrame": - """Convert results field to pandas dataframe. + """Convert results field to Pandas DataFrame. - Supports converting creating pandas DataFrames from the following + Supports converting creating Pandas DataFrames from the following serializable data formats: - List[BaseModel] @@ -116,11 +153,13 @@ class OBBject(Tagged, Generic[T]): Column name to use as index. sort_by : Optional[str] Column name to sort by. + ascending: Optional[bool] + Sort by ascending for each column specified in `sort_by`. Returns ------- DataFrame - Pandas dataframe. + Pandas DataFrame. """ # pylint: disable=import-outside-toplevel from pandas import DataFrame, concat # noqa @@ -142,8 +181,13 @@ class OBBject(Tagged, Generic[T]): df = None sort_columns = True + # BaseModel + if isinstance(res, BaseModel): + df = DataFrame(res.model_dump(exclude_unset=True, exclude_none=True)) + sort_columns = False + # List[Dict] - if isinstance(res, list) and len(res) == 1 and isinstance(res[0], dict): + elif isinstance(res, list) and len(res) == 1 and isinstance(res[0], dict): r = res[0] dict_of_df = {} @@ -178,10 +222,6 @@ class OBBject(Tagged, Generic[T]): else: try: df = DataFrame(res) # type: ignore[call-overload] - # Set index, if any - if df is not None and index is not None and index in df.columns: - df.set_index(index, inplace=True) - except ValueError: if isinstance(res, dict): df = DataFrame([res]) @@ -189,6 +229,10 @@ class OBBject(Tagged, Generic[T]): if df is None: raise OpenBBError("Unsupported data format.") + # Set index, if any + if index is not None and index in df.columns: + df.set_index(index, inplace=True) + # Drop columns that are all NaN, but don't rearrange columns if sort_columns: df.sort_index(axis=1, inplace=True) @@ -196,7 +240,11 @@ class OBBject(Tagged, Generic[T]): # Sort by specified column if sort_by: - df.sort_values(by=sort_by, inplace=True) + df.sort_values( + by=sort_by, + ascending=ascending if ascending is not None else True, + inplace=True, + ) except OpenBBError as e: raise e @@ -213,7 +261,7 @@ class OBBject(Tagged, Generic[T]): return df - def to_polars(self) -> "PolarsDataFrame": + def to_polars(self) -> "PolarsDataFrame": # type: ignore """Convert results field to polars dataframe.""" try: from polars import from_pandas # type: ignore # pylint: disable=import-outside-toplevel @@ -234,14 +282,13 @@ class OBBject(Tagged, Generic[T]): "dict", "list", "series", "split", "tight", "records", "index" ] = "list", ) -> Union[Dict[Hashable, Any], List[Dict[Hashable, Any]]]: - """Convert results field to a dictionary using any of pandas to_dict options. + """Convert results field to a dictionary using any of Pandas `to_dict` options. Parameters ---------- orient : Literal["dict", "list", "series", "split", "tight", "records", "index"] Value to pass to `.to_dict()` method - Returns ------- Union[Dict[Hashable, Any], List[Dict[Hashable, Any]]] @@ -278,7 +325,7 @@ class OBBject(Tagged, Generic[T]): date_unit="s", ) - return results + return results # type: ignore def show(self, **kwargs: Any) -> None: """Display chart.""" diff --git a/openbb_platform/core/openbb_core/provider/standard_models/country_interest_rates.py b/openbb_platform/core/openbb_core/provider/standard_models/country_interest_rates.py new file mode 100644 index 00000000000..bea3d0b361f --- /dev/null +++ b/openbb_platform/core/openbb_core/provider/standard_models/country_interest_rates.py @@ -0,0 +1,43 @@ +"""Country Interest Rates 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 CountryInterestRatesQueryParams(QueryParams): + """Country Interest Rates Query.""" + + country: str = Field( + default="united_states", + description=QUERY_DESCRIPTIONS.get("country"), + ) + 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 CountryInterestRatesData(Data): + """Country Interest Rates Data.""" + + date: dateType = Field(default=None, description=DATA_DESCRIPTIONS.get("date")) + value: float = Field( + default=None, + description="The interest rate value.", + json_schema_extra={"x-unit_measurment": "percent", "x-frontend_multiply": 100}, + ) + country: Optional[str] = Field( + default=None, + description="Country for which the interest rate is given.", + ) 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 38aca52b57d..b09a900d4e5 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 @@ -4,16 +4,16 @@ from datetime import ( date as dateType, datetime, ) -from typing import Optional +from typing import List, Union from pydantic import Field, field_validator -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, ) +from openbb_core.provider.utils.options_chains_properties import OptionsChainsProperties class OptionsChainsQueryParams(QueryParams): @@ -28,161 +28,323 @@ class OptionsChainsQueryParams(QueryParams): return v.upper() -class OptionsChainsData(Data): - """Options Chains Data.""" +class OptionsChainsData(OptionsChainsProperties): + """Options Chains Data. - underlying_symbol: Optional[str] = Field( - default=None, + Note: The attached properties and methods are available only when working with an instance of this class, + initialized with validated provider data. The items below bind to the `results` object in the function's output. + + Properties + ---------- + dataframe: DataFrame + Return all data as a Pandas DataFrame, with additional computed columns (Breakeven, GEX, DEX) if available. + expirations: List[str] + Return a list of unique expiration dates, as strings. + strikes: List[float] + Return a list of unique strike prices. + has_iv: bool + Return True if the data contains implied volatility. + has_greeks: bool + Return True if the data contains greeks. + total_oi: Dict + Return open interest stats as a nested dictionary with keys: total, expiration, strike. + Both, "expiration" and "strike", contain a list of records with fields: Calls, Puts, Total, Net Percent, PCR. + total_volume: Dict + Return volume stats as a nested dictionary with keys: total, expiration, strike. + Both, "expiration" and "strike", contain a list of records with fields: Calls, Puts, Total, Net Percent, PCR. + total_dex: Dict + Return Delta Dollars (DEX), if available, as a nested dictionary with keys: total, expiration, strike. + Both, "expiration" and "strike", contain a list of records with fields: Calls, Puts, Total, Net Percent, PCR. + total_gex: Dict + Return Gamma Exposure (GEX), if available, as a nested dictionary with keys: total, expiration, strike. + Both, "expiration" and "strike", contain a list of records with fields: Calls, Puts, Total, Net Percent, PCR. + last_price: float + Manually set the underlying price by assigning a float value to this property. + Certain provider/symbol combinations may not return the underlying price, + and it may be necessary, or desirable, to set it post-initialization. + This property can be used to override the underlying price returned by the provider. + It is not set automatically, and this property will return None if it is not set. + + Methods + ------- + filter_data( + date: Optional[Union[str, int]] = None, column: Optional[str] = None, + option_type: Optional[Literal["call", "put"]] = None, + moneyness: Optional[Literal["otm", "itm"]] = None, + value_min: Optional[float] = None, + value_max: Optional[float] = None, + stat: Optional[Literal["open_interest", "volume", "dex", "gex"]] = None, + by: Literal["expiration", "strike"] = "expiration", + ) -> DataFrame: + Return statistics by strike or expiration; or, the filtered chains data. + skew( + days: Optional[int] = None, underlying_price: Optional[float] = None) + -> DataFrame: + Return skewness of the options, either vertical or horizontal, by nearest DTE. + straddle( + days: Optional[int] = None, strike: Optional[float] = None, underlying_price: Optional[float] = None + ) -> DataFrame: + Calculates the cost of a straddle, by nearest DTE. Use a negative strike price for short options. + strangle( + days: Optional[int] = None, moneyness: Optional[float] = None, underlying_price: Optional[float] = None + ) -> DataFrame: + Calculates the cost of a strangle, by nearest DTE and % moneyness. + Use a negative value for moneyness for short options. + synthetic_long( + days: Optional[int] = None, strike: Optional[float] = None, underlying_price: Optional[float] = None + ) -> DataFrame: + Calculates the cost of a synthetic long position, by nearest DTE and strike price. + synthetic_short( + days: Optional[int] = None, strike: Optional[float] = None, underlying_price: Optional[float] = None + ) -> DataFrame: + Calculates the cost of a synthetic short position, by nearest DTE and strike price. + vertical_call( + days: Optional[int] = None, sold: Optional[float] = None, bought: Optional[float] = None, + underlying_price: Optional[float] = None + ) -> DataFrame: + Calculates the cost of a vertical call spread, by nearest DTE and strike price to sold and bought levels. + vertical_put( + days: Optional[int] = None, sold: Optional[float] = None, bought: Optional[float] = None, + underlying_price: Optional[float] = None + ) -> DataFrame: + Calculates the cost of a vertical put spread, by nearest DTE and strike price to sold and bought levels. + strategies( + days: Optional[int] = None, + straddle_strike: Optional[float] = None, + strangle_moneyness: Optional[List[float]] = None, + synthetic_longs: Optional[List[float]] = None, + synthetic_shorts: Optional[List[float]] = None, + vertical_calls: Optional[List[tuple]] = None, + vertical_puts: Optional[List[tuple]] = None, + underlying_price: Optional[float] = None, + ) -> DataFrame: + Method for combining multiple strategies and parameters in a single DataFrame. + To get all expirations, set days to -1. + + Raises + ------ + OpenBBError + OpenBBError will raise when accessing properties and methods if required, specific, data was not found. + """ + + underlying_symbol: List[Union[str, None]] = Field( + default_factory=list, description="Underlying symbol for the option.", ) - underlying_price: Optional[float] = Field( - default=None, + underlying_price: List[Union[float, None]] = Field( + default_factory=list, description="Price of the underlying stock.", + json_schema_extra={"x-unit_measurement": "currency"}, + ) + contract_symbol: List[str] = Field(description="Contract symbol for the option.") + eod_date: List[Union[dateType, None]] = Field( + default_factory=list, + description="Date for which the options chains are returned.", ) - 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: List[dateType] = Field(description="Expiration date of the contract.") + dte: List[Union[int, None]] = Field( + default_factory=list, description="Days to expiration of the contract." ) - expiration: dateType = Field(description="Expiration date of the contract.") - dte: Optional[int] = Field( - default=None, description="Days to expiration of the contract." + strike: List[float] = Field( + description="Strike price of the contract.", + json_schema_extra={"x-unit_measurement": "curre |