トレーリングストップ P181
トレーリングストップとは? P181
トレーリングストップは、ポジションの利益が増加するにつれて移動するストップロスです。買い注文の場合、トレーリングストップはポジションが利益を得るにつれて上昇し、売り注文の場合、トレーリングストップはポジションが利益を得るにつれて下落します。トレーリングストップが逆方向に動くことはありません。
トレーリングストップは通常、指定されたポイント数だけ現在の価格に従います。たとえば、トレーリングストップが500ポイントに設定されている場合、現在の価格がストップロス価格から少なくとも500ポイント離れると、ストップロスが動き始めます。最初に最小レベルの利益に到達することを要求することで、トレーリングストップを遅らせることができます。トレーリングストップは通常、ポイントごとに価格に従いますが、より大きな単位でストップを追跡することもできます。
簡単なトレーリングストップの実装方法を見てみましょう。トレーリングストップ価格を計算するには、現在のビッドまたはアスク価格からポイント単位でトレーリングストップを加算または減算します。ポジションの現在のストップロスと現在の価格との間の距離がトレーリングストップのポイント数よりも大きい場合、ポジションのストップロスを変更してトレーリングストップ価格に一致させます。
以下のコードは、単純なトレーリングストップをEAに追加します。このコードは、注文発注コードの下、OnTicke()イベントハンドラの末尾近くに配置されます。
//入力変数
input int TrailingStop =500;
//OnTicke()イベントハンドラ
if(PositionSelect(_Symbol) == true && TrailingStop > 0)
{
request.action = TRADE_ACTION_SLTP;
request.symbol = _Symbol;
long posType = PositionGetInterger(POSITION_TYPE);
double currentStop = PositionGetDouble(POSITION_SL);
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);
}
else if(posType == POSITION_TYPE_SELL)
{
trailStopPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK) + trailStop;
if(trailStopPrice < currentStop)
{
request.sl = trailStopPrice;
OrderSend(request, result);
}
}
}
TrailingStopという名前の入力変数を使用して、トレーリングストップをポイント単位で設定します。デフォルト値の500は、500ポイント(0.00500または0.500)のトレーリングストップを設定します。if演算子内のPositionSelect()関数は、現在のチャートシンボルにオープンポジションがあるかどうかを判断し、さらに処理するためにそのポジションを選択します。PositionSelect()関数がtrueを返し、TrailingStop設定が0より大きい場合、トレーリングストップのチェックに進みます。
request.action変数は、ポジションの変更を実行しているため、TRADE_ACTION_SLTPに設定されています。request.symbol変数は、現在のチャートシンボルを変更する位置として設定します。POSITION_TYPEパラメータを指定したPositionGetInteger()関数を使用して位置タイプを取得し、その結果をposType変数に格納します。現在のストップロスはPOSITION_SLパラメータを指定したPositionGetDouble()関数を取得され、currentStopに格納されます。TrailingStop入力変数を銘柄のポイント値で乗算することにより、価格値に変換します。この値をtrailStop変数に保存します。また、trailStopPriceという名前の変数も宣言します。この変数の値はすぐに計算します。
if-elseブロックは位置タイプをチェックします。ポジションが買いポジションの場合、現在のビッド価格からTrailStopを差し引いてトレーリングストップ価格を計算し、結果をTrailStopPrice変数に格納します。次に、currentStop変数に格納されている現在のストップロスと、trailStopPriceを比較します。トレーリングストップ価格が現在のストップロス価格よりも大きい場合、これはストップをトレーリングストップ価格に移動する必要があることを示します。request.sl変数はTrailStopPriceに設定され、OrderSend()関数はストップロスを変更します。
売りポジションの場合、トレーリングストップ価格(trailStopPrice)は、trailStop値を現在のアスク価格に追加することによって計算されます。トレーリングストップ価格が現在のストップロス価格よりも低い場合、ポジションのストップロスをトレーリングストップ価格に変更します。
最小利益 P183
単純なトレーリングストップにいくつかの変更を加えてみましょう。例えば、トレーリングストップは、最少額の利益が達成された後にのみ開始する必要があります。これを行うために、エキスパートアドバイザーに最小利益設定を追加します。まず、現在のポジションの利益をポイントで決定します。次に、これを最小利益設定と比較します。ポイントでのポジションの現在の利益が最小利益よりも大きい場合、トレーリングストップがアクティブになります。変更点は太字で強調表示されています。
//入力変数
input int TrailingStop = 500;
input int MinimumProfit = 200;
//OnTick()イベントハンドラ
if(PositionSelect(_Symbol) == true && TrailingStop > 0)
{
request.action = TRADE_ACTION_SLTP;
request.symbol = _Symbol;
long posType = PositionGetInteger(POSITION_TYPE);
double currentStop = PositionGetDouble(POSITION_SL);
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
double minProfit = MinimumProfit * _Point;
double trailStop = TrailingStop * _Point;
double trailStopPrice;
double currentProfit;
if(posType == POSITION_TYPE_BUY)
{
trailStopPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID) – trailStop;
currentProfit = SymbolInfoDouble(_Symbol, SYMBOL_BID) – openPrice;
if(trailStopPrice > currentStop && currentProfit >= minProfit)
{
request.sl = trailStopPrice;
OrderSend(request, result);
}
}
else if(posType == POSITION_TYPE_SELL)
{
trailStopPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK) + trailStop;
currentProfit = openPrice – SymbolInfoDouble(_Symbol, SYMBOL_ASK);
if(trailStopPrice < currentStop && currentProfit >= minProfit)
{
request.sl = trailStopPrice;
OrderSend(request, result);
}
}
}
MinimumProfitという名前の入力変数を追加しました。デフォルト値の200は、現在のポジションの最小利益が少なくとも200ポイント(0.00200または0.200)でなければならないことを意味します。POSITION_PRICE_OPENパラメータを指定したPositionGetDouble()関数を使用してポジションの始値を取得し、その結果をopenPrice変数に保存します。MinimumProfit設定を現在のシンボルの_Point値で乗算し、その結果をminProfit変数に格納することで価格に変換します。currentProfitという名前の変数が宣言され、すぐに計算されます。
現在のポジションが買いポジションの場合、現在のビッド価格から注文開始価格(openPrice)を引いて現在の利益を計算し、その結果をcurrentProfit変数に格納します。currentProfitがminProfitよりも大きく、現在のストップロス価格がトレーリングストップ価格よりも小さい場合、ストップロスを変更し、トレーリングストップ価格に設定します。
売りポジションの場合、注文の開始価格から現在のアスク価格を差し引いて、現在の利益を計算します。現在の利益が最小利益よりも大きく、現在のストップロス価格がトレーリングストップ価格よりも大きい場合、ストップロスを変更します。
トレーリングストップのステップ P184
トレーリングストップの最後の変更は、ステップ値を追加することです。上記のコードは、利益の方向への小さな価格変動ごとにトレーリングストップを変更します。これは、取引サーバーにとって少し圧迫感を引き起こす可能性があるため、最小ステップを10ポイントに制限し、ユーザーがより大きなステップ値を指定できるようにします。
//入力変数
input int TrailingStop = 500;
input int MinimumProfit = 200;
input int Step = 10;
//OnTick()イベントハンドラ
if(PositionSelect(_Symbol) == true && TrailingStop > 0)
{
request.action = TRADE_ACTION_SLTP;
request.symbol = _Symbol;
long posType = PositionGetInteger(POSITION_TYPE);
double currentStop = PositionGetDouble(POSITION_SL);
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
double minProfit = MinimumProfit * _Point;
if(Step < 10) Step = 10;
double step = step * _Point;
double trailStop = TrailingStop * _Point;
double trailStopPrice;
double currentProfit;
if(posType == POSITION_TYPE_BUY)
{
trailStopPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID) – trailStop;
currentProfit = SymbolInfoDouble(_Symbol, SYMBOL_BID) – openPrice;
if(trailStopPrice > currentStop + step && currentProfit >= minProfit)
{
request.sl = trailStopPrice;
OrderSend(request, result);
}
}
else if(posType == POSITION_TYPE_SELL)
{
trailStopPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK) + trailStop;
currentProfit = SymbolInfoDouble(_Symbol, SYMBOL_ASK) + openPrice;
if(trailStopPrice < currentStop – step && currentProfit >= minProfit)
{
request.sl = trailStopPrice;
OrderSend(request, result);
}
}
}
stepという名前の入力変数を追加しました。既定値は10ポイントです。stepが10未満に設定されている場合は、stepの値を10に設定します。stepをシンボルの_Point値で乗算し、結果を変数stepに格納することで、stepをポイント値に変換します。トレーリングストップ条件をチェックする時、currentStop変数からステップ値を加算または減算します。これにより、トレーリングストップが10ポイント単位で移動することが保証されます。
CTrailingクラス P185
トレーダーが必要とする可能性のあるあらゆる状況に対して十分に堅牢で柔軟な、再利用可能なトレーリングストップクラスを作成します。トレーリングストップクラスの新しいインクルードファイルを作成します。ファイルはTrailingStop.mqhという名前で、\MQL5\Include\Mql5Bookフォルダーに配置されます。
以下は、TrailingStops.mqhファイルの上部にあるインクルードディレクティブとクラス宣言です。
#include <errordescription.mqh>
#include “Trade.mqh”
class CTrailing
{
protected:
MqlTradeRequest request;
public:
MqlTradeResult result;
bool TrailingStop(string pSymbol, int pTrailPoints, int pMinProfit = 0,
int pStep = 10);
};
\MQL5\Includeフォルダーからerrordesvription.mqhファイルを含め、現在のフォルダからTrade.mghファイルを含めます。CTrailingクラス宣言には、前の章で説明した要求オブジェクトと結果オブジェクトが含まれています。トレーリングストップ機能のパラメータを見てみましょう。
bool TrailigStop(string pSymbol, int pTrailPoints, int pMinProfit = 0, int pStop = 10);
pSymbolパラメータは、ストップを追跡しているポジションのシンボルです。pTrailPointsは、ポイント単位のトレーリングストップです。pMinProfitはポイント単位の最小利益で、ディフォルト値は0です。最後に、pStepはポイント単位のステップ値です。デフォルト値の10ポイントは、トレーリングストップが大幅な価格変動(つまり、1pips以上)でのみ更新されることを保証します。
CTrailing::TrailingStop()関数のコードは、TrailingStops.mqhファイルで表示できます。前のセクションを学習したことがある場合は、非常に見慣れているはずです。EAでCTrailingクラスを使用する方法は次のとおりです。
//#includeとオブジェクトの初期化
#include <Mql5Book\TrailingStops.mqh>
CTrailing Trail;
//入力変数
input bool UseTrailingStop = false;
input int TrailingStop 0;
input int MinimumProfit =0;
input int Step = 0;
//OnTick()イベントハンドラ
//注文配置コードの後に配置
if(UseTrailingStop == true && PositionType(_Symbol) != -1)
{
Trail.TrailingStop(_Symbol, TrailingStop, MinimumProfit, Step);
}
TrailingStop.mqhファイルをインクルードし、CTrailingクラスに基づいてTrailオブジェクトを初期化します。入力変数セクションには、トレーリングストップ機能に必要な変数が含まれています。トレーリングストップのオンとオフを切り替えるUseTrailingStopという名前のbool変数があります。TrailingStopはトレーリングストップをポイント単位で設定します。MinimumProfitはポイント単位の最小ポジション利益で、Stepはトレーリングストップを増分で移動します。
トレーリングストップコードは、OnTick()イベントハンドラの末尾付近に配置されます。UseTrailingStop入力変数がtrueで、PositionType()関数が有効なポジションタイプを返す場合、CTrailingクラスのTrailingStop()関数が呼び出され、現在のポジションのトレーリングストップが必要に応じて変更されます。
動的トレーリングストップを使う P187
前の例では、固定トレーリングストップを使用しました。移動平均やPSARなどの指標を追跡したい場合はどうしますか?または、前の足の高値または安値を追跡したいですか?
指定された価格に基づいてストップロスを追跡する別の関数を作成します。価格が現在のストップロスよりも大きい(または小さい)場合、ストップロスはその価格まで引きずられます。前のセクションで定義したTrailingStop()関数と同じ関数名を使用します。唯一の違いは、関数のパラメータです。(第4章を思い出すかもしれませんが、これは関数のオーバーロードと呼ばれます。)
以下は、両方のトレーリングストップ関数を含むCTrailingクラス宣言です。2つの関数のパラメータの違いに注意してください。前のセクションで説明した最初のTrailingStop()関数には、pTrailPointsという名前のintパラメータがあります。2番目のTrailingStop()関数は、これをpTrailingPriceという名前のdoubleパラメータに置き換えます。
Class CTrailing
{
protected:
MqlTradeRequest request;
public:
MqlTradeResult result;
bool TrailingStop(string pSymbol, int pTrailPoints, int pMinProfit = 0,
int pStep = 10);
bool TrailingStop(string pSymbol, double pTrailPrice, int pMinProfit = 0,
int pStep = 10)
}
pTrailPriceパラメータは、ストップを追跡する価格です。この価格が最小利益とステップの条件を満たし、現在のストップロスよりも現在の価格に近い場合、ストップはその価格に移動します。
これは、パラボリックストップアンドリバースインジケータを使用した例です。PSARは、現在のバーの高値または安値に徐々に近づくストップロスを設定するために使用されます。PSAR値が近づきすぎるか、トレンドが反転すると、PSARは方向を反転します。PSARは方向を反転します。PSAR価格が現在のバーを下回っている場合、オープンな買いポジションのストップを追跡します。PSAR価格が最新のバーより上にある場合、オープン売りポジションのストップを追跡します。
//入力変数
input bool UseTrailingStop =false;
input int MinimumProfit = 0;
input int Step = 0;
input double SARStep = 0.2;
input double SARMaximum = 0.02;
//OnTick()イベントハンドラ
double close[];
ArraySetAsSeries(close, true);
CopyClose(_Symbol, 0, 1, 2, close);
//PSARインジケータ
double sar[];
ArraySetAsSeries(sar, true);
int sarHandle = iSAR(_Symbol, 0, SARStep, SARMaximum);
CopyBuffer(sarHandle, 0, 1, 2, sar);
//SAR価格と終値をチェック
bool sarSignal = false;
if((PositionType(_Symbol) == POSITION_TYPE_BUY && sar[1] < close[1])
|| (PositionType(_Symbol) == POSITION_TYPE_SELL && sar[1] > close[1]))
{
sarSignal = true;
}
//トレーリングストップ
if(UseTrailingStop == true && sarSignal == true)
{
Trail.TrailingStop(_Symbol, sar[1], MinimumProfit, Stop);
}
入力変数には、トレーリングストップのUseTrailingStop、MinimumProfit、およびStep設定が含まれます(PSAR価格がトレーリングストップ距離を決定するため、TrailingStop変数を省略したことに注意してください)。SARStepおよびSARMaximum入力変数は、PSARインジケータの設定です。残りのコードは、OnTick()イベントハンドラ、またはそこから呼び出される関数に属します。
close[]配列は各バーの終値を保持し、sar[]配列はPSAR指標値を保持します。トレーリングストップを変更する前に、終値に対するPSAR価格を確認する必要があります。PSARが終値を下回り、現在のポジションが買いの場合、またはPSARが終値を上回り、現在のポジションが売りの場合、sarSignal変数はtrueに設定されます。
UseTrailigStopとsarSignalが両方ともtrueの場合、最近閉じたバー(sar[1])のPSAR値をTrailingStop()関数に渡し、MinimumProfitとStepの条件が満たされている場合、ストップロスはPSAR価格に調整されます。TrailingStop()関数の2番目のパラメータはdouble型である必要があります。
図14.1パラボリックストップアンドリバース(PSAR)インジケータ
PSARが現在の終値に対して正しく配置され、最小利益および/またはステップ条件が満たされている限り、ストップロスはPSAR価格に一致するように更新されます。これは、ほかのインジケータでも行うことができます。買いポジションを追加している場合、または売りポジションの逆の場合は、インジケータの値が価格を上回っていないことを確認してください。
BreakEvenStop P189
トレーダーは、特定の利益額に達して時に、ストップロスを注文開始価格に移動することを好む場合があります。トレーリングストップとは異なり、ストップロスは1回だけ移動します。トレーリングストップは、取引の利益が増加する限り、ストップを移動し続けます。これをブレークイーブンストップと呼びます。
ブレークイーブンストップの背後にある原則は、トレーリングストップに似ています。まず、取引が指定された最小利益に達したかどうかを確認します。もしそうなら、ストップロスがポジションの開始価格よりも小さいか(大きいか)を確認してください。その場合、ストップロスは注文開始価格に移動されます。トレーリングストップと一緒にブレークイーブンストップを使用できます。
ブレークイーブンストップの前にトレーリングストップがアクティブにならないように、両方のストップタイプの最小利益設定を必ず調整してください。
コードで損益分岐点停止を実装する方法の例を次に示します。
//入力変数
input bool UseBreakEven = false;
input int BreakEven = 0;
input int LockProfit = 0;
//OnTick()イベントハンドラ
MqlTradeRequest request;
MqlTradeResult result;
ZeroMemory(request);
//ブレークイーブンストップ
if(UseBreakEven == true && PositionSelect(_Symbol) == BreakEven > 0)
{
request.action = TRADE_ACTION_SLTP;
request.symbol = _Symbol;
request.tp = 0;
long posType = PositionGetInteger(POSITION_TYPE);
double currentStop = PositionGetDouble(POSITION_SL);
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
if(posType == POSITION_TYPE_BUY)
{
double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BUY);
double breakEvenPrice = openPrice + (LockProfit * _Point);
double currentProfit = currentPrice – openPrice;
if(currentStop < breakEvenPrice && currentProfit >= BreakEven * _Point)
{
request.sl = breakEvenPrice;
OrderSend(request, result);
}
}
else if(posType == POSITION_TYPE_SELL)
{
double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double breakEvenPrice = openPrice – (LockProfit * _Point);
double currentProfit = openPrice – currentPrice;
if(currentStop > breakEvenPrice && currentProfit >= BreakEven * _Point)
{
request.sl = breakEvenPrice;
OrderSend(request, result);
}
}
}
BreakEven入力は、ストップをブレークイーブン価格に移動するために必要な利益のポイント数です。LockProfitパラメータは、指定されたポイント数を損益分岐点価格に加算または減算します。例えば、ストップロスを移動して+50 ポイントを突破したい場合は、LockProfitを50に設定します。
ブレークイーブンストップコードは、発注コードの後、OnTick()イベントハンドラの最後近くに配置されます。UseBreakEven入力パラメータがtrueで、BreakEvenが0より大きく、現在開いているポジションがある場合、ブレークイーブンストップ条件をチェックします。
現在のポジションのタイプ、ストップロス、始値を取得し、これらの値を変数posType、currentStop、openPriceにそれぞれ保存します。現在のポジションが買いポジションの場合、現在の買値を取得し、その値をcurrentPriceに保存します。次に、LockProfit(_Pointを掛けたもの)をopenPrice値に追加し、結果をbreakEvenPriceに格納することで、損益分岐点を計算します。次に、Bid(currentPrice)からポジションの始値(openPrice)を引き、その結果をcurrentProfitに格納することで、現在のポジションの利益を計算します。
最後に、損益分岐点の条件を確認します。現在のストップロス(currentStop)がブレークイーブン価格(breakEvenPrice)よりも小さく、現在のポジションの利益(currentProfit)がブレークイーブン(ポイントを掛けた値)よりも大きい場合、ストップロスをブレークイーブン価格に移動します。
BreakEven()関数 P191
CTrailingクラスにBreakEven()関数を追加しました。関数宣言は次のとおりです。
bool BreakEven(string pSymbol, int pBreakEven, int pLockProfit = 0);
pSymbolおよびpBreakEvenパラメータは必要です。pLockProfitパラメータはオプションです。EAでBreakEven()関数を使用する方法は次のとおりです。
#include <Mql5Book\TrailingStop.mqh>
CTrailing Trail;
//入力変数
input bool UseBreakEven = false;
input int BreakEven = 0;
input int LockProfit = 0;
//OnTick()イベントハンドラ
if(UseBreakEven == true && PositionType(_Symbol) != -1)
{
Trail.BreakEven(_Symbol, BreakEven, LockProfit);
}
損益分岐点のコードは、OnTick()イベントハンドラーの末尾近くにあります。必要なことは、UseBreakEvenがtrueに設定されていること、およびポジションが現在オープンであることを確認することだけです。PositionType()関数を使用して、オープンポジションをチェックします。BreakEven()関数は残りをチェックします。
\MQL5\Include\Mql5Book\TrailingStop.mqhファイルでBreakEven()関数のコードを表示できます。
ヘッジ口座のトレーリングストップ P192
予想通り、トレーリングストップは、ヘッジアカウントでは別の方法で処理する必要があります。トレーリングストップの注文の計算と変更のプロセスは同じです。ヘッジ注文のためにいくつかの変更を加える必要があるだけです。
チケット番号を最初のパラメータとして受け入れるCTrailingクラスのTrailingStop()およびBreakEven()関数のオーバーロードを追加しました。これは、ヘッジングアカウント用のTrailingStop()関数とBreakEven()関数の関数宣言です。
class CTrailing
{
protected:
MqlTradeRequest request;
public:
MqlTradeResult result;
bool TrailingStop(string pSymbol, int pTrailPoints, int pMinProfit = 0,
int pStep = 10);
bool TrailingStop(string pSymbol, double pTrailPrice, int pMinProfit = 0,
int pStep = 10);
bool TrailingStop(along pTicket, int pTrailPoints, int pMinProfit = 0,
int pStep = 10);
bool TrailingStop(ulong pTicket, double pTrailPrice, int pMinProfit = 0,
int pStep = 10);
bool BreakEven(string pSymbol, int pBreakEven, int pLockProfit = 0);
bool BreakEven(ulong pTicket, int pBreakEven, int pLockProfit = 0);
};
トレーリングストップバイポイント関数を使って変化を振り返ってみましょう。残りの関数の変更はほぼ同じです。
bool CTrailing::TrailingStop(ulong pTicket, int pTrailPoints, int pMinProfit = 10)
{
if(PositionSelectByTicket(pTicket) == true && pTrailPoints > 0)
{
request.action = TRADE_ACTION_SLTP;
request.position = pTicket;
long posType = PositionGetInteger(POSITION_POINT);
double currentStop = PositionGetDouble(POSITION_SL);
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
string symbol = PositionGetString(POSITION_SYMBOL);
double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
int digits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
if(pStep < 10) pStep = 10;
double step = pStep * point;
double minProfit = pMinProfit * point;
double trailStop = pTrailPoints * point;
currentStop = Normalize(currentStop, digits);
double trailStopPrice;
double currentProfit;
//注文ループ
int retryCount = 0;
int checkRes = 0;
do
{
if(posType == POSITION_TYPE_BUY)
{
trailStopPrice = SymbolInfoDouble(symbol, SYMBOL_BID) – trailStop;
trailStopPrice = NormalizeDouble(trailStopPrice, digits);
currentProfit = SymbolInfoDouble(symbol, SYMBOL_BID) – openPrice;
if(trailStopPrice > currentStop + step && currentProfit >= minProfit)
{
request.sl = trailStopPrice;
bool sent = OrderSend(request, result);
}
else return(false);
}
else if(posType == POSITION_TYPE_SELL)
{
trailStopPrice = SymbolInfoDouble(symbol, SYMBOL_ASK) + trailStop;
trailStopPrice = NormalizeDouble(trailStopPrice, digits);
currentProfit = openPrice – SymbolInfoDouble(symbol, SYMBOL_ASK);
if((trailStopPrice < currentStop – step || currentStop == 0)
&& currentProfit >= minProfit)
{
request.sl = trailStopPrice;
bool sent = OrderSend(request, result);
}
else return(false);
}
checkRes CheckReturnCode(result.retcode);
if(checkRes == CHECK_RETCODE_OK) break;
else if(checkRes == CHECK_RETCODE_ERROR)
{
string errDesc = TradeServerReturnCodeDescription(result.retcode);
Alert(“Trailing stop: Error ”, result.retcode,” – “, errDesc);
break;
}
else
{
Print(“サーバーエラーが検出されました。再試行しています…。”);
Sleep(RETRY_DELAY);
retryCount++;
}
}
while(retryCount < MAX_RETRIES);
if(retryCount >= MAX_RETRIES)
{
string errDesc = TradeSeverReturnCodeDescription(result.retcode);
Alert(“Max retries exceeded: Error “, result.retcode,” – “, errDesc);
}
string errDesc = TradeSeverReturnCodeDescription(result.retcode);
Print(“Trailing stop: ”, result.retcode,” – “, errDesc,”, #”, pTicket,”, Old SL: “,
currentStop,”, New SL: “, request.sl,”, Bid: “,
SymbolInfoDouble(symbol, SYMBOL_BID),”, Ask: “,
SymbolInfoDouble(symbol, SYMBOL_ASK),”, Stop Level: “,
SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL));
if(checkRes == CHECK_RETCODE_OK) return(true);
else return(false);
}
else return(false);
}
ヘッジアカウントpTicketのトレーリングストップ関数の最初のパラメータは、オープン成行注文のチケット番号を受け入れます。PositionSelectByTicket()関数を使用して、注文情報を取得するための注文を選択します。現在のトレードシンボルの情報を取得する必要があるため、PositionGetString()関数をPOSITION_SYMBOLパラメータとともに使用して、選択した注文のシンボルを取得します。その他の唯一の変更は、エラーが発生した場合に注文のチケット番号をログに記録することです。
トレーリングストップ関数をCPositionsクラスの注文情報関数と組み合わせて、すべてのオープン成行注文のトレーリングストップを調整できます。
//オブジェクト宣言
#include <Mql5Book\TradeHedge.mqh>
#include <Mql5Book\TrailingStops.mqh>
CPositions Positions;
CTrailing Trail;
//入力変数
input bool UseTrailingStop =false;
input int TrailingStop = 0;
input int MinimumProfit = 0;
input int Stop = 0;
//OnTick()イベントハンドラの終了
if(UseTrailingStop == true)
{
ulong tickets[];
Positions.GetTickets(MagicNumber, tickets);
int numTikets = ArraySize(tickets);
for(int i = 0; i < numTickets; i++)
{
Trail.TrailingStop(tickets[i], TrailingStop, MinimumProfit, Step);
}
}
この例では、Position.GetTickets()関数を使用して、すべてのオープン成行注文チケットで、tickets[]配列を埋めます。次に、MQL5でArraySize()関数を使用して、ticket[]配列の要素数を返します。配列内の各要素に対して、Trail.TrailingStop()関数を呼び出して、使注文のトレーリングストップを確認及び変更します。
このセクションで説明されている残りのトレーリングストップと損益分岐点関数は、使用法が上記のものと似ています。\MQL5\Include\Mql5Book\Trailing.Stop.mqhファイルでこれらの関数のコードを表示できます。
さらなる例 P196
第19章では、この章で説明されているトレーリングストップと損益分岐点関数を使用するいくつかのEAを作成します。これらが完全なEAプログラムのコンテキストで使用されていることを確認したい場合は、\MQL5\Experts\Mql5BookフォルダにあるBands RSI Countertrend およびMoving Average Crossプログラムを参照してください。