配列に値を代入しているのに、常に0になってしまう。 〜 配列のサイズ変更ArrayResize
単純なバグだけど、ハマってしまった。
インディケーター作成を題材にMQL4の練習をしているときの話。
次のコードはローソク足の終値(Close[i+j])を、予め用意した配列smaVal[]と変数tmpに代入するだけのコード。このコードにはバグが有る。
#property indicator_separate_window #property indicator_buffers 1 #property indicator_color1 Red #property indicator_width1 3 //線の太さ #property indicator_level1 20 extern int MA_Period = 5; double Buf[]; double smaVal[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int init() { SetIndexBuffer(0,Buf); return(0); } //+------------------------------------------------------------------+ //| Custom indicator deinitialization function | //+------------------------------------------------------------------+ int deinit() { //---- //---- return(0); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int start() { int limit = Bars - IndicatorCounted(); if(limit == Bars){ limit = limit -(MA_Period-1); } double tmp; for(int i=limit-1; 0<=i; i--){ smaVal[i] = 0; for(int j=0; j<MA_Period; j++){ smaVal[i] = Close[i+j]; tmp = Close[i+j]; Print("smaVal[i]="+smaVal[i]); Print("Close[i]="+Close[i+j]); Print("tmp="+tmp); Print("*******"); } smaVal[i] = smaVal[i]/MA_Period; //Print("****************"+smaVal[i]); Buf[i] = smaVal[i]/Close[i]*100; } return(0); }
結果を表示すると、tmpにはコピーされているが、smaValは常に0になってしまうバグが有ることが分かる。
「配列Bufと同じようにコピーしているだけなのに・・・。」と思いこんでいたが、よーく見直すと、配列smaValへ配列サイズを割り当てていない。
試しに、double smaVal[10000]として適当にサイズを割り当てると正常にコピーされる。
しかし、smaValのサイズは指標バッファ配列を使用して計算するため、予めサイズが分からない。このような場合、ArrayResize関数を使用する。
それで、ループを回す回数分だけ配列サイズを確保するように、 ArrayResize(smaVal,limit)をstart関数内に追記して出来た。
int start() { int limit = Bars - IndicatorCounted(); if(limit == Bars){ limit = limit -(MA_Period-1); } ArrayResize(smaVal,limit); double tmp; for(int i=limit-1; 0<=i; i--){ smaVal[i] = 0; for(int j=0; j<MA_Period; j++){ smaVal[i] = Close[i+j]; tmp = Close[i+j]; Print("smaVal[i]="+smaVal[i]); Print("Close[i]="+Close[i+j]); Print("tmp="+tmp); Print("*******"); } smaVal[i] = smaVal[i]/MA_Period; //Print("****************"+smaVal[i]); Buf[i] = smaVal[i]/Close[i]*100; } return(0); }