3. Wait for pullback with small volume after the breakout
4. After pullback enter at next day open if current close price is greater than previous day high
5. Set the cut loss point to previous day low
6. Sell at next day open if any of the condition met
- price open high close low with high volume
- price hits trailing stop
7. Note that the rule only applicable for stock with price from 0.2 to 1.5
At a glance, these are quite common and typical rules for a breakout or momentum strategy, I did apply some of the rules in some of my previous trading strategies and they work very well. But will all these rule work as a complete trading system or strategy? Let's find out.
Let's examine the rule one by one and I will show you how do I quantify it and convert it to Amibroker code.
Rule 1. Price breakout from side way with huge volume
Code explanation:
//sideway
sideway = Sum(RSI(14) > 65 OR RSI(14) < 35, 40) < 5 AND ROC(C, 40) < 15 AND ROC(C, 40) > -15;
Explanation: The line of code expresses price moving in side way for last 40 days. It seems a bit complex, but the idea of side way is price should not fluctuate too much and the different of today price with previous 40th days must be small, in the code it is within -15% and 15%. I uses RSI to indicate price should not fluctuate too much, RSI value should be mostly within 35 and 65 in 40 days period. The rules doesn't say how long is the period of side way, but here I have hard coded to 40 days. We could optimize this value in back testing later.
//breakout
breakout = C > Ref(HHV(H, 40), -1);
Explanation: The line of code above verifies the closing price today is greater than the highest price of previous 40 days. In another words, the price has breakout from 40 days highest price. Again we can leave 40 days as a parameter to optimize.
//decent volume
decentVolume = MA(V, 3) > MA(V, 18);
Explanation: 3 period moving average of volume of the stock is greater than 18 period of moving average of volume. It means the recent volume is relatively big.
Rule 2. Golden cross before the price break out - Short MA crosses above long MA
//short MAA stay above Long MA
shortMAAboveLongMA = MA(C, 20) >= MA(C, 60);
Explanation: I simplify the rule by short MA must stay above long MA.
Rule 3. Wait for pullback with small volume after the breakout
//monitor signal
tradeFilter = volumeFilter AND priceFilter;
monitorSignal = breakout AND decentVolume AND shortMAAboveLongMA AND Ref(sideway, -3) AND tradeFilter;
//Average volume around breakout period
averageBreakoutPeriodVolume = ValueWhen(monitorSignal, MA(V, 5));
//price drop with small volume
priceDropWithSmallVolume = C < Ref(C, -1) AND V <= averageBreakoutPeriodVolume;
fisrtAdjustAction = priceDropWithSmallVolume AND Ref(allUpSinceSignal, -1);
//adjust
allAdjustSinceFirstAdjust = priceDropWithSmallVolume AND BarsSince(fisrtAdjustAction) == Sum(priceDropWithSmallVolume, BarsSince(fisrtAdjustAction)) AND BarsSince(fisrtAdjustAction) <= 5;
Explanation: The codes above are not easy to understand especially for beginner. The first 2 lines however are not related to pullback, it just combines all of the conditions above so that we can pass the variable to our code about pullback. The third line is to get the average volume when the price breakout from side way. The second line is to define the pullback action where the price should drop and volume should be smaller than average volume when breakout. The last 2 lines express one or more than one pullback action on each bar until the current bar. For example, if price pullbacks from Monday to Wednesday, then stock price must drop everyday with small volume (compare to breakout volume) for every single days in this period.
Rule 4. After pullback enter at next day open if current close price is greater than previous day high
//entry bar
entrySignal = C > Ref(H, -1) AND Ref(allAdjustSinceFirstAdjust, -1);
//Buy Signal
Buy = entrySignal;
Explanation: This is our actual entry signal. It compares today close price with previous high price, if close price is higher than yesterday highest price, it is an indication that pullback is over and stock price is reversed. We set the entry signal as our buy signal. Based on backtest setting, we will buy this stock at next day open price.
So far we have completed our Buy rules. Let;s continue working on Sell rules below.
Rules 5. Set the cut loss point to previous day low
//cut loss level
cutLossPoint = ValueWhen(entrySignal, Ref(L, -1));
Explanation: This is a simple formula, we just get the lowest price of the bar when entry signal is triggered and set it as our cut loss point.
Rule 6. Sell at next day open if any of the condition met
- price hit cut loss point
- death cross - short MA cross below short MA
- price drop with huge volume
- price open high close low with high volume
//Death cross
deathCross = Cross(MA(C, 60), MA(C, 20));
//bad Volume
badVolume = V > MA(V, 5) * 2 OR V > averageBreakoutPeriodVolume;
//Drop with bad volume
badDrop = C < Ref(C, -1) AND C < O AND badVolume;
//Open Up Close Low with bad volume
openUpCloseLow = O > Ref(C, -1) AND C < O AND (C-L)/(H-L) < 0.5 AND badVolume;
Sell = C < cutLossPoint OR deathCross OR badDrop OR openUpCloseLow;
Explanation: The code above should be self explanatory. The badVolume variable refers to high volume when share price drop. I define it as volume of the bar greater than 2 times of 5 days moving average of volume or the volume is greater than the average volume when breakout. So if share price drop or share price open high and close low with with "bad" volume it will meet our sell condition. Similarly, we will sell the stock at next day market open.
Rule 7. Note that the rule only applicable for stock with price from 0.2 to 1.5 & volume filter
//price filter
priceFilter = C > 0.2 AND C < 1.5;
//decent volume to trade
volumeFilter = (MA(V, 20) * C) > 3500;
//monitor signal
tradeFilter = volumeFilter AND priceFilter;
Explanation: Again, a self explanatory code, we only buy stock which close price is between 0.2 to 1.5. We also have to make sure the volume of stock is liquid enough for us to trade. We simply check it by price volume value of the stock is greater than 3500 (or RM 350000 since in KLSE the volume is in lot - 100 shares). If you notice the code in Rule 3 above, the condition is applied by Anded with other rules.
That's all about the important part of my code for the breakout strategy, I have omitted some other codes like position sizing. I set the position size to maximum 5 positions with equal 20% of capital each.
Back test Result
Let jump to the back test result and examine a few of our sample trades.
The back test period is from 1-1-2001 to 31-12-2016 which cover 16 years of historical data for all stocks listed on KLSE. First image is statistic of backtest. It shows the performance summary with 7.89% annual return and 20.28% average draw down. The second image is equity curve and draw down chart.
The chart above shows a typical winning trade, green and red arrows are entry and exit respectively. You can refer to the rules explained above to learn how the signal are generated.
The chart above shows a typical lossing trade.
In conclusion, this post focuses on converting the rules of a strategy to code, back test and verify whether it meet our expectation. I will not touch on how to optimize the rule and to improve a strategy here. I always advise traders to backtest a strategy and verify any trading idea/rule before following it. Some of the rules seems to be working or it could be given by some successful sifu which looks convincing, but the result from backtesting could reveal another story. Back testing definitely will help to eliminate or reduce the risk in this respect.