Trabalho final da disciplina de Economia Matemática 3 Estimação dos preços históricos do milho para o “Cobweb Model”

Instalando pacotes para preço e quantidade de milho

library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(lubridate)
## 
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
## 
##     date, intersect, setdiff, union
library(ggplot2)
library(readxl)
 
# Fator de conversão: 1000 toneladas * 1000 (kg/ton) / 60 (kg/saca)
FATOR_CONVERSAO <- 1000000 / 60 

# Carregar Preços (CEPEA)
preco <- read_xlsx("CEPEA.xlsx", skip = 3) 

# Carregar Produção (MilhoTotal)
producao <- read_xlsx("MilhoTotalSerieHist.xlsx") 

LIMPEZA E CÁLCULO DA MÉDIA ANUAL DO PREÇO (CEPEA)

# 1. Leitura do arquivo (Mantida)
preco <- read_excel("CEPEA.xlsx", skip = 3) 

# 2. TRATAMENTO E CONVERSÃO DE DATA (Forçado fora do pipe)
# O read_excel pode ter lido a data como número serial (comum no Excel) ou como texto.

# Tentativa 1: Converter a coluna 'Data' assumindo que ela é um número serial do Excel.
# (Se for texto, resultará em NA, que será corrigido na próxima linha.)
preco$Data_Convertida <- as.Date(as.numeric(preco$Data), origin = "1899-12-30")
## Warning in as.Date(as.numeric(preco$Data), origin = "1899-12-30"): NAs
## introduzidos por coerção
# Tentativa 2: Para os valores que FALHARAM (NA) na Tentativa 1, tenta converter como texto Dia/Mês/Ano (dmy).
preco$Data_Convertida[is.na(preco$Data_Convertida)] <- dmy(preco$Data[is.na(preco$Data_Convertida)])

# 3. Cria a coluna Ano a partir da coluna de Data convertida.
preco$Ano <- year(preco$Data_Convertida) 

# 4. Filtrar a partir de 2003 e calcular a Média Anual (USANDO O NOVO DATAFRAME)
preco_anual <- preco %>%
  # Garante que filtra apenas onde a conversão para Ano foi bem-sucedida e o ano é >= 2003
  filter(!is.na(Ano), Ano >= 2003) %>% 
  group_by(Ano) %>%
  summarise(
    Preco_Medio_Anual = mean(`À vista R$`, na.rm = TRUE), 
    .groups = 'drop'
  )

PREPARAÇÃO, PIVOTAGEM E CONVERSÃO DA PRODUÇÃO (MILHOTOTAL)

# Fator de conversão: 1000 toneladas * 1000 (kg/ton) / 60 (kg/saca)
FATOR_CONVERSAO <- 1000000 / 60 

# Leitura do arquivo (Mantida: Renomeada de df_producao para producao)
producao <- read_excel("MilhoTotalSerieHist.xlsx") 
library(tidyr)

# Pivotar os dados (transformar de colunas de anos para uma coluna de Ano)
producao_long <- producao %>%
  # A coluna 'Anos' é o identificador, todas as outras são medidas (produção)
  pivot_longer(
    cols = -Anos, # Pivotar todas as colunas exceto a primeira ('Anos')
    names_to = "Ano_str",
    values_to = "Producao_1000Ton"
  ) %>%
  # Limpar e converter o ano para numérico
  mutate(
    Ano = as.integer(Ano_str), 
    Producao_1000Ton = as.numeric(Producao_1000Ton)
  ) %>%
  # Filtra anos a partir de 2003
  filter(!is.na(Ano), Ano >= 2003) 

# 3.2 Conversão de 1000 ton para sacas de 60kg
producao_limpa <- producao_long %>%
  mutate(
    Producao_Sacas_60kg = Producao_1000Ton * FATOR_CONVERSAO
  ) %>%
  select(Ano, Producao_Sacas_60kg)

COMBINAR AS SÉRIES E VISUALIZAR SÉRIE TEMPORAL

