English Русский Deutsch 日本語
preview
Filtragem de Sazonalidade e Período de Tempo para Modelos de Deep Learning ONNX com Python para EA

Filtragem de Sazonalidade e Período de Tempo para Modelos de Deep Learning ONNX com Python para EA

MetaTrader 5Experts | 20 agosto 2024, 10:09
15 0
Javier Santiago Gaston De Iriarte Cabrera
Javier Santiago Gaston De Iriarte Cabrera

Introdução

Depois de ler o artigo: Benefícios da Sazonalidade no Mercado Forex, decidi criar outro artigo para comparar um EA com e sem sazonalidade para ver se ele pode se beneficiar. 

Eu já sabia que os mercados eram influenciados por fatores sazonais. Isso ficou claro quando descobri que Mark Zuckerberg financiou o Facebook com dinheiro de um investidor. Esse investidor havia investido anteriormente o dinheiro do seu Bar Mitzvah em ações de petróleo, prevendo um aumento devido aos furacões esperados no Caribe. Ele havia analisado previsões meteorológicas que indicavam mau tempo durante aquele período.

Estou muito orgulhoso e interessado em escrever este artigo, que tem como objetivo explorar a ideia de que mercado e sazonalidade são bons companheiros. Uma boa abordagem para concretizar isso seria fundir ambos os EAs em um só, mas já temos um artigo sobre isso, aqui está o link: Um exemplo de como fazer ensemble de modelos ONNX no mql5.

Primeiro, vamos comparar modelos com e sem filtragem utilizando um EA, para ver como a filtragem de dados afeta ou não, e, depois disso, discutiremos a sazonalidade com um gráfico, para terminar com um estudo de caso real, para fevereiro de 2024, com e sem sazonalidade. Na última parte do artigo (que considero muito interessante), discutiremos outras abordagens para o EA que já temos no artigo: Como usar modelos ONNX no MQL5, e veremos se podemos nos beneficiar do ajuste fino desses EAs e modelos ONNX. Vou te adiantar que a resposta é sim, podemos.

Para que isso aconteça, primeiro vamos baixar os dados (todos os ticks) com este script: Baixar todos os dados de um símbolo. Basta adicionar o script ao gráfico do símbolo que precisamos estudar e, em algum tempo (menos de uma hora), teremos baixado todos os ticks históricos desse símbolo na nossa pasta Files.

Basta adicionar o script ao gráfico do símbolo que precisamos estudar e, em algum tempo (menos de uma hora), teremos baixado todos os ticks históricos desse símbolo na nossa pasta Files.


Sazonalidade

A sazonalidade no trading é sobre identificar os fluxos regulares nos preços dos ativos que ocorrem de forma previsível ao longo do ano. É como reconhecer que certas ações tendem a ter um desempenho melhor em determinados períodos do que em outros. Vamos explorar essa ideia um pouco mais.

Entendendo a Sazonalidade no Trading:

  • Definição: Sazonalidade significa notar como os preços tendem a flutuar em um padrão recorrente com base na época do ano. Isso pode estar relacionado às estações do ano (como verão ou inverno), estações comerciais (como a correria das compras de fim de ano), ou até meses específicos.
  • Exemplos: Investidores inteligentes ficam de olho nesses padrões porque eles geralmente são confiáveis e lucrativos. Aqui estão alguns exemplos:
    • Sazonalidade Relacionada ao Clima: Assim como o clima afeta as estações agrícolas, também impacta coisas como os preços das commodities e as ações relacionadas. Por exemplo, uma empresa que vende equipamentos de praia pode ver um aumento nas vendas durante o verão, mas uma queda nos meses mais frios, afetando suas ações.
    • Sazonalidade de Feriados: Ações de varejo geralmente veem um aumento durante as frenéticas compras de feriados. Empresas que prosperam nas vendas de fim de ano, como lojas de presentes, tendem a brilhar nesses períodos.
    • Sazonalidade de Resultados Trimestrais: Empresas de capital aberto relatam seus ganhos a cada trimestre, e os preços de suas ações podem reagir de maneira previsível durante essas temporadas.
    • Sazonalidade Fiscal: Eventos relacionados a impostos podem abalar o mercado, especialmente para setores ligados a finanças.
    • Ciclos Naturais: Indústrias como turismo ou energia têm seus próprios padrões sazonais de demanda, como férias de verão ou necessidades de aquecimento no inverno.

