A couple of weeks ago I read somewhere you couldn't build a trading system on isolated components of the Ichimoku Kink Hyo System, because each indicator works together with several others and only in combination the true power of Ichimoku unfolds. Sounded reasonable that time, but after a while I started to question that. Why should this not work? In the end such a system is trend following system build on a moving average at it´s core. Admittedly, the Kijun-Sen indicator is calculated differently than the SMAs or EMAs of this world, which most traders should be familiar. But it still is a moving average, and combined with a reasonable exit strategy I did not see why such a try should be doomed. That said, I fired up my program and did some backtesting :)

<another Edit:> This was article was written with a pretty old version of the ichinscratchy system. As I know now, the methodology I used has a major flaw: the comparison of Profits and Losses in %, completely ignoring the underlying currency of the markets and most likely different currency an account would have. So a translation between currencies would be needed, introducing a dependency of the acual p&l in one market to the currency changes. Later versions of the software do implement this whole idea. I will revisit this topic as soon as I finished the currently ongoing rewrite of major internal parts of my program. Meanwhile I am leaving this article online, mostly for transparency reasons, and for others to participate in my own learning curve.

<End of another Edit>

DISCLAIMER: Do not trust me, my software or anything on this blog. I am a guy you just stumbled upon on the internet. Do not trust your money to anything someone claims to be true, you do not understand fully or tested for yourself. In fact, I would be very happy if anyone could falsify (or even better: verify!) the ideas on my blog.

<Edit:> After showing this article to a professional trader and asking for his opinions, I received some very valuable feedback, which I incorporated into this article. This deals mainly with the description of the system itself, as well as the backtesting with non-trending markets. Since I already published this article online, for transparency reasons I mark every addition. <End Edit>

Kijun Sen as single indicator

