How a Macro Model Works

Models: inputs and outputs

A model is a rule that turns exogenous variables (fed in from outside) into endogenous variables (solved inside).

  • Endogenous = determined by the model — here, the equilibrium price \(P\) and quantity \(Q\).
  • Exogenous = taken as given — here, buyers’ income and the input price.
  • Comparative statics = how the solution moves when an exogenous variable changes.

Supply, demand, equilibrium

  • Demand slopes down: \(Q^d = 60 - 10P + 2\cdot\text{Income}\). Higher income shifts it right.
  • Supply slopes up: \(Q^s = 8P - 2\cdot\text{Input price}\). A costlier input shifts it left.
  • Equilibrium: the price where \(Q^d = Q^s\) — the market clears.

Try it. Raising income shifts demand right (P and Q both rise). Raising the input price shifts supply left (P rises, Q falls). The dashed point is the baseline for comparison.

#| standalone: true
#| viewerHeight: 520

library(shiny)
ui <- fluidPage(
  tags$head(tags$style(HTML("body{font-family:'Inter',system-ui,sans-serif;}
    .sb{background:#f0f4f8;border-radius:6px;padding:12px 14px;margin-top:10px;font-size:14px;line-height:1.8;} .sb b{color:#1f3b73;}"))),
  sidebarLayout(
    sidebarPanel(width=4,
      sliderInput("inc","Buyers' income:",min=0,max=30,value=10,step=1),
      sliderInput("pin","Input price:",min=0,max=20,value=5,step=1),
      uiOutput("sb")),
    mainPanel(width=8, plotOutput("plot",height="440px"))))
server <- function(input,output,session){
  solve <- function(inc,pin){ P <- (60+2*inc+2*pin)/18; Q <- 8*P-2*pin; list(P=P,Q=Q) }
  output$plot <- renderPlot({
    e <- solve(input$inc,input$pin); b <- solve(10,5)
    Pg <- seq(0,10,length.out=200); Qd <- 60-10*Pg+2*input$inc; Qs <- 8*Pg-2*input$pin
    par(mar=c(4.2,4.4,1,1))
    plot(NA,xlim=c(0,90),ylim=c(0,10),xlab="Quantity  Q",ylab="Price  P",las=1,bty="l",cex.lab=1.15)
    points(b$Q,b$P,pch=1,col="#9aa4b2",cex=1.4,lwd=2)
    lines(Qd,Pg,col="#1f3b73",lwd=3); lines(Qs,Pg,col="#b5462a",lwd=3)
    points(e$Q,e$P,pch=19,col="#1c6b4a",cex=1.7)
    segments(0,e$P,e$Q,e$P,lty=3,col="#5a6472"); segments(e$Q,0,e$Q,e$P,lty=3,col="#5a6472")
    legend("topright",c("Demand","Supply","Equilibrium","Baseline"),col=c("#1f3b73","#b5462a","#1c6b4a","#9aa4b2"),
           lwd=c(3,3,NA,NA),pch=c(NA,NA,19,1),bty="n")
  })
  output$sb <- renderUI({ e <- solve(input$inc,input$pin)
    HTML(sprintf("<div class='sb'>Equilibrium price <b>P* = %.2f</b><br>Equilibrium quantity <b>Q* = %.1f</b></div>",e$P,e$Q)) })
}
shinyApp(ui,server)

What to notice

  • Income up → demand shifts right → both P and Q rise.
  • Input price up → supply shifts left → P rises, Q falls.
  • The model can tell you how a shock moves P and Q — but not why income itself changed. That needs a bigger model.