ホーム » ソース共通化 » 取引関数 » OrderClose() – 取引関数

OrderClose() – 取引関数

取引関数

取引関数OrderClose()PositionClose()について、MQL4とMQL5のソースコード共通化する方法を説明しています。

関数定義

MQL4の定義

bool  OrderClose( 
   int        ticket,      // ticket 
   double     lots,        // volume 
   double     price,       // close price 
   int        slippage,    // slippage 
   color      arrow_color  // color 
   );

MQL5の定義

定義なし

EAでは使用頻度が高い関数ですが、MQL5では取引関数の仕様は大きく変更されてOrderClose()自体がMQL5では削除されています。
その為、MQL5用の定義をしてOrderClose()を利用できるように対応します。
ただし、MQL5ではオーダーポジションという表現を区別しているため工夫が必要です。

共通化方法

ソース共通化

対処方法

共通化するためにMQL5用の定義をします。
#ifdef __MQL5__ ~ #endifを使用することでMQL5のコンパイルにのみ有効となります。
MQL4の場合は「__MQL4__」を使用しますが、今回使用していないためMQL4は既存で組み込まれた定義済み変数が利用されます。
後述する使用例でポジションオープンを行うので、OrderSend()についても定義しています。

#ifdef __MQL5__
#define OP_BUY				((int)0)
#define OP_SELL				((int)1)
#define OP_BUYLIMIT			((int)2)
#define OP_SELLLIMIT		((int)3)
#define OP_BUYSTOP			((int)4)
#define OP_SELLSTOP			((int)5)

///////////////////////////////////////////////////////////////////////////////
// 約定ポジションをクローズする
bool OrderClose(int iTicket, double dLots, double dPrice, int iSlippage, color arrow_color = clrNONE)
{
	bool bResult = false;
	bResult = PositionSelectByTicket(iTicket);
	if (bResult) {
		MqlTradeRequest mqlRequest = {};
		MqlTradeResult mqlResult = {};
		ZeroMemory(mqlResult);
		ZeroMemory(mqlResult);
		mqlRequest.action		= TRADE_ACTION_DEAL;						// 取引操作タイプ
		mqlRequest.position		= iTicket;									// ポジションチケット
		mqlRequest.symbol		= PositionGetString(POSITION_SYMBOL);		// シンボル
		mqlRequest.volume		= dLots;									// ポジションボリューム
		mqlRequest.deviation	= iSlippage;								// 価格からの許容偏差
		mqlRequest.type			= (ENUM_ORDER_TYPE)PositionGetInteger(POSITION_TYPE) == ORDER_TYPE_BUY ? ORDER_TYPE_SELL : ORDER_TYPE_BUY;		// ポジションのType
		mqlRequest.magic		= 0;										// ポジションのMagicNumber
		long lMode = SymbolInfoInteger(mqlRequest.symbol, SYMBOL_FILLING_MODE);
		mqlRequest.type_filling	= SYMBOL_FILLING_IOC == lMode ? ORDER_FILLING_IOC : ORDER_FILLING_FOK;
		if (OrderSend(mqlRequest, mqlResult)) {
			bResult = true;
		} else {
			bResult = false;
		}
	}
	return bResult;
}
///////////////////////////////////////////////////////////////////////////////
// MQL5のオーダータイプに変換する
ENUM_ORDER_TYPE GetOrderType(int iOrderType)
{
	ENUM_ORDER_TYPE OrderTypeTbl [] = {
		ORDER_TYPE_BUY,
		ORDER_TYPE_SELL,
		ORDER_TYPE_BUY_LIMIT,
		ORDER_TYPE_SELL_LIMIT,
		ORDER_TYPE_BUY_STOP,
		ORDER_TYPE_SELL_STOP,
		ORDER_TYPE_BUY_STOP_LIMIT,
		ORDER_TYPE_SELL_STOP_LIMIT,
		ORDER_TYPE_CLOSE_BY,
	};
	return OrderTypeTbl[iOrderType];
}
///////////////////////////////////////////////////////////////////////////////
// オーダーによりポジションをオープンする
int OrderSend(string strSymbol, int iOrderType, double dLots, double dPrice, int iSlippage, 
				double dSL, double dTP, string strComment, int iMagicNumber, datetime dtExpiration, color clOrder)
{
	int iResult = -1;
	MqlTradeRequest mqlRequest = {};
	MqlTradeResult mqlResult = {};
	ZeroMemory(mqlRequest);
	ZeroMemory(mqlResult);
	if (OP_BUY == iOrderType || OP_SELL == iOrderType) {
		mqlRequest.action	= TRADE_ACTION_DEAL;
	} else {
		mqlRequest.action	= TRADE_ACTION_PENDING;
	}
	mqlRequest.symbol		= strSymbol;
	mqlRequest.volume		= dLots;
	mqlRequest.type			= GetOrderType(iOrderType);
	mqlRequest.price		= dPrice;
	mqlRequest.sl			= NormalizeDouble(dSL, (int)SymbolInfoInteger(strSymbol, SYMBOL_DIGITS));
	mqlRequest.tp			= NormalizeDouble(dTP, (int)SymbolInfoInteger(strSymbol, SYMBOL_DIGITS));
	mqlRequest.price		= dPrice;
	mqlRequest.deviation	= iSlippage;
	mqlRequest.magic		= iMagicNumber;
	mqlRequest.comment		= strComment;
	long lMode = SymbolInfoInteger(strSymbol, SYMBOL_FILLING_MODE);
	mqlRequest.type_filling	= SYMBOL_FILLING_IOC == lMode ? ORDER_FILLING_IOC : ORDER_FILLING_FOK;
	bool bResult =  OrderSend(mqlRequest, mqlResult);
	if (bResult) {
		iResult = (int)mqlResult.order;
	} else {
	    iResult = -1;
	}
	return iResult;
}

