Welches Design ist richtig? - Seite 8

 
valenok2003:

Vielen Dank, ich bearbeite die Fehler, es kommt die Meldung - falscher Preis, und ich kann nicht herausfinden, was falsch ist.

dann auch eine Zeile hinzufügen

int err = GetLastError();

am Anfang der Funktion - Fehlerpuffer löschen: manchmal ist es möglich, den Fehler eines anderen zu lesen, und auf diese Weise wird der Fehlerpuffer am Anfang der Funktion geleert.

Dies ist nicht erforderlich, aber wenn die Programme für die reale Welt, ist es sehr wünschenswert, alles so korrekt wie möglich zu tun.

Viel Glück!

 
VladislavVG:

dann auch eine Zeile hinzufügen

am Anfang der Funktion - Fehlerpuffer löschen: manchmal ist es möglich, den Fehler eines anderen zu lesen, und auf diese Weise wird der Fehlerpuffer am Anfang der Funktion geleert.

Dies ist nicht erforderlich, aber wenn die Programme für die reale Welt, ist es sehr wünschenswert, alles so korrekt wie möglich zu tun.

Viel Glück!


Ja, danke, das ist es, was ich in echter Software mache.
 
Liebe Leute, könnt ihr mir sagen, warum die Funktion 0 zurückgibt, obwohl es keine offenen Aufträge gibt. Sollte es eine Art Fehler geben?
//+------------------------------------------------------------------+
//| функция закрытия ордеров по символу
//+------------------------------------------------------------------+
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);
}
//+------------------------------------------------------------------+
 
Noch einmal: Nehmen wir die Teile auseinander?
 
valenok2003:
Liebe Leute, könnt ihr mir sagen, warum diese Funktion 0 zurückgibt, obwohl es keine offenen Aufträge gibt. Sollte es nicht eine Art Fehler geben?
int OrdersTotal( )

Gibt die Gesamtzahl der offenen und schwebenden Aufträge zurück.

Schreiben Sie immer noch auf Bestellung?

 

-- Die Verwendung von Namen, die mit einem Unterstrich und einem doppelten Unterstrich beginnen, ist eine Unsitte. Ich würde lieber einen Unterstrich am Ende verwenden.


-- Warum _Type_Order string? Unrealistisch ungeschickt, denke ich. Dann müsste sie zitiert werden. Denn wenn Sie "Verkaufen" oder "verkaufen" schreiben, wird es nicht funktionieren.


-- Wenn Sie einen Fehler machen wollen, machen Sie einen Fehler:

ERROR = -1;

Besser noch.

#define ERROR_NOTHING_TO_CLOSE -1
...

...
ERROR = ERROR_NOTHING_TO_CLOSE;


--

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

Warum brechen? Angenommen, der Auftrag wurde vor einer Millisekunde von TP geschlossen - warum sollten wir den Rest nicht schließen? Das ist besser:

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

--

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

Die Linie ist schlimmer als nutzlos - sie ist schädlich. Ist es das, was Sie gemeint haben müssen?

while (IsTradeContextBusy()) Sleep(1000);


--

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

Das heißt, wenn ein Auftrag plötzlich nicht abgeschlossen werden kann, "lassen Sie das Steuer los, schließen Sie die Augen und fangen Sie an zu schreien".

Es gibt keinen Grund, die anderen zu schließen? Kein Grund, es noch einmal zu versuchen?


-- Warum gibt es hier überhaupt eine Fehlerrückmeldung? Es wäre viel angemessener, z. B. true zurückzugeben, wenn alle erfolgreich abgeschlossen werden konnten, und false, wenn nicht.


Das ist alles für den Moment.

 
TheXpert:

-- Die Verwendung von Namen, die mit einem Unterstrich und einem doppelten Unterstrich beginnen, ist eine Unsitte. Ich würde lieber einen Unterstrich am Ende haben.


Durch die Verwendung von Namen, die mit Unterstrichen beginnen, innerhalb von Funktionen, schließe ich das Risiko der Überschreibung von Variablen aus. So kann ich die gleichen Namen in start() verwenden, aber ohne Unterstriche, was die Transparenz des Codes erhöht.

- Warum ist _Type_Order ein String? Das ist unrealistisch und unbequem, finde ich. Dann sollte sie gegeben werden. Denn wenn wir "verkaufen" oder "verkaufen" schreiben, wird nichts funktionieren.

Sie haben natürlich Recht. Die Verwendung einer Zeichenkette erhöht jedoch die Transparenz des Codes, und bei der Menge an Code, die ich derzeit habe, besteht keine Notwendigkeit für eine Unterstreichung. Wenn ich wirklich auf dieses Problem stoße, werde ich es tun, aber im Moment ist es nicht notwendig. Ich schreibe einfach VERKAUFEN oder KAUFEN.


Warum brechen? Nun, nehmen wir an, dass ein Auftrag vor einer Millisekunde von TP geschlossen wurde, warum sollten wir dann nicht alle anderen schließen? Das ist besser:

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

Sie haben sicher Recht, danke.


Die Linie ist mehr als nutzlos - sie ist schädlich. Ist es das, was ich denke, was Sie meinen?

Die Funktion IsTradeContextBusy() informiert nur über die Belegung von Threads, IsTradeAllowed() ist etwas weiter gefasst


Das heißt, wenn plötzlich die Bestellung nicht mehr geschlossen werden kann, "lassen Sie das Rad los, schließen Sie die Augen und fangen Sie an zu schreien"?


ja, für den Zeitraum der Fehlersuche ist es

Warum sollte es überhaupt eine Fehlerrückmeldung geben? Es wäre viel sinnvoller, true zurückzugeben, wenn alles geschlossen werden kann, und false, wenn nicht.


Danke, ich glaube, ich habe den Fehler herausgefunden. Ich werde das überprüfen und berichten.
 

Der Fehler war folgendermaßen:

Die Variable bool _Result ist nicht initialisiert und enthält daher false. Da keine der Bedingungen erfüllt ist, haben wir die Variable _Result nicht geändert und sie enthält bereits false. Und die Funktion fährt mit der Fehlerbehandlung fort, die eigentlich nicht stattgefunden hat.

Ich habe die Funktion korrigiert und stelle sie hier ein, vielleicht findet sie jemand nützlich.

//+------------------------------------------------------------------+
//| функция закрытия ордеров по символу
//+------------------------------------------------------------------+
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 an die Moderatoren. Ich habe eine solche Verzweigung zufällig erstellt - ein komplettes Selbstlernprogramm, wie man Aufträge richtig abschließt. Vielleicht sollte sie umbenannt werden in - wie man Aufträge korrekt abschließt, mit Beispielen.

PPS Vielen Dank an alle, die teilgenommen haben. Es wird wahrscheinlich noch mehr Fragen geben.

 
valenok2003:

Der Fehler war folgendermaßen:

Die Variable bool _Result ist nicht initialisiert und enthält daher false. Da keine der Bedingungen erfüllt ist, haben wir die Variable _Result nicht geändert und sie enthält bereits false. Und die Funktion fährt mit der Fehlerbehandlung fort, die eigentlich nicht stattgefunden hat.

Ich habe die Funktion korrigiert und stelle sie hier ein, vielleicht findet sie jemand nützlich.

PS an die Moderatoren. Ich habe eine solche Verzweigung zufällig erstellt - ein komplettes Selbstlernprogramm, wie man Aufträge richtig abschließt. Vielleicht sollte sie umbenannt werden in - wie man Aufträge korrekt abschließt, mit Beispielen.

PPS Vielen Dank an alle, die teilgenommen haben. Es wird wahrscheinlich noch mehr Fragen geben.


Wenn Sie sich die CodeBase ansehen und das Forum aufmerksam lesen - es gibt mehr als hundert Beispiele für das korrekte Schließen der Reihenfolge, aber das bedeutet nicht, dass alle Zweige auf einmal umbenannt werden sollten. Es gibt genug Helden.
 
valenok2003:

Der Fehler war folgendermaßen:

Die Variable bool _Result ist nicht initialisiert und enthält daher false. Da keine der Bedingungen erfüllt ist, haben wir die Variable _Result nicht geändert und sie enthält bereits false. Und die Funktion fährt mit der Fehlerbehandlung fort, die eigentlich nicht stattgefunden hat.

Ich habe die Funktion repariert und stelle sie hier ein, vielleicht findet sie jemand nützlich.

PS an die Moderatoren. Ich habe eine solche Verzweigung zufällig erstellt - ein komplettes Selbstlernprogramm, wie man Aufträge richtig abschließt. Vielleicht sollte sie umbenannt werden in - wie man Aufträge korrekt abschließt, mit Beispielen.

PPS Vielen Dank an alle, die sich beteiligt haben. Es wird wahrscheinlich noch mehr Fragen geben.

IMHO: Diese Funktion ist in ihrer Logik nicht klar. Wenn es für einen Prüfer ist, ist es zu viel unnötig, wenn es für die reale Welt ist, sollten die Fehler behandelt werden. Der zurückgegebene Wert hat keine Bedeutung, weil Sie auf der externen Ebene (auf der Ebene des Aufrufs) sagen, dass der Aufruf mit einem Fehler endete, Sie verlieren den Fehler selbst, nun, der Experte schrieb in das Protokoll - wie zählt das?

Was wäre besser: (wieder, IMHO)

1. Lesen und speichern Sie die Fehlernummer.

2. Unterteilen Sie die Fehler in behebbare und nicht behebbare. Um dies zu tun, sollten wir einen Handler erstellen - diese Fehler, bei deren Auftreten der Auftrag geschlossen werden kann (ein Thread ist beschäftigt, Verbindungsfehler ..., etc.) sollte sofort vor Ort behandelt werden. Ich habe es so gemacht (zuerst die nicht behebbaren Fehler und dann die, die "behoben" werden können):

#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. Beim Auftreten eines hartnäckigen Fehlers soll nicht ein Fehlerflag, sondern die Fehlernummer zurückgegeben werden, so dass diese Situation in einem externen Modul behandelt werden kann. Bei der Analyse des Ergebnisses einer Operation:

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

Viel Glück!

SZ über Pause/Fortsetzung

if( !OrderSelect(i,SELECT_BY_POS,MODE_TRADES) ) break;    // No more Orders
die Frage ist umstritten. Wenn es noch Aufträge gibt, ändert sich die Auftragsnummerierung, wenn ein Take/Stop ausgelöst wird, d.h. der Auftrag wird weiterhin ausgewählt: Sie wählen nach Auftragsnummer, nicht nach Ticket. Wenn der Auftrag nicht ausgewählt ist, bedeutet dies, dass es keinen Auftrag gibt. Da Sie die Anzahl der Aufträge nicht jedes Mal überprüfen, werden Sie den Zyklus einige Male leer laufen lassen.