Como calcular limite diário de ganhos e perdas?

 

Pessoal, bom dia. 


Como calcular limite diário e fazer com que o EA só inicie no dia seguinte?

Limites de ganhos e de perdas

 
marcelodelta:

Pessoal, bom dia. 

Como calcular limite diário e fazer com que o EA só inicie no dia seguinte?

Limites de ganhos e de perdas

Você precisa somar as perdas e ganhos, para isso existem algumas maneiras, talvez a mais simples seria usando OntradeTransaction. E quanto a iniciar no dia seguinte, basta comparar a data atual com alguma  função da própria  linguagem (TimeLocal(), TimeCurrent(), TimeTradeServer())  com uma variável do tipo MqlDateTime que você deve iniciar na OnInit, ai a comparação é simples, dia != dia, você atualiza sua variável.


Para entender as funções de data, sugiro que leia a documentação.

Referência MQL5 - Como usar um algorítimo/automatização para negociação na linguagem para MetaTrader 5
Referência MQL5 - Como usar um algorítimo/automatização para negociação na linguagem para MetaTrader 5
  • www.mql5.com
A MetaQuotes Language 5 (MQL5) é uma linguagem de programação para indicadores técnicos, para robôs de negociação e para aplicativos auxiliares, providenciando automatização da negociação nos mercados financeiros. A MQL5 é uma linguagem moderna de alto nível desenvolvida pela MetaQuotes Software Corp. para a sua própria plataforma de...
 

Rapaz, isso é complicado se vc não manja muito...mas vc tem que pegar os seguintes itens e estudar:

- PositionsTotal() para saber quantas posições estão em abertas

- PositionGetDouble(POSITION_PROFIT)e  : para ver o lucro/Prejuizo da posição atual

- HistoryDealsTotal()...

- HistoryDealGetDouble... para ver o que historico do profit

Em todos vc terá que ver como selecionar um ticket, verificar o simbolo

Estude esses itens que te passei pela documentação do MQL5, pode parecer que não mas é ele bem completo!

sobre selecionar as datas vc tem que usar as estruturas MqlDatetime e HistorySelect


Espero que tenha te dado um norte

 
marcelodelta:

Pessoal, bom dia. 


Como calcular limite diário e fazer com que o EA só inicie no dia seguinte?

Limites de ganhos e de perdas

Marcelo, vou postar aqui o código que utilizo e funciona... mas se rir do meu código não ser aqueles códigos todos bonitinhos, organizados, puxo sua orelha viu... Não é bonitinho mas é útil, e não preciso usar no OnTradeTransation().

//Coloque essa linha abaixo no scopo de inicial (junto as Classes, Instâncias, etc)
datetime start = (datetime) (86400*(((ulong)TimeCurrent())/86400)); //Pega o dia atual apenas. 

// INI: Resultado de todos os Trades do dia - Ruy Hoffmann 29-abr-2020
double ResultadoDia()
  {
   int VTType;
   HistorySelect(start,TimeCurrent());
   ulong _ticket;
   double VTSomatorio=0;
   _ticket = HistoryDealGetTicket(0);
   int deals=HistoryDealsTotal();
   for(int i=0; i<deals; i++)
   {
      _ticket = HistoryDealGetTicket(i);
      VTType=HistoryDealGetInteger(_ticket,DEAL_TYPE);
      if(VTType==0 || VTType==1)
      {
         VTSomatorio=VTSomatorio+HistoryDealGetDouble(_ticket,DEAL_PROFIT);
         if(HistoryDealGetDouble(_ticket,DEAL_PROFIT)<0)
            VVerifySaldoNegativo++;
      }
      
   }
   return VTSomatorio;
  }
// FIM: Resultado de todos os Trades do dia - Ruy Hoffmann 29-abr-2020

//INI: ControleSaldo
bool ControleSaldo()
{
   int VTPerda;

   if(MaxPerdaDia>0)
      VTPerda=MaxPerdaDia*-1;
   else
      VTPerda=MaxPerdaDia;

   if(VTipoControleSaldo==0)
   {
      VSaldoAtual=ResultadoDia();
      if(VSaldoAtual>=fabs(MaxGanhoDia) || VSaldoAtual<=VTPerda || MaxPerdaDia==0)
      {
         Print("Acima do Limite definido por você, então não serão abertas novas Ordens. Acumulado está em R$ ",ResultadoDia());
         return false;
      }
      else
         return true;
   }
   
   if(VTipoControleSaldo==1 && VVerifySaldoNegativo>0)
   {
      Print("Você definiu que na primeira PERDA do dia encerre e não abra novas Ordens");
      return false;
   }
   else
      return true;

   return true;
}
//FIM: ControleSaldo

//Carregue a condicional antes de abrir posição
if(ControleSaldo())
{...}

e lá no topo coloquei para o investidor decidir:

enum TipoControleSaldo 
  {
   Saldo_Acumulado=0,     //
   Primeira_Negativa_Encerra_Dia=1,     //
  };

