【EA制作記】トレイリングストップを1回だけ発動する方法

【EA制作記】トレイリングストップを1回だけ発動する方法 EA
【EA制作記】トレイリングストップを1回だけ発動する方法

まだ【EA制作記】の前置きを読んでない方は、

必ず、下記リンクの記事を読んでから

再度、この記事に戻ってきてください。

 

【EA制作記】前置き ※必ず最初に読んでください※

 

今回は、オリジナル関数制作の依頼を受け、

トレイリングストップの関数を作った時の話です。

 

トレイリングストップって何?

トレイリングストップを知らない人に向けて

もの凄く簡易的に説明しておきますが、

エントリー後に特定の価格になったら

指値(StopLoss)を変動させる事を指します。

 

【例題】
150.000円でドル円を買い、
価格が150.200円まで上昇した場合に
StopLossを150.000にセットする。

 

こうする事で、相場が予想外の動きをして

ドル円が急に下がって来てしまったとしても

150.000で「損切り」になるので、

実質、±0pipsで取引を終了出来ます。

 

FXでトレードをした事がある方なら

必ずと言って良いほど誰もが通る道だと思います。

 

※トレイリングストップの基本概念

先ほどの【例題】でも説明した通り、

基本的には、利益が○○以上になったら

損切り位置を更新していく。というのが、

トレイリングストップの基本的な機能です。

 

この時、「現在の価格」に対して

指定したpips以上の位置にレートがあり、

セットした「損切り=SL」ラインよりも

相場の価格が上にある状態の時に、

常に「損切りライン」を更新する事で

リスクを限定しながら最大利益を伸ばす。

 

これが、トレイリングストップの魅力であり
最大利益の追求を可能にしてくれる機能です。

 

トレイリングストップを1回だけ行いたい

今回、依頼があった関数制作の内容は、

トレイリングストップを段階的に発動させて、

それぞれが各1回ずつしか実行しない。

更に、これを任意のpips毎に5段階で行う。

という少し変わった依頼内容でした。

 

1回しかSLが変動しないですし、

随時価格変動を追わないという面では、

「トレイリングストップの基本概念」から

外れてしまっている気もしますが…

 

「利益が○○pips以上で発動する」

 

という面を考えるとトレイルしてますし、

どの道、前回のSLよりも上に設定するので

「特殊なトレイリングストップ」

という扱いになると考えて取り組みました。

 

1回だけ実行させるには?

言うまでもない気もしますが…

今回の関数で一番ネックになったのは、

トレイリングストップを1度のみ実行する。

という、制御面での機能でした。

 

もう一度、基本的なトレイリングストップの

実行条件を下記に簡易コードと共に解説します。

※とりあえず、説明用に買いエントリーのみです。

 

【指定した〇〇pips以上の含み益】

profit >= TSStartPips

 

TSStartPipsは、グローバル関数で宣言して、

指定したPipsを入力出来るようにしましょう。

 

TSStartPipsは、トレールを開始する際の

「起動装置」的な役割を果たします。

 

例えば、TSStartPips(開始Pips)を

20pipsと指定した場合には、

「損益が+20pips以上の時に」

という条件式になります。

 

※profitは、ポジションごとの損益を計算した物。
※TSStartPipsは、価格に変換する必要があります。

 

【現在のSLが現在価格から指定〇〇pipsを引いた価格以下】

OrderStopLoss() < NormalizeDouble(Bid – TSPips, Digits()))

※NormalizeDoubleを使用して
価格の正常化を行っています。

 

少しややこしいかもしれませんが、

2つ目の条件式は、現在セットされているSLと

現在価格(Bid)から指定したpipsを

引いた価格を比較する事で判定します。

 

TSPipsは、トレール幅のPipsです。

例えば、TSPipsを30pipsと指定した場合は、

「現在セットされているSLが、

現在価格-30pips以下の場合に」

という条件式になります。

 

※TSPipsは、価格に変換する必要があります。

 

【2つの条件式を合わせる】

この2つの条件式を && で繋いだら、

トレーリングの条件が完了します。

 

トレール発動(TSStartPips)が20pips、

トレール幅(TSPips)が30pipsの場合は…

 

「現在の損益が+20pips以上で、

現在セットされているSLが、

現在価格-30pips以下の場合に」

トレールが発揚する事になります。

 

後は、OrderModify関数を使用して

SLを Bid – TSPips * xpoint に変更します。

売値(Bid)からトレールPipsを引きます。

 

if (profit >= TSStartPips * xpoint && 
    OrderStopLoss() < NormalizeDouble(Bid - TSPips * xpoint, Digits()))
{
res = OrderModify(
      OrderTicket(), 
      OrderOpenPrice(), 
      Bid - TSPips * xpoint, 
      OrderTakeProfit(), 
      0, 
      Green);
}

 

トレールのおさらい

先ほどの通常のトレールのおさらいです。

 

①現在の損益が+20pips以上出ていれば、
トレールの準備が完了します。

②そして、現時点でセットされているSLが
売値(Bid)より30pips以上低いと発動します。

 

【例題】
150.000円でドル円を買い、
価格が150.200円になったとします。
もし、エントリーの段階でSLを
セットしていなかった場合は、
149.900円にSLがセットされます。

 

