Características da linguagem mql5, subtilezas e técnicas - página 184

 
enum EAct{PUSH,POP};

template<typename T>
void TempCondition(T &value,EAct act){
   static T temp=T();
   switch(act){
      case PUSH: temp=value; break;
      case POP: value=temp;
   }
}

#define  sortArray(_lArray,_lField) do {                     \
   for(int i = 0; i < ArraySize(_lArray); i++) {            \
      TempCondition(_lArray[i],PUSH);                       \
      for(int a = 1; a <= i; a++) {                         \
         if(_lArray[i]._lField < _lArray[a - 1]._lField){   \
            for(int b = i; b >= a; b--) {                   \
               _lArray[b] = _lArray[b - 1];                 \
               }                                            \
               TempCondition(_lArray[a - 1],POP);           \
               break;}}}} while(false)


struct STest{
   double a;
   int b;
};

void OnStart()
{
    STest test[700];
    sortArray(test,a);
}

É suposto funcionar. Mas não aconselharia fazê-lo desta forma).

 
Koldun Zloy:

Isto é de facto óptimo. E permite estabelecer condições de triagem mais complexas.

Por exemplo:

Sim e não há outras soluções de qualquer forma.

O objectivo do padrão é ser universal. Se passar outra estrutura no seu exemplo que não contenha pelo menos um campo a,b,c, esta não compilará. Ou seja, a função não pode funcionar com dois tipos de dados diferentes ao mesmo tempo.

 
Comentários não relacionados com este tópico foram movidos para"Quaisquer perguntas de novatos sobre MQL4 e MQL5, ajuda e discussão sobre algoritmos e códigos".
 

Fórum sobre comércio, sistemas comerciais automatizados e teste de estratégias comerciais

Painel de controlo para o comércio. MQL5 AJUDA NECESSÁRIA

Vladimir Karputov, 2020.08.18 09:04

Este código não funcionaria - não é possível comparar patties e quadrados:

   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      ulong OrderTicket=OrderGetTicket(i);
      if(OrderTicket>0 && PositionSelectByTicket(OrderTicket))
        {
         // Stop long позиции------------------------------------------
         if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
           {
            int cur_tr; //трейлинг
            double ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
            double newSl = ask - cur_tr*_Point;
            double positionSl = PositionGetDouble(POSITION_SL);
            double positionTP = PositionGetDouble(POSITION_TP);
            if(newSl > positionSl || positionSl == 0)
              {
               CTrade trade;
               trade.PositionModify(OrderTicket,newSl,positionTP);
              }
           }
        }
     }

Esta condição funcionará se a ordem pendente for parcialmente executada e gerar uma posição. Então, uma ordem e uma posição com o mesmo bilhete existirão ao mesmo tempo.

Por esta razão, a seguinte construção faz sentido em algumas situações.

::PositionSelectByTicket(::OrderGetInteger(ORDER_TICKET))
 
Se quiser zerar os dados MQL da posição ou ordem seleccionada.
PositionSelectByTicket(0); // Обнуляет PositionGet*
OrderSelect(0);            // Обнуляет OrderGet*
 

Fórum sobre comércio, sistemas de comércio automatizados e testes estratégicos

Bibliotecas: MT4Orders

fxsaber, 2020.08.20 15:44

Para quem trabalha com transacções assíncronas, será útil conhecer as definições para o maior número possível de transacções assíncronas não processadas na sua conta.

Isto não é difícil de descobrir.

Alert: 60 - Too many trade requests


Tenha cuidado, pode correr até um limite.

 
fxsaber:

Renat disse há muito tempo que não só se pode ser apanhado por um limite, como também pode ser bloqueado por um CD

 
fxsaber:

Esta condição será desencadeada se a ordem pendente for parcialmente executada e gerar uma posição. Então, uma ordem e uma posição com o mesmo carimbo existirão ao mesmo tempo.

O seguinte código numa conta de demonstração doRannForex-Server pode reproduzir imediatamente esta situação através da execução desta EA.

// Воспроизведение ситуации наличия позиции и отложенного ордера с одинаковыми тикетами.

#define  Ask SymbolInfoDouble(_Symbol, SYMBOL_ASK)

MqlTradeResult Result = {0};
MqlTradeRequest Request = {0};

