Перевод. Оригинал: Forecasting stock movements with Artificial Neural Networks in 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[ 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')
+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
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 для каждой акции, используя разные переменные и настраивая гиперпараметры.
Комментариев нет:
Отправить комментарий