Monocurl Essays
Series Download

Supply and demand: where a price comes from

Line up buyers by what they would pay and sellers by what they would accept. The price where the two counts match is the one that leaves nobody turned away.

21 min·High school and early college·

AssumesWhat slope means, and why y = mx + b is a lineSolving two equations at once: where lines meet

Eight buyers (blue staircase) and eight sellers (orange staircase) of one used textbook. As the price moves, the number who want to buy and the number who want to sell change. They are equal, at five each, only for prices between $50 and $55.
Monocurl source
let FH = BookFrame([-0.95, 0.15, 0], 4.3)
# the price moves in whole dollars, so the readout and the two counts always agree
let Sweep = |p| {
    let q = round(p)
    let d = count(SV, |v| v >= q)
    let s = count(SC, |c| c <= q)
    return [
        Market(FH, q),
        center{[2.7, 1.5, 0]} Note("price ($)", 0.74),
        center{[2.7, 1.08, 0]} scale{1.25} color{INK} Number(q, 0),
        center{[2.7, 0.4, 0]} Cap("want to buy", 0.74, AZURE),
        center{[2.7, -0.02, 0]} scale{1.25} color{AZURE} Number(d, 0),
        center{[2.7, -0.7, 0]} Cap("want to sell", 0.74, EMBER),
        center{[2.7, -1.12, 0]} scale{1.25} color{EMBER} Number(s, 0)
    ]
}
mesh plot = BookPlot(FH)
mesh stairs = [DStair(FH, SV), SStair(FH, SC)]
mesh sweep = Sweep(p: 22)

slide "sweep"
    play Wait(0.6)
    sweep.p = 78
    play Lerp(4.5, [&sweep], linear)
    play Wait(0.4)
    sweep.p = 52
    play Lerp(2.5, [&sweep])
    play Wait(1.8)

Uses the shared definitions for this lesson's figures.

Tickets for a 2000-seat concert go on sale at $80 and are gone within a minute. By the afternoon the same seats are listed on resale sites at $320. People blame greed, or bots, or a ticketing website that buckled. There is a plainer diagnosis, and to reach it we need to know where a price comes from in the first place.

So leave the concert for a few minutes and take a market small enough to count on your fingers. A calculus course requires a particular textbook. Eight students need a used copy, and eight students who finished the course last term each have one to sell. The copies are in the same condition, so nobody cares which one they get. What will a copy sell for?

Eight buyers and what each would pay

Ask each buyer privately for the most she would pay before giving up and making do with the library copy.

BuyerAnaBenChoDevEliFayGusHoa
Would pay up to$55$95$35$75$25$85$45$65

The number reflects her alternatives as much as her taste. Ben may be no keener on calculus than Eli; perhaps he has no time to sit in the library. All the model needs is the number itself.

Pause and try

If copies cost $60, which of the eight would buy? How many would buy at $30?

Show answerHide answer

At $60 the buyers are those willing to pay at least 60: Ben (95), Fay (85), Dev (75) and Hoa (65), so four copies. At $30 everyone buys except Eli (25), so seven copies.

Answering that question took a search through the table. Sorting the buyers from highest willingness to pay to lowest turns the search into reading a graph.

  1. The eight buyers in the order of the table: Ana, Ben, Cho, Dev, Eli, Fay, Gus, Hoa.
  2. Sort them from the highest willingness to pay to the lowest.
  3. Trace the tops of the bars. This staircase is the demand curve.
  4. Read it sideways. At a price of 60 dollars, four bars are tall enough: four copies are wanted.
Each bar is one buyer, as tall as the most that buyer would pay. Sorted from tallest to shortest, the tops of the bars form the demand curve: at any price, the number of bars reaching that height is the number of copies buyers want.
Monocurl source
let FB = BookFrame([0.2, 0.15, 0], 6.2)
let Bars = |t| block {
    for (i in range(0, 8)) {
        let v = VALS[i]
        let x = lerp(i, count(VALS, |u| u > v), t)
        . Region([at(FB, x + 0.1, 0), at(FB, x + 0.9, 0), at(FB, x + 0.9, v), at(FB, x + 0.1, v)], tint(AZURE, 0.32))
        . center{at(FB, x + 0.5, 9)} Cap(NAMES[i], 0.76, AZURE)
    }
}
mesh plot = BookPlot(FB)
mesh bars = Bars(t: 0)
mesh stair = []
mesh probe = []

slide "The eight buyers in the order of the table: Ana, Ben, Cho, Dev, Eli, Fay, Gus, Hoa."
    play Wait(0.5)

slide "Sort them from the highest willingness to pay to the lowest."
    bars.t = 1
    play Lerp(2)

slide "Trace the tops of the bars. This staircase is the demand curve."
    stair = DStair(FB, SV)
    play Write(1.2, [&stair])

