R: использование apply.fromstart для расчета доходности и стандартного отклонения

Я хотел бы найти общий доход, который кто-то получил за период, а также стандартное отклонение его доходов. Я нашел функцию apply.fromstart в пакете PerformanceAnalytics, которая выглядит многообещающе. Однако у меня возникают трудности с его реализацией.

Вот что у меня есть: кадр данных, содержащий различные данные, включая доход за период:
HourlyData

        Time            Position  
2014-08-01 01:00:00      1.01    
2014-08-01 02:00:00      0.99  
2014-08-01 03:00:00      1.01  
2014-08-01 04:00:00      1.02  

Я хотел бы найти общий доход в каждом периоде следующим образом:

Period                TotalReturn
2014-08-01 01:00:00      1.01    
2014-08-01 02:00:00      1.01*0.99
2014-08-01 03:00:00      1.01*.099*1.01
2014-08-01 04:00:00      1.01*.099*1.01*1.02

Мой код в настоящее время гласит:
apply.fromstart(hourlyData[,2,drop = FALSE],FUN="*",width=1)

Я также хотел бы найти стандартное отклонение его доходности. Мой код для этой части выглядит следующим образом:
apply.fromstart(hourlyData[,2,drop = FALSE],FUN="sd",width=1)

Тип данных hourlyData$Position — «зоопарк».

Я получаю следующую ошибку: In zoo(NA, order.by = as.Date(time(R))) : some methods for “zoo” objects do not work if the index entries in ‘order.by’ are not unique

Я проверил, и в моих именах строк нет дубликатов.

Вот результат запуска dput(hourlyData):

> structure(list(Period = structure(c(1406844000, 1406847600,
> 1406851200,  1406854800, 1406858400, 1406862000), class = c("POSIXct",
> "POSIXt" )), Login = c(173908L, 173908L, 173908L, 173908L, 173908L,
> 173908L ), NetExposureUSD = c(2188640, 2188730, 2189230, 2189000,
> 2188310,  2187710), EquityUSD = c(9303.51, 9237.82, 8582.18, 9074.76,
> 9929.96, 
> 10743.57), UnrealizedProfitUSD = c(-31.64, -97.33, -752.97, -260.39, 
> 594.81, 1408.42), DepositWithdrawal = c(0, 0, 0, 0, 0, 0), LaggedEquity = structure(c(0, 
> 9303.51, 9237.82, 8582.18, 9074.76, 9929.96), index = 1:6, class = "zoo"), 
>     Return = structure(c(0, -0.00706077598669755, -0.0709734547761268, 
>     0.0573956733603816, 0.0942394068823857, 0.0819348718423841
>     ), index = 1:6, class = "zoo"), Position = structure(c(1, 
>     0.992939224013302, 0.929026545223873, 1.05739567336038, 1.09423940688239, 
>     1.08193487184238), index = 1:6, class = "zoo"), SD = c(NA, 
>     NA, 0.0390979887599392, 0.0641847560185966, 0.0867288719859795, 
>     0.0187573743033249)), .Names = c("Period", "Login", "NetExposureUSD",  "EquityUSD", "UnrealizedProfitUSD",
> "DepositWithdrawal", "LaggedEquity",  "Return", "Position", "SD"),
> row.names = c("2014-08-01 01:00:00",  "2014-08-01 02:00:00",
> "2014-08-01 03:00:00", "2014-08-01 04:00:00",  "2014-08-01 05:00:00",
> "2014-08-01 06:00:00"), class = "data.frame")
>                                  Period  Login NetExposureUSD EquityUSD UnrealizedProfitUSD DepositWithdrawal LaggedEquity      
> Return  Position         SD 2014-08-01 01:00:00 2014-08-01 01:00:00
> 173908        2188640   9303.51              -31.64                 0 
> 0.00  0.000000000 1.0000000         NA 2014-08-01 02:00:00 2014-08-01 02:00:00 173908        2188730   9237.82              -97.33          
> 0      9303.51 -0.007060776 0.9929392         NA 2014-08-01 03:00:00
> 2014-08-01 03:00:00 173908        2189230   8582.18            
> -752.97                 0      9237.82 -0.070973455 0.9290265 0.03909799 2014-08-01 04:00:00 2014-08-01 04:00:00 173908        2189000   9074.76             -260.39                 0      8582.18 
> 0.057395673 1.0573957 0.06418476 2014-08-01 05:00:00 2014-08-01 05:00:00 173908        2188310   9929.96              594.81          
> 0      9074.76  0.094239407 1.0942394 0.08672887 2014-08-01 06:00:00
> 2014-08-01 06:00:00 173908        2187710  10743.57            
> 1408.42                 0      9929.96  0.081934872 1.0819349 0.01875737

