Quel modèle est correct ? - page 8

 
valenok2003:

Merci beaucoup, je traite les erreurs, le message arrive - mauvais prix, et je n'arrive pas à comprendre ce qui ne va pas.

puis ajoutez également une ligne

int err = GetLastError();

au début de la fonction - effacer le tampon d'erreur : il est parfois possible de lire l'erreur de "quelqu'un d'autre", et de cette façon le tampon d'erreur sera effacé au début de la fonction.

Ce n'est pas obligatoire, mais si les programmes sont destinés au monde réel, il est hautement souhaitable de tout faire aussi correctement que possible.

Bonne chance.

 
VladislavVG:

puis ajoutez également une ligne

au début de la fonction - effacer le tampon d'erreur : il est parfois possible de lire l'erreur de "quelqu'un d'autre", et de cette façon le tampon d'erreur sera effacé au début de la fonction.

Ce n'est pas obligatoire, mais si les programmes sont destinés au monde réel, il est hautement souhaitable de tout faire aussi correctement que possible.

Bonne chance.


Oui, merci, c'est ce que je fais dans les vrais logiciels.
 
Braves gens, pouvez-vous me dire pourquoi la fonction renvoie 0, alors qu'il n'y a pas d'ordres ouverts. Il est censé y avoir une sorte d'erreur ?
//+------------------------------------------------------------------+
//| функция закрытия ордеров по символу
//+------------------------------------------------------------------+
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);
}
//+------------------------------------------------------------------+
 
Une fois de plus, sommes-nous en train de décortiquer les pièces ?
 
valenok2003:
Braves gens, pouvez-vous me dire pourquoi cette fonction renvoie 0 alors qu'il n'y a pas d'ordre ouvert. Ne devrait-il pas y avoir une sorte d'erreur ?
int OrdersTotal( )

Renvoie le montant total des ordres ouverts et en attente.

Vous écrivez toujours pour commander ?

 

-- L'utilisation de noms qui commencent par un trait de soulignement et un double trait de soulignement est malvenue. Je préfère utiliser un trait de soulignement à la fin.


-- Pourquoi la chaîne _Type_Order ? Irréalisablement maladroit, je pense. Il faudrait alors la citer. Parce que si vous écrivez "Vendre" ou "vendre", ça ne marchera pas.


-- Si tu veux faire une erreur, fais une erreur :

ERROR = -1;

Encore mieux.

#define ERROR_NOTHING_TO_CLOSE -1
...

...
ERROR = ERROR_NOTHING_TO_CLOSE;


--

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

Pourquoi se casser ? Supposons qu'il y a une milliseconde, l'ordre a été fermé par TP - pourquoi ne fermerions-nous pas le reste ? C'est mieux :

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

--

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

La ligne est pire qu'inutile - elle est nuisible. C'est ce que vous vouliez dire ?

while (IsTradeContextBusy()) Sleep(1000);


--

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

En d'autres termes, si un ordre ne se ferme pas soudainement, "lâchez le volant, fermez les yeux et commencez à crier".

Il n'y a pas besoin de fermer les autres ? Pas besoin de réessayer ?


-- Pourquoi renvoyer une erreur ici ? Il serait beaucoup plus approprié de renvoyer, par exemple, true (vrai) si tout a réussi à fermer et false (faux) dans le cas contraire.


C'est tout pour le moment.

 
TheXpert:

-- L'utilisation de noms qui commencent par un trait de soulignement et un double trait de soulignement est malvenue. Je préfère utiliser un trait de soulignement à la fin.


En utilisant des noms commençant par un trait de soulignement à l'intérieur des fonctions, j'élimine le risque d'écrasement des variables. Ainsi, je peux utiliser les mêmes noms dans start() mais sans les underscores, ce qui augmente la transparence du code.

- Pourquoi _Type_Order est une chaîne de caractères ? C'est un inconvénient irréaliste, je pense. Alors il faut la donner. Parce que si nous écrivons "Vendre" ou "vendre", rien ne fonctionnera.

Vous avez raison, bien sûr. Cependant, l'utilisation d'une chaîne de caractères augmente la transparence du code et avec la quantité de code que j'ai en ce moment, il n'y a pas besoin de souligner. Quand je rencontrerai vraiment ce problème, je le ferai, mais pour l'instant ce n'est pas nécessaire. J'écris simplement VENDRE ou ACHETER.


Pourquoi se casser ? Supposons qu'un ordre ait été fermé par TP il y a une milliseconde, alors pourquoi ne pas fermer tous les autres ? C'est mieux :

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

Vous avez certainement raison, merci.


La ligne est pire qu'inutile - elle est nuisible. C'est ce que je pense que vous voulez dire ?

La fonction IsTradeContextBusy() informe uniquement sur l'occupation des threads, IsTradeAllowed() est un peu plus large