slide "Read it sideways. At a price of 60 dollars, four bars are tall enough: four copies are wanted."
    bars = []
    play Fade(0.5, [&bars])
    probe = [
        Seg(at(FB, 0, 60), at(FB, 4, 60), LEAF, 4),
        stroke{LEAF, 2.5} dashed{[0.1, 0.08]} Line(at(FB, 4, 60), at(FB, 4, 0)),
        Pt(at(FB, 4, 60), LEAF, 0.1),
        center{at(FB, 5, 70)} Cap("4 copies", 0.76, LEAF)
    ]
    play Fade(0.6, [&probe])

Uses the shared definitions for this lesson's figures.

The two terms sound alike and mean different things, and a later section depends on the difference. “Quantity demanded” is a single number, such as 4 copies at $60. “Demand” is the entire staircase.

One oddity of the graph is a convention you will meet everywhere in economics: price goes on the vertical axis even though it is the input. To use the curve, start from a price on the left edge, move across until you hit the staircase, and read the quantity below.

Eight sellers and what each would accept

Each seller also has a private number: the lowest price she would take. Below it she would sooner keep the book. Call that her cost of selling. The eight sellers’ costs are $10, $20, $30, $40, $50, $60, $70 and $80, and a seller sells when the price is at or above her cost.

The eight sellers sorted from the lowest cost to the highest. The tops of the bars form the supply curve: at any price, the number of bars no taller than the price is the number of copies offered.
The eight sellers sorted from the lowest cost to the highest. The tops of the bars form the supply curve: at any price, the number of bars no taller than the price is the number of copies offered.
Monocurl source
let FS = BookFrame([0.2, 0.15, 0], 6.2)
mesh plot = BookPlot(FS)
mesh bars = block {
    for (i in range(0, 8)) {
        . Region([at(FS, i + 0.1, 0), at(FS, i + 0.9, 0), at(FS, i + 0.9, SC[i]), at(FS, i + 0.1, SC[i])], tint(EMBER, 0.3))
    }
}
mesh stair = SStair(FS, SC)
mesh probe = [
    Seg(at(FS, 0, 60), at(FS, 6, 60), LEAF, 4),
    stroke{LEAF, 2.5} dashed{[0.1, 0.08]} Line(at(FS, 6, 60), at(FS, 6, 0)),
    Pt(at(FS, 6, 60), LEAF, 0.1),
    center{at(FS, 3, 70)} Cap("6 copies", 0.76, LEAF)
]

Uses the shared definitions for this lesson's figures.

The quantity supplied $Q_s(p)$ is the number of units sellers want to sell at price $p$, and supply is the whole relationship. This staircase climbs, because a higher price satisfies more sellers.

Before putting the two staircases together, here is what has been assumed. Every statement that follows is a statement about this model.

  • One homogeneous good. The copies are interchangeable, so only the price matters.
  • Unit trades. Each buyer wants one copy and each seller has one.
  • Price-taking. There is one going price, and each person decides only whether to trade at it. Nobody thinks she can move it alone.
  • Everything else fixed. Willingness to pay and costs stay put while we vary the price. Economists say ceteris paribus, “other things equal”.
  • Voluntary trade. Nobody can be made to buy or sell.

The price at which the two counts agree

Pause and try

Someone posts a notice: “used calculus books, $30 each”. Count the buyers who want a copy at that price and the sellers willing to part with one. Who ends up disappointed? Then look for a price at which nobody would be.

Show answerHide answer

At $30, seven buyers want a copy (all but Eli) and three sellers are willing (costs 10, 20, 30). Only three trades can happen, so four buyers who wanted a book at $30 go without. At $50 the willing buyers are Ben, Fay, Dev, Hoa and Ana, and the willing sellers are those with costs 10 to 50: five and five. Any price from $50 to $55 gives the same two lists.

Price$20$30$40$50$60$70$80
Quantity demanded8765432
Quantity supplied2345678
Copies traded2345432

The last row is the smaller of the two above it. Since nobody can be forced to trade, the scarcer side decides how many trades happen. Trade is largest at $50, the one column in which the counts agree.

  1. At 30 dollars, seven copies are wanted and three are offered. Four willing buyers go without.
  2. At 72 dollars, seven copies are offered and three are wanted. Four willing sellers find no buyer.
  3. At 52 dollars, five are wanted and five are offered. Everyone who wants to trade can.
The book market at three prices. The red bar is the gap between the number of copies wanted and the number offered. Only between $50 and $55 is there no gap.
Monocurl source
let FM = BookFrame([0.2, 0.15, 0], 6.2)
mesh plot = BookPlot(FM)
mesh stairs = [DStair(FM, SV), SStair(FM, SC)]
mesh mk = []
mesh notes = []

slide "At 30 dollars, seven copies are wanted and three are offered. Four willing buyers go without."
    mk = Market(FM, p: 30)
    notes = [center{at(FM, 5, 11)} Cap("4 too few", 0.76, ROSE)]
    play Fade(0.6)

slide "At 72 dollars, seven copies are offered and three are wanted. Four willing sellers find no buyer."
    notes = []
    play Fade(0.3, [&notes])
    mk.p = 72
    play Lerp(1.6, [&mk])
    notes = [center{at(FM, 5, 90)} Cap("4 too many", 0.76, ROSE)]
    play Fade(0.4, [&notes])

