前回は、講座記事第86回~91回までに解説してきた待機注文のクラス・関数を利用した待機注文専用のシンプルEAを制作し、その記述について解説しました。↓
今回からは、トレーリングストップについて解説していきたいと思います。
まずはそもそもトレーリングストップとは何か?という解説から始めていき、何回かに分けて、ミニマムプロフィットやステップ幅などの基本概念をお伝えして、最終的にはトレーリングストップ用のクラスを作る所まで解説していきます。
ボリュームのある内容ではありますが、今回の記事を含めた一連のトレーリングストップに関する講座記事を読んで学んで頂ければ、トレーリングストップをMQL5でかなり自在に扱えるようになると思いますので、是非楽しみにして頂ければと思います。
※トレーリングストップに関する今後の講座記事は以下のような進行になっています。
- MQL5 EA講座 第94回「トレーリングストップにおけるミニマムプロフィットについて」
- MQL5 EA講座 第95回「トレーリングストップにおけるステップ幅について」
- MQL5 EA講座 第96回「トレーリングストップクラスを作る1」
- MQL5 EA講座 第97回「トレーリングストップクラスを作る2」
- MQL5 EA講座 第98回「動的トレーリングストップについて」
- MQL5 EA講座 第99回「ブレイクイーブンストップについて」
- MQL5 EA講座 第100回「ブレイクイーブンストップ関数を作る」
トレーリングストップとは?
保有しているポジションが想定している方向に動き始めたとき、最初に設定している損切り価格を、(利益を確保できる方向に)変更する一連の処理
のことを指します。
簡単に言えば、
買いポジションだったら損切価格を引き上げる、
売りポジションだったら損切価格を引き下げる、
ということになります。
相場が、自分の想定している方向に動いていて一時期利益が出ていたのに、その後リミット(=利益確定価格)に到達する前に逆行して、結局ストップロスにかかり、損切になってしまった・・・
という事態を避けるために、相場が仮に逆行しても最低限の利益は確保しよう、という投資戦略に基づいた処理になります。
シンプルな仕組みのトレーリングストップ
トレーリングストップも、突き詰めていくと色々な方法があるとは思いますが、まずは極めてシンプルな形のトレーリングストップの仕組みを見ていきましょう。
トレーリングストップは銘柄の現在値が想定する方向(利益を生む方向)に向かった時、ストップロス価格も利益を生む方向に修正する、というのが原則です。
トレーリングストップを算出する為の値をinput変数でパラメータ化する
その為、まずはその修正する価格を計算する値をinput変数で予め用意しておくのが一般的です。↓
input int TrailingStop = 500;//トレイリンストップを設定する
↑のサンプルコードでは初期値を「500」としています。
これに定義済み変数「_Point」を掛け算すると、価格ベースでの値が算出されます(3桁通貨ペアであれば0.5、5桁通貨ペアであれば0.005が導き出されます)
※input変数については↓の記事をご覧ください
買いの場合であれば、現在値(Bid)から上記の値(TrailingStop*_Point)を引いた価格と、ストップロスに設定されている価格を比較して、現在値(Bid)が、現在のストップロスより価格が上回っているようならストップロス価格を修正します。
売りの場合であれば、現在値(Ask)から上記の値(TrailingStop*_Point)を足した価格と、ストップロスに設定されている価格を比較して、現在値(Ask)が、現在のストップロスより価格が下回っているようならストップロス価格を修正します。
コード記述にすると概ね以下のような形になります。↓
//パラメータ
input int TrailingStop = 500;//トレイリンストップを設定する
-----------------------------------------------------------
void OnTick()
{
if(PositionSelectByTicket(pTicket) == true && TrailingStop > 0)
{
request.action = TRADE_ACTION_SLTP;
request.position = ポジション番号;
long posType = PositionGetInteger(POSITION_TYPE);//ポジションタイプ
double currentStop = PositionGetDouble(POSITION_SL);//ストップロス価格
double currentLimit = PositionGetDouble(POSITION_TP);//テイクプロフィット価格
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);//ポジションの始値
string symbol = PositionGetString(POSITION_SYMBOL);//取引銘柄
double point = SymbolInfoDouble(symbol,SYMBOL_POINT);//ポイント
double trailStop = TrailingStop* point;//トレーリングストップポイント
double trailStopPrice;//トレーリングストップ価格
if(posType == POSITION_TYPE_BUY)
{ //トレーリングストップ価格を算出
trailStopPrice = SymbolInfoDouble(symbol,SYMBOL_BID) - trailStop;
if(trailStopPrice > currentStop)
{
request.sl = trailStopPrice;//
OrderSend(request,result);
}//if(trailStopPrice > currentStop)
}//if(posType == POSITION_TYPE_BUY)
else if(posType == POSITION_TYPE_SELL)
{
trailStopPrice = SymbolInfoDouble(symbol,SYMBOL_ASK) + trailStop;
if((trailStopPrice < currentStop)
{
request.sl = trailStopPrice;
OrderSend(request,result);
}
}
}
ポジション選択とトレーリングストップ値の設定有無を確認する
一番最初の
if(PositionSelectByTicket(pTicket) == true && TrailingStop > 0)
は、「ポジションの選択ができて、トレーリングストップの値が指定されている」という意味です。
このif文がtrueであれば、トレーリングストップの設定を執行する{}内の記述に移ります。
<参照>
トレーリングストップ算出に必要な値を取得する その1
{
request.action = TRADE_ACTION_SLTP;
request.position = ポジション番号;
long posType = PositionGetInteger(POSITION_TYPE);//ポジションタイプ
double currentStop = PositionGetDouble(POSITION_SL);//ストップロス価格
double currentLimit = PositionGetDouble(POSITION_TP);//テイクプロフィット価格
MqlTradeRequest構造体の各メンバ変数に値を設定していきます
ストップロスに修正を加えるので.actionには「TRADE_ACTION_SLTP」が入ります。
※過去の記事で何回か書いている事ではありますが、まだ指値価格に到達しておらず、ポジション保有に至っていない待機注文の変更をしたい時に使うTRADE_ACTION_MODIFYを用いないよう注意しましょう。
メンバ変数.position には ポジション番号が代入されます(ポジション番号を格納した変数が記述されるのが一般的でしょう)
ポジション種類が買いか、売りかを取得するにはPositionGetInteger関数の引数に定数値「POSITION_TYPE」を記述します。取得出来た値を変数「posType」に格納します。
現在のストップロス価格を取得するにはPositionGetDouble関数の引数に定数値「POSITION_SL」を記述します。取得出来た値を変数「currentStop」に格納します。
現在のテイクプロフィット価格を取得するにはPositionGetDouble関数の引数に定数値「POSITION_TP」を記述します。取得出来た値を変数「currentLimit」に格納します。
トレーリングストップ算出に必要な値を取得する その2
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);//ポジションの約定価格
string symbol = PositionGetString(POSITION_SYMBOL);//取引銘柄
double point = SymbolInfoDouble(symbol,SYMBOL_POINT);//ポイント
double trailStop = TrailingStop* point;//トレーリングストップポイント
double trailStopPrice;//トレーリングストップ価格
引き続き、トレーリングストップに必要な値を取得し、変数に格納していきます。
トレーリングストップ値を設定するには、ポジションの約定価格を知らないといけません。
ポジションの約定価格はPositionGetDouble関数の引数に定数値「POSITION_PRICE_OPEN」を記述します。取得結果を変数「openPrice」に格納します。
取引銘柄情報はPositionGetString関数の引数に定数値「POSITION_SYMBOL」を記述します。取得結果を変数「symbol」に格納します。
input変数「TrailingStop」で定めた値を価格情報に変換する為にポイント情報を取得します。
ポイント情報はSymbolInfoDouble関数の第2引数に定数値「SYMBOL_POINT」を記述します。取得結果を変数「point」に格納します。
この変数「point」に格納された値とinput変数「TrailingStop」の値を掛け算した値が、トレーリングストップのたたき台となります。計算結果を変数「trailStop」に格納します。
そして最終的なトレーリングストップ価格を格納する、double型の変数「trailStopPrice」を宣言します。
トレーリングストップの注文を出す(買いの場合)
if(posType == POSITION_TYPE_BUY)
{ //トレーリングストップ価格を算出
trailStopPrice = SymbolInfoDouble(symbol,SYMBOL_BID) - trailStop;
if(trailStopPrice > currentStop)
{
request.sl = trailStopPrice;//
OrderSend(request,result);
}//if(trailStopPrice > currentStop)
}//if(posType == POSITION_TYPE_BUY)
ポジションタイプが買いだった場合の記述に移ります。
買いの場合のトレーリングストップ価格はBid-変数「trailStop」の値で求まります。
Bidの価格はSymbolInfoDouble関数の第2引数に定数値「SYMBOL_BID」を記述することで取得出来ます。
SymbolInfoDouble(symbol,SYMBOL_BID) – trailStopの計算結果を最終的なトレーリングストップ価格を格納する、double型の変数「trailStopPrice」に格納します。
if(trailStopPrice > currentStop)は、
現在設定されているストップロス価格よりトレーリングストップ価格の方が上回っている状態を指しますから、トレーリングストップを発動させるべくrequest.sl に変数「trailStopPrice」の値を代入します。
OrderSend関数の引数にMqlTradeRequest構造体、MqlTradeResult構造体のインスタンスrequest,resultをそれぞれ設定して買いのトレーリングストップ設定は終了です。
トレーリングストップの注文を出す(売りの場合)
else if(posType == POSITION_TYPE_SELL)
{
trailStopPrice = SymbolInfoDouble(symbol,SYMBOL_ASK) + trailStop;
if(trailStopPrice < currentStop)
{
request.sl = trailStopPrice;
OrderSend(request,result);
}
}
}
続いてはポジションタイプが売りだった場合の記述です。
売りの場合のトレーリングストップ価格はAsk+変数「trailStop」の値で求まります。ちょうど買いの場合と逆ですね。
Askの価格はSymbolInfoDouble関数の第2引数に定数値「SYMBOL_ASK」を記述することで取得出来ます。
SymbolInfoDouble(symbol,SYMBOL_ASK) + trailStopの計算結果を最終的なトレーリングストップ価格を格納する、double型の変数「trailStopPrice」に格納します。
if(trailStopPrice < currentStop)は、
現在設定されているストップロス価格よりトレーリングストップ価格の方が下回っている状態を指しますから、トレーリングストップを発動させるべくrequest.sl に変数「trailStopPrice」の値を代入します。
OrderSend関数の引数にMqlTradeRequest構造体、MqlTradeResult構造体のインスタンスrequest,resultをそれぞれ設定して売りのトレーリングストップ設定は終了です。
シンプルな形のトレーリングストップは以上のようなプロセスを経て実現します。
まとめ
今回はトレーリングストップとは何か?という概要部分と、トレーリングストップの基本となるコード記述について解説しました。
ただし、今回解説したのはあくまで基本的なものであり、実践で用いていくには少し物足りませんし、挙動にも不備が残ります。もう少し色々な要素を足していく必要があります。
次回はトレーリングストップにおけるミニマムプロフィットと、ステップ幅という概念について解説しし、それをコードの中に取り入れていこうと思います。
※なお、トレーリングストップについては、記事カテゴリー:EA制作お役立ち記事内にて以下↓のような記事も過去に書いていますので宜しければ参考にして頂ければと思います。
今回は以上とさせていただきます。
最後までお読みいただきありがとうございました。