Back to Community
Long Only Mean Reversion For Robinhood Users. 100,000% Returns

I wrote this simple modification to "enhancing mean reversion algorithms" a while ago. I added some common sense and made it long only. Found it while going through old algorithms and figured I might as well post it.

Clone Algorithm
348
Loading...
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
import numpy as np
import pandas as pd
from quantopian.pipeline import Pipeline
from quantopian.pipeline import CustomFactor
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import SimpleMovingAverage, AverageDollarVolume
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.filters import Q500US

def initialize(context):
    set_long_only()
    
    set_benchmark(sid(8554))
    #orignially these were CLOSE: hours = 5
    schedule_function(ANALYZE,date_rules.every_day(), time_rules.market_open(hours = 2, minutes = 30))
    schedule_function(sell,date_rules.every_day(), time_rules.market_open(hours = 2, minutes = 31))
    schedule_function(buy,date_rules.every_day(), time_rules.market_open(hours = 2, minutes = 32))
    schedule_function(maximize,date_rules.every_day(), time_rules.market_open(hours = 2, minutes = 40))
    set_slippage(slippage.FixedSlippage(spread=0.0))
    set_commission(commission.PerShare(cost=0, min_trade_cost=0))
    context.nq=5
    context.nq_vol=3
    my_pipe = make_pipeline()
    attach_pipeline(my_pipe, 'my_pipeline')
    context.max_leverage = [0]
    context.ANV = []
    context.buy = []
    context.sell = []
    context.ETN_buy = []
    context.AmountHeldData = []
    context.B = []
    context.S = []
    context.DayCounter = 0.0
    context.L = 1.0
    context.Maximize = True
    
class Volatility(CustomFactor):  
    inputs = [USEquityPricing.close]
    window_length=132
    
    def compute(self, today, assets, out, close):

        daily_returns = np.log(close[1:-6]) - np.log(close[0:-7])
        out[:] = daily_returns.std(axis = 0)           

class Liquidity(CustomFactor):   
    inputs = [USEquityPricing.volume, morningstar.valuation.shares_outstanding] 
    window_length = 1
    
    def compute(self, today, assets, out, volume, shares):       
        out[:] = volume[-1]/shares[-1]        
        
class Sector(CustomFactor):
    inputs=[morningstar.asset_classification.morningstar_sector_code]
    window_length=1
    
    def compute(self, today, assets, out, sector):
        out[:] = sector[-1]   
        
        
def make_pipeline():
    profitable = morningstar.valuation_ratios.ev_to_ebitda.latest > 0 
    volume = USEquityPricing.volume
    pricing = USEquityPricing.close.latest    
    universe = ( Q500US()&(pricing>0)&(volume>1000000)&profitable )
    return Pipeline(screen=universe)

def before_trading_start(context, data):
    context.output = pipeline_output('my_pipeline')
    context.buy = []
    context.sell = []
    context.ETN_buy = []
    context.B = []
    context.S = []
    positions = []
    context.longs = []
    for sec in context.portfolio.positions:
        positions.append(sec)
    if len(positions) >= 1:
        context.AmountHeldData.append(len(positions))
        
    #print('=============================================================================================================' + '\n' )
    
            
def ANALYZE(context, data):
    Universe500=context.output.index.tolist()
    prices = data.history(Universe500,'price',6,'1d')
    daily_rets=np.log(prices/prices.shift(1))
    rets=(prices.iloc[-2] - prices.iloc[0]) / prices.iloc[0]
    # If you don't want to skip the most recent return, however, use .iloc[-1] instead of .iloc[-2]:
    # rets=(prices.iloc[-1] - prices.iloc[0]) / prices.iloc[0]
    stdevs=daily_rets.std(axis=0)
    rets_df=pd.DataFrame(rets,columns=['five_day_ret'])
    stdevs_df=pd.DataFrame(stdevs,columns=['stdev_ret'])
    context.output=context.output.join(rets_df,how='outer')
    context.output=context.output.join(stdevs_df,how='outer')    
    context.output['ret_quantile']=pd.qcut(context.output['five_day_ret'],context.nq,labels=False)+1
    context.output['stdev_quantile']=pd.qcut(context.output['stdev_ret'],3,labels=False)+1
    context.longs=context.output[(context.output['ret_quantile']==1) & 
                                (context.output['stdev_quantile']<context.nq_vol)].index.tolist()
    context.shorts=context.output[(context.output['ret_quantile']==context.nq) & 
                                 (context.output['stdev_quantile']<context.nq_vol)].index.tolist()    
#============================================================================================
#REBALANCE
#============================================================================================
    Universe500=context.output.index.tolist()
    context.existing_longs=0
    context.existing_shorts=0
    for security in context.portfolio.positions:
        if security not in Universe500 and data.can_trade(security): 
            order_target_percent(security, 0)
        else:
            if data.can_trade(security):
                current_quantile=context.output['ret_quantile'].loc[security]
                if context.portfolio.positions[security].amount>0:
                    if (current_quantile==1) and (security not in context.longs):
                        context.existing_longs += 1
                    elif (current_quantile>1) and (security not in context.shorts):
                        order_target_percent(security, 0)
                elif context.portfolio.positions[security].amount<0:
                    if (current_quantile==context.nq) and (security not in context.shorts):
                        context.existing_shorts += 1
                    elif (current_quantile<context.nq) and (security not in context.longs):
                        order_target_percent(security, 0)
#============================================================================================
#ANALYZE
#============================================================================================
    spy = [sid(8554)]
    spxs = [sid(37083)]
    Velocity = 0
    #long_leverage = 0
    #short_leverage = 0
    for sec in spy:
        Av = 0
        pri = data.history(spy, "price",200, "1d")
        pos_one = (pri[sec][-3:].mean())
        pos_two = (pri[sec][-15:].mean())
        pos_three = (pri[sec][-165:].mean())
        
        if pos_one < pos_two < pos_three:   
            context.Maximize = False
            context.L = 0.5
            for security in context.longs:
                pri = data.history(context.longs, "price",200, "1d")
                #pos = 'pri[security]'
                pos_one = (pri[security][-1])
                pos_six = (pri[security][-2:].mean())
                #VELOCITY
                velocity_stop = (pos_one - pos_six)
                Velocity = velocity_stop
                if Velocity < 0:
                    context.longs.remove(security)
        else:
            context.Maximize = True
            context.L = 1.0
            for security in context.longs:
                pri = data.history(context.longs, "price",200, "1d")
                #pos = 'pri[security]'
                pos_one = (pri[security][-1])
                pos_six = (pri[security][-2:].mean())
                #VELOCITY
                velocity_stop = (pos_one - pos_six)
                Velocity = velocity_stop
                if Velocity > 0:
                    context.longs.remove(security)
    for sec in spy:
        pri = data.history(spy, "price",200, "1d")
        pos_one = (pri[sec][-1])
        pos_six = (pri[sec][-45:].mean())
        Velocity = (pos_one - pos_six)
        
        if Velocity > -0.5:
            #long_leverage = 1.75
            pos_one = (pri[sec][-1])
            pos_six = (pri[sec][-2:].mean())
            #VELOCITY
            velocity_stop = (pos_one - pos_six)
            Velocity = velocity_stop
            if Velocity < -0.5:
                context.longs = []
            if Velocity < -1.0:
                context.longs = []
                for sec in spxs:
                    if data.can_trade(sec) and sec not in context.longs:
                        context.longs.append(sec)
            elif data.can_trade(sid(37083)):
                for sec in spxs:
                    context.sell.append(sec)
                
        else:
            pos_one = (pri[sec][-1])
            pos_six = (pri[sec][-2:].mean())
            Velocity = (pos_one - pos_six)
            if Velocity < -1.0:
                context.longs = []
                for sec in spxs:
                    if data.can_trade(sec) and sec not in context.longs:
                        context.longs.append(sec)
            else:
                for sec in spxs:
                    if data.can_trade(sec):
                        context.sell.append(sec)
            
    for sec in context.portfolio.positions:
        if sec not in context.buy:
            context.sell.append(sec)
           
def sell (context, data):
    for sec in context.sell:
        if data.can_trade(sec) and sec not in context.B:
            order_target_percent(sec, 0)
            context.S.append(sec)            
        
def buy (context, data):
    for sec in context.longs:
        if data.can_trade(sec) and sec not in context.portfolio.positions and sec not in context.S and (len(context.longs) > 0):
            order_target_percent(sec, context.L/(len(context.longs)))
            context.B.append(sec)
                      
def maximize (context, data):
    if context.Maximize == True:
        currentHold = len(context.portfolio.positions)
        for sec in context.portfolio.positions:
            order_target_percent(sec, 1.75/currentHold)
    record(leverage = context.account.leverage)              
def handle_data (context, data):
    for sec in context.portfolio.positions:
        if sec not in context.B:
            if context.portfolio.positions[sec].cost_basis * 0.935 > context.portfolio.positions[sec].last_sale_price:
                order_target_percent(sec, 0)
    for s in context.portfolio.positions:
        if context.portfolio.positions[s].amount < 0:
            order_target_percent(s, 0)
 
    
There was a runtime error.
27 responses

Pretty neat. How do you get it to stop borrowing cash ... ?

def maximize (context, data):  
    if context.Maximize == True:  
        currentHold = len(context.portfolio.positions)  
        for sec in context.portfolio.positions:  
            order_target_percent(sec, 1/currentHold)    <--------------------  I changed this from 1.75 to 1 and it seemed to stop going into negative cash, but don't know if what I did was the best way to accomplish it.  
    record(leverage = context.account.leverage)  

