[MT4][プログラミング][入門] 2. OnInit()の仕様と注意点

ここでは、mql4のEvent handlerから呼び出されるOnInit()に関して仕様や注意点について確認していきます。
OnInit()を実装する上での参考にになればと思います。

また、mql4を実装する上での、フォーマットとなるサンプルコードや、概要に関してはまず、Expert Advisorのフォーマットファイルと概要をご覧ください。

Contents

OnInit()の仕様と注意点

1. OnInit()の仕様

ここでは、mql4のEvent handling functionであるOnInit()の仕様について確認していきます。

1-1. Interface仕様

OnInit()関数は、2つの異なるInterface仕様があります。

Type戻り値関数名引数
1voidOnInit()void
2intOnInit()void
OnInit() Interface 仕様

上記のように、戻り値の異なる2パターンがあります。
実際に実装する場合は、どちらを使用するかで戻り値の型を指定してください。

Type1の場合は、OnInit()関数が実行されれば毎回「初期化成功」として内部的に処理されます。初期化成功の場合はその後、Tickイベント等があればOnTick()などの処理が呼ばれるようになります。

Type2の場合は、戻り値に0以外を設定した場合、「初期化失敗」として内部的に処理されます。また、初期化失敗の場合はOnDeinit()関数が呼び出されるようになり、そのEAは動作を停止します。
EAの初期条件や、設定Parameterに指定の条件がある場合は誤動作防止ように、Type2を使用して各種パラメータチェック処理を実装するのが良いでしょう。
OnDeinit()が呼ばれた後は、Tickイベントが発生しても、OnTick()などは呼びだされません。
また、返却値は以下のいずれかの使用が推奨されています。

推奨返却値:
INIT_SUCCEEDED : 問題なく本関数が完了した際に使用
INIT_FAILED : 初期化に失敗した場合に使用
INIT_PARAMETERS_INCORRECT : 入力されたパラメータが不正な場合に使用

参考:OnInit()のType1とType2の実装サンプル

void OnInit(void)
{
	// 初期化処理など実装
	return;
}
int OnInit(void)
{
	int ret = INIT_SUCCEEDED;
	
	if     (/* 何かしらの条件 */)	{ ret = INIT_FAILED; }
	else if(/* 何かしらの条件 */)	{ ret = INIT_PARAMETERS_INCORRECT; }
	
	return ret;
}

1-2. 呼び出しタイミング仕様

次に、OnInit()の呼び出しタイミングの使用について確認していきましょう。
OnInit()は下記に示すタイミングで呼び出されます。

  1. プログラム読み込み直後。
  2. このプログラムが追加されているChart上で時間足が変更された時。
  3. このプログラムがChartに追加されている状態で、このプログラムを再コンパイルした時。
  4. このプログラムのセットアップ画面でパラメータが変更(再度OKを押された場合も)された時
  5. アカウントが変更された時。

ここで気になるのが、グローバル変数との関係です。
グローバル変数が初期化済みでOnInit()が呼び出されるのか、または、場合によって初期化されている場合とされていない場合があるのでしょうか。

このグローバル変数の初期化タイミングの認識が異なっていると、思わぬバグを呼び起こすことになりますので、注意したいところです。

2. OnInit()関数実装時の注意点

上記でOnInit()とグローバル変数の初期化タイミングについての懸念が提起されましたがここでは、その詳細についてもう少し追っていきたいと思います。

2-1. OnInit()とグローバル変数の関係

MQL4の仕様が記述される、MQL4 Referenceを参照しても回答が見つからなかった為、実際に簡単なEAを作成して確認していくことにします。

まずは、簡単なテスト用EAを作成します。
今回は、mql4のフォーマットサンプルコードで紹介したサンプルコードをベースにOnInit()とグローバル変数の関係について確認して行こうと思います。

サンプルコード

/*****************************/
/* propety setting  ・・・ A */
/*****************************/
#property copyright   "2020-2021, x corp."
#property version     "1.00"
#property strict

/*****************************/
/* Input variables  ・・・ B */
/*****************************/
input double	parameter1		= 1.0;

/******************************/
/* Global variables  ・・・ C */
/******************************/
double 			glovalValue1	= 1.0;

/************************************/
/* Event Handing Functions ・・・ D */
/************************************/
int OnInit(void)
{
	int ret = INIT_SUCCEEDED;
	
	// グローバル変数の初期化と、OnInit()が呼び出されるタイミング確認用出力
	glovalValue1++;
	Print("OnInit() : ", glovalValue1);
	
	return ret;
}

