sugitora's picture
Update app.R
b199d48 verified
# 必要パッケージ
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)