slide "At 52 dollars, five are wanted and five are offered. Everyone who wants to trade can."
    notes = []
    play Fade(0.3, [&notes])
    mk.p = 52
    play Lerp(1.6, [&mk])
    notes = [center{at(FM, 7, 45)} Cap("5 and 5", 0.76, LEAF)]
    play Fade(0.4, [&notes])

Uses the shared definitions for this lesson's figures.

A price of $30 would not last, because four buyers are shut out, and at least one of them is willing to pay $65 or more, because only three of the seven hopefuls (Ana, Gus and Cho) have a willingness to pay below that. Say it is Hoa. She would gladly pay $45 to the seller whose cost is $40, and that seller would gladly accept. Both are better off than under the posted price, where neither trades. So the $30 price is broken by a buyer who offers more. At $72 the pressure runs the other way. Four willing sellers find no buyer, and at least one of them has a cost of $40 or less. She offers her copy for $60, and Hoa, who would not pay $72, takes it. At $52 no such deal exists. The buyers left out value the book at $45 or less, the sellers left out need $60 or more, and no price pleases both.

What we noticed in the table holds for any lists of numbers.

Match the parts to the book market. There $q^* = 5$, because $v_5 = 55 > c_5 = 50$ while $v_6 = 45 < c_6 = 60$. Part 2 is the four disappointed buyers at $30. Part 3 is Hoa and the $40 seller: at any price below $c_5 = 50$ fewer than five sellers are willing, at any price above $v_5 = 55$ fewer than five buyers are, and in both cases a trade that would help two people goes unmade.

Be clear about the status of these claims. The theorem compares prices; it is arithmetic inside the model and it is proved. The claim that real prices move to the clearing level is a claim about behavior, and the model contains no mechanism for it. The Hoa story makes it plausible. The evidence is experimental. In classroom markets that Vernon Smith reported in 1962, and in many repetitions since, students were given private values and costs like our table and allowed to call out bids and offers, and trading prices typically settled near the clearing price within a few rounds.

From staircases to curves

Eight buyers left a $5 range of clearing prices. That slack is an artifact of the small numbers.

  1. Eight on each side: steps of 10 dollars, and any price from 50 to 55 dollars clears the market.
  2. Eighty on each side: steps of 1 dollar. The clearing prices run only from 50 to 50.50 dollars.
  3. Eight hundred on each side: steps of 10 cents, and 500 copies trade at a price within a nickel of 50 dollars.
The same market with 8, 80 and 800 traders on each side, their values and costs spread evenly over the same ranges. As the steps shrink, the staircases become indistinguishable from two straight lines that cross at $50.
Monocurl source
let StairsN = |f, n| [
    DStair(f, map(range(1, n + 1), |k| 100 - (k - 0.5) * 80 / n), AZURE, 3.5),
    SStair(f, map(range(1, n + 1), |k| k * 80 / n), EMBER, 3.5)
]
let FN = |n| Frame(0, n, 0, 100, [0.2, 0.15, 0], 6.2, 2.9)
let PlotN = |n, ydx| Plot(FN(n), map([1, 2, 3, 4], |k| k * n / 4), [20, 40, 60, 80, 100], "copies of the book", "price (dollars per copy)", 1.25, ydx)
mesh plot = PlotN(8, 0.36)
mesh stairs = StairsN(FN(8), 8)
mesh notes = [center{[fx(FN(8), 6.4), fy(FN(8), 100) + 0.32, 0]} Cap("8 buyers, 8 sellers", 0.76, INK)]

slide "Eight on each side: steps of 10 dollars, and any price from 50 to 55 dollars clears the market."
    play Wait(0.5)

slide "Eighty on each side: steps of 1 dollar. The clearing prices run only from 50 to 50.50 dollars."
    plot = []
    stairs = []
    notes = []
    play Fade(0.4)
    plot = PlotN(80, 0.36)
    stairs = StairsN(FN(80), 80)
    notes = [center{[fx(FN(8), 6.4), fy(FN(8), 100) + 0.32, 0]} Cap("80 buyers, 80 sellers", 0.76, INK)]
    play Fade(0.6)

slide "Eight hundred on each side: steps of 10 cents, and 500 copies trade at a price within a nickel of 50 dollars."
    plot = []
    stairs = []
    notes = []
    play Fade(0.4)
    plot = PlotN(800, 0.36)
    stairs = StairsN(FN(800), 800)
    notes = [center{[fx(FN(8), 6.4), fy(FN(8), 100) + 0.32, 0]} Cap("800 buyers, 800 sellers", 0.76, INK)]
    play Fade(0.6)

Uses the shared definitions for this lesson's figures.

With 800 traders on each side the staircases are, to within a few cents, the straight lines

$$ Q_d = 1000 - 10P \quad (20 \le P \le 100), \qquad Q_s = 10P \quad (0 \le P \le 80), $$

