Exploring the Ups and Downs of Uber Stock: An Exploratory Data Analysis
Uber is one of the most well-known tech startups to emerge in the past decade. Founded in 2009, the ride-hailing and food delivery company has expanded rapidly and now operates in over 10,000 cities worldwide. Uber held its highly anticipated IPO in May 2019, making its stock market debut at $45 per share.
Since then, the Uber stock price has been on a rollercoaster ride. It‘s seen huge swings up and down as the company has grappled with profitability challenges, leadership changes, driver strikes, and increased competition. For investors and market watchers, Uber stock is never boring.
In this post, we‘ll take a deep dive into Uber‘s stock market data using exploratory data analysis (EDA). EDA is a crucial first step in any data science project. It allows us to summarize the main characteristics of a dataset, uncover hidden patterns, spot anomalies, and check assumptions. Skipping EDA and jumping straight into modeling is risky—it‘s like taking a road trip without checking your GPS first. You need to understand the lay of the land before planning your route.
Our dataset contains daily Uber stock prices from the IPO through April 2023. For each trading day, we have the following variables:
- Date
- Open: Opening stock price
- High: Highest price reached that day
- Low: Lowest price reached that day
- Close: Closing stock price
- Adj Close: Closing price adjusted for stock splits and dividends
- Volume: Number of shares traded
Let‘s load up the data and take a look!
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
uber_data = pd.read_csv(‘uber_stock_data.csv‘)
print(uber_data.head())
Date Open High Low Close Adj Close Volume
0 2019-05-10 44.53 45.00 41.06 41.70 41.70 97443346
1 2019-05-13 41.80 43.08 41.03 42.29 42.29 46941534
2 2019-05-14 42.34 43.59 41.82 43.38 43.38 29023248
3 2019-05-15 43.16 43.74 42.21 42.66 42.66 20753754
4 2019-05-16 42.17 43.25 41.89 43.20 43.20 17297808
We can see the dataset has 7 columns and spans nearly 4 years, giving us over 900 rows total. A quick check reveals there are no missing values, so we‘re good to go.
Next, let‘s generate some summary statistics for the numeric columns using the describe() method:
print(uber_data.describe())
Open High Low Close Adj Close Volume
count 922.000000 922.000000 922.000000 922.000000 922.000000 9.220000e+02
mean 40.235679 41.206079 39.163136 40.237013 40.237013 2.474020e+07
std 12.115975 12.280416 11.873681 12.112320 12.112320 2.244353e+07
min 14.820000 16.050000 13.710000 14.820000 14.820000 3.661180e+06
25% 31.807500 32.590000 30.925000 31.820000 31.820000 1.108548e+07
50% 40.540000 41.295000 39.425000 40.535000 40.535000 1.712294e+07
75% 49.997500 51.000000 48.702500 50.000000 50.000000 2.825671e+07
max 64.050000 64.050000 61.820000 63.700000 63.700000 2.095763e+08
This gives us a good overview of the distributions. We can see the mean stock price is around $40, but prices have ranged from a low of $13.71 to a high of $64.05. The mean daily trading volume is about 25 million shares, but volume is highly variable, ranging from 3.6 million to over 200 million shares in a single day!
Let‘s start visualizing the data. First we‘ll create a heatmap to examine the correlations between variables:
plt.figure(figsize=(8,6))
sns.heatmap(uber_data.corr(), annot=True, cmap=‘coolwarm‘)
plt.title(‘Correlation Heatmap‘)
plt.tight_layout()
plt.show()

The heatmap shows that, unsurprisingly, the open, high, low, and close prices are all very strongly positively correlated with each other. If the opening price is high, the closing price tends to be high as well, and vice versa.
Interestingly, the daily trading volume has only a weak positive correlation with the stock price variables. High volume doesn‘t necessarily mean high prices. We‘ll explore this further.
It‘s often insightful to look at the spreads between the daily high, low, and closing prices. Let‘s calculate a few of these metrics:
uber_data[‘high_low_spread‘] = uber_data[‘High‘] - uber_data[‘Low‘]
uber_data[‘open_close_spread‘] = uber_data[‘Close‘] - uber_data[‘Open‘]
print(uber_data.head())
Date Open High Low Close Adj Close Volume high_low_spread open_close_spread
0 2019-05-10 44.53 45.00 41.06 41.70 41.70 97443346 3.94 -2.83
1 2019-05-13 41.80 43.08 41.03 42.29 42.29 46941534 2.05 0.49
2 2019-05-14 42.34 43.59 41.82 43.38 43.38 29023248 1.77 1.04
3 2019-05-15 43.16 43.74 42.21 42.66 42.66 20753754 1.53 -0.50
4 2019-05-16 42.17 43.25 41.89 43.20 43.20 17297808 1.36 1.03
Now let‘s compare the trading volumes across different ranges of the high-low spread. We‘ll bin the spreads into 4 categories and plot the average volume for each:
uber_data[‘hl_spread_cat‘] = pd.cut(uber_data[‘high_low_spread‘], bins=[0,1,2,3,100], labels=[‘0-1‘,‘1-2‘,‘2-3‘,‘>3‘])
plt.figure(figsize=(8,5))
sns.barplot(data=uber_data, x=‘hl_spread_cat‘, y=‘Volume‘)
plt.title(‘Average Volume by High-Low Spread‘)
plt.show()

