「高勝率システムの考え方と作り方と検証」③紹介されている、押し目買いシステムがなかなか優良

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

前回は、指数を使わずに個別株価でシステムを評価すればパフォーマンスはマシになるのではないか?という仮定に対する検証を行い、確かにその通りのようだという結果を示しました。 今回も引き続き「高勝率システムの考え方と作り方と検証」の検証を行っていきます。

目次

実践

ルール

著書には次のようにあります。

1.トレード対象の銘柄は1株当たり5ドル以上で、200 日単純移動平均線を上回っていること。これによって、長期的な上昇トレンドであることが示される。

2.過去21 日(1カ月)での1日の平均出来高が少なくとも25 万株あること。これで、流動性がある銘柄であることが保証される。

3.100 日HV(ヒストリカルボラティリティ)の値が30 を超える(ヒストリカルボラティリティの定義については付録を参照のこと)。

4.10 日ADX(アベレージ・ディレクショナル・インデックス)の値が30 を超える(ADX の定義については付録を参照のこと)。

5.その銘柄が2日以上、続けて下げて引けていること。

6.今日、その銘柄はY期間移動平均線(Y=4、5、6)よりも少なくともX%(X=4%、5%、6%)下で引けること。この点については、具体例を見れば明らかになるだろう。

7.上のルールが満たされていれば、翌日に今日の終値よりもさらにZ%(Z=4~10%)下に指値を入れて買う。

8.3期間単純移動平均線を上回って引ける日に、終値で手仕舞う。

ローレンス・A・コナーズ他『高勝率システムの考え方と作り方と検証』(PanRolling、2014年)

前回もそうでしたが、場中や引けでのトレードが必要になるため、完全自動化を目指すのであればトレードシステムや、ブラウザの自動化などといったことが必要となります。今のところは手動でそういったことが出来るってことを前提にしておきます。

ストラテジーの構築

コードは下記のようになります。

class HvAdxPb < Strategy

    attr_accessor :closes, :z, :y, :x

    def initialize
      super
      @length = 201
      @t_price = nil
      @z = 0.04
      @y = 4
      @x = 0.04
    end

    def set_up
      super
    end

    def pass?
      super
    end

    def set_env
      super
      @t_price = nil
      if soks[-201..-1]
        @closes = Soks.parse(soks[-201..-2],:close)
        @open = soks[-1].open
        if soks[-1].low < soks[-2].close * (1-@z) and soks[-1].volume > @q / 3
          @t_price = (soks[-2].close * (1-@z)).to_i
        end
      end
    end

    def decide(env)
      if position.nil?
        return none if @t_price.nil?
      end
      if position
        ave = Soks.parse(soks[-3..-1], :close).ave(3)[-1]
        return none if ave > soks[-1].close
        return sell(soks[-1].close,@position.volume)
      else
        ave = closes.ave(200)[-1]
        return none if closes[-1] < ave

        hv = closes[-101..-1].log.dev(100)[-1] * Math.sqrt(365) * 100
        return none if hv < 30

        adx = soks[-25..-2].adx(10,14)[-1]
        return none if adx < 30

        diffs = closes[-3..-1].diff
        return none if not (diffs[-1] < 0 and diffs[-2] < 0)

        uave = closes[-@y..-1].ave(@y)[-1] * (1-@x)
        return none if closes[-1] > uave

        volume = calc_volume(@t_price,0.3)
        return buy(@t_price,volume)
      end
    end
  end
  • 終値 > 200日移動平均
  • ヒストリカルボラティリティ > 30
  • ADX > 30
  • 2日連続陰線
  • 4日移動平均からの乖離率 < -4%

だった場合に当日に前日比 -4%の位置で売買可能ならば買いを仕掛けます。つまり当日に取引があり、安値が前日比 -4%以下を満たしている場合となります。

チャートを書いて、確認をしておきます。

profit_histgram

問題なさそうですね。

ADXをRubyで実装したものが見当たらないので、ついでに紹介しておきます。このメソッドはArrayを継承しているクラスにあることを想定してます。

  def dx(length)
      result = []
      self.each_cons(length+1) do |values|
        pdm, mdm, tr = [], [], []
        values.each_cons(2) do |vs|
          pdm << vs[-1].high - vs[-2].high
          mdm << vs[-2].low - vs[-1].low
          if (pdm[-1] < 0 and mdm[-1] < 0) or pdm == mdm
            pdm[-1], mdm[-1] = 0, 0
          elsif pdm[-1] > mdm[-1]
            mdm[-1] = 0
          elsif pdm[-1] < mdm[-1]
            pdm[-1] = 0
          end
          tr << [vs[-1].high - vs[-1].low, vs[-1].high - vs[-2].close, vs[-2].close - vs[-1].low].max
        end
        ts, ps, ms = tr.sum, pdm.sum, mdm.sum
        pdi = ps / ts * 100
        mdi = ms / ts * 100
        result << (pdi - mdi).abs / (pdi + mdi) * 100
      end
      Soks[*result]
    end

    def adx(n,m)
      result = []
      self.dx(n).each_cons(m) do |dxs|
        result << dxs.sum / length
      end
      Soks[*result]
    end

