fintic-tracker/api_caller.py
2021-06-02 21:16:15 +01:00

368 lines
12 KiB
Python

import finnhub
import time
import csv
import pytz
from datetime import datetime
import json
import datetime as dt
import sys, os, base64, hashlib, hmac, select
import requests
from pycoingecko import CoinGeckoAPI
from newsapi import NewsApiClient
def getInput(Block=False):
if Block or select.select([sys.stdin], [], [], 0) == ([sys.stdin], [], []):
msg = sys.stdin.read(1)
#sys.stdin.flush()
else:
msg = ''
return msg
def readCSV(file_path, max_stocks):
symbols = []
stock_info = {}
f = open(file_path, 'r')
CSV = csv.reader(f)
next(CSV)
i = 0
for row in CSV:
if i < max_stocks:
i += 1
try:
symbol, current_price, opening_price = row
symbols.append(symbol)
stock_info[symbol] = [current_price, opening_price]
except:
symbol = row[0]
symbols.append(symbol)
stock_info[symbol] = []
else:
print('max stocks exceeded')
break
f.close()
return symbols, stock_info
def readCryptoCSV(file_path, max_stocks):
symbols = []
names = []
stock_info = {}
f = open(file_path, 'r')
CSV = csv.reader(f)
next(CSV)
i = 0
unique_bases = []
for row in CSV:
print(row)
if i < max_stocks:
i += 1
try:
symbol, name, base, current_price, opening_price = row
symbols.append(symbol)
names.append(name)
stock_info[name] = [symbol, base, current_price, opening_price]
if base not in unique_bases:
unique_bases.append(base)
except:
symbol, name, base = row
if base not in unique_bases:
unique_bases.append(base)
symbols.append(symbol)
names.append(name)
stock_info[name] = [symbol, base]
else:
print('max stocks exceeded')
break
f.close()
return names, stock_info, unique_bases
def emptyInfo(symbols, stock_info):
update = False
for symbol in symbols:
if len(stock_info[symbol]) == 1: # stock with no info
update = True
return update
def updateUpdate(NY_time):
NY_str = NY_time.strftime("%d/%m/%Y %H:%M:%S")
f = open('csv/last_update.csv', 'w+')
f.write(NY_str + '\n')
f.close()
def updateStockPrices(symbols):
try:
quotes = [finnhubClient.quote(symbol) for symbol in symbols]
current_prices = [quote['c'] for quote in quotes]
opening_prices = [quote['o'] for quote in quotes]
CSV = open('csv/tickers.csv', 'w+')
CSV.write('name,current,opening\n')
for i, symbol in enumerate(symbols):
CSV.write(symbol + ',' + str(current_prices[i]) + ',' + str(opening_prices[i]) + '\n')
CSV.close()
print('API called successfully')
except Exception as e:
print("Could not fetch data - API CALLS REACHED? - Will display old image")
print(e)
apiCalledError = True
def updateStockPricesIEX(symbols):
symbols_str = ','.join(symbols)
method = 'GET'
host = 'https://cloud.iexapis.com/stable'
lastEndpoint = '/tops/last'
querystring = '?symbols=' + symbols_str +'&token='+iexAPIkey
last_request_url = host + lastEndpoint + querystring
print('\nBEGIN REQUEST++++++++++++++++++++++++++++++++++++')
print('Request URL = ' + last_request_url)
last_response = requests.get(last_request_url)
if last_response.status_code == 200:
print('last success')
current_prices = []
for stock in last_response.json():
current_prices.append(stock['price'])
for symbol in symbols:
symbol = 'MSFT'
method = 'GET'
host = 'https://cloud.iexapis.com/stable'
lastEndpoint = '/tops/last'
intradayEndpoint = '/stock/'+ symbol+ '/intraday-prices'
querystring = '?chartIEXOnly=true&token='+iexAPIkey
intraday_request_url = host + intradayEndpoint + querystring
print('\nBEGIN REQUEST++++++++++++++++++++++++++++++++++++')
print('Request URL = ' + intraday_request_url)
intraday_response = requests.get(intraday_request_url)
print('\nRESPONSE++++++++++++++++++++++++++++++++++++')
print('Response code: %d\n' % intraday_response.status_code)
print(intraday_response.text)
for time_point in intraday_response.json():
print(time_point['date'])
print(time_point['open'])
CSV = open('csv/tickers.csv', 'w+')
CSV.write('name,current,opening\n')
for i, symbol in enumerate(symbols):
CSV.write(symbol + ',' + str(current_prices[i]) + ',' + str(opening_prices[i]) + '\n')
CSV.close()
def updateCrypto(coins, coin_info, unique_bases):
response = coingecko_client.get_price(ids=','.join(coins), vs_currencies = unique_bases, include_24hr_change=True)
CSV = open('csv/crypto.csv', 'w+')
CSV.write('symbol,name,base,current,24hr change\n')
for coin in coins:
info = coin_info[coin]
print(info)
CSV.write(info[0] + ',' + coin + ',' + info[1] + ',' +str(response[coin][info[1]]) + ',' + str(response[coin]['usd_24h_change']) + '\n')
CSV.close()
def updateNews():
try:
#load user settings
settings = json.load(open('csv/news_settings.json', 'r'))
print(settings)
headlines = newsapi.get_top_headlines(**settings)
except:
#if no settings just get top headlines
headlines = newsapi.get_top_headlines()
headline_titles = [headline['title'] for headline in headlines['articles']]
headline_sources = [headline['source']['name'] for headline in headlines['articles']]
headline_times = [headline['publishedAt']for headline in headlines['articles']]
CSV = open('csv/news.csv', 'w+')
CSV.write('headline,source,date,time\n')
for i, title in enumerate(headline_titles):
date, time = headline_times[i].split('T')
CSV.write(title.replace(',', '^') + ',' + headline_sources[i] + ',' + date + ',' + time + '\n')
CSV.close()
def updateWeather(location, api_key):
url = "https://api.openweathermap.org/data/2.5/weather?q={}&units=metric&appid={}".format(location, api_key)
r = requests.get(url)
weather = r.json()
current_weather = {}
coords = weather['coord']
lat = coords['lat']
lon = coords['lon']
url = 'https://api.openweathermap.org/data/2.5/onecall?lat={}&units=metric&lon={}&appid={}'.format(lat, lon, api_key)
r = requests.get(url)
current_weather['main_weather'] = weather['weather'][0]['main']
current_weather['description'] = weather['weather'][0]['description']
current_weather['temp'] = weather['main']['temp']
current_weather['min_temp'] = weather['main']['temp_min']
current_weather['max_temp'] = weather['main']['temp_max']
current_weather['feels_like'] = weather['main']['feels_like']
current_weather['humidity'] = weather['main']['humidity']
current_weather['clouds'] = weather['clouds']['all']
current_weather['wind_speed'] = weather['wind']['speed']
current_weather['wind_direction'] = weather['wind']['deg']
current_weather['visibility'] = weather['visibility']
current_weather['uv'] = r.json()['current']['uvi']
json.dump( current_weather, open( "csv/current_weather.json", 'w+' ))
daily_weather = []
daily = r.json()['daily']
for day in daily:
dct = {}
dct['main_weather'] = day['weather'][0]['main']
dct['description'] = day['weather'][0]['description']
dct['min_temp'] = day['temp']['min']
dct['min_temp'] = day['temp']['max']
daily_weather.append(dct)
json.dump( daily_weather, open( "csv/daily_weather.json", 'w+' ))
if __name__ == '__main__':
newsapi = NewsApiClient(api_key='cf08652bd17647b89aaf469a1a8198a9')
finnhubAPIkey = "c24qddqad3ickpckgg80" #Finnhub
finnhubsandboxAPIkey = "sandbox_c24qddqad3ickpckgg8g" #Finnhub
stock_time = 2 #minutes
news_time = 30 #minutes
weather_time = 10 #minutes
# TODO: different update times for stocks, weather and news
finnhubClient = finnhub.Client(api_key=finnhubAPIkey)
max_stocks = 200
iexAPIkey = 'pk_68ef6a15902c41f887f0b544a0ca17cf' #IEX
iexSandboxAPIkey = 'Tpk_0078dff413ef4f979137f7111452dc4b'
#updateStockPricesIEX(symbols)
finnhubClient = finnhub.Client(api_key=finnhubAPIkey)
coingecko_client = CoinGeckoAPI()
NY_zone = pytz.timezone('America/New_York')
NY_time = datetime.now(NY_zone)
opening = NY_time.replace(hour=9, minute=30, second=0, microsecond=0)
closing = NY_time.replace(hour=16, minute=0, second=0, microsecond=0)
NY_time = datetime.now(NY_zone)
symbols, stock_info = readCSV('csv/tickers.csv', max_stocks)
updateStockPrices(symbols)
updateUpdate(NY_time)
coins, coin_info, unique_bases = readCryptoCSV('csv/crypto.csv', max_stocks)
weather_location, weather_key = 'London', 'bd5d5096a5ba30bbcfb57ead42ab3fee'
updateWeather(weather_location, weather_key)
updateCrypto(coins, coin_info, unique_bases)
updateNews()
t = time.time()
logf = open("log.txt", "w")
try:
while True:
msg = getInput()
if msg == 'R' or time.time() - t > stock_time*60:
coins, coin_info, unique_bases = readCryptoCSV('csv/crypto.csv', max_stocks)
updateCrypto(coins, coin_info, unique_bases)
updateNews()
updateWeather(weather_location, weather_key)
NY_time = datetime.now(NY_zone)
symbols, stock_info = readCSV('csv/tickers.csv', max_stocks)
if opening < NY_time < closing and datetime.today().weekday() < 5: # we need to do real time updating
print('market open')
updateStockPrices(symbols)
updateUpdate(NY_time)
elif emptyInfo(symbols, stock_info): # if theres any empty stocks
updateStockPrices(symbols)
updateUpdate(NY_time)
else:
# update if last update was before the previous days closing
f = open('csv/last_update.csv', 'r')
CSV = csv.reader(f)
last_update_str = next(CSV)[0]
last_update = datetime.strptime(last_update_str, "%d/%m/%Y %H:%M:%S")
yday_closing = closing - dt.timedelta(days=1)
yday_str = yday_closing.strftime("%d/%m/%Y %H:%M:%S")
yday_closing = datetime.strptime(yday_str, "%d/%m/%Y %H:%M:%S")
if last_update < yday_closing:
updateStockPrices(symbols)
updateUpdate(NY_time)
t = time.time()
except Exception as e:
logf.write(srt(e))