Edit futures eod and add futures curve

This commit is contained in:
James Maslek
2023-08-14 16:13:18 -04:00
parent 45af506038
commit c1928f768f
6 changed files with 100 additions and 11 deletions

View File

@@ -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())

View File

@@ -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
},
)

View File

@@ -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,

View File

@@ -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})

View File

@@ -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",

View File

@@ -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", ""))