English 中文 Español Deutsch 日本語 Português
preview
Разметка данных в анализе временных рядов (Часть 2):Создаем наборы данных с маркерами тренда с помощью Python

Разметка данных в анализе временных рядов (Часть 2):Создаем наборы данных с маркерами тренда с помощью Python

MetaTrader 5Эксперты | 19 января 2024, 12:30
695 0
Yuqiang Pan
Yuqiang Pan

Введение

В предыдущей статье мы рассказали, как разметить данные, наблюдая за трендами на графике, и сохранять данные в csv-файл. В этой части поступим иначе: начнем с самих данных.

Мы будем обрабатывать данные с помощью Python. Почему Python? Он удобен в работе. К тому же, огромная библиотека Python может помочь нам значительно сократить цикл разработки.

Итак, начнем!

Содержание:

  1. Выбираем библиотеку Python
  2. Получаем данные MT5-клиента с помощью библиотеки MetaTrader 5.
  3. Преобразуем формат данных
  4. Разметка данных
  5. Ручная проверка
  6. Особенности


Выбираем библиотеку Python

Мы все знаем, что у Python много отличных разработчиков, которые создают большое количество разнообразных библиотек, что упрощает и ускоряет разработку. Ниже представлена моя коллекция библиотек Python. Некоторые из них основаны на разных архитектурах, некоторые можно использовать для торговли, а некоторые - для тестирования на истории. Сюда входят, помимо прочего, размеченные данные.

  1. statsmodels - модуль Python, который позволяет пользователям исследовать данные, оценивать статистические модели и выполнять статистические тесты:http://statsmodels.sourceforge.net
  2. dynts - пакет Python для анализа и управления таймсериями:https://github.com/quantmind/dynts
  3. PyFlux - библиотека Python для моделирования временных рядов и вывод (частотного и байесовского) по моделям:https://github.com/RJT1990/pyflux
  4. tsfresh - автоизвлечение соответствующих характеристик из временных рядов:https://github.com/blue-yonder/tsfresh
  5. hasura/quandl-metabase - быстрый запуск Hasura для визуализации наборов данных временных рядов Quandl с помощью Metabase:https://platform.hasura.io/hub/projects/anirudhm/quandl-metabase-time-series
  6. Facebook Prophet - инструмент для создания высококачественных прогнозов для данных временных рядов, имеющих множественную сезонность с линейным или нелинейным ростом:https://github.com/facebook/prophet
  7. tsmoothie - библиотека Python для сглаживания временных рядов и обнаружения выбросов векторизованным способом:https://github.com/cerlymarco/tsmoothie
  8. pmdarima - статистическая библиотека, предназначенная для заполнения пробелов в возможностях анализа временных рядов Python, включая эквивалент функции:https://github.com/alkaline-ml/pmdarima
  9. gluon-ts - Вероятностное (vProbabilistic) моделирование временных рядов в:https://github.com/awslabs/gluon-ts
  10. gs-quant - набор инструментов Python для количественного финансирования:https://github.com/goldmansachs/gs-quant
  11. willowtree - надежная и гибкая реализация на Python решетки willow tree для ценообразования деривативов:https://github.com/federicomariamassari/willowtree
  12. financial-engineering - применение методов Монте-Карло к проектам финансового инжиниринга на Python:https://github.com/federicomariamassari/financial-engineering
  13. optlib - Python-библиотека для ценообразования финансовых опционов:https://github.com/dbrojas/optlib
  14. tf-quant-finance - высокопроизводительная библиотека TensorFlow для количественного финансирования:https://github.com/google/tf-quant-finance
  15. Q-Fin - библиотека Python для финансовой математики:https://github.com/RomanMichaelPaolucci/Q-Fin
  16. Quantsbin - инструменты для ценообразования и построения графиков цен ванильных опционов, греков и других видов анализа:https://github.com/quantsbin/Quantsbin
  17. finoptions - полная реализация пакета R fOptions на Python с частичной реализацией fExoticOptions для ценообразования различных опций:https://github.com/bbcho/finoptions-dev
  18. pypme - расчет PME (Public Market Equivalent, эквивалент для публичного рынка):https://github.com/ymyke/pypme
  19. Blankly - полностью интегрированное тестирование на исторических данных, бумажная торговля и живое развертывание:https://github.com/Blankly-Finance/Blankly
  20. TA-Lib - оболочка Python для TA-Lib (http://ta-lib.org/):https://github.com/mrjbq7/ta-lib
  21. zipline - алгоритмическая торговая Python-библиотека:https://github.com/quantopian/zipline
  22. QuantSoftware Toolkit - программная платформа с открытым исходным кодом на основе Python, предназначенная для поддержки создания и управления портфелем:https://github.com/QuantSoftware/QuantSoftwareToolkit
  23. finta - индикаторы технического анализа, реализованные в Pandas:https://github.com/peerchemist/finta
  24. Tulipy - библиотека индикаторов финансового технического анализа (привязки Python для tulipindicators):https://github.com/cirla/tulipy
  25. lppls - модуль Python для установки модели Log-Periodic Power Law Singularity (LPPLS, логопериодический степенной закон сингулярности):https://github.com/Boulder-Investment-Technologies/lppls
Здесь мы используем библиотеку pytrendseries для обработки данных, разметки трендов и создания наборов данных, поскольку эта библиотека проста в использовании и удобна в визуальном восприятии. Давайте начнем создавать наш набор данных!


Получаем данные MT5-клиента с помощью библиотеки MetaTrader 5.

Если у вас еще не установлен Python, я не рекомендую устанавливать официальную версию. Лучше использовать Anaconda, которую легко поддерживать. Но обычная версия Anaconda огромна и включает в себя много контента - визуальное управление, редактор и многое другое. К моему стыду, я почти не использую эту версию и настоятельно рекомендую упрощенную версию miniconda. Найти ее можно здесь - Miniconda :: Anaconda.org


1. Базовая инициализация среды

    Начните с создания виртуальной среды и откройте тип Anaconda Promote:

    conda create -n Data_label python=3.10

    env

    Введите "y" и дождитесь создания среды, затем введите:

    conda activate Data_label

    Примечание:При создании виртуальной среды conda, добавьте python=x.xx, иначе во время использования вы столкнемся с проблемами.

    2. Установка необходимой библиотеки

    Установим нашу необходимую библиотеку MetaTrader 5, введем в conda Promote:

    pip install MetaTrader5

    Установим pytrendseries, введем в conda Promote:

    pip install pytrendseries

    3. Создание файла Python

    В MetaEditor перейдите в "Сервис" -> "Настройки", введите свой путь к Python в столбце Python параметра "Компиляторы". Мой собственный путь - G:miniconda3\envs\Data_label:

    установка

    Затем выберите "Файл" -> "Новый файл" (или нажмите Ctrl + N), чтобы создать новый файл, и во всплывающем окне выберите "Скрипт на Python":

    f0

    Нажмите "Далее" и введите имя файла, например:

    f1

    После нажатия кнопки "ОК" появится следующее окно:

    f3

    4. Подключение клиента и получение данных

    Удалим исходный автоматически сгенерированный код и заменим его следующим:

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

    Скомпилируйте и запустите его, чтобы проверить на наличие ошибок. Если проблем нет, мы увидим следующее:

    out

    При "initialize() failed!" добавьте путь к параметру в функцию initialize(), который является путем к исполняемому файлу клиента, как показано в следующем цветовзвешенном (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()
    Всё готово, давайте получим данные:
    # 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])

    В приведенном выше коде мы добавили "sb=mt.symbols_total()", чтобы предотвратить сообщение об ошибке, поскольку символы не были обнаружены, и "copy_rates_from_pos("GOLD_micro", mt. TIMEFRAME_M15,0,10000)" означает копирование 10 000 баров из периода GOLD_micro M15 period. После компиляции будет получен следующий результат:

    o0

    На данный момент мы успешно получили данные от клиента.

    Преобразуем формат данных

    Хотя мы получили данные от клиента, формат данных нам не нужен. Данные имеют вид "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)]"

    Давайте воспользуемся pandas для преобразования. Добавленный код отмечен зеленым:

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

    Теперь еще раз посмотрим на формат данных:

    print(rts_fm.head(10))

    d

    Входные данные должны быть pandas. Формат DataFrame содержит один столбец в качестве наблюдаемых данных (в формате float или int), поэтому мы должны обработать данные в формат, запрошенный pytrendseries, следующим образом:
    td_data=rts_fm[['time','close']].set_index('time')

    Давайте посмотрим, как выглядят первые 10 строк данных:

    print(td_data.head(10))


    o2


    Примечание:
    "td_data" — не последний стиль данных, это всего лишь переходный продукт для получения трендов данных.

    Теперь наши данные полностью пригодны для использования, но для последующих операций лучше преобразовать наш формат даты в фрейм данных, поэтому добавим следующий код перед "td_data=rts_fm[['time','close']].set_index('time')":

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

    Вывод данных будет выглядеть так:

    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  

    Полный код раздела:

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


    Разметка данных

    1. Получение трендовых данных

    Сначала импортируем пакет pytrendseries:

    import pytrendseries as pts

    Мы используем функцию pts.detecttrend() для поиска тренда, затем определяем переменную td для этой функции. Для этого параметра есть два варианта: "downtrend" (нисходящий тренд) и "uptrend" (восходящий тренд):

    td='downtrend' # or "uptrend"

    Нам нужен еще один параметр "wd" как максимальный период тренда:

    wd=120

    Существует также опциональный параметр, но я лично считаю, что лучше его определить: этот параметр определяет минимальный период тренда:

    limit=6

    Теперь мы можем заполнить параметры функции, чтобы получить тренд:

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

    Проверим результат:

    print(trends.head(15))

    от до 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

    Вы также можете визуализировать результат с помощью функции "pts.vizplot.plot_trend()":

    pts.vizplot.plot_trend(td_data,trends)

    f1

    Аналогичным образом мы можем посмотреть на восходящий тренд по коду:

    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)

    Результат такой:

    от до 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. Разметка данных

    1) Парсим формат данных
      ds

    ① означает начало данных до начала первого нисходящего тренда. Предположим, что это восходящий тренд;

    ② означает нисходящий тренд;

    ③ означает восходящий тренд в середине данных;

    ④ означает конец последнего нисходящего тренда.

    Поэтому мы должны реализовать логику разметки для этих четырех частей.

    2)  Логика разметки 

    Начнем с определения некоторых основных переменных:

    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

    Пройдем по переменной "trends" с помощью цикла for, чтобы получить начало и конец каждого фрагмента данных:

    for trend in trends.iterrows():
            pass

    Получим начальный и конечный индексы для каждого сегмента:

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

    Поскольку сам rts_fm["trend"] инициализирован равным 0, нет необходимости изменять столбец trend восходящего тренда, но нам нужно увидеть, является ли начало данных нисходящим трендом, Если нет, то предполагаем восходящий тренд:

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

    Как и в случае с началом данных, нам нужно увидеть, заканчивается ли он нисходящим трендом в конце данных:

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

    Обработка сегментов восходящего тренда, кроме начала и конца данных:

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

    Обработайте каждый сегмент нисходящего тренда:

    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) Дополнительно
    Мы предполагаем, что начало и конец данных имеют восходящий тренд. Если вы считаете, что это недостаточно точно, вы также можете удалить начальную и конечную части. Для этого добавьте следующий код после завершения цикла 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. Проверка

    Теперь посмотрим, соответствуют ли наши данные ожиданиям (в примере рассматриваются только первые 25 фрагментов данных):

    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

    Вы можете видеть, что мы успешно добавили к данным типы трендов и маркеры индексов трендов.

    4. Сохранение файла

    Мы можем сохранить данные в большинстве форматов. Например, мы можете сохранить их в виде файла JSON, используя метод to_json(), или в виде HTML-файла, используя метод to_html(), и т. д. В качестве демонстрации используем сохранение в формате CSV. В конце кода добавляем:

    rts_fm.to_csv('GOLD_micro_M15.csv')


    Ручная проверка

    На данный момент мы проделали основную работу, но если мы хотим получить более точные данные, нам потребуется дальнейшее ручное вмешательство в код. Я укажу здесь лишь несколько направлений и не буду приводить подробную демонстрацию.

    1. Проверка целостности данных

    Проверка может обнаружить, что информация о данных отсутствует, что может означать отсутствие всех данных или отсутствие поля в данных. Целостность данных является одним из наиболее фундаментальных критериев оценки качества данных. Например, если предыдущие данные фондового рынка за период M15 отличаются на 2 часа от следующих данных, то нам необходимо использовать соответствующие инструменты для завершения данных. Конечно, как правило, сложно получить данные о валютных курсах или данные о фондовом рынке из нашего клиентского терминала, но если вы получаете временные ряды из других источников, таких как данные о трафике или о погоде, вам необходимо обратить особое внимание на эту ситуацию.

    Целостность качества данных относительно легко оценить, и ее обычно можно оценить по зарегистрированным и уникальным значениям в статистике данных. Например, если в данных о цене акций в предыдущем периоде цена закрытия равна 1000, но цена открытия становится 10 в следующем периоде, вам необходимо проверить, отсутствуют ли данные.


    2. Проверка точности разметки данных

    Метод разметки данных, реализованный выше, может иметь определенные уязвимости. Мы не можем полагаться лишь на методы, представленные в библиотеке pytrendseries для получения точных данных разметки. Необходимо дополнительно визуализировать данные, наблюдать за тем, будет ли классификация трендов данных слишком чувствительной или наоборот нечувствительной. Возможно, данные понадобится разбить на части или объединить. Эта работа требует много усилий и времени, поэтому приводить конкретные примеры пока нет смысла.

    Показатель точности относится к информации, записанной в данных, и может обнаружить отклонения в ней. В отличие от последовательности, данные с проблемами точности — это не просто несоответствия в правилах. Проблемы с последовательностью могут быть вызваны несогласованными правилами регистрации данных, но не обязательно ошибками.

    3. Проведите базовую статистическую проверку, чтобы убедиться, что разметка обоснована

    • Распределение целостности: быстро и интуитивно проверяйте полноту набора данных.
    • Тепловая карта: позволяет легко наблюдать корреляцию между двумя переменными.
    • Иерархическая кластеризация: вы можете увидеть, насколько тесно связаны разные классы ваших данных.
    Конечно, это касается не только вышеперечисленных методов.


    Особенности

    Ссылка: GitHub - rafa-rod/pytrendseries

    Полный код показан ниже:

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

    Примечания:

    1. Помните, что если вы добавляете путь в функцию mt.initialize() следующим образом: mt.initialize("D:\\Project\\mt\\MT5\\terminal64.exe"), обязательно замените его на расположение вашего собственного исполняемого файла клиента.

    2. Если вы не можете найти файл GOLD_micro_M15.csv, найдите его в корне клиента. Например, мой файл находится по пути: "D:\\Project\\mt\\MT5\\".


    Спасибо за внимание!


    Перевод с английского произведен MetaQuotes Ltd.
    Оригинальная статья: https://www.mql5.com/en/articles/13253

    Прикрепленные файлы |
    Label_data.py (1.84 KB)
    Нейросети — это просто (Часть 73): АвтоБоты прогнозирования ценового движения Нейросети — это просто (Часть 73): АвтоБоты прогнозирования ценового движения
    Мы продолжаем рассмотрения алгоритмов обучения моделей прогнозирования траекторий. И в данной статье я предлагаю Вам познакомиться с методом под названием “AutoBots”.
    Теория категорий в MQL5 (Часть 19): Индукция квадрата естественности Теория категорий в MQL5 (Часть 19): Индукция квадрата естественности
    Мы продолжаем рассмотрение естественных преобразований, рассматривая квадратичную индукцию естественности. Небольшие ограничения на реализацию мультивалютности для экспертов, собранных с помощью мастера MQL5, означают, что мы демонстрируем свои возможности по классификации данных с помощью скрипта. В качестве основных областей применения рассматриваются классификация изменений цен и, соответственно, их прогнозирование.
    Эластичная чистая регрессия с использованием покоординатного спуска в MQL5 Эластичная чистая регрессия с использованием покоординатного спуска в MQL5
    В этой статье мы исследуем практическую реализацию эластичной чистой регрессии (elastic net regression), чтобы минимизировать переобучение и в то же время автоматически отделять полезные предикторы от тех, которые имеют небольшую прогностическую силу.
    Популяционные алгоритмы оптимизации: Алгоритмы искусственной микро-иммунной системы (Micro Artificial immune system, Micro-AIS) Популяционные алгоритмы оптимизации: Алгоритмы искусственной микро-иммунной системы (Micro Artificial immune system, Micro-AIS)
    Статья рассказывает о методе оптимизации, основанном на принципах функционирования иммунной системы организма — Micro Artificial Immune System (Micro-AIS) — модификацию AIS. Micro-AIS использует более простую модель иммунной системы и простые операции обработки иммунной информации. Статья также обсуждает преимущества и недостатки Micro-AIS по сравнению с обычным AIS.