Back to Community
Seminar: introduction to systematic investment strategies: market intraday momentum using spy as example

My investment hypothesis is based upon the paper “market intraday momentum” from Lei Gao, Yufeng Han, Sophia Zhengzi Li and Guofu Zhou (2017 version), which documented the intraday momentum pattern: the first half hour return on the market since the previous day’s market close predicts the last half-hour return; the predictability, both statistically and economically significant, is stronger on more volatile days, on higher volume days, on recession days, and on major macroeconomic news release days. The paper presented that the first half hour return and the second to last half hour return are independent and complementary in forecasting the last half-hour return.
However, from the regression model I did in the Quantopian notebook. The first half hour return is statistically insignificant. So I change my backtesting model’s investment hypothesis from “if the 1st and second to last return are both positive, then buy the stock 35 minutes before the market close and sell it 5 minutes before the market close; if the 1st and second to last return are both negative, then short sell the stock 35 minutes before the market close and buy it back 5 minutes before the market close.” to “if the second to last return is positive, then buy the stock 35 minutes before the market close and sell it 5 minutes before the market close; vice versa.” The result seems much better than the previous hypothesis.
The normal trading hours in the United States begin at 9:30 am and end at 4pm. I do the regression from 2002-1-2 to 2013-12-31 because the Quantopian can only start from 2002. The paper’s time span is from 1993-2-1 to 2013-12-31 because the TAQ data from WRDS is available only until December 2014 as of June 2017. The tradable SPY, the most actively traded ETF that tracks the S&P 500 is used for trading for simplicity. For the backtesting, I did it for two periods: from 2002.1.2 to 2013.12.31 and from 2013.12.31 to 2019.7.31.

Clone Algorithm
6
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
import quantopian.algorithm as algo
from quantopian.pipeline import Pipeline
from quantopian.pipeline.data.builtin import USEquityPricing
import quantopian.optimize as opt
from quantopian.pipeline.filters import QTradableStocksUS
from quantopian.pipeline.experimental import risk_loading_pipeline

import math
import numpy as np

def initialize(context):
    set_slippage(slippage.FixedSlippage(spread=0))
    set_commission(commission.PerTrade(cost=0))
    
    context.spy = sid(8554)  
    
 # Start function 5 mins before close, do calculations, send orders.
    algo.schedule_function(
        close,
        algo.date_rules.every_day(),
        algo.time_rules.market_close(minutes=5)
    )

 # Start function 35 mins before close, do calculations, send orders.
    algo.schedule_function(
        open,
        algo.date_rules.every_day(),
        algo.time_rules.market_close(minutes=35),
    )

def handle_data(context, data):
    """
    """
    pass

def open(context, data):
    second_to_last_30m_ret = get_30m_para(context, data)
    if second_to_last_30m_ret > 0:
        order_target_percent(context.spy, 1)
    elif second_to_last_30m_ret < 0:
        order_target_percent(context.spy, -1)
    else:
        pass

def close(context, data):
  order_target_percent(context.spy, 0)

def get_30m_para(context, data):
    prices = data.history(context.spy, 'price', 30, '1m')
    second_to_last_30m_ret = (prices[-2] - prices[-3]) / prices[-3]
    return second_to_last_30m_ret
There was a runtime error.