I was having a conversation with a friend at a small house party one day about how wrong she was regarding the GameStock stock. She firmly believes that the stock will ‘moon’ too far beyond $1000. Maybe all the way to $10,000. Could it go further? As far as she is concerned, it totally could.
Her belief in the stock (not even the company!) was ridiculous enough that I decided to make sure my ridicule was programmatically dished out everyday in the form of a message that tells her just how far away it was from her ludicrous ideas.
The first thing I needed to do was figure out how exactly I was going to do this. I settled on coding it as much as I could in Python. The main reason was because it’s an easy language. However, I learned so much doing this stupid little gag, that I realized the project was a teaching tool too.
Learning, what a concept?
To begin, I knew I needed to get the stock price of GameStop daily. Thankfully, that would be very easy as I was sure I could find an API that gave me free access to stock prices. I was right; not much tension there. Within a few moments of searching, I settled on FinnHub as my stock price provider. Since this was such a small project, their limitations were unproblematic and their Python package was simple to use.
Now that I could easily call their API and get the stock price, I needed to get a method of sending a message. But what kind of message? I couldn’t do a Discord message as that would be against their EULA and get me banned. I also couldn’t do a Twitter bot as my friend isn’t on Twitter. Instagram wouldn’t make sense. She also didn’t have Facebook Messenger. There was only one option left that made sense: good ol’ SMS.
I went back to DuckDuckGo (yes, I use it instead of Google) and found that Twilio was perfect. It was inexpensive to send a message—about $0.0017 per SMS plus a $1 for a number—and they provide some pretty solid documentation. Oh yeah, they have a solid Python library which means less coding from scratch.
So now I’m armed with two APIs that come with their own keys and tokens. It is now time to for me to employ them considering they don’t do much without being given some direction.
The first thing I learned was how to was set environment variables to protect the keys (and later phone numbers). Turns out they are pretty nifty at protecting secure pieces of information without embedding it into the source code.
I created a virtual environment to keep my computer nice and clean from the random Finnhub and Twilio Python packages that would otherwise be floating around. I loaded those environment variables into the source and started looking at how to grab the price of $GME from the FinnHub API.
Turns out the “Getting Started” documents from FinnHub for their Python package basically wrote the function for me. It was almost as easy a copy and paste. The only major difference was fitting it nicely into a function and making sure it pulls the price of the stock.
It looks something like this:
def getGMEprice(): finnhub_client = finnhub.Client(api_key=os.environ['FINNHUB_API_KEY']) quote = finnhub_client.quote('GME') return quote
The return
statement was a bit of pride from my part because I learned how to send data I got back into a function that can then be used when the function is called.
Next I needed to write a function that would actually fire off the text message using the Twilio API. I split it into two functions as I wanted two messages. I could probably turn it into one function but as of right now it works and I’d rather not mess with it. Here is what it looks like:
def send_up_message(price):
price = price
distanceFrom = 1000 - float(price["c"])
toSend = 'The price of GME went up by {}% (booo!) and is now: ${}. That is still ${} away from $1000 >:)'.format(price["dp"], price["c"], distanceFrom)
message = client.messages.create(
messaging_service_sid=messaging_service_sid,
body=toSend,
from_='+12513251057',
to=os.environ['RK_PHONE']
There are a couple of things here that I’m quite proud of: the inclusion of an argument, the use of a Python f-string, and the fact that I successfully used the array location to grab just the data I needed.
I have struggled with the idea of arguments required for functions for quite some time, but here, it seemed to click. The whole price = price
actually made sense the moment I wrote it down. It takes the price
object from the function argument and assigns it to another variable that I called price
. Brilliant.
The last bit of code that I loaded up in my Python script was a main
function that simply calls getGMEprice()
and loads it to a price
variable that can then be placed into the argument for the message functions. All that is determined by a dinky if
statement that checks if the price went up or down. Boom. It works.
Kinda sort of, not exactly.
Here is where a bulk of my time went: implementing my code. I knew I needed to load it into the cloud, since I don’t have a small computer that can run 24/7 (anymore), yet didn’t know where. I was aiming toward doing this on a Digital Ocean Function but realized they didn’t support scheduling apps. That became an instant no-go. I avoid AWS only because I don’t like Amazon. Maybe to my detriment, but I digress.
I settled on Google Cloud Apps as it was lightning quick to setup, required no major hassle loading the Python packages, and was super easy to setup my environment variables. After a few tests, it was time to see how to schedule it.
Turns out, I needed to add another small function to my script called hello_pubsub
that takes an event
and a context
to run. When it’s triggered it runs main
which runs the rest of the program. I had to translate a Monday through Friday at 1pm Pacific time trigger into cron (which wasn’t fun) but now it runs!
All this for a stupid little gag. I learned a ton and the best part was her reaction when she realized it was me. She originally thought there was a data leak somewhere but her other coworkers didn’t receive a text message. Within moments she narrowed it down to me—flattered, if disappointed it didn’t take longer—and sent me some all caps messages in incredulity.
Anyways, this was a lot of fun coding and learning. The result has been a lot of fun and it reminds her how garbage $GME is.
Cheers!