Mikroökonomie
Vorlesung 3

Prof. Frank Pisch PhD

Einführung

Ein Nachfrageschock für Nvidia

The Economist (2023).

Was passiert mit den Preisen?



U.S. Bureau of Labor Statistics (2024).

Reaktionen auf anderen Märkten?

google

Aktienkurs von ASML, dem Monopolisten für EUV Lithographie Maschinen, die für die Halbleiterproduktion benötigt werden

Trumps Handelskrieg seit 2018

Was sind die Effizienz- und Wohlfahrtseffekte von Steuern oder Zöllen?

Überblick und Ressourcen

Ziele

  • Das Konzept des Marktgleichgewichtes verstehen und anwenden

  • Die Rolle und die Effekte von Steuern/Subventionen in Märkten analysieren

  • Allgemeine Gleichgewichte und verschiedene Wohlfahrtsimplikationen verstehen

Ressourcen

  • Varian: 16, 32

  • Interaktive Diagramme

  • ChatGPT, YouTube

Marktgleichgewicht

Ein Markt

Bisher haben wir Konsumenten- und Unternehmensentscheidungen unter die Lupe genommen

  • Wir haben dabei vollkommenen Wettbewerb als benchmark angenommen, sodass alle Akteure Preisnehmer waren

  • So konnten wir eine fallende Marktnachfrage \(D(p)\) und ein steigendes Marktangebot \(S(p)\) herleiten

Nun suchen wir – mithilfe Adam Smiths “unsichtbarer Hand” – ein Gleichgewicht



Teamarbeit: Was ist ein Gleichgewicht (auf einem Markt)?

Gleichgewichtspreise

Ein GG in unserem Markt entsteht, wenn sich der Marktpreis so einstellt, dass das Angebot der nachgefragten Menge entspricht

\[ D(p^*)=S(p^*) \]

