From 0dcdd1049d2a32671e01adc6abb22df7229239b5 Mon Sep 17 00:00:00 2001 From: Andrew Dinh Date: Thu, 31 Jan 2019 13:22:02 -0800 Subject: [PATCH] Finished overhaul of version-1 --- .gitignore | 5 +- ExpenseRatio.py | 14 +- Functions.py | 57 ++- README.md | 2 - StockData.py | 915 ++++++++++++++++++++++++----------------------- StockReturn.py | 45 ++- listGoogle.py | 54 --- main.py | 569 ++++++++++++++++++++++++++--- requirements.txt | 4 +- 9 files changed, 1059 insertions(+), 606 deletions(-) delete mode 100644 listGoogle.py diff --git a/.gitignore b/.gitignore index 293b5a3..1acf435 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,5 @@ __pycache__/StockData.cpython-37.pyc __pycache__/ *.pyc -quickstart.py -creds.json test/ -.vscode/ -listGoogle.py \ No newline at end of file +.vscode/ \ No newline at end of file diff --git a/ExpenseRatio.py b/ExpenseRatio.py index f6d6df0..a64312e 100644 --- a/ExpenseRatio.py +++ b/ExpenseRatio.py @@ -12,17 +12,19 @@ import numpy from urllib.request import urlopen import re + class ExpenseRatio: def __init__(self): -def main(): # For testing purposes +def main(): # For testing purposes ''' - a = [1,2,3] - b = [2,4,6] - c = numpy.corrcoef(a, b)[0, 1] - print(c) + a = [1,2,3] + b = [2,4,6] + c = numpy.corrcoef(a, b)[0, 1] + print(c) ''' + if __name__ == "__main__": - main() + main() diff --git a/Functions.py b/Functions.py index 1ec3db4..ae24926 100644 --- a/Functions.py +++ b/Functions.py @@ -1,24 +1,47 @@ # Python file for general functions -class Functions: - def getNearest(items, pivot): - return min(items, key=lambda x: abs(x - pivot)) - def stringToDate(date): - from datetime import datetime +def getNearest(items, pivot): + return min(items, key=lambda x: abs(x - pivot)) + +def stringToDate(date): + from datetime import datetime + + #datetime_object = datetime.strptime('Jun 1 2005 1:33PM', '%b %d %Y %I:%M%p') + datetime_object = datetime.strptime(date, '%Y-%m-%d').date() + return(datetime_object) + ''' + dateSplit = date.split('-') + year = int(dateSplit[0]) + month = int(dateSplit[1]) + day = int(dateSplit[2]) + datetime_object = datetime.date(year, month, day) + ''' + return datetime_object + +def removeExtraDatesAndCloseValues(list1, list2): + # Returns the two lists but with the extra dates and corresponding close values removed + # list = [[dates], [close values]] + + newList1 = [[], []] + newList2 = [[], []] + + for i in range(0, len(list1[0]), 1): + for j in range(0, len(list2[0]), 1): + if list1[0][i] == list2[0][j]: + newList1[0].append(list1[0][i]) + newList2[0].append(list1[0][i]) + newList1[1].append(list1[1][i]) + newList2[1].append(list2[1][j]) + break + + returnList = [] + returnList.append(newList1) + returnList.append(newList2) + return returnList - #datetime_object = datetime.strptime('Jun 1 2005 1:33PM', '%b %d %Y %I:%M%p') - datetime_object = datetime.strptime(date, '%Y-%m-%d').date() - return(datetime_object) - ''' - dateSplit = date.split('-') - year = int(dateSplit[0]) - month = int(dateSplit[1]) - day = int(dateSplit[2]) - datetime_object = datetime.date(year, month, day) - ''' - return datetime_object def main(): exit() + if __name__ == "__main__": - main() + main() diff --git a/README.md b/README.md index d842a24..ebb6232 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,4 @@ To begin, run Some ticker values to try: SPY, VFINX, AAPL, GOOGL -`$ pip install numpy` - Created by Andrew Dinh from Dr. TJ Owens Gilroy Early College Academy diff --git a/StockData.py b/StockData.py index d515d3a..41f81f5 100644 --- a/StockData.py +++ b/StockData.py @@ -3,6 +3,9 @@ # Python 3.6.1 # Description: Returns all available dates and prices for each stock requested. +import json +import requests +from datetime import datetime ''' Available API's: Can it do mutual funds? IEX: No @@ -18,7 +21,7 @@ Barchart: No # If you're going to take these API keys and abuse it, you should really reconsider your life priorities apiAV = 'O42ICUV58EIZZQMU' -#apiBarchart = 'a17fab99a1c21cd6f847e2f82b592838' # 150 getHistory queries per day +# apiBarchart = 'a17fab99a1c21cd6f847e2f82b592838' # 150 getHistory queries per day apiBarchart = 'f40b136c6dc4451f9136bb53b9e70ffa' apiTiingo = '2e72b53f2ab4f5f4724c5c1e4d5d4ac0af3f7ca8' apiTradier = 'n26IFFpkOFRVsB5SNTVNXicE5MPD' @@ -29,18 +32,19 @@ Daily Requests = 20,000 Symbol Requests = 500 ''' -import requests, json -from datetime import datetime class StockData: - def __init__(self, newName = '', newAbsFirstLastDates = [], newFinalDatesAndClose = [], newFinalDatesAndClose2 = [],newAllLists = []): - self.name = newName # Name of stock - self.absFirstLastDates = newAbsFirstLastDates # Absolute first and last dates from all sources - self.finalDatesAndClose = newFinalDatesAndClose # All available dates with corresponding close values - self.finalDatesAndClose2 = newFinalDatesAndClose2 # After some consideration, I decided to keep what I had already done here and make a new list that's the same except dates are in datetime format - self.allLists = newAllLists - ''' + def __init__(self, newName='', newAbsFirstLastDates=[], newFinalDatesAndClose=[], newFinalDatesAndClose2=[], newAllLists=[]): + self.name = newName # Name of stock + # Absolute first and last dates from all sources + self.absFirstLastDates = newAbsFirstLastDates + # All available dates with corresponding close values + self.finalDatesAndClose = newFinalDatesAndClose + # After some consideration, I decided to keep what I had already done here and make a new list that's the same except dates are in datetime format + self.finalDatesAndClose2 = newFinalDatesAndClose2 + self.allLists = newAllLists + ''' Format: # List from each source containing: [firstDate, lastDate, allDates, values, timeFrame] # firstDate & lastDate = '2018-12-18' (year-month-date) @@ -49,197 +53,208 @@ class StockData: timeFrame = [days, weeks, years] ''' - def set(self, newName, newFirstLastDates, newAbsFirstLastDates, newFinalDatesAndClose, newAllLists): - self.name = newName # Name of stock - self.firstLastDates = newFirstLastDates # Dates that at least 2 sources have (or should it be all?) - Maybe let user decide - self.absFirstLastDates = newAbsFirstLastDates # Absolute first and last dates from all sources - self.finalDatesAndClose = newFinalDatesAndClose - self.allLists = newAllLists + def set(self, newName, newFirstLastDates, newAbsFirstLastDates, newFinalDatesAndClose, newAllLists): + self.name = newName # Name of stock + # Dates that at least 2 sources have (or should it be all?) - Maybe let user decide + self.firstLastDates = newFirstLastDates + # Absolute first and last dates from all sources + self.absFirstLastDates = newAbsFirstLastDates + self.finalDatesAndClose = newFinalDatesAndClose + self.allLists = newAllLists - def setName(self, newName): - self.name = newName - def returnName(self): - return self.name - def returnAllLists(self): - return self.allLists - def returnAbsFirstLastDates(self): - return self.absFirstLastDates - def returnAllLists(self): - return self.allLists - def returnFinalDatesAndClose(self): - return self.finalDatesAndClose - def returnFinalDatesAndClose2(self): - return self.finalDatesAndClose2 + def setName(self, newName): + self.name = newName - def getIEX(self): - url = ''.join(('https://api.iextrading.com/1.0/stock/', self.name, '/chart/5y')) - #link = "https://api.iextrading.com/1.0/stock/spy/chart/5y" - print("\nSending request to:", url) - f = requests.get(url) - json_data = f.text - #print(json_data) - if (json_data == 'Unknown symbol'): - print("IEX not available") - return 'Not available' - loaded_json = json.loads(json_data) - listIEX = [] + def returnName(self): + return self.name - print("\nFinding first and last date") - # Adding (firstDate, lastDate) to listIEX - # Find firstDate (comes first) - firstLine = loaded_json[0] - #print("firstLine:", firstLine) - firstDate = firstLine['date'] - #print("firstDate:",firstDate) - # Find lastDate (comes last) - lastLine = loaded_json[-1] # Returns last value of the list (Equivalent to len(loaded_json)-1) - #print("lastLine:", lastLine) - lastDate = lastLine['date'] - #print("last date:", lastDate) - listIEX.append(firstDate) - listIEX.append(lastDate) - print(listIEX[0], ',', listIEX[1]) + def returnAllLists(self): + return self.allLists - print("\nFinding all dates given") - allDates = [] + def returnAbsFirstLastDates(self): + return self.absFirstLastDates + + def returnAllLists(self): + return self.allLists + + def returnFinalDatesAndClose(self): + return self.finalDatesAndClose + + def returnFinalDatesAndClose2(self): + return self.finalDatesAndClose2 + + def getIEX(self): + url = ''.join( + ('https://api.iextrading.com/1.0/stock/', self.name, '/chart/5y')) + #link = "https://api.iextrading.com/1.0/stock/spy/chart/5y" + print("\nSending request to:", url) + f = requests.get(url) + json_data = f.text + # print(json_data) + if (json_data == 'Unknown symbol'): + print("IEX not available") + return 'Not available' + loaded_json = json.loads(json_data) + listIEX = [] + + print("\nFinding first and last date") + # Adding (firstDate, lastDate) to listIEX + # Find firstDate (comes first) + firstLine = loaded_json[0] + #print("firstLine:", firstLine) + firstDate = firstLine['date'] + # print("firstDate:",firstDate) + # Find lastDate (comes last) + # Returns last value of the list (Equivalent to len(loaded_json)-1) + lastLine = loaded_json[-1] + #print("lastLine:", lastLine) + lastDate = lastLine['date'] + #print("last date:", lastDate) + listIEX.append(firstDate) + listIEX.append(lastDate) + print(listIEX[0], ',', listIEX[1]) + + print("\nFinding all dates given") + allDates = [] # for i in range(0, len(loaded_json), 1): # If you want to do oldest first - for i in range(len(loaded_json)-1, -1, -1): - line = loaded_json[i] - date = line['date'] - allDates.append(date) - listIEX.append(allDates) + for i in range(len(loaded_json)-1, -1, -1): + line = loaded_json[i] + date = line['date'] + allDates.append(date) + listIEX.append(allDates) - #print(listIEX[2]) - print(len(listIEX[2]), "dates") + # print(listIEX[2]) + print(len(listIEX[2]), "dates") - print("\nFinding close values for each date") - values = [] + print("\nFinding close values for each date") + values = [] # for i in range(0, len(loaded_json), 1): # If you want to do oldest first - for i in range(len(loaded_json)-1, -1, -1): - line = loaded_json[i] - value = line['close'] - values.append(value) - listIEX.append(values) - #print(listIEX[3]) - print(len(listIEX[3]), "close values") + for i in range(len(loaded_json)-1, -1, -1): + line = loaded_json[i] + value = line['close'] + values.append(value) + listIEX.append(values) + # print(listIEX[3]) + print(len(listIEX[3]), "close values") - print("\nFinding time frame given [days, weeks, years]") - timeFrame = [] - d1 = datetime.strptime(firstDate, "%Y-%m-%d") - d2 = datetime.strptime(lastDate, "%Y-%m-%d") - timeFrameDays = abs((d2 - d1).days) - #print(timeFrameDays) - timeFrameYears = float(timeFrameDays / 365) - timeFrameWeeks = float(timeFrameDays / 7) - timeFrame.append(timeFrameDays) - timeFrame.append(timeFrameWeeks) - timeFrame.append(timeFrameYears) - listIEX.append(timeFrame) - print(listIEX[4]) + print("\nFinding time frame given [days, weeks, years]") + timeFrame = [] + d1 = datetime.strptime(firstDate, "%Y-%m-%d") + d2 = datetime.strptime(lastDate, "%Y-%m-%d") + timeFrameDays = abs((d2 - d1).days) + # print(timeFrameDays) + timeFrameYears = float(timeFrameDays / 365) + timeFrameWeeks = float(timeFrameDays / 7) + timeFrame.append(timeFrameDays) + timeFrame.append(timeFrameWeeks) + timeFrame.append(timeFrameYears) + listIEX.append(timeFrame) + print(listIEX[4]) - return listIEX + return listIEX - def getAV(self): - listAV = [] - #url = ''.join(('https://www.alphavantage.co/query?function=TIME_SERIES_MONTHLY&symbol=', self.name, '&apikey=', apiAV)) - # https://www.alphavantage.co/query?function=TIME_SERIES_MONTHLY&symbol=MSFT&apikey=demo + def getAV(self): + listAV = [] + #url = ''.join(('https://www.alphavantage.co/query?function=TIME_SERIES_MONTHLY&symbol=', self.name, '&apikey=', apiAV)) + # https://www.alphavantage.co/query?function=TIME_SERIES_MONTHLY&symbol=MSFT&apikey=demo - #url = ''.join(('https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=', self.name, '&outputsize=full&apikey=', apiAV)) - # https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=MSFT&outputsize=full&apikey=demo + #url = ''.join(('https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=', self.name, '&outputsize=full&apikey=', apiAV)) + # https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=MSFT&outputsize=full&apikey=demo - url = ''.join(('https://www.alphavantage.co/query?function=TIME_SERIES_DAILY_ADJUSTED&symbol=', self.name, '&outputsize=full&apikey=', apiAV)) - # https://www.alphavantage.co/query?function=TIME_SERIES_DAILY_ADJUSTED&symbol=MSFT&outputsize=full&apikey=demo + url = ''.join(('https://www.alphavantage.co/query?function=TIME_SERIES_DAILY_ADJUSTED&symbol=', + self.name, '&outputsize=full&apikey=', apiAV)) + # https://www.alphavantage.co/query?function=TIME_SERIES_DAILY_ADJUSTED&symbol=MSFT&outputsize=full&apikey=demo - print("\nSending request to:", url) - print("(This will take a while)") - f = requests.get(url) - json_data = f.text - loaded_json = json.loads(json_data) - #print(loaded_json) + print("\nSending request to:", url) + print("(This will take a while)") + f = requests.get(url) + json_data = f.text + loaded_json = json.loads(json_data) + # print(loaded_json) - #print(type(loaded_json)) # Dictionary - #print(len(loaded_json)) - if len(loaded_json) == 1: - print("Alpha Vantage not available") - return 'Not available' + # print(type(loaded_json)) # Dictionary + # print(len(loaded_json)) + if len(loaded_json) == 1: + print("Alpha Vantage not available") + return 'Not available' - #print(loaded_json['Monthly Time Series']) - dailyTimeSeries = loaded_json['Time Series (Daily)'] - #print(monthlyTimeSeries) - listOfDates = list(dailyTimeSeries) - #print(listOfDates) + #print(loaded_json['Monthly Time Series']) + dailyTimeSeries = loaded_json['Time Series (Daily)'] + # print(monthlyTimeSeries) + listOfDates = list(dailyTimeSeries) + # print(listOfDates) - firstDate = listOfDates[-1] - lastDate = listOfDates[0] - #print("firstDate:", firstDate) - #print("lastDate:", lastDate) - listAV.append(firstDate) - listAV.append(lastDate) - listAV.append(listOfDates) + firstDate = listOfDates[-1] + lastDate = listOfDates[0] + #print("firstDate:", firstDate) + #print("lastDate:", lastDate) + listAV.append(firstDate) + listAV.append(lastDate) + listAV.append(listOfDates) - print("\nFinding first and last date") - print(listAV[0], ',', listAV[1]) - print("\nFinding all dates given") - #print(listAV[2]) - print(len(listAV[2]), "dates") + print("\nFinding first and last date") + print(listAV[0], ',', listAV[1]) + print("\nFinding all dates given") + # print(listAV[2]) + print(len(listAV[2]), "dates") - print("\nFinding close values for each date") - values = [] - for i in range(0, len(listOfDates), 1): - temp = listOfDates[i] - loaded_json2 = dailyTimeSeries[temp] - #value = loaded_json2['4. close'] - value = loaded_json2['5. adjusted close'] - values.append(value) - listAV.append(values) - #print(listOfDates[0]) - #i = listOfDates[0] - #print(monthlyTimeSeries[i]) - #print(listAV[3]) - print(len(listAV[3]), "close values") + print("\nFinding close values for each date") + values = [] + for i in range(0, len(listOfDates), 1): + temp = listOfDates[i] + loaded_json2 = dailyTimeSeries[temp] + #value = loaded_json2['4. close'] + value = loaded_json2['5. adjusted close'] + values.append(value) + listAV.append(values) + # print(listOfDates[0]) + #i = listOfDates[0] + # print(monthlyTimeSeries[i]) + # print(listAV[3]) + print(len(listAV[3]), "close values") - print("\nFinding time frame given [days, weeks, years]") - timeFrame = [] - d1 = datetime.strptime(firstDate, "%Y-%m-%d") - d2 = datetime.strptime(lastDate, "%Y-%m-%d") - timeFrameDays = abs((d2 - d1).days) - #print(timeFrameDays) - timeFrameYears = float(timeFrameDays / 365) - timeFrameWeeks = float(timeFrameDays / 7) - timeFrame.append(timeFrameDays) - timeFrame.append(timeFrameWeeks) - timeFrame.append(timeFrameYears) - listAV.append(timeFrame) - print(listAV[4]) + print("\nFinding time frame given [days, weeks, years]") + timeFrame = [] + d1 = datetime.strptime(firstDate, "%Y-%m-%d") + d2 = datetime.strptime(lastDate, "%Y-%m-%d") + timeFrameDays = abs((d2 - d1).days) + # print(timeFrameDays) + timeFrameYears = float(timeFrameDays / 365) + timeFrameWeeks = float(timeFrameDays / 7) + timeFrame.append(timeFrameDays) + timeFrame.append(timeFrameWeeks) + timeFrame.append(timeFrameYears) + listAV.append(timeFrame) + print(listAV[4]) - return listAV + return listAV - def getTiingo(self): - ''' - #OR we can use the token directly in the url - headers = { - 'Content-Type': 'application/json' - } - requestResponse = requests.get("https://api.tiingo.com/api/test?token=", - headers=headers) - print(requestResponse.json()) - ''' - token = ''.join(('Token ', apiTiingo)) - headers = { - 'Content-Type': 'application/json', - 'Authorization' : token - } - url = ''.join(('https://api.tiingo.com/tiingo/daily/', self.name)) - print("\nSending request to:", url) - requestResponse = requests.get(url, headers=headers) - #print(requestResponse.json()) - loaded_json = requestResponse.json() - #print(len(loaded_json)) - if len(loaded_json) == 1: - print("Tiingo not available") - return 'Not available' - #print(loaded_json) - ''' + def getTiingo(self): + ''' + #OR we can use the token directly in the url + headers = { + 'Content-Type': 'application/json' + } + requestResponse = requests.get("https://api.tiingo.com/api/test?token=", + headers=headers) + print(requestResponse.json()) + ''' + token = ''.join(('Token ', apiTiingo)) + headers = { + 'Content-Type': 'application/json', + 'Authorization': token + } + url = ''.join(('https://api.tiingo.com/tiingo/daily/', self.name)) + print("\nSending request to:", url) + requestResponse = requests.get(url, headers=headers) + # print(requestResponse.json()) + loaded_json = requestResponse.json() + # print(len(loaded_json)) + if len(loaded_json) == 1: + print("Tiingo not available") + return 'Not available' + # print(loaded_json) + ''' list1 = list(loaded_json) for i in range (0, len(list1), 1): if list1[i] == 'startDate': @@ -249,274 +264,276 @@ class StockData: print(list1[startNum]) print(list1[endNum]) ''' - listTiingo = [] + listTiingo = [] - print("\nFinding first and last date") - firstDate = loaded_json['startDate'] - lastDate = loaded_json['endDate'] - #print(firstDate) - #print(lastDate) - listTiingo.append(firstDate) - listTiingo.append(lastDate) - print(listTiingo[0], ',', listTiingo[1]) + print("\nFinding first and last date") + firstDate = loaded_json['startDate'] + lastDate = loaded_json['endDate'] + # print(firstDate) + # print(lastDate) + listTiingo.append(firstDate) + listTiingo.append(lastDate) + print(listTiingo[0], ',', listTiingo[1]) - print("\nFinding all dates given") - dates = [] - values = [] # Used loop for finding values - url2 = ''.join((url, '/prices?startDate=', firstDate, '&endDate=', lastDate)) - # https://api.tiingo.com/tiingo/daily//prices?startDate=2012-1-1&endDate=2016-1-1 - print("\nSending request to:", url2) - requestResponse2 = requests.get(url2, headers=headers) - loaded_json2 = requestResponse2.json() - #print(loaded_json2) - #print(len(loaded_json2)) - for i in range(len(loaded_json2)-1, -1, -1): - line = loaded_json2[i] - dateWithTime = line['date'] - temp = dateWithTime.split('T00:00:00.000Z') - date = temp[0] - dates.append(date) + print("\nFinding all dates given") + dates = [] + values = [] # Used loop for finding values + url2 = ''.join((url, '/prices?startDate=', + firstDate, '&endDate=', lastDate)) + # https://api.tiingo.com/tiingo/daily//prices?startDate=2012-1-1&endDate=2016-1-1 + print("\nSending request to:", url2) + requestResponse2 = requests.get(url2, headers=headers) + loaded_json2 = requestResponse2.json() + # print(loaded_json2) + # print(len(loaded_json2)) + for i in range(len(loaded_json2)-1, -1, -1): + line = loaded_json2[i] + dateWithTime = line['date'] + temp = dateWithTime.split('T00:00:00.000Z') + date = temp[0] + dates.append(date) - value = line['close'] - values.append(value) - listTiingo.append(dates) - #print(listTiingo[2]) - print(len(listTiingo[2]), "dates") + value = line['close'] + values.append(value) + listTiingo.append(dates) + # print(listTiingo[2]) + print(len(listTiingo[2]), "dates") - print("Finding close values for each date") - # Used loop from finding dates - listTiingo.append(values) - #print(listTiingo[3]) - print(len(listTiingo[3]), "close values") + print("Finding close values for each date") + # Used loop from finding dates + listTiingo.append(values) + # print(listTiingo[3]) + print(len(listTiingo[3]), "close values") - print("Finding time frame given [days, weeks, years]") - timeFrame = [] - d1 = datetime.strptime(firstDate, "%Y-%m-%d") - d2 = datetime.strptime(lastDate, "%Y-%m-%d") - timeFrameDays = abs((d2 - d1).days) - #print(timeFrameDays) - timeFrameYears = float(timeFrameDays / 365) - timeFrameWeeks = float(timeFrameDays / 7) - timeFrame.append(timeFrameDays) - timeFrame.append(timeFrameWeeks) - timeFrame.append(timeFrameYears) - listTiingo.append(timeFrame) - print(listTiingo[4]) + print("Finding time frame given [days, weeks, years]") + timeFrame = [] + d1 = datetime.strptime(firstDate, "%Y-%m-%d") + d2 = datetime.strptime(lastDate, "%Y-%m-%d") + timeFrameDays = abs((d2 - d1).days) + # print(timeFrameDays) + timeFrameYears = float(timeFrameDays / 365) + timeFrameWeeks = float(timeFrameDays / 7) + timeFrame.append(timeFrameDays) + timeFrame.append(timeFrameWeeks) + timeFrame.append(timeFrameYears) + listTiingo.append(timeFrame) + print(listTiingo[4]) - return listTiingo + return listTiingo - def getFirstLastDate(self, listOfFirstLastDates): - listOfFirstDates = [] - listOfLastDates = [] - #print(len(listOfFirstLastDates)) - for i in range (0, len(listOfFirstLastDates), 1): - firstLastDates = listOfFirstLastDates[i] - firstDate = firstLastDates[0] - lastDate = firstLastDates[1] - listOfFirstDates.append(firstDate) - listOfLastDates.append(lastDate) - #print(listOfFirstDates) - #print(listOfLastDates) - for i in range (0, len(listOfFirstDates), 1): - date = listOfFirstDates[i] - if i == 0: - firstDate = date - yearMonthDay = firstDate.split('-') - firstYear = yearMonthDay[0] - firstMonth = yearMonthDay[1] - firstDay = yearMonthDay[2] - else: - yearMonthDay = date.split('-') - year = yearMonthDay[0] - month = yearMonthDay[1] - day = yearMonthDay[2] - if year < firstYear or (year == firstYear and month < firstMonth) or (year == firstYear and month == firstMonth and day < firstDay): - firstDate = date - firstYear = year - firstMonth = month - firstDay = day - #print(firstDate) - if len(listOfFirstDates) > 1: - for i in range(0, len(listOfLastDates),1): - date = listOfLastDates[i] - if i == 0: - lastDate = date - yearMonthDay = lastDate.split('-') - lastYear = yearMonthDay[0] - lastMonth = yearMonthDay[1] - lastDay = yearMonthDay[2] - else: - yearMonthDay = date.split('-') - year = yearMonthDay[0] - month = yearMonthDay[1] - day = yearMonthDay[2] - if year > lastYear or (year == lastYear and month > lastMonth) or (year == lastYear and month == lastMonth and day > lastDay): - lastDate = date - lastYear = year - lastMonth = month - lastDay = day - #print(lastDate) - absFirstLastDates = [] - absFirstLastDates.append(firstDate) - absFirstLastDates.append(lastDate) - return absFirstLastDates + def getFirstLastDate(self, listOfFirstLastDates): + listOfFirstDates = [] + listOfLastDates = [] + # print(len(listOfFirstLastDates)) + for i in range(0, len(listOfFirstLastDates), 1): + firstLastDates = listOfFirstLastDates[i] + firstDate = firstLastDates[0] + lastDate = firstLastDates[1] + listOfFirstDates.append(firstDate) + listOfLastDates.append(lastDate) + # print(listOfFirstDates) + # print(listOfLastDates) + for i in range(0, len(listOfFirstDates), 1): + date = listOfFirstDates[i] + if i == 0: + firstDate = date + yearMonthDay = firstDate.split('-') + firstYear = yearMonthDay[0] + firstMonth = yearMonthDay[1] + firstDay = yearMonthDay[2] + else: + yearMonthDay = date.split('-') + year = yearMonthDay[0] + month = yearMonthDay[1] + day = yearMonthDay[2] + if year < firstYear or (year == firstYear and month < firstMonth) or (year == firstYear and month == firstMonth and day < firstDay): + firstDate = date + firstYear = year + firstMonth = month + firstDay = day + # print(firstDate) + if len(listOfFirstDates) > 1: + for i in range(0, len(listOfLastDates), 1): + date = listOfLastDates[i] + if i == 0: + lastDate = date + yearMonthDay = lastDate.split('-') + lastYear = yearMonthDay[0] + lastMonth = yearMonthDay[1] + lastDay = yearMonthDay[2] + else: + yearMonthDay = date.split('-') + year = yearMonthDay[0] + month = yearMonthDay[1] + day = yearMonthDay[2] + if year > lastYear or (year == lastYear and month > lastMonth) or (year == lastYear and month == lastMonth and day > lastDay): + lastDate = date + lastYear = year + lastMonth = month + lastDay = day + # print(lastDate) + absFirstLastDates = [] + absFirstLastDates.append(firstDate) + absFirstLastDates.append(lastDate) + return absFirstLastDates - def getFinalDatesAndClose(self): - # finalDates and finalClose will coincide (aka i = 1 will correspond to one another) - finalDatesAndClose = [] # Will combine finalDates then finalClose - finalDates = [] - finalClose = [] - #print(self.absFirstLastDates) - absFirstDate = self.absFirstLastDates[0] - absLastDate = self.absFirstLastDates[1] - date = absFirstDate + def getFinalDatesAndClose(self): + # finalDates and finalClose will coincide (aka i = 1 will correspond to one another) + finalDatesAndClose = [] # Will combine finalDates then finalClose + finalDates = [] + finalClose = [] + # print(self.absFirstLastDates) + absFirstDate = self.absFirstLastDates[0] + absLastDate = self.absFirstLastDates[1] + date = absFirstDate - allLists = self.allLists - while date != absLastDate: # DOESN'T DO LAST DATE - tempListOfClose = [] - found = False - for j in range(0, len(allLists), 1): # Look for date in all lists - list1 = allLists[j] - listOfDates = list1[2] - listOfClose = list1[3] - for k in range(0, len(listOfDates), 1): - if listOfDates[k] == date: - if found == False: - finalDates.append(date) - found = True - #print(listOfDates[k]) - #print(listOfClose[k]) - #print(listOfClose) - tempListOfClose.append(float(listOfClose[k])) - k = len(listOfDates) # Dates don't repeat + allLists = self.allLists + while date != absLastDate: # DOESN'T DO LAST DATE + tempListOfClose = [] + found = False + for j in range(0, len(allLists), 1): # Look for date in all lists + list1 = allLists[j] + listOfDates = list1[2] + listOfClose = list1[3] + for k in range(0, len(listOfDates), 1): + if listOfDates[k] == date: + if found == False: + finalDates.append(date) + found = True + # print(listOfDates[k]) + # print(listOfClose[k]) + # print(listOfClose) + tempListOfClose.append(float(listOfClose[k])) + k = len(listOfDates) # Dates don't repeat - if found == True: + if found == True: + sum = 0 + for r in range(0, len(tempListOfClose), 1): + sum = sum + tempListOfClose[r] + close = sum/len(tempListOfClose) + + finalClose.append(close) + # print(close) + + # Go to the next day + yearMonthDay = date.split('-') + year = int(yearMonthDay[0]) + month = int(yearMonthDay[1]) + day = int(yearMonthDay[2]) + + day = day + 1 + if day == 32 and month == 12: # Next year + day = 1 + month = 1 + year = year + 1 + elif day == 32: # Next month + month = month + 1 + day = 1 + if day < 10: + day = ''.join(('0', str(day))) + if month < 10: + month = ''.join(('0', str(month))) + date = ''.join((str(year), '-', str(month), '-', str(day))) + # print(date) + + # For last date + finalDates.append(date) + tempListOfClose = [] + for j in range(0, len(allLists), 1): # Look for date in all lists + list1 = allLists[j] + listOfDates = list1[2] + listOfClose = list1[3] + for k in range(0, len(listOfDates), 1): + if listOfDates[k] == date: + tempListOfClose.append(float(listOfClose[k])) + k = len(listOfDates) # Dates don't repeat sum = 0 for r in range(0, len(tempListOfClose), 1): - sum = sum + tempListOfClose[r] + sum = sum + tempListOfClose[r] close = sum/len(tempListOfClose) - finalClose.append(close) - #print(close) + # print(finalDates) + # print(finalClose) - # Go to the next day - yearMonthDay = date.split('-') - year = int(yearMonthDay[0]) - month = int(yearMonthDay[1]) - day = int(yearMonthDay[2]) + # Want lists from most recent to oldest, comment this out if you don't want that + finalDates = list(reversed(finalDates)) + finalClose = list(reversed(finalClose)) - day = day + 1 - if day == 32 and month == 12: # Next year - day = 1 - month = 1 - year = year + 1 - elif day == 32: # Next month - month = month + 1 - day = 1 - if day < 10: - day = ''.join(('0', str(day))) - if month < 10: - month = ''.join(('0', str(month))) - date = ''.join((str(year), '-', str(month), '-', str(day))) - #print(date) + finalDatesAndClose.append(finalDates) + finalDatesAndClose.append(finalClose) + return finalDatesAndClose - # For last date - finalDates.append(date) - tempListOfClose = [] - for j in range(0, len(allLists), 1): # Look for date in all lists - list1 = allLists[j] - listOfDates = list1[2] - listOfClose = list1[3] - for k in range(0, len(listOfDates), 1): - if listOfDates[k] == date: - tempListOfClose.append(float(listOfClose[k])) - k = len(listOfDates) # Dates don't repeat - sum = 0 - for r in range(0, len(tempListOfClose), 1): - sum = sum + tempListOfClose[r] - close = sum/len(tempListOfClose) - finalClose.append(close) - #print(finalDates) - #print(finalClose) + def datetimeDates(self): + finalDatesAndClose2 = [] + finalDatesAndClose = self.finalDatesAndClose + finalDatesStrings = finalDatesAndClose[0] + finalClose = finalDatesAndClose[1] + finalDates = [] - # Want lists from most recent to oldest, comment this out if you don't want that - finalDates = list(reversed(finalDates)) - finalClose = list(reversed(finalClose)) + from Functions import Functions + for i in range(0, len(finalDatesStrings), 1): + temp = Functions.stringToDate(finalDatesStrings[i]) + finalDates.append(temp) + # print(finalDates) - finalDatesAndClose.append(finalDates) - finalDatesAndClose.append(finalClose) - return finalDatesAndClose + finalDatesAndClose2.append(finalDates) + finalDatesAndClose2.append(finalClose) + return(finalDatesAndClose2) - def datetimeDates(self): - finalDatesAndClose2 = [] - finalDatesAndClose = self.finalDatesAndClose - finalDatesStrings = finalDatesAndClose[0] - finalClose = finalDatesAndClose[1] - finalDates = [] + def is_connected(): + import socket # To check internet connection + try: + # connect to the host -- tells us if the host is actually + # reachable + socket.create_connection(("www.andrewkdinh.com", 80)) + return True + except OSError: + # pass + print("\nNo internet connection!") + return False - from Functions import Functions - for i in range(0, len(finalDatesStrings), 1): - temp = Functions.stringToDate(finalDatesStrings[i]) - finalDates.append(temp) - #print(finalDates) + def main(self): + print('Beginning StockData.py') - finalDatesAndClose2.append(finalDates) - finalDatesAndClose2.append(finalClose) - return(finalDatesAndClose2) + import importlib.util + import sys # To check whether a package is installed - def is_connected(): - import socket # To check internet connection - try: - # connect to the host -- tells us if the host is actually - # reachable - socket.create_connection(("www.andrewkdinh.com", 80)) - return True - except OSError: - #pass - print("\nNo internet connection!") - return False + packages = ['requests'] + for i in range(0, len(packages), 1): + package_name = packages[i] + spec = importlib.util.find_spec(package_name) + if spec is None: + print(package_name + " is not installed\nPlease type in 'pip install -r requirements.txt' to install all required packages") - def main(self): - print('Beginning StockData.py') - - import importlib.util, sys # To check whether a package is installed + # Test internet connection + internetConnection = StockData.is_connected() + if internetConnection == False: + return - packages = ['requests'] - for i in range(0, len(packages), 1): - package_name = packages[i] - spec = importlib.util.find_spec(package_name) - if spec is None: - print(package_name +" is not installed\nPlease type in 'pip install -r requirements.txt' to install all required packages") + listOfFirstLastDates = [] + self.allLists = [] - # Test internet connection - internetConnection = StockData.is_connected() - if internetConnection == False: - return + print('\nNOTE: Only IEX and Alpha Vantage support adjusted returns') + print('NOTE: Only Alpha Vantage and Tiingo support mutual fund data') - listOfFirstLastDates = [] - self.allLists = [] + # IEX + print("\nIEX") + listIEX = StockData.getIEX(self) + # print(listIEX) + if listIEX != 'Not available': + listOfFirstLastDates.append((listIEX[0], listIEX[1])) + self.allLists.append(listIEX) - print('\nNOTE: Only IEX and Alpha Vantage support adjusted returns') - print('NOTE: Only Alpha Vantage and Tiingo support mutual fund data') + # Alpha Vantage + print("\nAlpha Vantage (AV)") + listAV = StockData.getAV(self) + # print(listAV) + if listAV != 'Not available': + listOfFirstLastDates.append((listAV[0], listAV[1])) + self.allLists.append(listAV) - # IEX - print("\nIEX") - listIEX = StockData.getIEX(self) - #print(listIEX) - if listIEX != 'Not available': - listOfFirstLastDates.append((listIEX[0], listIEX[1])) - self.allLists.append(listIEX) - - # Alpha Vantage - print("\nAlpha Vantage (AV)") - listAV = StockData.getAV(self) - #print(listAV) - if listAV != 'Not available': - listOfFirstLastDates.append((listAV[0], listAV[1])) - self.allLists.append(listAV) - - # COMMENTED OUT FOR NOW B/C LIMITED - ''' + # COMMENTED OUT FOR NOW B/C LIMITED + ''' print("\nTiingo") print("NOTE: Tiingo does not return adjusted returns!!") listTiingo = StockData.getTiingo(self) @@ -526,36 +543,44 @@ class StockData: self.allLists.append(listTiingo) ''' - #print(self.allLists) - #print(listOfFirstLastDates) - if (len(self.allLists) > 0): - print("\n", end='') - print(len(self.allLists), "available source(s) for", self.name) - self.absFirstLastDates = StockData.getFirstLastDate(self, listOfFirstLastDates) - print("\nThe absolute first date with close values is:", self.absFirstLastDates[0]) - print("The absolute last date with close values is:", self.absFirstLastDates[1]) + # print(self.allLists) + # print(listOfFirstLastDates) + if (len(self.allLists) > 0): + print("\n", end='') + print(len(self.allLists), "available source(s) for", self.name) + self.absFirstLastDates = StockData.getFirstLastDate( + self, listOfFirstLastDates) + print("\nThe absolute first date with close values is:", + self.absFirstLastDates[0]) + print("The absolute last date with close values is:", + self.absFirstLastDates[1]) - print("\nCombining dates and averaging close values") - self.finalDatesAndClose = StockData.getFinalDatesAndClose(self) # Returns [List of Dates, List of Corresponding Close Values] - #print("All dates available:", self.finalDatesAndClose[0]) - #print("All close values:\n", self.finalDatesAndClose[1]) - finalDates = self.finalDatesAndClose[0] - finalClose = self.finalDatesAndClose[1] - print(len(finalDates), "unique dates:", finalDates[len(finalDates)-1], "...", finalDates[0]) - print(len(finalClose), "close values:", finalClose[len(finalClose)-1], "...", finalClose[0]) + print("\nCombining dates and averaging close values") + # Returns [List of Dates, List of Corresponding Close Values] + self.finalDatesAndClose = StockData.getFinalDatesAndClose(self) + #print("All dates available:", self.finalDatesAndClose[0]) + #print("All close values:\n", self.finalDatesAndClose[1]) + finalDates = self.finalDatesAndClose[0] + finalClose = self.finalDatesAndClose[1] + print(len(finalDates), "unique dates:", + finalDates[len(finalDates)-1], "...", finalDates[0]) + print(len(finalClose), "close values:", + finalClose[len(finalClose)-1], "...", finalClose[0]) - print("\nConverting list of final dates to datetime\n") - self.finalDatesAndClose2 = StockData.datetimeDates(self) - #print(self.finalDatesAndClose2[0][0]) + print("\nConverting list of final dates to datetime\n") + self.finalDatesAndClose2 = StockData.datetimeDates(self) + # print(self.finalDatesAndClose2[0][0]) - else: - print("No sources have data for", self.name) + else: + print("No sources have data for", self.name) + + +def main(): # For testing purposes + stockName = 'spy' + stock1 = StockData(stockName) + print("Finding available dates and close values for", stock1.name) + StockData.main(stock1) -def main(): # For testing purposes - stockName = 'spy' - stock1 = StockData(stockName) - print("Finding available dates and close values for", stock1.name) - StockData.main(stock1) if __name__ == "__main__": - main() + main() diff --git a/StockReturn.py b/StockReturn.py index 3911de5..5e8f78a 100644 --- a/StockReturn.py +++ b/StockReturn.py @@ -11,10 +11,11 @@ from StockData import StockData import datetime from Functions import Functions + class Return: - def __init__(self, newListOfReturn = [], newTimeFrame = [], newBeta = 0, newStandardDeviation = 0, newNegativeStandardDeviation = 0, newMarketReturn = 0, newSize = 0, newSizeOfNeg = 0, newFirstLastDates = [], newAllLists = [], newAbsFirstLastDates = ''): + def __init__(self, newListOfReturn=[], newTimeFrame=[], newBeta=0, newStandardDeviation=0, newNegativeStandardDeviation=0, newMarketReturn=0, newSize=0, newSizeOfNeg=0, newFirstLastDates=[], newAllLists=[], newAbsFirstLastDates=''): self.listOfReturn = newListOfReturn - self.timeFrame = newTimeFrame # [years, months (30 days)] + self.timeFrame = newTimeFrame # [years, months (30 days)] self.beta = newBeta self.standardDeviation = newStandardDeviation self.negativeStandardDeviation = newNegativeStandardDeviation @@ -32,12 +33,14 @@ class Return: def getFirstLastDates(self, stock): firstLastDates = [] timeFrame = self.timeFrame - firstDate = datetime.datetime.now() - datetime.timedelta(days=timeFrame[0]*365) + firstDate = datetime.datetime.now( + ) - datetime.timedelta(days=timeFrame[0]*365) firstDate = firstDate - datetime.timedelta(days=timeFrame[1]*30) - firstDate = ''.join((str(firstDate.year),'-', str(firstDate.month), '-', str(firstDate.day))) + firstDate = ''.join( + (str(firstDate.year), '-', str(firstDate.month), '-', str(firstDate.day))) lastDate = StockData.returnAbsFirstLastDates(stock)[1] - #print(lastDate) + # print(lastDate) firstLastDates.append(firstDate) firstLastDates.append(lastDate) return firstLastDates @@ -60,19 +63,21 @@ class Return: if firstDateExists == False: print("Could not find first date. Changing first date to closest date") - tempDate = Functions.stringToDate(firstDate) # Change to datetime + tempDate = Functions.stringToDate(firstDate) # Change to datetime print('Original first date:', tempDate) #tempDate = datetime.date(2014,1,17) - newFirstDate = Functions.getNearest(finalDatesAndClose2[0], tempDate) + newFirstDate = Functions.getNearest( + finalDatesAndClose2[0], tempDate) print('New first date:', newFirstDate) firstDate = str(newFirstDate) if lastDateExists == False: print("Could not find final date. Changing final date to closest date") - tempDate2 = Functions.stringToDate(lastDate) # Change to datetime + tempDate2 = Functions.stringToDate(lastDate) # Change to datetime print('Original final date:', tempDate2) #tempDate2 = datetime.date(2014,1,17) - newLastDate = Functions.getNearest(finalDatesAndClose2[0], tempDate2) + newLastDate = Functions.getNearest( + finalDatesAndClose2[0], tempDate2) print('New final date:', newLastDate) lastDate = str(newLastDate) @@ -97,7 +102,8 @@ class Return: print('Close values:', firstClose, '...', lastClose) fullUnadjustedReturn = float(lastClose/firstClose) - unadjustedReturn = fullUnadjustedReturn**(1/(self.timeFrame[0]+(self.timeFrame[1])*.1)) + unadjustedReturn = fullUnadjustedReturn**( + 1/(self.timeFrame[0]+(self.timeFrame[1])*.1)) return unadjustedReturn def getBeta(self): @@ -113,9 +119,9 @@ class Return: for i in range(0, len(finalDates), 1): if finalDates[i] == str(firstDate): firstClose = finalClose[i] -55ggbh - #list1 = - list2 = [1,2,4,1] + + # list1 = + list2 = [1, 2, 4, 1] print(numpy.corrcoef(list1, list2)[0, 1]) @@ -138,7 +144,7 @@ class Return: timeFrameMonth = 0 print(timeFrameMonth) self.timeFrame.append(timeFrameMonth) - #print(self.timeFrame) + # print(self.timeFrame) self.firstLastDates = Return.getFirstLastDates(self, stock) print('Dates: ', self.firstLastDates) @@ -149,10 +155,10 @@ class Return: print('\nGetting unadjusted return') unadjustedReturn = Return.getUnadjustedReturn(self, stock) self.listOfReturn.append(unadjustedReturn) - print('Average annual return for the past', self.timeFrame[0], 'years and', self.timeFrame[1], 'months: ', end='') + print('Average annual return for the past', + self.timeFrame[0], 'years and', self.timeFrame[1], 'months: ', end='') print((self.listOfReturn[0]-1)*100, '%', sep='') - def main(self, stock): print('Beginning StockReturn.py') @@ -169,12 +175,14 @@ class Return: print('\nGetting unadjusted return') unadjustedReturn = Return.getUnadjustedReturn(self, stock) self.listOfReturn.append(unadjustedReturn) - print('Average annual return for the past', self.timeFrame[0], 'years and', self.timeFrame[1], 'months: ', end='') + print('Average annual return for the past', + self.timeFrame[0], 'years and', self.timeFrame[1], 'months: ', end='') print((self.listOfReturn[0]-1)*100, '%', sep='') #print('\nGetting beta') #beta = Return.getBeta(self, stock) + def main(): stockName = 'spy' stock1 = StockData(stockName) @@ -186,5 +194,6 @@ def main(): Return.main(stock1Return, stock1) + if __name__ == "__main__": - main() + main() diff --git a/listGoogle.py b/listGoogle.py deleted file mode 100644 index f911dba..0000000 --- a/listGoogle.py +++ /dev/null @@ -1,54 +0,0 @@ -# https://support.google.com/docs/answer/3093281?hl=en -# Historical data cannot be downloaded or accessed via the Sheets API or Apps Script. If you attempt to do so, you will see a #N/A error in place of the values in the corresponding cells of your spreadsheet. - -import gspread, time, webbrowser, msvcrt -from oauth2client.service_account import ServiceAccountCredentials - -def main(): - scope = ['https://spreadsheets.google.com/feeds', - 'https://www.googleapis.com/auth/drive'] - - credentials = ServiceAccountCredentials.from_json_keyfile_name('creds.json', scope) - - gc = gspread.authorize(credentials) - ''' - # Just by ID: - #sheet = gc.open_by_key('1YS8qBQCXKNfSgQgXeUdSGOd6lM2wm-inV0_1YE36vQM') - sheet = gc.open_by_url('https://docs.google.com/spreadsheets/d/1YS8qBQCXKNfSgQgXeUdSGOd6lM2wm-inV0_1YE36vQM') - worksheet = sheet.get_worksheet(0) - worksheet.update_acell('B1', 'bingo!') - #worksheet.update_cell(1, 2, 'Bingo!') - val = worksheet.acell('B1').value - #val = worksheet.cell(1, 2).value - print(val) - ''' - url = 'https://docs.google.com/spreadsheets/d/1YS8qBQCXKNfSgQgXeUdSGOd6lM2wm-inV0_1YE36vQM' - surl = 'https://www.andrewkdinh.com/u/listGoogle' - print("Opening", url) - #webbrowser.open(surl) - sheet = gc.open_by_url(url) - worksheet = sheet.get_worksheet(0) - print('Writing Google Finance function to A1') - worksheet.update_cell(1, 1, '=GOOGLEFINANCE("GOOG", "price", DATE(2014,1,1), DATE(2014,12,31), "DAILY")') - print('\nOpening link to the Google Sheet. Please download the file as comma-separated values (.csv) and move it to the directory of this Python file', - '\nFile > Download as > Comma-separated values(.csv,currentsheet)') - print("If the link did not open, please go to", surl) - print("Press any key to continue") - #time.sleep(45) - ''' - for i in range(60, 0, -1): - print(i, end='\r') - time.sleep(1) - ''' - waiting = True - while waiting == True: - if msvcrt.kbhit(): - waiting = False - - print("e") - - #val = worksheet.acell('A1').value - #print(val) - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/main.py b/main.py index 138b810..2805c5b 100644 --- a/main.py +++ b/main.py @@ -1,55 +1,509 @@ # main.py # Andrew Dinh -# Python 3.6.1 -# Description: -''' -Asks users for mutual funds/stocks to compare -Asks to be compared (expense ratio, turnover, market capitalization, or persistence) -Asks for time period (Possibly: 1 year, 5 years, 10 years) -Makes the mutual funds as class Stock -Gets data from each API -Compare and contrast dates and end changeOverTime for set time period - NOTES: Later can worry about getting close values to make a graph or something -Gives correlation value using equation at the end (from 0 to 1) +# Python 3.6.7 -FIRST TESTING WITH EXPENSE RATIO +import requests +import json +import datetime +import numpy +import Functions + +# API Keys +apiAV = 'O42ICUV58EIZZQMU' +# apiBarchart = 'a17fab99a1c21cd6f847e2f82b592838' +apiBarchart = 'f40b136c6dc4451f9136bb53b9e70ffa' +apiTiingo = '2e72b53f2ab4f5f4724c5c1e4d5d4ac0af3f7ca8' +apiTradier = 'n26IFFpkOFRVsB5SNTVNXicE5MPD' +# If you're going to take these API keys and abuse it, you should really reconsider your life priorities + +''' +API Keys: + Alpha Vantage API Key: O42ICUV58EIZZQMU + Barchart API Key: a17fab99a1c21cd6f847e2f82b592838 + Possible other one? f40b136c6dc4451f9136bb53b9e70ffa + 150 getHistory queries per day + Tiingo API Key: 2e72b53f2ab4f5f4724c5c1e4d5d4ac0af3f7ca8 + Tradier API Key: n26IFFpkOFRVsB5SNTVNXicE5MPD + Monthly Bandwidth = 5 GB + Hourly Requests = 500 + Daily Requests = 20,000 + Symbol Requests = 500 + + Mutual funds: + Yes: Alpha Vantage, Tiingo + No: IEX, Barchart ''' + +class Stock: + + # GLOBAL VARIABLES + timeFrame = [] + benchmarkDates = [] + benchmarkCloseValues = [] + benchmarkUnadjustedReturn = 0 + + def __init__(self): + # BASIC DATA + self.name = '' # Ticker symbol + self.allDates = [] + self.allCloseValues = [] + self.dates = [] + self.closeValues = [] + self.datesMatchBenchmark = [] + self.closeValuesMatchBenchmark = [] + + # CALCULATED RETURN + self.unadjustedReturn = 0 + self.sortino = 0 + self.sharpe = 0 + self.treynor = 0 + self.alpha = 0 + self.beta = 0 + self.standardDeviation = 0 + self.negStandardDeviation = 0 + + # INDICATOR VALUES + self.expenseRatio = 0 + self.assetSize = 0 + self.turnover = 0 + self.persistence = [] # [Years, Months] + + # CALCULATED VALUES FOR INDICATORS + self.correlation = 0 + self.regression = 0 + + def setName(self, newName): + self.name = newName + + def getName(self): + return self.name + + def getAllDates(self): + return self.allDates + + def getAllCloseValues(self): + return self.allCloseValues + + def IEX(self): + print('IEX') + url = ''.join( + ('https://api.iextrading.com/1.0/stock/', self.name, '/chart/5y')) + #link = "https://api.iextrading.com/1.0/stock/spy/chart/5y" + print("\nSending request to:", url) + f = requests.get(url) + json_data = f.text + if json_data == 'Unknown symbol' or f.status_code == 404: + print("IEX not available") + return 'Not available' + loaded_json = json.loads(json_data) + listIEX = [] + + print("\nFinding all dates given") + allDates = [] + for i in range(0, len(loaded_json), 1): # If you want to do oldest first + # for i in range(len(loaded_json)-1, -1, -1): + line = loaded_json[i] + date = line['date'] + allDates.append(date) + listIEX.append(allDates) + print(len(listIEX[0]), "dates") + + print("\nFinding close values for each date") + values = [] + for i in range(0, len(loaded_json), 1): # If you want to do oldest first + # for i in range(len(loaded_json)-1, -1, -1): + line = loaded_json[i] + value = line['close'] + values.append(value) + listIEX.append(values) + print(len(listIEX[1]), "close values") + + return listIEX + + def AV(self): + print('Alpha Vantage') + listAV = [] + url = ''.join(('https://www.alphavantage.co/query?function=TIME_SERIES_DAILY_ADJUSTED&symbol=', + self.name, '&outputsize=full&apikey=', apiAV)) + # https://www.alphavantage.co/query?function=TIME_SERIES_DAILY_ADJUSTED&symbol=MSFT&outputsize=full&apikey=demo + + print("\nSending request to:", url) + print("(This will take a while)") + f = requests.get(url) + json_data = f.text + loaded_json = json.loads(json_data) + + if len(loaded_json) == 1 or f.status_code == 404: + print("Alpha Vantage not available") + return 'Not available' + + dailyTimeSeries = loaded_json['Time Series (Daily)'] + listOfDates = list(dailyTimeSeries) + # listAV.append(listOfDates) + listAV.append(list(reversed(listOfDates))) + + print("\nFinding close values for each date") + values = [] + for i in range(0, len(listOfDates), 1): + temp = listOfDates[i] + loaded_json2 = dailyTimeSeries[temp] + #value = loaded_json2['4. close'] + value = loaded_json2['5. adjusted close'] + values.append(value) + # listAV.append(values) + listAV.append(list(reversed(values))) + print(len(listAV[1]), "close values") + + return listAV + + def Tiingo(self): + print('Tiingo') + token = ''.join(('Token ', apiTiingo)) + headers = { + 'Content-Type': 'application/json', + 'Authorization': token + } + url = ''.join(('https://api.tiingo.com/tiingo/daily/', self.name)) + print("\nSending request to:", url) + f = requests.get(url, headers=headers) + loaded_json = f.json() + if len(loaded_json) == 1 or f.status_code == 404: + print("Tiingo not available") + return 'Not available' + + listTiingo = [] + + print("\nFinding first and last date") + firstDate = loaded_json['startDate'] + lastDate = loaded_json['endDate'] + print(firstDate, '...', lastDate) + + print("\nFinding all dates given", end='') + dates = [] + values = [] + url2 = ''.join((url, '/prices?startDate=', + firstDate, '&endDate=', lastDate)) + # https://api.tiingo.com/tiingo/daily//prices?startDate=2012-1-1&endDate=2016-1-1 + print("\nSending request to:", url2, '\n') + requestResponse2 = requests.get(url2, headers=headers) + loaded_json2 = requestResponse2.json() + for i in range(0, len(loaded_json2)-1, 1): + line = loaded_json2[i] + dateWithTime = line['date'] + temp = dateWithTime.split('T00:00:00.000Z') + date = temp[0] + dates.append(date) + + value = line['close'] + values.append(value) + listTiingo.append(dates) + print(len(listTiingo[0]), "dates") + + print("Finding close values for each date") + # Used loop from finding dates + listTiingo.append(values) + print(len(listTiingo[1]), "close values") + + return listTiingo + + def datesAndClose(self): + print('\n', Stock.getName(self), sep='') + + # sourceList = ['AV', 'Tiingo', 'IEX'] # Change back to this later + sourceList = ['Tiingo', 'IEX', 'AV'] + # Use each source until you get a value + for j in range(0, len(sourceList), 1): + source = sourceList[j] + print('\nSource being used: ', source) + + if source == 'AV': + datesAndCloseList = Stock.AV(self) + elif source == 'Tiingo': + datesAndCloseList = Stock.Tiingo(self) + elif source == 'IEX': + datesAndCloseList = Stock.IEX(self) + + if datesAndCloseList != 'Not available': + break + else: + #print(sourceList[j], 'does not have data available') + if j == len(sourceList)-1: + print('\nNo sources have data for', self.name) + return + # FIGURE OUT WHAT TO DO HERE + + # Convert dates to datetime + allDates = datesAndCloseList[0] + for j in range(0, len(allDates), 1): + allDates[j] = Functions.stringToDate(allDates[j]) + datesAndCloseList[0] = allDates + + return datesAndCloseList + + def datesAndClose2(self): + print('Shortening list to fit time frame') + # Have to do this because if I just make dates = self.allDates & closeValues = self.allCloseValues, then deleting from dates & closeValues also deletes it from self.allDates & self.allCloseValues (I'm not sure why) + dates = [] + closeValues = [] + for i in range(0, len(self.allDates), 1): + dates.append(self.allDates[i]) + closeValues.append(self.allCloseValues[i]) + + firstDate = datetime.datetime.now().date() - datetime.timedelta( + days=self.timeFrame[0]*365) - datetime.timedelta(days=self.timeFrame[1]*30) + print('\n', self.timeFrame[0], ' years and ', + self.timeFrame[1], ' months ago: ', firstDate, sep='') + closestDate = Functions.getNearest(dates, firstDate) + if closestDate != firstDate: + print('Closest date available for', self.name, ':', closestDate) + firstDate = closestDate + else: + print(self.name, 'has a close value for', firstDate) + + # Remove dates in list up to firstDate + while dates[0] != firstDate: + dates.remove(dates[0]) + + # Remove close values until list is same length as dates + while len(closeValues) != len(dates): + closeValues.remove(closeValues[0]) + + datesAndCloseList2 = [] + datesAndCloseList2.append(dates) + datesAndCloseList2.append(closeValues) + + print(len(dates), 'dates') + print(len(closeValues), 'close values') + + return datesAndCloseList2 + + def unadjustedReturn(self): + unadjustedReturn = (float(self.closeValues[len( + self.closeValues)-1]/self.closeValues[0])**(1/(self.timeFrame[0]+(self.timeFrame[1])*.1)))-1 + print('Annual unadjusted return:', unadjustedReturn) + return unadjustedReturn + + def beta(self, benchmarkMatchDatesAndCloseValues): + beta = numpy.corrcoef(self.closeValuesMatchBenchmark, + benchmarkMatchDatesAndCloseValues[1])[0, 1] + print('Beta:', beta) + return beta + + +def isConnected(): + import socket # To check 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!') + return True + except OSError: + # pass + print("No internet connection!") + return False + + +def checkPackages(): + import importlib.util + import sys + + packagesInstalled = True + packages = ['requests', 'numpy'] + for i in range(0, len(packages), 1): + package_name = packages[i] + spec = importlib.util.find_spec(package_name) + if spec is None: + print( + package_name + + " is not installed\nPlease type in 'pip install -r requirements.txt' to install all required packages") + packagesInstalled = False + return packagesInstalled + + +def benchmarkInit(): + # Treat benchmark like stock + benchmarkTicker = '' + while benchmarkTicker == '': + benchmarks = ['S&P500', 'DJIA', 'Russell 3000', 'MSCI EAFE'] + benchmarksTicker = ['SPY', 'DJIA', 'VTHR', 'EFT'] + print('\nList of benchmarks:', benchmarks) + + # benchmark = str(input('Benchmark to compare to: ')) + benchmark = 'S&P500' + + for i in range(0, len(benchmarks), 1): + if benchmark == benchmarks[i]: + benchmarkTicker = benchmarksTicker[i] + + if benchmarkTicker == '': + print('Benchmark not found. Please type in a benchmark from the list') + + print(benchmark, ' (', benchmarkTicker, ')', sep='') + + benchmark = Stock() + benchmark.setName(benchmarkTicker) + + return benchmark + + +def stocksInit(): + listOfStocks = [] + + # numberOfStocks = int(input('\nHow many stocks/mutual funds/ETFs would you like to analyze? ')) + numberOfStocks = 1 + + print('\nHow many stocks/mutual funds/ETFs would you like to analyze? ', numberOfStocks) + + for i in range(0, numberOfStocks, 1): + print('Stock', i + 1, ': ', end='') + #stockName = str(input()) + + stockName = 'FBGRX' + print(stockName) + + listOfStocks.append(stockName) + listOfStocks[i] = Stock() + listOfStocks[i].setName(stockName) + + return listOfStocks + + +def timeFrameInit(): + print('\nPlease enter the time frame in years and months (30 days)') + print("Years: ", end='') + #years = int(input()) + years = 5 + print(years) + print("Months: ", end='') + #months = int(input()) + months = 0 + print(months) + + timeFrame = [] + timeFrame.append(years) + timeFrame.append(months) + return timeFrame + + +def dataMain(listOfStocks): + print('\nGathering dates and close values') + for i in range(0, len(listOfStocks), 1): + + datesAndCloseList = Stock.datesAndClose(listOfStocks[i]) + listOfStocks[i].allDates = datesAndCloseList[0] + listOfStocks[i].allCloseValues = datesAndCloseList[1] + + # Clip list to fit time frame + datesAndCloseList2 = Stock.datesAndClose2(listOfStocks[i]) + listOfStocks[i].dates = datesAndCloseList2[0] + listOfStocks[i].closeValues = datesAndCloseList2[1] + + +def returnMain(benchmark, listOfStocks): + print('\nCalculating unadjusted return, Sharpe ratio, Sortino ratio, and Treynor ratio\n') + print(benchmark.name) + benchmark.unadjustedReturn = Stock.unadjustedReturn(benchmark) + + # Make benchmark data global + # Maybe remove this later + Stock.benchmarkDates = benchmark.dates + Stock.benchmarkCloseValues = benchmark.closeValues + Stock.benchmarkUnadjustedReturn = benchmark.unadjustedReturn + + for i in range(0, len(listOfStocks), 1): + print(listOfStocks[i].name) + + # Make sure each date has a value for both the benchmark and the stock + list1 = [] + list2 = [] + list1.append(listOfStocks[i].dates) + list1.append(listOfStocks[i].closeValues) + list2.append(Stock.benchmarkDates) + list2.append(Stock.benchmarkCloseValues) + temp = Functions.removeExtraDatesAndCloseValues(list1, list2) + listOfStocks[i].datesMatchBenchmark = temp[0][0] + listOfStocks[i].closeValuesMatchBenchmark = temp[0][1] + benchmarkMatchDatesAndCloseValues = temp[1] + + listOfStocks[i].unadjustedReturn = Stock.unadjustedReturn( + listOfStocks[i]) + listOfStocks[i].beta = Stock.beta( + listOfStocks[i], benchmarkMatchDatesAndCloseValues) + + +def main(): + # Test internet connection + internetConnection = isConnected() + if not internetConnection: + return + + # Check that all required packages are installed + packagesInstalled = checkPackages() + if not packagesInstalled: + return + + # Choose benchmark and makes it class Stock + benchmark = benchmarkInit() + # Add it to a list to work with other functions + benchmarkAsList = [] + benchmarkAsList.append(benchmark) + + # Asks for stock(s) ticker and makes them class Stock + listOfStocks = stocksInit() + + # Determine time frame [Years, Months] + timeFrame = timeFrameInit() + Stock.timeFrame = timeFrame # Needs to be a global variable for all stocks + + # Gather data for benchmark and stock(s) + dataMain(benchmarkAsList) + dataMain(listOfStocks) + + # Calculate return for benchmark and stock(s) + returnMain(benchmark, listOfStocks) + + +if __name__ == "__main__": + main() + + +''' from StockData import StockData from StockReturn import Return listOfStocksData = [] listOfStocksReturn = [] -#numberOfStocks = int(input("How many stocks or mutual funds would you like to analyze? ")) # CHANGE BACK LATER +# numberOfStocks = int(input("How many stocks or mutual funds would you like to analyze? ")) # CHANGE BACK LATER numberOfStocks = 1 for i in range(0, numberOfStocks, 1): - print("Stock", i+1, ": ", end='') - stockName = str(input()) - listOfStocksData.append(i) - listOfStocksData[i] = StockData() - listOfStocksData[i].setName(stockName) - # print(listOfStocksData[i].name) + print("Stock", i+1, ": ", end='') + stockName = str(input()) + listOfStocksData.append(i) + listOfStocksData[i] = StockData() + listOfStocksData[i].setName(stockName) + # print(listOfStocksData[i].name) - #listOfStocksReturn.append(i) - #listOfStocksReturn[i] = StockReturn() + # listOfStocksReturn.append(i) + # listOfStocksReturn[i] = StockReturn() # Decide on a benchmark benchmarkTicker = '' while benchmarkTicker == '': - listOfBenchmarks = ['S&P500', 'DJIA', 'Russell 3000', 'MSCI EAFE'] - listOfBenchmarksTicker = ['SPY', 'DJIA', 'VTHR', 'EFT'] - print('\nList of benchmarks:', listOfBenchmarks) - #benchmark = str(input('Benchmark to compare to: ')) - benchmark = 'S&P500' + listOfBenchmarks = ['S&P500', 'DJIA', 'Russell 3000', 'MSCI EAFE'] + listOfBenchmarksTicker = ['SPY', 'DJIA', 'VTHR', 'EFT'] + print('\nList of benchmarks:', listOfBenchmarks) + # benchmark = str(input('Benchmark to compare to: ')) + benchmark = 'S&P500' - for i in range(0,len(listOfBenchmarks), 1): - if benchmark == listOfBenchmarks[i]: - benchmarkTicker = listOfBenchmarksTicker[i] - i = len(listOfBenchmarks) + for i in range(0,len(listOfBenchmarks), 1): + if benchmark == listOfBenchmarks[i]: + benchmarkTicker = listOfBenchmarksTicker[i] + i = len(listOfBenchmarks) - if benchmarkTicker == '': - print('Benchmark not found. Please type in a benchmark from the list') + if benchmarkTicker == '': + print('Benchmark not found. Please type in a benchmark from the list') print('\n', benchmark, ' (', benchmarkTicker, ')', sep='') @@ -66,10 +520,10 @@ print('Time Frame [years, months]:', timeFrame) sumOfListLengths = 0 for i in range(0, numberOfStocks, 1): - print('\n', listOfStocksData[i].name, sep='') - StockData.main(listOfStocksData[i]) - # Count how many stocks are available - sumOfListLengths = sumOfListLengths + len(StockData.returnAllLists(listOfStocksData[i])) + print('\n', listOfStocksData[i].name, sep='') + StockData.main(listOfStocksData[i]) + # Count how many stocks are available + sumOfListLengths = sumOfListLengths + len(StockData.returnAllLists(listOfStocksData[i])) if sumOfListLengths == 0: print("No sources have data for given stocks") @@ -77,41 +531,40 @@ if sumOfListLengths == 0: # Find return over time using either Jensen's Alpha, Sharpe Ratio, Sortino Ratio, or Treynor Ratio for i in range(0, numberOfStocks, 1): - print('\n', listOfStocksData[i].name, sep='') - #StockReturn.main(listOfStocksReturn[i]) + print('\n', listOfStocksData[i].name, sep='') + # StockReturn.main(listOfStocksReturn[i]) # Runs correlation or regression study # print(listOfStocksData[0].name, listOfStocksData[0].absFirstLastDates, listOfStocksData[0].finalDatesAndClose) indicatorFound = False while indicatorFound == False: - print("1. Expense Ratio\n2. Asset Size\n3. Turnover\n4. Persistence\nWhich indicator would you like to look at? ", end='') - - #indicator = str(input()) # CHANGE BACK TO THIS LATER - indicator = 'Expense Ratio' - print(indicator, end='') + print("1. Expense Ratio\n2. Asset Size\n3. Turnover\n4. Persistence\nWhich indicator would you like to look at? ", end='') - indicatorFound = True - print('\n', end='') + # indicator = str(input()) # CHANGE BACK TO THIS LATER + indicator = 'Expense Ratio' + print(indicator, end='') - if indicator == 'Expense Ratio' or indicator == '1' or indicator == 'expense ratio': - #from ExpenseRatio import ExpenseRatio - print('\nExpense Ratio') + indicatorFound = True + print('\n', end='') - elif indicator == 'Asset Size' or indicator == '2' or indicator == 'asset size': - print('\nAsset Size') + if indicator == 'Expense Ratio' or indicator == '1' or indicator == 'expense ratio': + # from ExpenseRatio import ExpenseRatio + print('\nExpense Ratio') - elif indicator == 'Turnover' or indicator == '3' or indicator == 'turnover': - print('\nTurnover') + elif indicator == 'Asset Size' or indicator == '2' or indicator == 'asset size': + print('\nAsset Size') - elif indicator == 'Persistence' or indicator == '4' or indicator == 'persistence': - print('\nPersistence') + elif indicator == 'Turnover' or indicator == '3' or indicator == 'turnover': + print('\nTurnover') - else: - indicatorFound = False - print('Invalid input, please enter indicator again') + elif indicator == 'Persistence' or indicator == '4' or indicator == 'persistence': + print('\nPersistence') + + else: + indicatorFound = False + print('Invalid input, please enter indicator again') -''' stockName = 'IWV' stock1 = Stock(stockName) print("Finding available dates and close values for", stock1.name) diff --git a/requirements.txt b/requirements.txt index 2bd7352..fe41b2e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -requests==2.21.0 -numpy==1.15.4 \ No newline at end of file +requests~=2.21.0 +numpy~=1.15.4 \ No newline at end of file