我想要有效地模拟一个带有漂移d>0的布朗运动,如果超过一些障碍b或-b,漂移的方向会改变(没有反射,只是改变了漂移方向!)。
for
-loop是执行此操作的简单方法
step<-0.1 #step size
sig<-1 #sign of drift
T<-10^4 #length of process
b<-300; d<-0.5#barrier and drift
W<-rep(NA,(T/step))
W[1]<-0
for (i in 2:(T/step))
{
if (W[i-1]>b) {sig<- -1} #change drift to -1
if (W[i-1]< -b) {sig<-1} #change drift to +1
W[i]<-W[i-1]+rnorm(1,d*sig*step,sqrt(step))
}
当然,这个循环在R中需要很多时间,特别是在小步长的情况下。因此,我感兴趣的是一种更有效的解决方案,可能是使用向量运算或apply()
-command。(对于简单的布朗运动,我可以使用cumsum(rnorm())
,这里是否可能有类似的解决方案?)
非常感谢!
发布于 2016-07-08 14:03:57
您有一个针对W[i]
和sig
的递归计算,它还会在每个步骤中执行一些逻辑。在R中,你可能不能做太多的事情来减少执行时间,但是有几件事可以减少将近50%的执行时间。特别是,不是在每个步骤上调用rnorm
,而是通过使用mean=0
调用一次rnorm
来计算num_step
值并存储结果,从而向量化该计算。在循环的每一步中,来自该向量的值被加到该步的平均值上。确定sig
值的逻辑也可以简化一点。发布的方法和新代码的计时代码如下:
step<-0.1 #step size
T<-10^4 #length of process
b<-300; d<-0.5 #barrier and drift
print(system.time({
sig <- 1 #sign of drift
set.seed(123) # set seed
W<-rep(NA,(T/step))
W[1]<-0
for (i in 2:(T/step))
{
if (W[i-1]>b) {sig<- -1} #change drift to -1
if (W[i-1]< -b) {sig<-1} #change drift to +1
W[i]<-W[i-1]+rnorm(1,d*sig*step,sqrt(step))
}
}))
print(system.time({
sig <- 1 # reset value of sig
set.seed(123) # reset seed
num_steps <- trunc(T/step)
W1 <- numeric(num_steps)
ep <- rnorm(num_steps, 0, sqrt(step))
for (i in 2:num_steps) {
if(abs(W1[i-1]) > b) sig <- ifelse( W1[i-1] >b, -1, 1)
W1[i] <- W1[i-1]+d*sig*step +ep[i-1]
}
}))
W
和W1
这两个计算的结果应该是相同的。
https://stackoverflow.com/questions/38250459
复制