diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index d93beb9..fa5b131 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -30,7 +30,7 @@ To develop on fund-indicators you'll probably want to:
1. Read the [code of conduct](https://github.com/andrewkdinh/fund-indicators/blob/master/CODE-OF-CONDUCT.md)
2. Install normally, as documented in the [README](https://github.com/andrewkdinh/fund-indicators#quickstart)
3. Read the [documentation](https://github.com/andrewkdinh/fund-indicators/wiki) (although it's not much)
-4. Read the section below to understand the ways you could best help this project
+4. Read the section above to understand the ways you could best help this project
## Questions?
diff --git a/Functions.py b/Functions.py
index 3634655..efb7383 100644
--- a/Functions.py
+++ b/Functions.py
@@ -79,7 +79,7 @@ def getJoke():
'User-Agent': 'fund-indicators (https://github.com/andrewkdinh/fund-indicators)'}
url = 'https://icanhazdadjoke.com'
- cprint('Get: ' + url, 'white', attrs=['dark'])
+ cprint('Get:' + url, 'white', attrs=['dark'])
with Halo(spinner='dots'):
f = requests.get(url,
headers=headers).json()
@@ -209,13 +209,47 @@ def getWeather():
with requests_cache.disabled():
url = 'https://wttr.in?format=3'
- cprint('Get: ' + url, 'white', attrs=['dark'])
+ cprint('Get:' + url, 'white', attrs=['dark'])
with Halo(spinner='dots'):
f = requests.get(url)
print('')
print(colored('Current weather in ' + f.text, 'green'), end='')
+def detectDisplay():
+ import os
+ try:
+ t = os.environ["DISPLAY"]
+ except KeyError:
+ return False
+ if t == ':0.0':
+ return True
+ else:
+ return False
+
+
+def trueOrFalse():
+ found = False
+ print('[1] Yes\n[2] No')
+ while found is False:
+ answer = str(input('Answer: '))
+ if stringIsInt(answer) is True:
+ temp = int(answer)
+ if temp == 1:
+ return True
+ elif temp == 2:
+ return False
+ else:
+ print('Please choose either 1 or 2')
+ pass
+ elif answer.lower() == 'yes':
+ return True
+ elif answer.lower() == 'no':
+ return False
+ else:
+ print('Please either choose a number or type an answer')
+
+
def main():
exit()
@@ -238,4 +272,4 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
-'''
\ No newline at end of file
+'''
diff --git a/README.md b/README.md
index 69293eb..7fd21b2 100644
--- a/README.md
+++ b/README.md
@@ -6,16 +6,10 @@
![](https://img.shields.io/github/languages/code-size/andrewkdinh/fund-indicators.svg)
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/2667/badge)](https://bestpractices.coreinfrastructure.org/projects/2667)
-A project to determine relationships between mutual fund performance and different factors.
+fund-indicators is a cross-platform Python application that allows users to easily find relationships between various attributes of mutual funds and previous performance. This project is based on research from [*Performance Indicators of Mutual Funds*](https://nextcloud.andrewkdinh.com/s/xNgGQ4nPNkSqJti).
[![asciicast demo](https://asciinema.org/a/jLmZapnMFGCRiiSUITY21erLW.svg)](https://asciinema.org/a/jLmZapnMFGCRiiSUITY21erLW?autoplay=1&preload=1)
-Calculates relationships between: Previous performance, Alpha, Sharpe Ratio, Sortino Ratio
-
-and Expense ratios, Turnover, Market Capitalization (Asset Size), Persistence
-
-Give it a try at [repl.run](https://fund-indicators.andrewkdinh.repl.run) or [repl.it](https://repl.it/@andrewkdinh/fund-indicators).
-
## Key Features
- 100% automated
@@ -26,9 +20,14 @@ Give it a try at [repl.run](https://fund-indicators.andrewkdinh.repl.run) or [re
- Optional graphs to easily visualize linear regression results
- A new joke every time
- Cross-platform (tested on Windows and Linux)
+- Simple to use
## Quickstart
+Give it a try at [repl.run](https://fund-indicators.andrewkdinh.repl.run) or [repl.it](https://repl.it/@andrewkdinh/fund-indicators).
+
+If you would like to clone to your own machine:
+
```shell
git clone https://github.com/andrewkdinh/fund-indicators.git && cd fund-indicators
pip install -r requirements.txt
@@ -38,7 +37,12 @@ python main.py
- Common mutual funds are listed in `stocks.txt`
- Configure and rename `config.example.json` to `config.json` if you would like to skip beginning questions (only for advanced users)
-### Contributing
+## Planned Features
+
+- Graphical user interface (GUI)
+- Multithreading/asynchronous requests
+
+## Contributing
Want to help? Great! Check out the [CONTRIBUTING.md](https://github.com/andrewkdinh/fund-indicators/blob/master/CONTRIBUTING.md) file!
@@ -46,7 +50,7 @@ Want to help? Great! Check out the [CONTRIBUTING.md](https://github.com/andrewkd
This project utilizes a wide variety of open-source projects:
-- [NumPy](https://github.com/numpy/numpy), [Termcolor](https://github.com/hfeeki/termcolor), [Beautiful Soup](https://launchpad.net/beautifulsoup), [yahoofinancials](https://github.com/JECSand/yahoofinancials), [requests-cache](https://github.com/reclosedev/requests-cache), [halo](https://github.com/manrajgrover/halo), [matplotlib](https://github.com/matplotlib/matplotlib), [asciinema](https://github.com/asciinema/asciinema)
+- [NumPy](https://github.com/numpy/numpy), [Termcolor](https://github.com/hfeeki/termcolor), [Beautiful Soup](https://launchpad.net/beautifulsoup), [yahoofinancials](https://github.com/JECSand/yahoofinancials), [requests-cache](https://github.com/reclosedev/requests-cache), [halo](https://github.com/manrajgrover/halo), [matplotlib](https://github.com/matplotlib/matplotlib), [asciinema](https://github.com/asciinema/asciinema), [Core Infrastructure Initiative Best Practices Badge](https://github.com/coreinfrastructure/best-practices-badge)
And thank you to those that have helped me with the idea and product:
diff --git a/main.py b/main.py
index 5551c59..4ae413d 100644
--- a/main.py
+++ b/main.py
@@ -19,7 +19,10 @@ from bs4 import BeautifulSoup
import numpy as np
# OPTIONAL
-# import matplotlib.pyplot as plt
+try:
+ import matplotlib.pyplot as plt
+except:
+ pass
from halo import Halo
# FOR ASYNC
@@ -79,6 +82,7 @@ class Stock:
# CONFIG
removeOutliers = True
sourceList = ['Yahoo', 'Alpha Vantage', 'IEX', 'Tiingo']
+ plotIndicatorRegression = False
config = 'N/A'
# BENCHMARK VALUES
@@ -135,7 +139,7 @@ class Stock:
url = ''.join(
('https://api.iextrading.com/1.0/stock/', self.name, '/chart/5y'))
# link = "https://api.iextrading.com/1.0/stock/spy/chart/5y"
- cprint("Get: " + url, 'white', attrs=['dark'])
+ cprint("Get:" + url, 'white', attrs=['dark'])
with Halo(spinner='dots'):
f = requests.get(url)
Functions.fromCache(f)
@@ -174,7 +178,7 @@ class Stock:
self.name, '&outputsize=full&apikey=', apiAV))
# https://www.alphavantage.co/query?function=TIME_SERIES_DAILY_ADJUSTED&symbol=MSFT&outputsize=full&apikey=demo
- cprint("Get: " + url, 'white', attrs=['dark'])
+ cprint("Get:" + url, 'white', attrs=['dark'])
with Halo(spinner='dots'):
f = requests.get(url)
Functions.fromCache(f)
@@ -211,7 +215,7 @@ class Stock:
'Authorization': token
}
url = ''.join(('https://api.tiingo.com/tiingo/daily/', self.name))
- cprint("Get: " + url, 'white', attrs=['dark'])
+ cprint("Get:" + url, 'white', attrs=['dark'])
with Halo(spinner='dots'):
f = requests.get(url, headers=headers)
Functions.fromCache(f)
@@ -233,7 +237,7 @@ class Stock:
url2 = ''.join((url, '/prices?startDate=',
firstDate, '&endDate=', lastDate))
# https://api.tiingo.com/tiingo/daily//prices?startDate=2012-1-1&endDate=2016-1-1
- cprint("\nGet: " + url2 + '\n', 'white', attrs=['dark'])
+ cprint("\nGet:" + url2 + '\n', 'white', attrs=['dark'])
with Halo(spinner='dots'):
requestResponse2 = requests.get(url2, headers=headers)
Functions.fromCache(requestResponse2)
@@ -261,7 +265,7 @@ class Stock:
def Yahoo(self):
url = ''.join(('https://finance.yahoo.com/quote/',
self.name, '?p=', self.name))
- cprint('Get: ' + url, 'white', attrs=['dark'])
+ cprint('Get:' + url, 'white', attrs=['dark'])
with Halo(spinner='dots'):
t = requests.get(url)
if t.history:
@@ -563,7 +567,7 @@ class Stock:
# Determine if ETF, Mutual fund, or stock
url = ''.join(('https://finance.yahoo.com/quote/',
self.name, '?p=', self.name))
- cprint('Get: ' + url, 'white', attrs=['dark'])
+ cprint('Get:' + url, 'white', attrs=['dark'])
with Halo(spinner='dots'):
t = requests.get(url)
Functions.fromCache(t)
@@ -575,7 +579,7 @@ class Stock:
stockType = ''
url2 = ''.join(('https://finance.yahoo.com/lookup?s=', self.name))
- cprint('Get: ' + url2, 'white', attrs=['dark'])
+ cprint('Get:' + url2, 'white', attrs=['dark'])
with Halo(spinner='dots'):
x = requests.get(url2)
raw_html = x.text
@@ -733,7 +737,7 @@ class Stock:
url = ''.join(('https://finance.yahoo.com/quote/',
self.name, '/profile?p=', self.name))
# https://finance.yahoo.com/quote/SPY/profile?p=SPY
- cprint('Get: ' + url, 'white', attrs=['dark'])
+ cprint('Get:' + url, 'white', attrs=['dark'])
with Halo(spinner='dots'):
raw_html = requests.get(url).text
soup = BeautifulSoup(raw_html, 'html.parser')
@@ -811,7 +815,7 @@ def benchmarkInit():
benchmarksTicker = ['SPY', 'DJIA', 'VTHR', 'EFT']
print('\nList of benchmarks:')
for i in range(0, len(benchmarks), 1):
- print(str(i+1) + '. ' +
+ print('[' + str(i+1) + '] ' +
benchmarks[i] + ' (' + benchmarksTicker[i] + ')')
while benchmarkTicker == '':
@@ -862,7 +866,7 @@ def stocksInit():
'Yahoo top mutual funds (25)']
for i in range(0, len(methods), 1):
- print(str(i+1) + '. ' + methods[i])
+ print('[' + str(i+1) + '] ' + methods[i])
while method == 0 or method > len(methods):
method = str(input('Which method? '))
if Functions.stringIsInt(method) is True:
@@ -877,9 +881,9 @@ def stocksInit():
if method == 1:
defaultFiles = ['.gitignore', 'LICENSE', 'main.py', 'Functions.py',
'README.md', 'requirements.txt', 'cache.sqlite',
- 'yahoofinancials.py', 'termcolor.py',
- 'README.html', 'config.json',
- 'config.example.json', '_test_runner.py']
+ 'config.json', 'CONTRIBUTING.md',
+ 'config.example.json', '_test_runner.py',
+ 'CODE-OF-CONDUCT.md']
# Added by repl.it for whatever reason
stocksFound = False
print('Files in current directory (without default files): ')
@@ -890,7 +894,7 @@ def stocksInit():
listOfFiles.append(files)
for i in range(0, len(listOfFiles), 1):
if listOfFiles[i][0] != '.':
- print(str(i+1) + '. ' + listOfFiles[i])
+ print('[' + str(i+1) + '] ' + listOfFiles[i])
while stocksFound is False:
fileName = str(input('What is the file number/name? '))
if Functions.stringIsInt(fileName) is True:
@@ -921,7 +925,7 @@ def stocksInit():
elif method == 2:
isInteger = False
while isInteger is False:
- temp = input('\nNumber of stocks to analyze (2 minimum): ')
+ temp = input('Number of stocks to analyze (2 minimum): ')
isInteger = Functions.stringIsInt(temp)
if isInteger is True:
if int(temp) >= 2:
@@ -951,7 +955,7 @@ def stocksInit():
url = 'https://www.kiplinger.com/tool/investing/T041-S001-top-performing-mutual-funds/index.php'
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36'}
- cprint('Get: ' + url, 'white', attrs=['dark'])
+ cprint('Get:' + url, 'white', attrs=['dark'])
with Halo(spinner='dots'):
f = requests.get(url, headers=headers)
Functions.fromCache(f)
@@ -978,7 +982,7 @@ def stocksInit():
url = 'https://www.thestreet.com/topic/21421/top-rated-mutual-funds.html'
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36'}
- cprint('Get: ' + url, 'white', attrs=['dark'])
+ cprint('Get:' + url, 'white', attrs=['dark'])
with Halo(spinner='dots'):
f = requests.get(url, headers=headers)
Functions.fromCache(f)
@@ -1008,7 +1012,7 @@ def stocksInit():
url = 'http://money.com/money/4616747/best-mutual-funds-etfs-money-50/'
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36'}
- cprint('Get: ' + url, 'white', attrs=['dark'])
+ cprint('Get:' + url, 'white', attrs=['dark'])
with Halo(spinner='dots'):
f = requests.get(url, headers=headers)
Functions.fromCache(f)
@@ -1041,7 +1045,7 @@ def stocksInit():
url = 'https://www.investors.com/etfs-and-funds/mutual-funds/best-mutual-funds-beating-sp-500-over-last-1-3-5-10-years/'
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36'}
- cprint('Get: ' + url, 'white', attrs=['dark'])
+ cprint('Get:' + url, 'white', attrs=['dark'])
with Halo(spinner='dots'):
f = requests.get(url, headers=headers)
Functions.fromCache(f)
@@ -1055,10 +1059,11 @@ def stocksInit():
t = k.text.strip()
if len(t) == 5 and Functions.strintIsFloat(t) is False:
if t not in listOfStocksOriginal or listOfStocksOriginal == []:
- listOfStocksOriginal.append(t)
- print(t, end=' ')
- listOfStocks.append(k.text.strip())
- file.write(str(k.text.strip()) + '\n')
+ if t[-1] != '%':
+ listOfStocksOriginal.append(t)
+ print(t, end=' ')
+ listOfStocks.append(k.text.strip())
+ file.write(str(k.text.strip()) + '\n')
file.close()
for i in range(0, len(listOfStocks), 1):
@@ -1073,7 +1078,7 @@ def stocksInit():
url = 'https://finance.yahoo.com/screener/predefined/top_mutual_funds/'
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36'}
- cprint('Get: ' + url, 'white', attrs=['dark'])
+ cprint('Get:' + url, 'white', attrs=['dark'])
with Halo(spinner='dots'):
f = requests.get(url, headers=headers)
Functions.fromCache(f)
@@ -1147,7 +1152,7 @@ def asyncData(benchmark, listOfStocks):
def sendAsync(url):
time.sleep(random.randrange(0, 2))
- cprint('Get: ' + url, 'white', attrs=['dark'])
+ cprint('Get:' + url, 'white', attrs=['dark'])
requests.get(url)
return
@@ -1156,7 +1161,7 @@ def timeFrameInit():
isInteger = False
while isInteger is False:
print(
- '\nPlease enter the time frame in months (<60 months recommended):', end='')
+ '\nPlease enter the time frame in months (<60 recommended):', end='')
temp = input(' ')
isInteger = Functions.stringIsInt(temp)
if isInteger is True:
@@ -1206,7 +1211,7 @@ def riskFreeRate():
('https://www.quandl.com/api/v3/datasets/USTREASURY/LONGTERMRATES.json?api_key=', apiQuandl))
# https://www.quandl.com/api/v3/datasets/USTREASURY/LONGTERMRATES.json?api_key=KUh3U3hxke9tCimjhWEF
- cprint('\nGet: ' + url, 'white', attrs=['dark'])
+ cprint('\nGet:' + url, 'white', attrs=['dark'])
with Halo(spinner='dots'):
f = requests.get(url)
Functions.fromCache(f)
@@ -1290,12 +1295,12 @@ def returnMain(benchmark, listOfStocks):
listOfStocks[i].sharpe = Stock.calcSharpe(listOfStocks[i])
listOfStocks[i].sortino = Stock.calcSortino(listOfStocks[i])
listOfStocks[i].treynor = Stock.calcTreynor(listOfStocks[i])
- listOfStocks[i].linearRegression = Stock.calcLinearRegression(
- listOfStocks[i])
+ # listOfStocks[i].linearRegression = Stock.calcLinearRegression(
+ # listOfStocks[i])
i += 1
- cprint('\nNumber of stocks from original list that fit time frame: ' +
+ cprint('\nNumber of stocks that fit time frame: ' +
str(len(listOfStocks)), 'green')
if len(listOfStocks) < 2:
# print('Cannot proceed to the next step. Exiting program.')
@@ -1306,7 +1311,7 @@ def returnMain(benchmark, listOfStocks):
def outlierChoice():
print('\nWould you like to remove indicator outliers?')
- print('1. Yes\n2. No')
+ print('[1] Yes\n[2] No')
found = False
while found is False:
outlierChoice = str(input('Choice: '))
@@ -1333,7 +1338,7 @@ def indicatorInit():
print('\n', end='')
print('List of indicators:')
for i in range(0, len(listOfIndicators), 1):
- print(str(i + 1) + '. ' + listOfIndicators[i])
+ print('[' + str(i + 1) + '] ' + listOfIndicators[i])
while indicatorFound is False:
indicator = str(input('Choose an indicator from the list: '))
@@ -1396,7 +1401,8 @@ def calcIndicatorRegression(listOfIndicatorValues, listOfReturns):
regression.append(b[1])
regressionList.append(regression)
- # plot_regression_line(x, y, b, i)
+ if Stock.plotIndicatorRegression is True:
+ plot_regression_line(x, y, b, i)
return regressionList
@@ -1588,62 +1594,42 @@ def checkConfig(fileName):
return r
+def continueProgram():
+ found = False
+ print('Would you like to rerun the program?')
+ return Functions.trueOrFalse()
+
+
+def plotIndicatorRegression():
+ if Functions.detectDisplay() is True:
+ if Functions.checkPackage('matplotlib') is False:
+ print(
+ 'matplotlib is not installed. \nIf you would like to install' +
+ ' it (and have a display), run `pip install matplotlib`')
+ return False
+ else:
+ print('\nWould you like to plot indicator linear regression '
+ 'results?')
+ plotLinear = Functions.trueOrFalse()
+ if plotLinear is True:
+ return True
+ else:
+ return False
+
+
def main():
'''
Check config file for errors and if not, then use values
- #! Only use this if you know it is exactly correct. I haven't spent much time debugging this
+ #! Only use this if you know it is exactly correct. I haven't spent much
+ #! time debugging this
'''
Stock.config = checkConfig('config.json')
- # Check if matplotlib is installed
- if Functions.checkPackage('matplotlib') is False:
- print(
- 'matplotlib is not installed. This is required for plotting linear regression')
+ runningProgram = True
+ while runningProgram is True:
- # Check that all required packages are installed
- if Stock.config == 'N/A':
- packagesInstalled = Functions.checkPackages(
- ['numpy', 'requests', 'bs4', 'requests_cache', 'halo'])
- if not packagesInstalled:
- exit()
- else:
- print('All required packages are installed')
-
- # Check python version is above 3.3
- pythonVersionGood = Functions.checkPythonVersion()
- if not pythonVersionGood:
- exit()
-
- # Test internet connection
- internetConnection = Functions.isConnected()
- if not internetConnection:
- exit()
- else:
- Functions.getJoke()
- # Functions.getWeather()
-
- # Choose benchmark and makes it class Stock
- benchmark = benchmarkInit()
- # Add it to a list to work with other functions
- benchmarkAsList = [benchmark]
-
- # Asks for stock(s) ticker and makes them class Stock
- listOfStocks = stocksInit()
-
- # Determine time frame (Years)
- timeFrame = timeFrameInit()
- Stock.timeFrame = timeFrame # Needs to be a global variable for all stocks
-
- # Choose indicator
- Stock.indicator = indicatorInit()
- # Choose time frame for initial persistence
- if Stock.indicator == 'Persistence':
- Stock.persTimeFrame = persistenceTimeFrame()
-
- # Choose whether to remove outliers or not
- Stock.removeOutliers = outlierChoice()
- else:
- if Stock.config['Check Packages'] is not False:
+ if Stock.config == 'N/A':
+ # Check that all required packages are installed
packagesInstalled = Functions.checkPackages(
['numpy', 'requests', 'bs4', 'requests_cache', 'halo'])
if not packagesInstalled:
@@ -1651,66 +1637,117 @@ def main():
else:
print('All required packages are installed')
- if Stock.config['Check Python Version'] is not False:
+ # Check python version is above 3.3
pythonVersionGood = Functions.checkPythonVersion()
if not pythonVersionGood:
exit()
- if Stock.config['Check Internet Connection'] is not False:
+ # Test internet connection
internetConnection = Functions.isConnected()
if not internetConnection:
exit()
- if Stock.config['Get Joke'] is not False:
- Functions.getJoke()
+ else:
+ Functions.getJoke()
+ # Functions.getWeather()
- benchmarksTicker = ['SPY', 'DJIA', 'VTHR', 'EFT']
- if Stock.config['Benchmark'] in benchmarksTicker:
- benchmark = Stock()
- benchmark.setName(str(Stock.config['Benchmark']))
- benchmarkAsList = [benchmark]
- else:
+ # Choose benchmark and makes it class Stock
benchmark = benchmarkInit()
+ # Add it to a list to work with other functions
benchmarkAsList = [benchmark]
- listOfStocks = stocksInit()
+ # Asks for stock(s) ticker and makes them class Stock
+ listOfStocks = stocksInit()
- if int(Stock.config['Time Frame']) >= 2:
- timeFrame = int(Stock.config['Time Frame'])
- else:
+ # Determine time frame (Years)
timeFrame = timeFrameInit()
- Stock.timeFrame = timeFrame # Needs to be a global variable for all stocks
+ Stock.timeFrame = timeFrame
- indicators = ['Expense Ratio',
- 'Market Capitalization', 'Turnover', 'Persistence']
- if Stock.config['Indicator'] in indicators:
- Stock.indicator = Stock.config['Indicator']
- else:
+ # Choose indicator
Stock.indicator = indicatorInit()
+ # Choose time frame for initial persistence
+ if Stock.indicator == 'Persistence':
+ Stock.persTimeFrame = persistenceTimeFrame()
- if Stock.indicator == 'Persistence':
- Stock.persTimeFrame = persistenceTimeFrame()
-
- # Choose whether to remove outliers or not
- if Stock.config['Remove Outliers'] is not False:
- Stock.removeOutliers = True
- else:
+ # Choose whether to remove outliers or not
Stock.removeOutliers = outlierChoice()
- # Send async request to AV for listOfStocks and benchmark
- # asyncData(benchmark, listOfStocks)
+ # Check if matplotlib is installed and if so, ask user if
+ # they want to plot
+ Stock.plotIndicatorRegression = plotIndicatorRegression()
- # Gather data for benchmark and stock(s)
- cprint('\nGathering data', 'white', attrs=['underline'])
- dataMain(benchmarkAsList)
- dataMain(listOfStocks)
+ else:
+ if Stock.config['Check Packages'] is not False:
+ packagesInstalled = Functions.checkPackages(
+ ['numpy', 'requests', 'bs4', 'requests_cache', 'halo'])
+ if not packagesInstalled:
+ exit()
+ else:
+ print('All required packages are installed')
- # Calculate return for benchmark and stock(s)
- returnMain(benchmark, listOfStocks)
+ if Stock.config['Check Python Version'] is not False:
+ pythonVersionGood = Functions.checkPythonVersion()
+ if not pythonVersionGood:
+ exit()
- # Choose indicator and calculate correlation with indicator
- indicatorMain(listOfStocks)
+ if Stock.config['Check Internet Connection'] is not False:
+ internetConnection = Functions.isConnected()
+ if not internetConnection:
+ exit()
+ if Stock.config['Get Joke'] is not False:
+ Functions.getJoke()
+
+ benchmarksTicker = ['SPY', 'DJIA', 'VTHR', 'EFT']
+ if Stock.config['Benchmark'] in benchmarksTicker:
+ benchmark = Stock()
+ benchmark.setName(str(Stock.config['Benchmark']))
+ benchmarkAsList = [benchmark]
+ else:
+ benchmark = benchmarkInit()
+ benchmarkAsList = [benchmark]
+
+ listOfStocks = stocksInit()
+
+ if int(Stock.config['Time Frame']) >= 2:
+ timeFrame = int(Stock.config['Time Frame'])
+ else:
+ timeFrame = timeFrameInit()
+ Stock.timeFrame = timeFrame # Needs to be a global variable for all stocks
+
+ indicators = ['Expense Ratio',
+ 'Market Capitalization', 'Turnover', 'Persistence']
+ if Stock.config['Indicator'] in indicators:
+ Stock.indicator = Stock.config['Indicator']
+ else:
+ Stock.indicator = indicatorInit()
+
+ if Stock.indicator == 'Persistence':
+ Stock.persTimeFrame = persistenceTimeFrame()
+
+ # Choose whether to remove outliers or not
+ if Stock.config['Remove Outliers'] is not False:
+ Stock.removeOutliers = True
+ else:
+ Stock.removeOutliers = outlierChoice()
+
+ # Send async request to AV for listOfStocks and benchmark
+ # asyncData(benchmark, listOfStocks)
+
+ # Gather data for benchmark and stock(s)
+ cprint('\nGathering data', 'white', attrs=['underline'])
+ dataMain(benchmarkAsList)
+ dataMain(listOfStocks)
+
+ # Calculate return for benchmark and stock(s)
+ returnMain(benchmark, listOfStocks)
+
+ # Choose indicator and calculate correlation with indicator
+ indicatorMain(listOfStocks)
+
+ # Decide if running program again
+ print('')
+ runningProgram = continueProgram()
+ print('')
- print('')
exit()