R语言中使用while循环更新列表对象时遇到问题
R语言模拟随机市场:事件驱动的while循环实现
这是一个典型的事件驱动模拟场景,我们可以通过while循环跟踪市场运行时间,每次生成下一个事件的触发时间,执行对应操作后更新时间,直到市场关闭(时间≥600分钟)。下面是完整的实现思路和代码:
1. 初始化参数与市场状态
首先定义模拟所需的核心参数,包括各事件的发生强度,以及数量、价格的正态分布参数;同时初始化市场时间和供需状态:
# 事件强度(单位:事件/分钟) lambda_supply_gen <- 0.8 # 供给产生强度 lambda_demand_gen <- 0.7 # 需求产生强度 lambda_supply_drop <- 0.3 # 供给消失强度 lambda_demand_drop <- 0.2 # 需求消失强度 # 数量与价格的正态分布参数(均值+标准差) supply_qty_params <- c(mean = 10, sd = 3) supply_price_params <- c(mean = 50, sd = 8) demand_qty_params <- c(mean = 8, sd = 2) demand_price_params <- c(mean = 55, sd = 7) # 初始化市场状态 current_time <- 0 supply_list <- list() # 存储当前供给:每个元素是list(qty, price, create_time) demand_list <- list() # 存储当前需求:每个元素是list(qty, price, create_time)
2. 核心while循环模拟
循环的核心逻辑是:每次生成四个事件的绝对触发时间,选择最早发生的事件执行,然后更新市场时间和状态:
while (current_time < 600) { # 生成每个事件的下一次触发时间(当前时间 + 指数分布间隔) next_supply_gen <- current_time + rexp(1, lambda_supply_gen) next_demand_gen <- current_time + rexp(1, lambda_demand_gen) next_supply_drop <- current_time + rexp(1, lambda_supply_drop) next_demand_drop <- current_time + rexp(1, lambda_demand_drop) # 找到最早发生的事件 event_times <- c( supply_gen = next_supply_gen, demand_gen = next_demand_gen, supply_drop = next_supply_drop, demand_drop = next_demand_drop ) next_event <- names(which.min(event_times)) current_time <- event_times[next_event] # 执行对应事件操作 switch(next_event, "supply_gen" = { # 生成供给数量(确保>0) qty <- max(rnorm(1, supply_qty_params["mean"], supply_qty_params["sd"]), 0.1) # 生成供给价格(确保>0) price <- max(rnorm(1, supply_price_params["mean"], supply_price_params["sd"]), 0.1) # 添加到供给列表 supply_list[[length(supply_list) + 1]] <- list(qty = qty, price = price, create_time = current_time) cat(sprintf("%.2f分钟:新增供给,数量=%.1f,价格=%.2f\n", current_time, qty, price)) }, "demand_gen" = { qty <- max(rnorm(1, demand_qty_params["mean"], demand_qty_params["sd"]), 0.1) price <- max(rnorm(1, demand_price_params["mean"], demand_price_params["sd"]), 0.1) demand_list[[length(demand_list) + 1]] <- list(qty = qty, price = price, create_time = current_time) cat(sprintf("%.2f分钟:新增需求,数量=%.1f,价格=%.2f\n", current_time, qty, price)) }, "supply_drop" = { if (length(supply_list) > 0) { # 随机移除一个供给 drop_idx <- sample(1:length(supply_list), 1) dropped <- supply_list[[drop_idx]] supply_list <- supply_list[-drop_idx] cat(sprintf("%.2f分钟:移除供给,数量=%.1f,价格=%.2f\n", current_time, dropped$qty, dropped$price)) } else { cat(sprintf("%.2f分钟:尝试移除供给,但当前无供给\n", current_time)) } }, "demand_drop" = { if (length(demand_list) > 0) { drop_idx <- sample(1:length(demand_list), 1) dropped <- demand_list[[drop_idx]] demand_list <- demand_list[-drop_idx] cat(sprintf("%.2f分钟:移除需求,数量=%.1f,价格=%.2f\n", current_time, dropped$qty, dropped$price)) } else { cat(sprintf("%.2f分钟:尝试移除需求,但当前无需求\n", current_time)) } } ) } # 模拟结束后输出最终状态 cat("\n市场关闭(600分钟),最终状态:\n") cat(sprintf("当前供给数量:%d\n", length(supply_list))) cat(sprintf("当前需求数量:%d\n", length(demand_list)))
关键细节说明
- 事件间隔模拟:用
rexp()生成指数分布的事件间隔,这是因为指数分布具有无记忆性,非常适合模拟泊松过程中的事件间隔(即事件发生概率与已等待时间无关)。 - 正数值处理:用
max(..., 0.1)确保生成的数量和价格为正,如果你需要更严谨的截断正态分布,可以使用truncnorm包的rtruncnorm()函数。 - 事件选择逻辑:通过比较四个事件的绝对触发时间,每次只处理最早发生的事件,保证模拟的时序正确性。
内容的提问来源于stack exchange,提问作者325bound
相关产品推荐
相关产品推荐

