REASON_CHARTCHANGEは通貨ペア、時間足の変更どちらも対象になってしまう
OnDeinit関数で終了時の処理を実行する際、どういう理由でOnDeinit関数が呼ばれたかを識別することができます。
それがOnDeinit関数の引数const int reasonです。
reasonの中身を確認して、その内容によってOnDeinit関数で処理する内容を条件分岐できるんですね。
reasonの詳細は非初期化コードに譲りますが、この中にREASON_CHARTCHANGEというのがあります。
REASON_CHARTCHANGEは通貨ペアまたは時間足が変更された時にreasonにセットされます。
ここでやっかいなのは通貨ペアまたは時間足というところ。
なぜ全然意味の異なるこの2つの事象を1つに混ぜてしまったのか。
REASON_SYMBOLCHANGE、REASON_TIMEFRAMECHANGEと分けてほしかったです。
「時間足変更時には何もしたくないけど、通貨ペア変更時にはグローバル変数やオブジェクトを削除したい」ことってありますよね?
MT4に標準で用意されていないのなら、自分で対処するしかありません。
じゃあ、どうやってREASON_CHARTCHANGEを疑似的に通貨ペア変更時と時間足変更時で分離するかと言いますと、グローバル変数とOnInit関数、OnDeinitk関数の呼ばれる順番の性質を活用します。
通貨ペア変更時を例にとって説明します。
以下のコードをご覧ください。
// 通貨ぺア変更直前に通貨ペア名を格納するグローバル変数 string gBeforeSwitchSymbol = ""; OnInit() { // 初期化前後で通貨ペア名を比較して、異なっていれば通貨ペア変更による初期化と判断 if(gBeforeSwitchSymbol != "" && Symbol() != gBeforeSwitchSymbol){ // 通貨変更時に実施したい処理をここに記述 } } OnDeinit(const int reason) { // REASON_CHARTCHANGEの場合に通貨ペア名をグローバル変数に格納(退避) if(reason == REASON_CHARTCHANGE){ gBeforeSwitchSymbol = Symbol(); } }
処理の流れとしては、グローバル変数gBeforeSwitchSymbolに空文字をセットしてOnInit関数が呼ばれる。しかし、空文字なのでEA適用直後でのOnInit関数のif文は無視。
その後、通貨ペアが変更されてOnDeinit関数が呼ばれ、REASON_CHARTCHANGEに合致。gBeforeSwitchSymbolに変更直前の通貨ペア名をセット。
OnDeinit関数の次はOnInit関数が再度呼ばれる。gBeforeSwitchSymbolは空ではない。そして通貨ペア変更後の通貨ペア名Symbol()と直前の通貨ペア名の入ったgBeforeSwitchSymbolを比較。
通貨ペアを変更しているので、両者は一致せず。結果、通貨ペア変更時に実行したい処理が呼ばれる、となります。
時間足変更時の場合は、Symbol()ではなくPeriod()にすればOKです。その際、変数の型はstringからintに変更しましょう。