Added options to restart program and plot indicator linear regression

Added link to the essay that was the basis of this project
This commit is contained in:
Andrew Dinh 2019-04-15 23:08:01 -07:00
parent fa3be3d7b9
commit a8b7b794ec
4 changed files with 209 additions and 134 deletions

View File

@ -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) 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) 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) 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? ## Questions?

View File

@ -79,7 +79,7 @@ def getJoke():
'User-Agent': 'fund-indicators (https://github.com/andrewkdinh/fund-indicators)'} 'User-Agent': 'fund-indicators (https://github.com/andrewkdinh/fund-indicators)'}
url = 'https://icanhazdadjoke.com' url = 'https://icanhazdadjoke.com'
cprint('Get: ' + url, 'white', attrs=['dark']) cprint('Get:' + url, 'white', attrs=['dark'])
with Halo(spinner='dots'): with Halo(spinner='dots'):
f = requests.get(url, f = requests.get(url,
headers=headers).json() headers=headers).json()
@ -209,13 +209,47 @@ def getWeather():
with requests_cache.disabled(): with requests_cache.disabled():
url = 'https://wttr.in?format=3' url = 'https://wttr.in?format=3'
cprint('Get: ' + url, 'white', attrs=['dark']) cprint('Get:' + url, 'white', attrs=['dark'])
with Halo(spinner='dots'): with Halo(spinner='dots'):
f = requests.get(url) f = requests.get(url)
print('') print('')
print(colored('Current weather in ' + f.text, 'green'), end='') 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(): def main():
exit() exit()

View File

@ -6,16 +6,10 @@
![](https://img.shields.io/github/languages/code-size/andrewkdinh/fund-indicators.svg) ![](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) [![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) [![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 ## Key Features
- 100% automated - 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 - Optional graphs to easily visualize linear regression results
- A new joke every time - A new joke every time
- Cross-platform (tested on Windows and Linux) - Cross-platform (tested on Windows and Linux)
- Simple to use
## Quickstart ## 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 ```shell
git clone https://github.com/andrewkdinh/fund-indicators.git && cd fund-indicators git clone https://github.com/andrewkdinh/fund-indicators.git && cd fund-indicators
pip install -r requirements.txt pip install -r requirements.txt
@ -38,7 +37,12 @@ python main.py
- Common mutual funds are listed in `stocks.txt` - 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) - 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! 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: 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: And thank you to those that have helped me with the idea and product:

279
main.py
View File

@ -19,7 +19,10 @@ from bs4 import BeautifulSoup
import numpy as np import numpy as np
# OPTIONAL # OPTIONAL
# import matplotlib.pyplot as plt try:
import matplotlib.pyplot as plt
except:
pass
from halo import Halo from halo import Halo
# FOR ASYNC # FOR ASYNC
@ -79,6 +82,7 @@ class Stock:
# CONFIG # CONFIG
removeOutliers = True removeOutliers = True
sourceList = ['Yahoo', 'Alpha Vantage', 'IEX', 'Tiingo'] sourceList = ['Yahoo', 'Alpha Vantage', 'IEX', 'Tiingo']
plotIndicatorRegression = False
config = 'N/A' config = 'N/A'
# BENCHMARK VALUES # BENCHMARK VALUES
@ -135,7 +139,7 @@ class Stock:
url = ''.join( url = ''.join(
('https://api.iextrading.com/1.0/stock/', self.name, '/chart/5y')) ('https://api.iextrading.com/1.0/stock/', self.name, '/chart/5y'))
# link = "https://api.iextrading.com/1.0/stock/spy/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'): with Halo(spinner='dots'):
f = requests.get(url) f = requests.get(url)
Functions.fromCache(f) Functions.fromCache(f)
@ -174,7 +178,7 @@ class Stock:
self.name, '&outputsize=full&apikey=', apiAV)) self.name, '&outputsize=full&apikey=', apiAV))
# https://www.alphavantage.co/query?function=TIME_SERIES_DAILY_ADJUSTED&symbol=MSFT&outputsize=full&apikey=demo # 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'): with Halo(spinner='dots'):
f = requests.get(url) f = requests.get(url)
Functions.fromCache(f) Functions.fromCache(f)
@ -211,7 +215,7 @@ class Stock:
'Authorization': token 'Authorization': token
} }
url = ''.join(('https://api.tiingo.com/tiingo/daily/', self.name)) 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'): with Halo(spinner='dots'):
f = requests.get(url, headers=headers) f = requests.get(url, headers=headers)
Functions.fromCache(f) Functions.fromCache(f)
@ -233,7 +237,7 @@ class Stock:
url2 = ''.join((url, '/prices?startDate=', url2 = ''.join((url, '/prices?startDate=',
firstDate, '&endDate=', lastDate)) firstDate, '&endDate=', lastDate))
# https://api.tiingo.com/tiingo/daily/<ticker>/prices?startDate=2012-1-1&endDate=2016-1-1 # https://api.tiingo.com/tiingo/daily/<ticker>/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'): with Halo(spinner='dots'):
requestResponse2 = requests.get(url2, headers=headers) requestResponse2 = requests.get(url2, headers=headers)
Functions.fromCache(requestResponse2) Functions.fromCache(requestResponse2)
@ -261,7 +265,7 @@ class Stock:
def Yahoo(self): def Yahoo(self):
url = ''.join(('https://finance.yahoo.com/quote/', url = ''.join(('https://finance.yahoo.com/quote/',
self.name, '?p=', self.name)) self.name, '?p=', self.name))
cprint('Get: ' + url, 'white', attrs=['dark']) cprint('Get:' + url, 'white', attrs=['dark'])
with Halo(spinner='dots'): with Halo(spinner='dots'):
t = requests.get(url) t = requests.get(url)
if t.history: if t.history:
@ -563,7 +567,7 @@ class Stock:
# Determine if ETF, Mutual fund, or stock # Determine if ETF, Mutual fund, or stock
url = ''.join(('https://finance.yahoo.com/quote/', url = ''.join(('https://finance.yahoo.com/quote/',
self.name, '?p=', self.name)) self.name, '?p=', self.name))
cprint('Get: ' + url, 'white', attrs=['dark']) cprint('Get:' + url, 'white', attrs=['dark'])
with Halo(spinner='dots'): with Halo(spinner='dots'):
t = requests.get(url) t = requests.get(url)
Functions.fromCache(t) Functions.fromCache(t)
@ -575,7 +579,7 @@ class Stock:
stockType = '' stockType = ''
url2 = ''.join(('https://finance.yahoo.com/lookup?s=', self.name)) 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'): with Halo(spinner='dots'):
x = requests.get(url2) x = requests.get(url2)
raw_html = x.text raw_html = x.text
@ -733,7 +737,7 @@ class Stock:
url = ''.join(('https://finance.yahoo.com/quote/', url = ''.join(('https://finance.yahoo.com/quote/',
self.name, '/profile?p=', self.name)) self.name, '/profile?p=', self.name))
# https://finance.yahoo.com/quote/SPY/profile?p=SPY # 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'): with Halo(spinner='dots'):
raw_html = requests.get(url).text raw_html = requests.get(url).text
soup = BeautifulSoup(raw_html, 'html.parser') soup = BeautifulSoup(raw_html, 'html.parser')
@ -811,7 +815,7 @@ def benchmarkInit():
benchmarksTicker = ['SPY', 'DJIA', 'VTHR', 'EFT'] benchmarksTicker = ['SPY', 'DJIA', 'VTHR', 'EFT']
print('\nList of benchmarks:') print('\nList of benchmarks:')
for i in range(0, len(benchmarks), 1): for i in range(0, len(benchmarks), 1):
print(str(i+1) + '. ' + print('[' + str(i+1) + '] ' +
benchmarks[i] + ' (' + benchmarksTicker[i] + ')') benchmarks[i] + ' (' + benchmarksTicker[i] + ')')
while benchmarkTicker == '': while benchmarkTicker == '':
@ -862,7 +866,7 @@ def stocksInit():
'Yahoo top mutual funds (25)'] 'Yahoo top mutual funds (25)']
for i in range(0, len(methods), 1): 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): while method == 0 or method > len(methods):
method = str(input('Which method? ')) method = str(input('Which method? '))
if Functions.stringIsInt(method) is True: if Functions.stringIsInt(method) is True:
@ -877,9 +881,9 @@ def stocksInit():
if method == 1: if method == 1:
defaultFiles = ['.gitignore', 'LICENSE', 'main.py', 'Functions.py', defaultFiles = ['.gitignore', 'LICENSE', 'main.py', 'Functions.py',
'README.md', 'requirements.txt', 'cache.sqlite', 'README.md', 'requirements.txt', 'cache.sqlite',
'yahoofinancials.py', 'termcolor.py', 'config.json', 'CONTRIBUTING.md',
'README.html', 'config.json', 'config.example.json', '_test_runner.py',
'config.example.json', '_test_runner.py'] 'CODE-OF-CONDUCT.md']
# Added by repl.it for whatever reason # Added by repl.it for whatever reason
stocksFound = False stocksFound = False
print('Files in current directory (without default files): ') print('Files in current directory (without default files): ')
@ -890,7 +894,7 @@ def stocksInit():
listOfFiles.append(files) listOfFiles.append(files)
for i in range(0, len(listOfFiles), 1): for i in range(0, len(listOfFiles), 1):
if listOfFiles[i][0] != '.': if listOfFiles[i][0] != '.':
print(str(i+1) + '. ' + listOfFiles[i]) print('[' + str(i+1) + '] ' + listOfFiles[i])
while stocksFound is False: while stocksFound is False:
fileName = str(input('What is the file number/name? ')) fileName = str(input('What is the file number/name? '))
if Functions.stringIsInt(fileName) is True: if Functions.stringIsInt(fileName) is True:
@ -921,7 +925,7 @@ def stocksInit():
elif method == 2: elif method == 2:
isInteger = False isInteger = False
while isInteger is 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) isInteger = Functions.stringIsInt(temp)
if isInteger is True: if isInteger is True:
if int(temp) >= 2: 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' url = 'https://www.kiplinger.com/tool/investing/T041-S001-top-performing-mutual-funds/index.php'
headers = { headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36'} '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'): with Halo(spinner='dots'):
f = requests.get(url, headers=headers) f = requests.get(url, headers=headers)
Functions.fromCache(f) Functions.fromCache(f)
@ -978,7 +982,7 @@ def stocksInit():
url = 'https://www.thestreet.com/topic/21421/top-rated-mutual-funds.html' url = 'https://www.thestreet.com/topic/21421/top-rated-mutual-funds.html'
headers = { headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36'} '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'): with Halo(spinner='dots'):
f = requests.get(url, headers=headers) f = requests.get(url, headers=headers)
Functions.fromCache(f) Functions.fromCache(f)
@ -1008,7 +1012,7 @@ def stocksInit():
url = 'http://money.com/money/4616747/best-mutual-funds-etfs-money-50/' url = 'http://money.com/money/4616747/best-mutual-funds-etfs-money-50/'
headers = { headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36'} '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'): with Halo(spinner='dots'):
f = requests.get(url, headers=headers) f = requests.get(url, headers=headers)
Functions.fromCache(f) 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/' url = 'https://www.investors.com/etfs-and-funds/mutual-funds/best-mutual-funds-beating-sp-500-over-last-1-3-5-10-years/'
headers = { headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36'} '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'): with Halo(spinner='dots'):
f = requests.get(url, headers=headers) f = requests.get(url, headers=headers)
Functions.fromCache(f) Functions.fromCache(f)
@ -1055,10 +1059,11 @@ def stocksInit():
t = k.text.strip() t = k.text.strip()
if len(t) == 5 and Functions.strintIsFloat(t) is False: if len(t) == 5 and Functions.strintIsFloat(t) is False:
if t not in listOfStocksOriginal or listOfStocksOriginal == []: if t not in listOfStocksOriginal or listOfStocksOriginal == []:
listOfStocksOriginal.append(t) if t[-1] != '%':
print(t, end=' ') listOfStocksOriginal.append(t)
listOfStocks.append(k.text.strip()) print(t, end=' ')
file.write(str(k.text.strip()) + '\n') listOfStocks.append(k.text.strip())
file.write(str(k.text.strip()) + '\n')
file.close() file.close()
for i in range(0, len(listOfStocks), 1): for i in range(0, len(listOfStocks), 1):
@ -1073,7 +1078,7 @@ def stocksInit():
url = 'https://finance.yahoo.com/screener/predefined/top_mutual_funds/' url = 'https://finance.yahoo.com/screener/predefined/top_mutual_funds/'
headers = { headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36'} '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'): with Halo(spinner='dots'):
f = requests.get(url, headers=headers) f = requests.get(url, headers=headers)
Functions.fromCache(f) Functions.fromCache(f)
@ -1147,7 +1152,7 @@ def asyncData(benchmark, listOfStocks):
def sendAsync(url): def sendAsync(url):
time.sleep(random.randrange(0, 2)) time.sleep(random.randrange(0, 2))
cprint('Get: ' + url, 'white', attrs=['dark']) cprint('Get:' + url, 'white', attrs=['dark'])
requests.get(url) requests.get(url)
return return
@ -1156,7 +1161,7 @@ def timeFrameInit():
isInteger = False isInteger = False
while isInteger is False: while isInteger is False:
print( print(
'\nPlease enter the time frame in months (<60 months recommended):', end='') '\nPlease enter the time frame in months (<60 recommended):', end='')
temp = input(' ') temp = input(' ')
isInteger = Functions.stringIsInt(temp) isInteger = Functions.stringIsInt(temp)
if isInteger is True: 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=', apiQuandl))
# https://www.quandl.com/api/v3/datasets/USTREASURY/LONGTERMRATES.json?api_key=KUh3U3hxke9tCimjhWEF # 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'): with Halo(spinner='dots'):
f = requests.get(url) f = requests.get(url)
Functions.fromCache(f) Functions.fromCache(f)
@ -1290,12 +1295,12 @@ def returnMain(benchmark, listOfStocks):
listOfStocks[i].sharpe = Stock.calcSharpe(listOfStocks[i]) listOfStocks[i].sharpe = Stock.calcSharpe(listOfStocks[i])
listOfStocks[i].sortino = Stock.calcSortino(listOfStocks[i]) listOfStocks[i].sortino = Stock.calcSortino(listOfStocks[i])
listOfStocks[i].treynor = Stock.calcTreynor(listOfStocks[i]) listOfStocks[i].treynor = Stock.calcTreynor(listOfStocks[i])
listOfStocks[i].linearRegression = Stock.calcLinearRegression( # listOfStocks[i].linearRegression = Stock.calcLinearRegression(
listOfStocks[i]) # listOfStocks[i])
i += 1 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') str(len(listOfStocks)), 'green')
if len(listOfStocks) < 2: if len(listOfStocks) < 2:
# print('Cannot proceed to the next step. Exiting program.') # print('Cannot proceed to the next step. Exiting program.')
@ -1306,7 +1311,7 @@ def returnMain(benchmark, listOfStocks):
def outlierChoice(): def outlierChoice():
print('\nWould you like to remove indicator outliers?') print('\nWould you like to remove indicator outliers?')
print('1. Yes\n2. No') print('[1] Yes\n[2] No')
found = False found = False
while found is False: while found is False:
outlierChoice = str(input('Choice: ')) outlierChoice = str(input('Choice: '))
@ -1333,7 +1338,7 @@ def indicatorInit():
print('\n', end='') print('\n', end='')
print('List of indicators:') print('List of indicators:')
for i in range(0, len(listOfIndicators), 1): for i in range(0, len(listOfIndicators), 1):
print(str(i + 1) + '. ' + listOfIndicators[i]) print('[' + str(i + 1) + '] ' + listOfIndicators[i])
while indicatorFound is False: while indicatorFound is False:
indicator = str(input('Choose an indicator from the list: ')) indicator = str(input('Choose an indicator from the list: '))
@ -1396,7 +1401,8 @@ def calcIndicatorRegression(listOfIndicatorValues, listOfReturns):
regression.append(b[1]) regression.append(b[1])
regressionList.append(regression) regressionList.append(regression)
# plot_regression_line(x, y, b, i) if Stock.plotIndicatorRegression is True:
plot_regression_line(x, y, b, i)
return regressionList return regressionList
@ -1588,62 +1594,42 @@ def checkConfig(fileName):
return r 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(): def main():
''' '''
Check config file for errors and if not, then use values 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') Stock.config = checkConfig('config.json')
# Check if matplotlib is installed runningProgram = True
if Functions.checkPackage('matplotlib') is False: while runningProgram is True:
print(
'matplotlib is not installed. This is required for plotting linear regression')
# Check that all required packages are installed if Stock.config == 'N/A':
if Stock.config == 'N/A': # Check that all required packages are installed
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:
packagesInstalled = Functions.checkPackages( packagesInstalled = Functions.checkPackages(
['numpy', 'requests', 'bs4', 'requests_cache', 'halo']) ['numpy', 'requests', 'bs4', 'requests_cache', 'halo'])
if not packagesInstalled: if not packagesInstalled:
@ -1651,66 +1637,117 @@ def main():
else: else:
print('All required packages are installed') 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() pythonVersionGood = Functions.checkPythonVersion()
if not pythonVersionGood: if not pythonVersionGood:
exit() exit()
if Stock.config['Check Internet Connection'] is not False: # Test internet connection
internetConnection = Functions.isConnected() internetConnection = Functions.isConnected()
if not internetConnection: if not internetConnection:
exit() exit()
if Stock.config['Get Joke'] is not False: else:
Functions.getJoke() Functions.getJoke()
# Functions.getWeather()
benchmarksTicker = ['SPY', 'DJIA', 'VTHR', 'EFT'] # Choose benchmark and makes it class Stock
if Stock.config['Benchmark'] in benchmarksTicker:
benchmark = Stock()
benchmark.setName(str(Stock.config['Benchmark']))
benchmarkAsList = [benchmark]
else:
benchmark = benchmarkInit() benchmark = benchmarkInit()
# Add it to a list to work with other functions
benchmarkAsList = [benchmark] benchmarkAsList = [benchmark]
listOfStocks = stocksInit() # Asks for stock(s) ticker and makes them class Stock
listOfStocks = stocksInit()
if int(Stock.config['Time Frame']) >= 2: # Determine time frame (Years)
timeFrame = int(Stock.config['Time Frame'])
else:
timeFrame = timeFrameInit() timeFrame = timeFrameInit()
Stock.timeFrame = timeFrame # Needs to be a global variable for all stocks Stock.timeFrame = timeFrame
indicators = ['Expense Ratio', # Choose indicator
'Market Capitalization', 'Turnover', 'Persistence']
if Stock.config['Indicator'] in indicators:
Stock.indicator = Stock.config['Indicator']
else:
Stock.indicator = indicatorInit() Stock.indicator = indicatorInit()
# Choose time frame for initial persistence
if Stock.indicator == 'Persistence':
Stock.persTimeFrame = persistenceTimeFrame()
if Stock.indicator == 'Persistence': # Choose whether to remove outliers or not
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() Stock.removeOutliers = outlierChoice()
# Send async request to AV for listOfStocks and benchmark # Check if matplotlib is installed and if so, ask user if
# asyncData(benchmark, listOfStocks) # they want to plot
Stock.plotIndicatorRegression = plotIndicatorRegression()
# Gather data for benchmark and stock(s) else:
cprint('\nGathering data', 'white', attrs=['underline']) if Stock.config['Check Packages'] is not False:
dataMain(benchmarkAsList) packagesInstalled = Functions.checkPackages(
dataMain(listOfStocks) ['numpy', 'requests', 'bs4', 'requests_cache', 'halo'])
if not packagesInstalled:
exit()
else:
print('All required packages are installed')
# Calculate return for benchmark and stock(s) if Stock.config['Check Python Version'] is not False:
returnMain(benchmark, listOfStocks) pythonVersionGood = Functions.checkPythonVersion()
if not pythonVersionGood:
exit()
# Choose indicator and calculate correlation with indicator if Stock.config['Check Internet Connection'] is not False:
indicatorMain(listOfStocks) 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() exit()