where $P$ is the price in dollars and quantities are copies per term. The coefficients are slopes: each extra dollar on the price loses 10 buyers and brings in 10 sellers. This is why economists draw demand and supply as smooth curves. A curve is a staircase with too many steps to see.

A change in demand is not a change in quantity demanded

Next term the course enrolls more students, and at every price 200 more copies are wanted than before. Nothing about the sellers has changed.

Pause and try

The new demand is $Q_d = 1200 - 10P$ and supply is still $Q_s = 10P$. Find the new clearing price and quantity. Did the quantity supplied change? Did supply?

Show answerHide answer

$1200 - 10P = 10P$ gives $P = 60$ and $Q = 600$. The quantity supplied rose from 500 to 600 copies, because the higher price satisfies 100 more sellers. Supply, the relationship $Q_s = 10P$, is exactly what it was.

Demand rises by 200 copies at every price, so the demand line slides to the right. The supply line does not move. The crossing point climbs along the supply line from $50 and 500 copies to $60 and 600 copies.
Monocurl source
let Shift = |k| {
    let p = (1000 + k) / 20
    let pr = round(p)
    return [
        Seg(at(FL, k, 100), at(FL, 800 + k, 20), AZURE, 4.5),
        stroke{SLATE, 2} dashed{[0.1, 0.08]} Line(at(FL, 0, p), at(FL, 10 * p, p)),
        stroke{SLATE, 2} dashed{[0.1, 0.08]} Line(at(FL, 10 * p, p), at(FL, 10 * p, 0)),
        Pt(at(FL, 10 * p, p), LEAF, 0.11),
        center{[2.7, 1.5, 0]} Note("price ($)", 0.74),
        center{[2.7, 1.08, 0]} scale{1.25} color{INK} Number(pr, 0),
        center{[2.7, 0.3, 0]} Note("copies traded", 0.74),
        center{[2.7, -0.12, 0]} scale{1.25} color{INK} Number(10 * pr, 0)
    ]
}
mesh plot = LinPlot(FL)
mesh ghost = stroke{tint(AZURE, 0.45), 3} dashed{[0.12, 0.08]} Line(at(FL, 0, 100), at(FL, 800, 20))
mesh supply = Seg(at(FL, 0, 0), at(FL, 800, 80), EMBER, 4.5)
mesh names = [
    center{at(FL, 900, 72)} Cap("supply", 0.74, EMBER),
    center{[2.7, -0.9, 0]} Cap("demand", 0.74, AZURE),
    center{[2.7, -1.25, 0]} Note("shifts right", 0.72)
]
mesh shift = Shift(k: 0)

slide "shift"
    play Wait(1)
    shift.k = 200
    play Lerp(4, [&shift])
    play Wait(2)

Uses the shared definitions for this lesson's figures.

Here the distinction from earlier does its work.

The rise in enrollment was a change in demand. It caused a change in price, which caused a change in quantity supplied. Each curve answers “what if only the price changed?”, so a price change can never shift either of them.

A price ceiling

Suppose the student union, wanting books to be affordable, rules that no used copy may sell for more than $30.

Pause and try

In the campus market, how many copies are wanted at $30, and how many are offered? How many students who would have bought a book at the clearing price of $50 now cannot get one?

Show answerHide answer

$Q_d = 1000 - 300 = 700$ and $Q_s = 300$. There is a shortage of 400 copies. Only 300 copies trade. Of the 500 students who would have bought at $50, at least 200 go without, and more than 200 if some of the 300 copies go to students outside that group. Trade has fallen by 200 copies even though 200 more students now want one.

A legal maximum price is lowered from $50 to $30. Sellers offer fewer copies and buyers want more, and the shortage (red) widens to 400 copies.
Monocurl source
let Cap30 = |c| block {
    let cr = round(c)
    . [
    Seg(at(FL, 0, c), at(FL, 1000, c), ROSE, 3),
    Seg(at(FL, 10 * c, c), at(FL, 1000 - 10 * c + 0.5, c), ROSE, 8),
    Pt(at(FL, 10 * c, c), EMBER, 0.1),
    Pt(at(FL, 1000 - 10 * c, c), AZURE, 0.1),
    center{[2.7, 1.55, 0]} Cap("offered", 0.74, EMBER),
    center{[2.7, 1.15, 0]} scale{1.25} color{EMBER} Number(10 * cr, 0),
    center{[2.7, 0.45, 0]} Cap("wanted", 0.74, AZURE),
    center{[2.7, 0.05, 0]} scale{1.25} color{AZURE} Number(1000 - 10 * cr, 0),
    center{[2.7, -0.65, 0]} Cap("shortage", 0.74, ROSE),
    center{[2.7, -1.05, 0]} scale{1.25} color{ROSE} Number(1000 - 20 * cr, 0)
    ]
}
mesh plot = LinPlot(FL)
mesh lines = [
    Seg(at(FL, 0, 100), at(FL, 800, 20), AZURE, 4.5),
    Seg(at(FL, 0, 0), at(FL, 800, 80), EMBER, 4.5),
    center{at(FL, 310, 90)} Cap("demand", 0.74, AZURE),
    center{at(FL, 900, 72)} Cap("supply", 0.74, EMBER)
]
mesh ceiling = Cap30(c: 50)

