-2

I am trying to run four nested loops like below. I am attempting to find the best combination of MA1, MA2, SL, and LS. To maintain simplicity I showed you an example of what I am running the the comment in the middle. As you can see below MA1 is 1-364, MA2 is 2-365, SL and LS are .001 - .05. I set it up so MA2 always starts one more than MA1 as checking 1 and 2 is the same as checking 2 and 1 (In this case).

main <- function(...) {
  MA1 <- 1
repeat{
    MA1 <- MA1 + 1
    if(MA1>364){
      break
    }
    MA2 <- MA1
    repeat{
      MA2 <- MA2 + 1
      SL <- 0
      if(MA2>365){
        break
      }
      repeat{
        SL <- SL + .001
        if(SL>.05){
          break
        }
        LS <- 0
        repeat{
          LS <- LS + .001
          Day <- MA2 + 1
          if(LS>.05){
            break
          }
          n <- n + 1
          #Finding the Profit/Loss of the combination
          #PnL <- FindPnL(MA1, MA2, SL, LS)
        }
      }

    }
  }
  return(n)
}

The n <- N+1 is just for running sake

Is there a different way I can create this looping sequence? Right now, using system.time() user system elapsed 156.972 0.693 158.555 With my goal making that number as small as possible.

LBD
  • 53
  • 4
  • 1
    You are around 146 what? – ASCIIThenANSI Apr 21 '15 at 20:41
  • 1
    Set up all combinations first, use `expand.grid` to get all combinations of `MA1`, `MA2`, `SL` and `LS` that you want to iterate over, then maybe you can even vectorize your function. – Gregor Thomas Apr 21 '15 at 20:44
  • Loops are often slow in R. I think the real question is _why_ are you doing it this way? There is likely a simpler solution. – Alex A. Apr 21 '15 at 20:44
  • 3
    Describe the goal of your code in words. Even better, provide a [reproducible example](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) with sample input data so we can run and compare different implementations. – MrFlick Apr 21 '15 at 20:46
  • @MrFlick I updated my question to do my best to give more information. I am not entirely sure how to give a reproducible example as the function that I am running is long and using more than one function within it. – LBD Apr 21 '15 at 21:10
  • 1
    You should time with `microbenchmark` how long a single iteration of `FindPnL` takes. Then multiply that number by the number of permutations you are trying (looks like 150MM to me). If that number is too large for your intents and purposes then it doesn't matter how you loop through your function. You either need to make your function faster, or the space you are sampling smaller. – BrodieG Apr 21 '15 at 22:26

1 Answers1

1

A slightly more R-like way to do things would be to set up a matrix of inputs and then go over them. I've done that here for you. I reduced the granularity of LS and SL by half to make the end size a bit more reasonable, but the resulting grid2 object still has 41,518,750 combinations of parameters... do you really need all of them??

MA1 = 1:364
MA2 = 2:365
SL = seq(0, 0.05, by = 0.002)[-1]
LS = seq(0, 0.05, by = 0.002)[-1]

grid1 = expand.grid(MA1, MA2)
names(grid1) = c("MA1", "MA2")
grid1 = grid1[grid1$MA1 < grid1$MA2, ]
grid2 = expand.grid(1:nrow(grid1), SL, LS)
names(grid2) = c("g1row", "SL", "LS")
grid2 = cbind(grid2, grid1$MA1[grid2$g1row], grid1$MA2[grid2$g1row])
names(grid2)[4:5] = c("MA1", "MA2")
grid2$g1row = NULL

With this setup, your nested loop can be replaced with a single loop over the rows of grid2, or you could rewrite it using apply or mapply. Pre-allocate a vector or list for results, and fill it in if you use a for loop.

Another advantage of this method is it's very clear the range of variables you use. This can help reduce bugs. In your code, for example, you have a mismatch between your description and your code: you say MA1 goes from 1 to 364, but in your code you initialize it to 1, then immediately add 1 so it starts at 2 by the time you get to your first n <- n + 1 step.

It might not be much or any faster than what you have above, your chance to use R in a truly R-like way is to vectorize your function, whatever you're doing in n <- n + 1---but you seem reluctant to provide even vague details.

If you're optimizing something, looking for a min or a max, then you'd be much better off using optimization functions instead, see, e.g., optim or the optimx package.

Gregor Thomas
  • 136,190
  • 20
  • 167
  • 294