person Mike    schedule 12.11.2014    source источник
comment
Разве вы не можете просто использовать Reduce(*, hourlyData$Position) ?   -  person David Arenburg    schedule 12.11.2014
comment
Спасибо за ответ. Я получаю сообщение об ошибке, когда запускаю это: unexpected * in Reduce. Нужно ли устанавливать отдельный пакет?   -  person Mike    schedule 12.11.2014
comment
Reduce - это основа R. Вам нужно поместить * в обратные кавычки, как в *. Это просто НАСТОЛЬКО не позволяет это в комментариях   -  person David Arenburg    schedule 12.11.2014
comment
Под обратными кавычками вы имеете в виду одинарные кавычки? Я поставил это, и теперь получаю ошибку Error in x[[i]] : subscript out of bounds. Не уверен, что это значит?   -  person Mike    schedule 12.11.2014
comment
Хорошо, попробуй Reduce("*", hourlyData$Position)   -  person David Arenburg    schedule 12.11.2014
comment
Это дает мне ту же ошибку. Тип данных для hourlyData$Position — зоопарк, если это важно.   -  person Mike    schedule 12.11.2014
comment
Можете ли вы предоставить dput(hourlyData)?   -  person David Arenburg    schedule 12.11.2014
comment
Хорошо, как мне это сделать?   -  person Mike    schedule 12.11.2014
comment
Просто напишите это в консоли и вставьте результат в вопрос?   -  person David Arenburg    schedule 12.11.2014
comment
Хорошо, я вставил это, но это полный беспорядок, извините. Я не знаю, как это очистить. Единственными двумя важными столбцами являются столбцы «Период» и «Позиция».   -  person Mike    schedule 12.11.2014
comment
Хорошо, попробуй Reduce("*", as.numeric(hourlyData$Position)). Фот sd, попробуй sd(as.numeric(hourlyData$Position))   -  person David Arenburg    schedule 12.11.2014
comment
Хорошо, это дает мне один номер. Кажется, это последнее число, производящее умножение всех элементов. Теперь я понимаю, что вопрос был неясен, извините. Я хочу рассчитать общий доход за КАЖДЫЙ период, позвольте мне быстро изменить вопрос. Извини за это!   -  person Mike    schedule 12.11.2014
comment
Превосходно! Огромное спасибо! Это отлично работает для возврата, есть ли аналогичная функция для стандартного отклонения?   -  person Mike    schedule 12.11.2014
comment
Вы хотите прогрессировать SD?   -  person David Arenburg    schedule 12.11.2014
comment
Как ранее предоставил @akrun sapply(seq_len(nrow(hourlyData)), function(i) sd(hourlyData$Position[1:i]))   -  person David Arenburg    schedule 12.11.2014
comment
кстати, вы можете сохранить свой zoo класс, работая cumprod всего на cumprod(hourlyData$Position)   -  person David Arenburg    schedule 12.11.2014
comment
Идеально, большое спасибо! Если хотите, добавьте ответ на этот вопрос, чтобы я мог принять. Спасибо еще раз!   -  person Mike    schedule 12.11.2014
comment
@Mike, для совокупного SD, который кажется быстрым, см. этот ответ ,. Это также выглядит соответствующий.   -  person Henrik    schedule 12.11.2014


Ответы (1)


Используйте очень эффективную векторизованную базовую функцию R cumprod для получения первого желаемого результата. В то время как второй результат может быть достигнут (менее эффективно) с помощью простого цикла *apply

Если вы хотите сохранить класс zoo, сделайте

cumprod(hourlyData$Position)
#         1         2         3         4         5         6 
# 1.0000000 0.9929392 0.9224669 0.9754125 1.0673348 1.1547867

В противном случае

cumprod(as.numeric(hourlyData$Position))
## [1] 1.0000000 0.9929392 0.9224669 0.9754125 1.0673348 1.1547867

Для sd (как предложил @akrun) (использовал vapply вместо sapply, чтобы "выжать" из него максимальную производительность)

vapply(seq_len(nrow(hourlyData)), function(i) sd(hourlyData$Position[1:i]), FUN.VALUE = double(1))
# [1] NA 0.004992723 0.039097989 0.052519398 0.063598345 0.063156702
person David Arenburg    schedule 12.11.2014
comment
@ Дэвид Аренбург, вы можете посмотреть здесь для вычисления кумулятивного стандартного отклонения без *apply (что кажется быстрым). - person Henrik; 12.11.2014