Часть 4: Поиск сигналов

Зарегистрируйтесь для участия в бета-тестировании на сайте http://daytrader.ai, чтобы одними из первых получать данные об акциях, сгенерированные AI.

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

Обзор искусственной нейронной сети

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

Первое, что нам нужно сделать, чтобы начать процесс обучения, - это подготовить данные.

Векторизация наших данных

Данные, которые я предоставил, содержат данные о запасах за 2420 минут из 1 минуты. Эта точка входа или условие высокого уровня было обнаружено в точке 2400 в наборе. Оттуда я предлагаю 20 минут будущей истории. Поэтому первое, что мы захотим сделать, - это разделить данные на нашу матрицу функций, а также извлечь вектор меток. Следующий код утилиты создаст матрицу функций numpy с формой M x N, где M = 2400, а N - количество обучающих примеров.

Визуализация некоторых данных

На этом этапе рекомендуется взглянуть на некоторые образцы данных. Они нормально выглядят? Я включил служебный метод для построения индивидуальных обучающих примеров. Вот пример:

Вы можете визуализировать любой обучающий пример в обучающей выборке, используя следующий метод.

Центрирование данных

Одна из ключевых задач в подобной проблеме науки о данных - как правильно сформулировать проблему для машины. Необработанные данные, которые я предоставил, включают цену закрытия и объем для ряда биржевых символов. Первое, что следует заметить, это то, что эти акции оцениваются по-разному. Например, акции Amazon продаются в диапазоне более 1000 долларов за акцию, тогда как акции Intel торгуются ниже 100 долларов. Нам нужно сначала нормализовать эти значения, чтобы правильно их сравнить. Вот несколько способов сделать это:

Центрирование скорости изменений

Здесь мы берем цену во время T и делим ее на цену закрытия в момент T-1, а затем вычитаем 1 из этого значения.

(цена в момент T) / (цена в момент T-1) - 1.0

Eg:

2017–10–17T14:18:00.000Z,201.87,55800.0

2017–10–17T14:19:00.000Z,201.21,137786.0

Цена на 14:19 это 201,21

Цена на 14:18 составляет 201,87

(201.21/201.87) — 1.0 = −0.002824859

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

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

Центрирование точки входа

Здесь мы вычисляем скорость изменения относительно точки входа наших данных. Опять же, точка входа для данных примера - это когда EMA-15 пересекает EMA-65. Это будет последний столбец данных о ценах в нашей матрице характеристик. Итак, теперь мы делим каждую цену на эту цену точки входа и вычитаем из нее 1.

(цена в момент T) / (ЦЕНА ВХОДА) - 1.0

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

Нормализация данных

На этом этапе мы будем использовать Стандартизацию scikit-learn. Из документации:

Стандартизация наборов данных - это общее требование для многих оценщиков машинного обучения, реализованное в scikit-learn; они могут вести себя плохо, если отдельные функции не более или менее выглядят как стандартные данные с нормальным распределением: по Гауссу с нулевым средним и единичной дисперсией.

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

Создание классов из наших этикеток

Напомним, что вектор наших этикеток - это просто стоимость этой акции через 20 минут. Приведенный выше код центрирования также применил такое же центрирование к нашим этикеткам. Давайте посмотрим, что это на самом деле означает. Сначала мы можем построить кривую распределения для наших этикеток.

мин: -0,02869251474715062 или 2,9%

макс: 0,037285348922177386 или 3,7%

Большинство наших данных сосредоточено вокруг нуля. Это то, что мы ожидаем увидеть, при этом наихудшим исходом будет потеря 2,9% стоимости акций, а наилучшим сценарием - рост на 3,7%. Стоит отметить, что на самом деле у нас всегда будет стоп-лосс для любой сделки. В большинстве случаев наша сделка будет около 40000 долларов, а мы рискнем около 150 долларов. Поэтому всякий раз, когда мы «проигрываем», это равносильно простому срабатыванию STOP. Обратной стороной этого является то, что наш максимально возможный прирост в 3,7% дает доход в районе 1500 долларов.

Первые несколько моделей, которые мы создаем, будут классификаторами, поэтому мы хотим создать N классов, представляющих сегменты одинакового размера из приведенного выше распределения. Чем больше количество занятий, тем сложнее будет учиться. На данный момент мы собираемся оставить количество классов равным 5. Это должно поместить 2 класса в положительный диапазон и 2 класса в отрицательный диапазон, причем последний класс представляет собой большой кусок в середине со значениями, близкими к нулю. Это также с 5 классами дает нам базовый уровень для нашей производительности, поскольку предположение в среднем дает точность 20%. Поэтому мы стремимся достичь точности более 20% в качестве доказательства «некоторого» сигнала. Как только мы нашли сигнал, мы можем начать попытки настроиться.

