mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-27 20:42:26 +00:00
Edit futures eod and add futures curve
This commit is contained in:
@@ -22,3 +22,14 @@ def load(
|
||||
) -> OBBject[BaseModel]:
|
||||
"""Futures EOD Price."""
|
||||
return OBBject(results=Query(**locals()).execute())
|
||||
|
||||
|
||||
@router.command(model="FuturesCurve")
|
||||
def curve(
|
||||
cc: CommandContext,
|
||||
provider_choices: ProviderChoices,
|
||||
standard_params: StandardParams,
|
||||
extra_params: ExtraParams,
|
||||
) -> OBBject[BaseModel]:
|
||||
"""Futures EOD Price."""
|
||||
return OBBject(results=Query(**locals()).execute())
|
||||
@@ -6,6 +6,7 @@ from openbb_yfinance.models.forex_eod import YFinanceForexEODFetcher
|
||||
from openbb_yfinance.models.major_indices_eod import YFinanceMajorIndicesEODFetcher
|
||||
from openbb_yfinance.models.stock_eod import YFinanceStockEODFetcher
|
||||
from openbb_yfinance.models.futures_eod import YFinanceFuturesEODFetcher
|
||||
from openbb_yfinance.models.futures_curve import YFinanceFuturesCurveFetcher
|
||||
|
||||
yfinance_provider = Provider(
|
||||
name="yfinance",
|
||||
@@ -19,6 +20,7 @@ yfinance_provider = Provider(
|
||||
"ForexEOD": YFinanceForexEODFetcher,
|
||||
"MajorIndicesEOD": YFinanceMajorIndicesEODFetcher,
|
||||
"StockEOD": YFinanceStockEODFetcher,
|
||||
"FuturesEOD": YFinanceFuturesEODFetcher
|
||||
"FuturesEOD": YFinanceFuturesEODFetcher,
|
||||
"FuturesCurve": YFinanceFuturesCurveFetcher
|
||||
},
|
||||
)
|
||||
|
||||
@@ -14,7 +14,7 @@ from pydantic import Field, validator
|
||||
from yfinance import Ticker
|
||||
|
||||
from openbb_yfinance.utils.types import INTERVALS, PERIODS
|
||||
|
||||
from openbb_yfinance.utils.futures_reference import futures_data, MONTHS
|
||||
|
||||
class YFinanceFuturesEODQueryParams(FuturesEODQueryParams):
|
||||
"""YFinance Futures end of day Query.
|
||||
@@ -28,6 +28,7 @@ class YFinanceFuturesEODQueryParams(FuturesEODQueryParams):
|
||||
)
|
||||
|
||||
|
||||
|
||||
class YFinanceFuturesEODData(FuturesEODData):
|
||||
"""YFinance Futures end of day Data."""
|
||||
|
||||
@@ -70,18 +71,27 @@ class YFinanceFuturesEODFetcher(
|
||||
**kwargs: Any,
|
||||
) -> List[YFinanceFuturesEODData]:
|
||||
now = datetime.now().date()
|
||||
query.start_date = query.start_date or (now - timedelta(days=8))
|
||||
query.start_date = query.start_date or (now - timedelta(days=365))
|
||||
query.end_date = query.end_date or (now - timedelta(days=1))
|
||||
symbol = ""
|
||||
if query.expiration:
|
||||
expiry_date = datetime.strptime(query.expiration, "%Y-%m")
|
||||
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 query.symbol+"=F"
|
||||
|
||||
if query.period:
|
||||
data = Ticker(query.symbol+"=F").history(
|
||||
data = Ticker(query_symbol).history(
|
||||
interval=query.interval,
|
||||
period=query.period,
|
||||
actions=False,
|
||||
raise_errors=True,
|
||||
)
|
||||
else:
|
||||
data = Ticker(query.symbol+"=F").history(
|
||||
data = Ticker(query_symbol).history(
|
||||
interval=query.interval,
|
||||
start=query.start_date,
|
||||
end=query.end_date,
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
import pandas as pd
|
||||
import yfinance as yf
|
||||
from typing import Optional
|
||||
from datetime import datetime
|
||||
from openbb_yfinance.utils.futures_reference import futures_data, MONTHS
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
|
||||
def get_futures_curve(symbol: str, date: Optional[str]) -> pd.DataFrame:
|
||||
"""Helper to get the futures curve
|
||||
|
||||
Parameters
|
||||
----------
|
||||
symbol: str
|
||||
Symbol to get futures for
|
||||
date: Optional[str]
|
||||
Optional historical date to get curve for
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
DataFrame with futures curve
|
||||
"""
|
||||
exchange = futures_data[futures_data["Ticker"] == symbol]["Exchange"].values[0]
|
||||
today = datetime.today()
|
||||
futures_index = list()
|
||||
futures_curve = list()
|
||||
historical_curve = list()
|
||||
i = 0
|
||||
empty_count = 0
|
||||
# Loop through until we find 12 consecutive empty months
|
||||
while empty_count < 12:
|
||||
future = today + relativedelta(months=i)
|
||||
future_symbol = (
|
||||
f"{symbol}{MONTHS[future.month]}{str(future.year)[-2:]}.{exchange}"
|
||||
)
|
||||
data = yf.download(future_symbol, progress=False, ignore_tz=True)
|
||||
|
||||
if data.empty:
|
||||
empty_count += 1
|
||||
|
||||
else:
|
||||
empty_count = 0
|
||||
futures_index.append(future.strftime("%b-%Y"))
|
||||
futures_curve.append(data["Adj Close"].values[-1])
|
||||
if date is not None:
|
||||
historical_curve.append(
|
||||
data["Adj Close"].get(date.strftime("%Y-%m-%d"), None)
|
||||
)
|
||||
|
||||
i += 1
|
||||
|
||||
if not futures_index:
|
||||
return pd.DataFrame({"date": [], "Last Price": []})
|
||||
|
||||
if historical_curve:
|
||||
print(historical_curve)
|
||||
return pd.DataFrame(
|
||||
{"Last Price": historical_curve, "expiration": futures_index}
|
||||
)
|
||||
return pd.DataFrame({"Last Price": futures_curve, "expiration": futures_index})
|
||||
@@ -36,6 +36,7 @@
|
||||
"news_sectornews": "/news/sectornews",
|
||||
"futures_load": "/futures/load",
|
||||
"futures": "/futures",
|
||||
"futures_curve": "/futures/curve",
|
||||
"stocks_fa_analysis": "/stocks/fa/analysis",
|
||||
"stocks": "/stocks",
|
||||
"stocks_fa": "/stocks/fa",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from datetime import date, datetime
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import Field, PositiveFloat
|
||||
from pydantic import Field
|
||||
|
||||
from openbb_provider.abstract.data import Data
|
||||
from openbb_provider.abstract.query_params import QueryParams
|
||||
@@ -23,14 +23,18 @@ class FuturesEODQueryParams(QueryParams, BaseSymbol):
|
||||
default=None,
|
||||
description=QUERY_DESCRIPTIONS.get("end_date", ""),
|
||||
)
|
||||
expiration: Optional[str] = Field(
|
||||
default=None,
|
||||
description="Future expiry date with format YYYY-MM",
|
||||
)
|
||||
|
||||
|
||||
class FuturesEODData(Data):
|
||||
"""Futures end of day price Data."""
|
||||
|
||||
date: datetime = Field(description=DATA_DESCRIPTIONS.get("date", ""))
|
||||
open: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("open", ""))
|
||||
high: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("high", ""))
|
||||
low: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("low", ""))
|
||||
close: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("close", ""))
|
||||
volume: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("volume", ""))
|
||||
open: float = Field(description=DATA_DESCRIPTIONS.get("open", ""))
|
||||
high: float = Field(description=DATA_DESCRIPTIONS.get("high", ""))
|
||||
low: float = Field(description=DATA_DESCRIPTIONS.get("low", ""))
|
||||
close: float = Field(description=DATA_DESCRIPTIONS.get("close", ""))
|
||||
volume: float = Field(description=DATA_DESCRIPTIONS.get("volume", ""))
|
||||
Reference in New Issue
Block a user