StockFetcher Forums · Filter Exchange · HOW TO DESIGN A SYSTEM (NOT JUST A FILTER)<< 1 2 3 4 5 ... 43 >>Post Follow-up
Kevin_in_GA
4,599 posts
msg #101013
Ignore Kevin_in_GA
6/2/2011 10:25:56 PM

Well, I haven’t posted any new filters in a while, and it got me thinking about exactly how a filter (in essence, a trading system) should be developed. My personal feeling is that simply designing an entry filter falls far short of the goal. The entry assumes all of the risk – the exit gets all of the reward. Without thinking holistically, all of the effort that you put into a filter is wasted.

So here is something that I did over the Memorial Day weekend. I’ll explain my thinking as we go forward.

First, I believe that a good trading system is inherently understandable - that is, you can look at the rationale for stock selection and understand why it is supposed to work. How many people here use exotic indicators that they really don’t understand? Even the pedestrian ones like the MACD are not really clear as to why they might work – who really understands why the MACD is a good signal? (if it actually is, which I might debate endlessly with some folks here ...)

Ones that pass the test for me are usually based on simple things that have strong statistical underpinnings. I have always looked at Bollinger Bands as a good example of statistics used wisely. Stocks that close more than 2 standard deviations away from their historical mean usually revert back to that mean. I also think that most stocks tend to move in sync with the sector or index of which they are part, and when that usual correlation is disturbed, the stock will also revert back to its normal relationship with the index.

Working from that basic premise, one should be able to develop trading systems based on perturbations from the equilibrium between a stock and its index (e.g., AAPL and the Nasdaq, or WMT and the ^SPX). These short term deviations can be effectively traded long or short using the ratio of a stock and its index as the price that one follows.

I started by simply writing some code that took the ratio of each of the component stocks of the S&P 500, and then determined the historical relationship for the pair and how far from that mean the current close was.

/*FIRST DETERMINE HISTORICAL RATIO OF STOCK TO THE ^SPX*/
SET{PRICERATIO, CLOSE / IND(^SPX,CLOSE)}
SET{RATIOMA, CMA(PRICERATIO,100)}
SET{RATIOSTD100, CSTDDEV(PRICERATIO,100)}
SET{DIFF100, PRICERATIO - RATIOMA}
SET{ZSCORE100, DIFF100 / RATIOSTD100}
SET{THRESHOLD, RATIOSTD100 * 2}

I started by simply picking 100 days as the length, but I knew that other time frames would likely be more profitable. This piece of SF code tells me the number of standard deviations from the 100 day mean for the pair (stock / ^SPX). This is a simple way to get a Bollinger Band for the ratio of two stocks.

Statistics says that only about 5% of the time should any stock be more than 2 SD from its mean, and that this is usually not sustained for long (think of these bands as elastics that want to pull the stock back to its mean – the farther out they are the harder they try to pull back).

So far so good, but I need to determine when an entry is called for, and when to exit. So I need to look at different combinations of moving averages, entry point by Z-score, and exit criteria (should also be by Z-score).

Using StrataSearch, I programmed this in and looked at several hundred combinations for the period 12/31/1999 through 12/31/2009. All S&P500 stocks were included. The result was a profitable set of times around 10-30 days, centered between 15 and 20. The typical number of days in a trade was 5-10, so I added the requirement that all trades are ended after 20 days to weed out losers.

The best times for entry typically were when the ratio crossed beyond 2 SD, then reverted back to close inside of 1 SD. I had thought that it would be a larger move (2 back to the mean, for example) but those larger moves were fewer and the percent win rates were less.

So now the code looked like this:

/*FIRST DETERMINE HISTORICAL RATIO OF SECTOR ETF TO THE SPY*/
SET{PRICERATIO, CLOSE / IND(SPY,CLOSE)}
SET{RATIOMA, CMA(PRICERATIO,20)}
SET{RATIOSTD20, CSTDDEV(PRICERATIO,20)}
SET{DIFF20, PRICERATIO - RATIOMA}
SET{ZSCORE20, DIFF20 / RATIOSTD20}

ENTRY: Z-SCORE BELOW -2
EXIT: Z-SCORE ABOVE -1 OR DAYS HELD >20

This still returned too many stocks, and during market corrections the system took some big hits. So I simply added a criteria that included “close above MA(XX)” for each stock, where XX was 50, 100, 150 or 200 days. This hopefully keeps you out of taking long positions on stocks that are tanking (keeps you “buying the dips”).

This definitely helped, and the system dramatically beat out the ^SPX, but the equity curves were still choppy and the system called for a lot of trades.

I also figured that the ratio could be out of whack but the individual stock should also look like it is oversold as well. So I looked at different settings of the Williams %R (between -70 and -100) and also looked for stocks that closed below their individual Bollinger Bands. I could have used the RSI, or MACD, or any other indicator. I chose the Williams %R because I have seen a good correlation between it and a stock being oversold in the past (and it was easy to code).

So in a single massive optimization, I evaluated all possible combinations of timeframe, Z-score entry and exit, William’s %R and close relative to the Stock’s Bollinger bands. Days were all set to the same (for any daily input, varying from 10 to 30). In the end, the best system by backtesting was as follows:


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
]



EXIT: Z-SCORE ABOVE -1 OR DAYS HELD >20


I’ll let the equity curve and stats speak for themselves:


Photobucket



Yes, that little white line at the bottom is the performance of the ^SPX over this 10 year period!

Photobucket







A 900% return on an all long strategy during one of the most turbulent decades in recent history, including not one but two massive recessions that wiped out many people’s lifetime savings.

About 4 trades a week on average, with a CAGR of almost 26% (compared to the ^SPX at -2.74%). You just can't argue with those kind of numbers.

What I like most about this strategy is the Sharpe ratio - StrataSearch uses the monthly ratio, so one must multiply by the square root of 12 (3.46) to annualize it. The ratio is just over 1.7, which is exceptionally high for most trading systems, especially during that period.

Also note that the portfolio size is only 10 trades at any time, and historically your money was only in the market ~46% of the time. The rest sat risk-free in cash.

Why post this? because I think that people can not only take the filter and make money with it, but hopefully learn a little about the types of analysis and thinking that goes into design and validation of a good trading system.

Enjoy!

Kevin

03bsbme
20 posts
msg #101015
Ignore 03bsbme
6/2/2011 11:52:52 PM

Nice work Kevin. I liked how you explained the reasoning behind the system. One thing I think may improve it is to only select stocks that are correlated with the underlying index. A highly correlated stock should have a relatively stable ratio as it will move up and down with the market. When it doesn't, then you enter as you have with this filter. For an uncorrelated stock, the ratio may move more sporatically so a zscore of less than negative two may not be as meaningful. It may be irrelevant, but food for thought at least.

Kevin_in_GA
4,599 posts
msg #101017
Ignore Kevin_in_GA
6/3/2011 12:05:24 AM

I actually started my refinement by looking at exactly this aspect, but found that despite my original thinking on this, correlation made no improvement whatsoever to system performance. I even looked at correlations from 10 to 250 days to see if that would help. In general, it eroded profits and Sharpe ratio, so I moved on.

Note that I was surprised by this (as you probably are as well). This is why backtesting lots of possible avenues is an important step in strategy design.

03bsbme
20 posts
msg #101018
Ignore 03bsbme
6/3/2011 12:36:43 AM

That is a bit surprising, but maybe that is somehow accounted for by the ratio itself. I'll have to think more about that although it appears I shouldn't spend too much time worrying about it.

On another note, if I am thinking about this correctly when the zscore drops below 2 std below the ratio it essentially means the price is falling faster (or rising slower) than the market. It could be possible that both the index and stock went down, but the stock decreased by a greater percentage. If the market continues to fall, the stock may not fall as fast, stay the same, or go up just a small amount. In those cases the ratio increases without the price of the stock increasing much if at all. Similar idea to relative strength. Perhaps you might want to consider adding in something dealing with looking at what the market is doing (going up, sideways, or down). I realize that the close being above the MA may account for that somewhat, but there might be something else that improves your system in addition to that.

I definitely like the idea behind this. Just trying to think of other things to consider. I typically like to keep things simple, but don't mind adding to things if they seem pretty intuitive.

Kevin_in_GA
4,599 posts
msg #101020
Ignore Kevin_in_GA
6/3/2011 7:00:15 AM

The strategy here is really half of a pair trade strategy. My original thinking was to simply reverse this and to simultaneously go short an overvalued stock (Z-score above 2). However, looking at all of the possible combinations of these variables failed to identify a short system that would perform anywhere near as well, or trade as frequently.

The basic thinking here was to have 2 pairs (A/B and C/B) with the first pair Z-score below -2 and the second pair Z-score above 2. Then one could go long on A and simultaneously short C to make a dollar-neutral pair strategy that mitigates some risk while generating profits from both trades.

However, one could simply buy SH (effectively shorting the market) each time you buy one of these stocks - that creates the correct pair trade since the ratio uses the ^SPX in the denominator. My guess is that you would not do as well, since we know that the market spends longer time in slow growth phases and then has short abrupt corrections.


novacane32000
331 posts
msg #101037
Ignore novacane32000
6/3/2011 2:38:02 PM

Kevin
I have been working with Stratasearch for the past week or so after reading one of your post referencing it. Appears to be a powerful program ! I am still in the learning phase.

How would you trade your SF code above? Exit ?

Kevin_in_GA
4,599 posts
msg #101040
Ignore Kevin_in_GA
6/3/2011 3:09:04 PM

