# Petra on Programming: Short-Term Candle Patterns

Japanese rice merchants invented candle patterns in the eighteenth century. Some traders believe that those patterns are still valid today. But alas, it seems no one yet got rich with them. Still, trading book authors are all the time praising patterns and inventing new ones, in hope to find one pattern that is really superior to randomly entering positions. In the Stocks & Commodities January 2021 issue, Perry Kaufman presented several new candle patterns. Let’s repeat his pattern tests with major US stocks and indices, and with or without an additional trend filter.

Kaufman’s 6 patterns were named Key Reversal, Island Reversal, Outside Days, Wide Ranging days, 3-Day Compression, and Gap opening. All are calculated from the previous 3 or 4 candles or price ranges. All but one are symmetric, meaning they deliver bullish and bearish signals. And because I’m a bit on the evil side, I added a 7th pattern that I just invented: TotalRandom.

Here’s how the patterns look as indicators in C:

```// a higher high followed by a lower close.
var cdlKeyReversal()
{
if(priceHigh(0) > priceHigh(1) && priceLow(0) < priceLow(1)) {
if(priceClose(0) < priceLow(1)) return -100; // sell
if(priceClose(0) > priceHigh(1)) return 100; // buy
}
return 0;
}

// recent 3 days each have a true range smaller than the 4th previous day.
var cdl3DayCompression()
{
vars TRs = series(TrueRange(),4);
if(TRs[0] < TRs[3] && TRs[1] < TRs[3] && TRs[2] < TRs[3])
return 100;
else
return 0;
}

// a gap higher followed by a lower close, but not filling the gap.
var cdlIslandReversal()
{
if(priceLow(0) > priceHigh(1) && priceClose(0) < priceOpen(0))
return -100; // sell
if(priceLow(1) > priceHigh(0) && priceClose(0) > priceOpen(0))
else return 0;
}

// a higher high and a lower low, close in upper or lower 25% of the range.
var cdlOutsideDay()
{
if(priceHigh(0) > priceHigh(1) && priceLow(0) < priceLow(1)) {
if(priceClose(0) < 0.75*priceLow(0) + 0.25*priceHigh(0))
return -100; // sell
if(priceClose(0) > 0.25*priceLow(0) + 0.75*priceHigh(0))
}
return 0;
}

// same as outside days, but true range must exceed 1.5 ร 20-day ATR
var cdlWideRangeDays()
{
if(TrueRange() > 1.5*ATR(20))
return cdlOutsideDay();
else
return 0;
}

// gap must be larger than 0.5 ร 20-day ATR.
var cdlGapOpening()
{
var Ratio = (priceOpen(0) - priceClose(1))/ATR(20);
if(Ratio >= 0.5) return 100;
if(Ratio <= -0.5) return -100;
return 0;
}

// just enter a trade when you feel lucky
var cdlTotalRandom()
{
int Pattern = random(100);
if(Pattern > 90) return 100;
if(Pattern < 10) return -100;
return 0;
}```

Following the convention of the classic candle pattern indicators from the TA library, the pattern functions return +100 for a bullish pattern, -100 for a bearish pattern, and 0 for no pattern.

We’re now putting them to theย  test. We want to trade the patterns with IWM, AAPL, AMZN, GE, WMT, and TSLA stocks, with SPY and QQQ index ETFs, and with and without an additional trend filter. For any detected pattern, we’re entering a long or short position depending on if it’s bullish or bearish. We always invest the same amount, regardless of the price of the stock. The position is closed after 1, 2, 3, 4, or 5 days. For any asset and any exit type we’ll export the number of trades and the total win and loss to a table in HTML format. That is convenient for me because I can paste it directly in this blog article.

The test script:

```var pattern();

function run()
{
pattern = cdlKeyReversal;
bool WithTrend = 0;
string Name = "KeyRev";

BarPeriod = 1440;
StartDate = 20100101; // TSLA went public in 2010
EndDate = 2020; // test until 2020
var Investment = 10000;
TradesPerBar = 40; // 8 assets * 5 algos

char File[100];
if(is(EXITRUN)) {
sprintf(File,"Log\\%s.htm",strf("%s%s",
Name,ifelse(WithTrend,"WithTrend","NoTrend")));
printf("\nStoring results in %s",File);
file_write(File,strf("<p>%s:</p>\n<table><tr>",File),0);
file_append(File,"<td>Asset</td>",0);
file_append(File,"<td>Long/Short</td>",0);
file_append(File,"<td>Day 1</td>",0);
file_append(File,"<td>Day 2</td>",0);
file_append(File,"<td>Day 3</td>",0);
file_append(File,"<td>Day 4</td>",0);
file_append(File,"<td>Day 5</td></tr>",0);
}

while(asset(loop("SPY","QQQ","IWM","AAPL","AMZN","GE","WMT","TSLA"))) {
vars Trend = series(SMA(seriesC(),80));
while(algo(loop("Day1","Day2","Day3","Day4","Day5"))) {

Lots = Investment/priceClose();
LifeTime = Itor2+1; // life time in days
int Signal = pattern();
if(Signal > 0 && (!WithTrend || rising(Trend)))
enterLong();
else if(Signal < 0 && (!WithTrend || falling(Trend)))
enterShort();
if(is(EXITRUN)) {
if(Algo == "Day1") // first loop run
file_append(File,strf("\n<tr><td>%s</td><td>%i/%i</td>",
Asset,NumWinLong+NumLossLong,NumWinShort+NumLossShort),0);
string Color = ifelse(WinLong-LossLong+WinShort-LossShort > 0,
"bgcolor=\"lime\"","bgcolor=\"red\"");
file_append(File,strf("<td %s>%.0f/%.0f</td>",
Color,WinLong-LossLong,WinShort-LossShort),0);
if(Algo == "Day5")
file_append(File,"</tr>",0);
}

}} // loops
if(is(EXITRUN)) {
file_append(File,"</table>",0);
file_append(File,strf("<p>Total Profit: %.0f (%.0f%%)</p>",
WinTotal-LossTotal,100*(WinTotal-LossTotal)/Investment),0);
}
}
```

Some explanations about the code. At the begin of the run() function the pattern and the trend mode are set up. For convenience we’re using a function pointer that is set to the pattern function to be tested. Afterwards, when it’s the last run, the table header is written into the HTM file. A char array (File) and the sprintf() function is used for the file name instead of the more convenient strf(), because we need to keep the file name for later writing into the table.

The test uses two nested loops, first for selecting the stocks, second for selecting the trade life time to get the results from a 1-day trade up to a 5-days trade. The predefined Itor2 variable is the iterator of the second loop and runs from 0 to 4, so we just use it to set the LifeTime variable for the subsequent trade. The results are printed in the EXITRUN at the last day of the simulation.

The numbers in the tables are the results from long/short trades. A winning pattern is displayed in green, a losing pattern in red. Transaction costs are considered.

KeyRev, No Trend:

 Asset Long/Short Day 1 Day 2 Day 3 Day 4 Day 5 SPY 54/73 379/-74 787/-1126 1276/-1753 1203/-2587 986/-3444 QQQ 66/80 1028/-2222 1842/-1958 2042/-2242 2008/-2681 1179/-4133 IWM 63/84 19/-300 756/-488 1298/-502 1386/-900 2063/-2429 AAPL 59/61 -1346/-7827 -947/-9158 -559/-13563 -1237/-11751 356/-11040 AMZN 69/58 142/-1259 2013/-2446 1252/-2293 2208/-4940 3134/-7322 GE 66/61 -4510/-2948 -7995/-6381 -8232/-6583 -7267/-8451 -7646/-10219 WMT 62/69 -337/-177 228/-100 1709/-821 1612/-128 1472/-983 TSLA 65/52 5480/2377 11321/814 11299/-206 9784/-1291 5640/-5471

Total Profit: -103182 (-1032%)

