Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
An implementation of the Robust Asset Allocation Strategy from Alpha Architects

The attached backtest illustrates an implementation of the RAA strategy from AlphaArchitects (described in this post). The strategy requires an implementation of both a Value and Momentum strategy. To ease the implementation I created a framework for incorporating multiple strategies ( I adapted some of the ideas from these posts, modular framework for trading algorithms, and abstracting an algorithm from one stock to many)

I thought it may be useful to the community so I’ve posted it here.

A couple of notes on the implementation,

  • all strategies are required to implement a robust asset allocation function
  • as a simplification the framework assumes all existing assets in a strategy are sold before new assets are ranked and then bought
  • the implementation ensures that strategies that do fundamental queries are executed on distinct days so that a maximum number of securities relevant to the particular strategy are examined (i.e. the 500 securities in 'data' are selected by the specific strategy and there is no overlap with other strategies)
  • Since stocks in the Q universe are generally restricted to those that trade on a US exchange, no distinct allocation is made to domestic and international equities, rather fundamental queries are allowed to invest in ADRs, and in securities not necessarily domiciled in the US
  • a Gold etf (GSG) is used to approximate an allocation to commodities. This is done to allow for a longer backtest.
  • the Value strategy implemented is the Magic formula
  • the momentum strategy is Time Series Momentum with a 12 month lookback
  • the strategy simply goes to cash when out of the market instead of investing in treasuries. An improvement to the framework would be to add a Portfolio Manager class to manage all trades from all strategies and put any cash in an appropriate alternative

Regards,
Mark

18 responses

I tried to run this framework in minute mode of backtest. I have a running error as below. Does anyone success to get it done?

AttributeError: 'Mom_Strat' object has no attribute 'candidates'
USER ALGORITHM:260, in exec_rankGo to IDE
h = history( self.lookback,'1d','price')[self.candidates]

Hi Adam,

thanks for pointing this out. The framework assumes that before_trading_start executes before handle_data, that is not the case when running in minute mode. The reason before_trading_start needs to execute before handle_data is to ensure candidates are available before they are ranked. To ensure that is the case in minute mode I added a check to ensure that get_candidates is executed,

def before_trading_start(self,context,data):

    if self.buy_day:  
        self.get_candidates()  
        if len(self.candidates) > 0:  
            **self.candidates_available = True** -code added  
            update_universe(self.candidates)  


def handle_data(self,context,data):  
    if self.sell_day:  
        self.exec_sell(context,data)  
        self.sell_day = False  

    if self.buy_day and **self.candidates_available:** -code added  
        self.exec_rank(context, data)  
        self.exec_buy(context,data)  
        self.buy_day = False  
        **self.candidates_available = False** --code added

This addresses the problem you ran into. However it leads to another problem which is that the algorithm fails because of a MemoryError. I get the following message,

There was a runtime error.
MemoryError
Algorithm used too much memory. Need to optimize your code for better performance. Learn More

This happens the first time the algorithm tries to calculate the moving average for the index,

def robust(self,context,data):
r = 0.0

    ex_return = self.get_excess_return(context,data)  
    if ex_return > 0.0:  
        r += 0.5  
    if data[self.index].price > **data[self.index].mavg(self.ma_threshold)**:  -see here  
        r += 0.5  

    return r

Since it is happening the very first time this code is executed I'm not sure why its running out of memory, when it is not in daily mode. So, I'm stuck on how to address the issue. Perhaps someone from Quantopian can comment?

Alisa said use .mean() instead of .mavg, here and indeed it is far faster.

I implemented the .mean() to def robust(self,context,data) function as suggested.

# if data[self.etf].price > data[self.etf].mavg(self.ma_threshold):  
    if data[self.etf].price > history(self.ma_threshold, '1d', 'price')[self.etf].mean():  

It helps execution speed a lot. Unfortunately, I still can not get rid of memory error problem. Any suggestion please?

MemoryError
Algorithm used too much memory. Need to optimize your code for better performance.

Hi Adam,

I think the code you want to change is in the Equity_Strat class,

if data[self.index].price > data[self.index].mavg(self.ma_threshold):

    if data[self.index].price > history(self.ma_threshold, '1d', 'price')[self.index].mean():

I've made that change and the strat is currently running without hitting the memory error yet.

Hi Mark,

My algorithm seems not work in minutes mode still. Do you mind sharing the minute mode of backtest result to the community?

Thanks,
Adam

This backtest works for 2015, essentially you need to replace any calls to mavg with a call to numpy.mean, as noted above.

For some reason in minute mode certain trades in the value strategy result in a key error, not sure why, since they work in monthly mode. Will have to look into that at some point.

Regards,
Mark

Hi all,

I refactored the code to work in minute mode, see attached backtest.

@Mark: Is the idea to check for a 'buy day' one day, and then trade the next if the condition is met? or should you instead be trading on the day when the check is made? Just curious!

Disclaimer

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by Quantopian. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. No information contained herein should be regarded as a suggestion to engage in or refrain from any investment-related course of action as none of Quantopian nor any of its affiliates is undertaking to provide investment advice, act as an adviser to any plan or entity subject to the Employee Retirement Income Security Act of 1974, as amended, individual retirement account or individual retirement annuity, or give advice in a fiduciary capacity with respect to the materials presented herein. If you are an individual retirement or other investor, contact your financial advisor or other fiduciary unrelated to Quantopian about whether any given investment idea, strategy, product or service described herein may be appropriate for your circumstances. All investments involve risk, including loss of principal. Quantopian makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances.

Mark,

In line 459 you declared 'SHY' as risk-free asset.
It will be good to use it instead of cash.

@Jamie:

Hi Jamie, are you referring to the fact that the exec_buy/exec_sell functions are scheduled one day after the update_universe_buy/ update_universe_sell functions? If so this is because the universe has to be updated before trading starts, so what happens is the update universe function executes which causes the universe to be updated before start of trading the next day, then the buy/sell orders are executed. So candidates are actually analyzed on the same day they are bought.

Hope that helps,
Mark

Hey there, not able to get this to run in Minute mode. (Mark Segal on 1/12/16)

Hi Corey,

I just cloned the algorithm and ran the attached backtest, seems to run fine.

So much to learn. Im new to Python. Thank you so much.

Mark. Is there any chance you have version Q2 for this. Im spending 2 days trying to get it to work with Q2 but Ii could. This is so good framework for me to work with. But i guess I'm too new to Quantopian as well as Python. So if you have time to port i would really appreciated it.
Thanks

  • could not i meant

Can anyone fix this?

There was a runtime error.
AttributeError: 'Mom_Strat' object has no attribute 'candidates'
... USER ALGORITHM:260, in exec_rank
h = history( self.lookback,'1d','price')[self.candidates]

now fundamental is no longer supported, need to use pipeline. how to refactor? Thanks :)