Dies ist ein Gleichgewicht, wie wir mithilfe des tâtonnement Gedankens einfach nachvollziehen können

  • Bei \(p'<p^*\) gibt es zu viel Nachfrage (Nachfrageüberhang) und Unternehmen können ihre Preise erhöhen (siehe Nvidia)

  • Bei \(p'> p^*\) gibt es zu viel Angebot (Angebotsüberhang) und Unternehmen müssen ihre Preise senken (siehe Intel Aktien)

  • Nur wenn kein Preisdruck mehr da ist, haben wir ein (temporäres) Gleichgewicht

Dieses Gleichgewicht nennen wir partiell, weil wir nicht wissen, ob andere Märkte auch im Gleichgewicht sind

  • wenn alle Märkte geräumt werden, sprechen wir von einem allgemeinen GG

Die unsichtbare Hand hat zugeschlagen!

Unzählige dezentrale Entscheidungen von Nachfragern und Anbietern werden durch Preise perfekt koordiniert

DALL-E

Let’s do something useful with this…

Gehen Sie zur nächsten Folie und analysieren Sie folgende Szenarien

  1. Nachfrage nach KI-Chips

  2. Die deutsche Bevölkerung altert und die allermeisten Menschen in der Babyboomer-Generation treten in den nächsten 15 Jahren in den Ruhestand. Was erwarten wir für den Arbeitsmarkt?

  3. Eine Verbesserung von Kinderbetreuung und der allgemeine gesellschaftliche Wandel (Rollenbilder, Anstellungspraktiken, Gleichstellungsinitiativen etc.) in Deutschland führen dazu, dass Frauen öfter und mehr arbeiten. Diskutieren Sie die Auswirkungen auf den Arbeitsmarkt.

  4. Um einen Beitrag zur Lösung der Klimakrise zu leisten, verknappt die EU im Rahmen des EU-ETS immer weiter das Angebot an Emissionslizenzen. Welche Auswirkungen werden Unternehmen spüren?

Markt-App

#| standalone: true
#| viewerHeight: 600

library(shiny)
library(shinydashboard)
library(ggplot2)
library(graphics)
library(ggpattern)
library(dplyr)
library(purrr)
library(bslib)
library(bs4Dash)




ui <- fluidPage(
  
  
  sidebarLayout(
    sidebarPanel(
      tabsetPanel(
        tabPanel(h5("Einstellungen"),
                 br(),
                 checkboxInput("supp", "Inverses Angebot anzeigen", value = FALSE),
                 
                 checkboxInput("dem", "Inverse Nachfrage anzeigen", value = FALSE),
                 
                 sliderInput("slope_s", "Steigung Angebot", min = 0, max = 10, value = 1, step = 0.5),
                 sliderInput("slope_d", "Steigung Nachfrage", min = -10, max = 0, value = -1, step = 0.5),
                 
                 numericInput("absch_d", "Achsenabschnitt Nachfrage", min = 0, max = 100, value = 75),
                 
                 actionButton("reset", "Reset")
        ),
        
        
        
        tabPanel(h5("Wohlfahrt"),
                 checkboxInput("cs", "Konsumentenrente anzeigen", value = FALSE),
                 
                 checkboxInput("ps", "Produzentenrente anzeigen", value = FALSE),
                 
                 br(),
                 
                 
                 uiOutput('kons_r')   
                 
        ),
        
        
        tabPanel(h5("Steuern"),
                 
                 sliderInput("tax", "Steuerrate t", min = -30, max = 30, value = 0, step = 1),
                 br(),
                 uiOutput("steu_totg")
                 
                 
        )
      )
    ),
    mainPanel(align = "center",
              plotOutput(outputId = "ggwplot", height = "500px", width = "600px"),
    ),
  )
)


server <- function(input, output, session) {
  
  angebot <- function(a_s, x) {
    
    # p_s <- (x - 5)/a_s
    
    p_s <- a_s * x + 5
    
    return(p_s)
  }
  
  nachfrage <- function(a_d, b_d, x){
    
    # p_d <- (x - b_d)/a_d
    
    p_d <- a_d * x + b_d
    
    return(p_d)
    
  }
  
  opt <- function(a_s, a_d, b_d) {
    
    # p_opt <- (b_d - 5) / (a_s - a_d)
    #  x_opt <- a_d * p_opt + b_d
    
    x_opt <- (b_d - 5) / (a_s - a_d)
    p_opt <- a_d * x_opt + b_d 
    
    return(list(p_opt = p_opt, x_opt = x_opt))
  }
  
  
  
  
  
  
  
  
  observeEvent(list(input$tax, input$cs, input$ps, input$supp, input$dem, input$slope_d, input$slope_s, input$absch_d), {
    a_s <- input$slope_s
    a_d <- input$slope_d
    b_d <- input$absch_d
    
    cs <- input$cs
    ps <- input$ps
    
    
    x_v <- seq(0, 100, by = 0.5)
    
    p_s <- angebot(a_s, x_v)
    p_d <- nachfrage(a_d, b_d, x_v)
    t <- input$tax
    
    if (t != 0) {
      
      
      grid <- tibble(
        
        x_val = x_v,
        
        S = p_s + t,
        
        D = p_d
      )
      
      Ergebnisse <- opt(a_s, a_d, b_d)
      #p_s_opt <- (Ergebnisse$p_opt + (t*a_d)/(a_s-a_d))
      # p_d_opt <- (Ergebnisse$p_opt + (t*a_s)/(a_s-a_d))
      
      p_s_opt <- (((t - b_d)/a_d)+(5/a_s))/((1/a_s)-(1/a_d))
      p_d_opt <- p_s_opt + t
      
      x_t <- (p_s_opt - 5)/a_s
      
      # p_opt <- (b_d-5)/(a_s-a_d)
      # x_opt <- a_s * p_opt + 5
      
      x_opt <- (b_d - 5) / (a_s - a_d)
      p_opt <- a_d * x_opt + b_d 
    }
    
    else {
      
      
      grid <- tibble(
        
        x_val = x_v,
        
        S = p_s,
        
        D = p_d
      )
      
      Ergebnisse <- opt(a_s, a_d, b_d)
      p_opt <- Ergebnisse$p_opt 
      x_opt <- Ergebnisse$x_opt
      
      
    }
    
    output$ggwplot <- renderPlot({
      if (input$dem == TRUE && input$supp == TRUE) {
        g_plot <- ggplot(grid) +
          geom_line(aes(x = x_val, y = D, color = "Nachfrage"), size = 1.3) +
          geom_line(aes(x = x_val, y = S, color = "Angebot"), size = ifelse(t != 0, 1, 1.3), linetype = ifelse(t != 0, "dashed", "solid")) +
          scale_color_manual(values = c("Angebot" = "blue", "Nachfrage" = "red")) +
          guides(color = guide_legend(title = "Kurven", position = "bottom", title.position = "left", title.hjust = 0.5)) +
          
          coord_cartesian(xlim = c(-10, 100), ylim = c(-5, 100)) +
          theme_minimal() +
          labs(x = "Menge y", y = "Preis p") +
          theme(
            axis.text = element_text(size = 14),
            axis.title = element_text(size = 16),
            plot.title = element_text(size = 20),
            legend.position = c(0.9, 0.9),  # position -> legend
            legend.justification = c(0.5, 0.5),  # Top right corner
            legend.background = element_rect(fill = "white", color = "black"),
            legend.key = element_rect(fill = "white", color = "white")
          )
        
        
        
      } else if (input$dem == TRUE && input$supp == FALSE) {
        
        g_plot <- ggplot(grid) +
          geom_line(aes(x = x_val, y = D, color = "Nachfrage"), size = 1.3) +
          scale_color_manual(values = c("Nachfrage" = "red")) +
          guides(color = guide_legend(title = "Kurven", position = "bottom", title.position = "left", title.hjust = 0.5)) +
          coord_cartesian(xlim = c(-10, 100), ylim = c(-5, 100)) +
          theme_minimal() +
          labs(x = "Menge y", y = "Preis p") +
          theme(
            axis.text = element_text(size = 14),
            axis.title = element_text(size = 16),
            plot.title = element_text(size = 20),
            legend.position = c(0.9, 0.9),  # Adjust this as necessary to position the legend
            legend.justification = c(0.5, 0.5),  # Top right corner
            legend.background = element_rect(fill = "white", color = "black"),
            legend.key = element_rect(fill = "white", color = "white")
          )
        
      } else if (input$dem == FALSE && input$supp == TRUE ) {
        
        g_plot <- ggplot(grid) +
          geom_line(aes(x = x_val, y = S, color = "Angebot"), size = ifelse(t != 0, 1, 1.3), linetype = ifelse(t != 0, "dashed", "solid")) +
          scale_color_manual(values = c("Angebot" = "blue")) +
          guides(color = guide_legend(title = "Kurven", position = "bottom", title.position = "left", title.hjust = 0.5)) +
          coord_cartesian(xlim = c(-10, 100), ylim = c(-5, 100)) +
          theme_minimal() +
          labs(x = "Menge y", y = "Preis p") +
          theme(
            axis.text = element_text(size = 14),
            axis.title = element_text(size = 16),
            plot.title = element_text(size = 20),
            legend.position = c(0.9, 0.9),  # Adjust this as necessary to position the legend
            legend.justification = c(0.5, 0.5),  # Top right corner
            legend.background = element_rect(fill = "white", color = "black"),
            legend.key = element_rect(fill = "white", color = "white")
          )
        
      } else {
        
        g_plot <- ggplot(grid) +
          geom_line(aes(x = x_val, y = D), color = "white", size = 0.1) +
          coord_cartesian(xlim = c(-5, 100), ylim = c(-5, 100)) +
          theme_minimal() +
          labs(x = "Menge y", y = "Preis p") +
          theme(
            axis.text = element_text(size = 14),
            axis.title = element_text(size = 16),
            plot.title = element_text(size = 20),
            legend.position = c(0.9, 0.9),  # Adjust this as necessary to position the legend
            legend.justification = c(0.5, 0.5),  # Top right corner
            legend.background = element_rect(fill = "white", color = "black"),
            legend.key = element_rect(fill = "white", color = "white")
          )
      }
      
      
      
      if (input$dem && !is.null(p_opt) && cs == TRUE && t == 0) {
        g_plot <- g_plot +
          geom_ribbon_pattern(data = grid %>% filter(x_val <= x_opt),
                              aes(x = x_val, ymin = p_opt, ymax = D, fill = "Konsumentenrente"),
                              # fill = "#FF9999", 
                              pattern = "stripe", 
                              pattern_fill = "red", 
                              pattern_angle = 45, 
                              pattern_density = 0.3, 
                              pattern_spacing = 0.01, 
                              alpha = 0.3) 
        #   annotate("Text", x = -5, y = p_opt + 15, label = "KR", color = "red", size = 7)
        
        
      } else if (input$dem && !is.null(p_opt) && cs == TRUE && t != 0) {
        
        g_plot <- g_plot +
          geom_ribbon_pattern(data = grid %>% filter(x_val <= x_t),
                              aes(x = x_val, ymin = p_d_opt, ymax = D, fill = "Konsumentenrente" ),
                              # fill = "#FF9999", 
                              pattern = "stripe", 
                              pattern_fill = "red", 
                              pattern_angle = 45, 
                              pattern_density = 0.3, 
                              pattern_spacing = 0.01, 
                              alpha = 0.3) 
        
        
      } 
      
      if (input$supp && !is.null(p_opt) && input$ps && t == 0) {
        g_plot <- g_plot +
          geom_ribbon_pattern(data = grid %>% filter(x_val <= x_opt),
                              aes(x = x_val, ymin = S, ymax = p_opt, fill = "Produzentenrente"),
                              #        fill = "#ADD8E6", 
                              pattern = "stripe", 
                              pattern_fill = "blue", 
                              pattern_angle = 135, 
                              pattern_density = 0.3, 
                              pattern_spacing = 0.01, 
                              alpha = 0.3) 
        #  annotate("text", x = -5, y = p_opt - 15, label = "PS", color = "blue", size = 7)
        
        
        
        
      } else if (input$supp && !is.null(p_opt) && input$ps && t != 0) {
        
        g_plot <- g_plot +
          geom_ribbon_pattern(data = grid %>% filter(x_val <= x_t),
                              aes(x = x_val, ymin = S - t, ymax = p_s_opt, fill = "Produzentenrente"),
                              #       fill = "#ADD8E6", 
                              pattern = "stripe", 
                              pattern_fill = "blue", 
                              pattern_angle = 135, 
                              pattern_density = 0.3, 
                              pattern_spacing = 0.01, 
                              alpha = 0.3) 
        
        
      } 
      
      if (input$supp && !is.null(p_opt) && t > 0) {
        g_plot <- g_plot +
          geom_ribbon(data = grid %>% filter(x_val <= x_t),
                      aes(x = x_val, ymin = p_s_opt, ymax = p_opt,  fill = "Steuererträge"),
                      #     fill = "grey", 
                      alpha = 1) +
          geom_ribbon(data = grid %>% filter(x_val <= x_t),
                      aes(x = x_val, ymin = p_opt, ymax = p_d_opt,  fill = "Steuererträge"),
                      #     fill = "grey", 
                      alpha = 1) +
          
          geom_ribbon(data = grid %>% filter(x_val >= x_t & x_val <= x_opt),
                      aes(x = x_val, ymin = S - t, ymax = D, fill = "Wohlfahrtsverlust"),
                      #     fill = "black", 
                      alpha = 1) 
        # annotate("text", x = -5, y = p_opt - 15, label = "PS", color = "blue", size = 7)
      }
      
      
      if (t != 0) {
        g_plot <- g_plot +
          
          geom_line(aes(x = x_val, y = S - t, color = "Angebot"), size = 1.3, linetype = "solid") 
      }  
      
      label1 <- bquote(p[d] ~ "≈")
      label2 <- bquote(p[s] ~ "≈")
      label3 <- bquote(x[t] ~ "≈")
      
      if (t != 0) {
        g_plot <- g_plot +
          geom_segment(aes(x = x_t, xend = x_t, y = -5, yend = p_d_opt), color = "violet", linetype = "longdash", size = 0.7) +
          geom_segment(aes(x = 0, xend = x_t, y = p_d_opt, yend = p_d_opt), color = "violet", linetype = "longdash", size = 0.7) +
          geom_segment(aes(x = 0, xend = x_t, y = p_s_opt, yend = p_s_opt), color = "violet", linetype = "longdash", size = 0.7) +
          annotate("text", x = x_t, y = -5, label = as.expression(bquote(.(label3) ~ .(round(x_t)))), vjust = 1, hjust = 1, color = "violet", size = 5) +
          annotate("text", x = 0, y = p_d_opt, label = as.expression(bquote(.(label1) ~ .(round(p_d_opt)))), vjust = 0.5, hjust = 1, color = "violet", size = 5) +
          annotate("text", x = 0, y = p_s_opt, label = as.expression(bquote(.(label2) ~ .(round(p_s_opt)))), vjust = 0.5, hjust = 1, color = "violet", size = 5)
      }
      
      if ( t < 0) {
        g_plot <- g_plot +
          geom_segment(aes(x = x_t, xend = x_t, y = -5, yend = p_s_opt), color = "violet", linetype = "longdash", size = 0.7)
      }
      
      
      
      if (input$dem == TRUE && input$supp == TRUE) {
        g_plot <- g_plot +
          geom_segment(aes(x = x_opt, xend = x_opt, y = 0, yend = p_opt), color = "orange", linetype = "longdash", size = 0.7) +
          geom_segment(aes(x = 0, xend = x_opt, y = p_opt, yend = p_opt), color = "orange", linetype = "longdash", size = 0.7) +
          annotate("text", x = x_opt, y = 0, label = paste("x* ≈ ", round(x_opt)), vjust = 1, hjust = 0.5, color = "orange", size = 5) +
          annotate("text", x = 0, y = p_opt, label = paste("p* ≈ ", round(p_opt)), vjust = 0.5, hjust = 1, color = "orange", size = 5)
      }
      
      
      g_plot <- g_plot +
        scale_color_manual(
          values = c("Angebot" = "blue", "Nachfrage" = "red"),
          name = "Kurven"
        ) +
        scale_fill_manual(
          values = c("Konsumentenrente" = "#FF9999", "Produzentenrente" = "#ADD8E6", "Steuererträge" = "grey", "Wohlfahrtsverlust" = "black"), name = "") +
        guides(color = guide_legend(title = "Geraden", position = "bottom", title.position = "left", title.hjust = 1))
      
      
      
      
      
      print(g_plot) 
      
    })
  })
  
  
  
  
  observeEvent(input$reset, {
    updateSliderInput(inputId = "slope_d", value = -1)
    updateSliderInput(inputId = "slope_s", value = 1)
    updateSliderInput(inputId = "tax", value = 0)
    
    updateNumericInput(inputId = "absch_d", value = 75)
    updateCheckboxInput(inputId = "cs", value = FALSE)
    updateCheckboxInput(inputId = "ps", value = FALSE)
    
  })
  
  
  kons_r <- reactiveVal(0)
  prod_r <- reactiveVal(0)
  
  observeEvent(list(input$cs, input$ps, input$supp, input$tax, input$dem, input$slope_d, input$slope_s, input$absch_d), {
    a_s <- input$slope_s
    a_d <- input$slope_d
    b_d <- input$absch_d
    Ergebnisse <- opt(a_s, a_d, b_d)
    p_opt <- Ergebnisse$p_opt
    x_opt <- Ergebnisse$x_opt
    t <- input$tax
    
    p_s_opt <- (((t - b_d)/a_d)+(5/a_s))/((1/a_s)-(1/a_d))
    p_d_opt <- p_s_opt + t
    x_t <- (p_s_opt - 5)/a_s
    
    if (input$cs == TRUE && input$supp == TRUE && input$dem == TRUE && t == 0) {
      kons_r(((b_d-p_opt) * x_opt) / 2)
    } else if (input$cs == TRUE && input$supp == TRUE && input$dem == TRUE && t != 0) {
      kons_r(((b_d-p_d_opt) * x_t) / 2)
    } else {
      kons_r(0)
    }
    
    if (input$ps == TRUE && input$supp == TRUE && input$dem == TRUE && t == 0) {
      prod_r((p_opt * x_opt) / 2)
    } else if (input$cs == TRUE && input$supp == TRUE && input$dem == TRUE && t != 0) {
      prod_r((p_s_opt * x_t) / 2)
    } else {
      prod_r(0)
    }
    
  })
  
  
  
  
  output$kons_r <- renderUI({
    
    kons_r_r <- round(kons_r(), digits = 2)
    prod_r_r <- round(prod_r(), digits = 2)
    
    withMathJax(HTML(paste("Konsumentenrente:", kons_r_r, "<br>",
                           "Produzentenrente:", prod_r_r))
    )
  })
  
  
  steu_ber <- reactiveVal(0)
  totg_ber <- reactiveVal(0)
  
  observeEvent(list(input$cs, input$ps, input$supp, input$tax, input$dem, input$slope_d, input$slope_s, input$absch_d), {
    a_s <- input$slope_s
    a_d <- input$slope_d
    b_d <- input$absch_d
    Ergebnisse <- opt(a_s, a_d, b_d)
    p_opt <- Ergebnisse$p_opt
    x_opt <- Ergebnisse$x_opt
    t <- input$tax
    
    p_s_opt <- (((t - b_d)/a_d)+(5/a_s))/((1/a_s)-(1/a_d))
    p_d_opt <- p_s_opt + t
    x_t <- (p_s_opt - 5)/a_s
    
    
    if (input$supp == TRUE && input$dem == TRUE && t > 0) {
      
      steu_ber(-1 * (x_t*(p_d_opt-p_s_opt)))
      
      totg_ber((p_opt-p_s_opt)*(x_opt-x_t)/2 + (p_d_opt-p_opt)*(x_opt-x_t)/2 )
    }
    
    if (input$supp == TRUE && input$dem == TRUE && t < 0) {
      
      steu_ber(x_t*(p_s_opt-p_d_opt))
      
      totg_ber((p_s_opt-p_opt)*(x_t-x_opt)/2 + (p_opt-p_d_opt)*(x_t-x_opt)/2 )
    }
    
  })
  
  
  
  
  output$steu_totg <- renderUI({
    
    steu <- round(steu_ber(), digits = 2)
    totg <- round(totg_ber(), digits = 2)
    
    withMathJax(HTML(paste("Steuereinnahmen:", -steu, "<br>",
                           "Wohlfahrtsverlust:", totg))
    )
  })
  
}

shinyApp(ui = ui, server = server)

Steuern im partiellen Gleichgewicht

Wo auch immer wir hinschauen…

Steuern (und Subventionen) begegnen uns wirklich überall

  • Mehrwertsteuer (19 und 5%)
  • Einkommensteuer, Kapitalertragssteuer, Gewerbesteuer
  • Zölle
  • Automobilsteuer, Benzinsteuer, Tabaksteuer, Bettensteuer
  • CO\(_2\) Steuer

Zwei zentrale Aufgaben

  • Finanzierungsfunktion: Der Staat benötigt Mittel für Infrastruktur, Verwaltung, Sicherheit
  • Steuerungsfunktion: Der Staat greift lenkend in die Wirtschaft ein

Wichtige Fragen

  • Welche Wirkungen erwarten wir auf Preise und Mengen?
  • Wer trägt die Steuerlast?
  • Welche Effekte auf Wohlfahrt und Effizienz erwarten wir?

Arten von Steuern

Mengensteuern beziehen sich auf die Menge des Konsums \[ p_D = p_S + t \] Wert- oder ad-valorem Steuern beziehen sich auf den Preis eines Gutes \[ p_D = (1 + \tau) p_S \]

Wobei \(p_D\) (\(p_S\)) die Preise sind, die Konsument:innen zahlen (Produzenten erhalten)



Teamarbeit: Auf der letzten Folie waren einige prominente Steuern aufgelistet – welche sind Mengen-, welche sind ad-valorem Steuern?

Mengensteuern und -subventionen im Gleichgewicht

#| standalone: true
#| viewerHeight: 600

library(shiny)
library(shinydashboard)
library(ggplot2)
library(graphics)
library(ggpattern)
library(dplyr)
library(purrr)
library(bslib)
library(bs4Dash)




ui <- fluidPage(
  
  
  sidebarLayout(
    sidebarPanel(
      tabsetPanel(
        tabPanel(h5("Einstellungen"),
                 br(),
                 checkboxInput("supp", "Inverses Angebot anzeigen", value = FALSE),
                 
                 checkboxInput("dem", "Inverse Nachfrage anzeigen", value = FALSE),
                 
                 sliderInput("slope_s", "Steigung Angebot", min = 0, max = 10, value = 1, step = 0.5),
                 sliderInput("slope_d", "Steigung Nachfrage", min = -10, max = 0, value = -1, step = 0.5),
                 
                 numericInput("absch_d", "Achsenabschnitt Nachfrage", min = 0, max = 100, value = 75),
                 
                 actionButton("reset", "Reset")
        ),
        
        
        
        tabPanel(h5("Wohlfahrt"),
                 checkboxInput("cs", "Konsumentenrente anzeigen", value = FALSE),
                 
                 checkboxInput("ps", "Produzentenrente anzeigen", value = FALSE),
                 
                 br(),
                 
                 
                 uiOutput('kons_r')   
                 
        ),
        
        
        tabPanel(h5("Steuern"),
                 
                 sliderInput("tax", "Steuerrate t", min = -30, max = 30, value = 0, step = 1),
                 br(),
                 uiOutput("steu_totg")
                 
                 
        )
      )
    ),
    mainPanel(align = "center",
              plotOutput(outputId = "ggwplot", height = "500px", width = "600px"),
    ),
  )
)


server <- function(input, output, session) {
  
  angebot <- function(a_s, x) {
    
    # p_s <- (x - 5)/a_s
    
    p_s <- a_s * x + 5
    
    return(p_s)
  }
  
  nachfrage <- function(a_d, b_d, x){
    
    # p_d <- (x - b_d)/a_d
    
    p_d <- a_d * x + b_d
    
    return(p_d)
    
  }
  
  opt <- function(a_s, a_d, b_d) {
    
    # p_opt <- (b_d - 5) / (a_s - a_d)
    #  x_opt <- a_d * p_opt + b_d
    
    x_opt <- (b_d - 5) / (a_s - a_d)
    p_opt <- a_d * x_opt + b_d 
    
    return(list(p_opt = p_opt, x_opt = x_opt))
  }
  
  
  
  
  
  
  
  
  observeEvent(list(input$tax, input$cs, input$ps, input$supp, input$dem, input$slope_d, input$slope_s, input$absch_d), {
    a_s <- input$slope_s
    a_d <- input$slope_d
    b_d <- input$absch_d
    
    cs <- input$cs
    ps <- input$ps
    
    
    x_v <- seq(0, 100, by = 0.5)
    
    p_s <- angebot(a_s, x_v)
    p_d <- nachfrage(a_d, b_d, x_v)
    t <- input$tax
    
    if (t != 0) {
      
      
      grid <- tibble(
        
        x_val = x_v,
        
        S = p_s + t,
        
        D = p_d
      )
      
      Ergebnisse <- opt(a_s, a_d, b_d)
      #p_s_opt <- (Ergebnisse$p_opt + (t*a_d)/(a_s-a_d))
      # p_d_opt <- (Ergebnisse$p_opt + (t*a_s)/(a_s-a_d))
      
      p_s_opt <- (((t - b_d)/a_d)+(5/a_s))/((1/a_s)-(1/a_d))
      p_d_opt <- p_s_opt + t
      
      x_t <- (p_s_opt - 5)/a_s
      
      # p_opt <- (b_d-5)/(a_s-a_d)
      # x_opt <- a_s * p_opt + 5
      
      x_opt <- (b_d - 5) / (a_s - a_d)
      p_opt <- a_d * x_opt + b_d 
    }
    
    else {
      
      
      grid <- tibble(
        
        x_val = x_v,
        
        S = p_s,
        
        D = p_d
      )
      
      Ergebnisse <- opt(a_s, a_d, b_d)
      p_opt <- Ergebnisse$p_opt 
      x_opt <- Ergebnisse$x_opt
      
      
    }
    
    output$ggwplot <- renderPlot({
      if (input$dem == TRUE && input$supp == TRUE) {
        g_plot <- ggplot(grid) +
          geom_line(aes(x = x_val, y = D, color = "Nachfrage"), size = 1.3) +
          geom_line(aes(x = x_val, y = S, color = "Angebot"), size = ifelse(t != 0, 1, 1.3), linetype = ifelse(t != 0, "dashed", "solid")) +
          scale_color_manual(values = c("Angebot" = "blue", "Nachfrage" = "red")) +
          guides(color = guide_legend(title = "Kurven", position = "bottom", title.position = "left", title.hjust = 0.5)) +
          
          coord_cartesian(xlim = c(-10, 100), ylim = c(-5, 100)) +
          theme_minimal() +
          labs(x = "Menge y", y = "Preis p") +
          theme(
            axis.text = element_text(size = 14),
            axis.title = element_text(size = 16),
            plot.title = element_text(size = 20),
            legend.position = c(0.9, 0.9),  # position -> legend
            legend.justification = c(0.5, 0.5),  # Top right corner
            legend.background = element_rect(fill = "white", color = "black"),
            legend.key = element_rect(fill = "white", color = "white")
          )
        
        
        
      } else if (input$dem == TRUE && input$supp == FALSE) {
        
        g_plot <- ggplot(grid) +
          geom_line(aes(x = x_val, y = D, color = "Nachfrage"), size = 1.3) +
          scale_color_manual(values = c("Nachfrage" = "red")) +
          guides(color = guide_legend(title = "Kurven", position = "bottom", title.position = "left", title.hjust = 0.5)) +
          coord_cartesian(xlim = c(-10, 100), ylim = c(-5, 100)) +
          theme_minimal() +
          labs(x = "Menge y", y = "Preis p") +
          theme(
            axis.text = element_text(size = 14),
            axis.title = element_text(size = 16),
            plot.title = element_text(size = 20),
            legend.position = c(0.9, 0.9),  # Adjust this as necessary to position the legend
            legend.justification = c(0.5, 0.5),  # Top right corner
            legend.background = element_rect(fill = "white", color = "black"),
            legend.key = element_rect(fill = "white", color = "white")
          )
        
      } else if (input$dem == FALSE && input$supp == TRUE ) {
        
        g_plot <- ggplot(grid) +
          geom_line(aes(x = x_val, y = S, color = "Angebot"), size = ifelse(t != 0, 1, 1.3), linetype = ifelse(t != 0, "dashed", "solid")) +
          scale_color_manual(values = c("Angebot" = "blue")) +
          guides(color = guide_legend(title = "Kurven", position = "bottom", title.position = "left", title.hjust = 0.5)) +
          coord_cartesian(xlim = c(-10, 100), ylim = c(-5, 100)) +
          theme_minimal() +
          labs(x = "Menge y", y = "Preis p") +
          theme(
            axis.text = element_text(size = 14),
            axis.title = element_text(size = 16),
            plot.title = element_text(size = 20),
            legend.position = c(0.9, 0.9),  # Adjust this as necessary to position the legend
            legend.justification = c(0.5, 0.5),  # Top right corner
            legend.background = element_rect(fill = "white", color = "black"),
            legend.key = element_rect(fill = "white", color = "white")
          )
        
      } else {
        
        g_plot <- ggplot(grid) +
          geom_line(aes(x = x_val, y = D), color = "white", size = 0.1) +
          coord_cartesian(xlim = c(-5, 100), ylim = c(-5, 100)) +
          theme_minimal() +
          labs(x = "Menge y", y = "Preis p") +
          theme(
            axis.text = element_text(size = 14),
            axis.title = element_text(size = 16),
            plot.title = element_text(size = 20),
            legend.position = c(0.9, 0.9),  # Adjust this as necessary to position the legend
            legend.justification = c(0.5, 0.5),  # Top right corner
            legend.background = element_rect(fill = "white", color = "black"),
            legend.key = element_rect(fill = "white", color = "white")
          )
      }
      
      
      
      if (input$dem && !is.null(p_opt) && cs == TRUE && t == 0) {
        g_plot <- g_plot +
          geom_ribbon_pattern(data = grid %>% filter(x_val <= x_opt),
                              aes(x = x_val, ymin = p_opt, ymax = D, fill = "Konsumentenrente"),
                              # fill = "#FF9999", 
                              pattern = "stripe", 
                              pattern_fill = "red", 
                              pattern_angle = 45, 
                              pattern_density = 0.3, 
                              pattern_spacing = 0.01, 
                              alpha = 0.3) 
        #   annotate("Text", x = -5, y = p_opt + 15, label = "KR", color = "red", size = 7)
        
        
      } else if (input$dem && !is.null(p_opt) && cs == TRUE && t != 0) {
        
        g_plot <- g_plot +
          geom_ribbon_pattern(data = grid %>% filter(x_val <= x_t),
                              aes(x = x_val, ymin = p_d_opt, ymax = D, fill = "Konsumentenrente" ),
                              # fill = "#FF9999", 
                              pattern = "stripe", 
                              pattern_fill = "red", 
                              pattern_angle = 45, 
                              pattern_density = 0.3, 
                              pattern_spacing = 0.01, 
                              alpha = 0.3) 
        
        
      } 
      
      if (input$supp && !is.null(p_opt) && input$ps && t == 0) {
        g_plot <- g_plot +
          geom_ribbon_pattern(data = grid %>% filter(x_val <= x_opt),
                              aes(x = x_val, ymin = S, ymax = p_opt, fill = "Produzentenrente"),
                              #        fill = "#ADD8E6", 
                              pattern = "stripe", 
                              pattern_fill = "blue", 
                              pattern_angle = 135, 
                              pattern_density = 0.3, 
                              pattern_spacing = 0.01, 
                              alpha = 0.3) 
        #  annotate("text", x = -5, y = p_opt - 15, label = "PS", color = "blue", size = 7)
        
        
        
        
      } else if (input$supp && !is.null(p_opt) && input$ps && t != 0) {
        
        g_plot <- g_plot +
          geom_ribbon_pattern(data = grid %>% filter(x_val <= x_t),
                              aes(x = x_val, ymin = S - t, ymax = p_s_opt, fill = "Produzentenrente"),
                              #       fill = "#ADD8E6", 
                              pattern = "stripe", 
                              pattern_fill = "blue", 
                              pattern_angle = 135, 
                              pattern_density = 0.3, 
                              pattern_spacing = 0.01, 
                              alpha = 0.3) 
        
        
      } 
      
      if (input$supp && !is.null(p_opt) && t > 0) {
        g_plot <- g_plot +
          geom_ribbon(data = grid %>% filter(x_val <= x_t),
                      aes(x = x_val, ymin = p_s_opt, ymax = p_opt,  fill = "Steuererträge"),
                      #     fill = "grey", 
                      alpha = 1) +
          geom_ribbon(data = grid %>% filter(x_val <= x_t),
                      aes(x = x_val, ymin = p_opt, ymax = p_d_opt,  fill = "Steuererträge"),
                      #     fill = "grey", 
                      alpha = 1) +
          
          geom_ribbon(data = grid %>% filter(x_val >= x_t & x_val <= x_opt),
                      aes(x = x_val, ymin = S - t, ymax = D, fill = "Wohlfahrtsverlust"),
                      #     fill = "black", 
                      alpha = 1) 
        # annotate("text", x = -5, y = p_opt - 15, label = "PS", color = "blue", size = 7)
      }
      
      
      if (t != 0) {
        g_plot <- g_plot +
          
          geom_line(aes(x = x_val, y = S - t, color = "Angebot"), size = 1.3, linetype = "solid") 
      }  
      
      label1 <- bquote(p[d] ~ "≈")
      label2 <- bquote(p[s] ~ "≈")
      label3 <- bquote(x[t] ~ "≈")
      
      if (t != 0) {
        g_plot <- g_plot +
          geom_segment(aes(x = x_t, xend = x_t, y = -5, yend = p_d_opt), color = "violet", linetype = "longdash", size = 0.7) +
          geom_segment(aes(x = 0, xend = x_t, y = p_d_opt, yend = p_d_opt), color = "violet", linetype = "longdash", size = 0.7) +
          geom_segment(aes(x = 0, xend = x_t, y = p_s_opt, yend = p_s_opt), color = "violet", linetype = "longdash", size = 0.7) +
          annotate("text", x = x_t, y = -5, label = as.expression(bquote(.(label3) ~ .(round(x_t)))), vjust = 1, hjust = 1, color = "violet", size = 5) +
          annotate("text", x = 0, y = p_d_opt, label = as.expression(bquote(.(label1) ~ .(round(p_d_opt)))), vjust = 0.5, hjust = 1, color = "violet", size = 5) +
          annotate("text", x = 0, y = p_s_opt, label = as.expression(bquote(.(label2) ~ .(round(p_s_opt)))), vjust = 0.5, hjust = 1, color = "violet", size = 5)
      }
      
      if ( t < 0) {
        g_plot <- g_plot +
          geom_segment(aes(x = x_t, xend = x_t, y = -5, yend = p_s_opt), color = "violet", linetype = "longdash", size = 0.7)
      }
      
      
      
      if (input$dem == TRUE && input$supp == TRUE) {
        g_plot <- g_plot +
          geom_segment(aes(x = x_opt, xend = x_opt, y = 0, yend = p_opt), color = "orange", linetype = "longdash", size = 0.7) +
          geom_segment(aes(x = 0, xend = x_opt, y = p_opt, yend = p_opt), color = "orange", linetype = "longdash", size = 0.7) +
          annotate("text", x = x_opt, y = 0, label = paste("x* ≈ ", round(x_opt)), vjust = 1, hjust = 0.5, color = "orange", size = 5) +
          annotate("text", x = 0, y = p_opt, label = paste("p* ≈ ", round(p_opt)), vjust = 0.5, hjust = 1, color = "orange", size = 5)
      }
      
      
      g_plot <- g_plot +
        scale_color_manual(
          values = c("Angebot" = "blue", "Nachfrage" = "red"),
          name = "Kurven"
        ) +
        scale_fill_manual(
          values = c("Konsumentenrente" = "#FF9999", "Produzentenrente" = "#ADD8E6", "Steuererträge" = "grey", "Wohlfahrtsverlust" = "black"), name = "") +
        guides(color = guide_legend(title = "Geraden", position = "bottom", title.position = "left", title.hjust = 1))
      
      
      
      
      
      print(g_plot) 
      
    })
  })
  
  
  
  
  observeEvent(input$reset, {
    updateSliderInput(inputId = "slope_d", value = -1)
    updateSliderInput(inputId = "slope_s", value = 1)
    updateSliderInput(inputId = "tax", value = 0)
    
    updateNumericInput(inputId = "absch_d", value = 75)
    updateCheckboxInput(inputId = "cs", value = FALSE)
    updateCheckboxInput(inputId = "ps", value = FALSE)
    
  })
  
  
  kons_r <- reactiveVal(0)
  prod_r <- reactiveVal(0)
  
  observeEvent(list(input$cs, input$ps, input$supp, input$tax, input$dem, input$slope_d, input$slope_s, input$absch_d), {
    a_s <- input$slope_s
    a_d <- input$slope_d
    b_d <- input$absch_d
    Ergebnisse <- opt(a_s, a_d, b_d)
    p_opt <- Ergebnisse$p_opt
    x_opt <- Ergebnisse$x_opt
    t <- input$tax
    
    p_s_opt <- (((t - b_d)/a_d)+(5/a_s))/((1/a_s)-(1/a_d))
    p_d_opt <- p_s_opt + t
    x_t <- (p_s_opt - 5)/a_s
    
    if (input$cs == TRUE && input$supp == TRUE && input$dem == TRUE && t == 0) {
      kons_r(((b_d-p_opt) * x_opt) / 2)
    } else if (input$cs == TRUE && input$supp == TRUE && input$dem == TRUE && t != 0) {
      kons_r(((b_d-p_d_opt) * x_t) / 2)
    } else {
      kons_r(0)
    }
    
    if (input$ps == TRUE && input$supp == TRUE && input$dem == TRUE && t == 0) {
      prod_r((p_opt * x_opt) / 2)
    } else if (input$cs == TRUE && input$supp == TRUE && input$dem == TRUE && t != 0) {
      prod_r((p_s_opt * x_t) / 2)
    } else {
      prod_r(0)
    }
    
  })
  
  
  
  
  output$kons_r <- renderUI({
    
    kons_r_r <- round(kons_r(), digits = 2)
    prod_r_r <- round(prod_r(), digits = 2)
    
    withMathJax(HTML(paste("Konsumentenrente:", kons_r_r, "<br>",
                           "Produzentenrente:", prod_r_r))
    )
  })
  
  
  steu_ber <- reactiveVal(0)
  totg_ber <- reactiveVal(0)
  
  observeEvent(list(input$cs, input$ps, input$supp, input$tax, input$dem, input$slope_d, input$slope_s, input$absch_d), {
    a_s <- input$slope_s
    a_d <- input$slope_d
    b_d <- input$absch_d
    Ergebnisse <- opt(a_s, a_d, b_d)
    p_opt <- Ergebnisse$p_opt
    x_opt <- Ergebnisse$x_opt
    t <- input$tax
    
    p_s_opt <- (((t - b_d)/a_d)+(5/a_s))/((1/a_s)-(1/a_d))
    p_d_opt <- p_s_opt + t
    x_t <- (p_s_opt - 5)/a_s
    
    
    if (input$supp == TRUE && input$dem == TRUE && t > 0) {
      
      steu_ber(-1 * (x_t*(p_d_opt-p_s_opt)))
      
      totg_ber((p_opt-p_s_opt)*(x_opt-x_t)/2 + (p_d_opt-p_opt)*(x_opt-x_t)/2 )
    }
    
    if (input$supp == TRUE && input$dem == TRUE && t < 0) {
      
      steu_ber(x_t*(p_s_opt-p_d_opt))
      
      totg_ber((p_s_opt-p_opt)*(x_t-x_opt)/2 + (p_opt-p_d_opt)*(x_t-x_opt)/2 )
    }
    
  })
  
  
  
  
  output$steu_totg <- renderUI({
    
    steu <- round(steu_ber(), digits = 2)
    totg <- round(totg_ber(), digits = 2)
    
    withMathJax(HTML(paste("Steuereinnahmen:", -steu, "<br>",
                           "Wohlfahrtsverlust:", totg))
    )
  })
  
}

shinyApp(ui = ui, server = server)

Überwälzung

Ist es wichtig, wer die Steuer abführt bzw. zahlt?

  • Nein!

\[p_D(q^*)=p_S(q^*) + t \leftrightarrow p_D(q^*)-t=p_S(q^*)\]

  • Bei der Umsatzsteuer achtet ja niemand auf den Kassenbon…

Wer trägt die Steuerlast?

  • Ist die Nachfrage relativ preisunelastisch, können Konsumenten nicht gut wegsubstituieren, sodass sie einen großen Preisanstieg des Konsumentenpreises schultern müssen

  • Ist sie preiselastisch, muss eine Steuererhöhung zumindest teilweise von den Unternehmen abgefangen werden, die ihren Angebotspreis stärker senken müssen

Schlägt sich dies auch in der Wohlfahrt nieder?

Grafik: Wohlfahrtseffekte und Überwälzung

#| standalone: true
#| viewerHeight: 600

library(shiny)
library(shinydashboard)
library(ggplot2)
library(graphics)
library(ggpattern)
library(dplyr)
library(purrr)
library(bslib)
library(bs4Dash)




ui <- fluidPage(
  
  
  sidebarLayout(
    sidebarPanel(
      tabsetPanel(
        tabPanel(h5("Einstellungen"),
                 br(),
                 checkboxInput("supp", "Inverses Angebot anzeigen", value = FALSE),
                 
                 checkboxInput("dem", "Inverse Nachfrage anzeigen", value = FALSE),
                 
                 sliderInput("slope_s", "Steigung Angebot", min = 0, max = 10, value = 1, step = 0.5),
                 sliderInput("slope_d", "Steigung Nachfrage", min = -10, max = 0, value = -1, step = 0.5),
                 
                 numericInput("absch_d", "Achsenabschnitt Nachfrage", min = 0, max = 100, value = 75),
                 
                 actionButton("reset", "Reset")
        ),
        
        
        
        tabPanel(h5("Wohlfahrt"),
                 checkboxInput("cs", "Konsumentenrente anzeigen", value = FALSE),
                 
                 checkboxInput("ps", "Produzentenrente anzeigen", value = FALSE),
                 
                 br(),
                 
                 
                 uiOutput('kons_r')   
                 
        ),
        
        
        tabPanel(h5("Steuern"),
                 
                 sliderInput("tax", "Steuerrate t", min = -30, max = 30, value = 0, step = 1),
                 br(),
                 uiOutput("steu_totg")
                 
                 
        )
      )
    ),
    mainPanel(align = "center",
              plotOutput(outputId = "ggwplot", height = "500px", width = "600px"),
    ),
  )
)


server <- function(input, output, session) {
  
  angebot <- function(a_s, x) {
    
    # p_s <- (x - 5)/a_s
    
    p_s <- a_s * x + 5
    
    return(p_s)
  }
  
  nachfrage <- function(a_d, b_d, x){
    
    # p_d <- (x - b_d)/a_d
    
    p_d <- a_d * x + b_d
    
    return(p_d)
    
  }
  
  opt <- function(a_s, a_d, b_d) {
    
    # p_opt <- (b_d - 5) / (a_s - a_d)
    #  x_opt <- a_d * p_opt + b_d
    
    x_opt <- (b_d - 5) / (a_s - a_d)
    p_opt <- a_d * x_opt + b_d 
    
    return(list(p_opt = p_opt, x_opt = x_opt))
  }
  
  
  
  
  
  
  
  
  observeEvent(list(input$tax, input$cs, input$ps, input$supp, input$dem, input$slope_d, input$slope_s, input$absch_d), {
    a_s <- input$slope_s
    a_d <- input$slope_d
    b_d <- input$absch_d
    
    cs <- input$cs
    ps <- input$ps
    
    
    x_v <- seq(0, 100, by = 0.5)
    
    p_s <- angebot(a_s, x_v)
    p_d <- nachfrage(a_d, b_d, x_v)
    t <- input$tax
    
    if (t != 0) {
      
      
      grid <- tibble(
        
        x_val = x_v,
        
        S = p_s + t,
        
        D = p_d
      )
      
      Ergebnisse <- opt(a_s, a_d, b_d)
      #p_s_opt <- (Ergebnisse$p_opt + (t*a_d)/(a_s-a_d))
      # p_d_opt <- (Ergebnisse$p_opt + (t*a_s)/(a_s-a_d))
      
      p_s_opt <- (((t - b_d)/a_d)+(5/a_s))/((1/a_s)-(1/a_d))
      p_d_opt <- p_s_opt + t
      
      x_t <- (p_s_opt - 5)/a_s
      
      # p_opt <- (b_d-5)/(a_s-a_d)
      # x_opt <- a_s * p_opt + 5
      
      x_opt <- (b_d - 5) / (a_s - a_d)
      p_opt <- a_d * x_opt + b_d 
    }
    
    else {
      
      
      grid <- tibble(
        
        x_val = x_v,
        
        S = p_s,
        
        D = p_d
      )
      
      Ergebnisse <- opt(a_s, a_d, b_d)
      p_opt <- Ergebnisse$p_opt 
      x_opt <- Ergebnisse$x_opt
      
      
    }
    
    output$ggwplot <- renderPlot({
      if (input$dem == TRUE && input$supp == TRUE) {
        g_plot <- ggplot(grid) +
          geom_line(aes(x = x_val, y = D, color = "Nachfrage"), size = 1.3) +
          geom_line(aes(x = x_val, y = S, color = "Angebot"), size = ifelse(t != 0, 1, 1.3), linetype = ifelse(t != 0, "dashed", "solid")) +
          scale_color_manual(values = c("Angebot" = "blue", "Nachfrage" = "red")) +
          guides(color = guide_legend(title = "Kurven", position = "bottom", title.position = "left", title.hjust = 0.5)) +
          
          coord_cartesian(xlim = c(-10, 100), ylim = c(-5, 100)) +
          theme_minimal() +
          labs(x = "Menge y", y = "Preis p") +
          theme(
            axis.text = element_text(size = 14),
            axis.title = element_text(size = 16),
            plot.title = element_text(size = 20),
            legend.position = c(0.9, 0.9),  # position -> legend
            legend.justification = c(0.5, 0.5),  # Top right corner
            legend.background = element_rect(fill = "white", color = "black"),
            legend.key = element_rect(fill = "white", color = "white")
          )
        
        
        
      } else if (input$dem == TRUE && input$supp == FALSE) {
        
        g_plot <- ggplot(grid) +
          geom_line(aes(x = x_val, y = D, color = "Nachfrage"), size = 1.3) +
          scale_color_manual(values = c("Nachfrage" = "red")) +
          guides(color = guide_legend(title = "Kurven", position = "bottom", title.position = "left", title.hjust = 0.5)) +
          coord_cartesian(xlim = c(-10, 100), ylim = c(-5, 100)) +
          theme_minimal() +
          labs(x = "Menge y", y = "Preis p") +
          theme(
            axis.text = element_text(size = 14),
            axis.title = element_text(size = 16),
            plot.title = element_text(size = 20),
            legend.position = c(0.9, 0.9),  # Adjust this as necessary to position the legend
            legend.justification = c(0.5, 0.5),  # Top right corner
            legend.background = element_rect(fill = "white", color = "black"),
            legend.key = element_rect(fill = "white", color = "white")
          )
        
      } else if (input$dem == FALSE && input$supp == TRUE ) {
        
        g_plot <- ggplot(grid) +
          geom_line(aes(x = x_val, y = S, color = "Angebot"), size = ifelse(t != 0, 1, 1.3), linetype = ifelse(t != 0, "dashed", "solid")) +
          scale_color_manual(values = c("Angebot" = "blue")) +
          guides(color = guide_legend(title = "Kurven", position = "bottom", title.position = "left", title.hjust = 0.5)) +
          coord_cartesian(xlim = c(-10, 100), ylim = c(-5, 100)) +
          theme_minimal() +
          labs(x = "Menge y", y = "Preis p") +
          theme(
            axis.text = element_text(size = 14),
            axis.title = element_text(size = 16),
            plot.title = element_text(size = 20),
            legend.position = c(0.9, 0.9),  # Adjust this as necessary to position the legend
            legend.justification = c(0.5, 0.5),  # Top right corner
            legend.background = element_rect(fill = "white", color = "black"),
            legend.key = element_rect(fill = "white", color = "white")
          )
        
      } else {
        
        g_plot <- ggplot(grid) +
          geom_line(aes(x = x_val, y = D), color = "white", size = 0.1) +
          coord_cartesian(xlim = c(-5, 100), ylim = c(-5, 100)) +
          theme_minimal() +
          labs(x = "Menge y", y = "Preis p") +
          theme(
            axis.text = element_text(size = 14),
            axis.title = element_text(size = 16),
            plot.title = element_text(size = 20),
            legend.position = c(0.9, 0.9),  # Adjust this as necessary to position the legend
            legend.justification = c(0.5, 0.5),  # Top right corner
            legend.background = element_rect(fill = "white", color = "black"),
            legend.key = element_rect(fill = "white", color = "white")
          )
      }
      
      
      
      if (input$dem && !is.null(p_opt) && cs == TRUE && t == 0) {
        g_plot <- g_plot +
          geom_ribbon_pattern(data = grid %>% filter(x_val <= x_opt),
                              aes(x = x_val, ymin = p_opt, ymax = D, fill = "Konsumentenrente"),
                              # fill = "#FF9999", 
                              pattern = "stripe", 
                              pattern_fill = "red", 
                              pattern_angle = 45, 
                              pattern_density = 0.3, 
                              pattern_spacing = 0.01, 
                              alpha = 0.3) 
        #   annotate("Text", x = -5, y = p_opt + 15, label = "KR", color = "red", size = 7)
        
        
      } else if (input$dem && !is.null(p_opt) && cs == TRUE && t != 0) {
        
        g_plot <- g_plot +
          geom_ribbon_pattern(data = grid %>% filter(x_val <= x_t),
                              aes(x = x_val, ymin = p_d_opt, ymax = D, fill = "Konsumentenrente" ),
                              # fill = "#FF9999", 
                              pattern = "stripe", 
                              pattern_fill = "red", 
                              pattern_angle = 45, 
                              pattern_density = 0.3, 
                              pattern_spacing = 0.01, 
                              alpha = 0.3) 
        
        
      } 
      
      if (input$supp && !is.null(p_opt) && input$ps && t == 0) {
        g_plot <- g_plot +
          geom_ribbon_pattern(data = grid %>% filter(x_val <= x_opt),
                              aes(x = x_val, ymin = S, ymax = p_opt, fill = "Produzentenrente"),
                              #        fill = "#ADD8E6", 
                              pattern = "stripe", 
                              pattern_fill = "blue", 
                              pattern_angle = 135, 
                              pattern_density = 0.3, 
                              pattern_spacing = 0.01, 
                              alpha = 0.3) 
        #  annotate("text", x = -5, y = p_opt - 15, label = "PS", color = "blue", size = 7)
        
        
        
        
      } else if (input$supp && !is.null(p_opt) && input$ps && t != 0) {
        
        g_plot <- g_plot +
          geom_ribbon_pattern(data = grid %>% filter(x_val <= x_t),
                              aes(x = x_val, ymin = S - t, ymax = p_s_opt, fill = "Produzentenrente"),
                              #       fill = "#ADD8E6", 
                              pattern = "stripe", 
                              pattern_fill = "blue", 
                              pattern_angle = 135, 
                              pattern_density = 0.3, 
                              pattern_spacing = 0.01, 
                              alpha = 0.3) 
        
        
      } 
      
      if (input$supp && !is.null(p_opt) && t > 0) {
        g_plot <- g_plot +
          geom_ribbon(data = grid %>% filter(x_val <= x_t),
                      aes(x = x_val, ymin = p_s_opt, ymax = p_opt,  fill = "Steuererträge"),
                      #     fill = "grey", 
                      alpha = 1) +
          geom_ribbon(data = grid %>% filter(x_val <= x_t),
                      aes(x = x_val, ymin = p_opt, ymax = p_d_opt,  fill = "Steuererträge"),
                      #     fill = "grey", 
                      alpha = 1) +
          
          geom_ribbon(data = grid %>% filter(x_val >= x_t & x_val <= x_opt),
                      aes(x = x_val, ymin = S - t, ymax = D, fill = "Wohlfahrtsverlust"),
                      #     fill = "black", 
                      alpha = 1) 
        # annotate("text", x = -5, y = p_opt - 15, label = "PS", color = "blue", size = 7)
      }
      
      
      if (t != 0) {
        g_plot <- g_plot +
          
          geom_line(aes(x = x_val, y = S - t, color = "Angebot"), size = 1.3, linetype = "solid") 
      }  
      
      label1 <- bquote(p[d] ~ "≈")
      label2 <- bquote(p[s] ~ "≈")
      label3 <- bquote(x[t] ~ "≈")
      
      if (t != 0) {
        g_plot <- g_plot +
          geom_segment(aes(x = x_t, xend = x_t, y = -5, yend = p_d_opt), color = "violet", linetype = "longdash", size = 0.7) +
          geom_segment(aes(x = 0, xend = x_t, y = p_d_opt, yend = p_d_opt), color = "violet", linetype = "longdash", size = 0.7) +
          geom_segment(aes(x = 0, xend = x_t, y = p_s_opt, yend = p_s_opt), color = "violet", linetype = "longdash", size = 0.7) +
          annotate("text", x = x_t, y = -5, label = as.expression(bquote(.(label3) ~ .(round(x_t)))), vjust = 1, hjust = 1, color = "violet", size = 5) +
          annotate("text", x = 0, y = p_d_opt, label = as.expression(bquote(.(label1) ~ .(round(p_d_opt)))), vjust = 0.5, hjust = 1, color = "violet", size = 5) +
          annotate("text", x = 0, y = p_s_opt, label = as.expression(bquote(.(label2) ~ .(round(p_s_opt)))), vjust = 0.5, hjust = 1, color = "violet", size = 5)
      }
      
      if ( t < 0) {
        g_plot <- g_plot +
          geom_segment(aes(x = x_t, xend = x_t, y = -5, yend = p_s_opt), color = "violet", linetype = "longdash", size = 0.7)
      }
      
      
      
      if (input$dem == TRUE && input$supp == TRUE) {
        g_plot <- g_plot +
          geom_segment(aes(x = x_opt, xend = x_opt, y = 0, yend = p_opt), color = "orange", linetype = "longdash", size = 0.7) +
          geom_segment(aes(x = 0, xend = x_opt, y = p_opt, yend = p_opt), color = "orange", linetype = "longdash", size = 0.7) +
          annotate("text", x = x_opt, y = 0, label = paste("x* ≈ ", round(x_opt)), vjust = 1, hjust = 0.5, color = "orange", size = 5) +
          annotate("text", x = 0, y = p_opt, label = paste("p* ≈ ", round(p_opt)), vjust = 0.5, hjust = 1, color = "orange", size = 5)
      }
      
      
      g_plot <- g_plot +
        scale_color_manual(
          values = c("Angebot" = "blue", "Nachfrage" = "red"),
          name = "Kurven"
        ) +
        scale_fill_manual(
          values = c("Konsumentenrente" = "#FF9999", "Produzentenrente" = "#ADD8E6", "Steuererträge" = "grey", "Wohlfahrtsverlust" = "black"), name = "") +
        guides(color = guide_legend(title = "Geraden", position = "bottom", title.position = "left", title.hjust = 1))
      
      
      
      
      
      print(g_plot) 
      
    })
  })
  
  
  
  
  observeEvent(input$reset, {
    updateSliderInput(inputId = "slope_d", value = -1)
    updateSliderInput(inputId = "slope_s", value = 1)
    updateSliderInput(inputId = "tax", value = 0)
    
    updateNumericInput(inputId = "absch_d", value = 75)
    updateCheckboxInput(inputId = "cs", value = FALSE)
    updateCheckboxInput(inputId = "ps", value = FALSE)
    
  })
  
  
  kons_r <- reactiveVal(0)
  prod_r <- reactiveVal(0)
  
  observeEvent(list(input$cs, input$ps, input$supp, input$tax, input$dem, input$slope_d, input$slope_s, input$absch_d), {
    a_s <- input$slope_s
    a_d <- input$slope_d
    b_d <- input$absch_d
    Ergebnisse <- opt(a_s, a_d, b_d)
    p_opt <- Ergebnisse$p_opt
    x_opt <- Ergebnisse$x_opt
    t <- input$tax
    
    p_s_opt <- (((t - b_d)/a_d)+(5/a_s))/((1/a_s)-(1/a_d))
    p_d_opt <- p_s_opt + t
    x_t <- (p_s_opt - 5)/a_s
    
    if (input$cs == TRUE && input$supp == TRUE && input$dem == TRUE && t == 0) {
      kons_r(((b_d-p_opt) * x_opt) / 2)
    } else if (input$cs == TRUE && input$supp == TRUE && input$dem == TRUE && t != 0) {
      kons_r(((b_d-p_d_opt) * x_t) / 2)
    } else {
      kons_r(0)
    }
    
    if (input$ps == TRUE && input$supp == TRUE && input$dem == TRUE && t == 0) {
      prod_r((p_opt * x_opt) / 2)
    } else if (input$cs == TRUE && input$supp == TRUE && input$dem == TRUE && t != 0) {
      prod_r((p_s_opt * x_t) / 2)
    } else {
      prod_r(0)
    }
    
  })
  
  
  
  
  output$kons_r <- renderUI({
    
    kons_r_r <- round(kons_r(), digits = 2)
    prod_r_r <- round(prod_r(), digits = 2)
    
    withMathJax(HTML(paste("Konsumentenrente:", kons_r_r, "<br>",
                           "Produzentenrente:", prod_r_r))
    )
  })
  
  
  steu_ber <- reactiveVal(0)
  totg_ber <- reactiveVal(0)
  
  observeEvent(list(input$cs, input$ps, input$supp, input$tax, input$dem, input$slope_d, input$slope_s, input$absch_d), {
    a_s <- input$slope_s
    a_d <- input$slope_d
    b_d <- input$absch_d
    Ergebnisse <- opt(a_s, a_d, b_d)
    p_opt <- Ergebnisse$p_opt
    x_opt <- Ergebnisse$x_opt
    t <- input$tax
    
    p_s_opt <- (((t - b_d)/a_d)+(5/a_s))/((1/a_s)-(1/a_d))
    p_d_opt <- p_s_opt + t
    x_t <- (p_s_opt - 5)/a_s
    
    
    if (input$supp == TRUE && input$dem == TRUE && t > 0) {
      
      steu_ber(-1 * (x_t*(p_d_opt-p_s_opt)))
      
      totg_ber((p_opt-p_s_opt)*(x_opt-x_t)/2 + (p_d_opt-p_opt)*(x_opt-x_t)/2 )
    }
    
    if (input$supp == TRUE && input$dem == TRUE && t < 0) {
      
      steu_ber(x_t*(p_s_opt-p_d_opt))
      
      totg_ber((p_s_opt-p_opt)*(x_t-x_opt)/2 + (p_opt-p_d_opt)*(x_t-x_opt)/2 )
    }
    
  })
  
  
  
  
  output$steu_totg <- renderUI({
    
    steu <- round(steu_ber(), digits = 2)
    totg <- round(totg_ber(), digits = 2)
    
    withMathJax(HTML(paste("Steuereinnahmen:", -steu, "<br>",
                           "Wohlfahrtsverlust:", totg))
    )
  })
  
}

shinyApp(ui = ui, server = server)

Zusammenfassung Wohlfahrtseffekte

  1. Steuern treiben einen Keil zwischen Angebot und Nachfrage, sodass eine Zusatzlast entsteht (deadweight loss, “Totgewicht”)

  2. Steuern erhöhen Konsumenten- und senken Produzentenpreise – die Elastizität entscheidet, wer welchen Teil der Last trägt

  3. Caveat: Der Staat kann mit den Steuern etwas Sinnvolles anfangen – dies muss man miteinbeziehen

Effizienz bzw. Wirtschaftlichkeit

Ein zentrales Maß ökonomischer Effizienz ist die Pareto-Effizienz

  • Eine Allokation – also wer was bekommt – ist Pareto-effizient, wenn man niemanden besser stellen kann, ohne dass jemand anderes schlechter gestellt wird

  • Beispiel Warteschlange bei Tickets: Oft würde sich der Weiterverkauf aufgrund der Zeitkosten lohnen; ist das nicht möglich, ist dieser Mechanismus nicht Pareto-effizient

  • Ein Pareto-effizientes GG wird auch als Pareto-GG bezeichnet

Steuern als Friktion

Steuern erzeugen Effizienzverluste

  • Es gibt Nachfrager, die eine hohe Zahlungsbereitschaft haben, aber nicht kaufen können, weil der Konsumentenpreis zu hoch ist

  • Es gibt Produzenten, die nicht produzieren können, obwohl sie effizient genug wären, Konsumenten zu bedienen

  • Dies entspricht der Zusatzlast

Im Umkehrschluss: Wenn es keine Steuern (oder andere Friktionen wie Marktmacht) gibt, die den vollständigen Wettbewerb stören, können wir uns sicher sein, dass das GG effizient ist

  • Dies ist das Erste Wohlfahrtstheorem: Alle Allokationen unter vollständigem Wettbewerb sind Parto-effizient.

Allgemeines Gleichgewicht

Motivation

Bestandteile und Verwendung des Computerchips

  • Silizium, Gold, Kupfer, Platin, etc.
  • Prozessoren, Autos, KI, Smartphones, etc.

open.sourcemap.com, Fairphone 3

Marktzusammenhänge

Viele Märkte sind eng miteinander verknüpft

  • Z.B. durch Wertschöpfungsketten oder durch Faktormärkte

  • Preisänderungen bei Substituten und Komplementen für Nvidia Chips lösen Nachfragereaktionen aus

  • Arbeitsmarktentwicklungen und Preisänderungen lösen Einkommenseffekte aus usw.

Um das tatsächliche Funktionieren eines Marktes (und der Volkswirtschaft als Ganzes) zu verstehen, müssen wir also eigentlich alle Märkte gleichzeitig betrachten

  • Oft arbeiten Makro- und Handelsökonom:innen daher mit allgemeinen Gleichgewichten

  • Für viele Anwendungen sind solche Überlegungen jedoch zweitrangig bzw. approximativ vernachlässigbar

In diesem Kapitel beschäftigen wir uns mit einem sehr einfachen Fall, dem Tausch in einer Zwei-Güter-Welt

  • Hierbei nutzen wir ein praktisches Werkzeug: Die Edgeworth Box

  • Zwei Konsument:innen, zwei Güter, Anfangsausstattungen und Tausch

Die Ausstattungen

  • Zwei Personen, \(A\) und \(B\), zwei Güter \(1\) und \(2\)

  • Anfangsausstattungen \(\omega_{A_1}\), \(\omega_{B_1}\) etc.

Die Konsummengen

  • Konsummengen werden von den Ursprüngen aus gemessen und mit \(x_{A_1}\), \(x_{B_1}\) etc. bezeichnet

Nutzenniveaus und Indifferenzkurven in der Anfangsausstattung

  • Indifferenzkurven werden ebenfalls vom jeweiligen Ursprung aus gezeichnet

  • Im gezeigten Fall werden die Nutzenniveaus der Ausstattung gezeigt

Teamarbeit: Könnte sich hier ein Tausch lohnen?

Pareto Verbesserungen

  • Alle Bündel in der grauen Fläche stellen mindestens eine Person besser, ohne die andere schlechter zu stellen

Pareto-optimale Allokationen: Die Pareto Menge/Kontraktkurve

  • Unabhängig von der Ausstattung würden sich beide Personen nur auf Allokationen einigen, die Pareto-optimal sind

Teamarbeit: Suchen Sie sich einen Punkt abseits der Kontraktkurve und argumentieren Sie, warum sich die Parteien nicht auf diese Allokation einigen wollen würden

Kern der Pareto Menge

  • Durch die Ausstattungen können wir somit den Raum der möglichen Gleichgewichte auf die Schnittmenge der Kontraktkurve mit der Pareto-Menge beschränken

Aber welche Allokation ist nun ein allgemeines Gleichgewicht?

Preisbildung: Der Walras’sche Auktionator

Nehmen wir an, es gibt einen Walras'schen Auktionator

  • Legt Preise als Signal für Knappheit in Abhängigkeit von Nachfrage- und Angebotsüberhängen fest

  • Die Budgetgeraden von \(A\) und \(B\) schneiden die Ausstattung und haben eine Steigung von \(-p_1/p_2\) (aus \(A\)’s Perspektive)

  • \(x_{A_1}\) etc. sind die Bruttonachfragen, also die absoluten Mengen, die bei gegebenem Preis nachgefragt werden

  • \(x_{A_1}-\omega_{A_1}\) etc. sind die Nettonachfragen

Preisbildung im Ungleichgewicht

  • Solange \(x_{A_1}-\omega_{A_1} \neq \omega_{B_1} - x_{B_1}\) haben wir kein Gleichgewicht

Teamarbeit: Wie muss der Auktionator die relativen Preise in diesem konkreten Fall anpassen?

Allgemeines Tauschgleichgewicht

Die gezeigten relativen Preise führen zu einem Gleichgewicht in beiden Märkten

Markträumung und relative Preise

Solange Budgets ausgeschöpft werden, stellen Preise sicher, dass im allgemeinen Gleichgewicht immer alle Märkte im Gleichgewicht sind

  • Walras'sches Gesetz: Wenn \(n-1\) Märkte geräumt sind, ist auch der \(n\)te Markt geräumt

  • Nur relative Preise beeinflussen das Verhalten

  • Man kann also ein Numéraire Gut wählen und alle Preise sind im Wert dieses Gutes gemessen

Wohlfahrtstheoreme

Erstes Wohlfahrstheorem: Alle vollständig wettbewerblichen Gleichgewichte sind Pareto-effizient

  • Unser Auktionator stellt sicher, dass die Personen Preisnehmer sind (keine Marktmacht)

  • Man kann das Theorem in deutlich generelleren Modellen zeigen, solange es weiterhin keine externen Effekte gibt

Zweites Wohlfahrtstheorem: Jede Pareto-effiziente Allokation kann durch Umverteilung als Wettbewerbsgleichgewicht erreicht werden

  • Wir passen einfach durch Pauschalsteuern die Anfangsausstattung an und Preise regulieren den Tausch hin zu einem gewünschten Gleichgewicht

  • Verteilung und Effizienz sind getrennte Probleme: In unserem benchmark können wir jede Verteilung von Einkommen/Vermögen erreichen, ohne Effizienz zu beeinträchtigen

Eine interaktive Edgeworth Box

Eine interaktive Edgeworth Box (in englischer Spache) finden Sie im Internet unter

www.berndneumann.eu/project/ysidro.php

Wiederholungsfragen

  • Erklären Sie jemandem, was ein partielles Markgleichgewicht ist und welche Rolle Preise spielen

  • Analysieren Sie eine Subvention im interaktiven Diagramm auf Folie 19: welche Auswirkungen gibt es auf Preise, Mengen und die Wohfahrt einzelner Akteure?

  • Öffnen Sie das interaktive Edgeworth Box Diagramm auf der vorherigen Folie. Klicken Sie alle Boxen und Parameterwerte durch und versuchen Sie zu verstehen, welche deutschen Begriffe wir verwenden. Bilden Sie die Folien 26 bis 34 mithilfe des interaktiven Diagramms nach und spielen Sie mit den Parametern