This chart reveals an interesting pattern. Days with the highest high-low spreads (over $3) actually have the lowest average trading volumes. The highest volumes occur on days when the high-low spread is between $1-2.
This makes some intuitive sense. High-low spreads over $3 indicate days with very dramatic swings in price, which may spook many investors and deter them from trading. Whereas more modest high-low spreads in the $1-2 range represent active but orderly trading days that draw in higher volumes.
We can create a similar chart comparing volumes across different ranges of the open-close spread:

Here we don‘t see any meaningful differences in average volume. Whether the stock closes higher or lower than its opening price doesn‘t seem to impact the trading volume.
Finally, let‘s zoom out and look at the big picture trends in Uber‘s stock price and trading volume over time. We‘ll use line charts to visualize the time series:
fig, ax1 = plt.subplots(figsize=(12,6))
color = ‘tab:blue‘
ax1.plot(uber_data[‘Date‘], uber_data[‘Close‘], color=color)
ax1.set_xlabel(‘Date‘)
ax1.set_ylabel(‘Closing Price ($)‘, color=color)
ax1.tick_params(axis=‘y‘, labelcolor=color)
ax2 = ax1.twinx()
color = ‘tab:red‘
ax2.plot(uber_data[‘Date‘], uber_data[‘Volume‘], color=color)
ax2.set_ylabel(‘Volume‘, color=color)
ax2.tick_params(axis=‘y‘, labelcolor=color)
fig.tight_layout()
plt.show()

This chart depicts Uber‘s tumultuous journey as a public company. The stock debuted around $45 but fell sharply in the months after the IPO, hitting a low around $26 in November 2019. Prices rebounded in early 2020 before crashing to an all-time low near $14 during the March 2020 pandemic selloff.
From there, Uber began a stunning recovery, soaring to record highs above $60 by February 2021 as investors bet on a reopening boom. But the euphoria didn‘t last, and the stock entered a prolonged slump from mid-2021 through 2022 as growth slowed and losses mounted. As of April 2023, Uber trades around $33, still well below its IPO price.
Throughout these dramatic price swings, we can see that trading volumes generally spiked during periods of heightened volatility, both on the upside and downside. The highest volume days coincide with key events like the IPO, the pandemic crash, and the meme stock mania of early 2021.
So what can we take away from this exploratory analysis of Uber stock? A few key insights:
-
Uber‘s stock price has been highly volatile and event-driven, with multiple +50% rallies and -50% crashes in its short history. This makes it a risky but potentially lucrative trading vehicle.
-
Trading volume is not consistently correlated with price. The highest volume occurs on moderately volatile days, not necessarily the most extreme up or down days.
-
Price trends appear to be driven more by sentiment and news flow than fundamentals. The stock seems to overreact to both positive and negative headlines.
Of course, this analysis only scratches the surface. To build an effective trading strategy, we‘d need to dive deeper into Uber‘s financial statements, compare its performance to peers like Lyft, and develop predictive models incorporating external economic and behavioral data. A time series forecasting model could be valuable for anticipating future price moves.
Still, EDA is a critical first step that provides a foundation of insights to guide further analysis. It helps test our assumptions, raise new questions, and spark ideas for features to use in machine learning.
The explosion of financial data and computing power has made the stock market ripe for exploration with data science techniques. Yet markets are still driven by stories, emotions, and human biases that can be hard to capture in a spreadsheet. The most successful investors find a way to combine data insights with a nuanced understanding of crowd psychology and market dynamics.
Uber‘s wild ride from private startup darling to embattled public company is a case study in how quickly market narratives can shift in today‘s fast-paced, hyper-connected world. While predicting the future is never easy, applying the tools of data science to analyze the past and present can help guide smarter decision making. EDA is the map that orients us to navigate the tricky terrain of the stock market.
So I encourage you to try exploring some stock data yourself! Pick a company you‘re curious about, download their trading history, and see what patterns you can uncover with Python and some creative visualizations. The road to profitable trading is long, but it all starts with a thirst for exploration and a commitment to continually learning from the data.
Happy analyzing!