#endif

MQL4ではOrderClose()ですが、MQL5ではOrderSend()でクローズしていることがわかります。
MQL4で指定する必要がない、シンボル(通貨)やオーダータイプ(ENUM_ORDER_TYPE)で反対となるオーダータイプを指定していることから、逆の注文を行うことでクローズするイメージであることがわかります。

使用例

0.02LotsのBUYポジションをオープンして、10秒後にクローズする処理です。
OrderClose()の5つめの引数でcolorを指定していますが、MQL5で色の指定が無いようなので無視する実装としています。

int iNewTicket = -1;
void OnTick()
{
	if (-1 == iNewTicket) {
		iNewTicket = OrderSend(Symbol(), OP_BUY, 0.02,
					NormalizeDouble(Ask, Digits),		//注文価格
					10,
					NormalizeDouble(100, Digits),		//S/L
					NormalizeDouble(150, Digits),		//T/P
					"",
					1,
					0,
					clrBlue);
		EventSetTimer(10);
	}
}
void OnTimer()
{
	bool bResult = OrderClose(iNewTicket, 0.02, Bid, 10, clrNONE);
	EventKillTimer();
}

オーターとポジションの区別

MQL5では、未約定の予約注文をオーダー、約定済をポジションと明確に区別しています。
その為、OrderClose()という関数名はMQL5では未約定オーダーに関する関数のように見えます。
よって、オーダーとポジションを区別するために関数名が以下の名前であることが良いのですが、懸念点も生じます。

No関数名懸念
1PositionClose()MQL4ではOrderClose()が組込み関数のためPositionClose()に関数名変更しなければMQL4では今まで通りの動作になる
2OrderClose()MQL5の場合、OrderClose()という関数名は未約定ポジションのクローズという意味となるが、未約定ポジションのクローズはMQL4ではOrderDelete()がある
未約定ポジションは削除する必要があるためである
懸念点

MQL4において、OrderClose()としての役割と名前がMQL5となった場合に矛盾が生じるが以下の定義とします。

No関数名MT動作説明
1PositionClose()MT4ポジションのクローズ新たな関数としてポジションのクローズを行う
(可読性を考慮して、今後はPositionClose()で記述することが望ましい)
2MT5ポジションのクローズ新たな関数としてポジションのクローズを行う
3OrderClose()MT4オーダーのクローズオーダーのクローズを行う
ただしポジションを指定するとポジションもクローズ出来てしまう
4MT5ポジションのクローズMQL4からの移植を考慮してポジションのクローズを行う
5OrderDelete()MT4注文の削除注文の削除を行う
6MT5注文の削除MQL4と同様に注文の削除を行う

追加の定義

オーダーとポジションの区別を考慮するために以下の追加定義を行います。
MQL4/5の両方で呼出しができるように定義します。

///////////////////////////////////////////////////////////////////////////////
//	MQL4/5用コード
///////////////////////////////////////////////////////////////////////////////
bool PositionClose(int iTicket, double dLots, double dPrice, int iSlippage, color arrow_color = clrNONE)
{
	bool bResult = false;
	return OrderClose(iTicket, dLots, dPrice, iSlippage, arrow_color);
}

使用例も以下のコードが推奨となります。
OnTimer()でOrderClose()ではなく、PositionClose()を使用しています。
何故、PositionSend()ではなく、OrderSend()で成行注文をしているかというのは、ポジションも成行で注文して約定しているためOrderSend()で注文していることとなります。

int iNewTicket = -1;
void OnTick()
{
	if (-1 == iNewTicket) {
		iNewTicket = OrderSend(Symbol(), OP_BUY, 0.02,
					NormalizeDouble(Ask, Digits),		//注文価格
					10,
					NormalizeDouble(100, Digits),		//S/L
					NormalizeDouble(150, Digits),		//T/P
					"",
					1,
					0,
					clrBlue);
		EventSetTimer(10);
	}
}
void OnTimer()
{
	bool bResult = PositionClose(iNewTicket, 0.02, Bid, 10, clrNONE);
	EventKillTimer();
}

以下の関数については別途説明します。

  1. OrderSend()

余談

ヒナタ
ヒナタ

オーダーとポジション区別するMQL5で不都合な関数名だね

ITサービス屋
ITサービス屋

未約定のオーダーはクローズ(Close)ではなく、削除(Delete)だもんね
過去の関数名をなかったことにする潔さ

ヒナタ
ヒナタ

抹消する必要があった関数名だね・・・💤

コメント

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