MT4においてユーザーは下図のようなパラメータ入力欄を操作することでインジケーターやEAが内部で使うパラメータを変更することができます。このパラメータはプログラム外部から渡されることから「外部パラメータ」などとも呼ばれたりします。
さてプログラム内部では以下のように関数の外でinputまたはexternを宣言することで外部パラメータを受け取るができます。
extern int ExternParam = 0; //externパラメータ
このinputとexternの違いは、前者がプログラム内部で変更できないのに対して後者が変更できる点です。
ここからが本題です。externで外部パラメータを受け取り、それを変数として使い回すと予期してない問題が発生する可能性があります。
解説用の以下のプログラムを見てください(動作に必要なOnCalculate関数などは省いています)。このプログラムはクリックチャートイベントが発生した時にexternで宣言した外部パラメータ(ExternParam)に1を代入する処理をしています。そしてOnInit関数とクリックチャートイベントの最後でExternParamの値を確認するためにPrint関数を実行しています。
//--- input parameters extern int ExternParam = 0; //externパラメータ //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { Print("ExternParam in OnInit: ", ExternParam); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| ChartEvent function | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { if(id == CHARTEVENT_CLICK) { ExternParam = 1; Print("ExternParam after CHARTEVENT_CLICK: ", ExternParam); } }
このプログラムを以下の手順で実行してみます。
- 外部パラメータ(ExternParam)は初期値0のまま変更せずにチャートにセットする。
- チャートをクリックしてクリックチャートイベントを発生させる。
- 時間軸を変更する。
はたしてExternParamの値はどのように変化しているでしょうか。以下コンソールログでExternParamの変化を確認してみてください。
チャートにセット直後はExternParamは初期値の0です。クリックチャートイベント発生で1に変化しています。ここまではいいのですが、そのあと時間軸を変更すると0に初期化されてしまいました!!
時間軸の変更だけではなく通貨ペアの変更やMT4の再起動などでもこのように外部パラメータの初期化処理が入ってしまうので、externを使うのであればOnInit関数内で外部パラメータを適切にケアしておく必要があります。
ただ外部パラメータはユーザー入力値であり、そもそも定数として扱うべき存在なのです。上記のように思わぬ値に変わってしまい問題を引き起こす可能性もあるため、外部パラメータはexternではなくinputを使うことをおすすめします。