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.

- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso
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!