まだ【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以上の含み益】
TSStartPipsは、グローバル関数で宣言して、
指定したPipsを入力出来るようにしましょう。
TSStartPipsは、トレールを開始する際の
「起動装置」的な役割を果たします。
例えば、TSStartPips(開始Pips)を
20pipsと指定した場合には、
「損益が+20pips以上の時に」
という条件式になります。
※profitは、ポジションごとの損益を計算した物。
※TSStartPipsは、価格に変換する必要があります。
【現在のSLが現在価格から指定〇〇pipsを引いた価格以下】
※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つ目の条件も満たします。
価格に変換: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)を
比較する事で制御する形になります。
「現在のSLが指定したSLと同じだったら」
トレールが発動する仕組みです。
トレール発動後は、SLの価格が変わるので
基本的には、1回しか発動しません。
ん?基本的には…???
実は、ある特定の条件を満たすと
複数回、発動してしまう場合があります。
150.000で買って、SLが50Pipsの時、
SLは、149.500円なわけですが…
トレール発動が30Pipsで
トレール幅が80Pipsだった場合…150.300円の時にトレールが発動し
SLが149.500円から移動しません。
この場合、トレールは複数回発動します。
まぁ、そもそもトレールの位置を
最初のSLと同じにする意味がないので
発動条件を事前に考慮しておけば、
実際には問題ないと思います。
更に、SLをセットしない場合も考慮すると
下記の様なコードに行き着きます。
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にも実装してみてください。
※もしトレイルを実装する際には、
必ずデモ口座等で動作確認行ってください。
コメント