Estratégias de Trading Baseadas na Sazonalidade:

  • Os traders podem alavancar a sazonalidade de algumas maneiras:
    • Identificação de Padrões Sazonais: Explorar dados passados para identificar tendências que se repetem em determinados períodos do ano.
    • Sincronização de Trades: Fazer movimentos de entrada e saída de posições com base nessas tendências sazonais.
    • Gerenciamento de Risco: Ajustar o quanto de risco você está assumindo durante períodos voláteis.
    • Rotação de Setores: Alternar investimentos entre setores que tendem a ter um desempenho melhor em diferentes épocas do ano.


Filtragem de Dados

Usaremos o filtro passa-baixa. De acordo com a Wikipedia:

Um filtro passa-baixa é um filtro que permite a passagem de sinais com uma frequência inferior a uma frequência de corte selecionada e atenua sinais com frequências superiores à frequência de corte. A resposta exata em frequência do filtro depende do design do filtro. O filtro às vezes é chamado de filtro corta-altas ou filtro corta-agudos em aplicações de áudio. Um filtro passa-baixa é o complemento de um filtro passa-alta.

Por que escolhemos filtros passa-baixa em vez de filtros passa-alta no trading algorítmico? No trading algorítmico, a preferência por filtros passa-baixa decorre de várias vantagens-chave:
  1. Suavização de Sinais: Filtros passa-baixa suavizam efetivamente os movimentos de preço ruidosos, enfatizando as tendências de longo prazo sobre as flutuações de curto prazo.
  2. Redução de Ruído de Alta Frequência: Eles ajudam a atenuar o ruído de alta frequência, que pode não fornecer informações significativas para as estratégias de trading.
  3. Custos de Transação Mais Baixos: Ao focar em tendências de longo prazo, os filtros passa-baixa podem levar a menos negociações, mais estratégicas, potencialmente reduzindo as despesas de transação.
  4. Melhor Gestão de Riscos: Os filtros passa-baixa contribuem para uma estratégia de negociação mais estável e previsível, reduzindo o impacto das flutuações de mercado de curto prazo.
  5. Alinhamento com o Horizonte de Investimento: Eles são bem adequados para estratégias com horizontes de investimento de longo prazo, capturando tendências ao longo de períodos estendidos de forma eficaz.

Eu pessoalmente uso filtro passa-baixa para filtrar altas frequências. Não faz muito sentido usar um filtro passa-alta aqui.

Isso é o que vamos usar (nota: acabei mudando os parâmetros de order e cutoff_frequency na última parte do artigo para 0,1 de cutoff e order igual a 1, porque acabaram dando melhores resultados). Além disso, o .py correto para filtragem é o da última parte do artigo (lá, usei não apenas melhores parâmetros, mas também usei minmaxscaler para ajustar e reverter).

# Low-pass filter parameters
cutoff_frequency = 0.01  # Cutoff frequency as a proportion of the Nyquist frequency
order = 4

# Apply the low-pass filter
def butter_lowpass_filter(data, cutoff, fs, order):
    nyquist = 0.5 * fs
    normal_cutoff = cutoff / nyquist
    b, a = butter(order, normal_cutoff, btype='low', analog=False)
    print("Filter coefficients - b:", b)
    print("Filter coefficients - a:", a)
    y = lfilter(b, a, data)
    return y

filtered_data_low = butter_lowpass_filter(df2['close'], cutoff_frequency, fs=1, order=order)

Usaremos "onnx_LSTM_simple_filtered.py" e "onnx_LSTM_simple_not_filtered.py" para criar os modelos ONNX e compará-los.

Nota: Usei o modelo v1 e o modelo v2, que têm diferentes parâmetros de filtro passa-baixa.

Aqui estão os resultados:

Vamos usar os mesmos inputs para os EAs

inputs

inputs2

O período de tempo a ser estudado será de primeiro de fevereiro a primeiro de março.

Para o modelo não filtrado:

RMSE         : 0.0010798043714784716
MSE          : 1.165977480664017e-06
R2 score     : 0.8799146678247277

Not filtered


Filtered v1

# Parámetros del filtro pasa bajo

cutoff_frequency = 0.01  # Frecuencia de corte en proporción a la frecuencia de Nyquist

order = 4


RMSE         : 0.0010228999869332884
MSE          : 1.0463243832681218e-06
R2 score     : 0.8922378749062259


filtered v1


Filtered v2

cutoff_frequency = 0.1  # Frecuencia de corte en proporción a la frecuencia de Nyquist

order = 2

RMSE         : 0.0010899163515744447
MSE          : 1.1879176534293484e-06
R2 score     : 0.8775550550819025

filtered v2


Conclusão sobre filtragem

Ele produz melhores resultados apenas quando se usam os parâmetros corretos.

Então, sim. É conveniente usar filtragem.

Código usado e modelos:


Os símbolos são sazonais?

Para esta parte, vamos primeiro ver isso em um gráfico, vamos obter os dados de fevereiro desde 2015 até 2023 e vamos adicionar os dados para ver como eles se comportam ao longo dessas semanas.

Isso é o que podemos ver desse período:

Soma de fevereiro

Conclusão

Podemos ver que há algumas tendências, ou pelo menos não vemos uma linha horizontal preta (linha da soma). Há lacunas entre cada linha, porque o símbolo é negociado ao longo do ano e seus preços flutuam. É por isso que, na próxima parte do artigo, vamos concatenar todos os símbolos por anos em fevereiro e é por isso que precisamos usar um filtro, para que não passe a alta frequência de, por exemplo, a última data de 2022 para o primeiro de fevereiro de 2023 e quando a IA for treinada, por exemplo, no fechamento de uma sexta-feira e na abertura de uma segunda-feira, para que não estude essas mudanças e busque dados mais suavizados.

Scripts e dados utilizados:


Esses dados do símbolo são correlacionados?

A autocorrelação é uma característica dos dados que mostra o grau de similaridade entre valores em intervalos de tempo sucessivos.

Um valor próximo a 1 indica que há uma grande correlação positiva.

Abaixo estão os resultados que obtivemos com autocorrelation.py

[1.         0.99736147 0.99472432 0.99206626 0.98937664 0.98671649
 0.98405706 0.98144222 0.9787753  0.97615525 0.97356318 0.97099777
 0.96848029 0.96602671 0.96360361 0.96113539 0.95865344 0.95615626
 0.95362417 0.95108177 0.94854957 0.94599045 0.94346076 0.94091564
 0.93837742 0.93583734 0.9332909  0.93074655 0.92826504 0.92579028
 0.92330505 0.92084645 0.91834403 0.91581296 0.91328091 0.91076099
 0.90826447]


Criando um modelo ONNX para as estações de fevereiro

Para esta tarefa, só precisamos concatenar todos os dados em um único arquivo CSV e criar um modelo com ele.

Vamos usar o script criado concat_seasonal.py para fazer um único arquivo CSV, que será adicionado ao zip seasonal_feb_concat. Com o script onnx_LSTM_..._seasonals.py, vamos treinar e criar o modelo.

Scripts e dados utilizados:


Resultados dos testes para o modelo sazonal e comparação com o modelo filtrado de 120 dias (1h)

Modelo Sazonal

RMSE         : 0.013137568368684325
MSE          : 0.00017259570264185493
R2 score     : 0.7166764010650979

Embora não sejam surpreendentes, os resultados parecem bons no geral (não apresenta muitos resultados negativos de Sharpe).

Sharpe

sharpe2

seasonal optimization


Se compararmos com o modelo filtrado,

Sharpe filtered

Sharpe filtered 2d

filtered optimization


O que achei curioso é que o número de valores de Sharpe negativos ocupa metade da tabela de otimização para o modelo filtrado, enquanto os negativos para o modelo sazonal ocupam cerca de um quinto da tabela. Isso é notável, porque, mesmo tendo um r2 mais baixo, parece ser um modelo robusto que proporciona retornos lucrativos.

Eu também poderia ter testado o EA sem SL e TP, mas acho uma prática melhor sempre usá-los em EAs.


Código e modelo ONNX utilizados:

ONNX.eurusd.H1.120.Prediction_seasonal.mq5 EURUSD_LSTM_270_1h_filtered_seasonal0.72.onnx onnx_LSTM_simple_EURUSD_concat_seasonals.py



Qual período de tempo usar?

Para esta parte do artigo, ajustei o filtro para obter melhores resultados para o EURUSD.

cutoff_frequency = 0.1  # Frecuencia de corte en proporción a la frecuencia de Nyquist
order = 1

Também modifiquei o filtro:

from sklearn.preprocessing import MinMaxScaler
from scipy.signal import butter, lfilter

# Parámetros del filtro pasa bajo
cutoff_frequency = 0.1  # Frecuencia de corte en proporción a la frecuencia de Nyquist
order = 1

# Aplicar filtro pasa bajo
def butter_lowpass_filter(data, cutoff, fs, order):
    nyquist = 0.5 * fs
    normal_cutoff = cutoff / nyquist
    b, a = butter(order, normal_cutoff, btype='low', analog=False)
    print("Coeficientes del filtro - b:", b)
    print("Coeficientes del filtro - a:", a)
    y = lfilter(b, a, data)
    return y

scaled = MinMaxScaler(feature_range=(0,1))

valores_df1 = df.filter(['close']).values
valores_df1 = pd.DataFrame(valores_df1)
x_features1 = valores_df1[[0]]
valores_df2 = x_features1.values


data_escalada = scaled.fit_transform(valores_df2)

print(data_escalada)

filtered_data_low = butter_lowpass_filter(data_escalada, cutoff_frequency, fs=1, order=order)
print("filtered_data_low",filtered_data_low)

filtered_data_low_unscaled = scaled.inverse_transform(filtered_data_low)

A ordem deve ser arredondada para um preço inteiro.

Essa estratégia é testada ao longo de um mês para o intervalo de 1 hora, especificamente em fevereiro de 2024. Para o intervalo de 30 minutos, o teste é realizado de 1 a 15 de fevereiro, e assim por diante.

Para o intervalo de 15 minutos, realizei testes com e sem filtros. Os resultados indicam que o uso de um filtro com ajuste fino proporciona melhores resultados (pelo menos no geral).

15 minutos com filtro (Sharpe)

testes de 15 minutos com filtro


tester 2d 15 min

testes de 15 min com filtro


LTSM_simple_15m_filtrado.py LSTM.15m.EURUSD.120.0.98.onnx ONNX.eurusd.H1.120.15m_eurusd.mq5


15 min sem filtro

15 min sem testes de filtro

2d 15 min sem filtro

testes de 15 minutos com filtro.

LTSM_simple_15m_filtrado_sin.py LSTM.15m.EURUSD.120.0.98.onnx ONNX.eurusd.H1.120.15m_eurusd.mq5


30 min com filtro (agora sempre usarei filtro)

tester 30 min

tester 30 min 2d

testando 30 min


LSTM.30m.EURUSD.120.0.94.onnx
LTSM_simple_30m_filtrado.py ONNX.eurusd.H1.120.30m_eurusd.mq5


1 hora

Testes de 1 hora

Mapa de calor de testes de 1 hora

Testes de 1 hora


1 hour files.zip (815.64 KB)


2 horas

Como não posso usar um período de dois dias, utilizei um período de um dia (para o valor do próximo dia no EA).

testador 2h

mapa de calor 2h

Teste 2h

gráfico 2h

Backtesting 2h


2h.zip

Como não posso carregar mais de 32 arquivos, os próximos arquivos serão todos carregados em uma pasta.


Conclusão

Parece que, com essa estratégia, à medida que o período aumenta, os resultados parecem mais robustos para todos os TPs e SLs.


Var NextDay

Usei a estratégia deste artigo: Como usar modelos ONNX no mql5, mas como tive bons resultados com a estratégia de 2 horas, e nesse usei o período de 1 dia. Estudaremos outros valores para a variável NextDays.

   if(TimeCurrent()>=ExtNextDay)
     {
      GetMinMax();
      //--- set next day time
      ExtNextDay=TimeCurrent();
      ExtNextDay-=ExtNextDay%PeriodSeconds(PERIOD_D1);
      ExtNextDay+=PeriodSeconds(PERIOD_D1);
     }
void GetMinMax(void)
  {
   vectorf close;
   close.CopyRates(_Symbol,PERIOD_D1,COPY_RATES_CLOSE,0,SAMPLE_SIZE);
   ExtMin=close.Min();
   ExtMax=close.Max();
  }

Agora procederemos ao estudo do EURUSD com período de 30 minutos com dados filtrados, e diferentes períodos de NextDay (Usaremos 1D, 12h e 6h) e discutiremos os resultados.

1D com período de 30 min

1D 30min

Mapa de calor 1D 30min

Teste 1D


12 H com período de 30 min

Testes 12h 30 min

Mapa de calor de 12h

12h testes 30 min


6h com período de 30 min

6h com período de 30 min

Mapa de calor 6h com período de 30 min

Testes 6h 30 min


Os resultados parecem melhores ao ajustar a variável NextDay. Vamos ver como isso evolui em períodos de NextDay mais curtos.

30 min com períodos de NextDay de 4h

Períodos de 4h

Mapas de calor de períodos de 4h

Testes de períodos de 4h


30 min com períodos de NextDay de 2h

30 min 2 h períodos

Mapa de calor de períodos de NextDay de 30 min 2h

Testes de períodos de 2h


30 min com períodos de NextDay de 1h

h1 períodos 30 min

Mapa de calor h1 30 min

Testes 1h 30 min


Parece que, para períodos de pelo menos 30 minutos, cerca de 8 a 12 barras de 30 minutos dão melhores resultados.


Como este "jogo" é para ganhar mais dinheiro, e uma maneira de fazer isso é ter mais operações vencedoras e uma estratégia sólida. Vamos ver se podemos usar esse início para vencer com períodos de 5 minutos, então tentaremos essa estratégia para 5 minutos e 1 hora e 30 minutos para a variável NextDay.

Inputs

5 minutos com variável NextDay de 1h.

Teste de 1h (período de 5 min)

Mapa de calor de 1h (período de 5 min)

Resultados do teste de 1h (5 min)



5 minutos com variável NextDay de 30 min.

Teste de 30 min (5 min)

Mapa de calor de 30 min (5 min)

Teste de 30 min (5 min)

Arquivos usados:   Last files.zip

Outros períodos de tempo parecem ser mais confiáveis, mas, se você quiser outro EA, tem mais para usar.


Por fim, podemos fazer ajustes na estratégia, o que poderia resultar em melhores ou mais sólidos resultados, como estabelecer um limite de tempo ou barras, por exemplo, em períodos de 1 hora, e usar um período de 12 horas para o próximo dia. Poderíamos estabelecer que, uma vez que a ordem seja feita, ela deve permanecer aberta por no máximo 12 horas.

   if(ExtPredictedClass>=0)
     {
      if(PositionSelect(_Symbol))
         CheckForClose();
      else
        {
         CheckForOpen();
         started_time1 = rates[0].time;
         string started_time1_str = TimeToString(started_time1);
int total = PositionsTotal();
   if(total>0)
     {
      datetime started_time2 = rates[0].time;
      string started_time2_str = TimeToString(started_time2);
      int segundos = started_time2 - started_time1;
      Print("Tiempo 1: ", started_time1_str);
      Print("Tiempo 2: ", started_time2_str);
      Print("Diferencia en segundos: ", segundos);
      if((segundos >= days*PeriodSeconds(PERIOD_H12)) && segundos != 0)
        {
         Print("closing position----------------");
         ExtTrade.PositionClose(_Symbol,3);

        }
     }

testador

Mapa de calor

Testes

gráfico


ONNX.eurusd.120.1h_H12_eurusd.v3.mq5
 (9.23 KB)


Conclusão

Vimos temperar, filtrar e comparar modelos, EAs e parâmetros, tentando alcançar melhores resultados com ajustes finos. Espero que você tenha gostado de ler este artigo tanto quanto eu gostei de escrevê-lo. 


Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/14424

Desenvolvendo um sistema de Replay (Parte 61): Dando play no serviço (II) Desenvolvendo um sistema de Replay (Parte 61): Dando play no serviço (II)
Acompanhe neste artigo, as modificações que foram necessárias serem feitas, para que o serviço de replay / simulação, pudesse trabalhar de forma mais eficiente e segura. Aqui também, irei mostrar algo que pode ser de grande interesse para quem deseja fazer um uso mais eficiente das classes. Além de falar e explicar como contornar um problema que existe no MQL5, que reduz a performance do código quando usamos classes.
Redes neurais de maneira fácil (Parte 82): modelos de equações diferenciais ordinárias (NeuralODE) Redes neurais de maneira fácil (Parte 82): modelos de equações diferenciais ordinárias (NeuralODE)
Neste artigo, gostaria de apresentar outro tipo de modelos voltados para o estudo da dinâmica do estado do ambiente.
Está chegando o novo MetaTrader 5 e MQL5 Está chegando o novo MetaTrader 5 e MQL5
Esta é apenas uma breve resenha do MetaTrader 5. Eu não posso descrever todos os novos recursos do sistema por um período tão curto de tempo - os testes começaram em 09.09.2009. Esta é uma data simbólica, e tenho certeza que será um número de sorte. Alguns dias passaram-se desde que eu obtive a versão beta do terminal MetaTrader 5 e MQL5. Eu ainda não consegui testar todos os seus recursos, mas já estou impressionado.
Hibridização de algoritmos populacionais. Estruturas sequenciais e paralelas Hibridização de algoritmos populacionais. Estruturas sequenciais e paralelas
Aqui, vamos mergulhar no mundo da hibridização de algoritmos de otimização, analisando três tipos principais: mistura de estratégias, hibridização sequencial e paralela. Realizaremos uma série de experimentos combinando e testando algoritmos de otimização relevantes.