mirror of
https://github.com/andrewkdinh/fund-indicators.git
synced 2024-11-21 14:34:20 -08:00
Last commit
This commit is contained in:
parent
5423e4e281
commit
765b1f4012
10
README.md
10
README.md
@ -1,23 +1,17 @@
|
|||||||
# Mutual Fund Indicators
|
# Mutual Fund Indicators
|
||||||
|
|
||||||
A project to determine indicators of overperforming mutual funds.
|
A project to determine indicators of overperforming mutual funds.
|
||||||
This project is written in Python and will examine market capitalization, persistence, turnover, and expense ratios.
|
This project is written in Python 3 and will examine market capitalization, persistence, turnover, and expense ratios.
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
`$ pip install -r requirements.txt`
|
`$ pip install -r requirements.txt`
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
`$ pip install requests`
|
|
||||||
|
|
||||||
`$ pip install numpy`
|
|
||||||
|
|
||||||
### Quickstart
|
### Quickstart
|
||||||
|
|
||||||
To begin, run
|
To begin, run
|
||||||
|
|
||||||
`$ python(3) main.py`
|
`$ python main.py`
|
||||||
|
|
||||||
Some ticker values to try:
|
Some ticker values to try:
|
||||||
SPY, VFINX, AAPL, GOOGL
|
SPY, VFINX, AAPL, GOOGL
|
||||||
|
@ -477,6 +477,8 @@ class StockData:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def main(self):
|
def main(self):
|
||||||
|
print('Beginning StockData.py')
|
||||||
|
|
||||||
import importlib.util, sys # To check whether a package is installed
|
import importlib.util, sys # To check whether a package is installed
|
||||||
|
|
||||||
packages = ['requests']
|
packages = ['requests']
|
||||||
@ -495,6 +497,7 @@ class StockData:
|
|||||||
self.allLists = []
|
self.allLists = []
|
||||||
|
|
||||||
print('\nNOTE: Only IEX and Alpha Vantage support adjusted returns')
|
print('\nNOTE: Only IEX and Alpha Vantage support adjusted returns')
|
||||||
|
print('NOTE: Only Alpha Vantage and Tiingo support mutual fund data')
|
||||||
|
|
||||||
# IEX
|
# IEX
|
||||||
print("\nIEX")
|
print("\nIEX")
|
||||||
@ -526,7 +529,7 @@ class StockData:
|
|||||||
#print(self.allLists)
|
#print(self.allLists)
|
||||||
#print(listOfFirstLastDates)
|
#print(listOfFirstLastDates)
|
||||||
if (len(self.allLists) > 0):
|
if (len(self.allLists) > 0):
|
||||||
print("\n")
|
print("\n", end='')
|
||||||
print(len(self.allLists), "available source(s) for", self.name)
|
print(len(self.allLists), "available source(s) for", self.name)
|
||||||
self.absFirstLastDates = StockData.getFirstLastDate(self, listOfFirstLastDates)
|
self.absFirstLastDates = StockData.getFirstLastDate(self, listOfFirstLastDates)
|
||||||
print("\nThe absolute first date with close values is:", self.absFirstLastDates[0])
|
print("\nThe absolute first date with close values is:", self.absFirstLastDates[0])
|
||||||
@ -541,7 +544,7 @@ class StockData:
|
|||||||
print(len(finalDates), "unique dates:", finalDates[len(finalDates)-1], "...", finalDates[0])
|
print(len(finalDates), "unique dates:", finalDates[len(finalDates)-1], "...", finalDates[0])
|
||||||
print(len(finalClose), "close values:", finalClose[len(finalClose)-1], "...", finalClose[0])
|
print(len(finalClose), "close values:", finalClose[len(finalClose)-1], "...", finalClose[0])
|
||||||
|
|
||||||
print("\nConverting list of final dates to datetime")
|
print("\nConverting list of final dates to datetime\n")
|
||||||
self.finalDatesAndClose2 = StockData.datetimeDates(self)
|
self.finalDatesAndClose2 = StockData.datetimeDates(self)
|
||||||
#print(self.finalDatesAndClose2[0][0])
|
#print(self.finalDatesAndClose2[0][0])
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
# Description:
|
# Description:
|
||||||
'''
|
'''
|
||||||
Calculates return for each stock from the lists from ExpenseRatio.py
|
Calculates return for each stock from the lists from ExpenseRatio.py
|
||||||
listOfReturn = [Unadjsted Return, Sharpe Ratio, Sortino Ratio, Treynor Ratio, Jensen's Alpha]
|
listOfReturn = [Unadjusted Return, Sharpe Ratio, Sortino Ratio, Treynor Ratio, Jensen's Alpha]
|
||||||
'''
|
'''
|
||||||
|
|
||||||
from StockData import StockData
|
from StockData import StockData
|
||||||
@ -14,7 +14,7 @@ from Functions import Functions
|
|||||||
class Return:
|
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.listOfReturn = newListOfReturn
|
||||||
self.timeFrame = newTimeFrame # [year, months (30 days)]
|
self.timeFrame = newTimeFrame # [years, months (30 days)]
|
||||||
self.beta = newBeta
|
self.beta = newBeta
|
||||||
self.standardDeviation = newStandardDeviation
|
self.standardDeviation = newStandardDeviation
|
||||||
self.negativeStandardDeviation = newNegativeStandardDeviation
|
self.negativeStandardDeviation = newNegativeStandardDeviation
|
||||||
@ -23,6 +23,12 @@ class Return:
|
|||||||
self.sizeOfNeg = newSizeOfNeg
|
self.sizeOfNeg = newSizeOfNeg
|
||||||
self.firstLastDates = newFirstLastDates
|
self.firstLastDates = newFirstLastDates
|
||||||
|
|
||||||
|
def returnTimeFrame(self):
|
||||||
|
return self.timeFrame
|
||||||
|
|
||||||
|
def setTimeFrame(self, newTimeFrame):
|
||||||
|
self.timeFrame = newTimeFrame
|
||||||
|
|
||||||
def getFirstLastDates(self, stock):
|
def getFirstLastDates(self, stock):
|
||||||
firstLastDates = []
|
firstLastDates = []
|
||||||
timeFrame = self.timeFrame
|
timeFrame = self.timeFrame
|
||||||
@ -77,7 +83,6 @@ class Return:
|
|||||||
|
|
||||||
def getUnadjustedReturn(self, stock):
|
def getUnadjustedReturn(self, stock):
|
||||||
finalDatesAndClose = StockData.returnFinalDatesAndClose(stock)
|
finalDatesAndClose = StockData.returnFinalDatesAndClose(stock)
|
||||||
finalDatesAndClose2 = StockData.returnFinalDatesAndClose2(stock)
|
|
||||||
firstDate = self.firstLastDates[0]
|
firstDate = self.firstLastDates[0]
|
||||||
lastDate = self.firstLastDates[1]
|
lastDate = self.firstLastDates[1]
|
||||||
finalDates = finalDatesAndClose[0]
|
finalDates = finalDatesAndClose[0]
|
||||||
@ -91,15 +96,34 @@ class Return:
|
|||||||
i = len(finalDates)
|
i = len(finalDates)
|
||||||
|
|
||||||
print('Close values:', firstClose, '...', lastClose)
|
print('Close values:', firstClose, '...', lastClose)
|
||||||
unadjustedReturn = float(lastClose/firstClose)
|
fullUnadjustedReturn = float(lastClose/firstClose)
|
||||||
unadjustedReturn = unadjustedReturn * 100
|
unadjustedReturn = fullUnadjustedReturn**(1/(self.timeFrame[0]+(self.timeFrame[1])*.1))
|
||||||
return unadjustedReturn
|
return unadjustedReturn
|
||||||
|
|
||||||
# def getBeta(self, timeFrame):
|
def getBeta(self):
|
||||||
|
# Can be calculated with correlation
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
finalDatesAndClose = StockData.returnFinalDatesAndClose(stock)
|
||||||
|
firstDate = self.firstLastDates[0]
|
||||||
|
lastDate = self.firstLastDates[1]
|
||||||
|
finalDates = finalDatesAndClose[0]
|
||||||
|
finalClose = finalDatesAndClose[1]
|
||||||
|
|
||||||
|
for i in range(0, len(finalDates), 1):
|
||||||
|
if finalDates[i] == str(firstDate):
|
||||||
|
firstClose = finalClose[i]
|
||||||
|
55ggbh
|
||||||
|
#list1 =
|
||||||
|
list2 = [1,2,4,1]
|
||||||
|
|
||||||
|
print(numpy.corrcoef(list1, list2)[0, 1])
|
||||||
|
|
||||||
# def getStandardDeviation(self, timeFrame):
|
# def getStandardDeviation(self, timeFrame):
|
||||||
|
|
||||||
def main(self, stock):
|
def mainBenchmark(self, stock):
|
||||||
|
print('Beginning StockReturn.py')
|
||||||
|
|
||||||
# Find date to start from and last date
|
# Find date to start from and last date
|
||||||
self.timeFrame = []
|
self.timeFrame = []
|
||||||
self.listOfReturn = []
|
self.listOfReturn = []
|
||||||
@ -125,8 +149,31 @@ class Return:
|
|||||||
print('\nGetting unadjusted return')
|
print('\nGetting unadjusted return')
|
||||||
unadjustedReturn = Return.getUnadjustedReturn(self, stock)
|
unadjustedReturn = Return.getUnadjustedReturn(self, stock)
|
||||||
self.listOfReturn.append(unadjustedReturn)
|
self.listOfReturn.append(unadjustedReturn)
|
||||||
print(self.listOfReturn[0])
|
print('Average annual return for the past', self.timeFrame[0], 'years and', self.timeFrame[1], 'months: ', end='')
|
||||||
print(self.listOfReturn[0]/timeFrameYear, '%')
|
print((self.listOfReturn[0]-1)*100, '%', sep='')
|
||||||
|
|
||||||
|
|
||||||
|
def main(self, stock):
|
||||||
|
print('Beginning StockReturn.py')
|
||||||
|
|
||||||
|
# Find date to start from and last date
|
||||||
|
self.listOfReturn = []
|
||||||
|
|
||||||
|
self.firstLastDates = Return.getFirstLastDates(self, stock)
|
||||||
|
print('Dates: ', self.firstLastDates)
|
||||||
|
|
||||||
|
print('\nMaking sure dates are within list...')
|
||||||
|
self.firstLastDates = Return.getFirstLastDates2(self, stock)
|
||||||
|
print('New dates: ', self.firstLastDates)
|
||||||
|
|
||||||
|
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((self.listOfReturn[0]-1)*100, '%', sep='')
|
||||||
|
|
||||||
|
#print('\nGetting beta')
|
||||||
|
#beta = Return.getBeta(self, stock)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
stockName = 'spy'
|
stockName = 'spy'
|
||||||
@ -135,6 +182,8 @@ def main():
|
|||||||
StockData.main(stock1)
|
StockData.main(stock1)
|
||||||
|
|
||||||
stock1Return = Return()
|
stock1Return = Return()
|
||||||
|
Return.setTimeFrame(stock1Return, [5, 0])
|
||||||
|
|
||||||
Return.main(stock1Return, stock1)
|
Return.main(stock1Return, stock1)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
73
main.py
73
main.py
@ -16,40 +16,83 @@ FIRST TESTING WITH EXPENSE RATIO
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
from StockData import StockData
|
from StockData import StockData
|
||||||
|
from StockReturn import Return
|
||||||
|
|
||||||
listOfStocks = []
|
listOfStocksData = []
|
||||||
numberOfStocks = int(input("How many stocks or mutual funds would you like to analyze? "))
|
listOfStocksReturn = []
|
||||||
|
#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):
|
for i in range(0, numberOfStocks, 1):
|
||||||
print("Stock", i+1, ": ", end='')
|
print("Stock", i+1, ": ", end='')
|
||||||
stockName = str(input())
|
stockName = str(input())
|
||||||
listOfStocks.append(i)
|
listOfStocksData.append(i)
|
||||||
listOfStocks[i] = StockData()
|
listOfStocksData[i] = StockData()
|
||||||
listOfStocks[i].setName(stockName)
|
listOfStocksData[i].setName(stockName)
|
||||||
#print(listOfStocks[i].name)
|
# print(listOfStocksData[i].name)
|
||||||
|
|
||||||
|
#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'
|
||||||
|
|
||||||
|
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')
|
||||||
|
|
||||||
|
print('\n', benchmark, ' (', benchmarkTicker, ')', sep='')
|
||||||
|
|
||||||
|
benchmarkName = str(benchmark)
|
||||||
|
benchmark = StockData()
|
||||||
|
benchmark.setName(benchmarkName)
|
||||||
|
StockData.main(benchmark)
|
||||||
|
|
||||||
|
benchmarkReturn = Return()
|
||||||
|
Return.mainBenchmark(benchmarkReturn, benchmark)
|
||||||
|
|
||||||
|
timeFrame = Return.returnTimeFrame(benchmarkReturn)
|
||||||
|
print('Time Frame [years, months]:', timeFrame)
|
||||||
|
|
||||||
sumOfListLengths = 0
|
sumOfListLengths = 0
|
||||||
for i in range(0, numberOfStocks, 1):
|
for i in range(0, numberOfStocks, 1):
|
||||||
print(listOfStocks[i].name)
|
print('\n', listOfStocksData[i].name, sep='')
|
||||||
StockData.main(listOfStocks[i])
|
StockData.main(listOfStocksData[i])
|
||||||
# Count how many stocks are available
|
# Count how many stocks are available
|
||||||
temp = StockData.returnAllLists(listOfStocks[i])
|
sumOfListLengths = sumOfListLengths + len(StockData.returnAllLists(listOfStocksData[i]))
|
||||||
sumOfListLengths = sumOfListLengths + len(temp)
|
|
||||||
|
|
||||||
if sumOfListLengths == 0:
|
if sumOfListLengths == 0:
|
||||||
print("No sources have data for given stocks")
|
print("No sources have data for given stocks")
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
# Find return over time using either Jensen's Alpha, Sharpe Ratio, Sortino Ratio, or Treynor Ratio
|
# Find return over time using either Jensen's Alpha, Sharpe Ratio, Sortino Ratio, or Treynor Ratio
|
||||||
#from StockReturn import Return
|
for i in range(0, numberOfStocks, 1):
|
||||||
|
print('\n', listOfStocksData[i].name, sep='')
|
||||||
|
#StockReturn.main(listOfStocksReturn[i])
|
||||||
|
|
||||||
|
|
||||||
# Runs correlation or regression study
|
# Runs correlation or regression study
|
||||||
#print(listOfStocks[0].name, listOfStocks[0].absFirstLastDates, listOfStocks[0].finalDatesAndClose)
|
# print(listOfStocksData[0].name, listOfStocksData[0].absFirstLastDates, listOfStocksData[0].finalDatesAndClose)
|
||||||
indicatorFound = False
|
indicatorFound = False
|
||||||
while indicatorFound == False:
|
while indicatorFound == False:
|
||||||
print("\n1. Expense Ratio\n2. Asset Size\n3. Turnover\n4. Persistence\nWhich indicator would you like to look at? ", end='')
|
print("1. Expense Ratio\n2. Asset Size\n3. Turnover\n4. Persistence\nWhich indicator would you like to look at? ", end='')
|
||||||
indicator = str(input())
|
|
||||||
|
#indicator = str(input()) # CHANGE BACK TO THIS LATER
|
||||||
|
indicator = 'Expense Ratio'
|
||||||
|
print(indicator, end='')
|
||||||
|
|
||||||
indicatorFound = True
|
indicatorFound = True
|
||||||
|
print('\n', end='')
|
||||||
|
|
||||||
if indicator == 'Expense Ratio' or indicator == '1' or indicator == 'expense ratio':
|
if indicator == 'Expense Ratio' or indicator == '1' or indicator == 'expense ratio':
|
||||||
#from ExpenseRatio import ExpenseRatio
|
#from ExpenseRatio import ExpenseRatio
|
||||||
@ -66,7 +109,7 @@ while indicatorFound == False:
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
indicatorFound = False
|
indicatorFound = False
|
||||||
print('\nInvalid input, please enter indicator again')
|
print('Invalid input, please enter indicator again')
|
||||||
|
|
||||||
'''
|
'''
|
||||||
stockName = 'IWV'
|
stockName = 'IWV'
|
||||||
|
Loading…
Reference in New Issue
Block a user