summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanglewood <85772166+deeleeramone@users.noreply.github.com>2024-01-08 02:13:22 -0800
committerGitHub <noreply@github.com>2024-01-08 10:13:22 +0000
commit1d77e03177e01910354b31c54d2ae3c0574de6e6 (patch)
tree36077fea6b55f2041869eafb9095f9c7f205ae45
parenta7514bc588e70bd1fbcff95d7d43742c4168ebc3 (diff)
hotfix/yf-futures-historical: yfinance historical futures multi-ticker support and symbol parsing (#5923)
* multi-ticker support for yfinance futures historical * raise-missing-from * integration test params * equity_historical adjusted kwargs * pylint unused argument
-rw-r--r--openbb_platform/extensions/derivatives/integration/test_derivatives_api.py17
-rw-r--r--openbb_platform/extensions/derivatives/integration/test_derivatives_python.py18
-rw-r--r--openbb_platform/providers/yfinance/openbb_yfinance/models/equity_historical.py6
-rw-r--r--openbb_platform/providers/yfinance/openbb_yfinance/models/futures_historical.py130
-rw-r--r--openbb_platform/providers/yfinance/openbb_yfinance/utils/futures.csv1
-rw-r--r--openbb_platform/providers/yfinance/openbb_yfinance/utils/helpers.py9
6 files changed, 74 insertions, 107 deletions
diff --git a/openbb_platform/extensions/derivatives/integration/test_derivatives_api.py b/openbb_platform/extensions/derivatives/integration/test_derivatives_api.py
index 421cb41c312..9132ab86138 100644
--- a/openbb_platform/extensions/derivatives/integration/test_derivatives_api.py
+++ b/openbb_platform/extensions/derivatives/integration/test_derivatives_api.py
@@ -63,24 +63,11 @@ def test_derivatives_options_unusual(params, headers):
(
{
"provider": "yfinance",
- "symbol": "ES",
- "start_date": "2023-01-01",
- "end_date": "2023-06-06",
- "expiration": "2024-06",
- }
- ),
- (
- {
- "provider": "yfinance",
"interval": "1d",
- "period": "max",
- "prepost": True,
- "adjust": True,
- "back_adjust": True,
- "symbol": "ES",
+ "symbol": "CL,BZ",
"start_date": "2023-01-01",
"end_date": "2023-06-06",
- "expiration": "2024-06",
+ "expiration": "2025-12",
}
),
],
diff --git a/openbb_platform/extensions/derivatives/integration/test_derivatives_python.py b/openbb_platform/extensions/derivatives/integration/test_derivatives_python.py
index 02d0ee4bc78..ed967cbc5cc 100644
--- a/openbb_platform/extensions/derivatives/integration/test_derivatives_python.py
+++ b/openbb_platform/extensions/derivatives/integration/test_derivatives_python.py
@@ -54,24 +54,12 @@ def test_derivatives_options_unusual(params, obb):
[
(
{
- "symbol": "ES",
- "start_date": "2023-01-01",
- "end_date": "2023-06-06",
- "expiration": "2024-06",
- }
- ),
- (
- {
"provider": "yfinance",
"interval": "1d",
- "period": "max",
- "prepost": True,
- "adjust": True,
- "back_adjust": True,
- "symbol": "ES",
- "start_date": "2023-05-05",
+ "symbol": "CL,BZ",
+ "start_date": "2023-01-01",
"end_date": "2023-06-06",
- "expiration": "2024-06",
+ "expiration": "2025-12",
}
),
],
diff --git a/openbb_platform/providers/yfinance/openbb_yfinance/models/equity_historical.py b/openbb_platform/providers/yfinance/openbb_yfinance/models/equity_historical.py
index b56c0ffd60c..f42e043ec39 100644
--- a/openbb_platform/providers/yfinance/openbb_yfinance/models/equity_historical.py
+++ b/openbb_platform/providers/yfinance/openbb_yfinance/models/equity_historical.py
@@ -1,4 +1,5 @@
"""Yahoo Finance Equity Historical Price Model."""
+# pylint: disable=unused-argument
# ruff: noqa: SIM105
from datetime import datetime, timedelta
@@ -112,7 +113,9 @@ class YFinanceEquityHistoricalFetcher(
query.interval = "1mo"
elif query.interval == "3M":
query.interval = "3mo"
-
+ kwargs = (
+ {"auto_adjust": True, "back_adjust": True} if query.adjusted is True else {}
+ )
# pylint: disable=protected-access
data = yf_download(
symbol=query.symbol,
@@ -129,6 +132,7 @@ class YFinanceEquityHistoricalFetcher(
rounding=query._rounding,
group_by=query._group_by,
adjusted=query.adjusted,
+ **kwargs,
)
if data.empty:
diff --git a/openbb_platform/providers/yfinance/openbb_yfinance/models/futures_historical.py b/openbb_platform/providers/yfinance/openbb_yfinance/models/futures_historical.py
index 72213843e69..3a877ef992b 100644
--- a/openbb_platform/providers/yfinance/openbb_yfinance/models/futures_historical.py
+++ b/openbb_platform/providers/yfinance/openbb_yfinance/models/futures_historical.py
@@ -1,7 +1,7 @@
"""Yahoo Finance Futures Historical Price Model."""
+# pylint: disable=unused-argument
# ruff: noqa: SIM105
-
from datetime import datetime, timedelta
from typing import Any, Dict, List, Optional
@@ -13,11 +13,10 @@ from openbb_core.provider.standard_models.futures_historical import (
)
from openbb_core.provider.utils.descriptions import QUERY_DESCRIPTIONS
from openbb_core.provider.utils.errors import EmptyDataError
-from openbb_yfinance.utils.helpers import get_futures_data
+from openbb_yfinance.utils.helpers import get_futures_data, yf_download
from openbb_yfinance.utils.references import INTERVALS, MONTHS, PERIODS
from pandas import Timestamp, to_datetime
from pydantic import Field, field_validator
-from yfinance import Ticker
class YFinanceFuturesHistoricalQueryParams(FuturesHistoricalQueryParams):
@@ -30,13 +29,6 @@ class YFinanceFuturesHistoricalQueryParams(FuturesHistoricalQueryParams):
period: Optional[PERIODS] = Field(
default=None, description=QUERY_DESCRIPTIONS.get("period", "")
)
- prepost: bool = Field(
- default=False, description="Include Pre and Post market data."
- )
- adjust: bool = Field(default=True, description="Adjust all the data automatically.")
- back_adjust: bool = Field(
- default=False, description="Back-adjusted data to mimic true historical prices."
- )
class YFinanceFuturesHistoricalData(FuturesHistoricalData):
@@ -62,94 +54,88 @@ class YFinanceFuturesHistoricalFetcher(
@staticmethod
def transform_query(params: Dict[str, Any]) -> YFinanceFuturesHistoricalQueryParams:
"""Transform the query. Setting the start and end dates for a 1 year period."""
- if params.get("period") is None:
- transformed_params = params
-
- now = datetime.now().date()
- if params.get("start_date") is None:
- transformed_params["start_date"] = now - relativedelta(years=1)
-
- if params.get("end_date") is None:
- transformed_params["end_date"] = now
+ transformed_params = params.copy()
+
+ symbols = params["symbol"].split(",")
+ new_symbols = []
+ futures_data = get_futures_data()
+ for symbol in symbols:
+ if params.get("expiration"):
+ expiry_date = datetime.strptime(
+ transformed_params["expiration"], "%Y-%m"
+ )
+ if "." not in symbol:
+ exchange = futures_data[futures_data["Ticker"] == symbol][
+ "Exchange"
+ ].values[0]
+ new_symbol = (
+ f"{symbol}{MONTHS[expiry_date.month]}{str(expiry_date.year)[-2:]}.{exchange}"
+ if "." not in symbol
+ else symbol
+ )
+ new_symbols.append(new_symbol)
+ else:
+ new_symbols.append(symbol)
+ formatted_symbols = [
+ f"{s.upper()}=F" if "." not in s.upper() else s.upper() for s in new_symbols
+ ]
+ transformed_params["symbol"] = ",".join(formatted_symbols)
+
+ now = datetime.now()
+
+ if params.get("start_date") is None:
+ transformed_params["start_date"] = (now - relativedelta(years=1)).strftime(
+ "%Y-%m-%d"
+ )
- else:
- transformed_params = params
+ if params.get("end_date") is None:
+ transformed_params["end_date"] = now.strftime("%Y-%m-%d")
return YFinanceFuturesHistoricalQueryParams(**transformed_params)
@staticmethod
def extract_data(
- query: YFinanceFuturesHistoricalQueryParams, # pylint: disable=unused-argument
+ query: YFinanceFuturesHistoricalQueryParams,
credentials: Optional[Dict[str, str]],
**kwargs: Any,
- ) -> dict:
+ ) -> List[Dict]:
"""Return the raw data from the Yahoo Finance endpoint."""
- symbol = ""
-
- if query.expiration:
- expiry_date = datetime.strptime(query.expiration, "%Y-%m")
- futures_data = get_futures_data()
- exchange = futures_data[futures_data["Ticker"] == query.symbol][
- "Exchange"
- ].values[0]
- symbol = f"{query.symbol}{MONTHS[expiry_date.month]}{str(expiry_date.year)[-2:]}.{exchange}"
-
- query_symbol = symbol if symbol else f"{query.symbol}=F"
-
- if query.period:
- data = Ticker(query_symbol).history(
- interval=query.interval,
- period=query.period,
- prepost=query.prepost,
- auto_adjust=query.adjust,
- back_adjust=query.back_adjust,
- actions=False,
- raise_errors=True,
- )
- else:
- data = Ticker(query_symbol).history(
- interval=query.interval,
- start=query.start_date,
- end=query.end_date,
- prepost=query.prepost,
- auto_adjust=query.adjust,
- back_adjust=query.back_adjust,
- actions=False,
- raise_errors=True,
- )
+ data = yf_download(
+ query.symbol,
+ start=query.start_date,
+ end=query.end_date,
+ interval=query.interval, # type: ignore
+ prepost=True,
+ auto_adjust=False,
+ actions=False,
+ )
if data.empty:
raise EmptyDataError()
- query.end_date = (
- datetime.now().date() if query.end_date is None else query.end_date
- )
days = (
1
if query.interval in ["1m", "2m", "5m", "15m", "30m", "60m", "1h", "90m"]
else 0
)
+ if "date" in data.columns:
+ data.set_index("date", inplace=True)
+ data.index = to_datetime(data.index)
if query.start_date:
- data.index = to_datetime(data.index).tz_convert(None)
-
- start_date_dt = datetime.combine(query.start_date, datetime.min.time())
- end_date_dt = datetime.combine(query.end_date, datetime.min.time())
-
data = data[
- (data.index >= start_date_dt + timedelta(days=days))
- & (data.index <= end_date_dt)
+ (data.index >= to_datetime(query.start_date))
+ & (data.index <= to_datetime(query.end_date + timedelta(days=days)))
]
- data = data.reset_index().rename(
- columns={"index": "Date", "Datetime": "Date"}, errors="ignore"
- )
- data.columns = data.columns.str.lower()
+ data.reset_index(inplace=True)
+ data.rename(columns={"index": "date"}, inplace=True)
+
return data.to_dict("records")
@staticmethod
def transform_data(
- query: YFinanceFuturesHistoricalQueryParams, # pylint: disable=unused-argument
- data: dict,
+ query: YFinanceFuturesHistoricalQueryParams,
+ data: List[Dict],
**kwargs: Any,
) -> List[YFinanceFuturesHistoricalData]:
"""Transform the data to the standard format."""
diff --git a/openbb_platform/providers/yfinance/openbb_yfinance/utils/futures.csv b/openbb_platform/providers/yfinance/openbb_yfinance/utils/futures.csv
index 8dc4c5a86fd..91907e51153 100644
--- a/openbb_platform/providers/yfinance/openbb_yfinance/utils/futures.csv
+++ b/openbb_platform/providers/yfinance/openbb_yfinance/utils/futures.csv
@@ -183,6 +183,7 @@ SF,Sugar No. 16 Futures,NYB,agriculture
SB,Sugar No. 11 Futures,NYB,agriculture
OJ,Orange Juice Futures,NYB,agriculture
NG,Natural Gas Futures,NYM,hydrocarbon
+HO,Heating Oil Futures,NYM,hydrocarbon
RB,RBOB Gasoline Futures,NYM,hydrocarbon
CL,WTI Crude Oil Futures,NYM,hydrocarbon
TRM,ICE TRY/USD Futures,NYB,currency
diff --git a/openbb_platform/providers/yfinance/openbb_yfinance/utils/helpers.py b/openbb_platform/providers/yfinance/openbb_yfinance/utils/helpers.py
index d89c0847827..a46d6afb206 100644
--- a/openbb_platform/providers/yfinance/openbb_yfinance/utils/helpers.py
+++ b/openbb_platform/providers/yfinance/openbb_yfinance/utils/helpers.py
@@ -1,5 +1,5 @@
"""Yahoo Finance helpers module."""
-
+# pylint: disable=unused-argument
from datetime import (
date as dateType,
datetime,
@@ -134,8 +134,8 @@ def yf_download(
threads=False,
**kwargs,
)
- except ValueError:
- raise EmptyDataError()
+ except ValueError as exc:
+ raise EmptyDataError() from exc
tickers = symbol.split(",")
if len(tickers) > 1:
@@ -148,7 +148,8 @@ def yf_download(
columns={"Date": "date", "Datetime": "date"}
)
_data = pd.concat([_data, temp])
- _data = _data.set_index(["date", "symbol"]).sort_index()
+ index_keys = ["date", "symbol"] if "symbol" in _data.columns else ["date"]
+ _data = _data.set_index(index_keys).sort_index()
data = _data
if not data.empty:
data = data.reset_index()