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() print(weather) 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))