My goal is to have a window with the latest quote of a stock updating during the day. I chose alpha_vantage
as a quote source, pysimplegui
to create the window and twisted to run a loop to update the window every minute. The code works as written, prints the correct quote and change, creates the window as desired, but the window does not update.
Why doesn't the window update?
from alpha_vantage.timeseries import TimeSeries
from twisted.internet import task, reactor
import PySimpleGUI as sg
def paintQuote():
quote, quote_meta = av.get_intraday(symbol='spy', interval = '1min')
last = quote.iloc[-1][3]
print('{0:6.2f}'.format(last))
change = (last / yesterday - 1) * 100
print('{0:4.2f}%'.format(change))
event, values = window.read()
window['quote'].update(last)
# window color
sg.theme('BluePurple')
# window layout
layout = [[sg.Text('last price', size=(20, 2), justification='center')],
[sg.Text(''), sg.Text(size=(24,1), key='quote')]]
# create window
window = sg.Window('MikeQuote', layout)
wait = 60.0
av = TimeSeries(key ='your_key', output_format = 'pandas')
yest, yest_meta = av.get_daily(symbol='spy')
yesterday = yest.iloc[-2][3]
loop = task.LoopingCall(paintQuote)
loop.start(wait)
reactor.run()
window.close()
Answer:
Your script is not calling paintQuote
more than once. Add print lines in there and you'll see it never calls it more than once.
Suggested solutions:
I don't know much about that reactor
or loopingCall
thing or how it works. A simpler solution is just to use a while loop with a sleep in it. Here is my solution that seemed to work well:
import PySimpleGUI as sg
from alpha_vantage.timeseries import TimeSeries
import time
sg.theme('BluePurple')
layout = [[sg.Text('Last Price', size=(20, 2), justification='center')],
[sg.Text('', size=(10, 2), font=('Helvetica', 20),
justification='center', key='quote')]]
window = sg.Window('MikeQuote', layout)
av = TimeSeries(key = 'key')
spy, _ = av.get_quote_endpoint(symbol='SPY')
last = spy['05. price']
yest = spy['08. previous close']
wait = 1 # Wait is in seconds
while True:
event, values = window.read(timeout=10)
if event in (None, 'Quit'):
break
spy, _ = av.get_quote_endpoint(symbol='SPY')
last = spy['05. price']
window['quote'].update(last)
time.sleep(wait)
I added a few tweaks including:
Calling just the "GLOBAL_QUOTE" endpoint (so you're not returning the entire massive intraday dataset)
Remove twisted
package for a simple while loop with a time.sleep
function.
Added a 'Quit' event so it actually stop when you close the window.
Removed the paintQuote()
function. I think clean code ideally would have this function not removed, but you can add it back in however you like.
Removed the pandas integration. You're not dealing with massive data manipulation so it's easier and faster to just use the JSON format.