Ярлыки наших классов попадают в эти ведра:

  • Класс 1: -0.02869 ›-0.00204
  • Класс 2: -0,00204 ›-0,00058
  • Класс 3: -0,00058 ›0,000453
  • Класс 4: 0,000453 ›0,001992
  • Класс 5: 0,001992 ›0,037285

Затем берем нашу метку Vector и значения One-Hot encode. Это дает нам окончательную матрицу меток, каждая строка которой содержит вектор с 5 записями, содержащими одну единицу в столбце класса и нули в каждом другом столбце.

Набор для обучения и тестирования

Теперь, когда мы отформатировали наши данные и нормализовали их, мы можем начать экспериментировать с некоторыми другими моделями. Для этого мы разделим наши данные на обучающий и тестовый набор. Мы будем использовать данные обучения для обучения модели. Мы протянем набор тестов, чтобы прогнать модель и определить, насколько хорошо мы справляемся с данными, которые модель никогда не видела.

Это приведет к тому, что наша модель выдаст 2 балла: один для обучающего набора и один для тестового набора. Обычно мы можем называть то, насколько хорошо модель соответствует обучающим данным, смещением: модель, которая лучше соответствует обучающим данным, имеет более высокую точность и, следовательно, более низкое смещение. Затем мы можем обозначить, насколько хорошо модель соответствует тестовым данным, Дисперсия, опять же, более высокая точность на тестовом наборе будет указывать на более низкую Дисперсию. Наша цель - иметь низкий смещение и низкую дисперсию для нашей модели.

Для наших данных часто легко достичь высокого уровня точности на обучающем наборе (низкое смещение), но очень сложно поддерживать высокий уровень точности на тестовом наборе. Таким образом, у нас большая дисперсия. Это классически называется переоснащением данных и похоже на то, что модель запоминает обучающие данные, но это не применимо к обобщению для невидимых данных. Есть много способов борьбы с переобучением, и мы рассмотрим некоторые из них в следующем разделе. Если вы хотите узнать больше о переобучении, вы можете прочитать этот пост: https://elitedatascience.com/overfitting-in-machine-learning

Многослойный персептрон

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

Точность

Потеря

Мы смогли добиться 30% точности на нашем испытательном наборе. Это неплохо, учитывая, что единственная особенность на данный момент - цена. Это также дает некоторые доказательства того, что в нашем наборе данных есть сигнал. Одна из проблем с нашей сетью, описанной выше, заключается в том, что она не может вспомнить что-либо, что она видела во временном ряду, что потенциально могло бы помочь сделать прогноз позже.

Рекуррентные нейронные сети (RNN)

Рекуррентная нейронная сеть - это особый вид нейронной сети, которая обладает некоторой «памятью». Эти сети хорошо подходят для данных временных рядов, имея большой успех в задачах НЛП и речи. Тип сети RNN, который мы будем применять, называется долгосрочной краткосрочной памятью. Вот еще немного информации об этих типах архитектуры:

При использовании RNN необходимо учитывать ряд факторов, в том числе: исчезающие градиенты и то, как далеко назад сеть может запомнить. Имея действительно многомерные данные (2400 временных шагов), мы не сможем вспомнить что-либо полезное так далеко назад. Одна вещь, которую мы можем попытаться сделать, - это уменьшить размерность наших данных.

Уменьшение размерности

Существует ряд методов уменьшения размерности данных. Одним из таких методов является анализ главных компонентов или PCA. PCA проецирует точки из пространства более высокой размерности на подпространство меньшей размерности. Примером этого может быть набор точек в 3-х измерениях. Мы могли бы найти плоскую поверхность, которая лучше всего аппроксимирует данные, и спроецировать все трехмерные точки на поверхность плоскости. Теперь мы можем представить точки в 2D. Мы собираемся применить PCA к выходным данным, чтобы уменьшить размерность, прежде чем передавать их в сеть RNN. Однако PCA остается плохим выбором для сокращения наших данных. Поскольку каждая функция представляет собой 1-минутный временной интервал, PCA будет искать во всем пространстве функции, обеспечивающие небольшую вариативность набора данных. Другими словами, PCA может обнаружить, что минута 55 обеспечивает наименее значимое изменение по всему обучающему набору, однако все еще может быть небольшое количество примеров, что минута 55 была ключом к пониманию этого конкретного примера.

