Предсказание курса валют с помощью нейросети

Прогнозирование курса валюты на основе нейронных сетей

экономические науки

  • Баранова Мария Андреевна , студент
  • Галиаскарова Гузелия Рафкатовна , кандидат наук, доцент, доцент
  • Стерлитамакский филиал Башкирского государственного университета
  • Похожие материалы

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

    Задача прогнозирования динамики индекса курсов доллара США и евро как всемирных эквивалентов является – актуальной. Изменения валютных курсов очень сложно предсказать в связи с их зависимостью от политической, экономической обстановки в стране и в мире.

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

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

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

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

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

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

    Нейронные сети способны к адаптивному обучению путём реакции на положительные и отрицательные воздействия. Они показывают хорошие результаты при решении неформализованных или плохо формализованных процессов, обладают устойчивостью к частым изменениям среды [1, 2].

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

    В качестве входных параметров модели будем использовать данные котировок EURUSD в период с 20.07.2016 по 21.01.2017. Данные взяты с сайта http://www.finam.ru/. Задача будет состоять в том, что на основе имеющейся статистической информации, необходимо произвести прогноз EURUSD на 7 дней вперед. В таблице 1 частично представлены используемые входные параметры за рассматриваемый период.

    Таблица 1. Исходные данные EURUSD с 20.07.2016 по 21.01.2017

    Источник

    Можно ли прогнозировать цену ценных бумаг нейронной сетью?

    Когда рассматривается задача прогнозирования временных рядов нейронной сетью у читателя (слушателя, зрителя, …) часто возникает идея о том, что можно же сетью прогнозировать и цену акций, обретя возможность узнать, когда стоит докупить, а когда продать. Временами даже встречаются работы, в которых описывается, как именно можно нейронной сетью прогнозировать этот самый курс акций. Примером здесь может быть работа[1], там авторы приводят даже некоторые результаты. А вот в книге Ф. Шолле “Глубокое обучение на Python”[2], имеется вполне недвусмысленное предупреждение о том, что не стоит пытаться пытаться использовать машинное обучение для предсказаний курсов ценных бумаг. Шолле объясняет это тем, что в случае рынка, данные о прошлом состоянии являются плохой основой для предсказания будущего состояния. В работе [3]авторы вообще приходят к выводу, что курс ценных бумаг это мартингал (в математическом смысле этого слова), и наилучшим прогнозом (с точки зрения величины ошибки прогноза) его будущего состояния является его текущее состояние.

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

    Теория

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

    Что такое акция? Акция это ценная бумага, которая удостоверяет право её держателя на получение части прибыли предприятия. Уже из одного этого следует, что цена акции должна быть связана с прибылью предприятия. Более того, цена связана не столько с фактической прибылью предприятия, сколько с ожидаемой прибылью, то есть цена выражает мнение рынка о том, какой будет эта прибыль. А мнение может быть ошибочным. Мы помним историю стартапа Theranos, который утверждал, что у них есть революционная технология анализа ДНК чуть ли не по одной капле крови, а потом оказалась, что точность анализа сопоставима с тычками пальцем в небо. Таким образом, цена акции зависит от субъективного мнения инвесторов о компании.

    Посмотрим на рисунок ниже. На нём график изменения цены акций компании Maersk. Как видим, 2 апреля 2019 акция стоила 7718 DKK, а на следующий день — уже 7750. Почему? Причиной тому маленькая буква D внизу графика. 3 апреля выплачивались дивиденды, и, видимо, сумма была обещана хорошая, раз инвесторы начали скупать акции. То есть, к росту цен привело некоторое приближающееся событие.

    Теперь посмотрим на ещё один график. Это курс акций нашего Яндекса в те дни, когда в сеть просочились слухи о том, что Сбербанк собирается его купить. Обычно, на таких слухах цена акций как раз резко взлетает (ну ещё бы, компания-покупатель будет выкупать акции с рынка и всем хочется, чтобы акции выкупили именно у него…), но в этот раз инвесторы, видимо, решили, что покупка частного Яндекса государственным Сбербанком не несёт ничего хорошего.

    По мнению специалистов Отдела Небеснопальцевого Метода Познания НИИ Банальных Исследований, отсюда следует довольно простой вывод: цена акций зависит, в первую очередь, от мнения инвесторов о будущем компании, а не от её текущего состояния, и уж тем более не от текущей цены на акции как таковой. Поэтому прогнозировать будущую цену на основе текущей (или нескольких предыдущих) не имеет смысла.

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

    Практика

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

    Мы будем обучать нейронную сеть, которая по (n) ценам предскажет (n+1)-ю. При этом мы предполагаем, что время между двумя последовательными замерами одинаково. Для начала, нам потребуется набор данных, то есть те самые цены, брать данные мы будем с Yahoo Finance.

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

    Получать данные мы будем с помощью питоньего пакета yfinance . Тут нужно учесть, что Yahoo могут внезапно поменять API для получения данных из Finance, поэтому этот пакет может внезапно перестать работать, такое уже бывало, так что приведённый ниже код может внезапно перестать работать, к этому надо быть морально готовым. Итак, установим пакет yfinance :

    Как им пользоваться можно ознакомится тут. Теперь обратимся к бирже:

    На самом деле никаких данных мы пока не получили, мы пока что создали объект, через который мы сможем обращаться к бирже за данными. Yahoo Finance для Maersk предоставляет и информацию о выплате дивидендов. Как мы ранее выяснили из графика, выплата дивидендов приводит к росту спроса на ценные бумаги и, следовательно, к росту цены. Поэтому логично будет учесть и выплату дивидентов при прогнозе. То есть, прогнозируя цену акций для некоторого дня мы укажем, выплачиваются ли в этот день дивиденды. Получить информацию о дивидентах можно из поля maersk.dividends . Чтобы получить историю изменения цен акций нужно использовать метод history . Метод принимает ряд аргументов, для нас сейчас важны аргументы period и interval .

    Параметр period задаёт временной период, за который мы запрашиваем данные. Он поддерживает предопределённые строковые идентификаторы периодов, мы будет использовать значение ‘max’ , то есть запросим данные за всё время. С помощью аргументов start и end можно указать точный временной промежуток, для которого мы хотим получить данные, но мы будем использовать все доступные данные, так что нам подойдёт параметр period и значение ‘max’ .

    Параметр interval позволяет указать, с каким шагом получать данные, то есть задаёт временной промежуток между двумя идущими подряд значениями. Он точно также принимает значения из некоторого набора значений. Так как прогнозировать мы будем по дням, то используем значение ‘1d’ .

    Подробно прочитать про функцию history и то, какие параметры она принимает, и какие константы поддерживаются для параметров period и interval можно тут.

    Итак, запросим данные:

    Теперь в переменной history у нас данные о ценах в виде pandas DataFrame, посмотрим на них подробнее:

    Подготовим набор данных. Одной из задач при выборе архитектуры нейронной сети является определение количества входов, в нашем случае, количества дней, данные за которые мы должны подать на вход сети, чтобы получить ожидаемую цену. Поэтому для нас разумным будет предусмотреть возможность получить наборы данных с разным количеством входов. К счастью, всё уже придумало до нас и в пакете Keras уже есть генератор данных, который умеет варьировать количество входов. В случае прогнозирования временных рядов (а у нас именно эта задача, если кто ещё не понял), входные сигналы и ожидаемые выходные мы получаем из одного временного ряда. Мы используем метод скользящего окна размера n, где n — число входных сигналов модели, которая прогнозирует то, что мы прогнозируем. То есть, мы берем \(n\) последовательных элементов ряда, то есть , затем берём n+1 элемент как ожидаемый выход (то есть элемент x_ ) и получаем один обучающий пример. Затем мы сдвигаем окно на 1 элемент, и получаем обучающий пример со входными сигналами > и ожидаемым выходом x_ , и так далее. В общем случае не обязательно иметь именно один выходной сигнал (причём, на сколько элементов ряда сдвигать окно зависит от задачи, в общем случае сдвигать надо всё равно на один элемент), но в нашем случае это именно так.

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

    Функция принимает два параметра: набор данных, преобразование которого нужно выполнить ( data ) и количество значений цены закрытия, на основе которых будем выполнять прогнозирование ( value_num ).

    Мы упомянули пакеты, так что стоит пояснить, что это вообще такое. Обучение нейронной сети выполняется градиентным методом, который требует вычисления градиента функции потерь (отсюда и название). Самым простым является метод градиентного спуска. Классический подход предполагает, что градиент функции потерь вычисляется для всей обучающей выборки. Но тут есть недостатки. Во-первых, это может быть весьма накладно с вычислительной точки зрения — обучающая выборка может быть очень большой. Во-вторых, замечено, что при обучающих выборках очень большого размера, величина градиента может оказаться очень большой, и могут начаться проблемы с тем, что такие числа просто не помещаются в их машинное представление. Второе, конечно, имеет смысл в самых крайних случаях. Знающие люди отмечают, что нам, на самом деле, не очень-то и нужно точное значение градиента целевой функции[4]. Нам нужна оценка того, в какую сторону смещаться, чтобы минимизировать функцию потерь. Поэтому мы можем оценить градиент на основе некоторого подмножества обучающих примеров, чтобы определить это направление движения. Конечно, нам всё же придётся обойти все примеры, но теперь мы знаем, что нам не обязательно обрабатывать их все сразу. Мы можем разделить обучающую выборку на части равного размера (то есть на пакеты, batch) и вычислять градиент для каждого пакета отдельно, корректируя веса нейронной сети только на основе такого, “частичного”, градиента. После того, как обработали все пакеты, можно считать, что завершили одну эпоху обучения. В процессе обучения эпох может быть несколько, их количество зависит от задачи и самого хода обучения. Те же знающие люди также отмечают, что примеры должны быть распределены по пакетам случайно[4], то есть если два примера в обучающей выборке расположены друг за другом, они не должны попасть в один пакет, или, во всяком случае, должны быть расположены в ином порядке и не друг за другом.

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

    Посмотрим на один пакет обучающих примеров.

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

    Мы видим, что величина значений цен довольно высока. Действительно, цена закрытия изменяется в интервале \(<767.7, 12740.0>\) что говорит о том, что нужно нормализовать значения. Воспользуемся методом нормализации MinMax.

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

    Посмотрим на нормализованные данные.

    Как видно, значения цены закрытия приведены к интервалу [0, 1], что облегчит нашу задачу. Однако теперь нам нужно хранить значения h.min() и h.max() , чтобы иметь возможность нормализовать входы сети при её использовании, и чтобы «разнормализовать» её ответ обратно.

    Пришло время, наконец, собрать сеть и обучить её. Итак, наша сеть будет иметь (N+1) вход и один выход. Входы соответствуют замерам цены акции, а также содержат признак того, что в целевой день выплачиваются дивиденды, а выход соответствует цене закрытия для целевого дня. Величину N, число значений, на основе которых прогнозируется результат, нам предстоит определить. Поэтому напишем функцию, которая будет генерировать нам сети с разным числом входов. Мы используем конструкцию n+1 чтобы добавить вход, отвечающий за дивиденды.

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

    Ура, наконец-то создаём сеть:

    Теперь скомпилируем и обучим сеть. Под компиляцией в данном случае понимается подготовка внутренних структур сети к обучению и использованию. Мы должны указать, какой оптимизатор использовать (мы будем использовать adam ) и какую функцию потерь использовать (мы будем использовать mse , то есть среднеквадратичную ошибку). Функция потерь указывает, насколько плохо сеть решает задачу, следовательно, нашей целью является минимизация функции потерь.

    Метод fit обучает сеть, используя функцию потерь и оптимизатор, которые были указаны при вызове метода compile . Мы передаём обучающую выборку, входные сигналы и ожидаемый выход отдельно, также передаём число эпох (параметр epochs ), размер пакета (того самого, о котором говорили ранее, через параметр batch_size ) и тестовую (валидационную) выборку (через параметр validation_data , подаём кортеж, который содержит тестовые входы и тестовые выходы). Метод fit возвращает объект History , который описывает, как шло обучение.

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

    Теперь обучим сети, меняя число входов от 2 до 10 и обучая в течения 20 эпох.

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

    Выведя значение переменной model_stats , посмотрим на совокупные результаты:

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

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

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

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

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

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

    Посмотрим на график самого предсказания. Красным здесь обозначено ожидаемое значение, а синим — предсказание.

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

    Выводы

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

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

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

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

    Если уж очень хочется заработать не за счёт вдумчивого чтения финансовой отчётности, а за счёт математического анализа биржевых показателей, то стоит посмотреть на Quantitative Analysis. Говорят, работает.

    Источник

    Читайте также:  Предсказания друг другу шуточные
Оцените статью