Add Insider Activity over time command from Business Insider

This commit is contained in:
didier
2021-01-31 19:59:22 +00:00
parent f073b50843
commit 2db75c1d02
2 changed files with 118 additions and 1 deletions

View File

@@ -201,3 +201,116 @@ def estimates(l_args, s_ticker):
except:
print("")
return
# ----------------------------------------------- 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')
try:
(ns_parser, l_unknown_args) = parser.parse_known_args(l_args)
if l_unknown_args:
print(f"The following args couldn't be interpreted: {l_unknown_args}\n")
return
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"})):
#print(insider_val.text.strip())
l_insider_vals.append(insider_val.text.strip())
# Add value to dictionary
if (idx+1)%6 == 0:
# Check if we are still parsing insider trading activity
if '/' not in l_insider_vals[0]:
break
d_insider[(idx+1)//6] = l_insider_vals
l_insider_vals = list()
df_insider = pd.DataFrame.from_dict(d_insider, orient='index',
columns = ['Date', 'Shares Traded', 'Shares Held', 'Price', 'Type', 'Option'])
df_insider['Date'] = pd.to_datetime(df_insider['Date'])
df_insider = df_insider.set_index('Date')
df_insider = df_insider.sort_index(ascending=True)
if s_start:
df_insider = df_insider[s_start:]
pfig, ax = plt.subplots()
if s_interval == "1440min":
plt.plot(df_stock.index, df_stock['5. adjusted close'].values, lw=3)
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")
plt.xlabel('Time')
plt.ylabel('Share Price ($)')
df_insider['Trade'] = df_insider.apply(lambda row: (1, -1)[row.Type == 'Sell'] * float(row['Shares Traded'].replace(',','')), axis=1)
plt.xlim(df_insider.index[0], df_stock.index[-1])
min_price, max_price = ax.get_ylim()
price_range = max_price - min_price
shares_range = df_insider[df_insider['Type'] == 'Buy'].groupby(by=['Date']).sum()['Trade'].max() - df_insider[df_insider['Type'] == 'Sell'].groupby(by=['Date']).sum()['Trade'].min()
n_proportion = price_range / shares_range
for ind in df_insider[df_insider['Type'] == 'Sell'].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]
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,
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]
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]),
colors='green', ls='-', lw=5)
plt.grid(b=True, which='major', color='#666666', linestyle='-')
plt.minorticks_on()
plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2)
plt.show()
l_names = list()
for s_name in text_soup_market_business_insider.findAll('a', {'onclick':"silentTrackPI()"}):
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

View File

@@ -40,6 +40,7 @@ def print_due_diligence(s_ticker, s_start, s_interval):
print(" rating rating of the company from strong sell to strong buy [FMP]")
print(" pt price targets over time [Business Insider]")
print(" est quarter and year analysts earnings estimates [Business Insider]")
print(" ins insider activity over time [Business Insider]")
print(" insider insider trading of the company [Finviz]")
print(" sec SEC filings [Market Watch]")
print(" short short interest [Quandl]")
@@ -57,7 +58,7 @@ def dd_menu(df_stock, s_ticker, s_start, s_interval):
'red', # Reddit
'short', # Quandl
'rating', # FMP
'pt', 'est', # BI
'pt', 'est', 'ins', # BI
'insider', 'news', 'analyst', # Finviz
'warnings', 'sec']) # MW
@@ -108,6 +109,9 @@ def dd_menu(df_stock, s_ticker, s_start, s_interval):
elif ns_known_args.cmd == 'est':
bi_api.estimates(l_args, s_ticker)
elif ns_known_args.cmd == 'ins':
bi_api.insider_activity(l_args, df_stock, s_ticker, s_start, s_interval)
# FINANCIAL MODELING PREP API
elif ns_known_args.cmd == 'rating':
fmp_api.rating(l_args, s_ticker)