static変数を多用したEAは危険!~PART2

前回の記事では、ティック変動で初期化されずに以前の数値等を記憶できるstatic変数や外部変数について紹介し、それらは、パソコンまたはメタトレーダーもしくはEAのいずれかが再起動されたときに、再び初期化されるため、保存されていた記憶が切断されてしまい、再起動後のEAがわけのわからない作動をしてしまう、という危険性について指摘しました。

こういった問題に対する解決策として、一般的によく知られているのが、グローバル変数(大域変数)す。

 

これは、前回紹介した外部変数をメタトレーダー内に一時的に登録することによって、EA再起動時にも以前の数値を保持できる仕組みです。

 

登録は手動でもできます。

メニューの「ツール」から「グローバル変数」を選択すると、上のような登録画面が出て、自由に設定できますが、今回は、プログラミングによって、グローバル変数の登録と再利用をする方法を、まずは簡単に紹介しておきます。

 

プログラムの流れをザックリと示すと、

 

①前回同様、まずは外部変数をスタート関数外で宣言する。

②ティック変動にもかかわらず、その外部変数が以前の数値を記憶しながら変化していく。

③EAが停止する直前に、その最後の数値だけをグローバル変数としてメタトレーダー内に登録しておく。

④次にEAを再起動したときに一回だけその数値を呼び出して元の外部変数に返してやる。

 

となります。

まずは、スタート関数で、適当に外部変数を宣言しましょう。

次に、スタート関数で、前回と同様にティック変動のたびに「1」を加算していき、それをチャート左上にコメント表示させます。

もしも、EAが停止したときに備えて、今度は、deinit()関数内に、グローバル変数への登録プログラムを書きます。

 

このdeinit()関数は、EAやインジケーターが停止するときに、一度だけ呼び出される関数で、こんなときには重宝します。

GlobalVariableSet()関数は、外部変数をメタトレーダー内へグローバル変数として登録するための関数で、上のように、パラメーターは、("変数名",値)となります。

 

最後に、init()関数内に、登録済のグローバル変数の値をEA上へ読み込むプログラムを書きます。

 

このinit()関数は、EAやインジケーターが挿入されたときに一度だけ呼び出される関数です。

上のように、GlobalVariableGet()関数を使って、変数名を指定すると、登録された時点の値が呼び出されるので、その値を元の外部変数Gへ返してやります。

 

あとは、スタート関数の実行で、その値にさらに「1」が加算されていくわけです。

 

こうして、結局、Gの値は、

 

0,1,2,3   再起動  4,5,6…

 

と連続していきます。

 

 

 

しか~し、

このグローバル変数(大域変数)には、いくつかリスクがあります。

 

通常の外部変数と異なり、メタトレーダー内のどのEA、どのインジケーターからも呼び出すことが可能なため、別のEAでうっかり同じ名前のグローバル変数の登録をしてしまうと、それらEA間で相互干渉が生じてしまいます。5~6個程度の登録であれば少し注意すれば済む話ですが、30個も40個もグローバル変数を登録してしまうと、わけがわからなくなってしまい、重大な事故につながります。

この問題を解決する方法はいくつかありますが、とりあえず、一番手っ取り早い方法としては、グローバル変数の名前に、マジックナンバーと通貨ペア名を付与することでしょう

たとえば、上のようにしてやれば、

という具合に登録され、

 

①マジックナンバー1234のEAで

②USDJPYのチャートで使用される

③「1」つ目のグローバル変数

 

というふうに特定されるので、かなり事故防止になるかなと思います。

 

 

しか~し、

グローバル変数(大域変数)には、もう一つリスクがあります。

 

それは、有効期限があって、最後に値が更新されてから4週間経過すると自動的に登録が抹消されるということです。

 

まあ、4週間も以前の数値を記憶しているようなグローバル変数は一度抹消して、新たに初期化された外部変数を利用した方が好都合だという話もありますが、ユーザーの意図とは異なる作動が自動的に生じるというのは、あまり気持ちのいいものではありません。

 

次回は、外部変数を無期限でメタトレーダー内に保存する方法を考えたいと思います。