[Dúvida] Problemas com PositionClosePartial

 

Senhoras e senhores, bom dia, boa tarde ou boa noite! Espero que todos estejam bem!


Venho por meio deste tópico, manifestar mais uma de minhas dúvidas. Desta vez estou tentando incrementar meu filhote com um alvo parcial. O take profit é de 90 pontos (mini-indice), e o alvo parcial seria metade do TP total, ou seja, 45 pontos.

Através de meus estudos e fuçadas nos fóruns e diversas tentativas serem realizadas, cheguei ao seguinte código: 


//=====================================TAKE PROFIT PARCIAL=====================================


   double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID);
     bid = NormalizeDouble(bid, _Digits);
     
     double ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
     ask = NormalizeDouble(ask, _Digits);
          
     for(int i = PositionsTotal()-1; i>=0; i--)
         {
            string symbol = PositionGetSymbol(i);
            ulong magic = PositionGetInteger(POSITION_MAGIC);
               if(symbol == _Symbol && magic == magic_number)
                  {
                     
                     double precoEntrada = PositionGetDouble(POSITION_PRICE_OPEN);
                     ulong ticket = PositionGetInteger(POSITION_TICKET);
                     double posVolume = PositionGetDouble(POSITION_VOLUME);
                     ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
                     
                     
                        if(posVolume == Contratos){  
                        
                           double Volume_close = posVolume * Porcentagem_Parcial;
                           Volume_close = NormalizeDouble(Volume_close, 2);
                        
                     if(posType == POSITION_TYPE_BUY){
                     
                                         
                     if(bid >= precoEntrada + Take_Profit_Parcial * _Point){
                     
                           Print("Teste: já alcançou metade do alvo!");
                                            
                           if(Trade.PositionClosePartial(_Symbol, Volume_close, 0)){
                           
                           Print("Pos ", ticket, " foi fechado porque a gente programou pra que acontecesse!");
                           
                              }                           
                           }
                        }
                     

                     else if(posType == POSITION_TYPE_SELL){

                     
                     if(ask <= precoEntrada - Take_Profit_Parcial * _Point){
                     
                         Print("Teste: já alcançou metade do alvo!");
                           
                         if(Trade.PositionClosePartial(_Symbol, Volume_close, 0)){
                         
                         Print("Pos ", ticket, " foi fechado porque a gente programou pra que acontecesse!");
                         
                              }
                           }
                        }
                        
                        
                     }
                  }
              }


Percebam que: dentro de ambos os if's, tanto de compra (if(bid >= precoEntrada + Take_Profit_Parcial * _Point) quanto de venda (if(ask <= precoEntrada - Take_Profit_Parcial * _Point), coloquei um Print para que aparecesse na tela o seguinte: "Teste: já alcançou metade do alvo!", para que eu pudesse verificar se de fato estava conseguindo identificar essa diferença de 45 pontos do momento da entrada. Para minha surpresa, deu tudo certo! Estou conseguindo identificar quando uma posição é realizada e a mesma já possui 45 pontos de lucro. Segue a imagem abaixo, exemplificando tanto uma compra quanto uma venda (teste realizado no simulador ao vivo, 21/11/2022).



Apesar do texto aparecer na aba expert, o código que segue em seguinte, "if(Trade.PositionClosePartial(_Symbol, Volume_close, 0))", acaba por ser ignorado pelo robô e acaba não sendo lido/executado. Já tentei retira-lo do if, tentei substituir Volume_close (cujo valor seria o total de contratos, 10, dividido por 50% do valor, no caso, 5 contratos) por um número inteiro, mas infelizmente nada acontece. Tentei também, ao invés de utilizar o _Symbol, utilizar o Ticket da posição, porém também sem sucesso.

Cheguei a procurar nos fóruns e vi que outras pessoas também tinham alguns problemas com esse código, porém não encontrei solução alguma. Agradeço caso alguma alma possa me auxiliar com meu problema e dar-me uma luz de conhecimento!


Grande abraço a todos, obrigado pela atenção e pelo carinho.


Christian Alves

Princípios gerais - Operações comerciais - Ajuda para o MetaTrader 5
Princípios gerais - Operações comerciais - Ajuda para o MetaTrader 5
  • www.metatrader5.com
Antes de começar a estudar as funções da plataforma, você deve compreender claramente todos os termos e funç...
 

Olá, Christian, boa tarde!!


Primeira tentativa: 😁


1. Inclua a função abaixo no seu código:

//+--------------------------------------------------------------------------------------------------------------------+
//| This function normalizes the volume according to the minimum volume change step                                    |
//+--------------------------------------------------------------------------------------------------------------------+
double NormalizeVolume(double Lot)
  {
//--- Minimal and maximal allowed volume for trade operations
   double LotMin  = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
   double LotMax  = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
//--- Get minimal step of volume changing
   double LotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);

//--- Checks volume size
   if(Lot < LotMin)
     {
      return(LotMin);
     }
   if(Lot > LotMax)
     {
      return(LotMax);
     }

//--- Normalizes the volume
   Lot = LotMin + MathFloor((Lot - LotMin) / LotStep) * LotStep;
   Lot = MathMin(LotMax, Lot);

//--- Normalized volume
   return(NormalizeDouble(Lot, 2));
  }

 


2. Substitua:

   double Volume_close = posVolume * Porcentagem_Parcial;
   Volume_close = NormalizeDouble(Volume_close, 2);

... Por:

   double Volume_close = NormalizeVolume(posVolume * Porcentagem_Parcial);



3. Substitua:

   if(Trade.PositionClosePartial(_Symbol, Volume_close, 0))

... Por:

   if(Trade.PositionClosePartial(ticket, Volume_close))



Depois, avise se mudou alguma coisa e possíveis mensagens de erro... 😊



EDIT.1: Após a função Trade.PositionClosePartial(), lembre-se de colocar um Print do Trade.ResultRetcode() para ver o que está acontecendo na execução da função, o que ela está retornando...

Ex.:

   if(!Trade.PositionClosePartial(ticket, Volume_close))
     {
      Print(Trade.ResultRetcode(), " ", Trade.ResultRetcodeDescription());
      // . . .
     }
 
Vinicius de Oliveira #:

Olá, Christian, boa tarde!!


Primeira tentativa: 😁


1. Inclua a função abaixo no seu código:

 


2. Substitua:

... Por:



3. Substitua:

... Por:



Depois, avise se mudou alguma coisa e possíveis mensagens de erro... 😊



EDIT.1: Após a função Trade.PositionClosePartial(), lembre-se de colocar um Print do Trade.ResultRetcode() para ver o que está acontecendo na execução da função, o que ela está retornando...

Ex.:


Bom dia Vini! Tudo certo por ai? Espero que sim!

Primeiramente lhe agradeço por responder e mais uma vez auxiliar em meu processo de aprendizagem! Realizei todas alterações conforme você pontuou uma a uma, infelizmente o robô continua somente a fechar a operação no take profit de 90 pontos, com todos os contratos.


Em contrapartida, como anteriormente, ele ainda segue identificando que o valor atual do preço alcançou metade do alvo desejado, no caso o alvo do take profit parcial. E como código do ResultRetCode, ele retorna 10009, "Solicitação Concluída". A mensagem e o código foram retornados tanto na compra quanto na venda.


 



Tenha um ótimo dia por ai, aguardo seu retorno!


Grande abraço,

Christian Alves

 

Bom dia, Christian!!


Pergunta básica que eu esqueci: sua conta é Hedging ou Netting? Se for Netting, dê uma olhada nesse tópico:

Fórum de negociação, sistemas de negociação automatizados e testes de estratégias de negociação

Realização Parcial

Rogerio Giannetti Torres, 2020.09.06 18:45

Juliano

Faltou testar o retorno de  trade.PositionClosePartial(PositionGetTicket(0),contratos);

O problema não é só a falta do parm de derrapagem, o problema é a função que testa se está em modo headging, se for outro modo de negociação  dá erro.

(*) Tinha comentado que a documentação estava errada, foi um equivoco meu, a documentação está correta, a função é usada somente para o modo cobertura (hedging)!

Fórum de negociação, sistemas de negociação automatizados e testes de estratégias de negociação

Realização Parcial

Jonathan Pereira, 2020.09.06 21:33

Seguindo o que o Rogério disse, vc deve fazer algo como:


//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   ENUM_ACCOUNT_MARGIN_MODE mode=(ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   if(mode!=ACCOUNT_MARGIN_MODE_RETAIL_HEDGING)
     {
      if(liga_parcial == SIM && PositionSelect(_Symbol) && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY && num_lots>1 && contratos<num_lots)
        {
         double preco_entrada = PositionGetDouble(POSITION_PRICE_OPEN);
         double preco_sl      = PositionGetDouble(POSITION_SL);
         double preco_tp      = PositionGetDouble(POSITION_TP);
         double preco_parcial = preco_entrada + pont_parcial;

         if(tick.last >= preco_parcial && !pa_ativado_c)
           {
            trade.Sell(contratos);
            trade.PositionModify(PositionGetTicket(0),preco_entrada - pont_parcial + ganho,preco_tp);
            pa_ativado_c = true;
            Print("Realização Parcial = ", preco_parcial);
           }
        }
     }

   if(mode==ACCOUNT_MARGIN_MODE_RETAIL_HEDGING)
     {
      if(liga_parcial == SIM && PositionSelect(_Symbol) && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY && num_lots>1 && contratos<num_lots)
        {
         double preco_entrada = PositionGetDouble(POSITION_PRICE_OPEN);
         double preco_sl      = PositionGetDouble(POSITION_SL);
         double preco_tp      = PositionGetDouble(POSITION_TP);
         double preco_parcial = preco_entrada + pont_parcial;

         if(tick.last >= preco_parcial && !pa_ativado_c)
           {
            trade.PositionClosePartial(PositionGetTicket(0),contratos, 50);
            trade.PositionModify(PositionGetTicket(0),preco_entrada - pont_parcial + ganho,preco_tp);
            pa_ativado_c = true;
            Print("Realização Parcial = ", preco_parcial);
           }
        }
     }
//+------------------------------------------------------------------+
   

 
Vinicius de Oliveira #:

Bom dia, Christian!!


Pergunta básica que eu esqueci: sua conta é Hedging ou Netting? Se for Netting, dê uma olhada nesse tópico:



Minha conta é Netting! Dei uma olhada no tópico e pelo que entendi a realização parcial funciona apenas em Hedging, certo? Tentei realizar algumas alterações nas minhas linhas de código, incluindo: 


 if(posVolume == Contratos){  
                        
                         ENUM_ACCOUNT_MARGIN_MODE mode=(ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE);
                        
                         if(mode!=ACCOUNT_MARGIN_MODE_RETAIL_HEDGING){
                        
                        double Volume_close = NormalizeVolume(posVolume * Porcentagem_Parcial);
                        
                     if(posType == POSITION_TYPE_BUY){

                        ...... }

                     else if(posType == POSITION_TYPE_SELL){
                        ...... }


Não sei se coloquei o código no local ideal, mas quando tentei fazer igual ao do Jonathan, que postou o código neste outro tópico, não foi possível reconhecer o "Mode" quando inclua o código em OnInit, ai resolvi coloca-lo dentro da própria estrutura do take profit parcial. O código foi lido normalmente, o robô reconheceu o alvo parcial mais uma vez e retornou novamente o código 10009, mas sem executar de fato o tp_parcial, apenas finalizando a operação com o take profit com valor/contratos cheios. Até havia pensado em encaminhar outra foto do log, mas ele segue igual ao que enviei anteriormente...:

"Teste: já alcançou metade do alvo!"
"10009 done"

 

Consegui fazer com que metade dos contratos fossem fechados Vini! Não havia prestado atenção na questão da linha grifada em roxo, alterei o Trade.PositionClosePartial por apenas Trade.Sell/Trade.Buy como demonstrado quando a conta é diferente de Hedging! Também coloquei Segue como foi possível realizar o take profit parcial:

if(bid >= precoEntrada + Take_Profit_Parcial * _Point){
                     
                           Print("Teste: já alcançou metade do alvo!");
                                            
                           if(Trade.Sell(Volume_close)){
                           
                           Print("Pos ", ticket, " foi fechado porque a gente programou pra que acontecesse!");
                           
                           }
                }


Percebi aqui nos backtests que algumas vezes ele realizava o take profit parcial e outras não, acredito que preciso aprimorar meus códigos de obtenção de preços ao vivo através do MQLTick, trabalharei em cima disso agora! Muito obrigado pela ajuda até então Vini, grande abraço!


Christian Alves

 

Opa, bom que está dando certo, Christian!!


Rogerio GiannettiJonathan Pereira conhecem tudo dessa MQL5.


Grande abraço e boa tarde aí pra você!!

 

Fala amigo, na verdade quando sua conta é netting é mais facil vc fazer uma operação inversa e na conta hedge vc faz uma parcial do jeito que está fazendo, ou seja,

se vc estiver em uma operação de compra e queira fazer uma parcial na conta netting é só então fazer uma operação de venda apenas ajustando o tamanho do lote, o mesmo funcionamento seria para quando vc for fazer uma reversão, que é só colocar mais lotes do que a que ja possui em aberto