Pull to refresh

Применение машинного обучения в трейдинге. Часть 2

Reading time6 min
Views21K
Original author: Tad Slaff
Примечание переводчика. Продолжаю перевод серии статей по применению машинного обучения в трейдинге. Предыдущая часть здесь. О любых ошибках и исправлениях пишите в личку.

Как использовать дерево решений для торговли акциями Bank of America.




Предположим вам нравится использовать разнообразные технические индикаторы и вы хотите создать стратегию, которая ищет конкретные высоко-вероятностные возможности на рынке. Что если значение RSI находящееся выше 85 и, одновременно, линия MACD ниже 20, означают хорошую возможность открыть короткую позицию? Вы можете потратить дни/недели/месяцы в попытках вручную просчитать все комбинации ваших индикаторов, а можете использовать дерево решений – мощный и легко интерпретируемый алгоритм.

Для начала давайте разберёмся, как работают дерева решений, затем рассмотрим их использование на примере построения стратегии торговли акциями Bank of America.

Как работает дерево решений


Деревья решений являются одним из наиболее популярных алгоритмов машинного обучения, поскольку они позволяют моделировать данные с сильным шумом, легко выделять не линейные тренды и отлавливать взаимосвязь между вашими индикаторами. При этом они являются еще и легко интерпретируемыми. Деревья решений применяют нисходящий, «разделяй и властвуй» подход для анализа данных. Они ищут индикатор и значение индикатора, которое лучше всего расщепляет данные на две противоположные группы. Затем алгоритм повторяет этот процесс на каждой из групп и так продолжается до тех пор, пока он не классифицирует каждую точку данных или будет достигнут критерий остановки. В нашем случае данные могут принадлежать одной из двух групп: «Вверх» или «Вниз». Каждое расщепление, именуемое узлом, пытается максимизировать чистоту результирующих веток. Чистота в данном случае – вероятность того, что данные принадлежат к одной из групп, она характеризуется параметром сложности для каждого узла.

Деревья решений, могут легко переобучиться на тестовых данных и дать ужасный результат на новых данных. Существует три способа решения этой проблемы:
• Вы можете контролировать рост дерева, указывая порог параметра сложности или минимальное число точек данных в каждой ветке, для фиксирования подмножества. Это создает дерево, которое будет стараться охватить более широкие модели и не будет фокусироваться на незначительных подмножествах, которые могут быть уникальными для вашего набора данных
• Вы можете так же обрезать деревья, после того как они были построены. Обычно это делается путем выбора размера дерева, который минимизирует ошибку перекрестной проверки. Перекрестная проверка – процесс, который разделяет данные на несколько групп, затем использует все группы кроме одной для построения модели, а оставшуюся группу данных задействует для тестирования модели. Затем этот процесс повторяется таким образом, чтобы каждая группа использовалась для тестирования. После чего выбирается дерево с самой низкой средней ошибкой. Этот метод также хорош для предотвращения переобучения, если у вас ограниченное количество данных.
• Наиболее сложный способ, состоит в построении множества различных деревьев и совместного их использования для принятия решений. Существуют три популярных метода построения более одного дерева решений: «мешок», «повышенные»деревья и случайные леса. Возможно в следующих статьях мы рассмотрим эти методы подробнее.

Теперь, когда у нас есть базовое представление о деревьях решений, давайте построим свою стратегию!

Построение стратегии


Давайте посмотрим, как построить стратегию, основываясь на 4-х технических индикаторах, чтобы определить движение акций BoA.
Для начала, давайте убедимся, что у нас есть все нужные библиотеки.

install.packages("quantmod")
library("quantmod")
#Позволяет импортировать необходимые данные и рассчитывать технические индикаторы

install.packages("rpart") 
library("rpart")
#Даёт доступ к деревам решений, которые мы будем использовать.

install.packages("rpart.plot") 
library("rpart.plot")
#Позволяет легко создать симпатичные диаграммы деревьев

Затем, давайте получим данные и рассчитаем индикаторы.

startDate = as.Date("2012-01-01")
#Начало рассматриваемого промежутка

endDate = as.Date("2014-01-01") 
#Конец промежутка

getSymbols("BAC", src = "yahoo", from = startDate, to = endDate) 
#Получаем данные стоимости акций Bank of America

RSI3<-RSI(Op(BAC), n= 3) 
#Рассчитываем 3-х дневный индекс относительной силы (RSI) по цене открытия

EMA5<-EMA(Op(BAC),n=5) 
#Рассчитываем 5-дневную экспоненциальную скользящую среднюю (EMA)
EMAcross<- Op(BAC)-EMA5 
#Давайте посмотрим на разницу между ценой открытия и нашей 5-ти дневной EMA

