4

我想计算自单变量时间序列的 200 个周期高点以来经过的周期数。例如,这是 SPY 的收盘价:

require(quantmod)
getSymbols("SPY",from='01-01-1900')
Data <- Cl(SPY)

Lag现在,我可以使用quantmod中的函数找到该系列的 200 个周期高点:

periodHigh <- function(x,n) {
    Lags <- Lag(x,1:n)
    High <- x == apply(Lags,1,max)
    x[High]
}
periodHigh(Data, 200)

但现在我被困住了。如何将其合并回原始序列 ( Data) 并计算序列中的每个点,自上一个 n 周期高点以来已经过去了多少周期?

4

3 回答 3

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")

在此处输入图像描述

于 2011-09-08T21:52:22.840 回答
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 个日期。(在另一个涉及“多变”数据的 SO 会话中,我展示了如何使用嵌入来填充“尾随”句点:R 中的数据转换,但我不知道您是否要构建 200 倍于输入数据的矩阵.)

于 2011-09-08T21:38:24.830 回答
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 的代码)更好。

于 2011-09-12T15:17:37.540 回答