diff --git a/gamestonk_terminal/government/README.md b/gamestonk_terminal/government/README.md index e9bffc33909..129a9e22cee 100644 --- a/gamestonk_terminal/government/README.md +++ b/gamestonk_terminal/government/README.md @@ -25,6 +25,8 @@ This data has been provided by [quiverquant](https://www.quiverquant.com). * last government contracts * [sum_contracts](#sum_contracts) * plot sum of last government contracts +* [qtr_contracts](#qtr_contracts) + * quarterly government contracts best regression #### WITH TICKER PROVIDED @@ -44,6 +46,8 @@ This data has been provided by [quiverquant](https://www.quiverquant.com). * raw contracts on the ticker * [contracts](#contracts) * plot sum of contracts on the ticker +* [qtr_contracts_hist](#qtr_contracts_hist) + * quarterly government contracts historical ## last_congress ```text @@ -174,6 +178,15 @@ Sum latest contracts. [Source: www.quiverquant.com] ![sum_contracts](https://user-images.githubusercontent.com/25267873/119065220-f33d0580-b9d4-11eb-8870-37ca352b187c.png) +## qtr_contracts +```text +usage: qtr_contracts [-t TOP] +``` +Quarterly government contracts best regression. [Source: www.quiverquant.com] + +![top_promising_stocks](https://user-images.githubusercontent.com/25267873/120394857-f963a800-c32b-11eb-9d3f-2295f7216b67.png) + + #### WITH TICKER PROVIDED ## raw_congress @@ -262,3 +275,13 @@ Contracts associated with ticker. [Source: www.quiverquant.com] * -p : Past transaction months. Default: 10. ![contracts](https://user-images.githubusercontent.com/25267873/119065405-59c22380-b9d5-11eb-9a34-9cad288b22de.png) + + +## qtr_contracts_hist +```text +usage: qtr_contracts_hist +``` +Quarterly government contracts historical. [Source: www.quiverquant.com] + +![qtr_contracts_hist](https://user-images.githubusercontent.com/25267873/120394929-113b2c00-c32c-11eb-8241-78d5d1328386.png) + diff --git a/gamestonk_terminal/government/gov_controller.py b/gamestonk_terminal/government/gov_controller.py index 70edad786dd..c90613a5f28 100644 --- a/gamestonk_terminal/government/gov_controller.py +++ b/gamestonk_terminal/government/gov_controller.py @@ -38,6 +38,8 @@ class GovController: "sum_contracts", "raw_contracts", "contracts", + "qtr_contracts", + "qtr_contracts_hist", ] def __init__( @@ -61,28 +63,30 @@ class GovController: print(" quit quit to abandon program") print("") print("Explore:") - print(" last_congress last congress trading") - print(" buy_congress plot top buy congress tickers") - print(" sell_congress plot top sell congress tickers") - print(" last_senate last senate trading") - print(" buy_senate plot top buy senate tickers") - print(" sell_senate plot top sell senate tickers") - print(" last_house last house trading") - print(" buy_house plot top buy house tickers") - print(" sell_house plot top sell house tickers") - print(" last_contracts last government contracts") - print(" sum_contracts plot sum of last government contracts") + print(" last_congress last congress trading") + print(" buy_congress plot top buy congress tickers") + print(" sell_congress plot top sell congress tickers") + print(" last_senate last senate trading") + print(" buy_senate plot top buy senate tickers") + print(" sell_senate plot top sell senate tickers") + print(" last_house last house trading") + print(" buy_house plot top buy house tickers") + print(" sell_house plot top sell house tickers") + print(" last_contracts last government contracts") + print(" sum_contracts plot sum of last government contracts") + print(" qtr_contracts quarterly government contracts best regression") print("") if self.ticker: print(f"Ticker: {self.ticker}") - print(" raw_congress raw congress trades on the ticker") - print(" congress plot congress trades on the ticker") - print(" raw_senate raw senate trades on the ticker") - print(" senate plot senate trades on the ticker") - print(" raw_house raw house trades on the ticker") - print(" house plot house trades on the ticker") - print(" raw_contracts raw contracts on the ticker") - print(" contracts plot sum of contracts on the ticker") + print(" raw_congress raw congress trades on the ticker") + print(" congress plot congress trades on the ticker") + print(" raw_senate raw senate trades on the ticker") + print(" senate plot senate trades on the ticker") + print(" raw_house raw house trades on the ticker") + print(" house plot house trades on the ticker") + print(" raw_contracts raw contracts on the ticker") + print(" contracts plot sum of contracts on the ticker") + print(" qtr_contracts_hist quarterly government contracts historical") print("") return @@ -190,6 +194,14 @@ class GovController: """Process contracts command""" quiverquant_view.contracts(other_args, self.ticker) + def call_qtr_contracts(self, other_args: List[str]): + """Process qtr_contracts command""" + quiverquant_view.call_qtr_contracts(other_args) + + def call_qtr_contracts_hist(self, other_args: List[str]): + """Process qtr_contracts_hist command""" + quiverquant_view.call_qtr_contracts_hist(other_args, self.ticker) + def menu(ticker: str): """Government Menu""" diff --git a/gamestonk_terminal/government/quiverquant_model.py b/gamestonk_terminal/government/quiverquant_model.py index 7c625c71086..9fedb5cb801 100644 --- a/gamestonk_terminal/government/quiverquant_model.py +++ b/gamestonk_terminal/government/quiverquant_model.py @@ -2,7 +2,9 @@ import requests import pandas as pd # Provided by Quiverquant guys to GST users -API_QUIVERQUANT_KEY = "5cd2a65e96d0486efbe926a7cdbc1e8d8ab6c7b3" +API_QUIVERQUANT_KEY = ( + "5cd2a65e96d0486efbe926a7cdbc1e8d8ab6c7b3" # pragma: allowlist secret +) def get_government_trading(gov_type: str, ticker: str = "") -> pd.DataFrame: @@ -11,7 +13,7 @@ def get_government_trading(gov_type: str, ticker: str = "") -> pd.DataFrame: Parameters ---------- gov_type: str - Type of government data between: Congress, Senate, House and Contracts + Type of government data between: Congress, Senate, House, Contracts and Quarter-Contracts ticker : str Ticker to get congress trading data from @@ -49,12 +51,18 @@ def get_government_trading(gov_type: str, ticker: str = "") -> pd.DataFrame: else: url = "https://api.quiverquant.com/beta/live/govcontractsall" + elif gov_type == "quarter-contracts": + if ticker: + url = f"https://api.quiverquant.com/beta/historical/govcontracts/{ticker}" + else: + url = "https://api.quiverquant.com/beta/live/govcontracts" + else: return pd.DataFrame() headers = { "accept": "application/json", - "X-CSRFToken": "TyTJwjuEC7VV7mOqZ622haRaaUr0x0Ng4nrwSRFKQs7vdoBcJlK9qjAS69ghzhFu", + "X-CSRFToken": "TyTJwjuEC7VV7mOqZ622haRaaUr0x0Ng4nrwSRFKQs7vdoBcJlK9qjAS69ghzhFu", # pragma: allowlist secret "Authorization": f"Token {API_QUIVERQUANT_KEY}", } response = requests.get(url, headers=headers) @@ -63,7 +71,6 @@ def get_government_trading(gov_type: str, ticker: str = "") -> pd.DataFrame: return pd.DataFrame(response.json()).rename( columns={"Date": "TransactionDate", "Senator": "Representative"} ) - else: - return pd.DataFrame(response.json()) + return pd.DataFrame(response.json()) return pd.DataFrame() diff --git a/gamestonk_terminal/government/quiverquant_view.py b/gamestonk_terminal/government/quiverquant_view.py index 6bb0c866a4d..03ceade274c 100644 --- a/gamestonk_terminal/government/quiverquant_view.py +++ b/gamestonk_terminal/government/quiverquant_view.py @@ -1,6 +1,8 @@ import argparse from typing import List from datetime import datetime, timedelta +import numpy as np +from sklearn import linear_model import pandas as pd from matplotlib import pyplot as plt import matplotlib.dates as mdates @@ -761,3 +763,168 @@ def contracts(other_args: List[str], ticker: str): except Exception as e: print(e, "\n") + + +def call_qtr_contracts(other_args: List[str]): + """Quarter contracts + + Parameters + ---------- + other_args : List[str] + Command line arguments to be processed with argparse + """ + parser = argparse.ArgumentParser( + add_help=False, + prog="qtr_contracts", + description="Quarterly-contracts, best regression slope. [Source: www.quiverquant.com]", + ) + parser.add_argument( + "-t", + "--top", + action="store", + dest="top", + type=check_positive, + default=5, + help="Top promising stocks with best quarterly-contracts momentum", + ) + + try: + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + + df_contracts = quiverquant_model.get_government_trading("quarter-contracts") + + if df_contracts.empty: + print("No quarterly government contracts found\n") + return + + df_coef = pd.DataFrame(columns=["Ticker", "Coef"]) + + for symbol in df_contracts["Ticker"].unique(): + # Create linear regression object + regr = linear_model.LinearRegression() + + amounts = ( + df_contracts[df_contracts["Ticker"] == symbol] + .sort_values(by=["Year", "Qtr"])["Amount"] + .values + ) + + # Train the model using the training sets + regr.fit(np.arange(0, len(amounts)).reshape(-1, 1), amounts) + + df_coef = df_coef.append( + {"Ticker": symbol, "Coef": regr.coef_[0]}, ignore_index=True + ) + + plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI) + + tickers = df_coef.sort_values(by=["Coef"], ascending=False).head(ns_parser.top)[ + "Ticker" + ] + + max_amount = 0 + quarter_ticks = list() + for symbol in tickers: + amounts = ( + df_contracts[df_contracts["Ticker"] == symbol] + .sort_values(by=["Year", "Qtr"])["Amount"] + .values + ) + + qtr = ( + df_contracts[df_contracts["Ticker"] == symbol] + .sort_values(by=["Year", "Qtr"])["Qtr"] + .values + ) + year = ( + df_contracts[df_contracts["Ticker"] == symbol] + .sort_values(by=["Year", "Qtr"])["Year"] + .values + ) + + plt.plot(np.arange(0, len(amounts)), amounts / 1000, "-*", lw=2, ms=15) + + if len(amounts) > max_amount: + max_amount = len(amounts) + quarter_ticks = [ + f"{quarter[0]} - {quarter[1]} Qtr" for quarter in zip(year, qtr) + ] + + plt.xlim([-0.5, max_amount - 0.5]) + plt.xticks(np.arange(0, max_amount), quarter_ticks) + plt.grid() + plt.legend(tickers) + plt.title("Quarterly Government Contracts - Top promising stocks") + plt.xlabel("Date") + plt.ylabel("Amount [1k $]") + plt.show() + + if gtff.USE_ION: + plt.ion() + + plt.show() + print("") + + except Exception as e: + print(e, "\n") + + +def call_qtr_contracts_hist(other_args: List[str], ticker: str): + """Quarter contracts + + 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="qtr_contracts_hist", + description="Quarterly-contracts historical [Source: www.quiverquant.com]", + ) + try: + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + + df_contracts = quiverquant_model.get_government_trading( + "quarter-contracts", ticker=ticker + ) + + if df_contracts.empty: + print("No quarterly government contracts found\n") + return + + plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI) + + amounts = df_contracts.sort_values(by=["Year", "Qtr"])["Amount"].values + + qtr = df_contracts.sort_values(by=["Year", "Qtr"])["Qtr"].values + year = df_contracts.sort_values(by=["Year", "Qtr"])["Year"].values + + quarter_ticks = [ + f"{quarter[0]}" if quarter[1] == 1 else "" for quarter in zip(year, qtr) + ] + + plt.plot(np.arange(0, len(amounts)), amounts / 1000, "-*", lw=2, ms=15) + + plt.xlim([-0.5, len(amounts) - 0.5]) + plt.xticks(np.arange(0, len(amounts)), quarter_ticks) + plt.grid() + plt.title(f"Quarterly Government Contracts Historical on {ticker.upper()}") + plt.xlabel("Date") + plt.ylabel("Amount [1k $]") + plt.show() + + if gtff.USE_ION: + plt.ion() + + plt.show() + print("") + + except Exception as e: + print(e, "\n")