R: Эффективное поднабор данных в зависимости от времени суток. - PullRequest
4 голосов
/ 18 декабря 2011

У меня большой (150 000x7) фрейм данных, который я собираюсь использовать для бэк-тестирования и анализа финансового рынка в режиме реального времени. Данные представляют состояние инвестиционного инструмента с 5-минутными интервалами (, хотя дыры существуют ). Это выглядит так (но гораздо дольше):

        pTime     Time  Price       M1       M2        M3        M4
1  1212108300 20:45:00 1.5518 12.21849 -0.37125   4.50549 -31.00559
2  1212108900 20:55:00 1.5516 11.75350 -0.81792  -1.53846 -32.12291
3  1212109200 21:00:00 1.5512 10.75070 -1.47438  -8.24176 -34.35754
4  1212109500 21:05:00 1.5514 10.23529 -1.06044  -8.46154 -33.24022
5  1212109800 21:10:00 1.5514  9.74790 -1.02759 -10.21978 -33.24022
6  1212110100 21:15:00 1.5513  9.31092 -1.17076 -11.97802 -33.79888
7  1212110400 21:20:00 1.5512  8.84034 -1.28428 -13.62637 -34.35754
8  1212110700 21:25:00 1.5509  8.07843 -1.63715 -18.24176 -36.03352
9  1212111000 21:30:00 1.5509  7.39496 -1.49198 -20.65934 -36.03352
10 1212111300 21:35:00 1.5512  7.65266 -1.03717 -18.57143 -34.35754

Данные предварительно загружены в R, но во время моего бэк-теста мне нужно установить их по двум критериям:

Первый критерий - это скользящее окно, чтобы не заглядывать в будущее. Окно должно быть таким, чтобы каждый новый 5-минутный интервал бэк-теста сдвигал все окно в будущее на 5 минут. Эту часть я могу сделать так:

require(zoo)
zooser <- zoo(x=tser$Close, order.by=as.POSIXct(tser$pTime, origin="1970-01-01"))
window(zooser, start=A, end=B)    

Вторым критерием является другое скользящее окно, но оно скользит по time of day и содержит только те записи, которые находятся в пределах N минут от времени ввода в любой данный день.

Пример. Если размер окна равен 2 hours, а время ввода - 12:00PM, то в окне должны быть все строки с Time в диапазоне от 10:00AM до 2:00PM

Это та часть, которую мне трудно понять.

Редактировать: в моих данных есть дыры, две последовательные строки могут быть более 5 минут друг от друга. Данные выглядят так (очень увеличено) enter image description here

Когда окно проходит через эти промежутки, количество точек внутри окна должно меняться.

Ниже приведен мой код MySQL, который делает то, что я хочу сделать в R (та же структура таблицы):

SET @qTime = Time(FROM_UNIXTIME(SAMP_endTime));

SET @inc = -1;
INSERT INTO MetIndListBuys (pTime,ArrayPos,M1,M2,M3,M4)
SELECT pTime,@inc:=@inc+1,M1,M2,M3,M4
 FROM mergebuys USE INDEX (`y`) WHERE  pTime BETWEEN SAMP_startTime AND SAMP_endTime 
AND TIME_TO_SEC(TIMEDIFF(Time,@qTime))/3600 BETWEEN 0-HourSpan AND HourSpan
;  

Ответы [ 2 ]

3 голосов
/ 19 декабря 2011

Скажите, что у вас есть целевое время t0 в том же масштабе, что и pTime: секунды с начала эпохи.Тогда t0 - pTime = (разница в количестве дней с начала эпохи между ними) + (разница в оставшихся секундах).Если взять t0 - pTime %% (количество секунд в день), то у нас останется разница в секундах в арифметике часов (оборачивается, если разница отрицательная).Это предполагает следующую функцию:

SecondsPerDay <- 24 * 60 * 60
within <- function(d, t0Sec, wMin) {
  diff <- (d$pTime - t0Sec) %% SecondsPerDay
  wSec <- 60 * wMin
  return(d[diff < wSec | diff > (SecondsPerDay - wSec), ])
}
3 голосов
/ 19 декабря 2011

1) Если DF - это фрейм данных, показанный в вопросе, то создайте из него объект зоопарка, как вы это сделали, и разделите его на дни, дающие zs.Затем lapply ваша функция f для каждого последующего набора w точек в каждом компоненте (то есть в каждый день).Например, если вы хотите применить свою функцию к 2 часам данных за раз, и ваши данные регулярно разнесены на 5-минутные данные, тогда w = 24 (так как в течение двух часов есть 24 пятиминутных периода).В таком случае f будет передано 24 строки данных в виде матрицы каждый раз, когда ее вызывают.Также align было установлено на "right" ниже, но его можно альтернативно установить на align="center", а условие, дающее ix, можно изменить на двухстороннее и т. Д. Подробнее о rollapply см .: ?rollapply

library(zoo)
z <- zoo(DF[-2], as.POSIXct(DF[,1], origin = "1970-01-01"))
w <- 3 # replace this with 24 to handle two hours at a time with five min data
f <- function(x) {
            tt <- x[, 1]
            ix <- tt[w] - tt <= w * 5 * 60 # RHS converts w to seconds
            x <- x[ix, -1]
            sum(x) # replace sum with your function
    }
out <- rollapply(z, w, f, by.column = FALSE, align = "right")

Используя фрейм данных в вопросе, мы получаем это:

> out
$`2008-05-30`
2008-05-30 02:00:00 2008-05-30 02:05:00 2008-05-30 02:10:00 2008-05-30 02:15:00 
          -66.04703           -83.92148           -95.93558          -100.24924 
2008-05-30 02:20:00 2008-05-30 02:25:00 2008-05-30 02:30:00 2008-05-30 02:35:00 
         -108.15038          -121.24519          -134.39873          -140.28436 

Кстати, обязательно прочитайте этот пост .

2) Это можно сделать поочередно следующим образом, где w и f такие же, как указано выше:

n <- nrow(DF)
m <- as.matrix(DF[-2])
sapply(w:n, function(i) { m <- m[seq(length = w, to = i), ]; f(m) })

Замените sapply на lapply при необходимости.Также это может показаться короче, чем первое решение, но не сильно отличается, когда вы добавляете код для определения f и w (которые появляются в первом, но не во втором).

Если в течение дня дыр нет, а между днями дыр, то эти решения могут быть упрощены.

...