Методы машинного обучения для моделирования и прогнозирования финансовых временных рядов

Дипломная работа

AdaBoost: алгоритм усиления слабых классификаторов

В отличие от всех алгоритмов, что были описаны ранее, алгоритмAdaBoostработает с другими алгоритмами, создавая конструкции из моделей. Концепция усиления (boosting) основывается на идее создания сильного и точного правила классификации путем комбинации нескольких слабых и относительно неточных классификаторов. Алгоритм AdaBoost, разработанный Йоавом Фройндом и Робертом Гапире в 1997 году, является первым примером реализации подобной идеи. Более того этот алгоритм до сих пор является наиболее используемым и исследованным среди всего класса усиливающих алгоритмов. Во многом это связано с сильными сторонами предложенного алгоритма.

Сформулируем задачу, стоящую перед алгоритмом: Требуется построить классификатор , где X — пространство векторов признаков, а Y — пространство классов. Данный алгоритм является методом машинного обучения с учителем, а потому имеется обучающая выборка , где . Обычно в рамках алгоритма рассматривается бинарная классификация, где {.Так же мы имеем множество слабых классификаторов >y, … , } Итоговым классификатор Сбудет иметь вид кусочно-постоянно функции, составленной из взвешенных слабых классификаторов:

, где — вес l-его классификатора

В рамках работы алгоритма происходит два важных этапа: отбор слабых классификаторов и их комбинирование. Структура алгоритма выглядит следующим образом.

Задается исходное распределение ;

Для каждой итерации :

  • в распределении ;

вычисляется весовой коэффициент

взвешенный классификатор

обновляется распределение весов

Подбирается нормализующий коэффициент ;

Создается ансамбль, представляющий собой кусочно-линейный классификатор

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

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

12 стр., 5587 слов

Усиление кирпичных конструкций виды и методики расчета

... Виды усиления стен. А) Усиление стен врезными колоннами. Если вследствие перегрузок (замена перекрытий, надстройка этажей) стеновые конструкции не соответствуют требованиям по прочности, имеющиеся кирпичные ... обеспечивающим усиление слабого, пониженной ... и для ленточных фундаментов. Важно, чтобы бетонные накладки по бокам фундамента (обкладки) соединялись снизу стяжками, выполненными по расчету. ...

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

  • Классификация;
  • поиск ассоциативных правил;
  • сокращение размерности данных;
  • ранжирования;
  • кластеризация.

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

Применение алгоритмов машинного обучения для прогнозирования поведения финансовых временных рядов

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

Так группа исследователей из МадридскогоГосударственного Университета, Педро Н. Родригез и Симон Сосвилла-Риверо провели исследование американского рынка акций. (Using machine learning algorithms to find patterns in stock prices, 2006) Они рассмотрели применение алгоритма С4.5 в связке с методом адаптивного усиления классификаторов. Проанализировав большой пласт исторических данных с 1962 по 2004 годы. Исследователями была выявлена возможность прогнозирования поведения финансовых временных рядов. Испанские исследователи варьировали количество итераций усиливающего алгоритма, пытаясь оценить влияние данного параметра на внутри-выборочную и вне-выборочную точность.

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

Другим исследованием, рассматривающим применение целого набора методов машинного обучения, а также их комбинацию, является работа польского доктора информатики Крустофа Д. Г. (Krzysztof Jerzy Geras).

В этой работе исследователь выстраивает инструментарий машинного обучения для поиска прогнозной функции (bettingfunction) или, как она еще называется, функции покупки (buyingfunction).

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

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

13 стр., 6328 слов

Машинное обучение (2)

... показывают лучшие результаты. Методы машинного обучения могут позволить предсказать исход какой-либо ситуации, основываясь на исторических данных. В отличие от ... машинного обучения Машинное обучения позволяет решать ряд задач, самыми распространёнными из которых являются: 1. Классификация 2. Регрессия 3. Кластеризация 4. Фильтрация выбросов Задача классификации задачи регрессии При прогнозировании ...

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

Говоря о теме усиливающих алгоритмов, нельзя не упомянуть о работе индийской группы исследователей доктора Субхенду Пани (Dr.Subhendu Pani) и Сунджайя Сен (Sanjaya Sen).

Ученые рассмотрели классификационный алгоритм CART в приложение к различным методам построения ансамблей моделей. Ученые рассмотрели такие алгоритмы, как ADABOOST, LOGIBOOST, BAGGING, DAGGING. В рамках работы анализировался индийский рынок акций. Задачей, поставленной исследователями, была успешная классификация направления движения. Согласно исследованию, алгоритм ADABOOST давал наилучший результат среди других алгоритмов усиления.

Хорошие результаты в прогнозировании финансовых временных рядов и в частности фондовых рынков, показали такие методы как модель классификационных деревьев CART, область построения искусственных нейронных сетей, алгоритм ADAboost, а также машина опорных векторов SVM. Врядеработ (Using machine learning algorithms to find patterns in stock prices, 2006), (Prediction Markets for Machine Learning, 2011), (Machine Learning Techniques for Stock Prediction, 2007), (Application of Machine Learning Algorithm in Indian Stock Market Data, 2014), (Satish Rao, 2010) выделяется эффективность таких методов, как деревья принятия решений. Возможность построения сильного классификатора, эффективно справляющегося с поставленными задачами. Так же отмечена эффективность использования ансамблей из слабых классификаторов, в частности классификационно-регрессионных деревьев, для прогнозирования и различных методов бустинга. В рамках практической части работы будет рассмотрена модель, реализующая принципы машинного обучения, в рамках решения задачи из области финансов, применяя комбинацию методов CART + ADAboost.

2.Модель ансамблей классификационных деревьев для прогнозирования динамики финансовых временных рядов

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

2.1 Постановка практической задачи

В рамках объекта исследования был выбран американский фондовый рынок. Американский фондовый рынок — крупнейший региональный сегмент фондового рынка, обладающей капитализацией более 19 триллионов долларов(Bank of America Merrill Lynch, 2014).

На рынке NYSE прошли процедуру листинга более 3,5 тысяч компаний, среди которых крупнейшие компании американской экономики и мира. Обладая огромной ликвидностью этот рынок является отличной модельной площадкой для применения численных методов.

Анализ будет проводиться на котировках акций компании Apple (тикет: AAPL).

Компания занимает первое место по капитализации не только среди американских, но и среди мировых компаний. Ликвидность, публичность и длительная история котирования на рынке — три критерия, по которым был отобран данный символ.

Основной задачей финансового моделирования является прогнозирование динамики финансового временного ряда — в нашем случае это котировки символа AAPL. При прогнозировании движения котировки наибольшую важность имеют такие показатели как направление прогнозируемого движения (d), влияющая на тип торгового приказа, прогнозируемая амплитуда (a), вероятность прогноза и горизонт прогноза (t).

Опираясь на принцип построения алгоритмов «разделяй и властвуй» мы можем рекурсивно разбивать задачу прогнозирования F c характеристиками a, d, с,tна n подзадач , , … . Если экстраполировать, то мы придем к атомарной операции — прогнозу движения цены на минимальный инвестиционный горизонт. В данном случае мы можем перейти к прогнозированию направления движения.

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

2.2 Выбор алгоритма для анализа данных

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

Данная комбинация аналитических инструментов является эффективной с точки зрения вычислительной эффективности. При использовании алгоритмов усиления простых классификаторов важным требованием является производительность базового алгоритма. Именно по этой причине такой эффективный алгоритм как SVM ограничен в применение с усиливающими алгоритмами.

