From a0b533d91c43e189b6e3779ef52606307c046271 Mon Sep 17 00:00:00 2001 From: didier Date: Thu, 6 May 2021 00:10:09 +0100 Subject: [PATCH 01/27] add government menu, in particular congress data --- .../government/gov_controller.py | 136 ++++++ .../government/quiverquant_model.py | 36 ++ .../government/quiverquant_view.py | 392 ++++++++++++++++++ gamestonk_terminal/main_helper.py | 1 + terminal.py | 5 + 5 files changed, 570 insertions(+) create mode 100644 gamestonk_terminal/government/gov_controller.py create mode 100644 gamestonk_terminal/government/quiverquant_model.py create mode 100644 gamestonk_terminal/government/quiverquant_view.py diff --git a/gamestonk_terminal/government/gov_controller.py b/gamestonk_terminal/government/gov_controller.py new file mode 100644 index 00000000000..2fe42da2a57 --- /dev/null +++ b/gamestonk_terminal/government/gov_controller.py @@ -0,0 +1,136 @@ +"""Government Controller Module""" +__docformat__ = "numpy" + +import argparse +from typing import List +from datetime import datetime +import pandas as pd +from matplotlib import pyplot as plt +from gamestonk_terminal import feature_flags as gtff +from gamestonk_terminal.helper_funcs import get_flair +from gamestonk_terminal.menu import session +from prompt_toolkit.completion import NestedCompleter +from gamestonk_terminal.government import quiverquant_view + + +class GovController: + """Gov Controller class""" + + # Command choices + CHOICES = [ + "help", + "q", + "quit", + "last_congress", + "buy_congress", + "sell_congress", + "congress", + ] + + def __init__( + self, + ticker: str, + ): + """Constructor""" + self.ticker = ticker + self.gov_parser = argparse.ArgumentParser(add_help=False, prog="gov") + self.gov_parser.add_argument( + "cmd", + choices=self.CHOICES, + ) + + @staticmethod + def print_help(self): + """Print help""" + + print("\nExploratory Data Analysis:") + print(" help show this comparison analysis menu again") + print(" q quit this menu, and shows back to main menu") + print(" quit quit to abandon program") + print("") + print("Explore:") + print(" last_congress last congress trading") + print(" buy_congress top buy congress tickers") + print(" sell_congress top sell congress tickers") + print("") + if self.ticker: + print(f"Ticker: {self.ticker}") + print(" congress congress trades on the ticker") + print("") + return + + def switch(self, an_input: str): + """Process and dispatch input + + Returns + ------- + True, False or None + False - quit the menu + True - quit the program + None - continue in the menu + """ + (known_args, other_args) = self.gov_parser.parse_known_args(an_input.split()) + + return getattr( + self, "call_" + known_args.cmd, lambda: "Command not recognized!" + )(other_args) + + def call_help(self, _): + """Process Help command""" + self.print_help(self) + + def call_q(self, _): + """Process Q command - quit the menu""" + return False + + def call_quit(self, _): + """Process Quit command - quit the program""" + return True + + def call_last_congress(self, other_args: List[str]): + """Process last_congress command""" + quiverquant_view.last_congress(other_args) + + def call_buy_congress(self, other_args: List[str]): + """Process buy_congress command""" + quiverquant_view.buy_congress(other_args) + + def call_sell_congress(self, other_args: List[str]): + """Process sell_congress command""" + quiverquant_view.sell_congress(other_args) + + def call_congress(self, other_args: List[str]): + """Process congress command""" + quiverquant_view.congress(other_args, self.ticker) + + +def menu(ticker: str): + """Government Menu""" + + gov_controller = GovController(ticker) + gov_controller.call_help(None) + + while True: + # Get input command from user + if session and gtff.USE_PROMPT_TOOLKIT: + completer = NestedCompleter.from_nested_dict( + {c: None for c in gov_controller.CHOICES} + ) + an_input = session.prompt( + f"{get_flair()} (gov)> ", + completer=completer, + ) + else: + an_input = input(f"{get_flair()} (gov)> ") + + try: + plt.close("all") + + process_input = gov_controller.switch(an_input) + + if process_input is not None: + return process_input + + except SystemExit: + print("The command selected doesn't exist\n") + continue diff --git a/gamestonk_terminal/government/quiverquant_model.py b/gamestonk_terminal/government/quiverquant_model.py new file mode 100644 index 00000000000..3bf5527108a --- /dev/null +++ b/gamestonk_terminal/government/quiverquant_model.py @@ -0,0 +1,36 @@ +import requests +import pandas as pd + +# Provided by Quiverquant guys to GST users +API_QUIVERQUANT_KEY = "5cd2a65e96d0486efbe926a7cdbc1e8d8ab6c7b3" + + +def get_congress_trading(ticker: str = "") -> pd.DataFrame: + """Returns the most recent transactions by members of U.S. Congress + + Parameters + ---------- + ticker : str + Ticker to get congress trading data from + + Returns + ------- + pd.DataFrame + Most recent transactions by members of U.S. Congress + """ + + if ticker: + url = f"https://api.quiverquant.com/beta/historical/congresstrading/{ticker}" + else: + url = "https://api.quiverquant.com/beta/live/congresstrading" + + headers = { + "accept": "application/json", + "X-CSRFToken": "TyTJwjuEC7VV7mOqZ622haRaaUr0x0Ng4nrwSRFKQs7vdoBcJlK9qjAS69ghzhFu", + "Authorization": f"Token {API_QUIVERQUANT_KEY}", + } + response = requests.get(url, headers=headers) + if response.status_code == 200: + return pd.DataFrame(response.json()) + + return pd.DataFrame() diff --git a/gamestonk_terminal/government/quiverquant_view.py b/gamestonk_terminal/government/quiverquant_view.py new file mode 100644 index 00000000000..f61dc32a3f8 --- /dev/null +++ b/gamestonk_terminal/government/quiverquant_view.py @@ -0,0 +1,392 @@ +import argparse +from typing import List +import pandas as pd +from datetime import datetime, timedelta +from gamestonk_terminal.government import quiverquant_model +from matplotlib import pyplot as plt +from gamestonk_terminal.helper_funcs import ( + parse_known_args_and_warn, + check_positive, + plot_autoscale, +) +from gamestonk_terminal.config_plot import PLOT_DPI +from gamestonk_terminal import feature_flags as gtff + + +def last_congress(other_args: List[str]): + """Last congress trading + + Parameters + ---------- + other_args : List[str] + Command line arguments to be processed with argparse + """ + parser = argparse.ArgumentParser( + add_help=False, + prog="last_congress", + description=""" + Last congress trading. [Source: www.quiverquant.com] + """, + ) + parser.add_argument( + "-p", + "--past_transactions_days", + action="store", + dest="past_transactions_days", + type=check_positive, + default=3, + help="Past transaction days", + ) + + try: + if other_args: + if "-" not in other_args[0]: + other_args.insert(0, "-p") + + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + + df_congress = quiverquant_model.get_congress_trading() + + if df_congress.empty: + print("No congress trading data found\n") + return + + df_congress = df_congress.sort_values("TransactionDate", ascending=False) + + df_congress = df_congress[ + df_congress["TransactionDate"].isin( + df_congress["TransactionDate"].unique()[ + : ns_parser.past_transactions_days + ] + ) + ] + + df_congress = df_congress[ + [ + "TransactionDate", + "Ticker", + "Representative", + "Transaction", + "House", + "Range", + "ReportDate", + ] + ].rename( + columns={"TransactionDate": "Transaction Date", "ReportDate": "Report Date"} + ) + + print(df_congress.to_string(index=False)) + print("") + + except Exception as e: + print(e, "\n") + + +def buy_congress(other_args: List[str]): + """Top buy congress trading + + Parameters + ---------- + other_args : List[str] + Command line arguments to be processed with argparse + """ + parser = argparse.ArgumentParser( + add_help=False, + prog="buy_congress", + description=""" + Top buy congress trading. [Source: www.quiverquant.com] + """, + ) + parser.add_argument( + "-p", + "--past_transactions_months", + action="store", + dest="past_transactions_months", + type=check_positive, + default=6, + help="Past transaction months", + ) + parser.add_argument( + "-t", + "--top", + action="store", + dest="top_num", + type=check_positive, + default=10, + help="Number of top tickers", + ) + + try: + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + + df_congress = quiverquant_model.get_congress_trading() + + if df_congress.empty: + print("No congress trading data found\n") + return + + df_congress = df_congress.sort_values("TransactionDate", ascending=False) + + start_date = datetime.now() - timedelta( + days=ns_parser.past_transactions_months * 30 + ) + + df_congress["TransactionDate"] = pd.to_datetime(df_congress["TransactionDate"]) + + df_congress = df_congress[df_congress["TransactionDate"] > start_date].dropna() + + df_congress["min"] = df_congress["Range"].apply( + lambda x: x.split("-")[0].strip("$").replace(",", "").strip() + ) + df_congress["max"] = df_congress["Range"].apply( + lambda x: x.split("-")[1].replace(",", "").strip().strip("$") + if "-" in x + else x.strip("$").replace(",", "") + ) + + df_congress["lower"] = df_congress[["min", "max", "Transaction"]].apply( + lambda x: float(x["min"]) + if x["Transaction"] == "Purchase" + else -float(x["max"]), + axis=1, + ) + df_congress["upper"] = df_congress[["min", "max", "Transaction"]].apply( + lambda x: float(x["max"]) + if x["Transaction"] == "Purchase" + else -float(x["min"]), + axis=1, + ) + + df_congress = df_congress.sort_values("TransactionDate", ascending=True) + + print( + f"Top {ns_parser.top_num} most sold stocks since last {ns_parser.past_transactions_months} months in the worst case scenario" + ) + print( + df_congress.groupby("Ticker")["lower"] + .sum() + .sort_values() + .abs() + .head(n=ns_parser.top_num) + .to_string(header=False) + ) + print("") + + except Exception as e: + print(e, "\n") + + +def sell_congress(other_args: List[str]): + """Top sell congress trading + + Parameters + ---------- + other_args : List[str] + Command line arguments to be processed with argparse + """ + parser = argparse.ArgumentParser( + add_help=False, + prog="sell_congress", + description=""" + Top sell congress trading. [Source: www.quiverquant.com] + """, + ) + parser.add_argument( + "-p", + "--past_transactions_months", + action="store", + dest="past_transactions_months", + type=check_positive, + default=6, + help="Past transaction months", + ) + parser.add_argument( + "-t", + "--top", + action="store", + dest="top_num", + type=check_positive, + default=10, + help="Number of top tickers", + ) + + try: + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + + df_congress = quiverquant_model.get_congress_trading() + + if df_congress.empty: + print("No congress trading data found\n") + return + + df_congress = df_congress.sort_values("TransactionDate", ascending=False) + + start_date = datetime.now() - timedelta( + days=ns_parser.past_transactions_months * 30 + ) + + df_congress["TransactionDate"] = pd.to_datetime(df_congress["TransactionDate"]) + + df_congress = df_congress[df_congress["TransactionDate"] > start_date].dropna() + + df_congress["min"] = df_congress["Range"].apply( + lambda x: x.split("-")[0].strip("$").replace(",", "").strip() + ) + df_congress["max"] = df_congress["Range"].apply( + lambda x: x.split("-")[1].replace(",", "").strip().strip("$") + if "-" in x + else x.strip("$").replace(",", "") + ) + + df_congress["lower"] = df_congress[["min", "max", "Transaction"]].apply( + lambda x: float(x["min"]) + if x["Transaction"] == "Purchase" + else -float(x["max"]), + axis=1, + ) + df_congress["upper"] = df_congress[["min", "max", "Transaction"]].apply( + lambda x: float(x["max"]) + if x["Transaction"] == "Purchase" + else -float(x["min"]), + axis=1, + ) + + df_congress = df_congress.sort_values("TransactionDate", ascending=True) + + print( + f"Top {ns_parser.top_num} most sold stocks since last {ns_parser.past_transactions_months} months in the worst case scenario" + ) + print( + df_congress.groupby("Ticker")["upper"] + .sum() + .sort_values(ascending=False) + .head(n=ns_parser.top_num) + .to_string(header=False) + ) + print("") + + except Exception as e: + print(e, "\n") + + +def plot_congress(congress: pd.DataFrame, ticker: str): + """Plot congress trading + + Parameters + ---------- + other_args : List[str] + Command line arguments to be processed with argparse + ticker: str + Ticker to plot congress trading + """ + plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI) + + plt.gca().fill_between( + congress["TransactionDate"].unique(), + congress.groupby("TransactionDate")["lower"].sum().values / 1000, + congress.groupby("TransactionDate")["upper"].sum().values / 1000, + ) + + plt.xlim( + [congress["TransactionDate"].values[0], congress["TransactionDate"].values[-1]] + ) + plt.grid() + plt.title(f"Congress trading on {ticker}") + plt.xlabel("Date") + plt.ylabel("Amount [1k $]") + + if gtff.USE_ION: + plt.ion() + + plt.show() + + +def congress(other_args: List[str], ticker: str): + """Congress trading + + Parameters + ---------- + other_args : List[str] + Command line arguments to be processed with argparse + ticker: str + Ticker to get congress trading data from + """ + parser = argparse.ArgumentParser( + add_help=False, + prog="congress", + description=""" + Congress trading. [Source: www.quiverquant.com] + """, + ) + parser.add_argument( + "-p", + "--past_transactions_months", + action="store", + dest="past_transactions_months", + type=check_positive, + default=6, + help="Past transaction months", + ) + + try: + + if other_args: + if "-" not in other_args[0]: + other_args.insert(0, "-p") + + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + + df_congress = quiverquant_model.get_congress_trading(ticker) + + if df_congress.empty: + print("No congress trading data found\n") + return + + df_congress = df_congress.sort_values("TransactionDate", ascending=False) + + start_date = datetime.now() - timedelta( + days=ns_parser.past_transactions_months * 30 + ) + + df_congress["TransactionDate"] = pd.to_datetime(df_congress["TransactionDate"]) + + df_congress = df_congress[df_congress["TransactionDate"] > start_date] + + df_congress["min"] = df_congress["Range"].apply( + lambda x: x.split("-")[0].strip("$").replace(",", "").strip() + ) + df_congress["max"] = df_congress["Range"].apply( + lambda x: x.split("-")[1].replace(",", "").strip().strip("$") + if "-" in x + else x.strip("$").replace(",", "") + ) + + df_congress["lower"] = df_congress[["min", "max", "Transaction"]].apply( + lambda x: int(x["min"]) + if x["Transaction"] == "Purchase" + else -int(x["max"]), + axis=1, + ) + df_congress["upper"] = df_congress[["min", "max", "Transaction"]].apply( + lambda x: int(x["max"]) + if x["Transaction"] == "Purchase" + else -int(x["min"]), + axis=1, + ) + + df_congress = df_congress.sort_values("TransactionDate", ascending=True) + + plot_congress(df_congress, ticker) + + print("") + + except Exception as e: + print(e, "\n") diff --git a/gamestonk_terminal/main_helper.py b/gamestonk_terminal/main_helper.py index 30ef54f0af0..e1d14aae445 100644 --- a/gamestonk_terminal/main_helper.py +++ b/gamestonk_terminal/main_helper.py @@ -65,6 +65,7 @@ def print_help(s_ticker, s_start, s_interval, b_is_market_open): print( " > po portfolio optimization, \t optimal portfolio weights from pyportfolioopt" ) + print(" > gov government menu, \t\t congress, senate, house trading") print(" > fx forex menu, \t\t\t forex support through Oanda") print(" > rc resource collection, \t\t e.g. hf letters") diff --git a/terminal.py b/terminal.py index 69e6e6f5919..03189c3b1fc 100644 --- a/terminal.py +++ b/terminal.py @@ -43,6 +43,7 @@ from gamestonk_terminal.forex import fx_controller from gamestonk_terminal.backtesting import bt_controller from gamestonk_terminal.resource_collection import rc_controller from gamestonk_terminal.research import res_controller +from gamestonk_terminal.government import gov_controller # pylint: disable=too-many-statements,too-many-branches @@ -99,6 +100,7 @@ def main(): "po", "fx", "rc", + "gov", ] menu_parser.add_argument("opt", choices=choices) @@ -378,6 +380,9 @@ def main(): elif ns_known_args.opt == "rc": b_quit = rc_controller.menu() + elif ns_known_args.opt == "gov": + b_quit = gov_controller.menu(s_ticker) + else: print("Shouldn't see this command!") continue From b9e8aca947b6e11aca38b6e2c52074b73a8664bc Mon Sep 17 00:00:00 2001 From: didier Date: Thu, 6 May 2021 00:14:17 +0100 Subject: [PATCH 02/27] fix flake8 --- gamestonk_terminal/government/gov_controller.py | 2 -- gamestonk_terminal/government/quiverquant_view.py | 6 ++++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gamestonk_terminal/government/gov_controller.py b/gamestonk_terminal/government/gov_controller.py index 2fe42da2a57..5084cefb981 100644 --- a/gamestonk_terminal/government/gov_controller.py +++ b/gamestonk_terminal/government/gov_controller.py @@ -3,8 +3,6 @@ __docformat__ = "numpy" import argparse from typing import List -from datetime import datetime -import pandas as pd from matplotlib import pyplot as plt from gamestonk_terminal import feature_flags as gtff from gamestonk_terminal.helper_funcs import get_flair diff --git a/gamestonk_terminal/government/quiverquant_view.py b/gamestonk_terminal/government/quiverquant_view.py index f61dc32a3f8..259d30886d3 100644 --- a/gamestonk_terminal/government/quiverquant_view.py +++ b/gamestonk_terminal/government/quiverquant_view.py @@ -164,7 +164,8 @@ def buy_congress(other_args: List[str]): df_congress = df_congress.sort_values("TransactionDate", ascending=True) print( - f"Top {ns_parser.top_num} most sold stocks since last {ns_parser.past_transactions_months} months in the worst case scenario" + f"Top {ns_parser.top_num} most sold stocks since last {ns_parser.past_transactions_months} " + "months in the worst case scenario" ) print( df_congress.groupby("Ticker")["lower"] @@ -260,7 +261,8 @@ def sell_congress(other_args: List[str]): df_congress = df_congress.sort_values("TransactionDate", ascending=True) print( - f"Top {ns_parser.top_num} most sold stocks since last {ns_parser.past_transactions_months} months in the worst case scenario" + f"Top {ns_parser.top_num} most sold stocks since last {ns_parser.past_transactions_months} " + "months in the worst case scenario" ) print( df_congress.groupby("Ticker")["upper"] From 2a4746bddd68988a86bf958ec81df47c5e07b811 Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Thu, 6 May 2021 19:28:07 +0100 Subject: [PATCH 03/27] gov readme --- gamestonk_terminal/government/README.md | 63 +++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 gamestonk_terminal/government/README.md diff --git a/gamestonk_terminal/government/README.md b/gamestonk_terminal/government/README.md new file mode 100644 index 00000000000..c6e5f7a11b9 --- /dev/null +++ b/gamestonk_terminal/government/README.md @@ -0,0 +1,63 @@ +# GOVERNMENT + +This menu aims to get some insights regarding government data, and the usage of the following commands along with an example will be exploited below. +This data has been provided by [quiverquant](https://www.quiverquant.com). + +* [last_congress](#last_congress) + * last congress trading +* [buy_congress](#buy_congress) + * top buy congress tickers +* [sell_congress](#sell_congress) + * top sell congress tickers + +#### WITH TICKER PROVIDED + +* [congress](#congress) + * congress trades on the ticker + + +## last_congress +```text +usage: last_congress [-p PAST_TRANSACTIONS_DAYS] +``` +Last congress trading. [Source: www.quiverquant.com] + +* -p : Past transaction days. Default: 3. + +last_congress + + +## buy_congress +```text +usage: buy_congress [-p PAST_TRANSACTIONS_MONTHS] [-t TOP_NUM] +``` +Top buy congress trading. [Source: www.quiverquant.com] + +* -p : Past transaction months. Default: 6. +* -t : Number of top tickers. Default: 10. + +buy_congress + + +## sell_congress +```text +usage: sell_congress [-p PAST_TRANSACTIONS_MONTHS] [-t TOP_NUM] +``` +Top sell congress trading. [Source: www.quiverquant.com] + +* -p : Past transaction months. Default: 6. +* -t : Number of top tickers. Default: 10. + +sell_congress + + +## congress +```text +usage: congress [-p PAST_TRANSACTIONS_MONTHS] +``` +Congress trading. [Source: www.quiverquant.com] + +* -p : Past transaction months. Default: 6. + +![congress](https://user-images.githubusercontent.com/25267873/117347548-280f6f80-aea1-11eb-8ee7-b511cdf863e1.png) + From 581913ba8cbb8c9c35d7204a35fab451b5e195e1 Mon Sep 17 00:00:00 2001 From: didier Date: Thu, 6 May 2021 19:29:48 +0100 Subject: [PATCH 04/27] improve xlabel of dates --- gamestonk_terminal/government/quiverquant_view.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gamestonk_terminal/government/quiverquant_view.py b/gamestonk_terminal/government/quiverquant_view.py index 259d30886d3..4ffb6f757ea 100644 --- a/gamestonk_terminal/government/quiverquant_view.py +++ b/gamestonk_terminal/government/quiverquant_view.py @@ -4,6 +4,7 @@ import pandas as pd from datetime import datetime, timedelta from gamestonk_terminal.government import quiverquant_model from matplotlib import pyplot as plt +import matplotlib.dates as mdates from gamestonk_terminal.helper_funcs import ( parse_known_args_and_warn, check_positive, @@ -302,6 +303,8 @@ def plot_congress(congress: pd.DataFrame, ticker: str): plt.title(f"Congress trading on {ticker}") plt.xlabel("Date") plt.ylabel("Amount [1k $]") + plt.gca().xaxis.set_major_formatter(mdates.DateFormatter("%Y/%m/%d")) + plt.gcf().autofmt_xdate() if gtff.USE_ION: plt.ion() From 99d15606574f7a93b9b7ffeaa84d6865e677f3c3 Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Thu, 6 May 2021 19:35:38 +0100 Subject: [PATCH 05/27] Update README.md --- gamestonk_terminal/README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/gamestonk_terminal/README.md b/gamestonk_terminal/README.md index 8a5f6c790ae..f75f52a3334 100644 --- a/gamestonk_terminal/README.md +++ b/gamestonk_terminal/README.md @@ -20,6 +20,7 @@ * [Forex](#Forex-) * [Backtesting](#Backtesting-) * [Resource Collection](#Resource-Collection-) +* [Government](#Government-) ## Main @@ -425,3 +426,14 @@ Command|Website   +## Government [»](government/README.md) +Command|Website +----|---- +`last_congress` |last congress trading +`buy_congress` |top buy congress tickers +`sell_congress` |top sell congress tickers +with ticker provided | +`congress` | congress trades on the ticker + +  + From d86a7592ee52a93545f4a91d3794054e596f6150 Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Thu, 6 May 2021 19:37:16 +0100 Subject: [PATCH 06/27] Update ROADMAP.md --- ROADMAP.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ROADMAP.md b/ROADMAP.md index f9fa2be7b1e..e85e9f418dc 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -23,6 +23,7 @@ * [Forex](#Forex) * [Backtesting](#Backtesting) * [Resource Collection](#Resource-Collection) +* [Government](#Government) ## Additional @@ -246,6 +247,13 @@ ___ --- +## Government +* [x] Add congress data (@didier) [PR #438](https://github.com/DidierRLopes/GamestonkTerminal/pull/438) + +**NEXT** + +--- + ## Backend **NEXT** From 2944a8dd5f71d654ebf5bb1cb841ebf0d3441ffe Mon Sep 17 00:00:00 2001 From: didier Date: Thu, 6 May 2021 20:43:59 +0100 Subject: [PATCH 07/27] Allow to see screener filters with: view filter_name --- .../screener/screener_controller.py | 77 ++++++++++++++----- 1 file changed, 57 insertions(+), 20 deletions(-) diff --git a/gamestonk_terminal/screener/screener_controller.py b/gamestonk_terminal/screener/screener_controller.py index ae7a07ab050..13a600f6d9a 100644 --- a/gamestonk_terminal/screener/screener_controller.py +++ b/gamestonk_terminal/screener/screener_controller.py @@ -3,6 +3,7 @@ __docformat__ = "numpy" import os import argparse +import configparser from typing import List import matplotlib.pyplot as plt from gamestonk_terminal import feature_flags as gtff @@ -86,37 +87,73 @@ class ScreenerController: prog="view", description="""View available presets under presets folder.""", ) + parser.add_argument( + "-p", + "--preset", + action="store", + dest="preset", + type=str, + help="View specific preset", + default="", + choices=[ + preset.split(".")[0] + for preset in os.listdir("gamestonk_terminal/screener/presets") + if preset[-4:] == ".ini" + ], + ) try: + if other_args: + if "-" not in other_args[0]: + other_args.insert(0, "-p") ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return - presets = [ - preset.split(".")[0] - for preset in os.listdir("gamestonk_terminal/screener/presets") - if preset[-4:] == ".ini" - ] + if ns_parser.preset: + preset_filter = configparser.RawConfigParser() + preset_filter.optionxform = str # type: ignore + preset_filter.read( + "gamestonk_terminal/screener/presets/" + ns_parser.preset + ".ini" + ) - for preset in presets: - with open( - "gamestonk_terminal/screener/presets/" + preset + ".ini", - encoding="utf8", - ) as f: - description = "" - for line in f: - if "[General]" == line.strip(): - break - description += line.strip() - print(f"\nPRESET: {preset}") - print(description.split("Description: ")[1].replace("#", "")) + filters_headers = ["General", "Descriptive", "Fundamental", "Technical"] + + print("") + for filter_header in filters_headers: + print(f" - {filter_header} -") + d_filters = {**preset_filter[filter_header]} + d_filters = dict((k, v) for k, v in d_filters.items() if v) + if d_filters: + max_len = len(max(d_filters, key=len)) + for key, value in d_filters.items(): + print(f"{key}{(max_len-len(key))*' '}: {value}") + print("") + + else: + presets = [ + preset.split(".")[0] + for preset in os.listdir("gamestonk_terminal/screener/presets") + if preset[-4:] == ".ini" + ] + + for preset in presets: + with open( + "gamestonk_terminal/screener/presets/" + preset + ".ini", + encoding="utf8", + ) as f: + description = "" + for line in f: + if "[General]" == line.strip(): + break + description += line.strip() + print(f"\nPRESET: {preset}") + print(description.split("Description: ")[1].replace("#", "")) + print("") except Exception as e: print(e) - print("") - return - @staticmethod def set_preset(self, other_args: List[str]): """Set preset""" From 14898e5333efb0fa078ea2335de94d15d58fd42c Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Thu, 6 May 2021 20:47:16 +0100 Subject: [PATCH 08/27] Update README.md --- gamestonk_terminal/screener/README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/gamestonk_terminal/screener/README.md b/gamestonk_terminal/screener/README.md index af2a3feeab2..c4530de1335 100644 --- a/gamestonk_terminal/screener/README.md +++ b/gamestonk_terminal/screener/README.md @@ -29,12 +29,14 @@ This menu aims to filter stocks based on pre-specified preset filters, and the u ## view ```text -view +usage: view [-p {template,sexy_year}] ``` - View available presets under presets folder. -Captura de ecrã 2021-04-05, às 20 13 28 +* -p : View specific preset filters. + +Captura de ecrã 2021-05-06, às 20 46 41 + ## set From ee1d9f8543b55917fcb3687037b40c25690ec457 Mon Sep 17 00:00:00 2001 From: didier Date: Thu, 6 May 2021 20:59:14 +0100 Subject: [PATCH 09/27] fix pyupgrade --- gamestonk_terminal/screener/screener_controller.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gamestonk_terminal/screener/screener_controller.py b/gamestonk_terminal/screener/screener_controller.py index 13a600f6d9a..9ca084e180b 100644 --- a/gamestonk_terminal/screener/screener_controller.py +++ b/gamestonk_terminal/screener/screener_controller.py @@ -123,7 +123,7 @@ class ScreenerController: for filter_header in filters_headers: print(f" - {filter_header} -") d_filters = {**preset_filter[filter_header]} - d_filters = dict((k, v) for k, v in d_filters.items() if v) + d_filters = {k: v for k, v in d_filters.items() if v} if d_filters: max_len = len(max(d_filters, key=len)) for key, value in d_filters.items(): From f14fa8e6af5722fd60aa3c301ba392d9d936a507 Mon Sep 17 00:00:00 2001 From: didier Date: Thu, 6 May 2021 23:14:49 +0100 Subject: [PATCH 10/27] Get similar companies on comparison analysis from finnhub source as well --- .../comparison_analysis/ca_controller.py | 53 +++++++++++++------ 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/gamestonk_terminal/comparison_analysis/ca_controller.py b/gamestonk_terminal/comparison_analysis/ca_controller.py index 3772807b71a..74fda2f90c9 100644 --- a/gamestonk_terminal/comparison_analysis/ca_controller.py +++ b/gamestonk_terminal/comparison_analysis/ca_controller.py @@ -136,25 +136,25 @@ class ComparisonAnalysisController: other_args : List[str] argparse other args """ - parser = argparse.ArgumentParser( add_help=False, prog="get", description="""Get similar companies to compare with.""", ) parser.add_argument( - "-p", - "--polygon", - action="store_true", - default=False, - dest="b_polygon", - help="Polygon data source flag.", + "-s", + "--source", + action="store", + default="finviz", + dest="source", + choices=["polygon", "finnhub", "finviz"], + help="source that provides similar companies", ) - # If polygon source not selected, the user may want to get + # If source is finviz the user may want to get # similar companies based on Industry and Sector only, and not # on the fact that they are based on the same country - if "-p" not in other_args and "--polygon" not in other_args: + if "finviz" in other_args or not other_args: parser.add_argument( "--nocountry", action="store_true", @@ -164,11 +164,15 @@ class ComparisonAnalysisController: ) try: + if other_args: + if "-" not in other_args[0]: + other_args.insert(0, "-s") + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return - if ns_parser.b_polygon: + if ns_parser.source == "polygon": result = requests.get( f"https://api.polygon.io/v1/meta/symbols/{self.ticker.upper()}/company?&apiKey={cfg.API_POLYGON_KEY}" ) @@ -179,6 +183,20 @@ class ComparisonAnalysisController: else: print(result.json()["error"]) + elif ns_parser.source == "finnhub": + result = requests.get( + f"https://finnhub.io/api/v1/stock/peers?symbol={self.ticker}&token={cfg.API_FINNHUB_KEY}" + ) + + if result.status_code == 200: + d_peers = result.json() + + if d_peers: + self.similar = d_peers + self.user = "Finnhub" + else: + print("Similar companies not found.") + else: if ns_parser.b_no_country: compare_list = ["Sector", "Industry"] @@ -192,17 +210,18 @@ class ComparisonAnalysisController: ) self.user = "Finviz" - if self.similar: - print(f"\n[{self.user}] Similar Companies: {', '.join(self.similar)}") + if self.ticker.upper() in self.similar: + self.similar.remove(self.ticker.upper()) if len(self.similar) > 10: - print( - "\nThe limit of stocks to compare with are 10. Hence, 10 random similar stocks will be displayed.", - "\nThe selected list will be:", - ) random.shuffle(self.similar) self.similar = sorted(self.similar[:10]) - print(", ".join(self.similar)) + print( + "The limit of stocks to compare with are 10. Hence, 10 random similar stocks will be displayed.\n", + ) + + if self.similar: + print(f"[{self.user}] Similar Companies: {', '.join(self.similar)}") except Exception as e: print(e) From dbc5b33db892db1f85798325a8d36be88b70243f Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Thu, 6 May 2021 23:22:59 +0100 Subject: [PATCH 11/27] Update get similar companies --- gamestonk_terminal/comparison_analysis/README.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/gamestonk_terminal/comparison_analysis/README.md b/gamestonk_terminal/comparison_analysis/README.md index c60dfd305d0..3f62d9dbafb 100644 --- a/gamestonk_terminal/comparison_analysis/README.md +++ b/gamestonk_terminal/comparison_analysis/README.md @@ -3,7 +3,7 @@ This menu aims to compare a pre-loaded stock with similar companies, and the usage of the following commands along with an example will be exploited below. * [get](#get) - * get similar companies [Finviz or Polygon] + * get similar companies [Finviz, Finnhub, Polygon] * [select](#select) * select similar companies * [historical](#historical) @@ -39,13 +39,16 @@ This menu aims to compare a pre-loaded stock with similar companies, and the usa ## get ```text -get [-p] [--nocountry] +get [-s {polygon,finnhub,finviz}] [--nocountry] ``` Get similar companies to compare with. [Source: Finviz by default] -* -p : get similar companies using polygon source. Default False, i.e. using Finviz source. -* --nocountry : when getting similar companies from Finviz, we filter by same Industry, Sector and Country. However, if we don't want to filter by same country we can set this flag. For this flag to work, the `-p` flag can't be selected +* -s : source that provides similar companies. Default: polygon. +* --nocountry : when getting similar companies from Finviz, we filter by same Industry, Sector and Country. However, if we don't want to filter by same country we can set this flag. For this flag to work, the `-p` flag can't be selected. + +Captura de ecrã 2021-05-06, às 23 09 22 + ## select From f6c5613d6036ec002d8e6d9ebe2ca4bfd70942f2 Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Thu, 6 May 2021 23:24:02 +0100 Subject: [PATCH 12/27] Update README.md --- gamestonk_terminal/comparison_analysis/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gamestonk_terminal/comparison_analysis/README.md b/gamestonk_terminal/comparison_analysis/README.md index 3f62d9dbafb..487f11df011 100644 --- a/gamestonk_terminal/comparison_analysis/README.md +++ b/gamestonk_terminal/comparison_analysis/README.md @@ -33,7 +33,7 @@ This menu aims to compare a pre-loaded stock with similar companies, and the usa * [technical](#technical) * brief technical (e.g. Beta, SMA50, 52W Low, RSI, Change) [Finviz] * [> po](portfolio_optimization/README.md) - * portfolio optimization for selected tickers + * **portfolio optimization for selected tickers** ## get From dac50ddd96caa893fba9d68b757e3a5c8cd8256f Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Thu, 6 May 2021 23:24:33 +0100 Subject: [PATCH 13/27] Update README.md --- gamestonk_terminal/screener/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gamestonk_terminal/screener/README.md b/gamestonk_terminal/screener/README.md index c4530de1335..23ede646ac7 100644 --- a/gamestonk_terminal/screener/README.md +++ b/gamestonk_terminal/screener/README.md @@ -24,7 +24,7 @@ This menu aims to filter stocks based on pre-specified preset filters, and the u * [signals](#signals) * view filter signals (e.g. -s top_gainers) [Finviz] * [> po](portfolio_optimization/README.md) - * portfolio optimization for last screened tickers + * **portfolio optimization for last screened tickers** ## view From 2bed53c6f89a5ef702de8463b22214861e241d81 Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Thu, 6 May 2021 23:30:43 +0100 Subject: [PATCH 14/27] Update README.md --- gamestonk_terminal/portfolio_optimization/README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/gamestonk_terminal/portfolio_optimization/README.md b/gamestonk_terminal/portfolio_optimization/README.md index 3e9e44d4603..9aa9f6551a5 100644 --- a/gamestonk_terminal/portfolio_optimization/README.md +++ b/gamestonk_terminal/portfolio_optimization/README.md @@ -1,4 +1,4 @@ -# Portfolio Optimization +# PORTFOLIO OPTIMIZATION This menu aims to optimize a portfolio of pre-loaded stocks, and the usage of the following commands along with an example will be exploited below. @@ -6,6 +6,9 @@ This menu aims to optimize a portfolio of pre-loaded stocks, and the usage of th * add ticker to optimize * [select](#select) * overwrite current tickers with new tickers + +[Optimization](#Optimization) + * [equal](#equal) * equally weighted * [mktcap](#mktcap) @@ -30,6 +33,10 @@ This menu aims to optimize a portfolio of pre-loaded stocks, and the usage of th * [ef](#ef) * show the efficient frontier +  +* [> ca](comparison_analysis/README.md) + * **comparison analysis for selected tickers** + ### add @@ -53,6 +60,8 @@ Add/Select tickers for portfolio to be optimized. * -t : Tickers to be used in the portfolio to optimize +## Optimization + ### equal ```text From cd62c585d65337b770e04a13170dc3a295078e86 Mon Sep 17 00:00:00 2001 From: didier Date: Thu, 6 May 2021 23:32:29 +0100 Subject: [PATCH 15/27] only show CA menu on PO when more than 1 ticker selected --- gamestonk_terminal/main_helper.py | 2 +- gamestonk_terminal/portfolio_optimization/po_controller.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gamestonk_terminal/main_helper.py b/gamestonk_terminal/main_helper.py index e1d14aae445..0261e231870 100644 --- a/gamestonk_terminal/main_helper.py +++ b/gamestonk_terminal/main_helper.py @@ -101,7 +101,7 @@ def print_help(s_ticker, s_start, s_interval, b_is_market_open): " > ra residuals analysis, \t e.g.: model fit, qqplot, hypothesis test" ) print( - " > op options info , \t e.g.: volume and open interest" + " > op options info, \t e.g.: volume and open interest" ) print("") diff --git a/gamestonk_terminal/portfolio_optimization/po_controller.py b/gamestonk_terminal/portfolio_optimization/po_controller.py index 5940d0b969e..87e6513d98a 100644 --- a/gamestonk_terminal/portfolio_optimization/po_controller.py +++ b/gamestonk_terminal/portfolio_optimization/po_controller.py @@ -79,7 +79,7 @@ class PortfolioOptimization: print("") print(" ef show the efficient frontier") print("") - if tickers: + if len(tickers) > 1: print(" > ca comparison analysis for selected tickers") print("") From d9db1e3dfef8aef30b234806cc3e83e06240c268 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Fri, 7 May 2021 10:13:13 -0700 Subject: [PATCH 16/27] Fix residuals_analysis link and formatting --- gamestonk_terminal/README.md | 131 ++++++++++++++++++++--------------- 1 file changed, 74 insertions(+), 57 deletions(-) diff --git a/gamestonk_terminal/README.md b/gamestonk_terminal/README.md index 8a5f6c790ae..5a8b1d29f4d 100644 --- a/gamestonk_terminal/README.md +++ b/gamestonk_terminal/README.md @@ -1,6 +1,7 @@ # Features 📈 ### Table of contents + * [Discover Stocks](#Discover-Stocks-) * [Behavioural Analysis](#Behavioural-Analysis-) * [Research](#Research-) @@ -24,48 +25,54 @@ ## Main The main menu allows the following commands: + ``` load -t S_TICKER [-s S_START_DATE] [-i {1,5,15,30,60}] ``` - * Load stock ticker to perform analysis on. When the data source is 'yf', an Indian ticker can be loaded by using '.NS' at the end, e.g. 'SBIN.NS'. See available market in https://help.yahoo.com/kb/exchanges-data-providers-yahoo-finance-sln2310.html. - * -s : The starting date (format YYYY-MM-DD) of the stock - * -i : Intraday stock minutes - * --source : Source of historical data. 'yf' and 'av' available. Default 'yf' - * -p : Pre/After market hours. Only works for 'yf' source, and intraday data + +* Load stock ticker to perform analysis on. When the data source is 'yf', an Indian ticker can be loaded by using '.NS' at the end, e.g. 'SBIN.NS'. See available market in . + * -s : The starting date (format YYYY-MM-DD) of the stock + * -i : Intraday stock minutes + * --source : Source of historical data. 'yf' and 'av' available. Default 'yf' + * -p : Pre/After market hours. Only works for 'yf' source, and intraday data **Note:** Until a ticker is loaded, the menu will only show *disc* and *sen* menu, as the others require a ticker being provided. ``` clear ``` - * Clear previously loaded stock ticker. + +* Clear previously loaded stock ticker. ``` view -t S_TICKER [-s S_START_DATE] [-i {1,5,15,30,60}] [--type N_TYPE] ``` - * Visualise historical data of a stock. An alpha_vantage key is necessary. - * -s : The starting date (format YYYY-MM-DD) of the stock - * -i : Intraday stock minutes - * --type : 1234 corresponds to types: 1. open; 2. high; 3.low; 4. close; while 14 corresponds to types: 1.open; 4. close + +* Visualise historical data of a stock. An alpha_vantage key is necessary. + * -s : The starting date (format YYYY-MM-DD) of the stock + * -i : Intraday stock minutes + * --type : 1234 corresponds to types: 1. open; 2. high; 3.low; 4. close; while 14 corresponds to types: 1.open; 4. close ![GNUS](https://user-images.githubusercontent.com/25267873/108925137-f2920e80-7633-11eb-8274-6e3bb6a19592.png) ``` candle ``` - * Visualize candles historical data from the past 6 months, with support and resistance bars, and moving averages of 20 and 50 + +* Visualize candles historical data from the past 6 months, with support and resistance bars, and moving averages of 20 and 50 ![nio](https://user-images.githubusercontent.com/25267873/111053397-4d609e00-845b-11eb-9c94-89b8892a8e81.png) ``` export -f GNUS_data -F csv ``` - * Exports the historical data from this ticker to a file or stdout. - * -f : Name of file to save the historical data exported (stdout if unspecified). Default: stdout. - * -F : Export historical data into following formats: csv, json, excel, clipboard. Default: csv. +* Exports the historical data from this ticker to a file or stdout. + * -f : Name of file to save the historical data exported (stdout if unspecified). Default: stdout. + * -F : Export historical data into following formats: csv, json, excel, clipboard. Default: csv. ## Discover Stocks [»](discovery/README.md) + Command|Description|Source ---|---|--- `ipo` |past and future IPOs |[Finnhub](https://finnhub.io) @@ -86,12 +93,13 @@ Command|Description|Source `spectrum` |spectrum of sectors, industry, country |[Finviz](https://finviz.com) `latest` |latest news |[Seeking Alpha](https://seekingalpha.com/) `trending` |trending news |[Seeking Alpha](https://seekingalpha.com/) -`ratings ` |top ratings updates |[MarketBeat](https://marketbeat.com) +`ratings` |top ratings updates |[MarketBeat](https://marketbeat.com) `darkpool` |dark pool tickers with growing activity |[FINRA](https://www.finra.org)   ## Behavioural Analysis [»](behavioural_analysis/README.md) + Command|Description ----|---- [FinBrain](https://finbrain.tech)| @@ -120,26 +128,27 @@ Command|Description   ## Research [»](research/README.md) + Command|Website ----|---- -`macroaxis` |www.macroaxis.com -`yahoo` |www.finance.yahoo.com -`finviz` |www.finviz.com -`marketwatch` |www.marketwatch.com -`fool` |www.fool.com -`businessinsider` |www.markets.businessinsider.com -`fmp` |www.financialmodelingprep.com -`fidelity` |www.eresearch.fidelity.com -`tradingview` |www.tradingview.com -`marketchameleon` |www.marketchameleon.com -`stockrow` |www.stockrow.com -`barchart` |www.barchart.com -`grufity` |www.grufity.com -`fintel` |www.fintel.com -`zacks` |www.zacks.com -`macrotrends` |www.macrotrends.net -`newsfilter` |www.newsfilter.io -`stockanalysis` |www.stockanalysis.com +`macroaxis` | +`yahoo` | +`finviz` | +`marketwatch` | +`fool` | +`businessinsider` | +`fmp` | +`fidelity` | +`tradingview` | +`marketchameleon` | +`stockrow` | +`barchart` | +`grufity` | +`fintel` | +`zacks` | +`macrotrends` | +`newsfilter` | +`stockanalysis` |   @@ -180,6 +189,7 @@ Command|Description   ## Technical Analysis [»](technical_analysis/README.md) + Command | Description | Sources ------ | ------ | ------ `view` | view historical data and trendlines| [Finviz](https://finviz.com/quote.ashx?t=tsla) @@ -207,6 +217,7 @@ Command | Description | Sources   ## Due Diligence [»](due_diligence/README.md) + Command|Description|Source ------ | --------|---- `news` |latest news of the company |[Finviz](https://finviz.com/) @@ -227,6 +238,7 @@ Command|Description|Source   ## Prediction Techniques [»](prediction_techniques/README.md) + Command|Technique|Sources ------ | ------------|--- `sma` |simple moving average | [Wikipedia](https://en.wikipedia.org/wiki/Moving_average#Simple_moving_average), [Investopedia](https://www.investopedia.com/terms/s/sma.asp) @@ -279,9 +291,9 @@ Command|Description Command|Description ------ | ------------ [coingecko](#https://www.coingecko.com/en)| -`load`| load cryptocurrency data -`view`| view loaded cryptocurrency data -`trend`| view top 7 coins +`load`| load cryptocurrency data +`view`| view loaded cryptocurrency data +`trend`| view top 7 coins [coinmarketcap](#http://coinmarketcap.com)| `top` | view top coins from coinmarketcap [binance](#http://binance.us)| @@ -293,6 +305,7 @@ Command|Description   ## Comparison Analysis [»](comparison_analysis/README.md) + Command|Description|Source ------ | --------|---- `get` |get similar companies |[Polygon](https://polygon.io) @@ -308,6 +321,7 @@ Command|Description|Source   ## Exploratory Data Analysis [»](exploratory_data_analysis/README.md) + Command|Description|Source ------ | --------|---- `get` |get similar companies |[Polygon](https://polygon.io) @@ -322,7 +336,8 @@ Command|Description|Source   -## Residual Analysis [»](residual_analysis/README.md) +## Residual Analysis [»](residuals_analysis/README.md) + Command|Description|Source ------ | --------|---- `pick` |pick one of the model fitting | Supports [ARIMA](https://en.wikipedia.org/wiki/Autoregressive_integrated_moving_average), [Naive](https://en.wikipedia.org/wiki/Forecasting#Naïve_approach) @@ -340,25 +355,27 @@ Command|Description|Source   ## Economy [»](econ/README.md) + Command|Description|Source ------- | -------- | -------- -`events` | economic impact events | https://finnhub.io -`fred` | display customized FRED data | https://fred.stlouisfed.org -`vixcls` | Volatility Index | https://fred.stlouisfed.org -`gdp` | Gross Domestic Product | https://fred.stlouisfed.org -`unrate` | Unemployment Rate | https://fred.stlouisfed.org -`dgs1` | 1-Year Treasury Constant Maturity Rate | https://fred.stlouisfed.org -`dgs5` | 5-Year Treasury Constant Maturity Rate | https://fred.stlouisfed.org -`dgs10` | 10-Year Treasury Constant Maturity Rate | https://fred.stlouisfed.org -`dgs30` | 30-Year Treasury Constant Maturity Rate | https://fred.stlouisfed.org -`mortgage30us` | 30-Year Fixed Rate Mortgage Average | https://fred.stlouisfed.org -`fedfunds` | Effective Federal Funds Rate | https://fred.stlouisfed.org -`aaa` | Moody's Seasoned AAA Corporate Bond Yield | https://fred.stlouisfed.org -`dexcaus` | Canada / U.S. Foreign Exchange Rate (CAD per 1 USD) | https://fred.stlouisfed.org +------ | -------- | -------- +`events` | economic impact events | +`fred` | display customized FRED data | +`vixcls` | Volatility Index | +`gdp` | Gross Domestic Product | +`unrate` | Unemployment Rate | +`dgs1` | 1-Year Treasury Constant Maturity Rate | +`dgs5` | 5-Year Treasury Constant Maturity Rate | +`dgs10` | 10-Year Treasury Constant Maturity Rate | +`dgs30` | 30-Year Treasury Constant Maturity Rate | +`mortgage30us` | 30-Year Fixed Rate Mortgage Average | +`fedfunds` | Effective Federal Funds Rate | +`aaa` | Moody's Seasoned AAA Corporate Bond Yield | +`dexcaus` | Canada / U.S. Foreign Exchange Rate (CAD per 1 USD) |   ## Options [»](options/README.md) + Command|Description|Source ------ | --------|---- `exp` | see/set expiry date @@ -371,6 +388,7 @@ Command|Description|Source   ## Screener [»](screener/README.md) + Command|Description|Source ------ | --------|---- view |view available presets | [presets]((screener/presets/README.md)) @@ -388,6 +406,7 @@ signals |view filter signals (e.g. -s top_gainers)   ## Forex [»](forex/README.md) + Command|Description ------ | -------- summary |display a summary of your account @@ -408,20 +427,18 @@ positionbook |display the positionbook if Oanda provides one for the forex instr   ## Backtesting [»](backtesting/README.md) + Command|Description ------ | -------- `ema` | buy when price exceeds EMA(l) `ema_cross` | buy when EMA(short) > EMA(long) `rsi` | buy when RSI < low and sell when RSI > high - - ## Resource Collection [»](resource_collection/README.md) + Command|Website ----|---- -`hfletters` |https://miltonfmr.com/hedge-fund-letters/ -`learn` |https://moongangcapital.com/free-stock-market-resources/ +`hfletters` | +`learn` |   - - From 60af4052b1b5561251740bf97c1da0059d69ce71 Mon Sep 17 00:00:00 2001 From: didier Date: Fri, 7 May 2021 21:27:47 +0100 Subject: [PATCH 17/27] add search for representative and bar plots --- .../government/quiverquant_view.py | 77 +++++++++++++------ 1 file changed, 54 insertions(+), 23 deletions(-) diff --git a/gamestonk_terminal/government/quiverquant_view.py b/gamestonk_terminal/government/quiverquant_view.py index 4ffb6f757ea..ffe7631b4c0 100644 --- a/gamestonk_terminal/government/quiverquant_view.py +++ b/gamestonk_terminal/government/quiverquant_view.py @@ -35,9 +35,18 @@ def last_congress(other_args: List[str]): action="store", dest="past_transactions_days", type=check_positive, - default=3, + default=5, help="Past transaction days", ) + parser.add_argument( + "-r", + "--representative", + action="store", + dest="representative", + type=str, + default="", + help="Congress representative", + ) try: if other_args: @@ -78,7 +87,21 @@ def last_congress(other_args: List[str]): columns={"TransactionDate": "Transaction Date", "ReportDate": "Report Date"} ) - print(df_congress.to_string(index=False)) + if ns_parser.representative: + df_congress_rep = df_congress[ + df_congress["Representative"].str.split().str[0] + == ns_parser.representative + ] + + if df_congress_rep.empty: + print( + f"No representative {ns_parser.representative} found in the past {ns_parser.past_transactions_days}" + f" days. The following are available: {', '.join(df_congress['Representative'].str.split().str[0].unique())}" + ) + else: + print(df_congress_rep.to_string(index=False)) + else: + print(df_congress.to_string(index=False)) print("") except Exception as e: @@ -164,18 +187,21 @@ def buy_congress(other_args: List[str]): df_congress = df_congress.sort_values("TransactionDate", ascending=True) - print( - f"Top {ns_parser.top_num} most sold stocks since last {ns_parser.past_transactions_months} " - "months in the worst case scenario" - ) - print( - df_congress.groupby("Ticker")["lower"] - .sum() - .sort_values() - .abs() - .head(n=ns_parser.top_num) - .to_string(header=False) + plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI) + + df_congress.groupby("Ticker")["upper"].sum().sort_values(ascending=False).head( + n=ns_parser.top_num + ).plot(kind="bar", rot=0) + plt.ylabel("Amount [$]") + plt.title( + f"Top {ns_parser.top_num} most bought stocks since last {ns_parser.past_transactions_months} " + "months (upper bound)" ) + plt.gcf().axes[0].yaxis.get_major_formatter().set_scientific(False) + if gtff.USE_ION: + plt.ion() + + plt.show() print("") except Exception as e: @@ -261,17 +287,22 @@ def sell_congress(other_args: List[str]): df_congress = df_congress.sort_values("TransactionDate", ascending=True) - print( - f"Top {ns_parser.top_num} most sold stocks since last {ns_parser.past_transactions_months} " - "months in the worst case scenario" - ) - print( - df_congress.groupby("Ticker")["upper"] - .sum() - .sort_values(ascending=False) - .head(n=ns_parser.top_num) - .to_string(header=False) + plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI) + + df_congress.groupby("Ticker")["lower"].sum().sort_values().abs().head( + n=ns_parser.top_num + ).plot(kind="bar", rot=0) + plt.ylabel("Amount [$]") + plt.title( + f"Top {ns_parser.top_num} most sold stocks since last {ns_parser.past_transactions_months} months" + " (upper bound)" ) + plt.gcf().axes[0].yaxis.get_major_formatter().set_scientific(False) + if gtff.USE_ION: + plt.ion() + + plt.show() + print("") except Exception as e: From 6fc58b72267675b141e6610818c67b026176e899 Mon Sep 17 00:00:00 2001 From: didier Date: Fri, 7 May 2021 21:34:03 +0100 Subject: [PATCH 18/27] flake8 line length --- gamestonk_terminal/government/quiverquant_view.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gamestonk_terminal/government/quiverquant_view.py b/gamestonk_terminal/government/quiverquant_view.py index ffe7631b4c0..88f314fa72e 100644 --- a/gamestonk_terminal/government/quiverquant_view.py +++ b/gamestonk_terminal/government/quiverquant_view.py @@ -96,7 +96,8 @@ def last_congress(other_args: List[str]): if df_congress_rep.empty: print( f"No representative {ns_parser.representative} found in the past {ns_parser.past_transactions_days}" - f" days. The following are available: {', '.join(df_congress['Representative'].str.split().str[0].unique())}" + f" days. The following are available: " + f"{', '.join(df_congress['Representative'].str.split().str[0].unique())}" ) else: print(df_congress_rep.to_string(index=False)) From d0a669c6ee70dc4ba96a99ec30081a681d2c028d Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Fri, 7 May 2021 21:38:48 +0100 Subject: [PATCH 19/27] Update README.md --- gamestonk_terminal/government/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/gamestonk_terminal/government/README.md b/gamestonk_terminal/government/README.md index c6e5f7a11b9..4792d404426 100644 --- a/gamestonk_terminal/government/README.md +++ b/gamestonk_terminal/government/README.md @@ -22,7 +22,8 @@ usage: last_congress [-p PAST_TRANSACTIONS_DAYS] ``` Last congress trading. [Source: www.quiverquant.com] -* -p : Past transaction days. Default: 3. +* -p : Past transaction days. Default: 5. +* -r : Congress representative. last_congress @@ -36,7 +37,7 @@ Top buy congress trading. [Source: www.quiverquant.com] * -p : Past transaction months. Default: 6. * -t : Number of top tickers. Default: 10. -buy_congress +![buy](https://user-images.githubusercontent.com/25267873/117505803-8b220480-af7c-11eb-91cb-f51d2b585a17.png) ## sell_congress @@ -48,7 +49,7 @@ Top sell congress trading. [Source: www.quiverquant.com] * -p : Past transaction months. Default: 6. * -t : Number of top tickers. Default: 10. -sell_congress +![sold](https://user-images.githubusercontent.com/25267873/117505806-8c533180-af7c-11eb-8223-f11b08c72675.png) ## congress From 6b5ec102a39f5141a83532778f266e909d2f9f2c Mon Sep 17 00:00:00 2001 From: didier Date: Fri, 7 May 2021 22:05:47 +0100 Subject: [PATCH 20/27] Add finra,edgar,fred,arxiv to resource collection --- .../resource_collection/rc_controller.py | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/gamestonk_terminal/resource_collection/rc_controller.py b/gamestonk_terminal/resource_collection/rc_controller.py index 4ba30e38107..81366356460 100644 --- a/gamestonk_terminal/resource_collection/rc_controller.py +++ b/gamestonk_terminal/resource_collection/rc_controller.py @@ -14,7 +14,17 @@ class ResourceCollectionController: """Resources Controller class""" # Command choices - CHOICES = ["help", "q", "quit", "hfletters", "learn"] + CHOICES = [ + "help", + "q", + "quit", + "hfletters", + "arxiv", + "finra", + "edgar", + "fred", + "learn", + ] def __init__(self): """Constructor""" @@ -34,6 +44,10 @@ class ResourceCollectionController: print(" quit quit to abandon program") print("") print(" hfletters hedge fund letters or reports") + print(" arxiv open-access archive for academic articles") + print(" finra self-regulatory organization") + print(" edgar online public database from SEC") + print(" fred economic research data") print(" learn trading analysis, tips and resources") print("") @@ -73,6 +87,26 @@ class ResourceCollectionController: webbrowser.open("https://miltonfmr.com/hedge-fund-letters/") print("") + def call_arxiv(self, other_args: List[str]): + """Process arxiv command""" + webbrowser.open("https://arxiv.org") + print("") + + def call_finra(self, other_args: List[str]): + """Process finra command""" + webbrowser.open("https://www.finra.org/#/") + print("") + + def call_edgar(self, other_args: List[str]): + """Process edgar command""" + webbrowser.open("https://www.sec.gov/edgar.shtml") + print("") + + def call_fred(self, other_args: List[str]): + """Process fred command""" + webbrowser.open("https://fred.stlouisfed.org") + print("") + def call_learn(self, other_args: List[str]): """Process learn command""" webbrowser.open("https://moongangcapital.com/free-stock-market-resources/") From badb3cde9662ec457cf821173069b2fb3a3bcaaf Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Fri, 7 May 2021 22:08:00 +0100 Subject: [PATCH 21/27] Update README.md --- gamestonk_terminal/README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/gamestonk_terminal/README.md b/gamestonk_terminal/README.md index 08fa4e164df..a1d86689ddb 100644 --- a/gamestonk_terminal/README.md +++ b/gamestonk_terminal/README.md @@ -439,8 +439,12 @@ Command|Description Command|Website ----|---- -`hfletters` | -`learn` | +`hfletters` | +`arxiv` | +`finra` | +`edgar` | +`fred` | +`learn` |   From 6d5ca604e065cbfaefba9ddb4e5cfa3bc0a1fac0 Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Fri, 7 May 2021 22:28:21 +0100 Subject: [PATCH 22/27] Update README.md --- .../resource_collection/README.md | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/gamestonk_terminal/resource_collection/README.md b/gamestonk_terminal/resource_collection/README.md index 80a2ba94580..f065660eee1 100644 --- a/gamestonk_terminal/resource_collection/README.md +++ b/gamestonk_terminal/resource_collection/README.md @@ -4,6 +4,14 @@ This menu aims to store a collection of useful resources that can't be scraped, * [hfletters](#hfletters) * hedge fund letters or reports +* [arxiv](#arxiv) + * open-access archive for academic articles +* [finra](#finra) + * self-regulatory organization +* [edgar](#edgar) + * online public database from SEC +* [fred](#fred) + * economic research data * [learn](#learn) * trading analysis, tips and resources @@ -18,6 +26,42 @@ usage: hfletters Captura de ecrã 2021-05-01, às 21 14 08 +## arxiv + +```text +usage: arxiv +``` + +arxiv + + +## finra + +```text +usage: finra +``` + +finra + + +## edgar + +```text +usage: edgar +``` + +edgar + + +## fred + +```text +usage: fred +``` + +fred + + ## learn ```text From f751811d2da8b54ecf89e6ca23f2f939e81af45d Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Fri, 7 May 2021 22:29:29 +0100 Subject: [PATCH 23/27] Update ROADMAP.md --- ROADMAP.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ROADMAP.md b/ROADMAP.md index e85e9f418dc..9c01e5dcf5f 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -234,6 +234,7 @@ ___ ## Resource Collection * [x] Add hfletters and learn commands to resource collection (@didier) - [PR #427](https://github.com/DidierRLopes/GamestonkTerminal/pull/427) +* [x] Add arxiv, finra, edgar, fred (@didier) - [PR #438](https://github.com/DidierRLopes/GamestonkTerminal/pull/438) **NEXT** From 54f4039bfb6fbb709551dbfda9f9012eae86eac2 Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Fri, 7 May 2021 23:28:00 +0100 Subject: [PATCH 24/27] add donation sector and replace install walkthough --- README.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 5d6ddd3a4e6..a428bb44354 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,7 @@

