рекомендации

среда, 11 декабря 2019 г.

Прогнозирование движения цен акций с помощью искусственных нейронных сетей в R


В этом посте я объясню, как я построил однослойную ANN, используя пакет neuralnet в R, чтобы прогнозировать движение цен шести акций, торгуемых на NYSE и NASDAQ, используя некоторые технические индикаторы плюс индекс SP500 в качестве входных данных.

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


Извлечение и предварительная обработка данных

В качестве акций использовались Google, Boeing, Sanderson Farm Inc, Cognizant, Apple и Teradyne, для которых я получил цену и объем с января 2010 года по май 2018 года, всего 1859 торговых дней.

Источник данных - Yahoo! Finance, доступ к которому осуществляется с помощью функции getSymbol в пакете quantmod. Как только были получены цены и объем каждой акции, я приступил к вычислению всех необходимых переменных:

- изменение индекса SP500 (SP500)
- изменение 20, 10 и 5-дневных скользящих средних (MA20D, MA10D, MA5D)
- изменение объемов торгов (VOLCHANGE)
- историческая волатильность за 252 дня (HV)

Я также создал еще 2 признака. Предположим, что полосы Боллинджера служат уровнями сопротивления и поддержки, чтобы узнать, как далеко цена находится от этих уровней, я вычел разницу в цене из верхней и нижней полос Боллинджера (используя скользящее среднее за 5 дней). Я назвал их SprdLW5 и SprdUP5.
b_bands5 = na.exclude(BBands(price, n = 5 ))
lwr5 = b_bands5[,1]
upper5 = b_bands5[,3]spread_lwr5 = price - lwr5 
spread_upper5 = price - upper5

Самое главное, что я вычислил движение акций (теперь оно называется direction), используя доходности, и присвоив ему значение 1, когда доходность была положительной, и 0 в противном случае.

direction = rturn
direction[ direction > 0] = 1 # if rturn > 0, then 1
direction[ direction <= 0] = 0 # if rturn <= 0, then 0

Теперь переменная direction становится нашим y, а все остальные нашими x. Последние необходимо сместить назд в прошлое, чтобы построить модель, которая может делать прогнозы на день вперед. Как только набор данных с необходимыми переменными был готов, он был разделен на 90/10 для обучения и проверки соответственно. Всего 1859 наблюдений, 186 в проверочной выборке, 1673 в обучающей выборке.

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

Перед обучением ANN необходимо выполнить нормализацию всех данных, используя приведенную ниже формулу, чтобы значения данных были в диапазоне от 0 до 1 (нормализация от -1 до 1 тоже работает), в противном случае ANN не сойдется:

X' = (X - Xmin) / (Xmax - Xmin)

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

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

ANN с наилучшей производительностью представляла собой однослойную сеть из 3 нейронов с логистической функцией в качестве функции активации и квадратичной стандартной ошибкой в качестве функции стоимости.

nn = neuralnet(direction ~ SP500+MA20D+MA10D+MA5D+HV+VOLCHANGE
+SprdLW5+ SprdUP5,
data = tr_df, hidden = 3 , rep = 10 ,
linear.output = FALSE , algorithm = 'rprop-',
act.fct = 'logistic', stepmax = 400000,
err.fct = 'sse')

Изменение этих гиперпараметров (например, увеличение количества нейронов или изменение функции стоимости) приводило к длительным периодам обучения и/или ухудшению эффективности на проверочном наборе из-за переобучения



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

test.pred.nn = compute(nn, coredata(vl_df_price), rep=
which.min(nn$result.matrix[1,]) )$net.result

Эти прогнозы варьировались от 0 до 1, поэтому я заменил результаты на 1, если они были больше 0,5, и на 0 в противном случае. Точность определялась тем, какой процент предсказаний направления был правильным.
fcst_error = vl_df[,'direction']
fcst_error[vl_df[,'direction'] == test.pred.nn ] = 1
fcst_error[vl_df[,'direction'] != test.pred.nn ] = 0fcst_error =  sum(fcst_error)/length(vl_df[,'direction'])

Точность

Ниже приведена точность на акцию или просто процентное отношение правильного направления движения прогноза за 186 дней:

GOOG   BA     SAFM   CTSH   AAPL   TER
0.538  0.522  0.532  0.548  0.484  0.527

Заключение

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

Учитывая ограничения пакета neuralnet (доступны только две функции активации) и простую модель, есть шанс для ее улучшения при использовании других библиотек (Tensorflow?), а также создавая разные ANN для каждой акции, используя разные переменные и настраивая гиперпараметры.

Комментариев нет:

Отправка комментария