mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-27 04:31:13 +00:00
Split code across different files
This commit is contained in:
@@ -1,430 +0,0 @@
|
||||
""" 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.
|
||||
|
||||
Finviz for data
|
||||
|
||||
"""
|
||||
|
||||
from alpha_vantage.timeseries import TimeSeries
|
||||
import argparse
|
||||
import config_bot as cfg
|
||||
import pandas as pd
|
||||
import pandas_ta as ta
|
||||
from datetime import datetime
|
||||
import matplotlib
|
||||
import matplotlib.pyplot as plt
|
||||
from pandas.plotting import register_matplotlib_converters
|
||||
from pytz import timezone
|
||||
from holidays import US as holidaysUS
|
||||
from datetime import datetime, time as Time
|
||||
register_matplotlib_converters()
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
def print_help(s_ta_ticker, s_ta_start, b_is_market_open):
|
||||
""" Print help
|
||||
"""
|
||||
print("What do you want to do?")
|
||||
|
||||
print("\n--- Screeners:")
|
||||
print("view view and load a specific stock ticker for technical analysis")
|
||||
print("gainers show latest top gainers")
|
||||
print("load load a specific stock ticker for technical analysis")
|
||||
print("clear clear a specific stock ticker from technical analysis")
|
||||
|
||||
if s_ta_ticker and s_ta_start:
|
||||
print(f"\n--- Technical Analysis on {s_ta_ticker} starting at {s_ta_start.strftime('%Y-%m-%d')}:")
|
||||
elif s_ta_ticker:
|
||||
print(f"\n--- Technical Analysis on {s_ta_ticker}:")
|
||||
else:
|
||||
print("\n--- Technical Analysis:")
|
||||
print("sma simple moving average")
|
||||
print("ema exponential moving average")
|
||||
|
||||
print("\n--- Prediction:")
|
||||
print("RNN")
|
||||
print("ARIMA")
|
||||
print("LSTM")
|
||||
print("Facebook prophet")
|
||||
|
||||
print(f"\n--- Market {('Closed', 'Open')[b_is_market_open]}. Play stocks:")
|
||||
print("Stock name, and how much money to bet?")
|
||||
|
||||
print("\n--- Others:")
|
||||
print("help help to see this menu again")
|
||||
print("quit to abandon the program")
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
def check_positive(value):
|
||||
ivalue = int(value)
|
||||
if ivalue <= 0:
|
||||
raise argparse.ArgumentTypeError(f"{value} is an invalid positive int value")
|
||||
return ivalue
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
def valid_date(s):
|
||||
try:
|
||||
return datetime.strptime(s, "%Y-%m-%d")
|
||||
except ValueError:
|
||||
raise argparse.ArgumentTypeError("Not a valid date: {s}")
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
def plot_view_stock(df, symbol):
|
||||
pfig, axVolume = plt.subplots()
|
||||
plt.bar(df.index, df['5. volume'].values, color='k', alpha=0.8)
|
||||
plt.ylabel('Volume')
|
||||
axPrice = axVolume.twinx()
|
||||
plt.plot(df.index, df.iloc[:, :-1])
|
||||
plt.title(symbol + ' (Time Series)')
|
||||
plt.xlim(df.index[0], df.index[-1])
|
||||
plt.xlabel('Time')
|
||||
plt.ylabel('Share Price ($)')
|
||||
plt.legend(df.columns)
|
||||
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()
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
def plot_stock_ta(df_stock, s_stock, df_ta, s_ta):
|
||||
plt.plot(df_stock.index, df_stock['4. close'].values)
|
||||
plt.plot(df_ta.index, df_ta.values)
|
||||
plt.title(f"{s_ta} on {s_stock}")
|
||||
plt.xlim(df_stock.index[0], df_stock.index[-1])
|
||||
plt.xlabel('Time')
|
||||
plt.ylabel('Share Price ($)')
|
||||
plt.legend([s_stock, s_ta])
|
||||
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()
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
def b_is_stock_market_open():
|
||||
''' checks if the stock market is open '''
|
||||
# Get current US time
|
||||
now = datetime.now(timezone('US/Eastern'))
|
||||
# Check if it is a weekend
|
||||
if now.date().weekday() > 4:
|
||||
return False
|
||||
# Check if it is a holiday
|
||||
if now.strftime('%Y-%m-%d') in holidaysUS():
|
||||
return False
|
||||
# Check if it hasn't open already
|
||||
if now.time() < Time(hour=9, minute=30, second=0):
|
||||
return False
|
||||
# Check if it has already closed
|
||||
if now.time() > Time(hour=16, minute=0, second=0):
|
||||
return False
|
||||
# Otherwise, Stock Market is open!
|
||||
return True
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
def main():
|
||||
""" Main function of the program
|
||||
"""
|
||||
|
||||
# temporary
|
||||
#parser.add_argument('-a', action="store_true", default=False, help='example of flag')
|
||||
#parser.add_argument('-b', action="store", dest="b", help='example of string')
|
||||
#parser.add_argument('-c', action="store", dest="c", type=int, help='example of int')
|
||||
|
||||
s_ta_ticker = ""
|
||||
s_ta_start = ""
|
||||
main_parser = argparse.ArgumentParser(prog='stock_market_bot', add_help=False)
|
||||
|
||||
# Add list of arguments that the main parser accepts
|
||||
main_parser.add_argument('cmd', choices=['quit', 'help', 'gainers' ,'view', 'load', 'clear', 'sma', 'ema'])
|
||||
|
||||
# Print first welcome message and help
|
||||
print("\nWelcome to Didier's Stock Market Bot\n")
|
||||
print_help(s_ta_ticker, s_ta_start, b_is_stock_market_open())
|
||||
print("\n")
|
||||
|
||||
# Loop forever and ever
|
||||
while True:
|
||||
# Get input command from user
|
||||
as_input = input('> ')
|
||||
|
||||
# Parse main command of the list of possible commands
|
||||
try:
|
||||
(ns_known_args, l_args) = main_parser.parse_known_args(as_input.split())
|
||||
except SystemExit:
|
||||
print("The command selected doesn't exist\n")
|
||||
continue
|
||||
|
||||
# ---------------------------------------------------- GAINERS ----------------------------------------------------
|
||||
if ns_known_args.cmd == 'gainers':
|
||||
parser = argparse.ArgumentParser(prog='gainers',
|
||||
description='Show top ticker gainers from Yahoo Finance')
|
||||
parser.add_argument('-n', "--num", action="store", dest="n_gainers", type=int, default=5, choices=range(1, 25),
|
||||
help='Number of the top gainers stocks to retrieve (default 5)')
|
||||
|
||||
try:
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
except SystemExit:
|
||||
print("")
|
||||
continue
|
||||
|
||||
if l_unknown_args:
|
||||
print(f"The following args couldn't be interpreted: {l_unknown_args}")
|
||||
|
||||
df_gainers = pd.read_html('https://finance.yahoo.com/screener/predefined/day_gainers')[0]
|
||||
print(df_gainers.head(ns_parser.n_gainers).to_string(index=False))
|
||||
|
||||
|
||||
# ---------------------------------------------------- VIEW ----------------------------------------------------
|
||||
elif ns_known_args.cmd == 'view':
|
||||
parser = argparse.ArgumentParser(prog='view',
|
||||
description='Given a stock market ticker, allows to see historical data of \
|
||||
the corresponding stock. Note that the alpha_vantage key is necessary \
|
||||
for this to work!')
|
||||
parser.add_argument('-t', "--ticker" ,action="store", dest="s_ticker", required=True, help='Stock ticker')
|
||||
parser.add_argument("--type", action="store", dest="n_type", type=check_positive, default=4,
|
||||
help='1234 corresponds to types: 1. open; 2. high; 3.low; 4. close \
|
||||
while 14 corresponds to types: 1.open; 4. close')
|
||||
parser.add_argument('-s', "--start", type=valid_date, dest="s_start_date",
|
||||
help="The starting date (format YYYY-MM-DD) of the stock")
|
||||
|
||||
try:
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
except SystemExit:
|
||||
print("")
|
||||
continue
|
||||
|
||||
if l_unknown_args:
|
||||
print(f"The following args couldn't be interpreted: {l_unknown_args}")
|
||||
|
||||
# Currently only supports daily stocks
|
||||
# TODO: Intra-daily perhaps
|
||||
ts = TimeSeries(key=cfg.API_KEY, output_format='pandas')
|
||||
try:
|
||||
df_stock, d_stock_metadata = ts.get_daily(symbol=ns_parser.s_ticker, outputsize='full')
|
||||
except:
|
||||
print("Either the ticker or the API_KEY are invalids. Try again!")
|
||||
continue
|
||||
|
||||
s_ta_ticker = ns_parser.s_ticker
|
||||
|
||||
# Add function to plot data
|
||||
ln_col_idx = [int(x)-1 for x in list(str(ns_parser.n_type))]
|
||||
# Check that the types given are not bigger than 3, as there are only 4 types (0-3)
|
||||
if len([i for i in ln_col_idx if i > 3]) > 0:
|
||||
print("An index bigger than 3 was given, which is wrong. Try again")
|
||||
continue
|
||||
|
||||
# Slice dataframe from the starting date YYYY-MM-DD selected
|
||||
if ns_parser.s_start_date:
|
||||
df_stock = df_stock[ns_parser.s_start_date:]
|
||||
s_ta_start = ns_parser.s_start_date
|
||||
|
||||
ln_col_idx.append(4) # Append last column of df to be filtered which corresponds to: 5. Volume
|
||||
|
||||
plot_view_stock(df_stock.iloc[:, ln_col_idx], ns_parser.s_ticker)
|
||||
|
||||
|
||||
# ---------------------------------------------------- LOAD ----------------------------------------------------
|
||||
elif ns_known_args.cmd == 'load':
|
||||
parser = argparse.ArgumentParser(prog='load',
|
||||
description=""" Given a stock market ticker, and an optional starting time,
|
||||
load a stock in order to perform technical analysis""")
|
||||
parser.add_argument('-t', "--ticker", action="store", dest="s_ticker", required=True, help='Stock ticker')
|
||||
parser.add_argument("--type", action="store", dest="n_type", type=check_positive, default=4,
|
||||
help='1234 corresponds to types: 1. open; 2. high; 3.low; 4. close \
|
||||
while 14 corresponds to types: 1.open; 4. close')
|
||||
parser.add_argument('-s', "--start", type=valid_date, dest="s_start_date",
|
||||
help="The starting date (format YYYY-MM-DD) of the stock")
|
||||
|
||||
try:
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
except SystemExit:
|
||||
print("")
|
||||
continue
|
||||
|
||||
if l_unknown_args:
|
||||
print(f"The following args couldn't be interpreted: {l_unknown_args}")
|
||||
|
||||
# Currently only supports daily stocks
|
||||
# TODO: Intra-daily perhaps
|
||||
ts = TimeSeries(key=cfg.API_KEY, output_format='pandas')
|
||||
try:
|
||||
df_stock, d_stock_metadata = ts.get_daily(symbol=ns_parser.s_ticker, outputsize='full')
|
||||
except:
|
||||
print("Either the ticker or the API_KEY are invalids. Try again!")
|
||||
continue
|
||||
|
||||
s_ta_ticker = ns_parser.s_ticker
|
||||
|
||||
# Add function to plot data
|
||||
ln_col_idx = [int(x)-1 for x in list(str(ns_parser.n_type))]
|
||||
# Check that the types given are not bigger than 3, as there are only 4 types (0-3)
|
||||
if len([i for i in ln_col_idx if i > 3]) > 0:
|
||||
print("An index bigger than 3 was given, which is wrong. Try again")
|
||||
continue
|
||||
|
||||
# Slice dataframe from the starting date YYYY-MM-DD selected
|
||||
if ns_parser.s_start_date:
|
||||
df_stock = df_stock[ns_parser.s_start_date:]
|
||||
s_ta_start = ns_parser.s_start_date
|
||||
else:
|
||||
s_ta_start = ""
|
||||
|
||||
if s_ta_start:
|
||||
print(f"Loading {s_ta_ticker} stock with starting period {s_ta_start.strftime('%Y-%m-%d')} for technical analysis.")
|
||||
else:
|
||||
print(f"Loading {s_ta_ticker} stock for technical analysis.")
|
||||
|
||||
|
||||
# ---------------------------------------------------- CLEAR ----------------------------------------------------
|
||||
elif ns_known_args.cmd == 'clear':
|
||||
print("Clearing stock ticker to be used for technical analysis")
|
||||
s_ta_ticker = ""
|
||||
s_ta_start = ""
|
||||
|
||||
# --------------------------------------------------------------------------------------------------------------
|
||||
# -------------------------------------------- TECHNICAL ANALYSIS ----------------------------------------------
|
||||
# --------------------------------------------------------------------------------------------------------------
|
||||
|
||||
# ---------------------------------------------------- SMA ----------------------------------------------------
|
||||
elif ns_known_args.cmd == 'sma':
|
||||
parser = argparse.ArgumentParser(prog='sma',
|
||||
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('-p', "--period", action="store", dest="n_time_period", type=check_positive, default=20,
|
||||
help='Number of data points used to calculate each moving average value.')
|
||||
parser.add_argument("-s", "--start", type=valid_date, dest="s_start_date",
|
||||
help="The starting date (format YYYY-MM-DD) of the stock")
|
||||
if s_ta_ticker:
|
||||
parser.add_argument('-t', "--ticker", action="store", dest="s_ticker", default=s_ta_ticker, help='Stock ticker')
|
||||
else:
|
||||
parser.add_argument('-t', "--ticker", action="store", dest="s_ticker", required=True, help='Stock ticker')
|
||||
|
||||
try:
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
except SystemExit:
|
||||
print("")
|
||||
continue
|
||||
|
||||
if l_unknown_args:
|
||||
print(f"The following args couldn't be interpreted: {l_unknown_args}")
|
||||
|
||||
try: # Get stock data
|
||||
ts = TimeSeries(key=cfg.API_KEY, output_format='pandas')
|
||||
df_stock, d_stock_metadata = ts.get_daily(symbol=ns_parser.s_ticker, outputsize='full')
|
||||
except:
|
||||
print("ERROR! Try again!")
|
||||
print("Check that: 1. The ticker symbol exists and is valid")
|
||||
print(" 2. Less than 5 AlphaVantage requests have been made in 1 minute")
|
||||
print(" 3. The API_KEY is (still) valid")
|
||||
continue
|
||||
|
||||
# Update TA ticker
|
||||
s_ta_ticker = ns_parser.s_ticker
|
||||
|
||||
# Update TA starting point if needed
|
||||
if ns_parser.s_start_date:
|
||||
s_ta_start = ns_parser.s_start_date
|
||||
|
||||
# Slice dataframe from the starting date YYYY-MM-DD selected
|
||||
if s_ta_start:
|
||||
df_stock = df_stock[ns_parser.s_start_date:]
|
||||
|
||||
df_ta = ta.sma(df_stock['4. close'], timeperiod=ns_parser.n_time_period).dropna()
|
||||
|
||||
plot_stock_ta(df_stock, d_stock_metadata['2. Symbol'], df_ta, f"{ns_parser.n_time_period} SMA")
|
||||
|
||||
continue
|
||||
|
||||
|
||||
# ---------------------------------------------------- EMA ----------------------------------------------------
|
||||
elif ns_known_args.cmd == 'ema':
|
||||
parser = argparse.ArgumentParser(prog='ema',
|
||||
description=""" The Exponential Moving Average is a staple of technical
|
||||
analysis and is used in countless technical indicators. 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. However, the Exponential
|
||||
Moving Average is a cumulative calculation, including all data. Past values have
|
||||
a diminishing contribution to the average, while more recent values have a greater
|
||||
contribution. This method allows the moving average to be more responsive to changes
|
||||
in the data. """)
|
||||
parser.add_argument('-p', "--period", action="store", dest="n_time_period", type=check_positive, default=20,
|
||||
help='Number of data points used to calculate each moving average value.')
|
||||
parser.add_argument("-s", "--start", type=valid_date, dest="s_start_date",
|
||||
help="The starting date (format YYYY-MM-DD) of the stock")
|
||||
if s_ta_ticker:
|
||||
parser.add_argument('-t', "--ticker", action="store", dest="s_ticker", default=s_ta_ticker, help='Stock ticker')
|
||||
else:
|
||||
parser.add_argument('-t', "--ticker", action="store", dest="s_ticker", required=True, help='Stock ticker')
|
||||
|
||||
try:
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
except SystemExit:
|
||||
print("")
|
||||
continue
|
||||
|
||||
if l_unknown_args:
|
||||
print(f"The following args couldn't be interpreted: {l_unknown_args}")
|
||||
|
||||
try: # Get stock data
|
||||
ts = TimeSeries(key=cfg.API_KEY, output_format='pandas')
|
||||
df_stock, d_stock_metadata = ts.get_daily(symbol=ns_parser.s_ticker, outputsize='full')
|
||||
except:
|
||||
print("ERROR! Try again!")
|
||||
print("Check that: 1. The ticker symbol exists and is valid")
|
||||
print(" 2. Less than 5 AlphaVantage requests have been made in 1 minute")
|
||||
print(" 3. The API_KEY is (still) valid")
|
||||
continue
|
||||
|
||||
# Update TA ticker
|
||||
s_ta_ticker = ns_parser.s_ticker
|
||||
|
||||
# Update TA starting point if needed
|
||||
if ns_parser.s_start_date:
|
||||
s_ta_start = ns_parser.s_start_date
|
||||
|
||||
# Slice dataframe from the starting date YYYY-MM-DD selected
|
||||
if s_ta_start:
|
||||
df_stock = df_stock[ns_parser.s_start_date:]
|
||||
|
||||
df_ta = ta.ema(df_stock['4. close'], timeperiod=ns_parser.n_time_period).dropna()
|
||||
|
||||
plot_stock_ta(df_stock, d_stock_metadata['2. Symbol'], df_ta, f"{ns_parser.n_time_period} EMA")
|
||||
|
||||
continue
|
||||
|
||||
|
||||
# ---------------------------------------------------- HELP ----------------------------------------------------
|
||||
elif ns_known_args.cmd == 'help':
|
||||
print_help(s_ta_ticker, s_ta_start, b_is_stock_market_open())
|
||||
|
||||
# ---------------------------------------------------- QUIT ----------------------------------------------------
|
||||
elif ns_known_args.cmd == 'quit':
|
||||
print("Hope you made money today. Good bye my lover, good bye my friend.\n")
|
||||
break
|
||||
|
||||
else:
|
||||
print('Shouldnt see this command!')
|
||||
|
||||
print("\n")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
172
stock_market_cli.py
Normal file
172
stock_market_cli.py
Normal file
@@ -0,0 +1,172 @@
|
||||
""" 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.
|
||||
|
||||
Finviz for data
|
||||
|
||||
"""
|
||||
|
||||
from alpha_vantage.timeseries import TimeSeries
|
||||
import argparse
|
||||
import config_bot as cfg
|
||||
import pandas as pd
|
||||
import pandas_ta as ta
|
||||
from pandas.plotting import register_matplotlib_converters
|
||||
register_matplotlib_converters()
|
||||
|
||||
from stock_market_helper_funcs import *
|
||||
import stock_market_menu as smm
|
||||
import stock_market_technical_analysis as smta
|
||||
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
def print_help(s_ticker, s_start, b_is_market_open):
|
||||
""" Print help
|
||||
"""
|
||||
print("What do you want to do?")
|
||||
|
||||
print("\nMenu:")
|
||||
print(" gainers show latest top gainers")
|
||||
print(" view view and load a specific stock ticker for technical analysis")
|
||||
print(" clear clear a specific stock ticker from technical analysis")
|
||||
print(" load load a specific stock ticker for technical analysis")
|
||||
print(" help help to see this menu again")
|
||||
print(" quit to abandon the program")
|
||||
|
||||
if s_ticker and s_start:
|
||||
print(f"\n-----> {s_ticker} starting at {s_start.strftime('%Y-%m-%d')} <-----")
|
||||
elif s_ticker:
|
||||
print(f"\n-----> {s_ticker} <-----")
|
||||
else:
|
||||
print("\n-----> ? <-----")
|
||||
|
||||
print("\nFundamental Analysis:")
|
||||
print(" example not yet covered")
|
||||
|
||||
print("\nTechnical Analysis:")
|
||||
print(" sma simple moving average")
|
||||
print(" ema exponential moving average")
|
||||
|
||||
print("\nPrediction:")
|
||||
print(" ma")
|
||||
print(" ema")
|
||||
print(" lr")
|
||||
print(" knn")
|
||||
print(" arima")
|
||||
print(" rnn")
|
||||
print(" lstm")
|
||||
print(" prophet")
|
||||
|
||||
print(f"\nMarket {('Closed', 'Open')[b_is_market_open]}. Play stocks:")
|
||||
print("Stock name, and how much money to bet?")
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
def main():
|
||||
""" Main function of the program
|
||||
"""
|
||||
|
||||
# temporary
|
||||
#parser.add_argument('-a', action="store_true", default=False, help='example of flag')
|
||||
#parser.add_argument('-b', action="store", dest="b", help='example of string')
|
||||
#parser.add_argument('-c', action="store", dest="c", type=int, help='example of int')
|
||||
|
||||
s_ticker = ""
|
||||
s_start = ""
|
||||
df_stock = pd.DataFrame()
|
||||
|
||||
main_parser = argparse.ArgumentParser(prog='stock_market_bot', add_help=False)
|
||||
|
||||
# Add list of arguments that the main parser accepts
|
||||
main_parser.add_argument('cmd', choices=['quit', 'help', 'gainers' ,'view', 'load', 'clear', 'sma', 'ema'])
|
||||
|
||||
# Print first welcome message and help
|
||||
print("\nWelcome to Didier's Stock Market Bot\n")
|
||||
print_help(s_ticker, s_start, b_is_stock_market_open())
|
||||
print("\n")
|
||||
|
||||
# Loop forever and ever
|
||||
while True:
|
||||
# Get input command from user
|
||||
as_input = input('> ')
|
||||
|
||||
# Parse main command of the list of possible commands
|
||||
try:
|
||||
(ns_known_args, l_args) = main_parser.parse_known_args(as_input.split())
|
||||
except SystemExit:
|
||||
print("The command selected doesn't exist\n")
|
||||
continue
|
||||
|
||||
# --------------------------------------------------------------------------------------------------------------
|
||||
# --------------------------------------------------- MENU -----------------------------------------------------
|
||||
# --------------------------------------------------------------------------------------------------------------
|
||||
|
||||
# --------------------------------------------------- GAINERS --------------------------------------------------
|
||||
if ns_known_args.cmd == 'gainers':
|
||||
smm.gainers(l_args)
|
||||
continue
|
||||
|
||||
# --------------------------------------------------- CLEAR ----------------------------------------------------
|
||||
elif ns_known_args.cmd == 'clear':
|
||||
print("Clearing stock ticker to be used for analysis")
|
||||
s_ticker = ""
|
||||
s_start = ""
|
||||
|
||||
# ---------------------------------------------------- LOAD ----------------------------------------------------
|
||||
elif ns_known_args.cmd == 'load':
|
||||
[s_ticker, s_start, df_stock] = smm.load(l_args, s_ticker, s_start, df_stock)
|
||||
continue
|
||||
|
||||
# ---------------------------------------------------- VIEW ----------------------------------------------------
|
||||
elif ns_known_args.cmd == 'view':
|
||||
smm.view(l_args, s_ticker, s_start)
|
||||
continue
|
||||
|
||||
# ---------------------------------------------------- HELP ----------------------------------------------------
|
||||
elif ns_known_args.cmd == 'help':
|
||||
print_help(s_ticker, s_start, b_is_stock_market_open())
|
||||
|
||||
# ----------------------------------------------------- QUIT ----------------------------------------------------
|
||||
elif ns_known_args.cmd == 'quit':
|
||||
print("Hope you made money today. Good bye my lover, good bye my friend.\n")
|
||||
break
|
||||
|
||||
# --------------------------------------------------------------------------------------------------------------
|
||||
# ------------------------------------------- FUNDAMENTAL ANALYSIS ---------------------------------------------
|
||||
# --------------------------------------------------------------------------------------------------------------
|
||||
|
||||
# --------------------------------------------------------------------------------------------------------------
|
||||
# -------------------------------------------- TECHNICAL ANALYSIS ----------------------------------------------
|
||||
# --------------------------------------------------------------------------------------------------------------
|
||||
|
||||
# --------------------------------------------------------------------------------------------------------------
|
||||
# ------------------------------------------------ PREDICTION --------------------------------------------------
|
||||
# --------------------------------------------------------------------------------------------------------------
|
||||
|
||||
# ---------------------------------------------------- SMA ----------------------------------------------------
|
||||
elif ns_known_args.cmd == 'sma':
|
||||
[s_ticker, s_start] = smta.sma(l_args, s_ticker, s_start)
|
||||
continue
|
||||
|
||||
# ---------------------------------------------------- EMA ----------------------------------------------------
|
||||
elif ns_known_args.cmd == 'ema':
|
||||
[s_ticker, s_start] = smta.ema(l_args, s_ticker, s_start)
|
||||
continue
|
||||
|
||||
|
||||
|
||||
else:
|
||||
print('Shouldnt see this command!')
|
||||
|
||||
print("\n")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
76
stock_market_helper_funcs.py
Normal file
76
stock_market_helper_funcs.py
Normal file
@@ -0,0 +1,76 @@
|
||||
|
||||
from pytz import timezone
|
||||
from holidays import US as holidaysUS
|
||||
from datetime import datetime, time as Time
|
||||
import matplotlib
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
def check_positive(value):
|
||||
ivalue = int(value)
|
||||
if ivalue <= 0:
|
||||
raise argparse.ArgumentTypeError(f"{value} is an invalid positive int value")
|
||||
return ivalue
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
def valid_date(s):
|
||||
try:
|
||||
return datetime.strptime(s, "%Y-%m-%d")
|
||||
except ValueError:
|
||||
raise argparse.ArgumentTypeError("Not a valid date: {s}")
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
def plot_view_stock(df, symbol):
|
||||
pfig, axVolume = plt.subplots()
|
||||
plt.bar(df.index, df['5. volume'].values, color='k', alpha=0.8)
|
||||
plt.ylabel('Volume')
|
||||
axPrice = axVolume.twinx()
|
||||
plt.plot(df.index, df.iloc[:, :-1])
|
||||
plt.title(symbol + ' (Time Series)')
|
||||
plt.xlim(df.index[0], df.index[-1])
|
||||
plt.xlabel('Time')
|
||||
plt.ylabel('Share Price ($)')
|
||||
plt.legend(df.columns)
|
||||
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()
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
def plot_stock_ta(df_stock, s_stock, df_ta, s_ta):
|
||||
plt.plot(df_stock.index, df_stock['4. close'].values)
|
||||
plt.plot(df_ta.index, df_ta.values)
|
||||
plt.title(f"{s_ta} on {s_stock}")
|
||||
plt.xlim(df_stock.index[0], df_stock.index[-1])
|
||||
plt.xlabel('Time')
|
||||
plt.ylabel('Share Price ($)')
|
||||
plt.legend([s_stock, s_ta])
|
||||
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()
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
def b_is_stock_market_open():
|
||||
''' checks if the stock market is open '''
|
||||
# Get current US time
|
||||
now = datetime.now(timezone('US/Eastern'))
|
||||
# Check if it is a weekend
|
||||
if now.date().weekday() > 4:
|
||||
return False
|
||||
# Check if it is a holiday
|
||||
if now.strftime('%Y-%m-%d') in holidaysUS():
|
||||
return False
|
||||
# Check if it hasn't open already
|
||||
if now.time() < Time(hour=9, minute=30, second=0):
|
||||
return False
|
||||
# Check if it has already closed
|
||||
if now.time() > Time(hour=16, minute=0, second=0):
|
||||
return False
|
||||
# Otherwise, Stock Market is open!
|
||||
return True
|
||||
|
||||
122
stock_market_menu.py
Normal file
122
stock_market_menu.py
Normal file
@@ -0,0 +1,122 @@
|
||||
import argparse
|
||||
from alpha_vantage.timeseries import TimeSeries
|
||||
import config_bot as cfg
|
||||
import pandas as pd
|
||||
from stock_market_helper_funcs import *
|
||||
|
||||
|
||||
# ---------------------------------------------------- GAINERS ----------------------------------------------------
|
||||
def gainers(l_args):
|
||||
parser = argparse.ArgumentParser(prog='gainers',
|
||||
description='Show top ticker gainers from Yahoo Finance')
|
||||
parser.add_argument('-n', "--num", action="store", dest="n_gainers", type=int, default=5, choices=range(1, 25),
|
||||
help='Number of the top gainers stocks to retrieve (default 5)')
|
||||
|
||||
try:
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
except SystemExit:
|
||||
print("")
|
||||
return
|
||||
|
||||
if l_unknown_args:
|
||||
print(f"The following args couldn't be interpreted: {l_unknown_args}")
|
||||
|
||||
df_gainers = pd.read_html('https://finance.yahoo.com/screener/predefined/day_gainers')[0]
|
||||
print(df_gainers.head(ns_parser.n_gainers).to_string(index=False))
|
||||
print("")
|
||||
|
||||
# ----------------------------------------------------- LOAD -----------------------------------------------------
|
||||
def load(l_args, s_ticker, s_start, df_stock):
|
||||
parser = argparse.ArgumentParser(prog='load',
|
||||
description=""" Given a stock market ticker, and an optional starting time,
|
||||
load a stock in order to perform analysis""")
|
||||
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")
|
||||
|
||||
try:
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
except SystemExit:
|
||||
print("")
|
||||
return [s_ticker, s_start, df_stock]
|
||||
|
||||
if l_unknown_args:
|
||||
print(f"The following args couldn't be interpreted: {l_unknown_args}")
|
||||
|
||||
# Currently only supports daily stocks
|
||||
ts = TimeSeries(key=cfg.API_KEY_ALPHAVANTAGE, output_format='pandas')
|
||||
try:
|
||||
df_stock, d_stock_metadata = ts.get_daily(symbol=ns_parser.s_ticker, outputsize='full')
|
||||
except:
|
||||
print("Either the ticker or the API_KEY are invalids. Try again!")
|
||||
return [s_ticker, s_start, df_stock]
|
||||
|
||||
s_ticker = ns_parser.s_ticker
|
||||
|
||||
if ns_parser.s_start_date:
|
||||
s_start = ns_parser.s_start_date
|
||||
|
||||
# Slice dataframe from the starting date YYYY-MM-DD selected
|
||||
if ns_parser.s_start_date:
|
||||
df_stock = df_stock[ns_parser.s_start_date:]
|
||||
|
||||
# Get stock close price
|
||||
df_stock = df_stock.iloc[:, 3]
|
||||
|
||||
if s_start:
|
||||
print(f"Loading {s_ticker} stock with starting period {s_start.strftime('%Y-%m-%d')} for analysis.\n")
|
||||
else:
|
||||
print(f"Loading {s_ticker} stock for analysis.\n")
|
||||
|
||||
return [s_ticker, s_start, df_stock]
|
||||
|
||||
|
||||
# ----------------------------------------------------- VIEW -----------------------------------------------------
|
||||
def view(l_args, s_ticker, s_start):
|
||||
parser = argparse.ArgumentParser(prog='view',
|
||||
description='Given a stock market ticker, allows to see historical data of \
|
||||
the corresponding stock. Note that the alpha_vantage key is necessary \
|
||||
for this to work!')
|
||||
if s_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")
|
||||
parser.add_argument("--type", action="store", dest="n_type", type=check_positive, default=4,
|
||||
help='1234 corresponds to types: 1. open; 2. high; 3.low; 4. close \
|
||||
while 14 corresponds to types: 1.open; 4. close')
|
||||
|
||||
try:
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
except SystemExit:
|
||||
print("")
|
||||
return
|
||||
|
||||
if l_unknown_args:
|
||||
print(f"The following args couldn't be interpreted: {l_unknown_args}")
|
||||
|
||||
# Currently only supports daily stocks
|
||||
ts = TimeSeries(key=cfg.API_KEY_ALPHAVANTAGE, output_format='pandas')
|
||||
try:
|
||||
df_stock, d_stock_metadata = ts.get_daily(symbol=ns_parser.s_ticker, outputsize='full')
|
||||
except:
|
||||
print("Either the ticker or the API_KEY are invalids. Try again!")
|
||||
return
|
||||
|
||||
# Slice dataframe from the starting date YYYY-MM-DD selected
|
||||
if ns_parser.s_start_date:
|
||||
df_stock = df_stock[ns_parser.s_start_date:]
|
||||
|
||||
# Add function to plot data
|
||||
ln_col_idx = [int(x)-1 for x in list(str(ns_parser.n_type))]
|
||||
# Check that the types given are not bigger than 3, as there are only 4 types (0-3)
|
||||
if len([i for i in ln_col_idx if i > 3]) > 0:
|
||||
print("An index bigger than 3 was given, which is wrong. Try again")
|
||||
return
|
||||
|
||||
ln_col_idx.append(4) # Append last column of df to be filtered which corresponds to: 5. Volume
|
||||
|
||||
plot_view_stock(df_stock.iloc[:, ln_col_idx], ns_parser.s_ticker)
|
||||
|
||||
117
stock_market_technical_analysis.py
Normal file
117
stock_market_technical_analysis.py
Normal file
@@ -0,0 +1,117 @@
|
||||
import argparse
|
||||
from alpha_vantage.timeseries import TimeSeries
|
||||
import pandas_ta as ta
|
||||
import config_bot as cfg
|
||||
from stock_market_helper_funcs import *
|
||||
|
||||
# ----------------------------------------------------- SMA -----------------------------------------------------
|
||||
def sma(l_args, s_ticker, s_start):
|
||||
parser = argparse.ArgumentParser(prog='sma',
|
||||
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('-p', "--period", action="store", dest="n_time_period", type=check_positive, default=20,
|
||||
help='Number of data points used to calculate each moving average value.')
|
||||
parser.add_argument("-s", "--start", type=valid_date, dest="s_start_date",
|
||||
help="The starting date (format YYYY-MM-DD) of the stock")
|
||||
if s_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')
|
||||
|
||||
try:
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
except SystemExit:
|
||||
print("")
|
||||
return [s_ticker, s_start]
|
||||
|
||||
if l_unknown_args:
|
||||
print(f"The following args couldn't be interpreted: {l_unknown_args}")
|
||||
|
||||
try: # Get stock data
|
||||
ts = TimeSeries(key=cfg.API_KEY_ALPHAVANTAGE, output_format='pandas')
|
||||
df_stock, d_stock_metadata = ts.get_daily(symbol=ns_parser.s_ticker, outputsize='full')
|
||||
except:
|
||||
print("ERROR! Try again!")
|
||||
print("Check that: 1. The ticker symbol exists and is valid")
|
||||
print(" 2. Less than 5 AlphaVantage requests have been made in 1 minute")
|
||||
print(" 3. The API_KEY is (still) valid")
|
||||
return [s_ticker, s_start]
|
||||
|
||||
# Update TA ticker
|
||||
s_ticker = ns_parser.s_ticker
|
||||
|
||||
# Update TA starting point if needed
|
||||
if ns_parser.s_start_date:
|
||||
s_start = ns_parser.s_start_date
|
||||
|
||||
# Slice dataframe from the starting date YYYY-MM-DD selected
|
||||
if s_start:
|
||||
df_stock = df_stock[ns_parser.s_start_date:]
|
||||
|
||||
df_ta = ta.sma(df_stock['4. close'], timeperiod=ns_parser.n_time_period).dropna()
|
||||
|
||||
plot_stock_ta(df_stock, d_stock_metadata['2. Symbol'], df_ta, f"{ns_parser.n_time_period} SMA")
|
||||
|
||||
return [s_ticker, s_start]
|
||||
|
||||
|
||||
# ----------------------------------------------------- EMA -----------------------------------------------------
|
||||
def ema(l_args, s_ticker, s_start):
|
||||
parser = argparse.ArgumentParser(prog='ema',
|
||||
description=""" The Exponential Moving Average is a staple of technical
|
||||
analysis and is used in countless technical indicators. 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. However, the Exponential
|
||||
Moving Average is a cumulative calculation, including all data. Past values have
|
||||
a diminishing contribution to the average, while more recent values have a greater
|
||||
contribution. This method allows the moving average to be more responsive to changes
|
||||
in the data. """)
|
||||
parser.add_argument('-p', "--period", action="store", dest="n_time_period", type=check_positive, default=20,
|
||||
help='Number of data points used to calculate each moving average value.')
|
||||
parser.add_argument("-s", "--start", type=valid_date, dest="s_start_date",
|
||||
help="The starting date (format YYYY-MM-DD) of the stock")
|
||||
if s_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')
|
||||
|
||||
try:
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(l_args)
|
||||
except SystemExit:
|
||||
print("")
|
||||
return [s_ticker, s_start]
|
||||
|
||||
if l_unknown_args:
|
||||
print(f"The following args couldn't be interpreted: {l_unknown_args}")
|
||||
|
||||
try: # Get stock data
|
||||
ts = TimeSeries(key=cfg.API_KEY_ALPHAVANTAGE, output_format='pandas')
|
||||
df_stock, d_stock_metadata = ts.get_daily(symbol=ns_parser.s_ticker, outputsize='full')
|
||||
except:
|
||||
print("ERROR! Try again!")
|
||||
print("Check that: 1. The ticker symbol exists and is valid")
|
||||
print(" 2. Less than 5 AlphaVantage requests have been made in 1 minute")
|
||||
print(" 3. The API_KEY is (still) valid")
|
||||
return [s_ticker, s_start]
|
||||
|
||||
# Update TA ticker
|
||||
s_ticker = ns_parser.s_ticker
|
||||
|
||||
# Update TA starting point if needed
|
||||
if ns_parser.s_start_date:
|
||||
s_start = ns_parser.s_start_date
|
||||
|
||||
# Slice dataframe from the starting date YYYY-MM-DD selected
|
||||
if s_start:
|
||||
df_stock = df_stock[ns_parser.s_start_date:]
|
||||
|
||||
df_ta = ta.ema(df_stock['4. close'], timeperiod=ns_parser.n_time_period).dropna()
|
||||
|
||||
plot_stock_ta(df_stock, d_stock_metadata['2. Symbol'], df_ta, f"{ns_parser.n_time_period} EMA")
|
||||
|
||||
return [s_ticker, s_start]
|
||||
Reference in New Issue
Block a user