diff --git a/.gitignore b/.gitignore index a204a08..238abb6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ -__pycache__/StockData.cpython-37.pyc __pycache__/ -*.pyc test/ .vscode/ -requests_cache.sqlite \ No newline at end of file +requests_cache.sqlite +README.html \ No newline at end of file diff --git a/Functions.py b/Functions.py index 32aeab4..63ae2db 100644 --- a/Functions.py +++ b/Functions.py @@ -42,6 +42,7 @@ def stringIsInt(s): except ValueError: return False + def strintIsFloat(s): try: float(s) @@ -49,10 +50,13 @@ def strintIsFloat(s): except ValueError: return False + def fromCache(r): import requests_cache if r.from_cache == True: print('(Response taken from cache)') + return + def main(): exit() diff --git a/README.md b/README.md index ebb6232..d33a263 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,25 @@ # Mutual Fund Indicators -A project to determine indicators of overperforming mutual funds. -This project is written in Python 3 and will examine market capitalization, persistence, turnover, and expense ratios. +[![License](https://img.shields.io/github/license/andrewkdinh/fund-indicators.svg)](https://raw.githubusercontent.com/andrewkdinh/fund-indicators/master/LICENSE) +![](https://img.shields.io/github/last-commit/andrewkdinh/fund-indicators.svg) +![](https://img.shields.io/github/languages/top/andrewkdinh/fund-indicators.svg) +![](https://img.shields.io/github/languages/code-size/andrewkdinh/fund-indicators.svg) -### Prerequisites +A project to determine indicators of overperforming mutual funds. + +Examine correlation between performance and market capitalization, persistence, turnover, and expense ratios. + +## Prerequisites `$ pip install -r requirements.txt` -### Quickstart +## Quickstart To begin, run `$ python main.py` Some ticker values to try: -SPY, VFINX, AAPL, GOOGL +SPY, VFINX, VTHR, DJIA Created by Andrew Dinh from Dr. TJ Owens Gilroy Early College Academy diff --git a/main.py b/main.py index c1a43a0..3358188 100644 --- a/main.py +++ b/main.py @@ -4,6 +4,7 @@ # Python 3.6.7 # Required +from concurrent.futures import ThreadPoolExecutor as PoolExecutor import requests import json import datetime @@ -16,10 +17,10 @@ import sys # Optional import requests_cache -# https://requests-cache.readthedocs.io/en/lates/user_guide.html requests_cache.install_cache( 'requests_cache', backend='sqlite', expire_after=43200) # 12 hours + # API Keys apiAV = 'O42ICUV58EIZZQMU' # apiBarchart = 'a17fab99a1c21cd6f847e2f82b592838' @@ -119,7 +120,7 @@ class Stock: f = requests.get(url) Functions.fromCache(f) json_data = f.text - if json_data == 'Unknown symbol' or f.status_code == 404: + if json_data == 'Unknown symbol' or f.status_code != 200: print("IEX not available") return 'Not available' loaded_json = json.loads(json_data) @@ -160,7 +161,7 @@ class Stock: json_data = f.text loaded_json = json.loads(json_data) - if len(loaded_json) == 1 or f.status_code == 404: + if len(loaded_json) == 1 or f.status_code != 200: print("Alpha Vantage not available") return 'Not available' @@ -195,7 +196,7 @@ class Stock: f = requests.get(url, headers=headers) Functions.fromCache(f) loaded_json = f.json() - if len(loaded_json) == 1 or f.status_code == 404 or loaded_json['startDate'] == None: + if len(loaded_json) == 1 or f.status_code != 200 or loaded_json['startDate'] == None: print("Tiingo not available") return 'Not available' @@ -497,11 +498,11 @@ def datesToDays(dates): def isConnected(): import socket # To check internet connection - print('Checking internet connection') + #print('Checking internet connection') try: # connect to the host -- tells us if the host is actually reachable socket.create_connection(("www.andrewkdinh.com", 80)) - print('Internet connection is good!') + print('Internet connection is good') return True except OSError: # pass @@ -526,6 +527,22 @@ def checkPackages(): return packagesInstalled +def checkPythonVersion(): + import platform + #print('Checking Python version') + i = platform.python_version() + r = i.split('.') + k = ''.join((r[0], '.', r[1])) + k = float(k) + if k < 3.3: + print('Your Python version is', i, + '\nIt needs to be greater than version 3.3') + return False + else: + print('Your Python version of', i, 'is good') + return True + + def benchmarkInit(): # Treat benchmark like stock benchmarkTicker = '' @@ -601,11 +618,45 @@ def stocksInit(): return listOfStocks +def asyncData(benchmark, listOfStocks): + # Make list of urls to send requests to + urlList = [] + # Benchmark + url = ''.join(('https://www.alphavantage.co/query?function=TIME_SERIES_DAILY_ADJUSTED&symbol=', + benchmark.name, '&outputsize=full&apikey=', apiAV)) + urlList.append(url) + + # Stocks + for i in range(0, len(listOfStocks), 1): + # Alpha Vantage + url = ''.join(('https://www.alphavantage.co/query?function=TIME_SERIES_DAILY_ADJUSTED&symbol=', + listOfStocks[i].name, '&outputsize=full&apikey=', apiAV)) + urlList.append(url) + + # Risk-free rate + url = ''.join( + ('https://www.quandl.com/api/v3/datasets/USTREASURY/LONGTERMRATES.json?api_key=', apiQuandl)) + urlList.append(url) + + # Send async requests + print('\nSending async requests (Assuming Alpha Vantage is first choice)') + with PoolExecutor(max_workers=3) as executor: + for _ in executor.map(sendAsync, urlList): + pass + + return + + +def sendAsync(url): + requests.get(url) + return + + def timeFrameInit(): isInteger = False while isInteger == False: print( - '\nPlease enter the time frame in years (10 years or less recommended):', end='') + '\nPlease enter the time frame in years (<10 years recommended):', end='') temp = input(' ') isInteger = Functions.stringIsInt(temp) if isInteger == True: @@ -660,7 +711,7 @@ def riskFreeRate(): riskFreeRate = round(riskFreeRate, 2) print('Risk-free rate:', riskFreeRate, end='\n\n') - if f.status_code == 404: + if f.status_code != 200: print("Quandl not available") print('Returning 2.50 as risk-free rate', end='\n\n') # return 0.0250 @@ -950,12 +1001,18 @@ def main(): packagesInstalled = checkPackages() if not packagesInstalled: return + else: + print('All required packages are installed') + + # Check python version is above 3.3 + pythonVersionGood = checkPythonVersion() + if not pythonVersionGood: + return # Choose benchmark and makes it class Stock benchmark = benchmarkInit() # Add it to a list to work with other functions - benchmarkAsList = [] - benchmarkAsList.append(benchmark) + benchmarkAsList = [benchmark] # Asks for stock(s) ticker and makes them class Stock listOfStocks = stocksInit() @@ -964,6 +1021,9 @@ def main(): timeFrame = timeFrameInit() Stock.timeFrame = timeFrame # Needs to be a global variable for all stocks + # Send async request to AV for listOfStocks and benchmark + asyncData(benchmark, listOfStocks) + # Gather data for benchmark and stock(s) dataMain(benchmarkAsList) dataMain(listOfStocks) diff --git a/output.bin b/output.bin deleted file mode 100644 index 109a282..0000000 --- a/output.bin +++ /dev/null @@ -1,51 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - -