summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIgor Radovanovic <74266147+IgorWounds@users.noreply.github.com>2024-07-02 16:24:35 +0200
committerGitHub <noreply@github.com>2024-07-02 16:24:35 +0200
commit7b2e77a2b33e032dc239faef97de0fd0bff75184 (patch)
treeb7b0a0ab58dda07e31ad9f274031aeb99377b04e
parent93486b55ed1ed426d9fb5ef6f715e797a30c596b (diff)
parent5c1a1efa9ae64b88e6f25504e9e0b6ca3128b220 (diff)
Merge branch 'develop' into bugfix/uncover-cmd-len-warn
-rw-r--r--openbb_platform/core/openbb_core/app/utils.py10
-rw-r--r--openbb_platform/core/openbb_core/provider/standard_models/futures_curve.py15
-rw-r--r--openbb_platform/extensions/derivatives/integration/test_derivatives_api.py18
-rw-r--r--openbb_platform/extensions/derivatives/integration/test_derivatives_python.py4
-rw-r--r--openbb_platform/extensions/derivatives/openbb_derivatives/derivatives_views.py219
-rw-r--r--openbb_platform/obbject_extensions/charting/integration/test_charting_api.py36
-rw-r--r--openbb_platform/obbject_extensions/charting/integration/test_charting_python.py28
-rw-r--r--openbb_platform/obbject_extensions/charting/openbb_charting/charting.py12
-rw-r--r--openbb_platform/obbject_extensions/charting/openbb_charting/query_params.py2
-rw-r--r--openbb_platform/providers/cboe/openbb_cboe/models/futures_curve.py64
-rw-r--r--openbb_platform/providers/cboe/openbb_cboe/utils/vix.py326
-rw-r--r--openbb_platform/providers/cboe/tests/record/http/test_cboe_fetchers/test_cboe_futures_curve_fetcher_urllib3_v1.yaml7180
-rw-r--r--openbb_platform/providers/cboe/tests/record/http/test_cboe_fetchers/test_cboe_futures_curve_fetcher_urllib3_v2.yaml7261
-rw-r--r--openbb_platform/providers/cboe/tests/test_cboe_fetchers.py2
-rw-r--r--openbb_platform/providers/yfinance/openbb_yfinance/models/futures_curve.py49
-rw-r--r--openbb_platform/providers/yfinance/openbb_yfinance/utils/helpers.py343
16 files changed, 15341 insertions, 228 deletions
diff --git a/openbb_platform/core/openbb_core/app/utils.py b/openbb_platform/core/openbb_core/app/utils.py
index 452300c4334..366fcb6e447 100644
--- a/openbb_platform/core/openbb_core/app/utils.py
+++ b/openbb_platform/core/openbb_core/app/utils.py
@@ -21,12 +21,16 @@ def basemodel_to_df(
) -> pd.DataFrame:
"""Convert list of BaseModel to a Pandas DataFrame."""
if isinstance(data, list):
- df = pd.DataFrame([d.model_dump() for d in data])
+ df = pd.DataFrame(
+ [d.model_dump(exclude_none=True, exclude_unset=True) for d in data]
+ )
else:
try:
- df = pd.DataFrame(data.model_dump())
+ df = pd.DataFrame(data.model_dump(exclude_none=True, exclude_unset=True))
except ValueError:
- df = pd.DataFrame(data.model_dump(), index=["values"])
+ df = pd.DataFrame(
+ data.model_dump(exclude_none=True, exclude_unset=True), index=["values"]
+ )
if "is_multiindex" in df.columns:
col_names = ast.literal_eval(df.multiindex_names.unique()[0])
diff --git a/openbb_platform/core/openbb_core/provider/standard_models/futures_curve.py b/openbb_platform/core/openbb_core/provider/standard_models/futures_curve.py
index 266de2e79e2..2afd1cf8a60 100644
--- a/openbb_platform/core/openbb_core/provider/standard_models/futures_curve.py
+++ b/openbb_platform/core/openbb_core/provider/standard_models/futures_curve.py
@@ -1,7 +1,7 @@
"""Futures Curve Standard Model."""
from datetime import date as dateType
-from typing import Optional
+from typing import Optional, Union
from pydantic import Field, field_validator
@@ -17,14 +17,14 @@ class FuturesCurveQueryParams(QueryParams):
"""Futures Curve Query."""
symbol: str = Field(description=QUERY_DESCRIPTIONS.get("symbol", ""))
- date: Optional[dateType] = Field(
+ date: Optional[Union[dateType, str]] = Field(
default=None,
description=QUERY_DESCRIPTIONS.get("date", ""),
)
@field_validator("symbol", mode="before", check_fields=False)
@classmethod
- def to_upper(cls, v: str) -> str:
+ def to_upper(cls, v):
"""Convert field to uppercase."""
return v.upper()
@@ -32,7 +32,12 @@ class FuturesCurveQueryParams(QueryParams):
class FuturesCurveData(Data):
"""Futures Curve Data."""
+ date: Optional[dateType] = Field(
+ default=None, description=DATA_DESCRIPTIONS.get("date", "")
+ )
expiration: str = Field(description="Futures expiration month.")
- price: Optional[float] = Field(
- default=None, description=DATA_DESCRIPTIONS.get("close", "")
+ price: float = Field(
+ default=None,
+ description="The price of the futures contract.",
+ 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 97e9a3551eb..8e52112ead0 100644
--- a/openbb_platform/extensions/derivatives/integration/test_derivatives_api.py
+++ b/openbb_platform/extensions/derivatives/integration/test_derivatives_api.py
@@ -128,8 +128,20 @@ def test_derivatives_futures_historical(params, headers):
@parametrize(
"params",
[
- ({"provider": "cboe", "symbol": "VX", "date": None}),
- ({"provider": "yfinance", "symbol": "ES", "date": "2023-08-01"}),
+ (
+ {
+ "provider": "yfinance",
+ "symbol": "ES",
+ "date": None,
+ }
+ ),
+ (
+ {
+ "provider": "cboe",
+ "symbol": "VX_EOD",
+ "date": None,
+ }
+ ),
],
)
@pytest.mark.integration
@@ -139,7 +151,7 @@ def test_derivatives_futures_curve(params, headers):
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/derivatives/futures/curve?{query_str}"
- result = requests.get(url, headers=headers, timeout=60)
+ result = requests.get(url, headers=headers, timeout=10)
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 4e04039bc7a..0ba718e01fc 100644
--- a/openbb_platform/extensions/derivatives/integration/test_derivatives_python.py
+++ b/openbb_platform/extensions/derivatives/integration/test_derivatives_python.py
@@ -115,8 +115,8 @@ def test_derivatives_futures_historical(params, obb):
@parametrize(
"params",
[
- ({"symbol": "VX", "provider": "cboe", "date": None}),
- ({"provider": "yfinance", "symbol": "ES", "date": "2023-08-01"}),
+ ({"provider": "yfinance", "symbol": "ES", "date": None}),
+ ({"provider": "cboe", "symbol": "VX", "date": None}),
],
)
@pytest.mark.integration
diff --git a/openbb_platform/extensions/derivatives/openbb_derivatives/derivatives_views.py b/openbb_platform/extensions/derivatives/openbb_derivatives/derivatives_views.py
index c83b090e206..abe2fedba31 100644
--- a/openbb_platform/extensions/derivatives/openbb_derivatives/derivatives_views.py
+++ b/openbb_platform/extensions/derivatives/openbb_derivatives/derivatives_views.py
@@ -1,9 +1,9 @@
"""Views for the Derivatives Extension."""
-from typing import Any, Dict, Tuple
+from typing import TYPE_CHECKING, Any, Dict, Tuple
-from openbb_charting.charts.price_historical import price_historical
-from openbb_charting.core.openbb_figure import OpenBBFigure
+if TYPE_CHECKING:
+ from openbb_charting.core.openbb_figure import OpenBBFigure
class DerivativesViews:
@@ -12,6 +12,215 @@ class DerivativesViews:
@staticmethod
def derivatives_futures_historical( # noqa: PLR0912
**kwargs,
- ) -> Tuple[OpenBBFigure, Dict[str, Any]]:
- """Get Derivatives Price Historical Chart."""
+ ) -> Tuple["OpenBBFigure", Dict[str, Any]]:
+ """Get Derivatives Futures Historical Chart."""
+ # pylint: disable=import-outside-toplevel
+ from openbb_charting.charts.price_historical import price_historical
+
return price_historical(**kwargs)
+
+ @staticmethod
+ def derivatives_futures_curve( # noqa: PLR0912
+ **kwargs,
+ ) -> Tuple["OpenBBFigure", Dict[str, Any]]:
+ """Futures curve chart. All parameters are optional, and are kwargs.
+ Parameters can be directly accessed from the function end point by
+ entering as a nested dictionary to the 'chart_params' key.
+
+ From the API, `chart_params` must be passed as a JSON in the request body with `extra_params`.
+
+ If using the chart post-request, the parameters are passed directly
+ as `key=value` pairs in the `charting.to_chart` or `charting.show` methods.
+
+ Parameters
+ ----------
+ data : Optional[Union[List[Data], DataFrame]]
+ Data for the chart. Required fields are: 'expiration' and 'price'.
+ Multiple dates will be plotted on the same chart.
+ If not supplied, the original OBBject.results will be used.
+ If a DataFrame is supplied, flat data is expected, without a set index.
+ title: Optional[str]
+ Title for the chart. If not supplied, a default title will be used.
+ colors: Optional[List[str]]
+ List of colors to use for the chart. If not supplied, the default colorway will be used.
+ Colors should be in hex format, or named Plotly colors. Invalid colors will raise a Plotly error.
+ layout_kwargs: Optional[Dict[str, Any]]
+ Additional layout parameters for the chart, passed directly to `figure.update_layout` before output.
+ See Plotly documentation for available options.
+
+ Returns
+ -------
+ Tuple[OpenBBFigure, Dict[str, Any]]
+ Tuple with the OpenBBFigure object, and the JSON-serialized content.
+ If using the API, only the JSON content will be returned.
+
+ Examples
+ --------
+ ```python
+ from openbb import obb
+ data = obb.derivatives.futures.curve(symbol="vx", provider="cboe", date=["2020-03-31", "2024-06-28"], chart=True)
+ data.show()
+ ```
+
+ Redraw the chart, from the same data, with a custom colorway and title:
+
+ ```python
+ data.charting.to_chart(colors=["green", "red"], title="VIX Futures Curve - 2020 vs. 2024")
+ ```
+ """
+ # pylint: disable=import-outside-toplevel
+ from openbb_charting.core.chart_style import ChartStyle
+ from openbb_charting.core.openbb_figure import OpenBBFigure
+ from openbb_charting.styles.colors import LARGE_CYCLER
+ from openbb_core.app.model.abstract.error import OpenBBError
+ from openbb_core.provider.abstract.data import Data
+ from pandas import DataFrame, to_datetime
+
+ data = kwargs.get("data", None)
+ symbol = kwargs.get("standard_params", {}).get("symbol", "")
+ df: DataFrame = DataFrame()
+ if data:
+ if isinstance(data, DataFrame) and not data.empty: # noqa: SIM108
+ df = data
+ elif isinstance(data, (list, Data)):
+ df = DataFrame([d.model_dump(exclude_none=True, exclude_unset=True) for d in data]) # type: ignore
+ else:
+ pass
+ else:
+ df = DataFrame(
+ [
+ d.model_dump(exclude_none=True, exclude_unset=True) # type: ignore
+ for d in kwargs["obbject_item"]
+ ]
+ if isinstance(kwargs.get("obbject_item"), list)
+ else kwargs["obbject_item"].model_dump(exclude_none=True, exclude_unset=True) # type: ignore
+ )
+
+ if df.empty:
+ raise OpenBBError("Error: No data to plot.")
+
+ if "expiration" not in df.columns:
+ raise OpenBBError("Expiration field not found in the data.")
+
+ if "price" not in df.columns:
+ raise ValueError("Price field not found in the data.")
+
+ provider = kwargs.get("provider", "")
+
+ df["expiration"] = to_datetime(df["expiration"], errors="ignore").dt.strftime(
+ "%b-%Y"
+ )
+
+ if (
+ provider == "cboe"
+ and "date" in df.columns
+ and len(df["date"].unique()) > 1
+ and "symbol" in df.columns
+ ):
+ df["expiration"] = df.symbol
+
+ # Use a complete list of expirations to categorize the x-axis across all dates.
+ expirations = df["expiration"].unique().tolist()
+
+ # Use the supplied colors, if any.
+ colors = kwargs.get("colors", [])
+ if not colors:
+ colors = LARGE_CYCLER
+ color_count = 0
+
+ figure = OpenBBFigure().create_subplots(shared_xaxes=True)
+ figure.update_layout(ChartStyle().plotly_template.get("layout", {}))
+
+ def create_fig(figure, df, dates, color_count):
+ """Create a scatter for each date in the data."""
+ for date in dates:
+ color = colors[color_count % len(colors)]
+ plot_df = (
+ df[df["date"].astype(str) == date].copy()
+ if "date" in df.columns
+ else df.copy()
+ )
+ plot_df = plot_df.drop(
+ columns=["date"] if "date" in plot_df.columns else []
+ ).rename(columns={"expiration": "Expiration", "price": "Price"})
+ figure.add_scatter(
+ x=plot_df["Expiration"],
+ y=plot_df["Price"],
+ mode="lines+markers",
+ name=date,
+ line=dict(width=3, color=color),
+ marker=dict(size=10, color=color),
+ hovertemplate=(
+ "Expiration: %{x}<br>Price: $%{y}<extra></extra>"
+ if len(dates) == 1
+ else "%{fullData.name}<br>Expiration: %{x}<br>Price: $%{y}<extra></extra>"
+ ),
+ )
+ color_count += 1
+ return figure, color_count
+
+ dates = (
+ df.date.astype(str).unique().tolist()
+ if "date" in df.columns
+ else ["Current"]
+ )
+ figure, color_count = create_fig(figure, df, dates, color_count)
+
+ # Set the title for the chart
+ title: str = ""
+ if provider == "cboe":
+ vx_eod_symbols = ["vx", "vix", "vx_eod", "^vix"]
+ title = (
+ "VIX EOD Futures Curve"
+ if symbol.lower() in vx_eod_symbols
+ else "VIX Mid-Morning TWAP Futures Curve"
+ )
+ if len(dates) == 1 and dates[0] != "Current":
+ title = f"{title} for {dates[0]}"
+ elif provider == "yfinance":
+ title = f"{symbol.upper()} Futures Curve"
+
+ # Use the supplied title, if any.
+ title = kwargs.get("title", title)
+
+ # Update the layout of the figure.
+ figure.update_layout(
+ title=dict(text=title, x=0.5, font=dict(size=20)),
+ plot_bgcolor="rgba(255,255,255,0)",
+ xaxis=dict(
+ title="",
+ ticklen=0,
+ showgrid=False,
+ type="category",
+ categoryorder="array",
+ categoryarray=expirations,
+ ),
+ yaxis=dict(
+ title="Price ($)",
+ ticklen=0,
+ showgrid=True,
+ gridcolor="rgba(128,128,128,0.3)",
+ ),
+ legend=dict(
+ orientation="v",
+ yanchor="top",
+ xanchor="right",
+ y=0.95,
+ x=0,
+ xref="paper",
+ font=dict(size=12),
+ bgcolor="rgba(0,0,0,0)",
+ ),
+ margin=dict(
+ b=10,
+ t=10,
+ ),
+ )
+
+ layout_kwargs = kwargs.get("layout_kwargs", {})
+ if layout_kwargs:
+ figure.update_layout(layout_kwargs)
+
+ content = figure.show(external=True).to_plotly_json()
+
+ return figure, content
diff --git a/openbb_platform/obbject_extensions/charting/integration/test_charting_api.py b/openbb_platform/obbject_extensions/charting/integration/test_charting_api.py
index 76bcba65d7f..7dbd1497eb1 100644
--- a/openbb_platform/obbject_extensions/charting/integration/test_charting_api.py
+++ b/openbb_platform/obbject_extensions/charting/integration/test_charting_api.py
@@ -791,3 +791,39 @@ def test_charting_derivatives_futures_historical(params, headers):
assert chart
assert not fig
assert list(chart.keys()) == ["content", "format"]
+
+
+@parametrize(
+ "params",
+ [
+ (
+ {
+ "provider": "yfinance",
+ "symbol": "VX",
+ }
+ ),
+ (
+ {
+ "provider": "cboe",
+ "symbol": "VX",
+ }
+ ),
+ ],
+)
+@pytest.mark.integration
+def test_charting_derivatives_futures_curve(params, headers):
+ """Test chart derivatives futures curve."""
+ params = {p: v for p, v in params.items() if v}
+ body = (json.dumps({"extra_params": {"chart_params": {"title": "test chart"}}}),)
+ query_str = get_querystring(params, [])
+ url = f"http://0.0.0.0:8000/api/v1/derivatives/futures/curve?{query_str}"
+ result = requests.get(url, headers=headers, timeout=10, json=body)
+ assert isinstance(result, requests.Response)
+ assert result.status_code == 200
+
+ chart = result.json()["chart"]
+ fig = chart.pop("fig", {})
+
+ assert chart
+ assert not fig
+ assert list(chart.keys()) == ["content", "format"]
diff --git a/openbb_platform/obbject_extensions/charting/integration/test_charting_python.py b/openbb_platform/obbject_extensions/charting/integration/test_charting_python.py
index 34705bb149f..6b95902bf2c 100644
--- a/openbb_platform/obbject_extensions/charting/integration/test_charting_python.py
+++ b/openbb_platform/obbject_extensions/charting/integration/test_charting_python.py
@@ -646,3 +646,31 @@ def test_charting_derivatives_futures_historical(params, obb):
assert len(result.results) > 0
assert result.chart.content
assert isinstance(result.chart.fig, OpenBBFigure)
+
+
+@parametrize(
+ "params",
+ [
+ (
+ {
+ "provider": "yfinance",
+ "symbol": "VX",
+ }
+ ),
+ (
+ {
+ "provider": "cboe",
+ "symbol": "VX",
+ }
+ ),
+ ],
+)
+@pytest.mark.integration
+def test_charting_derivatives_futures_curve(params, obb):
+ """Test chart derivatives futures curve."""
+ result = obb.derivatives.futures.curve(**params)
+ assert result
+ assert isinstance(result, OBBject)
+ assert len(result.results) > 0
+ assert result.chart.content
+ assert isinstance(result.chart.fig, OpenBBFigure)
diff --git a/openbb_platform/obbject_extensions/charting/openbb_charting/charting.py b/openbb_platform/obbject_extensions/charting/openbb_charting/charting.py
index efe4672533d..24ef1bd466f 100644
--- a/openbb_platform/obbject_extensions/charting/openbb_charting/charting.py
+++ b/openbb_platform/obbject_extensions/charting/openbb_charting/charting.py
@@ -121,10 +121,11 @@ class Charting:
)
return self._functions[adjusted_route]
- def get_params(self) -> ChartParams:
+ def get_params(self) -> Union[ChartParams, None]:
"""Return the ChartQueryParams class for the function the OBBject was created from.
Without assigning to a variable, it will print the docstring to the console.
+ If the class is not defined, the help for the function will be returned.
"""
if self._obbject._route is None: # pylint: disable=protected-access
raise ValueError("OBBject was initialized with no function route.")
@@ -133,8 +134,13 @@ class Charting:
).replace("/", "_")[1:]
if hasattr(ChartParams, charting_function):
return getattr(ChartParams, charting_function)()
- raise ValueError(
- f"Error: No chart parameters are defined for the route: {charting_function}"
+
+ return help( # type: ignore
+ self._get_chart_function( # pylint: disable=protected-access
+ self._obbject.extra[ # pylint: disable=protected-access
+ "metadata"
+ ].route
+ )
)
def _prepare_data_as_df(
diff --git a/openbb_platform/obbject_extensions/charting/openbb_charting/query_params.py b/openbb_platform/obbject_extensions/charting/openbb_charting/query_params.py
index c9caad2ebd9..4d95aabf84b 100644
--- a/openbb_platform/obbject_extensions/charting/openbb_charting/query_params.py
+++ b/openbb_platform/obbject_extensions/charting/openbb_charting/query_params.py
@@ -396,10 +396,10 @@ class ChartParams:
"""Chart Query Params."""
crypto_price_historical = EquityPriceHistoricalChartQueryParams
+ derivatives_futures_historical = EquityPriceHistoricalChartQueryParams
equity_price_historical = EquityPriceHistoricalChartQueryParams
economy_fred_series = EconomyFredSeriesChartQueryParams
equity_price_historical = EquityPriceHistoricalChartQueryParams
- derivatives_futures_historical = EquityPriceHistoricalChartQueryParams
equity_price_performance = EquityPricePerformanceChartQueryParams
etf_historical = EtfPricePerformanceChartQueryParams
etf_holdings = EtfHoldingsChartQueryParams
diff --git a/openbb_platform/providers/cboe/openbb_cboe/models/futures_curve.py b/openbb_platform/providers/cboe/openbb_cboe/models/futures_curve.py
index ce1a267f4df..af605c21d83 100644
--- a/openbb_platform/providers/cboe/openbb_cboe/models/futures_curve.py
+++ b/openbb_platform/providers/cboe/openbb_cboe/models/futures_curve.py
@@ -1,17 +1,22 @@
"""CBOE Futures Curve Model."""
-# IMPORT STANDARD
-from typing import Any, Dict, List, Optional
+# pylint: disable=unused-argument
+
+from typing import Any, Dict, List, Literal, Optional
-from openbb_cboe.utils.helpers import get_settlement_prices
-from openbb_core.app.model.abstract.error import OpenBBError
from openbb_core.provider.abstract.fetcher import Fetcher
from openbb_core.provider.standard_models.futures_curve import (
FuturesCurveData,
FuturesCurveQueryParams,
)
+from openbb_core.provider.utils.descriptions import (
+ DATA_DESCRIPTIONS,
+ QUERY_DESCRIPTIONS,
+)
from openbb_core.provider.utils.errors import EmptyDataError
-from pydantic import Field
+from pydantic import Field, field_validator
+
+SymbolChoices = Literal["VX_AM", "VX_EOD"]
class CboeFuturesCurveQueryParams(FuturesCurveQueryParams):
@@ -20,11 +25,32 @@ class CboeFuturesCurveQueryParams(FuturesCurveQueryParams):
Source: https://www.cboe.com/
"""
+ __json_schema_extra__ = {"date": {"multiple_items_allowed": True}}
+
+ symbol: SymbolChoices = Field(
+ default="VX_EOD",
+ description=QUERY_DESCRIPTIONS.get("symbol", "")
+ + "Default is 'VX_EOD'. Entered dates return the data nearest to the entered date."
+ + "\n 'VX_AM' = Mid-Morning TWAP Levels"
+ + "\n 'VX_EOD' = 4PM Eastern Time Levels",
+ json_schema_extra={"choices": ["VX_AM", "VX_EOD"]},
+ )
+
+ @field_validator("symbol", mode="before", check_fields=False)
+ @classmethod
+ def validate_symbol(cls, v):
+ """Validate the symbol."""
+ if not v or v.lower() in ["vx", "vix", "^vix", "vix_index"]:
+ return "VX_EOD"
+ return v.upper()
+
class CboeFuturesCurveData(FuturesCurveData):
"""CBOE Futures Curve Data."""
- symbol: str = Field(description="The trading symbol for the tenor of future.")
+ symbol: Optional[str] = Field(
+ default=None, description=DATA_DESCRIPTIONS.get("symbol", "")
+ )
class CboeFuturesCurveFetcher(
@@ -47,19 +73,21 @@ class CboeFuturesCurveFetcher(
**kwargs: Any,
) -> List[Dict]:
"""Return the raw data from the CBOE endpoint."""
- symbol = query.symbol.upper().split(",")[0]
- FUTURES = await get_settlement_prices(**kwargs)
- if len(FUTURES) == 0:
- raise EmptyDataError()
-
- if symbol not in FUTURES["product"].unique().tolist():
- raise OpenBBError(
- "The symbol, "
- f"{symbol}"
- ", is not valid. Chose from: "
- f"{FUTURES['product'].unique().tolist()}"
+ # pylint: disable=import-outside-toplevel
+ from openbb_cboe.utils.vix import get_vx_by_date, get_vx_current
+
+ symbol = "am" if query.symbol == "VX_AM" else "eod"
+ if query.date is not None:
+ data = await get_vx_by_date(
+ date=query.date, # type: ignore
+ vx_type=symbol,
+ use_cache=False,
)
- data = FUTURES[FUTURES["product"] == symbol][["expiration", "symbol", "price"]]
+ else:
+ data = await get_vx_current(vx_type=symbol, use_cache=