Для работы подобного алгоритма необходимо сформировать данные в определенном формате. Данные необходимо разбить на следующие категории: предикторы, временные ряды, что объясняют изменения и предиктанды — временные ряды, поведение которых объясняют предикторы.

Форма представления предиктанда, при подаче его в алгоритм CARTдолжна быть категориальной, то есть должна принимать ограниченный набор значений. В нашем случае это прогнозируемый рост значения временного ряда (UP) и прогнозируемое падение значения временного ряда (DOWN).

Предикторы имеют свободную форму представления, но в нашем случае это буду значения .В качестве предикторов были выбраны временные ряды котировки AAPL, индекса S&P500, характеризующего экономику, а также технологический индекс NASDAQ, а также их производные.

Предиктанд

Предиктор

Ряд , где .

Цена открытия AAPL, а также ее лаг на 14 периодов;

приращение цены открытия AAPL, a также ее лаг на 14 периодов;

цена закрытия AAPL, a также ее лаг на 14 периодов;

приращение цены закрытия AAPL, a также ее лаг на 14 периодов;

максимальная цена AAPL за период;

минимальная цена AAPL за период;

торговый объем AAPL за период a также его лаг на 14 периодов;

приращение торгового объема AAPL, a также его лаг на 14 периодов;

значения индикатора MACD* по цене открытия AAPL периода;

значение индикатора macd по цене закрытия AAPL периода;

значение индикатора Stochastic;

значение осциллятора RSI** по цене открытия AAPL периода;

значение осциллятора RSI по цене закрытия AAPL периода;

Цена открытия COMP***, а также ее лаг на 14 периодов;

приращение цены открытия COMP, a также ее лаг на 14 периодов;

цена закрытия COMP, a также ее лаг на 14 периодов;

приращение цены закрытия COMP, a также ее лаг на 14 периодов;

максимальная цена COMP за период;

минимальная цена COMP за период;

торговый объем COMP за период a также его лаг на 14 периодов;

приращение торгового объема COMP, a также его лаг на 14 периодов;

значения индикатора MACD по цене открытия COMP периода;

значение индикатора MACD по цене закрытия COMP периода;

значение индикатора Stochastic;

значение осциллятора RSI по цене открытия COMP периода;

значение осциллятора RSI по цене закрытия COMP периода;

Цена открытия SPY****, а также ее лаг на 14 периодов;

приращение цены открытия SPY, a также ее лаг на 14 периодов;

цена закрытия SPY, a также ее лаг на 14 периодов;

приращение цены закрытия SPY, a также ее лаг на 14 периодов;

максимальная цена SPY за период;

минимальная цена SPY за период;

торговый объем SPY за период a также его лаг на 14 периодов;

приращение торгового объема SPY, a также его лаг на 14 периодов;

значения индикатора MACD по цене открытия SPY периода;

значение индикатора MACD по цене закрытия SPY периода;

значение индикатора Stochastic;

значение осциллятора RSI по цене открытия SPY периода;

значение осциллятора RSI по цене закрытия SPY периода;

Таблица 2

*MACD — технический индикатор, разработанный Джеральдом Аппеем. Широко используется трейдерами для прогнозирования поведения биржевых котировок. Технически, представляет собой композицию из скользящих средних разного периода.

**RSI — технический индикатор, широко применяемый для, так называемого, диагностирования разворотных точек при торговле. Разработан Уилисом Валдером и стал одним из самых широко применимых инструментов технического анализа.

***COMP — NASDAQCOMPosite. Сводный индекс американской высокотехнологической биржи США. Индекс включает акции более 5 тысяч компаний-эмитентов из США и других стран.

****SPY — индексный фонд, портфель которого в точности повторяет индекс S&P 500.

2.3 Практическая реализация модели

В рамках исследования был построена программная реализация практической модели. Модель была реализована средствами программной среды R. Данная среда включает язык программирования, ориентированный на реализацию статистических вычислений. В рамках реализации были разработан ряд скриптов. Скрипты реализуют один или несколько этапов задачи:

  • Подготовка данных;
  • отбор переменных;
  • построение модели;
  • оптимизация модели;
  • оценка модели.

Первым этапом была подготовка сырых данных, поданных на вход к удобному для анализа виду. В рамках работы первого скрипта были проведены такие процедуры, как выстраивание таймфрейма, очистка данных от выбросов и неполных данных, генерация производных временных рядов и упорядочивание массива данных. Данная процедура в специализированной литературе получила название «Datatidying». Основной задачей данной процедуры является получение упорядоченного набора данных — такого массива данных, которых подчинялся бы трем признакам:

  • Каждая переменная формирует столбец;
  • каждое наблюдение формирует строчку;
  • каждый тип единиц наблюдения образует таблицу.

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

Данные

Символ

Период

Наблюдения

1.

Котировки компании Apple

AAPL

2005-01-03/2015-11-13

1 063 974

2.

Сводныйиндекс NASDAQ

COMP

2014-01-02/2015-12-31

195 596

3.

Индекс S&P 500

SPY

2005-01-03/2015-11-16

1 072 501

Таблица 3

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

# Establishingconvenienttimeframe

kTimeframe<- 15

# AAPL

dF<

  • AAPL.M1[(1 : kTimeframe),c(‘AAPL.Open’,’AAPL.High’,’AAPL.Low’,

‘AAPL.Close’,’AAPL.Volume’)]

AAPL.Open <

  • as.numeric(dF[1,’AAPL.Open’])

AAPL.High <

  • max(dF[,’AAPL.High’])

AAPL.Low <

  • min(dF[,’AAPL.Low’])

AAPL.Close <

  • AAPL.M1[timeframe,’AAPL.Close’]

AAPL.Volume <

  • sum(dF[,’AAPL.Volume’])

AAPL.0row <

  • cbind(AAPL.Open, AAPL.High, AAPL.Low, AAPL.Close, AAPL.Volume)

names(AAPL.0row)<

  • c(‘AAPL.Open’,

‘AAPL.High’,

‘AAPL.Low’,

‘AAPL.Close’,

‘AAPL.Volume’)

rm(dF, AAPL.Open, AAPL.High, AAPL.Low, AAPL.Close, AAPL.Volume)

for(i in(1 : (as.integer(nrow(AAPL.M1)/kTimeframe) — kTimeframe))){

dF <

  • AAPL.M1[(1 + kTimeframe*i):(kTimeframe*(i+1)),]

AAPL.Open <

  • as.numeric(dF[1,’AAPL.Open’])

AAPL.High <

  • max(dF[,’AAPL.High’])

AAPL.Low <

  • min(dF[,’AAPL.Low’])

AAPL.Close <

  • dF[kTimeframe,’AAPL.Close’]

AAPL.Volume <

  • sum(dF[,’AAPL.Volume’])

AAPL.row <

  • cbind(AAPL.Open, AAPL.High, AAPL.Low, AAPL.Close, AAPL.Volume)

names(AAPL.row)<

  • c(‘AAPL.Open’,

‘AAPL.High’,

‘AAPL.Low’,

‘AAPL.Close’,

‘AAPL.Volume’)

AAPL.0row <

  • rbind(AAPL.0row, AAPL.row)

}

AAPL.M15 <

  • AAPL.0row

rm(AAPL.0row,AAPL.Open, AAPL.High, AAPL.Low, AAPL.Close, AAPL.Volume, AAPL.row,

i,dF)

