Back to Community
mean reversion- intraday vector analysis for overnight gains

I wanted to find out if the intraday vector (direction of price change) in the last 30 minutes of trading could be indicative of overnight gains. There are four combinations of vectors (++,--,+-,-+) that designate whether to be long or short any given stock overnight. The vectors are derived from the direction of price change from market open to 35 minutes before close, and 35 minutes from close to 5 minutes to close. All positions are opened 5 minutes before close and are sold at market open the following day.

This is far from a solid stand alone strategy, but it could be a useful way get returns on any excess cash that hasn't been deployed prior to market close.

There are a few issues with it in its current state:

Common returns are exceptionally high. I'm guessing this is due to the fact that I'm only selecting stocks in top 99.75th percentile for average daily volume. Could this be attributed to "wisdom of the crowd" rather then being mean reversion?

I also found that it is only profitable when longing stocks. I have yet to run a back test with positive returns that both long and shorts stocks.

Lastly, I need to find a better way to equally weight the positions. Each position weight is determined by 1/ the number of stocks in the pipeline. That would work fine if it were taking positions on every stock in the pipeline but because isn't taking short positions, only a fraction of the capital is utilized when taking positions overnight. If it were able to be fully invested in the long positions, the returns could be much higher.

I'd greatly appreciate some feedback on this. Let me know what you guys think.

Clone Algorithm
139
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 the libraries we will use here.
import quantopian.algorithm as algo
import quantopian.optimize as opt
from quantopian.pipeline import Pipeline
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import Returns, SimpleMovingAverage, DailyReturns, AverageDollarVolume
from quantopian.pipeline.filters import QTradableStocksUS
from quantopian.pipeline.filters.morningstar import Q1500US, Q500US, Q3000US 
def initialize(context):
    #Buys five minutes before market close
    algo.schedule_function(
        rebalance,
        algo.date_rules.every_day(),
        algo.time_rules.market_open(hours=6, minutes=25))
    
    #Sells all positions at open to secure overnight gains
    schedule_function(sell_all, date_rules.every_day(),  
                      time_rules.market_open())
    
    algo.attach_pipeline(make_pipeline(context), 'mean_reversion_example')
def sell_all(context,data):
    order_optimal_portfolio(
    objective=opt.TargetWeights({sid(8554): 0.0}) ,
    constraints=[],)
 
def make_pipeline(context):    
    universe =QTradableStocksUS()
    #primary factor is by volume
    volume=AverageDollarVolume(window_length=30,mask=universe)  
    #returns=volume for labling purposes 
    recent_returns_zscore = volume.zscore()    
    #selects a handful of the most liquid stocks
    high_returns = recent_returns_zscore.percentile_between(99.75,100)
    #low_returns = recent_returns_zscore.percentile_between(0,.5)
    
    securities_to_trade = (high_returns)
    pipe = Pipeline(
        columns={
            'recent_returns_zscore': recent_returns_zscore
        },
        screen=securities_to_trade
    )
 
    return pipe
 
def before_trading_start(context, data):


    context.output = algo.pipeline_output('mean_reversion_example')  
    context.recent_returns_zscore = context.output['recent_returns_zscore']
 
 
def rebalance(context, data):
    #put stocks on a list to run analysis on
    stocks=context.recent_returns_zscore.index
    
    #need quantity of stocks in pipeline to equally weigh portfolio
    num=context.recent_returns_zscore.count()
    
    print(num)
    for stock in stocks:
        #gets intra day price data on stock
        price=data.history(stock, 'price', 385, '1m') 
        
        o=price[-1]#opening price        
        mid=price[30] #price an hour befor we trade
        cur=price[0] #current price 
        
        v1=(mid-o)/o #percent change from open to midday price
        v2=(cur-mid)/mid #percent change from midday to current price
        
        #characterizes each intraday price changes as a vector
        if v1 > 0:
            v1="+"
        else:
            v1="-"
        if v2 > 0:
            v2="+"
        else:
            v2="-"
        #determince if intra day price movement is congruent    
        if v1==v2:
            congruence="Y"
        else:
            congruence="N"
        #print(congruence)
        #mean reversion plays based on the four possible vector combos
        # ++|Short, +-|Long, --|Long, -+|Short
        if congruence== "Y" and v2=="+":
             play="Short"
        if congruence=="N" and v2=="+":
             play="Short"    
        if congruence=="Y" and v2=="-":
             play="Long"
        if congruence=="N" and v2=="-":
             play="Long"  
                
        open_orders = get_open_orders()
        #Longs the stock
        if play=="Long":
           if stock not in open_orders:
                order_target_percent(stock,1/num)#portfolio is equal weighted by dividing by number of stocks in pipeline
        #Shorts the stock        
        '''if play=="Short":
           if stock not in open_orders:
             order_target_percent(stock,-1/num)'''
There was a runtime error.
1 response

@Mike

It would be correct to change

        o=price[-1]#opening price  
        mid=price[30] #price an hour befor we trade  
        cur=price[0] #current price  

to

        o   = price[0]       # opening price  
        mid = price[-60]     # price an hour before we trade  
        cur = price[-1]      # current price  

It should completely change the picture.