# 必要パッケージ library(shiny) library(ggplot2) library(dplyr) library(readr) library(writexl) library(tidyr) # UI定義 ui <- fluidPage( titlePanel("Gibson-Schwartzモデルによる銅価格シミュレーション"), sidebarLayout( sidebarPanel( numericInput("kappa", "κ(平均回帰速度)", 3.77), numericInput("alpha", "α(便利性利得の平均)", -0.003), numericInput("sigma_delta", "σδ(便利性利得のボラティリティ)", 0.015), numericInput("sigma_S", "σS(価格のボラティリティ)", 0.02), numericInput("rho", "相関係数ρ", 0.3), numericInput("n_path", "シミュレーションパス数", 20, min = 1, max = 100), actionButton("run", "シミュレーション実行"), downloadButton("download", "CSVでダウンロード") ), mainPanel( plotOutput("simPlot") ) ) ) # サーバー定義 server <- function(input, output) { sim_data <- reactiveVal(NULL) observeEvent(input$run, { df <- read_csv("copper_futures_cleaned.csv") df <- df %>% drop_na() S0 <- exp(mean(df$log_price, na.rm = TRUE)) T_days <- 252 dt <- 1 / T_days n <- input$n_path logS <- matrix(0, nrow = T_days + 1, ncol = n) delta <- matrix(0, nrow = T_days + 1, ncol = n) logS[1, ] <- log(S0) delta[1, ] <- input$alpha set.seed(123) for (i in 2:(T_days + 1)) { Z1 <- rnorm(n) Z2 <- rnorm(n) W_delta <- Z1 W_S <- input$rho * Z1 + sqrt(1 - input$rho^2) * Z2 delta[i, ] <- delta[i - 1, ] + input$kappa * (input$alpha - delta[i - 1, ]) * dt + input$sigma_delta * sqrt(dt) * W_delta logS[i, ] <- logS[i - 1, ] + (- delta[i - 1, ] - 0.5 * input$sigma_S^2) * dt + input$sigma_S * sqrt(dt) * W_S } # ワイド形式のデータフレーム作成 df_sim <- as.data.frame(exp(logS)) colnames(df_sim) <- paste0("path_", 1:n) df_sim$day <- 0:T_days df_sim <- df_sim %>% relocate(day) sim_data(df_sim) # ロング形式でプロット用データも作成 df_long <- df_sim %>% pivot_longer(-day, names_to = "path", values_to = "price") output$simPlot <- renderPlot({ ggplot(df_long, aes(x = day, y = price, group = path, color = path)) + geom_line(alpha = 0.8) + scale_color_viridis_d(option = "D") + labs(title = "Copper Price Simulation using the Gibson-Schwartz Model", x = "Days", y = "Copper Price (USD/t)", color = "Path") + theme_minimal(base_size = 14) + theme(legend.position = "none") }) }) output$download <- downloadHandler( filename = function() { paste0("copper_simulation_", Sys.Date(), ".csv") }, content = function(file) { write.csv(sim_data(), file, row.names = FALSE) } ) } # アプリ起動 shinyApp(ui = ui, server = server)