取引関数のOrderTicket()、PositionTicket()について、MQL4とMQL5のソースコード共通化する方法を説明しています。
関数定義
MQL4の定義
int OrderTicket();
ポジション、オーダーの区別はなくチケットを取得します。
MQL5の定義
定義なし
MQL5には、OrderTicket()がありません。
MQL5では、オーダーチケットとポジションチケットで区別されている点がMQL4と変更点です。
共通化方法
- Order系関数はオーダーで使用することとする
OrderType() - Position系関数はポジションで使用することとする
PositionType()
ただし、MQL5でオーダーはOrder系関数を使った記述をしても、MQL4に移植するとポジションも含まれてしまいます。
ソースを共通化するだけではなく、MQL4→MQL5とMQL5→MQL4への移植のケースもあると思います。よってこれら2つのケースも考慮したソース共通化を考えます。
No. | 移植方法 | 特徴 |
---|---|---|
1 | MQL4→MQL5 | オーダー、ポジション共にOrderTicket()でチケットの取得が行われている OrderTicket()はオーダー、ポジションの区別をしない使われ方をしていることを考慮する必要がある PositionType()の使用に分けた実装にすることが望ましい |
2 | MQL5→MQL4 | MQL4と同じ引数のOrderTicket()を定義するが、OrderTicket()はオーダーのチケット取得することと定義し、ポジションはPositionType()関数を定義して利用することとする |
ソース共通化
対処方法
共通化するためにMQL4とMQL5用の定義をします。
#ifdef __MQL5__ ~ #elseを使用することでMQL5のコンパイルにのみ有効となります。
#else~#endifはMQL5以外となるため、必然的にMQL4でのコンパイルのみ有効となります。
#ifdef __MQL5__
///////////////////////////////////////////////////////////////////////////////
// オーダーのチケットを取得
long OrderTicket()
{
long lResult = OrderGetInteger(ORDER_TICKET);
return lResult;
}
///////////////////////////////////////////////////////////////////////////////
// ポジションのチケットを取得
int PositionTicket()
{
return (int)PositionGetInteger(POSITION_TICKET);
}
#else //__MQL4__
///////////////////////////////////////////////////////////////////////////////
// 約定済ポジション(未決済)のチケットを取得
int PositionTicket()
{
return OrderTicket();
}
#endif
MQL5にOrderTicket()とPositionTicket()の定義をし、MQL4にはPositionTicket()を定義しています。
MQL4のPositionTicket()は、OrderTicket()をそのまま呼び出す移植用のラッパー関数でしかありません。そのため、オーダーに対して使用してもそのまま動作します。よってMQL5に移植した場合に動作が不一致になるため、間違った使用をしないように注意が必要です。
使用例
ポジションとオーダーをオープンし、その後オーダー、ポジションの更新を行った後、クローズしています。
更新(OrderModify()、PositionModify())、削除(OrderDelete())、クローズ(PositionClose())を行う際にOrderTicket()とPositionTicket()を使用しています。
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;
}
//更新
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;
}
//価格設定
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;
}
//削除
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;
}
//価格設定
double dPrice = OP_BUY == PositionType() ? Bid : Ask;
//クローズ
bResult = PositionClose(PositionTicket(), PositionLots(), dPrice, 5);
}
}
以下の関数については別途説明します。
コメント