mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-11-13 12:51:49 +00:00
Minor improvements in overall code for consistency
This commit is contained in:
@@ -19,33 +19,33 @@
|
||||
# - The loss function
|
||||
|
||||
MultiLayer_Perceptron \
|
||||
= [ {'Dense':
|
||||
= [ {'Dense':
|
||||
{'units':50, 'activation':'relu'} },
|
||||
{'Dense':
|
||||
{'Dense':
|
||||
{'units':100, 'activation':'relu'} },
|
||||
{'Dense':
|
||||
{'Dense':
|
||||
{'units':80, 'activation':'relu'} },
|
||||
{'Dense':
|
||||
{'Dense':
|
||||
{'units':30, 'activation':'relu'} },
|
||||
{'Dense':
|
||||
{'Dense':
|
||||
{'activation':'linear'} }]
|
||||
|
||||
Recurrent_Neural_Network \
|
||||
= [ {'SimpleRNN':
|
||||
= [ {'SimpleRNN':
|
||||
{'units':100, 'activation':'linear', 'return_sequences':True} },
|
||||
{'SimpleRNN':
|
||||
{'SimpleRNN':
|
||||
{'units':50, 'activation':'linear', 'return_sequences':True} },
|
||||
{'Dropout':
|
||||
{'Dropout':
|
||||
{'rate':0.2} },
|
||||
{'SimpleRNN':
|
||||
{'SimpleRNN':
|
||||
{'units':21, 'activation':'linear', 'return_sequences':False} },
|
||||
{'Dense':
|
||||
{'Dense':
|
||||
{'activation':'linear'} }]
|
||||
|
||||
Long_Short_Term_Memory \
|
||||
= [ {'LSTM':
|
||||
= [ {'LSTM':
|
||||
{'units':25, 'activation':'tanh', 'return_sequences':True} },
|
||||
{'LSTM':
|
||||
{'LSTM':
|
||||
{'units':15, 'activation':'tanh', 'return_sequences':False} },
|
||||
{'Dense':
|
||||
{'activation':'linear'} }]
|
||||
{'Dense':
|
||||
{'activation':'linear'} }]
|
||||
|
||||
@@ -16,10 +16,11 @@ register_matplotlib_converters()
|
||||
|
||||
# ------------------------------------------- PRICE_TARGET_FROM_ANALYSTS -------------------------------------------
|
||||
def price_target_from_analysts(l_args, df_stock, s_ticker, s_start, s_interval):
|
||||
parser = argparse.ArgumentParser(prog='price_target_from_analysts',
|
||||
description="""Price target from analysts [Source: Business Insider API]""")
|
||||
|
||||
parser.add_argument('-n', "--num", action="store", dest="n_num", type=check_positive, default=10, help='Number of latest price targets')
|
||||
parser = argparse.ArgumentParser(prog='pt',
|
||||
description="""Prints price target from analysts. [Source: Business Insider]""")
|
||||
|
||||
parser.add_argument('-n', "--num", action="store", dest="n_num", type=check_positive, default=10,
|
||||
help='number of latest price targets from analysts to print.')
|
||||
|
||||
try:
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
@@ -38,14 +39,14 @@ def price_target_from_analysts(l_args, df_stock, s_ticker, s_start, s_interval):
|
||||
s_analyst_data = script.get_text().split("config: ",1)[1].split(",\r\n",1)[0]
|
||||
d_analyst_data = json.loads(s_analyst_data)
|
||||
break
|
||||
|
||||
|
||||
#pprint.pprint(d_analyst_data)
|
||||
df_analyst_data = pd.DataFrame.from_dict(d_analyst_data['Markers'])
|
||||
df_analyst_data = pd.DataFrame.from_dict(d_analyst_data['Markers'])
|
||||
df_analyst_data = df_analyst_data[['DateLabel', 'Company', 'InternalRating', 'PriceTarget']]
|
||||
df_analyst_data.columns = ['Date', 'Company', 'Rating', 'Price Target']
|
||||
df_analyst_data
|
||||
df_analyst_data['Rating'].replace({'gut': 'BUY',
|
||||
'neutral': 'HOLD',
|
||||
df_analyst_data['Rating'].replace({'gut': 'BUY',
|
||||
'neutral': 'HOLD',
|
||||
'schlecht':'SELL'}, inplace=True)
|
||||
df_analyst_data['Date'] = pd.to_datetime(df_analyst_data['Date'])
|
||||
df_analyst_data = df_analyst_data.set_index('Date')
|
||||
@@ -56,7 +57,7 @@ def price_target_from_analysts(l_args, df_stock, s_ticker, s_start, s_interval):
|
||||
|
||||
if s_interval == "1440min":
|
||||
plt.plot(df_stock.index, df_stock['5. adjusted close'].values, lw=3)
|
||||
# Intraday
|
||||
# Intraday
|
||||
else:
|
||||
plt.plot(df_stock.index, df_stock['4. close'].values, lw=3)
|
||||
|
||||
@@ -82,7 +83,7 @@ def price_target_from_analysts(l_args, df_stock, s_ticker, s_start, s_interval):
|
||||
pd.set_option('display.max_colwidth', -1)
|
||||
print(df_analyst_data.sort_index(ascending=False).head(ns_parser.n_num).to_string())
|
||||
print("")
|
||||
|
||||
|
||||
except:
|
||||
print("")
|
||||
return
|
||||
@@ -90,8 +91,8 @@ def price_target_from_analysts(l_args, df_stock, s_ticker, s_start, s_interval):
|
||||
|
||||
# ----------------------------------------------- ESTIMATES -----------------------------------------------
|
||||
def estimates(l_args, s_ticker):
|
||||
parser = argparse.ArgumentParser(prog='estimates',
|
||||
description="""Yearly and quarter earnings estimates [Source: Business Insider API]""")
|
||||
parser = argparse.ArgumentParser(prog='est',
|
||||
description="""Yearly estimates and quarter earnings/revenues [Source: Business Insider]""")
|
||||
|
||||
try:
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
@@ -115,7 +116,7 @@ def estimates(l_args, s_ticker):
|
||||
l_estimates_year_metric = list()
|
||||
for estimates_year_metric in text_soup_market_business_insider.findAll('td', {'class': 'table__td black'}):
|
||||
l_estimates_year_metric.append(estimates_year_metric.text)
|
||||
|
||||
|
||||
l_estimates_quarter_metric = list()
|
||||
for estimates_quarter_metric in text_soup_market_business_insider.findAll('td', {'class': 'table__td font-color-dim-gray'}):
|
||||
l_estimates_quarter_metric.append(estimates_quarter_metric.text)
|
||||
@@ -127,32 +128,32 @@ def estimates(l_args, s_ticker):
|
||||
n_metrics = 0
|
||||
b_year = True
|
||||
for idx, metric_value in enumerate(text_soup_market_business_insider.findAll('td', {'class': 'table__td text-right'})):
|
||||
|
||||
|
||||
if b_year:
|
||||
# YEAR metrics
|
||||
l_metrics.append(metric_value.text.strip())
|
||||
|
||||
|
||||
# Check if we have processed all year metrics
|
||||
if n_metrics > len(l_estimates_year_metric)-1:
|
||||
b_year = False
|
||||
n_metrics = 0
|
||||
l_metrics = list()
|
||||
idx_y = idx
|
||||
|
||||
|
||||
# Add value to dictionary
|
||||
if (idx+1)%len(l_estimates_year_header) == 0:
|
||||
d_metric_year[l_estimates_year_metric[n_metrics]] = l_metrics
|
||||
l_metrics = list()
|
||||
n_metrics += 1
|
||||
|
||||
if not b_year:
|
||||
|
||||
if not b_year:
|
||||
# QUARTER metrics
|
||||
l_metrics.append(metric_value.text.strip())
|
||||
|
||||
|
||||
# Check if we have processed all quarter metrics
|
||||
if n_metrics > len(l_estimates_quarter_metric)-1:
|
||||
break
|
||||
|
||||
|
||||
# Add value to dictionary
|
||||
if (idx-idx_y+1)%len(l_estimates_quarter_header) == 0:
|
||||
if n_metrics < 4:
|
||||
@@ -177,7 +178,7 @@ def estimates(l_args, s_ticker):
|
||||
l_date.append('ending ' + re.split(' ending',quarter_title)[1].strip())
|
||||
else:
|
||||
l_date.append('-')
|
||||
|
||||
|
||||
df_quarter_earnings.columns = l_quarter
|
||||
df_quarter_earnings.loc["Date"] = l_date
|
||||
df_quarter_earnings = df_quarter_earnings.reindex(["Date", "No. of Analysts", "Average Estimate", "Year Ago", "Publish Date"])
|
||||
@@ -197,7 +198,7 @@ def estimates(l_args, s_ticker):
|
||||
|
||||
print(text_soup_market_business_insider.find('div', {'class': "text_right instrument-description"}).text.strip())
|
||||
print("")
|
||||
|
||||
|
||||
except:
|
||||
print("")
|
||||
return
|
||||
@@ -205,9 +206,10 @@ def estimates(l_args, s_ticker):
|
||||
|
||||
# ----------------------------------------------- INSIDER_ACTIVITY -----------------------------------------------
|
||||
def insider_activity(l_args, df_stock, s_ticker, s_start, s_interval):
|
||||
parser = argparse.ArgumentParser(prog='insider_activity',
|
||||
description="""Insider activity over time [Source: Business Insider API]""")
|
||||
parser.add_argument('-n', "--num", action="store", dest="n_num", type=check_positive, default=10, help='Number of latest insider activity')
|
||||
parser = argparse.ArgumentParser(prog='ins',
|
||||
description="""Prints insider activity over time [Source: Business Insider]""")
|
||||
parser.add_argument('-n', "--num", action="store", dest="n_num", type=check_positive, default=10,
|
||||
help='number of latest insider activity.')
|
||||
|
||||
try:
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
@@ -218,7 +220,7 @@ def insider_activity(l_args, df_stock, s_ticker, s_start, s_interval):
|
||||
|
||||
url_market_business_insider = f"https://markets.businessinsider.com/stocks/{s_ticker.lower()}-stock"
|
||||
text_soup_market_business_insider = BeautifulSoup(requests.get(url_market_business_insider).text, "lxml")
|
||||
|
||||
|
||||
d_insider = dict()
|
||||
l_insider_vals = list()
|
||||
for idx, insider_val in enumerate(text_soup_market_business_insider.findAll('td', {'class':"table__td text-center"})):
|
||||
@@ -248,7 +250,7 @@ def insider_activity(l_args, df_stock, s_ticker, s_start, s_interval):
|
||||
|
||||
if s_interval == "1440min":
|
||||
plt.plot(df_stock.index, df_stock['5. adjusted close'].values, lw=3)
|
||||
else: # Intraday
|
||||
else: # Intraday
|
||||
plt.plot(df_stock.index, df_stock['4. close'].values, lw=3)
|
||||
|
||||
plt.title(f"{s_ticker.upper()} (Time Series) and Price Target")
|
||||
@@ -269,33 +271,33 @@ def insider_activity(l_args, df_stock, s_ticker, s_start, s_interval):
|
||||
ind_dt = ind
|
||||
else:
|
||||
ind_dt = get_next_stock_market_days(ind, 1)[0]
|
||||
|
||||
|
||||
n_stock_price = 0
|
||||
if s_interval == "1440min":
|
||||
n_stock_price = df_stock['5. adjusted close'][ind_dt]
|
||||
n_stock_price = df_stock['5. adjusted close'][ind_dt]
|
||||
else:
|
||||
n_stock_price = df_stock['4. close'][ind_dt]
|
||||
|
||||
plt.vlines(x=ind_dt,
|
||||
ymin= n_stock_price + n_proportion * float(df_insider[df_insider['Type'] == 'Sell'].groupby(by=['Date']).sum()['Trade'][ind]),
|
||||
ymax= n_stock_price,
|
||||
|
||||
plt.vlines(x=ind_dt,
|
||||
ymin= n_stock_price + n_proportion * float(df_insider[df_insider['Type'] == 'Sell'].groupby(by=['Date']).sum()['Trade'][ind]),
|
||||
ymax= n_stock_price,
|
||||
colors='red', ls='-', lw=5)
|
||||
|
||||
|
||||
for ind in df_insider[df_insider['Type'] == 'Buy'].groupby(by=['Date']).sum().index:
|
||||
if ind in df_stock.index:
|
||||
ind_dt = ind
|
||||
else:
|
||||
ind_dt = get_next_stock_market_days(ind, 1)[0]
|
||||
|
||||
|
||||
n_stock_price = 0
|
||||
if s_interval == "1440min":
|
||||
n_stock_price = df_stock['5. adjusted close'][ind_dt]
|
||||
n_stock_price = df_stock['5. adjusted close'][ind_dt]
|
||||
else:
|
||||
n_stock_price = df_stock['4. close'][ind_dt]
|
||||
|
||||
plt.vlines(x=ind_dt,
|
||||
ymin=n_stock_price,
|
||||
ymax=n_stock_price + n_proportion * float(df_insider[df_insider['Type'] == 'Buy'].groupby(by=['Date']).sum()['Trade'][ind]),
|
||||
|
||||
plt.vlines(x=ind_dt,
|
||||
ymin=n_stock_price,
|
||||
ymax=n_stock_price + n_proportion * float(df_insider[df_insider['Type'] == 'Buy'].groupby(by=['Date']).sum()['Trade'][ind]),
|
||||
colors='green', ls='-', lw=5)
|
||||
|
||||
plt.grid(b=True, which='major', color='#666666', linestyle='-')
|
||||
@@ -305,12 +307,12 @@ def insider_activity(l_args, df_stock, s_ticker, s_start, s_interval):
|
||||
|
||||
l_names = list()
|
||||
for s_name in text_soup_market_business_insider.findAll('a', {'onclick':"silentTrackPI()"}):
|
||||
l_names.append(s_name.text.strip())
|
||||
l_names.append(s_name.text.strip())
|
||||
df_insider['Insider'] = l_names
|
||||
|
||||
print(df_insider.sort_index(ascending=False).head(n=ns_parser.n_num).to_string())
|
||||
print("")
|
||||
|
||||
|
||||
except:
|
||||
print("")
|
||||
return
|
||||
|
||||
@@ -53,8 +53,8 @@ def print_due_diligence(s_ticker, s_start, s_interval):
|
||||
def dd_menu(df_stock, s_ticker, s_start, s_interval):
|
||||
|
||||
# Add list of arguments that the due diligence parser accepts
|
||||
dd_parser = argparse.ArgumentParser(prog='due_diligence', add_help=False)
|
||||
dd_parser.add_argument('cmd', choices=['info', 'help', 'q', 'quit',
|
||||
dd_parser = argparse.ArgumentParser(prog='dd', add_help=False)
|
||||
dd_parser.add_argument('cmd', choices=['info', 'help', 'q', 'quit',
|
||||
'red', # Reddit
|
||||
'short', # Quandl
|
||||
'rating', # FMP
|
||||
@@ -68,7 +68,7 @@ def dd_menu(df_stock, s_ticker, s_start, s_interval):
|
||||
while True:
|
||||
# Get input command from user
|
||||
as_input = input('> ')
|
||||
|
||||
|
||||
# Parse due diligence command of the list of possible commands
|
||||
try:
|
||||
(ns_known_args, l_args) = dd_parser.parse_known_args(as_input.split())
|
||||
@@ -76,7 +76,7 @@ def dd_menu(df_stock, s_ticker, s_start, s_interval):
|
||||
except SystemExit:
|
||||
print("The command selected doesn't exist\n")
|
||||
continue
|
||||
|
||||
|
||||
if ns_known_args.cmd == 'help':
|
||||
print_due_diligence(s_ticker, s_start, s_interval)
|
||||
|
||||
@@ -91,7 +91,7 @@ def dd_menu(df_stock, s_ticker, s_start, s_interval):
|
||||
# REDDIT API
|
||||
elif ns_known_args.cmd == 'red':
|
||||
r_api.due_diligence(l_args, s_ticker)
|
||||
|
||||
|
||||
# FINVIZ API
|
||||
elif ns_known_args.cmd == 'insider':
|
||||
fvz_api.insider(l_args, s_ticker)
|
||||
|
||||
@@ -8,11 +8,11 @@ import pandas as pd
|
||||
|
||||
# ---------------------------------------------------- RATING ----------------------------------------------------
|
||||
def rating(l_args, s_ticker):
|
||||
parser = argparse.ArgumentParser(prog='rating',
|
||||
description="""Based on specific ratios, provides information whether the company
|
||||
parser = argparse.ArgumentParser(prog='rating',
|
||||
description="""Based on specific ratios, prints information whether the company
|
||||
is a (strong) buy, neutral or a (strong) sell. The following fields are expected:
|
||||
P/B, ROA, DCF, P/E, ROE, and D/E. [Source: Financial Modeling Prep API]""")
|
||||
|
||||
P/B, ROA, DCF, P/E, ROE, and D/E. [Source: Financial Modeling Prep]""")
|
||||
|
||||
try:
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
|
||||
@@ -29,4 +29,3 @@ def rating(l_args, s_ticker):
|
||||
print("")
|
||||
return
|
||||
|
||||
|
||||
@@ -5,12 +5,13 @@ import pandas as pd
|
||||
|
||||
# ---------------------------------------------------- INSIDER ----------------------------------------------------
|
||||
def insider(l_args, s_ticker):
|
||||
parser = argparse.ArgumentParser(prog='insider',
|
||||
description="""Gives information about inside traders. The following fields are expected:
|
||||
Date, Relationship, Transaction, #Shares, Cost, Value ($), #Shares Total, Insider Trading,
|
||||
SEC Form 4. [Source: Finviz API]""")
|
||||
|
||||
parser.add_argument('-n', "--num", action="store", dest="n_num", type=check_positive, default=10, help='Number of latest inside traders')
|
||||
parser = argparse.ArgumentParser(prog='insider',
|
||||
description="""Prints information about inside traders. The following fields are expected:
|
||||
Date, Relationship, Transaction, #Shares, Cost, Value ($), #Shares Total, Insider Trading,
|
||||
SEC Form 4. [Source: Finviz]""")
|
||||
|
||||
parser.add_argument('-n', "--num", action="store", dest="n_num", type=check_positive, default=10,
|
||||
help='number of latest inside traders.')
|
||||
|
||||
try:
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
@@ -21,7 +22,7 @@ def insider(l_args, s_ticker):
|
||||
|
||||
d_finviz_insider = finviz.get_insider(s_ticker)
|
||||
df_fa = pd.DataFrame.from_dict(d_finviz_insider)
|
||||
df_fa.set_index("Date", inplace=True)
|
||||
df_fa.set_index("Date", inplace=True)
|
||||
df_fa = df_fa[['Relationship', 'Transaction', '#Shares', 'Cost', 'Value ($)', '#Shares Total', 'Insider Trading', 'SEC Form 4']]
|
||||
print(df_fa.head(n=ns_parser.n_num))
|
||||
|
||||
@@ -34,11 +35,12 @@ def insider(l_args, s_ticker):
|
||||
|
||||
# ---------------------------------------------------- NEWS ----------------------------------------------------
|
||||
def news(l_args, s_ticker):
|
||||
parser = argparse.ArgumentParser(prog='news',
|
||||
description="""Gives latest news about company. The following fields are expected:
|
||||
Title, and http link. [Source: Finviz API]""")
|
||||
|
||||
parser.add_argument('-n', "--num", action="store", dest="n_num", type=check_positive, default=5, help='Number of latest inside traders')
|
||||
parser = argparse.ArgumentParser(prog='news',
|
||||
description="""Prints latest news about company, including title and web link.
|
||||
[Source: Finviz]""")
|
||||
|
||||
parser.add_argument('-n', "--num", action="store", dest="n_num", type=check_positive, default=5,
|
||||
help='Number of latest news being printed.')
|
||||
|
||||
try:
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
@@ -53,7 +55,7 @@ def news(l_args, s_ticker):
|
||||
print(f"-> {s_news_title}")
|
||||
print(f"{s_news_link}\n")
|
||||
i+=1
|
||||
|
||||
|
||||
if i > (ns_parser.n_num-1):
|
||||
break
|
||||
|
||||
@@ -66,11 +68,11 @@ def news(l_args, s_ticker):
|
||||
|
||||
# ---------------------------------------------------- ANALYST ----------------------------------------------------
|
||||
def analyst(l_args, s_ticker):
|
||||
parser = argparse.ArgumentParser(prog='analyst',
|
||||
description="""Gives analyst prices and ratings of the company. The following fields
|
||||
parser = argparse.ArgumentParser(prog='analyst',
|
||||
description="""Print analyst prices and ratings of the company. The following fields
|
||||
are expected: date, analyst, category, price from, price to, and rating.
|
||||
[Source: Finviz API]""")
|
||||
|
||||
[Source: Finviz]""")
|
||||
|
||||
try:
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
|
||||
@@ -80,9 +82,8 @@ def analyst(l_args, s_ticker):
|
||||
|
||||
d_finviz_analyst_price = finviz.get_analyst_price_targets(s_ticker)
|
||||
df_fa = pd.DataFrame.from_dict(d_finviz_analyst_price)
|
||||
df_fa.set_index("date", inplace=True)
|
||||
df_fa.set_index("date", inplace=True)
|
||||
print(df_fa)
|
||||
|
||||
print("")
|
||||
|
||||
except:
|
||||
|
||||
@@ -8,12 +8,13 @@ from helper_funcs import *
|
||||
|
||||
# ---------------------------------------------------- SEC FILLINGS ----------------------------------------------------
|
||||
def sec_fillings(l_args, s_ticker):
|
||||
parser = argparse.ArgumentParser(prog='sec',
|
||||
description="""Gives SEC filings of the company. The following fields
|
||||
parser = argparse.ArgumentParser(prog='sec',
|
||||
description="""Prints SEC filings of the company. The following fields
|
||||
are expected: Filing Date, Document Date, Type, Category, Amended, and Link.
|
||||
[Source: Market Watch BS]""")
|
||||
|
||||
parser.add_argument('-n', "--num", action="store", dest="n_num", type=check_positive, default=5, help='Number of latest SEC filings')
|
||||
[Source: Market Watch]""")
|
||||
|
||||
parser.add_argument('-n', "--num", action="store", dest="n_num", type=check_positive, default=5,
|
||||
help='number of latest SEC filings.')
|
||||
|
||||
try:
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
@@ -25,7 +26,7 @@ def sec_fillings(l_args, s_ticker):
|
||||
pd.set_option('display.max_colwidth', -1)
|
||||
|
||||
url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/secfilings"
|
||||
|
||||
|
||||
text_soup_financials = BeautifulSoup(requests.get(url_financials).text,"lxml")
|
||||
|
||||
a_financials_header = list()
|
||||
@@ -33,20 +34,20 @@ def sec_fillings(l_args, s_ticker):
|
||||
soup_financials = text_soup_financials.findAll('tr', {'class': 'table__row'})
|
||||
for financials_info in soup_financials:
|
||||
a_financials = financials_info.text.split('\n')
|
||||
|
||||
|
||||
# If header has been processed and dataframe created ready to populate the SEC information
|
||||
if b_ready_to_process_info:
|
||||
l_financials_info = [a_financials[2]]
|
||||
l_financials_info = [a_financials[2]]
|
||||
l_financials_info.extend(a_financials[5:-1])
|
||||
l_financials_info.append(financials_info.a['href'])
|
||||
# Append data values to financials
|
||||
df_financials.loc[len(df_financials.index)] = l_financials_info
|
||||
|
||||
|
||||
if 'Filing Date' in a_financials:
|
||||
l_financials_header = [a_financials[2]]
|
||||
l_financials_header = [a_financials[2]]
|
||||
l_financials_header.extend(a_financials[5:-1])
|
||||
l_financials_header.append('Link')
|
||||
|
||||
|
||||
df_financials = pd.DataFrame(columns=l_financials_header)
|
||||
df_financials.set_index('Filing Date')
|
||||
b_ready_to_process_info = True
|
||||
@@ -56,7 +57,7 @@ def sec_fillings(l_args, s_ticker):
|
||||
|
||||
print(df_financials.head(n=ns_parser.n_num).to_string())
|
||||
print("")
|
||||
|
||||
|
||||
except:
|
||||
print("")
|
||||
return
|
||||
@@ -64,13 +65,17 @@ def sec_fillings(l_args, s_ticker):
|
||||
|
||||
# ---------------------------------------------------- Sean Seah Warnings ----------------------------------------------------
|
||||
def sean_seah_warnings(l_args, s_ticker):
|
||||
parser = argparse.ArgumentParser(prog='warnings',
|
||||
parser = argparse.ArgumentParser(prog='warnings',
|
||||
description="""Sean Seah warnings. Check: Consistent historical earnings per share;
|
||||
Consistently high return on equity; Consistently high return on assets; 5x Net
|
||||
Income > Long-Term Debt; and Interest coverage ratio more than 3. [Source: Market Watch BS]""")
|
||||
Consistently high return on equity; Consistently high return on assets; 5x Net
|
||||
Income > Long-Term Debt; and Interest coverage ratio more than 3. See
|
||||
https://www.drwealth.com/gone-fishing-with-buffett-by-sean-seah/comment-page-1/
|
||||
[Source: Market Watch]""")
|
||||
|
||||
parser.add_argument('-i', "--info", action="store_true", default=False, dest="b_info", help='Give Sean Seah books information')
|
||||
parser.add_argument('-d', "--debug", action="store_true", default=False, dest="b_debug", help='Show data used to calculate warnings')
|
||||
parser.add_argument('-i', "--info", action="store_true", default=False, dest="b_info",
|
||||
help='provide more information about Sean Seah warning rules.')
|
||||
parser.add_argument('-d', "--debug", action="store_true", default=False, dest="b_debug",
|
||||
help='print insights into warnings calculation.')
|
||||
|
||||
try:
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
@@ -88,7 +93,7 @@ def sean_seah_warnings(l_args, s_ticker):
|
||||
line = fp.readline()
|
||||
print("")
|
||||
|
||||
# From INCOME STATEMENT, get: 'EPS (Basic)', 'Net Income', 'Interest Expense', 'EBITDA'
|
||||
# From INCOME STATEMENT, get: 'EPS (Basic)', 'Net Income', 'Interest Expense', 'EBITDA'
|
||||
url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/income"
|
||||
text_soup_financials = BeautifulSoup(requests.get(url_financials).text,"lxml")
|
||||
|
||||
@@ -103,7 +108,7 @@ def sean_seah_warnings(l_args, s_ticker):
|
||||
soup_financials += text_soup_financials.findAll('tr', {'class': 'table__row is-highlighted'})
|
||||
for financials_info in soup_financials:
|
||||
a_financials_info = financials_info.text.split('\n')
|
||||
l_financials = [a_financials_info[2]]
|
||||
l_financials = [a_financials_info[2]]
|
||||
l_financials.extend(a_financials_info[5:-2])
|
||||
# Append data values to financials
|
||||
df_financials.loc[len(df_financials.index)] = l_financials
|
||||
@@ -114,7 +119,7 @@ def sean_seah_warnings(l_args, s_ticker):
|
||||
df_sean_seah = df_financials.loc[['EPS (Basic)', 'Net Income', 'Interest Expense', 'EBITDA']]
|
||||
|
||||
# From BALANCE SHEET, get: 'Liabilities & Shareholders\' Equity', 'Long-Term Debt'
|
||||
url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/balance-sheet"
|
||||
url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/balance-sheet"
|
||||
text_soup_financials = BeautifulSoup(requests.get(url_financials).text,"lxml")
|
||||
|
||||
# Define financials columns
|
||||
@@ -130,7 +135,7 @@ def sean_seah_warnings(l_args, s_ticker):
|
||||
soup_financials += text_soup_financials.findAll('tr', {'class': 'table__row is-highlighted'})
|
||||
for financials_info in soup_financials:
|
||||
a_financials_info = financials_info.text.split('\n')
|
||||
l_financials = [a_financials_info[2]]
|
||||
l_financials = [a_financials_info[2]]
|
||||
l_financials.extend(a_financials_info[5:-2])
|
||||
# Append data values to financials
|
||||
df_financials.loc[len(df_financials.index)] = l_financials
|
||||
|
||||
@@ -10,12 +10,14 @@ from helper_funcs import *
|
||||
|
||||
# -------------------------------------------------------- SHORT_INTEREST --------------------------------------------------------
|
||||
def short_interest(l_args, s_ticker, s_start):
|
||||
parser = argparse.ArgumentParser(prog='short',
|
||||
description="""Short interest corresponds to the number of shares that have been sold short
|
||||
but have not yet been covered or closed out. [Source: Quandl API]""")
|
||||
parser = argparse.ArgumentParser(prog='short',
|
||||
description="""Plots the short interest of a stock. This corresponds to the number of shares that
|
||||
have been sold short but have not yet been covered or closed out. Either NASDAQ or NYSE [Source: Quandl]""")
|
||||
|
||||
parser.add_argument('-n', "--nyse", action="store_true", default=False, dest="b_nyse", help='Data from NYSE')
|
||||
parser.add_argument('-d', "--days", action="store", dest="n_days", type=check_positive, default=10, help='Number of latest days to see data')
|
||||
parser.add_argument('-n', "--nyse", action="store_true", default=False, dest="b_nyse",
|
||||
help='data from NYSE flag.')
|
||||
parser.add_argument('-d', "--days", action="store", dest="n_days", type=check_positive, default=10,
|
||||
help='number of latest days to print data.')
|
||||
|
||||
try:
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
@@ -45,7 +47,7 @@ def short_interest(l_args, s_ticker, s_start):
|
||||
ax.set_title(f"{('NASDAQ', 'NYSE')[ns_parser.b_nyse]} Short Interest on {s_ticker} from {s_start.date()}")
|
||||
else:
|
||||
ax.set_title(f"{('NASDAQ', 'NYSE')[ns_parser.b_nyse]} Short Interest on {s_ticker}")
|
||||
|
||||
|
||||
ax.legend(labels=['Short Volume', 'Total Volume'])
|
||||
ax.tick_params(axis='both', which='major')
|
||||
ax.yaxis.set_major_formatter(ticker.EngFormatter())
|
||||
@@ -56,7 +58,7 @@ def short_interest(l_args, s_ticker, s_start):
|
||||
ax_twin.tick_params(axis='y', which='major', color='green')
|
||||
ax_twin.yaxis.set_major_formatter(ticker.FormatStrFormatter('%.0f%%'))
|
||||
plt.xlim([df_short_interest.index[0], df_short_interest.index[-1]])
|
||||
|
||||
|
||||
df_short_interest['% of Volume Shorted'] = df_short_interest['% of Volume Shorted'].apply(lambda x: f'{x/100:.2%}')
|
||||
df_short_interest = df_short_interest.applymap(lambda x: long_number_format(x)).sort_index(ascending=False)
|
||||
|
||||
@@ -69,4 +71,3 @@ def short_interest(l_args, s_ticker, s_start):
|
||||
except:
|
||||
print("")
|
||||
return
|
||||
|
||||
@@ -14,15 +14,16 @@ import config_terminal as cfg
|
||||
|
||||
# -------------------------------------------------------------------------------------------------------------------
|
||||
def due_diligence(l_args, s_ticker):
|
||||
parser = argparse.ArgumentParser(prog='dd',
|
||||
description=""" Search for a stock's due diligence [Reddit] """)
|
||||
parser.add_argument('-l', "--limit", action="store", dest="n_limit", type=check_positive, default=5,
|
||||
help='Limit of posts with the watchlist word')
|
||||
parser = argparse.ArgumentParser(prog='red',
|
||||
description="""Print top stock's due diligence from other users. [Source: Reddit] """)
|
||||
|
||||
parser.add_argument('-l', "--limit", action="store", dest="n_limit", type=check_positive, default=5,
|
||||
help='limit of posts to retrieve.')
|
||||
parser.add_argument('-d', "--days", action="store", dest="n_days", type=check_positive, default=3,
|
||||
help="Look for a watchlist created on the past n days")
|
||||
help="number of prior days to look for.")
|
||||
parser.add_argument('-a', "--all", action="store_true", dest="b_all", default=False,
|
||||
help=""" Search through all flairs (apart from Yolo and Meme), otherwise we focus on the
|
||||
flairs: DD, technical analysis, Catalyst, News, Advice, Chart """)
|
||||
help="""search through all flairs (apart from Yolo and Meme), otherwise we focus on
|
||||
specific flairs: DD, technical analysis, Catalyst, News, Advice, Chart """)
|
||||
|
||||
try:
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
@@ -54,12 +55,12 @@ def due_diligence(l_args, s_ticker):
|
||||
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 in the meanwhile
|
||||
if not submission.removed_by_category:
|
||||
|
||||
# Either just filter out Yolo, and Meme flairs, or focus on DD, based on b_DD flag
|
||||
if (submission.link_flair_text in l_flair_text,
|
||||
if (submission.link_flair_text in l_flair_text,
|
||||
submission.link_flair_text not in ['Yolo', 'Meme'])[ns_parser.b_all]:
|
||||
|
||||
# Refactor data
|
||||
@@ -87,20 +88,20 @@ def due_diligence(l_args, s_ticker):
|
||||
print(f"{s_datetime} - {submission.title}")
|
||||
print(f"{s_link}")
|
||||
t_post = PrettyTable(['Subreddit', 'Flair', 'Score', '# Comments', 'Upvote %', "Awards"])
|
||||
t_post.add_row([submission.subreddit, submission.link_flair_text, submission.score,
|
||||
t_post.add_row([submission.subreddit, submission.link_flair_text, submission.score,
|
||||
submission.num_comments,f"{round(100*submission.upvote_ratio)}%", s_all_awards])
|
||||
print(t_post)
|
||||
print("\n")
|
||||
|
||||
|
||||
# If needed, submission.comments could give us the top comments
|
||||
|
||||
# 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
|
||||
|
||||
@@ -75,10 +75,10 @@ def print_fundamental_analysis(s_ticker, s_start, s_interval):
|
||||
|
||||
# ---------------------------------------------------- INFO ----------------------------------------------------
|
||||
def info(l_args, s_ticker):
|
||||
parser = argparse.ArgumentParser(prog='info',
|
||||
parser = argparse.ArgumentParser(prog='info',
|
||||
description="""Provides information about main key metrics. Namely: EBITDA,
|
||||
EPS, P/E, PEG, FCF, P/B, ROE, DPR, P/S, Dividend Yield Ratio, D/E, and Beta.""")
|
||||
|
||||
|
||||
try:
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
|
||||
@@ -96,13 +96,13 @@ def info(l_args, s_ticker):
|
||||
except:
|
||||
print("ERROR!\n")
|
||||
return
|
||||
|
||||
|
||||
|
||||
# ---------------------------------------------------- MENU ----------------------------------------------------
|
||||
def fa_menu(s_ticker, s_start, s_interval):
|
||||
|
||||
# Add list of arguments that the fundamental analysis parser accepts
|
||||
fa_parser = argparse.ArgumentParser(prog='fundamental_analysis', add_help=False)
|
||||
fa_parser = argparse.ArgumentParser(prog='fa', add_help=False)
|
||||
fa_parser.add_argument('cmd', choices=['help', 'q', 'quit', #
|
||||
'screener', # Finviz
|
||||
'mgmt', # Business Insider
|
||||
@@ -118,7 +118,7 @@ def fa_menu(s_ticker, s_start, s_interval):
|
||||
while True:
|
||||
# Get input command from user
|
||||
as_input = input('> ')
|
||||
|
||||
|
||||
# Parse fundamental analysis command of the list of possible commands
|
||||
try:
|
||||
(ns_known_args, l_args) = fa_parser.parse_known_args(as_input.split())
|
||||
@@ -129,7 +129,7 @@ def fa_menu(s_ticker, s_start, s_interval):
|
||||
|
||||
#if ns_known_args.cmd == 'info':
|
||||
# info(l_args, s_ticker)
|
||||
|
||||
|
||||
if ns_known_args.cmd == 'help':
|
||||
print_fundamental_analysis(s_ticker, s_start, s_interval)
|
||||
|
||||
@@ -180,7 +180,7 @@ def fa_menu(s_ticker, s_start, s_interval):
|
||||
|
||||
elif ns_known_args.cmd == 'cal':
|
||||
yf_api.calendar_earnings(l_args, s_ticker)
|
||||
|
||||
|
||||
# ALPHA VANTAGE API
|
||||
elif ns_known_args.cmd == 'overview':
|
||||
av_api.overview(l_args, s_ticker)
|
||||
@@ -204,7 +204,7 @@ def fa_menu(s_ticker, s_start, s_interval):
|
||||
|
||||
elif ns_known_args.cmd == 'quote':
|
||||
fmp_api.quote(l_args, s_ticker)
|
||||
|
||||
|
||||
elif ns_known_args.cmd == 'enterprise':
|
||||
fmp_api.enterprise(l_args, s_ticker)
|
||||
|
||||
|
||||
@@ -44,13 +44,13 @@ def load(l_args, s_ticker, s_start, s_interval, df_stock):
|
||||
ts = TimeSeries(key=cfg.API_KEY_ALPHAVANTAGE, output_format='pandas')
|
||||
# Daily
|
||||
if s_interval == "1440min":
|
||||
df_stock, d_stock_metadata = ts.get_daily_adjusted(symbol=ns_parser.s_ticker, outputsize='full')
|
||||
df_stock, d_stock_metadata = ts.get_daily_adjusted(symbol=ns_parser.s_ticker, outputsize='full')
|
||||
# Intraday
|
||||
else:
|
||||
df_stock, d_stock_metadata = ts.get_intraday(symbol=ns_parser.s_ticker, outputsize='full', interval=s_interval)
|
||||
else:
|
||||
df_stock, d_stock_metadata = ts.get_intraday(symbol=ns_parser.s_ticker, outputsize='full', interval=s_interval)
|
||||
|
||||
df_stock.sort_index(ascending=True, inplace=True)
|
||||
|
||||
|
||||
except:
|
||||
print("Either the ticker or the API_KEY are invalids. Try again!")
|
||||
return [s_ticker, s_start, s_interval, df_stock]
|
||||
@@ -72,7 +72,7 @@ def load(l_args, s_ticker, s_start, s_interval, df_stock):
|
||||
def view(l_args, s_ticker, s_start, s_interval, df_stock):
|
||||
parser = argparse.ArgumentParser(prog='view', description='Visualise historical data of a stock. An alpha_vantage key is necessary.')
|
||||
if s_ticker:
|
||||
parser.add_argument('-t', "--ticker", action="store", dest="s_ticker", default=s_ticker, help='Stock ticker')
|
||||
parser.add_argument('-t', "--ticker", action="store", dest="s_ticker", default=s_ticker, help='Stock ticker')
|
||||
else:
|
||||
parser.add_argument('-t', "--ticker", action="store", dest="s_ticker", required=True, help='Stock ticker')
|
||||
parser.add_argument('-s', "--start", type=valid_date, dest="s_start_date", help="The starting date (format YYYY-MM-DD) of the stock")
|
||||
@@ -85,7 +85,7 @@ def view(l_args, s_ticker, s_start, s_interval, df_stock):
|
||||
except SystemExit:
|
||||
print("")
|
||||
return
|
||||
|
||||
|
||||
if l_unknown_args:
|
||||
print(f"The following args couldn't be interpreted: {l_unknown_args}")
|
||||
|
||||
@@ -105,8 +105,8 @@ def view(l_args, s_ticker, s_start, s_interval, df_stock):
|
||||
df_stock, d_stock_metadata = ts.get_daily_adjusted(symbol=s_ticker, outputsize='full')
|
||||
# Intraday
|
||||
else:
|
||||
df_stock, d_stock_metadata = ts.get_intraday(symbol=s_ticker, outputsize='full', interval=s_interval)
|
||||
|
||||
df_stock, d_stock_metadata = ts.get_intraday(symbol=s_ticker, outputsize='full', interval=s_interval)
|
||||
|
||||
except:
|
||||
print("Either the ticker or the API_KEY are invalids. Try again!")
|
||||
return
|
||||
@@ -125,7 +125,7 @@ def view(l_args, s_ticker, s_start, s_interval, df_stock):
|
||||
print("An index bigger than 4 was given, which is wrong. Try again")
|
||||
return
|
||||
# Append last column of df to be filtered which corresponds to: 6. Volume
|
||||
ln_col_idx.append(5)
|
||||
ln_col_idx.append(5)
|
||||
# Intraday
|
||||
else:
|
||||
# The default doesn't exist for intradaily data
|
||||
@@ -138,7 +138,7 @@ def view(l_args, s_ticker, s_start, s_interval, df_stock):
|
||||
print("An index bigger than 3 was given, which is wrong. Try again")
|
||||
return
|
||||
# Append last column of df to be filtered which corresponds to: 5. Volume
|
||||
ln_col_idx.append(4)
|
||||
ln_col_idx.append(4)
|
||||
|
||||
# Plot view of the stock
|
||||
plot_view_stock(df_stock.iloc[:, ln_col_idx], ns_parser.s_ticker)
|
||||
@@ -155,7 +155,7 @@ def print_help(s_ticker, s_start, s_interval, b_is_market_open):
|
||||
print(" clear clear a specific stock ticker from analysis")
|
||||
print(" load load a specific stock ticker for analysis")
|
||||
print(" view view and load a specific stock ticker for technical analysis")
|
||||
|
||||
|
||||
s_intraday = (f'Intraday {s_interval}', 'Daily')[s_interval == "1440min"]
|
||||
if s_ticker and s_start:
|
||||
print(f"\n{s_intraday} Stock: {s_ticker} (from {s_start.strftime('%Y-%m-%d')})")
|
||||
@@ -179,7 +179,7 @@ def print_help(s_ticker, s_start, s_interval, b_is_market_open):
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
def main():
|
||||
""" Main function of the program
|
||||
"""
|
||||
"""
|
||||
|
||||
s_ticker = ""
|
||||
s_start = ""
|
||||
@@ -188,12 +188,12 @@ def main():
|
||||
s_interval = "1440min"
|
||||
|
||||
# Set stock by default to speed up testing
|
||||
s_ticker = "AAPL"
|
||||
s_ticker = "BB"
|
||||
s_start = datetime.strptime("2020-06-04", "%Y-%m-%d")
|
||||
ts = TimeSeries(key=cfg.API_KEY_ALPHAVANTAGE, output_format='pandas')
|
||||
df_stock, d_stock_metadata = ts.get_daily_adjusted(symbol=s_ticker, outputsize='full')
|
||||
df_stock.sort_index(ascending=True, inplace=True)
|
||||
df_stock = df_stock[s_start:]
|
||||
df_stock = df_stock[s_start:]
|
||||
# Delete above in the future
|
||||
|
||||
# Add list of arguments that the main parser accepts
|
||||
@@ -201,7 +201,7 @@ def main():
|
||||
menu_parser.add_argument('opt', choices=['help', 'quit', 'q',
|
||||
'clear', 'load', 'view',
|
||||
'disc', 'sen', 'res', 'fa', 'ta', 'dd', 'pred'])
|
||||
|
||||
|
||||
# Print first welcome message and help
|
||||
print("\nWelcome to Didier's Gamestonk Terminal\n")
|
||||
print_help(s_ticker, s_start, s_interval, b_is_stock_market_open())
|
||||
@@ -215,7 +215,7 @@ def main():
|
||||
if not len(as_input):
|
||||
print("")
|
||||
continue
|
||||
|
||||
|
||||
# Parse main command of the list of possible commands
|
||||
try:
|
||||
(ns_known_args, l_args) = menu_parser.parse_known_args(as_input.split())
|
||||
@@ -230,7 +230,7 @@ def main():
|
||||
elif (ns_known_args.opt == 'quit') or (ns_known_args.opt == 'q'):
|
||||
print("Hope you made money today. Good bye my lover, good bye my friend.\n")
|
||||
return
|
||||
|
||||
|
||||
elif ns_known_args.opt == 'clear':
|
||||
print("Clearing stock ticker to be used for analysis")
|
||||
s_ticker = ""
|
||||
@@ -304,7 +304,7 @@ def main():
|
||||
|
||||
# PREDICTION TECHNIQUES
|
||||
elif ns_known_args.opt == 'pred':
|
||||
|
||||
|
||||
if s_interval == "1440min":
|
||||
b_quit = pm.pred_menu(df_stock, s_ticker, s_start, s_interval)
|
||||
# If stock data is intradaily, we need to get data again as prediction techniques work on daily adjusted data
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
from pytz import timezone
|
||||
from holidays import US as holidaysUS
|
||||
from datetime import datetime, time as Time
|
||||
import re
|
||||
import numpy as np
|
||||
import sys
|
||||
import iso8601
|
||||
import matplotlib
|
||||
import matplotlib.pyplot as plt
|
||||
from datetime import timedelta
|
||||
@@ -147,11 +150,11 @@ def long_number_format(num):
|
||||
magnitude = 0
|
||||
while abs(num) >= 1000:
|
||||
magnitude += 1
|
||||
num /= 1000.0
|
||||
num /= 1000.0
|
||||
if num.is_integer():
|
||||
return '%d%s' % (num, ['', ' K', ' M', ' B', ' T', ' P'][magnitude])
|
||||
else:
|
||||
return '%.3f%s' % (num, ['', ' K', ' M', ' B', ' T', ' P'][magnitude])
|
||||
return '%.3f%s' % (num, ['', ' K', ' M', ' B', ' T', ' P'][magnitude])
|
||||
if isinstance(num, int):
|
||||
num = str(num)
|
||||
if num.lstrip("-").isdigit():
|
||||
@@ -160,11 +163,11 @@ def long_number_format(num):
|
||||
magnitude = 0
|
||||
while abs(num) >= 1000:
|
||||
magnitude += 1
|
||||
num /= 1000.0
|
||||
num /= 1000.0
|
||||
if num.is_integer():
|
||||
return '%d%s' % (num, ['', ' K', ' M', ' B', ' T', ' P'][magnitude])
|
||||
else:
|
||||
return '%.3f%s' % (num, ['', ' K', ' M', ' B', ' T', ' P'][magnitude])
|
||||
return '%.3f%s' % (num, ['', ' K', ' M', ' B', ' T', ' P'][magnitude])
|
||||
return num
|
||||
|
||||
|
||||
@@ -175,10 +178,10 @@ def clean_data_values_to_float(val):
|
||||
val = val[1:]
|
||||
if val.endswith(')'):
|
||||
val = val[:-1]
|
||||
|
||||
|
||||
if val == '-':
|
||||
val = '0'
|
||||
|
||||
|
||||
# Convert percentage to decimal
|
||||
if val.endswith('%'):
|
||||
val = float(val[:-1])/100.0
|
||||
@@ -206,9 +209,9 @@ def int_or_round_float(x):
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
def divide_chunks(l, n):
|
||||
# looping till length l
|
||||
for i in range(0, len(l), n):
|
||||
def divide_chunks(l, n):
|
||||
# looping till length l
|
||||
for i in range(0, len(l), n):
|
||||
yield l[i:i + n]
|
||||
|
||||
|
||||
@@ -230,5 +233,37 @@ def get_next_stock_market_days(last_stock_day, n_next_days):
|
||||
else:
|
||||
n_days += 1
|
||||
l_pred_days.append(last_stock_day)
|
||||
|
||||
|
||||
return l_pred_days
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
def get_data(tweet):
|
||||
if '+' in tweet['created_at']:
|
||||
s_datetime = tweet['created_at'].split(' +')[0]
|
||||
else:
|
||||
s_datetime = iso8601.parse_date(tweet['created_at']).strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
if 'full_text' in tweet.keys():
|
||||
s_text = tweet['full_text']
|
||||
else:
|
||||
s_text = tweet['text']
|
||||
|
||||
data = {'created_at': s_datetime,
|
||||
'text': s_text }
|
||||
return data
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
def clean_tweet(tweet, s_ticker):
|
||||
whitespace = re.compile(r"\s+")
|
||||
web_address = re.compile(r"(?i)http(s):\/\/[a-z0-9.~_\-\/]+")
|
||||
ticker = re.compile(r"(?i)@{}(?=\b)".format(s_ticker))
|
||||
user = re.compile(r"(?i)@[a-z0-9_]+")
|
||||
|
||||
tweet = whitespace.sub(' ', tweet)
|
||||
tweet = web_address.sub('', tweet)
|
||||
tweet = ticker.sub(s_ticker, tweet)
|
||||
tweet = user.sub('', tweet)
|
||||
|
||||
return tweet
|
||||
|
||||
@@ -10,25 +10,25 @@ from statsmodels.tsa.arima.model import ARIMA
|
||||
# -------------------------------------------------- ARIMA --------------------------------------------------
|
||||
def arima(l_args, s_ticker, s_interval, df_stock):
|
||||
parser = argparse.ArgumentParser(prog='arima',
|
||||
description="""In statistics and econometrics, and in particular in time
|
||||
series analysis, an autoregressive integrated moving average (ARIMA) model
|
||||
is a generalization of an autoregressive moving average (ARMA) model. Both
|
||||
of these models are fitted to time series data either to better understand
|
||||
the data or to predict future points in the series (forecasting).
|
||||
ARIMA(p,d,q) where parameters p, d, and q are non-negative integers, p is
|
||||
the order (number of time lags) of the autoregressive model, d is the degree
|
||||
of differencing (the number of times the data have had past values subtracted),
|
||||
description="""In statistics and econometrics, and in particular in time
|
||||
series analysis, an autoregressive integrated moving average (ARIMA) model
|
||||
is a generalization of an autoregressive moving average (ARMA) model. Both
|
||||
of these models are fitted to time series data either to better understand
|
||||
the data or to predict future points in the series (forecasting).
|
||||
ARIMA(p,d,q) where parameters p, d, and q are non-negative integers, p is
|
||||
the order (number of time lags) of the autoregressive model, d is the degree
|
||||
of differencing (the number of times the data have had past values subtracted),
|
||||
and q is the order of the moving-average model.""")
|
||||
|
||||
parser.add_argument('-d', "--days", action="store", dest="n_days", type=check_positive, default=5,
|
||||
parser.add_argument('-d', "--days", action="store", dest="n_days", type=check_positive, default=5,
|
||||
help='prediction days.')
|
||||
parser.add_argument('-i', "--ic", action="store", dest="s_ic", type=str, default='aic',
|
||||
parser.add_argument('-i', "--ic", action="store", dest="s_ic", type=str, default='aic',
|
||||
choices=['aic', 'aicc', 'bic', 'hqic', 'oob'], help='information criteria.')
|
||||
parser.add_argument('-s', "--seasonal", action="store_true", default=False, dest="b_seasonal",
|
||||
help='weekly seasonality flag.')
|
||||
parser.add_argument('-o', "--order", action="store", dest="s_order", type=str,
|
||||
help='arima model order.')
|
||||
parser.add_argument('-r', "--results", action="store_true", dest="b_results", default=False,
|
||||
parser.add_argument('-s', "--seasonal", action="store_true", default=False, dest="b_seasonal",
|
||||
help='Use weekly seasonal data.')
|
||||
parser.add_argument('-o', "--order", action="store", dest="s_order", type=str,
|
||||
help='arima model order (p,d,q) in format: pdq.')
|
||||
parser.add_argument('-r', "--results", action="store_true", dest="b_results", default=False,
|
||||
help='results about ARIMA summary flag.')
|
||||
|
||||
try:
|
||||
|
||||
@@ -45,14 +45,14 @@ def print_prediction(s_ticker, s_start, s_interval):
|
||||
print(" lstm Long-Short Term Memory")
|
||||
print("")
|
||||
|
||||
|
||||
|
||||
# ---------------------------------------------------- MENU ----------------------------------------------------
|
||||
def pred_menu(df_stock, s_ticker, s_start, s_interval):
|
||||
|
||||
# Add list of arguments that the prediction techniques parser accepts
|
||||
pred_parser = argparse.ArgumentParser(prog='technical_analysis', add_help=False)
|
||||
pred_parser = argparse.ArgumentParser(prog='pred', add_help=False)
|
||||
pred_parser.add_argument('cmd', choices=['help', 'q', 'quit',
|
||||
'sma', 'knn',
|
||||
'sma', 'knn',
|
||||
'linear', 'quadratic', 'cubic', 'regression',
|
||||
'arima', 'prophet', 'mlp', 'rnn', 'lstm'])
|
||||
|
||||
@@ -62,7 +62,7 @@ def pred_menu(df_stock, s_ticker, s_start, s_interval):
|
||||
while True:
|
||||
# Get input command from user
|
||||
as_input = input('> ')
|
||||
|
||||
|
||||
# Parse prediction techniques command of the list of possible commands
|
||||
try:
|
||||
(ns_known_args, l_args) = pred_parser.parse_known_args(as_input.split())
|
||||
|
||||
@@ -18,11 +18,11 @@ def get_last_time_market_was_open(dt):
|
||||
# Check if it is a weekend
|
||||
if dt.date().weekday() > 4:
|
||||
dt = get_last_time_market_was_open(dt - timedelta(hours=24))
|
||||
|
||||
|
||||
# Check if it is a holiday
|
||||
if dt.strftime('%Y-%m-%d') in holidaysUS():
|
||||
dt = get_last_time_market_was_open(dt - timedelta(hours=24))
|
||||
|
||||
|
||||
dt = dt.replace(hour=21, minute=0, second=0)
|
||||
|
||||
return dt
|
||||
@@ -30,9 +30,10 @@ def get_last_time_market_was_open(dt):
|
||||
|
||||
# -------------------------------------------------------------------------------------------------------------------
|
||||
def watchlist(l_args):
|
||||
parser = argparse.ArgumentParser(prog='watchlist',
|
||||
description=""" Show other users watchlist [Reddit] """)
|
||||
parser.add_argument('-l', "--limit", action="store", dest="n_limit", type=check_positive, default=5, help='Limit of posts with watchlists retrieved')
|
||||
parser = argparse.ArgumentParser(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, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
@@ -61,21 +62,21 @@ def watchlist(l_args):
|
||||
subreddit=l_sub_reddits,
|
||||
q='WATCHLIST|Watchlist|watchlist',
|
||||
filter=['id'])
|
||||
|
||||
|
||||
n_flair_posts_found = 0
|
||||
while True:
|
||||
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:
|
||||
|
||||
|
||||
# Make sure there is at least 1 ticker found on the post text
|
||||
l_tickers_found = set(re.findall("[A-Z]{3,5}", submission.selftext))
|
||||
if l_tickers_found:
|
||||
@@ -120,18 +121,18 @@ def watchlist(l_args):
|
||||
print(f"\n{s_datetime} - {submission.title}")
|
||||
print(f"{s_link}")
|
||||
t_post = PrettyTable(['Subreddit', 'Flair', 'Score', '# Comments', 'Upvote %', "Awards"])
|
||||
t_post.add_row([submission.subreddit, submission.link_flair_text, submission.score,
|
||||
t_post.add_row([submission.subreddit, submission.link_flair_text, submission.score,
|
||||
submission.num_comments,f"{round(100*submission.upvote_ratio)}%", s_all_awards])
|
||||
print(t_post)
|
||||
print("\n")
|
||||
print("")
|
||||
|
||||
# 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
|
||||
@@ -160,15 +161,15 @@ def watchlist(l_args):
|
||||
|
||||
# -------------------------------------------------------------------------------------------------------------------
|
||||
def popular_tickers(l_args):
|
||||
parser = argparse.ArgumentParser(prog='popular',
|
||||
parser = argparse.ArgumentParser(prog='popular',
|
||||
description=""" Latest popular tickers [Reddit] """)
|
||||
parser.add_argument('-l', "--limit", action="store", dest="n_limit", type=check_positive, default=30,
|
||||
help='Limit of posts retrieved per sub reddit')
|
||||
parser.add_argument('-s', "--sub", action="store", dest="s_subreddit", type=str,
|
||||
help="""Subreddit to look for tickers. Default: pennystocks, RobinHoodPennyStocks, Daytrading,
|
||||
parser.add_argument('-l', "--limit", action="store", dest="n_limit", type=check_positive, default=30,
|
||||
help='limit of posts retrieved per sub reddit.')
|
||||
parser.add_argument('-s', "--sub", action="store", dest="s_subreddit", type=str,
|
||||
help="""subreddit to look for tickers. Default: pennystocks, RobinHoodPennyStocks, Daytrading,
|
||||
StockMarket, stocks, investing, wallstreetbets""")
|
||||
parser.add_argument('-d', "--days", action="store", dest="n_days", type=check_positive, default=1,
|
||||
help="Look for the tickers from those n past days")
|
||||
help="look for the tickers from those n past days.")
|
||||
|
||||
try:
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
@@ -176,7 +177,7 @@ def popular_tickers(l_args):
|
||||
if l_unknown_args:
|
||||
print(f"The following args couldn't be interpreted: {l_unknown_args}\n")
|
||||
return
|
||||
|
||||
|
||||
n_ts_after = int((datetime.today() - timedelta(days=ns_parser.n_days)).timestamp())
|
||||
|
||||
if ns_parser.s_subreddit:
|
||||
@@ -211,41 +212,41 @@ def popular_tickers(l_args):
|
||||
# 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,
|
||||
# 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.link_flair_text not in ['Yolo', 'Meme'] \
|
||||
and submission.author.name not in l_watchlist_author:
|
||||
|
||||
# Make sure there is at least 1 ticker found on the post text
|
||||
l_tickers_found = set(re.findall("[A-Z]{3,5}", submission.selftext))
|
||||
if not l_tickers_found:
|
||||
l_tickers_found = set(re.findall("[A-Z]{3,5}", submission.title))
|
||||
|
||||
if l_tickers_found:
|
||||
|
||||
n_tickers += len(l_tickers_found)
|
||||
# Make sure there is at least 1 ticker found on the post text
|
||||
l_tickers_found = set(re.findall("[A-Z]{3,5}", submission.selftext))
|
||||
if not l_tickers_found:
|
||||
l_tickers_found = set(re.findall("[A-Z]{3,5}", submission.title))
|
||||
|
||||
# Add another author's name to the parsed watchlists
|
||||
l_watchlist_author.append(submission.author.name)
|
||||
if l_tickers_found:
|
||||
|
||||
# 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
|
||||
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
|
||||
|
||||
|
||||
print(f" {n_tickers} tickers found.")
|
||||
|
||||
|
||||
|
||||
|
||||
lt_watchlist_sorted = sorted(d_watchlist_tickers.items(), key=lambda item: item[1], reverse=True)
|
||||
print("\nThe following TOP10 tickers have been mentioned in the last 24 hours:")
|
||||
@@ -265,15 +266,16 @@ def popular_tickers(l_args):
|
||||
|
||||
except:
|
||||
print("")
|
||||
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------------------------------------------------
|
||||
def spac(l_args):
|
||||
parser = argparse.ArgumentParser(prog='spac',
|
||||
parser = argparse.ArgumentParser(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')
|
||||
parser.add_argument('-l', "--limit", action="store", dest="n_limit", type=check_positive, default=5,
|
||||
help='limit of posts with SPACs retrieved')
|
||||
parser.add_argument('-d', "--days", action="store", dest="n_days", type=check_positive, default=5,
|
||||
help="Look for the tickers from those n past days")
|
||||
help="look for the tickers from those n past days")
|
||||
|
||||
try:
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
@@ -295,7 +297,7 @@ def spac(l_args):
|
||||
|
||||
n_ts_after = int((datetime.today() - timedelta(days=ns_parser.n_days)).timestamp())
|
||||
l_sub_reddits = ['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,
|
||||
@@ -308,14 +310,14 @@ def spac(l_args):
|
||||
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:
|
||||
|
||||
|
||||
# Make sure there is at least 1 ticker found on the post text
|
||||
l_tickers_found = set(re.findall("[A-Z]{3,5}", submission.selftext))
|
||||
if not l_tickers_found:
|
||||
@@ -362,18 +364,18 @@ def spac(l_args):
|
||||
print(f"{s_datetime} - {submission.title}")
|
||||
print(f"{s_link}")
|
||||
t_post = PrettyTable(['Subreddit', 'Flair', 'Score', '# Comments', 'Upvote %', "Awards"])
|
||||
t_post.add_row([submission.subreddit, submission.link_flair_text, submission.score,
|
||||
t_post.add_row([submission.subreddit, submission.link_flair_text, submission.score,
|
||||
submission.num_comments,f"{round(100*submission.upvote_ratio)}%", s_all_awards])
|
||||
print(t_post)
|
||||
print("\n")
|
||||
|
||||
# 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
|
||||
@@ -402,10 +404,12 @@ def spac(l_args):
|
||||
|
||||
# -------------------------------------------------------------------------------------------------------------------
|
||||
def spac_community(l_args):
|
||||
parser = argparse.ArgumentParser(prog='spac_c',
|
||||
description=""" Show other users SPACs announcement under subreddit SPACs [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='If popular, the posts retrieved are based on score rather than time')
|
||||
parser = argparse.ArgumentParser(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, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
@@ -437,18 +441,18 @@ def spac_community(l_args):
|
||||
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.author.name not in l_watchlist_author: # and submission.link_flair_text not in ['Yolo', 'Meme'] \
|
||||
|
||||
|
||||
# Make sure there is at least 1 ticker found on the post text
|
||||
l_tickers_found = set(re.findall("[A-Z]{3,5}", submission.selftext))
|
||||
if not l_tickers_found:
|
||||
l_tickers_found = set(re.findall("[A-Z]{3,5}", submission.title))
|
||||
|
||||
|
||||
if l_tickers_found:
|
||||
# Add another author's name to the parsed watchlists
|
||||
l_watchlist_author.append(submission.author.name)
|
||||
@@ -490,11 +494,11 @@ def spac_community(l_args):
|
||||
print(f"{s_datetime} - {submission.title}")
|
||||
print(f"{s_link}")
|
||||
t_post = PrettyTable(['Subreddit', 'Flair', 'Score', '# Comments', 'Upvote %', "Awards"])
|
||||
t_post.add_row([submission.subreddit, submission.link_flair_text, submission.score,
|
||||
t_post.add_row([submission.subreddit, submission.link_flair_text, submission.score,
|
||||
submission.num_comments,f"{round(100*submission.upvote_ratio)}%", s_all_awards])
|
||||
print(t_post)
|
||||
print("\n")
|
||||
|
||||
|
||||
# Check if search_submissions didn't get anymore posts
|
||||
else:
|
||||
break
|
||||
@@ -516,17 +520,19 @@ def spac_community(l_args):
|
||||
print("The following stock tickers have been mentioned across the previous SPACs:")
|
||||
print(s_watchlist_tickers[:-2])
|
||||
print("")
|
||||
|
||||
|
||||
except:
|
||||
print("")
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------------------------------------------------
|
||||
def wsb_community(l_args):
|
||||
parser = argparse.ArgumentParser(prog='wsb',
|
||||
description="""Show what WSB gang are up to in subreddit wallstreetbets [Reddit] """)
|
||||
parser.add_argument('-l', "--limit", action="store", dest="n_limit", type=check_positive, default=10, help='Limit of posts')
|
||||
parser.add_argument('-n', "--new", action="store_true", default=False, dest="b_new", help='If new, the posts retrieved are based on more recent rather than score')
|
||||
parser = argparse.ArgumentParser(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, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
@@ -542,9 +548,7 @@ def wsb_community(l_args):
|
||||
password=cfg.API_REDDIT_PASSWORD)
|
||||
|
||||
d_submission = {}
|
||||
d_watchlist_tickers = {}
|
||||
l_watchlist_links = list()
|
||||
l_watchlist_author = list()
|
||||
|
||||
psaw_api = PushshiftAPI()
|
||||
|
||||
@@ -552,91 +556,52 @@ def wsb_community(l_args):
|
||||
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:
|
||||
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.author.name not in l_watchlist_author: # and submission.link_flair_text not in ['Yolo', 'Meme'] \
|
||||
|
||||
# Make sure there is at least 1 ticker found on the post text
|
||||
l_tickers_found = set(re.findall("[A-Z]{3,5}", submission.selftext))
|
||||
if not l_tickers_found:
|
||||
l_tickers_found = set(re.findall("[A-Z]{3,5}", submission.title))
|
||||
|
||||
if l_tickers_found:
|
||||
# Add another author's name to the parsed watchlists
|
||||
l_watchlist_author.append(submission.author.name)
|
||||
if not submission.removed_by_category:
|
||||
|
||||
# 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://www.reddit.com{submission.permalink}")
|
||||
|
||||
l_watchlist_links.append(f"https://www.reddit.com{submission.permalink}")
|
||||
# delte below, not necessary I reckon. Probably just link?
|
||||
# Refactor data
|
||||
s_datetime = datetime.utcfromtimestamp(submission.created_utc).strftime("%d/%m/%Y %H:%M:%S")
|
||||
s_link = f"https://www.reddit.com{submission.permalink}"
|
||||
s_all_awards = ""
|
||||
for award in submission.all_awardings:
|
||||
s_all_awards += f"{award['count']} {award['name']}\n"
|
||||
s_all_awards = s_all_awards[:-2]
|
||||
|
||||
# Refactor data
|
||||
s_datetime = datetime.utcfromtimestamp(submission.created_utc).strftime("%d/%m/%Y %H:%M:%S")
|
||||
s_link = f"https://www.reddit.com{submission.permalink}"
|
||||
s_all_awards = ""
|
||||
for award in submission.all_awardings:
|
||||
s_all_awards += f"{award['count']} {award['name']}\n"
|
||||
s_all_awards = s_all_awards[:-2]
|
||||
# Create dictionary with data to construct dataframe allows to save data
|
||||
d_submission[submission.id] = {
|
||||
'created_utc': s_datetime,
|
||||
'subreddit': submission.subreddit,
|
||||
'link_flair_text': submission.link_flair_text,
|
||||
'title':submission.title,
|
||||
'score': submission.score,
|
||||
'link': s_link,
|
||||
'num_comments': submission.num_comments,
|
||||
'upvote_ratio': submission.upvote_ratio,
|
||||
'awards': s_all_awards
|
||||
}
|
||||
|
||||
# Create dictionary with data to construct dataframe allows to save data
|
||||
d_submission[submission.id] = {
|
||||
'created_utc': s_datetime,
|
||||
'subreddit': submission.subreddit,
|
||||
'link_flair_text': submission.link_flair_text,
|
||||
'title':submission.title,
|
||||
'score': submission.score,
|
||||
'link': s_link,
|
||||
'num_comments': submission.num_comments,
|
||||
'upvote_ratio': submission.upvote_ratio,
|
||||
'awards': s_all_awards
|
||||
}
|
||||
|
||||
# Print post data collected so far
|
||||
print(f"{s_datetime} - {submission.title}")
|
||||
print(f"{s_link}")
|
||||
t_post = PrettyTable(['Subreddit', 'Flair', 'Score', '# Comments', 'Upvote %', "Awards"])
|
||||
t_post.add_row([submission.subreddit, submission.link_flair_text, submission.score,
|
||||
submission.num_comments,f"{round(100*submission.upvote_ratio)}%", s_all_awards])
|
||||
print(t_post)
|
||||
print("\n")
|
||||
|
||||
# Print post data collected so far
|
||||
print(f"{s_datetime} - {submission.title}")
|
||||
print(f"{s_link}")
|
||||
t_post = PrettyTable(['Subreddit', 'Flair', 'Score', '# Comments', 'Upvote %', "Awards"])
|
||||
t_post.add_row([submission.subreddit, submission.link_flair_text, submission.score,
|
||||
submission.num_comments,f"{round(100*submission.upvote_ratio)}%", s_all_awards])
|
||||
print(t_post)
|
||||
print("")
|
||||
# Check if search_submissions didn't get anymore posts
|
||||
else:
|
||||
break
|
||||
|
||||
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])
|
||||
s_watchlist_tickers += f"{t_ticker[1]} {t_ticker[0]}, "
|
||||
n_tickers += 1
|
||||
except:
|
||||
pass
|
||||
if n_tickers:
|
||||
print("The following stock tickers have been mentioned across the previous SPACs:")
|
||||
print(s_watchlist_tickers[:-2])
|
||||
print("")
|
||||
|
||||
print("")
|
||||
except:
|
||||
print("")
|
||||
@@ -55,7 +55,7 @@ def print_technical_analysis(s_ticker, s_start, s_interval):
|
||||
def ta_menu(df_stock, s_ticker, s_start, s_interval):
|
||||
|
||||
# Add list of arguments that the technical analysis parser accepts
|
||||
ta_parser = argparse.ArgumentParser(prog='technical_analysis', add_help=False)
|
||||
ta_parser = argparse.ArgumentParser(prog='ta', add_help=False)
|
||||
ta_parser.add_argument('cmd', choices=['help', 'q', 'quit',
|
||||
'ema', 'sma', 'vwap', # overlap
|
||||
'cci', 'macd', 'rsi', 'stoch', # momentum
|
||||
@@ -69,7 +69,7 @@ def ta_menu(df_stock, s_ticker, s_start, s_interval):
|
||||
while True:
|
||||
# Get input command from user
|
||||
as_input = input('> ')
|
||||
|
||||
|
||||
# Parse fundamental analysis command of the list of possible commands
|
||||
try:
|
||||
(ns_known_args, l_args) = ta_parser.parse_known_args(as_input.split())
|
||||
@@ -111,7 +111,7 @@ def ta_menu(df_stock, s_ticker, s_start, s_interval):
|
||||
|
||||
elif ns_known_args.cmd == 'stoch':
|
||||
ta_momentum.stoch(l_args, s_ticker, s_interval, df_stock)
|
||||
|
||||
|
||||
# ---------------------------------------------------- TREND ----------------------------------------------------
|
||||
elif ns_known_args.cmd == 'adx':
|
||||
ta_trend.adx(l_args, s_ticker, s_interval, df_stock)
|
||||
|
||||
Reference in New Issue
Block a user