A little while ago I came across two short-term trading strategies that backtest extremely well,
with nice stable equity-curves, even through 2008. Neither of the strategies are confined to a single asset.
Both strategies require a StockFetcher.com subscription (currently about $25 / quarter) to screen for the stocks to invest in. The nice thing is that you can set up e-mail alerts for the screens, so that you get daily e-mails after the market closes with the filtered stocks listed, to be bought at the open of the next day.
The first strategy I call "ROC Buy on Dips". It is based on a technical indicator called "Rate of Change" and it filters stocks that are in an upward trend, experiencing a short-term dip. For the backtest period from January 2008 to May 2013 the CAGR was +20.65% and Max DD (realized): -6.24%. The average time held per asset was 8 days. Here's the link to read more about the details and comments on the strategy. Here's the code to use in the "My Filters" section of the StockFetcher interface:
Fetcher[
S&P 500
ROC(7,1) crossed below -2
ROC(80,1) above 20
close above MA(200)
add column ROC(7,1)
sort on column 5 ascending
draw ROC(7,1) on plot ROC(80,1)
]
The exit parameter is "ROC(7,1) > 2", which can for example checked easily on StockCharts.
The first strategy I call "ROC Buy on Dips". It is based on a technical indicator called "Rate of Change" and it filters stocks that are in an upward trend, experiencing a short-term dip. For the backtest period from January 2008 to May 2013 the CAGR was +20.65% and Max DD (realized): -6.24%. The average time held per asset was 8 days. Here's the link to read more about the details and comments on the strategy. Here's the code to use in the "My Filters" section of the StockFetcher interface:
Fetcher[
S&P 500
ROC(7,1) crossed below -2
ROC(80,1) above 20
close above MA(200)
add column ROC(7,1)
sort on column 5 ascending
draw ROC(7,1) on plot ROC(80,1)
]
The exit parameter is "ROC(7,1) > 2", which can for example checked easily on StockCharts.
The second I call "Z-Scored Reversion to the Mean". Here's the link to read more about it. For the backtest period of 1999-2009 the CAGR was +25.92% and Max DD (realized) -12.18%. Average time held per asset was 5 days, and interestingly Percent in Market was only 46.18%, meaning over 50% of the time this strategy was in cash or "risk-off".
Fetcher[
S&P500
/*FIRST DETERMINE HISTORICAL RATIO OF S&P STOCK TO THE SPY OVER THE LAST 16 DAYS*/
SET{PRICERATIO, CLOSE / IND(^SPX,CLOSE)}
SET{RATIOMA16, CMA(PRICERATIO,16)}
SET{RATIOSTD16, CSTDDEV(PRICERATIO,16)}
SET{DIFF16, PRICERATIO - RATIOMA16}
SET{ZSCORE16, DIFF16 / RATIOSTD16}
SET{THRESHOLD16, RATIOSTD16 * 2}
/*NEXT, SET CRITERIA NECESSARY TO TRIGGER A PAIR TRADE*/
SET{UPPERBAND16, RATIOMA16 + THRESHOLD16}
SET{LOWERBAND16, RATIOMA16 - THRESHOLD16}
ZSCORE16 BELOW -2
WILLIAMS %R(16) BELOW -94
CLOSE BELOW LOWER BOLLINGER BAND(16,2)
CLOSE ABOVE MA(200)
DRAW LOWERBAND16 ON PLOT PRICERATIO
DRAW UPPERBAND16 ON PLOT PRICERATIO
DRAW BOLLINGER BANDS(16,2)
ADD COLUMN ZSCORE16 {Z-score}
ADD COLUMN WILLIAMS %R(16)
DRAW ZSCORE16 LINE AT -1
DRAW ZSCORE16 LINE AT -2
DRAW ZSCORE16 LINE AT 0
SORT ON COLUMN 5 ASCENDING
CHART-TIME IS 6 MONTHS
]
/*FIRST DETERMINE HISTORICAL RATIO OF S&P STOCK TO THE SPY OVER THE LAST 16 DAYS*/
SET{PRICERATIO, CLOSE / IND(^SPX,CLOSE)}
SET{RATIOMA16, CMA(PRICERATIO,16)}
SET{RATIOSTD16, CSTDDEV(PRICERATIO,16)}
SET{DIFF16, PRICERATIO - RATIOMA16}
SET{ZSCORE16, DIFF16 / RATIOSTD16}
SET{THRESHOLD16, RATIOSTD16 * 2}
/*NEXT, SET CRITERIA NECESSARY TO TRIGGER A PAIR TRADE*/
SET{UPPERBAND16, RATIOMA16 + THRESHOLD16}
SET{LOWERBAND16, RATIOMA16 - THRESHOLD16}
ZSCORE16 BELOW -2
WILLIAMS %R(16) BELOW -94
CLOSE BELOW LOWER BOLLINGER BAND(16,2)
CLOSE ABOVE MA(200)
DRAW LOWERBAND16 ON PLOT PRICERATIO
DRAW UPPERBAND16 ON PLOT PRICERATIO
DRAW BOLLINGER BANDS(16,2)
ADD COLUMN ZSCORE16 {Z-score}
ADD COLUMN WILLIAMS %R(16)
DRAW ZSCORE16 LINE AT -1
DRAW ZSCORE16 LINE AT -2
DRAW ZSCORE16 LINE AT 0
SORT ON COLUMN 5 ASCENDING
CHART-TIME IS 6 MONTHS
]
The exit parameters are "zscore16 > -1" or "days held > 20". To know when to exit, add the stocks you've bought to a watch list called "zscore_portfolio", and use this filter to show what the current zscore16 is for the assets:
Fetcher[
watchlist(zscore_portfolio)
SET{PRICERATIO, CLOSE / IND(^SPX,CLOSE)}
SET{RATIOMA16, CMA(PRICERATIO,16)}
SET{RATIOSTD16, CSTDDEV(PRICERATIO,16)}
SET{DIFF16, PRICERATIO - RATIOMA16}
SET{ZSCORE16, DIFF16 / RATIOSTD16}
SET{THRESHOLD16, RATIOSTD16 * 2}
zscore16 above -1
]
watchlist(zscore_portfolio)
SET{PRICERATIO, CLOSE / IND(^SPX,CLOSE)}
SET{RATIOMA16, CMA(PRICERATIO,16)}
SET{RATIOSTD16, CSTDDEV(PRICERATIO,16)}
SET{DIFF16, PRICERATIO - RATIOMA16}
SET{ZSCORE16, DIFF16 / RATIOSTD16}
SET{THRESHOLD16, RATIOSTD16 * 2}
zscore16 above -1
]
The downsides of these strategies are commissions; "ROC Buy on Dips" generates about 100 trades / year, "Z-Scored Reversion to the Mean" about 220 trades / year. Add roundtrip costs (buy and sell) and at a regular broker charging $18 / roundtrip the average costs would be around $1800 / year and $4000 / year. This kind of regular trading is where you really want a discount broker, for example Interactive Brokers, where roundtrip costs would be around $2 / trade.