input TipoControleSaldo VTipoControleSaldo=0; //Tipo de Controle do Saldo Diário
input int MaxGanhoDia="70"; //Acumulado Dia: Bloquear novas Ordens ao ganhar:
input int MaxPerdaDia="35"; //Acumulado Dia: Bloquear novas Ordens ao perder:

 

Obrigado pessoal. 

Fiz um básico iniciando o AccountInfoDouble(ACCOUNT_BALANCE) no OnInit e no OnTick faço o calculo entre o valor de inicio e o valor do tick atual. Assim saberei pelo menos o imite diário

E ligo e desligo o AE manualmente.

 
Ruy Christian Hoffmann:

Marcelo, vou postar aqui o código que utilizo e funciona... mas se rir do meu código não ser aqueles códigos todos bonitinhos, organizados, puxo sua orelha viu... Não é bonitinho mas é útil, e não preciso usar no OnTradeTransation().

e lá no topo coloquei para o investidor decidir:

 



enum TipoControleSaldo 
  {
   Saldo_Acumulado=0,     //
   Primeira_Negativa_Encerra_Dia=1,     //
  };

input TipoControleSaldo VTipoControleSaldo=0; //Tipo de Controle do Saldo Diário
input int MaxGanhoDia="70"; //Acumulado Dia: Bloquear novas Ordens ao ganhar:
input int MaxPerdaDia="35"; //Acumulado Dia: Bloquear novas Ordens ao perder:

//Coloque essa linha abaixo no scopo de inicial (junto as Classes, Instâncias, etc)
datetime start = (datetime) (86400*(((ulong)TimeCurrent())/86400)); //Pega o dia atual apenas.
OniNIT(){ // INI: Resultado de todos os Trades do dia - Ruy Hoffmann 29-abr-2020 double ResultadoDia()   {    int VTType;    HistorySelect(start,TimeCurrent());    ulong _ticket;    double VTSomatorio=0;    _ticket = HistoryDealGetTicket(0);    int deals=HistoryDealsTotal();    for(int i=0; i<deals; i++)    {       _ticket = HistoryDealGetTicket(i);       VTType=HistoryDealGetInteger(_ticket,DEAL_TYPE);       if(VTType==0 || VTType==1)       {          VTSomatorio=VTSomatorio+HistoryDealGetDouble(_ticket,DEAL_PROFIT);          if(HistoryDealGetDouble(_ticket,DEAL_PROFIT)<0)             VVerifySaldoNegativo++;       }           }    return VTSomatorio;   } // FIM: Resultado de todos os Trades do dia - Ruy Hoffmann 29-abr-2020 } On Tick(){
//Carregue a condicional antes de abrir posição
if(ControleSaldo())
{...}
} //INI: ControleSaldo bool ControleSaldo() {    int VTPerda;    if(MaxPerdaDia>0)       VTPerda=MaxPerdaDia*-1;    else       VTPerda=MaxPerdaDia;    if(VTipoControleSaldo==0)    {       VSaldoAtual=ResultadoDia();       if(VSaldoAtual>=fabs(MaxGanhoDia) || VSaldoAtual<=VTPerda || MaxPerdaDia==0)       {          Print("Acima do Limite definido por você, então não serão abertas novas Ordens. Acumulado está em R$ ",ResultadoDia());          return false;       }       else          return true;    }       if(VTipoControleSaldo==1 && VVerifySaldoNegativo>0)    {       Print("Você definiu que na primeira PERDA do dia encerre e não abra novas Ordens");       return false;    }    else       return true;    return true; } //FIM: ControleSaldo

Boa noite, esse codigou seria dessa forma que eu coloquei as ordens, porque não estou conseguindo, esta dando erro??


agradeço muito se puder me ajudar


abs

 
RAFAEL DITTRICH:

Boa noite, esse codigou seria dessa forma que eu coloquei as ordens, porque não estou conseguindo, esta dando erro??


agradeço muito se puder me ajudar


abs

Rafael, não... infelizmente tá meio bagunçado a ordem das coisas que você colocou...

Entenda esse exemplo duas pessoas distintas perguntando sobre um problema em seu veículo:

a) Estou com problemas no meio freio, ao pressionar o pedal ele falha etc etc etc...;

b) Estou com poblemas no meu freio. Alguém sabe me informar desses 3 pedais qual é o freio?...

Então, olhando o acima, dá para identificar que a pessoa "b" não sabe conduzir um veículo e nada adiantará explicar qual é o pedal correto.

Infelizmente Rafael sua pergunta ainda está no patamar do exemplo acima "b". Você precisa ANTES de se aventurar na construção dos códigos é aprender primeiro a estrutura de programação em sí no MQL5, ou seja, suas seções, como elas funcionam, como devem ocorrer as chamadas, etc. 

