From fc8dec2b7a7ee2c2ec8b164a5dd1f60c58c3d047 Mon Sep 17 00:00:00 2001 From: Colin Delahunty <72827203+colin99d@users.noreply.github.com> Date: Tue, 16 Aug 2022 10:30:39 -0400 Subject: [PATCH] More Options Tradier Fixes (#2309) * Added features * Fixed tests Co-authored-by: James Maslek --- .../stocks/options/chartexchange_model.py | 5 +- .../stocks/options/chartexchange_view.py | 5 +- .../stocks/options/options_controller.py | 26 +++++--- .../stocks/options/tradier_model.py | 5 +- .../stocks/options/tradier_view.py | 57 ++++++++-------- ...test_display_chains[False-False--1--1].txt | 66 ++++++++++++------- .../test_display_chains[False-True--1--1].txt | 22 +++++++ .../test_display_chains[True-False--1--1].txt | 22 +++++++ 8 files changed, 148 insertions(+), 60 deletions(-) diff --git a/openbb_terminal/stocks/options/chartexchange_model.py b/openbb_terminal/stocks/options/chartexchange_model.py index 52a21ffb56a..d49fbeea6be 100644 --- a/openbb_terminal/stocks/options/chartexchange_model.py +++ b/openbb_terminal/stocks/options/chartexchange_model.py @@ -43,7 +43,10 @@ def get_option_history(ticker: str, date: str, call: bool, price: str) -> pd.Dat data = requests.get(url, headers={"User-Agent": get_user_agent()}).content soup = BeautifulSoup(data, "html.parser") table = soup.find("div", attrs={"style": "display: table; font-size: 0.9em; "}) - rows = table.find_all("div", attrs={"style": "display: table-row;"}) + if table: + rows = table.find_all("div", attrs={"style": "display: table-row;"}) + else: + return pd.DataFrame() clean_rows = [] if rows: diff --git a/openbb_terminal/stocks/options/chartexchange_view.py b/openbb_terminal/stocks/options/chartexchange_view.py index 076d33d3d1c..6160f5b42a3 100644 --- a/openbb_terminal/stocks/options/chartexchange_view.py +++ b/openbb_terminal/stocks/options/chartexchange_view.py @@ -17,7 +17,7 @@ from openbb_terminal.helper_funcs import ( ) from openbb_terminal.stocks.options import chartexchange_model from openbb_terminal.config_terminal import theme - +from openbb_terminal.rich_config import console from openbb_terminal.helper_funcs import ( plot_autoscale, lambda_long_number_format_y_axis, @@ -55,6 +55,9 @@ def display_raw( """ df = chartexchange_model.get_option_history(ticker, date, call, price)[::-1] + if df.empty: + console.print("[red]No data found[/red]\n") + return df["Date"] = pd.to_datetime(df["Date"]) df = df.set_index("Date") diff --git a/openbb_terminal/stocks/options/options_controller.py b/openbb_terminal/stocks/options/options_controller.py index 57df97740e0..ead7b0ba366 100644 --- a/openbb_terminal/stocks/options/options_controller.py +++ b/openbb_terminal/stocks/options/options_controller.py @@ -545,9 +545,15 @@ class OptionsController(BaseController): console.print("") if self.ticker and self.selected_date: - self.chain = yfinance_model.get_option_chain( - self.ticker, self.selected_date - ) + try: + self.chain = yfinance_model.get_option_chain( + self.ticker, self.selected_date + ) + except ValueError: + console.print( + f"[red]{self.ticker} does not have expiration" + f" {self.selected_date}.[/red]" + ) @log_start_end(log=logger) def call_exp(self, other_args: List[str]): @@ -679,7 +685,10 @@ class OptionsController(BaseController): ) else: - if TRADIER_TOKEN != "REPLACE_ME": # nosec + if ( + TRADIER_TOKEN != "REPLACE_ME" + or self.source == "tradier" + ): # nosec tradier_view.display_historical( ticker=self.ticker, expiry=self.selected_date, @@ -835,7 +844,7 @@ class OptionsController(BaseController): if ( ns_parser.source == "tradier" and TRADIER_TOKEN != "REPLACE_ME" # nosec - ): + ) or self.source == "tradier": tradier_view.plot_vol( ticker=self.ticker, expiry=self.selected_date, @@ -904,7 +913,7 @@ class OptionsController(BaseController): if ( ns_parser.source == "tradier" and TRADIER_TOKEN != "REPLACE_ME" # nosec - ): + ) or self.source == "tradier": tradier_view.plot_volume_open_interest( ticker=self.ticker, expiry=self.selected_date, @@ -934,7 +943,8 @@ class OptionsController(BaseController): add_help=False, formatter_class=argparse.ArgumentDefaultsHelpFormatter, prog="oi", - description="Plot open interest. Open interest represents the number of contracts that exist.", + description="""Plot open interest. Open interest represents the number of + contracts that exist.""", ) parser.add_argument( "-m", @@ -979,7 +989,7 @@ class OptionsController(BaseController): if ( ns_parser.source == "tradier" and TRADIER_TOKEN != "REPLACE_ME" # nosec - ): + ) or self.source == "tradier": tradier_view.plot_oi( ticker=self.ticker, expiry=self.selected_date, diff --git a/openbb_terminal/stocks/options/tradier_model.py b/openbb_terminal/stocks/options/tradier_model.py index bc729dbe6fb..745d8136920 100644 --- a/openbb_terminal/stocks/options/tradier_model.py +++ b/openbb_terminal/stocks/options/tradier_model.py @@ -241,7 +241,10 @@ def last_price(ticker: str): }, ) if r.status_code == 200: - return float(r.json()["quotes"]["quote"]["last"]) + last = r.json()["quotes"]["quote"]["last"] + if last is None: + return 0 + return float(last) else: console.print("Error getting last price") return None diff --git a/openbb_terminal/stocks/options/tradier_view.py b/openbb_terminal/stocks/options/tradier_view.py index d63d58b06f0..db78243afe3 100644 --- a/openbb_terminal/stocks/options/tradier_view.py +++ b/openbb_terminal/stocks/options/tradier_view.py @@ -1,11 +1,12 @@ """Tradier options view""" __docformat__ = "numpy" +import warnings import argparse import logging import os from bisect import bisect_left -from typing import List, Optional +from typing import List, Optional, Tuple import matplotlib.pyplot as plt import mplfinance as mpf @@ -31,6 +32,28 @@ from openbb_terminal import rich_config logger = logging.getLogger(__name__) column_map = {"mid_iv": "iv", "open_interest": "oi", "volume": "vol"} +warnings.filterwarnings("ignore") + + +def get_strike_bounds( + options: pd.DataFrame, current_price: float, min_sp: float, max_sp: float +) -> Tuple[float, float]: + if min_sp == -1: + if current_price == 0: + min_strike = options["strike"].iat[0] + else: + min_strike = 0.75 * current_price + else: + min_strike = min_sp + + if max_sp == -1: + if current_price == 0: + max_strike = options["strike"].iat[-1] + else: + max_strike = 1.25 * current_price + else: + max_strike = max_sp + return min_strike, max_strike def lambda_red_highlight(val) -> str: @@ -145,15 +168,7 @@ def display_chains( columns = to_display + ["strike", "option_type"] chains_df = chains_df[columns].rename(columns=column_map) - if min_sp == -1: - min_strike = np.percentile(chains_df["strike"], 25) - else: - min_strike = min_sp - - if max_sp == -1: - max_strike = np.percentile(chains_df["strike"], 75) - else: - max_strike = max_sp + min_strike, max_strike = get_strike_bounds(chains_df, 0, min_sp, max_sp) chains_df = chains_df[chains_df["strike"] >= min_strike] chains_df = chains_df[chains_df["strike"] <= max_strike] @@ -245,15 +260,11 @@ def plot_oi( options = tradier_model.get_option_chains(ticker, expiry) current_price = tradier_model.last_price(ticker) - if min_sp == -1: - min_strike = 0.75 * current_price - else: - min_strike = min_sp + min_strike, max_strike = get_strike_bounds(options, current_price, min_sp, max_sp) - if max_sp == -1: - max_strike = 1.25 * current_price - else: - max_strike = max_sp + if max_strike == min_strike: + console.print("[red]Not enough data for analysis[/red]\n") + return if calls_only and puts_only: console.print("Both flags selected, please select one", "\n") @@ -340,15 +351,7 @@ def plot_vol( options = tradier_model.get_option_chains(ticker, expiry) current_price = tradier_model.last_price(ticker) - if min_sp == -1: - min_strike = 0.75 * current_price - else: - min_strike = min_sp - - if max_sp == -1: - max_strike = 1.25 * current_price - else: - max_strike = max_sp + min_strike, max_strike = get_strike_bounds(options, current_price, min_sp, max_sp) if calls_only and puts_only: console.print("Both flags selected, please select one", "\n") diff --git a/tests/openbb_terminal/stocks/options/txt/test_tradier_view/test_display_chains[False-False--1--1].txt b/tests/openbb_terminal/stocks/options/txt/test_tradier_view/test_display_chains[False-False--1--1].txt index ab0ee0eb8f8..c76a98ddb7a 100644 --- a/tests/openbb_terminal/stocks/options/txt/test_tradier_view/test_display_chains[False-False--1--1].txt +++ b/tests/openbb_terminal/stocks/options/txt/test_tradier_view/test_display_chains[False-False--1--1].txt @@ -1,23 +1,45 @@ vol_x strike vol_y -0 [green]0[/green] 148.0 [red]15[/red] -1 [green]0[/green] 149.0 [red]11[/red] -2 [green]144[/green] 150.0 [red]375[/red] -3 [green]1[/green] 152.5 [red]82[/red] -4 [green]3[/green] 155.0 [red]745[/red] -5 [green]1[/green] 157.5 [red]291[/red] -6 [green]158[/green] 160.0 [red]1204[/red] -7 [green]36[/green] 162.5 [red]747[/red] -8 [green]140[/green] 165.0 [red]1968[/red] -9 [green]82[/green] 167.5 [red]2392[/red] -10 [green]439[/green] 170.0 [red]2361[/red] -11 [green]1043[/green] 172.5 [red]1860[/red] -12 [green]4640[/green] 175.0 [red]1046[/red] -13 [green]1442[/green] 177.5 [red]80[/red] -14 [green]5482[/green] 180.0 [red]158[/red] -15 [green]1218[/green] 182.5 [red]25[/red] -16 [green]2680[/green] 185.0 [red]20[/red] -17 [green]385[/green] 187.5 [red]1[/red] -18 [green]519[/green] 190.0 [red]1[/red] -19 [green]875[/green] 192.5 [red]0[/red] -20 [green]394[/green] 195.0 [red]1[/red] -21 [green]19[/green] 197.5 [red]0[/red] +0 [green]0[/green] 105.0 [red]370[/red] +1 [green]0[/green] 110.0 [red]0[/red] +2 [green]0[/green] 115.0 [red]9[/red] +3 [green]0[/green] 120.0 [red]921[/red] +4 [green]0[/green] 125.0 [red]28[/red] +5 [green]0[/green] 130.0 [red]146[/red] +6 [green]0[/green] 135.0 [red]33[/red] +7 [green]4[/green] 140.0 [red]125[/red] +8 [green]2[/green] 145.0 [red]203[/red] +9 [green]20[/green] 146.0 [red]21[/red] +10 [green]0[/green] 147.0 [red]5[/red] +11 [green]0[/green] 148.0 [red]15[/red] +12 [green]0[/green] 149.0 [red]11[/red] +13 [green]144[/green] 150.0 [red]375[/red] +14 [green]1[/green] 152.5 [red]82[/red] +15 [green]3[/green] 155.0 [red]745[/red] +16 [green]1[/green] 157.5 [red]291[/red] +17 [green]158[/green] 160.0 [red]1204[/red] +18 [green]36[/green] 162.5 [red]747[/red] +19 [green]140[/green] 165.0 [red]1968[/red] +20 [green]82[/green] 167.5 [red]2392[/red] +21 [green]439[/green] 170.0 [red]2361[/red] +22 [green]1043[/green] 172.5 [red]1860[/red] +23 [green]4640[/green] 175.0 [red]1046[/red] +24 [green]1442[/green] 177.5 [red]80[/red] +25 [green]5482[/green] 180.0 [red]158[/red] +26 [green]1218[/green] 182.5 [red]25[/red] +27 [green]2680[/green] 185.0 [red]20[/red] +28 [green]385[/green] 187.5 [red]1[/red] +29 [green]519[/green] 190.0 [red]1[/red] +30 [green]875[/green] 192.5 [red]0[/red] +31 [green]394[/green] 195.0 [red]1[/red] +32 [green]19[/green] 197.5 [red]0[/red] +33 [green]202[/green] 200.0 [red]0[/red] +34 [green]46[/green] 205.0 [red]0[/red] +35 [green]315[/green] 210.0 [red]0[/red] +36 [green]0[/green] 215.0 [red]0[/red] +37 [green]7[/green] 220.0 [red]0[/red] +38 [green]1[/green] 225.0 [red]0[/red] +39 [green]0[/green] 230.0 [red]0[/red] +40 [green]0[/green] 235.0 [red]0[/red] +41 [green]164[/green] 240.0 [red]0[/red] +42 [green]21[/green] 245.0 [red]0[/red] +43 [green]1[/green] 250.0 [red]0[/red] diff --git a/tests/openbb_terminal/stocks/options/txt/test_tradier_view/test_display_chains[False-True--1--1].txt b/tests/openbb_terminal/stocks/options/txt/test_tradier_view/test_display_chains[False-True--1--1].txt index 6400427604b..4d3c9452aca 100644 --- a/tests/openbb_terminal/stocks/options/txt/test_tradier_view/test_display_chains[False-True--1--1].txt +++ b/tests/openbb_terminal/stocks/options/txt/test_tradier_view/test_display_chains[False-True--1--1].txt @@ -1,4 +1,15 @@ vol strike +0 370 105.0 +2 0 110.0 +4 9 115.0 +6 921 120.0 +8 28 125.0 +10 146 130.0 +12 33 135.0 +14 125 140.0 +16 203 145.0 +19 21 146.0 +20 5 147.0 22 15 148.0 24 11 149.0 26 375 150.0 @@ -21,3 +32,14 @@ 61 0 192.5 62 1 195.0 65 0 197.5 +66 0 200.0 +68 0 205.0 +70 0 210.0 +72 0 215.0 +74 0 220.0 +77 0 225.0 +78 0 230.0 +80 0 235.0 +82 0 240.0 +84 0 245.0 +86 0 250.0 diff --git a/tests/openbb_terminal/stocks/options/txt/test_tradier_view/test_display_chains[True-False--1--1].txt b/tests/openbb_terminal/stocks/options/txt/test_tradier_view/test_display_chains[True-False--1--1].txt index f3f52191907..f88a7809a89 100644 --- a/tests/openbb_terminal/stocks/options/txt/test_tradier_view/test_display_chains[True-False--1--1].txt +++ b/tests/openbb_terminal/stocks/options/txt/test_tradier_view/test_display_chains[True-False--1--1].txt @@ -1,4 +1,15 @@ vol strike +1 0 105.0 +3 0 110.0 +5 0 115.0 +7 0 120.0 +9 0 125.0 +11 0 130.0 +13 0 135.0 +15 4 140.0 +17 2 145.0 +18 20 146.0 +21 0 147.0 23 0 148.0 25 0 149.0 27 144 150.0 @@ -21,3 +32,14 @@ 60 875 192.5 63 394 195.0 64 19 197.5 +67 202 200.0 +69 46 205.0 +71 315 210.0 +73 0 215.0 +75 7 220.0 +76 1 225.0 +79 0 230.0 +81 0 235.0 +83 164 240.0 +85 21 245.0 +87 1 250.0