EA com múltiplas entradas, mas só a primeira é executada.

 
Estou finalizando um EA que faz uma entrada ao ser carregado e gráfico e outras N entradas conforme o preço ande contra a operação. 

Porém, ele faz a primeira entrada e:
  1.  Se chega no objetivo, fecha e não opera mais até que o MT5 seja reiniciado. 
  2.  Não abre as demais operações,  mas se o mt5 é fechado e reaberto,  ele abre todas as entradas dos níveis que deram sinal.
Alguma coisa meio que universal pra colocar no ontick ou outra função?

Valeu.
[Excluído]  

Se necessita de ajuda ou conselhos sobre o seu código, terá de o mostrar. Não existem respostas “universais”.

 
Fernando Carreiro #:

Se necessita de ajuda ou conselhos sobre o seu código, terá de o mostrar. Não existem respostas “universais”.

void OnTick()
{
    static datetime lastCheckDay = 0;
    static datetime lastCloseByCheck = 0; // Para verificar fechamentos por close by
    double gapOpenPrice = 0;
    bool isUpGap = false;

    // Verifica se é um novo dia
    if (GetDay(TimeCurrent()) != GetDay(lastCheckDay))
    {
        if (UseGapFilter && CheckForGap(gapOpenPrice, isUpGap))
        {
            initialPrice = gapOpenPrice; // Define o preço de abertura como novo preço inicial
        }
        else if (!UseGapFilter)
        {
            ExecutePendingOrdersAtOpen();
        }
        lastCheckDay = TimeCurrent(); // Atualiza o último dia verificado
    }

    // Atualiza informações de posição
    UpdatePositionInfo();

    // Verifica spread e condições de mercado
    bool spreadOK = CheckSpread();
    UpdateSpreadStatus(spreadOK);

    // Recalcula e redesenha as linhas de suporte, resistência e ponto médio
    double support, resistance;
    CalculateSupportResistance(support, resistance);

    // Cancela ordens pendentes irrelevantes
    CancelIrrelevantPendingOrders();

    // Lógica de transição de estados
    switch (eaState)
    {
        case EA_STATE_WAITING_FOR_SIGNAL:
            // Verifica se o preço atingiu suporte, resistência ou ponto médio
            if (spreadOK && CheckSignalConditions())
            {
                OpenPositionBasedOnMode();
                eaState = EA_STATE_IN_TRADE;
            }
            // Para START_AUTO_BUY e START_AUTO_SELL
            else if (StartMode == START_AUTO_BUY || StartMode == START_AUTO_SELL)
            {
                if (purchaseCount < MaxPurchases)
                {
                    double nextPurchaseLevel = CalculateNextPurchaseLevel();
                    double currentBid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
                    double currentAsk = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
                    if ((StartMode == START_AUTO_BUY && currentBid <= nextPurchaseLevel) ||
                        (StartMode == START_AUTO_SELL && currentAsk >= nextPurchaseLevel))
                    {
                        // Verifica se já existem posições abertas no nível de preço
                        if (!CheckPendingOrderExists(nextPurchaseLevel) && !CheckOpenPositionExists(nextPurchaseLevel))
                        {
                            double lotSize = CalculateNextLotSize();
                            if (StartMode == START_AUTO_BUY)
                                OpenBuyPosition(lotSize);
                            else
                                OpenSellPosition(lotSize);
                        }
                    }
                }
            }
            break;

        case EA_STATE_IN_TRADE:
            // Verifica se todas as posições foram fechadas
            if (CountPositions() == 0 && OrdersTotal() == 0)
            {
                eaState = EA_STATE_RESET; // Muda para o estado RESET
            }
            break;

        case EA_STATE_RESET:
            // Reinicia as variáveis e volta ao estado WAITING_FOR_SIGNAL
            ResetTrading();
            eaState = EA_STATE_WAITING_FOR_SIGNAL; // Aguarda um novo sinal
            break;
    }

    // Verifica se deve operar com base nas regras normais (apenas no estado IN_TRADE)
    if (eaState == EA_STATE_IN_TRADE && spreadOK && purchaseCount < MaxPurchases)
    {
        double nextPurchaseLevel = CalculateNextPurchaseLevel();
        double currentBid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
        double currentAsk = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
        if (StartMode == START_AUTO_BUY || StartMode == START_SIGNAL_SUPPORT || StartMode == START_SIGNAL_MIDPOINT)
        {
            if (currentBid <= nextPurchaseLevel)
            {
                // Verifica se já existem posições abertas no nível de preço
                if (!CheckPendingOrderExists(nextPurchaseLevel) && !CheckOpenPositionExists(nextPurchaseLevel))
                {
                    double lotSize = CalculateNextLotSize();
                    if (isHedgeAccount)
                    {
                        if (UsePendingOrders)
                            OpenBuyLimitOrder(lotSize, nextPurchaseLevel);
                    }
                    else
                    {
                        OpenBuyPosition(lotSize);
                    }
                }
            }
        }
        else if (StartMode == START_AUTO_SELL || StartMode == START_SIGNAL_RESISTANCE)
        {
            if (currentAsk >= nextPurchaseLevel)
            {
                // Verifica se já existem posições abertas no nível de preço
                if (!CheckPendingOrderExists(nextPurchaseLevel) && !CheckOpenPositionExists(nextPurchaseLevel))
                {
                    double lotSize = CalculateNextLotSize();
                    if (isHedgeAccount)
                    {
                        if (UsePendingOrders)
                            OpenSellLimitOrder(lotSize, nextPurchaseLevel);
                    }
                    else
                    {
                        OpenSellPosition(lotSize);
                    }
                }
            }
        }
    }

    // Ajusta o TP e SL das posições abertas
    AdjustTPAndSLForAllPositions();

    // Atualiza o painel de resumo
    UpdateSummaryPanel();

    // Verifica e tenta fechar posições opostas por close by
    const int CheckInterval = 1; // Intervalo de verificação em segundos
    if (TimeCurrent() - lastCloseByCheck >= CheckInterval && isHedgeAccount)
    {
        lastCloseByCheck = TimeCurrent();
        CloseOppositePositions();
    }
}
 

