OrderSend() perguntas - página 5

 

Aparentemente, não expliquei o problema anterior de forma muito clara. Deixe-me tentar novamente.

Durante o último ano, a descrição da lista de valores de enumeraçãoENUM_ORDER_TYPE_FILLING foi alterada pelo menos três vezes. A descrição anterior era a seguinte

ENUM_ORDER_TYPE_FILLING

Identificador

Descrição

ORDER_FILLING_FOK

Uma transacção só pode ser executada no volume especificado e a um preço igual ou melhor do que o especificado na encomenda. Se não houver oferta suficiente no mercado neste momento para o símbolo da encomenda, então a encomenda não será preenchida. Este tipo de preenchimento é utilizado no modo de execução SYMBOL_TRADE_EXECUTION_INSTANT ouSYMBOL_TRADE_EXECUTION_REQUEST.

ORDER_FILLING_IOC

Um acordo para executar uma transacção no volume máximo disponível no mercado dentro do volume especificado na ordem e a um preço igual ou melhor do que o especificado na ordem. Neste caso, não serão feitas encomendas adicionais para o volume em falta. Este tipo de preenchimento só pode estar disponível nos modos de execução SYMBOL_TRADE_EXECUTION_MARKET eSYMBOL_TRADE_EXECUTION_EXCHANGE dependendo das definições no servidor de negociação.

ORDER_FILLING_RETURN

Acordo para executar uma transacção sobre o volume máximo disponível no mercado dentro do volume especificado na ordem e a um preço igual ou melhor do que o especificado na ordem. Neste caso, será feita uma encomenda adicional para o volume em falta ao preço especificado nesta encomenda. Este tipo de enchimento é utilizado apenas para encomendas pendentes (TRADE_ACTION_PENDING).

Como podemos facilmente ver, existe uma correspondência um-para-um entre ORDER_FILLING_RETURN e ordens pendentes, nomeadamente ORDER_FILLING_RETURN só poderia ser aplicado a encomendas pendentes e o campo type_filling de todas as encomendas pendentes só poderia ser preenchido com o valor de ORDER_FILLING_RETURN.

Para ordens de mercado(action===TRADE_ACTION_DEAL) o campo type_filling deveria ter sido preenchido em função dos modos de execução definidos no lado do servidor.

Assim, tínhamos um certo paradigma: se houvesse uma ordem pendente,ORDER_FILLING_RETURN; se houvesse uma ordem de mercado, ORDER_FILLING_FOK ou ORDER_FILLING_IOC (dependendo do modo).

Agora tudo está um pouco virado do avesso, nomeadamente:

ENUM_ORDER_TYPE_FILLING

Identificador

Descrição

ORDER_FILLING_FOK

Esta política de preenchimento de encomendas significa que a encomenda só pode ser preenchida até ao volume especificado. Se não houver volume suficiente do instrumento financeiro no mercado neste momento, a ordem não será executada. O volume necessário pode ser compilado a partir de várias ofertas actualmente disponíveis no mercado.

ORDER_FILLING_IOC

Indica acordo para executar uma transacção até ao volume máximo disponível no mercado dentro do volume especificado na ordem. Se a execução completa não for possível, a encomenda será preenchida até ao volume disponível, e o volume não preenchido será cancelado.

ORDER_FILLING_RETURN

Este modo só é utilizado para encomendas de ORDER_TYPE_BUY_LIMIT e ORDER_TYPE_SELLL_LIMIT. Em caso de execução parcial, a ordem limite com o volume restante não é eliminada, mas permanece em vigor.

Para ORDER_TYPE_BUY_BUY_STOP_LIMIT e ORDER_TYPE_SELLL_STOP_LIMIT ordena a ordem correspondente ORDER_TYPE_BUY_LIMIT/ORDER_TYPE_SELLL_LIMIT com o tipo de execução ORDER_FILLING_RETURN será criada aquando da activação.

A restrição de utilizar ORDER_FILLING_FOK e ORDER_FILLING_IOC apenas com ordens do mercado desapareceu. Também não há restrições à utilização de ORDER_FILLING_FOK e ORDER_FILLING_IOC com ordens de mercado, dependendo do modo de execução definido no servidor. Existe uma restrição ao uso de ORDER_FILLING_RETURN apenas com ordens de limite e stop_limit .

Então a minha pergunta é: É aceitável usar ORDER_FILLING_FOK e ORDER_FILLING_IOC para todas as ordens (tanto de mercado como pendentes), incluindo ordens de limite e stop_limit? Alguém descobriu as mudanças?

 

A Biblioteca Standard tem este método (esquemático):

bool CTrade::PositionClose(const string symbol,ulong deviation)
  {
   do
     {
      //--- checking
      if(PositionSelect(symbol))
        {
         if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
           {
            //--- prepare request for close BUY position
            m_request.type =ORDER_TYPE_SELL;
            m_request.price=SymbolInfoDouble(symbol,SYMBOL_BID);
           }
         else
           {
            //--- prepare request for close SELL position
            m_request.type =ORDER_TYPE_BUY;
            m_request.price=SymbolInfoDouble(symbol,SYMBOL_ASK);
           }
        }
      else
        {
         //--- position not found
         m_result.retcode=retcode;
         return(false);
        }
      m_request.action      =TRADE_ACTION_DEAL;
      m_request.volume      =PositionGetDouble(POSITION_VOLUME);
      //--- check volume
      double max_volume=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
      if(m_request.volume>max_volume)
        {
         m_request.volume=max_volume;
         partial_close=true;
        }
      else
         partial_close=false;
      //--- order send
      if(!OrderSend(m_request,m_result))
        {
         if(--retry_count!=0) continue;
         if(retcode==TRADE_RETCODE_DONE_PARTIAL)
            m_result.retcode=retcode;
         return(false);
        }
      retcode=TRADE_RETCODE_DONE_PARTIAL;
      if(partial_close) Sleep(1000);
     }
   while(partial_close);
   return(true);
  }

Aqui, caso o volume da posição seja maior queo volume máximo para fazer uma troca, são feitastentativas sucessivas de fechar parcialmente a posição.

Após uma chamada bem sucedida da função OrderSend(), é definido um atraso de segundos e depois a funçãoPositionSelect() é chamada no corpo do loop do-while. Isto é, supõe-se que no caso do servidor aceitar com sucesso uma ordem de mercado, um segundo é suficiente para actualizar os dados sobre a posição aberta no terminal base e obter os dados actualizados da posição (neste exemplo - o volume da posição) na iteração seguinte. Mas há dois anos atrás, o atraso no mesmo método antes de chamar a função PositionSelect() era de três segundos. A questão é, portanto, a seguinte:

Um segundo é suficiente em todos os casos para garantir que, após uma chamada bem sucedida para OrderSend(), a base de dados do terminal receba dados de posição actualizados (e assim permitir que o volume restante da posição seja processado correctamente no lado do terminal)? Qual é o tempo máximo em que a base de dados do terminal deve ser garantida para receber dados de posição actualizados neste caso?

 

O campeonato tem uma tal regra:

As condições comerciais serão as mais próximas do real possível:

  • Tempo de processamento dos pedidos comerciais de 2 a 7 segundos
Em real com um corretor (após retirada) o processamento tornou-se cerca de 3 segundos (abertura-fechamento-modificação). Imediatamente mudado para NDD.Satisfeito até agora.
 
Karlson:

O campeonato tem uma tal regra:

As condições comerciais serão as mais próximas do real possível:

  • tempo de processamento de 2 a 7 segundos

OK, obrigado pela dica! Acontece que um segundo não é suficiente para a base de dados do terminal receber os dados actualizados da posição após uma chamada bem sucedida da função OrderSend()?

Desta conclusão resulta que o método da Biblioteca Padrão que citei não garante de modo algum que a posição será invertida em vez de ser fechada. Isto é, se o método PositionClose() atrasar a próxima iteração em um segundo, e os pedidos de troca puderem levar 2-7 vezes mais tempo a processar, não podemos excluir que durante as novas iterações, a funçãoPositionSelect() receba os dados anteriores sobre os estados de posição do terminal base e bombardeie o servidor com ordens idênticas, cujo volume total neste caso será maior do que ovolume de fecho da posiçãoinicial.

Então porque é que existe um atraso de um segundo no método PositionClose(), se permite inverter a posição em vez de a fechar? E não é coerente com as"condições comerciais, tão próximas quanto possível das reais"?

Em geral, preciso de mais informações sobre quanto tempo a base de dados do terminal, após uma chamada bem sucedida da função OrderSend(), tem a garantia de receber os dados actualizados da posição, e qual a razão do atraso de um segundo no método padrão PositionClose().

 
Comecemos com o facto de que
if(PositionSelect(symbol))

não garante nada. Não pode ser utilizado.

Em segundo lugar, não são dadas garantias para a actualização dos dados do terminal. Tem de criar você mesmo um TradeContextBusy artificial e esperar que todas as suas encomendas sejam processadas.
Não é possível fazê-lo imediatamente e de frente para a MQL5. Não há garantias de tempo.

 

sergeev:

начнем с того, что

if(PositionSelect(symbol))

não garante nada. Não pode ser aplicado.

Em segundo lugar, não há garantia de actualização dos dados do terminal - tem de organizar você mesmo um TradeContextBusy artificial e esperar que todas as suas encomendas sejam processadas.
Não se pode utilizar a MQL5 directa e directamente. Não há garantias de tempo.

Sim, vou ter de continuar a ponderar. Acontece que eu deveria ter tomado o método padrão da biblioteca como exemplo para a reciclagem.

Pode dizer-me se aparece um acordo na história com o

DEAL_ENTRY_OUT

Saída do Mercado

significa que todas as informações na base de dados do terminal foram automaticamente alteradas (actualizadas para o estado actual)? Ou o comércio pode já aparecer na história e a informação sobre a posição ainda não será actualizada? Por outras palavras, a questão é interessante: as informações sobre negócios na história e as informações sobre as posições correspondentes mudam simultaneamente? Ou, neste caso, as ofertas e posições também são actualizadas no terminal de forma assíncrona? Não consegui apanhá-lo no artigo de Rosh - tanto quanto percebi, a assincronia entre a actualização da base terminal e o retorno do resultado do pedido comercial é aí descrita.

 

O modelo de troca de dados no terminal é assíncrono, como notou.

por isso, quando negociamos (recuperando propriedades de ordens/contratos/posições), precisamos de analisar o sucesso da recuperação de dados. E no caso de qualquer erro (false/0), terminar a análise da lógica comercial.

Todas as ordens de encomenda executadas e não confirmadas serão lembradas e aguardarão o aparecimento da ordem, bloqueando o novo envio se ainda não houver resposta do envio anterior.

E, por exemplo, seria melhor substituir PositionSelect por uma construção

for(int i=PositionsTotal()-1;i>=0;i--) 
{
  if(PositionGetSymbol(i)==Symbol())
  {
    ....
  }

Em geral, a lógica comercial deve ser assíncrona. Como o terminal é assíncrono, o MT-server e o servidor do fornecedor de liquidez são assíncronos.

A tarefa de verificar a sincronização é inteiramente da responsabilidade do programador MQL.

Документация по MQL5: Стандартные константы, перечисления и структуры / Торговые константы / Типы торговых операций
Документация по MQL5: Стандартные константы, перечисления и структуры / Торговые константы / Типы торговых операций
  • www.mql5.com
Стандартные константы, перечисления и структуры / Торговые константы / Типы торговых операций - Документация по MQL5
 

Não tive problemas em utilizar esta resposta no último campeonato

https://www.mql5.com/ru/forum/4342#comment_88688

Дублирование запросов на открытие позиций.
Дублирование запросов на открытие позиций.
  • www.mql5.com
Дублирование запросов на открытие позиций.
 
sergeev:

E, por exemplo, seria melhor substituir a PositionSelect pela construção

for(int i=PositionsTotal()-1;i>=0;i--) 
{
  if(PositionGetSymbol(i)==Symbol())
  {
    ....
  }

Por favor explique, se não for difícil, qual é a vantagem de usarPositionsTotal() + PositionGetSymbol() em vez de usar PositionSelect()? Todas as três funções estão a aceder à mesma base terminal, e as funções PositionGetSymbol() e PositionSelect() podem falhar. Isto é, se a posição existir na base terminal, tanto a função PositionSelect() como a construção proposta podem falhar. Ainda tem de verificar o código de erro.

Quais são as peculiaridades/confiabilidade da sua construção? Ainda não consegui perceber.

Документация по MQL5: Торговые функции / PositionSelect
Документация по MQL5: Торговые функции / PositionSelect
  • www.mql5.com
Торговые функции / PositionSelect - Документация по MQL5
 

Estou a bater o meu cérebro... a paragem não se estabelece... e muitos erros. isto é o que resta da experiência, e já não funciona

void OnTick(){ if(PositionsTotal()<1){OPEN();}}

bool OPEN(){
             MqlTradeRequest request;
             MqlTradeResult result;
             

             request.symbol       = _Symbol;
             request.action       = TRADE_ACTION_DEAL;
             request.type_filling = ORDER_FILLING_FOK;
             request.deviation    = 100;
             request.volume       = NormalizeDouble(2,2);
             request.type         = ORDER_TYPE_BUY;
             request.price        = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
             request.tp           = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK) + 500*_Point,_Digits);
             request.sl           = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK) - 500*_Point,_Digits);

             OrderSend(request,result);     
                        
             if(result.retcode==10009 || result.retcode==10008)  Print("Succsesful open");
             else                                               Print("Error open: ",DoubleToString(GetLastError(),0),"  response code: ",result.retcode);
    
   return(true);}

Se eu fizer isto, não há erros, mas o stop-loss ainda não está definido

MqlTradeRequest request={0};MqlTradeResult result={0};