diff --git a/gamestonk_terminal/README.md b/gamestonk_terminal/README.md index aaf9a94e512..208ff4bcd21 100644 --- a/gamestonk_terminal/README.md +++ b/gamestonk_terminal/README.md @@ -2,7 +2,7 @@ ### Table of contents * [Discover Stocks](#Discover-Stocks-) -* [Market Sentiment](#Market-Sentiment-) +* [Behavioural Analysis](#Behavioural-Analysis-) * [Research Web pages](#Research-Web-pages) * [Fundamental Analysis](#Fundamental-Analysis-) * [Technical Analysis](#Technical-Analysis-) @@ -66,7 +66,7 @@ Command|Description|Source   -## Market Sentiment [»](sentiment/README.md) +## Behavioural Analysis [»](behavioural_analysis/README.md) Command|Description ----|---- [Reddit](https://reddit.com)| diff --git a/gamestonk_terminal/sentiment/README.md b/gamestonk_terminal/behavioural_analysis/README.md similarity index 95% rename from gamestonk_terminal/sentiment/README.md rename to gamestonk_terminal/behavioural_analysis/README.md index 1a9e973c128..bdb8fed002f 100644 --- a/gamestonk_terminal/sentiment/README.md +++ b/gamestonk_terminal/behavioural_analysis/README.md @@ -1,6 +1,6 @@ -# MARKET SENTIMENT +# BEHAVIOURAL ANALYSIS -This menu aims to extrapolate market's sentiment regarding a pre-loaded ticker, and the usage of the following commands along with an example will be exploited below. +This menu aims to extrapolate behavioural analysis regarding a pre-loaded ticker, and the usage of the following commands along with an example will be exploited below. [REDDIT](#REDDIT) * [wsb](#wsb) @@ -12,11 +12,11 @@ This menu aims to extrapolate market's sentiment regarding a pre-loaded ticker, * [spac_c](#spac_c) - show other users spacs announcements from subreddit SPACs community * [spac](#spac) - - show other users spacs announcements from other subs + - show other users spacs announcements from other subs [STOCKTWITS](#STOCKTWITS) * [bullbear](#bullbear) - - estimate quick sentiment from last 30 messages on board + - estimate quick sentiment from last 30 messages on board * [messages](#messages) - output up to the 30 last messages on the board * [trending](#trending) @@ -29,7 +29,7 @@ This menu aims to extrapolate market's sentiment regarding a pre-loaded ticker, - infer about stock's sentiment from latest tweets * [sentiment](#sentiment) - in-depth sentiment prediction from tweets over time - + [GOOGLE](#GOOGLE) * [mentions](#mentions) - interest over time based on stock's mentions @@ -106,7 +106,7 @@ usage: bullbear [-t S_TICKER] ``` Print bullbear sentiment based on last 30 messages on the board. Also prints the watchlist_count. [Source: Stocktwits] * -t : ticker to gather sentiment from. - + sentiment @@ -156,7 +156,7 @@ Print quick sentiment inference from last tweets that contain the ticker. This m ``` usage: sentiment [-n N_NUM] [-d N_DAYS_PAST] ``` -Plot in-depth sentiment extracted from tweets from last days that contain pre-defined ticker. This model splits the text into character-level tokens and uses the DistilBERT model to make predictions. DistilBERT is a distilled version of the powerful BERT transformer model. Note that a big num of tweets extracted per hour in conjunction with a high number of days in the past, will make the algorithm take a long period of time to estimate sentiment. Inspired by https://towardsdatascience.com/sentiment-analysis-for-stock-price-prediction-in-python-bed40c65d178. [Source: Twitter] +Plot in-depth sentiment extracted from tweets from last days that contain pre-defined ticker. This model splits the text into character-level tokens and uses the DistilBERT model to make predictions. DistilBERT is a distilled version of the powerful BERT transformer model. Note that a big num of tweets extracted per hour in conjunction with a high number of days in the past, will make the algorithm take a long period of time to estimate sentiment. Inspired by https://towardsdatascience.com/sentiment-analysis-for-stock-price-prediction-in-python-bed40c65d178. [Source: Twitter] * -n : num of tweets to extract per hour. Default 100. * -d : num of days in the past to extract tweets. Default 7. diff --git a/gamestonk_terminal/sentiment/__init__.py b/gamestonk_terminal/behavioural_analysis/__init__.py similarity index 100% rename from gamestonk_terminal/sentiment/__init__.py rename to gamestonk_terminal/behavioural_analysis/__init__.py diff --git a/gamestonk_terminal/behavioural_analysis/ba_controller.py b/gamestonk_terminal/behavioural_analysis/ba_controller.py new file mode 100644 index 00000000000..6a204c82f26 --- /dev/null +++ b/gamestonk_terminal/behavioural_analysis/ba_controller.py @@ -0,0 +1,235 @@ +"""Behavioural Analysis Controller Module""" +__docformat__ = "numpy" + +import argparse +from typing import List +from datetime import datetime + +from gamestonk_terminal import feature_flags as gtff +from gamestonk_terminal.helper_funcs import get_flair +from gamestonk_terminal.menu import session +from gamestonk_terminal.behavioural_analysis import ( + google_view, + reddit_view, + stocktwits_view, +) +from prompt_toolkit.completion import NestedCompleter + + +class BehaviouralAnalysisController: + """Behavioural Analysis Controller class""" + + def __init__(self, ticker: str, start: datetime): + """Constructor""" + self.ticker = ticker + self.start = start + self.ba_parser = argparse.ArgumentParser(add_help=False, prog="ba") + self.ba_parser.add_argument( + "cmd", + choices=[ + "help", + "q", + "quit", + "watchlist", + "spac", + "spac_c", + "wsb", + "popular", + "bullbear", + "messages", + "trending", + "stalker", + "infer", + "sentiment", + "mentions", + "regions", + "queries", + "rise", + ], + ) + + @staticmethod + def print_help(): + """Print help""" + + print("\nBehavioural Analysis:") + print(" help show this behavioural analysis menu again") + print(" q quit this menu, and shows back to main menu") + print(" quit quit to abandon program") + print("") + print("Reddit:") + print( + " wsb show what WSB gang is up to in subreddit wallstreetbets" + ) + print(" watchlist show other users watchlist") + print(" popular show popular tickers") + print( + " spac_c show other users spacs announcements from subreddit SPACs community" + ) + print(" spac show other users spacs announcements from other subs") + print("") + print("Stocktwits:") + print( + " bullbear estimate quick sentiment from last 30 messages on board" + ) + print(" messages output up to the 30 last messages on the board") + print(" trending trending stocks") + print(" stalker stalk stocktwits user's last messages") + print("") + print("Twitter:") + print(" infer infer about stock's sentiment from latest tweets") + print(" sentiment in-depth sentiment prediction from tweets over time") + print("") + print("Google:") + print(" mentions interest over time based on stock's mentions") + print(" regions regions that show highest interest in stock") + print(" queries top related queries with this stock") + print(" rise top rising related queries with stock") + print("") + + 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.ba_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() + + 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_watchlist(self, other_args: List[str]): + """Process watchlist command""" + reddit_view.watchlist(other_args) + + def call_spac(self, other_args: List[str]): + """Process spac command""" + reddit_view.spac(other_args) + + def call_spac_c(self, other_args: List[str]): + """Process spac_c command""" + reddit_view.spac_community(other_args) + + def call_wsb(self, other_args: List[str]): + """Process wsb command""" + reddit_view.wsb_community(other_args) + + def call_popular(self, other_args: List[str]): + """Process popular command""" + reddit_view.popular_tickers(other_args) + + def call_bullbear(self, other_args: List[str]): + """Process bullbear command""" + stocktwits_view.bullbear(other_args, self.ticker) + + def call_messages(self, other_args: List[str]): + """Process messages command""" + stocktwits_view.messages(other_args, self.ticker) + + def call_trending(self, other_args: List[str]): + """Process trending command""" + stocktwits_view.trending(other_args) + + def call_stalker(self, other_args: List[str]): + """Process stalker command""" + stocktwits_view.stalker(other_args) + + def call_mentions(self, other_args: List[str]): + """Process mentions command""" + google_view.mentions(other_args, self.ticker, self.start) + + def call_regions(self, other_args: List[str]): + """Process regions command""" + google_view.regions(other_args, self.ticker) + + def call_queries(self, other_args: List[str]): + """Process queries command""" + google_view.queries(other_args, self.ticker) + + def call_rise(self, other_args: List[str]): + """Process rise command""" + google_view.rise(other_args, self.ticker) + + def call_infer(self, other_args: List[str]): + """Process infer command""" + if not gtff.ENABLE_PREDICT: + print("Predict is not enabled in feature_flags.py") + print("Twitter inference menu is disabled", "\n") + return + + try: + # pylint: disable=import-outside-toplevel + from gamestonk_terminal.behavioural_analysis import twitter_view + except ModuleNotFoundError as e: + print("Optional packages need to be installed") + print(e, "\n") + return + except Exception as e: + print(e, "\n") + return + + twitter_view.inference(other_args, self.ticker) + + def call_sentiment(self, other_args: List[str]): + """Process sentiment command""" + if not gtff.ENABLE_PREDICT: + print("Predict is not enabled in feature_flags.py") + print("Twitter inference menu is disabled", "\n") + return + + try: + # pylint: disable=import-outside-toplevel + from gamestonk_terminal.behavioural_analysis import twitter_view + except ModuleNotFoundError as e: + print("Optional packages need to be installed") + print(e, "\n") + return + except Exception as e: + print(e, "\n") + return + + twitter_view.sentiment(other_args, self.ticker) + + +def menu(ticker: str, start: datetime): + """Behavioural Analysis Menu""" + + ba_controller = BehaviouralAnalysisController(ticker, start) + ba_controller.call_help(None) + + while True: + # Get input command from user + if session and gtff.USE_PROMPT_TOOLKIT: + an_input = session.prompt( + f"{get_flair()} (ba)> ", + completer=completer, + ) + else: + an_input = input(f"{get_flair()} (ba)> ") + + try: + process_input = ba_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/sentiment/google_api.py b/gamestonk_terminal/behavioural_analysis/google_view.py similarity index 100% rename from gamestonk_terminal/sentiment/google_api.py rename to gamestonk_terminal/behavioural_analysis/google_view.py diff --git a/gamestonk_terminal/sentiment/reddit_api.py b/gamestonk_terminal/behavioural_analysis/reddit_view.py similarity index 99% rename from gamestonk_terminal/sentiment/reddit_api.py rename to gamestonk_terminal/behavioural_analysis/reddit_view.py index ae51bde4e86..5093b2c4658 100644 --- a/gamestonk_terminal/sentiment/reddit_api.py +++ b/gamestonk_terminal/behavioural_analysis/reddit_view.py @@ -17,6 +17,7 @@ from gamestonk_terminal.reddit_helpers import ( def watchlist(l_args): + # other_args: List[str] parser = argparse.ArgumentParser( add_help=False, prog="watchlist", diff --git a/gamestonk_terminal/sentiment/sen_menu.py b/gamestonk_terminal/behavioural_analysis/sen_menu.py similarity index 100% rename from gamestonk_terminal/sentiment/sen_menu.py rename to gamestonk_terminal/behavioural_analysis/sen_menu.py diff --git a/gamestonk_terminal/sentiment/stocktwits_api.py b/gamestonk_terminal/behavioural_analysis/stocktwits_view.py similarity index 100% rename from gamestonk_terminal/sentiment/stocktwits_api.py rename to gamestonk_terminal/behavioural_analysis/stocktwits_view.py diff --git a/gamestonk_terminal/sentiment/twitter_api.py b/gamestonk_terminal/behavioural_analysis/twitter_view.py similarity index 99% rename from gamestonk_terminal/sentiment/twitter_api.py rename to gamestonk_terminal/behavioural_analysis/twitter_view.py index ca31ee737a7..dcad4037e8d 100644 --- a/gamestonk_terminal/sentiment/twitter_api.py +++ b/gamestonk_terminal/behavioural_analysis/twitter_view.py @@ -357,6 +357,7 @@ def sentiment(l_args, s_ticker): df_tweets["created_at"].values[0], "%Y-%m-%d %H:%M:%S" ).day n_idx = 0 + n_next_idx = 0 for n_next_idx, dt_created in enumerate(df_tweets["created_at"]): if datetime.strptime(dt_created, "%Y-%m-%d %H:%M:%S").day > n_day: l_xticks.append(n_next_idx) diff --git a/gamestonk_terminal/main_helper.py b/gamestonk_terminal/main_helper.py index 78272a3b092..ce0b0e4d46c 100644 --- a/gamestonk_terminal/main_helper.py +++ b/gamestonk_terminal/main_helper.py @@ -50,14 +50,14 @@ def print_help(s_ticker, s_start, s_interval, b_is_market_open): " disc discover trending stocks, \t e.g. map, sectors, high short interest" ) print(" mill papermill menu, \t\t\t menu to generate notebook reports") - print( - " sen sentiment of the market, \t from: reddit, stocktwits, twitter" - ) print( " fred economic data, \t\t\t from: Federal Reserve Bank of St. Louis " ) if s_ticker: + print( + " ba behavioural analysis, \t\t\t from: reddit, stocktwits, twitter" + ) print( " res research web page, \t e.g.: macroaxis, yahoo finance, fool" ) diff --git a/terminal.py b/terminal.py index 7fdcdf2f797..4e826a1e686 100644 --- a/terminal.py +++ b/terminal.py @@ -19,7 +19,7 @@ from gamestonk_terminal.helper_funcs import b_is_stock_market_open, get_flair from gamestonk_terminal.main_helper import clear, export, load, print_help, view, candle from gamestonk_terminal.menu import session from gamestonk_terminal.papermill import papermill_controller as mill -from gamestonk_terminal.sentiment import sen_menu as sm +from gamestonk_terminal.behavioural_analysis import ba_controller from gamestonk_terminal.technical_analysis import ta_menu as tam from gamestonk_terminal.comparison_analysis import ca_menu as cam from gamestonk_terminal.fred import fred_menu as fm @@ -65,7 +65,7 @@ def main(): "export", "disc", "mill", - "sen", + "ba", "res", "fa", "ta", @@ -162,8 +162,8 @@ def main(): elif ns_known_args.opt == "mill": b_quit = mill.papermill_menu() - elif ns_known_args.opt == "sen": - b_quit = sm.sen_menu(s_ticker, s_start) + elif ns_known_args.opt == "ba": + b_quit = ba_controller.menu(s_ticker, s_start) elif ns_known_args.opt == "res": b_quit = rm.res_menu(s_ticker, s_start, s_interval)