Adaptive Asset Allocation(AAA 2015) is a process of constantly rotating into assets with the strongest momentum, and minimizing portfolio risk through diversification. It was written by Adam Butler at ReSolve Asset Management. Selecting from a globally diverse set of ten stock, bond, commodity, and REIT ETFs, at the end of each month calculate the six month cumulative returns, rank and select the top five assets. AAA is weighted according to minimum variance optimization, using a covariance matrix calculated based on 126-day correlation and 20-day volatility.


The ten ETFs used in this replication and have ticker symbols:

(SPY) SPDR S&P 500 Trust

(VGK) Vanguard FTSE Europe Index Fund Shares

(EWJ) iShares MSCI Japan

(EEM) iShares, Inc. - iShares MSCI Emerging Markets

(VNQ) Vanguard Real Estate Index

(RWX) SPDR Dow Jones International Real Estate

(IEF) iShares 7-10 Year Treasury Bond

(TLT) iShares 20+ Year Treasury Bond

(DBC) Invesco DB Commodity Index Tracking Fund

(GLD) SPDR Gold Shares


AAA equity curve, daily return histogram and drawdown curve from Jun 2007


A performance metric displaying Annual Returns, Annual Standard Deviation, Annual Sharpe Ratio Max Drawdown and Calmar Ratio.

##                           AAA Strategy
## Annualized Return            0.0678000
## Annualized Std Dev           0.0939000
## Annualized Sharpe (Rf=0%)    0.7221000
## Max Drawdown                 0.1960292
## Calmar Ratio                 0.3458669


The opensource code is presented below written in R and can be run calling the quantstrat and tseries packages.

require(quantstrat)
require(tseries)

#################################################################################################
########### Replication of Adaptive Asset Allocation AAA by Adam Butler ReSolve Asset Management 

### By: Matthew Kiegerl
  # 
  # In this illustration, I will attempt to replicate the 
  # Adaptive Asset Allocation strategy from ReSolve Asset Management
  #
  # Step 1: Select from 5 Globally Diversified Asset Classes 
  # from the list of 10 based on 6 month momentum
  #
  # Step 2: weight portfolio mean-var optimization every month 
  # using 6m correlations and 1 month volatilities
  # 

#################################################################################################



  # 10 major Global Asset Classes represented by ETF tickers 
  tickers <- c("SPY", # SPDR S&P 500 ETF Trust
               "VGK", # Vanguard FTSE Europe Index Fund ETF Shares
               "EWJ", # iShares MSCI Japan ETF
               "EEM", # iShares, Inc. - iShares MSCI Emerging Markets ETF
               "VNQ", # Vanguard  Real Estate Index ETF
               "RWX", # SPDR Dow Jones International Real Estate ETF 
               "IEF", # iShares 7-10 Year Treasury Bond ETF
               "TLT", # iShares 20+ Year Treasury Bond ETF 
               "DBC", # Invesco DB Commodity Index Tracking Fund
               "GLD"  # SPDR Gold Shares
  ) 
  
  
  # Store Log returns data caluclated from adjusted prices to a list
  returns <- list()
  
  for(i in 1:length(tickers)) {
    rets <- Return.calculate(Ad(get(getSymbols(tickers[i],
                                                  from = '2000-01-01', 
                                                  method = "log"))))
    colnames(rets) <- tickers[i]
    returns[[i]] <- rets
  }
  
  # cbind rets
  returns <- na.omit(do.call(cbind, returns))
  
  
  # The Adaptive Asset Allocation algorithm- ReSolve Asset Management ala KiegerlQuant
 
    # create monthly endpoints, apply crash prevention
    endMonth <- endpoints(returns)
    endMonth[endMonth < 1] <- 1
    endMonth[endMonth > nrow(returns)] <- nrow(returns)
    endMonth <- unique(endMonth)
    emDiff <- diff(endMonth)
    if(last(emDiff)==1) { # if the last period only has one observation, remove it
      endMonth <- endMonth[-length(endMonth)] 
    }
    
    # initialize vector holding zeroes for assets placement
    emptyVector <- data.frame(t(rep(0, length(tickers))))
    colnames(emptyVector) <- tickers[1:(length(tickers))]
    
    
    # Create List to store weights
    allWeights <- list()
    
      # Start loop for 6m filter
      for(i in 1:(length(endMonth)-6)) {
        
        # subset for 6m of returns- store subsetted returns data for 6 and 1 month
        retSubset <- returns[c((endMonth[i]+1):endMonth[(i+6)]),]
        emSub <- endMonth[i:(i+6)]
        sixMonths <- returns[(emSub[1]+1):emSub[7],]
        oneMonth <- returns[(emSub[6]+1):emSub[7],]
      
        # compute 6 month cumulativer returns as momentum factor
        momentums <- Return.cumulative(sixMonths)
        
        # find top five assets
        highRankAssets <- rank(momentums) >= (length(tickers) - 4) 
        
        # index the assets in top five by rank
        indx <- which(highRankAssets)
        
        # 6m correlation to match with momentum filter, 1m volatilities, calc Covariance Matrix
        correlations <- cor(sixMonths[,indx])
        
        # use last month of data for volatility computation 
        volatilities <- StdDev(oneMonth[,indx]) 
        covariances <- t(volatilities) %*% volatilities * correlations
        
        # compute standard min vol optimization
        minVolRets <- t(matrix(rep(1, sum(highRankAssets))))
        minVolWts <- portfolio.optim(x=minVolRets, covmat = covariances)$pw
        names(minVolWts) <- colnames(covariances)
        investedAssets <- emptyVector
        investedAssets[,highRankAssets] <- minVolWts
        
        # append to list of monthly allocations
        weights <- xts(investedAssets, order.by=last(index(retSubset)))
        allWeights[[i]] <- weights
        
      }
  
    # put all weights  and returns together 
    allWeights <- do.call(rbind, allWeights)
    investedRets <- returns[,1:(length(tickers))]
  
    # compute AAA portfolio returns
    AAA <- Return.portfolio(R = investedRets, weights = allWeights)
    colnames(AAA) <- "AAA Strategy"

Thanky!