From 8fcdc14a0d99b02888c545e2353a6fa718f96174 Mon Sep 17 00:00:00 2001 From: didier Date: Sun, 7 Feb 2021 18:28:02 +0000 Subject: [PATCH] Add SMA to prediction techniques menu --- prediction_techniques/pred_menu.py | 74 ++++++++++++++++++++++++++++++ prediction_techniques/sma.py | 64 ++++++++++++++++++++++++++ stock_market_cli.py | 53 ++++++--------------- 3 files changed, 152 insertions(+), 39 deletions(-) create mode 100644 prediction_techniques/pred_menu.py create mode 100644 prediction_techniques/sma.py diff --git a/prediction_techniques/pred_menu.py b/prediction_techniques/pred_menu.py new file mode 100644 index 00000000000..f64f48b3706 --- /dev/null +++ b/prediction_techniques/pred_menu.py @@ -0,0 +1,74 @@ +import config_bot as cfg +import argparse +import datetime +from datetime import datetime +from stock_market_helper_funcs import * +import config_bot as cfg +import pandas as pd +import matplotlib.pyplot as plt +from pandas.plotting import register_matplotlib_converters +register_matplotlib_converters() + +from prediction_techniques import sma + +# ----------------------------------------------------------------------------------------------------------------------- +def print_prediction(s_ticker, s_start, s_interval): + """ Print help """ + + s_intraday = (f'Intraday {s_interval}', 'Daily')[s_interval == "1440min"] + + if s_start: + print(f"\n{s_intraday} Stock: {s_ticker} (from {s_start.strftime('%Y-%m-%d')})") + else: + print(f"\n{s_intraday} Stock: {s_ticker}") + + print("\nPrediction Techniques:") + print(" help show this prediction techniques menu again") + print(" q quit this menu, and shows back to main menu") + print(" quit quit to abandon program") + print("") + print(" sma simple moving average") + 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.add_argument('cmd', choices=['help', 'q', 'quit', + 'sma']) + + print_prediction(s_ticker, s_start, s_interval) + + # Loop forever and ever + 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()) + + except SystemExit: + print("The command selected doesn't exist\n") + continue + + if ns_known_args.cmd == 'help': + print_prediction(s_ticker, s_start, s_interval) + + elif ns_known_args.cmd == 'q': + # Just leave the FA menu + return False + + elif ns_known_args.cmd == 'quit': + # Abandon the program + return True + + # ------------------------------------------ SIMPLE MOVING AVERAGE ------------------------------------------ + elif ns_known_args.cmd == 'sma': + sma.simple_moving_average(l_args, s_ticker, s_interval, df_stock) + + # ------------------------------------------------------------------------------------------------------------ + else: + print("Command not recognized!") diff --git a/prediction_techniques/sma.py b/prediction_techniques/sma.py new file mode 100644 index 00000000000..15c9d16aeff --- /dev/null +++ b/prediction_techniques/sma.py @@ -0,0 +1,64 @@ +import argparse +import numpy as np +from stock_market_helper_funcs import * +import pandas as pd +import matplotlib.pyplot as plt +from pandas.plotting import register_matplotlib_converters +register_matplotlib_converters() + +# ----------------------------------------------------- SMA ----------------------------------------------------- +def simple_moving_average(l_args, s_ticker, s_interval, df_stock): + parser = argparse.ArgumentParser(prog='simple_moving_average', + description=""" Moving Averages are used to smooth the data in an array to + help eliminate noise and identify trends. The Simple Moving Average is literally + the simplest form of a moving average. Each output value is the average of the + previous n values. In a Simple Moving Average, each value in the time period carries + equal weight, and values outside of the time period are not included in the average. + This makes it less responsive to recent changes in the data, which can be useful for + filtering out those changes. """) + + parser.add_argument('-l', "--length", action="store", dest="n_length", type=check_positive, default=20, help='length of SMA window') + parser.add_argument('-d', "--days", action="store", dest="n_days", type=check_positive, default=5, help='prediction days') + + 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 + + l_predictions = list() + for pred_day in range(ns_parser.n_days): + if pred_day < ns_parser.n_length: + l_ma_stock = df_stock['4. close'].values[-ns_parser.n_length+pred_day:] + else: + l_ma_stock = list() + l_predictions.append(np.mean(np.append(l_ma_stock, l_predictions))) + + l_pred_days = get_next_stock_market_days(last_stock_day=df_stock['4. close'].index[-1], n_next_days=ns_parser.n_days) + df_pred = pd.Series(l_predictions, index=l_pred_days, name='Price') + + plt.plot(df_stock.index, df_stock['4. close'], lw=3) + plt.title(f"{ns_parser.n_length} Moving Average on {s_ticker} - {ns_parser.n_days} days prediction") + plt.xlim(df_stock.index[0], get_next_stock_market_days(df_pred.index[-1], 10)[-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) + df_ma = df_stock['4. close'].rolling(window=ns_parser.n_length).mean() + plt.plot(df_ma.index, df_ma, lw=2) + plt.plot(df_pred.index, df_pred, lw=2) + cmap = plt.get_cmap("tab10") + plt.axvspan(df_pred.index[0], df_pred.index[-1], facecolor=cmap(1), alpha=0.2) + xmin, xmax, ymin, ymax = plt.axis() + plt.vlines(df_stock.index[-1], ymin, ymax, colors=cmap(0), linewidth=1, linestyle='--', color='k') + plt.show() + + df_pred = df_pred.apply(lambda x: f"{x:.2f} $") + print(df_pred.to_string()) + print("") + + except: + print("") + diff --git a/stock_market_cli.py b/stock_market_cli.py index 913942636f3..473ea110caa 100644 --- a/stock_market_cli.py +++ b/stock_market_cli.py @@ -1,42 +1,7 @@ """ Example or something - Is this not informative enough? - - Load a specific stock - Then apply a specific TA on it - - Do this because AlphaVantage only allows 5 API calls per minutes. - This way we only need 1 call, and can apply TA to the result without - using an API request. - - Multiple TA with kind stock - - Do my own personal Fundamental Analysis Dataframe - Do option to explain important key metrics - - Do own personal Technical Analysis with multiple indicators perhaps? - - Split Menu into fa, ta and pred. Fundamental Analysis, Technical Analysis and Prediction, respectively. - - Do Reddit popularity study! - - By using defined ticker - - By looking for mentioned tickers - - By giving your own subreddit, using used ones. - - At the end, provide save tool where we save all data into an excel with: - - NIO_datetimesaved.xlsx - - Sheet1 - Profile/Overview (FMP or AV) - - Sheet2 - Finance (Market watch) - - Sheet3 - Earnings (Market watch) - - Sheet4 - SEC filings - - Sheet5 - Insiders - - Sheet6 - Analyst prices - - Sheet7 - News - - Sheet8 - Warnings & Key metrics - - Sheet9 - Reddit popularity - """ + import argparse import pandas as pd from stock_market_helper_funcs import * @@ -45,6 +10,7 @@ from technical_analysis import ta_menu as tam from due_diligence import dd_menu as ddm from discovery import disc_menu as dm from sentiment import sen_menu as sm +from prediction_techniques import pred_menu as pm import res_menu as rm # delete this important when automatic loading tesla @@ -205,8 +171,7 @@ def print_help(s_ticker, s_start, s_interval, b_is_market_open): print(" fa fundamental analysis, \t e.g.: income, balance, cash, earnings") print(" ta technical analysis, \t e.g.: ema, macd, rsi, adx, bbands, obv") print(" dd in-depth due-diligence, \t e.g.: news, analyst, shorts, insider, sec") - #print("") - #print(" pred prediction techniques, \t e.g.: regression, arima, rnn, lstm, prophet") + print(" pred prediction techniques, \t e.g.: regression, arima, rnn, lstm, prophet") ''' print("\nPrediction:") @@ -244,7 +209,7 @@ def main(): menu_parser = argparse.ArgumentParser(prog='stock_market_bot', add_help=False) menu_parser.add_argument('opt', choices=['help', 'quit', 'q', 'clear', 'load', 'view', - 'disc', 'sen', 'res', 'fa', 'ta', 'dd']) + 'disc', 'sen', 'res', 'fa', 'ta', 'dd', 'pred']) # Print first welcome message and help @@ -348,6 +313,16 @@ def main(): else: print_help(s_ticker, s_start, s_interval, b_is_stock_market_open()) + # PREDICTION TECHNIQUES + elif ns_known_args.opt == 'pred': + b_quit = pm.pred_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") + return + else: + print_help(s_ticker, s_start, s_interval, b_is_stock_market_open()) + else: print('Shouldnt see this command!')