Build an Algorithmic Trading System | by Posey | Towards Data Science

After dozens of emails and DMs, it seemed appropriate to write a proper introduction to getting started with Algorithmic Trading. This guide should serve as a walkthrough for building your first Proof of Concept algorithmic trading system.
Disclaimer: Luke is a Co-Founder of Spawner, a company whose tech is directly mentioned and used in this article.
Note: Nothing herein is investment advice. This is purely for educational purposes. Good returns with algorithmic trading requires many hours of programming, testing, failing, retrying, and testing again before you have a system robust enough to automatically trade securities. Please try everything in a Paper Trading account before ever testing with real money. Use common sense.
Let’s compartmentalize some of the pieces of an algorithmic trading system or automated trading system. We’ll go through them step-by-step and then showcase a finished example at the end of the article.
Some key ingredients for your trading system:
Signals and Indicators
Trade Execution System
Backtesting
Indicators are the generators of a signal. Indicators are some signal generator that will alert your trading system of when it’s a good time to buy, sell, or hold a security (stock, bond, option, etc.). This could mean opening a position, adding to a position, decreasing a position, shorting, employing some strategy with derivatives, etc...
Technical Indicators have long been used in algorithmic trading systems to generate a signal. Algorithmic traders often build and backtest dozens of combinations of indicators, timeframes, and entries to build a signal that actually generates alpha.
At Spawner, we’re building all sorts of indicators to help users tap into signals and build more robust systems. We’ll use some of the technical indicators provided by Spawner in this article. The perk of using these indicators is we don’t need to gather our own pricing data, as all you need to do is pass the ticker to the API, and the API will return your desired indicator.
You can get your API Token to start interacting with the API.
Using standard REST we’ll pass a ticker and our token and get back JSON:
token = 'sp_znci3#zcnz49Kjznkkze'url = "https://spawnerapi.com/bollinger/aapl/token"response = requests.get(url)print(response.json())
returns:
[{‘upper’: [302.74, 307.65, (...)],
‘lower’: [302.74, 288.01, (...)]}]
These are the upper and lower bands of Bollinger Bands. We’ve got other indicators in the API like RSI, Kelton Bands, and more. The perk to using such an API is we don’t have to gather our own data. We can skip setting up massive data pipelines and directly access our indicators.
We can visualize what our upper and lower Bollinger Bands would look like:
bands = response.json()upper = bands[0]['upper']lower = bands[0]['lower']# Using Plotlyfig.add_trace(go.Scatter(x=date, y=upper, line_color='rgba(107, 191, 22,1)', name='Upper Band'))fig.add_trace(go.Scatter(x=date, y=lower, line_color='rgba(214, 14, 14,1)', name='Lower Band'))
The upper and lower Bollinger Bands above are plotted at one standard deviation above and below the simple moving average (SMA) of the stock price. The bands are sensitive to volatility. Some traders like to buy when the price touches the lower band, go short from upper band, and exit either position when price touches the moving average.
How can we implement that logic in an algorithm? Let’s do some napkin logic and write some pseudo-code:
if price divided by lower band less than 5% different and price > lower band:      long $1500if price divided by upper band less than 5% different and price < upper band:      short $1500
We can then write the logic for exiting a position. The exit logic can get complex super quick. For example, you might want to gradually take profits, take profits under certain conditions, have stop orders in case your position gets wrecked, etc...:
if position_value > 1550:       exit position if position_value < 1450:       exit position
Let’s write this out in Python and see how we would do order execution.
So we’ve got a signal we might like. How do we set up order execution? We’ll use the Alpaca API for this. Alpaca has a free trading API through which we can programmatically set up our trades. I’m not associated with Alpaca in any way, other than as a user. But I can say from setting up these systems in various brokerages, Alpaca is far easier to use than the majority of APIs offered by mainstream brokerages.
We could build an API and expose endpoints for our trading system, maybe as a Flask App. For the purposes of this article, we’ll keep it all in one file. We’ll use timers to constantly check market conditions of the tickers we’re following. If any of them trigger our indicators to provide a signal we’ll execute a trade!
Here is an example of an indicator. We return a signal if the price enters the range < .5% above lower Bollinger Band.
def indicator(ticker):    # Get lower Bollinger Band    url = "https://spawnerapi.com/bollinger/" + ticker + "/" + token    response = requests.get(url)    bands = response.json()    lower = bands[0]['lower']    moving_avg = bands[0]['average']    # get last value in list (latest band values)    lower = lower[-1]    moving_avg = moving_avg[-1]    # Get real-time price quote    url = "https://spawnerapi.com/price/" + ticker + "/" + token    response = requests.get(url)    price = response.json()['price']    # Return signal or no signal     if price > lower and ((price / lower)-1) < .005:        return 'buy lower', moving_avg[-1], price    else:        return 'no signal', 'no avg', price
Now we can build our order execution function...
# We'll pass a ticker, quantity to buy, and profit and stop limits.def submit(ticker, quantity, profit_limit, stop_limit):    api.submit_order(       symbol=ticker,       side='buy',       type='market',       qty=str(quantity),       time_in_force='day',       order_class='bracket',       take_profit=dict(           limit_price=str(profit_limit),       ),       stop_loss=dict(           stop_price=str(stop_limit),           limit_price=str(stop_limit),       )    )
Finally, we’ll write an oversimplified function (not robust!) to check our signal every few seconds and execute a trade if our signal hits.
Note: it’s important we don’t trigger the buy order an infinite number of times. Signals can stay high for a long time, so make sure you’re getting out of the loop! One way to do this is have a list of tickers you’re watching, and whenever you trigger a buy you can remove that ticker from the list. Up to you! Here’s an oversimplified function that will only check the signal once, execute, and quit.
def timer():   x = True   while x==True:       print('Checking Signal...')       signal, moving_avg, price = indicator('AAPL')       if signal == 'buy lower':          submit('AAPL', 5, moving_avg, (price-(price*.02)))          print("Executing Trade.")          # exit loop          x = False       else:          print("No Signal.")       time.sleep(2)
Let’s test!
If we check our Alpaca portal we’ll see the trade was submitted and our limits for profit and stop loss are set.
Keeping your trades within set risk parameters is important. This means appropriately sizing positions, limiting exposure to conditions like volatility, minimizing drawdowns, managing Value at Risk, etc... We’ll do another article discussing risk in the future. Many of these metrics are already active in the Spawner API.
Backtesting is the one (crucial!) piece we’ll save for another more in-depth article. Backtesting is a monster and we’re spending time making examples for backtesting that should make implementation much easier. Standby for that!
To support my writing and get full access to all articles on Medium, visit https://posey.medium.com/membership
Note from Towards Data Science’s editors: While we allow independent authors to publish articles in accordance with our rules and guidelines, we do not endorse each author’s contribution. You should not rely on an author’s works without seeking professional advice. See our Reader Terms for details.