取引関数のOrderOpenTime()、PositionOpenTime()について、MQL4とMQL5のソースコード共通化する方法を説明しています。
関数定義
MQL4の定義
datetime OrderOpenTime();
ポジション、オーダーの区別はなくオープン時間を取得します。
MQL5の定義
定義なし
MQL5には、OrderOpenTime()がありません。
共通化方法
- Order系関数はオーダーで使用することとする
OrderOpenTime() - Position系関数はポジションで使用することとする
PositionOpenTime()
ただし、MQL5でオーダーはOrder系関数を使った記述をしても、MQL4に移植するとポジションも含まれてしまいます。
ソースを共通化するだけではなく、MQL4→MQL5とMQL5→MQL4への移植のケースもあると思います。よってこれら2つのケースも考慮したソース共通化を考えます。
No. | 移植方法 | 特徴 |
---|---|---|
1 | MQL4→MQL5 | オーダー、ポジション共にOrderOpenTime()でSL価格の取得が行われている OrderOpenTime()はオーダー、ポジションの区別をしない使われ方をしていることを考慮する必要がある PositionOpenTime()の使用に分けた実装にすることが望ましい |
2 | MQL5→MQL4 | MQL4と同じ引数のOrderOpenTime()を定義するが、OrderOpenTime()はオーダーのSL価格を取得することと定義し、ポジションはPositionOpenTime()関数を定義して利用することとする |
ソース共通化
対処方法
共通化するためにMQL4とMQL5用の定義をします。
#ifdef __MQL5__ ~ #elseを使用することでMQL5のコンパイルにのみ有効となります。
#else~#endifはMQL5以外となるため、必然的にMQL4でのコンパイルのみ有効となります。
#ifdef __MQL5__
///////////////////////////////////////////////////////////////////////////////
// オーダーのSL価格を取得
double OrderStopLoss()
{
double dResult = OrderGetDouble(ORDER_SL);
return dResult;
}
///////////////////////////////////////////////////////////////////////////////
// ポジションのオープン時間を取得
datetime PositionOpenTime()
{
datetime dtResult = (datetime)PositionGetInteger(POSITION_TIME);
return dtResult;
}
#else //__MQL4__
///////////////////////////////////////////////////////////////////////////////
// ポジションのオープン時間を取得
datetime PositionOpenTime()
{
return OrderOpenTime();
}
#endif
MQL5にOrderOpenTime()とPositionOpenTime()の定義をし、MQL4にはPositionOpenTime()を定義しています。
MQL4のPositionOpenTime()は、OrderOpenTime()をそのまま呼び出す移植用のラッパー関数でしかありません。そのため、オーダーに対して使用してもそのまま動作します。よってMQL5に移植した場合に動作が不一致になるため、間違った使用をしないように注意が必要です。
使用例
ポジションとオーダーをオープンし、それぞれでオーダー、ポジションのオープン時間を取得しています。
input int MagicNumber = 1;
int iNewTicket = -1;
int OnInit()
{
#ifdef __MQL5__
Print("これはMT5で動作しています");
#else //__MQL4__
Print("これはMT4で動作しています");
#endif
return(INIT_SUCCEEDED);
}
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);
if (0 <= iNewTicket) {
if (PositionSelect(iNewTicket, SELECT_BY_TICKET)) {
Print("PositionOpenTime():", PositionOpenTime(), " - ", TimeToString(PositionOpenTime(), TIME_DATE | TIME_SECONDS));
Print("OrderOpenTime():", OrderOpenTime(), " - ", TimeToString(OrderOpenTime(), TIME_DATE | TIME_SECONDS ));
}
}
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);
if (0 <= iNewOrder) {
if (OrderSelect(iNewOrder, SELECT_BY_TICKET)) {
Print("PositionOpenTime():", PositionOpenTime(), " - ", TimeToString(PositionOpenTime(), TIME_DATE | TIME_SECONDS));
Print("OrderOpenTime():", OrderOpenTime(), " - ", TimeToString(OrderOpenTime(), TIME_DATE | TIME_SECONDS ));
}
}
}
}
以下の関数については別途説明します。
MT5での実行結果
1回目のOrderOpenTime()はポジションであるため、オープン時間は取得できません(1970.01.01 00:00:00)。
2回目のPositionOpenTime()は最初のオープン時間がそのまま引き継がれているため、2回目のポジションのオープン時間は2022.08.08 08:12:55になります。
MT4での実行結果
1回目のOrderOpenTime()はポジションにもかかわらず、ポジションと同じでオープン時間は2022.07.08 10:35:06になります。
2回目のPositionOpenTime()はオーダーにもかかわらず、ポジションと同じでオープン時間は2022.07.08 10:35:07になります。
これらの差が、ポジションとオーダーを区別していないMQL4での特徴です。この特徴を認識した上で注意した実装が必要です。
コメント