Qual é o projeto correto? - página 8

 
valenok2003:

Muito obrigado, estou processando os erros, a mensagem vem - preço errado, e não consigo descobrir o que está errado.

então acrescente também uma linha

int err = GetLastError();

no início da função - clear error buffer: às vezes é possível ler o erro "de outra pessoa", e desta forma o buffer de erros será limpo no início da função.

Isto não é necessário, mas se os programas para o mundo real, é altamente desejável fazer tudo da maneira mais correta possível.

Boa sorte.

 
VladislavVG:

então também acrescente uma linha

no início da função - clear error buffer: às vezes é possível ler o erro "de outra pessoa", e desta forma o buffer de erros será limpo no início da função.

Isto não é necessário, mas se os programas para o mundo real, é altamente desejável fazer tudo da maneira mais correta possível.

Boa sorte.


Sim, obrigado, isso é o que eu faço em software real.
 
Boa gente, você pode me dizer por que a função retorna 0, embora não haja ordens em aberto. Existe algum tipo de erro?
//+------------------------------------------------------------------+
//| функция закрытия ордеров по символу
//+------------------------------------------------------------------+
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);
}
//+------------------------------------------------------------------+
 
Mais uma vez, estamos separando as peças?
 
valenok2003:
Boa gente, você pode me dizer por que esta função retorna 0 mesmo não havendo pedidos em aberto. Não deveria haver algum tipo de erro?
int OrdensTotal( )

Devolve a quantidade total de ordens pendentes e em aberto.

Ainda escrevendo sob encomenda?

 

-- Usar nomes que começam com um sublinhado e um duplo sublinhado é má forma. Eu prefiro usar um sublinhado no final.


-- Por que _Type_Order string? Acho que é irrealisticamente embaraçoso. Então, teria que ser citado. Porque se você escrever "Vender" ou "vender", não vai funcionar.


-- Se você quiser cometer um erro, cometa um erro:

ERROR = -1;

Melhor ainda.

#define ERROR_NOTHING_TO_CLOSE -1
...

...
ERROR = ERROR_NOTHING_TO_CLOSE;


--

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

Por que quebrar? Suponha que, há um milissegundo atrás, o pedido foi fechado pela TP - por que não deveríamos fechar o resto? Isto é melhor:

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

--

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

A linha é pior do que inútil - é prejudicial. É isso que você deve ter querido dizer?

while (IsTradeContextBusy()) Sleep(1000);


--

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

Isto é, se uma ordem não fechar de repente, "solte a roda, feche os olhos e comece a gritar".

Não há necessidade de fechar os outros? Não há necessidade de tentar novamente?


-- Por que há um retorno de erro aqui? Seria muito mais apropriado retornar, por exemplo, verdadeiro se todos fossem bem sucedidos para fechar e falso se não o fossem.


Isso é tudo por enquanto.

 
TheXpert:

-- Usar nomes que começam com um sublinhado e um duplo sublinhado é má forma. Eu prefiro usar um sublinhado no final.


Ao usar nomes que começam com sublinhados dentro das funções, elimino o risco de sobreposição de variáveis. Assim, eu posso usar os mesmos nomes no início() mas sem sublinhados, o que aumenta a transparência do código.

- Por que é _Type_Order string? Incômodo irreal, imho. Então, deve ser dada. Porque se escrevermos "Vender" ou "vender" nada vai funcionar.

Você está certo, é claro. Entretanto, o uso de uma string aumenta a transparência do código e, com a quantidade de código que tenho no momento, não há necessidade de um sublinhado. Quando eu encontrar este problema realmente, eu o farei, mas por enquanto não é necessário. Eu simplesmente escrevo SELL ou BUY.


Por que quebrar? Bem, vamos assumir que um pedido foi fechado pela TP há um milissegundo atrás, então por que não deveríamos fechar todos os outros? Isto é melhor:

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

Você certamente está certo, obrigado.


A linha é pior do que inútil - é prejudicial. É isso que eu acho que você quer dizer?

A função IsTradeContextBusy() informa apenas sobre a ocupação dos fios, IsTradeAllowed() é um pouco mais ampla


Isto é, se de repente a ordem não puder ser fechada, "solte a roda, feche os olhos e comece a gritar"?


