mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-29 05:21:48 +00:00
* ycrv bug * fred search multiple, test fix * ba/interest to allow multiple words * Fixes #3642 * Date logic * debug
909 lines
32 KiB
Python
909 lines
32 KiB
Python
"""Behavioural Analysis Controller Module"""
|
|
__docformat__ = "numpy"
|
|
|
|
import argparse
|
|
import logging
|
|
from datetime import datetime, timedelta
|
|
from typing import List
|
|
|
|
import yfinance as yf
|
|
|
|
from openbb_terminal.custom_prompt_toolkit import NestedCompleter
|
|
|
|
from openbb_terminal import feature_flags as obbff
|
|
from openbb_terminal.common.behavioural_analysis import (
|
|
finbrain_view,
|
|
google_view,
|
|
reddit_view,
|
|
stocktwits_view,
|
|
twitter_view,
|
|
)
|
|
from openbb_terminal.stocks.behavioural_analysis import finnhub_view, cramer_view
|
|
from openbb_terminal.decorators import log_start_end
|
|
from openbb_terminal.helper_funcs import (
|
|
EXPORT_BOTH_RAW_DATA_AND_FIGURES,
|
|
EXPORT_ONLY_RAW_DATA_ALLOWED,
|
|
check_int_range,
|
|
check_positive,
|
|
valid_date,
|
|
)
|
|
from openbb_terminal.menu import session
|
|
from openbb_terminal.parent_classes import StockBaseController
|
|
from openbb_terminal.rich_config import console, MenuText
|
|
|
|
# pylint:disable=R0904,C0302
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class BehaviouralAnalysisController(StockBaseController):
|
|
"""Behavioural Analysis Controller class"""
|
|
|
|
CHOICES_COMMANDS = [
|
|
"load",
|
|
"watchlist",
|
|
"spac",
|
|
"spacc",
|
|
"wsb",
|
|
"popular",
|
|
"bullbear",
|
|
"messages",
|
|
"trending",
|
|
"stalker",
|
|
"infer",
|
|
"sentiment",
|
|
"redditsent",
|
|
"mentions",
|
|
"regions",
|
|
"queries",
|
|
"rise",
|
|
"headlines",
|
|
"popular",
|
|
"getdd",
|
|
"snews",
|
|
"interest",
|
|
]
|
|
|
|
historical_sort = ["date", "value"]
|
|
historical_direction = ["asc", "desc"]
|
|
historical_metric = ["sentiment", "AHI", "RHI", "SGP"]
|
|
reddit_sort = ["relevance", "hot", "top", "new", "comments"]
|
|
reddit_time = ["hour", "day", "week", "month", "year", "all"]
|
|
PATH = "/stocks/ba/"
|
|
CHOICES_GENERATION = True
|
|
|
|
def __init__(self, ticker: str, start: datetime, queue: List[str] = None):
|
|
"""Constructor"""
|
|
super().__init__(queue)
|
|
|
|
self.ticker = ticker
|
|
self.start = start
|
|
|
|
if session and obbff.USE_PROMPT_TOOLKIT:
|
|
choices: dict = self.choices_default
|
|
|
|
self.completer = NestedCompleter.from_nested_dict(choices)
|
|
|
|
def print_help(self):
|
|
"""Print help"""
|
|
mt = MenuText("stocks/ba/")
|
|
mt.add_cmd("load")
|
|
mt.add_raw("\n")
|
|
mt.add_param("_ticker", self.ticker.upper())
|
|
mt.add_raw("\n")
|
|
mt.add_cmd("headlines", self.ticker)
|
|
mt.add_cmd("snews", self.ticker)
|
|
mt.add_cmd("wsb")
|
|
mt.add_cmd("watchlist")
|
|
mt.add_cmd("popular")
|
|
mt.add_cmd("spacc")
|
|
mt.add_cmd("spac")
|
|
mt.add_cmd("getdd", self.ticker)
|
|
mt.add_cmd("redditsent", self.ticker)
|
|
mt.add_cmd("trending")
|
|
mt.add_cmd("stalker")
|
|
mt.add_cmd("bullbear", self.ticker)
|
|
mt.add_cmd("messages", self.ticker)
|
|
mt.add_cmd("infer", self.ticker)
|
|
mt.add_cmd("sentiment", self.ticker)
|
|
mt.add_cmd("mentions", self.ticker)
|
|
mt.add_cmd("regions", self.ticker)
|
|
mt.add_cmd("interest", self.ticker)
|
|
mt.add_cmd("queries", self.ticker)
|
|
mt.add_cmd("rise", self.ticker)
|
|
console.print(text=mt.menu_text, menu="Stocks - Behavioural Analysis")
|
|
|
|
def custom_reset(self):
|
|
"""Class specific component of reset command"""
|
|
if self.ticker:
|
|
return ["stocks", "ba", f"load {self.ticker}"]
|
|
return []
|
|
|
|
@log_start_end(log=logger)
|
|
def call_watchlist(self, other_args: List[str]):
|
|
"""Process watchlist command"""
|
|
parser = argparse.ArgumentParser(
|
|
add_help=False,
|
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
prog="watchlist",
|
|
description="""Print other users watchlist. [Source: Reddit]""",
|
|
)
|
|
parser.add_argument(
|
|
"-l",
|
|
"--limit",
|
|
action="store",
|
|
dest="limit",
|
|
type=check_positive,
|
|
default=5,
|
|
help="limit of posts with watch lists retrieved.",
|
|
)
|
|
if other_args and "-" not in other_args[0][0]:
|
|
other_args.insert(0, "-l")
|
|
ns_parser = self.parse_known_args_and_warn(parser, other_args)
|
|
if ns_parser:
|
|
reddit_view.display_watchlist(limit=ns_parser.limit)
|
|
|
|
@log_start_end(log=logger)
|
|
def call_snews(self, other_args: List[str]):
|
|
"""Process snews command"""
|
|
parser = argparse.ArgumentParser(
|
|
add_help=False,
|
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
prog="snews",
|
|
description="Display stock price and headlines sentiment using VADER model over time. [Source: Finnhub]",
|
|
)
|
|
ns_parser = self.parse_known_args_and_warn(
|
|
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
|
|
)
|
|
if ns_parser:
|
|
finnhub_view.display_stock_price_headlines_sentiment(
|
|
symbol=self.ticker, export=ns_parser.export
|
|
)
|
|
|
|
@log_start_end(log=logger)
|
|
def call_spac(self, other_args: List[str]):
|
|
"""Process spac command"""
|
|
parser = argparse.ArgumentParser(
|
|
add_help=False,
|
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
prog="spac",
|
|
description="""Show other users SPACs announcement. [Source: Reddit]""",
|
|
)
|
|
parser.add_argument(
|
|
"-l",
|
|
"--limit",
|
|
action="store",
|
|
dest="n_limit",
|
|
type=check_positive,
|
|
default=5,
|
|
help="limit of posts with SPACs retrieved.",
|
|
)
|
|
if other_args and "-" not in other_args[0][0]:
|
|
other_args.insert(0, "-l")
|
|
ns_parser = self.parse_known_args_and_warn(parser, other_args)
|
|
if ns_parser:
|
|
reddit_view.display_spac(limit=ns_parser.n_limit)
|
|
|
|
@log_start_end(log=logger)
|
|
def call_spacc(self, other_args: List[str]):
|
|
"""Process spacc command"""
|
|
parser = argparse.ArgumentParser(
|
|
add_help=False,
|
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
prog="spacc",
|
|
description="""Print other users SPACs announcement under subreddit 'SPACs'. [Source: Reddit]""",
|
|
)
|
|
parser.add_argument(
|
|
"-l",
|
|
"--limit",
|
|
action="store",
|
|
dest="n_limit",
|
|
type=check_positive,
|
|
default=10,
|
|
help="limit of posts with SPACs retrieved",
|
|
)
|
|
parser.add_argument(
|
|
"-p",
|
|
"--popular",
|
|
action="store_true",
|
|
default=False,
|
|
dest="b_popular",
|
|
help="popular flag, if true the posts retrieved are based on score rather than time",
|
|
)
|
|
if other_args and "-" not in other_args[0][0]:
|
|
other_args.insert(0, "-l")
|
|
ns_parser = self.parse_known_args_and_warn(parser, other_args)
|
|
if ns_parser:
|
|
reddit_view.display_spac_community(
|
|
limit=ns_parser.n_limit, popular=ns_parser.b_popular
|
|
)
|
|
|
|
@log_start_end(log=logger)
|
|
def call_wsb(self, other_args: List[str]):
|
|
"""Process wsb command"""
|
|
parser = argparse.ArgumentParser(
|
|
add_help=False,
|
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
prog="wsb",
|
|
description="""Print what WSB gang are up to in subreddit wallstreetbets. [Source: Reddit]""",
|
|
)
|
|
parser.add_argument(
|
|
"-l",
|
|
"--limit",
|
|
action="store",
|
|
dest="n_limit",
|
|
type=check_positive,
|
|
default=10,
|
|
help="limit of posts to print.",
|
|
)
|
|
parser.add_argument(
|
|
"--new",
|
|
action="store_true",
|
|
default=False,
|
|
dest="b_new",
|
|
help="new flag, if true the posts retrieved are based on being more recent rather than their score.",
|
|
)
|
|
if other_args and "-" not in other_args[0][0]:
|
|
other_args.insert(0, "-l")
|
|
ns_parser = self.parse_known_args_and_warn(parser, other_args)
|
|
if ns_parser:
|
|
reddit_view.display_wsb_community(
|
|
limit=ns_parser.n_limit, new=ns_parser.b_new
|
|
)
|
|
|
|
@log_start_end(log=logger)
|
|
def call_popular(self, other_args: List[str]):
|
|
"""Process popular command"""
|
|
parser = argparse.ArgumentParser(
|
|
add_help=False,
|
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
prog="popular",
|
|
description="""Print latest popular tickers. [Source: Reddit]""",
|
|
)
|
|
parser.add_argument(
|
|
"-l",
|
|
"--limit",
|
|
action="store",
|
|
dest="limit",
|
|
type=check_positive,
|
|
default=10,
|
|
help="limit of top tickers to retrieve",
|
|
)
|
|
parser.add_argument(
|
|
"-n",
|
|
"--num",
|
|
action="store",
|
|
dest="num",
|
|
type=check_positive,
|
|
default=50,
|
|
help="number of posts retrieved per sub reddit.",
|
|
)
|
|
parser.add_argument(
|
|
"-s",
|
|
"--sub",
|
|
action="store",
|
|
dest="s_subreddit",
|
|
type=str,
|
|
help="""
|
|
Subreddits to look for tickers, e.g. pennystocks,stocks.
|
|
Default: pennystocks, RobinHoodPennyStocks, Daytrading, StockMarket, stocks, investing,
|
|
wallstreetbets
|
|
""",
|
|
)
|
|
if other_args and "-" not in other_args[0][0]:
|
|
other_args.insert(0, "-l")
|
|
ns_parser = self.parse_known_args_and_warn(parser, other_args)
|
|
if ns_parser:
|
|
reddit_view.display_popular_tickers(
|
|
limit=ns_parser.limit,
|
|
post_limit=ns_parser.num,
|
|
subreddits=ns_parser.s_subreddit,
|
|
)
|
|
|
|
@log_start_end(log=logger)
|
|
def call_getdd(self, other_args: List[str]):
|
|
"""Process getdd command"""
|
|
parser = argparse.ArgumentParser(
|
|
add_help=False,
|
|
prog="getdd",
|
|
description="""
|
|
Print top stock's due diligence from other users. [Source: Reddit]
|
|
""",
|
|
)
|
|
parser.add_argument(
|
|
"-l",
|
|
"--limit",
|
|
action="store",
|
|
dest="limit",
|
|
type=check_positive,
|
|
default=5,
|
|
help="limit of posts to retrieve.",
|
|
)
|
|
parser.add_argument(
|
|
"-d",
|
|
"--days",
|
|
action="store",
|
|
dest="days",
|
|
type=check_positive,
|
|
default=3,
|
|
help="number of prior days to look for.",
|
|
)
|
|
parser.add_argument(
|
|
"-a",
|
|
"--all",
|
|
action="store_true",
|
|
dest="all",
|
|
default=False,
|
|
help="""
|
|
search through all flairs (apart from Yolo and Meme), otherwise we focus on
|
|
specific flairs: DD, technical analysis, Catalyst, News, Advice, Chart""",
|
|
)
|
|
if other_args and "-" not in other_args[0][0]:
|
|
other_args.insert(0, "-l")
|
|
ns_parser = self.parse_known_args_and_warn(parser, other_args)
|
|
if ns_parser:
|
|
if self.ticker:
|
|
reddit_view.display_due_diligence(
|
|
symbol=self.ticker,
|
|
limit=ns_parser.limit,
|
|
n_days=ns_parser.days,
|
|
show_all_flairs=ns_parser.all,
|
|
)
|
|
else:
|
|
console.print("No ticker loaded. Please load using 'load <ticker>'\n")
|
|
|
|
@log_start_end(log=logger)
|
|
def call_redditsent(self, other_args: List[str]):
|
|
"""Process redditsent command"""
|
|
parser = argparse.ArgumentParser(
|
|
add_help=False,
|
|
prog="redditsent",
|
|
description="""
|
|
Determine general Reddit sentiment about a ticker. [Source: Reddit]
|
|
""",
|
|
)
|
|
parser.add_argument(
|
|
"-s",
|
|
"--sort",
|
|
action="store",
|
|
dest="sort",
|
|
choices=self.reddit_sort,
|
|
default="relevance",
|
|
help="search sorting type",
|
|
)
|
|
parser.add_argument(
|
|
"-c",
|
|
"--company",
|
|
action="store",
|
|
dest="company",
|
|
default=None,
|
|
help="explicit name of company to search for, will override ticker symbol",
|
|
)
|
|
parser.add_argument(
|
|
"--subreddits",
|
|
action="store",
|
|
dest="subreddits",
|
|
default="all",
|
|
help="comma-separated list of subreddits to search",
|
|
)
|
|
parser.add_argument(
|
|
"-l",
|
|
"--limit",
|
|
action="store",
|
|
dest="limit",
|
|
default=10,
|
|
type=check_positive,
|
|
help="how many posts to gather from each subreddit",
|
|
)
|
|
parser.add_argument(
|
|
"-t",
|
|
"--time",
|
|
action="store",
|
|
dest="time",
|
|
default="week",
|
|
choices=self.reddit_time,
|
|
help="time period to get posts from -- all, year, month, week, or day; defaults to week",
|
|
)
|
|
parser.add_argument(
|
|
"--full",
|
|
action="store_true",
|
|
dest="full_search",
|
|
default=False,
|
|
help="enable comprehensive search",
|
|
)
|
|
parser.add_argument(
|
|
"-g",
|
|
"--graphic",
|
|
action="store_true",
|
|
dest="graphic",
|
|
default=True,
|
|
help="display graphic",
|
|
)
|
|
parser.add_argument(
|
|
"-d",
|
|
"--display",
|
|
action="store_true",
|
|
dest="display",
|
|
default=False,
|
|
help="Print table of sentiment values",
|
|
)
|
|
if other_args and "-" not in other_args[0][0]:
|
|
other_args.insert(0, "-l")
|
|
ns_parser = self.parse_known_args_and_warn(
|
|
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
|
|
)
|
|
if ns_parser:
|
|
ticker = ns_parser.company if ns_parser.company else self.ticker
|
|
if self.ticker:
|
|
reddit_view.display_redditsent(
|
|
symbol=ticker,
|
|
sortby=ns_parser.sort,
|
|
limit=ns_parser.limit,
|
|
graphic=ns_parser.graphic,
|
|
time_frame=ns_parser.time,
|
|
full_search=ns_parser.full_search,
|
|
subreddits=ns_parser.subreddits,
|
|
export=ns_parser.export,
|
|
display=ns_parser.display,
|
|
)
|
|
else:
|
|
console.print("No ticker loaded. Please load using 'load <ticker>'\n")
|
|
|
|
@log_start_end(log=logger)
|
|
def call_bullbear(self, other_args: List[str]):
|
|
"""Process bullbear command"""
|
|
parser = argparse.ArgumentParser(
|
|
add_help=False,
|
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
prog="bullbear",
|
|
description="""
|
|
Print bullbear sentiment based on last 30 messages on the board.
|
|
Also prints the watchlist_count. [Source: Stocktwits]
|
|
""",
|
|
)
|
|
ns_parser = self.parse_known_args_and_warn(parser, other_args)
|
|
if ns_parser:
|
|
if self.ticker:
|
|
stocktwits_view.display_bullbear(symbol=self.ticker)
|
|
else:
|
|
console.print("No ticker loaded. Please load using 'load <ticker>'\n")
|
|
|
|
@log_start_end(log=logger)
|
|
def call_messages(self, other_args: List[str]):
|
|
"""Process messages command"""
|
|
parser = argparse.ArgumentParser(
|
|
add_help=False,
|
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
prog="messages",
|
|
description="""Print up to 30 of the last messages on the board. [Source: Stocktwits]""",
|
|
)
|
|
parser.add_argument(
|
|
"-l",
|
|
"--limit",
|
|
action="store",
|
|
dest="limit",
|
|
type=check_positive,
|
|
default=30,
|
|
help="limit messages shown.",
|
|
)
|
|
if other_args and "-" not in other_args[0][0]:
|
|
other_args.insert(0, "-l")
|
|
ns_parser = self.parse_known_args_and_warn(parser, other_args)
|
|
if ns_parser:
|
|
if self.ticker:
|
|
stocktwits_view.display_messages(
|
|
symbol=self.ticker, limit=ns_parser.limit
|
|
)
|
|
else:
|
|
console.print("No ticker loaded. Please load using 'load <ticker>'\n")
|
|
|
|
@log_start_end(log=logger)
|
|
def call_trending(self, other_args: List[str]):
|
|
"""Process trending command"""
|
|
parser = argparse.ArgumentParser(
|
|
add_help=False,
|
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
prog="trending",
|
|
description="""Stocks trending. [Source: Stocktwits]""",
|
|
)
|
|
ns_parser = self.parse_known_args_and_warn(parser, other_args)
|
|
if ns_parser:
|
|
stocktwits_view.display_trending()
|
|
|
|
@log_start_end(log=logger)
|
|
def call_stalker(self, other_args: List[str]):
|
|
"""Process stalker command"""
|
|
parser = argparse.ArgumentParser(
|
|
add_help=False,
|
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
prog="stalker",
|
|
description="""Print up to the last 30 messages of a user. [Source: Stocktwits]""",
|
|
)
|
|
parser.add_argument(
|
|
"-u",
|
|
"--user",
|
|
action="store",
|
|
dest="s_user",
|
|
type=str,
|
|
default="Newsfilter",
|
|
help="username.",
|
|
)
|
|
parser.add_argument(
|
|
"-l",
|
|
"--limit",
|
|
action="store",
|
|
dest="limit",
|
|
type=check_positive,
|
|
default=30,
|
|
help="limit messages shown.",
|
|
)
|
|
if other_args and "-" not in other_args[0][0]:
|
|
other_args.insert(0, "-l")
|
|
ns_parser = self.parse_known_args_and_warn(
|
|
parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED
|
|
)
|
|
if ns_parser:
|
|
stocktwits_view.display_stalker(
|
|
user=ns_parser.s_user, limit=ns_parser.limit
|
|
)
|
|
|
|
@log_start_end(log=logger)
|
|
def call_mentions(self, other_args: List[str]):
|
|
"""Process mentions command"""
|
|
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=self.start if self.start != "" else "2000-01-01",
|
|
help="starting date (format YYYY-MM-DD) from when we are interested in stock's mentions.",
|
|
)
|
|
if other_args and "-" not in other_args[0][0]:
|
|
other_args.insert(0, "-s")
|
|
ns_parser = self.parse_known_args_and_warn(
|
|
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
|
|
)
|
|
if ns_parser:
|
|
if self.ticker:
|
|
google_view.display_mentions(
|
|
symbol=self.ticker,
|
|
start_date=ns_parser.start,
|
|
export=ns_parser.export,
|
|
)
|
|
else:
|
|
console.print("No ticker loaded. Please load using 'load <ticker>'\n")
|
|
|
|
@log_start_end(log=logger)
|
|
def call_regions(self, other_args: List[str]):
|
|
"""Process regions command"""
|
|
parser = argparse.ArgumentParser(
|
|
add_help=False,
|
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
prog="regions",
|
|
description="""Plot bars of regions based on stock's interest. [Source: Google]""",
|
|
)
|
|
parser.add_argument(
|
|
"-l",
|
|
"--limit",
|
|
action="store",
|
|
dest="limit",
|
|
type=check_positive,
|
|
default=10,
|
|
help="limit of regions to plot that show highest interest.",
|
|
)
|
|
if other_args and "-" not in other_args[0][0]:
|
|
other_args.insert(0, "-l")
|
|
ns_parser = self.parse_known_args_and_warn(
|
|
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
|
|
)
|
|
if ns_parser:
|
|
if self.ticker:
|
|
google_view.display_regions(
|
|
symbol=self.ticker, limit=ns_parser.limit, export=ns_parser.export
|
|
)
|
|
else:
|
|
console.print("No ticker loaded. Please load using 'load <ticker>'\n")
|
|
|
|
@log_start_end(log=logger)
|
|
def call_interest(self, other_args: List[str]):
|
|
"""Process interest command"""
|
|
parser = argparse.ArgumentParser(
|
|
add_help=False,
|
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
prog="interest",
|
|
description="""
|
|
Plot interest over time of words/sentences versus stock price. [Source: Google]
|
|
""",
|
|
)
|
|
parser.add_argument(
|
|
"-s",
|
|
"--start",
|
|
type=valid_date,
|
|
dest="start",
|
|
default=(datetime.now() - timedelta(days=2 * 366)).strftime("%Y-%m-%d"),
|
|
help="starting date (format YYYY-MM-DD) of interest",
|
|
)
|
|
parser.add_argument(
|
|
"-w",
|
|
"--words",
|
|
help="Select multiple sentences/words separated by commas. E.g. COVID,WW3,NFT",
|
|
dest="words",
|
|
nargs="+",
|
|
type=str,
|
|
default=None,
|
|
)
|
|
if other_args and "-" not in other_args[0][0]:
|
|
other_args.insert(0, "-w")
|
|
ns_parser = self.parse_known_args_and_warn(
|
|
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
|
|
)
|
|
if ns_parser:
|
|
if self.ticker:
|
|
if ns_parser.words:
|
|
words = " ".join(ns_parser.words).split(",")
|
|
df_stock = yf.download(
|
|
self.ticker,
|
|
start=ns_parser.start.strftime("%Y-%m-%d"),
|
|
progress=False,
|
|
)
|
|
|
|
if not df_stock.empty:
|
|
google_view.display_correlation_interest(
|
|
symbol=self.ticker,
|
|
data=df_stock,
|
|
words=words,
|
|
export=ns_parser.export,
|
|
)
|
|
else:
|
|
console.print(
|
|
"[red]Ticker provided doesn't exist, load another one.\n[/red]"
|
|
)
|
|
else:
|
|
console.print("[red]Please provide a phrase for analysis.\n[/red]")
|
|
else:
|
|
console.print(
|
|
"[red]No ticker loaded. Please load using 'load <ticker>'.\n[/red]"
|
|
)
|
|
|
|
@log_start_end(log=logger)
|
|
def call_queries(self, other_args: List[str]):
|
|
"""Process queries command"""
|
|
parser = argparse.ArgumentParser(
|
|
add_help=False,
|
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
prog="queries",
|
|
description="""Print top related queries with this stock's query. [Source: Google]""",
|
|
)
|
|
parser.add_argument(
|
|
"-l",
|
|
"--limit",
|
|
action="store",
|
|
dest="limit",
|
|
type=check_positive,
|
|
default=10,
|
|
help="limit of top related queries to print.",
|
|
)
|
|
if other_args and "-" not in other_args[0][0]:
|
|
other_args.insert(0, "-l")
|
|
ns_parser = self.parse_known_args_and_warn(
|
|
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
|
|
)
|
|
if ns_parser:
|
|
if self.ticker:
|
|
google_view.display_queries(
|
|
symbol=self.ticker, limit=ns_parser.limit, export=ns_parser.export
|
|
)
|
|
else:
|
|
console.print("No ticker loaded. Please load using 'load <ticker>'\n")
|
|
|
|
@log_start_end(log=logger)
|
|
def call_rise(self, other_args: List[str]):
|
|
"""Process rise command"""
|
|
parser = argparse.ArgumentParser(
|
|
add_help=False,
|
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
prog="rise",
|
|
description="""Print top rising related queries with this stock's query. [Source: Google]""",
|
|
)
|
|
parser.add_argument(
|
|
"-l",
|
|
"--limit",
|
|
action="store",
|
|
dest="limit",
|
|
type=check_positive,
|
|
default=10,
|
|
help="limit of top rising related queries to print.",
|
|
)
|
|
if other_args and "-" not in other_args[0][0]:
|
|
other_args.insert(0, "-l")
|
|
ns_parser = self.parse_known_args_and_warn(
|
|
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
|
|
)
|
|
if ns_parser:
|
|
if self.ticker:
|
|
google_view.display_rise(
|
|
symbol=self.ticker, limit=ns_parser.limit, export=ns_parser.export
|
|
)
|
|
else:
|
|
console.print("No ticker loaded. Please load using 'load <ticker>'\n")
|
|
|
|
@log_start_end(log=logger)
|
|
def call_infer(self, other_args: List[str]):
|
|
"""Process infer command"""
|
|
parser = argparse.ArgumentParser(
|
|
add_help=False,
|
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
prog="infer",
|
|
description="""
|
|
Print quick sentiment inference from last tweets that contain the ticker.
|
|
This model splits the text into character-level tokens and uses vader sentiment analysis.
|
|
[Source: Twitter]
|
|
""",
|
|
)
|
|
parser.add_argument(
|
|
"-l",
|
|
"--limit",
|
|
action="store",
|
|
dest="limit",
|
|
type=check_int_range(10, 100),
|
|
default=100,
|
|
help="limit of latest tweets to infer from.",
|
|
)
|
|
if other_args and "-" not in other_args[0][0]:
|
|
other_args.insert(0, "-l")
|
|
ns_parser = self.parse_known_args_and_warn(
|
|
parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED
|
|
)
|
|
if ns_parser:
|
|
if self.ticker:
|
|
twitter_view.display_inference(
|
|
symbol=self.ticker, limit=ns_parser.limit
|
|
)
|
|
else:
|
|
console.print("No ticker loaded. Please load using 'load <ticker>'\n")
|
|
|
|
@log_start_end(log=logger)
|
|
def call_sentiment(self, other_args: List[str]):
|
|
"""Process sentiment command"""
|
|
parser = argparse.ArgumentParser(
|
|
add_help=False,
|
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
prog="sentiment",
|
|
description="""
|
|
Plot in-depth sentiment predicted from tweets from last days
|
|
that contain pre-defined ticker. [Source: Twitter]
|
|
""",
|
|
)
|
|
# in reality this argument could be 100, but after testing it takes too long
|
|
# to compute which may not be acceptable
|
|
# TODO: use https://github.com/twintproject/twint instead of twitter API
|
|
parser.add_argument(
|
|
"-l",
|
|
"--limit",
|
|
action="store",
|
|
dest="limit",
|
|
type=check_int_range(10, 62),
|
|
default=15,
|
|
help="limit of tweets to extract per hour.",
|
|
)
|
|
parser.add_argument(
|
|
"-d",
|
|
"--days",
|
|
action="store",
|
|
dest="n_days_past",
|
|
type=check_int_range(1, 6),
|
|
default=6,
|
|
help="number of days in the past to extract tweets.",
|
|
)
|
|
parser.add_argument(
|
|
"-c",
|
|
"--compare",
|
|
action="store_true",
|
|
dest="compare",
|
|
help="show corresponding change in stock price",
|
|
)
|
|
if other_args and "-" not in other_args[0][0]:
|
|
other_args.insert(0, "-l")
|
|
ns_parser = self.parse_known_args_and_warn(
|
|
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES
|
|
)
|
|
if ns_parser:
|
|
if self.ticker:
|
|
twitter_view.display_sentiment(
|
|
symbol=self.ticker,
|
|
n_tweets=ns_parser.limit,
|
|
n_days_past=ns_parser.n_days_past,
|
|
compare=ns_parser.compare,
|
|
export=ns_parser.export,
|
|
)
|
|
else:
|
|
console.print("No ticker loaded. Please load using 'load <ticker>'\n")
|
|
|
|
@log_start_end(log=logger)
|
|
def call_headlines(self, other_args: List[str]):
|
|
"""Process finbrain command"""
|
|
parser = argparse.ArgumentParser(
|
|
add_help=False,
|
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
prog="headlines",
|
|
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]""",
|
|
)
|
|
ns_parser = self.parse_known_args_and_warn(
|
|
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES, raw=True
|
|
)
|
|
if ns_parser:
|
|
if self.ticker:
|
|
finbrain_view.display_sentiment_analysis(
|
|
symbol=self.ticker, raw=ns_parser.raw, export=ns_parser.export
|
|
)
|
|
else:
|
|
console.print("No ticker loaded. Please load using 'load <ticker>'\n")
|
|
|
|
def call_jcdr(self, other_args: List[str]):
|
|
"""Process jcdr command"""
|
|
parser = argparse.ArgumentParser(
|
|
add_help=False,
|
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
prog="jcdr",
|
|
description="""
|
|
Show daily cramer recommendation
|
|
""",
|
|
)
|
|
parser.add_argument(
|
|
"-i",
|
|
"--inverse",
|
|
default=False,
|
|
action="store_true",
|
|
help="Show inverse recommendation",
|
|
dest="inverse",
|
|
)
|
|
|
|
ns_parser = self.parse_known_args_and_warn(
|
|
parser, other_args, export_allowed=EXPORT_ONLY_RAW_DATA_ALLOWED
|
|
)
|
|
|
|
if ns_parser:
|
|
cramer_view.display_cramer_daily(inverse=ns_parser.inverse)
|
|
|
|
@log_start_end(log=logger)
|
|
def call_jctr(self, other_args: List[str]):
|
|
"""Process jctr command"""
|
|
parser = argparse.ArgumentParser(
|
|
add_help=False,
|
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
prog="jctr",
|
|
description="""
|
|
Show cramer recommendation for loaded ticker
|
|
""",
|
|
)
|
|
ns_parser = self.parse_known_args_and_warn(
|
|
parser,
|
|
other_args,
|
|
export_allowed=EXPORT_BOTH_RAW_DATA_AND_FIGURES,
|
|
raw=True,
|
|
)
|
|
|
|
if ns_parser:
|
|
if self.ticker:
|
|
cramer_view.display_cramer_ticker(
|
|
symbol=self.ticker, raw=ns_parser.raw, export=ns_parser.export
|
|
)
|
|
else:
|
|
console.print(
|
|
"[red]No ticker loaded. Please use load <ticker> first.\n[/red]"
|
|
)
|