我想计算自单变量时间序列的200个周期高点以来经过的周期数。例如,这是SPY的收盘价:
require(quantmod)
getSymbols("SPY",from='01-01-1900')
Data <- Cl(SPY)
现在,我可以使用quantmod中的Lag
函数找到本系列的200个周期的高点:
periodHigh <- function(x,n) {
Lags <- Lag(x,1:n)
High <- x == apply(Lags,1,max)
x[High]
}
periodHigh(Data, 200)
但现在我被卡住了。如何将其合并回原始系列(Data
)并计算系列中的每个点,自上一个n期间高点以来经过了多少个时段?
答案 0 :(得分:5)
这个小函数返回一个列表:
high
高日期的索引号recentHigh
最近一个高日的索引号daysSince
自上次上诉以来的天数data
只有高天数的xts对象。用于绘图。代码:
daysSinceHigh <- function(data, days){
highs <- days-1+which(apply(embed(data, days), 1, which.max)==1)
recentHigh <- max(highs)
daysSince <- nrow(data) - recentHigh
list(
highs=highs,
recentHigh = recentHigh,
daysSince = daysSince,
data=data[highs, ])
}
结果:
daysSinceHigh(Data, 200)$daysSince
[1] 90
plot(Data)
points(daysSinceHigh(Data, 200)$data, col="red")
答案 1 :(得分:3)
您修改后的问题的答案:
require(zoo)
x <- sample(300:500, 1000, replace=TRUE)
str(rollapply(x, 200, function(x) which.max(x)))
# int [1:801] 14 13 12 11 10 9 8 7 6 5 ...
plot(x)
plot(200:1000, rollapply(x, 200, function(x) 200-which.max(x)))
所以对于xts系列:
plot( rollapply(coredata(Data), 200, function(x) 200-which.max(x)))
您显然无法将任何内容合并回前200个日期,除非您应用更宽松的滚动最大值定义。 (在另一个涉及“shifty”数据的SO会话中,我展示了如何使用embed填充“尾随”句点:Data transformation in R但我不知道你是否想要构造200倍于输入的矩阵数据。)
答案 2 :(得分:0)
我编辑了之前答案中的代码,使得它们是采用相同输入的函数(单变量时间序列)并返回相同的输出(自上一个n天高以来的天数):
daysSinceHigh1 <- function(x,n) {
as.vector(n-rollapply(x, n, which.max))
}
daysSinceHigh2 <- function(x, n){
apply(embed(x, n), 1, which.max)-1
}
第二个功能似乎是最快的,但它们提供的结果略有不同:
> getSymbols("^GSPC",from='01-01-1900')
[1] "GSPC"
> system.time(x <- daysSinceHigh1(Cl(GSPC), 200))
user system elapsed
0.42 0.00 0.42
> system.time(y <- daysSinceHigh2(Cl(GSPC), 200))
user system elapsed
0.24 0.00 0.24
> all.equal(x,y)
[1] "Mean relative difference: 0.005025126"
仔细观察后,第一个函数中似乎有一些奇怪的边缘情况:
data <- c(1,2,3,4,5,6,7,7,6,5,6,7,8,5,4,3,2,1)
answer <- c(0,0,0,0,1,2,3,0,0,1,2,3,4,4)
x <- daysSinceHigh1(data, 5)
y <- daysSinceHigh2(data, 5)
> x
[1] 0 0 0 1 2 3 4 4 0 1 2 3 4 4
> y
[1] 0 0 0 0 1 2 3 0 0 1 2 3 4 4
> answer
[1] 0 0 0 0 1 2 3 0 0 1 2 3 4 4
> all.equal(x,answer)
[1] "Mean relative difference: 0.5714286"
> all.equal(y,answer)
[1] TRUE
因此,似乎第二个功能(基于Andrie的代码)更好。