哪种设计是正确的? - 页 8

 
valenok2003:

非常感谢,我正在处理错误,信息来了--错误的价格,我想不出哪里出了问题。

然后还添加一行

int err = GetLastError();

在函数开始时--清除错误缓冲区:有时可以读取 "别人的 "错误,这样错误缓冲区将在函数开始时被清除。

这不是必须的,但如果程序用于现实世界,则非常希望尽可能正确地完成一切。

好运。

 
VladislavVG:

然后还添加一行

在函数开始时--清除错误缓冲区:有时可以读取 "别人的 "错误,这样错误缓冲区将在函数开始时被清除。

这不是必须的,但如果程序用于现实世界,则非常希望尽可能正确地完成一切。

好运。


是的,谢谢你,这就是我在真正的软件中所做的。
 
好心人,你能告诉我为什么函数返回0,虽然没有未结订单。是否应该有某种错误?
//+------------------------------------------------------------------+
//| функция закрытия ордеров по символу
//+------------------------------------------------------------------+
int Close_This_Symbol_All(string _Symbol_Name, string _Type_Order, int _Slippage, bool _Alert_ON)
{
  bool _Result;
  ERROR = 0;
//----
  if(OrdersTotal() == 0) return(-1);
  for (int _Cnt = OrdersTotal()-1; _Cnt >= 0; _Cnt--) 
  {
    if(!OrderSelect(_Cnt, SELECT_BY_POS, MODE_TRADES)) break;
    if(OrderSymbol() == _Symbol_Name)
    { 
      while (!IsTradeAllowed()) Sleep(1000);
      RefreshRates();
      if(OrderType() == OP_BUY   && _Type_Order == "BUY") 
      {
        _Result = OrderClose(OrderTicket(), OrderLots(), MarketInfo(_Symbol_Name,MODE_BID), _Slippage, CLR_NONE);
        ERROR = GetLastError();
      }
      if(OrderType() == OP_SELL && _Type_Order == "SELL") 
      {
        _Result = OrderClose(OrderTicket(), OrderLots(), MarketInfo(_Symbol_Name,MODE_ASK), _Slippage, CLR_NONE);
        ERROR = GetLastError();
      }
      if(_Result == true) PlaySound(Name_Sound_Close);
      else 
      {
        Error(Name_Expert," Close "+_Type_Order+": ",ERROR,_Alert_ON);
        break;
      }
    }  
  }
//----
  return(ERROR);
}
//+------------------------------------------------------------------+
 
再一次,我们是否在挑剔碎片?
 
valenok2003:
好心人,你能告诉我为什么这个函数在没有未结订单的情况下仍然返回0。难道不应该有某种错误吗?
intOrdersTotal( )

返回未结 订单和挂单 的总金额。

还在写信订购吗?

 

-- 使用以下划线和双下划线开头的名称是不好的形式。我宁愿在最后使用下划线。


-- 为什么是_Type_Order字符串?不现实的尴尬,我想。那么它就必须被引用。因为如果你写 "卖 "或 "卖",就不会有效果。


--如果你想犯错,就犯错。

ERROR = -1;

更好的是。

#define ERROR_NOTHING_TO_CLOSE -1
...

...
ERROR = ERROR_NOTHING_TO_CLOSE;


--

if(!OrderSelect(_Cnt, SELECT_BY_POS, MODE_TRADES)) break;

为什么要打破?假设在一毫秒前,订单被TP关闭--为什么我们不应该关闭其余的订单?这样更好。

if(!OrderSelect(_Cnt, SELECT_BY_POS, MODE_TRADES)) continue;

--

while (!IsTradeAllowed()) Sleep(1000);

这条线不仅仅是无用的 -- 它是有害的。你一定是这个意思吗?

while (IsTradeContextBusy()) Sleep(1000);


--

else 
      {
        Error(Name_Expert," Close "+_Type_Order+": ",ERROR,_Alert_ON);
        break;
      }

也就是说,如果一个订单突然无法成交,"放开车轮,闭上眼睛,开始尖叫"。

没有必要关闭其他的?不需要再试了?


-- 为什么要在这里返回一个错误?例如,如果全部成功关闭则返回true,如果不成功则返回false,这样会更合适。


