「売買システム入門」トゥーシャー・シャンデ〜ストラテジ検証① SMA65CC3

このエントリーをはてなブックマークに追加

Intel Core-i9は12コアってPentiumを経験してきた世代としては信じられないです。AMDもRyzen8コアのCPUを出してたんですね。ここのところVPS環境での作業がメインなのでPCいじりとは疎遠なのですが、少しさわってみたい衝動に駆られました。

さて、このサイトはRubyでバックテストツールを作成し様々なストラテジーを検証することを目的としています。前回の記事で作成したツールのチュートリアルを兼ねてテストを行いましたので、いよいよストラテジーの検証に入っていきたいと思います。

最初に検証していくのは「売買システム入門〜金融工学の考え方→作り方→評価法」著トゥーシャー・シャンデに紹介されているストラテジーです。

この本では、シンプルなストラテジーの説明から始まって、騙しシグナルのためのフィルターに対する検証、ストップロスの効果についての検証、資金管理方法についての検証など、ストラテジー構築に必要な要素が網羅されています。私も追随しながら何回かに分けて検証を行っていきたいと思います。

今回検証を行うのは65SMA-3CCトレンドフォローシステムとして紹介されているシステムです。一番はじめに紹介されている最適化のされていないシステムとなります。

検証を行ってみると、このままのシステムでは使えんだろうなぁという結果が得られました。

それでは順次見ていきましょう。

目次

実践

65SMA-3CCとは

65SMA-3CCシステムでは、トレンドの転換を確認するために65日間単純移動平均線(65SMA)より上や下で3日連続して引ける(3CC)ことを条件とする。

トゥーシャー・シャンデ『売買システム入門』(PanRolling、2000年)

と説明されています。やけにシンプルですね。

ストラテジーの構築

きれいなコードでかけませんね。Noneをわざわざ定義しなけりゃいけないあたりが、微妙な感じで。

n日検定用と、本番用のコードです。それぞれexample/back_test/strategy1-1に有るコードからの抜粋です。

  • n日検定
class Sma65Cc3
  def initialize(n)
   @n = n    
  end  
  def decide(env)  
    code = env[:code]
    date = env[:date]  
    closes = env[:closes] 
    open = env[:open]  
    position = env[:position] 
    aves = closes[-67..-1].ave(65)
    is_buy = 3.times.inject(true) do |ret, i|
    ret = ret and (closes[-i-1] > aves[-i-1]) 
    end
    if not position.nil? and position.buy? 
      if position.term >= @n
        Action::Sell.new(code,date,open,1)   
      else
        Action::None.new(code)
      end
    else 
      if is_buy 
        Action::Buy.new(code,date,open,1) 
      else
        Action::None.new(code)  
      end 
    end 
  end 
end
  • SMA65CC3
class Sma65Cc3

  def decide(env)
    code = env[:code]
    date = env[:date]
    closes = env[:closes]
    open = env[:open]
    position = env[:position]

    aves = closes[-67..-1].ave(65)
    is_buy = 3.times.inject(true) do |ret, i|
      ret = (ret and (closes[-1-i] > aves[-i-1]))
    end

    is_sell = 3.times.inject(true) do |ret, i|
      ret = (ret and (closes[-1-i] < aves[-i-1]))
    end

    if not position.nil? and position.buy?
      if is_sell
        Action::Sell.new(code,date,open,2)
      else
        Action::None.new(code)
      end
    elsif not position.nil? and position.sell?
      if is_buy
        Action::Buy.new(code,date,open,2)
      else
        Action::None.new(code)
      end
    else
      if is_buy
        Action::Buy.new(code,date,open,1)
      elsif is_sell
        Action::Sell.new(code,date,open,1)
      else
        Action::None.new(code)
      end
    end
  end
end 

n日検定

解説を進める前に65SMA-3CCの仕掛ける方法がランダムな方法と比べて有効だと言い切れるかをチェックする重要な検証を行ってみよう。ルビューとルーカス(詳細は参考文献の欄参照)のアプローチ法に従い、この仕掛ける方法にn日後の大引けで仕切るという条件を加えて検証してみよう。ストップロスは使用せず、スリッページと手数料もないものと仮定する。

トゥーシャー・シャンデ『売買システム入門』(PanRolling、2000年)

シャンデ氏に習って私も同じことをしてみます。複数の市場を用いて行っていますが、私の手元には日本市場のものしかありません。加えてこのツールは、まだ株式の分割・統合の対応を行っていないので、闇雲に銘柄をピックアップすると結果が無意味となる場合があります。そこで、33業種別株価指数を用いて検証することにします。指数は、K-Db様のサイトよりダウンロードさせていただきます。下記コマンドにて皆様の環境にも準備することができます。ただし、1アクセスごとに10秒間のスリープを設けているので、時間はかかると思います。

git pull
bundle exec ruby exe/setup.rb
bundle exec rake db:seed
bundle exec ruby exe/index_setup.rb

シャンデ氏の著書では1975年〜1995年の間で入手可能な英ポンド、コーヒー、日本円、S&P500、国債など21のマーケットデータを使って検定が行われています。N日後手仕舞のNは5,10,15,20,30,50が用いられ、それぞれの勝率の業種間平均は55%を上回るものだと記されています。この55%を上回るってところがこの検定のキモのようです。

2007〜2017年の期間で、33業種別株価指数を用いて検定を行った結果は下記です。

bundle exec ruby example/back_test/strategy1-1/n_kentei.rb
code 5 10 15 20 30 50
I201 0.57 0.58 0.56 0.53 0.53 0.57
I202 0.51 0.47 0.43 0.40 0.54 0.50
I203 0.58 0.53 0.51 0.59 0.48 0.66
I204 0.56 0.52 0.47 0.54 0.50 0.53
I205 0.57 0.56 0.54 0.56 0.55 0.52
I206 0.52 0.50 0.55 0.49 0.52 0.50
I207 0.56 0.56 0.63 0.59 0.61 0.57
I208 0.56 0.52 0.56 0.53 0.56 0.50
I209 0.50 0.56 0.53 0.51 0.44 0.44
I210 0.49 0.48 0.47 0.44 0.43 0.49
I211 0.55 0.53 0.54 0.57 0.57 0.51
I212 0.52 0.50 0.48 0.53 0.55 0.47
I213 0.57 0.52 0.53 0.60 0.55 0.51
I214 0.59 0.51 0.57 0.53 0.52 0.51
I215 0.57 0.58 0.56 0.59 0.62 0.65
I216 0.55 0.57 0.54 0.56 0.58 0.64
I217 0.52 0.56 0.52 0.51 0.53 0.48
I218 0.53 0.53 0.51 0.51 0.56 0.46
I219 0.52 0.58 0.54 0.58 0.52 0.61
I220 0.48 0.48 0.45 0.45 0.42 0.52
I221 0.49 0.50 0.46 0.45 0.38 0.44
I222 0.55 0.55 0.54 0.50 0.57 0.47
I223 0.52 0.46 0.49 0.53 0.48 0.42
I224 0.49 0.50 0.47 0.45 0.46 0.47
I225 0.48 0.44 0.48 0.49 0.46 0.44
I226 0.53 0.56 0.55 0.54 0.54 0.50
I227 0.57 0.53 0.54 0.55 0.48 0.44
I228 0.49 0.48 0.48 0.52 0.51 0.42
I229 0.50 0.50 0.51 0.50 0.48 0.42
I230 0.52 0.50 0.52 0.53 0.49 0.50
I231 0.49 0.54 0.49 0.54 0.52 0.46
I232 0.51 0.48 0.51 0.49 0.46 0.45
I233 0.54 0.55 0.55 0.59 0.57 0.55
0.53 0.52 0.52 0.52 0.51 0.50  

微妙ですね。先に進めてみましょう。

検証

