From d5929d0a3f519da14a731c4f40b32b9db55e5752 Mon Sep 17 00:00:00 2001 From: jmaslek Date: Wed, 27 Oct 2021 18:17:52 -0400 Subject: [PATCH] Add put-call ratio for given ticker (#865) * Add put call ratio to options * Update _index.md * sources Co-authored-by: James Maslek --- .../options/alphaquery_model.py | 41 +++++++++++++ gamestonk_terminal/options/alphaquery_view.py | 58 +++++++++++++++++++ .../options/options_controller.py | 55 +++++++++++++++++- website/content/options/pcr/_index.md | 18 ++++++ website/data/menu/main.yml | 2 + 5 files changed, 171 insertions(+), 3 deletions(-) create mode 100644 gamestonk_terminal/options/alphaquery_model.py create mode 100644 gamestonk_terminal/options/alphaquery_view.py create mode 100644 website/content/options/pcr/_index.md diff --git a/gamestonk_terminal/options/alphaquery_model.py b/gamestonk_terminal/options/alphaquery_model.py new file mode 100644 index 00000000000..0401d232e60 --- /dev/null +++ b/gamestonk_terminal/options/alphaquery_model.py @@ -0,0 +1,41 @@ +"""AlphaQuery Model""" +__docformat__ = "numpy" + +from datetime import datetime, timedelta +import requests +import pandas as pd + + +def get_put_call_ratio( + ticker: str, + window: int = 30, + start_date: str = (datetime.now() - timedelta(days=366)).strftime("%Y-%m-%d"), +) -> pd.DataFrame: + """Gets put call ratio over last time window [Source: AlphaQuery.com] + + Parameters + ---------- + ticker : str + Ticker to look for + window : int, optional + Window to consider, by default 30 + start_date : str, optional + Start date to plot, by default last 366 days + """ + url = f"https://www.alphaquery.com/data/option-statistic-chart?ticker={ticker}\ + &perType={window}-Day&identifier=put-call-ratio-volume" + headers = { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) \ + Chrome/70.0.3538.77 Safari/537.36" + } + + r = requests.get(url, headers=headers) + if r.status_code != 200: + return pd.DataFrame() + + pcr = pd.DataFrame.from_dict(r.json()) + pcr.rename(columns={"x": "Date", "value": "PCR"}, inplace=True) + pcr.set_index("Date", inplace=True) + pcr.index = pd.to_datetime(pcr.index).tz_localize(None) + + return pcr[pcr.index > start_date] diff --git a/gamestonk_terminal/options/alphaquery_view.py b/gamestonk_terminal/options/alphaquery_view.py new file mode 100644 index 00000000000..f04d80c135b --- /dev/null +++ b/gamestonk_terminal/options/alphaquery_view.py @@ -0,0 +1,58 @@ +"""AlphaQuery View""" +__docforma__ = "numpy" + +from datetime import datetime, timedelta +import os + +import matplotlib.pyplot as plt +import matplotlib.dates as mdates + +from gamestonk_terminal.options import alphaquery_model +from gamestonk_terminal.helper_funcs import export_data, plot_autoscale +from gamestonk_terminal.config_plot import PLOT_DPI +from gamestonk_terminal import feature_flags as gtff + + +def display_put_call_ratio( + ticker: str, + window: int = 30, + start_date: str = (datetime.now() - timedelta(days=366)).strftime("%Y-%m-%d"), + export: str = "", +): + """Display put call ratio [Source: AlphaQuery.com] + + Parameters + ---------- + ticker : str + Stock ticker + window : int, optional + Window length to look at, by default 30 + start_date : str, optional + Starting date for data, by default (datetime.now() - timedelta(days=366)).strftime("%Y-%m-%d") + export : str, optional + Format to export data, by default "" + """ + pcr = alphaquery_model.get_put_call_ratio(ticker, window, start_date) + if pcr.empty: + print("No data found.\n") + return + dateFmt = mdates.DateFormatter("%m/%d/%Y") + fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) + + ax.plot(pcr.index, pcr.values) + ax.xaxis.set_major_formatter(dateFmt) + ax.tick_params(axis="x", labelrotation=45) + ax.grid("on") + ax.axhline(y=1, lw=2, c="k") + ax.set_title(f"Put Call Ratio for {ticker.upper()}") + fig.tight_layout() + if gtff.USE_ION: + plt.ion() + plt.show() + print("") + export_data( + export, + os.path.dirname(os.path.abspath(__file__)), + "pcr", + pcr, + ) diff --git a/gamestonk_terminal/options/options_controller.py b/gamestonk_terminal/options/options_controller.py index a2aefe06bbe..9a69face4e2 100644 --- a/gamestonk_terminal/options/options_controller.py +++ b/gamestonk_terminal/options/options_controller.py @@ -5,6 +5,7 @@ __docformat__ = "numpy" import argparse import os +from datetime import datetime, timedelta from typing import List import matplotlib.pyplot as plt @@ -14,12 +15,15 @@ from prompt_toolkit.completion import NestedCompleter from gamestonk_terminal import feature_flags as gtff from gamestonk_terminal.config_terminal import TRADIER_TOKEN from gamestonk_terminal.helper_funcs import ( + EXPORT_BOTH_RAW_DATA_AND_FIGURES, check_positive, get_flair, parse_known_args_and_warn, MENU_GO_BACK, MENU_QUIT, MENU_RESET, + try_except, + valid_date, ) from gamestonk_terminal.menu import session from gamestonk_terminal.options import ( @@ -31,6 +35,7 @@ from gamestonk_terminal.options import ( tradier_view, yfinance_model, yfinance_view, + alphaquery_view, ) from gamestonk_terminal.stocks import stocks_controller from gamestonk_terminal.options import payoff_controller, chartexchange_view @@ -48,13 +53,14 @@ class OptionsController: "reset", ] - CHOICES_MENUS = [ + CHOICES_COMMANDS = [ "disp", "scr", "calc", "yf", "tr", "info", + "pcr", "load", "exp", "vol", @@ -70,7 +76,7 @@ class OptionsController: "parity", ] - CHOICES += CHOICES_MENUS + CHOICES += CHOICES_COMMANDS PRESET_PATH = os.path.join(os.path.abspath(os.path.dirname(__file__)), "presets/") @@ -135,7 +141,8 @@ Current Expiry: {self.selected_date or None} load load new ticker exp see and set expiration dates -{Style.DIM if not colored else ''} +{"" if self.ticker else Style.DIM} + pcr display put call ratio for ticker [AlphaQuery.com]{Style.DIM if not colored else ''} info display option information (volatility, IV rank etc) [Barchart.com] chains display option chains with greeks [Tradier] oi plot open interest [Tradier/YF] @@ -323,6 +330,48 @@ Current Expiry: {self.selected_date or None} except Exception as e: print(e, "\n") + @try_except + def call_pcr(self, other_args: List[str]): + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="pcr", + description="Display put to call ratio for ticker [AlphaQuery.com]", + ) + parser.add_argument( + "-l", + "-length", + help="Window length to get", + dest="length", + choices=[10, 20, 30, 60, 90, 120, 150, 180], + default=30, + type=int, + ) + parser.add_argument( + "-s", + "--start-date", + help="Start date for plot", + type=valid_date, + default=datetime.now() - timedelta(days=366), + dest="start", + ) + + ns_parser = parse_known_args_and_warn( + parser, other_args, export_allowed=EXPORT_BOTH_RAW_DATA_AND_FIGURES + ) + if not ns_parser: + return + if not self.ticker: + print("No ticker loaded.\n") + return + + alphaquery_view.display_put_call_ratio( + ticker=self.ticker, + window=ns_parser.length, + start_date=ns_parser.start.strftime("%Y-%m-%d"), + export=ns_parser.export, + ) + def call_info(self, other_args: List[str]): """Process info command""" if not self.ticker: diff --git a/website/content/options/pcr/_index.md b/website/content/options/pcr/_index.md new file mode 100644 index 00000000000..9ef512b432d --- /dev/null +++ b/website/content/options/pcr/_index.md @@ -0,0 +1,18 @@ +``` +usage: pcr [-l {10,20,30,60,90,120,150,180}] [-s START] [-h] [--export {png,jpg,pdf,svg}] +``` + +Display put to call ratio for ticker [AlphaQuery.com] + +``` +optional arguments: + -l {10,20,30,60,90,120,150,180}, -length {10,20,30,60,90,120,150,180} + Window length to get (default: 30) + -s START, --start-date START + Start date for plot (default: 2020-10-25 15:15:36.908882) + -h, --help show this help message (default: False) + --export {png,jpg,pdf,svg} + Export or figure into png, jpg, pdf, svg (default: ) +``` + +![AAPL_PCR](https://user-images.githubusercontent.com/18151143/138947156-9bbee8e0-0ea2-4ff7-8c6b-dd1d24cd7693.png) diff --git a/website/data/menu/main.yml b/website/data/menu/main.yml index 6c709ee205e..4a9fa981881 100755 --- a/website/data/menu/main.yml +++ b/website/data/menu/main.yml @@ -568,6 +568,8 @@ main: ref: "/options/load" - name: exp ref: "/options/exp" + - name: pcr + ref: "/options/pcr" - name: info ref: "/options/info" - name: chains