請問為什麼編譯後會顯示數組越界(71,55),感謝。我是想計算從昨天開始20天的平均振幅(調用的指標就是這個代碼本身)

 
代碼如下,問題如標題,如果有更好的計算方式請不吝提出意見,謝謝!
#property indicator_chart_window

#property indicator_buffers 4
#property indicator_plots 4

double DayHigh[];
double DayLow[];
double DayAmplitudeBuffer[];
double AverageDayAmplitudeBuffer[];

int DayAmplitudeHandle;
double DayAmplitudeCurrentBuffer[];
double AverageDayAmplitudeCurrentBuffer[];
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
   SetIndexBuffer(0,DayHigh,INDICATOR_DATA);
   SetIndexBuffer(1,DayLow,INDICATOR_DATA);
   SetIndexBuffer(2,DayAmplitudeBuffer,INDICATOR_DATA);
   SetIndexBuffer(3,AverageDayAmplitudeBuffer,INDICATOR_DATA);

   DayAmplitudeHandle=iCustom(_Symbol,PERIOD_D1,"自訂\\12");

   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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[])
  {
   CopyHigh(Symbol(),PERIOD_D1,TimeCurrent(),rates_total,DayHigh);
   CopyLow(Symbol(),PERIOD_D1,TimeCurrent(),rates_total,DayLow);
   
   for(int i=0; i<rates_total; i++)
     {
      DayAmplitudeBuffer[i]=StringToDouble(IntegerToString(StringToInteger(DoubleToString((DayHigh[i]-DayLow[i])/Point()))));
      AverageDayAmplitudeBuffer[i]=CalculateAverageDayAmplitude(i);
     }
   CopyBuffer(DayAmplitudeHandle,2,0,rates_total,DayAmplitudeCurrentBuffer);
   CopyBuffer(DayAmplitudeHandle,3,0,rates_total,AverageDayAmplitudeCurrentBuffer);

   datetime Time[];
   CopyTime(_Symbol,PERIOD_D1,0,rates_total,Time);

   int pos=0;
   for(int i=0; i<rates_total; i++)
     {
      if(time[i]>Time[pos]) //如果當前時間週期超越日周期的開始時間,日週期就加一,想做成跨周期的效果
        {
         pos++;
        }
      DayAmplitudeBuffer[i]=DayAmplitudeCurrentBuffer[pos];
      AverageDayAmplitudeBuffer[i]=AverageDayAmplitudeCurrentBuffer[pos];
     }
   return(rates_total);
  }
//+------------------------------------------------------------------+
double CalculateAverageDayAmplitude(int StartBar)
  {
   double DayAmplitudeSum=0;
   for(int pos=StartBar-20; pos<StartBar; pos++)
     {
      if(StartBar-20<0)
        {
         return(0);
        }
      DayAmplitudeSum=DayAmplitudeSum+DayAmplitudeBuffer[pos];
     }
   return(DayAmplitudeSum/20);
  }
//+------------------------------------------------------------------+
 

帮你问了下GPT,他说:

在函数 CalculateAverageDayAmplitude 中,您有一个循环,它从 StartBar-20 开始。如果 StartBar 小于20,循环将尝试访问负数索引的数组,这显然是不可能的。虽然您的代码试图通过检查 StartBar-20<0 来避免这种情况,但这个检查是在循环内部进行的,这意味着在执行到这个检查之前,已经尝试过了非法的数组访问。

为了解决这个问题,您应该在开始循环之前进行检查,以确保不会尝试访问数组的负数索引。此外,由于 pos 在循环中递增,您还应该检查 pos 是否小于 rates_total 。以下是修正后的 CalculateAverageDayAmplitude 函数:

//+------------------------------------------------------------------+

double CalculateAverageDayAmplitude(int StartBar)

  {

   // 确保没有尝试访问负数索引

   if(StartBar<20)

     {

      return(0);

     }

   

   double DayAmplitudeSum=0;

   int pos;

   // 确保在数组范围内

   for(pos=StartBar-20; pos<StartBar && pos>=0; pos++)

     {

      DayAmplitudeSum += DayAmplitudeBuffer[pos];

     }

   // 防止除以零的情况

   if(pos > 0)

     {

      return(DayAmplitudeSum / pos);

     }

   else

     {

      return(0);

     }

  }

//+------------------------------------------------------------------+

此外,我注意到您在 OnCalculate 函数中使用了 StringToDouble(IntegerToString(StringToInteger(DoubleToString((DayHigh[i]-DayLow[i])/Point())))) 。这种转换序列非常复杂,并且可能不是必要的。您可以直接计算价差然后赋值给 DayAmplitudeBuffer[i] 。

请注意,如果您的指标是在图表加载时立即计算,您可能还需要处理 CopyHigh 和 CopyLow 函数的返回值,以确保它们成功复制了数据。如果它们没有复制足够的数据,任何尝试访问尚未定义的索引都可能导致数组越界错误。


 
Wei Tu #:

帮你问了下GPT,他说:

在函数 CalculateAverageDayAmplitude 中,您有一个循环,它从 StartBar-20 开始。如果 StartBar 小于20,循环将尝试访问负数索引的数组,这显然是不可能的。虽然您的代码试图通过检查 StartBar-20<0 来避免这种情况,但这个检查是在循环内部进行的,这意味着在执行到这个检查之前,已经尝试过了非法的数组访问。

为了解决这个问题,您应该在开始循环之前进行检查,以确保不会尝试访问数组的负数索引。此外,由于 pos 在循环中递增,您还应该检查 pos 是否小于 rates_total 。以下是修正后的 CalculateAverageDayAmplitude 函数:

//+------------------------------------------------------------------+

double CalculateAverageDayAmplitude(int StartBar)

  {

   // 确保没有尝试访问负数索引

   if(StartBar<20)

     {

      return(0);

     }

   

   double DayAmplitudeSum=0;

   int pos;

   // 确保在数组范围内

   for(pos=StartBar-20; pos<StartBar && pos>=0; pos++)

     {

      DayAmplitudeSum += DayAmplitudeBuffer[pos];

     }

   // 防止除以零的情况

   if(pos > 0)

     {

      return(DayAmplitudeSum / pos);

     }

   else

     {

      return(0);

     }

  }

//+------------------------------------------------------------------+

此外,我注意到您在 OnCalculate 函数中使用了 StringToDouble(IntegerToString(StringToInteger(DoubleToString((DayHigh[i]-DayLow[i])/Point())))) 。这种转换序列非常复杂,并且可能不是必要的。您可以直接计算价差然后赋值给 DayAmplitudeBuffer[i] 。

请注意,如果您的指标是在图表加载时立即计算,您可能还需要处理 CopyHigh 和 CopyLow 函数的返回值,以确保它们成功复制了数据。如果它们没有复制足够的数据,任何尝试访问尚未定义的索引都可能导致数组越界错误。


啊啊我也有問過GPT,我目前排查覺得最有可能出問題的地方是在pos的循環中但不知道是哪個部分越界(StartBar我記得有改過i的初始值過但沒有在pos那裏加上判斷條件,我再試試這個方法),轉換序列其實我不知道有沒有更好的方法,因為數組好像只能用double,然後計算出的值會變成小數點後超級多位所以才這樣轉。無論如何感謝你的幫助~
 

數組越界(71,55)

具體哪個位置不知道 應該是循環位置

沒仔細研究後面的計算式需要怎樣的前處理

建議你可以嘗試修改



if(prev_calculated>1)

      pos=prev_calculated-1;

   else

      pos=0;

for
(int i=pos; i<rates_total; i++)      { }
 
Hung Wen Lin #:

數組越界(71,55)

具體哪個位置不知道 應該是循環位置

沒仔細研究後面的計算式需要怎樣的前處理

建議你可以嘗試修改 

好的我再試試看,謝謝~剛剛看了下好像是Time[]這個動態數組的問題,因為Copytime後我用arrayprint不管怎麼切換時間週期似乎都只會是日週期的量,不知道是不是因為這個原因,有什麼更好的寫法嗎?感恩