Module 1 — The Invisible Hand

Adam Smith and Market Equilibrium

From Smith to Simulation: Computing the Ideas that Built Economics
The University of Edinburgh · School of Economics


Part I — The History

Edinburgh, 1776

In March 1776, a retired professor of moral philosophy published a book in London. He had spent ten years writing it — mostly in his mother’s house in Kirkcaldy, a small fishing town across the Firth of Forth from Edinburgh. The book was called An Inquiry into the Nature and Causes of the Wealth of Nations, and it changed everything.

The professor was Adam Smith (1723–1790), and the book we now call The Wealth of Nations is the founding text of modern economics.

The World Smith Lived In

To understand what Smith was doing, you need to understand what he was arguing against. In 1776, most European governments practised mercantilism — the belief that national wealth meant hoarding gold and silver. Governments set tariffs, granted monopolies, banned exports of raw materials, and micro-managed trade. The economy was something to be directed from above.

Smith’s radical claim was that this was not only unnecessary but counterproductive. He argued that when individuals are left to pursue their own self-interest in competitive markets, they end up — almost by accident — producing outcomes that benefit society as a whole.

“It is not from the benevolence of the butcher, the brewer, or the baker that we expect our dinner, but from their regard to their own interest.”
— Adam Smith, The Wealth of Nations, Book I, Chapter 2

This is the idea of the invisible hand: no one plans the economy, yet bread gets baked, shoes get made, and goods reach the people who want them — all through the decentralised mechanism of prices and markets.

The Scottish Enlightenment

Smith was not working in isolation. He was part of the Scottish Enlightenment, one of the most extraordinary periods of intellectual creativity in European history. In 18th-century Edinburgh, Smith’s circle included:

  • David Hume — philosopher, historian, and Smith’s closest friend. Hume’s radical empiricism (“we can only know what we observe”) shaped Smith’s method.
  • Joseph Black — chemist who discovered latent heat, right here at the University of Edinburgh.
  • James Hutton — geologist who realised the Earth was unimaginably old.
  • Adam Ferguson — philosopher who coined the phrase “civil society.”

What these thinkers shared was a commitment to understanding the world through careful observation and systematic reasoning — not through appeals to authority or tradition. Smith applied this empirical method to the economy: he walked through factories, studied trade records, and talked to merchants. The pin factory that opens The Wealth of Nations (which we’ll explore in Week 2) was a real place he visited.

Edinburgh connection. Smith attended the University of Edinburgh before going to Oxford (which he found vastly inferior — he said the professors at Oxford had “given up altogether even the pretence of teaching”). He later returned to Edinburgh and lived the last years of his life at Panmure House on the Canongate, just off the Royal Mile. You can still visit it today.

How Markets Work: Supply and Demand

Smith didn’t use supply and demand curves — those came later, with Alfred Marshall in the 1890s. But the logic is already in Smith’s writing. He distinguished between:

  • The natural price — what a good costs to produce (including wages, rent, and profit at their “ordinary” rates).
  • The market price — what the good actually sells for, determined by the balance of supply and demand.

When the market price is above the natural price, sellers earn extra profits, which attracts new sellers into the market, which increases supply, which pushes the price back down. When the market price is below the natural price, sellers leave, supply falls, and the price rises. The market gravitates toward the natural price — without anyone directing it.

“The natural price, therefore, is, as it were, the central price, to which the prices of all commodities are continually gravitating.”
— Adam Smith, The Wealth of Nations, Book I, Chapter 7

This is the invisible hand at work. And in this module, we are going to compute it.


Part II — The Computation

Setting Up

We need two Python libraries: numpy for numerical work and matplotlib for plotting. We’ll also use scipy.optimize to find equilibria numerically — the computational equivalent of Smith’s “gravitating” market price.

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import fsolve

Supply and Demand as Functions

Let’s start with the simplest possible model of a market — say, the market for oats in 18th-century Edinburgh.

Demand tells us how much buyers want at each price. When the price is high, fewer people buy; when the price is low, demand rises. We’ll model this as a straight line:

\[Q^D(P) = a - bP\]

Supply tells us how much sellers are willing to produce. When the price is high, it’s worth producing more; when the price is low, fewer sellers bother. Again, a straight line:

\[Q^S(P) = c + dP\]

Here \(a\), \(b\), \(c\), \(d\) are positive parameters. Let’s define these in Python:

# Parameters for Edinburgh's oat market
a = 200    # maximum demand (bushels per week) when price is zero
b = 4      # how much demand falls per shilling increase in price
c = 20     # minimum supply
d = 3      # how much supply rises per shilling increase in price

def demand(P):
    """Quantity demanded at price P."""
    return a - b * P

def supply(P):
    """Quantity supplied at price P."""
    return c + d * P

# Test: at a price of 20 shillings, how much is demanded and supplied?
P_test = 20
print(f"At P = {P_test} shillings:")
print(f"  Demand = {demand(P_test)} bushels")
print(f"  Supply = {supply(P_test)} bushels")

Plotting the Market

Economists plot supply and demand with price on the vertical axis and quantity on the horizontal axis (a tradition that goes back to Marshall — and which confuses every student, since we’re treating price as the independent variable but plotting it on the y-axis). Let’s follow convention:

P_range = np.linspace(0, 50, 200)

fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(demand(P_range), P_range, color='steelblue', linewidth=2, label='Demand')
ax.plot(supply(P_range), P_range, color='coral', linewidth=2, label='Supply')
ax.set_xlabel('Quantity (bushels per week)', fontsize=12)
ax.set_ylabel('Price (shillings)', fontsize=12)
ax.set_title("Edinburgh's Oat Market, c. 1770", fontsize=13)
ax.set_xlim(0, 220)
ax.set_ylim(0, 55)
ax.legend(fontsize=11)
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()

The curves cross — that’s where supply equals demand. That crossing point is the market equilibrium, and finding it is our computational task.

Excess Demand

The key idea is excess demand: the gap between what buyers want and what sellers offer at a given price.

\[ED(P) = Q^D(P) - Q^S(P)\]

  • If \(ED(P) > 0\): there’s a shortage — buyers want more than sellers offer. Prices tend to rise.
  • If \(ED(P) < 0\): there’s a surplus — sellers offer more than buyers want. Prices tend to fall.
  • If \(ED(P) = 0\): the market is in equilibrium.

This is exactly Smith’s gravitational logic, expressed as a function whose root gives us the equilibrium price.

def excess_demand(P):
    """Excess demand: positive means shortage, negative means surplus."""
    return demand(P) - supply(P)

# Plot excess demand
fig, ax = plt.subplots(figsize=(8, 4))
ax.plot(P_range, excess_demand(P_range), color='darkgreen', linewidth=2)
ax.axhline(0, color='black', linewidth=0.8)
ax.fill_between(P_range, excess_demand(P_range), 0,
                where=excess_demand(P_range) > 0, alpha=0.15, color='steelblue', label='Shortage')
ax.fill_between(P_range, excess_demand(P_range), 0,
                where=excess_demand(P_range) < 0, alpha=0.15, color='coral', label='Surplus')
ax.set_xlabel('Price (shillings)', fontsize=12)
ax.set_ylabel('Excess demand (bushels)', fontsize=12)
ax.set_title('Excess Demand Function', fontsize=13)
ax.legend(fontsize=11)
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()

Finding Equilibrium with fsolve

For this simple linear model, we could solve by hand:

\[a - bP = c + dP \implies P^* = \frac{a - c}{b + d}\]

But in more complex models — with nonlinear demand, multiple goods, taxes — an analytical solution may not exist. So we’ll use a numerical root-finder: scipy.optimize.fsolve.

fsolve takes a function and a starting guess, and finds a value where the function equals zero.

# Numerical solution
P_star = fsolve(excess_demand, x0=10)[0]  # x0=10 is our initial guess
Q_star = demand(P_star)

# Analytical solution for comparison
P_analytical = (a - c) / (b + d)
Q_analytical = demand(P_analytical)

print("Numerical solution:")
print(f"  P* = {P_star:.4f} shillings")
print(f"  Q* = {Q_star:.4f} bushels")
print(f"\nAnalytical solution:")
print(f"  P* = {P_analytical:.4f} shillings")
print(f"  Q* = {Q_analytical:.4f} bushels")
print(f"\nDifference: {abs(P_star - P_analytical):.2e}")

The numerical solution matches the analytical one (to machine precision). Now let’s visualise it:

fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(demand(P_range), P_range, color='steelblue', linewidth=2, label='Demand')
ax.plot(supply(P_range), P_range, color='coral', linewidth=2, label='Supply')
ax.plot(Q_star, P_star, 'ko', markersize=10, zorder=5)
ax.annotate(f'Equilibrium\nP* = {P_star:.1f}, Q* = {Q_star:.1f}',
            xy=(Q_star, P_star), xytext=(Q_star + 30, P_star + 8),
            fontsize=11, arrowprops=dict(arrowstyle='->', color='black'),
            bbox=dict(boxstyle='round,pad=0.3', facecolor='lightyellow', edgecolor='gray'))
ax.set_xlabel('Quantity (bushels per week)', fontsize=12)
ax.set_ylabel('Price (shillings)', fontsize=12)
ax.set_title("Smith's Invisible Hand: the Market Finds Equilibrium", fontsize=13)
ax.set_xlim(0, 220)
ax.set_ylim(0, 55)
ax.legend(fontsize=11)
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()

What Happens When the Government Intervenes? Price Floors

Smith was deeply sceptical of government interference in markets. Let’s see what happens when Edinburgh’s town council sets a price floor — a minimum legal price — for oats, perhaps to protect farmers.

If the floor is set above the equilibrium price, it creates a surplus: more is supplied than demanded.

P_floor = 35  # price floor at 35 shillings (above equilibrium)

Q_demanded_at_floor = demand(P_floor)
Q_supplied_at_floor = supply(P_floor)
surplus = Q_supplied_at_floor - Q_demanded_at_floor

print(f"Equilibrium price:   P* = {P_star:.1f} shillings")
print(f"Price floor:         P  = {P_floor} shillings")
print(f"Quantity demanded:   {Q_demanded_at_floor:.1f} bushels")
print(f"Quantity supplied:   {Q_supplied_at_floor:.1f} bushels")
print(f"Surplus (unsold):    {surplus:.1f} bushels")

# Visualise
fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(demand(P_range), P_range, color='steelblue', linewidth=2, label='Demand')
ax.plot(supply(P_range), P_range, color='coral', linewidth=2, label='Supply')
ax.axhline(P_floor, color='red', linestyle='--', linewidth=1.5, label=f'Price floor = {P_floor}')
ax.plot(Q_star, P_star, 'ko', markersize=8, zorder=5, label='Free-market equilibrium')

# Show the surplus as a bracket
ax.annotate('', xy=(Q_supplied_at_floor, P_floor - 1),
            xytext=(Q_demanded_at_floor, P_floor - 1),
            arrowprops=dict(arrowstyle='<->', color='red', lw=2))
ax.text((Q_demanded_at_floor + Q_supplied_at_floor) / 2, P_floor - 3.5,
        f'Surplus = {surplus:.0f}', ha='center', fontsize=11, color='red', fontweight='bold')

ax.set_xlabel('Quantity (bushels per week)', fontsize=12)
ax.set_ylabel('Price (shillings)', fontsize=12)
ax.set_title('Effect of a Price Floor: Unsold Oats', fontsize=13)
ax.set_xlim(0, 220)
ax.set_ylim(0, 55)
ax.legend(fontsize=10, loc='upper right')
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()

This is precisely what Smith warned about: the government, trying to help farmers by guaranteeing a high price, instead creates a pile of unsold oats and reduces the quantity actually traded. The invisible hand has been overruled — and the result is waste.

A Nonlinear Market: Why We Need Computers

The linear model above is useful for building intuition, but real markets are rarely linear. Let’s make things more interesting with a market where demand and supply are nonlinear:

\[Q^D(P) = \frac{500}{1 + 0.1P^{1.5}}\]

\[Q^S(P) = 10 \cdot \ln(1 + P)\]

Now there’s no neat algebraic solution — but fsolve handles it without breaking a sweat.

def demand_nonlinear(P):
    return 500 / (1 + 0.1 * P**1.5)

def supply_nonlinear(P):
    return 10 * np.log(1 + P)

def excess_demand_nonlinear(P):
    return demand_nonlinear(P) - supply_nonlinear(P)

# Solve
P_star_nl = fsolve(excess_demand_nonlinear, x0=20)[0]
Q_star_nl = demand_nonlinear(P_star_nl)

print(f"Nonlinear equilibrium:")
print(f"  P* = {P_star_nl:.4f}")
print(f"  Q* = {Q_star_nl:.4f}")

# Verify: excess demand at P* should be (essentially) zero
print(f"  Excess demand at P*: {excess_demand_nonlinear(P_star_nl):.2e}")

# Plot
P_vals = np.linspace(0.1, 80, 300)

fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(demand_nonlinear(P_vals), P_vals, color='steelblue', linewidth=2, label='Demand (nonlinear)')
ax.plot(supply_nonlinear(P_vals), P_vals, color='coral', linewidth=2, label='Supply (nonlinear)')
ax.plot(Q_star_nl, P_star_nl, 'ko', markersize=10, zorder=5)
ax.annotate(f'P* = {P_star_nl:.1f}, Q* = {Q_star_nl:.1f}',
            xy=(Q_star_nl, P_star_nl), xytext=(Q_star_nl + 25, P_star_nl + 10),
            fontsize=11, arrowprops=dict(arrowstyle='->', color='black'),
            bbox=dict(boxstyle='round,pad=0.3', facecolor='lightyellow', edgecolor='gray'))
ax.set_xlabel('Quantity', fontsize=12)
ax.set_ylabel('Price', fontsize=12)
ax.set_title('A Nonlinear Market — No Closed-Form Solution', fontsize=13)
ax.legend(fontsize=11)
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()

This is the power of computational thinking: Smith’s invisible hand works the same way whether the curves are straight lines or complicated nonlinear functions. The computer doesn’t care — it just finds the root.

Simulating the Invisible Hand: Convergence to Equilibrium

Smith described the market price “gravitating” toward the natural price. Let’s simulate that process. We’ll use a simple rule: if there’s excess demand (shortage), the price rises; if there’s excess supply (surplus), the price falls. The speed of adjustment is governed by a parameter \(\lambda\).

\[P_{t+1} = P_t + \lambda \cdot ED(P_t)\]

def simulate_market(P0, lam, T, ed_func):
    """
    Simulate price adjustment toward equilibrium.
    P0    : initial price
    lam   : adjustment speed
    T     : number of periods
    ed_func: excess demand function
    """
    prices = np.empty(T)
    prices[0] = P0
    for t in range(1, T):
        prices[t] = prices[t-1] + lam * ed_func(prices[t-1])
    return prices

# Try different starting prices
T = 50
lam = 0.05

fig, ax = plt.subplots(figsize=(9, 5))
for P0, color in [(5, 'steelblue'), (40, 'coral'), (15, 'seagreen')]:
    path = simulate_market(P0, lam, T, excess_demand)
    ax.plot(path, linewidth=2, color=color, label=f'Start P = {P0}')

ax.axhline(P_star, color='black', linestyle='--', linewidth=1, label=f'Equilibrium P* = {P_star:.1f}')
ax.set_xlabel('Time period', fontsize=12)
ax.set_ylabel('Price (shillings)', fontsize=12)
ax.set_title("The Invisible Hand at Work: Prices Gravitate to Equilibrium", fontsize=13)
ax.legend(fontsize=10)
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()

No matter where the price starts, it converges to the equilibrium. This is Smith’s insight, now visible as a computational simulation. The market corrects itself — shortages drive prices up, surpluses drive them down, and the invisible hand guides the economy toward balance.


Part III — Exercises

Now it’s your turn. These exercises ask you to apply the tools from Part II to new situations.

Exercise 1 — A Tax on Oats

The Scottish Parliament imposes a per-unit tax of \(\tau = 5\) shillings on each bushel of oats, paid by sellers. This shifts the supply curve up: sellers now need a price that is 5 shillings higher to supply the same quantity. The new supply function is:

\[Q^S_{\text{tax}}(P) = c + d(P - \tau)\]

(a) Define a new function supply_tax(P, tau=5) and a new excess demand function incorporating the tax.

(b) Use fsolve to find the new equilibrium price and quantity.

(c) Who bears more of the tax burden — buyers or sellers? Compute the price increase paid by buyers (\(P^*_{\text{tax}} - P^*\)) and the effective price decrease received by sellers (\(P^* - (P^*_{\text{tax}} - \tau)\)).

(d) Plot the old and new supply curves together with the demand curve, marking both equilibria.

# Your answer here

Exercise 2 — The Corn Laws

One of the great economic debates in British history concerned the Corn Laws — tariffs on imported grain that kept prices high, benefiting landowners but hurting urban workers and manufacturers. The Corn Laws were finally repealed in 1846, but the arguments for and against are pure Adam Smith.

Model two countries — Britain and France — each with a domestic oat market:

Britain France
Demand \(Q^D = 300 - 5P\) \(Q^D = 200 - 3P\)
Supply \(Q^S = 50 + 2P\) \(Q^S = 30 + 4P\)

(a) Find the equilibrium price in each country separately (in autarky — no trade).

(b) Which country has the lower equilibrium price? What does Smith’s logic say should happen when trade is allowed?

(c) Now suppose trade is allowed and a single world price prevails. The world excess demand is the sum of both countries’ excess demands. Find the world equilibrium price using fsolve.

(d) At the world price, how much does each country import or export? Does trade make both countries better off in terms of total quantity traded?

# Your answer here

Exercise 3 — Does the Starting Guess Matter?

Numerical methods need a starting point. For well-behaved functions this doesn’t matter much, but for complicated ones it can.

(a) Using the nonlinear excess demand function from Part II (excess_demand_nonlinear), try fsolve with starting guesses \(P_0 = 1, 10, 50, 100, 500\). Do all of them converge to the same solution? Print the result and the number of function evaluations for each (use fsolve(..., full_output=True)).

(b) Now try this pathological excess demand function:

\[ED(P) = \sin(P) - 0.1P + 1\]

Plot it for \(P \in [0, 30]\). How many roots does it have? Try fsolve from \(P_0 = 1, 5, 15, 25\) and report which root each finds.

(c) What lesson does this hold for computational economics? Write 2–3 sentences connecting this to Smith’s idea of the “natural price” — is there always just one?

# Your answer here

Part IV — Quiz

Test your understanding of both the history and the computation.

Conceptual Questions

Q1. What economic system was Adam Smith arguing against in The Wealth of Nations?

  1. Socialism
  2. Feudalism
  3. Mercantilism
  4. Communism

Q2. In Smith’s metaphor, the “invisible hand” refers to:

  1. Government regulation guiding the economy
  2. The tendency of self-interested actions to produce socially beneficial outcomes through markets
  3. The role of religious institutions in economic life
  4. The hidden power of banks and financial institutions

Q3. Smith’s “natural price” is closest in meaning to which modern concept?

  1. The GDP deflator
  2. The long-run equilibrium price
  3. The consumer price index
  4. The spot price on a commodity exchange

Q4. The Scottish Enlightenment was characterised by:

  1. A return to classical Greek philosophy
  2. An emphasis on empirical observation, scepticism, and systematic reasoning
  3. Rejection of all forms of commercial activity
  4. A focus on theological debate above all other inquiry

Q5. David Hume’s relationship to Adam Smith was that of:

  1. His doctoral supervisor
  2. His closest intellectual companion and friend
  3. His political opponent
  4. His publisher

Computational Questions

Q6. If demand is \(Q^D = 100 - 2P\) and supply is \(Q^S = 20 + 3P\), the equilibrium price is:

  1. 12
  2. 16
  3. 20
  4. 25

Q7. Excess demand is defined as \(ED(P) = Q^D(P) - Q^S(P)\). At equilibrium:

  1. \(ED(P) > 0\)
  2. \(ED(P) < 0\)
  3. \(ED(P) = 0\)
  4. \(ED(P)\) is undefined

Q8. scipy.optimize.fsolve finds a value where:

  1. A function reaches its maximum
  2. A function reaches its minimum
  3. A function equals zero
  4. A function’s derivative equals zero

Q9. A price floor set below the equilibrium price will:

  1. Create a shortage
  2. Create a surplus
  3. Have no effect on the market
  4. Eliminate all trade

Q10. When we simulate the invisible hand with \(P_{t+1} = P_t + \lambda \cdot ED(P_t)\), a larger \(\lambda\) means:

  1. The market adjusts more slowly
  2. The market adjusts more quickly
  3. The equilibrium price changes
  4. The demand curve shifts

Quiz Answers

Click to reveal answers

Q1. (c) Mercantilism — the dominant economic doctrine of Smith’s time, based on hoarding precious metals and government control of trade.

Q2. (b) The invisible hand describes how self-interested actions, channelled through competitive markets, produce outcomes that benefit society without any central planner.

Q3. (b) The long-run equilibrium price — the price determined by costs of production, to which the market price continually “gravitates.”

Q4. (b) Empirical observation, scepticism, and systematic reasoning were the hallmarks of Hume, Smith, and their Edinburgh contemporaries.

Q5. (b) Hume and Smith were lifelong friends and intellectual companions. Hume’s philosophy deeply influenced Smith’s economic thinking.

Q6. (b) 16 — Setting \(100 - 2P = 20 + 3P\) gives \(80 = 5P\), so \(P = 16\).

Q7. (c) \(ED(P) = 0\) — equilibrium is defined as the price where quantity demanded equals quantity supplied.

Q8. (c) fsolve is a root-finder: it finds where a function equals zero. (For minima/maxima, you’d use minimize.)

Q9. (c) A price floor below the equilibrium is not binding — the market price is already above the floor, so it has no effect.

Q10. (b) A larger \(\lambda\) means the price responds more strongly to excess demand in each period, so the market reaches equilibrium faster (though if \(\lambda\) is too large, the process can overshoot).


Further Reading

  • Smith, A. The Wealth of Nations (1776), Book I, Chapters 1–7. Available free online via econlib.org.
  • Heilbroner, R. The Worldly Philosophers, Chapter 3 (“The Wonderful World of Adam Smith”).
  • Broadie, A. The Scottish Enlightenment — for the intellectual world Smith inhabited.
  • Phillipson, N. Adam Smith: An Enlightened Life — the best modern biography.

Next week: The Division of Labour and the Pin Factory — Smith’s most famous example, and the logic of specialisation and trade.