Pergunta

I have another R beginner question...

How can I vectorize (avoid for loop in) following code:

# algorithm for getting entry prices (when signal > 0): look back from current
# position until you find first signal > 0,
# `mktdataclose` at that time is entry price
# `entryPrices` is an xts object representing entry prices
# if entryPrices are not available (is.null == TRUE) then wee need to reconstruct
# them from signal (xts object with 1 when entry signal triggered and 0 
# otherwise) and close prices available in mktdataclose (an xts object with the
# same length as signal and same dates just that it represents closing prices)

EntryPrices <- entryPrices
if (is.null(EntryPrices)) {
    # get entryprices as close prices on buy signal
    EntryPrices <- ifelse(signal > 0, mktdataclose, 0)
    entryPrice <- 0
    for (i in 1:NROW(signal)) {
        if (signal[i] > 0) entryPrice <- mktdataclose[i]
        EntryPrices[i] <- entryPrice
    }
}

I am stuck at thinking SAS data step way and desperatley looking for retain etc. Where can I find some simple exaples in order to understand sapply etc (r help via ?sapply is unfortunately to complicated for me... :( )

Thank you for your kind help.

Best, Samo.

Foi útil?

Solução

If I understood correctly, your problem is: you have two vectors signal and mktdataclose of length n, and you want to create a new vector EntryPrices of length n such that mktdataclose[i] is the value of mktdataclose the last time signal was 1 at or before time i. You can do this without a for loop, using cummax, an often unexpectedly useful function (Note that this question is similar in flavor to some of your earlier questions, which were similarly solved using this function and cumsum). Here we go, using Gavin's data:

set.seed(123)
signal <- sample(0:1, 10, replace = TRUE)
mktdataclose <- runif(10, 1, 10)  

Our problem is really to convert the signal vector into a vector of the appropriate indices:

indices <- cummax( seq_along(signal) * signal)

This is exactly the indices we want, except for the 0. Now we set EntryPrices by extracting the values at the non-zero indices from mktdataclose:

EntryPrices <- c( rep(0, sum(indices==0)), mktdataclose[ indices ])

>   cbind(signal, indices, mktdataclose, EntryPrices)
      signal indices mktdataclose EntryPrices
 [1,]      0       0     9.611500    0.000000
 [2,]      1       2     5.080007    5.080007
 [3,]      0       2     7.098136    5.080007
 [4,]      1       4     6.153701    6.153701
 [5,]      1       5     1.926322    1.926322
 [6,]      0       5     9.098425    1.926322
 [7,]      1       7     3.214790    3.214790
 [8,]      1       8     1.378536    1.378536
 [9,]      1       9     3.951286    3.951286
[10,]      0       9     9.590533    3.951286

Outras dicas

since signal is 0 and 1 i presume you can vectorize with:

EntryPrices * signal

Here's another solution that you may find more straight-forward. I'm using Prasad's psudo-data.

> EntryPrices <- ifelse(signal > 0, mktdataclose, NA)
> EntryPrices <- na.locf(EntryPrices, na.rm=FALSE)
> cbind(signal,mktdataclose,EntryPrices)
      signal mktdataclose EntryPrices
 [1,]      0     9.611500          NA
 [2,]      1     5.080007    5.080007
 [3,]      0     7.098136    5.080007
 [4,]      1     6.153701    6.153701
 [5,]      1     1.926322    1.926322
 [6,]      0     9.098425    1.926322
 [7,]      1     3.214790    3.214790
 [8,]      1     1.378536    1.378536
 [9,]      1     3.951286    3.951286
[10,]      0     9.590533    3.951286
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top