mirror of
https://github.com/andrewkdinh/fund-indicators.git
synced 2024-11-21 20:34:21 -08:00
Add async function
This commit is contained in:
parent
d398924c0d
commit
531c41862a
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,6 +1,5 @@
|
|||||||
__pycache__/StockData.cpython-37.pyc
|
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.pyc
|
|
||||||
test/
|
test/
|
||||||
.vscode/
|
.vscode/
|
||||||
requests_cache.sqlite
|
requests_cache.sqlite
|
||||||
|
README.html
|
@ -42,6 +42,7 @@ def stringIsInt(s):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def strintIsFloat(s):
|
def strintIsFloat(s):
|
||||||
try:
|
try:
|
||||||
float(s)
|
float(s)
|
||||||
@ -49,10 +50,13 @@ def strintIsFloat(s):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def fromCache(r):
|
def fromCache(r):
|
||||||
import requests_cache
|
import requests_cache
|
||||||
if r.from_cache == True:
|
if r.from_cache == True:
|
||||||
print('(Response taken from cache)')
|
print('(Response taken from cache)')
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
exit()
|
exit()
|
||||||
|
16
README.md
16
README.md
@ -1,19 +1,25 @@
|
|||||||
# Mutual Fund Indicators
|
# Mutual Fund Indicators
|
||||||
|
|
||||||
A project to determine indicators of overperforming mutual funds.
|
[![License](https://img.shields.io/github/license/andrewkdinh/fund-indicators.svg)](https://raw.githubusercontent.com/andrewkdinh/fund-indicators/master/LICENSE)
|
||||||
This project is written in Python 3 and will examine market capitalization, persistence, turnover, and expense ratios.
|
![](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`
|
`$ pip install -r requirements.txt`
|
||||||
|
|
||||||
### Quickstart
|
## Quickstart
|
||||||
|
|
||||||
To begin, run
|
To begin, run
|
||||||
|
|
||||||
`$ python main.py`
|
`$ python main.py`
|
||||||
|
|
||||||
Some ticker values to try:
|
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
|
Created by Andrew Dinh from Dr. TJ Owens Gilroy Early College Academy
|
||||||
|
80
main.py
80
main.py
@ -4,6 +4,7 @@
|
|||||||
# Python 3.6.7
|
# Python 3.6.7
|
||||||
|
|
||||||
# Required
|
# Required
|
||||||
|
from concurrent.futures import ThreadPoolExecutor as PoolExecutor
|
||||||
import requests
|
import requests
|
||||||
import json
|
import json
|
||||||
import datetime
|
import datetime
|
||||||
@ -16,10 +17,10 @@ import sys
|
|||||||
|
|
||||||
# Optional
|
# Optional
|
||||||
import requests_cache
|
import requests_cache
|
||||||
# https://requests-cache.readthedocs.io/en/lates/user_guide.html
|
|
||||||
requests_cache.install_cache(
|
requests_cache.install_cache(
|
||||||
'requests_cache', backend='sqlite', expire_after=43200) # 12 hours
|
'requests_cache', backend='sqlite', expire_after=43200) # 12 hours
|
||||||
|
|
||||||
|
|
||||||
# API Keys
|
# API Keys
|
||||||
apiAV = 'O42ICUV58EIZZQMU'
|
apiAV = 'O42ICUV58EIZZQMU'
|
||||||
# apiBarchart = 'a17fab99a1c21cd6f847e2f82b592838'
|
# apiBarchart = 'a17fab99a1c21cd6f847e2f82b592838'
|
||||||
@ -119,7 +120,7 @@ class Stock:
|
|||||||
f = requests.get(url)
|
f = requests.get(url)
|
||||||
Functions.fromCache(f)
|
Functions.fromCache(f)
|
||||||
json_data = f.text
|
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")
|
print("IEX not available")
|
||||||
return 'Not available'
|
return 'Not available'
|
||||||
loaded_json = json.loads(json_data)
|
loaded_json = json.loads(json_data)
|
||||||
@ -160,7 +161,7 @@ class Stock:
|
|||||||
json_data = f.text
|
json_data = f.text
|
||||||
loaded_json = json.loads(json_data)
|
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")
|
print("Alpha Vantage not available")
|
||||||
return 'Not available'
|
return 'Not available'
|
||||||
|
|
||||||
@ -195,7 +196,7 @@ class Stock:
|
|||||||
f = requests.get(url, headers=headers)
|
f = requests.get(url, headers=headers)
|
||||||
Functions.fromCache(f)
|
Functions.fromCache(f)
|
||||||
loaded_json = f.json()
|
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")
|
print("Tiingo not available")
|
||||||
return 'Not available'
|
return 'Not available'
|
||||||
|
|
||||||
@ -497,11 +498,11 @@ def datesToDays(dates):
|
|||||||
|
|
||||||
def isConnected():
|
def isConnected():
|
||||||
import socket # To check internet connection
|
import socket # To check internet connection
|
||||||
print('Checking internet connection')
|
#print('Checking internet connection')
|
||||||
try:
|
try:
|
||||||
# connect to the host -- tells us if the host is actually reachable
|
# connect to the host -- tells us if the host is actually reachable
|
||||||
socket.create_connection(("www.andrewkdinh.com", 80))
|
socket.create_connection(("www.andrewkdinh.com", 80))
|
||||||
print('Internet connection is good!')
|
print('Internet connection is good')
|
||||||
return True
|
return True
|
||||||
except OSError:
|
except OSError:
|
||||||
# pass
|
# pass
|
||||||
@ -526,6 +527,22 @@ def checkPackages():
|
|||||||
return packagesInstalled
|
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():
|
def benchmarkInit():
|
||||||
# Treat benchmark like stock
|
# Treat benchmark like stock
|
||||||
benchmarkTicker = ''
|
benchmarkTicker = ''
|
||||||
@ -601,11 +618,45 @@ def stocksInit():
|
|||||||
return listOfStocks
|
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():
|
def timeFrameInit():
|
||||||
isInteger = False
|
isInteger = False
|
||||||
while isInteger == False:
|
while isInteger == False:
|
||||||
print(
|
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(' ')
|
temp = input(' ')
|
||||||
isInteger = Functions.stringIsInt(temp)
|
isInteger = Functions.stringIsInt(temp)
|
||||||
if isInteger == True:
|
if isInteger == True:
|
||||||
@ -660,7 +711,7 @@ def riskFreeRate():
|
|||||||
riskFreeRate = round(riskFreeRate, 2)
|
riskFreeRate = round(riskFreeRate, 2)
|
||||||
print('Risk-free rate:', riskFreeRate, end='\n\n')
|
print('Risk-free rate:', riskFreeRate, end='\n\n')
|
||||||
|
|
||||||
if f.status_code == 404:
|
if f.status_code != 200:
|
||||||
print("Quandl not available")
|
print("Quandl not available")
|
||||||
print('Returning 2.50 as risk-free rate', end='\n\n')
|
print('Returning 2.50 as risk-free rate', end='\n\n')
|
||||||
# return 0.0250
|
# return 0.0250
|
||||||
@ -950,12 +1001,18 @@ def main():
|
|||||||
packagesInstalled = checkPackages()
|
packagesInstalled = checkPackages()
|
||||||
if not packagesInstalled:
|
if not packagesInstalled:
|
||||||
return
|
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
|
# Choose benchmark and makes it class Stock
|
||||||
benchmark = benchmarkInit()
|
benchmark = benchmarkInit()
|
||||||
# Add it to a list to work with other functions
|
# Add it to a list to work with other functions
|
||||||
benchmarkAsList = []
|
benchmarkAsList = [benchmark]
|
||||||
benchmarkAsList.append(benchmark)
|
|
||||||
|
|
||||||
# Asks for stock(s) ticker and makes them class Stock
|
# Asks for stock(s) ticker and makes them class Stock
|
||||||
listOfStocks = stocksInit()
|
listOfStocks = stocksInit()
|
||||||
@ -964,6 +1021,9 @@ def main():
|
|||||||
timeFrame = timeFrameInit()
|
timeFrame = timeFrameInit()
|
||||||
Stock.timeFrame = timeFrame # Needs to be a global variable for all stocks
|
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)
|
# Gather data for benchmark and stock(s)
|
||||||
dataMain(benchmarkAsList)
|
dataMain(benchmarkAsList)
|
||||||
dataMain(listOfStocks)
|
dataMain(listOfStocks)
|
||||||
|
51
output.bin
51
output.bin
@ -1,51 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
|
||||||
|
|
||||||
<script src="/cdn-cgi/apps/head/GA7wuz-FE88SDVynGgn9Aq5W6rI.js"></script><link rel="apple-touch-icon" sizes="57x57" href="/images/logo/apple-icon-57x57.png">
|
|
||||||
<link rel="apple-touch-icon" sizes="60x60" href="/images/logo/apple-icon-60x60.png">
|
|
||||||
<link rel="apple-touch-icon" sizes="72x72" href="/images/logo/apple-icon-72x72.png">
|
|
||||||
<link rel="apple-touch-icon" sizes="76x76" href="/images/logo/apple-icon-76x76.png">
|
|
||||||
<link rel="apple-touch-icon" sizes="114x114" href="/images/logo/apple-icon-114x114.png">
|
|
||||||
<link rel="apple-touch-icon" sizes="120x120" href="/images/logo/apple-icon-120x120.png">
|
|
||||||
<link rel="apple-touch-icon" sizes="144x144" href="/images/logo/apple-icon-144x144.png">
|
|
||||||
<link rel="apple-touch-icon" sizes="152x152" href="/images/logo/apple-icon-152x152.png">
|
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/images/logo/apple-icon-180x180.png">
|
|
||||||
<link rel="icon" type="image/png" sizes="192x192" href="/images/logo/android-icon-192x192.png">
|
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="/images/logo/favicon-32x32.png">
|
|
||||||
<link rel="icon" type="image/png" sizes="96x96" href="/images/logo/favicon-96x96.png">
|
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="/images/logo/favicon-16x16.png">
|
|
||||||
<link rel="manifest" href="/manifest.json">
|
|
||||||
<meta name="msapplication-TileColor" content="#ffffff">
|
|
||||||
<meta name="msapplication-TileImage" content="/images/logo/ms-icon-144x144.png">
|
|
||||||
<meta name="theme-color" content="#ffffff">
|
|
||||||
|
|
||||||
<title>Andrew Dinh</title>
|
|
||||||
<meta name="description" content="Andrew Dinh is a young professional delving into the world of computer science to expand financial literacy." />
|
|
||||||
<meta name="keywords" content="Andrew Dinh, Andrew K Dinh, Gilroy, GECA, Gavilan College, Dr. TJ Owens Gilroy Early College Academy, computer science" />
|
|
||||||
|
|
||||||
<meta property="og:title" content="Andrew Dinh" />
|
|
||||||
<meta property="og:description" content="A young professional delving into the world of computer science to expand financial literacy" />
|
|
||||||
<meta property="og:image" content="/images/profile.jpg" />
|
|
||||||
|
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
||||||
|
|
||||||
<script>(function(a,b,c){if(c in b&&b[c]){var d,e=a.location,f=/^(a|html)$/i;a.addEventListener("click",function(a){d=a.target;while(!f.test(d.nodeName))d=d.parentNode;"href"in d&&(chref=d.href).replace(e.href,"").indexOf("#")&&(!/^[a-z\+\.\-]+:/i.test(chref)||chref.indexOf(e.protocol+"//"+e.host)===0)&&(a.preventDefault(),e.href=d.href)},!1)}})(document,window.navigator,"standalone");</script>
|
|
||||||
|
|
||||||
|
|
||||||
<script> function myFunction() {var x = document.getElementById("myTopnav");if (x.className === "topnav") {x.className += " responsive";} else {x.className = "topnav";}}</script>
|
|
||||||
|
|
||||||
<script>window.onload=function(){function a(a,b){var c=/^(?:file):/,d=new XMLHttpRequest,e=0;d.onreadystatechange=function(){4==d.readyState&&(e=d.status),c.test(location.href)&&d.responseText&&(e=200),4==d.readyState&&200==e&&(a.outerHTML=d.responseText)};try{d.open("GET",b,!0),d.send()}catch(f){}}var b,c=document.getElementsByTagName("*");for(b in c)c[b].hasAttribute&&c[b].hasAttribute("data-include")&&a(c[b],c[b].getAttribute("data-include"))};</script>
|
|
||||||
|
|
||||||
<link rel="stylesheet preload" title="classic" href="/css/general.css" media="screen" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<div data-include="/html/menu.html"></div>
|
|
||||||
<main>
|
|
||||||
</main>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
Loading…
Reference in New Issue
Block a user