Расчет размера выигрышной и проигрышной серии - PullRequest
4 голосов
/ 20 января 2011

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

Вот так выглядят мои данные:

> 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 и далее, функция использует неправильный ввод, несмотря на изменение условий.

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

1 Ответ

5 голосов
/ 20 января 2011

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

Позвольте мне немного упростить вещи. С помощью основной функции я демонстрирую расчет как длин серий, так и итогов. Примите во внимание, что ваше решение в вопросе не является точным: есть 2 самых длинных отрицательных прогона для 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) заключается в том, что вы можете использовать значения в качестве индекса, что значительно упрощает работу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...