買いのみなのか売りもありなのか本文から汲めなかったので売りありで検証を行ってみました。著書の中では売買コストに100ドルを設定してありますが、私の検証ではコストは0です。著書の表と同じように出してみたつもりですが、集計で意味あるのってプロフィットファクターと勝率だけだと思います。

結果はさんさんたるものです。勝率は平均して30%。トレンドフォローであるのならばこの辺なのでしょう。プロフィットファクターは平均0.9なんで優位性は全くありません。ここに取引コストを加味されるのですから、とても使えるものではありません。

code net income trades win pf average dd
I201 159.96 63 0.32 1.38 2.54 -137.61
I202 -614.11 79 0.27 0.64 -7.77 -550.86
I203 -513.45 72 0.24 0.66 -7.13 -389.4
I204 -1294.94 90 0.13 0.49 -14.39 -848.49
I205 -41.89 66 0.27 0.96 -0.63 -157.73
I206 -213.75 73 0.27 0.75 -2.93 -210.31
I207 -236.23 72 0.19 0.89 -3.28 -558.33
I208 77.81 74 0.38 1.03 1.05 -872.83
I209 361.21 69 0.28 1.17 5.23 -594.46
I210 -2962.06 87 0.17 0.55 -34.05 -2786.72
I211 9.51 74 0.24 1.0 0.13 -410.62
I212 373.69 71 0.3 1.24 5.26 -413.2
I213 8.81 66 0.32 1.0 0.13 -250.29
I214 -195.77 66 0.26 0.9 -2.97 -319.01
I215 27.06 64 0.27 1.01 0.42 -488.34
I216 1283.03 60 0.32 1.53 21.38 -384.72
I217 887.11 60 0.28 1.23 14.79 -1075.7
I218 -2274.93 68 0.22 0.72 -33.45 -1933.22
I219 60.13 56 0.32 1.02 1.07 -1490.11
I220 183.9 59 0.31 1.21 3.12 -205.26
I221 -2117.07 84 0.19 0.43 -25.2 -1602.8
I222 465.29 59 0.31 1.3 7.89 -455.35
I223 41.74 61 0.28 1.08 0.68 -207.15
I224 -1060.79 80 0.23 0.65 -13.26 -1061.65
I225 -799.62 40 0.28 0.53 -19.99 -647.42
I226 -719.74 80 0.25 0.73 -9.0 -340.07
I227 -381.61 75 0.27 0.73 -5.09 -298.31
I228 5.14 75 0.27 1.01 0.07 -65.49
I229 148.02 66 0.29 1.11 2.24 -247.4
I230 -299.08 72 0.22 0.85 -4.15 -464.03
I231 226.39 63 0.29 1.21 3.59 -216.29
I232 75.7 59 0.27 1.02 1.28 -645.36
I233 -413.32 59 0.27 0.77 -7.01 -616.77
  -295.3 68.0 0.3 0.9 -3.6 -634.7

本来であれば、なぞって作ったシステムを同じデータを使って著書の結果が得られるのかを再現しなければならないのですが、データがないのでってことで確認はしません。

確かに理想的なトレードをしている局面もあります。

profit_histgram

profit_histgram

まとめ

2007年から2017年の業種別株価指数を用いて検証を行いました。この期間は序盤ダダッさげの相場で後半盛り返す、お椀型のチャートを形成しています。業種によってどの程度盛り返すのかってところで差異はありますが、基本的に変わりません。下げあり、上げありヨコヨコありと見ようによってはいいサンプルかもしれませんが、もう少し幅を広げてサンプルをえらべば結果は変わるのかもしれません。

あるいは、株式を取りまく環境の変化によってこの手法はすでに有効でなくなった可能性もあります。

2007〜2017の日本市場においてSMA65CC3という非常にシンプルな手法は有効とは言い難いという結果が得られました。次回も引き続きこの本になぞってすすめ、SMA65CC3に改良を加えていこうと思います。

Recent Entries
Categories
    Tags
    Archives
    Search