C'est-à-dire, si soudainement la commande ne peut être fermée, "lâchez la roue, fermez les yeux et commencez à crier" ?


oui, pour la période de débogage, il est

Pourquoi y aurait-il un retour d'erreur ? Il serait beaucoup plus approprié de renvoyer true si tout peut être fermé et false sinon.


Merci, je semble avoir trouvé la cause de l'erreur. Je vais vérifier et faire un rapport.
 

L'erreur était la suivante :

la variable bool _Result n'est pas initialisée, elle contiendra donc false ; ainsi, puisqu'aucune des conditions n'a été remplie, nous n'avons pas modifié la variable _Result, et elle contient déjà false. Et la fonction procède au traitement d'une erreur qui ne s'est pas produite.

J'ai réparé la fonction et je la poste ici, je pense que quelqu'un peut la trouver utile.

//+------------------------------------------------------------------+
//| функция закрытия ордеров по символу
//+------------------------------------------------------------------+
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 aux modérateurs. J'ai créé une telle branche par accident - un auto-tutoriel complet sur la façon de clôturer correctement les ordres. Peut-être devrait-il être renommé comme suit : comment clôturer correctement les ordres avec des exemples.

PPS Merci beaucoup à tous ceux qui ont participé. Il y aura probablement d'autres questions.

 
valenok2003:

L'erreur était la suivante :

la variable bool _Result n'est pas initialisée, elle contiendra donc false ; ainsi, puisqu'aucune des conditions n'a été remplie, nous n'avons pas modifié la variable _Result, et elle contient déjà false. Et la fonction procède au traitement d'une erreur qui ne s'est pas produite.

J'ai réparé la fonction et je la poste ici, je pense que quelqu'un peut la trouver utile.

PS aux modérateurs. J'ai créé une telle branche par accident - un auto-tutoriel complet sur la façon de clôturer correctement les ordres. Peut-être devrait-il être renommé comme suit : comment clôturer correctement les ordres avec des exemples.

PPS Merci beaucoup à tous ceux qui ont participé. Il y aura probablement d'autres questions.


Si vous regardez la CodeBase et lisez attentivement le forum - il y a plus d'une centaine d'exemples de fermeture d'ordre correcte, mais cela ne signifie pas que toutes les branches doivent être renommées en même temps. Il y a assez de héros.
 
valenok2003:

L'erreur était la suivante :

La variable bool _Result n'est pas initialisée, elle contiendra donc false ; ainsi, puisqu'aucune des conditions n'a été remplie, nous n'avons pas modifié la variable _Result, et elle contient déjà false. Et la fonction procède au traitement d'une erreur qui ne s'est pas produite.

J'ai réparé la fonction et je la poste ici, je pense que quelqu'un peut la trouver utile.

PS aux modérateurs. J'ai créé une telle branche par accident - un auto-tutoriel complet sur la façon de fermer les ordres correctement. Peut-être devrait-il être renommé comme suit : comment clôturer correctement les ordres avec des exemples.

PPS Merci beaucoup à tous ceux qui ont participé. Nous aurons probablement d'autres questions.

IMHO : Cette fonction n'est pas claire dans sa logique. Si c'est pour un testeur, c'est trop inutile, si c'est pour le monde réel, les erreurs doivent être traitées. La valeur renvoyée n'a aucune signification car vous dites au niveau externe (au niveau de l'appel) que l'appel s'est terminé par une erreur, vous perdez l'erreur elle-même, enfin, l'expert a écrit dans le journal - comment cela compte-t-il ?

Ce qui serait mieux : (encore une fois, IMHO)

1. Lire et enregistrer le numéro d'erreur.

2. Divisez les erreurs en réparables et non réparables. Pour ce faire, nous devrions créer un gestionnaire - ces erreurs, à l'apparition desquelles la commande peut être fermée (un thread est occupé, échec de connexion ..., etc.) devraient être traitées immédiatement sur place. J'ai procédé de cette façon (d'abord les erreurs irrécupérables, puis celles qui peuvent être "réparées") :

#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. Lorsqu'une erreur insoluble se produit, renvoyer non pas un drapeau d'erreur, mais son numéro, afin que cette situation puisse être gérée dans un module externe. Lors de l'analyse du résultat d'une opération:

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))

Bonne chance.

SZ à propos de pause/continuation

if( !OrderSelect(i,SELECT_BY_POS,MODE_TRADES) ) break;    // No more Orders
la question est discutable. S'il y a encore des ordres, lorsqu'une prise/arrêt est déclenchée, la numérotation des ordres changera - c'est-à-dire que l'ordre sera encore sélectionné : vous sélectionnez par numéro d'ordre, pas par ticket. Si la commande n'est pas sélectionnée, cela signifie qu'il n'y a pas de commande. Comme vous ne vérifiez pas le nombre de commandes à chaque fois, vous exécuterez le cycle à blanc un certain nombre de fois.