That said, let`s start with something I would call "the primitive Kijun Sen trading system". First I take a default configuration of my my ichinscratchy trading system and switch off the execution of all signals with the exception of Kijun-Sen Cross with price:

###############################################################################
# Ichimoku related settings
###############################################################################
ICHI_DAYS_TO_ANALYZE = 1467
ICHI_PERIOD_SHORT = 9 # default 9
ICHI_PERIOD_MID = 26 # default 26
ICHI_PERIOD_LONG = 52 # default: 52
ICHI_CHIKOU_CONFIRM = false # use chikou span as confirmation/filter for trend (default true)
ICHI_EXECUTION_SENKOU_X = false # execute Signal Senkou Cross, default true
ICHI_EXECUTION_KIJUN_X = true # execute Signal Kijun Cross, default true
ICHI_EXECUTION_CHIKOU_X = false # execute Chikou Cross, default true
ICHI_EXECUTION_TK_X = false # execute Tenkan/Kijun Cross, default true
ICHI_EXECUTION_KUMOBREAK =false # execute Kumo breakout, default true

<Edit:> So what my software does now, is basically an Ichimoku analysis of the given market(s), but executing only signals that were triggered by Kijun-Sen Crosses with price. Furthermore, only so called "strong" signals are executed, which means that the crossing has to take place above the Kumo for uptrends (=> long signals) or below Kumo for downtrends (==> short signal). Neutral and weak signals are disregarded. <End Edit>

I have price data of my home market, the german DAX30 for the time period 2006 - 2011, which are 1467 days of data. The basic idea is to do some testing and tweaking with this dataset, and let the result run against an out-of-sample data set from 2012 - 2016 to make sure I did not curve fit the results to the data.

The result of this first shot is as follows:

Orderbook statistics
====================
                   ALL      LONG      SHORT
                   ---      ----      -----
Number of trades:  39        21        18
Number of winners: 19        9         10
Number of losers:  20        12         8
Win percentage:    48.72%   42.86%    55.56%

Total Win:         80.44%   54.73%    25.70%
Total Loss:       -27.56%   -14.57%   -13.00%
avg win:           4.23%     6.08%     2.57%
avg loss:         -1.38%    -1.21%    -1.62%
Profit Factor:     3.07      5.01      1.58
Expectancy:        1.36%     1.91%     0.71%

First Trade: 2006-12-01    Last Trade: 2011-12-16
Nr. Drawdowns: 4 Days in drawdown: 1410
Max days in drawdown: 1087 avg days in drawdown: 352.5
Largest Drawdown: -10.25%
max consecutive loose trades: 4     max consecutive win trades: 4
holding days (mean avg): 8.8        holding days (median): 2.0

real 0m5.692s
user 0m0.256s
sys 0m0.126s

Not too bad for a first try. If you are curious, for each step I describe in this post I provide an export of the orderbook table within the database as .csv file, so you can see which trades were taken when and with what result. You will find the downloads at the bottom of this page

Chikou-Span as signal filter

But I have build in too much goodies to not use them- Lets switch on the additional chikou-span trend filter: a Kijun-Sen Golden Cross will only be valid and thus executed, if Chikou-Span is above Kumo and the price. Same logic for Kijun-Sen Death Cross: only use it if Chikou-Span is below price and Kumo. To switch the filter on, I used

###############################################################################
# Ichimoku related settings
###############################################################################
ICHI_CHIKOU_CONFIRM = true # use chikou span as confirmation/filter for trend (default true)

This resulted in the following:

Orderbook statistics
====================
                     ALL      LONG      SHORT
                     ---      ----      -----
Number of trades:    28        17         11
Number of winners:   15        8          7
Number of losers:    13        9          4
Win percentage:      53.57%   47.06%    63.64%
Total Win:           65.62%   54.46%    11.16%

Total Loss:          -16.54% -11.39%    -5.15%

avg win:             4.37%     6.81%     1.59%
avg loss:            -1.27%    -1.27%   -1.29%
Profit Factor:       3.44      5.38      1.24
Expectancy:          1.75%     2.53%     0.55%

First Trade: 2006-12-01     Last Trade: 2011-12-16
Nr. Drawdowns: 5            Days in drawdown: 952
Max days in drawdown: 296   avg days in drawdown: 190.4
Largest Drawdown: -4.27%
max consecutive loose trades: 3    max consecutive win trades: 3
holding days (mean avg): 10.6      holding days (median): 2.0

real 0m4.790s
user 0m0.213s
sys 0m0.104s

As expected, the signal quality (an indicator is the win percentage) got better.  At the moment if a signal occures, a position is bought. No limit is imposed on the number of positions the system accumulates (the config file calls that pyramiding, I don't know if thats the correct term).

Buy only 1 position per direction

Lets see how the numbers look if only a single position per direction (1 long and/or 1 short) is allowed. I edited the config again:

###############################################################################
# Signal execution settings
################################################################################
SIGNAL_EXECUTION_PYRAMID = none # pyramid buy/sell signals, e.g. buy more than 1 position in same direction?
# none: buy max 1 position in short/max 1 in long position, daily: execute only 1
# long and 1 short position per day, pyramid on consecutive days, full: do not
# impose any limits, buy every single signal

After endless 4 seconds of waiting the results appeared:

Orderbook statistics
====================
                     ALL     LONG     SHORT
                     ---     ----     -----
Number of trades:    26       15       11
Number of winners:   14       7        7
Number of losers:    12       8        4
Win percentage:     53.85%   46.67%   63.64%

Total Win:          64.10%   52.94%   11.16%
Total Loss:         -14.20%  -9.04%   -5.15%
avg win:            4.58%     7.56%   1.59%
avg loss:          -1.18%    -1.13%   -1.29%
Profit Factor:       3.87     6.69     1.24
Expectancy:          1.92%    2.93%   0.55%

First Trade: 2006-12-01     Last Trade: 2011-12-16
Nr. Drawdowns: 5            Days in drawdown: 759
Max days in drawdown: 288   avg days in drawdown: 151.8
Largest Drawdown: -3.25%
max consecutive loose trades: 3    max consecutive win trades: 3
holding days (mean avg): 9.6       holding days (median): 2.0

real 0m4.393s
user 0m0.180s
sys 0m0.107s

Not that much of a change, but keep in mind, we are talking about 1 indicator, 1 single market and a pretty conservative SL strategy (chandelier stop with factor 3 and an ATR period of 100 days). Compared to before, now we did only 2 trades less, but it looks 1 of those 2 trades was a winner, the other one a loser. So profit factor, Expectancy and largest drawdown improved.

Tweak volatility-based stop loss

As I said, all of the above was run on a conservative ATR stop loss. I was curious how the result would behave if I tweak the SL settings a bit... so I set a tighter ATR factor:

##############################################################################
# Stop Loss settings
###############################################################################
SL_CHANDELIER_ATR_FACTOR = 2      # SL_TYPE=chandelier: Place the SL x-times the ATR away (default 3)

To my surpise the results did not change dramatically:

Orderbook statistics
====================
                  ALL      LONG     SHORT
                  ---      ----     -----
Number of trades:  28       17       11
Number of winners: 22       12       10
Number of losers:   6        5        1
Win percentage:    78.57%  70.59%   90.91%
Total Win:         85.36%  56.24%   29.12%
Total Loss:        -4.58%  -1.58%   -3.00%
avg win:           3.88%    4.69%    2.91%
avg loss:          -0.76%  -0.32%   -3.00%
Profit Factor:     5.08     14.82    0.97
Expectancy:        2.88%    3.22%    2.37%
First Trade: 2006-11-30     Last Trade: 2011-12-16
Nr. Drawdowns: 5            Days in drawdown: 267
Max days in drawdown: 170   avg days in drawdown: 53.4
Largest Drawdown: -3.00%
max consecutive loose trades: 2    max consecutive win trades: 7
holding days (mean avg): 4.6       holding days (median): 2.0
real 0m3.361s
user 0m0.142s
sys 0m0.083s

That still looks too good to be true... on the other hand the data basis is WAY to small to make a judgement yet. 28 trades is of no statistical significance at all. Note that with turning the Chikou filter on, the first trade happened at the end of the first year (but keep in mind I use the chandelier stop with an ATR period of 100 days- the very first signal can be executed after 100 days of data). Despite having the years 2008/2009 within the data set, maybe all results so far were pure luck with the DAX in this timeframe.

Adding more markets

Lets add more markets: DAX, Nikkei, S&P 500, Gold, EUR/USD in the same timeframe:

Orderbook statistics
====================
                    ALL     LONG      SHORT
                    ---     ----      -----
Number of trades:   191      106        85
Number of winners:  135      66         69
Number of losers:    56      40         16
Win percentage:     70.68%  62.26%    81.18%

Total Win:         533.78%  209.79%   323.98%
Total Loss:        -44.43%  -23.39%   -21.04%
avg win:             3.95%   3.18%     4.70%
avg loss:           -0.79%  -0.58%    -1.32%
Profit Factor:       4.98     5.44     3.57
Expectancy:         2.56%     1.76%    3.56%

First Trade: 2006-06-30     Last Trade: 2011-12-26
Nr. Drawdowns: 28           Days in drawdown: 573
Max days in drawdown: 130   avg days in drawdown: 20.5
Largest Drawdown: -7.84%
max consecutive loose trades: 8  max consecutive win trades: 17
holding days (mean avg): 4.0     holding days (median): 2.0

real 0m19.470s
user 0m0.807s
sys 0m0.338s

This still looks very convincing, almost a little bit too tempting for my perspective. I did not do a lot of tweaking, but still there is chance that by pure accident I did kind of data mining or curve fitting of the perfect trading strategy for an existing set of data. Which would be bad, as the system might fail on another set of data.

Out of sample test

How to mitigate that problem? As you might have noted, using a 2006-2011 timeframe set of data  indicates that I have another set of data available. So what I did next was an an out-of-sample test with exact settings and markets but different period. Another bonus is, that the out of sample set ends very recently and so the market conditions are comparable to what are the conditions today. Enough talking, the results:

Orderbook statistics
====================
                        ALL      LONG     SHORT
                        ---      ----     -----
Number of trades:       171       102      69
Number of winners:      114        56      58
Number of losers:        57        46      11
Win percentage:        66.67%    54.90%   84.06%

Total Win:             303.84%   141.37%  162.47%
Total Loss:            -41.68%   -28.54%  -13.14%
avg win:                 2.67%     2.52%    2.80%
avg loss:               -0.73%    -0.62%   -1.19%
Profit Factor:            3.64      4.07    2.35
Expectancy:               1.53%     1.11%   2.16%

First Trade: 2012-07-30      Last Trade: 2016-12-30
Nr. Drawdowns: 31            Days in drawdown: 698
Max days in drawdown: 99     avg days in drawdown: 22.5
Largest Drawdown: -6.33%
max consecutive loose trades: 3   max consecutive win trades: 13
holding days (mean avg): 4.3      holding days (median): 2.0
real 0m16.730s
user 0m0.634s
sys 0m0.297s

Hm...the results look very good indeed. 171 trades in 4,5 years equals roughly a buy or sell every 3 days (on average, I did not analyze the orderbook). That fits my requirements for a system I could trade in my spare time- firing it up every morning or evening. This is definitely something I will look into further.

Critizism on Methodology

Some words of caution, though. Although I am pretty sure that my program does well with the signal generation part, and the calculation and tracking of the volatility stops, I can't be 100% sure for now. I am very bad at programming and I am human. Although I try to test and verify every bit of code, humans create bugs.

<Edit:> As mentioned, I asked someone about his opinion about my methology and results, especially that they look too good to be true. Part of his feedback was, that I indeed chose a couple of markets, which had some pretty good trends in the given timeframes. I didn't do that on purpose, but looks I applied a kind of bias here. To make this point clearer, I grabbed some weekly charts from investing.com:

  • EURUSDEURUSD
  • N225N225
  • SPXSPX
  • daxdax
  • goldgold

I should have though about that, but didn't. Now that I know, it´s easy to make a query how the 5 markets performed individually for each year (the specific command is documented under /docs or following this link: Ichinscratchy database structure):

+------+--------+-------------------+---------------+
| year | symbol | Profit by percent | nr. of trades |
+------+--------+-------------------+---------------+
| 2012 | DAX    |           -0.0265 |             2 |
| 2012 | EURUSD |           -0.0082 |             1 |
| 2012 | N225   |            0.1309 |             3 |
| 2012 | SPX    |            0.0465 |             4 |
| 2013 | DAX    |           -0.0374 |            10 |
| 2013 | EURUSD |            0.0531 |             5 |
| 2013 | Gold   |            0.5257 |            12 |
| 2013 | N225   |            0.1196 |             2 |
| 2013 | SPX    |            0.1237 |            10 |
| 2014 | DAX    |            0.1824 |            12 |
| 2014 | EURUSD |            0.0453 |             8 |
| 2014 | Gold   |            0.2512 |             9 |
| 2014 | N225   |            0.0705 |             8 |
| 2014 | SPX    |           -0.0036 |             4 |
| 2015 | DAX    |            0.1551 |             4 |
| 2015 | EURUSD |            0.1630 |             9 |
| 2015 | Gold   |            0.1904 |            10 |
| 2015 | N225   |            0.0419 |             5 |
| 2015 | SPX    |            0.0587 |            15 |
| 2016 | DAX    |            0.1605 |             6 |
| 2016 | EURUSD |            0.0591 |            11 |
| 2016 | Gold   |           -0.0255 |             5 |
| 2016 | N225   |            0.1836 |             4 |
| 2016 | SPX    |            0.1041 |             5 |
+------+--------+-------------------+---------------+

Do the same, but this time sum up all markets to show each year`s performance:

