Как рассчитать периоды, начиная с 200-периодного максимума акции - PullRequest
4 голосов
/ 09 сентября 2011

Я хотел бы рассчитать количество периодов, прошедших с максимума 200 периодов одномерного временного ряда. Например, вот цена закрытия SPY:

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

Теперь я могу найти 200-периодные максимумы этой серии, используя функцию Lag в quantmod:

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

Но теперь я застрял. Как мне слить это обратно в исходный ряд (Data) и рассчитать, для каждой точки ряда, сколько периодов прошло с момента предыдущего максимума n-периода?

Ответы [ 3 ]

5 голосов
/ 09 сентября 2011

Эта небольшая функция возвращает список с:

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

enter image description here

3 голосов
/ 09 сентября 2011

Ответ на ваш исправленный вопрос:

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

enter image description here Очевидно, что вы ничего не сможете объединить обратно к первым 200 датам, если не примените более слабое определение скользящего максимума. (В другом сеансе SO, в котором использовались «сдвинутые» данные, я показал, как использовать embed для заполнения «завершающих» периодов: Преобразование данных в R , но я не знаю, хотите ли вы построить матрицы, которые в 200 раз больше размером с ваши входные данные.)

0 голосов
/ 12 сентября 2011

Я отредактировал код из предыдущих ответов так, что они являются функциями, которые принимают одинаковые входные данные (одномерный временной ряд) и возвращают тот же результат (вектор дней с момента последнего 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"

При ближайшем рассмотрении оказывается, что в 1-й функции есть некоторые странные крайние случаи:

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

Поэтому, похоже, что вторая функция (на основе кода Андри) лучше.

...