slide "lower"
    play Wait(1)
    ceiling.c = 30
    play Lerp(4, [&ceiling])
    play Wait(2)

Uses the shared definitions for this lesson's figures.

The 300 students who get a book pay $20 less than before, and they are better off. But the price no longer decides who those 300 are. Something else has to: who saw the notice first, who knows a seller, who is willing to slip the seller an extra $20. And since fewer than $q^* = 500$ trades take place, part 3 of the theorem applies. Some student who would pay more than $50 has no book while an owner who would sell for $35 keeps hers, and the rule forbids the trade that would help both.

Now return to the concert. The hall has 2000 seats whatever the price, so supply is a vertical line. Suppose the number of tickets fans want is $Q_d = 10000 - 25P$.

The concert. Supply is 2000 seats at any price. At the $80 face price fans want 8000 tickets, a shortage of 6000. The price at which exactly 2000 are wanted is $320.
The concert. Supply is 2000 seats at any price. At the $80 face price fans want 8000 tickets, a shortage of 6000. The price at which exactly 2000 are wanted is $320.
Monocurl source
let FC = Frame(0, 10000, 0, 400, [0.25, 0.15, 0], 6.1, 2.9)
mesh plot = Plot(FC, [2000, 4000, 6000, 8000, 10000], [80, 160, 240, 320, 400], "tickets", "price (dollars per ticket)", 1.3, 0.42)
mesh lines = [
    Seg(at(FC, 0, 400), at(FC, 10000, 0), AZURE, 4.5),
    Seg(at(FC, 2000, 0), at(FC, 2000, 400), EMBER, 4.5)
]
mesh face = [
    Seg(at(FC, 0, 80), at(FC, 10000, 80), ROSE, 2.5),
    Seg(at(FC, 2000, 80), at(FC, 8000, 80), ROSE, 8),
    Pt(at(FC, 8000, 80), AZURE, 0.1),
    Pt(at(FC, 2000, 80), EMBER, 0.1),
    Pt(at(FC, 2000, 320), LEAF, 0.12)
]
mesh labels = [
    center{[fx(FC, 7300), fy(FC, 400) + 0.32, 0]} Cap("shortage at $80: 6000 tickets", 0.76, ROSE),
    center{at(FC, 3000, 352)} Cap("$320", 0.76, LEAF),
    center{at(FC, 7300, 200)} Cap("demand", 0.74, AZURE),
    center{at(FC, 2950, 200)} Cap("2000 seats", 0.74, EMBER)
]

Uses the shared definitions for this lesson's figures.

So nothing broke. A price set well below the clearing level produces a shortage as a matter of arithmetic, and a shortage produces a scramble and a second market. The demand numbers here are invented to fit the story, and the model is silent on why a promoter would choose $80. Loyalty to fans, fear of looking greedy and the hope of selling merchandise have all been proposed, and deciding among them takes evidence.

What the model leaves out

Each assumption fails somewhere. Used cars are not homogeneous, and a buyer who cannot judge quality behaves differently from Ben. A town with one employer or one pharmacy has a trader who sets the price and knows it. And “other things equal” is a discipline: every prediction has the form “if only this changes, then that follows”. The model is also silent about whether a clearing price is fair. Eli, who could pay only $25, has no book at $52, and whether that is acceptable is a question the arithmetic cannot answer.

Check yourself

A frost in Brazil raises the price of coffee. Tea is a substitute for coffee. In the market for tea, what happens?

The hard part of this lesson was keeping a number apart from a curve. A price selects one point on each curve, a clearing price is where those points coincide, and events outside the market move a whole curve and drag the crossing point with it. The next lesson asks how strongly quantity responds to price, which decides whether a seller who raises her price ends up with more revenue or less.

Problems

The first three repeat the lesson’s moves, the next three combine them, and the last two ask for an argument.

Problem 1

Five buyers would pay up to $12, $10, $9, $7 and $4 for a concert poster. Five sellers would accept no less than $3, $5, $6, $8 and $11. Find $q^*$, the quantity demanded and supplied at $7.50, and all market-clearing prices.

Show solutionHide solution

Compare in order: $12 > 3$, $10 > 5$, $9 > 6$, but $7 < 8$. So $q^* = 3$. At $7.50 the willing buyers are those at 12, 10 and 9, and the willing sellers are those at 3, 5 and 6, so $Q_d = Q_s = 3$ and $7.50 clears the market. The counts stay at three and three for every price above 7 and below 8. At exactly $7 the fourth buyer is also willing ($Q_d = 4$), and at exactly $8 the fourth seller is ($Q_s = 4$), so the clearing prices are those strictly between $7 and $8.

Problem 2

Demand for a brand of notebook is $Q_d = 600 - 20P$ and supply is $Q_s = 40P - 120$, with $P$ in dollars and quantities in notebooks per week. Find the equilibrium.

