Milktrader

Iterating Until Convergence

Saturday, April 9, 2011

A Super-Easy, Simple-Dimple Backtester in R

I cut my finger on a paring knife this morning. Don't use a sharp knife to spread butter on your toast. It's better to limit yourself to using dull kitchen utensils until the caffeine kicks in. No matter, I still have most of my digits to type in a simple backtesting program in R. Good thing it's only about 15 lines of code.


require(quantmod)

getSymbols("GLD")

for(i in seq(5, 15, 5))
  for(j in seq(50, 80, 15))

{
    GLD$fast     <- SMA(Cl(GLD), n=i)     
    GLD$slow     <- SMA(Cl(GLD), n=j)         

    golden_cross <- Lag(ifelse(GLD$fast > GLD$slow, 1, -1))
    golden_cross <- na.locf(golden_cross, na.rm=TRUE)
        
    coin         <- ROC(Cl(GLD))*golden_cross
    best_coin    <- max(coin)
    worst_coin   <- min(coin)
    last_coin    <- cumprod(1+coin)[NROW(coin),]  
    
    annual_coin   <- round((last_coin-1)*100, digits=2)/(NROW(coin)/252)

    cat(i,j,annual_coin, best_coin, worst_coin, "\n", file="~/goldcat", append=TRUE)  
    cat(i,j,annual_coin, best_coin, worst_coin, "\n")  
}

10 comments:

  1. I think you missed a few lines there.....

    ReplyDelete
    Replies
    1. The majority of the respectable paid computer registry optimizers that exist on the Internet are good and are also not too costly.

      Delete
  2. @Andreas fixed it. Was missing the closing bracket at the very end.

    ReplyDelete
  3. thanks Milky I am enjoying your posts

    ReplyDelete
  4. Hi. Appreciate your blog! I'm very new to R and in fact my mind has been tarnished by years programming in C style static languages so I'm having a little problem getting to grips with the magic of R. A few questions that I came across while looking at this code, would be awesome if you could provide some hints:
    1)ifelse(GLD$fast > GLD$slow, 1, -1)--> This does just a comparison of the SMAs correct? I'd be more interested to find out the actual crossover of the SMA i.e.
    GLD$fast[n-1]GLD$slow[n]

    2)I've seen the documentation to check what lag and na.locf do but they break my code when I remove the NAs with this error
    "Error: dims [product 23989] do not match the length of object [23994]"
    while running coin <- ROC(eurusd$close)*golden_cross

    3) Due to the above I've skipped of the few NAs to the code written below - but I'm not 100% sure if it works :). Also the coin_mean should be a good indicator, correct?

    eurusd$fast <- SMA(eurusd$close, n=i)
    eurusd$slow <- SMA(eurusd$close, n=j)

    cross <- ifelse(eurusd$fast > eurusd$slow, 1, -1)#cross <- Lag(ifelse(eurusd$fast > eurusd$slow, 1, -1))
    #cross <- na.locf(cross, na.rm=TRUE)

    coin <- ROC(eurusd$close)*cross
    #coin <- na.locf(coin, na.rm=TRUE)
    best_coin <- max(na.locf(coin, na.rm=TRUE))#best_coin <- max(coin)
    worst_coin <- min(na.locf(coin, na.rm=TRUE))#worst_coin <- min(coin)
    last_coin <- cumprod(1+coin)[NROW(coin)] # last_coin <- cumprod(1+coin)[NROW(coin),]
    mean_coin <- mean(na.locf(coin, na.rm=TRUE))

    cat(i,j, best_coin, worst_coin, mean_coin, "\n", file=op, append=TRUE)
    cat(i,j, best_coin, worst_coin, mean_coin, "\n")

    ReplyDelete
  5. I've actually gone ahead and implemented a cross over(at least I think I have :) style the way I discussed above:


    for(i in seq(2, 5))
    {
    for(j in seq(6, 15))
    {
    eurusd$fast<-SMA(eurusd$close, n=i)
    eurusd$slow<-SMA(eurusd$close,n=j)

    cross <- NA
    for(n in 2:length(eurusd$close))
    {
    cross[n] <- ifelse(eurusd$fast[n] > eurusd$slow[n] && eurusd$fast[n-1] < eurusd$slow[n-1] , 1, (ifelse(eurusd$fast[n] < eurusd$slow[n] && eurusd$fast[n-1] > eurusd$slow[n-1], -1, 0)))

    }

    I'm guessing there might be a way to improve performance but this is all I could conjure up with the little R experience I have..

    ReplyDelete
  6. I love what you created for helping people do R backtesters. I have created a platform to backtest in various languages including R. I've also included a large list of built in indicators.

    check it out, R backtester documentation

    cheers,
    Joshua
    Quantonomics

    ReplyDelete
    Replies
    1. I wish you wouldn't spam these forums with
      your (yet) non existent website.

      Delete
  7. Error in xts(new.x, x.index) :
    order.by requires an appropriate time-based object

    I get this error when running the code?

    ReplyDelete