ここでは、EAお悩み相談で預かったOverHeatというEAに対して行ったロジックの変更をする過程が現在EAを作成している多くの開発者さんに役に立つ内容だと思ったので公開しています。
また、後半ではEAを作る上での押さえておくべき基本事項を説明します。
※この記事はシストレファクトリー開発部より寄稿されました。
マーチンゲール法と複数ポジションの相性は最悪
まず、ロットとポジションについて理解しておいて欲しいことがあります。
マーチンゲール法とは、1回負けたらロットをx倍し、また負けたらさらにx倍、これを勝つまで続けるというロット計算方法です。
この方法は、コイントスで表と裏を当てるゲームで必勝法としてよく挙げられますが、コイントスというゲームが示すとおり、エントリーと勝敗が常に一対一の関係にあることが前提となる方法です。つまり、エントリーがあり、勝敗が決し、次のエントリーがあり、また勝敗が決する場合に使われます。
しかしマーチンゲール法を複数ポジション前提のEAで使おうとすると、非常に大きな問題を引き起こします。次の例を考えてみてください。
初期ロットを0.01、マーチンゲール倍率を2倍で考えます。
最初のエントリーをします。(エントリー1、ロット0.01)
- エントリー1が決済されていないうちに、2つ目のエントリーが入ります。(エントリー2、ロット0.01)
- エントリー1とエントリー2が決済されていないうちに、3つ目のエントリーが入ります。(エントリー3、ロット0.01)
- エントリー1、エントリー2、エントリー3が同時に損切になります。
- エントリー4のロットを計算します。エントリー1~3が損切になっているので、3敗です。エントリー4のロットは0.01×2×2×2=0.08です。
人間の心理からいくと、損切になった時点では「1敗」です。エントリー4は0.01の2倍の0.02で入ると思いますよね。
それか100歩譲って3エントリーで合計0.03ロット負けたんだから0.06で入ってもらいたいかもしれない。しかし、残念ながら現在のロジックでは0.08でのエントリーになってしまいます。これは利用者側からしたら「バグだ」と言われてもおかしくないです。この先も考えてみましょう。
- エントリー4が入ります。(エントリー4、ロット0.08)
- エントリー4が決済されていないうちに、エントリー5が入ります。(エントリー5、ロット0.08)
この時点でもうやばいですよね。前回までは合計0.03ロットだったのに、すでに0.16ロットです。
- エントリー4、エントリー5、が同時に損切になります。
- エントリー6のロットを計算します。エントリー4、5が損切になっているので、2敗です。エントリー6のロットは0.08×2×2=0.32です。
この時点で、人間的には2敗です。なのにロジックとしては5敗が計上されています。
人間的には3つ目のエントリー、想定では0.04ロットで入って欲しいエントリーが、初期ロットの32倍というロットでエントリーされてしまいます。
以上が、「マーチンゲール法」と「複数ポジション」の相性が悪い理由です。
もちろん「マーチンゲール法」と「複数ポジション」を同時に使うアイデアも考えられますが、少なくとも今のままのロット計算ではダメでしょう。そこで、まず「最大ポジション数」のパラメータを1に固定し、変更できないようinputを外しました。
また、開発時点ではマーチンゲール法の倍率は1.0固定で開発を進めます。マーチンゲール法によるロットの操作は、獲得利益を増大させるためのもので、勝敗に直接つながるロジックではないからです。開発中からここをいじってしまうと、ロジックにより勝てているのか利益が増大された結果勝てるように見えているのかわからなくなってしまいます。
ロジックの改良
まずはプロフィットファクター1.0以上を目指す
バックテストの結果にはいろいろな情報が出てきます。勝率、純益、取引数、ドローダウン…
見るべき情報は多いですが、最初から全部見ててもどうしたらいいかわからなくなるだけです。
そもそも、勝てるEAというのは、バックテスト期間中で 利益>損失 になるものです。そこで、まずはプロフィットファクターが1.0以上になることを目指します。
プロフィットファクターとは、総利益÷総損失の値です。たとば利益が100万円で損失が80万円だったらプロフィットファクターは1,000,000÷800,000=1.25となります。
OverHeatのプロフィットファクターは0.78
決済ロジックに違和感
OverHeatの決済ロジックは「MACDがライン超過かつデッドクロス」というものでした。
しかし、バックテスト結果のチャートを眺めていても、MACDのデッドクロス+ライン上で決済という条件が、良いところで決済できているとは言えず、優位性を見つけることができませんでした。このロジックを使う理由が説明できません。
バックテストの結果が右肩下がりということは、このロジック自体に優位性がなさそうです。
そこで、決済条件を「EMAにタッチしたら決済」に変更しました。
このロジックを選んだ理由は、OverHeatのエントリーロジックが順張りであることから、決済ロジックはトレンドの転換を目安にするのが良いと思い、現在価格がEMAに触れたらトレンド転換と考えられるのでふさわしいのではないかと思ったからです。
決済ロジックのMACDを、EMAタッチに書き換えます。
この状態でバックテストを行い、チャートを確認しました。
うまくトレンドを追って、トレンド転換で決済できた例
負けエントリーも、EMAにタッチしたところで決済されている
これだけで、パフォーマンスがだいぶ変わりました。プロフィットファクターが0.78から0.91まで改善しています。
ただ、これでもまだ利益はでません。引き続きチャートをよく観察すると、変更後のロジックではEMAに近いところで何度も何度もやられてることに気づきました。
この関係か、連敗数もかなり増えています。まだ負けている原因はここにありそうです。
EMAに近いところでエントリーすると即損切になることが多い
そこで、エントリーの条件に「EMA近くではエントリーしないようにする」というエントリーフィルターを追加することにしました。
このロジックは、「エントリー時の現在価格がエンベロープの上下ラインの中にある場合はエントリーしない」という内容を追加することで実現することができます。
白い線がエンベロープ。この間ではエントリーしないようにすれば改善するんじゃないだろうか。
まずはエンベロープの標準偏差を設定するパラメータを準備します。エンベロープの期間はEMAと同じものにするため、パラメータは用意せずp_EMAPeriodを流用します。
続いて、価格がエンベロープの中にあるかどうかを判定する関数を作ります。
そしてこれをエントリーロジックに追加します。
そしてバックテストを行いました。
目論見通りです。連敗数は減り、プロフィットファクターは1.0をギリギリ超えました。希望が見えてきました。
満を持してロット操作を追加
今回はお客様からのご相談でEAの修正を引き継いだのみですので、OverHeatの精神を必要以上に変更してはいけません。
これ以上ロジックを触るとあまりにも別物になりそうな気もするので、ロジックの変更はここで止めました。まぁ本当の理由はこのEAにあまり時間がかけられないというのもありますが。(本来であればまだまだチャートを隅々まで確認し、連敗数を減らしたりする余地があります。)
そこで、一旦無効にしていたマーチンゲール法を試すことにしました。現状でトントンの結果が出せるなら、マーチンゲール法にすることで利益を増やせるのではないかと考えたためです。
ただし、マーチンゲール法の倍率を安易に2.0にするのはいけません。ロットを倍々で増やしたら、10連敗もすればいくら金があっても全額飛びます。このEAは現時点で15連敗ほどをする記録があります。確実に飛びます。そこで、控えめに1.2くらいに設定して試してみましょう。
バックテストを行います。
利益が増えました。こんなにうまくいくとは思わなかったのでニヤニヤが止まりません。
ここまで作れたら、あとは最適化をすればそれなりのバックテスト結果が出せるようになります。
本当はEMA設定とEnverope設定のみの最適化をするつもりだったのですが、間違えてMACD設定も最適化項目に含めてしまったことに気づかず最適化を始めてしまい、それに気づいたのが翌朝で残り時間101時間と表示されていて絶望しました。
最適化をストップし、現時点での結果をプロフィットファクターで並び替えます。
プロフィットファクター1.93をたたき出しています。ただ、8年間のバックテストで取引数63は少なすぎます。年間8エントリーです。5分足なのですが・・・
そこで、上位の中でも取引数の多い3番目の結果を使うことにしました。パラメータを確認し、改めてバックテストします。
うん、よさげです。取引回数はまだ少ないですが、長期バックテストの結果としては悪くありません。
無事に右肩上がりになるよう修正できたので、ここで私の出番は終わりです。仕上げはOverHeatの開発者に任せることとしましょう。いろいろな条件で最適化を行い、EAを完成させてください。
EAを開発するときに意識すべきポイント
- 自分の考えたロジックを正しくソースコードに反映できるようにする
- バックテストの結果とチャートを分析し、ロジックのどこを改良すればいいか考える
順に説明していきます。
自分の考えたロジックを正しくソースコードに反映できるようにする
そもそも我々は、作りたいものが正しく反映されたソースコードを書く必要があります。
プログラムにバグが残っていたら、たとえそれで右肩上がりのグラフができたとしてもただの奇跡です。いつバグが爆発し大損害に繋がるかわかりません。
ロジックがソースコードに正しく反映されているというのは最低限の要求で、ここは確実に満たす必要があります。
そのためには、自分が作った関数が正しい結果を返すのか、逐一ちゃんと確認してください。今回で言えばEMAIncrease()に大きな問題がありました。関数を修正したら必ず先に関数の結果をテストする。面倒でも絶対にやってください。
今回ご相談のお客様は、コンパイルエラーが出ないようにプログラムを書きEAを完成させています。
そして、いざ完成しバックテストをすると結果が表示されない等の症状に直面し、そこでようやくソースコードのどこに問題があるかを探し始めるという手順でした。
しかしこれでは、自分が書いたソースコード全てを調べ間違いを探さなければならず、どこから手を付けたらいいかわからなくて思考が止まってしまう状態ではないでしょうか。
プログラムは、作ったそばから正しく作れているか確認するのが基本です。関数を作ったら正しいか確認する。エントリーロジックを書いたら正しいか確認する。エントリーが正しいとわかったら決済ロジックを書いてまた確認する。一発で正しいコードが書けるようになるまでは基本であるこれを忠実に行うべきですね。
そして、完成したEAはバックテストを流しグラフを見るだけではだめです。
バックテストのチャートを確認し、取引履歴と見比べ、自分のロジック通りに取引が行われているか絶対に確認してください。
自分のロジック通りに取引していなければ、そのEAが動いているとしてもそれは「バグを含んだEA」です。いつバグが爆発し大損害に繋がるかわかりません。
バックテストの結果とチャートを分析し、ロジックのどこを改良すればいいか考える
コードに問題がなく、バックテストも無事に結果が出ることを確認したら、ようやくパフォーマンスの改善です。
最初のバックテストで良いパフォーマンスが出なかったといって、やみくもにロジックを変えたりテクニカル指標を追加してはいけません。いきあたりばったりでは何も解決しません。
まずはバックテストのチャートを眺めてください。一つ一つの取引を確認してください。その取引は思ったとおりの場所でエントリーし、思った通りの流れで利益を増やし、思った通りのところで決済できていますか?
相場はそんな簡単に思った通りの動きをしてはくれません。
しかし、せめてチャートを確認して「ゴールデンクロスでエントリーしたいとは思ったけど、こんなヨコヨコのゴールデンクロスでエントリーするのは嫌だ」といった事実を見つけることが重要です。だってそれはあなたの思ったとおりのエントリーではないのですから。
チャートをじっくり確認してようやく「ヨコヨコでエントリーしないようにするにはどうすればいいのか」という課題が出現し、「相場のボラティリティを計測するATRをエントリーフィルターに使ったらどうだろう」という確かな解決法が出てくるのです。
これが適当にテクニカル指標を追加しようとすると「ヨコヨコでエントリーする」という課題に対し「RSIを追加する」という選択肢が出てきたりします。RSIは買われすぎ売られすぎを示すテクニカル指標です。ここで追加しようとするのは意味不明です。
まとめ
プログラムは一度に全部作ろうとしない
バグだらけになって自分の首を絞めるだけ。自分の書いたコードが正しく動作しているか逐一確認すべし。
プログラムの動作が正しいか確認する
バックテストの結果を精査し、自分の考えた通りの取引になっているか確認すべし。
「このロジックで勝てる」理由を説明できるEAを作る
説明するためには、机上の空論ではなく、実際にチャート等でそういう傾向があることを見せられるようにすべし。
闇雲にテクニカル指標を組み合わせようとしない
テクニカルを闇雲に2つ3つ掛け合わして最適化したところで、それは「たまたまそのパラメータとその期間で右肩上がりのグラフができただけ」にすぎないし、そもそもなぜそれで勝てるか説明できない。ちゃんと芯の通った解決法を探し出すべし。
今回は以上です。シストレファクトリーは、駆け出しの開発者さんが素晴らしいEAの開発ができることを応援しております。