KeyRev, With Trend:

 Asset Long/Short Day 1 Day 2 Day 3 Day 4 Day 5 SPY 44/13 208/472 276/260 744/198 96/-236 345/-855 QQQ 53/12 448/-490 1350/-427 1763/-488 1806/-1524 985/-1860 IWM 43/22 563/557 831/-150 81/-773 225/-1174 -55/-2342 AAPL 46/10 -842/-475 55/-926 955/-1562 -149/-1882 603/-2556 AMZN 58/16 314/-661 1254/-897 -727/-566 -680/-1734 -27/-1628 GE 36/29 -1967/-645 -2990/-2871 -1527/-3644 -262/-4542 -1106/-6970 WMT 42/26 -438/215 -379/676 610/-9 312/706 1050/-76 TSLA 41/17 5530/-1068 11484/-1301 10308/-3273 10240/-3127 7723/-3471

Total Profit: -2109 (-21%)

Compression, No Trend:

 Asset Long/Short Day 1 Day 2 Day 3 Day 4 Day 5 SPY 699/0 6795/0 11511/0 17027/0 18998/0 23941/0 QQQ 694/0 13941/0 22562/0 28398/0 33369/0 35845/0 IWM 719/0 9964/0 15613/0 19472/0 22317/0 22088/0 AAPL 740/0 -32636/0 -19330/0 -12002/0 -2776/0 2230/0 AMZN 733/0 25188/0 37365/0 49592/0 52783/0 62537/0 GE 728/0 -48784/0 -45754/0 -40932/0 -41726/0 -44097/0 WMT 743/0 4060/0 9378/0 19676/0 19954/0 19714/0 TSLA 701/0 34085/0 39053/0 50163/0 74096/0 93178/0

Total Profit: 606857 (6069%)

Compression With Trend:

 Asset Long/Short Day 1 Day 2 Day 3 Day 4 Day 5 SPY 561/0 5212/0 8658/0 9792/0 10530/0 12164/0 QQQ 571/0 10895/0 18052/0 20473/0 24411/0 26917/0 IWM 525/0 6363/0 9300/0 9143/0 14086/0 15742/0 AAPL 547/0 -20085/0 -4174/0 -1241/0 5801/0 5899/0 AMZN 557/0 19877/0 28991/0 34042/0 32737/0 38519/0 GE 385/0 -24387/0 -22127/0 -16754/0 -16487/0 -19714/0 WMT 501/0 4228/0 9813/0 18114/0 21492/0 20353/0 TSLA 443/0 29320/0 34921/0 42957/0 58827/0 66305/0

Total Profit: 548966 (5490%)

Island, No Trend:

 Asset Long/Short Day 1 Day 2 Day 3 Day 4 Day 5 SPY 19/32 547/696 540/314 -262/1357 -282/1186 -517/133 QQQ 24/26 300/-283 -684/-452 -1190/360 -2194/-65 -1274/-920 IWM 10/27 921/-15 1587/-112 1610/1583 1936/918 1698/924 AAPL 30/33 -2304/-1850 -2055/-2128 -3958/-2921 -4046/-3311 -5085/-3696 AMZN 20/25 498/-1995 454/-1575 -28/-1469 -150/-2013 -214/-2048 GE 20/28 24/-1885 -1181/-221 -719/1343 2468/106 682/-1594 WMT 23/17 1099/972 2056/605 2508/697 3300/1188 3094/782 TSLA 25/28 1029/-5539 1732/-7774 3167/-5777 1278/-6200 -2787/-10091

Total Profit: -47171 (-472%)

Island With Trend:

 Asset Long/Short Day 1 Day 2 Day 3 Day 4 Day 5 SPY 11/5 348/391 -19/444 104/841 -69/910 133/411 QQQ 15/4 -43/376 -274/407 -1069/948 -1588/1139 -1544/557 IWM 5/7 47/173 461/234 562/1312 539/1506 643/1364 AAPL 24/4 -1095/-337 -1625/104 -3931/26 -4541/175 -5013/115 AMZN 12/3 90/-377 -1049/-311 -1364/-3 -2070/214 -1720/-32 GE 10/15 -407/-829 -2018/34 -2323/1562 -1673/767 -2358/-155 WMT 13/3 813/58 1138/-257 1269/185 1484/365 1389/-15 TSLA 13/8 -12/-1216 1134/-1731 1574/-1913 -41/-2357 -5443/-2904

Total Profit: -27380 (-274%)

