コンパイルエラー
constant expression required
double ma0 = iMA(Symbol(), PERIOD_CURRENT, 9, 0, MODE_SMA, PRICE_CLOSE, 0);
double ma1 = iMA(Symbol(), PERIOD_CURRENT, 9, 0, MODE_SMA, PRICE_CLOSE, 1);
double ma2 = iMA(Symbol(), PERIOD_CURRENT, 9, 0, MODE_SMA, PRICE_CLOSE, 2);
double array[3] = {ma0, ma1, ma2};
これはリファレンスに記載がないのでハマる人も多いんじゃないでしょうか。
constant expression requiredの原因「配列は変数で初期化できない」
配列を変数で初期化しようとすると起こるエラーです。配列は変数で初期化することはできません。
配列を宣言してから変数を代入する
double ma0 = iMA(Symbol(), PERIOD_CURRENT, 9, 0, MODE_SMA, PRICE_CLOSE, 0);
double ma1 = iMA(Symbol(), PERIOD_CURRENT, 9, 0, MODE_SMA, PRICE_CLOSE, 1);
double ma2 = iMA(Symbol(), PERIOD_CURRENT, 9, 0, MODE_SMA, PRICE_CLOSE, 2);
double array[3];
array[0] = ma0;
array[1] = ma1;
array[2] = ma2;
ランタイムエラー
trade operations not allowed by settings
これは、EAがエントリーや決済しようとしたときに起るエラーです。
trade operations not allowed by settingsの原因「自動売買が許可されていない」
自動売買ボタンが赤いマークになっているときは自動売買が許可されていませんのでこのエラーが出ます。
自動売買を許可する
自動売買ボタンをクリックし、緑色になっていれば大丈夫です。
自動売買が許可されているか調べるコード
VPSでEAを実行してしばらく経って「トレードされてるかな~」なんて思いながらVPSを開いたときにこのエラーが出てたら機会損失だったりして萎えちゃいますよね。そういったミスを防ぐためにも、自動売買が許可されているか調べるコードを実装しておきましょう。
if(!IsTradeAllowed()) {
MessageBox("自動売買が許可されていません。", "エラー", MB_ICONWARNING | MB_OK);
}
このコードをInit時に実行しておけば、自動売買が許可されていないときに警告を出すようになります。
先ほどの例では、ローソク足(Bars)が300本しかないのに、Open[300]で301本目の始値を取りに行った場合にエラーが起こると言いました。
Open[]の最大値はBars – 1なので、ローソク足が300本しかないときは、Open[]の最大値は299です。これは、配列は0から数えるというルールがあるためなのですが、このルールをよく理解していない人はよくこのミスをしちゃいます。
最新のローソク足の始値はOpen[0]とわかっているけど、最後のローソク足の始値はOpen[Bars]って書いてしまいがちですよね。
300本目の始値を取りに行くときはOpen[299]が正しいです。
また、移動平均線のように過去のローソク足を数本にわたって参照する場合は特に注意が必要です。
例えば移動平均線の期間を60にしている場合、移動平均線の計算をするのに最低60本のローソク足が必要になります。もしローソク足が300本しかない場合は、古い方から数えて59本は移動平均線が計算できず、60本目からようやく移動平均線を計算することができます。
ところが、そのことを忘れていて、forループですべてのローソク足の移動平均線を計算しにいくと、最新のローソク足から241本目までは、241本目から数えて60本、つまり300本目のローソク足まで取りに行けるので問題なく移動平均線が計算できますが、242本目の移動平均線を計算しようとすると、301本目のローソク足の終値を取りに行く必要があり、ここでarray out of rangeが発生します。
forループの処理はきちんと
期間60の移動平均線をforループで回して計算するときは、計算するローソク足の本数がBarsの最大値を超えたら計算しないようにする工夫が必要です。
int limit = Bars - IndicatorCounted();
for(int i = limit - 1; i >= 0; i--) {
if(i + 60 > Bars - 1) continue;
double iMA(Symbol(), PERIOD_CURRENT, 60, 0, MODE_SMA, PRICE_CLOSE, 0);
}
こんな感じに書けばarray out of rangeは起こりません。
array out of rangeの原因②「そもそも配列が存在しない」
インジケーターとしてラインや矢印を表示させるとき、まずインジケーター用のBufferを用意し、そこに値を入れる必要があります。
インジケーター用のBufferを用意するには、配列の宣言と、さらに「いくつBufferを用意するか」を宣言しなければいけません。
double Buf0[];
double Buf1[];
double Buf2[];
double Buf3[];
#property indicator_buffers 4
ここまでは問題ないのですが、例えばインジケーターを作っているうちにラインを1本増やしたくなった時、配列の宣言だけ追加してBufferの数の宣言を修正し忘れるケースがあります。
#property indicator_buffers 4
double Buf0[];
double Buf1[];
double Buf2[];
double Buf3[];
double Buf4[];
この状態で、Buf4[]に値を入れようとしたりすると、Buf4[]はインジケーターのBufferとして用意していない状態なので、array out of rangeが発生します。
配列を増やすのとBufferを増やすのはセットで
#property indicator_buffers 5
double Buf0[];
double Buf1[];
double Buf2[];
double Buf3[];
double Buf4[];
ここでは説明を省きましたが、もちろんSetIndexBuffer()で配列をBufferとしてマッピングすることをお忘れなく。
SetIndexBuffer(0,Buf0);
SetIndexBuffer(1,Buf1);
SetIndexBuffer(2,Buf2);
SetIndexBuffer(3,Buf3);
SetIndexBuffer(4,Buf4);
インジケーター販売にとっても便利な「MQLAuth実装代行サービス」