![Técnicas do MQL5 Wizard que você deve conhecer (14): Previsão de Séries Temporais Multiobjetivo com STF](https://c.mql5.com/2/73/MQL5_Wizard_tPart_140._Multi_Objective_Timeseries_Forecasting_with_STF_600x314.jpg)
Técnicas do MQL5 Wizard que você deve conhecer (14): Previsão de Séries Temporais Multiobjetivo com STF
Introdução
Este artigo sobre Fusão Espaço-Temporal (STF) despertou meu interesse sobre o assunto, graças à sua abordagem de duas faces para a previsão. Para refrescar a memória, o artigo é inspirado na solução de um problema de previsão baseado em probabilidade que é colaborativo tanto para a oferta quanto para a demanda em plataformas de transporte por aplicativo de duas faces, como Uber e Didi. Relações colaborativas de oferta e demanda são comuns em vários mercados de duas faces, como Amazon, Airbnb e eBay, onde, essencialmente, a empresa não serve apenas o 'cliente' ou comprador tradicional, mas também atende aos fornecedores do cliente.
Portanto, a previsão de duas faces, em um caso onde a oferta é parcialmente dependente da demanda, pode ser importante para essas empresas de forma frequente. Essa projeção dupla, entretanto, de demanda e oferta, certamente foi uma ruptura em relação à abordagem convencional de prever um valor específico para uma série temporal ou conjunto de dados. O artigo também introduziu o que chamou de framework causaltrans, onde a relação causal 'colaborativa' entre oferta e demanda foi capturada por uma matriz G, e todas as previsões foram feitas via rede de transformadores, com resultados notáveis.
Inspirados por isso, buscamos prever oferta e demanda para títulos negociados, usando o pessimismo e otimismo como proxies para essas duas métricas. Estritamente falando, a classe Expert-Signal típica calcula ambos os valores como inteiros na faixa de 0-100, como pode ser visto nos arquivos da biblioteca MQL5 ou nos arquivos que codificamos nesta série até agora. O que seria novo, no entanto, será a adição de uma matriz espacial e um parâmetro de tempo em nossas previsões (os 2 inputs extras que citamos no artigo).
A quantização espacial dos títulos negociados é subjetiva, assim como a escolha da métrica de tempo. Usando séries de preços máximos e mínimos como âncoras para demanda e oferta, utilizamos os valores de autocorrelação entre esses buffers como coordenadas para uma matriz espacial, bem como o índice do dia da semana como indicador de tempo. Essa abordagem rudimentar, que pode ser personalizada e melhorada, serve aos nossos propósitos para este artigo.
O artigo usou redes de transformadores, que não utilizaremos, pois são ineficientes para nossos propósitos; no entanto, todas as previsões serão feitas por um perceptron multicamadas codificado manualmente. Com tantas bibliotecas e exemplos de código sobre o assunto, pareceria uma perda de tempo tentar codificar o próprio perceptron multicamadas. No entanto, a classe de rede usada tem menos de 300 linhas de comprimento e é razoavelmente escalável no que diz respeito à personalização do número de camadas e tamanho de cada uma, algo que ainda falta na maioria das bibliotecas prontas disponíveis.
Portanto, ao usar uma rede neural singular e não transformadores, a implementação do framework causaltrans do artigo não será realizada aqui. No entanto, ainda temos muito trabalho a fazer com o que vamos usar, já que ainda faremos previsões duplas para demanda e oferta, além de usar uma matriz espacial e o tempo no processo. E, como sempre, existem riscos inerentes em qualquer sistema de negociação, então o leitor é convidado a realizar sua própria diligência antes de utilizar qualquer material compartilhado aqui para uso posterior.
Ilustração do STF
STF é predominantemente usado em sensoriamento remoto e atividades centradas em imagens, onde métricas de espaço e tempo podem ser tangivelmente combinadas.
Se você não está muito interessado em explorar o potencial do STF fora da negociação, pode pular esta seção e continuar para a implementação do MQL5.
Se olharmos para o sensoriamento remoto, por exemplo, as imagens capturadas por satélite capturam o componente espacial dos dados e da região em exame, enquanto o tempo se refere a quando as imagens foram tiradas. Essas informações não apenas podem formar uma série temporal, mas também serem importantes para fazer previsões sobre mudanças no clima, na vida vegetal ou até no habitat animal na área em estudo, tudo graças ao STF.
Vamos considerar, passo a passo, como o STF poderia ajudar com problemas relacionados ao desmatamento e à vegetação. O primeiro passo nisso, como é frequentemente o caso em problemas de aprendizado de máquina, é a coleta de dados. Satélites de sensoriamento remoto capturariam imagens multiespectrais da área de estudo ao longo de um período de tempo. Considerando que os satélites podem ser multiespectrais, capturando informações de comprimentos de onda refletidos e absorvidos não visíveis a olho nu, mas em bandas de comprimento de onda associadas à vegetação, corpos d'água, etc. Tudo isso adiciona uma riqueza (e complexidade) ao tipo de dados que podem ser modelados em uma série, já que essas imagens seriam capturadas ao longo do tempo.
A integração de dados espaciais seria o próximo passo, uma vez que cada imagem já está carimbada com o tempo; um sistema de coordenadas GPS apropriado poderia ser usado para mapear cada imagem, garantindo a consistência das informações espaciais em todas as imagens e em todos os pontos de tempo em que foram capturadas.
Em seguida, seria a normalização de nossos ‘dados’ para garantir que estejam em um formato pertinente à vegetação e ao desmatamento. Uma das formas de conseguir isso é registrando assinaturas espectrais de cada imagem em diferentes pontos de tempo por meio de indexação, para que os dados não sejam apenas mais fáceis de manipular ao treinar modelos, mas também estejam focados no assunto em questão.
Essa normalização também envolveria a detecção de mudanças nas imagens capturadas ao longo do tempo, de forma que características importantes para a vegetação possam ser extraídas ou definidas, e essas podem incluir taxas de crescimento, variações sazonais, padrões de distribuição, etc. Cada uma dessas características poderia formar uma dimensão para os dados.
O treinamento do modelo então segue, e a escolha do modelo pode variar, mas espera-se que uma rede neural seja a principal candidata. Uma boa parte das imagens, que agora estão como dados normalizados, seria usada para isso, com um conjunto de dados menor reservado para teste, como é normalmente o caso.
Portanto, a previsão com o modelo ocorreria após o treinamento e os resultados de teste bem-sucedidos, sendo que a principal coisa a ter em mente é a interpretação, já que muita normalização já foi feita, a reversão teria que ser cuidadosamente feita para as saídas do modelo.
No nosso artigo citado, que foi recentemente aceito pela ACM, as equações para a demanda e oferta futuras são representadas da seguinte forma:
x v (t+δt) = f x (x v (t), G v (t), δt),
y v (t+δt) = f y (x v (t), y v (t), G v (t), δt),
onde:
- x v é a função de demanda em relação ao tempo,
- y v é a função de oferta em relação ao tempo,
- G v também é um vetor ou matriz para informações espaciais,
- δt é o incremento de tempo para o qual a previsão é feita,
- t é o tempo.
Assim, em nosso caso, as funções f x e f y serão redes neurais com os vetores ou matrizes de parâmetros contendo os dados que são alimentados em suas respectivas camadas de entrada.
Implementando STF com MQL5
Para implementar o STF em MQL5, seguiríamos as equações compartilhadas acima para definir como estruturamos os dados de entrada para o nosso modelo. A partir das 2 equações, fica claro que os dados de entrada para cada uma delas geralmente assumem um formato de vetor ou matriz, o que, é claro, apresenta inúmeras possibilidades e desafios. Os possíveis inputs de cada função f nas 2 equações são buffers semelhantes, com a única diferença entre as 2 equações sendo que a equação de oferta depende não apenas de seus valores anteriores, mas também dos de demanda. Isso segue a tese do autor do artigo de que a oferta é dependente da demanda e não vice-versa.
Portanto, o número total de buffers, dado o overlap entre ambas as equações, é 4. Todos estão presentes na equação de oferta, e para listá-los, são eles: demanda anterior, oferta anterior, valores espaciais e o incremento de tempo.
O buffer de demanda é interpretado como um buffer de série temporal de pontos de preço 'bullish' para este artigo. Argumentavelmente, um buffer mais conciso poderia ser o volume real de contratos longos, mas tal informação raramente é compartilhada pelos corretores e, mesmo que fosse, não seria uma representação precisa do volume, dada a natureza fracionada das informações de volume nos mercados de forex. Portanto, os preços altos menos os preços de abertura são escolhidos como um buffer alternativo para contratos longos reais de volume. Outros buffers possíveis que poderiam preencher esse papel poderiam ser métricas específicas da moeda, como taxas de juros, inflação ou até mesmo índices de oferta monetária do banco central. A escolha de Altos menos Preços de Abertura como um buffer destina-se a medir a volatilidade para cima e, como isso pode ser entendido como correlacionado positivamente com contratos de volume longos, é usado como um melhor proxy disponível. Esses valores só podem ser positivos ou zero, com uma leitura zero indicando um "enforcado" ou uma barra de preço plana.
O buffer de oferta, assim como o seu equivalente acima, também será aproximado tomando os Preços de Abertura menos os Preços Mínimos. Isso também pode ser interpretado como uma leitura da volatilidade descendente, que se correlaciona positivamente com contratos de volume bearish. Também como acima, os valores para este buffer serão apenas positivos, com um valor zero indicando uma estrela "Gravestone-Doji" ou uma barra plana. A equação de oferta é diferente da demanda em que toma mais inputs, o que implica que, além disso, seu modelo também será semelhante ao da demanda, mas diferente. Portanto, haverá duas instâncias do modelo de previsão, uma para demanda e outra para oferta. Como nosso resultado final é obter um único sinal, isso será determinado subtraindo a previsão de oferta da previsão de demanda. Lembre-se de que, a partir do que foi dito acima, todos os inputs para o modelo de demanda e oferta são positivos ou zero, então, provavelmente, os outputs também serão, e, portanto, ao subtrair a saída do modelo de oferta da saída de demanda, obtemos um número duplo, cujo valor positivo indicaria otimismo e cujo valor negativo significaria pessimismo.
A escolha do buffer de tempo é simplesmente um índice para o dia da semana. O teste, que será abordado na próxima seção, será feito no período diário, de modo que o índice da semana se encaixa facilmente nisso. Se, no entanto, um período de tempo alternativo fosse considerado, que fosse menor que o período diário, então um índice que abrange dentro de um dia ou até mesmo uma semana poderia ser considerado. Por exemplo, no período de 8 horas, há quinze barras de 8 horas em uma semana de negociação, o que fornece quinze possíveis índices de tempo intra-semana. Você poderia escolher a hora do dia ou a sessão de negociação de um dia, etc. as opções aqui são muitas, e testes preliminares para escolher o que funciona melhor para o seu sistema de negociação podem ser uma abordagem melhor. Nossa função simples que retorna o índice do dia da semana é a seguinte:
//+------------------------------------------------------------------+ //| Temporal (Time) Indexing function | //+------------------------------------------------------------------+ int CSignalNetwork::T(datetime Time) { MqlDateTime _dt; if(TimeToStruct(Time,_dt)) { if(_dt.day_of_week==TUESDAY) { return(1); } else if(_dt.day_of_week==WEDNESDAY) { return(2); } else if(_dt.day_of_week==THURSDAY) { return(3); } else if(_dt.day_of_week==FRIDAY||_dt.day_of_week==SATURDAY) { return(4); } } return(0); }
A matriz G captura nossos dados espaciais para este modelo, e isso pode ser complicado de definir. Como definimos o espaço em um ambiente de negociação de títulos? Se considerarmos o artigo de referência, por exemplo, uma tabela cruzada de metadados entre oferta e demanda é 'normalizada' ao ser alimentada por meio do que o artigo se refere como Transformadores de Atenção Gráfica (GAT). Eles operam em duas camadas: a primeira camada captura relações complexas de nós, e a segunda camada agrega informações de vizinhos para previsões finais dos nós. As leituras do GAT fazem parte do que é alimentado através das respectivas redes neurais para prever demanda ou oferta. No nosso caso, os metadados para nossos buffers de preços bullish e bearish serão obtidos a partir das leituras de correlação compartilhadas por esses buffers. Essas correlações são capturadas conforme mostrado no código abaixo:
//+------------------------------------------------------------------+ //| Spatial (Space) Indexing function. Returns Matrix Determinant | //| This however can be customised to return all matrix values as | //| a vector, depending on the detail required. | //+------------------------------------------------------------------+ double CSignalNetwork::G(vector &X,vector &Y) { matrix _m; if(X.Size()!=2*m_train_set||Y.Size()!=2*m_train_set) { return(0.0); } _m.Init(2,2); vector _x1,_x2,_y1,_y2; _x1.Init(m_train_set);_x1.Fill(0.0); _x2.Init(m_train_set);_x2.Fill(0.0); _y1.Init(m_train_set);_y1.Fill(0.0); _y2.Init(m_train_set);_y2.Fill(0.0); for(int i=0;i<m_train_set;i++) { _x1[i] = X[i]; _x2[i] = X[i+m_train_set]; _y1[i] = Y[i]; _y2[i] = Y[i+m_train_set]; } _m[0][0] = _x1.CorrCoef(_x2); _m[0][1] = _x1.CorrCoef(_y2); _m[1][0] = _y1.CorrCoef(_x2); _m[1][1] = _y1.CorrCoef(_y2); return(_m.Det()); }
Observe que retornamos um único valor que representa a matriz e não suas leituras individuais, pois estamos usando seu determinante. Leituras individuais também poderiam ser usadas alternativamente, uma vez que os valores de correlação são sempre normalizados de -1,0 a +1,0, o que poderia levar a resultados mais precisos para o modelo em geral. Para nossos propósitos, no entanto, optamos pelo determinante, pois a eficiência é um pouco mais importante, pelo menos para os testes preliminares.
Com todos os 4 buffers de dados mencionados, pode ser útil também falar sobre o nosso modelo muito rudimentar, que é uma rede neural simples, codificada sem o uso de bibliotecas. Decompomos uma rede em seus componentes mais básicos: inputs, pesos, biases, saídas ocultas, saídas e alvo; e usamos apenas esses componentes para fazer forward feeds e backpropagation. Nossa interface de rede é a seguinte:
//+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class Cnetwork { protected: matrix weights[]; vector biases[]; vector inputs; vector hidden_outputs[]; vector target; int hidden_layers; double Softplus(double X); double SoftplusDerivative(double X); public: vector output; void Get(vector &Target) { target.Copy(Target); } void Set(vector &Inputs) { inputs.Copy(Inputs); } bool Get(string File, double &Criteria, datetime &Version); bool Set(string File, double Criteria); void Forward(); void Backward(double LearningRate); void Cnetwork(int &Settings[],double InitialWeight,double InitialBias) { ... ... }; void ~Cnetwork(void) { }; };
Além das funções comuns para definir e obter inputs e alvos, também estão incluídas algumas funções de exportação para pesos e vieses após o treinamento. O algoritmo de feed forward é comum, utilizando soft-plus para ativação em cada camada, e a função de back-propagation também é tradicional, dependendo da regra da cadeia e dos métodos de descida de gradiente para ajustar os pesos e vieses da rede. No entanto, a inicialização da rede requer alguns inputs, e esses passam por uma 'validação' antes que a instância da classe possa ser usada com segurança. Os inputs para criar a rede são o array de configurações, o valor para pesos iniciais (em toda a rede), bem como os valores iniciais de vieses. O array de configurações determina o número de camadas ocultas que a rede terá pelo seu próprio tamanho, e cada número inteiro em seus índices define o tamanho da respectiva camada.
void Cnetwork(int &Settings[],double InitialWeight,double InitialBias) { int _size = ArraySize(Settings); if(_size >= 2 && _size <= USHORT_MAX && Settings[ArrayMinimum(Settings)] > 0 && Settings[ArrayMaximum(Settings)] < USHORT_MAX) { ArrayResize(weights, _size - 1); ArrayResize(biases, _size - 1); ArrayResize(hidden_outputs, _size - 2); hidden_layers = _size - 2; for(int i = 0; i < _size - 1; i++) { weights[i].Init(Settings[i + 1], Settings[i]); weights[i].Fill(InitialWeight); biases[i].Init(Settings[i + 1]); biases[i].Fill(InitialBias); if(i < _size - 2) { hidden_outputs[i].Init(Settings[i + 1]); hidden_outputs[i].Fill(0.0); } } output.Init(Settings[_size - 1]); target.Init(Settings[_size - 1]); } else { printf(__FUNCSIG__ + " invalid network settings. "); //~Cnetwork(void); } };
Como estamos prevendo tanto a demanda quanto a oferta, precisaremos de duas instâncias separadas da nossa rede, uma para lidar com cada tarefa. Nossa função get output, que atua como um feed para as funções Check Open Long e Check Open Short, preencherá as respectivas camadas de entrada de cada rede com os buffers de dados já mencionados acima. Para a demanda, como a demanda depende apenas de seus valores anteriores, além dos parâmetros de espaço e tempo, sua camada de entrada tem tamanho 3; no entanto, a oferta, além de depender de seus valores anteriores, pode ser influenciada pela demanda anterior, então sua camada de entrada tem tamanho 4, se você considerar os inputs semelhantes de espaço e tempo. O preenchimento dessas camadas é tratado dentro da função get output em cada nova barra, da seguinte forma:
//+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double CSignalNetwork::GetOutput() { ... ... for(int i = 0; i < m_train_set; i++) { for(int ii = 0; ii < __LONGS_INPUTS; ii++) { if(ii==0)//time { m_model_longs.x[i][ii] = T(m_time.GetData(i)); } else if(ii==1)//spatial matrix { vector _x,_y; _x.CopyRates(m_symbol.Name(),m_period,2,StartIndex() + ii + i,2*m_train_set); _y.CopyRates(m_symbol.Name(),m_period,4,StartIndex() + ii + i,2*m_train_set); m_model_longs.x[i][ii] = G(_x,_y); } else if(ii==2)//demand { m_model_longs.x[i][ii] = (m_high.GetData(StartIndex() + ii + i) - m_open.GetData(StartIndex() + ii + i)); } } if(i > 0) //assign classifier { m_model_longs.y[i - 1] = (m_high.GetData(StartIndex() + i - 1) - m_open.GetData(StartIndex() + i - 1)); } } for(int i = 0; i < m_train_set; i++) { for(int ii = 0; ii < __SHORTS_INPUTS; ii++) { if(ii==0)//time { m_model_shorts.x[i][ii] = T(m_time.GetData(i)); } else if(ii==1)//spatial matrix { vector _x,_y; _x.CopyRates(m_symbol.Name(),m_period,4,StartIndex() + ii + i,2*m_train_set); _y.CopyRates(m_symbol.Name(),m_period,2,StartIndex() + ii + i,2*m_train_set); m_model_shorts.x[i][ii] = G(_x,_y); } else if(ii==2)//demand { m_model_shorts.x[i][ii] = (m_high.GetData(StartIndex() + ii + i) - m_open.GetData(StartIndex() + ii + i)); } else if(ii==3)//supply { m_model_shorts.x[i][ii] = (m_open.GetData(StartIndex() + ii + i) - m_low.GetData(StartIndex() + ii + i)); } } if(i > 0) //assign classifier { m_model_shorts.y[i - 1] = (m_open.GetData(StartIndex() + i - 1) - m_low.GetData(StartIndex() + i - 1)); } } ... ... }
Após isso, atribuímos valores de input e target para as duas redes, recuperando essas informações da estrutura do modelo nos loops de treinamento, onde cada loop itera através das redes por um número definido de épocas. A partir dos testes preliminares, o número ideal de épocas foi encontrado em cerca de 10.000, com uma taxa de aprendizado de 0,5 por loop de treinamento. Isso é certamente intensivo em computação, por isso os resultados de teste apresentados aqui na próxima seção usam valores muito conservadores de cerca de 250 épocas.
A função set output nos permite registrar os pesos e vieses da rede em cada passagem, desde que os resultados da passagem superem os critérios estabelecidos pelos pesos usados na inicialização. Ao inicializar, há a opção de ler os pesos, e os critérios estabelecidos por esses pesos servem como referência para o teste atual.
Execuções de Teste
Realizamos testes no EURUSD no período diário para o ano de 2023, com configurações de rede muito simples. A rede de previsão de demanda tem 3 camadas no total, com uma camada oculta, e seus tamanhos são 3, 5 e 1. A rede de previsão de oferta também tem 3 camadas, mas como mencionado acima, a camada de entrada tem um tamanho diferente, então seus tamanhos são 4, 5 e 1. O 1 no final de ambas as redes armazena as saídas de cada rede.
Como sempre, montar o código anexado ao final deste artigo em um consultor especialista é realizado via MQL5 Wizard, então, se você é novo ou não está familiarizado, consulte os artigos aqui e aqui para orientação.
Essas duas configurações são muito básicas e, indiscutivelmente, as mais simples que você pode criar, dado que a classe de rede referenciada pode gerar até UCHAR_MAX camadas, cada uma com um tamanho de também UCHAR_MAX, se as configurações de inicialização definirem isso. À medida que mais camadas e até tamanhos maiores de camada são usados, os recursos de computação aumentam; no entanto, vale a pena mencionar que tamanhos de camada na faixa de 100 unidades são geralmente considerados suficientes, mesmo quando configurados com poucas camadas.
Realizamos as execuções, como sempre, sem metas de preço de saída, onde as posições são mantidas até que o sinal seja revertido, pois essa abordagem tende a ser mais de longo prazo e avalia melhor as grandes tendências de preço. Uma passagem de tick real com algumas das configurações ideais nos dá o relatório abaixo:
E a curva de capital mostrada abaixo:
Se analisarmos este relatório, fica claro que poucas negociações foram realizadas ao longo do ano, o que, em primeiro lugar, não é uma coisa ruim, pois a qualidade delas foi sólida, visto que foram mantidas por longos períodos até que as reversões de sinal fossem acionadas e, para este período testado, sofreram quedas mínimas. O problema, porém, é que em mercados laterais ou de whipsaw, muitas vezes é prudente, especialmente em casos onde há alavancagem envolvida, ser mais sensível aos micro-movimentos de preço. No sistema que testamos, estávamos usando o período diário, o que é bom, pois tende a focar na visão geral, mas se fôssemos tornar isso um pouco mais pragmático, teríamos que considerar períodos de tempo menores, provavelmente de 4 horas ou até 1 hora. Quando fazemos isso, nossos recursos de computação para teste aumentam consideravelmente; de fato, dizer que essa relação é exponencial não é um exagero. E lembre-se de que esta era uma rede muito rudimentar de 3 camadas, com a camada oculta tendo 5 pontos e a matriz espacial reduzida a um determinante. Todos esses fatores são importantes porque, à medida que se começa a lidar com períodos de tempo menores, a necessidade de filtrar o ruído torna-se ainda mais importante, e uma das melhores maneiras de fazer isso é sendo um pouco pedante.
Além disso, dentro da classe de rede referenciada, há funções que ajudam a importar e exportar as configurações de peso e viés da rede no início e no final de cada passagem. Eu não as usei para essas execuções de teste, pois isso também estava desacelerando um pouco o processo, mas elas precisariam ser usadas ao testar por períodos prolongados (consideramos apenas um ano para este teste). Quando elas estão sendo usadas, os critérios para os quais as execuções de teste estão sendo realizadas precisam ser cuidadosamente ponderados, pois, por padrão, na classe de rede, "maior é melhor". Então, se alguém está mais preocupado com quedas, por exemplo, o código anexado na classe de rede precisa ser modificado de acordo para refletir isso, de modo que em cada passagem, os pesos escritos no arquivo só sejam atualizados se o valor do critério daquela execução for MENOR que o valor anterior. Isso também implica que o valor inicial ou padrão em cada execução precisa ser DBL_MAX ou um valor suficientemente alto para evitar erros desnecessários.
Conclusão
A capacidade do STF de lidar com previsões duplas certamente apresenta uma abordagem intrigante, que não é muito comum e, indiscutivelmente, tem potencial para refinamento e melhoria. A matriz G para informações espaciais usada em nossos testes, por exemplo, pode ser expandida para uma n x n ao dividir os vetores de dados de entrada em partes menores, e até mesmo cada um de seus valores poderia ser pontos de dados de entrada para uma rede, assim como muitos outros ajustes, mas essas mudanças, entretanto, têm um custo de recursos computacionais.
De fato, de maneira geral, implementar o STF por meio de redes neurais é essencialmente um empreendimento intensivo em computação, que requer testes em grandes quantidades de dados para obter uma validação cruzada confiável. E isso apresenta sua principal limitação, que é ainda mais evidente quando implementado no artigo citado acima, onde transformadores de rede foram usados.
No entanto, é um aspecto desta prática que está sendo lentamente aceito pela indústria, à medida que vemos a NVIDIA se tornando cada vez mais relevante nesse cenário. Modelos alternativos mais eficientes, como florestas aleatórias, poderiam ser explorados, desde que suas configurações acompanhantes também não sejam excessivamente complexas, mas à medida que os custos de computação começam a diminuir, os custos-benefícios disso podem não ser viáveis.
O MQL5 Wizard, no entanto, continua sendo uma ferramenta para prototipagem rápida e teste de ideias, e este artigo sobre Fusão Espaço-Temporal apresenta mais uma ilustração disso.
Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/14552
![Caminhe em novos trilhos: Personalize indicadores no MQL5](https://c.mql5.com/2/0/862_14.png)
![Técnicas do MQL5 Wizard que você deve conhecer (Parte 13): DBSCAN para a Classe de Sinais de Expert](https://c.mql5.com/2/73/MQL5_Wizard_Techniques_you_should_know_Part_13_DBSCAN_for_Expert_Signal_Class___LOGO.png)
![Está chegando o novo MetaTrader 5 e MQL5](https://c.mql5.com/2/0/851_25.jpg)
![Do básico ao intermediário: Comando IF ELSE](https://c.mql5.com/2/90/logo-midjourney_image_15365_401_3870__8.png)
![MQL5 - Linguagem para estratégias de negociação inseridas no terminal do cliente MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- 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