2011-01-20 1 views
4

Я пытаюсь вычислить размер выигрышной и проигрышной серии, и этот вопрос является продолжением earlier question, когда я попытался рассчитать длину полоса.Вычисление размера выигрышной и проигрывающей полосы

Это то, что выглядит мои данные, как:

> subRes 
    Instrument TradeResult.Currency. 
1   JPM     -3 
2   JPM     264 
3   JPM     284 
4   JPM     69 
5   JPM     283 
6   JPM     -219 
7   JPM     -91 
8   JPM     165 
9   JPM     -35 
10  JPM     -294 
11  KFT     -8 
12  KFT     -48 
13  KFT     125 
14  KFT     -150 
15  KFT     -206 
16  KFT     107 
17  KFT     107 
18  KFT     56 
19  KFT     -26 
20  KFT     189 
> dput(subRes) 
structure(list(Instrument = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("JPM", 
"KFT"), class = "factor"), TradeResult.Currency. = c(-3, 264, 
284, 69, 283, -219, -91, 165, -35, -294, -8, -48, 125, -150, 
-206, 107, 107, 56, -26, 189)), .Names = c("Instrument", "TradeResult.Currency." 
), class = "data.frame", row.names = c(NA, 20L)) 

Моя цель: Я хочу, чтобы вычислить размер самой длинной выигрышной и проигрыш, для каждого инструмента. Таким образом, для JPM это будут строки 2, 3, 4 и 5 из приведенных выше данных, что дает следующие значения TradeResult.Currency.: 264 + 284 + 69 +283, в общей сложности 900. Размер самой длинной проигрышной полосы для JPM будет строка 9 и 10, что даст общий результат -329 (-35 + -294). Для KFT размер самой длинной выигрышной полосы составляет 270 (107 + 107 + 56, строчки с 16 по 18), а размер самой длинной полосы потерь будет -356 (-150 + -206, строки 14 & 15).

Следующая функция дает правильного размера победной серии ...

WinStreakSize <- function(x){ 
    df.rle <- ifelse(x > 0, 1, 0) 
    df.rle <- rle(df.rle) 
    wh <- which(df.rle$lengths == max(df.rle$lengths)) 
    mx <- df.rle$lengths[wh] 
    suma <- df.rle$lengths[1:wh] 
    out <- x[(sum(suma) - (suma[length(suma)] - 1)):sum(suma)] 
    return(sum(out)) 
} 

.. в результате:

> with(subRes, tapply(TradeResult.Currency., Instrument, WinStreakSize) 
+) 
JPM KFT 
900 270 

Однако, я не могу показаться, чтобы адепт эту функцию для отображения размер самой длинной проигрышной полосы (чтобы он выводил -329 для JPM и -356 для KFT), насколько глупо это звучит. Я попытался изменить функцию различными способами, раздели ее и перестроить, и я не могу найти причину этого.

Вот что я имею в виду (выход из отладки функции, где x значения являются значениями для JPM после разделения subRes):

Browse[2]> ifelse(x > 0, 1, 0) 
[1] 0 1 1 1 1 0 0 1 0 0 
Browse[2]> ifelse(x < 0, 1, 0) 
[1] 1 0 0 0 0 1 1 0 1 1 
Browse[2]> rle(ifelse(x > 0, 1, 0)) 
Run Length Encoding 
    lengths: int [1:5] 1 4 2 1 2 
    values : num [1:5] 0 1 0 1 0 
Browse[2]> rle(ifelse(x < 0, 1, 0)) 
Run Length Encoding 
    lengths: int [1:5] 1 4 2 1 2 
    values : num [1:5] 1 0 1 0 1 
Browse[2]> inverse.rle(ifelse(x > 0, 1, 0)) 
Error in x$lengths : $ operator is invalid for atomic vectors 
Browse[2]> rle(!ifelse(x < 0, 1, 0)) 
Run Length Encoding 
    lengths: int [1:5] 1 4 2 1 2 
    values : logi [1:5] FALSE TRUE FALSE TRUE FALSE 

Таким образом, изменение условий в этой функции не имеет никакого значения на выходе функции. Это предполагает, что я ищу неправильную часть функции для решения, но оператор ifelse является первым из функции. Другими словами, из строки 1 и далее функция использует неправильный ввод, несмотря на изменение условий.

Какой очевидный момент я пропущу?

+2

Я не достаточно хорошо, чтобы опубликовать ответ, но я предполагаю, что ваша функция WinStreakSize действительно возвращает самую длинную полосу (выигрыш или проигрыш). Самые длинные полосы - это просто победные полосы в вашем примере. – Henrik

+0

@ Хенрик Вы не я. ВАУ! Я немного раздражен. – Henrik

+0

Кстати: если вы посмотрите на то, что делает «rle', то, как я думаю, что я прав ... – Henrik

ответ

5

rle(ifelse(x>0,1,0)) принципиально такой же, как rle(ifelse(x<0,1,0)) или rle(x>0) или rle(x<0), с той разницей, что значения для прогонов различны. Но вы никогда не работаете со значениями прогонов в своей функции, так что это не имеет значения. Когда вы выбираете по длине, а не по значениям, очевидно, что вы получите тот же результат каждый раз снова.

Позвольте мне немного упростить ситуацию. С помощью основной функции я демонстрирую расчет как длины выполнения, так и итогов. Учтите, что ваше решение в вопросе не является точным: для JPM существует два самых длинных отрицательных результата. Я решил вернуть только тот, у которого наибольшая абсолютная величина.

MaxStreakSize <- function(x){ 
    # Get the run lengths and values 
    df.rle <- rle(x>0) 
    ngroups <- length(df.rle$lengths) 
    ll <- df.rle$lengths 
    val <- df.rle$values 

    # calculate the sums 
    id <- rep(1:ngroups,ll) 
    sums <- tapply(x,id,sum) 

    # find the largest runs for positive (val) and negative (!val) 
    rmax <- which(ll==max(ll[val]) & val) 
    rmin <- which(ll==max(ll[!val]) & !val) 

    out <- list(
      "Lose"=c("length"=max(ll[rmin]), 
         "sum"=min(sums[rmin])), 
      "Win"=c("length"=max(ll[rmax]), 
        "sum"=max(sums[rmax])) 
      ) 
    return(out) 
} 

В таком роде проблемы, это очень хорошо, чтобы получить какое-то индекс, основанный на количестве групп и длину трассы. Это делает жизнь намного проще. Это позволяет мне рассчитать суммы, средства и т. Д. С простым tapply.После того как я построил три вектора одинаковой длины (ll, sums и val), я могу легко связать длину, значение и сумму прогонов и выбрать все, что захочу.

Преимущество использования rle (x> 0) заключается в том, что вы можете использовать значения как индекс, что значительно упрощает работу.

+0

Спасибо Джорису за ваш ответ, довольно изящное решение (меньше кода приводит к большему количеству выходных данных). Возвращение прогона с наибольшими значениями идеально! Правильно ли я утверждаю, что переменная 'll' в ваших кодах дает индекс, который в сочетании с' val' дает доступ к значению определенной точки? В таком случае, не должны ли значения 'll' быть уникальными, чтобы R различать их? (Сейчас они равны 1,4,2,1,2 для JPM). (Btw, это не критика, решение идеально. Я просто пытаюсь получить дальнейшее представление о мышлении, которое вы использовали для решения этой проблемы. :)) – Jura25

+0

@ Jura25 Ответ Jori's охватывает то, что я собираюсь сказать - по сути, вы взяли один из других ответов в предыдущем Q, где мой ответ был обновлен после того, как я заметил, что если потерявшая полоса будет длиннее, чем победная серия, она выберет это. Я обновил свой ответ там, чтобы показать, как получить выигрыш и потерю полос, а ответ @Joris прекрасно сочетает все эти идеи (+1) –

+1

@ Jura25 ll - это длины прогонов, val - значения для этих прогонов (TRUE или FALSE), а id - индекс, который будет использоваться для исходного вектора x. ngroups - число или пробег. Если вы добавите браузер() в первую строку в функцию, вы можете проверить, как они выглядят внутри. См. Также '? Browser' –

Смежные вопросы