MACD<-MACD(Op(BAC),fast = 12, slow = 26, signal = 9) 
#Рассчитываем MACD(Схождение/расхождение скользящих средних) со стандартными параметрами

MACDsignal<-MACD[,2] 
#Используем только сигнальную линию в качестве индикатора 

SMI<-SMI(Op(BAC),n=13,slow=25,fast=2,signal=9) 

#Стохастический осциллятор со стандартными параметрами
SMI<-SMI[,1] 
#Используем только осциллятор в качестве индикатора

Затем рассчитываем переменную, которую мы предсказываем и формируем data sets.

PriceChange<- Cl(BAC) - Op(BAC) 
#Рассчитываем разницу между ценой закрытия и открытия
Class<-ifelse(PriceChange>0,"UP","DOWN") 
#Переменная которую мы хотим предсказать.

DataSet<-data.frame(RSI3,EMAcross,MACDsignal,SMI,Class) 
#Создаем наш data set
colnames(DataSet)<-c("RSI3","EMAcross","MACDsignal","Stochastic","Class") 
#Задаем имена колонкам
DataSet<-DataSet[-c(1:33),] 
#Избавляемся от данных, на которых происходит первоначальное формирование индикаторов

TrainingSet<-DataSet[1:312,] 
#Используем 2/3 наших данных для построения дерева
TestSet<-DataSet[313:469,]
#И оставляем 1/3 данных для тестирования нашей стратегии

Теперь, когда у нас есть всё, что нужно, давайте построим уже это дерево!

DecisionTree<-rpart(Class~RSI3+EMAcross+MACDsignal+Stochastic,data=TrainingSet, cp=.001)
#Указываем индикаторы, которые мы хотим использовать для предсказания и контролируем рост дерева, указывая минимальное значение параметра сложности (ср), необходимого для организации разделения.

Отлично! У нас есть наше первое дерево решений, посмотрим, что же мы построили.

prp(DecisionTree,type=2,extra=8)
#Отличный графический инструмент, с несколькими параметрами для красивого отображения. 


Если вы хотите самостоятельно поиграть с визуализацией, вот отличный ресурс

Маленькая заметка по интерпретации этого дерева: узлы представляют расщепление, где левая ветка отражает ответ «да», а правая ветка ответ «нет». Число в конечном листе – процентное число случаев, которые были корректно классифицированы этим узлом.
Дерева решений так же могут быть использованы для выбора и оценки индикаторов. Индикаторы, которые ближе к корню (верх) дерева, дают больше разделений и содержат больше информации чем те, что внизу дерева. В нашем случае Стохастический Осциллятор даже не попал в дерево!

Хоть у нас и появился набор правил, которым можно следовать, стоит все-таки убедиться, что мы не переобучили модель, поэтому давайте подрежем дерево. Самый простой способ сделать это – посмотреть на параметр сложности, который является «стоимостью», или снижением производительности. Для этого нужно добавить еще одно разделение и выбрать размер дерева, который минимизирует нашу ошибку перекрестной проверки.

printcp(DecisionTree)
#Вывод минимального cp(параметра сложности) для каждого дерева, каждого размера
plotcp(DecisionTree,upper="splits")
#Чертеж среднего геометрического значения для деревьев каждого размера





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

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

PrunedDecisionTree<-prune(DecisionTree,cp=0.0272109)
#Я использую параметр сложности (cp), у которого наименьшая ошибка перекрестной проверки (xerror)

Теперь дерево выглядит так:

prp(PrunedDecisionTree, type=2, extra=8)




Так гораздо лучше! Здесь видно, что линия MACD сигнала больше не используется. Мы начали с 4-х индикаторов, из которых только 3-х дневный RSI, разница между ценами, и 5-ти дневный EMA могут быть полезны в предсказании движения цены.

Пришло время проверить модель на тестовых данных.

table(predict(PrunedDecisionTree,TestSet,type="class"),TestSet[,5],dnn=list('predicted','actual'))




В общем не плохо, 52% точность. Что более важно, у вас есть основа стратегии с четко определенными, математическими параметрами. Используя всего 25 команд, мы смогли определить, какие индикаторы полезны и какие специальные условия нам нужны для совершения сделки. Теперь вы можете использовать эти индикаторы для собственной торговли или улучшить дерево.

В следующей статье мы рассмотрим еще один мощный алгоритм машинного обучения, метод опорных векторов, и разберемся, как можно использовать его результаты для еще более здравой стратегии.
Tags:
Hubs:
Total votes 21: ↑19 and ↓2+17
Comments6

Articles