Применить функцию прокрутки к списку объектов xts

Это похоже на несколько других вопросов, но мне все еще не удалось заставить его работать. Я пытаюсь применить функцию прокрутки (runMAD из пакета TTR) к серии финансовой информации (цена и объем торговли), но операция прокрутки должна быть внутридневной (т.е. не переходить ни на следующий день, ни на предыдущий). день).

Данные хранятся в виде объекта xts с двумя столбцами (цена и объем). Я разделил этот объект по дням, чтобы создать список объектов xts по дням, надеясь затем применить функцию runMAD в течение каждого дня и вернуть список объектов xts с четырьмя столбцами (два столбца исходной цены и объема, а затем две новые для runMAD-price и runMAD-volume). Однако кажется, что lapply может возвращать только список длины, равной количеству дней, поэтому такая функция, как среднесуточное значение, будет работать, но не уверен, как заставить работать скользящие функции, которые выдают несколько результатов в день. В конечном счете, я хотел бы протестировать каждую строку цены и объема, чтобы увидеть, не превышает ли ее отклонение от медианы, скажем, в 3 раза больше соответствующего скользящего MAD. Такие экземпляры затем будут сохранены в переменной (с индексом xts).

sample data:
2011-01-02 09:11:00     20.20     20000
2011-01-02 10:42:00     20.40     50000
2011-01-02 12:33:00     20.90      5000
2011-01-02 12:33:00     20.90     10000
2011-01-02 13:25:00     20.90     10000
2011-01-02 15:36:00     20.90     50000
2011-01-02 15:39:00     20.90     50000
2011-01-02 16:12:00     20.90     15000
2011-01-02 16:33:00     20.90     50000
2011-01-02 17:04:00     20.90     50000
2011-01-02 17:05:00     20.90     50000
2011-01-02 18:26:00     20.90     10000
2011-01-03 09:21:00     20.20     20000
2011-01-03 11:19:00     20.40     50000
2011-01-03 17:33:00     20.90      5000
2011-01-06 12:33:00     20.90     10000
2011-01-06 13:25:00     20.90     10000
2011-01-06 15:36:00     20.90     50000
2011-01-06 15:39:00     20.90     50000
2011-01-06 16:20:00     20.90     15000
2011-01-06 16:20:00     20.90     50000
2011-01-06 17:24:00     20.90     50000
2011-01-06 17:55:00     20.90     50000
2011-01-06 18:49:00     20.90     10000

[РЕДАКТИРОВАТЬ: после комментария GSee, вот увеличенный (и фиксированный) образец вывода данных:]

dput(head(sample.data,200))
structure(c(23.48, 19.08, 22.43, 21.75, 19.78, 19.76, 23.11, 23.31, 19.58, 19.28, 23.68, 23.47, 22.13, 23.17, 24.53, 22.79, 20.28, 19.73, 22.05, 19.23, 22.40, 23.43, 20.40, 23.58, 19.94, 19.58, 21.70, 20.65, 21.69, 24.09, 22.21, 21.42, 19.48, 24.20, 23.37, 24.68, 21.64, 23.24, 23.59, 19.61, 21.89, 23.21, 19.47, 24.77, 19.64, 19.61, 21.07, 24.68, 20.20, 23.37, 24.47, 22.55, 19.64, 22.73, 23.94, 21.31, 19.69, 19.51, 21.27, 20.47, 23.67, 23.42, 20.56, 20.60, 22.23, 22.16, 20.78, 21.47, 24.82, 19.34, 19.08, 24.92, 24.12, 20.46, 21.67, 22.25, 19.16, 22.47, 24.00, 23.32, 21.13, 23.67, 20.35, 20.80, 23.48, 21.22, 21.51, 21.91, 24.06, 22.17, 24.23, 22.43, 24.94, 20.99, 24.93, 22.48, 21.74, 19.18, 21.14, 21.89, 20.23, 24.80, 22.81, 20.96, 24.30, 21.11, 23.69, 23.20, 20.09, 23.09, 21.56, 20.93, 22.97, 24.53, 23.96, 19.33, 24.63, 19.27, 19.57, 21.40, 24.04, 22.37, 24.95, 21.37, 24.01, 20.42, 21.82, 19.06, 23.08, 20.37, 21.28, 19.87, 21.84, 20.95, 20.89, 24.59, 19.18, 24.26, 20.64, 22.12, 20.85, 24.31, 22.55, 24.32, 19.90, 24.58, 24.13, 21.55, 21.06, 20.84, 20.68, 23.47, 19.67, 21.82, 23.31, 19.67, 19.45, 24.56, 20.06, 24.46, 19.89, 21.57, 20.21, 24.20, 20.53, 19.91, 23.67, 22.95, 21.18, 21.57, 20.01, 19.36, 20.65, 19.75, 22.12, 19.79, 21.07, 24.77, 21.46, 20.64, 21.94, 19.81, 23.58, 22.48, 21.03, 19.37, 19.46, 22.68, 24.56, 21.40, 21.94, 23.27, 21.26, 20.34, 23.39, 21.97, 22.25, 22.40, 23.44, 24.38, 5900, 2400, 3100, 1200, 5100, 5700, 3400, 4900, 3900, 6400, 2600, 2200, 2800, 6200, 1100, 2500, 3500, 5900, 6600, 5100, 1800, 4200, 4500, 1200, 6200, 1400, 2800, 2400, 1500, 900, 2900, 3200, 5800, 3500, 4500, 4500, 4500, 6800, 5000, 4900, 5300, 6100, 3400, 1500, 6200, 1500, 5400, 5800, 800, 6300, 5000, 3400, 5500, 5600, 2100, 3700, 4400, 3100, 4600, 2700, 2700, 2700, 2600, 1200, 1700, 2900, 5300, 4900, 2600, 3100, 4000, 6000, 2500, 3000, 6500, 3600, 5900, 2300, 1600, 1300, 4800, 3800, 4000, 1500, 5600, 5500, 1500, 3100, 1300, 3200, 1500, 1400, 1400, 4600, 5300, 5600, 1200, 1500, 6100, 2200, 6700, 1700, 4000, 6200, 2700, 1100, 4500, 5400, 1600, 2600, 5700, 4100, 7000, 2300, 2600, 5100, 4500, 1900, 2400, 2600, 6900, 2100, 3500, 3600, 2900, 900, 2800, 2200, 4900, 1700, 3000, 800, 2500, 6100, 3300, 6500, 2600, 6200, 900, 4000, 6600, 6400, 1000, 4800, 6900, 4000, 2800, 1200, 6200, 2700, 1300, 1200, 2800, 1300, 5900, 4000, 3900, 5300, 2400, 4700, 6900, 2900, 6200, 3300, 6900, 2200, 1800, 5500, 2000, 6400, 3500, 5300, 5000, 6700, 4500, 3200, 1700, 3300, 5000, 5800, 4900, 2100, 1200, 5200, 1000, 900, 2600, 1000, 5500, 3400, 1600, 4700, 1500, 5900, 6900, 3700, 4900, 5700, 900, 2400), class = c("xts", "zoo"), .indexCLASS = c("POSIXlt", 
"POSIXt"), .indexTZ = "", tclass = c("POSIXlt", "POSIXt"), tzone = "", index = structure(c(1325584080, 1325594940, 1325594940, 1325604600, 1325759100, 1325762520, 1325762520, 1325769300, 1325769300, 1325848080, 1325864880, 1326128220, 1326196500, 1326196500, 1326196500, 1326196500, 1326196500, 1326196500, 1326209700, 1326279480, 1326283620, 1326288300, 1326288300, 1326289680, 1326289680, 1326289680, 1326292320, 1326294060, 1326294600, 1326297600, 1326387000, 1326456720, 1326467160, 1326711600, 1326723000, 1326724260, 1326809940, 1326814860, 1326885960, 1326885960, 1326889980, 1326894000, 1326895200, 1326895200, 1326898080, 1326986700, 1326987240, 1326992100, 1327072140, 1327328040, 1327328040, 1327328040, 1327417920, 1327423140, 1327424820, 1327425240, 1327483200, 1327496520, 1327570320, 1327570320, 1327575420, 1327588680, 1327588980, 1327595880, 1327595880, 1327595880, 1327664820, 1327674720, 1327680660, 1327680780, 1327680780, 1327683960, 1327914300, 1327914300, 1327915260, 1327918140, 1327924860, 1327924920, 1327924980, 1327924980, 1327927680, 1328013360, 1328014200, 1328025000, 1328025000, 1328026740, 1328089440, 1328091360, 1328091360, 1328110620, 1328111340, 1328111340, 1328112420, 1328113800, 1328193540, 1328194080, 1328194140, 1328196720, 1328274360, 1328274420, 1328278320, 1328519280, 1328520120, 1328520600, 1328520600, 1328524140, 1328527980, 1328531580, 1328540880, 1328540880, 1328547600, 1328547660, 1328547720, 1328547780, 1328607060, 1328608080, 1328618760, 1328623380, 1328623380, 1328625720, 1328631480, 1328717760, 1328717880, 1328793000, 1328797980, 1329132840, 1329210480, 1329215400, 1329215820, 1329215820, 1329219480, 1329223140, 1329300900, 1329301620, 1329315240, 1329315240, 1329388740, 1329389700, 1329390000, 1329390000, 1329390180, 1329391860, 1329391860, 1329391860, 1329402120, 1329467700, 1329467700, 1329469080, 1329469080, 1329471300, 1329477000, 1329477000, 1329489840, 1329732660, 1329732660, 1329733080, 1329745980, 1329745980, 1329750120, 1329750120, 1329750780, 1329753780, 1329753780, 1329753900, 1329754080, 1329754260, 1329755520, 1329755520, 1329755820, 1329755880, 1329755880, 1329756000, 1329815040, 1329815040, 1329826380, 1329840000, 1329841200, 1329841200, 1329842220, 1329901080, 1329901200, 1329901200, 1329901680, 1329901680, 1329902040, 1329902100, 1329902100, 1329902100, 1329902340, 1329902340, 1329902340, 1329902520, 1329902880, 1329902880, 1329906720, 1329906840, 1329908460, 1329910980, 1329911880, 1329914400), tzone = "", tclass = c("POSIXlt", "POSIXt")), .Dim = c(200L, 2L), .Dimnames = list(NULL, c("sample.dataprice", "sample.datavol")))

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

Строка моих данных:

str (sample.data)

An ‘xts’ object on 2012-01-03 09:11:00/2012-03-30 18:49:00 containing:
  Data: num [1:459, 1:2] 22.6 22.5 22.5 22.5 22.8 ...
 - attr(*, "dimnames")=List of 2
  ..$ : NULL
  ..$ : chr [1:2] "sample.dataprice" "sample.datavol"
  Indexed by objects of class: [POSIXlt,POSIXt] TZ: 
  xts Attributes:  
 NULL

Я split это на дни, а затем runMAD:

sample.data.days <- split.xts(sample.data, f="days")
require(TTR)
runMAD(sample.data.days, n=6, stat="median", cumulative=FALSE, constant=1)
*Error in runMedian(x, n, cumulative = cumulative) : (list) object cannot be coerced to type 'double'*

Чтобы не применять runMAD к дням, когда количество наблюдений меньше, чем длина окна, я оставляю только дни с достаточным количеством наблюдений:

sample.data.days6<- sample.data.days[vapply(sample.data.days, FUN=nrow, FUN.VALUE=0L)>6]

Я тоже пробовал это:

do.call(runMAD, lapply(as.numeric(index(sample.data.days6)), function(x) runMAD(sample.data.days6, constant=1)))

Но он выдает ту же ошибку, что и выше (Ошибка в runMedian (x, n, cumulative = cumulative): объект (list) не может быть принудительно введен для ввода 'double').