В результате были получены 3 массива данных, состоящих из данных, отобранных с частотой 15 периодов из исходных сырых данных — AAPL.M15, COMP.M15, SP500.M15. В результате был получен ряд, повторяющий исходные данные, фильтрующий интерчастотные колебания. Важно заметить, что минимумы и максимумы колебаний учитываются.

Рисунок 15 Соотнесение таймфреймов M1 и M15

После того, как данные были переведены в старший таймфрейм была проведена проверка на полноту данных в разрезе каждого массива данных. После предварительных процедур была произведена генерация производных временных рядов от массивов AAPL.M15, COMP.M15, SP500.M15 (подробнее см. Приложение 1).

Были сформированы ряды, указанные в Табл. 3. На основание них были получены массивы Data.AAPL, Data.NASDAQи Data.SP500.

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

Решением возникшей проблемы может стать процедура отбора переменных (featureselection): необходимооценить временные ряды, их качественность с точки зрения прогностической способности. В результате станет возможным отсеять низкокачественные ряды. В рамках работы были применены следующие методы оценки: поиск линейно корреляции, а также информационная энтропия. Так же было принято решение об отказе от использования значений индекса NASDAQ в виду невозможности использования его для тестирования на разных рыночных эпохах, ввиду его краткости.

#Establishing library

library(quantmod)

library(FSelector)

#Loading tydied data