Show solutionHide solution

Set $600 - 20P = 40P - 120$. Then $720 = 60P$, so $P = 12$, and $Q = 600 - 240 = 360$. Check with supply: $40 \times 12 - 120 = 360$.

Problem 3

In the notebook market of the previous problem, a ceiling of $9 is imposed. Find the shortage and the number traded. What would a ceiling of $15 do?

Show solutionHide solution

At $9, $Q_d = 600 - 180 = 420$ and $Q_s = 360 - 120 = 240$. The shortage is 180 notebooks and 240 are traded, down from 360. A ceiling of $15 is above the clearing price of $12, so it is not binding and the market stays at $12 and 360.

Problem 4

For each event, say whether it is a change in demand, in quantity demanded, in supply or in quantity supplied in the used-textbook market: (a) the professor makes the book optional; (b) the price falls from $50 to $45 and more students buy; (c) a campus bookstore starts paying $10 more for returned copies, so owners are less eager to sell to students; (d) after (a), fewer owners bother to sell.

Show solutionHide solution

(a) A change in demand: fewer copies are wanted at every price, so the curve shifts left. (b) A change in quantity demanded: a movement along the demand curve caused by the book’s own price. (c) A change in supply: every owner’s cost of selling to a student rises, so fewer are offered at each price and the curve shifts left. (d) A change in quantity supplied: the fall in demand lowers the price, and sellers move down along an unchanged supply curve.

Problem 5

A price floor is a legal minimum price. In the campus market ($Q_d = 1000 - 10P$, $Q_s = 10P$), a floor of $70 is imposed. Find the quantity traded and the excess supply. Who is left disappointed?

Show solutionHide solution

At $70, $Q_d = 1000 - 700 = 300$ and $Q_s = 700$. Buyers are the scarcer side, so 300 copies trade and the excess supply is 400. The disappointed are 400 owners willing to sell at $70 who find no buyer. Trade is 300, the same as under the $30 ceiling: a price on either side of $50 reduces trade, because one side or the other withdraws.

Problem 6

In the campus market, enrollment adds 200 buyers at every price and, in the same term, a graduating class adds 200 sellers at every price. Find the new equilibrium and explain why the direction of the price change could not have been predicted from the directions of the shifts alone.

Show solutionHide solution

The new curves are $Q_d = 1200 - 10P$ and $Q_s = 10P + 200$. Setting them equal, $1000 = 20P$, so $P = 50$ and $Q = 700$. The price is unchanged and the quantity is up by 200. More demand pushes the price up, more supply pushes it down, and here the two pushes are equal. If supply had risen by 100 instead, $1100 = 20P$ gives $P = 55$; if by 300, $P = 45$. Both shifts raise the quantity, so that direction is certain, but the price depends on their sizes.

Problem 7

A newspaper writes: “Rents rose this year because of higher demand for apartments. But as rents rise, demand will fall, and so rents will soon come back down.” Find the error and say what the supply and demand model predicts.

Show solutionHide solution

The first sentence describes a shift of the demand curve to the right. The second uses “demand will fall” for the response of renters to a higher price, which is a fall in quantity demanded along the new curve. That movement is already part of the adjustment to the new crossing point; it does not shift the curve back. The model predicts that rents stay at the new, higher level until something else changes, for instance new building, which would be a shift in supply.

Problem 8

In the eight-student market, the price is capped at $30 and the three sellers with costs 10, 20 and 30 sell. Define the gain from a trade as the buyer’s willingness to pay minus the seller’s cost. (a) Find the total gain if the three books go to Ben, Fay and Dev. (b) Find it if they go to Ana, Gus and Cho. (c) Find the total gain at a clearing price. (d) In case (b), describe a resale that benefits both parties.

Show solutionHide solution

The three sellers’ costs total $10 + 20 + 30 = 60$. (a) $95 + 85 + 75 - 60 = 195$. (b) $55 + 45 + 35 - 60 = 75$. (c) At a clearing price the five highest-value buyers trade with the five lowest-cost sellers: $(95 + 85 + 75 + 65 + 55) - (10 + 20 + 30 + 40 + 50) = 375 - 150 = 225$. The price itself does not appear, because what the buyer pays the seller receives. (d) Cho values her copy at $35 and Ben would pay $95. If Ben buys it from her for $60, she gains $25 and he gains $35 compared with not trading. That resale is the concert’s secondary market in miniature, and it moves the total from the outcome in (b) toward the one in (a). Even (a) falls short of 225, because under the cap only three books change hands.

Shared definitions used by this lesson's figures
# house kit: prepended to every essay figure after the std imports

# palette. AZURE and EMBER are the two actors, LEAF marks an answer, ROSE a problem
let PAPER = [1, 1, 1, 1]
let INK = [0.08, 0.09, 0.11, 1]
let SLATE = [0.40, 0.44, 0.50, 1]
let MIST = [0.85, 0.86, 0.88, 1]
let AZURE = [0.13, 0.42, 0.68, 1]
let EMBER = [0.89, 0.42, 0.12, 1]
let LEAF = [0.13, 0.55, 0.36, 1]
let ROSE = [0.78, 0.22, 0.24, 1]
let PLUM = [0.47, 0.30, 0.66, 1]
let GOLD = [0.85, 0.62, 0.08, 1]

background = PAPER

# an opaque pastel of col; use for fills so overlaps do not darken
let tint = |col, amount = 0.18| [
    1 - (1 - col[0]) * amount,
    1 - (1 - col[1]) * amount,
    1 - (1 - col[2]) * amount,
    1
]

# text: Cap for labels, Note for quiet labels, Math for typeset maths
let Cap = |txt, size = 0.75, col = INK| color{col} Text(txt, size, "Charter")
let Note = |txt, size = 0.65| color{SLATE} Text(txt, size, "Charter")
let Math = |tex, size = 0.9, col = INK| color{col} Tex(tex, size)

# a paper rectangle to sit behind text that crosses lines
let Plate = |pos, size| center{pos} fill{PAPER} stroke{alpha{0} PAPER, 0} Rect(size)

# shapes with fill and stroke both set, so no stray black appears
let Pt = |pos, col = INK, r = 0.075| center{pos} fill{col} stroke{col, 1} Circle(r, 48)
let Ring = |pos, col = INK, r = 0.1, w = 3| center{pos} fill{PAPER} stroke{col, w} Circle(r, 48)
let Seg = |a, b, col = INK, w = 3| stroke{col, w} Line(a, b)
let Path = |pts, col = INK, w = 3| stroke{col, w} Polyline(pts)
let Region = |pts, col| fill{col} stroke{alpha{0} col, 0} Polygon(pts)
let Outline = |pts, col = INK, w = 3| fill{alpha{0} PAPER} stroke{col, w} Polygon(pts)
let Shape = |pts, col, amount = 0.18, w = 3| fill{tint(col, amount)} stroke{col, w} Polygon(pts)
let Disc = |pos, r, col, amount = 0.18, w = 3| center{pos} fill{tint(col, amount)} stroke{col, w} Circle(r, 96)
let Box = |pos, size, col, amount = 0.18, w = 3| center{pos} fill{tint(col, amount)} stroke{col, w} Rect(size)
# a line from a to b ending in a small solid arrowhead
let Tip = |a, b, col = INK, w = 3, head = 0.17| {
    let d = normalize([b[0] - a[0], b[1] - a[1], 0])
    let n = [-d[1], d[0], 0]
    let base = [b[0] - d[0] * head, b[1] - d[1] * head, 0]
    return [
        stroke{col, w} Line(a, base),
        fill{col} stroke{col, 1} Polygon([
            b,
            [base[0] + n[0] * head * 0.42, base[1] + n[1] * head * 0.42, 0],
            [base[0] - n[0] * head * 0.42, base[1] - n[1] * head * 0.42, 0]
        ])
    ]
}

# plots. a frame is [x0, x1, y0, y1, centre, width, height]: a data window and the scene box it fills
let Frame = |x0, x1, y0, y1, c = [0, 0, 0], w = 6.4, h = 3.6| [x0, x1, y0, y1, c, w, h]
let fx = |fr, x| fr[4][0] + (x - (fr[0] + fr[1]) / 2) * fr[5] / (fr[1] - fr[0])
let fy = |fr, y| fr[4][1] + (y - (fr[2] + fr[3]) / 2) * fr[6] / (fr[3] - fr[2])
let at = |fr, x, y| [fx(fr, x), fy(fr, y), 0]

# axes through the data origin (or the nearest edge of the window), with optional names
let Axes = |fr, x_name = "", y_name = "", col = SLATE| {
    let ox = clamp(fr[0], 0, fr[1])
    let oy = clamp(fr[2], 0, fr[3])
    var parts = [
        Tip(at(fr, fr[0], oy), [fx(fr, fr[1]) + 0.25, fy(fr, oy), 0], col, 2.5, 0.15),
        Tip(at(fr, ox, fr[2]), [fx(fr, ox), fy(fr, fr[3]) + 0.25, 0], col, 2.5, 0.15)
    ]
    if (x_name != "") {
        parts .= center{[fx(fr, fr[1]) + 0.5, fy(fr, oy), 0]} Math(x_name, 0.8, col)
    }
    if (y_name != "") {
        parts .= center{[fx(fr, ox), fy(fr, fr[3]) + 0.5, 0]} Math(y_name, 0.8, col)
    }
    return parts
}

# tick marks with numbers at the listed data values
let XTicks = |fr, xs, col = SLATE, places = 0| block {
    let oy = fy(fr, clamp(fr[2], 0, fr[3]))
    for (x in xs) {
        . Seg([fx(fr, x), oy - 0.07, 0], [fx(fr, x), oy + 0.07, 0], col, 2)
        . center{[fx(fr, x), oy - 0.33, 0]} Math(to_string(x, places), 0.72, col)
    }
}
let YTicks = |fr, ys, col = SLATE, places = 0| block {
    let ox = fx(fr, clamp(fr[0], 0, fr[1]))
    for (y in ys) {
        . Seg([ox - 0.07, fy(fr, y), 0], [ox + 0.07, fy(fr, y), 0], col, 2)
        . center{[ox - 0.36, fy(fr, y), 0]} Math(to_string(y, places), 0.72, col)
    }
}

