Похоже, эта процедура накладывает внутридневной стоп-лосс на основе максимального отката. Поэтому я предполагаю, что вы хотите иметь возможность передавать переменное ограничение в качестве второго аргумента вашей функции агрегирования, которая только в настоящее время принимает только 1 функцию из-за способа работы ave.
Если поместить все это в одну строку не является абсолютной необходимостью, я могу поделиться написанной мной функцией, которая обобщает агрегацию через «переменные среза». Вот код:
mtapplylist2 <- function(t, IDX, DEF, MoreArgs=NULL, ...)
{
if(mode(DEF) != "list")
{
cat("Definition must be list type\n");
return(NULL);
}
a <- c();
colnames <- names(DEF);
for ( i in 1:length(DEF) )
{
def <- DEF[[i]];
func <- def[1];
if(mode(func) == "character") { func <- get(func); }
cols <- def[-1];
# build the argument to be called
arglist <- list();
arglist[[1]] <- func;
for( j in 1:length(cols) )
{
col <- cols[j];
grp <- split(t[,col], IDX);
arglist[[1+j]] <- grp;
}
arglist[["MoreArgs"]] <- MoreArgs;
v <- do.call("mapply", arglist);
# print(class(v)); print(v);
if(class(v) == "matrix")
{
a <- cbind(a, as.vector(v));
} else {
a <- cbind(a, v);
}
}
colnames(a) <- colnames;
return(a);
}
И вы можете использовать его так:
# assuming you have the data in the data.frame
df <- data.frame(date=rep(1:10,10), ret=rnorm(100), limit=rep(c(0.25,0.50),50))
dfunc <- function(x, ...) { return(cummax(x)-x ) }
pfunc <- function(x,y, ...) { return((cummax(x)-x) < y) }
# assumes you have the function declared in the same namespace
def <- list(
"drawdown" = c("dfunc", "ret"),
"hasdrawdown" = c("pfunc", "ret", "limit")
);
# from R console
> def <- list("drawdown" = c("dfunc", "ret"),"happened" = c("pfunc","ret","limit"))
> dim( mtapplylist2(df, df$date, def) )
[1] 100 2
Обратите внимание, что переменная "def" представляет собой список, содержащий следующие элементы:
- имя вычисляемого столбца
- имя функции векторного аргумента в виде строки
- имя переменной во входных данных.frame, которые являются входными данными для функции
Если вы посмотрите на внутренности функции "mtapplylist2", ключевыми компонентами будут "split" и "mapply". Эти функции достаточно быстрые (я думаю, что разделение реализовано в C).
Это работает с функциями, требующими нескольких аргументов, а также с функциями, возвращающими вектор одинакового размера или агрегированного значения.
Попробуйте и дайте мне знать, если это решит вашу проблему.