Isso que estou te sinalizando não é uma crítica, é algo com a intenção de te ajudar, pois se você colocar um robô no mercado sem saber exatamente cada detalhe dele e como ele está funcionando, ou seja, um robô que é "copiado/colado" funções sem você saber exatamente o que está ocorrendo, isso vai lhe causar transtornos e perdas financeiras enormes. Já presenciei um investidor perder 90 mil reais em aproximadamente 1 minuto e meio por falha de programação no robô, não deu tempo nem dele "processar" na cabeça dele o que estava ocorrendo. E eu mesmo já perdi algumas vezes quantias menores por falhas minhas de programação.

Então, sugestão, vá do zero mesmo, faça aulas, literatura, biblioteca do fórum, começe exercitando com scripts, indicadores, depois pule para os EA´s, nesse percurso você já vai estar usando bastante backtest e conta demo, enfim, chegará um tempo que você vai olhar para o meu código acima e saberá que precisar copiar/colar isso no OnIni, aquilo no OnTick, e assim sucessivamente.

Abraços e boa sorte.

 
Ruy Christian Hoffmann:

Marcelo, vou postar aqui o código que utilizo e funciona... mas se rir do meu código não ser aqueles códigos todos bonitinhos, organizados, puxo sua orelha viu... Não é bonitinho mas é útil, e não preciso usar no OnTradeTransation().

e lá no topo coloquei para o investidor decidir:

Olá, Ruy, 

Eu estava tentando utilizar a função  HistorySelect, mas não estava conseguindo fazer ela acessar somente o dia atual, vi no seu código que vc faz essas conversões abaixo e que deste jeito dá certo, mas não consegui entender porquê. Percebi que o 86400 é quantidade de segundos em um dia, teria como explicar pq é necessário fazer essas conversões?

datetime start = (datetime) (86400*(((ulong)TimeCurrent())/86400)); //Pega o dia atual apenas. 
Desde já agradeço, abs
 
Laíza Coelho:

Olá, Ruy, 

Eu estava tentando utilizar a função  HistorySelect, mas não estava conseguindo fazer ela acessar somente o dia atual, vi no seu código que vc faz essas conversões abaixo e que deste jeito dá certo, mas não consegui entender porquê. Percebi que o 86400 é quantidade de segundos em um dia, teria como explicar pq é necessário fazer essas conversões?

Desde já agradeço, abs

Olá Laíza,

Não fui eu que fiz esse código também copiei do nosso amigo @Jonathan Evans, então, pelo que entendi ele faz um conversão do horário atual e coloca em segundos para chegar a quantidade máxima de segundos de um dia, assim a variável start sempre estará amarmazenado o dia atual apenas.

Ela funciona. Apesar de pequena a danadinha é difícil mesmo de interpretar.

Abraços,

 
Ruy Christian Hoffmann:

...

Essa conta serve para pegar o horário 00:00:00 de hoje, então como a pesquisa usando a função HistorySelect usa uma data inicial e uma final, vc garante que está pegando sempre "hoje" entra 00:00:00 ate hora atual...

uma forma mais simplificada de fazer isso seria assim..

 HistorySelect(TimeCurrent() - (TimeCurrent()%86400), TimeCurrent());

sem a necessidade de criar uma variável para isso;

 
input PerdaMaxima = 0;
input GanhoMaximo = 0;

// Adicionar esta função a algum manipulador de eventos 

double Controle ()
  {
  
   
   double resultado =0;
   double soma = 0;
   double profit = 0;

  //Lógica para o resultado do dia
   string CurrDate = TimeToString(TimeCurrent(), TIME_DATE);

   if (HistorySelect(StringToTime(CurrDate), TimeCurrent()))
   for (int i = HistoryDealsTotal(); i >= 0; i--) 
     {
      const ulong Ticket = HistoryDealGetTicket(i);
      if((HistoryDealGetInteger(Ticket, DEAL_MAGIC) == MagicNumber) && (HistoryDealGetString(Ticket, DEAL_SYMBOL) == _Symbol))
         profit += HistoryDealGetDouble(Ticket, DEAL_PROFIT);
     }
   
     
       
  
    // Lógica para o resultado do trade em aberto

   for(int i=PositionsTotal()-1; i>=0; i--) // Vare o histórico
     {
      string simbolo = PositionGetSymbol(i); // Verifica a posição no Simbolo
      ulong magic = PositionGetInteger(POSITION_MAGIC);  // cria a variável para o numero magico e define ele 
      if(simbolo==_Symbol && magic==MagicNumber )  // Verifica o número magico se ele é igual ao do robô que enviou a ordem
       resultado += PositionGetDouble(POSITION_PROFIT); // Soma todas as posições
      }
    
     //somatório do resultado do dia + trade em aberto

      soma = resultado + profit;
   
   
   return(soma);
     
  }

// Em sua lógica operacional adiciona

if(Controle() <= PerdaMaxima || Controle() >= GanhoMaximo)
  {
   //Lógica de fechamento de posições..

  }	

Apenas uma pequena ideia...

Razão: