diff options
author | jmaslek <jmaslek11@gmail.com> | 2021-10-01 12:01:00 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-01 12:01:00 -0400 |
commit | 876d1aab3e3f4cae0f568b0933970a55052cd295 (patch) | |
tree | 72f9d612e497985f0323830c7135595f73a7262e | |
parent | f93deafa5ee9e046cf45324a8f91e081c7e8f717 (diff) |
Refactor BA Menu (#768)
* Finnhub and finbrain fns
* Twitter menu (forex/ba adjusted)
* Google menu
* Reddit menu pt1
* Reddit commands
* Stocktwits commands
* Sentimentinvestor commands
* Update crypto-dd
* Review pt 1
* Hugo server
* Review comments - get rid of all prints/errors in model...
28 files changed, 3752 insertions, 2521 deletions
diff --git a/gamestonk_terminal/common/behavioural_analysis/finbrain_model.py b/gamestonk_terminal/common/behavioural_analysis/finbrain_model.py new file mode 100644 index 00000000000..7b08659c93d --- /dev/null +++ b/gamestonk_terminal/common/behavioural_analysis/finbrain_model.py @@ -0,0 +1,31 @@ +"""FinBrain Model""" +__docformat__ = "numpy" + +import pandas as pd +import requests + + +def get_sentiment(ticker: str) -> pd.DataFrame: + """Gets Sentiment analysis provided by FinBrain's API [Source: finbrain] + + Parameters + ---------- + ticker : str + Ticker to get the sentiment analysis from + + Returns + ------- + DataFrame() + Empty if there was an issue with data retrieval + """ + result = requests.get(f"https://api.finbrain.tech/v0/sentiments/{ticker}") + sentiment = pd.DataFrame() + if result.status_code == 200: + if "sentimentAnalysis" in result.json(): + sentiment = pd.DataFrame.from_dict( + result.json()["sentimentAnalysis"], orient="index" + ) + sentiment.index = pd.to_datetime(sentiment.index).to_pydatetime() + sentiment.index.name = "date" + sentiment.columns = ["Sentiment Analysis"] + return sentiment diff --git a/gamestonk_terminal/common/behavioural_analysis/finbrain_view.py b/gamestonk_terminal/common/behavioural_analysis/finbrain_view.py index 14004542dd3..1cfb189fa64 100644 --- a/gamestonk_terminal/common/behavioural_analysis/finbrain_view.py +++ b/gamestonk_terminal/common/behavioural_analysis/finbrain_view.py @@ -1,20 +1,16 @@ """FinBrain View Module""" __docformat__ = "numpy" -import argparse -from typing import List -import requests +import os from matplotlib import pyplot as plt import matplotlib.dates as mdates import pandas as pd from pandas.plotting import register_matplotlib_converters import numpy as np from colorama import Fore, Style - -from gamestonk_terminal.helper_funcs import ( - parse_known_args_and_warn, - plot_autoscale, -) +from tabulate import tabulate +from gamestonk_terminal.helper_funcs import plot_autoscale, export_data +from gamestonk_terminal.common.behavioural_analysis import finbrain_model from gamestonk_terminal.config_plot import PLOT_DPI from gamestonk_terminal import feature_flags as gtff @@ -23,44 +19,10 @@ register_matplotlib_converters() def sentiment_coloring(val: float, last_val: float) -> str: - if float(val) > last_val: - color = Fore.GREEN - else: - color = Fore.RED + color = Fore.GREEN if float(val) > last_val else Fore.RED return f"{color}{val}{Style.RESET_ALL}" -def get_sentiment(ticker: str) -> pd.DataFrame: - """Gets Sentiment analysis provided by FinBrain's API - - Parameters - ---------- - ticker : str - Ticker to get the sentiment analysis from - - Returns - ------- - DataFrame() - Empty if there was an issue with data retrieval - """ - result = requests.get(f"https://api.finbrain.tech/v0/sentiments/{ticker}") - sentiment = pd.DataFrame() - if result.status_code == 200: - if "sentimentAnalysis" in result.json(): - sentiment = pd.DataFrame.from_dict( - result.json()["sentimentAnalysis"], orient="index" - ) - sentiment.index = pd.to_datetime(sentiment.index).to_pydatetime() - sentiment.index.name = "date" - sentiment.columns = ["Sentiment Analysis"] - else: - print("Unexpected data format from FinBrain API") - else: - print("Request error in retrieving sentiment from FinBrain API") - - return sentiment - - def plot_sentiment(sentiment: pd.DataFrame, ticker: str): """Plot Sentiment analysis provided by FinBrain's API @@ -71,27 +33,29 @@ def plot_sentiment(sentiment: pd.DataFrame, ticker: str): ticker : str Ticker to get the sentiment analysis from """ - plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI) + fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) for index, row in sentiment.iterrows(): if float(row["Sentiment Analysis"]) >= 0: - plt.scatter(index, float(row["Sentiment Analysis"]), s=100, c="green") + ax.scatter(index, float(row["Sentiment Analysis"]), s=100, c="green") else: - plt.scatter(index, float(row["Sentiment Analysis"]), s=100, c="red") - plt.axhline(y=0, color="k", linestyle="--", lw=2) - plt.xlabel("Time") - plt.ylabel("Sentiment") - plt.grid(b=True, which="major", color="#666666", linestyle="-") - plt.minorticks_on() - plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2) + ax.scatter(index, float(row["Sentiment Analysis"]), s=100, c="red") + ax.axhline(y=0, color="k", linestyle="--", lw=2) + ax.set_xlabel("Time") + ax.set_ylabel("Sentiment") + ax.grid(b=True, which="major", color="#666666", linestyle="-") + ax.minorticks_on() + ax.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2) start_date = sentiment.index[-1].strftime("%Y/%m/%d") - plt.title(f"FinBrain's Sentiment Analysis for {ticker.upper()} since {start_date}") + ax.set_title( + f"FinBrain's Sentiment Analysis for {ticker.upper()} since {start_date}" + ) plt.gca().xaxis.set_major_formatter(mdates.DateFormatter("%Y/%m/%d")) plt.gca().xaxis.set_major_locator(mdates.DayLocator(interval=1)) plt.gcf().autofmt_xdate() - plt.ylim([-1.1, 1.1]) + ax.set_ylim([-1.1, 1.1]) senValues = np.array(pd.to_numeric(sentiment["Sentiment Analysis"].values)) senNone = np.array(0 * len(sentiment)) - plt.fill_between( + ax.fill_between( sentiment.index, pd.to_numeric(sentiment["Sentiment Analysis"].values), 0, @@ -100,7 +64,7 @@ def plot_sentiment(sentiment: pd.DataFrame, ticker: str): color="red", interpolate=True, ) - plt.fill_between( + ax.fill_between( sentiment.index, pd.to_numeric(sentiment["Sentiment Analysis"].values), 0, @@ -111,53 +75,57 @@ def plot_sentiment(sentiment: pd.DataFrame, ticker: str): ) if gtff.USE_ION: plt.ion() + fig.tight_layout() plt.show() -def sentiment_analysis(other_args: List[str], ticker: str): +def display_sentiment_analysis(ticker: str, export: str = ""): """Sentiment analysis from FinBrain Parameters ---------- - other_args : List[str] - Command line arguments to be processed with argparse ticker : str Ticker to get the sentiment analysis from + export : str + Format to export data """ - parser = argparse.ArgumentParser( - add_help=False, - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - prog="finbrain", - description="""FinBrain collects the news headlines from 15+ major financial news - sources on a daily basis and analyzes them to generate sentiment scores - for more than 4500 US stocks.FinBrain Technologies develops deep learning - algorithms for financial analysis and prediction, which currently serves - traders from more than 150 countries all around the world. - [Source: https://finbrain.tech]""", - ) - - try: - ns_parser = parse_known_args_and_warn(parser, other_args) - if not ns_parser: - return - - df_sentiment = get_sentiment(ticker) - - if not df_sentiment.empty: - plot_sentiment(df_sentiment, ticker) - - df_sentiment.sort_index(ascending=True, inplace=True) - - if gtff.USE_COLOR: + df_sentiment = finbrain_model.get_sentiment(ticker) + if df_sentiment.empty: + print("No sentiment data found.\n") + return + + plot_sentiment(df_sentiment, ticker) + + df_sentiment.sort_index(ascending=True, inplace=True) + + if gtff.USE_COLOR: + color_df = df_sentiment["Sentiment Analysis"].apply( + sentiment_coloring, last_val=0 + ) + if gtff.USE_TABULATE_DF: + color_df = pd.DataFrame( + data=color_df.values, + index=pd.to_datetime(df_sentiment.index).strftime("%Y-%m-%d"), + ) + print(tabulate(color_df, headers=["Sentiment"], tablefmt="fancy_grid")) + else: + print(color_df.to_string()) + else: + if gtff.USE_TABULATE_DF: print( - df_sentiment["Sentiment Analysis"] - .apply(sentiment_coloring, last_val=0) - .to_string() + tabulate( + pd.DataFrame( + data=df_sentiment.values, + index=pd.to_datetime(df_sentiment.index).strftime("%Y-%m-%d"), + ), + headers=["Sentiment"], + tablefmt="fancy_grid", + ) ) + else: print(df_sentiment.to_string()) - print("") - - except Exception as e: - print(e, "\n") - print("") + print("") + export_data( + export, os.path.dirname(os.path.abspath(__file__)), "headlines", df_sentiment + ) diff --git a/gamestonk_terminal/common/behavioural_analysis/finnhub_model.py b/gamestonk_terminal/common/behavioural_analysis/finnhub_model.py new file mode 100644 index 00000000000..95ff851ae52 --- /dev/null +++ b/gamestonk_terminal/common/behavioural_analysis/finnhub_model.py @@ -0,0 +1,28 @@ +"""Finnhub Model""" +__docformat__ = "numpy" + +from typing import Dict +import requests +from gamestonk_terminal import config_terminal as cfg + + +def get_sentiment_stats(ticker: str) -> Dict: + """Get sentiment stats [Source: finnhub] + + Parameters + ---------- + ticker : str + Ticker to get sentiment stats + + Returns + ------- + Dict + Get sentiment stats + """ + response = requests.get( + f"https://finnhub.io/api/v1/news-sentiment?symbol={ticker}&token={cfg.API_FINNHUB_KEY}" + ) + if response.status_code == 200: + return response.json() + + return {} diff --git a/gamestonk_terminal/common/behavioural_analysis/finnhub_view.py b/gamestonk_terminal/common/behavioural_analysis/finnhub_view.py index ab0c42ea933..63e652387f4 100644 --- a/gamestonk_terminal/common/behavioural_analysis/finnhub_view.py +++ b/gamestonk_terminal/common/behavioural_analysis/finnhub_view.py @@ -1,83 +1,50 @@ -import argparse -from typing import List, Dict -import requests -from gamestonk_terminal import config_terminal as cfg -from gamestonk_terminal.helper_funcs import ( - parse_known_args_and_warn, -) +"""Finnhub View""" +__docformat__ = "numpy" +import os -def get_sentiment_stats(ticker: str) -> Dict: - """Get sentiment stats +import pandas as pd - Parameters - ---------- - ticker : str - Ticker to get sentiment stats - - Returns - ------- - Dict - Get sentiment stats - """ - response = requests.get( - f"https://finnhub.io/api/v1/news-sentiment?symbol={ticker}&token={cfg.API_FINNHUB_KEY}" - ) - if response.status_code == 200: - return response.json() +from gamestonk_terminal.helper_funcs import export_data +from gamestonk_terminal.common.behavioural_analysis import finnhub_model - return {} - -def sentiment_stats(other_args: List[str], ticker: str): +def display_sentiment_stats(ticker: str, export: str = ""): """ Sentiment stats which displays buzz, news score, articles last week, articles weekly average, bullish vs bearish percentages, sector average bullish percentage, and sector average news score Parameters ---------- - other_args : List[str] - Command line arguments to be processed with argparse ticker : str Ticker to get sentiment stats + export : str + Format to export data """ - parser = argparse.ArgumentParser( - add_help=False, - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - prog="stats", - description=""" - Sentiment stats which displays buzz, news score, articles last week, articles weekly average, - bullish vs bearish percentages, sector average bullish percentage, and sector average news score. - [Source: https://finnhub.io] - """, - ) - - try: - ns_parser = parse_known_args_and_warn(parser, other_args) - if not ns_parser: - return - - d_stats = get_sentiment_stats(ticker) - - if d_stats: - print(f"Buzz: {round(100*d_stats['buzz']['buzz'],2)} %") - print(f"News Score: {round(100*d_stats['companyNewsScore'],2)} %") - print("") - print(f"Articles Last Week: {d_stats['buzz']['articlesInLastWeek']}") - print(f"Articles Weekly Average: {d_stats['buzz']['weeklyAverage']}") - print("") - print(f"Bullish: {round(100*d_stats['sentiment']['bullishPercent'],2)} %") - print(f"Bearish: {round(100*d_stats['sentiment']['bearishPercent'],2)} %") - print("") - print( - f"Sector Average Bullish: {round(100*d_stats['sectorAverageBullishPercent'],2)} %" - ) - print( - f"Sector Average News Score: {round(100*d_stats['sectorAverageNewsScore'],2)} %" - ) - else: - print("No sentiment stats found.") - print("") - - except Exception as e: - print(e, "\n") + d_stats = finnhub_model.get_sentiment_stats(ticker) + + if d_stats: + print( + f""" +Buzz: {round(100*d_stats['buzz']['buzz'],2)} % +News Score: {round(100*d_stats['companyNewsScore'],2)} % + +Articles Last Week: {d_stats['buzz']['articlesInLastWeek']} +Articles Weekly Average: {d_stats['buzz']['weeklyAverage']} + +Bullish: {round(100*d_stats['sentiment']['bullishPercent'],2)} % +Bearish: {round(100*d_stats['sentiment']['bearishPercent'],2)} % + +Sector Average Bullish: {round(100*d_stats['sectorAverageBullishPercent'],2)} +Sector Average News Score: {round(100*d_stats['sectorAverageNewsScore'],2)} %""" + ) + export_data( + export, + os.path.dirname(os.path.abspath(__file__)), + "stats", + pd.DataFrame(d_stats), + ) + + else: + print("No sentiment stats found.") + print("") diff --git a/gamestonk_terminal/common/behavioural_analysis/google_model.py b/gamestonk_terminal/common/behavioural_analysis/google_model.py new file mode 100644 index 00000000000..407892fc865 --- /dev/null +++ b/gamestonk_terminal/common/behavioural_analysis/google_model.py @@ -0,0 +1,78 @@ +"""Google Model""" +__docformat__ = "numpy" + +import pandas as pd +from pytrends.request import TrendReq + + +def get_mentions(ticker: str) -> pd.DataFrame: + """Get interest over time from google api [Source: google] + + Parameters + ---------- + ticker : str + Stock ticker + + Returns + ------- + pd.DataFrame + Dataframe of interest over time + """ + pytrend = TrendReq() + pytrend.build_payload(kw_list=[ticker]) + return pytrend.interest_over_time() + + +def get_regions(ticker: str) -> pd.DataFrame: + """Get interest by region from google api [Source: google] + + Parameters + ---------- + ticker : str + Ticker to look at + + Returns + ------- + pd.DataFrame + Dataframe of interest by region + """ + pytrend = TrendReq() + pytrend.build_payload(kw_list=[ticker]) + return pytrend.interest_by_region() + + +def get_queries(ticker: str) -> pd.DataFrame: + """Get related queries from google api [Source: google] + + Parameters + ---------- + ticker : str + Stock ticker to compare + + Returns + ------- + pd.DataFrame + Dataframe of related queries + """ + pytrend = TrendReq() + pytrend.build_payload(kw_list=[ticker]) + return pytrend.related_queries() + + +def get_rise(ticker: str) -> pd.DataFrame: + """Get top rising related queries with this stock's query [Source: google] + + Parameters + ---------- + ticker : str + Stock ticker + + Returns + ------- + pd.DataFrame + Dataframe containing rising related queries + """ + pytrend = TrendReq() + pytrend.build_payload(kw_list=[ticker]) + df_related_queries = pytrend.related_queries() + return df_related_queries[ticker]["rising"] diff --git a/gamestonk_terminal/common/behavioural_analysis/google_view.py b/gamestonk_terminal/common/behavioural_analysis/google_view.py index 74f198a221e..f6df2b24405 100644 --- a/gamestonk_terminal/common/behavioural_analysis/google_view.py +++ b/gamestonk_terminal/common/behavioural_analysis/google_view.py @@ -1,217 +1,160 @@ -import argparse -from typing import List +"""Google View""" +__docformat__ = "numpy" + +import os from datetime import datetime -from pytrends.request import TrendReq + +from tabulate import tabulate import matplotlib.pyplot as plt -from gamestonk_terminal.helper_funcs import ( - check_positive, - valid_date, - parse_known_args_and_warn, -) +from gamestonk_terminal.helper_funcs import plot_autoscale, export_data +from gamestonk_terminal.common.behavioural_analysis import google_model +from gamestonk_terminal import config_plot as cfp, feature_flags as gtff -def mentions(other_args: List[str], ticker: str, start: datetime): + +def display_mentions(ticker: str, start: datetime, export: str = ""): """Plot weekly bars of stock's interest over time. other users watchlist. [Source: Google] Parameters ---------- - other_args : List[str] - Command line arguments to be processed with argparse ticker : str Ticker - start : str + start : datetime Start date + export: str + Format to export data """ - parser = argparse.ArgumentParser( - add_help=False, - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - prog="mentions", - description=""" - Plot weekly bars of stock's interest over time. other users watchlist. [Source: Google] - """, - ) - parser.add_argument( - "-s", - "--start", - type=valid_date, - dest="start", - default=start, - help="starting date (format YYYY-MM-DD) from when we are interested in stock's mentions.", - ) - - try: - ns_parser = parse_known_args_and_warn(parser, other_args) - if not ns_parser: - return - - pytrend = TrendReq() - pytrend.build_payload(kw_list=[ticker]) - df_interest = pytrend.interest_over_time() - - plt.title(f"Interest over time on {ticker}") - if ns_parser.start: - df_interest = df_interest[ns_parser.start :] - plt.bar(df_interest.index, df_interest[ticker], width=2) - plt.bar( - df_interest.index[-1], - df_interest[ticker].values[-1], - color="tab:orange", - width=2, - ) - else: - plt.bar(df_interest.index, df_interest[ticker], width=1) - plt.bar( - df_interest.index[-1], - df_interest[ticker].values[-1], - color="tab:orange", - width=1, - ) - - plt.grid(b=True, which="major", color="#666666", linestyle="-") - plt.ylabel("Interest [%]") - plt.xlabel("Time") - plt.show() - print("") + df_interest = google_model.get_mentions(ticker) + + fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=cfp.PLOT_DPI) + ax.set_title(f"Interest over time on {ticker}") + if start: + df_interest = df_interest[start:] # type: ignore + ax.bar(df_interest.index, df_interest[ticker], width=2) + ax.bar( + |