int OnInit()
{

        Request.action = TRADE_ACTION_PENDING;
        Request.symbol = _Symbol;
        Request.volume = 100;
        Request.price = Ask;
        Request.type = ORDER_TYPE_BUY_LIMIT;
        
        return(!OrderSend(Request, Result)); // Выставили лимитник по текущей цене.
}

#define  TOSTRING(A) #A + " = " + DoubleToString(A, _Digits)

void OnTradeTransaction( const MqlTradeTransaction&, const MqlTradeRequest&, const MqlTradeResult& )
{
  if (OrderSelect(Result.order) && (OrderGetInteger(ORDER_STATE) == ORDER_STATE_PARTIAL)) // Если наш лимитник исполнился частично
  {
    if (Ask - OrderGetDouble(ORDER_PRICE_OPEN) < 100 * _Point)                            // и находится близко от текущей цены
    {
        Request.action = TRADE_ACTION_MODIFY;
        Request.order = Result.order;
        Request.price = Ask - 1000 * _Point;

      // тогда передвигаем его подальше.
      if (OrderSend(Request, Result)) // Если синхронный OrderSend выполнился успешно, то торговое окружение должно соответствовать.
      {
        // Проверка соответствия торгового окружения.
        if (OrderSelect(Request.order) &&                                                                // Если получилось взять данные нашего ордера
            NormalizeDouble(OrderGetDouble(ORDER_PRICE_OPEN) - Request.price, _Digits))                  // и цена ордера не равна цене успешного OrderSend
          Alert("Bug:" + TOSTRING(OrderGetDouble(ORDER_PRICE_OPEN)) + " != " + TOSTRING(Request.price)); // сообщаем о баге MT5.
      }
    }
    else
      ExpertRemove();
  }     
}


Resultado.


A propósito, o guião mostra (nem sempre da primeira vez) um erro na execução do OrderSend síncrono.

Alert: Bug:OrderGetDouble(ORDER_PRICE_OPEN) = 0.89837 != Request.price = 0.88837

Após a OrderSend ser executada durante alguns dez/centenas de milissegundos, o preço da encomenda é o antigo, e não o que foi colocado com sucesso pela OrderSend.


Voltando ao tema de bilhetes idênticos, podemos tirar algumas conclusões.

  1. Se uma ordem parcial de limite estiver pendurada, a guia "Ordens e comércios" não mostrará o comércio gerado.
  2. Numa cobertura, uma única ordem pode gerar múltiplas transacções IN com preços diferentes. O resultado será um preço de abertura fracionário (relativo a pips) da posição.
  3. Pode fechar a posição gerada sem remover o Put Parcial. Mas se depois disso a ordem pendente for accionada, então uma troca será aberta com o bilhete, igual ao bilhete da posição, que foi fechada antes. Ou seja, pode haver uma situação em que se fecha uma posição com um determinado bilhete. E depois reaparece uma posição com o mesmo ticker.
  4. A execução parcial pode ser implementada de forma diferente, dependendo do software do corretor. O acima exposto é uma implementação padrão do MT5.

Se alguém o conseguiu reproduzir noutro servidor comercial, por favor partilhe o nome.

Cadeia de pesquisa: Oshibka 010.

 
fxsaber:


  1. Pode fechar a posição gerada sem apagar o Put Parcial. Mas se depois disso a ordem pendente for accionada, abrirá uma troca com um bilhete igual ao bilhete da posição anteriormente fechada. Ou seja, pode haver uma situação em que se fecha uma posição com um determinado bilhete. E depois aparece novamente uma posição com o mesmo bilhete.

Não é um bilhete único? Como pode isto ser?

Tanto as encomendas como os negócios têm bilhetes únicos?

 
Andrey Khatimlianskii:

Não é um bilhete único? Como é que isso pode ser?

A explicação é que enquanto houver uma ordem de abertura, há sempre uma posição. Apenas nem sempre é visível - o volume é zero. E esta posição tem um bilhete único. Bem, numa sebe por esta razão, é bem possível que haja atiradores na mesma posição após as correspondentes entradas e saídas.

Será que as encomendas e ofertas têm sequer bilhetes únicos?

São únicos. Mas é claro que ORDER_TICKET pode ser igual a DEAL_TICKET.