🔰括弧を忘れるとでてしまうコンパイルエラー

コンパイルエラー
yuki
yuki
インジケーターを作り始めたばかりの方が必ずぶつかるコンパイルエラーに関して解説します

こんなエラーがでたら?

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つのエラーが同時に出たときは、括弧が多い(または少ない)というエラーです。

MQLのエラー

 

括弧忘れは初心者にありがちなエラー

';' - 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つのエラーがでます。

 

MQLのエラー

そこで最後に括弧をつけてコンパイルすると…

 

おや?違うエラーが出てしまいました。

 

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つのエラーは微妙にずれた内容を指摘しています。

 

MQLのエラー1.’;’ セミコロンが足りないよ!
2.括弧のバランスが悪いよ!
3.OnCalculate関数が見つからないよ!

 

カオチャイ
カオチャイ
3つで1セットのエラーではなくそれぞれちゃんと独自のエラーを指摘してくれているんですね

 

そして先ほどの括弧の位置が間違っていた時のエラーは

値を返さないパスがあるよ!(このエラーは通常、return文が足りていない時に出てきます。)

エラー内容だけで間違いを判断するのではなく、そのエラー内容が出るときに本当に起こっているエラーのパターンを知っておき、エラー修正の引き出しを増やしておくことが、プログラミングのコツです。

 

EA・インジケーター制作のご依頼はこちら
インジケーターのバックテスト&リペイントチェック代行サービスMT4やMT5に関するツールを作成する際の流れを説明しています。 シストレファクトリーでは一からEAの制作以外にもツールの修正や、統計的なアプローチができるソフトなどお客様の欲しいツールを形にいたします。...
EA&インジケーター制作代行
【MT4&MT5】EA&インジケーター制作代行承ります EA&インジケーター制作代行とは? EA&インジケーター制作代行では、皆さんが日頃使っている手法をMT4(MT5)でエントリーサイ...

 

インジケーターをより使いやすく
MQLコードでEAをカスタマイズ
【MQLコード解説】EA・インジケーターのカスタマイズ【体験版・LINE通知】EAやインジケーターに口座番号認証を実装する方法を紹介しています。 認証システムにはMQLAuthを利用して解説していきます。...
インジケーターダウンロード
MT4で使える無料のEAやバイナリーオプションインジケーターを配布しています無料配布EA&バイナリーオプションインジケーター ここではMT4で使える無料EAやバイナリーオプションのインジケーターを配布しています...
自動売買について
自動売買に関するQ&Aを集めてみました 自動売買に関する便利な用語集 https://intera...
体験版EA
自動的に期限付き体験版になる機能をEAに追加する方法 https://interactivebrokers.work/start_mqlauth/ 体験版機能を使うとなにができる?...
バイナリーオプションツールに認証をつける
バイナリーオプションのインジケーターに口座認証を実装する方法 https://interactivebrokers.work/start_mqlauth/ 口座番号認証はパスワードよりも安...