標準関数を使っても良いけれど
トラリピEAを作るにあたって、仕掛けの上限価格と下限価格を長期記憶しておく必要があることが分かりました。通常、変数はMT4を終了すると中身が消えてしまいます。それだと、ある情報を記憶し続けておく必要のある今回のようなケースでは困るわけです。そこで、MT4を終了しても情報が消えることの無いグローバル変数を使うことにしました。
グローバル変数には実は2つの意味がありまして、1つはMQL4内の全てをスコープにした変数(OnInit()、OnTick()等の外に宣言する変数のこと)、もう1つがMT4内の全てをスコープにした変数(MT4の[ツール]-[グローバル変数])です。
今回は後者の方の意味ですね。なぜ意味の異なる変数を同じ名前にしたのか理解に苦しみます…。
グローバル変数は、トラリピEAのように日を跨いでポジションを保有するEAで使われることが多い印象です。週末にOSを再起動するケースを想定しているわけです。
さて、このグローバル変数を扱う関数がMT4に標準で搭載されています。GlobalVariableSet()等です。
これをそのまま使っても勿論良いのですが、グローバル変数は1つのMT4内で共通して使われるものなので、全く性質の異なるEA1とEA2を同一MT4上で稼働し、それぞれのEAが同じ名前のグローバル変数をうっかり使っていたりすると、お互いが干渉しあっちゃって、不具合の原因になりかねません。
というわけで、うっかり防止のためにグローバル変数を制御するオリジナル関数を作りました(ただのラッパーなんですけどね)。
//+------------------------------------------------------------------+ //|【関数】グローバル変数設定 | //| | //|【引数】 IN OUT 引数名 説明 | //| --------------------------------------------------------- | //| ○ aName グローバル変数名 | //| ○ aMagic マジックナンバー | //| ○ aSymbol 通貨ペア名 | //| ○ aTimeframe 時間枠 | //| ○ aValue グローバル変数値 | //| | //|【戻値】なし | //| | //|【備考】なし | //+------------------------------------------------------------------+ void setGlobalVariables(string aName, int aMagic, string aSymbol, int aTimeframe, double aValue) { string name = aName + "_" + aMagic + "_" + aSymbol + "_" + aTimeframe; datetime result = GlobalVariableSet(name, aValue); } //+------------------------------------------------------------------+ //|【関数】グローバル変数取得 | //| | //|【引数】 IN OUT 引数名 説明 | //| --------------------------------------------------------- | //| ○ aName グローバル変数名 | //| ○ aMagic マジックナンバー | //| ○ aSymbol 通貨ペア名 | //| ○ aTimeframe 時間枠 | //| | //|【戻値】取得したグローバル変数値 | //| | //|【備考】なし | //+------------------------------------------------------------------+ double getGlobalVariables(string aName, int aMagic, string aSymbol, int aTimeframe) { string name = aName + "_" + aMagic + "_" + aSymbol + "_" + aTimeframe; if(GlobalVariableCheck(name)){ double result = GlobalVariableGet(name); } return(result); } //+------------------------------------------------------------------+ //|【関数】グローバル変数削除 | //| | //|【引数】 IN OUT 引数名 説明 | //| --------------------------------------------------------- | //| ○ aName グローバル変数名 | //| ○ aMagic マジックナンバー | //| ○ aSymbol 通貨ペア名 | //| ○ aTimeframe 時間枠 | //| | //|【戻値】なし | //| | //|【備考】なし | //+------------------------------------------------------------------+ void deleteGlobalVariables(string aName, int aMagic, string aSymbol, int aTimeframe) { string name = aName + "_" + aMagic + "_" + aSymbol + "_" + aTimeframe; if(GlobalVariableCheck(name)){ GlobalVariableDel(name); } } //+------------------------------------------------------------------+ //|【関数】グローバル変数存在チェック | //| | //|【引数】 IN OUT 引数名 説明 | //| --------------------------------------------------------- | //| ○ aName グローバル変数名 | //| ○ aMagic マジックナンバー | //| ○ aSymbol 通貨ペア名 | //| ○ aTimeframe 時間枠 | //| | //|【戻値】true :存在する | //| false:存在しない | //| | //|【備考】なし | //+------------------------------------------------------------------+ bool checkGlobalVariables(string aName, int aMagic, string aSymbol, int aTimeframe) { string name = aName + "_" + aMagic + "_" + aSymbol + "_" + aTimeframe; return(GlobalVariableCheck(name)); }
グローバル変数を扱う標準関数は他にもあるのですが、少なくとも私の場合、それらを使うことが殆ど無いので、割愛しました。
グローバル変数名にマジックナンバーと通貨ペア名と時間枠をくっつけることで、変数の重複防止を図っているのが分かると思います。若干やり過ぎな気もしますが、事故が起きるよりはマシでしょう。