sim, para o período de depuração é

Por que haveria um retorno de erro? Seria muito mais apropriado retornar verdadeiro se tudo pudesse ser fechado e falso se não fosse assim.


Obrigado, acho que já descobri qual é o erro. Vou verificar e apresentar um relatório.
 

O erro foi o seguinte:

a variável _Resultado não é inicializada, portanto conterá falso; assim, como nenhuma das condições foi cumprida, não alteramos a variável _Resultado, e ela já contém falso. E a função prossegue para o tratamento de erros que realmente não ocorreram.

Eu consertei a função e estou publicando-a aqui, acho que alguém pode achá-la útil.

//+------------------------------------------------------------------+
//| функция закрытия ордеров по символу
//+------------------------------------------------------------------+
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 aos moderadores. Eu criei tal ramo por acidente - auto-tutorial completo sobre como fechar os pedidos corretamente. Talvez devesse ser renomeado como - como fechar corretamente os pedidos com exemplos.

PPS Muito obrigado a todos que participaram. Haverá provavelmente mais perguntas.

 
valenok2003:

O erro foi o seguinte:

A variável _Resultado não é inicializada, portanto conterá falso; assim, como nenhuma das condições foi cumprida, não alteramos a variável _Resultado, e ela já contém falso. E a função prossegue para o tratamento de erros que realmente não ocorreram.

Eu consertei a função e estou publicando-a aqui, acho que alguém pode achá-la útil.

PS aos moderadores. Eu criei tal ramo por acidente - auto-tutorial completo sobre como fechar os pedidos corretamente. Talvez devesse ser renomeado como - como fechar corretamente os pedidos com exemplos.

PPS Muito obrigado a todos que participaram. Haverá provavelmente mais perguntas.


Se você olhar para o CodeBase e ler cuidadosamente o fórum - há mais de cem exemplos de fechamento de ordem correta, mas isso não significa que todas as filiais devem ser renomeadas de uma só vez. Já existem heróis suficientes.
 
valenok2003:

O erro foi o seguinte:

a variável _Resultado não é inicializada, portanto conterá falso; assim, como nenhuma das condições foi cumprida, não alteramos a variável _Resultado, e ela já contém falso. E a função prossegue para o tratamento de erros que realmente não ocorreram.

Eu consertei a função e estou publicando-a aqui, acho que alguém pode achá-la útil.

PS aos moderadores. Eu criei tal ramo por acidente - auto-tutorial completo sobre como fechar os pedidos corretamente. Talvez devesse ser renomeado como - como fechar corretamente os pedidos com exemplos.

PPS Muito obrigado a todos que participaram. Haverá provavelmente mais perguntas.

IMHO: Esta função não é clara em sua lógica. Se é para um testador, é desnecessário demais, se é para o mundo real, os erros devem ser tratados. O valor retornado não tem significado porque você está dizendo no nível externo (no nível de chamada) que a chamada terminou com um erro, você está perdendo o erro em si, bem, o especialista escreveu no registro - como isso conta?

O que seria melhor: (novamente, IMHO)

1. Leia e salve o número do erro.

2. Dividir os erros em corrigível e não recuperável. Para fazer isso, devemos criar um manipulador - aqueles erros, quando aparentam estar fechados (um fio está ocupado, falha de conexão ..., etc.) devem ser tratados imediatamente no local. Eu o fiz dessa maneira (primeiro os erros irrecuperáveis, e depois os que podem ser "corrigidos"):

#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 ocorre um erro intratável, para retornar não uma bandeira de erro, mas seu número, para que esta situação possa ser tratada em um módulo externo. Ao analisar o resultado de uma operação:

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

Boa sorte.

SZ sobre pausa/continuação

if( !OrderSelect(i,SELECT_BY_POS,MODE_TRADES) ) break;    // No more Orders
a questão é discutível. Se ainda houver pedidos, então quando um take/stop for acionado, a numeração do pedido será alterada - ou seja, o pedido ainda será selecionado: você seleciona por número de pedido, não por bilhete. Se a ordem não for selecionada, significa que não há ordem. Como você não verifica o número de pedidos a cada vez, você executará o ciclo em branco algumas vezes.
Razão: