Build an Algorithmic Trading System

From: https://towardsdatascience.com/build-an-algorithmic-trading-system-a5b54de5379

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.

Trading Systems

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

Signals and Indicators

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 free 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 Plotly
fig.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 $1500
if 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.

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!

Automatic Trading System…v0.1!

If we check our Alpaca portal we’ll see the trade was submitted and our limits for profit and stop loss are set.

Order History

Risk Management

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

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!

Conclusion

Hopefully, this helps you on your algorithmic trading journey! We’re constantly adding indicators, tools, and applications over at Spawner to help you navigate the markets…

Stay safe!

Leave a comment