mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-11-02 15:32:04 +00:00
697 lines
25 KiB
Python
697 lines
25 KiB
Python
import argparse
|
|
import warnings
|
|
import pandas as pd
|
|
from prawcore.exceptions import ResponseException
|
|
from requests import HTTPError
|
|
from psaw import PushshiftAPI
|
|
import praw
|
|
import finviz
|
|
from gamestonk_terminal.helper_funcs import check_positive, parse_known_args_and_warn
|
|
from gamestonk_terminal import config_terminal as cfg
|
|
from gamestonk_terminal.reddit_helpers import (
|
|
print_and_record_reddit_post,
|
|
find_tickers,
|
|
)
|
|
|
|
|
|
def watchlist(l_args):
|
|
parser = argparse.ArgumentParser(
|
|
add_help=False,
|
|
prog="watchlist",
|
|
description="""Print other users watchlist. [Source: Reddit]""",
|
|
)
|
|
parser.add_argument(
|
|
"-l",
|
|
"--limit",
|
|
action="store",
|
|
dest="n_limit",
|
|
type=check_positive,
|
|
default=5,
|
|
help="limit of posts with watchlists retrieved.",
|
|
)
|
|
|
|
try:
|
|
ns_parser = parse_known_args_and_warn(parser, l_args)
|
|
if not ns_parser:
|
|
return
|
|
|
|
l_sub_reddits = [
|
|
"Superstonk",
|
|
"pennystocks",
|
|
"RobinHoodPennyStocks",
|
|
"Daytrading",
|
|
"StockMarket",
|
|
"stocks",
|
|
"investing",
|
|
"wallstreetbets",
|
|
]
|
|
|
|
d_submission = {}
|
|
d_watchlist_tickers = {}
|
|
l_watchlist_links = list()
|
|
l_watchlist_author = list()
|
|
|
|
praw_api = praw.Reddit(
|
|
client_id=cfg.API_REDDIT_CLIENT_ID,
|
|
client_secret=cfg.API_REDDIT_CLIENT_SECRET,
|
|
username=cfg.API_REDDIT_USERNAME,
|
|
user_agent=cfg.API_REDDIT_USER_AGENT,
|
|
password=cfg.API_REDDIT_PASSWORD,
|
|
)
|
|
|
|
# dt_last_time_market_close = get_last_time_market_was_open(
|
|
# datetime.now() - timedelta(hours=24)
|
|
# )
|
|
# n_ts_after = int(dt_last_time_market_close.timestamp())
|
|
psaw_api = PushshiftAPI()
|
|
submissions = psaw_api.search_submissions(
|
|
# after=n_ts_after,
|
|
subreddit=l_sub_reddits,
|
|
q="WATCHLIST|Watchlist|watchlist",
|
|
filter=["id"],
|
|
)
|
|
|
|
n_flair_posts_found = 0
|
|
while True:
|
|
try:
|
|
submission = next(submissions, None)
|
|
|
|
# Check if search_submissions didn't get anymore posts
|
|
if not submission:
|
|
break
|
|
|
|
# Get more information about post using PRAW api
|
|
submission = praw_api.submission(id=submission.id)
|
|
|
|
# Ensure that the post hasn't been removed by moderator in the meanwhile,
|
|
# that there is a description and it's not just an image, that the flair is
|
|
# meaningful, and that we aren't re-considering same author's watchlist
|
|
if (
|
|
not submission.removed_by_category
|
|
and submission.selftext
|
|
and submission.link_flair_text not in ["Yolo", "Meme"]
|
|
and submission.author.name not in l_watchlist_author
|
|
):
|
|
l_tickers_found = find_tickers(submission)
|
|
|
|
if l_tickers_found:
|
|
# Add another author's name to the parsed watchlists
|
|
l_watchlist_author.append(submission.author.name)
|
|
|
|
# Lookup stock tickers within a watchlist
|
|
for key in l_tickers_found:
|
|
if key in d_watchlist_tickers:
|
|
# Increment stock ticker found
|
|
d_watchlist_tickers[key] += 1
|
|
else:
|
|
# Initialize stock ticker found
|
|
d_watchlist_tickers[key] = 1
|
|
|
|
l_watchlist_links.append(
|
|
f"https://old.reddit.com{submission.permalink}"
|
|
)
|
|
|
|
print_and_record_reddit_post(d_submission, submission)
|
|
|
|
# Increment count of valid posts found
|
|
n_flair_posts_found += 1
|
|
|
|
# Check if number of wanted posts found has been reached
|
|
if n_flair_posts_found > ns_parser.n_limit - 1:
|
|
break
|
|
except ResponseException:
|
|
print(
|
|
"Received a response from Reddit with an authorization error. check your token.\n"
|
|
)
|
|
return
|
|
|
|
if n_flair_posts_found:
|
|
lt_watchlist_sorted = sorted(
|
|
d_watchlist_tickers.items(), key=lambda item: item[1], reverse=True
|
|
)
|
|
s_watchlist_tickers = ""
|
|
n_tickers = 0
|
|
for t_ticker in lt_watchlist_sorted:
|
|
try:
|
|
# If try doesn't trigger exception, it means that this stock exists on finviz
|
|
# thus we can print it.
|
|
finviz.get_stock(t_ticker[0])
|
|
if int(t_ticker[1]) > 1:
|
|
s_watchlist_tickers += f"{t_ticker[1]} {t_ticker[0]}, "
|
|
n_tickers += 1
|
|
except Exception:
|
|
# print(e, "\n")
|
|
pass
|
|
if n_tickers:
|
|
print(
|
|
"The following stock tickers have been mentioned more than once across the previous watchlists:"
|
|
)
|
|
print(s_watchlist_tickers[:-2] + "\n")
|
|
print("")
|
|
|
|
except Exception as e:
|
|
print(e, "\n")
|
|
print("")
|
|
|
|
|
|
def popular_tickers(l_args):
|
|
parser = argparse.ArgumentParser(
|
|
add_help=False,
|
|
prog="popular",
|
|
description="""Print latest popular tickers. [Source: Reddit] """,
|
|
)
|
|
parser.add_argument(
|
|
"-n",
|
|
"--number",
|
|
action="store",
|
|
dest="n_top",
|
|
type=check_positive,
|
|
default=10,
|
|
help="display top N tickers",
|
|
)
|
|
parser.add_argument(
|
|
"-l",
|
|
"--limit",
|
|
action="store",
|
|
dest="n_limit",
|
|
type=check_positive,
|
|
default=50,
|
|
help="limit 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
|
|
""",
|
|
)
|
|
|
|
try:
|
|
ns_parser = parse_known_args_and_warn(parser, l_args)
|
|
if not ns_parser:
|
|
return
|
|
|
|
# n_ts_after = int(
|
|
# (datetime.today() - timedelta(days=ns_parser.n_days)).timestamp()
|
|
# )
|
|
|
|
if ns_parser.s_subreddit:
|
|
if "," in ns_parser.s_subreddit:
|
|
l_sub_reddits = ns_parser.s_subreddit.split(",")
|
|
else:
|
|
l_sub_reddits = [ns_parser.s_subreddit]
|
|
else:
|
|
l_sub_reddits = [
|
|
"Superstonk",
|
|
"pennystocks",
|
|
"RobinHoodPennyStocks",
|
|
"Daytrading",
|
|
"StockMarket",
|
|
"stocks",
|
|
"investing",
|
|
"wallstreetbets",
|
|
]
|
|
|
|
# d_submission = {}
|
|
d_watchlist_tickers = {}
|
|
# l_watchlist_links = list()
|
|
l_watchlist_author = list()
|
|
|
|
praw_api = praw.Reddit(
|
|
client_id=cfg.API_REDDIT_CLIENT_ID,
|
|
client_secret=cfg.API_REDDIT_CLIENT_SECRET,
|
|
username=cfg.API_REDDIT_USERNAME,
|
|
user_agent=cfg.API_REDDIT_USER_AGENT,
|
|
password=cfg.API_REDDIT_PASSWORD,
|
|
)
|
|
|
|
psaw_api = PushshiftAPI()
|
|
|
|
for s_sub_reddit in l_sub_reddits:
|
|
print(
|
|
f"Search for latest tickers under {ns_parser.n_limit} '{s_sub_reddit}' posts"
|
|
)
|
|
submissions = psaw_api.search_submissions(
|
|
# after=int(n_ts_after),
|
|
subreddit=s_sub_reddit,
|
|
limit=ns_parser.n_limit,
|
|
filter=["id"],
|
|
)
|
|
|
|
n_tickers = 0
|
|
while True:
|
|
try:
|
|
submission = next(submissions, None)
|
|
if submission:
|
|
# Get more information about post using PRAW api
|
|
submission = praw_api.submission(id=submission.id)
|
|
|
|
# Ensure that the post hasn't been removed by moderator in the meanwhile,
|
|
# that there is a description and it's not just an image, that the flair is
|
|
# meaningful, and that we aren't re-considering same author's content
|
|
if (
|
|
not submission.removed_by_category
|
|
and (submission.selftext or submission.title)
|
|
and submission.author.name not in l_watchlist_author
|
|
):
|
|
l_tickers_found = find_tickers(submission)
|
|
|
|
if l_tickers_found:
|
|
n_tickers += len(l_tickers_found)
|
|
|
|
# Add another author's name to the parsed watchlists
|
|
l_watchlist_author.append(submission.author.name)
|
|
|
|
# Lookup stock tickers within a watchlist
|
|
for key in l_tickers_found:
|
|
if key in d_watchlist_tickers:
|
|
# Increment stock ticker found
|
|
d_watchlist_tickers[key] += 1
|
|
else:
|
|
# Initialize stock ticker found
|
|
d_watchlist_tickers[key] = 1
|
|
|
|
# Check if search_submissions didn't get anymore posts
|
|
else:
|
|
break
|
|
except ResponseException:
|
|
print(
|
|
"Received a response from Reddit with an authorization error. check your token.\n"
|
|
)
|
|
return
|
|
|
|
print(f" {n_tickers} potential tickers found.")
|
|
|
|
lt_watchlist_sorted = sorted(
|
|
d_watchlist_tickers.items(), key=lambda item: item[1], reverse=True
|
|
)
|
|
|
|
if lt_watchlist_sorted:
|
|
n_top_stocks = 0
|
|
# pylint: disable=redefined-outer-name
|
|
popular_tickers = []
|
|
for t_ticker in lt_watchlist_sorted:
|
|
if n_top_stocks > ns_parser.n_top:
|
|
break
|
|
try:
|
|
# If try doesn't trigger exception, it means that this stock exists on finviz
|
|
# thus we can print it.
|
|
stock_info = finviz.get_stock(t_ticker[0])
|
|
popular_tickers.append(
|
|
(
|
|
t_ticker[1],
|
|
t_ticker[0],
|
|
stock_info["Company"],
|
|
stock_info["Sector"],
|
|
stock_info["Price"],
|
|
stock_info["Change"],
|
|
stock_info["Perf Month"],
|
|
f"https://finviz.com/quote.ashx?t={t_ticker[0]}",
|
|
)
|
|
)
|
|
n_top_stocks += 1
|
|
except HTTPError as e:
|
|
if e.response.status_code != 404:
|
|
print(f"Unexpected exception from Finviz: {e}")
|
|
except Exception as e:
|
|
print(e, "\n")
|
|
return
|
|
|
|
popular_tickers_df = pd.DataFrame(
|
|
popular_tickers,
|
|
columns=[
|
|
"Mentions",
|
|
"Ticker",
|
|
"Company",
|
|
"Sector",
|
|
"Price",
|
|
"Change",
|
|
"Perf Month",
|
|
"URL",
|
|
],
|
|
)
|
|
|
|
print(f"\nThe following TOP {ns_parser.n_top} tickers have been mentioned:")
|
|
|
|
print(popular_tickers_df, "\n")
|
|
else:
|
|
print("No tickers found")
|
|
|
|
print("")
|
|
|
|
except ResponseException:
|
|
print(
|
|
"Received a response from Reddit with an authorization error. check your token.\n"
|
|
)
|
|
return
|
|
|
|
except Exception as e:
|
|
print(e, "\n")
|
|
|
|
|
|
def spac_community(l_args):
|
|
parser = argparse.ArgumentParser(
|
|
add_help=False,
|
|
prog="spac_c",
|
|
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",
|
|
)
|
|
|
|
try:
|
|
ns_parser = parse_known_args_and_warn(parser, l_args)
|
|
if not ns_parser:
|
|
return
|
|
|
|
praw_api = praw.Reddit(
|
|
client_id=cfg.API_REDDIT_CLIENT_ID,
|
|
client_secret=cfg.API_REDDIT_CLIENT_SECRET,
|
|
username=cfg.API_REDDIT_USERNAME,
|
|
user_agent=cfg.API_REDDIT_USER_AGENT,
|
|
password=cfg.API_REDDIT_PASSWORD,
|
|
)
|
|
|
|
d_submission = {}
|
|
d_watchlist_tickers = {}
|
|
l_watchlist_links = list()
|
|
l_watchlist_author = list()
|
|
|
|
# psaw_api = PushshiftAPI()
|
|
|
|
if ns_parser.b_popular:
|
|
submissions = praw_api.subreddit("SPACs").hot(limit=ns_parser.n_limit)
|
|
else:
|
|
submissions = praw_api.subreddit("SPACs").new(limit=ns_parser.n_limit)
|
|
|
|
while True:
|
|
try:
|
|
submission = next(submissions, None)
|
|
if submission:
|
|
# Get more information about post using PRAW api
|
|
submission = praw_api.submission(id=submission.id)
|
|
|
|
# Ensure that the post hasn't been removed by moderator in the meanwhile,
|
|
# that there is a description and it's not just an image, that the flair is
|
|
# meaningful, and that we aren't re-considering same author's watchlist
|
|
if (
|
|
not submission.removed_by_category
|
|
and submission.selftext
|
|
and submission.link_flair_text not in ["Yolo", "Meme"]
|
|
and submission.author.name not in l_watchlist_author
|
|
):
|
|
l_tickers_found = find_tickers(submission)
|
|
|
|
if l_tickers_found:
|
|
# Add another author's name to the parsed watchlists
|
|
l_watchlist_author.append(submission.author.name)
|
|
|
|
# Lookup stock tickers within a watchlist
|
|
for key in l_tickers_found:
|
|
if key in d_watchlist_tickers:
|
|
# Increment stock ticker found
|
|
d_watchlist_tickers[key] += 1
|
|
else:
|
|
# Initialize stock ticker found
|
|
d_watchlist_tickers[key] = 1
|
|
|
|
l_watchlist_links.append(
|
|
f"https://old.reddit.com{submission.permalink}"
|
|
)
|
|
|
|
print_and_record_reddit_post(d_submission, submission)
|
|
|
|
# Check if search_submissions didn't get anymore posts
|
|
else:
|
|
break
|
|
except ResponseException:
|
|
print(
|
|
"Received a response from Reddit with an authorization error. check your token.\n"
|
|
)
|
|
return
|
|
|
|
if d_watchlist_tickers:
|
|
lt_watchlist_sorted = sorted(
|
|
d_watchlist_tickers.items(), key=lambda item: item[1], reverse=True
|
|
)
|
|
s_watchlist_tickers = ""
|
|
n_tickers = 0
|
|
for t_ticker in lt_watchlist_sorted:
|
|
try:
|
|
# If try doesn't trigger exception, it means that this stock exists on finviz
|
|
# thus we can print it.
|
|
finviz.get_stock(t_ticker[0])
|
|
if int(t_ticker[1]) > 1:
|
|
s_watchlist_tickers += f"{t_ticker[1]} {t_ticker[0]}, "
|
|
n_tickers += 1
|
|
except Exception:
|
|
# print(e, "\n")
|
|
pass
|
|
|
|
if n_tickers:
|
|
print(
|
|
"The following stock tickers have been mentioned more than once across the previous SPACs:"
|
|
)
|
|
print(s_watchlist_tickers[:-2])
|
|
print("")
|
|
|
|
except Exception as e:
|
|
print(e, "\n")
|
|
|
|
|
|
def spac(l_args):
|
|
parser = argparse.ArgumentParser(
|
|
add_help=False,
|
|
prog="spac",
|
|
description=""" Show other users SPACs announcement [Reddit] """,
|
|
)
|
|
parser.add_argument(
|
|
"-l",
|
|
"--limit",
|
|
action="store",
|
|
dest="n_limit",
|
|
type=check_positive,
|
|
default=5,
|
|
help="limit of posts with SPACs retrieved.",
|
|
)
|
|
|
|
try:
|
|
ns_parser = parse_known_args_and_warn(parser, l_args)
|
|
if not ns_parser:
|
|
return
|
|
|
|
praw_api = praw.Reddit(
|
|
client_id=cfg.API_REDDIT_CLIENT_ID,
|
|
client_secret=cfg.API_REDDIT_CLIENT_SECRET,
|
|
username=cfg.API_REDDIT_USERNAME,
|
|
user_agent=cfg.API_REDDIT_USER_AGENT,
|
|
password=cfg.API_REDDIT_PASSWORD,
|
|
)
|
|
|
|
d_submission = {}
|
|
d_watchlist_tickers = {}
|
|
l_watchlist_links = list()
|
|
l_watchlist_author = list()
|
|
|
|
# n_ts_after = int(
|
|
# (datetime.today() - timedelta(days=ns_parser.n_days)).timestamp()
|
|
# )
|
|
l_sub_reddits = [
|
|
"Superstonk",
|
|
"pennystocks",
|
|
"RobinHoodPennyStocks",
|
|
"Daytrading",
|
|
"StockMarket",
|
|
"stocks",
|
|
"investing",
|
|
"wallstreetbets",
|
|
]
|
|
|
|
warnings.filterwarnings("ignore") # To avoid printing the warning
|
|
psaw_api = PushshiftAPI()
|
|
submissions = psaw_api.search_submissions(
|
|
# after=n_ts_after,
|
|
subreddit=l_sub_reddits,
|
|
q="SPAC|Spac|spac|Spacs|spacs",
|
|
filter=["id"],
|
|
)
|
|
n_flair_posts_found = 0
|
|
while True:
|
|
try:
|
|
submission = next(submissions, None)
|
|
if submission:
|
|
# Get more information about post using PRAW api
|
|
submission = praw_api.submission(id=submission.id)
|
|
|
|
# Ensure that the post hasn't been removed by moderator in the meanwhile,
|
|
# that there is a description and it's not just an image, that the flair is
|
|
# meaningful, and that we aren't re-considering same author's watchlist
|
|
if (
|
|
not submission.removed_by_category
|
|
and submission.selftext
|
|
and submission.link_flair_text not in ["Yolo", "Meme"]
|
|
and submission.author.name not in l_watchlist_author
|
|
):
|
|
l_tickers_found = find_tickers(submission)
|
|
|
|
if l_tickers_found:
|
|
# Add another author's name to the parsed watchlists
|
|
l_watchlist_author.append(submission.author.name)
|
|
|
|
# Lookup stock tickers within a watchlist
|
|
for key in l_tickers_found:
|
|
if key in d_watchlist_tickers:
|
|
# Increment stock ticker found
|
|
d_watchlist_tickers[key] += 1
|
|
else:
|
|
# Initialize stock ticker found
|
|
d_watchlist_tickers[key] = 1
|
|
|
|
l_watchlist_links.append(
|
|
f"https://old.reddit.com{submission.permalink}"
|
|
)
|
|
|
|
print_and_record_reddit_post(d_submission, submission)
|
|
|
|
# Increment count of valid posts found
|
|
n_flair_posts_found += 1
|
|
|
|
# Check if number of wanted posts found has been reached
|
|
if n_flair_posts_found > ns_parser.n_limit - 1:
|
|
break
|
|
|
|
# Check if search_submissions didn't get anymore posts
|
|
else:
|
|
break
|
|
except ResponseException:
|
|
print(
|
|
"Received a response from Reddit with an authorization error. check your token.\n"
|
|
)
|
|
return
|
|
|
|
if n_flair_posts_found:
|
|
lt_watchlist_sorted = sorted(
|
|
d_watchlist_tickers.items(), key=lambda item: item[1], reverse=True
|
|
)
|
|
s_watchlist_tickers = ""
|
|
n_tickers = 0
|
|
for t_ticker in lt_watchlist_sorted:
|
|
try:
|
|
# If try doesn't trigger exception, it means that this stock exists on finviz
|
|
# thus we can print it.
|
|
finviz.get_stock(t_ticker[0])
|
|
if int(t_ticker[1]) > 1:
|
|
s_watchlist_tickers += f"{t_ticker[1]} {t_ticker[0]}, "
|
|
n_tickers += 1
|
|
except Exception:
|
|
# print(e, "\n")
|
|
pass
|
|
if n_tickers:
|
|
print(
|
|
"The following stock tickers have been mentioned more than once across the previous SPACs:"
|
|
)
|
|
print(s_watchlist_tickers[:-2])
|
|
print("")
|
|
|
|
except Exception as e:
|
|
print(e, "\n")
|
|
|
|
|
|
def wsb_community(l_args):
|
|
parser = argparse.ArgumentParser(
|
|
add_help=False,
|
|
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(
|
|
"-n",
|
|
"--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.",
|
|
)
|
|
|
|
try:
|
|
ns_parser = parse_known_args_and_warn(parser, l_args)
|
|
if not ns_parser:
|
|
return
|
|
|
|
praw_api = praw.Reddit(
|
|
client_id=cfg.API_REDDIT_CLIENT_ID,
|
|
client_secret=cfg.API_REDDIT_CLIENT_SECRET,
|
|
username=cfg.API_REDDIT_USERNAME,
|
|
user_agent=cfg.API_REDDIT_USER_AGENT,
|
|
password=cfg.API_REDDIT_PASSWORD,
|
|
)
|
|
|
|
d_submission = {}
|
|
l_watchlist_links = list()
|
|
|
|
# psaw_api = PushshiftAPI()
|
|
|
|
if ns_parser.b_new:
|
|
submissions = praw_api.subreddit("wallstreetbets").new(
|
|
limit=ns_parser.n_limit
|
|
)
|
|
else:
|
|
submissions = praw_api.subreddit("wallstreetbets").hot(
|
|
limit=ns_parser.n_limit
|
|
)
|
|
while True:
|
|
try:
|
|
submission = next(submissions, None)
|
|
if submission:
|
|
# Get more information about post using PRAW api
|
|
submission = praw_api.submission(id=submission.id)
|
|
|
|
# Ensure that the post hasn't been removed by moderator in the meanwhile,
|
|
# that there is a description and it's not just an image, that the flair is
|
|
# meaningful, and that we aren't re-considering same author's watchlist
|
|
if not submission.removed_by_category:
|
|
|
|
l_watchlist_links.append(
|
|
f"https://old.reddit.com{submission.permalink}"
|
|
)
|
|
|
|
print_and_record_reddit_post(d_submission, submission)
|
|
|
|
# Check if search_submissions didn't get anymore posts
|
|
else:
|
|
break
|
|
except ResponseException:
|
|
print(
|
|
"Received a response from Reddit with an authorization error. check your token.\n"
|
|
)
|
|
return
|
|
except Exception as e:
|
|
print(e, "\n")
|