Ajuda com Função de Take Profit
Boa tarde, pessoal da comunidade.
Estou desenvolvendo um EA que negocia exclusivamente o par EURUSD. A estratégia consiste em abrir uma nova posição para fazer o preço médio sempre que o preço se mover contra a posição atual. Esta parte está funcionando perfeitamente.
No entanto, estou enfrentando dificuldades com a função que posiciona os take profits em um único nível. Para ilustrar melhor, vou descrever um cenário:
Suponha que eu tenha posições de compra abertas nas seguintes cotações:
- 1.08500
- 1.08000
- 1.07500
Essas posições estão com os seguintes lotes:
- 0.01
- 0.01
- 0.02
A função que estou desenvolvendo (abaixo) deve ajustar o take profit dessas posições de modo que, quando o alvo for atingido, o lucro seja X (multipler) vezes maior do que a soma das perdas das posições que estão negativas. A maneira como a função está atualmente, ela retorna o erro [invalid stops].
Infelizmente, a minha função não está alcançando esse objetivo. Por isso, venho até vocês em busca de ajuda para ajustar a lógica e garantir que esse objetivo seja atingido.
Desde já, agradeço a colaboração de todos.
Obrigado!
Eu começaria revisando NormalizeDoubles() se realmente esta normalizando como deveria e também se esta sendo obdecido o nível de STOP_LEVEL do ativo. Também daria atenção ai a forma como ta lidando com o totalloss já que ele permite valores negativos e isso não parece ser o desejado.
Eu começaria revisando NormalizeDoubles() se realmente esta normalizando como deveria e também se esta sendo obdecido o nível de STOP_LEVEL do ativo. Também daria atenção ai a forma como ta lidando com o totalloss já que ele permite valores negativos e isso não parece ser o desejado.
Boa noite @Ricardo Rodrigues Lucca, primeiramente obrigado pela ajuda.
A função NormalizeDoubles() funciona como desejado, fiz alguns ajustes na função CalculateTakeProfit e o problema [invalid stops] foi resolvido. Também me atentei ao problema de valores negativos.
O problema agora é porque o Take Profit está sendo colocado um pouco acima do valor desejado. Por exemplo, tenho duas posições que abrem na taxa abaixo com seus respectivos lotes.
- 1.08801 / 0.02
- 1.07596 / 0.02
O Take Profit de ambas as negociações deveria ficar em 1.08498, mas a função está colocando em 1.08655. Isso se repete para todas as demais situações onde é feito o preço médio.
Abaixo envio as partes da função que fiz modificações.
//--- void CalculateTakeProfit(long type, double multipler) { // Continua o mesmo código... //--- for(int i = total - 1; i >= 0; i--) { // Continua o mesmo código... //--- if(type == BUY && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) { weightedPriceSum += PositionGetDouble(POSITION_PRICE_OPEN) * PositionGetDouble(POSITION_VOLUME); totalLots += PositionGetDouble(POSITION_VOLUME); double profit = PositionGetDouble(POSITION_PROFIT); if(profit < 0) totalLoss += profit; } } //--- if(buys > 0 && weightedPriceSum != 0) { AveragePrice = weightedPriceSum / totalLots; double desiredProfit = -totalLoss * multipler; double desiredPips = desiredProfit / (totalLots * 100000); buyTarget = NormalizeDoubles(AveragePrice + desiredPips); } //--- for(int i = total - 1; i >= 0; i--) { // Continua o mesmo código... } }
Mais uma vez obrigado pela ajuda.
Boa noite, Jeovane!! Nesse seu exemplo acima, onde você fala que o TP deveria ficar em 1.08498, qual é o preço atual (BID) pra eu fazer aqui a minha simulação?
Boa noite, Jeovane!! Nesse seu exemplo acima, onde você fala que o TP deveria ficar em 1.08498, qual é o preço atual (BID) pra eu fazer aqui a minha simulação?
Veja, pela simulação (manual) que fiz aqui, a função a seguir, sugerida pelo ChatGPT (com alguns ajustes), calcularia o TP de 1.09404 (aproximadamente) para o seu exemplo, mas, pelo que entendi, esse seria o TP correto (não 1.08498, como você sugeriu)...
Teste realizado com os dados do seu exemplo
void OnStart() { double curr_loss = 0.0, profit1 = 0.0, profit2 = 0.0; OrderCalcProfit(ORDER_TYPE_BUY, "EURUSD", 0.02, 1.08801, 1.07596, curr_loss); OrderCalcProfit(ORDER_TYPE_BUY, "EURUSD", 0.02, 1.08801, 1.09404, profit1); OrderCalcProfit(ORDER_TYPE_BUY, "EURUSD", 0.02, 1.07596, 1.09404, profit2); Print(curr_loss, " - ", profit1 + profit2); }

Função sugerida pelo ChatGPT (com ajustes)
double CalculateAverageTP(int type, double multiplier) { double total_volume = 0; double total_loss = 0; double tp_price = 0; double tick_size = 0.0; if(!SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE, tick_size)) { Print(__FUNCTION__, " - Error getting the SYMBOL_TRADE_TICK_SIZE: ", GetLastError(), " - ", _Symbol); return 0.0; } for(int i = PositionsTotal() - 1; i >= 0; i --) { if(PositionGetTicket(i) != 0) { if(PositionGetInteger(POSITION_TYPE) == type) { double price_open = PositionGetDouble(POSITION_PRICE_OPEN); double volume = PositionGetDouble(POSITION_VOLUME); double profit = PositionGetDouble(POSITION_PROFIT); total_volume += volume; if(profit < 0.0) { total_loss += MathAbs(profit); } tp_price += price_open * volume; } } } if(total_volume == 0) { return 0.0; // No positions to calculate } tp_price /= total_volume; double adjusted_tp = tp_price + (multiplier * total_loss / total_volume * tick_size); return adjusted_tp; }
... Faça os testes/ajustes necessário aí no seu sistema... Se não funcionar, a culpa é do ChatGPT... Agora, se der tudo certo... O mérito é dele também. 😊👍
Veja, pela simulação (manual) que fiz aqui, a função a seguir, sugerida pelo ChatGPT (com alguns ajustes), calcularia o TP de 1.09404 (aproximadamente) para o seu exemplo, mas, pelo que entendi, esse seria o TP correto (não 1.08498, como você sugeriu)...
Teste realizado com os dados do seu exemplo
Função sugerida pelo ChatGPT (com ajustes)
... Faça os testes/ajustes necessário aí no seu sistema... Se não funcionar, a culpa é do ChatGPT... Agora, se der tudo certo... O mérito é dele também. 😊👍
Bom dia,
O ChatGPT me levou ao mesmo resultado de uma forma mais elegante (até adotei rs).
Para efeitos de testes fiz uma função que fecha os trades quando o lucros das posições positivas é X vezes maior do que as negativas.
O preço onde as posições são fechadas é diferente do TP. Por isso afirmo que o TP deveria ficar em 1.08498 invés de 1.08655.
Abaixo a função que faz isso. Essa função na prática (mercado real) não é muito boa, pois se o mercado tiver em forte oscilação as posições abertas acabam sendo fechadas em taxas diferentes. Por isso a "necessidade" de colocar todos os TPs em uma só taxa.
//--- bool GetProfitPositions(long type, double multiplier) { double profit = 0; double sumGains = 0; double sumLosses = 0; int total = PositionsTotal(); for(int i = total - 1; i >= 0; i--) { if(!PositionSelectByTicket(PositionGetTicket(i))) continue; if(PositionGetInteger(POSITION_MAGIC) != MagicNumber || (_Symbol != "" && PositionGetSymbol(i) != _Symbol)) continue; if(PositionGetInteger(POSITION_TYPE) != type) continue; profit = PositionGetDouble(POSITION_PROFIT); if(profit > 0) sumGains += profit; else sumLosses += profit * (-1); } return sumGains > (sumLosses * multiplier); }
Você continua "afirmando", mas eu discordei e reproduzi o meu entendimento através de testes disponibilizados no fórum... Por favor, se você não concorda com o que demonstrei através dos testes disponibilizados, apresente a sua "afirmação" de forma que possa ser reproduzida... Com relação ao código não ser "muito bom", "elegante", não está pronto para o mercado real, essa não é a finalidade no fórum... O objetivo aqui seria sugerir formas, alternativas para você testar e fazer melhorias no SEU código para conseguir chegar aos resultados que deseja... Teste a função que sugeri, apresente os resultados, e explique o que está errado... Boa sorte aí!! 😊
Apenas 2 brevíssimas (mas, considero, importantes) recomendações antes de utilizar os códigos acima em mercado real:
1. A utilização de PositionSelectByTicket(PositionGetTicket(i)) é desnecessária, pois a PositionGetTicket(i) já seleciona a posição a ser trabalhada posteriormente;
2. Todas essas funções de gerenciamento de posições [PositionGetTicket(), PositionGetString(), PositionGetDouble(), PositionGetInteger(), ...] podem retornar erros que devem ser verificados/trabalhados antes de seguir com a execução do código.
Você continua "afirmando", mas eu discordei e reproduzi o meu entendimento através de testes disponibilizados no fórum... Por favor, se você não concorda com o que demonstrei através dos testes disponibilizados, apresente a sua "afirmação" de forma que possa ser reproduzida... Com relação ao código não ser "muito bom", "elegante", não está pronto para o mercado real, essa não é a finalidade no fórum... O objetivo aqui seria sugerir formas, alternativas para você testar e fazer melhorias no SEU código para conseguir chegar aos resultados que deseja... Teste a função que sugeri, apresente os resultados, e explique o que está errado... Boa sorte aí!! 😊
Bom dia!
Você está absolutamente correto. Para sair do campo teórico, envio em anexo um EA demonstrativo que desenvolvi.
Segue a descrição das principais funções que merecem atenção:
-
CalculateTakeProfit: Responsável por definir os take profits de maneira que, quando atingidos, o lucro das posições positivas seja X (multipler) vezes maior do que a soma das posições negativas.
-
GetProfitPositions: Retorna um valor booleano indicando se as posições abertas têm lucro X (multipler) vezes maior do que as perdas das posições negativas.
-
CloseAllForce: Fecha automaticamente as posições se a função GetProfitPositions retornar TRUE. Para desativá-la, basta alterar o valor da variável ClosePositions para FALSE.
-
Martingale: Além de fazer o médio das posições negativas, também chama a função CalculateTakeProfit para ajustar o take profit das posições abertas. Essa verificação/mudança ocorre a cada 1 minuto, conforme definido na função OnTick.
No print abaixo, pode-se observar que a função CloseAllForce fecha as posições antes do Take Profit setado pela função CalculateTakeProfit. Por isso, tenho insistido que os takes estão sendo definidos em um local "errado". A razão pela qual não quero usar a função CloseAllForce no mercado real já foi mencionada anteriormente.
A estratégia do EA é apenas para efeito demonstrativo. Sei que não é o propósito, mas abaixo é apresentado o resultado do backtesting entre 01.01.2020 e 01.01.2024. Caso alguém queira aprimorá-la, fique à vontade.
Mais uma vez obrigado pela disponibilidade em ajudar.
Bom dia!
Você está absolutamente correto. Para sair do campo teórico, envio em anexo um EA demonstrativo que desenvolvi.
Segue a descrição das principais funções que merecem atenção:
-
CalculateTakeProfit: Responsável por definir os take profits de maneira que, quando atingidos, o lucro das posições positivas seja X (multipler) vezes maior do que a soma das posições negativas.
-
GetProfitPositions: Retorna um valor booleano indicando se as posições abertas têm lucro X (multipler) vezes maior do que as perdas das posições negativas.
-
CloseAllForce: Fecha automaticamente as posições se a função GetProfitPositions retornar TRUE. Para desativá-la, basta alterar o valor da variável ClosePositions para FALSE.
-
Martingale: Além de fazer o médio das posições negativas, também chama a função CalculateTakeProfit para ajustar o take profit das posições abertas. Essa verificação/mudança ocorre a cada 1 minuto, conforme definido na função OnTick.
No print abaixo, pode-se observar que a função CloseAllForce fecha as posições antes do Take Profit setado pela função CalculateTakeProfit. Por isso, tenho insistido que os takes estão sendo definidos em um local "errado". A razão pela qual não quero usar a função CloseAllForce no mercado real já foi mencionada anteriormente.
A estratégia do EA é apenas para efeito demonstrativo. Sei que não é o propósito, mas abaixo é apresentado o resultado do backtesting entre 01.01.2020 e 01.01.2024. Caso alguém queira aprimorá-la, fique à vontade.
Mais uma vez obrigado pela disponibilidade em ajudar.
NormalizeDoubles nesse ultimo EA está claramente errado. Stop level só é usado no momento de colocar a ordem. O código supostamente modificado estava intocado. Mas não é bem o ponto.
Muda a ordem no OnTick para o CloseAll ser feito depois da martingale e da open alguma coisa. Me parece que não esta tendo chance desse código executar já que as posições foram encerradas.


Boa tarde, pessoal da comunidade.
Estou desenvolvendo um EA que negocia exclusivamente o par EURUSD. A estratégia consiste em abrir uma nova posição para fazer o preço médio sempre que o preço se mover contra a posição atual. Esta parte está funcionando perfeitamente.
No entanto, estou enfrentando dificuldades com a função que posiciona os take profits em um único nível. Para ilustrar melhor, vou descrever um cenário:
Suponha que eu tenha posições de compra abertas nas seguintes cotações:
Essas posições estão com os seguintes lotes:
A função que estou desenvolvendo (abaixo) deve ajustar o take profit dessas posições de modo que, quando o alvo for atingido, o lucro seja X (multipler) vezes maior do que a soma das perdas das posições que estão negativas. A maneira como a função está atualmente, ela retorna o erro [invalid stops].
Infelizmente, a minha função não está alcançando esse objetivo. Por isso, venho até vocês em busca de ajuda para ajustar a lógica e garantir que esse objetivo seja atingido.
Desde já, agradeço a colaboração de todos.
Obrigado!