+------+-------------------+---------------+
| year | Profit by percent | nr. of trades |
+------+-------------------+---------------+
| 2012 |            0.1427 |            10 |
| 2013 |            0.7847 |            39 |
| 2014 |            0.5458 |            41 |
| 2015 |            0.6092 |            43 |
| 2016 |            0.4819 |            31 |
+------+-------------------+---------------+

So, indeed a pretty strong bias to trending markets. See the addition a the end of this article for the results of some additional backtests on not-so-well trending markets. <End Edit>

On the upside I can state that I did not use the recently introduced portfolio allocation algorithm (so here all positions are equally weighted). That brings me to the most prominent deficiency of my trading system in its current state: the program has no idea about currencies, equity or even a concept of "trading account". All above presented statistics are based only on the percent that were gained or lost for each particular trade. Basis for that is the market, and it´s price on the day a position is bought/sold.The percentages do NOT represent a increase/decrease of actual money as at the moment the system has no idea what a DAX30 of 12387,43 has to do with money.

Especially the Drawdown is calculated by summing up the percentages of losing trades. So everything might look completely different when translating that into an account working with real money (even to the point that percentage wise it looks still manageable but depending on position sizes a real-money account could be broke already).

Simulating equity of a virtual account

To help myself understand above (<edit>: the out-of-sample tests with the original 5 markets <end edit>) results, and somewhat counter my own critizism, I fired up a spreadsheet and did kind of a backwards-simulation as if those trades were really executed using CFD (with reasonable settings, for example DAX: 1 point = 1 €, starting capital 10.000 Euro, trading costs/slippage per trade -5% of the results).

