我正在尝试运行模拟场景,这反过来应该为我提供给定日期的最佳场景,经过几个月的测试。特定场景的输入有4个输入变量,每个变量可以处于5个状态(625个排列)。模型的流程如下:
不幸的结果是5个嵌套for循环,这可能需要很长时间才能运行。我查看了foreach
包,但我担心输出的组合在我的场景中是如何工作的。
我正在使用的当前代码如下工作,首先我创建每个输入的可能状态以及窗口
a<-seq(as.Date("2015-12-01", "%Y-%m-%d"),as.Date(Sys.Date()-1, "%Y-%m-%d"),by="day")
#input variables
b<-seq(1,5,1)
c<-seq(1,5,1)
d<-seq(1,5,1)
e<-seq(1,5,1)
set.seed(3142)
tot_results<-NULL
接下来,嵌套的for循环继续为我运行模拟。
for(i in 1:length(a))
{
cat(paste0("\n","Current estimation date: ", a[i]),";itteration:",i," \n")
#subset data for backtesting
dataset_calc<-dataset[which(dataset$Date<=a[i]),]
p=1
results<-data.frame(rep(NA,625))
for(j in 1:length(b))
{
for(k in 1:length(c))
{
for(l in 1:length(d))
{
for(m in 1:length(e))
{
if(i==1)
{
#create a unique ID to merge onto later
unique_ID<-paste0(replicate(1, paste(sample(LETTERS, 5, replace=TRUE), collapse="")),round(runif(n=1,min=1,max=1000000)))
}
#Run profit calculation
post_sim_results<-profit_calc(dataset_calc, param1=e[m],param2=d[l],param3=c[k],param4=b[j])
#Exctract the final profit amount
profit<-round(post_sim_results[nrow(post_sim_results),],2)
results[p,]<-data.frame(unique_ID,profit)
p=p+1
}
}
}
}
#extract the ranks for all scenarios
rank<-rank(results$profit)
#bind the ranks for the expanding window
if(i==1)
{
tot_results<-data.frame(ID=results[,1],rank)
}else{
tot_results<-cbind(tot_results,rank)
}
suppressMessages(gc())
}
我最关心的是结果的绑定,因为外部循环的动作取决于内部循环的输出。
关于如何继续的任何建议将非常感激。
答案 0 :(得分:1)
所以我认为你可以对大部分内容进行矢量化,这样可以大大缩短运行时间。
目前,您使用for
- 循环(确切地说是5)来创建值的每个组合,然后通过profit_calc
(未指定的函数)逐个运行值。理想情况下,您只需一次性采用所有可能的组合,并通过一次操作将其推送到profit_calc
。
- 基本原理 -
a <- 1:10
b <- 1:10
d <- rep(NA,10)
for (i in seq(a)) d[i] <- a[i] * b[i]
d
# [1] 1 4 9 16 25 36 49 64 81 100
由于*
也适用于矢量,我们可以将其重写为:
a <- 1:10
b <- 1:10
d <- a*b
d
# [1] 1 4 9 16 25 36 49 64 81 100
虽然它可能只为我们节省了一行代码,但它实际上将问题从10步减少到1步。
- 申请
那么这对你的代码有何影响?好吧,鉴于我们可以对profit_calc
进行矢量化,您基本上可以生成一个数据框,其中每一行都是您参数的每种可能组合。我们可以使用expand.grid
:
foo <- expand.grid(b,c,d,e)
head(foo)
# Var1 Var2 Var3 Var4
# 1 1 1 1 1
# 2 2 1 1 1
# 3 3 1 1 1
# 4 4 1 1 1
# 5 5 1 1 1
# 6 1 2 1 1
让我们说我们有一个公式... (a - b) / (c + d)
...然后就像:
bar <- (foo[,1] - foo[,2]) * (foo[,3] + foo[,4])
head(bar)
# [1] 0 2 4 6 8 -2
所以基本上,尝试找到一种方法来替换for
- 循环与矢量化选项。如果您无法对某些内容进行矢量化,请尝试查看apply
,因为在大多数情况下这也可以节省您一些时间。如果您的代码运行速度太慢,那么您最好首先看看是否可以编写更高效的脚本。另外,您可能对microbenchmark
库或?system.time
感兴趣。