English Русский 中文 Español Deutsch 日本語
preview
ChatGPT da OpenAI dentro do framework de desenvolvimento MQL4 e MQL5

ChatGPT da OpenAI dentro do framework de desenvolvimento MQL4 e MQL5

MetaTrader 5Negociação | 11 outubro 2023, 14:57
1 570 0
Evgeniy Ilin
Evgeniy Ilin

Conteúdo



Introdução

Vamos começar pelo básico. Esta tecnologia é uma das variações de inteligência artificial da OpenAI, projetada para ajudar as pessoas na resolução de diversas tarefas. Esta ferramenta se parece com um chat de mensagens comum. No entanto, na outra ponta, há uma chamada inteligência artificial que responde em forma de texto.

Claro, o canal de comunicação é limitado apenas a um texto, mas ainda é suficiente para resolver vários problemas ou aprender muitas coisas novas. Este canal de texto é adequado para resolver problemas completamente diferentes, como programação, matemática, física, química, sem mencionar tradução habilidosa e outras habilidades.

Estamos interessados neste modelo apenas em termos de desenvolvimento de sistemas de negociação lucrativos. Fiquei interessado em como usar de forma ótima e correta esta tecnologia para um desenvolvimento mais rápido e fácil de sistemas de negociação. Em última análise, quem começa a aplicar corretamente uma tecnologia para o fim a que se destina reduz tanto o custo de qualquer desenvolvimento quanto os custos de mão de obra, o que oferece vantagens competitivas óbvias.


Perspectivas de uso do ChatGPT no MQL5

Vamos nos aprofundar mais detalhadamente nas perspectivas da tecnologia. Após um estudo bastante detalhado com meus próprios exemplos, percebi que essa tecnologia é apenas o começo de algo verdadeiramente grandioso. Mas mesmo agora, posso destacar as seguintes características:

  • Geração de quaisquer códigos MQL4 e MQL5
  • Refatoração e otimização de código funcional
  • Limpeza de código
  • Adição de comentários ao código
  • Correção de erros no código
  • Realização de modelos matemáticos
  • Construção subsequente de código com base em modelos matemáticos
  • Modernização de quaisquer algoritmos e modelos matemáticos conhecidos
  • Aceleração do processo de desenvolvimento do Expert Advisor
  • Uma enorme quantidade de informações

Esta lista está longe de ser final, e você pode adicionar algo de sua própria autoria aqui. Acho que, quando as pessoas ficam sabendo desse tipo de tecnologia, todas começam a se dividir em aproximadamente três subgrupos:

  1. "Agora faremos um super algoritmo"
  2. Aqueles que são cautelosos com a IA e questionam sua utilidade
  3. A máquina não pode ser melhor do que um humano. É tudo apenas mais um exagero.

Comecei a me familiarizar com essa tecnologia há muito tempo e, no início, pertencia à terceira categoria. Nos dois primeiros dias lidando com esta IA, mudei abruptamente da terceira para a primeira categoria. Após isso, um processo mais interessante e um tanto desagradável de ajustar minhas próprias crenças começou, o que mais se assemelha a um retrocesso para a categoria "1.5", que é uma avaliação mais realista desta tecnologia.
Essa tecnologia é útil, mas não tanto quanto você pode inicialmente pensar. Nesse sentido, vale a pena prestar homenagem aos desenvolvedores e profissionais de marketing desta tecnologia, nem que seja pelo fato de que ela cria um incrível efeito "uau" ao ser usada nos primeiros dias, o que é suficiente para uma reação em cadeia de autopromoção. Um grande elogio a eles por isso.

Para entender isso, é necessário muita prática ao lidar com esta IA. Pessoalmente, tive cerca de uma centena de diálogos diferentes com ela sobre vários temas. Posso dizer que adquiri prática suficiente no uso desta tecnologia para começar a usá-la para MQL5. Antes de passar para as aplicações práticas, preciso contar algumas informações muito importantes e, para isso, precisaremos olhar mais profundamente sob o capô desta tecnologia.


Possíveis armadilhas associadas ao ChatGPT

O chamado efeito "uau" que você experimentará nos primeiros dias de uso desta tecnologia se deve ao fato de que esta é principalmente um modelo de texto projetado para transformar sua pergunta em uma resposta. A razão pela qual você gostará de suas respostas é porque os criadores ensinaram este modelo a mentir de forma bela. Sim, não estou brincando! Ele mente tão bem que você vai querer acreditar, e mesmo após muitas tentativas de desmascará-lo, o modelo frequentemente lhe fornecerá algo como isto:

  • Desculpe! Sim, você está certo. Eu cometi um pequeno erro. Vou levar isso em consideração no futuro. (Não considera nada, apenas uma desculpa)
  • Desculpe pelo mal-entendido, cometi um erro. Aqui está a versão corrigida. (E comete ainda mais erros)
  • Você pode descobrir que o modelo cometeu um erro nos cálculos. (Mas na verdade ele não calculou nada, apenas encontrou um número aproximado em algum lugar)
  • Você detectou um erro em um código. (Também tentará se justificar e enganar você)
  • O modelo imita a execução de uma tarefa e tenta convencê-lo de que fez o que você pediu. (Na verdade, ele apenas procura algo semelhante e lhe apresenta. Se você aceitar isso, ótimo, você não sobrecarregará o servidor com perguntas desnecessárias)
  • Desculpe! Não pude ajudar você. (Isso é quando percebe que você o pegou em uma mentira ou erros óbvios, apenas para não ter mais nada a dizer)
  • O modelo adiciona muitas palavras excessivas à sua resposta para dar a impressão de uma resposta harmoniosa e coerente. (De novo, parece-me um elemento de preguiça, para otimizar o consumo de recursos)

Em resumo, o modelo tentará evitar a tarefa fornecida de todas as maneiras possíveis, aproveitando-se da imperfeição do seu "prompt". Em caso de erros, tentará se justificar de forma que você não possa pegá-lo fazendo a mesma coisa e, se perceber que você o desmascarou, tentará amenizar sua reação negativa com certas respostas e truques psicológicos. Em geral, acredito que o algoritmo seja ajustado para um consumo ótimo de recursos com um nível aceitável de satisfação do usuário. Em outras palavras, o objetivo neste caso não é fornecer a solução de maior qualidade para o problema, mas oferecer uma solução que você considere como tal, por razões completamente diferentes. Acontece que o objetivo é uma reação positiva do usuário, e não é tão importante se a tarefa é resolvida corretamente. É isso que ele busca. Do ponto de vista de marketing, isso está correto e, nesse sentido, a IA pode ser o mais persuasiva possível.

Considerando tudo isso, percebi que, para minimizar sua liberdade neste aspecto, devemos, antes de tudo, acumular experiência em comunicar-nos com ela e tirar conclusões sobre que tipo de tarefas não requer o uso dessa persuasão simplesmente porque será fácil para ela cumprir nosso pedido, já que é mais facilmente cumprido dada sua funcionalidade e é muito mais fácil dar uma resposta direta do que ativar a imaginação. Porque isso não será eficiente em termos de custos de recursos, em outras palavras, simplesmente não será lucrativo para ela enganar você, mas será muito mais fácil dar-lhe uma resposta verdadeira.

Para começarmos a entender como fazer tais perguntas, precisamos compreender o seguinte:

  1. A estrutura e o tipo de um "prompt" não são tão importantes, os detalhes e a qualidade da pergunta têm maior importância. (Ele entende tudo e não há necessidade de ler guias da internet sobre como elaborar prompts. Escreva como é, mas sem gírias)
  2. Divida perguntas ou solicitações complexas em subtópicos. (Simplifique e divida as perguntas para obter respostas mais precisas, simples e claras)
  3. Quanto mais inteligente e pontual for sua pergunta, mais útil será a resposta.
  4. Ele não lhe dará uma super ideia ou algoritmo. (Ele não tem amplitude de pensamento, planejamento e criatividade intelectual. Mas a princípio parecerá que ele pode, simplesmente porque, como eu disse, ele é muito bom em mentir)
  5. Devemos pensar no uso desta tecnologia exclusivamente no contexto de acelerar nosso trabalho e reduzir nossos custos de mão de obra.
  6. Cada nova solicitação deve ser o menos dependente de todo o diálogo. (Ele não pode manter todo o diálogo e as mensagens antigas nem sempre são consideradas na resposta. Tente e você entenderá o que quero dizer)
  7. Quanto mais complexa a pergunta e mais detalhes ela contiver, maior a probabilidade de obter um completo absurdo. (Isso é como uma explicação do segundo subitem)
  8. O modelo não tem acesso à Internet e gera todas as respostas apenas com base em sua base de conhecimento. (Se você o pressionar muito para que ele acesse a internet e faça algo, ele dirá que fez e lhe fornecerá dados antigos de seu banco de dados ou adaptará a resposta com base no contexto de sua pergunta, apresentando-os como novos. Tenha isso em mente. E ele faz isso simplesmente porque vê que é inútil discutir com você e é melhor convencê-lo de que fez tudo, para que você o deixe em paz)
  9. ChatGPT 3.5 foi treinado até 2019. (E isso significa que ele não tem nenhuma informação sobre o futuro após 2019, até a próxima sessão de treinamento sancionada pelos desenvolvedores)
  10. ChatGPT 4.0 foi treinado até 2021. (Ele é melhor porque mente muito pouco e sempre tenta responder corretamente. Quando você tentar fazer várias perguntas e comparar, verá como o 3.5 mente sem se envergonhar)

Na verdade, existem muitos outros pequenos momentos desagradáveis que prejudicam a impressão que temos desta tecnologia. Mas, ainda assim, eu não escreveria sobre isso se essa tecnologia não fosse útil. Tudo se resume ao fato de que isso de forma alguma é uma inteligência artificial. Mas, se permanecermos pragmáticos e pensarmos se tudo está tão ruim e quais operações rotineiras podemos realizar mais rapidamente e melhor com a ajuda desta tecnologia, tenho certeza de que não seremos tão severos em nosso julgamento. Só precisamos pensar em como usar tudo isso no desenvolvimento de sistemas de negociação.

Para concluir esta seção, quero focar sua atenção no ponto mais importante e básico que você precisa lembrar a todo momento:

  • Sempre verifique duas vezes as respostas do ChatGPT e, especialmente, números, equações e código gerado

Graças ao meu conhecimento em matemática e programação, tive a oportunidade de ver muitos exemplos de seus erros e deficiências, e posso dizer que eles são bastante comuns. Pode parecer insignificante do ponto de vista do texto gerado, mas quando estamos lidando com matemática ou código, até o erro mais insignificante torna a solução inteira inútil. Portanto, sempre verifique duas vezes as respostas, corrija os erros e chame a atenção do modelo para isso. Às vezes, ele responde corretamente por um tempo. Este subtópico, entre outras coisas, será extremamente útil ao desenvolver seus EAs.


Oportunidades de usar o ChatGPT para resolver problemas matemáticos e desenvolver modelos matemáticos para uso em um código

Como este modelo é textual, é fácil deduzir que, se escrevermos equações no formato correto, ele as entenderá e, além disso, realizará transformações matemáticas e resolverá problemas. Ao desenvolver muitos sistemas de negociação, você precisará de ajuda para criar equações e expressões matemáticas. É possível resolver alguns possíveis problemas matemáticos com sua subsequente implementação em um código. Existe o seguinte formato para escrever equações matemáticas, que o ChatGPT entende e usa para dar a resposta:

  • LaTeX

Um exemplo de uso do formato LaTeX para escrever equações:

Código:

E &=& mc^2\\
m &=& \frac{m_0}{\sqrt{1-\frac{v^2}{c^2}}}

Cole isso em qualquer conversor latex gratuito e obtenha uma visualização de dados de todas as expressões familiares:

Equações de expansão de energia e massa relativística de Einstein

Acredito que, agora, está claro como interpretar visualmente as respostas do modelo no formato LaTeX. Mais importante ainda, não se esqueça de pedir ao modelo para gerar equações neste formato se a resposta contiver expressões matemáticas. Existem também redes neurais capazes de converter equações em imagens ou outros formatos de volta ao formato que precisamos. Acredito que você encontrará essas ferramentas se precisar delas. Minha tarefa é mostrar a você a existência de tal possibilidade.

Existem bots do Telegram que combinam muitas redes neurais, incluindo o ChatGPT, e a função de converter imagens de volta para o formato LaTeX. Se desejar, você pode encontrar um deles no meu perfil. Este bot foi feito por meu amigo e testado por mim pessoalmente. Você pode usá-lo.

Você pode pedir ao ChatGPT, por exemplo, para resolver uma desigualdade ou uma equação, tanto numericamente quanto explicitamente. Você também pode pedir para resolver sistemas de equações ou desigualdades, bem como equações diferenciais ou integrais, ou realizar quaisquer transformações matemáticas necessárias. No entanto, como matemático, posso dizer que nem sempre faz isso de forma eficiente e racional e, às vezes, deixa a tarefa inacabada. Portanto, verificações duplas são necessárias.

Claro, esse recurso pode ser útil para não matemáticos. Em caso de uso prolongado, você cometerá mais erros e sua solução será bastante irracional e desajeitada. No entanto, você cobrirá alguns dos seus problemas matemáticos para o seu código, considerando que o código geralmente usa apenas métodos numéricos, enquanto a matemática aplicada não é tão complicada. Não há matemática diferencial aqui.


Abordagem correta para geração de código em MQL4 e MQL5

É aqui que as coisas ficam interessantes. Dado que os tamanhos dos códigos de todos os sistemas de negociação de qualidade suficientemente alta e mais ou menos decentes são bastante grandes, vale a pena pensar em como abordar o processo de geração de tais códigos. Aqui, o principal obstáculo é que o tamanho da resposta à sua pergunta é limitado a um certo número de caracteres, e após inúmeras tentativas de gerar códigos grandes e complexos, cheguei à conclusão de que cada saída de código deve ser curta o suficiente. Isso significa que o código deve ser exibido em partes. Como podemos alcançar isso? A resposta é muito simples - precisamos fazer um plano para desenvolver um EA, indicador ou script.

O plano deve ser elaborado com a condição de que cada subitem deve ser uma sub-tarefa separada que pode ser resolvida independentemente. Então, podemos simplesmente resolver cada sub-tarefa sequencialmente e, em seguida, combinar todo o código. Outra vantagem dessa abordagem é que cada sub-tarefa pode ser finalizada separadamente e, como cada sub-tarefa é mais simples do que todas elas combinadas, a finalização é realizada mais rapidamente e de maneira mais confortável. Além disso, evitaremos mais erros.

Como desenvolvedor, é muito mais confortável para mim pensar independentemente na arquitetura principal do meu EA sem permitir que a IA interfira. Em vez disso, deixe-a implementar procedimentos separados no meu EA. Que toda a lógica principal esteja contida nos procedimentos. Só teremos que implementar um modelo de código aproximado com funções vazias e, em seguida, pedir para implementar cada função individualmente. Também podemos pedir para implementar protótipos de função ou outras estruturas.

Uma vantagem adicional e importante é que você pode pedir para preparar um plano para um EA ou outro código, indicando suas exigências, e depois simplesmente implementar seu plano parte por parte. É bom quando você tem uma ideia aproximada ou precisa do que será o algoritmo do seu EA e quais indicadores ou outras abordagens ele usará. Mas, se não houver tal ideia, você pode primeiro conversar com ele e pedir que o ajude a escolher uma estratégia de negociação para seu EA. Ele oferecerá algumas opções. Vamos considerar este curso de ações aqui como um exemplo.

Vamos agora resumir o acima e formar subpontos breves, simbolizando os possíveis caminhos que tomaremos ao construir um novo EA do zero. Para começar, existem vários cenários possíveis óbvios para começar:

  1. Não decidimos sobre a arquitetura do código futuro e não sabemos por onde começar, e também não sabemos de todo qual das abordagens de negociação escolher.
  2. Não decidimos sobre a arquitetura do código futuro e não sabemos por onde começar, mas conhecemos um esboço do código de trabalho principal e o que queremos do EA.
  3. Temos uma arquitetura pronta que é confortável para nós, mas não sabemos absolutamente qual abordagem de negociação escolher.
  4. Sabemos a arquitetura que queremos usar e também temos uma ideia clara da futura lógica de negociação do EA.

Por regra, tudo será reduzido a construções similares. Todos os quatro pontos podem ser aplicados ao esquema geral de construção de qualquer sistema de negociação se fizermos o seguinte:

  • Se não conhecemos a arquitetura, primeiro precisamos implementá-la e, em seguida, implementar tudo o que garante o funcionamento dessa estrutura.

Isso pode significar, por exemplo, que podemos pedir para implementar classes, variáveis de entrada, campos e protótipos de métodos, interfaces, bem como a principal funcionalidade de negociação do EA, que usará as entidades descritas por nós. Com o manuseio adequado do ChatGPT, o código pode ser implementado de tal forma que leve, digamos, não mais do que 5-10% do número total de caracteres. Neste caso, podemos implementá-lo rapidamente e, em seguida, passar para a implementação dos procedimentos, que conterão cerca de 90% de todo o código. Estes procedimentos serão implementados da mesma maneira simples, porque haverá muitos deles e eles se mostrarão bastante pequenos e facilmente executáveis. Claro, é muito mais fácil quando você tem um modelo pronto e não precisa implementar tudo isso, mas isso exige conhecimento e experiência. Essas pessoas precisam saber por onde começar e como fazê-lo.


Desenvolvendo um sistema de negociação usando ChatGPT

Acredito que já lhe dei informações teóricas suficientes. É hora de aplicá-las. No meu caso, uso um modelo pronto para basear meus EAs. Descrevi tal padrão em um dos artigos anteriores. Sua peculiaridade é que permite a negociação paralela de muitos instrumentos, sendo ativada em um único gráfico. Ele já possui toda a funcionalidade de negociação necessária e a arquitetura principal. Vou construir um sistema de negociação seguindo estritamente as recomendações do ChatGPT. Implementarei a lógica principal de negociação do EA, bem como o componente visual, porque isso exigirá menos esforços da minha parte.

Quando você começar a interagir com o ChatGPT, perceberá que gastará muito mais esforços tentando explicar o que precisa ser feito, e corrigirá suas respostas centenas de vezes ao implementar algumas solicitações e tarefas. Depois de um tempo, você simplesmente começará a sentir quais perguntas valem a pena e quais não valem. Você começará a definir apenas aquelas tarefas que, no final das contas, economizarão seu tempo em vez de desperdiçá-lo. Há uma linha bastante tênue aqui, que você tem que sentir por si mesmo - não há outra maneira. Tudo é aprendido na prática. Minha abordagem ao design do EA foi totalmente formada devido a essas considerações.

Para começar, pedi que descrevesse a base do Expert Advisor - sobre qual princípio ele funcionaria e quais técnicas ou indicadores ele usaria (permiti que ele usasse qualquer informação disponível à sua discrição). Ao mesmo tempo, afirmei que só preciso de condições lógicas em uma forma legível, que posso implementar por conta própria nos quatro predicados seguintes:

  1. Abertura de uma posição de compra.
  2. Fechamento de uma posição de compra.
  3. Abertura de uma posição de venda.
  4. Fechamento de uma posição de venda.

Para implementar esses predicados, o modelo me sugeriu a seguinte lógica condicional:

  1. O preço atual está fixado acima da EMA, a diferença entre o preço atual e a EMA é menor que o ATR * razão, e o RSI é menor que 30.
  2. O preço atual fechou abaixo da SMA, ou o preço atual fechou acima da banda superior do indicador Bollinger Bands.
  3. O preço atual está fixado abaixo da EMA, a diferença entre o preço atual e a EMA é menor que o ATR * razão, e o RSI é maior que 70.
  4. O preço atual está fixado acima da SMA, ou o preço atual está fixado abaixo da banda inferior do indicador Bollinger Bands.

Obviamente, essas condições booleanas retornam 'verdadeiro' em caso de sucesso e 'falso' em caso de falha. Esses valores de sinal são bastante suficientes para negociação com ordens de mercado. Aqui, quero chamar sua atenção para a óbvia possibilidade de modernizar essa lógica. Para fazer isso, podemos fazer o seguinte:

  • [K1] — zona do valor inferior do RSI
  • [K2 = 100 - K1] — zona do valor superior do RSI

Essas expressões podem ser usadas para expandir a flexibilidade do algoritmo, o que subsequentemente terá um efeito positivo na eficiência da otimização do EA:

  1. O preço atual está fixado acima da EMA, a diferença entre o preço atual e a EMA é menor que o ATR * razão, e o RSI é menor que K1.
  2. O preço atual está fixado abaixo da SMA ou o preço atual fechou acima da banda superior do indicador Bollinger Bands.
  3. O preço atual fechou abaixo da EMA, a diferença entre o preço atual e a EMA é menor que o ATR * razão, e o RSI é maior que K2.
  4. O preço atual está fixado acima da SMA ou o preço atual está fixado abaixo da banda inferior do indicador Bollinger Bands.

Dei este exemplo porque você não deve hesitar em estender o modelo se for óbvio que a solução em questão é apenas um caso especial de um algoritmo diferente e mais extenso. Mesmo que você não saiba o que tal extensão pode lhe oferecer, ao fazer isso, pelo menos aumenta a flexibilidade do seu algoritmo e, portanto, a probabilidade de sua afinação mais precisa e, como resultado, um possível aumento em sua eficiência.

Considerando quais condições precisam ser implementadas, precisaremos de uma das duas opções para implementar os indicadores a seguir:

  1. SMA — média móvel simples
  2. EMA — média móvel exponencial
  3. Bollinger Bands — bandas de Bollinger
  4. RSI — índice de força relativa
  5. ATR — amplitude média verdadeira

Os indicadores podem ser implementados usando funções MQL5 predefinidas especiais, mas eu não gosto dessa abordagem, porque o código implementado será mais difícil de converter para a versão MQL4. Além disso, será mais difícil para mim integrá-lo, por exemplo, em meus projetos em outras linguagens, o que faço com muita frequência. Há muito tempo tenho o hábito de fazer tudo da maneira mais simples possível e pensando no uso futuro. Acho que este é um hábito muito bom.

O segundo ponto importante é que, via de regra, tais indicadores arrastam cálculos e funcionalidades desnecessários e redundantes. Além disso, é impossível refinar tais indicadores, já que suas funções são rigidamente definidas no nível do código. Para fazer alterações, você precisará criar sua própria versão do indicador de qualquer maneira. Acredito que é óbvio que é melhor ter uma implementação personalizada dentro de um EA ou script. Para implementar tais indicadores, eu inventei o seguinte truque:

  1. Criação de arrays para armazenar os valores das linhas do indicador.
  2. Implementação de deslocamento dos valores do array quando um novo bar aparece.
  3. Implementação da limpeza do array de valores do indicador em caso de erros ou uma longa desconexão.
  4. Implementação do cálculo do valor do indicador para o último bar quando ele fecha.

