错误、漏洞、问题 - 页 540

 

我的专家顾问,目前正在参加锦标赛,由于标准CTrade库的错误操作,正在执行不正确的行动。

我使用PositionClose函数来关闭头寸。但在平仓的同时,这个功能本身也是在开启交易!

该函数是这样使用的。

//--- Объект класса СTrade
CTrade mytrade;
//--- Объект класса СPositionInfo
CPositionInfo myposition;

//+------------------------------------------------------------------+
//| Проверяет и если нужно, закрывает открытую позицию               |
//+------------------------------------------------------------------+
bool ClosePosition(string ptype,double clp)
  {
   bool R=false, marker=false; int i;
     
      if(myposition.Select(_Symbol)==true)
        {
         if(myposition.Symbol()==_Symbol)
           {
            //--- Делаем попытки закрыть позицию, если позиция не закрылась с первого раза
              for (i=5; i>=1; i--) 
                {R=mytrade.PositionClose(_Symbol,50,5); if (R == true && myposition.Select(_Symbol)==false) break;}
               if(i >= 1) 
                 {//--- запрос успешно выполнен
                  Alert("Открытая позиция была успешно закрыта!!");
                  marker=true;
                 }
               else
                 {
                  Alert("Запрос на закрытие позиции не выполнен - ошибка: ",mytrade.ResultRetcodeDescription());
                 }
            //  }
           }
        }
      return(marker);
     }

仓位平仓最终会开出一些不必要的订单。

在这里,买入交易首先被关闭,然后开了一个相同规模的额外卖出交易。此外,AccountInfoDouble(ACCOUNT_FREEMARGIN)也没有注意到这个额外的交易。因为后面是用更大的手笔进行交易,虽然按照二手MM的说法,没有足够的钱。

我意识到,我可能没有以最佳方式使用MQL函数。但是,MQL专有库中一个用于关闭 交易的函数会自己打开 交易,这不符合我对函数可接受行为的想法。

 
masharov:

我明白,我可能没有以最佳方式使用MQL函数。但是,一个用于关闭 交易的MQL专有库函数本身会打开 交易,这不符合我对可接受的函数行为的想法。

阅读文章MetaTrader 5中的交易事件

交易事件和交易历史的变化通过独立渠道报告。当使用OrderSend()函数发送买入请求时,你可以立即识别订单的票据,如果请求被成功检查,它已经被创建。但与此同时,订单本身可能还没有出现在客户终端,试图用OrderSelect() 函数选择它将失败。

也请看文章《MetaTrader 5中的订单、头寸和交易》。
 

我没有使用OrderSend函数。使用了标准MQL库中的PositionClose 函数,该函数被设计用于处理订单。

这个功能的帮助没有描述它可以打开交易。

引自参考文献。

仓位关闭

在指定的符号处关闭一个位置。

bool PositionClose(
const string symbol, // symbol
ulong deviation=ULONG_MAX // deviation
)

参数

标志

[in] 交易工具的名称,在此基础上应关闭头寸。

偏差=ULONG_MAX

[in] 与当前价格的最大偏差(单位:点)。

返回的值

true - 如果结构的基本检查成功,否则为false。

注意事项

成功完成PositionClose(...)方法并不总是意味着交易操作的成功执行。有必要通过调用ResultRetcode()方法检查交易请求的结果(交易服务器的返回代码)。

 
masharov:

我没有使用OrderSend函数。使用了标准MQL库中的PositionClose 函数,其目的是为了简化订单的工作。

这个功能的帮助没有描述它可以打开交易。

引自参考文献。

仓位关闭

在指定的符号处关闭一个位置。

bool PositionClose(
const string symbol, // symbol
ulong deviation=ULONG_MAX // deviation
)

参数

标志

[in] 交易工具的名称,在此基础上应关闭头寸。

偏差=ULONG_MAX

[in] 与当前价格的最大偏差(单位:点)。

返回的值

true - 如果结构的基本检查成功,否则为false。

注意事项

成功完成PositionClose(...)方法并不总是意味着交易操作的成功执行。必须通过调用ResultRetcode()方法检查交易请求的执行结果(交易服务器的返回代码)。

在库函数PositionClose(...)中没有错误。但在你的代码中,有一个。以下是参考文献中的引用。

Успешное окончание работы метода PositionClose(...) не всегда означает успешное совершение торговой операции. 
Необходимо проверять результат выполнения торгового запроса (код возврата торгового сервера) вызовом метода ResultRetcode(). 

例如,我在你的代码中没有看到这个检查。

 
masharov:

我没有使用OrderSend函数。使用了标准 MQL库中的PositionClose 函数,该函数被设计用于处理订单。

这个功能的帮助没有描述它可以打开交易。


而你可以看看PositionClose函数的实现。

bool CTrade::PositionClose(const string symbol,ulong deviation)
  {
   bool   partial_close=false;
   int    retry_count  =10;
   uint   retcode      =TRADE_RETCODE_REJECT;
//--- check stopped
   if(IsStopped(__FUNCTION__)) return(false);
//--- variables
   string action,result;
//--- clean
   ClearStructures();
   do
     {
      //--- checking
      if(PositionSelect(symbol))
        {
         if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
           {
            //--- prepare request for close BUY position
            m_request.type =ORDER_TYPE_SELL;
            m_request.price=SymbolInfoDouble(symbol,SYMBOL_BID);
           }
         else
           {
            //--- prepare request for close SELL position
            m_request.type =ORDER_TYPE_BUY;
            m_request.price=SymbolInfoDouble(symbol,SYMBOL_ASK);
           }
        }
      else
        {
         //--- position not found
         m_result.retcode=retcode;
         return(false);
        }
      //--- setting request
      m_request.action      =TRADE_ACTION_DEAL;
      m_request.symbol      =symbol;
      m_request.deviation   =(deviation==ULONG_MAX) ? m_deviation : deviation;
      m_request.type_filling=m_type_filling;
      m_request.volume      =PositionGetDouble(POSITION_VOLUME);
      //--- check volume
      double max_volume=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
      if(m_request.volume>max_volume)
        {
         m_request.volume=max_volume;
         partial_close=true;
        }
      else
         partial_close=false;
      //--- order check
      if(!OrderCheck(m_request,m_check_result))
        {
         //--- copy return code
         m_result.retcode=m_check_result.retcode;
         if(m_log_level>LOG_LEVEL_NO)
            printf(__FUNCTION__+": %s [%s]",FormatRequest(action,m_request),FormatRequestResult(result,m_request,m_result));
         return(false);
        }
      //--- order send
      if(!OrderSend(m_request,m_result))
        {
         if(--retry_count!=0) continue;
         if(retcode==TRADE_RETCODE_DONE_PARTIAL)
            m_result.retcode=retcode;
         if(m_log_level>LOG_LEVEL_NO)
            printf(__FUNCTION__+": %s [%s]",FormatRequest(action,m_request),FormatRequestResult(result,m_request,m_result));
         return(false);
        }
      retcode=TRADE_RETCODE_DONE_PARTIAL;
      if(partial_close) Sleep(1000);
     }
   while(partial_close);
   if(m_log_level>LOG_LEVEL_ERRORS)
      printf(__FUNCTION__+": %s [%s]",FormatRequest(action,m_request),FormatRequestResult(result,m_request,m_result));
//--- ok
   return(true);
  }
 

我想我不需要研究标准库的 源代码。

帮助中没有描述用PositionClose函数打开交易的可能性。你们团队开发的针对用PositionClose函数开仓交易的检查和保护措施,应该包含其本身。我相信,标准库是一种理想的代码,应该作为其他人的模型。因此,在使用这些库之前,解析它们的代码应该是没有必要的。

引用。

标准的MQL5库是用MQL5语言编写的,目的是为了方便终端用户编写程序(指标、脚本、专家)。该库提供了对大多数MQL5内部函数的简单访问

 
masharov:

我想我不需要研究标准库的 源代码。

帮助中没有描述用PositionClose函数打开交易的可能性。你们团队开发的针对用PositionClose函数开仓交易的检查和保护措施,应该包含其本身。我相信,标准库是一种理想的代码,应该作为其他人的模型。因此,在使用库之前,不应该要求解析库的代码。

对法律的无知并不能免除你的责任。在你的代码中,在哪里检查头寸是否已经关闭?

            //--- Делаем попытки закрыть позицию, если позиция не закрылась с первого раза
              for (i=5; i>=1; i--) 
                {
                 R=mytrade.PositionClose(_Symbol,50,5); 
                 if (R == true && myposition.Select(_Symbol)==false) break;
                }

表达方式

R == true

只表示PositionClose() 函数被成功执行,但不表示该仓位被关闭。

注意事项

成功完成PositionClose(...)方法并不总是意味着交易操作的成功执行。有必要通过调用ResultRetcode() 方法检查交易请求的执行结果(交易服务器的返回代码)。

第二个表达式

myposition.Select(_Symbol)==false)

相当于

PositionSelect(_Symbol)==false)

而且对异步交易操作也没有保证。一个头寸已经在交易服务器上被关闭,而终端还没有收到关于它的信息。所以,事实证明,你的代码中产生了一个错误。

在现实生活中,并不是一切都像在测试器中那样顺利;在发送交易请求和执行结果之间可能会有小的延迟。每个人都自己解决这个问题,首先,使用 ResultRetcode() 函数检查返回代码不会有坏处 ,因为帮助中写到了

 

再一次。

我意识到,也许我没有以最佳方式使用MQL函数。但是,MQL专有库中一个用于关闭 交易的函数本身会打开 交易,这不符合我对函数可接受行为的想法。

你说的一切都适用于关闭交易。是的,该EA没有以最佳方式检查平仓。但这并不允许一个旨在关闭的功能自行打开交易。

帮助说。

仓位关闭

根据指定的符号关闭该位置。

没有描述该功能可以开启交易的条件。检查返回代码的建议也只是为了额外检查交易是否被关闭。

 
masharov:

再一次。

我明白,我可能没有以最佳方式使用MQL函数。但是,MQL专有库中用于关闭 交易的函数会自己打开 交易,这不符合我对函数可接受行为的想法。
没有平仓 功能,只有发送买入或卖出请求的功能(而结果是什么--开仓或平仓--是未知的)。在你的案例中,由于一个算法错误,重复的请求被发送而没有检查前一个请求是否被执行。
 
Rosh:
没有平仓 功能,只有发送买入或卖出请求的功能(而结果--开仓或平仓--是未知的)。在你的案例中,由于一个算法错误,重复的请求被发送而没有检查前一个请求是否被执行。

帮助有这样的功能

MQL5 参考 / 标准库 / 交易类 / CTrade / 关闭头寸

通过指定的符号关闭位置。

用户不应关心该功能在低层次上是如何实现的。由于这个功能的存在,MetaQuotes已经保证它不会有任何帮助中没有描述的非标准行为。

标准的MQL5库是用MQL5编写的,目的是方便最终用户编写程序(指标、脚本和专家顾问)。该库提供了对大多数MQL5内部函数的简单访问