MT5が登場してからもう何年も経過していますが、いまだに取引ツールの定番といえばMT4です。
しかし、枯れた技術であるにも関わらずコンパイル時のインクルードの仕様についての日本語ソースが見つかりませんでした。
自身で使うだけならこの仕様は気にする必要なんてほぼないんですが、
私は配布もするのでこの仕様の調査をしました。
そこで備忘録もかねて上記仕様の解説します。
- mql4のインクルードとは
- mql4のコンパイルとは
- mql4コンパイル時のインクルードの仕様
- mql4コンパイル時のインクルードの仕様:まとめ
mql4のインクルードとは
そもそもmql4のインクルードとは、外部ファイルを読み込んでそのmql4内で使用できるようにすることを指します。
よく見かけるインクルードは、mql4を開くと大体載ってる以下のインクルードです。
#include <stdlib.mqh>
これはstdlib.mqhというヘッダーファイルをインクルードしています。
stdlib.mqhはstdlib.ex4というライブラリのヘッダーファイルです。
stdlibはErrorDescriptionなど基本的な関数が定義されています。
これと同様に自作のライブラリとヘッダーファイルを作成し、インクルードすることで自作の関数を一々インジケーターやEA内部にハードコーディングする必要がなくなります。
また、ライブラリファイルを作成することなく、ヘッダーファイルに直接関数を定義し、ヘッダーファイルをインクルードすることもできます。
(以前作成したRiskManagedOrderPanelはこちらのやり方を採用しています。)
こうすることでインジケーターやEA作成時の手間を省くことができるのです。
mql4のコンパイルとは
コンパイルはmql4ファイルからex4ファイルを作成することです。
通常、メタエディターのコンパイルボタンを押下することでコンパイルすることができます。
もう一つのやり方として、メタエディターの起動引数を指定することでコンパイルすることもできます。
これをVisualStudioCodeから行うことも可能です。
やり方は以下の記事で解説しているので、ご興味があればぜひご覧ください。
>>Visual Studio Codeでmql4をコンパイルできない場合に見直すべき設定
mql4コンパイル時のインクルードの仕様
ここから本題に入ります。
mql4のインクルードは外部に定義した関数をそのmql4ファイル内で使用できるようにすることでした。
この外部に関数を定義する方法としては先述の通り、以下の2つのやり方があります。
- ライブラリファイルに関数を定義
- ヘッダーファイルに関数を定義
ただし、その場合やり方2は非推奨とされています。これはソースコードの隠蔽やカプセル化、もっと広く言えばオブジェクト指向などの話になってきます。
興味があればググってみてください。
上記2つのやり方はそれぞれコンパイル時の動作が異なります。
また、コンパイルした後の動作も変わってしまいます。
以下より、それぞれの場合に分けて解説します。
なお、例として自作の共通関数ライブラリである「CommonFunctions」を使用します。
ライブラリファイルに関数を定義
まず、ライブラリファイルに関数を定義した場合について解説します。
以下の通りに場合分けします。
- ヘッダーファイルをインクルードし、ライブラリファイルを適切に配置
- ヘッダーファイルをインクルードし、ライブラリファイルを配置しない
- ヘッダーファイルもライブラリファイルも配置しない
ヘッダーファイルをインクルードし、ライブラリファイルを適切に配置
正常にコンパイルできる場合です。
コンパイルを実行すると以下のようになります。
0 errorとなり正常にコンパイルできます。
この方法でコンパイルしたex4ファイルは、ライブラリであるCommonFunctions.ex4を正常に配置しないと動作しません。
しかし、ヘッダーファイルであるCommonFunctions.mqhは実は動作には必要ありません。
これはコンパイル時にヘッダーファイル内の情報をまるっと取り込んでコンパイルしているからです。
ライブラリが存在しない場合およびヘッダーファイルが存在しない場合、以下の画像のようにどちらも同じエラーメッセージが表示されます。
上がライブラリ無しで実行したときのエラーメッセージ、下がどちらもなしの場合のエラーメッセージです。
下の場合、ヘッダーファイルが無いのでどの関数を呼び出せばいいのか分からなくなる…と思いがちですが、
ちゃんとCommonFunctions.ex4に定義されている関数を呼び出したいのにファイルがなくて呼び出せないよと怒られています。
このことからも、ヘッダーファイルの情報はコンパイル時にすべて取り込まれていることがわかると思います。
ヘッダーファイルをインクルードし、ライブラリファイルを配置しない
次に異常なパターンです。
この場合、当然ライブラリファイルがないのでエラーになる…と思いきや、
普通にコンパイルできます。
上記画像はコンパイルした時のログの画像ですが、エラーなしでコンパイルできてしまっています。
このことから、インジケーターやEAのコンパイル時の依存関係はヘッダーファイルまでであることが分かります。
図示すると以下の画像のようになります。
つまりヘッダーファイルに関数の中身を書かずに定義のみ書いておけばコンパイルできるということです。
また、この方法でコンパイルしたインジケーターやEAは実行時にライブラリファイルを配置してやれば正常に動作します。
先にヘッダーファイルだけで用意しておいて後からライブラリファイルを作成し、
実行時に配置するということもできるでしょう。(やる意味があるかどうかは分かりませんが)
ヘッダーファイルもライブラリファイルも配置しない
最後のパターンになります。
当然ですが必要なファイルを何も配置していないのでコンパイルエラーになります。
ヘッダーファイルが読み込めないよ、という風にエラーが出ています。
ヘッダーファイルに関数を定義
続いて、ヘッダーファイルに直接関数を定義する場合を解説します。
この場合、ライブラリファイルの内容をすべてヘッダーファイル内に定義します。
そのため、前提としてライブラリファイルは必要ありません。
以下の通りに場合分けします。
- ヘッダーファイルを適切に配置してインクルード
- ヘッダーファイルを配置せずにインクルード
ヘッダーファイルを適切に配置してインクルード
まずは正常にコンパイルできる場合です。
CommonFunctions.mqhのみ適切に配置してコンパイルしてみます。
すると以下の画像のように正常にコンパイルされます。
この方法でコンパイルしたインジケーターやEAを使用する際、ヘッダーファイルは必要ありません。
なぜなら、先述の通りmql4のコンパイル時の仕様として、コンパイル時にヘッダーファイルの中身をすべて取り込んでコンパイルしているからです。
以下はこの方法でコンパイルしたEAのバックテストログです。
正常にバックテストが完了していることが分かります。
ヘッダーファイルを配置せずにインクルード
異常な場合です。
この場合、必要なファイルが配置されていないためコンパイルエラーになります。
ヘッダーもライブラリも配置しなかった時と同じエラーが発生しています。
mql4コンパイル時のインクルードの仕様:まとめ
mql4のインクルードとは、外部ファイルを読み込んでそのmql4内で使用できるようにすることを指します。
そして、コンパイルはmql4ファイルからex4ファイルを作成することです。
この外部に関数を定義する方法としては、以下の2つのやり方があります。
- ライブラリファイルに関数を定義
- ヘッダーファイルに関数を定義
それぞれのパターンをまとめると以下のようになります。
①のやり方
ファイル | コンパイル時 | 実行時 |
ヘッダー | 必要 | 不要 |
ライブラリ | 不要 | 必要 |
②のやり方
ファイル | コンパイル時 | 実行時 |
ヘッダー | 必要 | 不要 |
いかがでしたでしょうか。
今まで私はライブラリファイルに関数を定義していましたが、
これからは利便性を考えてヘッダーファイルに直接関数を定義しようかと思います。
セキュリティ的にどうなの?という感じもしますが、ライブラリファイルに定義しても結局配布するにはインジケーターやEA本体側に定義していた関数を移すか、ライブラリも配布するかしないといけません。
なので、ヘッダーファイルに直接関数を定義してもあまり変わらないと思っています。
今回の記事が少しでもお役に立てれば幸いです。
コメント