dados_milho_anual <- inner_join(preco_anual, producao_limpa, by = "Ano")
dados_milho_anual <- na.omit(dados_milho_anual)

# Visualização da Série Temporal do Preço
ggplot(data = dados_milho_anual, aes(x = Ano, y = Preco_Medio_Anual)) +
  geom_line(color = "blue") + geom_point(color = "darkblue") +
  labs(x = "Ano", y = "Preço Médio do Milho (R$/sc)") +
  theme_minimal()

ADAPTAÇÃO DO MODELO DA TEIA DE ARANHA (COBWEB MODEL)

#Calculando Pontos de Equilíbrio (P* e Q*)
preco_equilibrio_sugerido <- mean(dados_milho_anual$Preco_Medio_Anual, na.rm = TRUE)
Q_media_original <- mean(dados_milho_anual$Producao_Sacas_60kg, na.rm = TRUE)

#NORMALIZAÇÃO: Convertendo para Milhões de Sacas
Q_media_normalizada <- Q_media_original / FATOR_CONVERSAO

cat(paste("P* (Preço de Equilíbrio): R$", round(preco_equilibrio_sugerido, 2), "/sc\n"))
## P* (Preço de Equilíbrio): R$ 40.09 /sc
cat(paste("Q* (Quantidade de Equilíbrio):", round(Q_media_normalizada, 2), " Milhões de Sacas\n"))
## Q* (Quantidade de Equilíbrio): 83929.35  Milhões de Sacas
#Parâmetros de calibração na escala normalizada:
# b_valor: Declive da Demanda (quanto maior, mais horizontal/inelástica)
b_valor <- 5.0
# beta_valor: Controla a inclinação da Oferta (1/beta). Quanto MENOR beta, MAIS vertical/elástica a Oferta.
beta_valor <- 2.5 

lambda_valor <- 0.05 # Mantido no list, mas não mais usado na supply

#Recalculando 'a' para garantir Q_d = Q* em P=P*
a_recalibrado <- Q_media_normalizada + b_valor * preco_equilibrio_sugerido

#Definindo o modelo com Oferta Linear
Market_Milho <- function(a = a_recalibrado, 
                         b = b_valor, 
                         c = preco_equilibrio_sugerido, 
                         d = Q_media_normalizada, 
                         beta = beta_valor,
                         lambda = lambda_valor) { 
  
  list(
    a = a, b = b, c = c, d = d, beta = beta, lambda = lambda,
    demand = function(p) a - b * p, 
    # OFERTA LINEAR E ELÁSTICA
    supply = function(p) d + (1 / beta) * (p - c) 
  )
}

market_milho <- Market_Milho()

#Plot Oferta e Demanda (Gráfico com inclinações visíveis)
p_grid_milho <- seq(20, 50, length.out = 10) 
demand_milho <- market_milho$demand(p_grid_milho)
supply_milho <- market_milho$supply(p_grid_milho)
df_market_milho <- data.frame(p_grid = p_grid_milho, demand = demand_milho, supply = supply_milho)

ggplot(df_market_milho, aes(x = p_grid)) +
  geom_line(aes(y = demand, color = "Demanda")) +
  geom_line(aes(y = supply, color = "Oferta")) +
  labs(x = "Quantidade (Milhões de Sacas de 60kg)", y = "Preço (R$/sc)") +  
  theme_minimal()

FUNÇÕES E GRÁFICOS DINÂMICOS

# Função g para calcular o próximo preço (Cobweb Dynamics)
# P_t = (a - Q_s(P_{t-1})) / b
g <- function(model, current_price) {
  # Usando a função de Oferta LINEAR: Q_s(P_{t-1}) = d + (1 / beta) * (P_{t-1} - c)
  current_supply <- model$d + (1 / model$beta) * (current_price - model$c)
  # Preço de equilíbrio na Demanda: P_t = (a - Q_s) / b
  (model$a - current_supply) / model$b
}

