From a9561d83bece72bd763de405054dcd0e4a8a2087 Mon Sep 17 00:00:00 2001 From: didier Date: Sun, 31 Jan 2021 18:16:11 +0000 Subject: [PATCH] Add price target from analysts from Business Insider --- due_diligence/business_insider_api.py | 88 +++++++++++++++++++++++++++ due_diligence/dd_menu.py | 9 ++- stock_market_cli.py | 2 +- 3 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 due_diligence/business_insider_api.py diff --git a/due_diligence/business_insider_api.py b/due_diligence/business_insider_api.py new file mode 100644 index 00000000000..198209ce57a --- /dev/null +++ b/due_diligence/business_insider_api.py @@ -0,0 +1,88 @@ +from bs4 import BeautifulSoup +from alpha_vantage.timeseries import TimeSeries +from stock_market_helper_funcs import * +import requests +import pandas as pd +import re +import json +import config_bot as cfg +from datetime import datetime +import argparse +from fuzzywuzzy import fuzz +import matplotlib.pyplot as plt +from pandas.plotting import register_matplotlib_converters +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') + + 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") + + for script in text_soup_market_business_insider.find_all('script'): + # Get Analyst data + if 'window.analyseChartConfigs.push' in script.get_text(): + # Extract config data: + 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 = 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', + 'schlecht':'SELL'}, inplace=True) + df_analyst_data['Date'] = pd.to_datetime(df_analyst_data['Date']) + df_analyst_data = df_analyst_data.set_index('Date') + + # Slice start of ratings + if s_start: + df_analyst_data = df_analyst_data[s_start:] + + if s_interval == "1440min": + plt.plot(df_stock.index, df_stock['5. adjusted close'].values, lw=3) + # Intraday + else: + plt.plot(df_stock.index, df_stock['4. close'].values, lw=3) + + if s_start: + plt.plot(df_analyst_data.groupby(by=['Date']).mean()[s_start:]) + else: + plt.plot(df_analyst_data.groupby(by=['Date']).mean()) + + plt.scatter(df_analyst_data.index, df_analyst_data['Price Target'], c='r', s=40) + + plt.legend(['Closing Price', 'Average Price Target', 'Price Target']) + + plt.title(f"{s_ticker} (Time Series) and Price Target") + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.xlabel('Time') + plt.ylabel('Share Price ($)') + 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() + print("") + + 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 diff --git a/due_diligence/dd_menu.py b/due_diligence/dd_menu.py index 6c2e25d90a6..9c3939512c5 100644 --- a/due_diligence/dd_menu.py +++ b/due_diligence/dd_menu.py @@ -15,6 +15,7 @@ from due_diligence import market_watch_api as mw_api from due_diligence import reddit_api as r_api from due_diligence import quandl_api as q_api from due_diligence import financial_modeling_prep_api as fmp_api +from due_diligence import business_insider_api as bi_api # ----------------------------------------------------------------------------------------------------------------------- @@ -37,6 +38,7 @@ def print_due_diligence(s_ticker, s_start, s_interval): print(" red gets due diligence from another user's post [Reddit]") print(" analyst analyst prices and ratings of the company [Finviz]") print(" rating rating of the company from strong sell to strong buy [FMP]") + print(" pt price targets over time [Business Insider]") print(" insider insider trading of the company [Finviz]") print(" sec SEC filings [Market Watch]") print(" short short interest [Quandl]") @@ -46,7 +48,7 @@ def print_due_diligence(s_ticker, s_start, s_interval): # ---------------------------------------------------- MENU ---------------------------------------------------- -def dd_menu(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) @@ -54,6 +56,7 @@ def dd_menu(s_ticker, s_start, s_interval): 'red', # Reddit 'short', # Quandl 'rating', # FMP + 'pt', # BI 'insider', 'news', 'analyst', # Finviz 'warnings', 'sec']) # MW @@ -97,6 +100,10 @@ def dd_menu(s_ticker, s_start, s_interval): elif ns_known_args.cmd == 'analyst': fvz_api.analyst(l_args, s_ticker) + # BUSINESS INSIDER API + elif ns_known_args.cmd == 'pt': + bi_api.price_target_from_analysts(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) diff --git a/stock_market_cli.py b/stock_market_cli.py index 2dbdcc29dda..020e4ff4e0b 100644 --- a/stock_market_cli.py +++ b/stock_market_cli.py @@ -316,7 +316,7 @@ def main(): # DUE DILIGENCE MENU elif ns_known_args.opt == 'dd': - b_quit = ddm.dd_menu(s_ticker, s_start, s_interval) + b_quit = ddm.dd_menu(df_stock, s_ticker, s_start, s_interval) if b_quit: print("Hope you made money today. Good bye my lover, good bye my friend.\n")