Back to Community
A reverse buy/sell strategy

I am working on a research paper, but I am quite bad at programming. Actually, I have no experience in it. What I need is the following.

-To buy a stock that's part of the S&P the day after its price fell for 10% or more, hold it for 21 days and then sell it.
-To sell a stock that's part of the S&P the day after its price rose for 10% or more and hold it for 21 days.

Each investment will be 10% of the portfolio. If there are 10 stocks in the portfolio and there is a stock that fell/rose for 10% or more, its ignored.

I'm looking forward for your code.

Thank you,

9 responses

Without some kind of stop-loss, that strategy will lose your shirt on tail events like Amazon going to the moon or Lehman Bros. going bankrupt.

That said, if you convince me that the programming component is not part of what you're supposed to learn from the paper and pay me 1 BTC upfront, I can write you that algorithm by next Sunday Aug 7.

It won't lose money. I actually have a list of all the drops/rises of the 500 S&P companies during 2014/2015. I'm going to analyse the reasons for these abnormal returns as-well as their impact on the future returns. Anyway, I'm going to learn and I'll code this on my own.

Kind regards,

Kostadin, that's the spirit--code it yourself. if you get stuck, feel free to post, as long you show real effort, someone will help you.

I don't mind helping for free, as long as I get credited in the paper. I can see some promise in this strategy, and would be happy to help! :)

Kostadin, I can provide some hints for your projects, but not code:

  1. You need to study ALL drops, not just those which happen first, to have conclusive results
  2. You need to account for the PEAD anomaly, else if the move is earnings related, you will most likely lose money due to momentum in the first 20 days after an earnings surprise
  3. You need to tweak the 2 inputs: 10% and 21 days, and report results for other combinations of the two, not just this one
  4. You need to define "abnormal" and in that sense you need to study what was the return for the SPY on the same day....if SPY went up by 3% and your stock went up by 11%, then that stock's abnormal return is 8% not 11%.
  5. You MUST expand your time frame if you are writing an academic paper, since 2 years is going to be unacceptable to your professors - if it is, then you need to look for better professors.

Hope this helps,

The S&P companies had over 250 drops and rises during 2014 and 2015. Now, the goal of my academic paper is not only to test this strategy as many researchers did in the past (using similar formulas and different definition of "abnormal return" but different time periods), but to see the correlation between the reasons for the stock/rise and its performance in the next 21-days. Now, sadly, the only way to find the reasons is to google each stock drop or rise one by one. But, in reality, I am not going to invest in ALL of these as I am not sure when and how many of these events will happen. This strategy will help me test investing in 10 stocks at a time, for different periods and give me answer whether this is a good idea or not. It can also be tested whether there is a reversal or momentum strategy. Even if I am not beating the market, it is still a conclusion.

However, my academic paper, as I said before, will focus on the reasons and not only on the results. Sadly, that's something that nobody researched before.

Kind regards,

OK you seem set in your ways and you disregard the feedback, so...good luck to you.

It won't lose money. I actually have a list of all the drops/rises of the 500 S&P companies during 2014/2015. I'm going to analyse the reasons for these abnormal returns as-well as their impact on the future returns. Anyway, I'm going to learn and I'll code this on my own.

Here are your abnormal returns since 2002.

I'm not sure if this was the result you were looking for though...

Clone Algorithm
Backtest from to with initial capital
Total Returns
Max Drawdown
Benchmark Returns
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
from scipy import stats
from scipy.optimize import minimize
import pandas as pd
import talib
import time
import math
import random as rand

from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline
from import USEquityPricing
from quantopian.pipeline.factors import SimpleMovingAverage, Returns, EWMSTD
import as morningstar
from quantopian.pipeline import CustomFactor
from quantopian.pipeline.factors import AverageDollarVolume

from quantopian.pipeline.factors.eventvestor import (

# The initialize function is the place to set your tradable universe and define any parameters. 
def initialize(context):
    context.leverage = 1.
    context.trade_time = {}
    context.weights = pd.Series()

    pipe = Pipeline()
    attach_pipeline(pipe, 'pipe')  
    mkt_cap = morningstar.valuation.market_cap
def before_trading_start(context, data):                                           
    begin_time = time.time()    
    context.out = pipeline_output('pipe')
    context.eqs = context.out.index
def update_chart(context,data):
    record(leverage = context.account.leverage)

    longs = shorts = 0
    long_lever = 0
    short_lever = 0
    for position in context.portfolio.positions.itervalues():        
        if position.amount > 0:
            longs += 1
            long_lever += position.amount*data.current(position.sid, 'price')
        if position.amount < 0:
            shorts += 1
            short_lever += -position.amount*data.current(position.sid, 'price')
    #record(long_count=longs, short_count=shorts)
    long_lever /= context.portfolio.portfolio_value
    short_lever /= context.portfolio.portfolio_value
    record(long_lever=long_lever, short_lever=short_lever)
def rebalance(context, data):

    hist_eqs = np.unique(np.concatenate([context.eqs, context.portfolio.positions.keys()]))
    o = data.history(hist_eqs,'open',5,'1d')
    c = data.history(hist_eqs,'close',5,'1d')
    change = (c-o)/o
    weights = pd.Series(0., index=context.eqs)
    for eq in context.trade_time.keys():
        if (eq not in context.portfolio.positions or
            context.portfolio.positions[eq].amount == 0):
            del context.trade_time[eq]
        context.trade_time[eq] += 1            
        if context.trade_time[eq] >= 21:
            if not data.can_trade(eq):
                continue # Not tradeable for some reason
            log.debug("Close %s" % (eq))
            order_target(eq, 0)
    for eq in context.eqs:
        if eq in context.trade_time.keys():
        if len(context.trade_time) >= 10:
        if not data.can_trade(eq):
        if change[eq].iloc[-2] >= 0.1:
            log.debug("Short %s" % (eq))
            weights[eq] = -0.1
            context.trade_time[eq] = 0.
            order_target_percent(eq, weights[eq])
        if change[eq].iloc[-2] <= -0.1:
            log.debug("Long %s" % (eq))
            weights[eq] = 0.1
            context.trade_time[eq] = 0.
            order_target_percent(eq, weights[eq])
There was a runtime error.

The average return of all the stocks that rose for 10% or more during 2014 and 2015 in the next 21-trading days on average was -2%.

Now, as I mentioned above, I am not good at coding, but the logic says it is not possible to lose money by shorting these.

I'll take a look at your coding and try to understand what it does.

Thank you,