ARMA Models for Trading, Part II

[This article was first published on The Average Investor's Blog » R, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

We left the last post at the point of determining the best ARMA model. Before continuing the discussion, however, I would like to make a few points that might seem a bit questionable or unclear:

  • We model the daily returns instead of the prices. There are multiples reasons: this way financial series usually become stationary, we need some way to “normalize” a series, etc
  • We use the diff and log function to compute the daily returns instead of percentages. Not only this is a standard practice in statistics, but it also provides a damn good approximation

Now back to choosing the best fitting ARMA model. A well known statistic to measure the goodness of fit test is AIC (for Akaike Information Criteria). Once the fitting is done, the value of the aic statistics is accessible via:

xxArma = armaFit( xx ~ arma( 5, 1 ), data=xx )
xxArma@fit$aic

There are other statistics of course, which for instance penalize models with mode parameters to avoid over-parametrization, however, typically the results are quite similar.

To summarize, all we need is a loop to go through all parameter combinations we deem reasonable, for instance from 0 to 5, inclusive, both for the AR (the first component) and the MA (the second component), for each parameter pair fit the model, and finally pick the model with the lowest AIC or some other statistic. The full code for findBestArma is at the end of the post.

In the code below, note that sometimes armaFit fails to find a fit and returns an error, thus quitting the loop immediately. findBestArma handles this problem by using the tryCatch function to catch any error or warning and return a logical value (FALSE) instead of interrupting everything and exiting with an error. Thus we can distinguish an erroneous and normal function return just by checking the type of the result. A bit messy probably, but it works.

findBestArma = function( xx, minOrder=c(0,0), maxOrder=c(5,5), trace=FALSE )
{
   bestAic = 1e9
   len = NROW( xx )
   for( p in minOrder[1]:maxOrder[1] ) for( q in minOrder[2]:maxOrder[2] )
   {
      if( p == 0 && q == 0 )
      {
         next
      }   

      formula = as.formula( paste( sep="", "xx ~ arma(", p, ",", q, ")" ) ) 

      fit = tryCatch( armaFit( formula, data=xx ),
                      error=function( err ) FALSE,
                      warning=function( warn ) FALSE )
      if( !is.logical( fit ) )
      {
         fitAic = fit@fit$aic
         if( fitAic < bestAic )
         {
            bestAic = fitAic
            bestFit = fit
            bestModel = c( p, q )
         }   

         if( trace )
         {
            ss = paste( sep="", "(", p, ",", q, "): AIC = ", fitAic )
            print( ss )
         }
      }
      else
      {
         if( trace )
         {
            ss = paste( sep="", "(", p, ",", q, "): None" )
            print( ss )
         }
      }
   }   

   if( bestAic < 1e9 )
   {
      return( list( aic=bestAic, fit=bestFit, model=bestModel ) )
   }   

   return( FALSE )
}

To leave a comment for the author, please follow the link and comment on their blog: The Average Investor's Blog » R.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)