Vox Populi in the Stock Market

Brian Mullen
CodeX
Published in
5 min readMar 29, 2021
Photo by Ray Bilcliff from Pexels

There is a popular story from Statistics that in 1907, Sir Francis Galton wrote of a competition he witnessed at a local livestock exhibition. An ox was presented, and competitors purchased slips to write their guesses as to the animal’s weight. The person guessing closest to he actual weight would win the ox. The individuals participating were from all walks of life. Experienced individuals, such as Farmers and Butchers, as well as regular townsfolk with curiosity and an interest in the prize.

Almost 800 guesses were submitted, and after the competition Sir Galton was allowed to analyze the slips. The actual weight of the ox was 1,198 pounds, and the average of the guesses was 1,197 pounds. Sir Galton titled his paper “Vox Populi” or “the opinions or beliefs of the majority”. The phenomenon he noticed later became known as the “Wisdom of the Crowds”.

In the Stock Market, a company’s true value is unknown. The price individuals are willing to pay for it’s shares gives an estimate, but this isn’t a perfect system; supply and demand, changing goals of large institutional investors, and market reactions to news can all cause major fluctuations in a stock’s price. It would certainly help to know the true value of a company in order to better time a purchase of shares, buying when the company appears undervalued. These fluctuations also lead investors to try to protect their investments in a practice called “hedging”, where contracts are written to give a shareholder insurance against their investment being devalued.

A common hedging tool is an “option”, which is a contract to buy or sell a specified stock at a specified price at some point in the future. Options come in two varieties, a “call” option gives the buyer the right to purchase 100 shares of the underlying stock at the predetermined “strike” price, while a “put” option gives the right to sell at the strike price.

If an investor believes that a stock they own will go up, but wants to protect themselves in case of a drop, they could purchase a put option guaranteeing a buyer at an acceptable price, called the “strike”. For example, if someone currently owns a stock priced at $10 per share, they could purchase a put with a $10 strike (or whatever value they choose). If the stock price were to go down before the expiration of the put contract, they would still be able to sell their shares for $10 each to the entity they bought the contract from.

In the spirit of “Vox Populi”, we can think of share prices and options contracts as the investor’s guesses to the actual value of the company. Where share prices are a direct valuation, each put option contract is a vote of confidence (or fear) that the stock will be below the given strike price. Since each investor is trying to maximize profits, they have incentive to set the strike price as close to the actual value as possible.

The Data

To the implied value of a company based on it’s put options, I’ll be using free sample data from https://www.historicaloptiondata.com/. I’ll be looking at one month of Amazon data for contracts expiring on 2018–11–30. I’ve loaded the data into a MariaDB database hosted on my personal network.

# dbConnect is hiding the connection information for the server on my network.
import dbConnect
con, cur = dbConnect.connect()

# Pull the data for Amazon put options expiring on 2018-11-30
symbol = "AMZN"
expDate = "2018-11-30"
optionType = "put"

sql = "select underlying, sampleDate, strike, bid, openInterest " +\
"from optionHistory where symbol = %s and " +\
"expiration = %s and optionType = %s"

cur.execute(sql, (symbol, expDate, optionType))
optionHistory = cur.fetchall()

print(optionHistory[0])
{'underlying': 1665.53, 'sampleDate': datetime.date(2018, 11, 1), 'strike': 900.0, 'bid': 0.13, 'openInterest': 61}

Strike Prices vs. Share Price

As a sanity check, we can plot the histogram of a given day’s open contracts (called the open “interest”). We see that the majority of the open contracts are clustered around the current price.

from itertools import groupby
import matplotlib.pyplot as plt

dataset = []
showHist = True

# Group the entries by date
for k, g in groupby(optionHistory, lambda x: x['sampleDate']):
group = list(g)

# Show a histogram of the first day of data
if showHist:
plt.figure(figsize=(18, 7))
plt.bar([x['strike'] for x in group],
[x['openInterest'] for x in group])
plt.vlines([group[0]['underlying']],
ymin=0, ymax=500, colors=['r'])
plt.title("Open Interest for AMZN by Strike, Date: {}, " +\
"Close Price: {}".format(k, group[0]['underlying']))
showHist = False

# Calculate the weighted average of the strike prices
totalOpen = sum([x['openInterest'] for x in group])
totalWeighted = sum([x['strike'] * x['openInterest'] for x in group])

dataset.append({'date': k,
'price': group[0]['underlying'],
'impliedPrice': totalWeighted / totalOpen})
plt.show()
png

The Implied Share Price is Fairly Stable

We could see above that most of the open interest was around the closing price of the stock, but the options with the most interest were actually below the current price. This implies that most contract holders believe that the shares are overvalued. We can get an actual numerical value by taking the weighted average of the strike prices with the number of contracts at that strike. When we plot this implied price over time, we can see that it’s fairly stable. It doesn’t have nearly the variability that the underlying stock price has. Interestingly, over the limited (free) dataset, we see the actual price getting pulled back to the implied price when it diverges too far.

X = [x['date'] for x in dataset]
closePrices = [x['price'] for x in dataset]
weightedStrikes = [x['impliedPrice'] for x in dataset]

plt.figure(figsize=(18, 7))

plt.plot(X, closePrices, label="Close Price")
plt.plot(X, weightedStrikes, label="Implied Price")
plt.legend(loc="upper right")
plt.show()
png

Ran out of Data!

A large diversion takes place near the end of the set on 11/29. If we look at Amazon’s share price shortly after our option data runs out, we see that share prices did revert back closer to the implied price. The fact that the share price doesn’t stay divergent from the implied value lends credibility to the estimation. To take this further, one could compute the implied share prices of contracts with multiple expiration dates then average those, to give an estimation of whether the share price is over or under-valued.

import yfinance as yf
import datetime

data = yf.download(symbol, start="2018-11-21", end="2018-12-31")

plt.figure(figsize=(18, 7))
plt.annotate('Highly Overvalued',
xy=(datetime.date(2018, 11, 29),
data.loc["2018-11-29"]['Close']),
xytext=(datetime.date(2018, 11, 21), 1700),
arrowprops=dict(facecolor='black', shrink=0.05),
verticalalignment='top')
print(data['Close'].plot())
[*********************100%***********************] 1 of 1 completed
AxesSubplot(0.125,0.2;0.775x0.68)
png

Links

--

--

Brian Mullen
CodeX
Writer for

Technical Director of Agricair, using AI to monitor animal welfare on commercial farms. Agricair.com