The rise of commission free trading APIs along with cloud computing has made it possible for the average person to run their own algorithmic trading strategies. All you need is a little python and more than a little luck. I’ll show you how to run one on Google Cloud Platform (GCP) using Alpaca. As always, all the code can be found on my GitHub page.
The first thing you need is some data. There are a few free sources of data out there and of course sources that cost money. I’ll be using the TD Ameritrade API which is free. The next thing you need is a trading platform where you can submit commission free trades through an API.
For that I’ll be using Alpaca. Alpaca also allows paper trading (fake money) so we can test out our strategy in the wild without bankrupting our family 💸. Then you just need a way to run your bot automatically and store/retrieve data. For that we’ll use GCP because that’s what I’m familiar with but any cloud platform (AWS, Azure, etc.) will work just as well.
Oh and of course you need a trading strategy. This post is about setting up the framework to run a trading strategy so the strategy itself here isn’t important and not a focus. For demonstration purposes I will be using a momentum strategy that looks for the stocks over the past 125 days with the most momentum and trades every day.
You SHOULD NOT blindly use this strategy without backtesting it thoroughly. I really can’t stress that enough. You SHOULD NOT take investment advice from me, you will most likely be sorry 😄.
The first thing you need is a universe of stocks. I’ll be using all the stocks listed in the NYSE. To get the symbols for those stocks, we’ll scrape them from eoddata.com. Then we can request the data for each of those stock symbols from the TD Ameritrade API.
Once we have the data, we’ll store it in a BigQuery (BQ) table so we can get it later for our strategy. This will all be run in a cloud function that we can then schedule to run every weekday after the markets close to get the latest closing price.
I store the API credentials in a text file on Cloud Storage so they are not hard coded. We just retrieve them from there with an API call. Then we get the date to use to check if the market is open. Then we scrape the NYSE stock symbols and pass them to the TD Ameritrade API to get the day’s data.
Then we store that data in a BQ table through the API to use later for our bot.
I’m only using the closing price but the API returns a lot more data so it’s a good idea to just store it all. I created a dataset called ‘equity_data’ and the table will be called ‘daily_quote_data’. If the table doesn’t exist (i.e. the first time you’re doing this) the table will be created and then every day, the new data will get appended to that table.
In GCP you can create a Cloud Function with this script. To schedule this Cloud Function to run at a set time, simply choose ‘Cloud Pub/Sub’ for the trigger option and create a topic.
Then go over to Cloud Scheduler and set up the topic to run when you want it. Here we are setting it to run every weekday at 5pm eastern. The frequency is set in unix-cron format. The payload is just a message that will be sent and can be anything you want but it is required.
It’s also a good idea to set the timeout of the cloud function to the max of 540s to…well avoid timeouts. This can be found under the advanced options section.
This will download the data going forward but we’re also going to need back data for the trading bot. The endpoint I’m using here is the ‘quotes’ endpoint which does not provide historical data. To get historical price data you have to use the ‘pricehistory’ endpoint. I provided a file in the GitHub folder which for that called ‘get_historical_data.py’. You can run that file locally and then download the dataframe into a csv and upload it to a BQ table.
At a basic level, the trading bot needs to be able to:
- Know how much money we have available to trade with
- Get the data to use in the strategy
- Select the stocks we decide we want based on the strategy
- Buy/sell those stocks to update our portfolio
The entire cloud function is on the longer side so I’ll summarize it here but the full code is on my GitHub. Like I said, the strategy isn’t important here and I am using a simple momentum strategy that selects the ten stocks with the highest momentum over the past 125 of days.
First we download the historical data into a dataframe for the momentum strategy from the BQ API:
Then we get the current positions from the Alpaca API and our current portfolio value. They have an API wrapper which I’m using here. The credentials again are stored in a text file on cloud storage. Notice that the base url we are using is for paper trading. You can set any amount in your paper trading account, here I set it to $10K. Obviously if this is your first time running this you won’t have any positions in Alpaca, so before you run the cloud function, just run the script locally to get your initial portfolio based on the momentum stocks you choose. Then send those tot he Alpaca API to buy them. I’m assuming here you already did that.
Now that we have the historical data and the amount we have to trade with, we can select the stocks based on our strategy. The first step is to identify the stocks with the highest momentum.
The momentum calculation is from the book Trading Evolved from Andreas F. Clenow which I would recommend. It’s very easy to follow and has lot’s of different code examples in it for different types of strategies.
The way it works is that it calculates a linear regression for the log of the closing price for each stock over the past 125 days (minimum number of days is 40). The next step is to make it easier to relate to. It takes the exponent of the slope of the regression line (tells you how much percent up or down it is by day) and then annualizes it (raise to the power of 252 which is the number of trading days in a year) and multiplies it by 100. That is then multiplied by the r squared value which will give weight to models that explain the variance well.
After we identified the top 10 stocks with the highest momentum score, we then need to decide how many shares of each we will buy. Portfolio allocation is a whole topic in and of itself so I won’t get into it here as it’s not important. To allocate here I am using the pyportfolioopt library.
We now have a df with the stocks we want to buy and the quantity. Now we need to figure out if we need to sell any stocks based on what is in our current portfolio. It’s possible that:
- Our selection and allocation of momentum stocks today is exactly the same as yesterday and we don’t need to make any sales or buys
- There are stocks in our current portfolio that we do not want to hold anymore at all
- The stocks we want to buy today are the same as the ones we currently own but the amount we want to hold has changed (either increased or decreased)
- There are new stocks we want to buy today, that were not in our portfolio yesterday
We need to check for all those things and make any necessary sales or buys. First we’ll check to see if there’s any stocks in our current portfolio that we do not want anymore.
Now we have a dataframe with any stocks we want to sell and the quantity we need to sell. Next we’ll check to see if the quantity of any stock we currently own has decreased. Again, there may technically be no changes here so we need to check if there are. This will give us a final dataframe with all the stocks we need to sell.
Now that we have the full list of stocks to sell (if there are any), we can send those to the alpaca API to carry out the order.
Finally, we need to see if there are any new stocks we currently own that have increased in quantity or if there are any new stocks we want to buy today that we didn’t own yesterday.
If there are any we need to buy, we send those orders to the API.
It’s also a good idea to log the portfolio once we’re done. Alpaca only allows you to have a single paper trading account, so if you want to run multiple algorithms (which you should), you should create a log so you can track them on your own. We can create a strategy column to identify this strategy from others. Then we can simply add that to another BQ table.
The below SQL query will give you the daily totals with the percent change compared to the previous day for your portfolio.
That’s the bot. You can now schedule it to run everyday in a cloud function. This should give you a good framework in which to run your own trading strategies.