load(«I:/DataMining/#PROJECTS/Diplom/DATA/Data.tidyed.RData»)

#====================================================Filtering=================

# Linear correlations

lin.corr <

— linear.correlation(dCl.Px ~ Op.Px + Op.lag1.Px + Op.lag2.Px + Op.lag3.Px + Op.lag4.Px + Op.lag5.Px + Op.lag6.Px + Op.lag7.Px + Op.lag8.Px + Op.lag9.Px + Op.lag10.Px + Op.lag11.Px +Op.lag12.Px + Op.lag13.Px + Op.lag14.Px + dOp.Px + dOp.lag2.Px + dOp.lag3.Px + dOp.lag4.Px + dOp.lag5.Px + dOp.lag6.Px + dOp.lag7.Px + dOp.lag8.Px + dOp.lag9.Px + dOp.lag10.Px + dOp.lag11.Px + dOp.lag12.Px + dOp.lag13.Px + dOp.lag14.Px + Cl.Px + Cl.lag1.Px + Cl.lag2.Px + Cl.lag3.Px + Cl.lag4.Px + Cl.lag5.Px + Cl.lag6.Px + Cl.lag7.Px +Cl.lag8.Px + Cl.lag9.Px + Cl.lag10.Px+ Cl.lag11.Px + Cl.lag12.Px + Cl.lag13.Px + Cl.lag14.Px + dCl.lag2.Px + dCl.lag3.Px + dCl.lag4.Px + dCl.lag5.Px + dCl.lag6.Px + dCl.lag7.Px + dCl.lag8.Px + dCl.lag9.Px + dCl.lag10.Px + dCl.lag11.Px + dCl.lag12.Px + dCl.lag13.Px + dCl.lag14.Px + High.Px + Low.Px + Vo + Vo.lag1 + Vo.lag2 + Vo.lag3 + Vo.lag4 + Vo.lag5 + Vo.lag6 + Vo.lag7 + Vo.lag8 + Vo.lag9 + Vo.lag10 + Vo.lag11 + Vo.lag12 + Vo.lag13 + Vo.lag14 + dVo.Px + dVo.lag2 + dVo.lag3 + dVo.lag4 + dVo.lag5 + dVo.lag6 + dVo.lag7 + dVo.lag8 + dVo.lag9 + dVo.lag10 + dVo.lag11 + dVo.lag12 + dVo.lag13 + dVo.lag14 + MACD.Open + MACD.Open.signal + MACD.Volume + MACD.Volume.signal + Stoch.fastK + Stoch.fastD + Stoch.slowD + RSI.Open + RSI.Close + dOp.Px.SP500 + dOp.lag2.Px.SP500 + dOp.lag3.Px.SP500 + dOp.lag4.Px.SP500 + dOp.lag5.Px.SP500+ dOp.lag6.Px.SP500 + dOp.lag7.Px.SP500 + dOp.lag8.Px.SP500 + dOp.lag9.Px.SP500 + dOp.lag10.Px.SP500 + dOp.lag11.Px.SP500 + dOp.lag12.Px.SP500 + dOp.lag13.Px.SP500 + dOp.lag14.Px.SP500 + dCl.Px.SP500 + dCl.lag2.Px.SP500 + dCl.lag3.Px.SP500 + dCl.lag4.Px.SP500 + dCl.lag5.Px.SP500 + dCl.lag6.Px.SP500 + dCl.lag7.Px.SP500 + dCl.lag8.Px.SP500 + dCl.lag9.Px.SP500+ dCl.lag10.Px.SP500 + dCl.lag11.Px.SP500 + dCl.lag12.Px.SP500 + dCl.lag13.Px.SP500 + dCl.lag14.Px.SP500 + Vo.SP500 + Vo.lag1.SP500 + Vo.lag2.SP500 + Vo.lag3.SP500 + Vo.lag4.SP500 + Vo.lag5.SP500 + Vo.lag6.SP500 + Vo.lag7.SP500 + Vo.lag8.SP500 + Vo.lag9.SP500 + Vo.lag10.SP500 + Vo.lag11.SP500 + Vo.lag12.SP500 + Vo.lag13.SP500 + Vo.lag14.SP500 + dVo.Px.SP500 + dVo.lag2.SP500 + dVo.lag3.SP500 + dVo.lag4.SP500 + dVo.lag5.SP500 + dVo.lag6.SP500 + dVo.lag7.SP500+ dVo.lag8.SP500 + dVo.lag9.SP500 + dVo.lag10.SP500 + dVo.lag11.SP500 + dVo.lag12.SP500 + dVo.lag13.SP500 + dVo.lag14.SP500,data = Data)

# Information entropy

information.entropy <

— information.gain(dCl.Px ~ Op.Px + Op.lag1.Px + Op.lag2.Px + Op.lag3.Px + Op.lag4.Px + Op.lag5.Px + Op.lag6.Px + Op.lag7.Px + Op.lag8.Px + Op.lag9.Px + Op.lag10.Px + Op.lag11.Px +Op.lag12.Px + Op.lag13.Px + Op.lag14.Px + dOp.Px + dOp.lag2.Px + dOp.lag3.Px + dOp.lag4.Px + dOp.lag5.Px + dOp.lag6.Px + dOp.lag7.Px + dOp.lag8.Px + dOp.lag9.Px + dOp.lag10.Px + dOp.lag11.Px + dOp.lag12.Px + dOp.lag13.Px + dOp.lag14.Px + Cl.Px + Cl.lag1.Px + Cl.lag2.Px + Cl.lag3.Px + Cl.lag4.Px + Cl.lag5.Px + Cl.lag6.Px + Cl.lag7.Px +Cl.lag8.Px + Cl.lag9.Px + Cl.lag10.Px+ Cl.lag11.Px + Cl.lag12.Px + Cl.lag13.Px + Cl.lag14.Px + dCl.lag2.Px + dCl.lag3.Px + dCl.lag4.Px + dCl.lag5.Px + dCl.lag6.Px + dCl.lag7.Px + dCl.lag8.Px + dCl.lag9.Px + dCl.lag10.Px + dCl.lag11.Px + dCl.lag12.Px + dCl.lag13.Px + dCl.lag14.Px + High.Px + Low.Px + Vo + Vo.lag1 + Vo.lag2 + Vo.lag3 + Vo.lag4 + Vo.lag5 + Vo.lag6 + Vo.lag7 + Vo.lag8 + Vo.lag9 + Vo.lag10 + Vo.lag11 + Vo.lag12 + Vo.lag13 + Vo.lag14 + dVo.Px + dVo.lag2 + dVo.lag3 + dVo.lag4 + dVo.lag5 + dVo.lag6 + dVo.lag7 + dVo.lag8 + dVo.lag9 + dVo.lag10 + dVo.lag11 + dVo.lag12 + dVo.lag13 + dVo.lag14 + MACD.Open + MACD.Open.signal + MACD.Volume + MACD.Volume.signal + Stoch.fastK + Stoch.fastD + Stoch.slowD + RSI.Open + RSI.Close + dOp.Px.SP500 + dOp.lag2.Px.SP500 + dOp.lag3.Px.SP500 + dOp.lag4.Px.SP500 + dOp.lag5.Px.SP500+ dOp.lag6.Px.SP500 + dOp.lag7.Px.SP500 + dOp.lag8.Px.SP500 + dOp.lag9.Px.SP500 + dOp.lag10.Px.SP500 + dOp.lag11.Px.SP500 + dOp.lag12.Px.SP500 + dOp.lag13.Px.SP500 + dOp.lag14.Px.SP500 + dCl.Px.SP500 + dCl.lag2.Px.SP500 + dCl.lag3.Px.SP500 + dCl.lag4.Px.SP500 + dCl.lag5.Px.SP500 + dCl.lag6.Px.SP500 + dCl.lag7.Px.SP500 + dCl.lag8.Px.SP500 + dCl.lag9.Px.SP500+ dCl.lag10.Px.SP500 + dCl.lag11.Px.SP500 + dCl.lag12.Px.SP500 + dCl.lag13.Px.SP500 + dCl.lag14.Px.SP500 + Vo.SP500 + Vo.lag1.SP500 + Vo.lag2.SP500 + Vo.lag3.SP500 + Vo.lag4.SP500 + Vo.lag5.SP500 + Vo.lag6.SP500 + Vo.lag7.SP500 + Vo.lag8.SP500 + Vo.lag9.SP500 + Vo.lag10.SP500 + Vo.lag11.SP500 + Vo.lag12.SP500 + Vo.lag13.SP500 + Vo.lag14.SP500 + dVo.Px.SP500 + dVo.lag2.SP500 + dVo.lag3.SP500 + dVo.lag4.SP500 + dVo.lag5.SP500 + dVo.lag6.SP500 + dVo.lag7.SP500+ dVo.lag8.SP500 + dVo.lag9.SP500 + dVo.lag10.SP500 + dVo.lag11.SP500 + dVo.lag12.SP500 + dVo.lag13.SP500 + dVo.lag14.SP500,data = Data)

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

Рисунок 16

На основе полученных данных были отобран ряд рядов, обладающих сравнительным преимуществом. На основе этих аналитических данных общий массив входных данных для моделирования был уменьшен, сохранив только «эффективные» ряды. В итоговое моделирование попали следующие ряды: приращение цены открытия AAPLи ряд его лагов, приращение цены закрытия AAPL и ряд его лагов, значение торгового объема, значения индикатора StochasticпоAAPL, значение индикатора RSIпо ценам закрытия AAPL, а также приращение цены закрытия индекса S&P 500 и ряд его лагов.

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

Рисунок 17 Иттерационная структура алгоритма

Было принято решение выстроить модельную часть программы в виде функции, запускаемой lapply()-одной из функций семейства apply().

Программная реализация представлена ниже:

  • FunFitAndPred<
  • function(dF,index.par,index){

# Function split rolling window on train and test parts. Next step is modeling

# using rpart algorithms the model on the train sample. Futhermore this model

# boosts in ADAboost algorithm. Last step is predicting tests on the both

# samples — test and train.

#

# Agrs:

# dF: dataframe, where rolling window exist.

# index.par: index of matrix in global environment, which include sets of

# parameters. Set of parameters uses for fitting and modelling.

# index: index of dataframe, establishing rolling window position

#

# Returns:

# vector of errors in train and test sample

par<

  • parametr.valuation[index.par,]

# Routing parameters

N <- as.numeric(par[1])

n <- as.numeric(par[2])

m <- as.numeric(par[3])

control<

  • rpart.control(maxdepth = as.numeric(par[4]))

mfinal <- as.numeric(par[5])

# Training sample

train <- dF[(kN — n — 1 + index):(kN — 1 + index),]

train.predictand <

  • factor(ifelse(tail(train$dCl.Px, -1)>0,1,0),

levels = c(1,0))

train.predictand <

  • as.matrix(train.predictand)

colnames(train.predictand)<- c(‘predictand’)

train.predictors <- head(train[,c(1:21)], -1)

train.data <

  • cbind(train.predictand, train.predictors)

# Fiting tree and ADAboosting

fit <

  • boosting(predictand ~ dOp.Px + dOp.lag2.Px + dCl.lag2.Px + dCl.lag3.Px

+ dCl.lag4.Px + dCl.lag5.Px + dCl.lag6.Px + dCl.lag7.Px

+ dCl.lag8.Px + dCl.lag9.Px + dCl.lag10.Px + dCl.lag11.Px

+ dCl.lag12.Px + Vo + Stoch.fastK + Stoch.fastD + RSI.Close

+ dCl.Px.SP500 + dCl.lag2.Px.SP500 + dCl.lag3.Px.SP500

+ dCl.lag4.Px.SP500,data = train.data, mfinal = mfinal,

coeflearn = ‘Breiman’,control = control)

# Test sample

test <- dF[(kN + index):(kN + kM + index),]

test.predictand <

  • factor(ifelse(tail(test$dCl.Px, -1)>0,1,0),

levels = c(1,0))

test.predictand <

  • as.matrix(test.predictand)

colnames(test.predictand)<- c(‘predictand’)

test.predictors <- head(test[,c(1:21)], -1)

test.data <

  • cbind(test.predictand, test.predictors)

# Predicting

train.predict <

  • predict(fit, train.data)

test.predict <

  • predict(fit, test.data)

output <

  • c(test.predict[6])

print(«PROCESSING»)

return(output)

}

В рамках исполнения данной функции выполняется ряд задач. Так первоначально функция извлекает из всего массива анализируемых данных выборку, на которой будет проводиться моделирование. Алгоритм разбивает извлеченный суб-массив на обучающую выборку и тестовую. По данным обучающей выборки алгоритм формирует модель — набор классификационных деревьев. Данные деревья участвуют в формирование ансамбля, в рамках работы алгоритма адаптивного усиления. Когда ансамбль окончательно сформирован, он используется для прогнозирования значений предиктанда на тестовой выборке. Результатом работы моделирующей функции является точность прогноза на тестовой выборке.

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

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

Следующим этапом стало применение готовой модели с подобранными оптимальными параметрами. Для тестирования был выбран диапазон, находящийся вне обучающей выборки, длиной 2000 наблюдений. После прогонки задачи по этому диапазону была получена итоговая средняя точность прогноза — 50,8% на трехпериодном горизонте прогнозирования и 53,8% на однопериодном.

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

Заключение

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

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

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

Рисунок 18

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

Рисунок 19

Основная гипотеза работы о возможности применения методов машинного обучения для прогнозирования финансовых временных рядов, в частности данных рынка акций подтвердилась. Исследовательская модель, разработанная для проверки поставленной гипотезы, подтвердила возможность прогнозирования фондового рынка с помощью указанных методов. Точность прогноза направления изменения цены закрытия акций компании Apple(биржевой тикет: AAPL) при периоде прогноза в 3 периода составляет 50,8%. При прогнозе атомарного изменения цены результат прогноза составляет 53,8%. При этом разница в точности в обучающей и тестовой выборках составляет в среднем составляет 10%: 66,1%в среднем при описание обучающей выборки.Данные результаты свидетельствуют о том, что, используя данную модель можно извлекать аналитическую прибыль.

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

более качественный подбор входных данных, применение очистки данных от шума, в частности метода главных компонент

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

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

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

применение данной модели в связке с методом определения «режима» рынка.

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

Приложение 1

#Establishinglibrary

library(quantmod)

#Loading row data

load(«I:/DataMining/#PROJECTS/Diplom/DATA/aapl_2005_2015.RData»)

load(«I:/DataMining/#PROJECTS/Diplom/DATA/spy_2005_2015.RData»)

load(«I:/DataMining/#PROJECTS/Diplom/DATA/nasdaq.RData»)

AAPL.M1 <- aapl

NASDAQ.M1 <- nasdaq

SP500.M1 <- spy

rm(aapl, nasdaq, spy)

##=====================================Data Composition========================

# Establishing convenient timeframe

kTimeframe <- 15

# AAPL

dF <

  • AAPL.M1[(1 : kTimeframe),c(‘AAPL.Open’,’AAPL.High’,’AAPL.Low’,

‘AAPL.Close’,’AAPL.Volume’)]

AAPL.Open <

  • as.numeric(dF[1,’AAPL.Open’])

AAPL.High <

  • max(dF[,’AAPL.High’])

AAPL.Low <

  • min(dF[,’AAPL.Low’])

AAPL.Close <

  • AAPL.M1[timeframe,’AAPL.Close’]

AAPL.Volume <

  • sum(dF[,’AAPL.Volume’])

AAPL.0row <

  • cbind(AAPL.Open, AAPL.High, AAPL.Low, AAPL.Close, AAPL.Volume)

names(AAPL.0row)<

  • c(‘AAPL.Open’,

‘AAPL.High’,

‘AAPL.Low’,

‘AAPL.Close’,

‘AAPL.Volume’)

rm(dF, AAPL.Open, AAPL.High, AAPL.Low, AAPL.Close, AAPL.Volume)

for(i in(1 : (as.integer(nrow(AAPL.M1)/kTimeframe) — kTimeframe))){

dF <

  • AAPL.M1[(1 + kTimeframe*i):(kTimeframe*(i+1)),]

AAPL.Open <

  • as.numeric(dF[1,’AAPL.Open’])

AAPL.High <

  • max(dF[,’AAPL.High’])

AAPL.Low <

  • min(dF[,’AAPL.Low’])

AAPL.Close <

  • dF[kTimeframe,’AAPL.Close’]

AAPL.Volume <

  • sum(dF[,’AAPL.Volume’])

AAPL.row <

  • cbind(AAPL.Open, AAPL.High, AAPL.Low, AAPL.Close, AAPL.Volume)

names(AAPL.row)<

  • c(‘AAPL.Open’,

‘AAPL.High’,

‘AAPL.Low’,

‘AAPL.Close’,

‘AAPL.Volume’)

AAPL.0row <

  • rbind(AAPL.0row, AAPL.row)

}

AAPL.M15 <

  • AAPL.0row

rm(AAPL.0row,AAPL.Open, AAPL.High, AAPL.Low, AAPL.Close, AAPL.Volume, AAPL.row,

i, dF)

# NASDAQ

dF <

  • NASDAQ.M1[(1 : kTimeframe),c(‘COMP.Open’,’COMP.High’,’COMP.Low’,

‘COMP.Close’,’COMP.Volume’)]

COMP.Open <

  • as.numeric(dF[1,’COMP.Open’])

COMP.High <

  • max(dF[,’COMP.High’])

COMP.Low <

  • min(dF[,’COMP.Low’])

COMP.Close <

  • NASDAQ.M1[kTimeframe,’COMP.Close’]

COMP.Volume <

  • sum(dF[,’COMP.Volume’])

COMP.0row <

  • cbind(COMP.Open, COMP.High, COMP.Low, COMP.Close, COMP.Volume)

names(COMP.0row)<

  • c(‘COMP.Open’,

‘COMP.High’,

‘COMP.Low’,

‘COMP.Close’,

‘COMP.Volume’)

rm(dF, COMP.Open, COMP.High, COMP.Low, COMP.Close, COMP.Volume)

for(i in(1 : (as.integer(nrow(NASDAQ.M1)/kTimeframe) — kTimeframe))){

dF <

  • NASDAQ.M1[(1 + kTimeframe*i):(kTimeframe*(i+1)),]

COMP.Open <

  • as.numeric(dF[1,’COMP.Open’])

COMP.High <

  • max(dF[,’COMP.High’])

COMP.Low <

  • min(dF[,’COMP.Low’])

COMP.Close <

  • dF[kTimeframe,’COMP.Close’]

COMP.Volume <

  • sum(dF[,’COMP.Volume’])

COMP.row <

  • cbind(COMP.Open, COMP.High, COMP.Low, COMP.Close, COMP.Volume)

names(COMP.row)<

  • c(‘COMP.Open’,

‘COMP.High’,

‘COMP.Low’,

‘COMP.Close’,

‘COMP.Volume’)

COMP.0row <

  • rbind(COMP.0row, COMP.row)

}

NASDAQ.M15 <

  • COMP.0row

rm(COMP.0row,COMP.Open, COMP.High, COMP.Low, COMP.Close, COMP.Volume, COMP.row,

i, dF)

# S&P 500

dF <

  • SP500.M1[(1 : kTimeframe),c(‘SPY.Open’,’SPY.High’,’SPY.Low’,

‘SPY.Close’,’SPY.Volume’)]

SPY.Open <

  • as.numeric(dF[1,’SPY.Open’])

SPY.High <

  • max(dF[,’SPY.High’])

SPY.Low <

  • min(dF[,’SPY.Low’])

SPY.Close <

  • SP500.M1[kTimeframe,’SPY.Close’]

SPY.Volume <

  • sum(dF[,’SPY.Volume’])

SPY.0row <

  • cbind(SPY.Open, SPY.High, SPY.Low, SPY.Close, SPY.Volume)

names(SPY.0row)<

  • c(‘SP500.Open’,

‘SP500.High’,

‘SP500.Low’,

‘SP500.Close’,

‘SP500.Volume’)

rm(dF, SPY.Open, SPY.High, SPY.Low, SPY.Close, SPY.Volume)

for(i in(1 : (as.integer(nrow(SP500.M1)/kTimeframe) — kTimeframe))){

dF <

  • SP500.M1[(1 + kTimeframe*i):(kTimeframe*(i+1)),]

SPY.Open <

  • as.numeric(dF[1,’SPY.Open’])

SPY.High <

  • max(dF[,’SPY.High’])

SPY.Low <

  • min(dF[,’SPY.Low’])

SPY.Close <

  • dF[kTimeframe,’SPY.Close’]

SPY.Volume <

  • sum(dF[,’SPY.Volume’])

SPY.row <

  • cbind(SPY.Open, SPY.High, SPY.Low, SPY.Close, SPY.Volume)

names(SPY.row)<

  • c(‘SP500.Open’,

‘SP500.High’,

‘SP500.Low’,

‘SP500.Close’,

‘SP500.Volume’)

SPY.0row <

  • rbind(SPY.0row, SPY.row)

}

SP500.M15 <- SPY.0row

rm(SPY.0row,SPY.Open, SPY.High, SPY.Low, SPY.Close, SPY.Volume, SPY.row, i, dF)

# Creating temporary data-buffer

data.stoch <

  • AAPL.M15[,c(‘AAPL.High’,’AAPL.Low’,’AAPL.Close’)]

data.stoch.NASDAQ <

  • NASDAQ.M15[,c(‘COMP.High’,’COMP.Low’,’COMP.Close’)]

data.stoch.SP500 <

  • SP500.M15[,c(‘SP500.High’,’SP500.Low’,’SP500.Close’)]

# Fixing NAs

AAPL.M15 <

  • AAPL.M15[complete.cases(AAPL.M15),]

NASDAQ.M15 <

  • NASDAQ.M15[complete.cases(NASDAQ.M15),]

SP500.M15 <

  • SP500.M15[complete.cases(SP500.M15),]

# Naming variables

# AAPL

Op.Px <

  • Op(AAPL.M15)

Op.lag1.Px <

  • lag(Op(AAPL.M15), k=1)

Op.lag2.Px <

  • lag(Op(AAPL.M15), k=2)

Op.lag3.Px <

  • lag(Op(AAPL.M15), k=3)

Op.lag4.Px <

  • lag(Op(AAPL.M15), k=4)

Op.lag5.Px <

  • lag(Op(AAPL.M15), k=5)

Op.lag6.Px <

  • lag(Op(AAPL.M15), k=6)

Op.lag7.Px <

  • lag(Op(AAPL.M15), k=7)

Op.lag8.Px <

  • lag(Op(AAPL.M15), k=8)

Op.lag9.Px <

  • lag(Op(AAPL.M15), k=9)

Op.lag10.Px <

  • lag(Op(AAPL.M15), k=10)

Op.lag11.Px <

  • lag(Op(AAPL.M15), k=11)

Op.lag12.Px <

  • lag(Op(AAPL.M15), k=12)

Op.lag13.Px <

  • lag(Op(AAPL.M15), k=13)

Op.lag14.Px <

  • lag(Op(AAPL.M15), k=14)

dOp.Px <

  • (Op.Px — Op.lag1.Px)/Op.lag1.Px

dOp.lag2.Px <

  • (Op.Px — Op.lag2.Px)/Op.lag2.Px

dOp.lag3.Px <

  • (Op.Px — Op.lag3.Px)/Op.lag3.Px

dOp.lag4.Px <

  • (Op.Px — Op.lag4.Px)/Op.lag4.Px

dOp.lag5.Px <

  • (Op.Px — Op.lag5.Px)/Op.lag5.Px

dOp.lag6.Px <

  • (Op.Px — Op.lag6.Px)/Op.lag6.Px

dOp.lag7.Px <

  • (Op.Px — Op.lag7.Px)/Op.lag7.Px

dOp.lag8.Px <

  • (Op.Px — Op.lag8.Px)/Op.lag8.Px

dOp.lag9.Px <

  • (Op.Px — Op.lag9.Px)/Op.lag9.Px

dOp.lag10.Px <

  • (Op.Px — Op.lag10.Px)/Op.lag10.Px

dOp.lag11.Px <

  • (Op.Px — Op.lag11.Px)/Op.lag11.Px

dOp.lag12.Px <

  • (Op.Px — Op.lag12.Px)/Op.lag12.Px

dOp.lag13.Px <

  • (Op.Px — Op.lag13.Px)/Op.lag13.Px

dOp.lag14.Px <

  • (Op.Px — Op.lag14.Px)/Op.lag14.Px

Cl.Px <

  • Cl(AAPL.M15)

Cl.lag1.Px <

  • lag(Cl(AAPL.M15), k=1)

Cl.lag2.Px <

  • lag(Cl(AAPL.M15), k=2)

Cl.lag3.Px <

  • lag(Cl(AAPL.M15), k=3)

Cl.lag4.Px <

  • lag(Cl(AAPL.M15), k=4)

Cl.lag5.Px <

  • lag(Cl(AAPL.M15), k=5)

Cl.lag6.Px <

  • lag(Cl(AAPL.M15), k=6)

Cl.lag7.Px <

  • lag(Cl(AAPL.M15), k=7)

Cl.lag8.Px <

  • lag(Cl(AAPL.M15), k=8)

Cl.lag9.Px <

  • lag(Cl(AAPL.M15), k=9)

Cl.lag10.Px <

  • lag(Cl(AAPL.M15), k=10)

Cl.lag11.Px <

  • lag(Cl(AAPL.M15), k=11)

Cl.lag12.Px <

  • lag(Cl(AAPL.M15), k=12)

Cl.lag13.Px <

  • lag(Cl(AAPL.M15), k=13)

Cl.lag14.Px <

  • lag(Cl(AAPL.M15), k=14)

dCl.Px <

  • (Cl.Px — Cl.lag1.Px)/Cl.lag1.Px

dCl.lag2.Px <

  • (Cl.Px — Cl.lag2.Px)/Cl.lag2.Px

dCl.lag3.Px <

  • (Cl.Px — Cl.lag3.Px)/Cl.lag3.Px

dCl.lag4.Px <

  • (Cl.Px — Cl.lag4.Px)/Cl.lag4.Px

dCl.lag5.Px <

  • (Cl.Px — Cl.lag5.Px)/Cl.lag5.Px

dCl.lag6.Px <

  • (Cl.Px — Cl.lag6.Px)/Cl.lag6.Px

dCl.lag7.Px <

  • (Cl.Px — Cl.lag7.Px)/Cl.lag7.Px

dCl.lag8.Px <

  • (Cl.Px — Cl.lag8.Px)/Cl.lag8.Px

dCl.lag9.Px <

  • (Cl.Px — Cl.lag9.Px)/Cl.lag9.Px

dCl.lag10.Px <

  • (Cl.Px — Cl.lag10.Px)/Cl.lag10.Px

dCl.lag11.Px <

  • (Cl.Px — Cl.lag11.Px)/Cl.lag11.Px

dCl.lag12.Px <

  • (Cl.Px — Cl.lag12.Px)/Cl.lag12.Px

dCl.lag13.Px <

  • (Cl.Px — Cl.lag13.Px)/Cl.lag13.Px

dCl.lag14.Px <

  • (Cl.Px — Cl.lag14.Px)/Cl.lag14.Px

High.Px <

  • Hi(AAPL.M15)

Low.Px <

  • Lo(AAPL.M15)

Vo <

  • Vo(AAPL.M15)

# Fixing ejections in Vo

ejections <- which(Vo == 0)

replace.list <- c(length(ejections))

for(i in(1 : length(ejections))){

replace.list[i]<- mean(Vo[(ejections[i] — 5) : ejections[i]])

}

Vo <

  • replace(Vo, ejections, replace.list)

rm(i, ejections, replace.list)

Vo.lag1 <- lag(Vo, k=1)

Vo.lag2 <- lag(Vo, k=2)

Vo.lag3 <- lag(Vo, k=3)

Vo.lag4 <- lag(Vo, k=4)

Vo.lag5 <- lag(Vo, k=5)

Vo.lag6 <- lag(Vo, k=6)

Vo.lag7 <- lag(Vo, k=7)

Vo.lag8 <- lag(Vo, k=8)

Vo.lag9 <- lag(Vo, k=9)

Vo.lag10 <- lag(Vo, k=10)

Vo.lag11 <- lag(Vo, k=11)

Vo.lag12 <- lag(Vo, k=12)

Vo.lag13 <- lag(Vo, k=13)

Vo.lag14 <- lag(Vo, k=14)

dVo.Px <

  • (Vo — Vo.lag1)/Vo.lag1

dVo.lag2 <

  • (Vo — Vo.lag2)/Vo.lag2

dVo.lag3 <

  • (Vo — Vo.lag3)/Vo.lag3

dVo.lag4 <

  • (Vo — Vo.lag4)/Vo.lag4

dVo.lag5 <

  • (Vo — Vo.lag5)/Vo.lag5

dVo.lag6 <

  • (Vo — Vo.lag6)/Vo.lag6

dVo.lag7 <

  • (Vo — Vo.lag7)/Vo.lag7

dVo.lag8 <

  • (Vo — Vo.lag8)/Vo.lag8

dVo.lag9 <

  • (Vo — Vo.lag9)/Vo.lag9

dVo.lag10 <

  • (Vo — Vo.lag10)/Vo.lag10

dVo.lag11 <

  • (Vo — Vo.lag11)/Vo.lag11

dVo.lag12 <

  • (Vo — Vo.lag12)/Vo.lag12

dVo.lag13 <

  • (Vo — Vo.lag13)/Vo.lag13

dVo.lag14 <

  • (Vo — Vo.lag14)/Vo.lag14

MACD.Open <

  • MACD(AAPL.M15[,’AAPL.Open’],nFast = 12, nSlow = 26, nSig = 9,

maType = «EMA»)

MACD.Volume <

  • MACD(AAPL.M15[,’AAPL.Volume’],nFast = 12, nSlow = 26, nSig = 9,

maType = «EMA»)

Stoch <

  • stoch(data.stoch, nFastK = 5, nFastD = 3, nSlowD = 3,

maType = «EMA», bounded = FALSE,smooth = 3)

RSI.Open <

  • RSI(AAPL.M15[,’AAPL.Open’], n = 14, maType = «SMA»)

RSI.Close <

  • RSI(AAPL.M15[,’AAPL.Close’], n = 14, maType = «SMA»)

# NASDAQ

Op.Px.NASDAQ <

  • Op(NASDAQ.M15)

Op.lag1.Px.NASDAQ <

  • lag(Op(NASDAQ.M15), k=1)

Op.lag2.Px.NASDAQ <

  • lag(Op(NASDAQ.M15), k=2)

Op.lag3.Px.NASDAQ <

  • lag(Op(NASDAQ.M15), k=3)

Op.lag4.Px.NASDAQ <

  • lag(Op(NASDAQ.M15), k=4)

Op.lag5.Px.NASDAQ <

  • lag(Op(NASDAQ.M15), k=5)

Op.lag6.Px.NASDAQ <

  • lag(Op(NASDAQ.M15), k=6)

Op.lag7.Px.NASDAQ <

  • lag(Op(NASDAQ.M15), k=7)

Op.lag8.Px.NASDAQ <

  • lag(Op(NASDAQ.M15), k=8)

Op.lag9.Px.NASDAQ <

  • lag(Op(NASDAQ.M15), k=9)

Op.lag10.Px.NASDAQ <

  • lag(Op(NASDAQ.M15), k=10)

Op.lag11.Px.NASDAQ <

  • lag(Op(NASDAQ.M15), k=11)

Op.lag12.Px.NASDAQ <

  • lag(Op(NASDAQ.M15), k=12)

Op.lag13.Px.NASDAQ <

  • lag(Op(NASDAQ.M15), k=13)

Op.lag14.Px.NASDAQ <

  • lag(Op(NASDAQ.M15), k=14)

dOp.Px.NASDAQ <

  • (Op.Px.NASDAQ — Op.lag1.Px.NASDAQ)/Op.lag1.Px.NASDAQ

dOp.lag2.Px.NASDAQ <

  • (Op.Px.NASDAQ — Op.lag2.Px.NASDAQ)/Op.lag2.Px.NASDAQ

dOp.lag3.Px.NASDAQ <

  • (Op.Px.NASDAQ — Op.lag3.Px.NASDAQ)/Op.lag3.Px.NASDAQ

dOp.lag4.Px.NASDAQ <

  • (Op.Px.NASDAQ — Op.lag4.Px.NASDAQ)/Op.lag4.Px.NASDAQ

dOp.lag5.Px.NASDAQ <

  • (Op.Px.NASDAQ — Op.lag5.Px.NASDAQ)/Op.lag5.Px.NASDAQ

dOp.lag6.Px.NASDAQ <

  • (Op.Px.NASDAQ — Op.lag6.Px.NASDAQ)/Op.lag6.Px.NASDAQ

dOp.lag7.Px.NASDAQ <

  • (Op.Px.NASDAQ — Op.lag7.Px.NASDAQ)/Op.lag7.Px.NASDAQ

dOp.lag8.Px.NASDAQ <

  • (Op.Px.NASDAQ — Op.lag8.Px.NASDAQ)/Op.lag8.Px.NASDAQ

dOp.lag9.Px.NASDAQ <

  • (Op.Px.NASDAQ — Op.lag9.Px.NASDAQ)/Op.lag9.Px.NASDAQ

dOp.lag10.Px.NASDAQ <

  • (Op.Px.NASDAQ — Op.lag10.Px.NASDAQ)/Op.lag10.Px.NASDAQ

dOp.lag11.Px.NASDAQ <

  • (Op.Px.NASDAQ — Op.lag11.Px.NASDAQ)/Op.lag11.Px.NASDAQ

dOp.lag12.Px.NASDAQ <

  • (Op.Px.NASDAQ — Op.lag12.Px.NASDAQ)/Op.lag12.Px.NASDAQ

dOp.lag13.Px.NASDAQ <

  • (Op.Px.NASDAQ — Op.lag13.Px.NASDAQ)/Op.lag13.Px.NASDAQ

dOp.lag14.Px.NASDAQ <

  • (Op.Px.NASDAQ — Op.lag14.Px.NASDAQ)/Op.lag14.Px.NASDAQ

Cl.Px.NASDAQ <

  • Cl(NASDAQ.M15)

Cl.lag1.Px.NASDAQ <

  • lag(Cl(NASDAQ.M15), k=1)

Cl.lag2.Px.NASDAQ <

  • lag(Cl(NASDAQ.M15), k=2)

Cl.lag3.Px.NASDAQ <

  • lag(Cl(NASDAQ.M15), k=3)

Cl.lag4.Px.NASDAQ <

  • lag(Cl(NASDAQ.M15), k=4)

Cl.lag5.Px.NASDAQ <

  • lag(Cl(NASDAQ.M15), k=5)

Cl.lag6.Px.NASDAQ <

  • lag(Cl(NASDAQ.M15), k=6)

Cl.lag7.Px.NASDAQ <

  • lag(Cl(NASDAQ.M15), k=7)

Cl.lag8.Px.NASDAQ <

  • lag(Cl(NASDAQ.M15), k=8)

Cl.lag9.Px.NASDAQ <

  • lag(Cl(NASDAQ.M15), k=9)

Cl.lag10.Px.NASDAQ <

  • lag(Cl(NASDAQ.M15), k=10)

Cl.lag11.Px.NASDAQ <

  • lag(Cl(NASDAQ.M15), k=11)

Cl.lag12.Px.NASDAQ <

  • lag(Cl(NASDAQ.M15), k=12)

Cl.lag13.Px.NASDAQ <

  • lag(Cl(NASDAQ.M15), k=13)

Cl.lag14.Px.NASDAQ <

  • lag(Cl(NASDAQ.M15), k=14)

dCl.Px.NASDAQ <

  • (Cl.Px.NASDAQ — Cl.lag1.Px.NASDAQ)/Cl.lag1.Px.NASDAQ

dCl.lag2.Px.NASDAQ <

  • (Cl.Px.NASDAQ — Cl.lag2.Px.NASDAQ)/Cl.lag2.Px.NASDAQ

dCl.lag3.Px.NASDAQ <

  • (Cl.Px.NASDAQ — Cl.lag3.Px.NASDAQ)/Cl.lag3.Px.NASDAQ

dCl.lag4.Px.NASDAQ <

  • (Cl.Px.NASDAQ — Cl.lag4.Px.NASDAQ)/Cl.lag4.Px.NASDAQ

dCl.lag5.Px.NASDAQ <

  • (Cl.Px.NASDAQ — Cl.lag5.Px.NASDAQ)/Cl.lag5.Px.NASDAQ

dCl.lag6.Px.NASDAQ <

  • (Cl.Px.NASDAQ — Cl.lag6.Px.NASDAQ)/Cl.lag6.Px.NASDAQ

dCl.lag7.Px.NASDAQ <

  • (Cl.Px.NASDAQ — Cl.lag7.Px.NASDAQ)/Cl.lag7.Px.NASDAQ

dCl.lag8.Px.NASDAQ <

  • (Cl.Px.NASDAQ — Cl.lag8.Px.NASDAQ)/Cl.lag8.Px.NASDAQ

dCl.lag9.Px.NASDAQ <

  • (Cl.Px.NASDAQ — Cl.lag9.Px.NASDAQ)/Cl.lag9.Px.NASDAQ

dCl.lag10.Px.NASDAQ <

  • (Cl.Px.NASDAQ — Cl.lag10.Px.NASDAQ)/Cl.lag10.Px.NASDAQ

dCl.lag11.Px.NASDAQ <

  • (Cl.Px.NASDAQ — Cl.lag11.Px.NASDAQ)/Cl.lag11.Px.NASDAQ

dCl.lag12.Px.NASDAQ <

  • (Cl.Px.NASDAQ — Cl.lag12.Px.NASDAQ)/Cl.lag12.Px.NASDAQ

dCl.lag13.Px.NASDAQ <

  • (Cl.Px.NASDAQ — Cl.lag13.Px.NASDAQ)/Cl.lag13.Px.NASDAQ

dCl.lag14.Px.NASDAQ <

  • (Cl.Px.NASDAQ — Cl.lag14.Px.NASDAQ)/Cl.lag14.Px.NASDAQ

High.Px.NASDAQ <

  • Hi(NASDAQ.M15)

Low.Px.NASDAQ <

  • Lo(NASDAQ.M15)

Vo.NASDAQ <

  • Vo(NASDAQ.M15)

MACD.Open.NASDAQ <

  • MACD(NASDAQ.M15[,’COMP.Open’],nFast = 12, nSlow = 26,

nSig = 9, maType = «EMA»)

Stoch.NASDAQ <

  • stoch(data.stoch.NASDAQ, nFastK = 5, nFastD = 3,

nSlowD = 3, maType = «EMA», bounded = FALSE,

smooth = 3)

RSI.Open.NASDAQ <

  • RSI(NASDAQ.M15[,’COMP.Open’], n = 14, maType = «SMA»)

RSI.Close.NASDAQ <

  • RSI(NASDAQ.M15[,’COMP.Close’], n = 14, maType = «SMA»)

# SP500

Op.Px.SP500 <

  • Op(SP500.M15)

Op.lag1.Px.SP500 <

  • lag(Op(SP500.M15), k=1)

Op.lag2.Px.SP500 <

  • lag(Op(SP500.M15), k=2)

Op.lag3.Px.SP500 <

  • lag(Op(SP500.M15), k=3)

Op.lag4.Px.SP500 <

  • lag(Op(SP500.M15), k=4)

Op.lag5.Px.SP500 <

  • lag(Op(SP500.M15), k=5)

Op.lag6.Px.SP500 <

  • lag(Op(SP500.M15), k=6)

Op.lag7.Px.SP500 <

  • lag(Op(SP500.M15), k=7)

Op.lag8.Px.SP500 <

  • lag(Op(SP500.M15), k=8)

Op.lag9.Px.SP500 <

  • lag(Op(SP500.M15), k=9)

Op.lag10.Px.SP500 <

  • lag(Op(SP500.M15), k=10)

Op.lag11.Px.SP500 <

  • lag(Op(SP500.M15), k=11)

Op.lag12.Px.SP500 <

  • lag(Op(SP500.M15), k=12)

Op.lag13.Px.SP500 <

  • lag(Op(SP500.M15), k=13)

Op.lag14.Px.SP500 <

  • lag(Op(SP500.M15), k=14)

dOp.Px.SP500 <

  • (Op.Px.SP500 — Op.lag1.Px.SP500)/Op.lag1.Px.SP500

dOp.lag2.Px.SP500 <

  • (Op.Px.SP500 — Op.lag2.Px.SP500)/Op.lag2.Px.SP500

dOp.lag3.Px.SP500 <

  • (Op.Px.SP500 — Op.lag3.Px.SP500)/Op.lag3.Px.SP500

dOp.lag4.Px.SP500 <

  • (Op.Px.SP500 — Op.lag4.Px.SP500)/Op.lag4.Px.SP500

dOp.lag5.Px.SP500 <

  • (Op.Px.SP500 — Op.lag5.Px.SP500)/Op.lag5.Px.SP500

dOp.lag6.Px.SP500 <

  • (Op.Px.SP500 — Op.lag6.Px.SP500)/Op.lag6.Px.SP500

dOp.lag7.Px.SP500 <

  • (Op.Px.SP500 — Op.lag7.Px.SP500)/Op.lag7.Px.SP500

dOp.lag8.Px.SP500 <

  • (Op.Px.SP500 — Op.lag8.Px.SP500)/Op.lag8.Px.SP500

dOp.lag9.Px.SP500 <

  • (Op.Px.SP500 — Op.lag9.Px.SP500)/Op.lag9.Px.SP500

dOp.lag10.Px.SP500 <

  • (Op.Px.SP500 — Op.lag10.Px.SP500)/Op.lag10.Px.SP500

dOp.lag11.Px.SP500 <

  • (Op.Px.SP500 — Op.lag11.Px.SP500)/Op.lag11.Px.SP500

dOp.lag12.Px.SP500 <

  • (Op.Px.SP500 — Op.lag12.Px.SP500)/Op.lag12.Px.SP500

dOp.lag13.Px.SP500 <

  • (Op.Px.SP500 — Op.lag13.Px.SP500)/Op.lag13.Px.SP500

dOp.lag14.Px.SP500 <

  • (Op.Px.SP500 — Op.lag14.Px.SP500)/Op.lag14.Px.SP500

Cl.Px.SP500 <

  • Cl(SP500.M15)

Cl.lag1.Px.SP500 <

  • lag(Cl(SP500.M15), k=1)

Cl.lag2.Px.SP500 <

  • lag(Cl(SP500.M15), k=2)