暂时就这些了。

 
TheXpert:

-- 使用以下划线和双下划线开头的名称是不好的形式。我宁愿在最后使用下划线。


通过在函数中使用以下划线开头的名字,我消除了变量重写的风险。因此,我可以在start()中使用相同的名称,但没有下划线,这增加了代码透明度。

- 为什么_Type_Order是字符串?不现实的不方便,我认为。那么就应该给予。因为如果我们写 "卖 "或 "卖",什么都不会成功。

你是对的,当然了。然而,使用字符串可以增加代码的透明度,以我目前的代码量,没有必要使用下划线。当我真的遇到这个问题时,我会这样做,但现在还没有必要。我只需写上卖出或买入。


为什么要打破?好吧,让我们假设一个订单在一毫秒前就被TP关闭了,那么为什么我们不应该关闭所有其他的订单?这样更好。

if(!OrderSelect(_Cnt, SELECT_BY_POS, MODE_TRADES)) continue;

你当然是对的,谢谢你。


这条线不仅仅是无用的--它是有害的。我想你是这个意思吗?

IsTradeContextBusy()函数只通知线程占用情况,IsTradeAllowed()则更广泛一些


也就是说,如果突然间订单无法关闭,"放开车轮,闭上眼睛,开始尖叫"?


是的,在调试期间,它是

为什么会有一个错误的返回?如果一切都可以关闭,返回true;如果不能关闭,返回false,那就更合适了。


谢谢你,我似乎已经知道了错误的原因。我将检查并报告。
 

错误如下。

bool _Result变量没有被初始化,所以它将包含false;因此,由于没有一个条件被满足,我们没有改变_Result变量,它已经包含false。而函数进行错误处理 的时候,确实没有发生。

我修复了这个功能,并把它贴在这里,我想有人可能会发现它很有用。

//+------------------------------------------------------------------+
//| функция закрытия ордеров по символу
//+------------------------------------------------------------------+
int Close_This_Symbol_All(string _Symbol_Name, string _Type_Order, int _Slippage, bool _Alert_ON)
{
int _Cnt_Close_Orders = 0;
//----
  if(OrdersTotal() == 0) return(_Cnt_Close_Orders);
  for (int _Cnt = OrdersTotal()-1; _Cnt >= 0; _Cnt--) 
  {
    if(!OrderSelect(_Cnt, SELECT_BY_POS, MODE_TRADES)) continue;
    if(OrderSymbol() == _Symbol_Name)
    { 
      while (!IsTradeAllowed()) Sleep(1000);
      RefreshRates();
      if(OrderType() == OP_BUY   && _Type_Order == "BUY") 
      {
        if(OrderClose(OrderTicket(), OrderLots(), MarketInfo(_Symbol_Name,MODE_BID), _Slippage, CLR_NONE))
        {
          _Cnt_Close_Orders++;
          PlaySound(Name_Sound_Close);        
        } 
        else 
        {
          Error(Name_Expert," Close "+_Type_Order+": ",GetLastError(),_Alert_ON);
          continue;
        }
      }
      if(OrderType() == OP_SELL && _Type_Order == "SELL") 
      {
        if(OrderClose(OrderTicket(), OrderLots(), MarketInfo(_Symbol_Name,MODE_ASK), _Slippage, CLR_NONE))
        {
          _Cnt_Close_Orders++;
          PlaySound(Name_Sound_Close);        
        } 
        else 
        {
          Error(Name_Expert," Close "+_Type_Order+": ",GetLastError(),_Alert_ON);
          continue;
        }
      }
    }  
  }
//----
  return(_Cnt_Close_Orders);
}
//+------------------------------------------------------------------+

PS给版主。我无意中创建了这样一个分支--关于如何正确关闭订单的完整自学教程。也许它应该改名为--如何正确关闭订单的例子。

PPS非常感谢 每一位参与的人。可能会有更多的问题。

 
valenok2003:

错误如下。

bool _Result变量没有被初始化,所以它将包含false;因此,由于没有一个条件被满足,我们没有改变_Result变量,它已经包含false。而函数进行错误处理的时候,确实没有发生。