Вместо того, чтобы помещать данные в список для разбивки на дни, я также пробовал это:

apply.daily(sample.data, function(d){
  c(runMAD_price = runMAD(d$sample.data[, 1], n=6),
    runMAD_volume = runMAD(d$sample.data[, 2], n=6),
  )
})
*Error in array(x, c(length(x), 1L), if (!is.null(names(x))) list(names(x),  : 'data' must be of a vector type

Небольшая вариация этого вопроса состоит в том, чтобы увидеть, как то же самое можно сделать для скользящего временного окна (например, 1 час) вместо скользящего окна сделок.

Независимо от того, основано ли окно на времени или на наблюдениях, я хотел бы в конечном итоге создать объект xts, содержащий все наблюдения, для которых отклонение значения (цены или объема) от медианы определенного окна, деленное на MAD (в середине window) выше определенного порога (например, 3). Поскольку MAD будет 0, когда половина наблюдений одинакова, я хотел бы заменить любой 0 любым предыдущим MAD> 0.


person Rothsom    schedule 19.03.2013    source источник
comment
Пожалуйста, добавьте фиктивные данные, чтобы сделать их воспроизводимыми. Первым шагом будет сделать что-то вроде do.call(rbind, lapply(split(x, "days"), runMAD)), но будет легче показать это, если вы предоставите данные.   -  person GSee    schedule 19.03.2013
comment
Но ни один из дней в вашей выборке не содержит более 5 строк. Итак, к моменту попытки применить runMAD данных не останется   -  person GSee    schedule 19.03.2013
comment
Извините, GSee, я выложу более крупный образец, как только вытащу его.   -  person Rothsom    schedule 19.03.2013
comment
:-( Проверьте свой dput: Error: unexpected ')' in ""sample.datavol")". В любом случае, вы все еще не знаете, как делать то, что вы хотите?   -  person GSee    schedule 19.03.2013
comment
Теперь надо исправить dput. Полезный ответ Джошуа v завершил первую часть - теперь у меня есть данные (такие же, как dput) с двумя дополнительными столбцами, один для runMAD_price и один для runMAD_vol. Но я также хотел бы создать еще два столбца абсолютного отклонения каждого наблюдения цены и объема от медианы наблюдений в том же окне длины, что и runMAD, разделенных на runMAD. Поскольку он движется, abs dev создаст квадратную матрицу dim, равную количеству obs, но я бы хотел вытащить abs dev, соответствующий runMAD в этой строке. Надеюсь, это имеет смысл - и спасибо!   -  person Rothsom    schedule 19.03.2013
comment
GSee, я думаю, что решил это сейчас. Должно было быть реализовано раньше, но это точно такой же процесс, как у Джошуа, просто используя runMedian, затем создайте столбец абс (столбец цены - столбец цены runMedian) / runMadprice (и повторите для объема). Для других пользователей [R] со всем слиянием легче создать список новых созданных столбцов, а затем использовать Reduce (функция (...) merge (..., all = T), sampledatalist). Тем не менее, большое спасибо за помощь!   -  person Rothsom    schedule 19.03.2013


Ответы (1)


Вам нужно перебрать ваш sample.data.days список и применить runMAD к каждому элементу. Затем вы можете объединить его с исходным объектом. Например:

library(TTR)
data(sample_matrix)
x <- as.xts(sample_matrix)
close.months <- split(x$Close,"months")
mad <- do.call(rbind, lapply(close.months, runMAD, n=6, constant=1))
y <- merge(x,Close.MAD=mad)
person Joshua Ulrich    schedule 19.03.2013
comment
Спасибо, это отлично решило. Очень признателен за помощь! - person Rothsom; 19.03.2013