次に、この状態から1Pips上昇すると

価格は、150.210円になります。

そして、SLは149.900円なわけですが、

150.210円-30Pipsは、149.910円となるので…

下記の2つ目の条件も満たします。

 

OrderStopLoss() < NormalizeDouble(Bid – TSPips, Digits()))

価格に変換:149.900 < 149.910

 

つまり、0.1Pipsでも有利な方向に動くと

常にトレールが発動するわけです。

 

1回だけ!1回だけで良いのに…

さて、基本的なトレールの解説は、

上記の段落で終了したので…

 

ここからが本題です。

 

トレールを1度のみ発動させるには、

いくつか方法があると思いますが、

簡単なのは下記の3つだと思います。

 

①特定のSLを使用する

②特定のTPを使用する

③スイッチ(オンオフ判定)

 

今回は、①をメインに解説します。

※②と③も最後に記載しておきます。

 

①特定のSLを使用する

 

1回だけ発動するという事は、

価格を追随する必要がないので

「1回しか条件を満たさない」

「何か」を使用する必要があります。

 

そこで、トレール発動前のSLを使用します。

デフォルトでSLをセットしている場合、

その値と現在のSLが同じ場合のみ

トレールを発動させるわけです。

 

【例題】
150.000で買いエントリー時、
SLを50Pipsでセットすると149.500です。

 

つまり、現在のSLと注文時のSL(149.500)を

比較する事で制御する形になります。

 

OrderStopLoss() == NormalizeDouble(OrderOpenPrice()-StopLoss_pips*xpoint,Digits()))

 

「現在のSLが指定したSLと同じだったら」

トレールが発動する仕組みです。

トレール発動後は、SLの価格が変わるので

基本的には、1回しか発動しません。

 

ん?基本的には…???

 

実は、ある特定の条件を満たすと

複数回、発動してしまう場合があります。

150.000で買って、SLが50Pipsの時、

SLは、149.500円なわけですが…

 

【例題】
トレール発動が30Pipsで
トレール幅が80Pipsだった場合…
150.300円の時にトレールが発動し
SLが149.500円から移動しません。
この場合、トレールは複数回発動します。

 

まぁ、そもそもトレールの位置を

最初のSLと同じにする意味がないので

発動条件を事前に考慮しておけば、

実際には問題ないと思います。

 

更に、SLをセットしない場合も考慮すると

下記の様なコードに行き着きます。

 

(OrderStopLoss() == 0 ||
OrderStopLoss() == NormalizeDouble(OrderOpenPrice()-StopLoss_pips*xpoint,Digits())))

 

「現在のSLがセットされてない、

もしくは、現在のSLが指定したSLと同じだったら」

トレールが発動する事になります。

 

if (profit >= TSStartPips * xpoint && 
    (OrderStopLoss() == 0 ||
     OrderStopLoss() == NormalizeDouble(OrderOpenPrice()-StopLoss_pips*xpoint,Digits())))
{
res = OrderModify(
      OrderTicket(), 
      OrderOpenPrice(), 
      Bid - TSPips * xpoint, 
      OrderTakeProfit(), 
      0, 
      Green);
}

 

②特定のSLを使用する

今回は、SLを比較する設計でしたが、

TPの場合でも考え方は同じです。

 

正直、一番手っ取り早いのは、

最初からTPをセットしておいて

(仮に不要な場合は大きいPipsにする)

トレール発動後に消す方法です。

 

if (profit >= TSStartPips * xpoint && 
    OrderTakeProfit() == NormalizeDouble(OrderOpenPrice()+TakeProfit_pips*xpoint,Digits()))
{
res = OrderModify(
      OrderTicket(), 
      OrderOpenPrice(), 
      Bid - TSPips * xpoint, 
      0, 
      0, 
      Green);
}

 

ただし、複数のポジションを保有して

成り行きではなくTPで利確を行う場合、

上記のコードだと干渉してしまうので

実装の際には注意が必要になります。

 

③スイッチ(オンオフ判定)

適当にbool型で変数を宣言して

スイッチとして使用する方法もあります。

 

bool trail_ok = true;
//---------------------------------------

if (profit >= TSStartPips * xpoint &&
    trail_OK == true)
{
res = OrderModify(
      OrderTicket(), 
      OrderOpenPrice(), 
      Bid - TSPips * xpoint, 
      0, 
      0, 
      Green);
trail_ok = false;
}

 

もし、複数ポジションで使用する場合、

1ポジション目でしか発動しないので

少し工夫する必要があると思います。

 

まとめ

今回は、需要があるか不明ですが(笑)

1回だけ発動するトレイリングを解説しました。

 

いかがだったでしょうか?

 

トレイリングは、なかなか奥が深く、

EA制作には欠かせない機能の1つです。

利益を追求する事で「損小利大」になったり、

「建値ストップ」としても使えたり…

 

ちょっと処理がややこしいのが難点ですが、

絶対に覚えておいて損はないので

是非、あなたのEAにも実装してみてください。

※もしトレイルを実装する際には、
 必ずデモ口座等で動作確認行ってください。

 

コメント

タイトルとURLをコピーしました