我修复了这个功能,并把它贴在这里,我想有人可能会发现它很有用。

PS给版主。我无意中创建了这样一个分支--关于如何正确关闭订单的完整自学教程。也许它应该改名为--如何正确关闭订单的例子。

PPS非常感谢 每一位参与的人。可能会有更多的问题。


如果你看一下CodeBase并仔细阅读论坛--有一百多个正确的关闭顺序的例子,但这并不意味着所有的分支都应该一次重命名。有足够的英雄。
 
valenok2003:

错误如下。

bool _Result变量没有被初始化,所以它将包含false;因此,由于没有一个条件被满足,我们没有改变_Result变量,它已经包含false。而函数进行错误处理的时候,确实没有发生。

我修复了这个功能,并把它贴在这里,我想有人可能会发现它很有用。

PS给版主。我无意中创建了这样一个分支--关于如何正确关闭订单的完整自学教程。也许它应该改名为--如何正确关闭订单的例子。

PPS非常感谢 每一位参与的人。我们可能会有更多的问题。

IMHO:这个功能的逻辑不清楚。如果是为测试人员准备的,那就太没必要了,如果是为现实世界准备的,就应该处理这些错误。返回的值完全没有意义,你在外部层面上(在调用层面上)告诉大家,调用以错误结束,你失去了错误本身,好吧,它写在杂志上,专家是如何考虑的?

更好的做法是:(再次,IMHO)。

1.读取并保存错误编号。

2.将错误分成可修复的和不可修复的。要做到这一点,我们应该创建一个处理程序--那些错误,一旦出现,订单可能会被关闭(一个线程很忙,连接失败......等等),应该立即在现场处理。我曾这样做过(首先是无法恢复的错误,然后是可以 "修复 "的错误)。

#define MAXCYKLESCNT 20

int ErrReaction(int err)
{
    switch(err)
    {
        case ERR_TRADE_NOT_ALLOWED    :
                 Print("TRADE NOT ALLOWED ! SWITCH ON option \' Allow live trading\' (Необходимо включить опцию \'Разрешить советнику торговать\')");
        case ERR_INVALID_FUNCTION_PARAMSCNT :    
        case ERR_INVALID_FUNCTION_PARAMVALUE :    
        case ERR_INVALID_STOPS        : 
        case ERR_INVALID_TRADE_VOLUME : 
        case ERR_MARKET_CLOSED        : 
        case ERR_TRADE_DISABLED       : 
        case ERR_NOT_ENOUGH_MONEY     : 
                 return(-err);
        case ERR_NO_CONNECTION        :
                 ReScanServers();
        case ERR_BROKER_BUSY          : 
        case ERR_TRADE_CONTEXT_BUSY   : 
        case ERR_ORDER_LOCKED         :
                 int n=0;
                 while((!IsTradeAllowed())&&(n<20)){ Sleep(500);n++;}
        case ERR_PRICE_CHANGED : 
        case ERR_OFF_QUOTES    : 
        case ERR_REQUOTE       : 
                 RefreshRates();
                 break;
        default: break;
    }//switch(err)
    return(0);
}//int ErrReaction(int err)

3.当一个难以解决的错误发生时,返回的不是一个错误标志,而是它的编号,这样,这种情况可以在外部模块中处理。当分析一个操作的结果 时:

bool res    = false;
int  ncykls =     0;

    while((!res)&&(ncykls<MAXCYKLESCNT))
    {
        res = ...............
        if(!res)
        { 
            ncykls++;
            err=GetLastError();
            Print(ncykls," Err(",err,") : ",ErrorDescription(err)); 
            err_res = ErrReaction(err); 
            if(err_res<0) return(err_res);
        } 
    }//while((!res)&&(ncykls<MAXCYKLESCNT))

好运。

深圳关于休息/继续的问题

if( !OrderSelect(i,SELECT_BY_POS,MODE_TRADES) ) break;    // No more Orders
这个问题是值得商榷的。如果仍有订单,那么当触发取/停时,订单编号将发生变化--即订单仍将被选中:你通过订单编号而不是票据来选择。如果没有选择订单,意味着没有订单。由于你不是每次都检查订单的数量,你会在一定数量的时间内运行循环的空白。
原因: