【MQL5】 MT5のEA作成の勉強 その14 EA運用開始からの総損益 / ロスカット処理

【MQL5】 MT5のEA作成の勉強 その14 EA運用開始からの総損益 / ロスカット処理

まえがき

 前回の投稿では一旦MQL5から離れてMT5の使い方を学習しましたが、今回はまたMQL5の勉強に戻りたいと思います。今回のテーマは「ロスカット」です。紛らわしいですが、今までの投稿でも触れてきた、「損切」や、一定の損失が出た際の「逆指値注文」は「ストップロス」と呼ばれ、EAの戦略の一環として、個々のポジションの損失を抑えるために組み込まれるものです。対して、ロスカットはEAによる損失が一定以上になった場合に、EAそのものを強制終了する仕組みです。ロスカットの発動は、「このEAを使い続けるともっと損するからやめましょう」と宣言するに等しいので、EA開発者を目指すものとしては出来ればお世話になりたくない機能です。しかし、万が一の場合に口座資金が全損したりしては目も当てられないので、EAに実装しておくべき基本機能といえるでしょう。
 簡単かと思っていたんですが、どえらい苦労しました・・・(-_-;)。どえらい苦労した理由ですが、私がロスカットを「EA運用開始からの(約定含む)総損失が一定水準を超えたとき」に起こるものと思っていたからです。良く調べてみると、EAにおけるロスカットは「現在の証拠金にたいするEAの含み損の割合」で考えることが多いようです。(EAによっては証拠金の額を事前に指定する機能を持つものあります。)含み損を対象とする場合の実装はさして難しくありませんでした。
 とはいえ、もったいないので、検討した内容も忘れずにメモしておきたいと思います。運用開始からの総損益を取得する方法は何かの役に立つかもしれませんし。

検討した方法

 ロスカットを導入するためには、それまでのEAの損益を取得する必要があります(と最初は思っていました)。最初に、大まかなプランとして、以下の3パターンを考えました。

  1. 決済注文の直前に、CPositionInfoProfitを取得し、逐次加算してゆく。
  2. Processingメソッド内に、過去の取引データをすべて取得し、その損益を合算する処理を加える。
  3. OnTradeTransactionメソッド内に、取引の損益を取得する関数を加え、逐次加算してゆく。

 ですが、どのパターンにも問題があり、検討は困難を極めました。

決済注文の直前に、CPositionInfoProfitを取得し、逐次加算してゆくプラン(失敗)

 これは、取引の損益を取得するために、過去の取引データや、サーバーの取引ステータスにアクセスする必要が無いので、極めて分かりやすい上に効率的な方法です。しかし、この方法では、利食い・損切ラインに到達し、サーバー側で決済処理が行われた場合、その結果を反映できないという問題があり、断念しました。

Processingメソッド内に、過去の取引データをすべて取得し、その損益を合算する処理を加えるプラン (失敗)

  Processingメソッド内 、即ち、OnTickメソッド内で取引の判定処理を行う前に過去の取引データをすべて取得し、その損益を合算します。過去の確定したデータを基にしている為、誤差が発生しない(上記の決済注文前のポジション損益を取得する方法では、通信遅延などの影響で、EA側で想定した損益と実際の取引損益に誤差が生じる可能性があります。)のと、実装が簡単なのが利点です。HistorySelectメソッドの説明ページにかなり役に立つサンプルソースがありました。
 ただし、この方法はティックの度に履歴データにアクセスするため、長期間EAを運転した場合、負荷がかなり大きくなります。1年程度は問題ないようでしたが、数年、十数年となると、ティック内に処理が終わらない可能性が出てきます。

OnTradeTransactionメソッド内に、取引の損益を取得する関数を加え、逐次加算してゆくプラン (間違い)

 取引サーバーは、なんらかの取引が行われるたびに、その内容やステータスを送信してきます。それを受け取った瞬間(TradeTransactionイベント発生)に起動するのが OnTradeTransactionメソッドです。ここで引数として受け取った取引内容やステータスから、 損益を算出し、合計損益に合算してゆこうという趣旨です。
 こちらも、 OnTradeTransactionメソッド のページに大変役に立つサンプルソースがありますので、それを参考に進めました。
  OnTradeTransactionメソッド には3つの引数がありますが、取引の情報が格納されているのは、主にMqlTradeTransactionです。この中のtypeが「TRADE_TRANSACTION_DEAL_ADD」の場合、取引が約定されたことを意味します。この時、HistoryDealSelectに約定された取引のチケットと「DEAL_PROFIT」を渡すことで、約定された取引の損益を得ることができます。グローバル変数に「HistoricalProfit」を定義し、これにその都度加算してゆくことで、約定済み取引の総損益を取得することができます。後は、ナンピンの実装の時に学んだ方法で、オープンポジションの総損益を取得し、合算してあげれば、約定済み取引の損益と現在の含み損益の合計を取得できるわけです。

【MQL5】 MT5のEA作成の勉強 その12 ナンピンを実装する ( 2 / 2 )

EA運用開始から現時点までの約定済み損益+現在の含み損益を取得

ということで一区切りとしたいと思います。
 実装した処理で、初期証拠金10000USD、ロスカットは初期証拠金の20%の設定でバックテストしたところ、以下のような結果になりました。ちゃんと20%減の8000USD付近で処理が停止しています。その下の内訳でも、「総損益」が20%の2000ドル以内で抑えられています。

実現損益+含み損益でロスカットした場合

まとめ – 結局、ロスカットはどうしたのか –

 冒頭でも書きましたが、EAにおけるロスカットは「現在の含み損が、証拠金のn%以上になったらEAを強制停止」という定義で使われることが多いようです。従って、上記の総利益を基準とした考え方は間違っていると言えます。現在の含み損益の取得は上記でも紹介したナンピン実装の時に学んだ方法で実現でき、現在の口座残高(証拠金額)はCAccountInfoBalanceプロパティで取得できます。 この方法でロスカット処理を実装したところ、以下のような結果になりました。(含み損を大きくするため、上記とはパラメーターの設定を変えています)下記の例では損失が出ていますが、含み損のみをロスカット基準とする場合、実現損益がロスカットに設定した額(割合)を超えた時点で元本割れはなくなるというのが嬉しいですね。

含み損益のみでロスカットした場合


 次回からは、いよいよインジケータの使い方を学び、有利な取引条件を検討してゆきたいと思います。