どんな記事
この記事では、何となく「優位性を向上」してくれそうなこと(移動平均線を2本か ら3本にすることなど)が、「必ずしもそうなるとは限らない」ということの一例を、数字とともに解説します。
タートルズ流 投資の魔術 からの引用
まずは、「トリプル移動平均」について書かれている箇所を、書籍「伝説のトレーダー集団 タートルズ流投資の魔術」から引用します。
このシステムは150日、250日、350日の3つの移動平均を用いる。売買は150日移動平均が250日移動平均とクロスしたときに行われ、より長い350日移動平均はトレンドフィルターとして使われる。
短い2つの移動平均が長い350日移動平均と時価に対して同じ側にあるときのみ、取引が生じる。どちらも350日移動平均 より高ければ、買い持ちトレードが、どちらも低ければ売り持ちのみが可能だ。
ダブル移動平均システムと異なり、このシステムは、つねには市場にとどまらない。150日移動平均が250日移動平均とクロスして下に抜ければ、取引は手じまいとなる。
この記事は、上記の手法をTradingViewで再現することを目的としたものです。
ストラテジーを作成
エントリーとイグジット
買いエントリー
- 「EMA150 と EMA250 が EMA350 より上に位置」「EMA150 と EMA250 のゴールデンクロス(上抜け)」で買いエントリー
- 「EMA150 と EMA250 のデッドクロス(下抜け)」で決済
売りエントリー
- 「EMA150 と EMA250 が EMA350 より下に位置」「EMA150 と EMA250 のデッドクロス(下抜け)」で売りエントリー
- 「EMA150 と EMA350 のゴールデンクロス(上抜け)」で決済
バックテスト
同じ条件で手法を比べるために、以下の「基本条件」でテストしていきます。
バックテストの基本条件
期間
- 2005年1月1日 ~ 2017年12月31日(12年間)
資金 管理
- 単利
銘柄
為替 | USDJPY、EURJPY、GBPJPY、CHFJPY、CADJPY |
株価指数 | NKY日経225、DJI NYダウ、DAXドイツ、UKXイギリスFTSE、HSI香港ハンセン |
日本株 | 6098リクルート、4452花王、5711三菱マテリアル、7201日産、9984ソフトバンクグループ |
米株 | AAPLアップル、AXPアメリカン・エクスプレス、BAボーイング、JNJジョンソン・エンド・ジョンソン、MCDマクドナルド |
海外商品 | 金、白金、原油、コーン、大豆 |
手法は、市場との相性があるケースも多いので、主要な各市場 から5銘柄ずつピックアップしてテストしています。
テスト1
まずは、本に掲載されていたものと同じ設定でバックテストをしてみます。
テスト1 設定
EMA-s | EMA-m | EMA-l | Pyramiding |
---|---|---|---|
150 | 250 | 350 | None |
テスト1 結果
損益 | 最大DD | 取引数 | 勝数 | 勝率 | RR比 | |
---|---|---|---|---|---|---|
Total | 182 | 76 | 41.76% | 2.044 | ||
USDJPY | 34.95 | 13.95 | 7 | 3 | 42.86 | 3.350 |
EURJPY | 33.83 | 2.31 | 5 | 4 | 80.00 | 3.906 |
GBPJPY | 141.89 | 0.00 | 4 | 4 | 100.00 | - |
CHFJPY | -2.91 | 20.03 | 8 | 3 | 37.50 | 1.478 |
CADJPY | 22.42 | 8.71 | 6 | 5 | 83.33 | 0.715 |
NKY | 7414.47 | 3618.14 | 6 | 3 | 50.00 | 2.444 |
DJI | 4457.57 | 3498.32 | 5 | 3 | 60.00 | 1.516 |
DAX | 2146.54 | 3958.66 | 8 | 4 | 50.00 | 1.399 |
UKX | -350.80 | 2079.70 | 9 | 5 | 55.56 | 0.692 |
HSI | -33.59 | 8738.95 | 7 | 2 | 28.57 | 2.490 |
6098 | -181.50 | 181.50 | 1 | 0 | 0.00 | - |
4452 | 2662.00 | 801.00 | 6 | 3 | 50.00 | 3.390 |
5711 | -855.00 | 3275.00 | 10 | 2 | 20.00 | 3.222 |
7201 | -426.30 | 878.30 | 12 | 4 | 33.33 | 1.152 |
9984 | 1826.00 | 1405.00 | 10 | 4 | 40.00 | 2.458 |
AAPL | 20.64 | 18.80 | 6 | 3 | 50.00 | 1.461 |
AXP | 58.04 | 0.00 | 4 | 4 | 100.00 | - |
BA | 50.98 | 25.05 | 6 | 3 | 50.00 | 2.242 |
JNJ | -17.88 | 55.33 | 14 | 2 | 14.29 | 4.463 |
MCD | 38.81 | 7.56 | 5 | 2 | 40.00 | 6.997 |
GOLD | 90560.00 | 31640.00 | 6 | 3 | 50.00 | 3.862 |
PLATINUM | -4425.00 | 26475.00 | 6 | 3 | 50.00 | 0.874 |
WTI | -8130.00 | 59510.00 | 10 | 2 | 20.00 | 3.501 |
CORN | 6975.00 | 6475.00 | 8 | 3 | 37.50 | 2.595 |
SOY BEANS | -75550.00 | 75550.00 | 13 | 2 | 15.38 | 0.817 |
テスト1 統計
破産の確率 | 期待値/リスク | 収益の見込み |
---|---|---|
0.00% | 0.271 | 49.311 |
破産の確率は、損失の許容=2%で算出しています。期待値と収益の見込みは以下の計算式で算出しています。
「期待値」は、悪くはないですが長期の手法にしては低めな印象です。取引回数が少なく「収益の見込み」もあまり良くないですね。
テスト2
次に、ピラミッティングを試してみます。
テスト2 設定
EMA-s | EMA-m | EMA-l | Pyramiding |
---|---|---|---|
150 | 250 | 350 | 1-ATR 上限4 |
初回を含めて、4回エントリーします。
テスト2 結果
損益 | 最大DD | 取引数 | 勝数 | 勝率 | RR比 | |
---|---|---|---|---|---|---|
Total | 622 | 277 | 44.53% | 1.845 | ||
USDJPY | 154.21 | 41.00 | 22 | 10 | 45.45 | 4.170 |
EURJPY | 81.23 | 19.85 | 20 | 11 | 55.00 | 3.595 |
GBPJPY | 514.12 | 0.00 | 16 | 16 | 100.00 | - |
CHFJPY | -56.85 | 105.08 | 30 | 7 | 23.33 | 1.869 |
CADJPY | 71.03 | 15.20 | 21 | 16 | 76.19 | 1.629 |
NKY | 25819.01 | 11524.95 | 23 | 12 | 52.17 | 2.120 |
DJI | 21681.43 | 7793.57 | 16 | 12 | 75.00 | 1.261 |
DAX | 18369.38 | 7587.00 | 23 | 16 | 69.57 | 1.330 |
UKX | -2910.80 | 8199.90 | 32 | 17 | 53.13 | 0.622 |
HSI | -13905.68 | 46240.35 | 28 | 8 | 28.57 | 1.748 |
6098 | -621.50 | 621.50 | 3 | 0 | 0.00 | - |
4452 | 11851.00 | 1622.00 | 19 | 11 | 57.89 | 4.267 |
5711 | -8765.00 | 17415.00 | 38 | 8 | 21.05 | 2.186 |
7201 | -1966.20 | 3261.20 | 41 | 14 | 34.15 | 0.865 |
9984 | 4634.00 | 6863.00 | 35 | 12 | 34.29 | 2.598 |
AAPL | 50.69 | 111.05 | 23 | 12 | 52.17 | 1.148 |
AXP | 217.09 | 0.00 | 16 | 16 | 100.00 | - |
BA | 264.12 | 54.52 | 18 | 12 | 66.67 | 2.160 |
JNJ | -23.65 | 178.58 | 39 | 8 | 20.51 | 3.440 |
MCD | 138.63 | 45.71 | 18 | 8 | 44.44 | 4.700 |
GOLD | 368200.00 | 72030.00 | 19 | 12 | 63.16 | 3.565 |
PLATINUM | -37405.00 | 109275.00 | 21 | 12 | 57.14 | 0.537 |
WTI | -72050.00 | 270280.00 | 31 | 8 | 25.81 | 2.132 |
CORN | 6187.50 | 29787.50 | 30 | 12 | 40.00 | 1.667 |
SOY BEANS | -219787.50 | 219787.50 | 40 | 7 | 17.50 | 0.776 |
- 「取引回数」 182 → 622
- 「勝率」 41.76 → 44.53
- 「RR比」 2.044 → 1.845
勝率アップ、RR比はダウン。しかし、取引回数が増えているので「収益の見込み」はまったく問題ないでしょう。『「破産の確率」がアップしないか』と、『「期待値」がダウンしないか』に注目です。
テスト2 統計
破産の確率 | 期待値/リスク | 収益の見込み |
---|---|---|
0.00% | 0.267 | 166.045 |
破産の確率は、損失の許容=2%で算出しています。期待値と収益の見込みは以下の計算式で算出しています。
- 「期待値」 0.271 → 0.267
- 「見込み収益」 49.311 → 166.045
「破産の確率」は上昇せず、「期待値」もほとんど低下せず、「見込み収益」は大幅アップ。手法を改善する施策としては完璧です。あとは「ドローダウン」とか「コンスタントに安定して収益を上げられるか」とかを確かめる必要がありますが、TradingViewではちょっとむずかしいかもしれないですね。
考察
移動平均線を2本から3本に増やすことは、何となく「優位性を向上」してくれそうな気がしますが、「必ずしもそうとは限らない」ということですね。
このことは、言われてみれば誰しも「そりゃあそうだ」と思うことですが、そういう人に限って「わりとやりがち」なことだと思います。優位性を向上させるつもりが、逆効果になってしまうんですね。
- イメージだけで実践してしまう
- 検証のサンプルが少ない(銘柄、期間、足種など)
- そもそも優位性についての理解が足りない
こういうことがあると、逆効果になります。
「2」についてはいくつかアプローチがあって、特定の銘柄のクセに合わせて組み立てるとしたらサンプルを限定しても良いケースもあります。いずれにしても過剰な最適化には注意が必要だと思います。
Pineスクリプト
今回行ったバックテストに用いたストラテジーのコード(Pineスクリプト)を公開します。販売や二次配布以外は自由にご利用いただいて差し支えありません。ご自由にお使いください!
strategy("Strategy Turtle Triple EMA"
,default_qty_type=strategy.fixed
,default_qty_value=1
,pyramiding=4
,overlay=true)
src = close
S = input(150 ,minval=1 ,title="short_")
M = input(250 ,minval=1 ,title="middle_")
L = input(350 ,minval=1 ,title="long_")
MAX_N = input(1 ,type=integer ,minval=1 ,maxval=4 ,title="maximun num of unit")
LO_len = input(20 ,type=integer ,minval=1 ,title="pyramiding ATR length")
LO_N = input(1 ,type=float ,minval=0.5 ,title="pyramiding ATR*N")
fromYear = input(2005 ,type=integer ,minval=1900 ,title="test start")
endYear = input(2017 ,type=integer ,minval=1900 ,title="test end")
isWork = timestamp(fromYear ,1 ,1 ,00 ,00) <= time and time < timestamp(endYear+1 ,1 ,1 ,00 ,00)
S_ = ema(close ,S)
M_ = ema(close ,M)
L_ = ema(close ,L)
atr_LO_ = ema(tr ,LO_len)
atr_LO = atr_LO_*LO_N
countTradingDays = na
countNonTradingDays = na
countTradingDays := strategy.position_size==0 ? 0 : countTradingDays[1] + 1
countNonTradingDays := strategy.position_size!=0 ? 0 : countNonTradingDays[1] + 1
entry1 = close
entry2 = close
entry3 = close
entry4 = close
entry1 := strategy.position_size==0 ? na : entry1[1]
entry2 := strategy.position_size==0 ? na : entry2[1]
entry3 := strategy.position_size==0 ? na : entry3[1]
entry4 := strategy.position_size==0 ? na : entry4[1]
lo2 = close
lo3 = close
lo4 = close
lo2 := strategy.position_size==0 ? na : lo2[1]
lo3 := strategy.position_size==0 ? na : lo3[1]
lo4 := strategy.position_size==0 ? na : lo4[1]
L_EntrySig = S_ >= M_ and S_ >= L_ and M_ >= L_
S_EntrySig = S_ <= M_ and S_ <= L_ and S_ <= L_
lo_sig2 = strategy.position_size>0 ? lo2 < high : strategy.position_size<0 ? lo2 > low : na
lo_sig3 = strategy.position_size>0 ? lo3 < high : strategy.position_size<0 ? lo3 > low : na
lo_sig4 = strategy.position_size>0 ? lo4 < high : strategy.position_size<0 ? lo4 > low : na
if(strategy.position_size != 0)
L_ExitSig = S_ <= M_ and strategy.position_size > 0
S_ExitSig = S_ >= M_ and strategy.position_size < 0
strategy.close_all(when = L_ExitSig or S_ExitSig)
if(L_ExitSig or S_ExitSig)
entry1 := na
entry2 := na
entry3 := na
entry4 := na
lo2 := na
lo3 := na
lo4 := na
if(strategy.position_size > 0)
if(lo_sig2 and MAX_N >= 2)
lo2 := na
strategy.entry("L-Entry2" ,strategy.long ,comment="L-Entry2")
if(lo_sig3 and MAX_N >= 3)
lo3 := na
strategy.entry("L-Entry3" ,strategy.long ,comment="L-Entry3")
if(lo_sig4 and MAX_N >= 4)
lo4 := na
strategy.entry("L-Entry4" ,strategy.long ,comment="L-Entry4")
if(strategy.position_size < 0)
if(lo_sig2 and MAX_N >= 2)
lo2 := na
strategy.entry("S-Entry2" ,strategy.short ,comment="S-Entry2")
if(lo_sig3 and MAX_N >= 3)
lo3 := na
strategy.entry("S-Entry3" ,strategy.short ,comment="S-Entry3")
if(lo_sig4 and MAX_N >= 4)
lo4 := na
strategy.entry("S-Entry4" ,strategy.short ,comment="S-Entry4")
if((L_EntrySig or S_EntrySig) and isWork and strategy.position_size==0)
countTradingDays := 0
entry1 := close
if(L_EntrySig)
strategy.entry("L-Entry1" ,strategy.long ,comment="L-Entry1")
lo2 := MAX_N >= 2 ? close + atr_LO : na
lo3 := MAX_N >= 3 ? close + atr_LO * 2 : na
lo4 := MAX_N >= 4 ? close + atr_LO * 3 : na
if(S_EntrySig)
strategy.entry("S-Entry1" ,strategy.short ,comment="S-Entry1")
lo2 := MAX_N >= 2 ? close - atr_LO : na
lo3 := MAX_N >= 3 ? close - atr_LO * 2 : na
lo4 := MAX_N >= 4 ? close - atr_LO * 3 : na
plot(strategy.position_size ,transp=0 ,title="保有ポジションの数")
plot(strategy.openprofit ,transp=0 ,title="未決済の損益")
plot(strategy.netprofit ,transp=0 ,title="決済済みの損益")
plot(strategy.closedtrades ,transp=0 ,title="決済済み取引数")
plot(countTradingDays ,transp=0 ,title="取引日数")
plot(countNonTradingDays ,transp=0 ,title="ノンポジ日数")
plot(entry1 ,title="entry1" ,color=blue ,transp=0 ,style=linebr)
plot(lo2 ,title="lo2" ,color=red ,transp=0 ,style=linebr)
plot(lo3 ,title="lo3" ,color=red ,transp=0 ,style=linebr)
plot(lo4 ,title="lo4" ,color=red ,transp=0 ,style=linebr)
plot(atr_LO ,transp=0 ,title="ATR_LO")
plot(L_ ,color=#303F9F ,title="長期EMA" ,style=line ,linewidth=2, transp=0)
plot(M_ ,color=#4CAF50 ,title="中期EMA" ,style=line ,linewidth=2, transp=0)
plot(S_ ,color=red ,title="短期EMA" ,style=line ,linewidth=2, transp=0)
TradingViewでも公開しています!
TradingViewのインジケーターの検索で「Turtle Triple」と検索するとでてきます。上記のコードと同じストラテジーを使用することができます。
バックテストならTradingView
TradingViewのテストは大変便利で、
- かなり自由の効くバックテストを
- 短時間で簡単に、
- 価格データを用意することなく
- 豊富な銘柄と足種を対象に
行うことができます。
一方で、その簡便さと引き換えに「TradingViewではできないバックテスト」も多くあります。
たとえば「分散投資」や「資金管理」があげられますが、これらは投資において非常に重要な要素でもあり、これらを含めたバックテストをするならリアルさが不可欠です。こういったバックテストをするためには、やはりPythonなどのプログラミング言語で自作していくしかないと考えています。
とはいえ、TradingViewが便利であることは間違いなく、最近では、手法の検証はTradingViewで行い、良い手法が見つかったら更に詳細なテストをPythonで行うようにしています。できるものはTradingViewでサクサクやってしまいます。
わりと、30分くらいあればインジケーターを作成することもできます。便利。
- 記事をシェア