English Русский 中文 Español Deutsch 日本語
preview
Anotação de dados na análise de série temporal (Parte 2): Criação de conjuntos de dados com rótulos de tendência usando Python

Anotação de dados na análise de série temporal (Parte 2): Criação de conjuntos de dados com rótulos de tendência usando Python

MetaTrader 5Experts | 16 fevereiro 2024, 14:23
178 0
Yuqiang Pan
Yuqiang Pan

Introdução

No artigo anterior, explicamos como rotular dados observando tendências no gráfico e salvando os dados em um arquivo csv. Nesta parte, faremos de maneira diferente: começaremos com os próprios dados.

Vamos processar os dados usando Python. Por que Python? É fácil trabalhar com ele. Além disso, a vasta biblioteca do Python pode nos ajudar a reduzir significativamente o ciclo de desenvolvimento.

Então, vamos começar!

Conteúdo:

  1. Escolhemos a biblioteca Python
  2. Obtemos dados do cliente MT5 usando a biblioteca MetaTrader 5
  3. Vamos converter o formato dos dados
  4. Anotação de dados
  5. Verificação manual
  6. Características


Escolhemos a biblioteca Python

Todos sabemos que o Python tem muitos ótimos desenvolvedores, que criam uma grande diversidade de bibliotecas que tornam o desenvolvimento mais fácil e mais rápido. A seguir, apresento minha coleção de bibliotecas Python. Algumas delas são baseadas em diferentes arquiteturas, algumas podem ser usadas para negociação, e outras para testes históricos. Isso inclui, entre outros, dados rotulados.

  1. statsmodels - módulo Python que permite aos usuários explorar dados, estimar modelos estatísticos e realizar testes estatísticos: http://statsmodels.sourceforge.net
  2. dynts - pacote Python para análise e gerenciamento de séries temporais: https://github.com/quantmind/dynts
  3. PyFlux - biblioteca Python para modelagem de séries temporais e inferência (frequencista e Bayesiana) em modelos: https://github.com/RJT1990/pyflux
  4. tsfresh - autoextração de características relevantes de séries temporais: https://github.com/blue-yonder/tsfresh
  5. hasura/quandl-metabase - inicialização rápida do Hasura para visualização de conjuntos de dados de séries temporais Quandl usando Metabase: https://platform.hasura.io/hub/projects/anirudhm/quandl-metabase-time-series
  6. Facebook Prophet - ferramenta para criar previsões de alta qualidade para dados de séries temporais com múltiplas sazonalidades e crescimento linear ou não linear: https://github.com/facebook/prophet
  7. tsmoothie - biblioteca Python para suavização de séries temporais e detecção de outliers de maneira vetorizada: https://github.com/cerlymarco/tsmoothie
  8. pmdarima - biblioteca estatística projetada para preencher as lacunas nas capacidades de análise de séries temporais do Python, incluindo um equivalente à função: https://github.com/alkaline-ml/pmdarima
  9. gluon-ts - modelagem probabilística de séries temporais em: https://github.com/awslabs/gluon-ts
  10. gs-quant - suíte de ferramentas Python para finanças quantitativas: https://github.com/goldmansachs/gs-quant
  11. willowtree - implementação robusta e flexível em Python da grade de árvore de salgueiro para precificação de derivativos: https://github.com/federicomariamassari/willowtree
  12. financial-engineering - aplicação de métodos de Monte Carlo a projetos de engenharia financeira em Python: https://github.com/federicomariamassari/financial-engineering
  13. optlib - biblioteca Python para precificação de opções financeiras: https://github.com/dbrojas/optlib
  14. tf-quant-finance - biblioteca de alto desempenho TensorFlow para finanças quantitativas: https://github.com/google/tf-quant-finance
  15. Q-Fin - biblioteca Python para matemática financeira: https://github.com/RomanMichaelPaolucci/Q-Fin
  16. Quantsbin - ferramentas para precificação e plotagem de preços de opções vanilla, gregas e outros tipos de análise: https://github.com/quantsbin/Quantsbin
  17. finoptions - implementação completa do pacote R fOptions em Python com implementação parcial de fExoticOptions para precificação de várias opções: https://github.com/bbcho/finoptions-dev
  18. pypme - cálculo do PME (Public Market Equivalent, equivalente ao mercado público): https://github.com/ymyke/pypme
  19. Blankly - teste totalmente integrado em dados históricos, negociação em papel e implantação ao vivo: https://github.com/Blankly-Finance/Blankly
  20. TA-Lib - wrapper Python para TA-Lib (http://ta-lib.org/): https://github.com/mrjbq7/ta-lib
  21. zipline - biblioteca Python para negociação algorítmica: https://github.com/quantopian/zipline
  22. QuantSoftware Toolkit - plataforma de software de código aberto baseada em Python, projetada para auxiliar na criação e gerenciamento de portfólios: https://github.com/QuantSoftware/QuantSoftwareToolkit
  23. finta - indicadores de análise técnica implementados em Pandas: https://github.com/peerchemist/finta
  24. Tulipy - biblioteca de indicadores de análise técnica financeira (bindings Python para tulipindicators):https://github.com/cirla/tulipy
  25. lppls - módulo Python para ajuste do modelo Log-Periodic Power Law Singularity (LPPLS, lei de potência log-periódica de singularidade): https://github.com/Boulder-Investment-Technologies/lppls
Aqui usamos a biblioteca `pytrendseries` para processar dados, rotular tendências e criar conjuntos de dados, já que essa biblioteca é simples de usar e prática a nível visual. Vamos começar a criar nosso conjunto de dados!


Obtemos dados do cliente MT5 usando a biblioteca MetaTrader 5

Se você ainda não tem o Python instalado, eu não recomendo instalar a versão oficial. É melhor usar o Anaconda, que é fácil de manter. A versão padrão do Anaconda é enorme e inclui muito conteúdo: gerenciamento visual, editor e muito mais. Para minha vergonha, quase não uso essa versão e recomendo fortemente a versão simplificada, miniconda. Você pode encontrá-la aqui - Miniconda :: Anaconda.org


1. Inicialização básica do ambiente

    Comece criando um ambiente virtual e abra o tipo Anaconda Promote:

    conda create -n Data_label python=3.10

    env

    Digite "y" e aguarde a criação do ambiente, depois digite:

    conda activate Data_label

    Nota: Ao criar um ambiente virtual conda, adicione python=x.xx, caso contrário, você enfrentará problemas durante o uso.

    2. Instalação da biblioteca necessária

    Vamos instalar nossa biblioteca necessária MetaTrader 5, digitando Promote no conda:

    pip install MetaTrader5

    Instale pytrendseries, digitando no conda Promote:

    pip install pytrendseries

    3. Criação de arquivo Python

    No MetaEditor, vá para "Serviço" -> "Configurações", insira seu caminho para o Python na coluna Python da opção "Compiladores". Meu caminho é G:miniconda3\envs\Data_label:

    instalação

    Em seguida, selecione "Arquivo" -> "Novo arquivo" (ou pressione Ctrl + N) para criar um novo arquivo, e na janela que aparece, selecione "Script em Python":

    f0

    Pressione "Próximo" e digite o nome do arquivo, por exemplo:

    f1

    Após pressionar o botão "OK", a seguinte janela aparecerá:

    f3

    4. Conexão do cliente e obtenção de dados

    Vamos remover o código original automaticamente gerado e substituí-lo pelo seguinte:

    # Copyright 2021, MetaQuotes Ltd.
    # https://www.mql5.com
    
    import MetaTrader5 as mt
    
    if not mt.initialize():
        print('initialize() failed!')
    else:
       print(mt.version())
       mt.shutdown()
    

    Compile e execute para verificar a presença de erros. Se não houver problemas, veremos o seguinte:

    out

    Se aparecer "initialize() failed!", adicione o caminho ao parâmetro na função initialize(), que é o caminho para o arquivo executável do cliente, como mostrado no seguinte código marcado:

    # Copyright 2021, MetaQuotes Ltd.
    # https://www.mql5.com
    
    import MetaTrader5 as mt
    
    if not mt.initialize("D:\\Project\\mt\\MT5\\terminal64.exe"):
        print('initialize() failed!') 
    else:
        print(mt.version())
        mt.shutdown()
    Tudo pronto, vamos obter os dados:
    # Copyright 2021, MetaQuotes Ltd.
    # https://www.mql5.com
    
    import MetaTrader5 as mt
    
    if not mt.initialize("D:\\Project\\mt\\MT5\\terminal64.exe"):
        print('initialize() failed!')
    else:
       sb=mt.symbols_total()
       rts=None
       if sb > 0:    
         rts=mt.copy_rates_from_pos("GOLD_micro",mt.TIMEFRAME_M15,0,10000) 
       mt.shutdown()
       print(rts[0:5])

    No código acima, adicionamos "sb=mt.symbols_total()" para evitar a mensagem de erro, já que os símbolos não foram encontrados, e "copy_rates_from_pos("GOLD_micro", mt. TIMEFRAME_M15,0,10000)" significa copiar 10.000 barras do período GOLD_micro M15. Após a compilação, obteremos o seguinte resultado:

    o0

    Neste momento, obtivemos com sucesso os dados do cliente.

    Vamos converter o formato dos dados

    Embora tenhamos recebido os dados do cliente, o formato dos dados não é o que precisamos. Os dados estão no formato "numpy.ndarray":

    "[(1692368100, 1893.51, 1893.97,1893.08,1893.88,548, 35, 0)

    (1692369000, 1893.88, 1894.51, 1893.41, 1894.51, 665, 35, 0)

    (1692369900, 1894.5, 1894.91, 1893.25, 1893.62, 755, 35, 0)

    (1692370800, 1893.68, 1894.7 , 1893.16, 1893.49, 1108, 35, 0)

    (1692371700, 1893.5 , 1893.63, 1889.43, 1889.81, 1979, 35, 0)

    (1692372600, 1889.81, 1891.23, 1888.51, 1891.04, 2100, 35, 0)

    (1692373500, 1891.04, 1891.3 , 1889.75, 1890.07, 1597, 35, 0)

    (1692374400, 1890.11, 1894.03, 1889.2, 1893.57, 2083, 35, 0)

    (1692375300, 1893.62, 1894.94, 1892.97, 1894.25, 1692, 35, 0)

    (1692376200, 1894.25, 1894.88, 1890.72, 1894.66, 2880, 35, 0)

    (1692377100, 1894.67, 1896.69, 1892.47, 1893.68, 2930, 35, 0) 

    ...

    (1693822500, 1943.97, 1944.28, 1943.24, 1943.31, 883, 35, 0)

    (1693823400, 1943.25, 1944.13, 1942.95, 1943.4 , 873, 35, 0)

    (1693824300, 1943.4, 1944.07, 1943.31, 1943.64, 691, 35, 0)

    (1693825200, 1943.73, 1943.97, 1943.73, 1943.85, 22, 35, 0)]"

    Vamos utilizar o pandas para a conversão. O código adicionado está marcado em verde:

    # Copyright 2021, MetaQuotes Ltd.
    # https://www.mql5.com
    
    import MetaTrader5 as mt
    import pandas as pd
    
    if not mt.initialize("D:\\Project\\mt\\MT5\\terminal64.exe"):
        print('initialize() failed!')
    else:
       print(mt.version())
       sb=mt.symbols_total()
       rts=None
       if sb > 0:
         rts=mt.copy_rates_from_pos("GOLD_micro",mt.TIMEFRAME_M15,0,1000) 
       mt.shutdown()
       rts_fm=pd.DataFrame(rts)

    Agora, vamos olhar novamente para o formato dos dados:

    print(rts_fm.head(10))

    d

    Os dados de entrada devem ser em pandas. O formato DataFrame contém uma coluna como dados observados (em formato float ou int), então precisamos processar os dados no formato requisitado por pytrendseries, da seguinte maneira:
    td_data=rts_fm[['time','close']].set_index('time')

    Vamos ver como ficam as primeiras 10 linhas de dados:

    print(td_data.head(10))


    o2


    Nota:
    "td_data" não é o último estilo de dados, é apenas um produto intermediário para obter as tendências dos dados.

    Nossos dados agora estão totalmente utilizáveis, mas, para realizar operações adicionais é melhor converter nosso formato de data em um frame de dados, então adicionaremos o seguinte código antes de "td_data=rts_fm[['time','close']].set_index('time')":

    rts_fm['time']=pd.to_datetime(rts_fm['time'], unit='s')

    A saída dos dados será assim:

    time close
    2023-08-18 20:45:00
    1888.82000
    2023-08-18 21:00:00 1887.53000
    2023-08-18 21:15:00 1888.10000  
    2023-08-18 21:30:00 1888.98000  
    2023-08-18 21:45:00 1888.37000 
    2023-08-18 22:00:00 1887.51000  
    2023-08-18 22:15:00 1888.21000  
    2023-08-18 22:30:00 1888.73000  
    2023-08-18 22:45:00 1889.12000  
    2023-08-18 23:00:00 1889.20000  

    Código de seção completo:

    # Copyright 2021, MetaQuotes Ltd.
    # https://www.mql5.com
    
    import MetaTrader5 as mt
    import pandas as pd
    
    if not mt.initialize("D:\\Project\\mt\\MT5\\terminal64.exe"):
        print('initialize() failed!')
    else:
       print(mt.version())
       sb=mt.symbols_total()
       rts=None
       if sb > 0:
         rts=mt.copy_rates_from_pos("GOLD_micro",mt.TIMEFRAME_M15,0,1000) 
       mt.shutdown()
       rts_fm=pd.DataFrame(rts)
       rts_fm['time']=pd.to_datetime(rts_fm['time'], unit='s')
       td_data=rts_fm[['time','close']].set_index('time')
       print(td_data.head(10))


    Anotação de dados

    1. Recuperação de dados de tendência

    Primeiro, importamos o pacote pytrendseries:

    import pytrendseries as pts

    Usamos a função pts.detecttrend() para buscar a tendência, em seguida, definimos a variável td para essa função. Para este parâmetro, existem duas opções: "downtrend" (tendência descendente) e "uptrend" (tendência ascendente):

    td='downtrend' # or "uptrend"

    Precisamos de outro parâmetro "wd" como o período máximo de tendência:

    wd=120

    Existe também um parâmetro opcional, mas pessoalmente acho melhor defini-lo, pois este parâmetro determina o período mínimo de tendência:

    limit=6

    Agora podemos preencher os parâmetros da função para obter a tendência:

    trends=pts.detecttrend(td_data,trend=td,limit=limit,window=wd)

    Vamos verificar o resultado:

    print(trends.head(15))

    de até price0 price1 index_from index_to time_span drawdown
    1 2023-08-21 01:00:00 2023-08-21 02:15:00 1890.36000 1889.24000 13 18 5 0.00059
    2 2023-08-21 03:15:00 2023-08-21 04:45:00 1890.61000 1885.28000 22 28 6 0.00282
    3 2023-08-21 08:00:00 2023-08-21 13:15:00 1893.30000 1886.86000 41 62 21 0.00340
    4 2023-08-21 15:45:00 2023-08-21 17:30:00 1896.99000 1886.16000 72 79 7 0.00571
    5 2023-08-21 20:30:00 2023-08-21 22:30:00 1894.77000 1894.12000 91 99 8 0.00034
    6 2023-08-22 04:15:00 2023-08-22 05:45:00 1896.19000 1894.31000 118 124 6 0.00099
    7 2023-08-22 06:15:00 2023-08-22 07:45:00 1896.59000 1893.80000 126 132 6 0.00147
    8 2023-08-22 13:00:00 2023-08-22 16:45:00 1903.38000 1890.17000 153 168 15 0.00694
    9 2023-08-22 19:00:00 2023-08-22 21:15:00 1898.08000 1896.25000 177 186 9 0.00096
    10 2023-08-23 04:45:00 2023-08-23 06:00:00 1901.46000 1900.25000 212 217 5 0.00064
    11 2023-08-23 11:30:00 2023-08-23 13:30:00 1904.84000 1901.42000 239 247 8 0.00180
    12 2023-08-23 19:45:00 2023-08-23 23:30:00 1919.61000 1915.05000 272 287 15 0.00238
    13 2023-08-24 09:30:00 2023-08-25 09:45:00 1921.91000 1912.93000 323 416 93 0.00467
    14 2023-08-25 15:00:00 2023-08-25 16:30:00 1919.88000 1913.30000 437 443 6 0.00343
    15 2023-08-28 04:15:00 2023-08-28 07:15:00 1916.92000 1915.07000 486 498 12 0.00097

    Você também pode visualizar o resultado usando a função "pts.vizplot.plot_trend()":

    pts.vizplot.plot_trend(td_data,trends)

    f1

    Da mesma forma, podemos observar a tendência ascendente no código:

    td="uptrend"
    wd=120
    limit=6
    
    trends=pts.detecttrend(td_data,trend=td,limit=limit,window=wd)
    print(trends.head(15))
    pts.vizplot.plot_trend(td_data,trends)

    O resultado será:

    de até price0 price1 index_from index_to time_span drawup
    1 2023-08-18 22:00:00 2023-08-21 03:15:00 1887.51000 1890.61000 5 22 17 0.00164
    2 2023-08-21 04:45:00 2023-08-22 10:45:00 1885.28000 1901.35000 28 144 116 0.00852
    3 2023-08-22 11:15:00 2023-08-22 13:00:00 1898.78000 1903.38000 146 153 7 0.00242
    4 2023-08-22 16:45:00 2023-08-23 19:45:00 1890.17000 1919.61000 168 272 104 0.01558
    5 2023-08-23 23:30:00 2023-08-24 09:30:00 1915.05000 1921.91000 287 323 36 0.00358
    6 2023-08-24 15:30:00 2023-08-24 17:45:00 1912.97000 1921.24000 347 356 9 0.00432
    7 2023-08-24 23:00:00 2023-08-25 01:15:00 1916.41000 1917.03000 377 382 5 0.00032
    8 2023-08-25 03:15:00 2023-08-25 04:45:00 1915.20000 1916.82000 390 396 6 0.00085
    9 2023-08-25 09:45:00 2023-08-25 17:00:00 1912.93000 1920.03000 416 445 29 0.00371
    10 2023-08-25 17:45:00 2023-08-28 18:30:00 1904.37000 1924.86000 448 543 95 0.01076
    11 2023-08-28 20:00:00 2023-08-29 06:30:00 1917.74000 1925.41000 549 587 38 0.00400
    12 2023-08-29 10:00:00 2023-08-29 12:45:00 1922.00000 1924.21000 601 612 11 0.00115
    13 2023-08-29 15:30:00 2023-08-30 17:00:00 1914.98000 1947.79000 623 721 98 0.01713
    14 2023-08-30 23:45:00 2023-08-31 04:45:00 1942.09000 1947.03000 748 764 16 0.00254
    15 2023-08-31 09:30:00 2023-08-31 15:00:00 1943.52000 1947.00000 783 805 22 0.00179

    f2


    2. Anotação de dados

    1) Analisamos o formato dos dados
      ds

    ① indica o início dos dados até o começo do primeiro tendência descendente. Supomos que seja uma tendência ascendente;

    ② indica uma tendência descendente;

    ③ indica uma tendência ascendente no meio dos dados;

    ④ indica o fim da última tendência descendente.

    Assim sendo, devemos implementar a lógica de rotulação para estas quatro partes.

    2) Lógica de rotulação 

    Começaremos definindo algumas variáveis básicas:

    rts_fm['trend']=0
    rts_fm['trend_index']=0
    max_len_rts=len(rts_fm)
    max_len=len(trends)
    last_start=0
    last_end=0

    Percorremos variável "trends" com um laço for para obter o início e o fim de cada fragmento de dados:

    for trend in trends.iterrows():
            pass

    Recuperaremos os índices inicial e final para cada segmento:

    for trend in trends.iterrows():
        start=trend[1]['index_from']
        end=trend[1]['index_to']

    Como o próprio rts_fm["trend"] é inicializado como igual a 0, não há necessidade de alterar a coluna de tendência para uma tendência ascendente, mas precisamos verificar se o início dos dados é uma tendência descendente. Se não é, então assumimos uma tendência ascendente:

    for trend in trends.iterrows():
        start=trend[1]['index_from']
        end=trend[1]['index_to']
    
        if trend[0]==1 and start!=0:
            # Since the rts_fm["trend"] itself has been initialized to 0, there is no need to change the "trend" column
            rts_fm['trend_index'][0:start]=list(range(0,start))

    Assim como no caso do início dos dados, precisamos verificar se ele termina com uma tendência descendente no final dos dados:

    for trend in trends.iterrows():
        start=trend[1]['index_from']
        end=trend[1]['index_to']
    
        if trend[0]==1 and start!=0:
            # Since the rts_fm["trend"] itself has been initialized to 0, there is no need to change the "trend" column
            rts_fm['trend_index'][0:start]=list(range(0,start))
        elif trend[0]==max_len and end!=max_len_rts-1:
    	#we need to see if it ends in a downtrend at the end of the data
            rts_fm['trend_index'][last_end+1:len(rts_fm)]=list(range(0,max_len_rts-last_end-1))

    Processamento dos segmentos de tendência ascendente, exceto o início e o fim dos dados:

    for trend in trends.iterrows():
        start=trend[1]['index_from']
        end=trend[1]['index_to']
    
        if trend[0]==1 and start!=0:
            # Since the rts_fm["trend"] itself has been initialized to 0, there is no need to change the "trend" column
            rts_fm['trend_index'][0:start]=list(range(0,start))
        elif trend[0]==max_len and end!=max_len_rts-1:
            #we need to see if it ends in a downtrend at the end of the data
            rts_fm['trend_index'][last_end+1:len(rts_fm)]=list(range(0,max_len_rts-last_end-1))
        else:
            #Process the uptrend segments other than the beginning and end of the data
            rts_fm["trend_index"][last_end+1:start]=list(range(0,start-last_end-1))

    Processamos cada segmento de tendência descendente:

    for trend in trends.iterrows():
        start=trend[1]['index_from']
        end=trend[1]['index_to']
    
        if trend[0]==1 and start!=0:
            # Since the rts_fm["trend"] itself has been initialized to 0, there is no need to change the "trend" column
            rts_fm['trend_index'][0:start]=list(range(0,start))
        elif trend[0]==max_len and end!=max_len_rts-1:
            #we need to see if it ends in a downtrend at the end of the data
            rts_fm['trend_index'][last_end+1:len(rts_fm)]=list(range(0,max_len_rts-last_end-1))
        else:
            #Process the uptrend segments other than the beginning and end of the data
            rts_fm["trend_index"][last_end+1:start]=list(range(0,start-last_end-1))
        
        #Process each segments of the downtrend
        rts_fm["trend"][start:end+1]=1
        rts_fm["trend_index"][start:end+1]=list(range(0,end-start+1))
        last_start=start
        last_end=end

    3) Adicionalmente
    Assumimos que o início e o fim dos dados têm uma tendência ascendente. Se você achar que isso não é suficientemente preciso, você também pode remover as partes inicial e final. Para fazer isso, adicione o seguinte código após a conclusão do laço for:

    rts_fm['trend']=0
    rts_fm['trend_index']=0
    max_len_rts=len(rts_fm)
    max_len=len(trends)
    last_start=0
    last_end=0
    for trend in trends.iterrows():
        start=trend[1]['index_from']
        end=trend[1]['index_to']
    
        if trend[0]==1 and start!=0:
            # Since the rts_fm["trend"] itself has been initialized to 0, there is no need to change the "trend" column
            rts_fm['trend_index'][0:start]=list(range(0,start))
        elif trend[0]==max_len and end!=max_len_rts-1:
            #we need to see if it ends in a downtrend at the end of the data
            rts_fm['trend_index'][last_end+1:len(rts_fm)]=list(range(0,max_len_rts-last_end-1))
        else:
            #Process the uptrend segments other than the beginning and end of the data
            rts_fm["trend_index"][last_end+1:start]=list(range(0,start-last_end-1))
        
        #Process each segments of the downtrend
        rts_fm["trend"][start:end+1]=1
        rts_fm["trend_index"][start:end+1]=list(range(0,end-start+1))
        last_start=start
        last_end=end
    rts_fm=rts_fm.iloc[trends.iloc[0,:]['index_from']:end,:]

    3. Verificação

    Agora, vamos verificar se nossos dados correspondem às expectativas (o exemplo considera apenas os primeiros 25 fragmentos de dados):

    rts_fm.head(25)
    time open high low close tick_volume spread real_volume trend trend_index
    0 2023-08-22 11:30:00 1898.80000 1899.72000 1898.22000 1899.30000 877 35 0 0 0
    1 2023-08-22 11:45:00 1899.31000 1899.96000 1898.84000 1899.81000 757 35 0 0 1
    2 2023-08-22 12:00:00 1899.86000 1900.50000 1899.24000 1900.01000 814 35 0 0 2
    3 2023-08-22 12:15:00 1900.05000 1901.26000 1899.99000 1900.48000 952 35 0 0 3
    4 2023-08-22 12:30:00 1900.48000 1902.44000 1900.17000 1902.19000 934 35 0 0 4
    5 2023-08-22 12:45:00 1902.23000 1903.59000 1902.21000 1902.64000 891 35 0 0 5
    6 2023-08-22 13:00:00 1902.69000 1903.94000 1902.24000 1903.38000 873 35 0 1 0
    7 2023-08-22 13:15:00 1903.40000 1904.29000 1901.71000 1902.08000 949 35 0 1 1
    8 2023-08-22 13:30:00 1902.10000 1903.37000 1902.08000 1902.63000 803 35 0 1 2
    9 2023-08-22 13:45:00 1902.64000 1902.75000 1901.75000 1901.80000 1010 35 0 1 3
    10 2023-08-22 14:00:00 1901.79000 1902.47000 1901.33000 1901.96000 800 35 0 1 4
    11 2023-08-22 14:15:00 1901.94000 1903.04000 1901.72000 1901.73000 785 35 0 1 5
    12 2023-08-22 14:30:00 1901.71000 1902.62000 1901.66000 1902.38000 902 35 0 1 6
    13 2023-08-22 14:45:00 1902.38000 1903.23000 1901.96000 1901.96000 891 35 0 1 7
    14 2023-08-22 15:00:00 1901.94000 1903.25000 1901.64000 1902.41000 1209 35 0 1 8
    15 2023-08-22 15:15:00 1902.39000 1903.00000 1898.97000 1899.87000 1971 35 0 1 9
    16 2023-08-22 15:30:00 1899.86000 1901.17000 1896.72000 1896.85000 2413 35 0 1 10
    17 2023-08-22 15:45:00 1896.85000 1898.15000 1896.12000 1897.26000 2010 35 0 1 11
    18 2023-08-22 16:00:00 1897.29000 1897.45000 1895.52000 1895.97000 2384 35 0 1 12
    19 2023-08-22 16:15:00 1895.96000 1896.31000 1893.87000 1894.48000 1990 35 0 1 13
    20 2023-08-22 16:30:00 1894.43000 1894.60000 1892.64000 1893.38000 2950 35 0 1 14
    21 2023-08-22 16:45:00 1893.48000 1894.17000 1888.94000 1890.17000 2970 35 0 1 15
    22 2023-08-22 17:00:00 1890.19000 1894.53000 1889.94000 1894.20000 2721 35 0 0 0
    23 2023-08-22 17:15:00 1894.18000 1894.73000 1891.51000 1891.71000 1944 35 0 0 1
    24 2023-08-22 17:30:00 1891.74000 1893.70000 1890.91000 1893.59000 2215 35 0 0 2

    Você pode ver que conseguimos adicionar aos dados os tipos de tendências e os rótulos dos índices das tendências.

    4. Armazenamento do arquivo

    Podemos salvar os dados na maioria dos formatos. Por exemplo, podemos salvá-los como um arquivo JSON, usando o método to_json(), ou como um arquivo HTML, usando o método to_html(), etc. Como demonstração, usaremos o salvamento no formato CSV. No final do código, adicionamos:

    rts_fm.to_csv('GOLD_micro_M15.csv')


    Verificação manual

    Até agora fizemos o trabalho principal, mas se quisermos obter dados mais precisos, precisaremos de mais intervenção manual no código. Eu destacarei aqui apenas algumas direções e não farei uma demonstração detalhada.

    1. Verificação da integridade dos dados

    Essa verificação pode encontrar informações sobre os dados que estão faltando, o que pode significar a ausência de todos os dados ou a ausência de um campo nos dados. A integridade dos dados é um dos critérios mais fundamentais para avaliar a qualidade dos dados. Por exemplo, se os dados anteriores do mercado de ações para o período M15 diferem em 2 horas dos dados seguintes, precisamos usar as ferramentas apropriadas para completar os dados. Claro, geralmente é difícil obter dados de taxas de câmbio ou dados do mercado de ações do nosso terminal cliente, mas se você está obtendo séries temporais de outras fontes, como dados de tráfego ou dados meteorológicos, você precisa prestar atenção especial a essa situação.

    A integridade da qualidade dos dados é relativamente fácil de avaliar, e geralmente pode ser estimada pelos valores registrados e únicos na estatística dos dados. Por exemplo, se nos dados sobre o preço das ações no período anterior, o preço de fechamento foi de 1000, mas o preço de abertura se torna 10 no período seguinte, você precisa verificar se há dados faltando.


    2. Verificação da precisão da rotulação de dados

    O método de rotulação de dados implementado acima pode ter certas vulnerabilidades. Não podemos confiar apenas nos métodos apresentados na biblioteca pytrendseries para obter dados de rotulação precisos. É necessário visualizar adicionalmente os dados, observar se a classificação de tendências dos dados é muito sensível ou, ao contrário, insensível. Talvez seja necessário dividir os dados em partes ou combiná-los. Isso exige muito esforço e tempo, por isso, ainda não vale a pena dar exemplos específicos.

    O indicador de precisão refere-se à informação registrada nos dados e pode detectar desvios nela. Ao contrário da sequência, dados com problemas de precisão não são apenas discrepâncias nas regras. Problemas de sequência podem ser causados por regras de registro de dados inconsistentes, mas não necessariamente por erros.

    3. Faça uma verificação estatística básica para garantir que a rotulação seja justificada

    • Distribuição da integridade: verifique de forma rápida e intuitiva se um conjunto de dados está completo.
    • Mapa de calor: permite observar facilmente a correlação entre duas variáveis.
    • Agrupamento hierárquico: você pode ver quão intimamente relacionadas estão as diferentes classes dos seus dados.
    Claro, isso não se limita apenas aos métodos listados acima.


    Características

    Referência: GitHub - rafa-rod/pytrendseries

    O código completo é mostrado abaixo:

    # Copyright 2021, MetaQuotes Ltd.
    # https://www.mql5.com
    
    import MetaTrader5 as mt
    import pandas as pd
    import pytrendseries as pts
    
    if not mt.initialize("D:\\Project\\mt\\MT5\\terminal64.exe"):
        print('initialize() failed!')
    else:
       print(mt.version())
       sb=mt.symbols_total()
       rts=None
       if sb > 0:
         rts=mt.copy_rates_from_pos("GOLD_micro",mt.TIMEFRAME_M15,0,1000) 
       mt.shutdown()
       rts_fm=pd.DataFrame(rts)
       rts_fm['time']=pd.to_datetime(rts_fm['time'], unit='s')
       td_data=rts_fm[['time','close']].set_index('time')
       # print(td_data.head(10))
    
    td='downtrend' # or "uptrend"
    wd=120
    limit=6
    
    trends=pts.detecttrend(td_data,trend=td,limit=limit,window=wd)
    # print(trends.head(15))
    # pts.vizplot.plot_trend(td_data,trends)
    
    rts_fm['trend']=0
    rts_fm['trend_index']=0
    max_len_rts=len(rts_fm)
    max_len=len(trends)
    last_start=0
    last_end=0
    for trend in trends.iterrows():
        start=trend[1]['index_from']
        end=trend[1]['index_to']
    
        if trend[0]==1 and start!=0:
            # Since the rts_fm["trend"] itself has been initialized to 0, there is no need to change the "trend" column
            rts_fm['trend_index'][0:start]=list(range(0,start))
        elif trend[0]==max_len and end!=max_len_rts-1:
            #we need to see if it ends in a downtrend at the end of the data
            rts_fm['trend_index'][last_end+1:len(rts_fm)]=list(range(0,max_len_rts-last_end-1))
        else:
            #Process the uptrend segments other than the beginning and end of the data
            rts_fm["trend_index"][last_end+1:start]=list(range(0,start-last_end-1))
        
        #Process each segments of the downtrend
        rts_fm["trend"][start:end+1]=1
        rts_fm["trend_index"][start:end+1]=list(range(0,end-start+1))
        last_start=start
        last_end=end
    #rts_fm=rts_fm.iloc[trends.iloc[0,:]['index_from']:end,:]
    rts_fm.to_csv('GOLD_micro_M15.csv')

    Notas:

    1. Lembre-se de que se você adicionar um caminho na função mt.initialize() da seguinte maneira: mt.initialize("D:\\Project\\mt\\MT5\\terminal64.exe"), certifique-se de substituí-lo pelo local do seu próprio arquivo executável do cliente.

    2. Se você não conseguir encontrar o arquivo GOLD_micro_M15.csv, procure-o na raiz do cliente. Por exemplo, meu arquivo está localizado em: "D:\\Project\\mt\\MT5\\".


    Obrigado pela atenção!


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

    Arquivos anexados |
    Label_data.py (1.84 KB)
    Desenvolvendo um sistema de Replay (Parte 43): Projeto do Chart Trade (II) Desenvolvendo um sistema de Replay (Parte 43): Projeto do Chart Trade (II)
    Grande parte das pessoas que querem, ou desejam aprender a programar, não fazem de fato ideia, do que estão fazendo. O que elas fazem é tentar criar as coisas de uma determinada maneira. No entanto, quando programamos não estamos de fato tentando criar um solução. Se você tentar fazer isto, desta forma irá gerar mais problemas do que realmente uma solução. Aqui iremos fazer algo um pouco mais avançado, e por consequência diferente.
    Redes neurais de maneira fácil (Parte 57): Stochastic Marginal Actor-Critic (SMAC) Redes neurais de maneira fácil (Parte 57): Stochastic Marginal Actor-Critic (SMAC)
    Apresentamos um algoritmo relativamente novo, o Stochastic Marginal Actor-Critic (SMAC), que permite a construção de políticas de variáveis latentes no contexto da maximização da entropia.
    Regressão rede elástica usando descida de coordenadas no MQL5 Regressão rede elástica usando descida de coordenadas no MQL5
    Neste artigo, exploraremos a implementação prática da regressão rede elástica (elastic net regularization) para minimizar o sobreajuste e, ao mesmo tempo, separar automaticamente preditores úteis daqueles que possuem pouca força preditiva.
    Teoria das Categorias em MQL5 (Parte 19): Indução do quadrado de naturalidade Teoria das Categorias em MQL5 (Parte 19): Indução do quadrado de naturalidade
    Continuamos a análise das transformações naturais, examinando a indução do quadrado de naturalidade. Por causa das limitações na implementação de várias moedas para os Expert Advisors desenvolvidos com o assistente MQL5, temos de buscar soluções criativas e eficientes para a classificação de dados usando scripts. As principais áreas de aplicação consideradas são a classificação de variações de preço e, consequentemente, sua previsão.