Outside, No Trend:

 Asset Long/Short Day 1 Day 2 Day 3 Day 4 Day 5 SPY 77/77 888/-1105 1410/-1913 2295/-2788 1849/-3487 1555/-3798 QQQ 86/86 919/-1641 1510/-2001 1638/-1562 2132/-2919 1198/-3920 IWM 89/83 -17/-740 205/216 15/155 885/-739 419/-1453 AAPL 65/65 2441/-3824 3324/-5405 4000/-7484 4439/-7002 6148/-7471 AMZN 85/68 489/-561 2895/-1176 2629/-2024 2498/-3505 4767/-6733 GE 74/73 -239/-4137 -2582/-6322 -3096/-7272 -3567/-8987 -3550/-11511 WMT 72/84 -491/1036 461/361 1678/-514 1991/-700 879/-2724 TSLA 74/59 6927/1382 11200/0 12701/-1546 11173/-5879 6769/-6498

Total Profit: -35405 (-354%)

Outside With Trend:

 Asset Long/Short Day 1 Day 2 Day 3 Day 4 Day 5 SPY 63/13 664/123 977/-243 1430/-396 596/-887 830/-1168 QQQ 69/11 214/-123 371/-70 481/-8 919/-998 -43/-1275 IWM 59/23 918/-59 1629/-481 1346/-1381 1447/-2182 1339/-2496 AAPL 51/11 2210/-377 3673/-635 4927/-799 5244/-1175 6062/-2042 AMZN 67/14 979/-563 1886/-906 89/-377 316/-1515 1795/-1141 GE 42/34 677/-2682 -353/-4345 1801/-5183 1663/-6603 -732/-10460 WMT 49/31 -746/1081 -482/1016 1165/267 644/244 1183/-976 TSLA 49/23 6834/-1174 11638/333 10403/-871 10899/-1795 8143/-2696

Total Profit: 38018 (380%)

Range, NoTrend:

 Asset Long/Short Day 1 Day 2 Day 3 Day 4 Day 5 SPY 18/27 205/-520 206/-1392 179/-1244 -10/-1337 -254/-2635 QQQ 18/30 -64/-214 274/-741 412/161 839/72 558/-1528 IWM 19/25 -392/-382 -873/-88 -711/1284 -1083/1207 -886/456 AAPL 9/13 404/-293 318/-951 1193/-420 1187/-576 980/-1500 AMZN 13/17 1100/-1315 1785/-843 938/612 1702/526 2577/-667 GE 17/23 -1281/-181 -1833/-2128 -3415/-2288 -4833/-1910 -5257/-3787 WMT 12/14 -142/399 -433/915 -1078/801 -1232/998 -1746/697 TSLA 21/17 849/33 3714/-1998 3761/-3474 2735/-7781 386/-7093

Total Profit: -38348 (-383%)

Range With Trend:

 Asset Long/Short Day 1 Day 2 Day 3 Day 4 Day 5 SPY 15/4 -245/51 -193/283 11/413 -409/105 -522/-507 QQQ 13/5 -585/-99 -374/151 -293/514 -138/86 -539/-216 IWM 11/5 393/-230 304/-222 212/-246 -74/-9 77/-157 AAPL 8/2 517/295 254/21 1049/448 1092/335 840/103 AMZN 11/4 -34/-1248 252/-1603 -759/-364 -603/-1203 -141/-1438 GE 9/10 906/319 496/-1302 389/-1897 -343/-1786 -1874/-3716 WMT 6/4 -262/154 -545/604 -328/404 -704/424 -558/61 TSLA 13/3 386/-191 4201/309 1815/-35 1290/-206 1/-597

Total Profit: -7235 (-72%)

Gap, No Trend:

 Asset Long/Short Day 1 Day 2 Day 3 Day 4 Day 5 SPY 349/281 1843/-2647 5590/-3626 7139/-5568 8563/-8215 9461/-9622 QQQ 307/249 -436/-2679 947/-5712 3275/-8531 7805/-12092 9842/-13431 IWM 234/209 2551/-84 3639/-418 5118/-2119 6055/-3499 9321/-5574 AAPL 270/192 6959/-1638 7870/-5676 9847/-7260 13533/-5428 16900/-8041 AMZN 195/135 1427/-2939 2777/-4051 4995/-4568 8998/-6259 13534/-6271 GE 241/195 112/371 -4831/5254 -3762/3531 -1410/5945 1695/4319 WMT 125/180 -1507/-7044 329/-7500 448/-6792 24/-6722 876/-7916 TSLA 197/154 21127/-6332 36571/-12591 46932/-11143 58537/-9760 71862/-9286

