取引関数のOrderSymbol()、PositionSymbol()について、MQL4とMQL5のソースコード共通化する方法を説明しています。
関数定義
MQL4の定義
string  OrderSymbol();ポジション、オーダーの区別はなくシンボル(通貨)を取得します。
MQL5の定義
定義なし
MQL5には、OrderSymbol()がありません。
共通化方法
- Order系関数はオーダーで使用することとする
 OrderSymbol()
- Position系関数はポジションで使用することとする
 PositionSymbol()
ただし、MQL5でオーダーはOrder系関数を使った記述をしても、MQL4に移植するとポジションも含まれてしまいます。
ソースを共通化するだけではなく、MQL4→MQL5とMQL5→MQL4への移植のケースもあると思います。よってこれら2つのケースも考慮したソース共通化を考えます。
| No. | 移植方法 | 特徴 | 
|---|---|---|
| 1 | MQL4→MQL5 | オーダー、ポジション共にOrderSymbol()でシンボル取得が行われている OrderSymbol()はオーダー、ポジションの区別をしない使われ方をしていることを考慮する必要がある PositionSymbol()の使用に分けた実装にすることが望ましい | 
| 2 | MQL5→MQL4 | MQL4と同じ引数のOrderSymbol()を定義するが、OrderSymbol()はオーダーのシンボル取得することと定義し、ポジションはPositionSymbol()関数を定義して利用することとする | 
ソース共通化
対処方法
共通化するためにMQL4とMQL5用の定義をします。
#ifdef __MQL5__ ~ #elseを使用することでMQL5のコンパイルにのみ有効となります。
#else~#endifはMQL5以外となるため、必然的にMQL4でのコンパイルのみ有効となります。
#ifdef __MQL5__
///////////////////////////////////////////////////////////////////////////////
// オーダーのシンボルを取得
string OrderSymbol()
{
	string strResult = OrderGetString(ORDER_SYMBOL);
	return strResult;
}
///////////////////////////////////////////////////////////////////////////////
// ポジションのシンボルを取得する
string PositionSymbol()
{
	string strSymbol = PositionGetString(POSITION_SYMBOL);
	return strSymbol;
}
#else	//__MQL4__
///////////////////////////////////////////////////////////////////////////////
// ポジションのシンボルを取得する
string PositionSymbol()
{
	return OrderSymbol();
}
#endifMQL5にOrderSymbol()とPositionSymbol()の定義をし、MQL4にはPositionSymbol()を定義しています。
MQL4のPositionSymbol()は、OrderSymbol()をそのまま呼び出す移植用のラッパー関数でしかありません。そのため、オーダーに対して使用してもそのまま動作します。よってMQL5に移植した場合に動作が不一致になるため、間違った使用をしないように注意が必要です。
使用例
ポジションとオーダーをオープンし、その後オーダー、ポジションの更新を行った後、クローズしています。
更新、クローズを行う際にシンボルが一致しているかをOrderSymbol()とPositionSymbol()で確認しています。
input	int			MagicNumber = 1;
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
					"",
					MagicNumber,
					0,
					clrBlue);
		int iNewOrder = OrderSend(Symbol(), OP_BUYSTOP, 0.03,
					NormalizeDouble(140, Digits()),		//注文価格
					10,
					NormalizeDouble(100, Digits()),		//S/L
					NormalizeDouble(150, Digits()),		//T/P
					"",
					MagicNumber,
					0,
					clrBlue);
		EventSetTimer(10);
	}
}
void OnTimer()
{
	static int iCountCall = 0;
	switch (iCountCall) {
	case 0:
		Modify(iCountCall);
		break;
	case 1:
		Close();
		break;
	default:
		EventKillTimer();
		break;
	}
	iCountCall++;
}
void Modify(int iCount)
{
	bool bResult = false;
	//オーダーの更新
	for (int iOrderIndex = OrdersTotal() - 1; iOrderIndex >= 0; iOrderIndex--) {
		//オーダー選択
		if (!OrderSelect(iOrderIndex, SELECT_BY_POS, MODE_TRADES)) {
			continue;
		}
		if (OP_BUY == OrderType() || OP_SELL == OrderType()) {
			continue;
		}
		//通貨確認
		if (Symbol() != OrderSymbol()) {
			continue;
		}
		//更新
		bResult = OrderModify(OrderTicket(), OrderOpenPrice() + 1, OrderStopLoss() + 1, OrderTakeProfit() + 1, 0, clrNONE);
	}
	//ポジションの更新
	for (int iPositionIndex = PositionsTotal() - 1; iPositionIndex >= 0; iPositionIndex--) {
		//ポジション選択
		if (!PositionSelect(iPositionIndex, SELECT_BY_POS, MODE_TRADES)) {
			continue;
		}
		if (OP_BUY != PositionType() && OP_SELL != PositionType()) {
			continue;
		}
		//通貨確認
		if (Symbol() != PositionSymbol()) {
			continue;
		}
		//価格設定
		double dPrice = OP_BUY == PositionType() ? Bid : Ask;
		//クローズ
		bResult = PositionModify(PositionTicket(), PositionOpenPrice(), PositionStopLoss() + 1, PositionTakeProfit() + 1, 0, clrNONE);
	}
}
void Close()
{
	bool bResult = false;
	//注文の削除
	for (int iOrderIndex = OrdersTotal() - 1; iOrderIndex >= 0; iOrderIndex--) {
		//注文選択
		if (!OrderSelect(iOrderIndex, SELECT_BY_POS, MODE_TRADES)) {
			continue;
		}
		if (OP_BUY == OrderType() || OP_SELL == OrderType()) {
			continue;
		}
		//通貨確認
		if (Symbol() != OrderSymbol()) {
			continue;
		}
		//削除
		bResult = OrderDelete(OrderTicket());
	}
	//ポジションのクローズ
	for (int iPositionIndex = PositionsTotal() - 1; iPositionIndex >= 0; iPositionIndex--) {
		//ポジション選択
		if (!PositionSelect(iPositionIndex, SELECT_BY_POS, MODE_TRADES)) {
			continue;
		}
		if (OP_BUY != PositionType() && OP_SELL != PositionType()) {
			continue;
		}
		//通貨確認
		if (Symbol() != PositionSymbol()) {
			continue;
		}
		//価格設定
		double dPrice = OP_BUY == PositionType() ? Bid : Ask;
		//クローズ
		bResult = PositionClose(PositionTicket(), PositionLots(), dPrice, 5);
	}
}以下の関数については別途説明します。
 
  
  
  
  
コメント