From 7cceeba054167752a578681ee70471dcd43a12f4 Mon Sep 17 00:00:00 2001 From: Colin Delahunty <72827203+colin99d@users.noreply.github.com> Date: Thu, 3 Nov 2022 16:28:32 +0100 Subject: [PATCH] Improves Error Handling for option.grhist (#3284) * Added bad index error handling * Handle screener errors * More error handling Co-authored-by: James Maslek --- .../stocks/options/options_controller.py | 5 +-- .../stocks/options/screen/syncretism_model.py | 25 ++++++++++++--- .../stocks/options/screen/syncretism_view.py | 32 +++++++++++++++---- 3 files changed, 50 insertions(+), 12 deletions(-) diff --git a/openbb_terminal/stocks/options/options_controller.py b/openbb_terminal/stocks/options/options_controller.py index a38652d336d..b5f1305c358 100644 --- a/openbb_terminal/stocks/options/options_controller.py +++ b/openbb_terminal/stocks/options/options_controller.py @@ -124,10 +124,10 @@ class OptionsController(BaseController): if ticker: if API_TRADIER_TOKEN == "REPLACE_ME": # nosec - console.print("Loaded expiry dates from Yahoo Finance") + console.print("Loaded expiry dates from Yahoo Finance\n") self.expiry_dates = yfinance_model.option_expirations(self.ticker) else: - console.print("Loaded expiry dates from Tradier") + console.print("Loaded expiry dates from Tradier\n") self.expiry_dates = tradier_model.option_expirations(self.ticker) else: self.expiry_dates = [] @@ -621,6 +621,7 @@ class OptionsController(BaseController): "--limit", dest="limit", default=20, + type=int, help="Limit of raw data rows to display", ) if other_args and "-" not in other_args[0][0]: diff --git a/openbb_terminal/stocks/options/screen/syncretism_model.py b/openbb_terminal/stocks/options/screen/syncretism_model.py index 69e3c5ed04a..0e2c300be51 100644 --- a/openbb_terminal/stocks/options/screen/syncretism_model.py +++ b/openbb_terminal/stocks/options/screen/syncretism_model.py @@ -4,7 +4,7 @@ __docformat__ = "numpy" import configparser import logging from pathlib import Path -from typing import Dict, Tuple +from typing import Dict, Tuple, Union import pandas as pd import requests @@ -35,7 +35,11 @@ accepted_orders = [ @log_start_end(log=logger) def get_historical_greeks( - symbol: str, expiry: str, strike: float, chain_id: str = "", put: bool = False + symbol: str, + expiry: str, + strike: Union[str, float], + chain_id: str = "", + put: bool = False, ) -> pd.DataFrame: """Get histoical option greeks @@ -45,7 +49,7 @@ def get_historical_greeks( Stock ticker symbol expiry: str Option expiration date - strike: float + strike: Union[str, float] Strike price to look for chain_id: str OCC option symbol. Overwrites other inputs @@ -57,6 +61,14 @@ def get_historical_greeks( df: pd.DataFrame Dataframe containing historical greeks """ + if isinstance(strike, str): + try: + strike = float(strike) + except ValueError: + console.print( + f"[red]Strike of {strike} cannot be converted to a number.[/red]\n" + ) + return pd.DataFrame() if not chain_id: options = yfinance_model.get_option_chain(symbol, expiry) @@ -65,7 +77,12 @@ def get_historical_greeks( else: options = options.calls - chain_id = options.loc[options.strike == strike, "contractSymbol"].values[0] + selection = options.loc[options.strike == strike, "contractSymbol"] + try: + chain_id = selection.values[0] + except IndexError: + console.print(f"[red]Strike price of {strike} not found.[/red]\n") + return pd.DataFrame() r = requests.get(f"https://api.syncretism.io/ops/historical/{chain_id}") diff --git a/openbb_terminal/stocks/options/screen/syncretism_view.py b/openbb_terminal/stocks/options/screen/syncretism_view.py index 946d73be38b..6a643393e1e 100644 --- a/openbb_terminal/stocks/options/screen/syncretism_view.py +++ b/openbb_terminal/stocks/options/screen/syncretism_view.py @@ -4,7 +4,7 @@ __docformat__ = "numpy" import configparser import logging import os -from typing import List, Optional +from typing import List, Optional, Union import matplotlib.pyplot as plt @@ -106,12 +106,12 @@ def view_screener_output( def view_historical_greeks( symbol: str, expiry: str, - strike: float, + strike: Union[float, str], greek: str = "Delta", chain_id: str = "", put: bool = False, raw: bool = False, - limit: int = 20, + limit: Union[int, str] = 20, export: str = "", external_axes: Optional[List[plt.Axes]] = None, ): @@ -123,7 +123,7 @@ def view_historical_greeks( Stock ticker expiry: str Expiration date - strike: float + strike: Union[str, float] Strike price to consider greek: str Greek variable to plot @@ -141,10 +141,25 @@ def view_historical_greeks( External axes (1 axis is expected in the list), by default None """ df = syncretism_model.get_historical_greeks(symbol, expiry, strike, chain_id, put) + if df is None: + return + if df.empty: + return + if isinstance(limit, str): + try: + limit = int(limit) + except ValueError: + console.print( + f"[red]Could not convert limit of {limit} to a number.[/red]\n" + ) + return if raw: print_rich_table( - df.tail(limit), headers=list(df.columns), title="Historical Greeks" + df.tail(limit), + headers=list(df.columns), + title="Historical Greeks", + show_index=True, ) if not external_axes: @@ -154,7 +169,12 @@ def view_historical_greeks( else: return - im1 = ax.plot(df.index, df[greek], label=greek.title(), color=theme.up_color) + try: + greek_df = df[greek.lower()] + except KeyError: + console.print(f"[red]Could not find greek {greek} in data.[/red]\n") + return + im1 = ax.plot(df.index, greek_df, label=greek.title(), color=theme.up_color) ax.set_ylabel(greek) ax1 = ax.twinx() im2 = ax1.plot(df.index, df.price, label="Stock Price", color=theme.down_color)