No trecho abaixo, o estado do EA não deveria ser alterado também?

// Verifica se já existem posições abertas no nível de preço
   if(!CheckPendingOrderExists(nextPurchaseLevel) && !CheckOpenPositionExists(nextPurchaseLevel))
     {
      double lotSize = CalculateNextLotSize();
      if(StartMode == START_AUTO_BUY)
        {
         OpenBuyPosition(lotSize);
        }
      else
        {
         OpenSellPosition(lotSize);
        }
      eaState = EA_STATE_IN_TRADE;
     }
 
Vinicius Pereira De Oliveira #:

No trecho abaixo, o estado do EA não deveria ser alterado também?

Obrigado, vou testar isso!

 
Thiago Lopes #:

Obrigado, vou testar isso!

Estou olhando o código e achando aquele ELSE dentro switch meio estranho. Outra coisa que parece muito estranha no trecho logo depois do switch tem uma parte que esta dizendo SE for conta hedge e não for para usar ordens pendentes não faça nada tanto na compra e venda. Dai voltando pro código do ELSE dentro do switch tudo faz sentido. Provavelmente, o ELSE era pra estar no estado EA_STATE_IN_TRADE e pra ser feito somente se fosse conta hedge a mercado (mas o teste nao existe lá pra isso).

Acredito que talvez o mais facil é fazer o seguinte:

void OnTick()
{
    static datetime lastCheckDay = 0;
    static datetime lastCloseByCheck = 0; // Para verificar fechamentos por close by
    double gapOpenPrice = 0;
    bool isUpGap = false;

    // Verifica se é um novo dia
    if (GetDay(TimeCurrent()) != GetDay(lastCheckDay))
    {
        if (UseGapFilter && CheckForGap(gapOpenPrice, isUpGap))
        {
            initialPrice = gapOpenPrice; // Define o preço de abertura como novo preço inicial
        }
        else if (!UseGapFilter)
        {
            ExecutePendingOrdersAtOpen();
        }
        lastCheckDay = TimeCurrent(); // Atualiza o último dia verificado
    }

    // Atualiza informações de posição
    UpdatePositionInfo();

    // Verifica spread e condições de mercado
    bool spreadOK = CheckSpread();
    UpdateSpreadStatus(spreadOK);

    // Recalcula e redesenha as linhas de suporte, resistência e ponto médio
    double support, resistance;
    CalculateSupportResistance(support, resistance);

    // Cancela ordens pendentes irrelevantes
    CancelIrrelevantPendingOrders();

    // Lógica de transição de estados
    switch (eaState)
    {
        case EA_STATE_WAITING_FOR_SIGNAL:
            // Verifica se o preço atingiu suporte, resistência ou ponto médio
            if (spreadOK && CheckSignalConditions())
            {
                OpenPositionBasedOnMode();
                eaState = EA_STATE_IN_TRADE;
            }
            break;

        case EA_STATE_IN_TRADE:
            // Verifica se todas as posições foram fechadas
            if (CountPositions() == 0 && OrdersTotal() == 0)
            {
                eaState = EA_STATE_RESET; // Muda para o estado RESET
            }
            break;

        case EA_STATE_RESET:
            // Reinicia as variáveis e volta ao estado WAITING_FOR_SIGNAL
            ResetTrading();
            eaState = EA_STATE_WAITING_FOR_SIGNAL; // Aguarda um novo sinal
            break;
    }

    // Verifica se deve operar com base nas regras normais (apenas no estado IN_TRADE)
    if (eaState == EA_STATE_IN_TRADE && spreadOK && purchaseCount < MaxPurchases)
    {
        double nextPurchaseLevel = CalculateNextPurchaseLevel();
        double currentBid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
        double currentAsk = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
        if (StartMode == START_AUTO_BUY || StartMode == START_SIGNAL_SUPPORT || StartMode == START_SIGNAL_MIDPOINT)
        {
            if (currentBid <= nextPurchaseLevel)
            {
                // Verifica se já existem posições abertas no nível de preço
                if (!CheckPendingOrderExists(nextPurchaseLevel) && !CheckOpenPositionExists(nextPurchaseLevel))
                {
                    double lotSize = CalculateNextLotSize();
                    if (isHedgeAccount && UsePendingOrders)
                    {
                         OpenBuyLimitOrder(lotSize, nextPurchaseLevel);
                    }
                    else
                    {
                        OpenBuyPosition(lotSize);
                    }
                }
            }
        }
        else if (StartMode == START_AUTO_SELL || StartMode == START_SIGNAL_RESISTANCE)
        {
            if (currentAsk >= nextPurchaseLevel)
            {
                // Verifica se já existem posições abertas no nível de preço
                if (!CheckPendingOrderExists(nextPurchaseLevel) && !CheckOpenPositionExists(nextPurchaseLevel))
                {
                    double lotSize = CalculateNextLotSize();
                    if (isHedgeAccount && UsePendingOrders)
                    {
                        OpenSellLimitOrder(lotSize, nextPurchaseLevel);
                    }
                    else
                    {
                        OpenSellPosition(lotSize);
                    }
                }
            }
        }
    }

    // Ajusta o TP e SL das posições abertas
    AdjustTPAndSLForAllPositions();

    // Atualiza o painel de resumo
    UpdateSummaryPanel();

    // Verifica e tenta fechar posições opostas por close by
    const int CheckInterval = 1; // Intervalo de verificação em segundos
    if (TimeCurrent() - lastCloseByCheck >= CheckInterval && isHedgeAccount)
    {
        lastCloseByCheck = TimeCurrent();
        CloseOppositePositions();
    }
}
 
Ricardo Rodrigues Lucca #:

Estou olhando o código e achando aquele ELSE dentro switch meio estranho. Outra coisa que parece muito estranha no trecho logo depois do switch tem uma parte que esta dizendo SE for conta hedge e não for para usar ordens pendentes não faça nada tanto na compra e venda. Dai voltando pro código do ELSE dentro do switch tudo faz sentido. Provavelmente, o ELSE era pra estar no estado EA_STATE_IN_TRADE e pra ser feito somente se fosse conta hedge a mercado (mas o teste nao existe lá pra isso).

Acredito que talvez o mais facil é fazer o seguinte:

Existe um input de true ou false se é para usar ordem pendente. Quando está true ele remeter para a função de ordem limit, quando tá false remete pra função de ordem a mercado. 
 
Thiago Lopes #:
Existe um input de true ou false se é para usar ordem pendente. Quando está true ele remeter para a função de ordem limit, quando tá false remete pra função de ordem a mercado. 

Isso não esta escrito no seu codigo desse jeito, vamos simular...

                if (isHedgeAccount)
                    {
                        //B
                        if (UsePendingOrders)
                            OpenSellLimitOrder(lotSize, nextPurchaseLevel);
                    }
                    else
                    {
                        //A
                        OpenSellPosition(lotSize);
                    }

Vamos começar pelo primeiro, caso não é conta hedge. Logo, ele abre a venda a mercado.

Se for conta hedge somente o bloco B vai ser executado e o A não será, não fazendo a venda a mercado.

Porque o código abaixo deveria dar certo?

                if (isHedgeAccount && UsePendingOrders)
                    {
                        OpenSellLimitOrder(lotSize, nextPurchaseLevel); // B
                    }
                    else
                    {
                        OpenSellPosition(lotSize); // A
                    }

Note que aqui só temos um fluxo e não dois para executar. Aqui para a venda limitada ser feita não é criado um bloco exclusivo e se qualquer das duas coisas for false a venda a mercado é feita no bloco A. Mas o bloco B não tem nenhum caminho exclusivo.

 
Ricardo Rodrigues Lucca #:

Isso não esta escrito no seu codigo desse jeito, vamos simular...

Vamos começar pelo primeiro, caso não é conta hedge. Logo, ele abre a venda a mercado.

Se for conta hedge somente o bloco B vai ser executado e o A não será, não fazendo a venda a mercado.

Porque o código abaixo deveria dar certo?

Note que aqui só temos um fluxo e não dois para executar. Aqui para a venda limitada ser feita não é criado um bloco exclusivo e se qualquer das duas coisas for false a venda a mercado é feita no bloco A. Mas o bloco B não tem nenhum caminho exclusivo.

Estou testando sempre em Hedge, vou rodar na NETTING pra fechar essa questão, valeu!!