English Русский 中文 Deutsch 日本語 Português
preview
Marcado de datos en el análisis de series temporales (Parte 2): Creando conjuntos de datos con marcadores de tendencias utilizando Python

Marcado de datos en el análisis de series temporales (Parte 2): Creando conjuntos de datos con marcadores de tendencias utilizando Python

MetaTrader 5Asesores Expertos | 19 febrero 2024, 09:36
199 0
Yuqiang Pan
Yuqiang Pan

Introducción

En el artículo anterior, hablamos sobre el marcado de datos, la observación de tendencias en un gráfico y el almacenamiento de datos en un archivo csv. En esta parte haremos las cosas de forma distinta: comenzaremos con los datos en sí.

Así, procesaremos los datos usando Python. ¿Por qué Python? Porque es cómodo de usar. Además, la enorme biblioteca de Python puede ayudarnos a abreviar significativamente nuestro ciclo de desarrollo.

¡Manos a la obra!

Contenido:

  1. Seleccionando una biblioteca de Python
  2. Obteniendo los datos del cliente MT5 con ayuda de la biblioteca MetaTrader 5.
  3. Convirtiendo el formato de datos
  4. Marcado de datos
  5. Verificación manual
  6. Particularidades


Seleccionando una biblioteca de Python

Todos sabemos que Python tiene muchos desarrolladores excelentes para crear una amplia variedad de bibliotecas, lo cual hace que el desarrollo resulte más rápido y fácil. A continuación podrá ver mi colección de bibliotecas de Python. Algunas se basan en distintas arquitecturas, algunas pueden usarse para operar y otras pueden utilizarse para realizar pruebas con la historia comercial. Esto incluye, entre otros, datos marcados.

  1. statsmodels - módulo de Python que permite a los usuarios explorar datos, estimar modelos estadísticos y realizar pruebas estadísticas:http://statsmodels.sourceforge.net
  2. dynts - paquete de Python para analizar y gestionar series temporales:https://github.com/quantmind/dynts
  3. PyFlux - biblioteca de Python para el modelado de series temporales y la inferencia (frecuentista y bayesiana) a partir de modelos:https://github.com/RJT1990/pyflux
  4. tsfresh - extracción automática de características relevantes de series temporales:https://github.com/blue-yonder/tsfresh
  5. hasura/quandl-metabase - inicio rápido de Hasura para visualizar conjuntos de datos de series temporales de Quandl usando Metabase:https://platform.hasura.io/hub/projects/anirudhm/quandl-metabase-time-series
  6. Facebook Prophet - herramienta para generar pronósticos de alta calidad para datos de series temporales que posean estacionalidad múltiple con crecimiento lineal o no lineal:https://github.com/facebook/prophet
  7. tsmoothie - biblioteca de Python para suavizar series temporales y detectar valores atípicos de forma vectorizada:https://github.com/cerlymarco/tsmoothie
  8. pmdarima -biblioteca estadística diseñada para llenar los vacíos en las capacidades de análisis de series temporales de Python, incluida una función equivalente:https://github.com/alkaline-ml/pmdarima
  9. gluon-ts - Modelado probabilístico (vProbabilistic) de series temporales en:https://github.com/awslabs/gluon-ts
  10. gs-quant - kit de herramientas Python para finanzas cuantitativas:https://github.com/goldmansachs/gs-quant
  11. willowtree - implementación de Python sólida y flexible de willow tree para fijar los precios de derivados:https://github.com/federicomariamassari/willowtree
  12. financial-engineering - aplicación de métodos de Monte Carlo a proyectos de ingeniería financiera en Python:https://github.com/federicomariamassari/financial-engineering
  13. optlib - biblioteca Python para fijar los precios de opciones financieras:https://github.com/dbrojas/optlib
  14. tf-quant-finance - biblioteca TensorFlow de alto rendimiento para finanzas cuantitativas:https://github.com/dbrojas/optlib
  15. Q-Fin - biblioteca Python para matemáticas financieras:https://github.com/RomanMichaelPaolucci/Q-Fin
  16. Quantsbin - herramientas para fijar precios y gráficos de precios de opciones vainilla, griegas y otros tipos de análisis:https://github.com/quantsbin/Quantsbin
  17. finoptions - implementación completa del paquete R fOptions en Python con una implementación parcial de fExoticOptions para fijar el precio de varias opciones:https://github.com/bbcho/finoptions-dev
  18. pypme - cálculo de PME (Public Market Equivalent, equivalente en el mercado público):https://github.com/ymyke/pypme
  19. Blankly - prueba con datos históricos totalmente integrada, negociación en papel e implementación en vivo:https://github.com/Blankly-Finance/Blankly
  20. TA-Lib - envoltorio Python para TA-Lib (http://ta-lib.org/):https://github.com/mrjbq7/ta-lib
  21. zipline - biblioteca Python de trading algorítmico:https://github.com/quantopian/zipline
  22. QuantSoftware Toolkit - plataforma de software de código abierto basada en Python diseñada para respaldar la creación y gestión de portafolios:https://github.com/QuantSoftware/QuantSoftwareToolkit
  23. finta - indicadores de análisis técnico implementados en Pandas:https://github.com/peerchemist/finta
  24. Tulipy - biblioteca de indicadores de análisis técnico financiero (enlaces de Python para tulipindicators):https://github.com/cirla/tulipy
  25. lppls - módulo de Python para configurar el modelo Log-Periodic Power Law Singularity (LPPLS, ley de potencia log-periódica de singularidad):https://github.com/Boulder-Investment-Technologies/lppls
Aquí utilizaremos la biblioteca pytrendseries para procesar datos, marcar tendencias y crear conjuntos de datos, ya que esta biblioteca es fácil de usar y visualmente cómoda. ¡Vamos a crear ahora nuestro conjunto de datos!


Obteniendo los datos del cliente MT5 con ayuda de la biblioteca MetaTrader 5.

Si aún no tiene instalado Python, no le recomiendo instalar la versión oficial. Es mejor usar Anaconda, que resulta más fácil de mantener. Pero la versión normal de Anaconda es enorme e incluye una gran cantidad de contenido: controles visuales, editor y mucho más. Para mi vergüenza, casi nunca he utilizado esta versión y recomiendo encarecidamente la versión simplificada, miniconda. Lo encontrará aquí - Miniconda :: Anaconda.org


1. Inicializamos el entorno básico

    Comenzaremos creando un entorno virtual y abriendo el tipo Anaconda Promote:

    conda create -n Data_label python=3.10

    env

    Escribiremos "y" y esperaremos a que se cree el entorno, luego introduciremos:

    conda activate Data_label

    Nota:Al crear un entorno virtual conda, añadiremos python=x.xx; de lo contrario, tendremos problemas durante el uso.

    2. Instalamos la biblioteca requerida

    Instalaremos nuestra biblioteca MetaTrader 5 necesaria, introduciendo en conda Promote:

    pip install MetaTrader5

    Luego instalaremos pytrendseries, e introduciremos en conda Promote:

    pip install pytrendseries

    3. Creamos un archivo Python

    En el MetaEditor, iremos a "Servicio" -> "Ajustes", e introduciremos nuestra ruta de Python en la columna Python de la opción "Compiladores". Nuestra propia ruta es G:miniconda3\envs\Data_label:

    instalación

    Luego seleccionaremos "Archivo" -> "Nuevo archivo" (o presione Ctrl + N) para crear un nuevo archivo, y en la ventana emergente seleccionaremos "Python Script":

    f0

    Después clicaremos en Siguiente e introduciremos un nombre de archivo, por ejemplo:

    f1

    Después de clicar en "Aceptar", aparecerá la siguiente ventana:

    f3

    4. Conectamos un cliente y recibimos datos

    Ahora eliminaremos el código original generado automáticamente y lo reemplazaremos con el siguiente:

    # 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()
    

    Luego lo compilaremos y lo ejecutaremos para comprobar si hay errores. Si no hay problemas veremos lo siguiente:

    out

    Si tenemos "initialize() failed!" añadiremos una ruta de parámetro a la función inicialize(), que será la ruta al archivo ejecutable del cliente, como se muestra en el siguiente código ponderado por colores (color-weighted):

    # 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()
    Todo está listo, vamos a obtener los datos:
    # 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])

    En el código anterior, añadiremos "sb=mt.symbols_total()" para evitar un mensaje de error, dado que no se han hallado símbolos, y "copy_rates_from_pos("GOLD_micro", mt. TIMEFRAME_M15,0,10000)" indicará el copiado de 10 000 barras del periodo GOLD_micro M15. Tras realizar la compilación, obtendremos el siguiente resultado:

    o0

    En este punto, habremos recibido correctamente los datos del cliente.

    Convirtiendo el formato de datos

    Aunque hayamos recibido los datos del cliente, no necesitaremos el formato de datos. Los datos tendrán el aspecto "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)]"

    Usaremos pandas para realizar la conversión. El código añadido estará marcado en 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)

    Ahora veremos nuevamente el formato de datos:

    print(rts_fm.head(10))

    d

    Los datos de entrada deberán ser pandas. El formato DataFrame contendrá una columna como datos observables (en formato float o int), por lo que deberemos procesar los datos en el formato solicitado por pytrendseries de la siguiente manera:
    td_data=rts_fm[['time','close']].set_index('time')

    Veamos cómo se ven las primeras 10 líneas de datos:

    print(td_data.head(10))


    o2


    Nota:
    "td_data" no será el último estilo de datos, sino solo un producto de transición para obtener las tendencias de los datos.

    Nuestros datos ahora serán completamente utilizables, pero para operaciones posteriores será mejor convertir nuestro formato de fecha en un marco de datos, por lo que añadiremos el siguiente código antes de "td_data=rts_fm[['time','close']].set_index( 'tiempo')":

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

    Los datos de salida se verán así:

    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 completo de la sección:

    # 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))


    Marcado de datos

    1. Obtenemos los datos de las tendencias

    Primero, importaremos el paquete pytrendseries:

    import pytrendseries as pts

    Usaremos la función pts.detecttrend() para encontrar la tendencia y luego definiremos una variable td para esta función. Hay dos opciones para este parámetro: "downtrend" (tendencia bajista) y "uptrend" (tendencia alcista):

    td='downtrend' # or "uptrend"

    Necesitaremos un parámetro más "wd" como periodo máximo de tendencia:

    wd=120

    También tendremos un parámetro opcional, pero personalmente creo que es mejor definirlo; este parámetro definirá el periodo mínimo de tendencia:

    limit=6

    Ahora podemos rellenar los parámetros de la función para obtener la tendencia:

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

    Comprobemos el resultado:

    print(trends.head(15))

    desde hasta 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

    También podremos visualizar el resultado usando la función "pts.vizplot.plot_trend()":

    pts.vizplot.plot_trend(td_data,trends)

    f1

    De forma similar, podremos observar la tendencia alcista por el 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)

    El resultado será:

    desde hasta 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. Marcado de datos

    1) Analizamos el formato de los datos
      ds

    ① indicará que los datos comienzan antes de que se inicie la primera tendencia bajista. Digamos que es una tendencia alcista;

    ② indicará una tendencia bajista;

    ③ indicará una tendencia alcista en la mitad de los datos;

    ④ indicará el final de la última tendencia bajista.

    Por lo tanto, deberemos implementar la lógica de marcado para estas cuatro partes.

    2) Lógica de marcado 

    Comenzaremos definiendo algunas variables 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

    Recorramos la variable "trends" para obtener el inicio y el final de cada dato:

    for trend in trends.iterrows():
            pass

    Luego obtendremos los índices inicial y final para cada segmento:

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

    Como rts_fm["tendencia"] se inicializará a 0, no necesitaremos cambiar la columna de tendencia de una tendencia alcista, pero sí necesitaremos ver si el inicio de los datos supone una tendencia bajista. Si no, entonces supondremos una tendencia alcista:

    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))

    Al igual que con el inicio de los datos, deberemos ver si termina en una tendencia bajista al final de los datos:

    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))

    Procesamiento de segmentos de tendencia alcista distintos del inicio y el final de los datos:

    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))

    Procesaremos cada segmento de tendencia bajista:

    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) Opcional
    Supondremos que el inicio y el final de los datos tienen una tendencia ascendente. Si creemos que no resulta lo suficientemente preciso, también podremos quitar las partes inicial y final. Para hacer esto, añadiremos el siguiente código después de que se complete el bucle 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. Comprobación

    Ahora veremos si nuestros datos coinciden con nuestras expectativas (el ejemplo solo analizará los primeros 25 datos):

    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

    Podemos ver que hemos añadido con éxito tipos de tendencias y marcadores de índices de tendencias a los datos.

    4. Guardamos un archivo

    Podemos guardar datos en la mayoría de formatos. Por ejemplo, podemos guardarlos como un archivo JSON utilizando el método to_json(), o como un archivo HTML usando el método to_html(), etc. Como demostración, utilizaremos el almacenamiento en formato CSV. Al final del código añadiremos:

    rts_fm.to_csv('GOLD_micro_M15.csv')


    Verificación manual

    Ya hemos realizado la mayor parte del trabajo por ahora, pero si queremos obtener datos más precisos, necesitaremos una mayor intervención manual en el código. Aquí solo señalaremos algunas áreas y no proporcionaremos una demostración detallada.

    1. Verificando la integridad de los datos

    La verificación puede encontrar que falta información de datos, lo cual podría significar que faltan todos los datos o que falta un campo en ellos. La integridad de los datos es uno de los criterios más esenciales al evaluar la calidad de los datos. Por ejemplo, si los datos del mercado de valores anteriores para el periodo M15 difieren en 2 horas de los datos siguientes, entonces deberemos utilizar las herramientas correspondientes para completar los datos. Obviamente, por lo general resulta difícil obtener datos sobre los tipos de cambio o los datos del mercado de valores desde nuestro terminal de cliente, pero si recibimos series temporales de otras fuentes, como datos de tráfico o meteorológicos, deberemos prestar especial atención a esta situación.

    La integridad de la calidad de los datos se puede evaluar de forma relativamente fácil y, por lo general, podremos valorarla usando valores registrados y únicos en las estadísticas de datos. Por ejemplo, si los datos del precio de las acciones en el periodo anterior tienen un precio de cierre de 1 000, pero el precio de apertura se convierte en 10 en el siguiente periodo, deberemos verificar si faltan datos.


    2. Comprobamos la precisión del marcado de datos

    El método de marcado de datos implementado anteriormente puede tener ciertas vulnerabilidades. Para obtener datos de marcado precisos, no podemos confiar únicamente en los métodos ofrecidos en la biblioteca pytrendseries. Deberemos visualizar los datos adicionalmente, observar si la clasificación de las tendencias de los datos resulta demasiado sensible o, por el contrario, insensible. Puede que sea necesario dividir los datos en partes o fusionarlos. Este trabajo requiere mucho esfuerzo y tiempo, por lo que no tendría sentido dar ejemplos específicos todavía.

    La medida de la precisión se refiere a la información registrada en los datos y puede detectar desviaciones en los mismos. A diferencia de la coherencia, los datos con problemas de precisión no suponen simplemente inconsistencias en las reglas. Los problemas de coherencia pueden deberse a reglas incoherentes de registro de datos, pero no necesariamente a errores.

    3. Realice pruebas estadísticas básicas para garantizar que el margen de beneficio sea razonable.

    • Distribución de integridad: compruebe de forma rápida e intuitiva que el conjunto de datos esté integro.
    • Mapa de calor: nos permite observar fácilmente la correlación entre dos variables.
    • Clusterización jerárquica: podrá ver cómo de relacionadas están las diferentes clases de sus datos.
    Por supuesto, esto no se aplica exclusivamente a los métodos anteriores.


    Particularidades

    Enlace: GitHub - rafa-rod/pytrendseries

    El código completo se muestra a continuación:

    # 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. Recuerde que si añade una ruta a la función mt.initialize() de la forma siguiente: mt.initialize("D:\\Project\\mt\\MT5\\terminal64.exe"), deberá asegurarse de reemplazarla con la ubicación de su propio cliente ejecutable.

    2. Si no puede encontrar el archivo GOLD_micro_M15.csv, búsquelo en la raíz del cliente. Por ejemplo, mi archivo se encuentra en: "D:\\Project\\mt\\MT5\\".


    ¡Gracias por su atención!


    Traducción del inglés realizada por MetaQuotes Ltd.
    Artículo original: https://www.mql5.com/en/articles/13253

    Archivos adjuntos |
    Label_data.py (1.84 KB)
    Regresión neta elástica mediante descenso de coordenadas en MQL5 Regresión neta elástica mediante descenso de coordenadas en MQL5
    En este artículo, analizaremos la implementación práctica de la regresión neta elástica para minimizar el sobreajuste y al mismo tiempo separar automáticamente los predictores útiles de aquellos que tienen poco poder de pronóstico.
    Redes neuronales: así de sencillo (Parte 57): Stochastic Marginal Actor-Critic (SMAC) Redes neuronales: así de sencillo (Parte 57): Stochastic Marginal Actor-Critic (SMAC)
    Hoy le proponemos introducir un algoritmo bastante nuevo, el Stochastic Marginal Actor-Critic (SMAC), que permite la construcción de políticas de variable latente dentro de un marco de maximización de la entropía.
    Desarrollando un cliente MQTT para MetaTrader 5: metodología de TDD (Parte 2) Desarrollando un cliente MQTT para MetaTrader 5: metodología de TDD (Parte 2)
    El artículo forma parte de una serie que describe las etapas de desarrollo de un cliente MQL5 nativo para el protocolo MQTT. En esta parte describiremos la organización de nuestro código, los primeros archivos de encabezado y las clases, así como la escritura de las pruebas. Este artículo también incluirá notas breves sobre un desarrollo basado en las pruebas y su aplicación a este proyecto.
    Teoría de categorías en MQL5 (Parte 19): Inducción cuadrática de la naturalidad Teoría de categorías en MQL5 (Parte 19): Inducción cuadrática de la naturalidad
    Continuamos analizando las transformaciones naturales considerando la inducción cuadrática de la naturalidad. Pequeñas restricciones en la implementación de las capacidades multidivisa para los asesores ensamblados usando el wizard MQL5 significan que estamos demostrando nuestras capacidades en la clasificación de datos usando un script. Las principales áreas de aplicación son la clasificación de las variaciones de precios y, como consecuencia, su previsión.