MQL4/MQL5で似たようなパラメーターをまとめて作成する


似たようなパラメーターをまとめて作成する方法を紹介します。

例えばEAやインジケーターで移動平均線を使用したいとき、次のようなパラメーターを作成するかと思います。

input int period = 10;
input int shift = 0;
input ENUM_MA_METHOD method = MODE_SMA;

使用する移動平均線が1本であればこれだけで済みますが、もし複数の移動平均線を使用する場合、パラメーター変数には同じ名前を使用できないのでパラメーターを変えて記述していく必要があります。
例えば期間に関するパラメーターであればperiod_1, period_2, ...といったように番号を振っていくこととなります。
もし移動平均線を10本や100本使用したいとなってくるとこの作業は少々面倒ですし、パラメーター名を変えたくなった際や、平滑化する価格に関するパラメーターも増やしたくなった場合などは更に手間が増えます。

そこでマクロを使って少し楽に作成する方法を紹介します。
実際に作成したコードは下記になります。

#define CREATE_PARAMS(index, period) \
    input int period_##index = period; \
    input int shift_##index = 0; \
    input ENUM_MA_METHOD method_##index = MODE_SMA;

マクロの基本

マクロを使うには#defineを使います。
基本は下記の形式で使用します。

#define 識別子 式

識別子にはパラメーターを渡すこともできます。(ただしパラメーターは最大8個まで)
その場合は下記の形式となります。

#define 識別子(パラメータ1,... パラメータ8) 式

今回はCREATE_PARAMSと命名しました。
バックスラッシュを使うことで改行もできるので、複数行の処理でも見やすく定義できます。

変数名への対応

#defineを使ってパラメーターのセットを定義した際に問題となるのが、パラメーターの変数名です。
同じ変数名は宣言できないため、CREATE_PARAMSの呼び出し毎に作成されるパラメーター名を変えてあげる必要があります。
今回CREATE_PARAMSにはindexというパラメーターを用意しました。
indexで渡された数字をパラメーター名に付けることで、この問題を解決します。

この時、indexの前に##が付いているのがポイントです。
もし##を付けずにperiod_indexとしてしまうと、作成されるパラメーターも「period_index」という名称になってしまいます。
period_##indexとすることで、indexが1であれば、「period_1」という名称となってパラメーターが作成されます。
後は適当なパラメーターをCREATE_PARAMSに渡して呼び出すだけです。

#define CREATE_PARAMS(index, period) \
    input int period_##index = period; \
    input int shift_##index = 0; \
    input ENUM_MA_METHOD method_##index = MODE_SMA; \

CREATE_PARAMS(1, 10)
// period_1, shift_1, method_1の3つのパラメーターが作られる
// period_1の初期値は10

CREATE_PARAMS(2, 20)
// period_2, shift_2, method_2の3つのパラメーターが作られる
// period_2の初期値は20

複数行必要だった宣言を1行で書けるようになり、コピペして数字を変えていく地道な作業から開放されます。

欠点

この方法の欠点として、コメントを使ったパラメーター名に日本語や記号を設定する方法を使用することができません。
通常のパラメーター宣言は、宣言した行の最後にコメントアウトを付けることで、コメントの内容がパラメーター名となります。
#define内でも/* コメント */形式でのコメントが挿入可能ですが、この方法を使ってもパラメーター名をコメントに変えることはできません。

input int test = 1; /* hoge */
// -> パラメーター名はhogeになる

#define CREATE_PARAMS(index, period) \
    input int period_##index = period; /* uga */ \

CREATE_PARAMS(1, 10)
// -> パラメーター名はperiod_1になる(ugaにはならない)

何らかの理由でパラメーター名に日本語や記号などを使いたい場合は、地道にパラメーターを宣言しましょう。