Table of Contents

  1. About The Project
  2. +
  3. Donation
  4. Getting Started
      @@ -84,11 +85,21 @@ Gamestonk Terminal provides a modern Python-based integrated environment for inv As a modern Python-based environment, GamestonkTerminal opens access to numerous Python data libraries in Data Science (Pandas, Numpy, Scipy, Jupyter), Machine Learning (Pytorch, Tensorflow, Sklearn, Flair), and Data Acquisition (Beautiful Soup, and numerous third-party APIs). +## Donation + +GST is a completely free open-source terminal. My personal goal has always been to keep this terminal available for everyone to use at zero cost. + +Lately, some developers have been helping me in this endeavour. As you can probably tell from the git history, the terminal has been increasing in features/robustness at a really fast pace. Since none of us are getting paid to do so, and we all have 9-5 jobs, it's hard to onbard people to work towards the cause. On a personal level, I stopped investing since the repository was made public, since I spend all my spare time working on it, and don't have time left for DD. + +There are many ways to help support GST. If technical development or support are one of your strengths, join our [discord](https://discord.gg/Up2QGbMKHY). Otherwise, you could certainly help us by providing a donation to our coinbase crypto wallet: **3Pfx7NwGgmZsk7hQJxzHdp5rGBftUHVTiM**. + +Thanks in advance ape. + ## Getting Started ### Install -If you'd like to see a video recording of the installation process, @JohnnyDankseed has made one available [here](https://www.twitch.tv/videos/1008414642). +If you'd like to see a video recording of the installation process, @JohnnyDankseed has made one available [here](https://www.twitch.tv/videos/1013768299). This project was originally written and tested with Python 3.6.8. It should now support Python 3.6, 3.7, and 3.8. @@ -321,9 +332,6 @@ If red is your favourite color, and you never sell for a loss. Welcome to the club, and feel free to support the developers behind this amazing open-source project. -Buy Me A Coffee - -OR, if you prefer a coinbase crypto wallet: **3Pfx7NwGgmZsk7hQJxzHdp5rGBftUHVTiM** ## License From 76dd3d081ec12d5d7b528905ab21e5c419b3370f Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Fri, 7 May 2021 23:36:13 +0100 Subject: [PATCH 25/27] Update README.md --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index a428bb44354..6f0553f445c 100644 --- a/README.md +++ b/README.md @@ -355,6 +355,14 @@ Feel free to share loss porn, memes or any questions at: * Discord: https://discord.gg/Up2QGbMKHY * Twitter: [@gamestonkt](https://twitter.com/gamestonkt) + +#### Shoutout to: +* **alokan** : Responsible by developing `Forex` menu +* **pll_llq** and **hinxx** : Working towards a GUI using Qt. + * Get in touch in our [#gui](https://discord.gg/gQ3VxXEj) discord channel. +* **1lluz10n**, **crspy**, and **martiaaz** : Working on our landing page https://gamestonk.vercel.app. + * Get in touch in our [#landing-page](https://discord.gg/wkyB4xcb) discord channel. + ## Acknowledgments * [VICE article - Gamestonk Terminal Is a DIY, Meme Stock Version of Bloomberg Terminal](https://www.vice.com/en/article/qjp9vp/gamestonk-terminal-is-a-diy-meme-stock-version-of-bloomberg-terminal) From a6a7bcc2596c7e93cf8fc3d2ddb2c2e4c322edd4 Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Fri, 7 May 2021 23:44:05 +0100 Subject: [PATCH 26/27] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6f0553f445c..78dd928313c 100644 --- a/README.md +++ b/README.md @@ -360,7 +360,7 @@ Feel free to share loss porn, memes or any questions at: * **alokan** : Responsible by developing `Forex` menu * **pll_llq** and **hinxx** : Working towards a GUI using Qt. * Get in touch in our [#gui](https://discord.gg/gQ3VxXEj) discord channel. -* **1lluz10n**, **crspy**, and **martiaaz** : Working on our landing page https://gamestonk.vercel.app. +* **1lluz10n**, **crspy**, and **martiaaz** : Working on our landing page https://gamestonkterminal.vercel.app. * Get in touch in our [#landing-page](https://discord.gg/wkyB4xcb) discord channel. ## Acknowledgments From 8746041a81692a8dfa87ad69325790400c45f166 Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Fri, 7 May 2021 23:50:50 +0100 Subject: [PATCH 27/27] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 78dd928313c..582fca4a5f3 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ Lately, some developers have been helping me in this endeavour. As you can proba There are many ways to help support GST. If technical development or support are one of your strengths, join our [discord](https://discord.gg/Up2QGbMKHY). Otherwise, you could certainly help us by providing a donation to our coinbase crypto wallet: **3Pfx7NwGgmZsk7hQJxzHdp5rGBftUHVTiM**. -Thanks in advance ape. +Sharing the terminal with friends and family would also go a long way. Thanks in advance ape. ## Getting Started