Função para plotar a linha de 45 graus (Diagrama de Fase)

  plot45 <- function(model, pmin, pmax, p0, num_arrows = 5) {
    p_grid <- seq(pmin, pmax, length.out = 150)
  g_values <- sapply(p_grid, function(p) g(model, p))
  
  df_45 <- data.frame(p_grid, g_values)
  
  ggplot(df_45, aes(x = p_grid)) +
    geom_line(aes(y = g_values, color = "g"), size = 1) +
    geom_abline(slope = 1, intercept = 0, color = "darkgreen", linetype = "dashed") +
    # Ajustando os limites para focar no intervalo de preço relevante
    xlim(c(pmin, pmax)) + ylim(c(pmin, pmax)) +
    labs(x = expression(p[t]), y = expression(p[t+1])) +
    theme_minimal() +
    theme(legend.position = "none")
}

EXIBINDO O DIAGRAMA DE FASE

plot45(market_milho, pmin = 20, pmax = 100, p0 = 30) 
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

Função para simular e plotar a série temporal do preço

ts_plot_price <- function(model, p0, ts_length = 20) {
  p <- numeric(ts_length)
  p[1] <- p0
  for (t in 2:ts_length) {
    p[t] <- g(model, p[t - 1])
  }
  df_ts <- data.frame(t = 1:ts_length, p = p)
  
# Adicionando uma linha horizontal no preço de equilíbrio (c) para referência
ggplot(df_ts, aes(x = t, y = p)) +
      geom_line(color = "blue") +
      geom_point(color = "darkblue") +
      geom_hline(yintercept = model$c, linetype="dashed", color="gray") +
      labs(x = "Período (t)", y = expression(p[t])) +
      theme_minimal()
}

# Simulação 1: Preço inicial (P0 = 35) ABAIXO do equilíbrio
ts_plot_price(market_milho, p0 = 35, ts_length = 50)

# Simulação 2: Preço inicial (P0 = 70) ACIMA do equilíbrio
ts_plot_price(market_milho, p0 = 70, ts_length = 20)

Função adaptada para calcular o preço atual (P_t) com base no preço esperado (P_e, t)

find_next_price_adaptive <- function(model, pe_t) {
  # 1. Oferta (Q_s) é baseada na Expectativa (P_e, t)
  # Q_s = d + (1 / beta) * (P_e, t - c)
  current_supply <- model$d + (1 / model$beta) * (pe_t - model$c)
  
  # 2. Preço de mercado (P_t) é definido pela Demanda (a - b * P_t = Q_s).
  # P_t = (a - Q_s) / b
  next_price <- (model$a - current_supply) / model$b
  return(next_price)
}

Função para simular e plotar a série temporal ADAPTATIVA

ts_plot_price_adaptive_ggplot <- function(model, p0, ts_length = 30, alpha = c(1.0, 0.9, 0.75)) 
  {all_results <- data.frame()
  
   for (a in alpha) {
    pe_last <- p0 
    p_values <- numeric(ts_length)
    p_values[1] <- find_next_price_adaptive(model, pe_last) 
    pe_last <- a * p_values[1] + (1 - a) * pe_last
    
    for (i in 2:ts_length) {
      p_values[i] <- find_next_price_adaptive(model, pe_last)
      pe_last <- a * p_values[i] + (1 - a) * pe_last
    }
  
    df_temp <- data.frame(
      t = 1:ts_length,
      p = p_values,
      alpha_label = paste("alpha =", a)
    )
    all_results <- rbind(all_results, df_temp)
  }
  
  # Plotar com ggplot2 e facet_wrap
  ggplot(all_results, aes(x = t, y = p)) +
    geom_line(color = "blue") +
    geom_point(color = "darkblue") +
    # Adicionando linha de equilíbrio para referência
    geom_hline(yintercept = model$c, linetype = "dashed", color = "gray") +
    facet_wrap(~ alpha_label) +
    labs(
      title = paste("Série Temporal Adaptativa para P0 =", p0),
      x = "Período (t)", 
      y = expression(p[t])
    ) +
    theme_minimal()
}

ts_plot_price_adaptive_ggplot(market_milho, p0 = 100, ts_length = 30)