Разметка данных в анализе временных рядов (Часть 2):Создаем наборы данных с маркерами тренда с помощью Python
Введение
В предыдущей статье мы рассказали, как разметить данные, наблюдая за трендами на графике, и сохранять данные в csv-файл. В этой части поступим иначе: начнем с самих данных.
Мы будем обрабатывать данные с помощью Python. Почему Python? Он удобен в работе. К тому же, огромная библиотека Python может помочь нам значительно сократить цикл разработки.
Итак, начнем!
Содержание:
- Выбираем библиотеку Python
- Получаем данные MT5-клиента с помощью библиотеки MetaTrader 5.
- Преобразуем формат данных
- Разметка данных
- Ручная проверка
- Особенности
Выбираем библиотеку Python
Мы все знаем, что у Python много отличных разработчиков, которые создают большое количество разнообразных библиотек, что упрощает и ускоряет разработку. Ниже представлена моя коллекция библиотек Python. Некоторые из них основаны на разных архитектурах, некоторые можно использовать для торговли, а некоторые - для тестирования на истории. Сюда входят, помимо прочего, размеченные данные.
- statsmodels - модуль Python, который позволяет пользователям исследовать данные, оценивать статистические модели и выполнять статистические тесты:http://statsmodels.sourceforge.net
- dynts - пакет Python для анализа и управления таймсериями:https://github.com/quantmind/dynts
- PyFlux - библиотека Python для моделирования временных рядов и вывод (частотного и байесовского) по моделям:https://github.com/RJT1990/pyflux
- tsfresh - автоизвлечение соответствующих характеристик из временных рядов:https://github.com/blue-yonder/tsfresh
- hasura/quandl-metabase - быстрый запуск Hasura для визуализации наборов данных временных рядов Quandl с помощью Metabase:https://platform.hasura.io/hub/projects/anirudhm/quandl-metabase-time-series
- Facebook Prophet - инструмент для создания высококачественных прогнозов для данных временных рядов, имеющих множественную сезонность с линейным или нелинейным ростом:https://github.com/facebook/prophet
- tsmoothie - библиотека Python для сглаживания временных рядов и обнаружения выбросов векторизованным способом:https://github.com/cerlymarco/tsmoothie
- pmdarima - статистическая библиотека, предназначенная для заполнения пробелов в возможностях анализа временных рядов Python, включая эквивалент функции:https://github.com/alkaline-ml/pmdarima
- gluon-ts - Вероятностное (vProbabilistic) моделирование временных рядов в:https://github.com/awslabs/gluon-ts
- gs-quant - набор инструментов Python для количественного финансирования:https://github.com/goldmansachs/gs-quant
- willowtree - надежная и гибкая реализация на Python решетки willow tree для ценообразования деривативов:https://github.com/federicomariamassari/willowtree
- financial-engineering - применение методов Монте-Карло к проектам финансового инжиниринга на Python:https://github.com/federicomariamassari/financial-engineering
- optlib - Python-библиотека для ценообразования финансовых опционов:https://github.com/dbrojas/optlib
- tf-quant-finance - высокопроизводительная библиотека TensorFlow для количественного финансирования:https://github.com/google/tf-quant-finance
- Q-Fin - библиотека Python для финансовой математики:https://github.com/RomanMichaelPaolucci/Q-Fin
- Quantsbin - инструменты для ценообразования и построения графиков цен ванильных опционов, греков и других видов анализа:https://github.com/quantsbin/Quantsbin
- finoptions - полная реализация пакета R fOptions на Python с частичной реализацией fExoticOptions для ценообразования различных опций:https://github.com/bbcho/finoptions-dev
- pypme - расчет PME (Public Market Equivalent, эквивалент для публичного рынка):https://github.com/ymyke/pypme
- Blankly - полностью интегрированное тестирование на исторических данных, бумажная торговля и живое развертывание:https://github.com/Blankly-Finance/Blankly
- TA-Lib - оболочка Python для TA-Lib (http://ta-lib.org/):https://github.com/mrjbq7/ta-lib
- zipline - алгоритмическая торговая Python-библиотека:https://github.com/quantopian/zipline
- QuantSoftware Toolkit - программная платформа с открытым исходным кодом на основе Python, предназначенная для поддержки создания и управления портфелем:https://github.com/QuantSoftware/QuantSoftwareToolkit
- finta - индикаторы технического анализа, реализованные в Pandas:https://github.com/peerchemist/finta
- Tulipy - библиотека индикаторов финансового технического анализа (привязки Python для tulipindicators):https://github.com/cirla/tulipy
- lppls - модуль Python для установки модели Log-Periodic Power Law Singularity (LPPLS, логопериодический степенной закон сингулярности):https://github.com/Boulder-Investment-Technologies/lppls
Получаем данные MT5-клиента с помощью библиотеки MetaTrader 5.
Если у вас еще не установлен Python, я не рекомендую устанавливать официальную версию. Лучше использовать Anaconda, которую легко поддерживать. Но обычная версия Anaconda огромна и включает в себя много контента - визуальное управление, редактор и многое другое. К моему стыду, я почти не использую эту версию и настоятельно рекомендую упрощенную версию miniconda. Найти ее можно здесь - Miniconda :: Anaconda.org
1. Базовая инициализация среды
Начните с создания виртуальной среды и откройте тип Anaconda Promote:
conda create -n Data_label python=3.10
Введите "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":
Нажмите "Далее" и введите имя файла, например:
После нажатия кнопки "ОК" появится следующее окно:
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()
Скомпилируйте и запустите его, чтобы проверить на наличие ошибок. Если проблем нет, мы увидим следующее:
При "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. После компиляции будет получен следующий результат:
На данный момент мы успешно получили данные от клиента.
Преобразуем формат данных
Хотя мы получили данные от клиента, формат данных нам не нужен. Данные имеют вид "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))
Входные данные должны быть pandas. Формат DataFrame содержит один столбец в качестве наблюдаемых данных (в формате float или int), поэтому мы должны обработать данные в формат, запрошенный pytrendseries, следующим образом:
td_data=rts_fm[['time','close']].set_index('time')
Давайте посмотрим, как выглядят первые 10 строк данных:
print(td_data.head(10))
Примечание: "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)
Аналогичным образом мы можем посмотреть на восходящий тренд по коду:
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 |
2. Разметка данных
1) Парсим формат данных
① означает начало данных до начала первого нисходящего тренда. Предположим, что это восходящий тренд;
② означает нисходящий тренд;
③ означает восходящий тренд в середине данных;
④ означает конец последнего нисходящего тренда.
Поэтому мы должны реализовать логику разметки для этих четырех частей.
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
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования