I need help.The error 4756

 

这是我的代码:

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

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

// 初始化函数
void OnInit()
  {
   // 初始化时的日志
   Print("初始化...");
   // 为轨道数组分配空间
   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)
{
    int _Digits = SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
    double _Lots = Lots;

    // 检查交易手数是否符合最小交易量要求
    double minVolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
    if(_Lots < minVolume)
    {
        Print("指定的交易手数小于最小交易量要求,将交易手数调整为最小交易量。");
        _Lots = minVolume;
    }

    // 检查交易手数是否符合最大交易量要求
    double maxVolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
    if(_Lots > maxVolume)
    {
        Print("指定的交易手数超过最大交易量要求,将交易手数调整为最大交易量。");
        _Lots = maxVolume;
    }

    // 检查交易手数是否符合交易量步长要求
    double volumeStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
    if(fmod(_Lots, volumeStep) != 0)
    {
        Print("指定的交易手数不符合交易量步长要求,将进行调整。");
        _Lots = NormalizeDouble((int(_Lots / volumeStep) + 1) * volumeStep, _Digits);
    }

    MqlTradeRequest request;
    MqlTradeResult result;
    request.action = TRADE_ACTION_DEAL;      // 直接成交
    request.symbol = _Symbol;                // 交易品种
    request.volume = _Lots;                  // 交易手数
    request.type = type;                     // 订单类型
    request.type_filling = SYMBOL_FILLING_IOC;  // 订单执行类型

    // 对价格进行规范化处理
    request.price = NormalizeDouble(price, _Digits);

    // 设置并规范化止损和止盈价格
    if(type == ORDER_TYPE_BUY)
    {
        request.sl = NormalizeDouble(request.price - StopLoss * _Point, _Digits);
        request.tp = NormalizeDouble(request.price + TakeProfit * _Point, _Digits);
    }
    else if(type == ORDER_TYPE_SELL)
    {
        request.sl = NormalizeDouble(request.price + StopLoss * _Point, _Digits);
        request.tp = NormalizeDouble(request.price - TakeProfit * _Point, _Digits);
    }

    request.magic = MagicNumber;             // 魔数
    request.comment = "This is a comment";  // 订单注释

    // 发送订单
    if (!OrderSend(request, result))
    {
        Print("正在尝试发送订单: 交易类型(Symbol)=", request.symbol, ", 订单类型(Type)=", request.type, ", 订单手数(Volume)=", request.volume, ", 订单价格(Price)=", request.price, ", 止损(Stop Loss)=", request.sl, ", 止盈(Take Profit)=", request.tp);
        Print("订单发送失败,错误码:", GetLastError());
        Print("交易商支持的交易类型:",SymbolInfoInteger(Symbol(),SYMBOL_FILLING_MODE));
        return false;
    }
    Print("订单发送成功: 交易类型(Symbol)=", request.symbol, ", 订单类型(Type)=", request.type, ", 订单手数(Volume)=", request.volume, ", 订单价格(Price)=", request.price, ", 止损(Stop Loss)=", request.sl, ", 止盈(Take Profit)=", request.tp);

    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[0] && currentPrice < MiddleBand[0] && openPrice < currentPrice)
           {
            // 多单平仓条件:当前价格低于上轨且低于中轨,且当前价格高于开仓价格
            if(CloseOrder(ticket)) Print("平多单成功");
           }
         else if(positionType == POSITION_TYPE_SELL && currentPrice > LowerBand[0] && currentPrice > MiddleBand[0] && 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;
  }

这是日志。

起初,我以为是填充类型问题,所以我添加了相应的反馈。但是,根据反馈将其替换为 SYMBOL-FILLING-IOC 后,问题仍未解决。(我尝试了所有三种类型,但它们不起作用)

无论如何,请帮帮我,我真的找不到解决方案。

 
bool CheckStopLoss_Takeprofit(ENUM_ORDER_TYPE type,double SL,double TP)
  {
//--- get the SYMBOL_TRADE_STOPS_LEVEL level
   int stops_level=(int)SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL);
   if(stops_level!=0)
     {
      PrintFormat("SYMBOL_TRADE_STOPS_LEVEL=%d: StopLoss and TakeProfit must"+
                  " not be nearer than %d points from the closing price",stops_level,stops_level);
     }
//---
   bool SL_check=false,TP_check=false;
//--- check only two order types
   switch(type)
     {
      //--- Buy operation
      case  ORDER_TYPE_BUY:
        {
         //--- check the StopLoss
         SL_check=(Bid-SL>stops_level*_Point);
         if(!SL_check)
            PrintFormat("For order %s StopLoss=%.5f must be less than %.5f"+
                        " (Bid=%.5f - SYMBOL_TRADE_STOPS_LEVEL=%d points)",
                        EnumToString(type),SL,Bid-stops_level*_Point,Bid,stops_level);
         //--- check the TakeProfit
         TP_check=(TP-Bid>stops_level*_Point);
         if(!TP_check)
            PrintFormat("For order %s TakeProfit=%.5f must be greater than %.5f"+
                        " (Bid=%.5f + SYMBOL_TRADE_STOPS_LEVEL=%d points)",
                        EnumToString(type),TP,Bid+stops_level*_Point,Bid,stops_level);
         //--- return the result of checking
         return(SL_check&&TP_check);
        }
      //--- Sell operation
      case  ORDER_TYPE_SELL:
        {
         //--- check the StopLoss
         SL_check=(SL-Ask>stops_level*_Point);
         if(!SL_check)
            PrintFormat("For order %s StopLoss=%.5f must be greater than %.5f "+
                        " (Ask=%.5f + SYMBOL_TRADE_STOPS_LEVEL=%d points)",
                        EnumToString(type),SL,Ask+stops_level*_Point,Ask,stops_level);
         //--- check the TakeProfit
         TP_check=(Ask-TP>stops_level*_Point);
         if(!TP_check)
            PrintFormat("For order %s TakeProfit=%.5f must be less than %.5f "+
                        " (Ask=%.5f - SYMBOL_TRADE_STOPS_LEVEL=%d points)",
                        EnumToString(type),TP,Ask-stops_level*_Point,Ask,stops_level);
         //--- return the result of checking
         return(TP_check&&SL_check);
        }
      break;
     }
//--- a slightly different function is required for pending orders
   return false;
  }

https://www.mql5.com/en/articles/2555

The checks a trading robot must pass before publication in the Market
The checks a trading robot must pass before publication in the Market
  • www.mql5.com
Before any product is published in the Market, it must undergo compulsory preliminary checks in order to ensure a uniform quality standard. This article considers the most frequent errors made by developers in their technical indicators and trading robots. An also shows how to self-test a product before sending it to the Market.
 
亚沙尔·赛耶丁 #

https://www.mql5.com/en/articles/2555

非常感谢您的帮助。我已将支票添加到我的代码中,并对盈利和止损设置进行了更正。

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

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

// 初始化函数
void OnInit()
{
   // 初始化时的日志
   Print("初始化...");
   // 为轨道数组分配空间
   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; // 如果当前持仓数达到或超过最大订单数,则不再开新仓

   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("开多单成功");
     }
}

// 检查并平仓函数
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[0] && currentPrice < MiddleBand[0] && openPrice < currentPrice)
           {
            if(CloseOrder(ticket)) Print("平多单成功");
           }
         else if(positionType == POSITION_TYPE_SELL && currentPrice > LowerBand[0] && currentPrice > MiddleBand[0] && 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;
}

// 检查止损和止盈设置是否符合经纪商的要求
bool CheckStopLoss_TakeProfit(ENUM_ORDER_TYPE type, double SL, double TP)
{
    int stops_level = (int)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL);
    double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);

    double minSL, maxTP;
    if(type == ORDER_TYPE_BUY)
    {
        minSL = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_BID) - stops_level * point, _Digits);
        maxTP = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_BID) + stops_level * point, _Digits);
    }
    else // ORDER_TYPE_SELL
    {
        minSL = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK) + stops_level * point, _Digits);
        maxTP = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK) - stops_level * point, _Digits);
    }

    bool slValid = (type == ORDER_TYPE_BUY) ? (SL > minSL) : (SL < minSL);
    bool tpValid = (type == ORDER_TYPE_BUY) ? (TP < maxTP) : (TP > maxTP);

    if(!slValid)
        PrintFormat("%s 止损 %f 太接近当前价格了。允许的最小值为: %f.", (type == ORDER_TYPE_BUY) ? "Buy" : "Sell", SL, minSL);
    if(!tpValid)
        PrintFormat("%s 止盈 %f 太接近当前价格了。允许的最大值为: %f.", (type == ORDER_TYPE_BUY) ? "Buy" : "Sell", TP, maxTP);

    return slValid && tpValid;
}

// 开仓函数
bool OpenOrder(ENUM_ORDER_TYPE type, double price)
{
   int _Digits = SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
   double _Lots = Lots;

   double minVolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
   if(_Lots < minVolume)
   {
       Print("指定的交易手数小于最小交易量要求,将交易手数调整为最小交易量。");
       _Lots = minVolume;
   }

   double maxVolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
   if(_Lots > maxVolume)
   {
       Print("指定的交易手数超过最大交易量要求,将交易手数调整为最大交易量。");
       _Lots = maxVolume;
   }

   double volumeStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
   if(fmod(_Lots, volumeStep) != 0)
   {
       Print("指定的交易手数不符合交易量步长要求,将进行调整。");
       _Lots = NormalizeDouble((int(_Lots / volumeStep) + 1) * volumeStep, _Digits);
   }

   double SL = (type == ORDER_TYPE_BUY) ? price - StopLoss * _Point : price + StopLoss * _Point;
   double TP = (type == ORDER_TYPE_BUY) ? price + TakeProfit * _Point : price - TakeProfit * _Point;
   SL = NormalizeDouble(SL, _Digits);
   TP = NormalizeDouble(TP, _Digits);

   if (!CheckStopLoss_TakeProfit(type, SL, TP))
   {
       Print("止损或止盈设置不符合经纪商要求,取消订单。");
       return false;
   }

   MqlTradeRequest request;
   MqlTradeResult result;
   request.action = TRADE_ACTION_DEAL;
   request.symbol = _Symbol;
   request.volume = _Lots;
   request.type = type;
   request.type_filling = ORDER_FILLING_IOC;
   request.price = NormalizeDouble(price, _Digits);
   request.sl = SL;
   request.tp = TP;
   request.magic = MagicNumber;
   request.comment = "This is a comment";

   if (!OrderSend(request, result))
   {
       Print("正在尝试发送订单: 交易类型(Symbol)=", request.symbol, ", 订单类型(Type)=", request.type, ", 订单手数(Volume)=", request.volume, ", 订单价格(Price)=", request.price, ", 止损(Stop Loss)=", request.sl, ", 止盈(Take Profit)=", request.tp);
       Print("订单发送失败,错误码:", GetLastError());
       Print("交易商支持的交易类型:",SymbolInfoInteger(Symbol(),SYMBOL_FILLING_MODE));
       return false;
   }
   Print("订单发送成功: 交易类型(Symbol)=", request.symbol, ", 订单类型(Type)=", request.type, ", 订单手数(Volume)=", request.volume, ", 订单价格(Price)=", request.price, ", 止损(Stop Loss)=", request.sl, ", 止盈(Take Profit)=", request.tp);

   return true;
}

But the problem has not been resolved, it still reports the error 4756.



Why Is MQL5 Market the Best Place for Selling Trading Strategies and Technical Indicators
Why Is MQL5 Market the Best Place for Selling Trading Strategies and Technical Indicators
  • www.mql5.com
MQL5.community Market provides Expert Advisors developers with the already formed market consisting of thousands of potential customers. This is the best place for selling trading robots and technical indicators!
 
int handle = iBands(_Symbol, BollingerTimeframe, BollingerPeriod, Deviation, 0, PRICE_CLOSE);

Forth input parameter for iBands is bands_shift and not deviation.

You may check here.
Documentation on MQL5: Technical Indicators / iBands
Documentation on MQL5: Technical Indicators / iBands
  • www.mql5.com
The function returns the handle of the Bollinger Bands® indicator. Parameters symbol [in] The symbol name of the security, the data of which...
 
Yashar Seyyedin #:

Forth input parameter for iBands is bands_shift and not deviation.

You may check here.
Thank you very much for your help, it doesn't report any more errors now. (Although still not working)