Companies seeking public funding partner up with investment banks who bear the responsibility of facilitating the private bidding process. The private company sells all shares to the investment bank who in turn take the outstanding shares public. Because the investment banks take on the risk of the shares, many hypothesize that the IPO price tends to be undervalued so that the bank is not left with excess stock (read: risk).
Is this myth true? Do IPOs truly tend to be underpriced? If so, is there a pattern that can be identified? Could short term underpricing really just be long-term overvaluation in disguise?
These questions will be explored in this report.
Credits:
-Yusef '18 (Project)
-Owen '18 (Help with multiprocessing code)
In [48]:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import requests
import re
plt.style.use('ggplot')
import matplotlib
%matplotlib inline
The data used in this report was originally taken from Google finance.
The multiprocessing code used to obtain the original Google finance data can be found here: http://puu.sh/oKMeh/1e7ee7d056.docx
Note that since the code takes a very long time to run (more than 15,000 calls, necessity of a VPN, etc) the code was ran ahead of time and the data was uploaded to a personal filehosting website. This is what PANDAS will read.
In [49]:
# Download the data file from `puu.sh` and save it locally under `file_name`:
url = "http://puu.sh/oBCfW/c006093339.xlsx" # Script was ran ahead of time and uploaded onto this website. Random sample.
file_name = "./IPO_Expanded_Multiprocessing_d.xlsx"
req = requests.get(url)
file = open(file_name, 'wb')
for chunk in req.iter_content(100000):
file.write(chunk)
file.close()
In [50]:
my_data = pd.read_excel(file_name,sheetname="Nasdaq_IPO_Expanded_Multiproces")
In [51]:
my_data.head(3)
Out[51]:
In [52]:
df = my_data.copy()
## These symbols were not available
df = df[df.Symbol != "GAV'U"]
df = df[df.Symbol != "AGR'A"]
df = df[df.Symbol != "TAP'A"]
df = df[df.Symbol != "PED'U"]
df.shape
Out[52]:
In [53]:
df["First Day Open Price"] = df["First Day Open Price"].replace("-",np.nan).astype('float')
df= df[df["First Day Open Price"]<200]
df.shape
Out[53]:
In [54]:
df.Sector.replace(to_replace="&",value="",regex=True,inplace=True)
In [55]:
df["Day_Closing"] = 100 * (df["First Day Open Price"] - df["First Day Close Price"])/(df["First Day Open Price"])
df["Day30_closing"] = 100 *(df["First Day Open Price"] - df["Thirty Days Later Close Price"])/(df["First Day Open Price"])
df["Current_closing"] = 100 * (df["First Day Open Price"] - df["Current Price"])/(df["First Day Open Price"])
a = {} b = [] for i in df.Symbol: try: x = Share(i).get_price() if x == None: b.append(i) else: a[i] = x except: print(i)
In [56]:
plt.figure();
df.Symbol.groupby(df["IPO Date"]).count().plot(title = "Frequency of IPO's Since 1997",
figsize=(15,15),color="b")
Out[56]:
In [57]:
df_graph2 = df["First Day Close Price"].groupby(df["IPO Date"]).count()
df_graph2 = pd.DataFrame(df_graph2)
df_graph2['index1'] = df_graph2.index
#df_graph2 = df_graph2.reset_index(drop = True)
df_graph2.columns = ["Number","IPO Date"]
df_graph2["Number"].cumsum().plot(title = "Total IPOs 1997-2016", figsize = (10,10), color="m")
Out[57]:
In [58]:
df_graph3 = df.groupby(["Sector"]).count()
df_graph3 = df_graph3.reset_index()
df_graph3.index = df_graph3["Sector"]
df_graph3 = df_graph3[["Symbol"]]
df_graph3.columns = ["Total Number of IPOs"]
df_graph3.plot(kind="barh",title = "Total Number of IPOs by Sector (Random Sample of 600)", figsize = (10,10),color="c")
Out[58]:
In [59]:
my_colors = 'cbmg'
df_graph1 = df[["Day_Closing","Day30_closing",]].groupby(df["Sector"]).mean()
df_graph1['index1'] = df_graph1.index
df_graph1.reset_index(drop=True)
df_graph1.plot(kind = "bar",title = "IPO Underpricing Percent by Period",
figsize=(10,10), subplots=False,legend = True,color=my_colors)
Out[59]:
In [60]:
df[["First Day Open Price","First Day Close Price",'Thirty Days Later Close Price',
'One Year Later Close Price']].groupby(df["Sector"]).mean().plot(kind = "bar",
legend= True,
figsize=(15,10),
title="Mean Share Price Per Period, Grouped by Sector",
color=my_colors
)
Out[60]:
In [61]:
df[["First Day Open Price","First Day Close Price",'Thirty Days Later Close Price',
'One Year Later Close Price']].groupby(df["Market"]).mean().drop(['American Stock Exchange'], axis=0).plot(kind = "bar",
legend= True,
figsize=(15,10),
title="Mean Share Price Per Period, Grouped by Market",
color=my_colors
)
Out[61]:
In [62]:
print("FIN")