Especialistas: eaBreakeven

 

eaBreakeven:

Expert Advisor que move o stop-loss da posição para o break-even.

Autor: Alexey Lopatin

 

Erros:

  1. O loop deve ser revertido.
  2. PositionSelect deve ser removido do código.

 
fxsaber:

Erros:

  1. O loop deve ser invertido.
  2. PositionSelect deve ser removido do código.


Argumentos para o estúdio.

 
Alexey Lopatin:

Argumentos, por favor.

É preciso muito tempo para explicar sobre o loop. E PositionSelect é desnecessário após PositionGetSymbol, porque a seleção já foi feita, se LastError estiver OK. Mas o PositionSelect também é ruim em uma conta de hedge.

A melhor opção é sempre usar essa opção em vez das mencionadas acima.

if (PositionGetTicket(i))


Além disso, o latest_price para qualquer direção de posição pode ser obtido por meio de POSITION_PRICE_CURRENT.


E essa condição

if(latest_price.bid-price_open>=Breakeven*point && new_stoploss>stoploss && latest_price.bid-new_stoploss>stop_level)

pode ser acionada mesmo em casos (devido a peculiaridades duplas) em que nada precisa ser modificado.


Em geral, você pode reescrevê-lo de forma um pouco mais compacta e sem erros. Eu faria isso no estilo MT4.

#include <MT4Orders.mqh>     // https://www.mql5.com/pt/code/16006
#include <Price_Compare.mqh> // https://www.mql5.com/pt/code/16169

input int    Breakeven           = 15;           //Breakeven em pontos
input int    Distance            = 5;            /Distância de equilíbrio em pontos do preço de abertura da posição
input int    MagicNumber         = 16112017;     /Número mágico
input bool   EnableSound         = true;         //Ativar/desativar a reprodução de som quando o ponto de equilíbrio for definido
input string SoundFile           = "alert1.wav"; /Nome do arquivo de som

void OnTick()
{
  DoBreakeven();
}

double GetNewStopLoss()
{
  const double point = SymbolInfoDouble(OrderSymbol(), SYMBOL_POINT);  
  const double stop_level = SymbolInfoInteger(OrderSymbol(), SYMBOL_TRADE_STOPS_LEVEL) * point;
  
  const double price_open = OrderOpenPrice();
  const double latest_price = OrderClosePrice();  
  const double stoploss = OrderStopLoss();

  double new_stoploss = 0;
  
  //--- Mova o stop-loss para o preço de equilíbrio + distância, se o lucro da posição for maior que os pontos de equilíbrio 
  return(((OrderType() == OP_BUY)  && (CP(latest_price - price_open, point) >= Breakeven * point) &&
                                      (CP(new_stoploss = price_open + Distance * point, point) > stoploss) &&
                                      (CP(latest_price - new_stoploss, point) > stop_level)) ||
         ((OrderType() == OP_SELL) && (CP(price_open - latest_price, point) >= Breakeven * point) &&
                                      ((CP(new_stoploss = price_open - Distance * point, point) < stoploss) || !stoploss) &&
                                      (CP(new_stoploss - latest_price, point) > stop_level))
         ? NormalizeDouble(new_stoploss, (int)SymbolInfoInteger(OrderSymbol(), SYMBOL_DIGITS)) : 0);
}

void DoBreakeven()
{
//Se o ponto de equilíbrio for negativo, desative a função de ponto de equilíbrio
  if (Breakeven >= 0)      
  //Loop para posições
    for (int i = OrdersTotal() - 1; i >= 0; i--)
      if (OrderSelect(i, SELECT_BY_POS) && (OrderType() <= OP_SELL) && (!MagicNumber || (OrderMagicNumber() == MagicNumber)))
      {
        const double new_stoploss = GetNewStopLoss();
        
        if (new_stoploss)      
        {
          if (!OrderModify(OrderTicket(), OrderOpenPrice(), new_stoploss, OrderTakeProfit(), OrderExpiration()))
            Print(GetLastError());
          else if(EnableSound)
            PlaySound(SoundFile);
        }
      }
}
 

Obrigado pela resposta com o exemplo. Sempre fico feliz em aprender algo novo para mim.

Mas seria interessante saber por que o PositionSelect é ruim em uma conta de hedge?

 
Alexey Lopatin:

Mas aqui seria interessante saber por que PositionSelect na contagem de hash é ruim?

Porque o símbolo não define a posição de forma exclusiva.

 
caolyhuynh:
 
5000000
 
caolyhuynh: