
Reimaginando Estratégias Clássicas em MQL5 (Parte II): FTSE100 e Títulos Públicos do Reino Unido
Existem potencialmente infinitas maneiras de o investidor moderno integrar a IA em suas estratégias de negociação. É altamente improvável que qualquer investidor individual tenha tempo suficiente para analisar cuidadosamente cada estratégia antes de decidir em qual confiar seu capital. Nesta série de artigos, exploraremos o vasto cenário de possíveis aplicações da IA no ambiente de negociação. Nosso objetivo é ajudá-lo a identificar uma estratégia adequada ao seu perfil específico de investidor.
Visão Geral da Estratégia de Negociação
O Financial Times Stock Exchange 100 (FTSE100) é um índice reconhecido mundialmente que acompanha o desempenho das 100 maiores empresas listadas na Bolsa de Valores de Londres (LSE). O índice foi criado em 1984 com um valor de 1000 pontos e atualmente está sendo negociado em torno de 8000 pontos. As empresas dentro do índice são ponderadas proporcionalmente à sua capitalização de mercado, o que significa que empresas maiores têm mais influência sobre o mercado do que empresas menores.
Todos os governos do mundo desenvolvido emitem títulos denominados em sua moeda local, e o governo do Reino Unido não é exceção. O “gilt” é um instrumento de dívida do governo britânico, também listado na LSE. Os gilts são títulos de renda fixa disponíveis em dois tipos diferentes. O primeiro tipo é o gilt convencional, que constitui a maioria das emissões de gilts. Esse gilt convencional paga um cupom fixo ao portador até o vencimento, momento em que o cupom final e o principal são devolvidos ao investidor.
O segundo tipo de gilt é o gilt indexado. Esse gilt específico não possui uma taxa de cupom fixa, em vez disso, os pagamentos recebidos do título são ajustados para compensar a inflação acumulada durante o período em que o investidor manteve o gilt. Esses gilts indexados não são tão populares quanto os gilts fixos devido aos seus fluxos de caixa imprevisíveis.
Existe uma relação inversa entre o rendimento de um título e a demanda por esse título. Sempre que um determinado título está em alta demanda entre os investidores, o rendimento associado a ele cai; por outro lado, se o título estiver com desempenho ruim, seu rendimento aumentará numa tentativa de atrair o interesse dos investidores.
Tipicamente, sempre que os mercados de ações estão com desempenho ruim, os investidores tendem a retirar seus fundos do mercado de ações (mais arriscado) e investir em ativos mais seguros, como títulos do governo. Por outro lado, quando os investidores recuperam a confiança no mercado de ações, eles tendem a retirar os fundos dos títulos do governo e investir no mercado de ações. A principal razão para esse comportamento está na diferença entre os retornos esperados. Em média, o mercado de ações oferece retornos médios maiores do que o mercado de títulos, tornando-se mais atraente. No entanto, o mercado de ações carrega riscos intrínsecos maiores, tornando seus investidores bastante sensíveis a sinais de fraqueza.
Visão Geral da Metodologia
Construímos um Expert Advisor com IA para aprender suas próprias regras de negociação com base nos dois mercados. Tipicamente, como investidores, tendemos a estratégias que nos agradam, porém, ao adotar uma abordagem de aprendizado algorítmico, podemos ter a certeza de que nosso programa está tomando decisões com base nos dados que coletamos.
Dados financeiros em séries temporais são notoriamente ruidosos. Ao lidar com conjuntos de dados ruidosos, é sabido que modelos mais simples podem ter desempenho tão bom quanto Redes Neurais. Portanto, implementamos um modelo de Regressão Linear do zero em MQL5 usando a API de matrizes e vetores. Padronizamos e escalamos nossos dados de entrada antes de ajustar o modelo, pois nossos dados de entrada estavam em escalas diferentes — os símbolos de Gilts e UK100 estão em escalas diferentes. Usamos a solução de pseudo-inversa para calcular os parâmetros do nosso modelo.
Além disso, guiamos nosso modelo de IA com análise técnica, portanto nosso sistema só entrará em uma operação se os indicadores técnicos também apontarem para a mesma conclusão. Por fim, também usamos nosso sistema de IA para nos ajudar a detectar possíveis reversões e decidir quando fechar nossas posições. Nos nossos artigos anteriores, ao desenvolver modelos lineares do zero, um dos usuários comentou que a saída do modelo estava fora da faixa aceitável. Neste artigo, tentamos resolver esse problema incluindo uma coluna para o intercepto do modelo e padronizando e escalando os dados.
Implementação em MQL5
Para começar, primeiro construímos um script em MQL5 para entender como todas as partes do nosso Expert Advisor se encaixariam. Primeiramente, temos que definir os parâmetros de entrada da aplicação. Precisamos definir quanto de dados buscar e até que ponto no futuro devemos fazer a previsão. Lembre-se que quanto mais dados você buscar, mais intensivo computacionalmente será o aplicativo. Portanto, tentamos encontrar um equilíbrio aqui, permitindo que o usuário final busque tantos dados quanto acreditar que seus recursos suportam. Além disso, devemos ter em mente que os regimes de mercado mudam. Portanto, pode não haver melhora no desempenho ao buscar todos os dados disponíveis.
Atualmente, as cotações do mercado são oferecidas de forma algorítmica, ao contrário do sistema de pregão aberto que a precedeu. Pode não haver valor em estudar cotações de mercado com base em comportamentos de mercado que provavelmente nunca mais veremos. Portanto, restringiremos nosso foco apenas aos dados mais recentes.
//+------------------------------------------------------------------+ //| UK100 Gilts.mq5 | //| Gamuchirai Zororo Ndawana | //| https://www.mql5.com/en/gamuchiraindawa | //+------------------------------------------------------------------+ #property copyright "Gamuchirai Zororo Ndawana" #property link "https://www.mql5.com/en/gamuchiraindawa" #property version "1.00" #property script_show_inputs //+------------------------------------------------------------------+ //| Inputs | //+------------------------------------------------------------------+ input int fetch = 20; //How much data should we fetch? input int look_ahead = 20; //How far into the future should we forecast?
Agora podemos começar a definir o núcleo do nosso script. Primeiro, definiremos variáveis que serão usadas ao longo do script.
//+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- Global variables we will need inside our expert advisor matrix coefficients = matrix::Zeros(1,9); vector mean_values = vector::Zeros(8); vector std_values = vector::Zeros(8); vector intercept = vector::Ones(fetch); matrix input_matrix = matrix::Zeros(9,fetch); matrix gilts_data,uk100_data,target;
Agora vamos buscar os dados necessários. Note que os dados de entrada estão sendo defasados por um número de etapas (look_ahead) e os dados-alvo estão sendo buscados à frente dos dados de entrada.
//--- First we will fetch the market data gilts_data.CopyRates("UKGB_Z4",PERIOD_CURRENT,COPY_RATES_OHLC,1+look_ahead,fetch); uk100_data.CopyRates("UK100",PERIOD_CURRENT,COPY_RATES_OHLC,1+look_ahead,fetch); target.CopyRates("UK100",PERIOD_CURRENT,COPY_RATES_CLOSE,1,fetch);
Agora precisamos criar uma matriz de entrada. A primeira coluna da nossa matriz de entrada será composta pelo número um, repetido tantas vezes quanto os dados de entrada buscados. Isso ocorre porque essa entrada de uns deve ser multiplicada pelo cálculo do termo de viés em nosso modelo linear. A partir daí, preenchemos os dados relacionados aos títulos do governo do Reino Unido e ao FTSE 100.
//--- Fill in the input matrix input_matrix.Row(intercept,0); input_matrix.Row(gilts_data.Row(0),1); input_matrix.Row(gilts_data.Row(1),2); input_matrix.Row(gilts_data.Row(2),3); input_matrix.Row(gilts_data.Row(3),4); input_matrix.Row(uk100_data.Row(0),5); input_matrix.Row(uk100_data.Row(1),6); input_matrix.Row(uk100_data.Row(2),7); input_matrix.Row(uk100_data.Row(3),8);
Vamos verificar os dados que buscamos, para garantir que estão no tamanho correto e que as matrizes que temos são compatíveis para as manipulações que estamos prestes a realizar. Note que se nossas matrizes não estiverem nos tamanhos apropriados, nossos cálculos falharão e retornarão erros na execução.
//--- Display the data fetched Print("Input matrix: "); Print("Rows: ",input_matrix.Rows()," Columns: ",input_matrix.Cols()); Print(input_matrix); Print("Target: "); Print("Rows: ",target.Rows()," Columns: ",target.Cols()); Print(target); Print("UK100: "); Print("Rows: ",uk100_data.Rows()," Columns: ",uk100_data.Cols()); Print(uk100_data); Print("GILTS: "); Print("Rows: ",gilts_data.Rows()," Columns: ",gilts_data.Cols()); Print(gilts_data);
Para escalar e normalizar nossos dados de entrada, precisamos calcular a média e o desvio padrão de cada coluna com que estamos lidando. Quando comecei a aprender machine learning, eu não sabia quando era necessário escalar e padronizar os dados. No entanto, com o tempo aprendi uma regra prática: o escalonamento é necessário quando suas entradas estão em escalas diferentes. Por exemplo, nossos dados do mercado de gilts variam na casa das centenas, mas os dados do mercado FTSE100 variam na casa dos 8000 — portanto, aqui o escalonamento é necessário. Note que nunca é necessário escalar o alvo (target).
//--- Calculate the scaling values mean_values = input_matrix.Mean(1); std_values = input_matrix.Std(1); Print("Mean values: "); Print(mean_values); Print("Std values: "); Print(std_values);
Note que nunca é necessário escalar o alvo (target). Essa etapa de pré-processamento ajuda nosso modelo a aprender com mais eficácia, sendo crítica quando os dados de entrada estão em escalas diferentes, como no nosso caso.
//--- Normalizing and scaling our input data for(int i = 0; i < 8; i++) { //--- Extract the vector vector temp = input_matrix.Row(i + 1); //--- Scale the data temp = ((temp - mean_values[i+1]) / std_values[i+1]); //--- Write the data back input_matrix.Row(temp,i+1); } //--- Finished normalizing the data Print("Finished normalizing the data."); Print(input_matrix);
Agora vamos calcular os parâmetros do nosso modelo, os coeficientes do nosso modelo linear. Podemos fazer isso realizando uma multiplicação de matrizes entre os dados-alvo e a pseudo-inversa dos dados de entrada. Isso nos retorna uma matriz 1xn com 1 valor de coeficiente para cada coluna da matriz. O sinal de cada valor do coeficiente nos indica a inclinação, ou seja, se o valor alvo aumenta ou diminui à medida que a variável de entrada aumenta.
//--- Now we can calculate our coefficient values coefficients = target.MatMul(input_matrix.PInv()); Print("Coefficient values"); Print(coefficients);
Para obter uma previsão do nosso modelo, primeiro precisamos buscar os valores atuais dos dados de entrada, escalá-los e então aplicar a fórmula de regressão linear para obter a previsão do nosso modelo.
//--- Now we can obtain a forecast from our model gilts_data.CopyRates("UKGB_Z4",PERIOD_CURRENT,COPY_RATES_OHLC,0,1); uk100_data.CopyRates("UK100",PERIOD_CURRENT,COPY_RATES_OHLC,0,1); //--- Scale our inputs gilts_data[0,0] = ((gilts_data[0,0] - mean_values[1]) / std_values[1]); gilts_data[1,0] = ((gilts_data[1,0] - mean_values[2]) / std_values[2]); gilts_data[2,0] = ((gilts_data[2,0] - mean_values[3]) / std_values[3]); gilts_data[3,0] = ((gilts_data[3,0] - mean_values[4]) / std_values[4]); uk100_data[0,0] = ((uk100_data[0,0] - mean_values[5]) / std_values[5]); uk100_data[1,0] = ((uk100_data[1,0] - mean_values[6]) / std_values[6]); uk100_data[2,0] = ((uk100_data[2,0] - mean_values[7]) / std_values[7]); uk100_data[3,0] = ((uk100_data[3,0] - mean_values[8]) / std_values[8]); Print("Normalized inputs: "); Print(gilts_data); Print(uk100_data); double forecast = ( (1 * coefficients[0,0]) + (gilts_data[0,0] * coefficients[0,1]) + (gilts_data[1,0] * coefficients[0,2]) + (gilts_data[2,0] * coefficients[0,3]) + (gilts_data[3,0] * coefficients[0,4]) + (uk100_data[0,0] * coefficients[0,5]) + (gilts_data[1,0] * coefficients[0,6]) + (gilts_data[2,0] * coefficients[0,7]) + (gilts_data[3,0] * coefficients[0,8]) ); //--- Give our predictions Comment("Model forecast: ",forecast);
Fig 1: Nosso script
Fig 2: Entradas do nosso script
Fig 3: Previsão do nosso modelo
Construindo Nosso Expert Advisor em MQL5
Agora que chegamos até aqui, estamos prontos para começar a construir nosso Expert Advisor. Para começar a construir nossa aplicação, primeiro vamos importar a biblioteca de negociação para que possamos gerenciar nossas posições.
//+------------------------------------------------------------------+ //| UK100 Gilts.mq5 | //| Gamuchirai Zororo Ndawana | //| https://www.mql5.com/en/gamuchiraindawa | //+------------------------------------------------------------------+ #property copyright "Gamuchirai Zororo Ndawana" #property link "https://www.mql5.com/en/gamuchiraindawa" #property version "1.00" //+------------------------------------------------------------------+ //|Libraries we need | //+------------------------------------------------------------------+ #include <Trade/Trade.mqh> //Trade class CTrade Trade; //Initialize the class
Em seguida, vamos configurar as entradas da nossa aplicação para que o usuário final possa decidir quanto de dados buscar e quão longe no futuro devemos fazer a previsão.
//+------------------------------------------------------------------+ //| Inputs | //+------------------------------------------------------------------+ input int fetch = 20; //How much data should we fetch? input int look_ahead = 20; //How far into the future should we forecast?
Também precisamos de variáveis globais que serão usadas em todo o programa.
//+------------------------------------------------------------------+ //| Global vairables | //+------------------------------------------------------------------+ matrix coefficients = matrix::Zeros(1,9); vector mean_values = vector::Zeros(8); vector std_values = vector::Zeros(8); vector intercept = vector::Ones(fetch); matrix input_matrix = matrix::Zeros(9,fetch); matrix gilts_data,uk100_data,target; double willr_buffer[],rsi_buffer[]; int willr_handler,rsi_handler; double forecast,bid,ask; int model_forecast = 0; int state = 0;
Vamos definir uma função responsável por buscar nossos dados de treinamento e obter os valores de escala que precisamos para padronizar e escalonar nossos dados. Observe que estamos usando matrizes em vez de arrays, pois pretendemos tirar proveito das funções especializadas de matrizes e vetores incluídas na API do MQL5.
//+------------------------------------------------------------------+ //| Let us fetch our training data | //+------------------------------------------------------------------+ void fetch_training_data(void) { //--- First we will fetch the market data gilts_data.CopyRates("UKGB_Z4",PERIOD_CURRENT,COPY_RATES_OHLC,1+look_ahead,fetch); uk100_data.CopyRates("UK100",PERIOD_CURRENT,COPY_RATES_OHLC,1+look_ahead,fetch); target.CopyRates("UK100",PERIOD_CURRENT,COPY_RATES_CLOSE,1,fetch); //--- Fill in the input matrix input_matrix.Row(intercept,0); input_matrix.Row(gilts_data.Row(0),1); input_matrix.Row(gilts_data.Row(1),2); input_matrix.Row(gilts_data.Row(2),3); input_matrix.Row(gilts_data.Row(3),4); input_matrix.Row(uk100_data.Row(0),5); input_matrix.Row(uk100_data.Row(1),6); input_matrix.Row(uk100_data.Row(2),7); input_matrix.Row(uk100_data.Row(3),8); //--- Display the data fetched Print("Input matrix: "); Print("Rows: ",input_matrix.Rows()," Columns: ",input_matrix.Cols()); Print(input_matrix); Print("Target: "); Print("Rows: ",target.Rows()," Columns: ",target.Cols()); Print(target); Print("UK100: "); Print("Rows: ",uk100_data.Rows()," Columns: ",uk100_data.Cols()); Print(uk100_data); Print("GILTS: "); Print("Rows: ",gilts_data.Rows()," Columns: ",gilts_data.Cols()); Print(gilts_data); //--- Calculate the scaling values mean_values = input_matrix.Mean(1); std_values = input_matrix.Std(1); Print("Mean values: "); Print(mean_values); Print("Std values: "); Print(std_values); } //+------------------------------------------------------------------+
Agora que temos nossos valores de escala, vamos definir uma função para realmente escalonar e padronizar nossos dados de entrada.
//+------------------------------------------------------------------+ //| Let us scale and standardize the training data | //+------------------------------------------------------------------+ void scale_training_data(void) { //--- Normalizing and scaling our input data for(int i = 0; i < 8; i++) { //--- Extract the vector vector temp = input_matrix.Row(i + 1); //--- Scale the data temp = ((temp - mean_values[i+1]) / std_values[i+1]); //--- Write the data back input_matrix.Row(temp,i+1); } //--- Finished normalizing the data Print("Finished normalizing the data."); Print(input_matrix); }
Depois que nossos dados de treinamento forem escalonados e padronizados, estaremos prontos para calcular os parâmetros do nosso modelo.
//+------------------------------------------------------------------+ //| Calculate coefficient values | //+------------------------------------------------------------------+ void calculate_coefficient_values(void) { //--- Now we can calculate our coefficient values coefficients = target.MatMul(input_matrix.PInv()); Print("Coefficient values"); Print(coefficients); }
Também precisamos de uma função responsável por obter uma previsão do nosso modelo. Nosso procedimento é simples: primeiro buscamos os dados do mercado, escalamos os dados e, por fim, aplicamos a fórmula de regressão linear para obter uma previsão.
//+------------------------------------------------------------------+ //| Fetch a forecast from our model | //+------------------------------------------------------------------+ void fetch_forecast(void) { //--- Now we can obtain a forecast from our model gilts_data.CopyRates("UKGB_Z4",PERIOD_CURRENT,COPY_RATES_OHLC,0,1); uk100_data.CopyRates("UK100",PERIOD_CURRENT,COPY_RATES_OHLC,0,1); //--- Scale our inputs gilts_data[0,0] = ((gilts_data[0,0] - mean_values[1]) / std_values[1]); gilts_data[1,0] = ((gilts_data[1,0] - mean_values[2]) / std_values[2]); gilts_data[2,0] = ((gilts_data[2,0] - mean_values[3]) / std_values[3]); gilts_data[3,0] = ((gilts_data[3,0] - mean_values[4]) / std_values[4]); uk100_data[0,0] = ((uk100_data[0,0] - mean_values[5]) / std_values[5]); uk100_data[1,0] = ((uk100_data[1,0] - mean_values[6]) / std_values[6]); uk100_data[2,0] = ((uk100_data[2,0] - mean_values[7]) / std_values[7]); uk100_data[3,0] = ((uk100_data[3,0] - mean_values[8]) / std_values[8]); Print("Normalized inputs: "); Print(gilts_data); Print(uk100_data); //--- Calculate the model's prediction forecast = ( (1 * coefficients[0,0]) + (gilts_data[0,0] * coefficients[0,1]) + (gilts_data[1,0] * coefficients[0,2]) + (gilts_data[2,0] * coefficients[0,3]) + (gilts_data[3,0] * coefficients[0,4]) + (uk100_data[0,0] * coefficients[0,5]) + (gilts_data[1,0] * coefficients[0,6]) + (gilts_data[2,0] * coefficients[0,7]) + (gilts_data[3,0] * coefficients[0,8]) ); //--- Store the model's prediction if(forecast < iClose("UK100",PERIOD_CURRENT,0)) { model_forecast = -1; } if(forecast > iClose("UK100",PERIOD_CURRENT,0)) { model_forecast = 1; } //--- Give the user feedback Comment("Model forecast: ",forecast); }
Por fim, também precisamos de uma função para buscar os dados atuais do mercado e os dados dos indicadores técnicos.
//+------------------------------------------------------------------+ //| This function will fetch current market data | //+------------------------------------------------------------------+ void update_market_data(void) { //--- Market prices bid = SymbolInfoDouble("UK100",SYMBOL_BID); ask = SymbolInfoDouble("UK100",SYMBOL_ASK); //--- Technical indicators CopyBuffer(rsi_handler,0,0,1,rsi_buffer); CopyBuffer(willr_handler,0,0,1,willr_buffer); }
Também precisamos de duas funções que validem a previsão do nosso modelo de IA com base nas leituras dos indicadores técnicos. Queremos entrar apenas em setups de alta probabilidade, quando nossa análise técnica e quantitativa apontarem na mesma direção.
//+------------------------------------------------------------------+ //| This function will check if we have oppurtunities to buy | //+------------------------------------------------------------------+ void check_bullish_sentiment(void) { if((willr_buffer[0] > -20) && (rsi_buffer[0] > 70)) { Trade.Buy(0.2,"UK100",ask,ask-5,ask+5,"UK100 Gilts AI"); state = 1; } } //+------------------------------------------------------------------+ //| This function will check if we have oppurtunities to sell | //+------------------------------------------------------------------+ void check_bearish_sentiment(void) { if((willr_buffer[0] < -80) && (rsi_buffer[0] <370)) { Trade.Sell(0.2,"UK100",ask,ask-5,ask+5,"UK100 Gilts AI"); state = -1; } }
Além disso, agora estamos prontos para começar a definir o procedimento de inicialização do nosso Expert Advisor. Primeiro, precisamos buscar os dados de treinamento, depois escalá-los e padronizá-los. Em seguida, calcularemos os valores dos coeficientes e, por fim, configuraremos nossos indicadores técnicos e validaremos se os mesmos estão operacionais.
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Fetch the training data fetch_training_data(); //--- Scale the training data scale_training_data(); //--- Calculate the coefficients calculate_coefficient_values(); //--- Setup the indicators rsi_handler = iRSI("UK100",PERIOD_CURRENT,20,PRICE_CLOSE); willr_handler = iWPR("UK100",PERIOD_CURRENT,30); //--- Validate the technical indicators if((rsi_handler == INVALID_HANDLE) || (willr_handler == INVALID_HANDLE)) { Comment("Failed to load indicators. ",GetLastError()); return(INIT_FAILED); } //--- Everything went well return(INIT_SUCCEEDED); }
Sempre que nosso Expert Advisor for removido do gráfico, liberaremos os recursos que não estivermos mais utilizando. Desanexaremos os indicadores usados na nossa análise técnica e, além disso, também removeremos nosso Expert Advisor do gráfico.
//+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- Free up the resoruces we don't need IndicatorRelease(willr_handler); IndicatorRelease(rsi_handler); ExpertRemove(); }
Sempre que recebermos preços atualizados, primeiro atualizaremos nossos dados de mercado, depois buscaremos uma previsão do nosso modelo de IA. Se não tivermos posições abertas, verificaremos se nossos indicadores técnicos estão alinhados com nosso modelo de IA antes de abrirmos novas posições. Caso contrário, se já tivermos posições abertas, verificaremos se nosso modelo de IA está prevendo uma reversão contra a posição aberta. Se nosso modelo estiver prevendo uma reversão, fecharemos as posições abertas.
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- Fetch updated market data update_market_data(); //--- Fetch a forecast from our model fetch_forecast(); //--- Check for a position we can open if(PositionsTotal() == 0) { if(model_forecast == 1) { check_bullish_sentiment(); } else if(model_forecast == -1) { check_bearish_sentiment(); } } //--- Check for a reversal else if(PositionsTotal() > 0) { if(model_forecast != state) { Alert("Reversal detected by our AI system! Closing all positions now."); Trade.PositionClose("UK100"); } } } //+------------------------------------------------------------------+
Fig 4: Nosso sistema de IA em ação
Conclusão
No artigo de hoje, demonstramos como você pode construir um Expert Advisor guiado por IA em MQL5. A maior vantagem da nossa abordagem é que podemos mudar o time-frame sem precisar recalibrar a aplicação, enquanto que, se implementássemos a solução usando ONNX, precisaríamos de pelo menos um modelo ONNX para cada time-frame em que desejássemos operar. Nossa solução atual é auto-otimizável e capaz de operar sob várias condições diferentes.
Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/15771





- 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
Confira o novo artigo: Reimaginando estratégias clássicas na MQL5 (Parte II): FTSE100 e Gilts do Reino Unido.
Autor: Gamuchirai Zororo Ndawana
Boa explicação de cada seção do código.