ストップロスとテイクプロフィット P121
固定ストップロスand/orテイクプロフィットの計算 P121
多くの取引戦略は、ストップロスを設定し、注文開始価格から一定の距離で利益を得ます。トレーダーは、EAのプロパティでストップロスとテイクプロフィットのポイント数を指定します。ストップロスとテイクプロフィットの価格は、注文またはポジションの開始価格に対して計算されます。
成行注文の場合、始値は、注文が約定された時点での現在のビッドまたはアスク価格です。注文が出された後、PositionSelectByTicket()関数でポジションを選択してポジションの始値を取得し、POSITION_PRICE_OPENパラメータを指定してPositionGetDluble()関数を使用して始値を取得します。次に、ストップロスを計算し、その価格に対して利益を確定します。
指値注文の場合、始値は、注文を開始するときに指定する価格です。注文を出す前に注文の始値に対してストップロスとテイクプロフィットの価格を計算します。
ストップロス(損切・逆指値) P121
買い注文の場合、ストップロスは始値からポイント単位のストップロス値を差し引いて計算されます。売り注文の場合、ストップロスは始値にポイント単位のストップロス値を追加することによって計算されます。
まず、ストップロス値にシンボルのポイント値を掛けます。たとえば、小数点以下5桁の外国為替シンボルのポイント値は0.00001になります。500ポイントのストップロスを指定した場合、500に0.00001を掛けて0.005の値を取得します。次に、始値に、この値を加算または減算して、ストップロス価格を見つけます。
以下の例は、ネッティング口座で取引していることを前提としています。ヘッジ口座を使用する場合は、PositionSelect(_Symbol)をPositionSelectByTiket()に置き換え、注文チケット番号をパラメータとして渡します。また、注文チケット番号をrequest.position変数に割り当てる必要があります。
買いポジションにストップロスを追加する例を次に示します。
//入力変数
input int StopLoss = 500;
//Ontick()イベントハンドラ
MqlTradeRequest request request;
MqlTradeResult result;
ZeroMemory(request);
request.action = TRADE_ACTION_SLTP;
request.symbol = _Symbol;
//買い注文のストップロスを計算します
PositionSelect(_Symbol);
double positionPrice = PositionGetDouble(POSITION_PRICE_OPEN);
double stopLossPoint = StopLoss * _Point;
request.sl =positionPrice – stopLossPoint;
OrderSend(request, result);
StopLoss入力変数は、プログラムの最初に定義されています。次のコードは、OnTick()イベントハンドラに配置されます。買いポジションが現在開いていると仮定します。request.action変数は、この取引操作をポジション変更(TRADE_ACTION_SLTP)として識別し、request.symbol変数は、変更するポジション(現在のチャートシンボル)を識別します。
ストップロス価格を計算するには、まず現在のポジションの始値を取得します。PositionSelect()関数は、さらなる処理のために現在のチャートシンボルのオープンポジションを選択します。次に、POSITION_PRICE_OPENパラメータを指定したPositionGetDouble()関数は、ポジションのオープン価格を返し、それをpositionPrice変数に格納します。
次に、StopLoss入力変数をシンボルのポイント値(_Point)で乗算します。結果は変数stopLossPointに保存されます。最後に、positionPriceからstopLossPointを減算してストップロス価格を計算し、その結果をresult.slに割り当てます。OrderSend()関数は、ポジションのストップロスを変更します。
売りポジションのストップロス計算はほぼ同じです。減算から加算への操作を単純に逆にしています。
//売り注文のストップロスを計算します
PositionSelect(_Symbol);
double positionPrice = PositionGetDouble(POSITION_PRICE_OPEN);
double stopLossPoint = StopLoss * _Point;
request.sl = positionPrice + stopLossPoint;
指値注文の場合、注文を出す前にストップロスが計算されます。この例では、買いストップ注文価格を現在のアスク価格より100ポイント上に設定します。
//入力変数
input int StopLoss = 500;
input int PendingPrice = 100;
//OnTick()イベントハンドラ
MqlTradeRequest request;
MqlTradeResult result;
ZeroMemory(request);
request.actiong = TRADE_ACTION_PENDING;
request.type = ORDER_TYPE_BUY_STOP;
request.symbol = _Symbol;
request.volume = 1;
request.type_time = ORDER_TIME_GTC;
//保留中の買い注文のストップロスを計算する
request,price = SymbolInfoDouble(_Symbol, SYMBOL_ASK) + (PendingPrice * _Point);
double stopLossPoint = StopLoss * _Point;
request.sl = request.price – stopLossPoint;
OrderSend(request, result);
現在のアスク価格に対する未決注文価格を計算するために、PendingPrice入力変数を定義しました。request.action変数はTRADE_ACTION_PENDINGに設定され、これが指値注文操作であることを示します。request.type変数は、これが買いストップ注文であることを示します。銘柄、取引量、有効期限タイプ(ORDER_TIME_GTC)を指定し、未決注文が期限切れにならないことを示します。
未決注文の価格(request.price)は、PendingPrice入力変数に現在の銘柄のポイント値(_Point)を掛けて、それを現在の売値に追加することによって計算されます。これは、SymbolInfoDouble()関数を使用して取得されます。これにより、未決注文の価格が現在のアスク価格より100ポイント高く設定されます。
ストップロスポイント値は依然と同様に計算され、ストップロス価格は指値注文の価格(request.price)からストップロスポイントを差し引いて計算されます。結果はrequest.sl変数に割り当てられ、未決注文リクエストが取引サーバーに送信されます。
保留中の売り注文のストップロスの計算を見てみましょう。
//保留中の売り注文のストップロスを計算する
request,price = SymbolInfoDouble(_Symbol, SYMBOL_BID) - (PendingPrice * _Point);
double stopLossPoint = StopLoss * _Point;
request.sl = request.price + stopLossPoint;
指値注文の価格は、現在の買気配価格から(PendingPrice * _Point)を引いて計算され、逆指値価格は指値注文の価格にstopLossPointを加えることで計算されます。
固定ストップロスの計算方法は、未決注文の種類に関係なく同じです。買い注文の場合、ストップロスは未決注文の価格より下に配置され、売り注文の場合、ストップロスは未決注文の価格より上に配置されます。
テイクプロフィット(利食い) P124
テイクプロフィット価格はストップロス価格と同じ方法で計算されますが、その逆になります。買い注文のテイクプロフィット価格は始値より高く設定され、売り注文のテイクプロフィット価格は始値より低く設定されます。
以下の例は、ネッティング口座で取引していることを前提としています。ヘッジ口座を使用する場合は、PositionSelect(_Symbol)をPositionSelectByTicket()に置き換え、注文チケット番号をパラメータとして渡します。また、注文チケット番号requset. position変数に割り当てる必要があります。
買いポジションのテイクプロフィット価格の計算は次のとおりです。
//入力変数
input int TakeProfit = 1000;
//OnTick()イベントハンドラ
MqlTradeRequest request;
MqlTradeResult result;
ZeroMemory(request);
request.action = TRADE_ACTION_SLTP;
request.symbol = _Symbol;
//買いポジションのテイクプロフィットを計算します
PositionSelect(_Symbol);
double positionPrice = PositionGetDouble(POSITION_PRICE_OPEN);
double takeProfitPoint = TakeProfit * _Point;
request.tp = positionPrice + takeProfitPoint;
OrderSend(result, request);
TakeProfitという名前の入力変数を宣言します。デフォルトのテイクプロフィット値は1000ポイントです。次のコードは、以前のストップロスの変更に似ています。現在のポジションを選択し、最初に現在のポジションの始値を取得します。次に、TakeProfitをPointで乗算し、その結果をtakeProfitPoint変数に格納することによって、テイクプロフィット価格を計算します。次に、takeProfitPointをpositionPriceに追加して、テイクプロフィット価格を計算します。結果はrequset.tp変数に割り当てられます。
売りポジションのテイクプロフィット価格を計算するコードは次のとおりです。
//売りポジションのテイクプロフィットを計算
double takeProfitPoint = TakeProfit * _Point;
PositionSelect(_Symbol);
double positionPrice = PositionGetDouble(POSITION_PRICE_OPEN);
request.tp = positionPrice – takeProfitPoint;
takeProfitの値がpositionPriceから差し引かれ、テイクプロフィット価格が取得されます。
未決注文の場合、同じロジックが適用されます。未決の買い注文の未決注文の価格にテイクプロフィット値を追加し、未決の売り注文の場合はそれを差し引きます。
停止計算関数の作成 P125
買い注文または売り注文のストップロスまたはテイクプロフィット価格を計算できる一連の関数を作成します。この方法では、ストップロスやテイクプロフィットの計算を覚えておく必要はありません。指定する必要があるのは、シンボル、ポイント単位のストップロスまたはテイクプロフィットの値、およびオプションで注文またはポジションの始値です。これらの関数は、ヘッジ口座とネッティング口座の両方で機能するため、両方の口座のタイプの違いについて説明する必要はありません。
ストップロス機能から始めましょう。買い注文のストップロスを計算する関数はBuyStopLoss()と呼ばれます。この関数は、Trade.mqhインクルードファイルにあります。
double BuyStopLoss(string pSymbol, int pStopPoints, double pOpenPrice =0)
{
if(pStopPoints <= 0) return(0);
double openPrice;
if(pOpenPrice > 0) openPrice = pOpentPrice;
else openPrice = SymbolInfoDouble(pSymbol, SYMBOL_ASK);
double point = SymbolInfoDouble(pSymbol, SYMBOL_POINT);
double stopLoss = openPrice – (pstopPoints * point);
long digits = SymbolInfoInteger(pSymbol, SYMBOL_DIGITS);
stopLoss = NormalizeDouble(stopLoss,(int)digits);
return(stopLoss);
}
BuyStopLoss()関数は、シンボル名(pSymbol)、ポイント単位のストップロス値(pStopPoints)、およびオプションの始値(pOpenPrice)の3つのパラメータを受け入れます。
関数の最初の行は、関数をすぐに終了し、pStopPointsが0以下の場合は値0を返します。次に、openPriceという名前のdouble変数を宣言します。これは、注文の始値を保持します。注文の開始価格がpOpenPriceで指定されている場合、pOpenPriceはopenPriceに割り当てられます。それ以外の場合は、pSymbolで指定された銘柄の現在の売り値が使用されます。
SymbolInfoDouble()関数をSYMBOL_POINTパラメータとともに使用して、pSymbolパラメータで指定されたシンボルのポイント値を取得します。これはpoint変数に割り当てられます。次に、pStopPositionにポイントを掛けて、openPriceからその値を差し引いて、ストップロス価格を計算します。結果はstopLoss変数に保存されます。
最後のステップは、ストップロス値をシンボル価格の桁数に正規化することです。外国為替シンボルの小数点以下は3桁または5桁なので、ストップロスを適切な桁数に収めます。SYMBOL_DIGITSパラメータを指定したSymbolInfoInteger()関数は、pSymbolの数字の値を取得し、それをlong変数digitsに割り当てます。
NormalizeDouble()関数は、stopLoss値をdigits変数で指定された桁数に収めます。NormalizeDouble()関数のdigits変数の前の(int)は、数字の値をint型に明示的にキャストします。これは絶対に必要というわけではありませんが、「型変換によるデータ損失の可能性」という警告を回避するために挿入しています。最後に、stopLossの正規化された値をプログラムに返します。
買い注文のテイクプロフィット価格を計算する関数を見てみましょう。コードはほぼ同じです。この場合、テイクプロフィット値を始値に追加するだけです。
double BuyTakeProfit(string pSymbol, int pProfitPoints, double pOpenPrice = 0)
{
if(pProfitPoints <= 0) return(0);
double openPrice;
if(pOpenPrice > 0) openPrice = pOpenPrice;
else openPrice = SymbolInfoDouble(pSymbol, SYMBOL_ASK);
double point = SymbolInfoDouble(pSymbol, SYMBOL_POINT);
double takeProfit = openPrice + (pProfitPoints * point);
long digits = SymbolInfoInteger(pSymbol, SYMBOL_DIGTS);
takeProfit = NomalizeDouble(takeProfit,(int)digits);
return(takeProfit);
}
売りストップロスとテイクプロフィットの計算コードは似ています。始値が指定されていない場合は、現在の買値を使用します。ストップロスとテイクプロフィットの計算は、買い注文の計算に対して逆になります。
double SellTakeProfit(string pSymbol, int pProfitPoints, double pOpenPrice = 0)
{
if(pProfitPoints <= 0) return(0);
double openPrice;
if(pOpenPrice > 0) openPrice = pOpenPrice;
else openPrice = SymbolInfoDouble(pSymbol, SYMBOL_BID);
double point = SymbolInfoDouble(pSymbol, SYMBOL_POINT);
double takeProfit = openPrice - (pProfitPoints * point);
long digits = SymbolInfoInteger(pSymbol, SYMBOL_DIGTS);
takeProfit = NomalizeDouble(takeProfit,(int)digits);
return(takeProfit);
}
SellStopLoss()関数も同様です-pProfitPointsを始値に追加するだけです。これらの関数は、Trade.mqhインクルードファイルで表示できます。
停止レベル P127
EAのプログラマーやトレーダーが犯す最も一般的なエラーの1つは、無効なストップ価格です。ストップロス、テイクプロフィット、または指値注文の価格は、現在のビッドおよびアスク価格から最小距離にある必要があります。この最小距離は停止レベルと呼ばれます。(実際には、ほとんどのブローカーはもうストップレベルを使用していませんが、使用している場合に備えて確認する必要があります。)
ストップレベルは、SYMBOL_TRADE_STOPS_LEVELパラメータを指定したSymbollInfoInteger()関数を使用して、サーバーから取得されます。まず、この値にシンボルのポイント値を掛ける必要があります。買いテイクプロフィット、売りストップロス、売りリミット価格の最小ストップ価格を計算するには、現在のアスク価格にストップレベルを追加するだけです。
double stopLevel = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * _Point;
double minStopLevel = SymbolInfoDouble(_Symbol, SYMBOL_ASK) + stopLevel;
SYMBOL_TRADE_STOPS_LEVELパラメータを指定したSymbollInfoInteger()関数は、サーバーからストップレベルを返します。ストップレベルは整数値であるため、_Pointを掛けて価格に変換する必要があります。この値はstopLevel変数に格納されます。
次に、SYMBOL_ASKを指定したSymbvollInfoDouble()関数は、現在の買値を返します。stopLevel変数の値をアスク価格に追加して、最小ストップレベルを取得します。買いのテイクプロフィット、売りのストップロス、買いのストップまたは売りの指値価格は、この値より上でなければなりません。その出ない場合は、TRADE_RETCODE_INVALID_STOPSリターンコードが返されます。
売りテイクプロフィット、買いストップロス、売りストップまたは、買いリミット価格の最大ストップ価格を計算するには、単純に現在のビッド価格からストップレベルを引きます。
double stopLevel = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * _Point;
double maxStopLevel = SymbolInfoDouble(_Symbol, SYMBOL_BID) - stopLevel;
ストップレベルを計算したら、これをストップロス、テイクプロフィット、または指値注文の価格と比較して、それが有効かどうかを確認できます。
double stopLevel = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * _Point;
double minStopLevel = SymbolInfoDouble(_Symbol, SYMBOL_ASK) + stopLevel;
if(request.price <= minStopLevel)
{
Print(“Invalid stop price”);
}
この例では、未決注文の価格を現在の売値より上の最小ストップレベルと比較します。requset.price変数がminStopLevel以下の場合、価格が無効であることを示すメッセージがログに出力されます。
最小または最大ストップレベルの価格がわかれば、関連するストップレベルより高くまたは低くするだけで、無効な価格を有効な価格に自動的に調節できます。
StopVeritication関数の作成 P128
新しく計算されたストップロスまたはテイクプロフィットの価格で注文を出す前に、価格がストップレベル内にないこと、または無効でないことを確認する必要があります。アスク価格を上回り、ビッド価格を下回った逆指値注文と未決注文の価格をチェックする一連の関数を作成します。使用する関数は、チェックしている注文の種類と価格の種類によって異なります。
アスク価格を上回る価格をチェックする関数を作成しましょう。これは、買いのテイクプロフィット、売りのストップロス、買いのストップ、売りの指値注文価格を確認するために使用されます。価格がストップレベルの価格を下回っている場合は、ストップレベルの上に指定されたポイント数をプラスまたはマイナスするように調整されます。
double AdjustAboveStopLevel(string pSymbol, double pPrice, int pPoints = 10)
{
double currPrice = SymbolInfoDouble(pSymbol, SYMBOL_ASK);
double point = SymbolInfoDouble(pSymbol, SYMBOL_POINT);
double stopLevel = SymbolInfoInterger(pSymbol, SYMBOL_TRADE_STOP_LEVEL) * point;
double stopPrice = currPrice + stopLevel;
double addPoints = pPoints * point;
if(pPrice > stopPrice + addPoints) return(pPrice);
else
{
double newPrice = stopPrice + addPoints;
Print(“Price adjusted above stop level to ” + DoubleToString(newPrice));
return(newPrice);
}
}
AdjustAboveStopLevel()関数には3つのパラメータがあります。pSymbol、確認するストップ価格であるpPriceおよびストップレベルに追加のポイント数を追加するオプションのパラメータpPointsです。これにより、スリッページがストップレベルの価格に非常に近い価格を無効にしないことが保証されます。
まず、pSymbolの売値を取得して現在の価格を決定し、それをcurrPrice変数に格納します。次に、シンボルのポイント値を取得し、ポイント変数に格納します。シンボルのストップレベルを取得し、その値にポイント変数を掛けます。結果は、stopLevel変数に格納されます。currPriceをstopLevelを追加し、その値をstopPrice変数に格納することで、ストップレベルの価格を計算します。次に、pPointsパラメータを銘柄のポイント値で乗算し、結果をaddPointsに格納することで価格値に変換します。
ストップ価格(pPrice)がストップレベル価格(stopPrice + addPoints)より大きい場合、元のpPrice値をプログラムに返します。それ以外の場合は、新しいストップ価格を計算する必要があります。newPriceという名前の変数を宣言し、stopPrice addPointsに設定します。これにより、調整されたストップ価格がストップ価格に近すぎないようにします。価格が調整されたことを示すメッセージをログに出力します。最後に、調整された価格をプログラムに返します。
次に、Bid価格を下回るストップ価格をチェックする関数を作成します。これは、売りストップ、買いリミット、買いストップロス、売りテイクプロフィット価格を確認するために使用されます。このコードは上記のAdjustAboveStopLevel()関数に似ています。
double AdjustAboveStopLevel(string pSymbol, double pPrice, int pPoints = 10)
{
double currPrice = SymbolInfoDouble(pSymbol, SYMBOL_BID);
double point = SymbolInfoDouble(pSymbol, SYMBOL_POINT);
double stopLevel = SymbolInfoInterger(pSymbol, SYMBOL_TRADE_STOP_LEVEL) * point;
double stopPrice = currPrice - stopLevel;
double addPoints = pPoints * point;
if(pPrice < stopPrice - addPoints) return(pPrice);
else
{
double newPrice = stopPrice - addPoints;
Print(“Price adjusted below stop level to ” + DoubleToString(newPrice));
return(newPrice);
}
}
変更点は太字で強調されています。現在の入札価格をcurrPrice変数に割り当てます。stopPrice変数は、currPriceからstopLevelを差し引いて計算されます。pPriceパラメータがstopPrice-addPointsより小さい場合、元のpPrice値がプログラムに返されます。それ以外の場合は、stopPrice-addPointsの結果をnewPrice変数に代入して、新しい価格を計算します。メッセージがログに出力され、newPrice変数がプログラムに返されます。
上記の関数は、無効な価格を自動的に調整します。しかし、価格を調節せずに、価格が有効かどうかだけを確認したい場合はどうでしょうか?CheckAboveStopLevel()およびCheckBelowStopLevel()関数を使用します。これらの関数は、価格が有効かどうかに応じて、trueまたはfalseのブール値を返します。
CheckAboveStopLevel()関数のコードは次のとおりです。
bool CheckAboveStopLevel(string pSymbol, double pPrice, int pPoints = 10)
{
double currPrice = SymbolInfoDouble(pSymbol, SYMBOL_ASK);
double point = SymbolInfoDouble(pSymbol, SYMBOL_POINT);
double stopLevel = SymbolInfoInterger(pSymbol, SYMBOL_TRADE_STOP_LEVEL) * point;
double stopPrice = currPrice + stopLevel;
double addPoints = pPoints * point;
if(pPrice >= stopPrice + addPoints) return(true);
else return(false);
}
したがって、関数はAdjustAboveStopLevel()関数に非常に似ています。相違点は太字で強調表示されています。逆指値レベルの価格に対してpPrice変数を調整する代わりに、価格が有効な場合はtrueの値を返し、そうでない場合はfalseの値を返します。これにより、価格が無効な場合、プログラマはほかのアクションを指定できます。
CheckBelowStopLevel()関数は類似しており、この章のすべての停止検証関数は、\MQL5\Include\Mql5Book\Trade.mqhファイルで表示できます。
停止計算と検証機能の使用 P130
固定ストップロスとテイクプロフィット価格を計算する関数、および価格を検証する関数を作成したので、EAプログラムでこれらを使用する方法を示しましょう。
成行注文の場合、注文後にストップロスとテイクプロフィットが計算されます。まず、現在のポジションの始値を取得します。次に、始値に対してストップロスとテイクプロフィットが計算されます。計算されたストップロスとテイクプロフィットの価格が検証され、最後に新しいストップロスおよび/またはテイクプロフィットの価格で注文が変更されます。
アカウントをネッティングするための簡単なEAプログラムに戻りましょう。ストップロスとテイクプロフィットの計算をストップ計算関数に置き換えます。結果の価格は逆指値レベルに対してチェックされ、それに応じて調整されます。
//買い成り行き注文を開く
If(close[0] > ma[0] && glBuyPlaced == false
&& (positionType != POSITION_TYPE_BUY || openPosition == false))
{
glBuyPlaced = Trade.Buy(_Symbol, TradeVolume);
// SL/TPを変更する
if(glBuyPlaced == true)
{
request.action = TRADE_ACTION_SLTP;
PositionSelect(_Symbol);
double positionOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);
double buyStopLoss = BuyStopLoss(_Symbol, StopLoss, positionOpenPrice);
if(buyStopLoss > 0) request.sl = AdjustBelowStopLevel(_Symbol, buyStopLoss);
double buyTakeProfit = BuyTakeProfit(_Symbol, TakeProfit, positionOpenPrice);
if(buyTakeProfit > 0) request.tp = AdjustAboveStopLevel(_Symbol, buyTakeProfit);
if(request.sl > 0 && request.tp > 0) OrderSend(request, result);
glSellPlaced = false;
}
}
//売り成り行き注文を開く
else if(close[0] < ma[0] && glSellPlaced == false && positionType != POSITION_TYPE_Sell)
{
glSellPlaced = Trade.Sell(_Symbol, TradeVolume);
// SL/TPを変更する
if(glSellPlaced == true)
{
request.action = TRADE_ACTION_SLTP;
PositionSelect(_Symbol);
double positionOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);
double sellStopLoss = SellStopLoss(_Symbol, StopLoss, positionOpenPrice);
if(sellStopLoss > 0) request.sl = AdjustAdoveStopLevel(_Symbol, sellStopLoss);
double sellTakeProfit = SellTakeProfit(_Symbol, TakeProfit, positionOpenPrice);
if(sellTakeProfit > 0) request.tp = AdjustBelowStopLevel(_Symbol, sellTakeProfit);
if(request.sl > 0 && request.tp > 0) OrderSend(request, result);
glBuyPlaced = false;
}
}
変更点は太字で強調表示されています。まず、ストップ計算機能を使用して、ストップロスとテイクプロフィットの価格を計算します。次に、必要に応じてストップ検証機能を使用して価格を調整します。検証された価格は、関連するリクエスト変数に割り当てられます。
買いストップロスとテイクプロフィットの計算を詳しく見てみましょう。
double buyStopLoss = BuyStopLoss(_Symbol, StopLoss, positionOpenPrice);
if(buyStopLoss > 0) request.sl = AdjustBelowStopLevel(_Symbol, buyStopLoss);
double buyTakeProfit = BuyTakeProfit(_Symbol, TakeProfit, positionOpenPrice);
if(buyTakeProfit > 0) request.tp = AdjustAboveStopLevel(_Symbol, buyTakeProfit);
BuyStopLoss()関数を使用して、positionOpenPriceに対するストップロスを計算します。結果はbuyStopLoss変数に割り当てられます。buyStopLossの値がゼロより大きい場合、buyStopLoss値をAdjustBelowStopLevel()関数に渡します。結果は、result.sl変数に割り当てられます。BuyTakeProfit()およびAdjustAboveStopLevel()関数を使用して、テイクプロフィットに対しても同じことが行われます。
シンプルなEAのヘッジバージョンへの変更は似ています。ストップロスとテイクプロフィットの計算コードを、上記の太文字で強調されたコードに置き換えるだけです。\MQL5\Experts\Mql5BookフォルダーにあるファイルSimpleExpertAdvisor with Function.mqhおよびSimple ExpertAdvisor with Function(Hedging).mq5で変更を表示できます。
上記の例では、無効な場合にストップロスまたはテイクプロフィットの価格が自動的に調整されます。しかし、単に価格が有効かどうかを確認したい場合はどうでしょうか?以下の例では、ストップロス価格を変更せずにチェックしています。
if(StopLoss > 0)
{
double buyStopLoss = BuyStopLoss(_Symbol, StopLoss, positionOpenPrice);
if(CheckBelowStopLevel(_Symbol, buyStopLoss) == false)
{
Alert(“Buy stop loss price is invalid!”);
}
else if(buyStopLoss > 0) request.sl = buyStopLoss;
}
CheckBelowStopLoss()関数は、buyStopLoss価格が有効かどうかを確認するために使用されます。関数がfalseを返す場合、アラートがユーザーに表示され、それ以上のアクションは実行されません。それ以外の場合、buyStopLossがゼロより大きい場合、buyStopLossの値がrequest.slに割り当てられます。
動的ストップロスの使用 P132
この章の例では、固定のストップロス値を使用します。指標値またはテクニカルサポート/レジスタンスレベルを使用するなど、ストップロス価格を決定するほかの方法があります。ストップロスまたはテイクプロフィットの絶対価格を使用する場合は、現在のポジションに追加する前に確認する必要があります。
以下の例では、変数stopLossPriceは、買いポジションのストップロスとして使用したい暫定価格を保持します。AdjustBelowStopLevel()関数を使用して検証し、注文の始値からの距離が最小であることを確認します。MinStopLoss入力変数を使用すると、ユーザーは最小ストップロス距離を強制できます。
//入力変数
input int MinStopLoss = 100;
//OnTick()イベントハンドラ
double stopLossPrice = Lowest(_Symbol, _Period, 8);
request.sl = AdjustBelowStopLossLevel(_Symbol, stopLossPrice, MinStopLoss);
LowestLow()関数は、最後の8つのバーの最低安値を取得し、結果をstopLossPriceに割り当てます。この関数については、第16章で説明します。AdjustBelowStopLoss()関数を使用して、ストップロス価格の値を検証し、現在の価格とストップロス価格の間の距離が少なくとも100ポイントであることを確認します。検証された価格は、result.sl変数に保存されます。
要約すると、ストップロスまたはテイクプロフィット価格をポジションに追加する必要がある場合、または指値注文をオープンする必要がある場合は、まず価格を確認してください。無効な設定または価格が現在のビッドまたはアスク価格に近すぎると、「無効なストップ」エラーが発生する可能性があります。これらは、EAに価格検証を組み込むことで簡単に回避できます。