ホーム » ソース共通化 » 定義済み変数 » 定義済み変数

定義済み変数

概要

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に存在しないため、利用するためには別途考慮が必要となります。

互換性ありの関数(定義)については、本サイトで共通化の解説は行っていません。

NoVariableMQL5有無共通構文対処方法
1_Digits_Digits互換性あり
2_Point_Point互換性あり
3_LastError_LastError互換性あり
4_Period_Period互換性あり
5_RandomSeed_RandomSeed互換性あり
6_StopFlag_StopFlag互換性あり
7_Symbol_Symbol互換性あり
8_UninitReason_UninitReason互換性あり
9AskAskMQL5用の定義をする
10BarsBarsMQL5用の定義をする
11BidBidMQL5用の定義をする
12Close[]Close()配列を使用しているため共通化するために記述を変えて共通化する
13DigitsDigitsMQL5用の定義をする(※利用に注意が必要)
14High[]High()配列を使用しているため共通化するために記述を変えて共通化する
15Low[]Low()配列を使用しているため共通化するために記述を変えて共通化する
16Open[]Open()配列を使用しているため共通化するために記述を変えて共通化する
17PointPointMQL5用の定義をする
18Time[]Time()配列を使用しているため共通化するために記述を変えて共通化する
19Volume[]Volume()配列を使用しているため共通化するために記述を変えて共通化する
20_AppliedToMQL4には存在しない
21_IsX64MQL4には存在しない
定義済み変数一覧

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で差が出ている点は注意すべきです。

コメント

タイトルとURLをコピーしました