first id get rid of currentHold since its just = to len(context.portfolio.positions) (im sure i had a reason for it existing at some point.

if you want to borrow money, you order over 100% (1) 1.75 is the safe range where you can pretty much always order and never worry about the orders canceling due to margin requirements (for me at least)
btw you may want to change that 1 from an integer to a float value. idk if it matters here or not.

but yeah, that is the best way to accomplish ordering only 100% of your total account value.

def maximize (context, data):  
    if context.Maximize == True:  
        for sec in context.portfolio.positions:  
            order_target_percent( sec, 1.0/len(context.portfolio.positions) )  

Ok, just ensuring that I understood what I changed and turns out I pretty much got it! Thanks!

Here were my results with that change.

Clone Algorithm
118
Loading...
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
import numpy as np
import pandas as pd
from quantopian.pipeline import Pipeline
from quantopian.pipeline import CustomFactor
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import SimpleMovingAverage, AverageDollarVolume
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.filters import Q500US

def initialize(context):
    set_long_only()
    
    set_benchmark(sid(8554))
    #orignially these were CLOSE: hours = 5
    schedule_function(ANALYZE,date_rules.every_day(), time_rules.market_open(hours = 2, minutes = 30))
    schedule_function(sell,date_rules.every_day(), time_rules.market_open(hours = 2, minutes = 31))
    schedule_function(buy,date_rules.every_day(), time_rules.market_open(hours = 2, minutes = 32))
    schedule_function(maximize,date_rules.every_day(), time_rules.market_open(hours = 2, minutes = 40))
    set_slippage(slippage.FixedSlippage(spread=0.0))
    set_commission(commission.PerShare(cost=0, min_trade_cost=0))
    context.nq=5
    context.nq_vol=3
    my_pipe = make_pipeline()
    attach_pipeline(my_pipe, 'my_pipeline')
    context.max_leverage = [0]
    context.ANV = []
    context.buy = []
    context.sell = []
    context.ETN_buy = []
    context.AmountHeldData = []
    context.B = []
    context.S = []
    context.DayCounter = 0.0
    context.L = 1.0
    context.Maximize = True
    
class Volatility(CustomFactor):  
    inputs = [USEquityPricing.close]
    window_length=132
    
    def compute(self, today, assets, out, close):

        daily_returns = np.log(close[1:-6]) - np.log(close[0:-7])
        out[:] = daily_returns.std(axis = 0)           

class Liquidity(CustomFactor):   
    inputs = [USEquityPricing.volume, morningstar.valuation.shares_outstanding] 
    window_length = 1
    
    def compute(self, today, assets, out, volume, shares):       
        out[:] = volume[-1]/shares[-1]        
        
class Sector(CustomFactor):
    inputs=[morningstar.asset_classification.morningstar_sector_code]
    window_length=1
    
    def compute(self, today, assets, out, sector):
        out[:] = sector[-1]   
        
        
def make_pipeline():
    profitable = morningstar.valuation_ratios.ev_to_ebitda.latest > 0 
    volume = USEquityPricing.volume
    pricing = USEquityPricing.close.latest    
    universe = ( Q500US()&(pricing>0)&(volume>1000000)&profitable )
    return Pipeline(screen=universe)

def before_trading_start(context, data):
    context.output = pipeline_output('my_pipeline')
    context.buy = []
    context.sell = []
    context.ETN_buy = []
    context.B = []
    context.S = []
    positions = []
    context.longs = []
    for sec in context.portfolio.positions:
        positions.append(sec)
    if len(positions) >= 1:
        context.AmountHeldData.append(len(positions))
        
    #print('=============================================================================================================' + '\n' )
    
            
def ANALYZE(context, data):
    Universe500=context.output.index.tolist()
    prices = data.history(Universe500,'price',6,'1d')
    daily_rets=np.log(prices/prices.shift(1))
    rets=(prices.iloc[-2] - prices.iloc[0]) / prices.iloc[0]
    # If you don't want to skip the most recent return, however, use .iloc[-1] instead of .iloc[-2]:
    # rets=(prices.iloc[-1] - prices.iloc[0]) / prices.iloc[0]
    stdevs=daily_rets.std(axis=0)
    rets_df=pd.DataFrame(rets,columns=['five_day_ret'])
    stdevs_df=pd.DataFrame(stdevs,columns=['stdev_ret'])
    context.output=context.output.join(rets_df,how='outer')
    context.output=context.output.join(stdevs_df,how='outer')    
    context.output['ret_quantile']=pd.qcut(context.output['five_day_ret'],context.nq,labels=False)+1
    context.output['stdev_quantile']=pd.qcut(context.output['stdev_ret'],3,labels=False)+1
    context.longs=context.output[(context.output['ret_quantile']==1) & 
                                (context.output['stdev_quantile']<context.nq_vol)].index.tolist()
    context.shorts=context.output[(context.output['ret_quantile']==context.nq) & 
                                 (context.output['stdev_quantile']<context.nq_vol)].index.tolist()    
#============================================================================================
#REBALANCE
#============================================================================================
    Universe500=context.output.index.tolist()
    context.existing_longs=0
    context.existing_shorts=0
    cash = cash = context.portfolio.cash
    
    for security in context.portfolio.positions:
        if security not in Universe500 and data.can_trade(security): 
            order_target_percent(security, 0)
        else:
            if data.can_trade(security):
                current_quantile=context.output['ret_quantile'].loc[security]
                if context.portfolio.positions[security].amount>0:
                    if (current_quantile==1) and (security not in context.longs):
                        context.existing_longs += 1
                    elif (current_quantile>1) and (security not in context.shorts):
                        order_target_percent(security, 0)
                elif context.portfolio.positions[security].amount<0:
                    if (current_quantile==context.nq) and (security not in context.shorts):
                        context.existing_shorts += 1
                    elif (current_quantile<context.nq) and (security not in context.longs):
                        order_target_percent(security, 0)
                        
    record(cash=cash)
                             
#============================================================================================
#ANALYZE
#============================================================================================
    spy = [sid(8554)]
    spxs = [sid(37083)]
    Velocity = 0
    #long_leverage = 0
    #short_leverage = 0
    for sec in spy:
        #Av = 0
        pri = data.history(spy, "price",200, "1d")
        pos_one = (pri[sec][-3:].mean())
        pos_two = (pri[sec][-15:].mean())
        pos_three = (pri[sec][-165:].mean())
        
        if pos_one < pos_two < pos_three:   
            context.Maximize = False
            context.L = 0.5
            for security in context.longs:
                pri = data.history(context.longs, "price",200, "1d")
                #pos = 'pri[security]'
                pos_one = (pri[security][-1])
                pos_six = (pri[security][-2:].mean())
                #VELOCITY
                velocity_stop = (pos_one - pos_six)
                Velocity = velocity_stop
                if Velocity < 0:
                    context.longs.remove(security)
        else:
            context.Maximize = True
            context.L = 1.0
            for security in context.longs:
                pri = data.history(context.longs, "price",200, "1d")
                #pos = 'pri[security]'
                pos_one = (pri[security][-1])
                pos_six = (pri[security][-2:].mean())
                #VELOCITY
                velocity_stop = (pos_one - pos_six)
                Velocity = velocity_stop
                if Velocity > 0:
                    context.longs.remove(security)
    for sec in spy:
        pri = data.history(spy, "price",200, "1d")
        pos_one = (pri[sec][-1])
        pos_six = (pri[sec][-45:].mean())
        Velocity = (pos_one - pos_six)
        
        if Velocity > -0.5:
            #long_leverage = 1.75
            pos_one = (pri[sec][-1])
            pos_six = (pri[sec][-2:].mean())
            #VELOCITY
            velocity_stop = (pos_one - pos_six)
            Velocity = velocity_stop
            if Velocity < -0.5:
                context.longs = []
            if Velocity < -1.0:
                context.longs = []
                for sec in spxs:
                    if data.can_trade(sec) and sec not in context.longs:
                        context.longs.append(sec)
            elif data.can_trade(sid(37083)):
                for sec in spxs:
                    context.sell.append(sec)
                
        else:
            pos_one = (pri[sec][-1])
            pos_six = (pri[sec][-2:].mean())
            Velocity = (pos_one - pos_six)
            if Velocity < -1.0:
                context.longs = []
                for sec in spxs:
                    if data.can_trade(sec) and sec not in context.longs:
                        context.longs.append(sec)
            else:
                for sec in spxs:
                    if data.can_trade(sec):
                        context.sell.append(sec)
            
    for sec in context.portfolio.positions:
        if sec not in context.buy:
            context.sell.append(sec)
           
def sell (context, data):
    for sec in context.sell:
        if data.can_trade(sec) and sec not in context.B:
            order_target_percent(sec, 0)
            context.S.append(sec)            
        
def buy (context, data):
    for sec in context.longs:
        if data.can_trade(sec) and sec not in context.portfolio.positions and sec not in context.S and (len(context.longs) > 0):
            order_target_percent(sec, context.L/(len(context.longs)))
            context.B.append(sec)
                      
def maximize (context, data):
    if context.Maximize == True:
        currentHold = len(context.portfolio.positions)
        for sec in context.portfolio.positions:
            order_target_percent(sec, .9/currentHold)
    record(leverage = context.account.leverage)
    
def handle_data (context, data):
   
    cash = cash = context.portfolio.cash
    post = context.portfolio.positions_value
    gain_loss = (cash+post) - 1000
   
    for sec in context.portfolio.positions:
        if sec not in context.B:
            if context.portfolio.positions[sec].cost_basis * 0.935 > context.portfolio.positions[sec].last_sale_price:
                order_target_percent(sec, 0)
    for s in context.portfolio.positions:
        if context.portfolio.positions[s].amount < 0:
            order_target_percent(s, 0)
            
    record(gain_loss = gain_loss, portval = post)
    
There was a runtime error.

Started paper trading with this today and realized that it will most likely break the day trading rule on Robinhood ... Will have to adjust code for that

I dont think it day trades but it might. there are situations where it will sell off specific stocks (large losses). There is an issue that, somehow, even when you only order using positive values, quantopian opens a short position. I'm looking into it before I come out and say that they have a legitimate bug on their hands. so if the algorithm opens short positions, the next minute it will close that position. with robinhood, this isnt an issue since you cant open short positions.

So you would need to keep upgrading your Robinhood Gold as this progresses?

I put in the IB commissions and it didn't end well -99%

I was attempting to change the timing so it entered 6 days after the move instead of 1 day after the move.

Clone Algorithm
6
Loading...
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
import numpy as np
import pandas as pd
from quantopian.pipeline import Pipeline
from quantopian.pipeline import CustomFactor
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import SimpleMovingAverage, AverageDollarVolume
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.filters import Q500US

def initialize(context):
    set_long_only()
    
    set_benchmark(sid(8554))
    #orignially these were CLOSE: hours = 5
    schedule_function(ANALYZE,date_rules.every_day(), time_rules.market_open(hours = 2, minutes = 30))
    schedule_function(sell,date_rules.every_day(), time_rules.market_open(hours = 2, minutes = 31))
    schedule_function(buy,date_rules.every_day(), time_rules.market_open(hours = 2, minutes = 32))
    schedule_function(maximize,date_rules.every_day(), time_rules.market_open(hours = 2, minutes = 40))
    set_slippage(slippage.FixedSlippage(spread=0.0))
    set_commission(commission.PerShare(cost=0, min_trade_cost=0))
    context.nq=5
    context.nq_vol=3
    my_pipe = make_pipeline()
    attach_pipeline(my_pipe, 'my_pipeline')
    context.max_leverage = [0]
    context.ANV = []
    context.buy = []
    context.sell = []
    context.ETN_buy = []
    context.AmountHeldData = []
    context.B = []
    context.S = []
    context.DayCounter = 0.0
    context.L = 1.0
    context.Maximize = True
    
class Volatility(CustomFactor):  
    inputs = [USEquityPricing.close]
    window_length=132
    
    def compute(self, today, assets, out, close):

        daily_returns = np.log(close[1:-6]) - np.log(close[0:-7])
        out[:] = daily_returns.std(axis = 0)           

class Liquidity(CustomFactor):   
    inputs = [USEquityPricing.volume, morningstar.valuation.shares_outstanding] 
    window_length = 1
    
    def compute(self, today, assets, out, volume, shares):       
        out[:] = volume[-1]/shares[-1]        
        
class Sector(CustomFactor):
    inputs=[morningstar.asset_classification.morningstar_sector_code]
    window_length=1
    
    def compute(self, today, assets, out, sector):
        out[:] = sector[-1]   
        
        
def make_pipeline():
    profitable = morningstar.valuation_ratios.ev_to_ebitda.latest > 0 
    volume = USEquityPricing.volume
    pricing = USEquityPricing.close.latest    
    universe = ( Q500US()&(pricing>0)&(volume>1000000)&profitable )
    return Pipeline(screen=universe)

def before_trading_start(context, data):
    context.output = pipeline_output('my_pipeline')
    context.buy = []
    context.sell = []
    context.ETN_buy = []
    context.B = []
    context.S = []
    positions = []
    context.longs = []
    for sec in context.portfolio.positions:
        positions.append(sec)
    if len(positions) >= 1:
        context.AmountHeldData.append(len(positions))
        
    #print('=============================================================================================================' + '\n' )
    
            
def ANALYZE(context, data):
    Universe500=context.output.index.tolist()
    prices = data.history(Universe500,'price',6,'1d')
    daily_rets=np.log(prices/prices.shift(1))
    rets=(prices.iloc[-2] - prices.iloc[0]) / prices.iloc[0]
    # If you don't want to skip the most recent return, however, use .iloc[-1] instead of .iloc[-2]:
    # rets=(prices.iloc[-1] - prices.iloc[0]) / prices.iloc[0]
    stdevs=daily_rets.std(axis=0)
    rets_df=pd.DataFrame(rets,columns=['five_day_ret'])
    stdevs_df=pd.DataFrame(stdevs,columns=['stdev_ret'])
    context.output=context.output.join(rets_df,how='outer')
    context.output=context.output.join(stdevs_df,how='outer')    
    context.output['ret_quantile']=pd.qcut(context.output['five_day_ret'],context.nq,labels=False)+1
    context.output['stdev_quantile']=pd.qcut(context.output['stdev_ret'],3,labels=False)+1
    context.longs=context.output[(context.output['ret_quantile']==1) & 
                                (context.output['stdev_quantile']<context.nq_vol)].index.tolist()
    context.shorts=context.output[(context.output['ret_quantile']==context.nq) & 
                                 (context.output['stdev_quantile']<context.nq_vol)].index.tolist()    
#============================================================================================
#REBALANCE
#============================================================================================
    Universe500=context.output.index.tolist()
    context.existing_longs=0
    context.existing_shorts=0
    cash = cash = context.portfolio.cash
    
    for security in context.portfolio.positions:
        if security not in Universe500 and data.can_trade(security): 
            order_target_percent(security, 0)
        else:
            if data.can_trade(security):
                current_quantile=context.output['ret_quantile'].loc[security]
                if context.portfolio.positions[security].amount>0:
                    if (current_quantile==1) and (security not in context.longs):
                        context.existing_longs += 1
                    elif (current_quantile>1) and (security not in context.shorts):
                        order_target_percent(security, 0)
                elif context.portfolio.positions[security].amount<0:
                    if (current_quantile==context.nq) and (security not in context.shorts):
                        context.existing_shorts += 1
                    elif (current_quantile<context.nq) and (security not in context.longs):
                        order_target_percent(security, 0)
                        
    record(cash=cash)
                             
#============================================================================================
#ANALYZE
#============================================================================================
    spy = [sid(8554)]
    spxs = [sid(37083)]
    Velocity = 0
    #long_leverage = 0
    #short_leverage = 0
    for sec in spy:
        #Av = 0
        pri = data.history(spy, "price",200, "1d")
        pos_one = (pri[sec][-3:].mean())
        pos_two = (pri[sec][-15:].mean())
        pos_three = (pri[sec][-165:].mean())
        
        if pos_one < pos_two < pos_three:   
            context.Maximize = False
            context.L = 0.5
            for security in context.longs:
                pri = data.history(context.longs, "price",200, "1d")
                #pos = 'pri[security]'
                pos_one = (pri[security][-1])
                pos_six = (pri[security][-2:].mean())
                #VELOCITY
                velocity_stop = (pos_one - pos_six)
                Velocity = velocity_stop
                if Velocity < 0:
                    context.longs.remove(security)
        else:
            context.Maximize = True
            context.L = 1.0
            for security in context.longs:
                pri = data.history(context.longs, "price",200, "1d")
                #pos = 'pri[security]'
                pos_one = (pri[security][-1])
                pos_six = (pri[security][-2:].mean())
                #VELOCITY
                velocity_stop = (pos_one - pos_six)
                Velocity = velocity_stop
                if Velocity > 0:
                    context.longs.remove(security)
    for sec in spy:
        pri = data.history(spy, "price",200, "1d")
        #start modifying dates here
        #changed from -1 to -6
        pos_one = (pri[sec][-6])
        pos_six = (pri[sec][-45:].mean())
        Velocity = (pos_one - pos_six)
        
        if Velocity > -0.5:
            #long_leverage = 1.75
            #replace 1,2 with 6,7
            pos_one = (pri[sec][-6])
            pos_six = (pri[sec][-7:].mean())
            #VELOCITY
            velocity_stop = (pos_one - pos_six)
            Velocity = velocity_stop
            if Velocity < -0.5:
                context.longs = []
            if Velocity < -1.0:
                context.longs = []
                for sec in spxs:
                    if data.can_trade(sec) and sec not in context.longs:
                        context.longs.append(sec)
            elif data.can_trade(sid(37083)):
                for sec in spxs:
                    context.sell.append(sec)
                
        else:
            #replace 1,2 with 6,7
            pos_one = (pri[sec][-6])
            pos_six = (pri[sec][-7:].mean())
            Velocity = (pos_one - pos_six)
            if Velocity < -1.0:
                context.longs = []
                for sec in spxs:
                    if data.can_trade(sec) and sec not in context.longs:
                        context.longs.append(sec)
            else:
                for sec in spxs:
                    if data.can_trade(sec):
                        context.sell.append(sec)
            
    for sec in context.portfolio.positions:
        if sec not in context.buy:
            context.sell.append(sec)
           
def sell (context, data):
    for sec in context.sell:
        if data.can_trade(sec) and sec not in context.B:
            order_target_percent(sec, 0)
            context.S.append(sec)            
        
def buy (context, data):
    for sec in context.longs:
        if data.can_trade(sec) and sec not in context.portfolio.positions and sec not in context.S and (len(context.longs) > 0):
            order_target_percent(sec, context.L/(len(context.longs)))
            context.B.append(sec)
                      
def maximize (context, data):
    if context.Maximize == True:
        currentHold = len(context.portfolio.positions)
        for sec in context.portfolio.positions:
            order_target_percent(sec, .9/currentHold)
    record(leverage = context.account.leverage)
    
def handle_data (context, data):
   
    cash = cash = context.portfolio.cash
    post = context.portfolio.positions_value
    gain_loss = (cash+post) - 1000
   
    for sec in context.portfolio.positions:
        if sec not in context.B:
            if context.portfolio.positions[sec].cost_basis * 0.935 > context.portfolio.positions[sec].last_sale_price:
                order_target_percent(sec, 0)
    for s in context.portfolio.positions:
        if context.portfolio.positions[s].amount < 0:
            order_target_percent(s, 0)
            
    record(gain_loss = gain_loss, portval = post)
    
There was a runtime error.

Tyler: yes, I use the algorithm attached to this post with robinhood gold currently. This is one of two algorithms that control the same account.
Robinhood gold is set to 2000 and stays that way the whole way through.

Eric: What you changed is this: The algorithms looks to see if the price has changed in a certain way recently. your changed extends the idea of ignoring the past 6 days which has been shown to yield higher returns. I am running a 14 year backtest on this change right now. Will post results when they are in.

Clone Algorithm
422
Loading...
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
import numpy as np
import pandas as pd
from quantopian.pipeline import Pipeline
from quantopian.pipeline import CustomFactor
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import SimpleMovingAverage, AverageDollarVolume
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.filters import Q500US

def initialize(context):
#============================================================================================   
#============================================================================================    
    context.Gold = 2000.00
#============================================================================================      
#============================================================================================        
    set_long_only()
    set_benchmark(sid(8554))
    #orignially these were CLOSE: hours = 5
    schedule_function(ANALYZE,date_rules.every_day(), time_rules.market_open(hours = 2, minutes = 30))
    schedule_function(sell,date_rules.every_day(), time_rules.market_open(hours = 2, minutes = 30))
    schedule_function(buy,date_rules.every_day(), time_rules.market_open(hours = 2, minutes = 30))
    schedule_function(Local_Maximize,date_rules.every_day(), time_rules.market_open(hours = 2, minutes = 35))
    schedule_function(GLOBAL_Maximize,date_rules.every_day(), time_rules.market_open(hours = 2, minutes = 40))
    schedule_function(day_end,date_rules.every_day(), time_rules.market_close())
    set_slippage(slippage.FixedSlippage(spread=0.0))
    set_commission(commission.PerShare(cost=0, min_trade_cost=0))
    context.nq=5
    context.nq_vol=3
    my_pipe = make_pipeline()
    attach_pipeline(my_pipe, 'my_pipeline')
    context.max_leverage = [0]
    context.ANV = []
    context.buy = []
    context.sell = []
    context.ETN_buy = []
    context.AmountHeldData = []
    context.B = []
    context.S = []
    context.DayCounter = 0.0
    context.L = 1.0
    context.Maximize = True
    
class Volatility(CustomFactor):  
    inputs = [USEquityPricing.close]
    window_length=132
    
    def compute(self, today, assets, out, close):

        daily_returns = np.log(close[1:-6]) - np.log(close[0:-7])
        out[:] = daily_returns.std(axis = 0)           

class Liquidity(CustomFactor):   
    inputs = [USEquityPricing.volume, morningstar.valuation.shares_outstanding] 
    window_length = 1
    
    def compute(self, today, assets, out, volume, shares):       
        out[:] = volume[-1]/shares[-1]        
        
class Sector(CustomFactor):
    inputs=[morningstar.asset_classification.morningstar_sector_code]
    window_length=1
    
    def compute(self, today, assets, out, sector):
        out[:] = sector[-1]   
        
        
def make_pipeline():
    sector = morningstar.asset_classification.morningstar_sector_code.latest
    profitable = morningstar.valuation_ratios.ev_to_ebitda.latest > 0 
    volume = USEquityPricing.volume
    pricing = USEquityPricing.close.latest    
    universe = ( Q500US()&(pricing>0)&(volume>1000000)&profitable&~sector.eq(103)&~sector.eq(104) )
    return Pipeline(screen=universe)

def before_trading_start(context, data):
    context.output = pipeline_output('my_pipeline')
    context.buy = []
    context.sell = []
    context.ETN_buy = []
    context.B = []
    context.S = []
    positions = []
    context.longs = []
    for sec in context.portfolio.positions:
        positions.append(sec)
        
    if len(positions) >= 1:
        context.AmountHeldData.append(len(positions))
        
    #print('=============================================================================================================' + '\n' )
    
            
def ANALYZE(context, data):
    Universe500=context.output.index.tolist()
    prices = data.history(Universe500,'price',3,'1d')
    daily_rets=np.log(prices/prices.shift(1))
    rets=(prices.iloc[-2] - prices.iloc[0]) / prices.iloc[0]
    # If you don't want to skip the most recent return, however, use .iloc[-1] instead of .iloc[-2]:
    # rets=(prices.iloc[-1] - prices.iloc[0]) / prices.iloc[0]
    stdevs=daily_rets.std(axis=0)
    rets_df=pd.DataFrame(rets,columns=['five_day_ret'])
    stdevs_df=pd.DataFrame(stdevs,columns=['stdev_ret'])
    context.output=context.output.join(rets_df,how='outer')
    context.output=context.output.join(stdevs_df,how='outer')    
    context.output['ret_quantile']=pd.qcut(context.output['five_day_ret'],context.nq,labels=False)+1
    context.output['stdev_quantile']=pd.qcut(context.output['stdev_ret'],3,labels=False)+1
    context.longs=context.output[(context.output['ret_quantile']==1) & 
                                (context.output['stdev_quantile']<context.nq_vol)].index.tolist()
    context.shorts=context.output[(context.output['ret_quantile']==context.nq) & 
                                 (context.output['stdev_quantile']<context.nq_vol)].index.tolist()    
#============================================================================================
#REBALANCE
#============================================================================================
    Universe500=context.output.index.tolist()
    context.existing_longs=0
    context.existing_shorts=0
    #not in filtered universe and not a stock being controlled by the Volatility Algorithm  : sell 
    for security in context.portfolio.positions:
        if security not in Universe500 and security!=sid(23921) and security!=sid(39214) and security!=sid(40516) and security!=sid(38054) and security!=sid(21507) and security!=sid(21508) and security!=sid(38294) and security!=sid(39214):
            order_target_percent(security, 0)
        if security in Universe500:
            if data.can_trade(security):
                current_quantile=context.output['ret_quantile'].loc[security]
                if context.portfolio.positions[security].amount>0:
                    if (current_quantile==1) and (security not in context.longs):
                        context.existing_longs += 1
                    elif (current_quantile>1) and (security not in context.shorts):
                        order_target_percent(security, 0)
                elif context.portfolio.positions[security].amount<0:
                    if (current_quantile==context.nq) and (security not in context.shorts):
                        context.existing_shorts += 1
                    elif (current_quantile<context.nq) and (security not in context.longs):
                        order_target_percent(security, 0)
#============================================================================================
#ANALYZE
#============================================================================================
    spy = [sid(8554)]
    spxs = [sid(37083)]
    Velocity = 0
    #long_leverage = 0
    #short_leverage = 0
    for sec in spy:
        pri = data.history(spy, "price",200, "1d")
        pos_one = (pri[sec][-10:].mean())
        pos_two = (pri[sec][-165:].mean())
        
        if pos_one < pos_two:   
            context.LocalMaximize = False
            context.L = 0.5
            for security in context.longs:
                pri = data.history(context.longs, "price",200, "1d")
                #pos = 'pri[security]'
                pos_one = (pri[security][-1])
                pos_six = (pri[security][-2:].mean())
                #VELOCITY
                velocity_stop = (pos_one - pos_six)
                Velocity = velocity_stop
                if Velocity < 0:
                    context.longs.remove(security)
        else:
            context.LocalMaximize = True
            context.L = 1.0
            for security in context.longs:
                pri = data.history(context.longs, "price",200, "1d")
                #pos = 'pri[security]'
                pos_one = (pri[security][-1])
                pos_six = (pri[security][-2:].mean())
                #VELOCITY
                velocity_stop = (pos_one - pos_six)
                Velocity = velocity_stop
                if Velocity > 0:
                    context.longs.remove(security)
    for sec in spy:
        pri = data.history(spy, "price",200, "1d")
        pos_one = (pri[sec][-1])
        pos_six = (pri[sec][-45:].mean())
        Velocity = (pos_one - pos_six)
        
        if Velocity > -0.5:
            #long_leverage = 1.75
            pos_one = (pri[sec][-1])
            pos_six = (pri[sec][-2:].mean())
            #VELOCITY
            velocity_stop = (pos_one - pos_six)
            Velocity = velocity_stop
            if Velocity < -0.5:
                context.longs = []
            if Velocity < -1.0:
                context.longs = []
                for sec in spxs:
                    if data.can_trade(sec): 
                        if sec not in context.longs:
                            context.longs.append(sec)
            elif data.can_trade(sid(37083)):
                for sec in spxs:
                    context.sell.append(sec)
                
        else:
            pos_one = (pri[sec][-1])
            pos_six = (pri[sec][-2:].mean())
            Velocity = (pos_one - pos_six)
            if Velocity < -1.0:
                context.longs = []
                for sec in spxs:
                    if data.can_trade(sec) and sec not in context.longs:
                        context.longs.append(sec)
            else:
                for sec in spxs:
                    if data.can_trade(sec):
                        context.sell.append(sec)
    VolatilityUniverse = [ sid(39214),sid(38294),sid(21508),sid(21507),sid(38054),sid(40516),sid(23921),sid(39214)]        
    for sec in context.portfolio.positions:
        if sec not in VolatilityUniverse:
            if sec not in context.buy:
                context.sell.append(sec)
           
def sell (context, data):
    for sec in context.sell:
        if data.can_trade(sec):
            if sec not in context.B:
                order_target_percent(sec, 0)
                context.S.append(sec)            
        
def buy (context, data):
    for sec in context.longs:
        if data.can_trade(sec):
            if sec not in context.portfolio.positions:
                if sec not in context.S:
                    if(len(context.longs) > 0):
                        Portfolio_Value_With_Gold = context.portfolio.portfolio_value + context.Gold  
                        #Place an order to adjust a position to a target value | Total will be 40% of buying power.
                        order_target_value(sec, (0.40*Portfolio_Value_With_Gold)/len(context.longs) ) 
            
def GLOBAL_Maximize (context, data):
    inVol = []
    NOTinVol = []
    VolatilityUniverse = [ sid(39214),sid(38294),sid(21508),sid(21507),sid(38054),sid(40516),sid(23921),sid(39214)]
    for sec in context.portfolio.positions:
        if sec in VolatilityUniverse: 
            inVol.append(sec)
        else:
            NOTinVol.append(sec)
    for sec in context.portfolio.positions:
        if sec not in VolatilityUniverse and len(NOTinVol) > 0:
            Portfolio_Value_With_Gold = context.portfolio.portfolio_value + context.Gold  
            order_target_value(sec, 0.5*Portfolio_Value_With_Gold/len(NOTinVol) )
    for sec in context.portfolio.positions:
        if sec in VolatilityUniverse:
            Portfolio_Value_With_Gold = context.portfolio.portfolio_value + context.Gold  
            order_target_value(sec, 0.5*Portfolio_Value_With_Gold/len(inVol) )
        
def Local_Maximize (context, data):
    VolatilityUniverse = [ sid(39214),sid(38294),sid(21508),sid(21507),sid(38054),sid(40516),sid(23921),sid(39214)]
    for sec in context.portfolio.positions:
        if sec not in VolatilityUniverse:
            if sec not in context.B:
                if context.portfolio.positions[sec].cost_basis * 0.935 > context.portfolio.positions[sec].last_sale_price:
                    order_target_percent(sec, 0)
             
    for sec in context.portfolio.positions:
        if context.portfolio.positions[sec].amount < 0:
            order_target_percent(sec, 0)
            
def day_end (context, data):
    context.DayCounter += 1
    ReturnRate = ((context.portfolio.returns*100)/context.DayCounter)
    SecCount = 0
    for sec in context.portfolio.positions:
        SecCount += 1
    print('| END OF DAY SUMMARY |')
    print('Day:                            ' + str(context.DayCounter))
    print('Initial Portfolio Value:        $' + str(context.portfolio.starting_cash))
    print('Current Portfolio Value:        $' + str(context.portfolio.portfolio_value))
    print('Profit & Loss:                  $' + str(context.portfolio.pnl))
    print('Total Returns:                  ' + str(context.portfolio.returns * 100) + '%')
    print(' Daily Return:                  ' + str(ReturnRate) + '%')
    print('Leverage:                       ' + str(context.account.leverage * 100) + '%')
    print('Positions:                      ' + str(SecCount))
    print('Initial Margin Requirement:     ' + str(context.account.initial_margin_requirement))
    print('Maintenance Margin Requirement: ' + str(context.account.maintenance_margin_requirement))
 
def handle_data (context, data):
    Portfolio_Value_With_Gold = context.portfolio.portfolio_value + context.Gold
    
    record(Portfolio_Value_With_Gold_THOU = Portfolio_Value_With_Gold/1000.00)
    record(Positions_Value_THOU = context.portfolio.positions_value/1000.00)
    record(Net_Value_THOU = (Portfolio_Value_With_Gold - context.Gold)/1000.00)    
    record(Positions_TEN = float(len(context.portfolio.positions))/10.00)
    record(Leverage = context.account.leverage)
    
    
    
There was a runtime error.

so you would have to stop the algorithm once you made enough to get more margin and then change the # and start is back up again?

Tyler: yes. pretty much. I keep a notebook with all the algorithms that have run to on that account that i use to figure out the total returns.

Eric: This is why I always do the longest backtest possible. your changes show promise, but they need improvement.

Clone Algorithm
41
Loading...
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
import numpy as np
import pandas as pd
from quantopian.pipeline import Pipeline
from quantopian.pipeline import CustomFactor
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import SimpleMovingAverage, AverageDollarVolume
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.filters import Q500US

def initialize(context):
    set_long_only()
    
    set_benchmark(sid(8554))
    #orignially these were CLOSE: hours = 5
    schedule_function(ANALYZE,date_rules.every_day(), time_rules.market_open(hours = 2, minutes = 30))
    schedule_function(sell,date_rules.every_day(), time_rules.market_open(hours = 2, minutes = 31))
    schedule_function(buy,date_rules.every_day(), time_rules.market_open(hours = 2, minutes = 32))
    schedule_function(maximize,date_rules.every_day(), time_rules.market_open(hours = 2, minutes = 40))
    set_slippage(slippage.FixedSlippage(spread=0.0))
    set_commission(commission.PerShare(cost=0, min_trade_cost=0))
    context.nq=5
    context.nq_vol=3
    my_pipe = make_pipeline()
    attach_pipeline(my_pipe, 'my_pipeline')
    context.max_leverage = [0]
    context.ANV = []
    context.buy = []
    context.sell = []
    context.ETN_buy = []
    context.AmountHeldData = []
    context.B = []
    context.S = []
    context.DayCounter = 0.0
    context.L = 1.0
    context.Maximize = True
    
class Volatility(CustomFactor):  
    inputs = [USEquityPricing.close]
    window_length=132
    
    def compute(self, today, assets, out, close):

        daily_returns = np.log(close[1:-6]) - np.log(close[0:-7])
        out[:] = daily_returns.std(axis = 0)           

class Liquidity(CustomFactor):   
    inputs = [USEquityPricing.volume, morningstar.valuation.shares_outstanding] 
    window_length = 1
    
    def compute(self, today, assets, out, volume, shares):       
        out[:] = volume[-1]/shares[-1]        
        
class Sector(CustomFactor):
    inputs=[morningstar.asset_classification.morningstar_sector_code]
    window_length=1
    
    def compute(self, today, assets, out, sector):
        out[:] = sector[-1]   
        
        
def make_pipeline():
    profitable = morningstar.valuation_ratios.ev_to_ebitda.latest > 0 
    volume = USEquityPricing.volume
    pricing = USEquityPricing.close.latest    
    universe = ( Q500US()&(pricing>0)&(volume>1000000)&profitable )
    return Pipeline(screen=universe)

def before_trading_start(context, data):
    context.output = pipeline_output('my_pipeline')
    context.buy = []
    context.sell = []
    context.ETN_buy = []
    context.B = []
    context.S = []
    positions = []
    context.longs = []
    for sec in context.portfolio.positions:
        positions.append(sec)
    if len(positions) >= 1:
        context.AmountHeldData.append(len(positions))
        
    #print('=============================================================================================================' + '\n' )
    
            
def ANALYZE(context, data):
    Universe500=context.output.index.tolist()
    prices = data.history(Universe500,'price',6,'1d')
    daily_rets=np.log(prices/prices.shift(1))
    rets=(prices.iloc[-2] - prices.iloc[0]) / prices.iloc[0]
    # If you don't want to skip the most recent return, however, use .iloc[-1] instead of .iloc[-2]:
    # rets=(prices.iloc[-1] - prices.iloc[0]) / prices.iloc[0]
    stdevs=daily_rets.std(axis=0)
    rets_df=pd.DataFrame(rets,columns=['five_day_ret'])
    stdevs_df=pd.DataFrame(stdevs,columns=['stdev_ret'])
    context.output=context.output.join(rets_df,how='outer')
    context.output=context.output.join(stdevs_df,how='outer')    
    context.output['ret_quantile']=pd.qcut(context.output['five_day_ret'],context.nq,labels=False)+1
    context.output['stdev_quantile']=pd.qcut(context.output['stdev_ret'],3,labels=False)+1
    context.longs=context.output[(context.output['ret_quantile']==1) & 
                                (context.output['stdev_quantile']<context.nq_vol)].index.tolist()
    context.shorts=context.output[(context.output['ret_quantile']==context.nq) & 
                                 (context.output['stdev_quantile']<context.nq_vol)].index.tolist()    
#============================================================================================
#REBALANCE
#============================================================================================
    Universe500=context.output.index.tolist()
    context.existing_longs=0
    context.existing_shorts=0
    cash = cash = context.portfolio.cash
    
    for security in context.portfolio.positions:
        if security not in Universe500 and data.can_trade(security): 
            order_target_percent(security, 0)
        else:
            if data.can_trade(security):
                current_quantile=context.output['ret_quantile'].loc[security]
                if context.portfolio.positions[security].amount>0:
                    if (current_quantile==1) and (security not in context.longs):
                        context.existing_longs += 1
                    elif (current_quantile>1) and (security not in context.shorts):
                        order_target_percent(security, 0)
                elif context.portfolio.positions[security].amount<0:
                    if (current_quantile==context.nq) and (security not in context.shorts):
                        context.existing_shorts += 1
                    elif (current_quantile<context.nq) and (security not in context.longs):
                        order_target_percent(security, 0)
                        
    record(cash=cash)
                             
#============================================================================================
#ANALYZE
#============================================================================================
    spy = [sid(8554)]
    spxs = [sid(37083)]
    Velocity = 0
    #long_leverage = 0
    #short_leverage = 0
    for sec in spy:
        #Av = 0
        pri = data.history(spy, "price",200, "1d")
        pos_one = (pri[sec][-3:].mean())
        pos_two = (pri[sec][-15:].mean())
        pos_three = (pri[sec][-165:].mean())
        
        if pos_one < pos_two < pos_three:   
            context.Maximize = False
            context.L = 0.5
            for security in context.longs:
                pri = data.history(context.longs, "price",200, "1d")
                #pos = 'pri[security]'
                pos_one = (pri[security][-1])
                pos_six = (pri[security][-2:].mean())
                #VELOCITY
                velocity_stop = (pos_one - pos_six)
                Velocity = velocity_stop
                if Velocity < 0:
                    context.longs.remove(security)
        else:
            context.Maximize = True
            context.L = 1.0
            for security in context.longs:
                pri = data.history(context.longs, "price",200, "1d")
                #pos = 'pri[security]'
                pos_one = (pri[security][-1])
                pos_six = (pri[security][-2:].mean())
                #VELOCITY
                velocity_stop = (pos_one - pos_six)
                Velocity = velocity_stop
                if Velocity > 0:
                    context.longs.remove(security)
    for sec in spy:
        pri = data.history(spy, "price",200, "1d")
        #start modifying dates here
        #changed from -1 to -6
        pos_one = (pri[sec][-6])
        pos_six = (pri[sec][-45:].mean())
        Velocity = (pos_one - pos_six)
        
        if Velocity > -0.5:
            #long_leverage = 1.75
            #replace 1,2 with 6,7
            pos_one = (pri[sec][-6])
            pos_six = (pri[sec][-7:].mean())
            #VELOCITY
            velocity_stop = (pos_one - pos_six)
            Velocity = velocity_stop
            if Velocity < -0.5:
                context.longs = []
            if Velocity < -1.0:
                context.longs = []
                for sec in spxs:
                    if data.can_trade(sec) and sec not in context.longs:
                        context.longs.append(sec)
            elif data.can_trade(sid(37083)):
                for sec in spxs:
                    context.sell.append(sec)
                
        else:
            #replace 1,2 with 6,7
            pos_one = (pri[sec][-6])
            pos_six = (pri[sec][-7:].mean())
            Velocity = (pos_one - pos_six)
            if Velocity < -1.0:
                context.longs = []
                for sec in spxs:
                    if data.can_trade(sec) and sec not in context.longs:
                        context.longs.append(sec)
            else:
                for sec in spxs:
                    if data.can_trade(sec):
                        context.sell.append(sec)
            
    for sec in context.portfolio.positions:
        if sec not in context.buy:
            context.sell.append(sec)
           
def sell (context, data):
    for sec in context.sell:
        if data.can_trade(sec) and sec not in context.B:
            order_target_percent(sec, 0)
            context.S.append(sec)            
        
def buy (context, data):
    for sec in context.longs:
        if data.can_trade(sec) and sec not in context.portfolio.positions and sec not in context.S and (len(context.longs) > 0):
            order_target_percent(sec, context.L/(len(context.longs)))
            context.B.append(sec)
                      
def maximize (context, data):
    if context.Maximize == True:
        currentHold = len(context.portfolio.positions)
        for sec in context.portfolio.positions:
            order_target_percent(sec, .9/currentHold)
    record(leverage = context.account.leverage)
    
def handle_data (context, data):
   
    cash = cash = context.portfolio.cash
    post = context.portfolio.positions_value
    gain_loss = (cash+post) - 1000
   
    for sec in context.portfolio.positions:
        if sec not in context.B:
            if context.portfolio.positions[sec].cost_basis * 0.935 > context.portfolio.positions[sec].last_sale_price:
                order_target_percent(sec, 0)
    for s in context.portfolio.positions:
        if context.portfolio.positions[s].amount < 0:
            order_target_percent(s, 0)
            
    record(gain_loss = gain_loss, portval = post)
    
There was a runtime error.

Is there any reason why this has been flat since February?

It has been on a tear since 2003, but for some reason this year has been mostly flat.

There are weird things happening in my paper trade - like shares disappearing. It will buy 20 shares of X stock, but only sell 15 - but the 5 remaining are not showing in the current holding. Anyone else seeing this with paper trading/live trading?

Can someone please re-post this algo with slippage enabled? Set it at either $0.01/share fixed slippage or the default volume share slippage model. Mine keeps crashing for some reasons... I also suspect that this strategy is not realistic because slippage and commissions are not baked into any of the shared algos above. Hopefully I am wrong.

2017-05-24 13:00 _pvr:287 INFO PvR 0.0285 %/day   cagr 0.613   Portfolio value 9694961   PnL 9684961  
2017-05-24 13:00 _pvr:288 INFO   Profited 9684961 on 9368814 activated/transacted for PvR of 103.4%  
2017-05-24 13:00 _pvr:289 INFO   QRet 96849.61 PvR 103.37 CshLw -7892046 MxLv 3.58 MxRisk 9368814 MxShrt -9368814  
2017-05-24 13:00 pvr:364 INFO 2003-01-02 to 2017-05-24  $10000  2017-08-15 21:55 US/Pacific  
Runtime 1 hr 43.9 min  

I only looked at the first algo, is there a version here that avoids 9.3 million short and 7.8 million margin? Returns on the amount invested are just 103%. Also consider track_orders.

@Kory - Slippage does need to be added, but not commissions as this is targeted to Robinhood - if you are taking margin you will need to manually factor the monthly cost

@Blue - I'll see if I can code in the track_orders. Also, Nicholas Forneris' algo on 6/20/2017 should be non margin

Here is a log of the original algorithm. Can you help review the log?:

It looks like it is selling shares it doesn't have - IE. Shorting.

2017-07-03 09:31 pvr:376 INFO 2017-07-03 to 2017-08-14  10000  minute  
2017-07-03 12:03 pvr:471 INFO 153 MaxLv 0.84 QRet 0.0 PvR 0.0 CshLw 1597 Shrt 0  
2017-07-03 12:11 pvr:471 INFO 161 MaxLv 1.66 QRet -0.1 PvR -0.0 CshLw -6570 Shrt 0  
2017-07-05 12:11 _trac:271 INFO  161   Buy 12 EIX (3) at 76.70                        cash -5845  5393  
2017-07-05 12:13 _trac:271 INFO  163      Bot 12 EIX (15) at 76.69                    cash -6765  5393  
2017-07-05 12:13 pvr:471 INFO 163 MaxLv 1.68 QRet -0.3 PvR -0.2 CshLw -6765 Shrt 0  
2017-07-06 12:01 _trac:271 INFO  151   Sell -8 CLX (8) at 133.62                        e580  
2017-07-06 12:02 _trac:271 INFO  152      Sold -8 CLX (-8) at 133.65                    e580  
2017-07-07 12:03 _trac:271 INFO  153   Buy 5 SJM _ at 115.47                            e743  
2017-07-07 12:04 _trac:271 INFO  154      Bot 5 SJM (5) at 115.45                       e743  
2017-07-07 12:11 pvr:471 INFO 161 MaxLv 1.72 QRet -0.6 PvR -0.4 CshLw -7132 Shrt 0  
2017-07-10 12:02 _trac:271 INFO  152   Sell -16 VTR (16) at 67.49                       bb64  
2017-07-10 12:02 _trac:271 INFO  152   Sell -25 PEG (25) at 42.10                       219a  
2017-07-10 12:03 _trac:271 INFO  153      Sold -16 VTR _ at 67.49                       bb64  
2017-07-10 12:03 _trac:271 INFO  153      Sold -25 PEG _ at 42.09                       219a  
2017-07-11 12:01 _trac:271 INFO  151   Sell -12 DPS (12) at 89.04                     cash -2744  2d2b  
2017-07-11 12:02 _trac:271 INFO  152      Sold -12 DPS (-12) at 89.06                   2d2b  
2017-07-12 12:01 _trac:271 INFO  151   Sell -7 SJM (7) at 115.62                      cash -4729  4f2e  
2017-07-12 12:02 _trac:271 INFO  152      Sold -7 SJM (-7) at 115.58                    4f2e  
2017-07-12 12:11 _trac:271 INFO  161   Buy 7 OMC (5) at 80.98                         cash -5719  4cbc  
2017-07-12 12:11 _trac:271 INFO  161   Buy 5 HSY (4) at 104.69                        cash -5719  e292  
2017-07-12 12:12 _trac:271 INFO  162      Bot 7 OMC (12) at 80.96                     cash -6809  4cbc  
2017-07-12 12:12 _trac:271 INFO  162      Bot 5 HSY (9) at 104.72                     cash -6809  e292  
2017-07-13 12:02 _trac:271 INFO  152   Sell -9 HSY (9) at 104.81                        19b1  
2017-07-13 12:03 _trac:271 INFO  153      Sold -9 HSY _ at 104.80                       19b1  
2017-07-13 12:03 _trac:271 INFO  153   Buy 2 CLX _ at 131.48                            5258  
2017-07-13 12:03 _trac:271 INFO  153   Buy 1 AVB _ at 186.53                            3943  
2017-07-13 12:03 _trac:271 INFO  153   Buy 2 MON _ at 116.74                            5b97  
2017-07-13 12:04 _trac:271 INFO  154      Bot 2 CLX (2) at 131.49                       5258  
2017-07-13 12:04 _trac:271 INFO  154      Bot 1 AVB (1) at 186.54                       3943  
2017-07-13 12:04 _trac:271 INFO  154      Bot 2 MON (2) at 116.72                       5b97  
2017-07-13 12:11 _trac:271 INFO  161   Buy 3 CB (1) at 145.22                         cash -6014  252f  
2017-07-13 12:12 _trac:271 INFO  162      Bot 3 CB (4) at 145.24                      cash -6449  252f  
2017-07-14 12:02 _trac:271 INFO  152   Sell -17 HRL (17) at 32.86                       d9b7  
2017-07-14 12:02 _trac:271 INFO  152   Sell -4 CB (4) at 144.80                         f63a  
2017-07-14 12:03 _trac:271 INFO  153      Sold -17 HRL _ at 32.85                       d9b7  
2017-07-14 12:03 _trac:271 INFO  153      Sold -4 CB _ at 144.77                        f63a  
2017-07-14 12:03 _trac:271 INFO  153   Buy 11 PHM _ at 24.39                            f6d2  
2017-07-14 12:03 _trac:271 INFO  153   Buy 2 CME _ at 120.80                            73a8  
2017-07-14 12:04 _trac:271 INFO  154      Bot 11 PHM (11) at 24.39                      f6d2  
2017-07-14 12:04 _trac:271 INFO  154      Bot 2 CME (2) at 120.81                       73a8  
2017-07-17 12:03 _trac:271 INFO  153   Buy 4 LEN _ at 53.81                             c53b  
2017-07-17 12:04 _trac:271 INFO  154      Bot 4 LEN (4) at 53.79                        c53b  
2017-07-17 12:11 _trac:271 INFO  161   Buy 4 WOOF (2) at 92.45                        cash -6054  cebe  
2017-07-17 12:12 _trac:271 INFO  162      Bot 4 WOOF (6) at 92.44                     cash -6424  cebe  
2017-07-18 12:02 _trac:271 INFO  152   Sell -8 VLO (8) at 67.55                         4efa  
2017-07-18 12:03 _trac:271 INFO  153      Sold -8 VLO _ at 67.61                        4efa  
2017-07-18 12:11 _trac:271 INFO  161   Buy 5 IR (2) at 92.36                          cash -6171  8a57  
2017-07-18 12:12 _trac:271 INFO  162      Bot 5 IR (7) at 92.41                       cash -6633  8a57  
2017-07-19 12:03 _trac:271 INFO  153   Buy 1 MLM _ at 223.33                            9095  
2017-07-19 12:03 _trac:271 INFO  153   Buy 1 HUM _ at 237.31                            2ea7  
2017-07-19 12:04 _trac:271 INFO  154      Bot 1 HUM (1) at 237.33                       2ea7  
2017-07-19 12:05 _trac:271 INFO  155      Bot 1 MLM (1) at 223.13                       9095  
2017-07-20 12:01 _trac:271 INFO  151   Sell -5 TWX (5) at 99.46                       cash -1504  0613  
2017-07-20 12:01 _trac:271 INFO  151   Sell -2 ROP (2) at 234.57                      cash -1504  4119  
2017-07-20 12:02 _trac:271 INFO  152      Sold -5 TWX (-5) at 99.46                     0613  
2017-07-20 12:02 _trac:271 INFO  152   Sell -6 ABC (6) at 91.80                         e8c1  
2017-07-20 12:02 _trac:271 INFO  152   Sell -6 ALK (6) at 89.55                         7529  
2017-07-20 12:02 _trac:271 INFO  152   Sell -2 ROP (2) at 234.57                        3360  
2017-07-20 12:03 _trac:271 INFO  153      Sold -6 ALK _ at 89.57                        7529  
2017-07-20 12:03 _trac:271 INFO  153      Sold -2 ROP (-2) at 234.59                    4119  
2017-07-20 12:03 _trac:271 INFO  153      Sold -2 ROP (-2) at 234.59                    3360  
2017-07-20 12:03 _trac:271 INFO  153      Sold -6 ABC _ at 91.80                        e8c1  
2017-07-20 12:11 _trac:271 INFO  161   Buy 4 FRC (2) at 99.54                         cash -6047  cf48  
2017-07-20 12:13 _trac:271 INFO  163      Bot 4 FRC (6) at 99.56                      cash -6445  cf48  
2017-07-21 12:02 _trac:271 INFO  152   Sell -6 FRC (6) at 99.94                         d81c  
2017-07-21 12:04 _trac:271 INFO  154      Sold -6 FRC _ at 99.89                        d81c  
2017-07-21 12:11 _trac:271 INFO  161   Buy 2 FDX (1) at 211.39                        cash -6271  6221  
2017-07-21 12:13 _trac:271 INFO  163      Bot 2 FDX (3) at 211.43                     cash -6694  6221  
2017-07-25 12:03 _trac:271 INFO  153   Buy 1 SHW _ at 350.55                            752f  
2017-07-25 12:04 _trac:271 INFO  154      Bot 1 SHW (1) at 350.46                       752f  
2017-07-25 12:11 _trac:271 INFO  161   Buy 7 HCN (5) at 72.57                         cash -5460  a320  
2017-07-25 12:11 _trac:271 INFO  161   Buy 1 SHW (1) at 350.88                        cash -5460  a6ff  
2017-07-25 12:12 _trac:271 INFO  162      Bot 7 HCN (12) at 72.59                     cash -6318  a320  
2017-07-25 12:12 _trac:271 INFO  162      Bot 1 SHW (2) at 350.30                     cash -6318  a6ff  
2017-07-26 12:03 _trac:271 INFO  153   Buy 4 DLPH _ at 90.91                            aea7  
2017-07-26 12:04 _trac:271 INFO  154      Bot 4 DLPH (4) at 90.89                       aea7  
2017-07-26 12:11 _trac:271 INFO  161   Buy 11 VNO (5) at 78.02                        cash -6266  1bc1  
2017-07-26 12:12 _trac:271 INFO  162      Bot 11 VNO (16) at 78.04                    cash -7124  1bc1  
2017-07-27 12:11 _trac:271 INFO  161   Buy 5 CNC (4) at 82.27                         cash -6123  859f  
2017-07-27 12:12 _trac:271 INFO  162      Bot 5 CNC (9) at 82.24                      cash -6534  859f  
2017-07-28 12:11 _trac:271 INFO  161   Buy 5 UTX (2) at 118.80                        cash -5779  467e  
2017-07-28 12:11 _trac:271 INFO  161   Buy 5 KSU (3) at 102.80                        cash -5779  9b41  
2017-07-28 12:12 _trac:271 INFO  162      Bot 5 UTX (7) at 118.82                     cash -6373  467e  
2017-07-28 12:13 _trac:271 INFO  163      Bot 5 KSU (8) at 102.78                     cash -6887  9b41  
2017-07-31 12:02 _trac:271 INFO  152   Sell -5 MCK (5) at 161.88                        e09c  
2017-07-31 12:03 _trac:271 INFO  153      Sold -5 MCK _ at 162.02                       e09c  
2017-07-31 12:03 _trac:271 INFO  153   Buy 13 FNSR _ at 27.10                           cff5  
2017-07-31 12:03 _trac:271 INFO  153   Buy 4 EMN _ at 83.46                             30aa  
2017-07-31 12:03 _trac:271 INFO  153   Buy 2 VMC _ at 123.35                            8fab  
2017-07-31 12:04 _trac:271 INFO  154      Bot 13 FNSR (13) at 27.11                     cff5  
2017-07-31 12:04 _trac:271 INFO  154      Bot 2 VMC (2) at 123.34                       8fab  
2017-07-31 12:04 _trac:271 INFO  154      Bot 4 EMN (4) at 83.45                        30aa  
2017-07-31 12:11 _trac:271 INFO  161   Buy 7 OMC (4) at 78.54                         cash -5695  0072  
2017-07-31 12:11 _trac:271 INFO  161   Buy 3 TMO (2) at 175.78                        cash -5695  efc5  
2017-07-31 12:12 _trac:271 INFO  162      Bot 7 OMC (11) at 78.59                     cash -6772  0072  
2017-07-31 12:12 _trac:271 INFO  162      Bot 3 TMO (5) at 175.71                     cash -6772  efc5  
2017-08-01 12:11 _trac:271 INFO  161   Buy 7 JBHT (5) at 89.47                        cash -6410  31ee  
2017-08-01 12:12 _trac:271 INFO  162      Bot 7 JBHT (12) at 89.49                    cash -7037  31ee  
2017-08-02 12:11 _trac:271 INFO  161   Buy 3 PX (2) at 130.53                         cash -5948  04d5  
2017-08-02 12:11 _trac:271 INFO  161   Buy 5 ALK (3) at 85.16                         cash -5948  1c31  
2017-08-02 12:12 _trac:271 INFO  162      Bot 3 PX (5) at 130.55                      cash -6765  04d5  
2017-08-02 12:12 _trac:271 INFO  162      Bot 5 ALK (8) at 85.07                      cash -6765  1c31  
2017-08-03 12:01 _trac:271 INFO  151   Sell -5 PX (5) at 130.52                         d3ab  
2017-08-03 12:02 _trac:271 INFO  152      Sold -5 PX (-5) at 130.46                     d3ab  
2017-08-03 12:03 _trac:271 INFO  153   Buy 5 PX (-5) at 130.46                          4b64  
2017-08-03 12:04 _trac:271 INFO  154      Bot 5 PX (5) at 130.45                        4b64  
2017-08-03 12:11 _trac:271 INFO  161   Buy 9 QRVO (6) at 66.55                        cash -6209  64e1  
2017-08-03 12:12 _trac:271 INFO  162      Bot 9 QRVO (15) at 66.59                    cash -6808  64e1  
2017-08-04 12:11 _trac:271 INFO  161   Buy 9 LEA (6) at 144.86                        cash -5962  aa2f  
2017-08-04 12:12 _trac:271 INFO  162      Bot 9 LEA (15) at 144.87                    cash -7266  aa2f  
2017-08-04 12:12 pvr:471 INFO 162 MaxLv 1.72 QRet 3.0 PvR 1.7 CshLw -7266 Shrt 0  
2017-08-07 12:03 _trac:271 INFO  153   Buy 3 UHS _ at 107.72                            1527  
2017-08-07 12:05 _trac:271 INFO  155      Bot 3 UHS (3) at 107.79                       1527  
2017-08-08 12:02 _trac:271 INFO  152   Sell -8 UHS (8) at 108.22                        d8f0  
2017-08-08 12:03 _trac:271 INFO  153      Sold -8 UHS _ at 108.20                       d8f0  
2017-08-09 12:11 _trac:271 INFO  161   Buy 3 AYI (2) at 194.22                        cash -6286  2f12  
2017-08-09 12:12 _trac:271 INFO  162      Bot 3 AYI (5) at 194.36                     cash -6869  2f12  
2017-08-10 12:02 _trac:271 INFO  152   Sell -5 AYI (5) at 189.90                        9bd4  
2017-08-10 12:04 _trac:271 INFO  154      Sold -5 AYI _ at 189.87                       9bd4  
2017-08-10 12:11 pvr:471 INFO 161 MaxLv 1.75 QRet 0.8 PvR 0.5 CshLw -7558 Shrt 0  
2017-08-11 12:11 _trac:271 INFO  161   Buy 3 TIF (4) at 90.45                         cash -6374  6d1f  
2017-08-11 12:11 _trac:271 INFO  161   Buy 3 AAP (3) at 105.95                        cash -6374  3aa3  
2017-08-11 12:12 _trac:271 INFO  162      Bot 3 AAP (6) at 105.92                     cash -6963  3aa3  
2017-08-11 12:12 _trac:271 INFO  162      Bot 3 TIF (7) at 90.46                      cash -6963  6d1f  
2017-08-14 12:11 _trac:271 INFO  161   Buy 36 GRUB (12) at 54.37                      cash -5641  31fe  
2017-08-14 12:13 _trac:271 INFO  163      Bot 36 GRUB (48) at 54.34                   cash -7597  31fe  
2017-08-14 12:13 pvr:471 INFO 163 MaxLv 1.76 QRet 4.6 PvR 2.6 CshLw -7597 Shrt 0  
2017-08-14 16:00 _pvr_:447 INFO PvR 0.0730 %/day     2017-07-03 to 2017-08-14  10000  minute  
2017-08-14 16:00 _pvr_:450 INFO   Profited 386 on 17597 activated/transacted for PvR of 2.2%  
2017-08-14 16:00 _pvr_:453 INFO   QRet 3.86 PvR 2.19 CshLw -7597 MxLv 1.76 RskHi 17597 Shrts 0  
End of logs.  

@Tyler, you should always bake both slippage and commissions into your backtest. Commissions can be $0.005/share with $1 minimum per order (IB's structure) and slippage can be default or just a fixed $0.01/share. I know RH doesn't charge commissions but this will help stress test the Algo and its robustness. If $0.01/share changes your results that much then no way it will survive IRL. And seeing how this algo trades, I can almost guarantee you it will not work IRL due to slippage, especially since it trades individual stocks and Robinhood can have larger bid/ask spreads on some stocks

I added slippage of 0.01/share, but not commissions as this is meant for Robinhood - DD is 100% in IB due to commissions.

@Blue - thanks for the message. I updated my post.

The backtest also doesn't match what was happening paper trading either. In live paper trading it sold all positions and went long SPXS - whereas in the backtest it did not. I would say this strategy is not valid.

Shouldn't be in negative cash immediately so it must be missing some orders. Try this, remove any calls to it and use this scheduling instead:

def initialize(context, data):  
    [your things]

    for i in range(1, 391):  
        schedule_function(track_orders, date_rules.every_day(), time_rules.market_open(minutes=i))  

To explain a bit:
Sell -6 ABC (6) at 91.80 e8c1
Sold -6 ABC _ at 91.80 e8c1

Current price that minute, and current number of shares in parens. Underscore means 0, no position (just easier to spot in a crowd than a 0).
You're right, some of those are negatives (short).
First column is minute of the day, 151 thru 153 here.
At the end, last four is the order id's. Sometimes those hexidecimals are just digits and no letters of course. In Notepad++ I highlight those which highlights matching instances.

2017-07-20 12:01 _trac:271 INFO  151   Sell -2 ROP (2) at 234.57                      cash -1504  4119  
2017-07-20 12:02 _trac:271 INFO  152      Sold -5 TWX (-5) at 99.46                     0613  
2017-07-20 12:02 _trac:271 INFO  152   Sell -6 ABC (6) at 91.80                         e8c1  
2017-07-20 12:02 _trac:271 INFO  152   Sell -6 ALK (6) at 89.55                         7529  
2017-07-20 12:02 _trac:271 INFO  152   Sell -2 ROP (2) at 234.57                        3360  
2017-07-20 12:03 _trac:271 INFO  153      Sold -6 ALK _ at 89.57                        7529  
2017-07-20 12:03 _trac:271 INFO  153      Sold -2 ROP (-2) at 234.59                    4119  
2017-07-20 12:03 _trac:271 INFO  153      Sold -2 ROP (-2) at 234.59                    3360  
2017-07-20 12:03 _trac:271 INFO  153      Sold -6 ABC _ at 91.80                        e8c1  

You have pvr there too and it didn't pick up shorting, something amiss, try the latest, I just updated it and scheduling that now too, no more calls from handle_data. I expected a look more like this, the latest, showing MxShrt:

2009-07-06 11:10 _pvr:89 INFO PvR 0.2127 %/day   cagr 0.877   Portfolio value 1370135   PnL 370135  
2009-07-06 11:10 _pvr:90 INFO   Profited 370135 on 1381059 activated/transacted for PvR of 26.8%  
2009-07-06 11:10 _pvr:91 INFO   QRet 37.01 PvR 26.80 CshLw -15397 MxLv 1.07 MxRisk 1381059 MxShrt -1381059  

It is just c.portfolio.positions[sid].amount revealing those negatives so there's definitely unwanted shorting it'll help you resolve. It was too easy in setting up track_orders to miss a spot, not a problem anymore with the switch to schedule_function, which surely will also make the source of that margin obvious since no orders would be overlooked that way. Unless Optimize API is present where orders are filled immediately, it could miss something then.

This has done well out of sample, anyone still trading it live and can verify results? Need to work some beta exposure into it though with some short positions.

@Chris D

I just tried running a backtest on the original algo posted and it hits -99% DD out of the gate....

Newbie question whats np.log (logarithm) used to calculate / indicate?

The script uses np.log(prices/prices.shift(1)) in the analyze function

@Jacob, interesting script.

Only changed a few numbers (13 in all). No change to the code itself.

The program could be improved. But, my first objective was to see if there was something there.

Instead of starting with $2 or $10k, I went directly for the $10 mil scenario and also opted to increase the trading activity.

The chart does say, for its 14-year simulation interval: 4.88 B in profits. Some might find it enough to compensate for the higher turbulence. It is a strategy that could be added to a group of strategies having lower volatility, thereby, reducing the overall turbulence.

However, I think there is something wrong with the above script. I don't have the tools to figure it out, but somebody else might.

Note that some leverage was applied: 1.25. Gross leverage came in at: 1.20. The presented outcome generated a lot more than enough to cover the leveraging fees.

The above chart is impressive.

@Jacob, after looking at some of the results of the presented screen snapshot above. I came to the conclusion that the strategy at that level is simply unfeasible.

It might work in theory, as the simulation can attest, but in real-life, the trades would not be executable as portrayed. It is all fine as the program starts, but as time progresses, the traded volume will become enormous as can be viewed in the following charts:

Also, these high volume trades are executed in a single minute. It is as if the 2.5% of available volume rule did not apply which in this case would have been quite a limiting factor.

Nonetheless, I suspect there are other problems in this script. My main question is: why did this program allow those results?

Changed a couple of numbers. It added some 2 B to the end game. But, then again. If it is not feasible, does it really matter?

because the slippage is set at a fixed 0.0 - that is why the orders are being filled in 1 second.