4

我有一个大型 (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 分钟以上。数据看起来像这样(非常放大) 在此处输入图像描述

随着窗口在这些间隙中移动,窗口内的点数应该会有所不同。

以下是我想要在 R 中执行的操作(相同的表结构)的 MySQL 代码:

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
;  
4

2 回答 2

3

1)如果DF是问题中显示的数据框,则按照您所做的那样从中创建一个 zoo 对象,并将其拆分为 daysgiving 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)这可以交替地按照以下方式完成,其中wf如上:

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

如果需要,将sapply其替换为。lapply此外,这可能看起来比第一个解决方案更短,但是一旦您添加代码来定义fw(出现在第一个而不是第二个),它并没有太大的不同。

如果白天没有空洞,而只有几天之间的空洞,那么可以简化这些解决方案。

于 2011-12-18T21:43:58.840 回答
3

假设您的目标时间 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), ])
}
于 2011-12-19T10:06:08.170 回答