Quale disegno è corretto? - pagina 8

 
valenok2003:

Grazie mille, sto elaborando gli errori, arriva il messaggio - prezzo sbagliato, e non riesco a capire cosa c'è di sbagliato.

poi aggiungere anche una linea

int err = GetLastError();

all'inizio della funzione - cancellare il buffer degli errori: a volte è possibile leggere l'errore di "qualcun altro", e in questo modo il buffer degli errori sarà cancellato all'inizio della funzione.

Questo non è richiesto, ma se i programmi per il mondo reale, è altamente auspicabile fare tutto il più correttamente possibile.

Buona fortuna.

 
VladislavVG:

poi aggiungere anche una linea

all'inizio della funzione - cancellare il buffer degli errori: a volte è possibile leggere l'errore di "qualcun altro", e in questo modo il buffer degli errori sarà cancellato all'inizio della funzione.

Questo non è richiesto, ma se i programmi per il mondo reale, è altamente auspicabile fare tutto il più correttamente possibile.

Buona fortuna.


Sì, grazie, è quello che faccio nel software reale.
 
Brava gente, potete dirmi perché la funzione restituisce 0, anche se non ci sono ordini aperti. Dovrebbe esserci un qualche tipo di errore?
//+------------------------------------------------------------------+
//| функция закрытия ордеров по символу
//+------------------------------------------------------------------+
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);
}
//+------------------------------------------------------------------+
 
Ancora una volta, stiamo smontando i pezzi?
 
valenok2003:
Brava gente, potete dirmi perché questa funzione restituisce 0 anche se non ci sono ordini aperti. Non dovrebbe esserci un qualche tipo di errore?
int OrdiniTotale( )

Restituisce l'importo totale degli ordini aperti e in sospeso.

Stai ancora scrivendo per ordinare?

 

-- Usare nomi che iniziano con un trattino basso e un doppio trattino basso è una cattiva forma. Preferisco usare un underscore alla fine.


-- Perché la stringa _Type_Order? Irrealmente imbarazzante, credo. Allora dovrebbe essere citato. Perché se scrivi "Vendere" o "vendere" non funzionerà.


-- Se vuoi fare un errore, fai un errore:

ERROR = -1;

Meglio ancora.

#define ERROR_NOTHING_TO_CLOSE -1
...

...
ERROR = ERROR_NOTHING_TO_CLOSE;


--

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

Perché rompere? Supponiamo che un millisecondo fa l'ordine sia stato chiuso da TP - perché non dovremmo chiudere il resto? Questo è meglio:

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

--

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

La linea è peggio che inutile, è dannosa. È questo che deve aver voluto dire?

while (IsTradeContextBusy()) Sleep(1000);


--

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

Cioè, se un ordine improvvisamente non si chiude, "lascia andare il volante, chiudi gli occhi e comincia a gridare".

Non c'è bisogno di chiudere gli altri? Non c'è bisogno di riprovare?


-- Perché c'è un ritorno di errore qui? Sarebbe molto più appropriato restituire, per esempio, true se tutti sono riusciti a chiudere e false se no.


Questo è tutto per ora.

 
TheXpert:

-- Usare nomi che iniziano con un trattino basso e un doppio trattino basso è una cattiva forma. Preferisco usare un underscore alla fine.


Usando nomi che iniziano con trattini bassi all'interno delle funzioni, elimino il rischio di sovrascrittura delle variabili. Così, posso usare gli stessi nomi in start() ma senza underscore, il che aumenta la trasparenza del codice.

- Perché _Type_Order è una stringa? Irrealmente scomodo, imho. Allora dovrebbe essere dato. Perché se scriviamo "Vendere" o "vendere" non funzionerà nulla.

Hai ragione, naturalmente. Tuttavia, usare una stringa aumenta la trasparenza del codice e con la quantità di codice che ho al momento, non c'è bisogno di una sottolineatura. Quando incontrerò davvero questo problema, lo farò, ma per ora non è necessario. Scrivo semplicemente VENDERE o COMPRARE.


Perché rompere? Bene, supponiamo che un ordine sia stato chiuso da TP un millisecondo fa, quindi perché non dovremmo chiudere tutti gli altri? Questo è meglio:

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

Ha certamente ragione, grazie.


La linea è peggio che inutile - è dannosa. È quello che penso tu voglia dire?

La funzione IsTradeContextBusy() informa solo sull'occupazione dei thread, IsTradeAllowed() è un po' più ampia


Cioè, se improvvisamente l'ordine non può essere chiuso, "lasciate andare il volante, chiudete gli occhi e cominciate a gridare"?


sì, per il periodo di debug è

Perché dovrebbe esserci un ritorno di errore? Sarebbe molto più appropriato restituire true se tutto può essere chiuso e false se no.


Grazie, mi sembra di aver capito qual è l'errore. Controllerò e riferirò.
 

L'errore era il seguente:

la variabile bool _Result non è inizializzata, quindi conterrà false; quindi, poiché nessuna delle condizioni è stata soddisfatta, non abbiamo cambiato la variabile _Result, e contiene già false. E la funzione procede alla gestione degli errori che in realtà non si sono verificati.

Ho aggiustato la funzione e la sto postando qui, penso che qualcuno possa trovarla 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 ai moderatori. Ho creato un tale ramo per caso - un completo autotutorial su come chiudere correttamente gli ordini. Forse dovrebbe essere rinominato come - come chiudere correttamente gli ordini con esempi.

PPS Grazie mille a tutti coloro che hanno partecipato. Probabilmente ci saranno altre domande.

 
valenok2003:

L'errore era il seguente:

la variabile bool _Result non è inizializzata, quindi conterrà false; quindi, poiché nessuna delle condizioni è stata soddisfatta, non abbiamo cambiato la variabile _Result, e contiene già false. E la funzione procede alla gestione degli errori che in realtà non si sono verificati.

Ho aggiustato la funzione e la sto postando qui, penso che qualcuno possa trovarla utile.

PS ai moderatori. Ho creato un tale ramo per caso - un autotutorial completo su come chiudere correttamente gli ordini. Forse dovrebbe essere rinominato come - come chiudere correttamente gli ordini con esempi.

PPS Grazie mille a tutti coloro che hanno partecipato. Probabilmente ci saranno altre domande.


Se guardate il CodeBase e leggete attentamente il forum - ci sono più di cento esempi di chiusura dell'ordine corretto, ma questo non significa che tutti i rami debbano essere rinominati in una volta sola. Ci sono abbastanza eroi.
 
valenok2003:

L'errore era il seguente:

La variabile bool _Result non è inizializzata, quindi conterrà false; quindi, poiché nessuna delle condizioni è stata soddisfatta, non abbiamo cambiato la variabile _Result, e contiene già false. E la funzione procede alla gestione degli errori che in realtà non si sono verificati.

Ho aggiustato la funzione e la sto postando qui, penso che qualcuno possa trovarla utile.

PS ai moderatori. Ho creato un tale ramo per caso - un completo autotutorial su come chiudere correttamente gli ordini. Forse dovrebbe essere rinominato come - come chiudere correttamente gli ordini con esempi.

PPS Grazie mille a tutti coloro che hanno partecipato. Probabilmente ci saranno altre domande.

IMHO: Questa funzione non è chiara nella sua logica. Se è per un tester, è troppo inutile, se è per il mondo reale, gli errori dovrebbero essere gestiti. Il valore restituito non ha alcun significato perché state dicendo a livello esterno (a livello di chiamata) che la chiamata è finita con un errore, state perdendo l'errore stesso, beh, l'esperto ha scritto nel log - come conta?

Cosa sarebbe meglio: (di nuovo, IMHO)

1. Leggere e salvare il numero di errore.

2. Dividete gli errori in risolvibili e non risolvibili. Per fare questo, dovremmo creare un gestore - quegli errori, alla comparsa dei quali l'ordine può essere chiuso (un thread è occupato, fallimento della connessione ..., ecc) dovrebbero essere gestiti immediatamente sul posto. Ho fatto così (prima gli errori irrecuperabili, e poi quelli che possono essere "aggiustati"):

#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. Quando si verifica un errore intrattabile, restituire non un flag di errore, ma il suo numero, in modo che questa situazione possa essere gestita in un modulo esterno. Quando si analizza il risultato di un'operazione:

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

Buona fortuna.

SZ su pausa/continua

if( !OrderSelect(i,SELECT_BY_POS,MODE_TRADES) ) break;    // No more Orders
la questione è discutibile. Se ci sono ancora ordini, allora quando viene attivato un take/stop la numerazione dell'ordine cambierà - cioè l'ordine sarà ancora selezionato: si seleziona per numero d'ordine, non per biglietto. Se l'ordine non è selezionato, significa che non c'è nessun ordine. Poiché non si controlla ogni volta il numero di ordini, il ciclo sarà vuoto per un certo numero di volte.