検証

33業種別株価指数の構成銘柄66個を適当に選んでそれぞれのパフォーマンスを調べてみます。ほとんど取引は行われないため、取引がなかった銘柄については表示していません。期間は2007年から2017年とし、単利での結果です。

Code Income Trades Win PF Average DD
1720 20.92 4.0 100.0 0.0 5.23 0.0
2768 2.39 1.0 100.0 0.0 2.39 0.0
3048 -2.35 1.0 0.0 0.0 -2.35 -2.35
3103 6.56 1.0 100.0 0.0 6.56 0.0
3105 1.85 1.0 100.0 0.0 1.85 0.0
3110 -0.56 1.0 0.0 0.0 -0.56 -0.56
3436 2.96 1.0 100.0 0.0 2.96 0.0
3632 9.14 3.0 66.67 7.54 3.05 -1.4
3656 32.24 7.0 57.14 3.68 4.61 -10.34
4506 6.9 1.0 100.0 0.0 6.9 0.0
4902 -6.08 1.0 0.0 0.0 -6.08 -6.08
5411 1.19 1.0 100.0 0.0 1.19 0.0
5631 9.52 1.0 100.0 0.0 9.52 0.0
5901 -1.52 1.0 0.0 0.0 -1.52 -1.52
6101 29.6 2.0 100.0 0.0 14.8 0.0
7211 9.51 2.0 100.0 0.0 4.76 0.0
7832 8.58 2.0 100.0 0.0 4.29 0.0
8303 4.36 1.0 100.0 0.0 4.36 0.0
8306 3.82 1.0 100.0 0.0 3.82 0.0
8473 24.12 2.0 100.0 0.0 12.06 0.0
8515 -9.29 6.0 83.33 0.7 -1.55 -31.43
平均 2.3 0.6 76.5 0.2 1.2 -0.8
偏差 6.95 1.31 38.83 1.02 3.15 4.08

合計して40回程度しか取引をしていないので、これだけで判断はしきれませんが、勝率76%、平均1.2%とかなりパフォーマンスが高いことがわかります。

次に複利で対象銘柄を広げ、より実運用に近い形でバックテストを行ってみます。

対象銘柄はコードの若い順に並べて10個飛ばしに1つづピックアップし、初期資産は100万円とします。著書のルールにあった出来高も考慮することとします。

期間は2000年から2017年をもちいますが、200日の日足が必要になることから実際は2001年辺りからの取引となります。

結果は次のようになります。

======================================================
net income:               2912364.5999999973
profit | loss:            9023931.799999999    | -6111567.2
average:                  11511.322529644258
pf:                       1.5
max profit | max loss:    822393.0     | -526104.0
trades | wins | looses:   253     | 182     | 71
wins{%}                   71.9
max series of wins:       18
max series of looses:     6
average span{win}:        2
average span{loose}:      5
max drow down:            -1454140.8
======================================================

200回を超えるトレード回数であっても7割を超える勝率があるので、このシステムに対する信頼度は上がるのではないでしょうか?

次に損益曲線を見てみます。

profit_histgram

今年に入るまでかなり安定した成績であることが分かりますが、今年のドローダウンはちときついですね。

パフォーマンス悪化は、単に資金が増えたからってのでは説明しにくい減り方な気がします。

この本の発売は2014年ですので、手法が広まったことによるものなのかもしれません。

あるいは、このシステムは恐怖心からトレード機会が生まれるはずだという信念がもとになっているため、恐怖心に対する麻痺から、かなり下押してからでないとトレード機会が生まれにくくなっている、というような理由も考えられます。

まとめ

押し目を利用したシステムについて検証を行いました。かなり安定したシステムであることがわかりました。しかし、ここ最近パフォーマンスが悪化しているため、利用するにあたってはひとまずその原因究明が必要かもしれません。

ともあれ、何かと併用しながら運用するのに十分魅力的なシステムだと思います。

Recent Entries
Categories
    Tags
    Archives
    Search