概要
MT4とMT5ではソースコードのビルド環境が別でもあり、MT4用の言語であるMQL4(MetaQuotes Language 4)とMT5用の言語であるMQL5(MetaQuotes Language 5)では互換性がありません。
ここでは、定義済み変数においてMT4用のソースコードとMT5用のソースコードを共通化するための方法について記載します。
ただし、MQL4の拡張子は「.mq4」MQL5の拡張子は「.mq5」の差がありますので、拡張子については変更してビルドする必要があります。
共通化一覧
No.1~8については、MQL4とMQL5は共通構文のためそのまま利用することが出来ます。
No.9以降がMQL5に存在しない構文のためソースコード共通化においては対処が必要です。
また、赤字で記載したNo.12,14~16,18~19についてはMQL4でも共通構文に置き換えてソースコードを記述する必要があります。
No.20,21はMQL4に存在しないため、利用するためには別途考慮が必要となります。
互換性ありの関数(定義)については、本サイトで共通化の解説は行っていません。
No | Variable | MQL5有無 | 共通構文 | 対処方法 |
---|---|---|---|---|
1 | _Digits | 〇 | _Digits | 互換性あり |
2 | _Point | 〇 | _Point | 互換性あり |
3 | _LastError | 〇 | _LastError | 互換性あり |
4 | _Period | 〇 | _Period | 互換性あり |
5 | _RandomSeed | 〇 | _RandomSeed | 互換性あり |
6 | _StopFlag | 〇 | _StopFlag | 互換性あり |
7 | _Symbol | 〇 | _Symbol | 互換性あり |
8 | _UninitReason | 〇 | _UninitReason | 互換性あり |
9 | Ask | ✕ | Ask | MQL5用の定義をする |
10 | Bars | ✕ | Bars | MQL5用の定義をする |
11 | Bid | ✕ | Bid | MQL5用の定義をする |
12 | Close[] | ✕ | Close() | 配列を使用しているため共通化するために記述を変えて共通化する |
13 | Digits | ✕ | Digits | MQL5用の定義をする(※利用に注意が必要) |
14 | High[] | ✕ | High() | 配列を使用しているため共通化するために記述を変えて共通化する |
15 | Low[] | ✕ | Low() | 配列を使用しているため共通化するために記述を変えて共通化する |
16 | Open[] | ✕ | Open() | 配列を使用しているため共通化するために記述を変えて共通化する |
17 | Point | ✕ | Point | MQL5用の定義をする |
18 | Time[] | ✕ | Time() | 配列を使用しているため共通化するために記述を変えて共通化する |
19 | Volume[] | ✕ | Volume() | 配列を使用しているため共通化するために記述を変えて共通化する |
20 | _AppliedTo | 〇 | ー | MQL4には存在しない |
21 | _IsX64 | 〇 | ー | MQL4には存在しない |
2022/07/04追記
Digitsについて、MQL5にDigits()が組込み関数で存在しておりますが、括弧が付かないDigitsの定義がありません。
#define Digits ((int)Digits())
の定義を記載していますが、組込み関数の「Digits()」を利用すると#define定義の反映で「Digits()()」となりますので、本#define定義は行わず「Digits」は利用せず「Digits()」を利用する方が良いかもしれません。
共通化方法
MQL5用の定義
対処方法
共通化するためにMQL5用の定義をします。
#ifdef __MQL5__ ~ #endifを使用することでMQL5のコンパイルにのみ有効となります。
MQL4の場合は「__MQL4__」を使用しますが、今回使用していないためMQL4は既存で組み込まれた定義済み変数が利用されます。
#ifdef __MQL5__
#define Ask ((double)AskMQL5())
#define Bars ((int)Bars(Symbol(), Period()))
#define Bid ((double)BidMQL5())
#define Digits ((int)Digits())
#define Point ((double)Point())
///////////////////////////////////////////////////////////////////////////////
// AskMQL5()
double AskMQL5()
{
MqlTick Tick;
SymbolInfoTick(Symbol(), Tick);
return Tick.ask;
}
///////////////////////////////////////////////////////////////////////////////
// BidMQL5()
double BidMQL5()
{
MqlTick Tick;
SymbolInfoTick(Symbol(), Tick);
return Tick.bid;
}
#endif
使用例
MQL4で記述していたままの使い方ができるようになります。
OnTick()で使用しています。
int OnInit()
{
#ifdef __MQL5__
Print("これはMT5で動作しています");
#else //__MQL4__
Print("これはMT4で動作しています");
#endif
return(INIT_SUCCEEDED);
}
void OnTick()
{
Print("Ask = ", Ask);
Print("Bid = ", Bid);
Print("Bars = ", Bars);
Print("Digits = ", Digits);
Print("Point = ", Point);
}
MT5で実行すると以下の様な実行結果が、エキスパートタブで確認することが出来ます。
記述を変える
対処方法
MQL4での構文が配列を使用するため、共通化することが出来ません。
よって、MQL4での構文を改善して共通化する手段を使います。
今回のケースではMQL4用とMQL5(__MQL5__)を分けて両方の定義を記述しています。
#ifdef __MQL5__
///////////////////////////////////////////////////////////////////////////////
// MQL5用コード
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Time()
datetime Time(int iShift)
{
datetime Time[];
ArraySetAsSeries(Time, true);
CopyTime(Symbol(), Period(), iShift, 1, Time);
return (datetime)Time[0];
}
///////////////////////////////////////////////////////////////////////////////
// Open()
double Open(int iShift)
{
double Open[];
ArraySetAsSeries(Open, true);
CopyOpen(Symbol(), Period(), iShift, 1, Open);
return Open[0];
}
///////////////////////////////////////////////////////////////////////////////
// Close()
double Close(int iShift)
{
double Close[];
ArraySetAsSeries(Close, true);
CopyClose(Symbol(), Period(), iShift, 1, Close);
return Close[0];
}
///////////////////////////////////////////////////////////////////////////////
// High()
double High(int iShift)
{
double High[];
ArraySetAsSeries(High, true);
CopyHigh(Symbol(), Period(), iShift, 1, High);
return High[0];
}
///////////////////////////////////////////////////////////////////////////////
// Low()
double Low(int iShift)
{
double Low[];
ArraySetAsSeries(Low, true);
CopyLow(Symbol(), Period(), iShift, 1, Low);
return Low[0];
}
///////////////////////////////////////////////////////////////////////////////
// Volume()
ulong Volume(int iShift)
{
long Volume[];
ArraySetAsSeries(Volume, true);
CopyTickVolume(Symbol(), Period(), iShift, 1, Volume);
return Volume[0];
}
#else //__MQL4__
///////////////////////////////////////////////////////////////////////////////
// MQL4用コード
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Time()
datetime Time(int iShift)
{
return (datetime)Time[iShift];
}
///////////////////////////////////////////////////////////////////////////////
// Open()
double Open(int iShift)
{
return Open[iShift];
}
///////////////////////////////////////////////////////////////////////////////
// Close()
double Close(int iShift)
{
return Close[iShift];
}
///////////////////////////////////////////////////////////////////////////////
// High()
double High(int iShift)
{
return High[iShift];
}
///////////////////////////////////////////////////////////////////////////////
// Low()
double Low(int iShift)
{
return Low[iShift];
}
///////////////////////////////////////////////////////////////////////////////
// Volume()
ulong Volume(int iShift)
{
return Volume[iShift];
}
#endif
使用例
Close[]などの配列を使った記述を、関数呼出しの構文に置き換えます。
例) Close[0] → Close(0)
int OnInit()
{
#ifdef __MQL5__
Print("これはMT5で動作しています");
#else //__MQL4__
Print("これはMT4で動作しています");
#endif
return(INIT_SUCCEEDED);
}
void OnTick()
{
Print("Close[0] = ", Close(0));
Print("Digits = ", Digits);
Print("High[0] = ", High(0));
Print("Low[0] = ", Low(0));
Print("Open[0] = ", Open(0));
Print("Point = ", Point);
Print("Time[0] = ", Time(0));
Print("Volume[0] = ", Volume(0));
}
MT5での実行結果は以下の通りです。
エキスパートタブで確認することが出来ます。
MT4での実行結果は以下の通りです。
エキスパートタブで確認することが出来ます。
MT4の表示は上が最新の表示のため、MT5と逆転しています。
Time(0)のPrint結果がMQL4とMQL5で差が出ている点は注意すべきです。
コメント