Сначала мы попробуем нашу модель LSTM с использованием PCA для уменьшения размерности, а в следующих статьях мы поговорим о более умных методах уменьшения размерности.

Модель LSTM

Наша модель LSTM не работает лучше, чем наша MLP. Я подозреваю, что это происходит из-за того, что мы на данном этапе сделали неудачный выбор уменьшения размерности. На обучение этих моделей уходит гораздо больше времени, поэтому я также прекратил обучение на 35 эпохах. Есть тонна вещей, которые мы могли бы настроить, прежде чем отказаться от этого стиля модели, и мы рассмотрим это в будущих публикациях.

Полученные результаты

Несмотря на низкую точность нашего тестового набора, эти результаты являются хорошей основой. Давайте еще раз подумаем о том, что мы пытаемся сделать. Мы только хотим заключать сделки, которые, по нашему мнению, принесут высокую доходность (мы поговорим о коротких продажах в другом посте). Это означает, что мы хотим совершать сделки с меткой класса 5. Если мы используем нашу модель для прогнозирования для этого класса, она должна быть верной почти в 30% случаев. Это оставляет нам возможность определить, насколько мы неправы в отношении остальных 70%. Если мы предположим равное распределение по другим классам 1, 2, 3, 4, это означает, что в 35% случаев мы прогнозируем класс 1 или 2, а в остальных 35% мы прогнозируем класс 2 или 3. В этом случае мы только достигаем результата. наш СТОП в 35% случаев, а остальные 35% мы приносим небольшую прибыль или не приносим никакой прибыли, а не СТОП-убыток.

Мы можем проверить это, выделив класс 5 из нашего набора тестов и построив фактические прогнозы, которые были сделаны для этого класса.

Как видите, наиболее распространенной ошибкой для класса 5 на самом деле является класс 1. Это довольно прискорбно, но заставляет меня задуматься, почему это может быть. Давайте углубимся еще немного, чтобы увидеть, что здесь может происходить.

Вот то, что дистрибутив ищет для некоторых других классов

В частности, мы замечаем ожидаемые распределения для всех классов, кроме 1 и 5. Это наводит меня на мысль, что мы искажаем данные из-за выбросов. Это акции на дальнем конце распределения положительной и отрицательной доходности. Тот факт, что они являются выбросами, заставляет меня думать, что эти колебания цен были ответом на некоторую движущую силу внешнего рынка (например, введение Трампом тарифов на китайские товары и т. Д.). Одна вещь, которую мы можем попробовать и сделать, - это вырезать положительные и отрицательные выбросы из класса, в котором они находятся, и добавить их в свой собственный класс. Мы рассмотрим это подробнее в следующей публикации.

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

Тюнинг

Теперь, когда у нас есть то, что кажется слабым сигналом в наших данных, мы можем начать применять некоторые методы для настройки на этот сигнал. Одно из первых действий, которое нужно сделать, - это получить больше данных. Если мы расширим наш поиск, добавив больше рыночных символов, мы сможем удвоить или даже утроить объем обучающих данных. Отсюда мы можем потратить больше времени на обрезку выбросов и попытаться определить дальнейшие индикаторы (применить индексы к компьютерному RSI). Есть еще ряд вещей, которые мы можем сделать, чтобы попытаться бороться с высокой дисперсией нашей модели.

Резюме

Этот пост затронул много вопросов. Сначала мы поговорим о загрузке данных и важности их центрирования. Затем мы переходим к формулировке некоторых категоричных проблем машинного обучения. Сначала мы применяем простой многослойный персептрон, а затем модели LSTM. Ранние результаты показывают, что в нашем наборе данных есть сигнал, и что даже при такой низкой точности на нашем тестовом наборе мы все еще можем использовать результаты для изменения шансов в нашу пользу.

Одной из мотиваций в публикации моих собственных данных и обучении в серии сообщений в блогах было осознание того, что - хотя я уверен, что эксперименты в области машинного обучения, применяемые к данным фондового рынка, имеют место - большая часть этих экспериментов не используется. Я не верю, что в Интернете есть еще одно место, которое предлагает модель машинного обучения, которая позволяет вам применять прогнозы рынка в реальном мире, и я рад предложить вам это. Убедитесь, что вы зарегистрируетесь здесь, чтобы быть одним из первых, кто поможет изменить мир внутридневной торговли.

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

Далее: Часть 5: Скрытый сдвиг фондового рынка с помощью автоэнкодеров