Total Profit: 192941 (1929%)

Gap With Trend:

 Asset Long/Short Day 1 Day 2 Day 3 Day 4 Day 5 SPY 282/82 2592/-488 5160/166 7869/-2794 8352/-3565 8935/-5882 QQQ 249/68 -718/-2463 -1388/-5109 91/-9515 4466/-11318 5774/-12975 IWM 163/82 2456/617 3057/2235 5188/917 6955/2870 8950/2094 AAPL 219/60 3901/-978 1837/-2601 2008/-5555 6634/-5316 10460/-6654 AMZN 169/34 -1685/-2236 -1130/-5903 -397/-6310 3148/-7550 6830/-6188 GE 138/91 969/1315 -1600/6072 -679/5257 748/5819 3337/2798 WMT 90/79 -465/-1144 174/-456 -93/-1071 -760/-1130 135/-2431 TSLA 151/62 16146/-4006 30939/-3936 42024/-3501 54105/-1597 70309/-915

Total Profit: 221201 (2212%)

Random, NoTrend:

 Asset Long/Short Day 1 Day 2 Day 3 Day 4 Day 5 SPY 264/245 2161/-2628 3479/-4002 4118/-3867 8184/-5686 3223/-7478 QQQ 274/256 6391/-6434 4669/-3082 6549/-7386 4095/-2891 11244/-6941 IWM 247/227 4546/-2869 7429/114 4610/1211 10551/1705 8259/-6920 AAPL 265/248 2130/-9670 2688/-4795 12171/-6907 17141/-9278 12451/-25170 AMZN 239/215 2970/-4240 3796/-6628 4579/-8738 7889/-6822 10022/-11536 GE 254/259 1016/-4440 -1860/-3617 3682/-2421 10588/552 -8794/-12820 WMT 258/260 670/-2260 2830/-459 -55/-2294 -3118/-5824 4529/-3994 TSLA 209/250 8366/-9571 -4906/-32877 17063/-33473 19937/-13389 8788/-53044

Total Profit: -115840 (-1158%)

Random With Trend:

 Asset Long/Short Day 1 Day 2 Day 3 Day 4 Day 5 SPY 189/55 2273/-386 597/-600 2753/-747 1864/883 -1143/-3324 QQQ 194/53 2461/-2976 3675/-947 1360/-3750 7607/-7892 12958/-2974 IWM 182/85 3478/2507 4262/-969 3827/-2263 902/-3130 8135/-4938 AAPL 183/70 7704/-2776 9537/-3962 8168/-759 13781/-5973 13117/-2048 AMZN 174/70 1795/-4108 -362/-2203 3809/-5626 9710/-8699 16006/-8834 GE 125/109 1187/3311 -3939/-1684 264/2732 -3265/4335 425/-8270 WMT 174/91 1962/132 2008/-1731 -946/-285 1927/1556 1790/-5483 TSLA 148/92 13794/-7286 13013/-3592 15655/-6054 15511/-10460 15264/-18641

Total Profit: 85014 (850%)

We can see that the trend filter always improves the results, which indicates some momentum in the stock markets. Aside from that, patterns show no real advantage over random trading. But wait, there’s an exception: the Compression pattern looks extraordinarily successful. Have we finally found the one pattern that beats randomness?

Unfortunately, a closer look reveals the real reason. The compression pattern opens only long positions, and since most stocks are bullish in the long term, a positive result is to be expected. If you modify the random pattern function so that it only opens long positions, you’ll get the same effect. Randomly opening long positions beats hands down all symmetric candle patterns. So it seems that trading with candle patterns, no matter old or new, still requires strong faith – and some disposable money.

The pattern functions and the test script can be downloaded from the 2020 script repository.

## 9 thoughts on “Petra on Programming: Short-Term Candle Patterns”

1. Paul Smith says:

Nice work!