This results in a pretty nice equity curve:

simlated equity

Because I`d like to keep this as transparent as possible, I made said spreadsheet also available, look at the very last download.

The graph looks absolutely impressive, what do you think? I really would like to hear my readers opinions, critizism, tipps on what I did and how I did it.

Edit: Backtests on not-so-well-trending markets

As mentioned I recieved the advice to try some markets that did not perform so well in the past. Namely 3 markets were mentioned: Corn Futures, Wheat Futures and EUR/HUF.

I grabbed some data, but this time first took a look at the charts (click to enlarge):

Corn Futures:

corn

EUR/HUF:

corn

Wheat Futures:

corn

Just by looking at the above, my stomach says that the EUR/HUF should perform horribly with a trend following system, while the first/last should be ok-ish.

Long story short, the results:

Corn:

+------+-------------------+---------------+
| year | Profit by percent | nr. of trades |
+------+-------------------+---------------+
| 2012 |            0.1772 |             4 |
| 2013 |            0.3032 |            11 |
| 2014 |            0.0139 |             8 |
| 2015 |            0.2904 |            10 |
| 2016 |            0.1450 |             6 |
+------+-------------------+---------------+

EUR/HUF:

+------+-------------------+---------------+
| year | Profit by percent | nr. of trades |
+------+-------------------+---------------+
| 2012 |            0.0276 |             5 |
| 2013 |            0.0197 |             5 |
| 2014 |           -0.0144 |             8 |
| 2015 |           -0.0165 |             7 |
| 2016 |           -0.0239 |             6 |
+------+-------------------+---------------+

Wheat:

+------+-------------------+---------------+
| year | Profit by percent | nr. of trades |
+------+-------------------+---------------+
| 2012 |            0.0488 |             6 |
| 2013 |            0.0988 |            14 |
| 2014 |           -0.0130 |             4 |
| 2015 |           -0.0041 |             7 |
| 2016 |           -0.0527 |            13 |
+------+-------------------+---------------+

Conclusion: I indeed influenced the outcome of my testing by chosing a couple of good trending markets. This was by chance, not on purpose. However:

Lesson learned: think about some kind of additional long-term trend filter that can switch certain markets on/off.

<End Edit>

Comments powered by CComment