# faint grid lines at the listed data values
let GridLines = |fr, xs, ys, col = MIST| block {
    for (x in xs) {
        . Seg(at(fr, x, fr[2]), at(fr, x, fr[3]), col, 1.5)
    }
    for (y in ys) {
        . Seg(at(fr, fr[0], y), at(fr, fr[1], y), col, 1.5)
    }
}

# the graph of f over [a, b], drawn in the frame. values are clamped to the window
let Graph = |fr, f, a, b, col = AZURE, w = 4, n = 160|
    stroke{col, w} Polyline(map(sample(a, b, n), |x| at(fr, x, clamp(fr[2], f(x), fr[3]))))

# the region between the graph of f and the x axis over [a, b]
let AreaUnder = |fr, f, a, b, col = AZURE, amount = 0.2, n = 80| {
    var pts = [at(fr, a, 0)]
    for (x in sample(a, b, n)) {
        pts .= at(fr, x, clamp(fr[2], f(x), fr[3]))
    }
    pts .= at(fr, b, 0)
    return fill{tint(col, amount)} stroke{alpha{0} col, 0} Polygon(pts)
}

# the book market: what each of eight buyers would pay, and what each of eight sellers would accept (dollars)
let NAMES = ["A", "B", "C", "D", "E", "F", "G", "H"]
let VALS = [55, 95, 35, 75, 25, 85, 45, 65]
let SV = [95, 85, 75, 65, 55, 45, 35, 25]
let SC = [10, 20, 30, 40, 50, 60, 70, 80]
# plot furniture: grid, left and bottom edges, numbers along the edges, axis names
let Plot = |f, gx, gy, xname, yname, ynx = 1.0, ydx = 0.36, vx = nil| block {
    var vs = vx
    if (vx == nil) { vs = gx }
    . GridLines(f, vs, gy)
    . Path([at(f, f[0], f[3]), at(f, f[0], f[2]), at(f, f[1], f[2])], SLATE, 2.5)
    for (x in gx) {
        . center{[fx(f, x), fy(f, f[2]) - 0.3, 0]} Math(to_string(x, 0), 0.72, SLATE)
    }
    for (y in gy) {
        . center{[fx(f, f[0]) - ydx, fy(f, y), 0]} Math(to_string(y, 0), 0.72, SLATE)
    }
    . center{[(fx(f, f[0]) + fx(f, f[1])) / 2, fy(f, f[2]) - 0.66, 0]} Note(xname, 0.72)
    . center{[fx(f, f[0]) + ynx, fy(f, f[3]) + 0.32, 0]} Note(yname, 0.72)
}
# demand staircase from values sorted high to low; supply staircase from costs sorted low to high
let DStair = |f, vs, col = AZURE, w = 4| {
    var pts = []
    for (i in range(0, len(vs))) {
        pts .= at(f, i, vs[i])
        pts .= at(f, i + 1, vs[i])
    }
    pts .= at(f, len(vs), 0)
    return stroke{col, w} Polyline(pts)
}
let SStair = |f, cs, col = EMBER, w = 4| {
    var pts = [at(f, 0, 0)]
    for (i in range(0, len(cs))) {
        pts .= at(f, i, cs[i])
        pts .= at(f, i + 1, cs[i])
    }
    pts .= at(f, len(cs), f[3])
    return stroke{col, w} Polyline(pts)
}
# the going price p: who wants to buy, who wants to sell, and the gap between the counts
let Market = |f, p| {
    let d = count(SV, |v| v >= p)
    let s = count(SC, |c| c <= p)
    var out = [Seg(at(f, 0, p), at(f, 8, p), SLATE, 2.5)]
    if (d != s) {
        out .= Seg(at(f, min(d, s), p), at(f, max(d, s), p), ROSE, 7)
    }
    out .= Pt(at(f, d, p), AZURE, 0.1)
    out .= Pt(at(f, s, p), EMBER, 0.1)
    if (d == s) {
        out .= Pt(at(f, d, p), LEAF, 0.12)
    }
    return out
}
let BookFrame = |c, w| Frame(0, 8, 0, 100, c, w, 2.9)
let BookPlot = |f| Plot(f, [1, 2, 3, 4, 5, 6, 7, 8], [20, 40, 60, 80, 100], "copies of the book", "price (dollars per copy)", 1.25, 0.36, [2, 4, 6, 8])
# the campus market: straight-line demand and supply, quantity in copies, price in dollars
let FL = Frame(0, 1000, 0, 100, [-0.95, 0.15, 0], 4.3, 2.9)
let LinPlot = |f| Plot(f, [200, 400, 600, 800, 1000], [20, 40, 60, 80, 100], "copies per term", "price (dollars per copy)", 1.25, 0.42)