2. Aaron Robson says:

I knew I was onto something with my random entries ๐
Really thought provoking, thanks. [Good find Paul Smith :)]

3. Michel Desrosiers says:

Wow! Amazing! I try it tomorrow. Thanks.

4. Diabolus says:

Correct me if I’m wrong… but when running some tests of your code (and by previous experience), if the goal is only to assess (Test/Backtest) the efficacy of a certain algo in a number of different assets, I don’t think running it in an asset loop is the correct way. It seems each asset loop doesn’t consider an asset as a “clean slate”, and instead run a certain algo as it would be managing a portfolio, where an entry in an asset could interfere with the possibility of entry in another asset if there is no margin, etc.

5. Hmm, asset loops are simply used for running the same code with many assets. They dont interfere with entry possibilities, whatever thats supposed to mean.

6. Diabolus says:

That is what I thought, until I saw huge inconsistencies between running backtests in asset loops and individually.. the documentation on this is scarce, and I couldn’t find explicitly why. If you can, I’d like you to run similar tests and help me verify if this is consistent with your findings as well. I assume all assets are sharing the same “Capital”/”Margin” variables, although I later realized this is probably being “ignored” as you are setting the lots by using a local variable (Investment)

On a side note, specifically for this code, I can’t seem to replicate your results. In fact, every run keeps returning different results (3 consecutive runs without modifying the code, just hitting “Test”):
Test 1:

AAPL avg .276 0.89 1249/1395 34.7
AMZN avg .025 0.92 1317/1362 24.9
GE avg .364 1.00 1260/1393 1.2
IWM avg .330 1.03 1363/1384 -6.6
QQQ avg .213 0.97 1313/1360 6.5
SPY avg .286 1.02 1338/1349 -3.0
TSLA avg .142 0.92 1194/1275 45.3
WMT avg .236 1.02 1331/1301 -3.1

Day1 avg .288 0.95 2059/2185 16.2
Day2 avg .200 0.89 1990/2175 42.3
Day3 avg .302 0.96 2142/2167 18.6
Day4 avg .370 1.03 2105/2148 -15.7
Day5 avg .244 0.93 2069/2144 38.6

Test 2:

AAPL avg .334 0.96 1323/1383 9.3
AMZN avg .032 1.18 1404/1271 -44.3
GE avg .251 0.91 1258/1393 24.6
IWM avg .220 1.02 1267/1278 -3.8
QQQ avg .216 0.94 1275/1382 9.3
SPY avg .169 0.98 1310/1301 2.5
TSLA avg .087 0.79 1201/1333 109.1
WMT avg .500 1.05 1326/1298 -6.8

Day1 avg .307 0.94 2082/2108 15.6
Day2 avg .344 0.95 2107/2118 15.6
Day3 avg .137 0.93 1982/2167 27.8
Day4 avg .311 0.99 2098/2098 5.2
Day5 avg .259 0.93 2095/2148 35.9

Test 3:

AAPL avg .100 0.87 1252/1386 36.8
AMZN avg .018 0.95 1404/1390 14.8
GE avg .172 0.92 1319/1368 22.4
IWM avg .176 0.93 1291/1299 13.2
QQQ avg .258 0.95 1254/1330 8.1
SPY avg .283 1.04 1288/1353 -4.9
TSLA avg .071 0.98 1216/1244 7.6
WMT avg .320 0.99 1221/1289 2.0

Day1 avg .186 0.98 2110/2115 4.4
Day2 avg .209 0.95 2051/2107 16.2
Day3 avg .305 0.98 2038/2084 6.2
Day4 avg .144 0.91 1999/2147 40.7
Day5 avg .206 0.94 2047/2206 32.4

7. I cannot tell why your script produces strange results because I don’t know it. Maybe you forgot to initialize some variable. If in doubt, just use my script from the repository.

8. Hannes says:

Thank you very much for this great investigative analysis! ๐

9. LeoPeru says:

Hi everyone! I’m new here.

Thanks, Petra, for sharing your work!
It’s mind-blowing and helpful for a beginner like me.

Hands down!

Looking forward to learning more from your posts.

This site uses Akismet to reduce spam. Learn how your comment data is processed.