Back to Community
Multi-strategy example

A first attempt to implement a multi-strategy multi-instrument backtest.
I am not a coder and I am just starting out with python here. Feel free to correct or improve.

The idea is to built a "template" that can "weight" different strategies without coding the internals of the strategies.
For example, assuming we have a Trend Following and a Mean Reverting strategy on can allocate 30-70 when VIX rises above a threshold and 70-30 when VIX comes back down.

Unfortunately I don't know how to code daily indicators to work with minute bars, so:
The existing strategies work best for EOD trading (if you clone and run the daily backtest you will see what I mean).
Keep in mind that this is implemented knowing full well what has worked in the past (in other words this is "manually" optimized), so past performance is no indication of future performance.

http://sanzprophet.blogspot.com/

Clone Algorithm
155
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
from datetime import datetime, timedelta
 
# Strategy class to keep track of basic strategy parameters
class Strategy:
            def __init__(self, id, name, allocation, instruments):
                self.id = id
                self.name = name
                #How much to allocate in this strategy in current Equity Percentage (i.e., 50.0 %)
                self.allocation = allocation
                # the instruments this strategy will trade [instrA,instrB,etc]
                self.instruments = instruments
                #Number of instruments
                self.numInstr=len(self.instruments)
                
                #Keep track if we are invested or Flat
                self.invested = {}
                #Keep track of the last shares bought from this strategy so we can exit only those shares
                self.lastorder = {}
                #init these dicts
                for cur_sid in self.instruments:
                        self.invested[cur_sid] = False
                        self.lastorder[cur_sid] = 0

 # Sub-Strategy class to implement specific rules     
class StrategyTAA(Strategy):
    #TAA stands for Tactical Allocation Strategy (aka. Faber's Ivy Portfolio)
    #On the first day of the month we look at each stock. If it is above it's 200day Moving average
    #we buy. If it's below we sell it. We allocate equally to each stock
           
            def Trade(self,data,context):
                   #Go through each Instrument
                for cur_sid in self.instruments:  
                    #If there's no data go up the loop to the next instrument
                    if not data.available(cur_sid):
                       continue
                    
                    
                    SMA = data[cur_sid].mavg(200)
                    month = data[cur_sid].datetime.month
                    Yestmonth=(data[cur_sid].datetime -timedelta(days=1)).month
                    price = data[cur_sid].price
                    #equity is cash + open positions
                    equity= data.portfolio.cash+data.portfolio.positions_value
                    #This stock should use equity allocated for this strategy / number of instruments in this strategy
                    shares=round(  (self.allocation/100) * (equity/self.numInstr)/ price )
                     
                     #Sell if  we are invested in this stock (from this strategy) and Close<sma200 and today is a new month 
                    if price <SMA and Yestmonth!=month and self.invested[cur_sid] and self.lastorder[cur_sid]>0:
                        order(cur_sid,-self.lastorder[cur_sid])
                        #Update we are not invested
                        self.invested[cur_sid]  = False
                        log.info('TAA:Sold SID %i by %i shares' %(cur_sid, -self.lastorder[cur_sid]))
                        #Update last order to 0 since position sold already
                        self.lastorder[cur_sid]  = 0    
                        
                    #Buy if  we are not invested in this stock (from this strategy) and Close>sma200 and today is a new month 
                    elif price > SMA and Yestmonth!=month and not self.invested[cur_sid]:
                        order(cur_sid,+shares)
                        #Set invested to true
                        self.invested[cur_sid]  = True
                        #Keep track of the shares so we can exit the same shares later
                        self.lastorder[cur_sid]  = shares 
                        log.info('TAA:Long SID %i by %i shares' %(cur_sid, shares))
        
    
class StrategyMeanRev(Strategy):    
        #This is a Mean Reverting strategy. Creates two bands above and bleow the price. If the price crosses the 
        #lower band the strategy buys. It sells when it hits the upper band
        #A basic bull/bear switch is used  (Close>SMA200). The bands are adjusted accordingly
    
            def Trade(self,data, context):  
                for cur_sid in self.instruments: 
                    if not data.available(cur_sid):
                         continue
     
                    price = data[cur_sid].price
                    stdev=data[cur_sid].stddev(10)
                    sma= data[cur_sid].mavg(5)
                    sma200=data[cur_sid].mavg(200)
                    
                    if (price>sma200):
                        upper = sma+2.0*stdev
                        lower = sma-0.8*stdev
                    else:
                        upper = sma+1.0*stdev
                        lower = sma-2.0*stdev                

                    equity= data.portfolio.cash + data.portfolio.positions_value
                    shares=round(  (self.allocation/100) * (equity/self.numInstr)/ price )
     
 
                    if price>upper and self.invested[cur_sid]  and self.lastorder[cur_sid]>0:
                        order(cur_sid,-self.lastorder[cur_sid])
                        self.invested[cur_sid]  = False
                        log.info('MR: Sold SID %i by %i shares' %(cur_sid, self.lastorder[cur_sid] ))
                        self.lastorder[cur_sid] = 0
        
                    if price<lower  and not self.invested[cur_sid]:
                        order(cur_sid,+shares)
                        self.invested[cur_sid]  = True
                        self.lastorder[cur_sid] = shares
                        log.info('MR: Long SID %i by %i shares' %(cur_sid, shares))
        
       
 
def initialize(context):
 
    context.previousday= 0
    #StrategyType(id,name,allocation,Instruments)
    context.strategies = [ 
                           StrategyTAA(1,'TAA200', 100.0 ,[sid(8554), sid(23921) ] ) ,
                           StrategyMeanRev(2,'Bands',100.0,[ sid(8554), sid(23921) ] ) 
                         ]
   
           
            
def handle_data(data, context):
    
    thisday = data[sid(3766)].datetime.day
 
    #only trade on new day
    if(thisday!=context.previousday):  
        #Implement each strategy
        for strat in context.strategies:
            strat.Trade(data,context)
            
    context.previousday = thisday      

   
      

            
       
       
        
This backtest was created using an older version of the backtester. Please re-run this backtest to see results using the latest backtester. Learn more about the recent changes.
There was a runtime error.
19 responses

@Sanz, awesome share!

In this example you're running two strategies in parallel - have you considered combinations where one strategy is a signal or factor that is input into the other? For example, instead of the TAA triggering a trade, maybe it just gates the execution of the MeanRev strategy.

Your code is quite readable, and I like that you added classes for the strategies. Some free (and worth every penny) few python tips for you:

  • Python uses camel case for classes, but lowercase with underscores for everything else. Single word functions are all lower.
  • method signatures separate parameters with comma-space
  • classes and methods are typically documented with docstrings -- triple quoted strings. Code level comments use the hashes.

For example, the beginning of your TAA description would be like this:

class StrategyTAA(Strategy):  
    """TAA stands for Tactical Allocation Strategy (aka. Faber's Ivy Portfolio)  
    On the first day of the month we look at each stock. If it is above it's 200day Moving average  
    we buy. If it's below we sell it. We allocate equally to each stock"""  
    def trade(self, data, context):  
        # do trade here...  
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.

Thanks John.

Nice site, by the way.
Yes, one strategy could trigger the other. There's many ways to use multi-strategy trading.
a. instead of finding uncorrelated assets to trade in a portfolio, create uncorrelated strategies and trade those.
b. Judge conditions and based on these deploy the appropriate of many strategies available as well as control their parameters.
c. Run all the strategies parallel "silently" (as if they traded) and trade the best ones (adaptive)
d. Once you have a strategy with a set of parameters, deploy multiple copies of it with different parameters to increase robustness (not performance) of the base strategy.

