OriginalTrailingStop.mqhファイルのコード全体記述は以下のようになっています。
//+------------------------------------------------------------------+
//| OriginalTrailingStop.mqh |
//| MQL5ssei |
//| https://mqlinvestmentlab.com/ |
//+------------------------------------------------------------------+
#property copyright "MQL5ssei"
#property link "https://mqlinvestmentlab.com/"
#include <errordescription.mqh>
#include <OriginalTrade.mqh>
class OriginalCTrailing
{
protected:
MqlTradeRequest request;
public:
MqlTradeResult result;
bool TrailingStop(ulong parTicket, int parTrailPoints, int parMinProfit = 0, int parStep = 10);
bool TrailingStop(ulong parTicket, double parTrailPrice, int parMinProfit = 0, int parStep = 10);
bool BreakEven(ulong parTicket, int parBreakEven, int parLockProfit=0);
};
//TrailingStop関数の書式1
bool OriginalCTrailing::TrailingStop(ulong parTicket,int parTrailPoints,int parMinProfit=0,int parStep=10)
{
if(PositionSelectByTicket(parTicket) == true && parTrailPoints > 0)//トレイルポイントが0以上なら
{
request.action = TRADE_ACTION_SLTP;//取引の種類
request.position = parTicket;//ポジション番号
long posType = PositionGetInteger(POSITION_TYPE);//ポジションタイプ
double currentStop = PositionGetDouble(POSITION_SL);//未決済ポジションのSL価格
double currentLimit = PositionGetDouble(POSITION_TP);//未決済ポジションのTP価格
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(parStep < 10) parStep = 10;//ステップ幅の修正
double step = parStep * point;//ステップ幅を価格ベースに変換
double minProfit = parMinProfit * point;//ミニマムプロフィットを価格ベースに変換
double trailStop = parTrailPoints * point;//トレイルストップ値を価格ベースに変換
currentStop = NormalizeDouble(currentStop,digits);//現在のSLを正規化
currentLimit = NormalizeDouble(currentLimit,digits);//現在のTPを正規化
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 /*現在のSL値+ステップ幅*/&& currentProfit >= minProfit)
{//現在値-トレールPが現在のSL値+ステップ幅より大きく、現在値-ポジションの始値がminProfitより大きい
request.sl = trailStopPrice;//現在値-トレールPを新しいSL値に設定
request.tp=currentLimit;
//トレーリングストップの発注
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)
{ /*(現在値+自分で決めたトレイルポイントが現在のSL-ステップ幅より大きい、または現時点で損切りが設定されていない<0だといつまでたっても小なり、にならない)
かつ、ポジションの始値-現在値 が minProfitより小さい*/
request.sl = trailStopPrice;
request.tp=currentLimit;
//トレーリングストップ発注
bool sent = OrderSend(request,result);
}
else return(false);
}
//リターンコードを変数checkRes に格納する
checkRes = ReturnCodeCheck(result.retcode);
//注文が成功したらループを抜ける
if(checkRes == CHECK_RETCODE_OK) break;
//注文が失敗した時
else if(checkRes == CHECK_RETCODE_ERROR)
{
string errDesc = TradeServerReturnCodeDescription(result.retcode);
Alert("トレイリングストップエラー: エラー内容",result.retcode," - ",errDesc);
break;
}
else
{
Print("サーバーエラーを検知。 再試行中...");
Sleep(RETRY_MILLISECONDS);
retryCount++;
}
}
while(retryCount < RETRY_LIMIT);
if(retryCount >= RETRY_LIMIT)
{
string errDesc = TradeServerReturnCodeDescription(result.retcode);
Alert("再注文上限回数に達しました: エラー内容 ",result.retcode," - ",errDesc);
}
string errDesc = TradeServerReturnCodeDescription(result.retcode);
Print("トレイリングストップ: ",result.retcode," - ",errDesc,", #",parTicket,", 前回のSL: ",
currentStop,", 新しいSL: ",request.sl,", Bid: ",SymbolInfoDouble(symbol,SYMBOL_BID),
", Ask: ",SymbolInfoDouble(symbol,SYMBOL_ASK),
", ストップレベル: ",SymbolInfoInteger(symbol,SYMBOL_TRADE_STOPS_LEVEL));
if(checkRes == CHECK_RETCODE_OK) return(true);
else return(false);
}//if(PositionSelectByTicket(parTicket) == true && parTrailPoints > 0)
else return(false);
}//TrailingStop
//TrailingStop関数の書式2
bool OriginalCTrailing::TrailingStop(ulong parTicket,double parTrailPrice,int parMinProfit=0,int parStep=10)
{
if(PositionSelectByTicket(parTicket) == true && parTrailPrice > 0)//96回との違い
{
request.action = TRADE_ACTION_SLTP;//取引の種類
request.position = parTicket;//ポジション番号
long posType = PositionGetInteger(POSITION_TYPE);//ポジションタイプ
double currentStop = PositionGetDouble(POSITION_SL);//未決済ポジションのSL価格
double currentLimit = PositionGetDouble(POSITION_TP);//未決済ポジションのTP価格
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(parStep < 10) parStep = 10;//ステップ幅の修正
double step = parStep * point;//ステップ幅を価格ベースに変換
double minProfit = parMinProfit * point;//ミニマムプロフィットを価格ベースに変換
currentStop = NormalizeDouble(currentStop,digits);//現在のSLを正規化
currentLimit = NormalizeDouble(currentLimit,digits);//現在のTPを正規化
parTrailPrice = NormalizeDouble(parTrailPrice,digits);//トレイリングストップの値を正規化
//↑現在のSLとトレールプライスをそれぞれ正規化
double currentProfit;//ポジションの損益情報を格納する変数を宣言
// リトライ回数とリターンコードを格納する変数を宣言する
int retryCount = 0;
int checkRes = 0;
//bid値とask値を格納する変数を宣言
double bid = 0, ask = 0;
do
{
if(posType == POSITION_TYPE_BUY)//買いポジションの場合
{
bid = SymbolInfoDouble(symbol,SYMBOL_BID);//bid値を変数に格納
currentProfit = bid - openPrice;//損益情報を格納
if(parTrailPrice> currentStop + step && currentProfit >= minProfit)
{//現在値-トレールPが現在のSL値+ステップ幅より大きく、損益情報がminProfitより大きい
request.sl = parTrailPrice;//新しいSL値に設定
request.tp=currentLimit;
//トレーリングストップの発注
bool sent = OrderSend(request,result);
}
else return(false);
}
else if(posType == POSITION_TYPE_SELL)//売りポジションの場合
{
ask = SymbolInfoDouble(symbol,SYMBOL_ASK);//ask値を変数に格納
currentProfit = openPrice - ask;
if((parTrailPrice < currentStop - step || currentStop == 0) && currentProfit >= minProfit)
{/*トレイルストップ値が現在のSL-ステップ幅より小さい、または現時点で損切りが設定されていない
かつ、ポジションの損益 が minProfitより大きい*/
request.sl = parTrailPrice;//新しいSL値に設定
request.tp=currentLimit;
//トレーリングストップの発注
bool sent = OrderSend(request,result);
}
else return(false);
}
//リターンコードを変数checkRes に格納する
checkRes = ReturnCodeCheck(result.retcode);
//注文が成功したらループを抜ける
if(checkRes == CHECK_RETCODE_OK) break;
else if(checkRes == CHECK_RETCODE_ERROR)
{
string errDesc = TradeServerReturnCodeDescription(result.retcode);
Alert("トレイリングストップエラー: エラー内容",result.retcode," - ",errDesc);
break;
}
else
{
Print("サーバーエラーを検知。 再試行中...");
Sleep(RETRY_MILLISECONDS);
retryCount++;
}
}
while(retryCount < RETRY_LIMIT);
//再試行上限回数に到達した場合
if(retryCount >= RETRY_LIMIT)
{
string errDesc = TradeServerReturnCodeDescription(result.retcode);
Alert("再注文上限回数に達しました: エラー内容 ",result.retcode," - ",errDesc);
}
string errDesc = TradeServerReturnCodeDescription(result.retcode);
Print("トレイリングストップ: ",result.retcode," - ",errDesc,", #",parTicket,", 前回のSL: ",
currentStop,", 新しいSL: ",request.sl,", Bid: ",SymbolInfoDouble(symbol,SYMBOL_BID),
", Ask: ",SymbolInfoDouble(symbol,SYMBOL_ASK),
", ストップレベル: ",SymbolInfoInteger(symbol,SYMBOL_TRADE_STOPS_LEVEL));
if(checkRes == CHECK_RETCODE_OK) return(true);
else return(false);
}
else return(false);
}
//BreakEven関数
bool OriginalCTrailing::BreakEven(ulong parTicket, int parBreakEven, int parLockProfit=0)
{ //ポジション選択が正しく行われ、parBreakEvenが0より大きければ
if(PositionSelectByTicket(parTicket) == true && parBreakEven > 0)
{
request.action = TRADE_ACTION_SLTP;//.actionへの設定
request.position = parTicket;//.positionへの設定
long posType = PositionGetInteger(POSITION_TYPE);//ポジションタイプの取得
double currentSL = 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);//ポイント情報の取得
int digits = (int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);//ポジション銘柄の桁数情報取得
double breakEvenStop;//ブレイクイーブン発動価格を格納する変数
double currentProfit;//ポジションの損益情報を格納する変数
// リトライ回数とリターンコードを格納する変数を宣言する
int retryCount = 0;
int checkRes = 0;
//Bid値、Ask値格納変数の初期化
double bid = 0, ask = 0;
do
{ //ポジションタイプが「買い」の場合
if(posType == POSITION_TYPE_BUY)
{
bid = SymbolInfoDouble(symbol,SYMBOL_BID);
breakEvenStop = openPrice + (parLockProfit* point);//ブレイクイーブン発動価格を変数に格納
currentProfit = bid - openPrice;//ポジション損益情報を変数に格納
//正規化
breakEvenStop = NormalizeDouble(breakEvenStop, digits);
currentProfit = NormalizeDouble(currentProfit, digits);
if(currentSL < breakEvenStop && currentProfit >= parBreakEven * point)
{//現在のSL値が約定価格+指定値より小さい、かつポジション損益が指定値より大きい
request.sl = breakEvenStop;
request.tp= currentLimit;
bool sent = OrderSend(request,result);
}
else return(false);
}
//ポジションタイプが売りの場合
else if(posType == POSITION_TYPE_SELL)
{
ask = SymbolInfoDouble(symbol,SYMBOL_ASK);
breakEvenStop = openPrice - (parLockProfit * point);//ブレイクイーブン発動価格を変数に格納
currentProfit = openPrice - ask;//ポジション損益情報を変数に格納
//正規化
breakEvenStop = NormalizeDouble(breakEvenStop, digits);
currentProfit = NormalizeDouble(currentProfit, digits);
if((currentSL > breakEvenStop || currentSL == 0) && currentProfit >= parBreakEven * point)
{//<現在のSL値が約定価格-指定値より大きい、または現在のSL値が0のとき>、かつポジション損益が指定値より大きい
request.sl = breakEvenStop;
request.tp= currentLimit;
bool sent = OrderSend(request,result);
}
else return(false);
}
//リターンコードの確認
checkRes = ReturnCodeCheck(result.retcode);
//正常に注文が行われていればループを抜ける
if(checkRes == CHECK_RETCODE_OK) break;
else if(checkRes == CHECK_RETCODE_ERROR)
{ //エラー情報の格納
string errDesc = TradeServerReturnCodeDescription(result.retcode);
Alert("ブレイクイーブン注文エラー: エラー内容 ",result.retcode," - ",errDesc);
break;
}
//再注文により、エラーが解消される可能性がある場合
else
{
Print("サーバーエラーを検知, 再試行中...");
Sleep(RETRY_MILLISECONDS);
retryCount++;
}
}
while(retryCount < RETRY_LIMIT);
//再試行の上限に達した場合
if(retryCount >= RETRY_LIMIT)
{
string errDesc = TradeServerReturnCodeDescription(result.retcode);
Alert("再試行の上限に達しました: エラー内容 ",result.retcode," - ",errDesc);
}
string errDesc = TradeServerReturnCodeDescription(result.retcode);
Print("ブレイクイーブンストップ: ",result.retcode," - ",errDesc,
", #",parTicket,", SL: ",request.sl,", Bid: ",bid,", Ask: ",ask,
", Stop Level: ",SymbolInfoInteger(symbol,SYMBOL_TRADE_STOPS_LEVEL));
if(checkRes == CHECK_RETCODE_OK) return(true);
else return(false);
}
else return(false);//ポジションが選択できなければfalseを返して終了
}
コメント