こんなエラーがでたら?
MT4に標準で入っているRSI.mq4のソースコードを使って、例を出します。(OnCalculate関数のみ抜粋しています。)
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
int i,pos;
double diff;
//---
if(Bars<=InpRSIPeriod || InpRSIPeriod<2)
return(0);
//--- counting from 0 to rates_total
ArraySetAsSeries(ExtRSIBuffer,false);
ArraySetAsSeries(ExtPosBuffer,false);
ArraySetAsSeries(ExtNegBuffer,false);
ArraySetAsSeries(close,false);
//--- preliminary calculations
pos=prev_calculated-1;
if(pos<=InpRSIPeriod)
{
ExtRSIBuffer[0]=0.0;
ExtPosBuffer[0]=0.0;
ExtNegBuffer[0]=0.0;
double sump=0.0;
double sumn=0.0;
for(i=1; i<=InpRSIPeriod; i++) { ExtRSIBuffer[i]=0.0; ExtPosBuffer[i]=0.0; ExtNegBuffer[i]=0.0; diff=close[i]-close[i-1]; if(diff>0)
sump+=diff;
else
sumn-=diff;
}
ExtPosBuffer[InpRSIPeriod]=sump/InpRSIPeriod;
ExtNegBuffer[InpRSIPeriod]=sumn/InpRSIPeriod;
if(ExtNegBuffer[InpRSIPeriod]!=0.0)
ExtRSIBuffer[InpRSIPeriod]=100.0-(100.0/(1.0+ExtPosBuffer[InpRSIPeriod]/ExtNegBuffer[InpRSIPeriod]));
else
{
if(ExtPosBuffer[InpRSIPeriod]!=0.0)
ExtRSIBuffer[InpRSIPeriod]=100.0;
else
ExtRSIBuffer[InpRSIPeriod]=50.0;
}
pos=InpRSIPeriod+1;
}
for(i=pos; i0.0?diff:0.0))/InpRSIPeriod;
ExtNegBuffer[i]=(ExtNegBuffer[i-1]*(InpRSIPeriod-1)+(diff<0.0?-diff:0.0))/InpRSIPeriod;
if(ExtNegBuffer[i]!=0.0)
ExtRSIBuffer[i]=100.0-100.0/(1+ExtPosBuffer[i]/ExtNegBuffer[i]);
else
{
if(ExtPosBuffer[i]!=0.0)
ExtRSIBuffer[i]=100.0;
else
ExtRSIBuffer[i]=50.0;
}
}
return(rates_total);
上記コードを実行しますと、MT4には下記のエラー表示が出てしまいます。この3つのエラーが同時に出たときは、括弧が多い(または少ない)というエラーです。
括弧忘れは初心者にありがちなエラー
';' - unexpected end of program
'{' - unbalanced parentheses
OnCalculate function not found in custom indicator
このエラー3つがセットになって出てくるパターンは、だれもが通る道だと思います。さて、どこが間違っているかわかりましたか?
プログラムでは、{ }や( )などの括弧(かっこ)をたくさん書くことになります。このとき、「開く括弧」と「閉じる括弧」は、必ず対になっています。
この括弧が足りていないと、上記のようなエラーが出ます。
インデントは必ずつけましょう
メタエディターでは、かっこの少し前にカーソルをもっていくと、対応する括弧がわかりやすく表示されるようになっています。
この機能で括弧の対応関係を見やすくしますと、一番外側の「開く括弧」に対応する「閉じる括弧」がないことがわかります。つまり、return(rates_total);の次に } を書いてやれば、エラーは無くなります。
括弧を書いたらさらにエラーでる?
MT4に標準で入っているRSI.mq4のソースコードを使って、もう一つ例を出します。(OnCalculate関数のみ抜粋しています。)
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[]) {
int i, pos;
double diff;
if(Bars <= InpRSIPeriod || InpRSIPeriod < 2)
return(0);
ArraySetAsSeries(ExtRSIBuffer, false);
ArraySetAsSeries(ExtPosBuffer, false);
ArraySetAsSeries(ExtNegBuffer, false);
ArraySetAsSeries(close, false);
pos = prev_calculated - 1;
if(pos <= InpRSIPeriod) {
ExtRSIBuffer[0] = 0.0;
ExtPosBuffer[0] = 0.0;
ExtNegBuffer[0] = 0.0;
double sump = 0.0;
double sumn = 0.0;
for(i = 1; i <= InpRSIPeriod; i++) { ExtRSIBuffer[i] = 0.0; ExtPosBuffer[i] = 0.0; ExtNegBuffer[i] = 0.0; diff = close[i] - close[i - 1]; if(diff > 0)
sump += diff;
else
sumn -= diff;
}
ExtPosBuffer[InpRSIPeriod] = sump / InpRSIPeriod;
ExtNegBuffer[InpRSIPeriod] = sumn / InpRSIPeriod;
if(ExtNegBuffer[InpRSIPeriod] != 0.0)
ExtRSIBuffer[InpRSIPeriod] = 100.0 - (100.0 / (1.0 + ExtPosBuffer[InpRSIPeriod] / ExtNegBuffer[InpRSIPeriod]));
else {
if(ExtPosBuffer[InpRSIPeriod] != 0.0)
ExtRSIBuffer[InpRSIPeriod] = 100.0;
else
ExtRSIBuffer[InpRSIPeriod] = 50.0;
}
pos = InpRSIPeriod + 1;
}
for(i = pos; i < rates_total && !IsStopped(); i++) { diff = close[i] - close[i - 1]; ExtPosBuffer[i] = (ExtPosBuffer[i - 1] * (InpRSIPeriod - 1) + (diff > 0.0 ? diff : 0.0)) / InpRSIPeriod;
ExtNegBuffer[i] = (ExtNegBuffer[i - 1] * (InpRSIPeriod - 1) + (diff < 0.0 ? -diff : 0.0)) / InpRSIPeriod;
if(ExtNegBuffer[i] != 0.0)
ExtRSIBuffer[i] = 100.0 - 100.0 / (1 + ExtPosBuffer[i] / ExtNegBuffer[i]);
else {
if(ExtPosBuffer[i] != 0.0)
ExtRSIBuffer[i] = 100.0;
else
ExtRSIBuffer[i] = 50.0;
}
return(rates_total);
}
このコードでも下記の括弧が多い(または少ない)ことを示す3つのエラーがでます。
そこで最後に括弧をつけてコンパイルすると…
おや?違うエラーが出てしまいました。
not all control paths return a valueってなあに?
「not all control paths return a value」というエラー表示は、「値を返さないパスがあります」という類のエラーです。
ですので指定された行をチェックしますが、そのようなパスが見当たりません。
そこで疑うべきはやはり括弧です。
実は今回のエラーは値を返す返さないの話ではなく、「括弧を付ける場所が間違っている」ことが原因で発生しているエラーなんですね。
もう一度先ほどのソースコードを見てみましょう。
for(i = pos; i < rates_total && !IsStopped(); i++) { diff = close[i] - close[i - 1]; ExtPosBuffer[i] = (ExtPosBuffer[i - 1] * (InpRSIPeriod - 1) + (diff > 0.0 ? diff : 0.0)) / InpRSIPeriod;
ExtNegBuffer[i] = (ExtNegBuffer[i - 1] * (InpRSIPeriod - 1) + (diff < 0.0 ? -diff : 0.0)) / InpRSIPeriod;
if(ExtNegBuffer[i] != 0.0)
ExtRSIBuffer[i] = 100.0 - 100.0 / (1 + ExtPosBuffer[i] / ExtNegBuffer[i]);
else {
if(ExtPosBuffer[i] != 0.0)
ExtRSIBuffer[i] = 100.0;
else
ExtRSIBuffer[i] = 50.0;
}
return(rates_total);
}
return(rates_total); は、OnCalcurate()の必ず最後の行に書かれる処理です。そのため、return(rates_total);の後ろには括弧が1つしかなくて正解です。
つまり、括弧が足りないのは一番最後ではありません。return(rates_total);の前です。試しにreturn(rates_total);の前に括弧を付けてみると…
for(i = pos; i < rates_total && !IsStopped(); i++) { diff = close[i] - close[i - 1]; ExtPosBuffer[i] = (ExtPosBuffer[i - 1] * (InpRSIPeriod - 1) + (diff > 0.0 ? diff : 0.0)) / InpRSIPeriod;
ExtNegBuffer[i] = (ExtNegBuffer[i - 1] * (InpRSIPeriod - 1) + (diff < 0.0 ? -diff : 0.0)) / InpRSIPeriod;
if(ExtNegBuffer[i] != 0.0)
ExtRSIBuffer[i] = 100.0 - 100.0 / (1 + ExtPosBuffer[i] / ExtNegBuffer[i]);
else {
if(ExtPosBuffer[i] != 0.0)
ExtRSIBuffer[i] = 100.0;
else
ExtRSIBuffer[i] = 50.0;
}
}
return(rates_total);
}
無事にコンパイルできました!
コンパイルエラーの本当に怖い所は、表示してくれているエラーが正しい間違い箇所を指摘しているとは限らない、という点です。
3つのエラーの詳細をチェック
3つのエラーを振り返ってみましょう。括弧が足りないのであれば「括弧が足りないよ!」というエラーを出してくれればよいのに、実は出ている3つのエラーは微妙にずれた内容を指摘しています。
1.’;’ セミコロンが足りないよ!
2.括弧のバランスが悪いよ!
3.OnCalculate関数が見つからないよ!
そして先ほどの括弧の位置が間違っていた時のエラーは
値を返さないパスがあるよ!(このエラーは通常、return文が足りていない時に出てきます。)
エラー内容だけで間違いを判断するのではなく、そのエラー内容が出るときに本当に起こっているエラーのパターンを知っておき、エラー修正の引き出しを増やしておくことが、プログラミングのコツです。