Kevin
I have been working with Stratasearch for the past week or so after reading one of your post referencing it. Appears to be a powerful program ! I am still in the learning phase.

How would you trade your SF code above? Exit ?
++++++++

The Zscore function I had to write as a custom function (not hard, as the SS coding language is not too complex). You can find it here:

http://www.stratasearch.com/forum/viewtopic.php?f=3&t=950&p=4243#p4243

The entry code is:

Zscore(16) < -2 and

close > mov(close,200,simple) and

wlr(16) < -94 and

close < bbl(close,16,2)


Exit code:

Zscore(16) > -1 or

$daysheld > 20


Kevin

mystiq
650 posts
msg #101060
Ignore mystiq
modified
6/4/2011 2:13:21 AM

can this be *modified* to show 16 weeks instead....(weekly version)

novacane32000
331 posts
msg #101068
Ignore novacane32000
modified
6/4/2011 5:15:26 PM

Kevin
I have been working with Stratasearch for the past week or so after reading one of your post referencing it. Appears to be a powerful program ! I am still in the learning phase.

How would you trade your SF code above? Exit ?
++++++++

The Zscore function I had to write as a custom function (not hard, as the SS coding language is not too complex). You can find it here:

http://www.stratasearch.com/forum/viewtopic.php?f=3&t=950&p=4243#p4243

The entry code is:

Zscore(16) < -2 and

close > mov(close,200,simple) and

wlr(16) < -94 and

close < bbl(close,16,2)

Exit code:

Zscore(16) > -1 or

$daysheld > 20

Kevin
*******************************************************************************************
*******************************************************************************************

Thanks Kevin
I tried to input the code in SS but apparently need to define the custom code for Zscore as you stated (easy for you is not easy for me).
Actually, I meant to ask how the StockFetcher filter itself posted above is best traded.

Would you simply buy the stock generated by the filter and sell after the zscore goes to -1 (I entered --zscore16 > -1 on the exit trigger for the backtest but it does not trigger an exit ) or also exit after holding > 20 days?

Simply buying the stock generated and selling after 5 days has produced good results YTD 2011. If Kevin or someone else can explain to me how to backtest with an exit of zscore above -1 it would be appreciated.

Trade Statistics
There were 294 total stocks entered. Of those, 272 or 92.52% were complete and 22 or 7.48% were open.
Of the 272 completed trades, 164 trades or 60.29%resulted in a net gain.
Your average net change for completed trades was: 0.85%.
The average draw down of your approach was: -2.52%.
The average max profit of your approach was: 3.03%
The Reward/Risk ratio for this approach is: 1.97
Annualized Return on Investment (ROI): 41.77%, the ROI of ^SPX was: 8.05%.


Kevin_in_GA
4,599 posts
msg #101070
Ignore Kevin_in_GA
6/4/2011 7:21:37 PM

To exit when Zscore16 is above -1, just put the same filter as you use in the entry but make the only selection condition "Zscore16 above -1" also make sure that the maximum days held is set to 20.

Here is the specific code I use in the backtest for exits:

/*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}

zscore16 above -1


That does it.

If you look at the last 4 months, the results are as follows:

There were 105 total stocks entered. Of those, 95 or 90.48% were complete and 10 or 9.52% were open.
Of the 95 completed trades, 65 trades or 68.42% resulted in a net gain.
Your average net change for completed trades was: 1.20%.
The average draw down of your approach was: -2.95%.
The average max profit of your approach was: 2.90%
The Reward/Risk ratio for this approach is: 2.72
Annualized Return on Investment (ROI): 55.29%, the ROI of ^SPX was: -0.60%.

But more important in any backtest is not so much the stats above, but the equity generated during the test period. From the equity summary:

Starting Equity: $100,000.00
Ending Equity: Total (Cash + Market): $108,934.55
Period: 75 days

8.9% gain. Not bad, especially when compared to the market as a whole for the same period. And yes, all trades here were closed on Friday (which probably brought the real performance of the filter down a lot).

StockFetcher Forums · Filter Exchange · HOW TO DESIGN A SYSTEM (NOT JUST A FILTER)<< 1 2 3 4 5 ... 43 >>Post Follow-up

*** Disclaimer *** StockFetcher.com does not endorse or suggest any of the securities which are returned in any of the searches or filters. They are provided purely for informational and research purposes. StockFetcher.com does not recommend particular securities. StockFetcher.com, Vestyl Software, L.L.C. and involved content providers shall not be liable for any errors or delays in the content, or for any actions taken based on the content.


Copyright 2022 - Vestyl Software L.L.C.Terms of Service | License | Questions or comments? Contact Us
EOD Data sources: DDFPlus & CSI Data Quotes delayed during active market hours. Delay times are at least 15 mins for NASDAQ, 20 mins for NYSE and Amex. Delayed intraday data provided by DDFPlus


This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.