Nesta abordagem, os três primeiros parágrafos criam blocos de array comuns e funções que fornecem as ações listadas. Vamos ver como isso parece usando nossa tarefa como exemplo. Vamos começar com o primeiro ponto:

   double SMA1Values[]; // Array for storing SMA values
   double EMAValues[];  // Array for storing EMA values (exponential)
   double RSIValues[];  // Array for storing RSI values
   
   double BollingerBandsUpperValues[];  // Array for storing BollingerBands values, upper
   double BollingerBandsMiddleValues[]; // Array for storing BollingerBands values, middle
   double BollingerBandsLowerValues[];  // Array for storing BollingerBands values, lower
   
   double ATRValues[];// array for storing Average True Range values

Esses arrays são inicializados no início do EA com os limites de comprimento dados:

   //Prepare indicator arrays
   void PrepareArrays()
   {
      ArrayResize(SMA1Values, LastBars);
      ArrayResize(EMAValues, LastBars);
      ArrayResize(RSIValues, LastBars);
      ArrayResize(BollingerBandsUpperValues, LastBars);
      ArrayResize(BollingerBandsMiddleValues, LastBars);
      ArrayResize(BollingerBandsLowerValues, LastBars);
      ArrayResize(ATRValues, LastBars);
   }

Ao contrário dos indicadores convencionais, não precisamos arrastar todos os valores anteriores conosco para esta estratégia. Isso é definitivamente uma vantagem. Gosto deste paradigma de implementação, porque garante a simplicidade do código e a equivalência tanto dos valores iniciais do indicador quanto dos obtidos usando os anteriores. Agora, vamos ver como se parece o deslocamento de valor:

   //shift of indicator values
   void ShiftValues()
   {
      int shift = 1;
      for (int i = LastBars - 1; i >= shift; i--)
      {
         SMA1Values[i] = SMA1Values[i - shift];
         EMAValues[i] = EMAValues[i - shift];
         RSIValues[i] = RSIValues[i - shift];
         BollingerBandsUpperValues[i] = BollingerBandsUpperValues[i - shift];
         BollingerBandsMiddleValues[i] = BollingerBandsMiddleValues[i - shift];
         BollingerBandsLowerValues[i] = BollingerBandsLowerValues[i - shift];
         ATRValues[i] = ATRValues[i - shift];
      }
   }

Como você pode ver, tudo é extremamente simples. O mesmo se aplica à limpeza de arrays:

   //reset all indicator arrays if connection fails [can also be used when initializing an EA]
   void EraseValues()
   {
      for (int i = 0; i < LastBars; i++)
      {
         SMA1Values[i] = -1.0;
         EMAValues[i] = -1.0;
         RSIValues[i] = -1.0;
         BollingerBandsUpperValues[i] = -1.0;
         BollingerBandsMiddleValues[i] = -1.0;
         BollingerBandsLowerValues[i] = -1.0;
         ATRValues[i] = -1.0;
      }
   }

Acho que não é necessário mostrar onde essa funcionalidade será aplicada. Acredito que muitos irão adivinhar por conta própria. Agora, vamos passar para a implementação dos próprios indicadores. Para fazer isso, pedi ao ChatGPT que implementasse a função apropriada, que seria adequada com base no meu paradigma de construção de código. Comecei com o indicador SMA:

   //1 Function that calculates the indicator value to bar "1"
   double calculateMA(int PeriodMA,int Shift=0)
   {
      int barIndex=Shift+1;//bar index SMA is calculated for (with a shift)
      int StartIndex=barIndex + PeriodMA-1;//starting bar index for calculating SMA
      if (StartIndex >= LastBars) return -1.0; // Check for the availability of the bars for calculating SMA (if not valid, then the value is -1)
      double sum = 0.0;

      for (int i = StartIndex; i >= barIndex; i--)
      {
         sum += Charts[chartindex].CloseI[i];
      }
      LastUpdateDateTime=TimeCurrent();
      return sum / PeriodMA;
   }

Como você pode ver, a função acabou sendo muito simples e curta. Inicialmente, a aparência desta função era um pouco diferente. Durante a primeira geração, encontrei muitos erros nela, por exemplo, relacionados ao fato de que ela não compreendeu a direção da numeração dos bares em relação ao tempo, e assim por diante. Muitos pequenos detalhes. Mas, após algumas manipulações, corrigi tudo isso e adicionei o parâmetro Shift, que não estava na implementação original. Após implementar algumas melhorias visuais, pedi para implementar o restante dos indicadores de forma semelhante. Depois disso, houve menos erros em suas implementações. Apenas enviei os seguintes pedidos para implementar uma função semelhante para outro indicador, incluindo exemplos de implementações anteriores no contexto da questão. Isso economizou muito tempo. Vamos agora olhar suas implementações subsequentes de todos os indicadores restantes. Vamos começar com EMA:

   //2 Function that calculates the value of the exponential moving average to bar "1"
   double calculateEMA(int PeriodEMA,double Flatness=2.0,int Shift=0)
   {
      int barIndex = Shift+1; // bar index EMA is calculated for (with a shift)
      int StartIndex=barIndex + PeriodEMA-1;//index of the starting bar for calculating the first SMA, for starting the recurrent calculation of EMA
      if (StartIndex >= LastBars) return -1.0; // Check for the availability of the bars for calculating EMA (if not valid, then the value is -1)
   
      double sum = 0.0;
      double multiplier = Flatness / (PeriodEMA + 1); // Weight multiplier 
      double prevEMA;
   
      // Calculate the initial value for the EMA (the first value is considered as a normal SMA) 
      for (int i = StartIndex; i >= barIndex; i--)
      {
         sum += Charts[chartindex].CloseI[i];
      }
      prevEMA = sum / PeriodEMA;//this is the starting value for the bar (StartIndex-1)
   
      // Apply the EMA formula for the remaining values 
      for (int i = StartIndex; i >= barIndex; i--)
      {
         prevEMA = (Charts[chartindex].CloseI[i] - prevEMA) * multiplier + prevEMA;
      }
   
      LastUpdateDateTime = TimeCurrent();
      return prevEMA;
   }

A propósito, ao pesquisar as gerações do ChatGPT, temos que recorrer a vários recursos da Internet para entender qual indicador é baseado em qual ideia. Isso nos torna mais competentes. Isso é especialmente evidente com o EMA. Se olharmos de perto o código, veremos que ele não difere muito da implementação mais simples do SMA e mais parece um complemento para a média móvel usual. Não há expoente aqui, embora por algum motivo esteja presente no nome do indicador. O próximo é o indicador RSI:

   //3 Function for calculating RSI to bar "1"
   double calculateRSI(int PeriodRSI,int Shift=0)
   {
       int barIndex = Shift+1; // bar index RSI is calculated for (with a shift)
       int StartIndex = barIndex + PeriodRSI - 1; // starting bar index for calculating RSI
       if (StartIndex >= LastBars) return -1.0; // Check for the availability of the bars for calculating RSI (if not valid, then the value is -1)
   
       double avgGain = 0.0;
       double avgLoss = 0.0;
       double change;
   
       // Calculate initial values for avgGain and avgLoss
       for (int i = StartIndex; i > barIndex; i--)
       {
           change = Charts[chartindex].CloseI[i]-Charts[chartindex].OpenI[i];
           if (change > 0)
           {
               avgGain += change;
           }
           else if (change < 0)
           {
               avgLoss -= change;
           }
       }
   
       avgGain /= PeriodRSI;
       avgLoss /= PeriodRSI;
   
       // RSI calculation
       double RS = 0.0;
       if (avgLoss != 0)
       {
           RS = avgGain / avgLoss;
       }
   
       double RSI = 100 - (100 / (1 + RS));
   
       LastUpdateDateTime = TimeCurrent();
       return RSI;
   }

Agora precisamos fazer um procedimento semelhante para o indicador Bollinger Bands. Este procedimento deve retornar os valores de três curvas, que podem ser colocados na estrutura previamente preparada:

   //structure to return all three bollinger band lines
   struct BollingerBands 
   {
       double upper;
       double middle;
       double lower;
   };

Agora, tendo adicionado essa estrutura ao contexto da questão, podemos pedir para implementar a função, levando em consideração o fato de que ela deve retornar o tipo BollingerBands. O modelo lidará com essa tarefa sem problemas:

   //4 Function for calculating the Bollinger Bands of the indicator 
   BollingerBands calculateBollingerBands(int PeriodBB, double DeviationBB,int Shift=0) 
   {
       int barIndex = Shift+1; // bar index Bollinger Bands is calculated for (with a shift)
       int StartIndex = barIndex + PeriodBB - 1; // index of the starting bar for calculating the first SMA, for starting the recurrent calculation of EMA
       BollingerBands rez;
       rez.lower=-1.0;
       rez.middle=-1.0;
       rez.upper=-1.0;
       if (StartIndex >= LastBars) return rez; // Check for the availability of the bars for calculating BB (if not valid, then the value is -1)
   
       double sum = 0.0;
       double prevBB;
       double sumSquares = 0.0;
   
       // Calculate the initial value for BB (the first value is considered as a normal SMA)
       for (int i = StartIndex; i >= barIndex; i--) {
           double closePrice = Charts[chartindex].CloseI[i];
           sum += closePrice;
       }
       prevBB = sum / PeriodBB; //this is the starting value for the bar (StartIndex-1)
   
       // Calculation of standard deviation
       for (int i = StartIndex; i >= barIndex; i--) {
           double closePrice = Charts[chartindex].CloseI[i];
           sumSquares += pow(closePrice - prevBB, 2);
       }
       double standardDeviation = sqrt(sumSquares / PeriodBB);
   
       // Calculate Bollinger Bands
       double upperBand = prevEMA + DeviationBB * standardDeviation;
       double lowerBand = prevEMA - DeviationBB * standardDeviation;
   
       rez.upper = upperBand;
       rez.middle = prevEMA;
       rez.lower = lowerBand;
   
       LastUpdateDateTime = TimeCurrent();
       return rez;
   }

Agora só resta implementar a versão da função para calcular o ATR:

   //5 Function for calculating Average True Range (Relative)
   double calculateRelativeATR(int PeriodATR,int Shift=0)
   {
       int barIndex = Shift+1; // bar index ATR is calculated for (with a shift)
       int StartIndex = barIndex + PeriodATR - 1; // starting bar index for calculating the first ATR
       if (StartIndex >= LastBars) return -1.0; // Check for the availability of the bars for calculating ATR and True Range (if not valid, then the value is -1)
   
       double sumPrice=0.0;
       double sumTrueRange = 0.0;
       double ATR;
   
       // Calculating True Range for bars and the sum of values for calculating the first ATR
       for (int i = StartIndex; i >= barIndex; i--)
       {
           sumPrice+=Charts[chartindex].HighI[i]+Charts[chartindex].LowI[i]+Charts[chartindex].CloseI[i]+Charts[chartindex].OpenI[i];//added by me 
           double high = Charts[chartindex].HighI[i];
           double low = Charts[chartindex].LowI[i];
           double trueRange = high - low;
           sumTrueRange += trueRange;
       }
   
       // ATR calculation
       //ATR = sumTrueRange / PeriodATR; - conventional calculation
       ATR = 100.0 * (sumTrueRange / PeriodATR)/(sumPrice/(PeriodATR*4.0));//calculation of relative ATR in %
   
       LastUpdateDateTime = TimeCurrent();
       return ATR;
   }

Aqui, peço que preste atenção na linha comentada no final. Eu modifiquei ligeiramente esse indicador para que ele operasse com valores relativos. Isso é necessário para que não seja preciso definir pesos para cada instrumento de negociação, pois isso ocorrerá automaticamente com base no preço atual. Isso permitirá uma otimização em várias moedas mais eficiente. Precisaremos disso para provar o fato de que até mesmo um algoritmo tão simples, se usado corretamente, pode nos dar um pequeno, mas suficiente período à frente para negociação. Em combinação com outros métodos de eficiência, esse comércio pode ser tornado bastante aceitável, mesmo no nível atualmente permitido pelo EA.

Eu implementei os predicados por mim mesmo. Foi muito fácil. Vamos olhar para um deles, digamos o primeiro:

   //to open buy positions
   bool bBuy()
      {
      //determine if an open position is already present
      bool ord;
      ulong ticket;
      bool bOpened=false;
      for ( int i=0; i<PositionsTotal(); i++ )
         {
         ticket=PositionGetTicket(i);
         ord=PositionSelectByTicket(ticket);
         if ( ord && PositionGetInteger(POSITION_MAGIC) == MagicF)
            {
            bOpened=true;
            return false;
            }
         }
         
      if (!bOpened && EMAValues[1] > 0.0)//only if nothing is open and the indicator has been calculated 
         {
         //K - control ratio
         //RSIPercentBorder - control RSI
         double Val1=Charts[chartindex].CloseI[1]-EMAValues[1];
         double Val2=ATRValues[1]*(1.0/K);
         if (Val1 > 0 && Val1 < Val2 && RSIValues[1] < RSIPercentBorder) return true;         
         } 
      return false;
      }

O predicado para abrir uma posição de venda é semelhante com pequenas exceções. O predicado de fechamento é ainda mais simples:

   //to close a buy position
   bool bCloseBuy()
      {
      if (SMA1Values[1] > 0.0)
         {
         if (Charts[chartindex].CloseI[1] < SMA1Values[1] || Charts[chartindex].CloseI[1] > BollingerBandsUpperValues[1] )
            {
            return true;
            }
         }
      return false;   
      }

Tudo isso funcionará de uma maneira muito simples:

   IndicatorDataRecalculate();//recalculate indicators

   if ( bCloseBuy() )
      {
         CloseBuyF();
      }
   if ( bCloseSell() )
      {
         CloseSellF();  
      }
   if ( bBuy() )
      {
         BuyF();
      }
   if ( bSell() )
      {
         SellF();
      } 

Acredito que seja o mais simples possível e não há necessidade de ser mais complicado. Todo esse código deve ser executado quando aparece uma nova barra. Implementei a visualização de indicadores separadamente. A única coisa que não gosto é que indicadores como ATR e RSI são projetados para serem desenhados em uma janela separada. Fiz minha versão de renderização para eles de modo que também estejam vinculados ao preço, já que uma janela separada não pode ser criada artificialmente e, francamente, eles não são realmente necessários. Para conseguir isso, criei um certo paradigma para desenhar indicadores de janela.

  1. Introdução do valor de controle Percent para criar três corredores a partir de um.
  2. Determinação dos valores máximo e mínimo do indicador para todo o array de valores armazenados.
  3. Cálculo do delta do corredor dado.
  4. Cálculo do corredor superior de valores aumentados.
  5. Cálculo do corredor inferior de valores aumentados.
  6. O corredor do meio já foi definido, uma vez que ambos os corredores superior e inferior foram definidos.

Se o valor atual do indicador estiver em um dos corredores, então seus pontos adquirem a cor apropriada correspondente ao corredor. Tudo é simples. É assim que podemos vincular valores às barras do gráfico e, por exemplo, apenas mudar sua cor de acordo, ou apenas criar objetos vinculados à barra e tendo a cor correspondente. Como muitos provavelmente notaram, fui inspirado pelo indicador RSI, porque essa estrutura particular é geralmente usada para negociação. Essas áreas são chamadas de zonas de sobrecompra e sobrevenda lá.

Eu acredito que o código aqui não é tão relevante, pois tem a menor relação com a implementação da nossa tarefa e apenas ajudará na correção de possíveis erros e ajustes. Se desejar, até essa renderização você poderá implementar com a ajuda do ChatGPT, se você pensar um pouco. No entanto, acho que vale a pena mostrar como essa renderização funciona:

Visualização de indicadores

Tudo aqui é feito da maneira mais simples, usando apenas o objeto "Linha". Se, ao criar uma linha, o ponto inicial e final da linha forem vinculados ao mesmo tempo e preço, a linha se transforma em um ponto. Com o ajuste da espessura da linha, ajustamos a espessura do ponto correspondente. Estas são apenas algumas dicas minhas que venho usando há muito tempo.


Avaliação da funcionalidade e análise dos resultados

Apesar de o ChatGPT considerar este algoritmo o ideal, não sabemos com base em que tais decisões foram tomadas. A medida de eficácia pode ser um bom backtest ou negociação real. Espero que todos entendam que a negociação real deve ser precedida por uma configuração ideal, que pode ser feita com o otimizador MetaTrader 5. Graças ao fato de que este terminal tem a capacidade de otimização em várias moedas e considerando as possibilidades do meu modelo, que utiliza plenamente a eficiência desta ferramenta, podemos otimizar o EA para todos os "28" pares de moedas, talvez, não valha a pena listá-los. Mas vale a pena destacar as óbvias vantagens dessa abordagem:

  1. Busca automática de regularidades em várias moedas
  2. Os padrões vistos em várias moedas têm maior peso e adaptabilidade futura às mudanças de mercado
  3. Há mais negócios, já que cada instrumento de negociação contribui de alguma forma
  4. Economia de tempo (porque não é necessário otimizar cada instrumento separadamente)

É claro que há desvantagens. Neste caso, o mais relevante é que o ajuste fino para cada instrumento não é possível. Claro, essa tarefa pode ser resolvida introduzindo funcionalidade adicional, mas esse não é o tema deste artigo. Mas não basta fazer essa otimização, é importante também selecionar corretamente os resultados de todo o conjunto que ela oferece. Eu selecionei o ideal:

Opção de otimização ideal

Como pode ser visto, eu otimizei desde "2018" até "2023", usando o timeframe "H4", e deixei todos os seis meses de "2023" para o forward test. Como é evidente, apesar da curva de lucro não muito agradável durante a fase de otimização, conseguimos mais dois ou três meses de negociação lucrativa, e este fato indica que a estratégia tem mérito e potencial para ser usada com sucesso na negociação. Muitos sistemas de negociação que você poderia otimizar provavelmente nem se aproximariam desse resultado. Às vezes, é possível testar sistemas incrivelmente sofisticados do ponto de vista do código e não obter nem isso.

Sim, eu certamente adicionaria muitas coisas a este algoritmo, e para mim é apenas um brinquedo. Mas o importante não é isso, e sim o potencial de expandir o EA obtido. O que importa aqui não é tanto o algoritmo proposto, mas a sua competência e criatividade que entram em jogo. Para uma integração bem-sucedida no processo de desenvolvimento em MQL5, você precisará das seguintes qualidades:

  • Habilidades de programação (essencial)
  • Habilidades em matemática (desejável)
  • Pensamento em blocos
  • Habilidade de simplificar a tarefa e dividi-la em partes
  • Entendimento de que o ChatGPT é apenas uma ferramenta, e não um mágico, e não se deve culpá-lo se algo não funcionar (tudo o que não funciona é sua parte do trabalho que você precisa fazer)
  • Interpretação correta da negociação resultante
  • Reconhecendo que ele comete erros de qualquer maneira, mas você não deve se preocupar com isso (o importante é que você ganhou tempo no esforço de desenvolvimento)
  • Desenvolvimento de seu próprio esquema de aplicação (isso não é necessário, claro, você pode usar minha abordagem)
  • ChatGPT é seu companheiro, cuja força depende diretamente de você. Quanto mais paciente, inteligente e engenhoso você for, mais eficaz será este companheiro.

Se resumirmos tudo o que foi dito, tudo depende diretamente de você. Você tem uma ferramenta que pode escolher usar ou não, a seu critério, mas posso dizer definitivamente que esta ferramenta tem sido muito útil para mim, inclusive para programação.


Considerações finais

Em resumo, não é realmente necessário seguir exatamente meu modelo de uso dessa ferramenta. Eu tentei fazer muitas coisas com ela, e posso dizer que quase tudo é possível. Só que, claro, antes de conseguir algo, você definitivamente gastará algum tempo e nervos, assim como eu fiz.

Mesmo assim, ainda recomendo que você experimente esta ferramenta e não se arrependa do tempo gasto. Pelo menos, com o exemplo do ChatGPT, você poderá adquirir a atitude correta em relação à inteligência artificial e entender como se relacionar com tais tecnologias no futuro. É potencialmente possível incorporar essa tecnologia em praticamente qualquer cadeia de desenvolvimento. Esta tecnologia, pode-se dizer, é uma pioneira aqui, e estou convencido de que isso é apenas o começo e que em breve veremos mudanças muito rápidas. Aconselho que você comece a se familiarizar com esta ferramenta o mais rápido possível e tente aplicá-la nos mais amplos espectros de tarefas.

Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/12475

Arquivos anexados |
ChatGPT_bot.set (2.99 KB)
ChatGPT_bot.mq5 (145.44 KB)
Entendendo a programação orientada a objetos (POO) em MQL5 Entendendo a programação orientada a objetos (POO) em MQL5
Como desenvolvedores, precisamos aprender a criar e desenvolver software que possa ser usado de forma repetida e flexível, sem duplicação de código, especialmente quando lidamos com diferentes objetos que têm comportamentos distintos. Isso pode ser facilmente alcançado usando métodos e princípios de programação orientada a objetos. Neste artigo, apresentaremos os fundamentos da programação orientada a objetos em MQL5.
Desenvolvendo um sistema de Replay (Parte 30): Projeto Expert Advisor - Classe C_Mouse (IV) Desenvolvendo um sistema de Replay (Parte 30): Projeto Expert Advisor - Classe C_Mouse (IV)
Aqui demonstrarei uma técnica que pode lhe ajudar muito, em vários momentos durante a sua vida como programador. Diferente do que muitos dizem, não é a plataforma que é limitada, mas sim o conhecimento do individuo que diz que tal coisa. O que será explicado aqui, mostrar que com um pouco de bom senso e criatividade, você pode tornar a plataforma MetaTrader 5 muito mais interessante e versátil. E sem precisar de fato criar programas malucos ou coisas do estilo. Você pode criar um código simples, porém seguro e confiável. Usando de perspicácia, domar o código a fim de modificar algo já existente, sem se quer remover ou adicionar uma única linha se quer, no código original.
DoEasy. Controles (Parte 32): "ScrollBar" horizontal, rolagem com a roda do mouse DoEasy. Controles (Parte 32): "ScrollBar" horizontal, rolagem com a roda do mouse
Neste artigo, concluiremos o desenvolvimento do funcional do objeto de barra de rolagem horizontal. Vamos habilitar a capacidade de rolar o conteúdo do contêiner movendo o controle deslizante da barra de rolagem e girando a roda do mouse. Além disso, faremos adições à biblioteca para acomodar a nova política de execução de ordens e os novos códigos de erro de tempo de execução no MQL5.
Estratégia de negociação simples: Reversão à média Estratégia de negociação simples: Reversão à média
A reversão à média é um tipo de negociação contra-tendência em que o trader espera que o preço retorne a algum tipo de equilíbrio, geralmente medido por uma média ou outra estatística de tendência central.