What I actually wanted to do was for these End of Day strategies (because that's what they are) to trigger Intra-day strategies that split up the orders and buy on certain rules (wnap rules or liquidity rules, etc) throughout the "buy" day.
I assume we cannot implement daily (or other custom) bars, just yet.

Hi Sanz,

While we have both day and minute bars, we don't have a way for you to stream both through your algorithm. However, you can approximate this by aggregating daily bars in your script when you run a minute bar backtest. Below, I put together a quick example of accumulating the bars in the script. Maybe you can try using it in your multi-strat simulations.

# defaultdict is a dictionary that can have a default value for a missing key  
# so you needn't hassle with initializing for every key (sid in our case)  
from collections import defaultdict

# a simple data object to accumulate the bar data.  
class Bar(object):  
    def __init__(self):  
        self.volume = 0  
        self.price = None  
        self.datetime = None

def initialize(context):  
    context.sids = [sid(3766)]  
    context.day_bars = defaultdict(Bar)  
    context.previousday = None  
def handle_data(data, context):  
    for cur_sid in context.sids:  
        event = data[cur_sid]  
        bar = context.day_bars[cur_sid]  
        # filter out events that are old (if a stock doesn't trade in a bar  
        # the prior bar is repeated. datetime field is the telltale)  
        if bar.datetime is not None and bar.datetime >= event.datetime:  
            continue

        bar.volume += event.volume  
        bar.price = event.price  
        bar.datetime = event.datetime  
    thisday = data[sid(3766)].datetime.day  
    #only trade on new day  
    if context.previousday is not None and thisday != context.previousday:  
        # implement calls to strategies with the bars in context.day_bars  
        pass  
    context.previousday = thisday  

Ok. I read up on Python and it seems that deque might be useful to keep track of a rolling historical window of daily or hourly prices.
Turns out Jonathan Kamens has already gone that route:
https://www.quantopian.com/posts/python-classes-implementing-true-range-and-average-true-range-indicators
I will try to see if I can implement a n-day Average and n-day standard dev from his example.

This might be a stupid question, but in the graph above, how is it that the benchmark went up in 2008 when the market crashed?

Eric - Your question wasn't stupid at all. It alerted us to a bug in our backtester, and we spent most of the day scrambling to correct it. Thank you very much for noticing and pointing it out to us. You can read more about the bug here.

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.

Hi,
I think it is very intersting and useful to be able to backtest multiple strategy switching.
I have a feature request : being able to define sub portfolio of the global portfolio object so that strategies can trade in their own portfolio and be able t access their own pnl . Obviously still be able to access whole portfolio .
Dan, what do you think ? Is that on the roadmap ?

Thanks

Hello Quentin,

That's an interesting idea. For the moment, I'd recommend doing that kind of portfolio management inside your code. We have some rudimentary portfolio limits today - like the amount of capital you start with. Everything beyond that, like your margin requirements, your position limits, etc. are done within the code you write. For now, it's probably best to extend your code to segment your portfolio.

We definitely have a lot of work to do to make that portfolio management easier in the future.

Dan

It's an old strategy and I thought I make it compatible with the current version of the backtester and 3 years later.. it still perform reasonably... any more improvements?

PB

Clone Algorithm
125
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
from datetime import datetime, timedelta
 
# Strategy class to keep track of basic strategy parameters
class Strategy:
            def __init__(self, id, name, allocation, instruments):
                self.id = id
                self.name = name
                #How much to allocate in this strategy in current Equity Percentage (i.e., 50.0 %)
                self.allocation = allocation
                # the instruments this strategy will trade [instrA,instrB,etc]
                self.instruments = instruments
                #Number of instruments
                self.numInstr=len(self.instruments)
                
                #Keep track if we are invested or Flat
                self.invested = {}
                #Keep track of the last shares bought from this strategy so we can exit only those shares
                self.lastorder = {}
                #init these dicts
                for cur_sid in self.instruments:
                        self.invested[cur_sid] = False
                        self.lastorder[cur_sid] = 0

 # Sub-Strategy class to implement specific rules     
class StrategyTAA(Strategy):
    #TAA stands for Tactical Allocation Strategy (aka. Faber's Ivy Portfolio)
    #On the first day of the month we look at each stock. If it is above it's 200day Moving average
    #we buy. If it's below we sell it. We allocate equally to each stock
           
            def Trade(self,data,context):
                   #Go through each Instrument
                for cur_sid in self.instruments:  
                    #If there's no data go up the loop to the next instrument
                    if not cur_sid in data:
                       continue
                    
                    
                    SMA = data[cur_sid].mavg(200)
                    month = data[cur_sid].datetime.month
                    Yestmonth=(data[cur_sid].datetime -timedelta(days=1)).month
                    price = data[cur_sid].price
                    #equity is cash + open positions
                    equity= context.portfolio.cash+context.portfolio.positions_value
                    #This stock should use equity allocated for this strategy / number of instruments in this strategy
                    shares=round(  (self.allocation/100) * (equity/self.numInstr)/ price )
                     
                     #Sell if  we are invested in this stock (from this strategy) and Close<sma200 and today is a new month 
                    if price <SMA and Yestmonth!=month and self.invested[cur_sid] and self.lastorder[cur_sid]>0:
                        order(cur_sid,-self.lastorder[cur_sid])
                        #Update we are not invested
                        self.invested[cur_sid]  = False
                        log.info('TAA:Sold SID %i by %i shares' %(cur_sid, -self.lastorder[cur_sid]))
                        #Update last order to 0 since position sold already
                        self.lastorder[cur_sid]  = 0    
                        
                    #Buy if  we are not invested in this stock (from this strategy) and Close>sma200 and today is a new month 
                    elif price > SMA and Yestmonth!=month and not self.invested[cur_sid]:
                        order(cur_sid,+shares)
                        #Set invested to true
                        self.invested[cur_sid]  = True
                        #Keep track of the shares so we can exit the same shares later
                        self.lastorder[cur_sid]  = shares 
                        log.info('TAA:Long SID %i by %i shares' %(cur_sid, shares))
        
    
class StrategyMeanRev(Strategy):    
        #This is a Mean Reverting strategy. Creates two bands above and bleow the price. If the price crosses the 
        #lower band the strategy buys. It sells when it hits the upper band
        #A basic bull/bear switch is used  (Close>SMA200). The bands are adjusted accordingly
    
            def Trade(self,data, context):  
                for cur_sid in self.instruments: 
                    if not cur_sid in data:
                         continue
     
                    price = data[cur_sid].price
                    stdev=data[cur_sid].stddev(10)
                    sma= data[cur_sid].mavg(5)
                    sma200=data[cur_sid].mavg(200)
                    
                    if (price>sma200):
                        upper = sma+2.0*stdev
                        lower = sma-0.8*stdev
                    else:
                        upper = sma+1.0*stdev
                        lower = sma-2.0*stdev                

                    equity= context.portfolio.cash + context.portfolio.positions_value
                    shares=round(  (self.allocation/100) * (equity/self.numInstr)/ price )
     
 
                    if price>upper and self.invested[cur_sid]  and self.lastorder[cur_sid]>0:
                        order(cur_sid,-self.lastorder[cur_sid])
                        self.invested[cur_sid]  = False
                        log.info('MR: Sold SID %i by %i shares' %(cur_sid, self.lastorder[cur_sid] ))
                        self.lastorder[cur_sid] = 0
        
                    if price<lower  and not self.invested[cur_sid]:
                        order(cur_sid,+shares)
                        self.invested[cur_sid]  = True
                        self.lastorder[cur_sid] = shares
                        log.info('MR: Long SID %i by %i shares' %(cur_sid, shares))
        
       
 
def initialize(context):
 
    context.previousday= 0
    #StrategyType(id,name,allocation,Instruments)
    context.strategies = [ 
                           StrategyTAA(1,'TAA200', 100.0 ,[sid(8554), sid(23921) ] ) ,
                           StrategyMeanRev(2,'Bands',100.0,[ sid(8554), sid(23921) ] ) 
                         ]
   
           
            
def handle_data(context, data):
    
    thisday = data[sid(3766)].datetime.day
 
    #only trade on new day
    if(thisday!=context.previousday):  
        #Implement each strategy
        for strat in context.strategies:
            strat.Trade(data,context)
            
    context.previousday = thisday      

   
      

            
       
       
        
There was a runtime error.

apologies, this the out of sample one

Clone Algorithm
125
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
from datetime import datetime, timedelta
 
# Strategy class to keep track of basic strategy parameters
class Strategy:
            def __init__(self, id, name, allocation, instruments):
                self.id = id
                self.name = name
                #How much to allocate in this strategy in current Equity Percentage (i.e., 50.0 %)
                self.allocation = allocation
                # the instruments this strategy will trade [instrA,instrB,etc]
                self.instruments = instruments
                #Number of instruments
                self.numInstr=len(self.instruments)
                
                #Keep track if we are invested or Flat
                self.invested = {}
                #Keep track of the last shares bought from this strategy so we can exit only those shares
                self.lastorder = {}
                #init these dicts
                for cur_sid in self.instruments:
                        self.invested[cur_sid] = False
                        self.lastorder[cur_sid] = 0

 # Sub-Strategy class to implement specific rules     
class StrategyTAA(Strategy):
    #TAA stands for Tactical Allocation Strategy (aka. Faber's Ivy Portfolio)
    #On the first day of the month we look at each stock. If it is above it's 200day Moving average
    #we buy. If it's below we sell it. We allocate equally to each stock
           
            def Trade(self,data,context):
                   #Go through each Instrument
                for cur_sid in self.instruments:  
                    #If there's no data go up the loop to the next instrument
                    if not cur_sid in data:
                       continue
                    
                    
                    SMA = data[cur_sid].mavg(200)
                    month = data[cur_sid].datetime.month
                    Yestmonth=(data[cur_sid].datetime -timedelta(days=1)).month
                    price = data[cur_sid].price
                    #equity is cash + open positions
                    equity= context.portfolio.cash+context.portfolio.positions_value
                    #This stock should use equity allocated for this strategy / number of instruments in this strategy
                    shares=round(  (self.allocation/100) * (equity/self.numInstr)/ price )
                     
                     #Sell if  we are invested in this stock (from this strategy) and Close<sma200 and today is a new month 
                    if price <SMA and Yestmonth!=month and self.invested[cur_sid] and self.lastorder[cur_sid]>0:
                        order(cur_sid,-self.lastorder[cur_sid])
                        #Update we are not invested
                        self.invested[cur_sid]  = False
                        log.info('TAA:Sold SID %i by %i shares' %(cur_sid, -self.lastorder[cur_sid]))
                        #Update last order to 0 since position sold already
                        self.lastorder[cur_sid]  = 0    
                        
                    #Buy if  we are not invested in this stock (from this strategy) and Close>sma200 and today is a new month 
                    elif price > SMA and Yestmonth!=month and not self.invested[cur_sid]:
                        order(cur_sid,+shares)
                        #Set invested to true
                        self.invested[cur_sid]  = True
                        #Keep track of the shares so we can exit the same shares later
                        self.lastorder[cur_sid]  = shares 
                        log.info('TAA:Long SID %i by %i shares' %(cur_sid, shares))
        
    
class StrategyMeanRev(Strategy):    
        #This is a Mean Reverting strategy. Creates two bands above and bleow the price. If the price crosses the 
        #lower band the strategy buys. It sells when it hits the upper band
        #A basic bull/bear switch is used  (Close>SMA200). The bands are adjusted accordingly
    
            def Trade(self,data, context):  
                for cur_sid in self.instruments: 
                    if not cur_sid in data:
                         continue
     
                    price = data[cur_sid].price
                    stdev=data[cur_sid].stddev(10)
                    sma= data[cur_sid].mavg(5)
                    sma200=data[cur_sid].mavg(200)
                    
                    if (price>sma200):
                        upper = sma+2.0*stdev
                        lower = sma-0.8*stdev
                    else:
                        upper = sma+1.0*stdev
                        lower = sma-2.0*stdev                

                    equity= context.portfolio.cash + context.portfolio.positions_value
                    shares=round(  (self.allocation/100) * (equity/self.numInstr)/ price )
     
 
                    if price>upper and self.invested[cur_sid]  and self.lastorder[cur_sid]>0:
                        order(cur_sid,-self.lastorder[cur_sid])
                        self.invested[cur_sid]  = False
                        log.info('MR: Sold SID %i by %i shares' %(cur_sid, self.lastorder[cur_sid] ))
                        self.lastorder[cur_sid] = 0
        
                    if price<lower  and not self.invested[cur_sid]:
                        order(cur_sid,+shares)
                        self.invested[cur_sid]  = True
                        self.lastorder[cur_sid] = shares
                        log.info('MR: Long SID %i by %i shares' %(cur_sid, shares))
        
       
 
def initialize(context):
 
    context.previousday= 0
    #StrategyType(id,name,allocation,Instruments)
    context.strategies = [ 
                           StrategyTAA(1,'TAA200', 100.0 ,[sid(8554), sid(23921) ] ) ,
                           StrategyMeanRev(2,'Bands',100.0,[ sid(8554), sid(23921) ] ) 
                         ]
   
           
            
def handle_data(context, data):
    
    thisday = data[sid(3766)].datetime.day
 
    #only trade on new day
    if(thisday!=context.previousday):  
        #Implement each strategy
        for strat in context.strategies:
            strat.Trade(data,context)
            
    context.previousday = thisday      

   
      

            
       
       
        
There was a runtime error.

@Peter Neat! This is a great example for people wanting to make multi-strategy algos.

Hi Peter,

Thanks for updating this algo. Since you asked, the next step/improvement, in terms of framework, would be to track performance of each individual strategy and adjust weights accordingly.

Hi
For testing pourpose I clone the last algo but the performance (without mod) is much higher 427%... where I'm wrong?
Also, I modify the deprecated code of the second strategy and the performance change again.... 284%?
Apologize me I'm a Phyton and english newbe, but I can't solve myself.
Thanks in advance.

.. this is the code changed around line 80 (new sma, sma200, stdev):

                price_hist1 = data.history(cur_sid, 'price', 5, '1d')  
                price_hist2 = data.history(cur_sid, 'price', 200, '1d')  
                stddev_hist = data.history(cur_sid, 'price', 10, '1d')[:-1]  
                sma = price_hist1.mean()  
                sma200 = price_hist2.mean()  
                stdev = stddev_hist.std()  


                price = data[cur_sid].price  
                #stdev=data[cur_sid].stddev(10)  
                #sma= data[cur_sid].mavg(5)  
                #sma200=data[cur_sid].mavg(200)  

Ummm nobody is interested...

Then I attach a exact clone of the algo of Peter (18 june) .. his return is 2,84, mine today is 4,27 why??????!!!
If I'm wrong, fine, I will fix it. But I want to be sure, before to go on, not a bug is present on the return calculation.

Ciao

Clone Algorithm
8
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
from datetime import datetime, timedelta
 
# Strategy class to keep track of basic strategy parameters
class Strategy:
            def __init__(self, id, name, allocation, instruments):
                self.id = id
                self.name = name
                #How much to allocate in this strategy in current Equity Percentage (i.e., 50.0 %)
                self.allocation = allocation
                # the instruments this strategy will trade [instrA,instrB,etc]
                self.instruments = instruments
                #Number of instruments
                self.numInstr=len(self.instruments)
                
                #Keep track if we are invested or Flat
                self.invested = {}
                #Keep track of the last shares bought from this strategy so we can exit only those shares
                self.lastorder = {}
                #init these dicts
                for cur_sid in self.instruments:
                        self.invested[cur_sid] = False
                        self.lastorder[cur_sid] = 0

 # Sub-Strategy class to implement specific rules     
class StrategyTAA(Strategy):
    #TAA stands for Tactical Allocation Strategy (aka. Faber's Ivy Portfolio)
    #On the first day of the month we look at each stock. If it is above it's 200day Moving average
    #we buy. If it's below we sell it. We allocate equally to each stock
           
            def Trade(self,data,context):
                   #Go through each Instrument
                for cur_sid in self.instruments:  
                    #If there's no data go up the loop to the next instrument
                    if not cur_sid in data:
                       continue
                    
                    
                    SMA = data[cur_sid].mavg(200)
                    month = data[cur_sid].datetime.month
                    Yestmonth=(data[cur_sid].datetime -timedelta(days=1)).month
                    price = data[cur_sid].price
                    #equity is cash + open positions
                    equity= context.portfolio.cash+context.portfolio.positions_value
                    #This stock should use equity allocated for this strategy / number of instruments in this strategy
                    shares=round(  (self.allocation/100) * (equity/self.numInstr)/ price )
                     
                     #Sell if  we are invested in this stock (from this strategy) and Close<sma200 and today is a new month 
                    if price <SMA and Yestmonth!=month and self.invested[cur_sid] and self.lastorder[cur_sid]>0:
                        order(cur_sid,-self.lastorder[cur_sid])
                        #Update we are not invested
                        self.invested[cur_sid]  = False
                        log.info('TAA:Sold SID %i by %i shares' %(cur_sid, -self.lastorder[cur_sid]))
                        #Update last order to 0 since position sold already
                        self.lastorder[cur_sid]  = 0    
                        
                    #Buy if  we are not invested in this stock (from this strategy) and Close>sma200 and today is a new month 
                    elif price > SMA and Yestmonth!=month and not self.invested[cur_sid]:
                        order(cur_sid,+shares)
                        #Set invested to true
                        self.invested[cur_sid]  = True
                        #Keep track of the shares so we can exit the same shares later
                        self.lastorder[cur_sid]  = shares 
                        log.info('TAA:Long SID %i by %i shares' %(cur_sid, shares))
        
    
class StrategyMeanRev(Strategy):    
        #This is a Mean Reverting strategy. Creates two bands above and bleow the price. If the price crosses the 
        #lower band the strategy buys. It sells when it hits the upper band
        #A basic bull/bear switch is used  (Close>SMA200). The bands are adjusted accordingly
    
            def Trade(self,data, context):  
                for cur_sid in self.instruments: 
                    if not cur_sid in data:
                         continue
     
                    price = data[cur_sid].price
                    stdev=data[cur_sid].stddev(10)
                    sma= data[cur_sid].mavg(5)
                    sma200=data[cur_sid].mavg(200)
                    
                    if (price>sma200):
                        upper = sma+2.0*stdev
                        lower = sma-0.8*stdev
                    else:
                        upper = sma+1.0*stdev
                        lower = sma-2.0*stdev                

                    equity= context.portfolio.cash + context.portfolio.positions_value
                    shares=round(  (self.allocation/100) * (equity/self.numInstr)/ price )
     
 
                    if price>upper and self.invested[cur_sid]  and self.lastorder[cur_sid]>0:
                        order(cur_sid,-self.lastorder[cur_sid])
                        self.invested[cur_sid]  = False
                        log.info('MR: Sold SID %i by %i shares' %(cur_sid, self.lastorder[cur_sid] ))
                        self.lastorder[cur_sid] = 0
        
                    if price<lower  and not self.invested[cur_sid]:
                        order(cur_sid,+shares)
                        self.invested[cur_sid]  = True
                        self.lastorder[cur_sid] = shares
                        log.info('MR: Long SID %i by %i shares' %(cur_sid, shares))
        
       
 
def initialize(context):
 
    context.previousday= 0
    #StrategyType(id,name,allocation,Instruments)
    context.strategies = [ 
                           StrategyTAA(1,'TAA200', 100.0 ,[sid(8554), sid(23921) ] ) ,
                           StrategyMeanRev(2,'Bands',100.0,[ sid(8554), sid(23921) ] ) 
                         ]
   
           
            
def handle_data(context, data):
    
    thisday = data[sid(3766)].datetime.day
 
    #only trade on new day
    if(thisday!=context.previousday):  
        #Implement each strategy
        for strat in context.strategies:
            strat.Trade(data,context)
            
    context.previousday = thisday      

   
      

            
       
       
        
There was a runtime error.

It's very odd indeed Michele. could be caused with Q2 release and I'm happy to look into it to see whether I get the same result and see what the difference is. Have you checked the backtest analyser in the Notebook environment? I would run both backtest through it and see where it deviates.

Hi Peter I'm glad you answer

This is the modified version correcting the deprecated code (still missing line 46 (I dont know how to do it) and 137 (the backtest become very very slow))
and the return this time is 354%!!!
I'm not able to finish the correction to see if is the deprecated code the problem..

Clone Algorithm
5
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
from datetime import datetime, timedelta
 
# Strategy class to keep track of basic strategy parameters
class Strategy:
            def __init__(self, id, name, allocation, instruments):
                self.id = id
                self.name = name
                #How much to allocate in this strategy in current Equity Percentage (i.e., 50.0 %)
                self.allocation = allocation
                # the instruments this strategy will trade [instrA,instrB,etc]
                self.instruments = instruments
                #Number of instruments
                self.numInstr=len(self.instruments)
                
                #Keep track if we are invested or Flat
                self.invested = {}
                #Keep track of the last shares bought from this strategy so we can exit only those shares
                self.lastorder = {}
                #init these dicts
                for cur_sid in self.instruments:
                        self.invested[cur_sid] = False
                        self.lastorder[cur_sid] = 0

 # Sub-Strategy class to implement specific rules     
class StrategyTAA(Strategy):
    #TAA stands for Tactical Allocation Strategy (aka. Faber's Ivy Portfolio)
    #On the first day of the month we look at each stock. If it is above it's 200day Moving average
    #we buy. If it's below we sell it. We allocate equally to each stock
           
            def Trade(self,data,context):
                   #Go through each Instrument
                for cur_sid in self.instruments:  
                    #If there's no data go up the loop to the next instrument
                    if not data.can_trade(cur_sid):
                       continue
                    
                    price = data.current(cur_sid, 'price')
                    price_hist2 = data.history(cur_sid, 'price', 200, '1d')
                    SMA = price_hist2.mean()
                    month = data.current(cur_sid, 'month')
                    #Yestmonth = data.current(cur_sid, 'datetime - timedelta(days=1).month')                     
                              
                    
                    #SMA = data[cur_sid].mavg(200)
                    #month = data[cur_sid].datetime.month
                    Yestmonth=(data[cur_sid].datetime -timedelta(days=1)).month
                    #price = data[cur_sid].price
                    #equity is cash + open positions
                    equity= context.portfolio.cash+context.portfolio.positions_value
                    #This stock should use equity allocated for this strategy / number of instruments in this strategy
                    shares=round(  (self.allocation/100) * (equity/self.numInstr)/ price )
                     
                     #Sell if  we are invested in this stock (from this strategy) and Close<sma200 and today is a new month 
                    if price <SMA and Yestmonth!=month and self.invested[cur_sid] and self.lastorder[cur_sid]>0:
                        order(cur_sid,-self.lastorder[cur_sid])
                        #Update we are not invested
                        self.invested[cur_sid]  = False
                        log.info('TAA:Sold SID %i by %i shares' %(cur_sid, -self.lastorder[cur_sid]))
                        #Update last order to 0 since position sold already
                        self.lastorder[cur_sid]  = 0    
                        
                    #Buy if  we are not invested in this stock (from this strategy) and Close>sma200 and today is a new month 
                    elif price > SMA and Yestmonth!=month and not self.invested[cur_sid]:
                        order(cur_sid,+shares)
                        #Set invested to true
                        self.invested[cur_sid]  = True
                        #Keep track of the shares so we can exit the same shares later
                        self.lastorder[cur_sid]  = shares 
                        log.info('TAA:Long SID %i by %i shares' %(cur_sid, shares))
        
    
class StrategyMeanRev(Strategy):    
        #This is a Mean Reverting strategy. Creates two bands above and bleow the price. If the price crosses the 
        #lower band the strategy buys. It sells when it hits the upper band
        #A basic bull/bear switch is used  (Close>SMA200). The bands are adjusted accordingly
    
            def Trade(self,data, context):  
                for cur_sid in self.instruments: 
                    if not data.can_trade(cur_sid):
                         continue
     
                    
                    price_hist1 = data.history(cur_sid, 'price', 5, '1d')
                    price_hist2 = data.history(cur_sid, 'price', 200, '1d')
                    stddev_hist = data.history(cur_sid, 'price', 10, '1d')[:-1]
                    sma = price_hist1.mean()
                    sma200 = price_hist2.mean()
                    stdev = stddev_hist.std()
                    price = data.current(cur_sid, 'price')
        
        
        
        
                    #price = data[cur_sid].price
                    #stdev=data[cur_sid].stddev(10)
                    #sma= data[cur_sid].mavg(5)
                    #sma200=data[cur_sid].mavg(200)
                    
                    if (price>sma200):
                        upper = sma+2.0*stdev
                        lower = sma-0.8*stdev
                    else:
                        upper = sma+1.0*stdev
                        lower = sma-2.0*stdev                

                    equity= context.portfolio.cash + context.portfolio.positions_value
                    shares=round(  (self.allocation/100) * (equity/self.numInstr)/ price )
     
 
                    if price>upper and self.invested[cur_sid]  and self.lastorder[cur_sid]>0:
                        order(cur_sid,-self.lastorder[cur_sid])
                        self.invested[cur_sid]  = False
                        log.info('MR: Sold SID %i by %i shares' %(cur_sid, self.lastorder[cur_sid] ))
                        self.lastorder[cur_sid] = 0
        
                    if price<lower  and not self.invested[cur_sid]:
                        order(cur_sid,+shares)
                        self.invested[cur_sid]  = True
                        self.lastorder[cur_sid] = shares
                        log.info('MR: Long SID %i by %i shares' %(cur_sid, shares))
        
       
 
def initialize(context):
 
    context.previousday= 0
    #StrategyType(id,name,allocation,Instruments)
    context.strategies = [ 
                           StrategyTAA(1,'TAA200', 100.0 ,[sid(8554), sid(23921) ] ) ,
                           StrategyMeanRev(2,'Bands',100.0,[ sid(8554), sid(23921) ] ) 
                         ]
   
           
            
def handle_data(context, data):
    
    thisday = data[sid(3766)].datetime.day
    #thisday = data.current(sid(3766), 'day')
    #only trade on new day
    if(thisday!=context.previousday):  
        #Implement each strategy
        for strat in context.strategies:
            strat.Trade(data,context)
            
    context.previousday = thisday      

   
      

            
       
       
        
There was a runtime error.

I Fixed it but I must say there were some other problems with the algo as it was overleveraged (x2). So Not only adjusted to Q2 code but also made the leverage around 1 (to make algo's comparable I always publish them with leverage of 1) and made sure it functions on 10K as well. The algo looked better then it was... although it generates an alpha at 0.12 which you can isolate by hedging and leverage the hell out of it

Clone Algorithm
39
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
from datetime import datetime, timedelta
import numpy as np
 
# Strategy class to keep track of basic strategy parameters
class Strategy:
            def __init__(self, id, name, allocation, instruments):
                self.id = id
                self.name = name
                #How much to allocate in this strategy in current Equity Percentage (i.e., 50.0 %)
                self.allocation = allocation
                # the instruments this strategy will trade [instrA,instrB,etc]
                self.instruments = instruments
                #Number of instruments
                self.numInstr=len(self.instruments)
                
                #Keep track if we are invested or Flat
                self.invested = {}
                #Keep track of the last shares bought from this strategy so we can exit only those shares
                self.lastorder = {}
                #init these dicts
                for cur_sid in self.instruments:
                        self.invested[cur_sid] = False
                        self.lastorder[cur_sid] = 0

 # Sub-Strategy class to implement specific rules     
class StrategyTAA(Strategy):
    #TAA stands for Tactical Allocation Strategy (aka. Faber's Ivy Portfolio)
    #On the first day of the month we look at each stock. If it is above it's 200day Moving average
    #we buy. If it's below we sell it. We allocate equally to each stock
           
            def Trade(self,data,context):
                   #Go through each Instrument
                for cur_sid in self.instruments:  
                    #If there's no data go up the loop to the next instrument
                    if not data.can_trade(cur_sid):
                       continue
                    
                    
                    SMA = data.history(cur_sid,'price',200,'1d').mean()
                    month = get_datetime().month
                    Yestmonth= (get_datetime() -timedelta(days=1)).month
                    price = data.current(cur_sid,"price")
                    #equity is cash + open positions
                    equity= context.portfolio.cash+context.portfolio.positions_value
                    #This stock should use equity allocated for this strategy / number of instruments in this strategy
                    shares=round(  (self.allocation/100) * (equity/self.numInstr)/ price )
                     
                     #Sell if  we are invested in this stock (from this strategy) and Close<sma200 and today is a new month 
                    if price <SMA and Yestmonth!=month and self.invested[cur_sid] and self.lastorder[cur_sid]>0:
                        order(cur_sid,-self.lastorder[cur_sid])
                        #Update we are not invested
                        self.invested[cur_sid]  = False
                        log.info('TAA:Sold SID %s by %i shares' %(cur_sid.symbol, -self.lastorder[cur_sid]))
                        #Update last order to 0 since position sold already
                        self.lastorder[cur_sid]  = 0    
                        
                    #Buy if  we are not invested in this stock (from this strategy) and Close>sma200 and today is a new month 
                    elif price > SMA and Yestmonth!=month and not self.invested[cur_sid]:
                        order(cur_sid,+shares)
                        #Set invested to true
                        self.invested[cur_sid]  = True
                        #Keep track of the shares so we can exit the same shares later
                        self.lastorder[cur_sid]  = shares 
                        log.info('TAA:Long SID %s by %i shares' %(cur_sid.symbol, shares))
        
    
class StrategyMeanRev(Strategy):    
        #This is a Mean Reverting strategy. Creates two bands above and bleow the price. If the price crosses the 
        #lower band the strategy buys. It sells when it hits the upper band
        #A basic bull/bear switch is used  (Close>SMA200). The bands are adjusted accordingly
    
            def Trade(self,data, context):  
                for cur_sid in self.instruments: 
                    if not data.can_trade(cur_sid):
                         continue
     
                    price = data.current(cur_sid,"price")
                    History = data.history(cur_sid,'price',200,'1d')
                    stdev=np.std(History[-10:])
                    sma= np.mean(History[-5:])
                    sma200 =np.mean(History)
                    
                    if (price>sma200):
                        upper = sma+2.0*stdev
                        lower = sma-0.8*stdev
                    else:
                        upper = sma+1.0*stdev
                        lower = sma-2.0*stdev                

                    equity= context.portfolio.cash + context.portfolio.positions_value
                    shares=round(  (self.allocation/100) * (equity/self.numInstr)/ price )
     
 
                    if price>upper and self.invested[cur_sid]  and self.lastorder[cur_sid]>0:
                        order(cur_sid,-self.lastorder[cur_sid])
                        self.invested[cur_sid]  = False
                        log.info('MR: Sold SID %s by %i shares' %(cur_sid.symbol, self.lastorder[cur_sid] ))
                        self.lastorder[cur_sid] = 0
        
                    if price<lower  and not self.invested[cur_sid]:
                        order(cur_sid,+shares)
                        self.invested[cur_sid]  = True
                        self.lastorder[cur_sid] = shares
                        log.info('MR: Long SID %s by %i shares' %(cur_sid.symbol, shares))
        
       
 
def initialize(context):
 
    context.previousday= 0
    #StrategyType(id,name,allocation,Instruments)
    context.strategies = [ 
                           StrategyTAA(1,'TAA200', 49.0 ,[sid(8554), sid(23921) ] ) ,
                           StrategyMeanRev(2,'Bands',49.0,[ sid(8554), sid(23921) ] ) 
                         ]
    schedule_function(Daily,date_rule=date_rules.every_day(),time_rule=time_rules.market_close(minutes=1))
   
           
           
def Daily(context, data):
    for strat in context.strategies:
        strat.Trade(data,context)
    record(leverage = context.account.leverage)
            
   
      

            
       
       
        
There was a runtime error.

Thanks Peter
Tuning the algo the performance will increase.
I like very much this algo: is multiple then ready to grow, simple, perfect to me to learn python and Q platform.

Cool, keep us posted on the improvements!