使用 quantmod 在 R 中回测交易策略:函数和函数内的 for 循环
Backtesting Trading Strategy in R using quantmod: Function and for loop within a Function
我正在使用 R、quantmod 和 Performanceanalystics 包。作为回测策略的一部分,我正在尝试创建一个 signal/holdings 向量,根据 RSI 的值告诉我是否应该 buy/sell/hold 一只股票。如果 RSI<30,则买入(因此持有量增加 1),如果 RSI 在 30 和 50 之间,则不要做任何事情(因此持有量与昨天相同)。如果 RSI >=50,则卖出所有(因此持有量变为零)。此后,使用 Performanceanalytics 的 dailyReturn() 函数计算并生成 returns 的图表。
请注意,RSI() 是一个接受 "price" 和 "day" 的函数,dailyReturn() 函数也接受 "price"
我已经能够用下面的代码做得很好。
library(quantmod)
library(PerformanceAnalytics)
getSymbols("IBM", src= "yahoo", from = "2000-01-01", to ="2015-09-25")
rsi<-RSI(Cl(IBM),14)
rsi<-lag(rsi,1)
rsi[is.na(rsi)] <- 0
holdings1 <-c() #initialize the vector
holdings1[1:14+1]<-0 #Not holding any shares of IBM from 1st to the 15th day
for (i in 14+2: length(Cl(IBM))){ #assume start buying from the 16th day onwards since we are using RSI where n=14
if (rsi[i]<30){ #if RSI<30, we buy one share of IBM
holdings1[i]<-holdings1[i-1]+1
} else if (rsi[i]>50){ # if RSI>50, we sell all holdings
holdings1[i]<-0
} else
holdings1[i]<- holdings1[i-1] # remains the same: if 30<=RSI<=50 we don't do anything, so same holdings as prior
}
size1<-reclass(holdings1,Cl(IBM))
ret1<-dailyReturn(Cl(IBM))*size1
charts.PerformanceSummary(ret1)
但我需要创建一个名为 "size1()" 的函数,它接受 "price" 和 "day"(教授说,我不做计算)。当我尝试这样做时,RStudio 告诉我 "Error in lag(rsi, 1) : object 'rsi' not found"。这是为什么?在函数中创建函数或向量是否合法?或者我应该以不同于上面第一个的方式构建我的代码?带有函数(价格,天)的代码如下:
library(quantmod)
library(PerformanceAnalytics)
getSymbols("IBM", src= "yahoo", from = "2000-01-01", to ="2015-09-25") #download IBM, from the stipulated range of dates
size1<-function(price,day){
ris<-RSI(price,day)
ris<-lag(rsi,1)
rsi[is.na(rsi)] <- 0
holdings1<-c()
holdings1[1:day+1]<-0
for (i in day+2: length(price)){ #assume start buying from the 15th day onwards since we are using RSI, n=14
if (rsi[i]<30){ #if RSI<30, we buy one share of IBM
holdings1[i]<-holdings1[i-1]+1
} else if (rsi[i]<50){ # if 30<RSI<50, we don't buy or sell, so that the holdings does not change
holdings1[i]<-holdings1[i-1]
} else
holdings1[i]<-0 # sell all if RSI>50
size<-reclass(holdings1,price)
}
}
ret1<-dailyReturn(Cl(IBM))*size1(Cl(IBM),14)
charts.PerformanceSummary(ret1)
day+2:length(price)
不是您所期望的。 :
优先于 +
(参见 ?Syntax
)。它的计算结果为 day + (2:length(price))
。你想要(day+2):length(price)
。另请注意,xts 对象是具有 index
属性的矩阵,而矩阵只是具有 dim
属性的向量。在矩阵 return 上调用 length
是观察的总数(向量的 length
)。您应该改用 nrow
。
在 for
循环之前预先分配整个结果向量也是一种很好的做法。当 i
大于 holdings
的当前长度时,每次调用 holdings[i] <-
时,您当前的代码都会附加到 holdings
。
另外,您的函数目前没有 return 任何东西。看起来您打算 return size
对象。请注意,您不需要在每次循环迭代时都重新创建该对象。
size1 <- function (price, day) {
rsi <- RSI(price, day)
rsi <- lag(rsi, 1)
rsi[is.na(rsi)] <- 0
holdings1 <- integer(nrow(price))
# assume start buying from the 15th day onwards,
# since we are using RSI, n=14
for (i in (day+1):nrow(price)) {
if (rsi[i] < 30) {
# if RSI<30, we buy one share of IBM
holdings1[i] <- holdings1[i - 1] + 1
}
else if (rsi[i] < 50) {
# if 30<RSI<50, we don't buy or sell,
# so that the holdings does not change
holdings1[i] <- holdings1[i - 1]
} else {
# sell all if RSI>50
holdings1[i] <- 0
}
}
reclass(holdings1, price)
}
我正在使用 R、quantmod 和 Performanceanalystics 包。作为回测策略的一部分,我正在尝试创建一个 signal/holdings 向量,根据 RSI 的值告诉我是否应该 buy/sell/hold 一只股票。如果 RSI<30,则买入(因此持有量增加 1),如果 RSI 在 30 和 50 之间,则不要做任何事情(因此持有量与昨天相同)。如果 RSI >=50,则卖出所有(因此持有量变为零)。此后,使用 Performanceanalytics 的 dailyReturn() 函数计算并生成 returns 的图表。
请注意,RSI() 是一个接受 "price" 和 "day" 的函数,dailyReturn() 函数也接受 "price"
我已经能够用下面的代码做得很好。
library(quantmod)
library(PerformanceAnalytics)
getSymbols("IBM", src= "yahoo", from = "2000-01-01", to ="2015-09-25")
rsi<-RSI(Cl(IBM),14)
rsi<-lag(rsi,1)
rsi[is.na(rsi)] <- 0
holdings1 <-c() #initialize the vector
holdings1[1:14+1]<-0 #Not holding any shares of IBM from 1st to the 15th day
for (i in 14+2: length(Cl(IBM))){ #assume start buying from the 16th day onwards since we are using RSI where n=14
if (rsi[i]<30){ #if RSI<30, we buy one share of IBM
holdings1[i]<-holdings1[i-1]+1
} else if (rsi[i]>50){ # if RSI>50, we sell all holdings
holdings1[i]<-0
} else
holdings1[i]<- holdings1[i-1] # remains the same: if 30<=RSI<=50 we don't do anything, so same holdings as prior
}
size1<-reclass(holdings1,Cl(IBM))
ret1<-dailyReturn(Cl(IBM))*size1
charts.PerformanceSummary(ret1)
但我需要创建一个名为 "size1()" 的函数,它接受 "price" 和 "day"(教授说,我不做计算)。当我尝试这样做时,RStudio 告诉我 "Error in lag(rsi, 1) : object 'rsi' not found"。这是为什么?在函数中创建函数或向量是否合法?或者我应该以不同于上面第一个的方式构建我的代码?带有函数(价格,天)的代码如下:
library(quantmod)
library(PerformanceAnalytics)
getSymbols("IBM", src= "yahoo", from = "2000-01-01", to ="2015-09-25") #download IBM, from the stipulated range of dates
size1<-function(price,day){
ris<-RSI(price,day)
ris<-lag(rsi,1)
rsi[is.na(rsi)] <- 0
holdings1<-c()
holdings1[1:day+1]<-0
for (i in day+2: length(price)){ #assume start buying from the 15th day onwards since we are using RSI, n=14
if (rsi[i]<30){ #if RSI<30, we buy one share of IBM
holdings1[i]<-holdings1[i-1]+1
} else if (rsi[i]<50){ # if 30<RSI<50, we don't buy or sell, so that the holdings does not change
holdings1[i]<-holdings1[i-1]
} else
holdings1[i]<-0 # sell all if RSI>50
size<-reclass(holdings1,price)
}
}
ret1<-dailyReturn(Cl(IBM))*size1(Cl(IBM),14)
charts.PerformanceSummary(ret1)
day+2:length(price)
不是您所期望的。 :
优先于 +
(参见 ?Syntax
)。它的计算结果为 day + (2:length(price))
。你想要(day+2):length(price)
。另请注意,xts 对象是具有 index
属性的矩阵,而矩阵只是具有 dim
属性的向量。在矩阵 return 上调用 length
是观察的总数(向量的 length
)。您应该改用 nrow
。
在 for
循环之前预先分配整个结果向量也是一种很好的做法。当 i
大于 holdings
的当前长度时,每次调用 holdings[i] <-
时,您当前的代码都会附加到 holdings
。
另外,您的函数目前没有 return 任何东西。看起来您打算 return size
对象。请注意,您不需要在每次循环迭代时都重新创建该对象。
size1 <- function (price, day) {
rsi <- RSI(price, day)
rsi <- lag(rsi, 1)
rsi[is.na(rsi)] <- 0
holdings1 <- integer(nrow(price))
# assume start buying from the 15th day onwards,
# since we are using RSI, n=14
for (i in (day+1):nrow(price)) {
if (rsi[i] < 30) {
# if RSI<30, we buy one share of IBM
holdings1[i] <- holdings1[i - 1] + 1
}
else if (rsi[i] < 50) {
# if 30<RSI<50, we don't buy or sell,
# so that the holdings does not change
holdings1[i] <- holdings1[i - 1]
} else {
# sell all if RSI>50
holdings1[i] <- 0
}
}
reclass(holdings1, price)
}