diff --git a/ROADMAP.md b/ROADMAP.md index ff7bfc21eeb..8989040cbad 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -19,7 +19,7 @@ * [Frontend](#Frontend) * [Developer Experience](#Developer-Experience) * [User Experience](#User-Experience) - +* [Options](#Options) --- ## Discovery @@ -205,3 +205,17 @@ ### Long term - [ ] Add a WHL installation + + +--- + +## Options + +### Short term + +- [ ] Add Volume graph (@lolrenx) +- [ ] Add Open Interest graph (@lolrenx) + +### Long term + +- [ ] Add max pain graph diff --git a/gamestonk_terminal/main_helper.py b/gamestonk_terminal/main_helper.py index 78272a3b092..4010e85a204 100644 --- a/gamestonk_terminal/main_helper.py +++ b/gamestonk_terminal/main_helper.py @@ -76,6 +76,7 @@ def print_help(s_ticker, s_start, s_interval, b_is_market_open): print( " pred prediction techniques, \t e.g.: regression, arima, rnn, lstm, prophet" ) + print(" op options info, \t e.g.: volume") print("") diff --git a/gamestonk_terminal/options/README.md b/gamestonk_terminal/options/README.md new file mode 100644 index 00000000000..da19584da2a --- /dev/null +++ b/gamestonk_terminal/options/README.md @@ -0,0 +1,18 @@ +# OPTIONS DATA + +This menu aims to give insight on options. options can cause significant share price movement, and option pricing gives info about market sentiment for a ticker. + +* [volume](#volume) + * Show traded options for a given expiry [Yahoo Finance] + + + +## volume + +```text +usage: volume -d 'yyyy-mm-dd' +``` + +Display volume graph for a date. [Source: Yahoo Finance] + +* -d : expiration date. diff --git a/gamestonk_terminal/options/op_menu.py b/gamestonk_terminal/options/op_menu.py new file mode 100644 index 00000000000..a386a584ec2 --- /dev/null +++ b/gamestonk_terminal/options/op_menu.py @@ -0,0 +1,59 @@ +import argparse + +from prompt_toolkit.completion import NestedCompleter +from gamestonk_terminal import feature_flags as gtff +from gamestonk_terminal.helper_funcs import get_flair +from gamestonk_terminal.options import volume as vol +from gamestonk_terminal.menu import session + + +def opt_menu(s_ticker): + + # Add list of arguments that the options parser accepts + opt_parser = argparse.ArgumentParser(prog="opt", add_help=False) + choices = ["help", "q", "quit", "volume", "oi"] + opt_parser.add_argument("cmd", choices=choices) + completer = NestedCompleter.from_nested_dict({c: None for c in choices}) + + # print_options(s_ticker, s_start, s_interval) + + # Loop forever and ever + while True: + # Get input command from user + if session and gtff.USE_PROMPT_TOOLKIT: + as_input = session.prompt( + f"{get_flair()} (opt)> ", + completer=completer, + ) + else: + as_input = input(f"{get_flair()} (opt)> ") + + # Parse fundamental analysis command of the list of possible commands + try: + (ns_known_args, l_args) = opt_parser.parse_known_args(as_input.split()) + + except SystemExit: + print("The command selected doesn't exist\n") + continue + + if ns_known_args.cmd == "help": + pass + # print_options(s_ticker) + + elif ns_known_args.cmd == "q": + # Just leave the options menu + return False + + elif ns_known_args.cmd == "quit": + # Abandon the program + return True + + elif ns_known_args.cmd == "volume": + # call the volume graph + vol.volume_graph(l_args, s_ticker) + + elif ns_known_args.cmd == "oi": + # call the volume graph + vol.open_interest_graph(l_args, s_ticker) + else: + print("Command not recognized!") diff --git a/gamestonk_terminal/options/volume.py b/gamestonk_terminal/options/volume.py new file mode 100644 index 00000000000..14440ef101e --- /dev/null +++ b/gamestonk_terminal/options/volume.py @@ -0,0 +1,144 @@ +import argparse +import yfinance as yf +import seaborn as sns +import pandas as pd +import matplotlib.pyplot as plt +import plotly.express as px +from gamestonk_terminal.helper_funcs import ( + parse_known_args_and_warn, + valid_date, +) + + +def open_interest_graph(l_args, s_ticker): + """ Show traded options volume. [Source: Yahoo Finance] """ + parser = argparse.ArgumentParser( + add_help=False, + prog="volume", + description="""Display volume graph for a date. [Source: Yahoo Finance].""", + ) + parser.add_argument( + "-e", + "--expiry", + type=valid_date, + dest="s_expiry_date", + help="The expiry date (format YYYY-MM-DD) for the option chain", + required=True, + ) + try: + ns_parser = parse_known_args_and_warn(parser, l_args) + if not ns_parser: + return + + __get_open_interest_graph( + s_ticker, ns_parser.s_expiry_date.strftime("%Y-%m-%d") + ) + + except SystemExit: + print("") + except Exception as e: + print(e) + + +def volume_graph(l_args, s_ticker): + """ Show traded options volume. [Source: Yahoo Finance] """ + parser = argparse.ArgumentParser( + add_help=False, + prog="volume", + description="""Display volume graph for a date. [Source: Yahoo Finance].""", + ) + parser.add_argument( + "-e", + "--expiry", + type=valid_date, + dest="s_expiry_date", + help="The expiry date (format YYYY-MM-DD) for the option chain", + required=True, + ) + + try: + ns_parser = parse_known_args_and_warn(parser, l_args) + if not ns_parser: + return + + __get_volume_graph(s_ticker, ns_parser.s_expiry_date.strftime("%Y-%m-%d")) + + except SystemExit: + print("") + except Exception as e: + print(e) + + +def __get_open_interest_graph(ticker_name, exp_date): + df = __get_volume_data(ticker_name, exp_date) + __generate_graph_sns(df, ticker_name, exp_date, True) + # __generate_graph_plotly(df, ticker_name, exp_date) + + +def __get_volume_graph(ticker_name, exp_date): + df = __get_volume_data(ticker_name, exp_date) + __generate_graph_sns(df, ticker_name, exp_date) + # __generate_graph_plotly(df, ticker_name, exp_date) + + +def __pull_call_put_data(call_put, flag): + df = call_put.pivot_table( + index="strike", values=["volume", "openInterest"], aggfunc="sum" + ) + + df.reindex() + + df["strike"] = df.index + df["type"] = flag + + return df + + +def __get_volume_data(ticker_name, exp_date): + + option_chain = yf.Ticker(ticker_name).option_chain(exp_date) + + calls = __pull_call_put_data(option_chain.calls, "calls") + + puts = __pull_call_put_data(option_chain.puts, "puts") + + volume_data = pd.concat([calls, puts], axis=0) + # dataframe + return volume_data + + +def __generate_graph_plotly(df, ticker_name, exp_date, for_open_interest=False): + # version with plotly express + if for_open_interest: + op_type = "openInterest" + else: + op_type = "volume" + + fig = px.line( + df, + x="strike", + y=op_type, + title=f"{ticker_name} options {op_type} for {exp_date}", + color="type", + ) + fig.show() + + return + + +def __generate_graph_sns(df, ticker_name, exp_date, for_open_interest=False): + # version with seaborn express + if for_open_interest: + op_type = "openInterest" + else: + op_type = "volume" + + plt.figure(figsize=(12, 6)) + fig = sns.lineplot( + data=df, x="strike", y=op_type, hue="type", palette=["limegreen", "tomato"] + ) + + plt.title(f"{ticker_name} options {op_type} for {exp_date}") + + plt.show() + return fig diff --git a/terminal.py b/terminal.py index 7fdcdf2f797..bb8f8ee39c5 100644 --- a/terminal.py +++ b/terminal.py @@ -22,6 +22,7 @@ from gamestonk_terminal.papermill import papermill_controller as mill from gamestonk_terminal.sentiment import sen_menu as sm from gamestonk_terminal.technical_analysis import ta_menu as tam from gamestonk_terminal.comparison_analysis import ca_menu as cam +from gamestonk_terminal.options import op_menu as opm from gamestonk_terminal.fred import fred_menu as fm # import warnings @@ -72,6 +73,7 @@ def main(): "dd", "pred", "ca", + "op", "fred", ] menu_parser.add_argument("opt", choices=choices) @@ -180,6 +182,9 @@ def main(): elif ns_known_args.opt == "dd": b_quit = ddm.dd_menu(df_stock, s_ticker, s_start, s_interval) + elif ns_known_args.opt == "op": + b_quit = opm.opt_menu(s_ticker) + elif ns_known_args.opt == "fred": b_quit = fm.fred_menu()