求助,invalid array access错误

 
// 输入参数
input int       MagicNumber=114514;            // 魔数
input double    Lots=0.1;                 // 每个订单的交易手数
input int       MaxOrders=5;              // 订单总手数上限
input double    StopLoss=50;              // 止损点(以点数为单位)
input double    TakeProfit=100;           // 止盈点(以点数为单位)
input int       BollingerPeriod=20;       // 布林带周期
input double    Deviation=2;              // 布林带偏差
input ENUM_TIMEFRAMES BollingerTimeframe=PERIOD_H1; // 布林带时间框架

// 全局变量
double UpperBand[], MiddleBand[], LowerBand[];  // 布林带的三个轨道

// 初始化函数
void OnInit()
  {
   // 初始化时的日志
   Print("EA初始化,开始交易...");

   // 为轨道数组分配空间
   ArraySetAsSeries(UpperBand, true);
   ArraySetAsSeries(MiddleBand, true);
   ArraySetAsSeries(LowerBand, true);
  }

// 每个tick的处理函数
void OnTick()
  {
   // 检查是否有新的K线
   static datetime lastBarTime = 0;
   datetime currentBarTime = iTime(_Symbol, BollingerTimeframe, 0);
   if(lastBarTime == currentBarTime) return; // 如果没有新的K线,不执行任何操作
   lastBarTime = currentBarTime; // 更新最后的K线时间

   // 计算布林带
   if(!CalculateBollingerBands()) return; // 如果计算布林带失败,则退出

   // 获取当前价格
   double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);

   // 检查并执行交易逻辑
   CheckAndTrade(currentPrice);

   // 检查并平仓
   CheckAndCloseOrders(currentPrice);
  }

// 计算布林带函数
bool CalculateBollingerBands()
  {
   int handle = iBands(_Symbol, BollingerTimeframe, BollingerPeriod, Deviation, 0, PRICE_CLOSE);
   if(handle == INVALID_HANDLE)
     {
      Print("无法获取布林带指标的句柄", GetLastError());
      return false;
     }
   
   // 为轨道数组分配空间并确保正确复制数据
   if(CopyBuffer(handle, 0, 0, 1, UpperBand) <= 0 ||
      CopyBuffer(handle, 1, 0, 1, MiddleBand) <= 0 ||
      CopyBuffer(handle, 2, 0, 1, LowerBand) <= 0)
     {
      Print("复制布林带数据失败", GetLastError());
      return false;
     }

   IndicatorRelease(handle); // 释放指标句柄
   return true; // 成功计算布林带
  }

// 检查并执行交易逻辑
void CheckAndTrade(double currentPrice)
  {
   // 判断是否超过订单上限
   if(PositionsTotal() >= MaxOrders) return; // 如果当前持仓数达到或超过最大订单数,则不再开新仓

   // 获取上一根K线的收盘价
   double lastClose = iClose(_Symbol, BollingerTimeframe, 1);

   // 判断是否需要开仓
   if(lastClose > MiddleBand[0] && currentPrice < MiddleBand[0]) // 当前价格低于中轨,上一根K线收盘价高于中轨,开空单
     {
      if(OpenOrder(ORDER_TYPE_SELL, currentPrice)) Print("开空单成功");
     }
   else if(lastClose < MiddleBand[0] && currentPrice > MiddleBand[0]) // 当前价格高于中轨,上一根K线收盘价低于中轨,开多单
     {
      if(OpenOrder(ORDER_TYPE_BUY, currentPrice)) Print("开多单成功");
     }
  }


// 开仓函数
bool OpenOrder(ENUM_ORDER_TYPE type, double price)
{
    MqlTradeRequest request;
    MqlTradeResult result;

    request.action = TRADE_ACTION_DEAL;      // 直接成交
    request.symbol = _Symbol;                // 交易品种
    request.volume = Lots;                   // 交易手数
    request.type = type;                     // 订单类型
    request.price = price;                   // 开仓价格
    request.sl = (type == ORDER_TYPE_BUY) ? price - StopLoss * _Point : price + StopLoss * _Point; // 止损价
    request.tp = (type == ORDER_TYPE_BUY) ? price + TakeProfit * _Point : price - TakeProfit * _Point; // 止盈价
    request.magic = MagicNumber;             // 魔数
    request.comment = "Bollinger Strategy";  // 订单注释

    // 发送订单
    if (!OrderSend(request, result))
    {
        Print("订单发送失败", GetLastError());
        return false;
    }

    return true;
}

// 检查并平仓函数
void CheckAndCloseOrders(double currentPrice)
  {
   // 遍历所有订单
   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {
      ulong ticket = PositionGetTicket(i);
      if(PositionSelectByTicket(ticket))
        {
         if(PositionGetInteger(POSITION_MAGIC) != MagicNumber) continue; // 忽略非EA生成的订单

         double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
         ENUM_POSITION_TYPE positionType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);

         // 根据订单类型判断平仓条件
         if(positionType == POSITION_TYPE_BUY && currentPrice < UpperBand && currentPrice < MiddleBand && openPrice < currentPrice)
           {
            // 多单平仓条件:当前价格低于上轨且低于中轨,且当前价格高于开仓价格
            if(CloseOrder(ticket)) Print("平多单成功");
           }
         else if(positionType == POSITION_TYPE_SELL && currentPrice > LowerBand && currentPrice > MiddleBand && openPrice > currentPrice)
           {
            // 空单平仓条件:当前价格高于下轨且高于中轨,且当前价格低于开仓价格
            if(CloseOrder(ticket)) Print("平空单成功");
           }
        }
     }
  }

// 平仓函数
bool CloseOrder(ulong ticket)
  {
   // 创建订单请求结构体
   MqlTradeRequest request;
   MqlTradeResult result;

   request.action = TRADE_ACTION_DEAL;      // 直接成交
   request.position = ticket;               // 订单票号
   request.symbol = _Symbol;                // 交易品种
   request.volume = Lots;                   // 交易手数
   request.type = (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) ? ORDER_TYPE_SELL : ORDER_TYPE_BUY; // 订单类型(反向)
   request.price = SymbolInfoDouble(_Symbol, (request.type == ORDER_TYPE_SELL) ? SYMBOL_BID : SYMBOL_ASK); // 平仓价格

   // 发送订单
   if(!OrderSend(request, result))
     {
      Print("平仓失败", GetLastError());
      return false;
     }

   return true;
  }

报错内容如下:

'upperBand'- invalid array access
'MiddleBand' - invalid array access
'LowerBand' - invalid array access
'MiddleBand' - invalid array access

出现在143行至148行。即以下段落:

         // 根据订单类型判断平仓条件
         if(positionType == POSITION_TYPE_BUY && currentPrice < UpperBand && currentPrice < MiddleBand && openPrice < currentPrice)
           {
            // 多单平仓条件:当前价格低于上轨且低于中轨,且当前价格高于开仓价格
            if(CloseOrder(ticket)) Print("平多单成功");
           }
         else if(positionType == POSITION_TYPE_SELL && currentPrice > LowerBand && currentPrice > MiddleBand && openPrice > currentPrice)
           {
            // 空单平仓条件:当前价格高于下轨且高于中轨,且当前价格低于开仓价格
            if(CloseOrder(ticket)) Print("平空单成功");
           }
MetaQuotes — 为交易商、银行、交易所和对冲基金开发交易平台的软件开发公司
MetaQuotes — 为交易商、银行、交易所和对冲基金开发交易平台的软件开发公司
  • www.metaquotes.net
MetaTrader 5 交易平台是一个免费的外汇和金融市场交易工具。
原因: