Writing Automatic Stock Alerts in Python and FinancialModeling Prep
In this blog post, we’re going to go over how you can create your own financial alerts using python and Stock APIs.
The general overview of this is that there are really 3 moving parts to this workflow. Part one is of course python, part two is FinancialModelingPrep.com api and part 3 is a CRON or task scheduler
Part 1: The Code
The code is broken down into 3 parts.
Load File:
loadfile = {
"Stocks": {
"Stock1": "aapl",
"Stock2": "BLOK"
},
"Operations": {
"twopercentof200": True
},
"endpoints":{
"historicalprice": "https://financialmodelingprep.com/api/v3/historical-price-full/",
"api_key": "your_api_key"
},
"params":{
"daysback": 200,
"password": "input_your_password",
"from_email": "yout_email_gmail"
}
}
The load file is a great place to organize variables and store some logic. In python, I just use a dictionary. It’s pretty straight forward. I name the file “Load.py” and if I want to access these members from main.py, I use the following snippet.
stock_to_get = load.loadfile["Stocks"]["Stock1"]
What this above snippet does is it takes the variable “stock_to_get” and stores the “aapl” string in it. Very simple.
The next part of this code is the logic for getting the json object from the api and manipulating that object to return the useful data.
import load
import smtplib, ssl
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
try:
# For Python 3.0 and later
from urllib.request import urlopen
except ImportError:
# Fall back to Python 2's urllib2
from urllib2 import urlopen
import certifi
import json
def get_jsonparsed_data(url):
response = urlopen(url, cafile=certifi.where())
data = response.read().decode("utf-8")
return json.loads(data)
def percentover200dayaverage(symbol,api_key):
i = 0
pricesum=0
base_url = load.loadfile["endpoints"]["historicalprice"]
url = base_url + symbol + "?apikey=" + api_key
the_data = get_jsonparsed_data(url)
while i < load.loadfile["params"]["daysback"]:
i = i + 1
pricesum = pricesum + the_data['historical'][i]['adjClose']
twohundreddayaverage = pricesum / load.loadfile["params"]["daysback"]
percent_over = ((the_data['historical'][0]['adjClose'] / twohundreddayaverage) * 100) -100
return percent_over
def email_the_result(symbol,api_key):
two_Hundred_day_average_stock = percentover200dayaverage(symbol, api_key)
print two_Hundred_day_average_stock
gmail_user = 'jonathannorthmoto@gmail.com'
gmail_password = load.loadfile["params"]["password"]
print(gmail_password)
sent_from = gmail_user
to = ['an_email@gmail.com', 'jonathannorthmoto@gmail.com']
subject = 'Daily Moving Average Alert'
body = "Stock: " + str(symbol) + " is trading at this percent of its 200 day average : " + str(two_Hundred_day_average_stock)
email_text = """\
From: %s
To: %s
Subject: %s
%s
""" % (sent_from, ", ".join(to), subject, body)
try:
server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
server.ehlo()
server.login(gmail_user, gmail_password)
server.sendmail(sent_from, to, email_text)
server.close()
print 'Email sent!'
except:
print 'Something went wrong...'
The function percentover200dayaverage() will get the json result, and find the 200 day moving average for the stock passed to it. This function returns a percentage value. The purpose of this app was to allow me to keep an eye on when certain stocks are trading close to their 200 day moving average. Now please understand, i make no warrants for this code. I cannot guarantee it works. And also, these 200 day moving averages are just numbers. How I act on it with any specific stock is highly situational and I make no warrants and claims.
And finally the function, email_the_result() will take the result and email it to me. I plan on running this script daily.
And thats it. As its configured right now, and this is something I wrote in about an hour, it will send two emails back to back about the Stock1 and Stock2 in relation to their 200 day moving average.
Part 2: The API
The name of the site I’m using is from Financial Modeling Pre and the calls for historical price data can be found here : https://financialmodelingprep.com/developer/docs/historical-stock-data-free-api#Historical-Daily-Prices
When you sign up with this API, they give you 250 free calls a month. That should be enough for a few days of coding, depending. If you really wanted to, you could make your calls and store some kind of persistant data and query that. Perhaps store what you need in a csv and reference that csv while prototyping. I would do that if I was really a tight wad. What you do is really up to you. Here is an example JSON response you will get from the API.
curl https://financialmodelingprep.com/api/v3/historical-price-full/AAPL
{
"symbol" : "AAPL",
"historical" : [ {
"date" : "2021-10-08",
"open" : 144.03,
"high" : 144.17,
"low" : 142.56,
"close" : 142.9,
"adjClose" : 142.9,
"volume" : 5.545036E7,
"unadjustedVolume" : 5.545036E7,
"change" : -1.13,
"changePercent" : -0.785,
"vwap" : 143.21,
"label" : "October 08, 21",
"changeOverTime" : -0.00785
}, {
"date" : "2021-10-07",
"open" : 143.06,
"high" : 144.215,
"low" : 142.73,
"close" : 143.29,
"adjClose" : 143.29,
"volume" : 6.1863761E7,
"unadjustedVolume" : 6.1863761E7,
"change" : 0.23,
"changePercent" : 0.161,
"vwap" : 143.41167,
"label" : "October 07, 21",
"changeOverTime" : 0.00161
}, ...
} ]
}
Part 3: Task Scheduler in Windows
To set this part up, you need at least Windows 10, you need to have python installed, and you need to have the necessary packages installed to run the script. First, my recommendation is to make sure to test run your script in powershell. If it works, great, step one done. If not, see step 1. So open up your task scheduler and create a new task.
So if you look below, the program/Script location is your python location. You can find this by running in powershell “Where.exe Python” or some variation there of. The argument is the script you want to run, the file name. And “start in” is the folder of that script. easy, ey?
And there you have it. Thats really all you need to know to set up automatic alerts. If you have any questions or you want some help with your code, feel free to contact me in the contact form at the main navigation menu.
Leave a Reply
You must be logged in to post a comment.