取引関数のOrderType()、PositionType()において、MQL4とMQL5のソースコード共通化する方法を説明しています。
関数定義
MQL4の定義
int OrderType();
ポジション、オーダーの区別はなく取引のタイプ(BUY,SELL等)を取得します。
MQL5の定義
定義なし
MQL5には、OrderType()がありません。
共通化方法
- Order系関数はオーダーで使用することとする
OrderType() - Position系関数はポジションで使用することとする
PositionType()
ただし、MQL5でオーダーはOrder系関数を使った記述をしても、MQL4に移植するとポジションも含まれてしまいます。
ソースを共通化するだけではなく、MQL4→MQL5とMQL5→MQL4への移植のケースもあると思います。よってこれら2つのケースも考慮したソース共通化を考えます。
No. | 移植方法 | 特徴 |
---|---|---|
1 | MQL4→MQL5 | オーダー、ポジション共にOrderType()でシンボル取得が行われている OrderType()はオーダー、ポジションの区別をしない使われ方をしていることを考慮する必要がある PositionType()の使用に分けた実装にすることが望ましい |
2 | MQL5→MQL4 | MQL4と同じ引数のOrderType()を定義するが、OrderType()はオーダーのシンボル取得することと定義し、ポジションはPositionType()関数を定義して利用することとする |
ソース共通化
対処方法
共通化するためにMQL4とMQL5用の定義をします。
#ifdef __MQL5__ ~ #elseを使用することでMQL5のコンパイルにのみ有効となります。
#else~#endifはMQL5以外となるため、必然的にMQL4でのコンパイルのみ有効となります。
#ifdef __MQL5__
///////////////////////////////////////////////////////////////////////////////
// オーダーのタイプを取得
int OrderType()
{
int iResult = -1;
ENUM_ORDER_TYPE iPositionType = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
iResult = GetOrderType(iPositionType);
return iResult;
}
///////////////////////////////////////////////////////////////////////////////
// ポジションの取引タイプを取得する
int PositionType()
{
return PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY ? OP_BUY : OP_SELL;
}
#else //__MQL4__
///////////////////////////////////////////////////////////////////////////////
// ポジションの取引タイプを取得する
int PositionType()
{
return OrderType();
}
#endif
MQL5にOrderType()とPositionType()の定義をし、MQL4にはPositionType()を定義しています。
MQL4のPositionType()は、OrderType()をそのまま呼び出す移植用のラッパー関数でしかありません。そのため、オーダーに対して使用してもそのまま動作します。よってMQL5に移植した場合に動作が不一致になるため、間違った使用をしないように注意が必要です。
使用例
ポジションとオーダーをオープンし、その後オーダー、ポジションの更新を行った後、クローズしています。
更新、クローズを行う際に取引タイプが正しいかをOrderType()とPositionType()で確認しています。MQL4では、OrdersTotal()でオーダーとポジションの区別を行わずに総数を返すため取引タイプを確認して処理を行う必要があります。
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);
}
}
以下の関数については別途説明します。
コメント