Click here to get a PDF of this post

This guest post was written by Troy Bombardia. He shares free market analysis, data, and trading algorithms at Bull Markets.

This is Part 4 in this Python for Trading Series. Parts 1, 2, and 3 can be found here, here, and here. In this tutorial I’m going to teach you how to code an easy-to-use strategy for trading stocks which recently went public (IPOs). These stocks are very volatile, which makes them excellent candidates for momentum strategies.

This strategy uses 1 index and 1 ETF, but for actual trading you can use the index’s matching ETF:

  1. Renaissance IPO Index (Renaissance IPO ETF: IPO)
  2. Treasury bond ETF: TLT

Here’s how to code this algorithmic trading strategy.

Import some libraries

First, import the libraries Pandas and Numpy. These Python libraries enable us to use pre-built functions instead of creating our own functions.

The line of code “%matplotlib inline” allows us to use matplotlib for charting in Python.

import pandas as pd
import numpy as np
%matplotlib inline

Read your CSV’s data as a dataframe

Next, we “read” the CSV file’s data and turn the data into a Dataframe called variable “df”:

df = pd.read_csv(‘C:\\Users\\vaish\\Desktop\\pythoncode\\y_new\\ipo_strategy.csv’)

Code the strategy

Our strategy for trading recently IPO stocks is simple yet effective: buy the IPO etf when the IPO Index’s 50 day moving average is going up, otherwise go long TLT (Treasury bonds).

df[‘IPO Trend’] = df[‘IPO Index’].rolling(window=50).mean() >= df[‘IPO Index’].rolling(window=50).mean().shift(1)
df[‘TLT Long’] = (df[‘IPO Trend’] == False)


Calculate the IPO Index and TLT’s daily price changes

Next, we need to calculate the IPO Index and TLT’s daily % change. To do this we use the .pct_change() function.

df[‘IPO Change’] = df[‘IPO Index’].pct_change()
df[‘TLT Change’] = df[‘TLT’].pct_change()


Calculate the strategy’s performance

Finally, it’s time to calculate the strategy’s performance over time.

df[‘Buy and hold IPO’] = 100*(1+df[‘IPO Change’]).cumprod()
df[‘Strategy’] = 100*(1+df[‘IPO Trend’].shift(1)*df[‘IPO Change’]+df[‘TLT Long’].shift(1)*df[‘TLT Change’]).cumprod()


The 1st line of code calculates buy and hold for the IPO Index.

The 2nd line of code calculates this trading algorithm’s performance over time. Every single day, the algorithm looks to see if yesterday’s “buy IPO” condition was TRUE or FALSE. If the condition was TRUE, then the strategy will go long the IPO Index today. If the condition was FALSE, then the strategy will go long TLT (Treasury bonds) today.

How well does this trading strategy perform

We can write a few lines of code to identify how well this trading algorithm performs.

start_portfolio = df[‘Strategy’].iloc[50]
end_portfolio = df[‘Strategy’].iloc[-1]
years = (2959-50)/252
average_return = (end_portfolio/start_portfolio)**(1/years)-1

print(‘Average trading algorithm return is’, average_return, ‘per year’)

ipo_start = df[‘IPO Index’].iloc[50]
ipo_end = df[‘IPO Index’].iloc[-1]
ipo_average_return = (ipo_end/ipo_start)**(1/years)-1
print(‘Average buy and hold IPO return is’, ipo_average_return, ‘per year’)

  1. The first line of code identifies this trading algorithm’s start value (start_portfolio)
  2. The second line of code identifies this trading algorithm’s ending value (end_portfolio)
  3. The third line of code calculates the number of years this strategy has been used (years)
  4. The fourth line of code calculates this trading algorithm’s average annual return (as a decimal instead of a %)

This trading algorithm yields an average of 16.19% per year

  1. The variable “ipo_start” identifies buy and hold’s start value
  2. The variable “ipo_end” identifies buy and hold’s ending value
  3. The variable “ipo_average_return” calculates buy and hold’s average annual return

Buy and hold the IPO index yields an average annual return of 17.9%

As you can see, this strategy underperforms buy and hold by a little. However, the key advantage is that this strategy is must less volatile than buy and hold – the drawdowns are smaller. Recent IPO stocks can be extremely volatile, so minimizing drawdowns is critical.

These 2 lines of code allow us to chart the strategy’s performance:

Thank you for reading this tutorial. I will share more trading algorithms in future parts of this Python for Trading Series.

Previous posts:

Python for Trading Series – Part 1

Python for Trading Series – Part 2

Python for Trading Series – Part 3

You can follow Troy Bombardia on Twitter @BullMarketsco. or at his website