OriginalTrailingStop.mqhファイルのコード全体記述

Uncategorized

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を返して終了
}

コメント

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