「売買システム入門」〜ストラテジ検証② SMA65CC3 ロスカットの設定どうしてます?

前回に引き続き、「売買システム入門」に従い、SMA65CC3を使ってストラテジーの検証を行っていきます。

ところで皆さんはロスカットをどうやって設定していますか?仕掛けの有効性はN日検定を用いることで調べることが出来ると記されていることを前回紹介しました。売買システム入門にはロスカットの評価方法についても詳細に説明されています。今回はその辺について紹介していきたいと思います。

目次

ロスカットを追加する理由

バックテストを行っていると、最終収益はいいけども果たしてこのシステムは別のシステムに勝っているのか?と疑問になることが多々有ると思います。特にロスカットの設定は、追加することで利益が減ることが多いため、それなら追加しないほうが良いのか?などと考えることも有るかもしれません。

シャンデ氏はトレーディングシステムの基本原則なるものを6つほど上げていまして、その一つにこのようにあります。

3.トレーディング・システムのパラメータの数値は堅牢なものでなければならない。要するに様々な時間枠、多くの異なるマーケットで機能する必要がある。

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

そして、ロスカットの追加がこの堅牢性を高めているってことが幾つかのデータを使って提示されています。著書に習って検証を行って行きたいと思います。

MFEの調査

MFEとは最高到達地点と呼ばれるもので、ポジションを持っているときに経験した最大の含み益や含み損のことを言うようです。ちなみに、なんの略かは記されていなのでわかりません。そこまで翻訳してほしいものです。

このMFEを調べることでロスカットのどこに置くべきか当たりをつけることが出来るようになります。早速調べてみましょう。

前回と同じように33業種別株価指数を用いて検証を行いますが、前回は円ベースで集計を行っていたため、銘柄間の比較を行うことができませんでした。そこで今回は収益をパーセントで集計するように回収を加え、銘柄間の比較がもうちょっとマシな形で出来るようにさせています。ストラテジーも同じものを使います。まだロスカットルールは追加しません。

勝ちトレードの最大含み損と負けトレードの最大含み益を集計してヒストグラムにすると、下記のようになりました。

  • 勝ちトレードのMFE

profit_histgram

  • 負けトレードのMFE

profit_histgram

Y軸が対数なんで、ぱっと見線形ですが気をつけてください。

これを見ると、勝ちトレードの大半は1% の含み損しか経験しておらず、負けトレードの中には20%もの含み益を持っていたものがある、などということが解ると思います。

勝ちトレードのMFEを累積させて表示させてみます。最大値は勝ちトレード数になりますので、そこを100とします。

profit_histgram

こうしてみると、例えば-4%当たりにロスカットラインを設定したとしても、残りの9割の勝ちトレードには影響を与えないことがわかります。これは有益な情報でですね。

ストラテジーの構築

ここで行いたいのは、ストップロスを使用しなかった最初のシミュレーションと全く同じトレードについて検証することである。この目的を達成するためには、同じシグナルが続くことを避けるためのルールを設定し、最初のシグナルで損切りを余儀なくされた後に再び同じ方向のトレードが続かないようにすることである。

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

ということですので、これをコーディングしていきます。Ifが深くなるので、ネストを浅くしときます。

class Sma65Cc3StopLoss

  def initialize(loss_line)
    @loss_line = loss_line
    @loss_cut = false
  end

  def reset
    @loss_cutted = false
    @last_position = nil
  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[-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 position.nil? and not @loss_cutted
      if is_buy
        return Action::Buy.new(code,date,open,1)
      elsif is_sell
        return Action::Sell.new(code,date,open,1)
      else
        return Action::None.new(code,open)
      end
    end

    if position.nil? and @loss_cutted
      if  @last_position.buy? and is_sell
        reset
        return Action::Sell.new(code,date,open,1)
      elsif @last_position.sell? and is_buy
        reset
        return Action::Buy.new(code,date,open,1)
      else
        return Action::None.new(code,open)
      end
    end

    is_loss_cut = position.gain(closes[-1],1) < @loss_line

    if is_loss_cut
      @loss_cutted = true
      @last_position = position
      if position.buy?
        return Action::Sell.new(code,date,open,1)
      elsif position.sell?
        return Action::Buy.new(code,date,open,1)
      end
    end

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

必要に応じてgit pullしてください。

ロスカットの効果

では、実際にロスカットラインを-10%〜-1%に設定させながら、バックテストを行い、結果にどのような影響を及ぼすのかを見てみましょう。2007年〜2017年の33業種別株価指数を用いて、バックテストを行い、銘柄間で平均した収益と、最大ドローダウンをロスカットラインに対して表示してみます。ただし-11%のデータはロスカットを設定しなかった場合の値です。

profit_histgram

ロスカットラインが狭くなるに連れて収益とドローダウンが減少しているのが見て取れます。この辺は予想通りでしょう。

続いて、銘柄間の偏差を見てみます。

profit_histgram

ロスカットラインが狭くなると、偏差も減少していることがわかります。つまり、銘柄間のバラ付きが少なくなったということです。この辺がシステムの堅牢性の話につながるのでしょう。

勝ちトレード数はもちろん減少しますが、平均値はどうでしょうか?

profit_histgram

悪化していますね。 ここまでの検証はexample/back_test/strategy1-2/にコードがあります。

まとめ

SMA65CC3にロスカットルールを加えました。すると、収益や平均収益が減少しました。悲しい限りです。

一方で最大ドローダウンが減少し、銘柄間の偏差も減少することがわかりました。つまり、システムが堅牢になったといえます。そもそもマイナス収益ですが。

システムの堅牢性に対する認識の差が、どのシステムを良しとするかの分かれ目になりそうですね。

次回も引き続き「売買システム入門」を読み進めて行きます。次回は騙しシグナルのフィルタリングの効果について検証していきます。