void OnDeinit(const int reason)
{
	return;
}

上記サンプルコードではOnInit()が呼び出されるごとに、グローバル変数のglovalValue1をインクリメントする処理を記述しそれを、「エキスパート」タブに結果出力する実装をしています。

このEAを使用して、OnInit()をそれぞれの呼び出し契機から呼び出してみましょう。

プログラム読み込み直後:
まずは、プログラム読み込み直後の確認です。
結果は、以下のようになっており、グローバル変数を定義した際の設定値「1」にさらに「1」を足した状態となっています。
プログラム読み込み直後は、グローバル変数の初期化後にOnInit()関数が呼び出されていることが分かります。

OnInit() : 2.0

Chart上で時間足が変更された時:
次にChart上で時間足が変更されたタイミングでのOnInit()の呼び出しについて見てみましょう。
結果は、以下のようになっており、プログラム読み込み直後の状態からさらに「1」を足した状態となっています。
このことから、時間足を変更したときは、グローバル変数の初期化がされていない状態でOnInit()が呼び出されていることが分かります。

OnInit() : 3.0

プログラムを再コンパイルした時:
ではそのほかもどんどん見ていきましょう。次はプログラムを再コンパイルした時です。
結果は、以下のようになっており、プログラム読み込み時と同様に、グローバル変数を定義した際の設定値「1」にさらに「1」を足した状態となっています。
プログラムを再コンパイルした時は、グローバル変数の初期化後にOnInit()関数が呼び出されていることが分かります。

OnInit() : 2.0

セットアップ画面でパラメータが変更:
最後に、セットアップ画面でパラメータを変更した時です。(アカウント変更については他のアカウントを所有していなかった為、試せませんでした。EA動作時にアカウント変更などを行う可能性のある方は、各自同じように試してみてください。)
結果は、以下のようになっており、プログラム読み込み直後の状態からさらに「1」を足した状態となっています。
このことから、セットアップ画面でパラメータを変更した時は、グローバル変数の初期化がされていない状態でOnInit()が呼び出されていることが分かります。

OnInit() : 3.0

2-2. OnInit()関数実装時の注意点まとめ

最後に、ここまで確認した、OnInit()の呼び出しとグローバル変数の初期化に関してのまとめです。

OnInit()呼び出しタイミンググローバル変数の初期化のありなし
プログラム読み込み直後あり
Chart上で時間足が変更された時なし
プログラムを再コンパイルした時あり
セットアップ画面でパラメータが変更なし
アカウントを変更した時– (各自で確認してみてください)
OnInit()の呼び出しタイミングとグローバル変数の初期化の関係まとめ

OnInit()関数内の初期化処理を実装する上で、グローバル変数の状態について、上記のように呼び出しタイミングにより異なってくるため、上記を考慮した実装を心掛けるようにし思わぬバグを埋め込まないようにしましょう。

次は、OnTick()の実装例です。

[お知らせ]MT4使いのあなたへ

日本の金融商品取引業者にも登録されているゴールデンウェイ・ジャパン社が運営するFXTF のご紹介です。

国内FX業者の中でも最狭水準のスプレッドで有名なFXTFでは、口座開設と2つの指定通貨ペアでの取引を行うだけで1万円のキャッシュバックがあります。

1万円キャッシュバックキャンペーンキャッシュバック受け取り方法:

キャッシュバックの受け取り方法は以下の2つの条件をクリアすることで取引口座へ振り込まれます。

条件1:
FXTFでの新規口座開設
※ここまでだけでも、3000円のキャッシュバックが受け取れます。

条件2:
以下の2通貨ペアそれぞれで1取引、合計2取引を口座開設から10日以内に行うこと。
USDJPY(スプレッド : 0.1銭 原則固定)
GBPJPY(スプレッド : 0.6銭 原則固定)
※取引量は問われないようです。
※この条件を達成すると追加で7000円キャッシュバックされます。(条件1と合わせて合計1万円になります)

その他補足情報:

MT4:利用可
関東財務局長(金商)登録番号:第258号

FXTFはMT4が使えて、スプレッドもとても小さいFX国内業者の為、このキャッシュバックキャンペーン期間中にメイン/サブ口座として開設するのもいいかもしれませんね。
※MT4での指定の取引量の取引を行うと、さらに+5万円がキャッシュバックされるキャンペーンもやっていますがこちらは、指定の取引量がかなり大きいので紹介は割愛させていただきます。