取引関数のPositionsTotal()について、MQL4とMQL5のソースコード共通化する方法を説明しています。
関数定義
MQL4の定義
定義なし
MQL4には、PositionsTotal()がありません。
MQL5の定義
int PositionsTotal();
ポジションの総数を取得します。
MQL4ではOrdersTotal()でオーダーとポジションの総数を取得することを意識する必要があります。
共通化方法
MQL4でオーダーとポジションを区別する概念がありません。そのためPositionsTotal()が存在しないことを考慮します。
ソースを共通化するだけではなく、MQL4→MQL5とMQL5→MQL4への移植のケースもあると思います。よってこれら2つのケースも考慮したソース共通化を考えます。
No. | 移植方法 | 特徴 |
---|---|---|
1 | MQL4→MQL5 | PositionsTotal()が存在しないため、MQL4ではオーダーとポジションの区別のないOrdersTotal()を利用されますが、移植した場合にMQL5ではオーダーとポジションの区別がされるため期待通りの動作にならない結果が生じる可能性があります MQL4でOrdersTotal()を使用してオーダーとポジションの総数を期待していても、MQL5に移植するとオーダーの総数となってしまうため、MQL4でオーダーとポジションの総数を期待した実装は避けるべきです |
2 | MQL5→MQL4 | PositionsTotal()はポジション総数のみの取得であるため、MQL4に移植した際を考慮し、OrderType()、PositionType()によりタイプを意識する必要があります |
ソース共通化
対処方法
共通化するためにMQL4用の定義をします。
#ifdef __MQL4__ ~ #endifを使用することでMQL4のコンパイルにのみ有効となります。
#ifdef __MQL4__
///////////////////////////////////////////////////////////////////////////////
// ポジション数を取得する(MQL4では注文も選択される)
int PositionsTotal()
{
int iResult = OrdersTotal();
return iResult;
}
#endif
使用例
ポジションとオーダーをオープンし、10秒後にオーダー削除、ポジションクローズをそれぞれ行っています。
input int MagicNumberOrder = 100;
input int MagicNumberPosition = 200;
int iNewTicket = -1;
void OnTick()
{
if (-1 == iNewTicket) {
iNewTicket = OrderSend(Symbol(), OP_BUY, 0.02,
NormalizeDouble(Ask, Digits()), //注文価格
10,
NormalizeDouble(20000, Digits()), //S/L
NormalizeDouble(25500, Digits()), //T/P
"Position",
MagicNumberOrder,
0,
clrBlue);
if (0 < iNewTicket) {
Print("ポジション成功:", iNewTicket);
}
int iNewOrder = OrderSend(Symbol(), OP_BUYSTOP, 0.03,
NormalizeDouble(22000, Digits()), //注文価格
10,
NormalizeDouble(20000, Digits()), //S/L
NormalizeDouble(25000, Digits()), //T/P
"Order",
MagicNumberPosition,
0,
clrBlue);
if (0 < iNewOrder) {
Print("オーダー成功:", iNewOrder);
}
EventSetTimer(10);
}
}
void OnTimer()
{
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());
if (bResult) {
Print("オーダーの削除成功:", 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);
if (bResult) {
Print("ポジションのクローズ成功:", PositionTicket());
}
}
EventKillTimer();
}
以下の関数については別途説明します。
MT5での実行結果
ポジションとオーダーをオープンし、オーダーの削除、ポジションのクローズを順に行っています。
MT4での実行結果
MQL4でのPositonsTotal()ではオーダーとポジションの総数が取得できますが、オーダーを除外してポジションを削除しています。
オーダーのクローズについては、OrdersTotal()を参照してください。
コメント